]> git-server-git.apps.pok.os.sepia.ceph.com Git - rocksdb.git/commitdiff
Cleanup page with place-holders.
authorDhruba Borthakur <dhruba@fb.com>
Fri, 7 Mar 2014 05:22:10 +0000 (21:22 -0800)
committerDhruba Borthakur <dhruba@fb.com>
Fri, 7 Mar 2014 05:22:10 +0000 (21:22 -0800)
Summary:

Test Plan:

Reviewers:

CC:

Task ID: #

Blame Rev:

366 files changed:
.arcconfig [new file with mode: 0644]
.gitignore [new file with mode: 0644]
CNAME [new file with mode: 0644]
Facebook_Mutual_NDA_2012.pdf [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Makefile [new file with mode: 0644]
PATENTS [new file with mode: 0644]
README [new file with mode: 0644]
README.fb [new file with mode: 0644]
benchmark_results.html [new file with mode: 0644]
build_tools/build_detect_platform [new file with mode: 0755]
build_tools/build_detect_version [new file with mode: 0755]
build_tools/fbcode.clang31.sh [new file with mode: 0644]
build_tools/fbcode.gcc471.sh [new file with mode: 0644]
build_tools/regression_build_test.sh [new file with mode: 0755]
build_tools/valgrind_test.sh [new file with mode: 0755]
coverage/coverage_test.sh [new file with mode: 0755]
coverage/parse_gcov_output.py [new file with mode: 0644]
db/builder.cc [new file with mode: 0644]
db/builder.h [new file with mode: 0644]
db/c.cc [new file with mode: 0644]
db/c_test.c [new file with mode: 0644]
db/corruption_test.cc [new file with mode: 0644]
db/db_bench.cc [new file with mode: 0644]
db/db_filesnapshot.cc [new file with mode: 0644]
db/db_impl.cc [new file with mode: 0644]
db/db_impl.h [new file with mode: 0644]
db/db_impl_readonly.cc [new file with mode: 0644]
db/db_impl_readonly.h [new file with mode: 0644]
db/db_iter.cc [new file with mode: 0644]
db/db_iter.h [new file with mode: 0644]
db/db_statistics.h [new file with mode: 0644]
db/db_stats_logger.cc [new file with mode: 0644]
db/db_test.cc [new file with mode: 0644]
db/dbformat.cc [new file with mode: 0644]
db/dbformat.h [new file with mode: 0644]
db/dbformat_test.cc [new file with mode: 0644]
db/deletefile_test.cc [new file with mode: 0644]
db/filename.cc [new file with mode: 0644]
db/filename.h [new file with mode: 0644]
db/filename_test.cc [new file with mode: 0644]
db/log_format.h [new file with mode: 0644]
db/log_reader.cc [new file with mode: 0644]
db/log_reader.h [new file with mode: 0644]
db/log_test.cc [new file with mode: 0644]
db/log_writer.cc [new file with mode: 0644]
db/log_writer.h [new file with mode: 0644]
db/memtable.cc [new file with mode: 0644]
db/memtable.h [new file with mode: 0644]
db/memtablelist.cc [new file with mode: 0644]
db/memtablelist.h [new file with mode: 0644]
db/merge_helper.cc [new file with mode: 0644]
db/merge_helper.h [new file with mode: 0644]
db/merge_operator.cc [new file with mode: 0644]
db/merge_test.cc [new file with mode: 0644]
db/perf_context_test.cc [new file with mode: 0644]
db/prefix_filter_iterator.h [new file with mode: 0644]
db/prefix_test.cc [new file with mode: 0644]
db/repair.cc [new file with mode: 0644]
db/simple_table_db_test.cc [new file with mode: 0644]
db/skiplist.h [new file with mode: 0644]
db/skiplist_test.cc [new file with mode: 0644]
db/snapshot.h [new file with mode: 0644]
db/table_cache.cc [new file with mode: 0644]
db/table_cache.h [new file with mode: 0644]
db/table_stats_collector.cc [new file with mode: 0644]
db/table_stats_collector.h [new file with mode: 0644]
db/table_stats_collector_test.cc [new file with mode: 0644]
db/transaction_log_impl.cc [new file with mode: 0644]
db/transaction_log_impl.h [new file with mode: 0644]
db/version_edit.cc [new file with mode: 0644]
db/version_edit.h [new file with mode: 0644]
db/version_edit_test.cc [new file with mode: 0644]
db/version_set.cc [new file with mode: 0644]
db/version_set.h [new file with mode: 0644]
db/version_set_reduce_num_levels.cc [new file with mode: 0644]
db/version_set_test.cc [new file with mode: 0644]
db/write_batch.cc [new file with mode: 0644]
db/write_batch_internal.h [new file with mode: 0644]
db/write_batch_test.cc [new file with mode: 0644]
doc/doc.css [new file with mode: 0644]
doc/index.html [new file with mode: 0644]
doc/log_format.txt [new file with mode: 0644]
doc/rockslogo.jpg [new file with mode: 0644]
doc/rockslogo.png [new file with mode: 0644]
hdfs/README [new file with mode: 0644]
hdfs/env_hdfs.h [new file with mode: 0644]
hdfs/hdfs.h [new file with mode: 0644]
hdfs/libhdfs.a [new file with mode: 0644]
helpers/memenv/memenv.cc [new file with mode: 0644]
helpers/memenv/memenv.h [new file with mode: 0644]
helpers/memenv/memenv_test.cc [new file with mode: 0644]
include/rocksdb/arena.h [new file with mode: 0644]
include/rocksdb/c.h [new file with mode: 0644]
include/rocksdb/cache.h [new file with mode: 0644]
include/rocksdb/compaction_filter.h [new file with mode: 0644]
include/rocksdb/comparator.h [new file with mode: 0644]
include/rocksdb/db.h [new file with mode: 0644]
include/rocksdb/env.h [new file with mode: 0644]
include/rocksdb/filter_policy.h [new file with mode: 0644]
include/rocksdb/flush_block_policy.h [new file with mode: 0644]
include/rocksdb/iterator.h [new file with mode: 0644]
include/rocksdb/ldb_tool.h [new file with mode: 0644]
include/rocksdb/memtablerep.h [new file with mode: 0644]
include/rocksdb/merge_operator.h [new file with mode: 0644]
include/rocksdb/options.h [new file with mode: 0644]
include/rocksdb/perf_context.h [new file with mode: 0644]
include/rocksdb/slice.h [new file with mode: 0644]
include/rocksdb/slice_transform.h [new file with mode: 0644]
include/rocksdb/statistics.h [new file with mode: 0644]
include/rocksdb/status.h [new file with mode: 0644]
include/rocksdb/table.h [new file with mode: 0644]
include/rocksdb/table_stats.h [new file with mode: 0644]
include/rocksdb/transaction_log.h [new file with mode: 0644]
include/rocksdb/types.h [new file with mode: 0644]
include/rocksdb/universal_compaction.h [new file with mode: 0644]
include/rocksdb/write_batch.h [new file with mode: 0644]
include/utilities/stackable_db.h [new file with mode: 0644]
include/utilities/utility_db.h [new file with mode: 0644]
index.html [new file with mode: 0644]
intro.pdf [new file with mode: 0644]
linters/src/.phutil_module_cache [new file with mode: 0644]
linters/src/__phutil_library_init__.php [new file with mode: 0644]
linters/src/__phutil_library_map__.php [new file with mode: 0644]
linters/src/cpp_linter/FbcodeCppLinter.php [new file with mode: 0644]
linters/src/cpp_linter/PfffCppLinter.php [new file with mode: 0644]
linters/src/lint_engine/FacebookFbcodeLintEngine.php [new file with mode: 0644]
meetup.html [new file with mode: 0644]
overview.html [new file with mode: 0644]
port/README [new file with mode: 0644]
port/atomic_pointer.h [new file with mode: 0644]
port/port.h [new file with mode: 0644]
port/port_example.h [new file with mode: 0644]
port/port_posix.cc [new file with mode: 0644]
port/port_posix.h [new file with mode: 0644]
port/stack_trace.cc [new file with mode: 0644]
port/win/stdint.h [new file with mode: 0644]
snappy/README [new file with mode: 0644]
snappy/libs [new symlink]
snappy/snappy-1.0.5/.deps/snappy-c.Plo [new file with mode: 0644]
snappy/snappy-1.0.5/.deps/snappy-sinksource.Plo [new file with mode: 0644]
snappy/snappy-1.0.5/.deps/snappy-stubs-internal.Plo [new file with mode: 0644]
snappy/snappy-1.0.5/.deps/snappy.Plo [new file with mode: 0644]
snappy/snappy-1.0.5/.deps/snappy_unittest-snappy-test.Po [new file with mode: 0644]
snappy/snappy-1.0.5/.deps/snappy_unittest-snappy_unittest.Po [new file with mode: 0644]
snappy/snappy-1.0.5/.libs/libsnappy.a [new file with mode: 0644]
snappy/snappy-1.0.5/.libs/libsnappy.la [new symlink]
snappy/snappy-1.0.5/.libs/libsnappy.lai [new file with mode: 0644]
snappy/snappy-1.0.5/.libs/libsnappy.so [new symlink]
snappy/snappy-1.0.5/.libs/libsnappy.so.1 [new symlink]
snappy/snappy-1.0.5/.libs/libsnappy.so.1.0.5 [new file with mode: 0755]
snappy/snappy-1.0.5/.libs/snappy_unittest [new file with mode: 0755]
snappy/snappy-1.0.5/AUTHORS [new file with mode: 0644]
snappy/snappy-1.0.5/COPYING [new file with mode: 0644]
snappy/snappy-1.0.5/ChangeLog [new file with mode: 0644]
snappy/snappy-1.0.5/INSTALL [new file with mode: 0644]
snappy/snappy-1.0.5/Makefile [new file with mode: 0644]
snappy/snappy-1.0.5/Makefile.am [new file with mode: 0644]
snappy/snappy-1.0.5/Makefile.in [new file with mode: 0644]
snappy/snappy-1.0.5/Makefile.in.orig [new file with mode: 0644]
snappy/snappy-1.0.5/Makefile.orig [new file with mode: 0644]
snappy/snappy-1.0.5/NEWS [new file with mode: 0644]
snappy/snappy-1.0.5/README [new file with mode: 0644]
snappy/snappy-1.0.5/aclocal.m4 [new file with mode: 0644]
snappy/snappy-1.0.5/autogen.sh [new file with mode: 0755]
snappy/snappy-1.0.5/autom4te.cache/output.0 [new file with mode: 0644]
snappy/snappy-1.0.5/autom4te.cache/output.1 [new file with mode: 0644]
snappy/snappy-1.0.5/autom4te.cache/requests [new file with mode: 0644]
snappy/snappy-1.0.5/autom4te.cache/traces.0 [new file with mode: 0644]
snappy/snappy-1.0.5/autom4te.cache/traces.1 [new file with mode: 0644]
snappy/snappy-1.0.5/compile.sh [new file with mode: 0755]
snappy/snappy-1.0.5/config.guess [new file with mode: 0755]
snappy/snappy-1.0.5/config.h [new file with mode: 0644]
snappy/snappy-1.0.5/config.h.in [new file with mode: 0644]
snappy/snappy-1.0.5/config.log [new file with mode: 0644]
snappy/snappy-1.0.5/config.status [new file with mode: 0755]
snappy/snappy-1.0.5/config.sub [new file with mode: 0755]
snappy/snappy-1.0.5/configure [new file with mode: 0755]
snappy/snappy-1.0.5/configure.ac [new file with mode: 0644]
snappy/snappy-1.0.5/depcomp [new file with mode: 0755]
snappy/snappy-1.0.5/dhruba.txt [new file with mode: 0644]
snappy/snappy-1.0.5/format_description.txt [new file with mode: 0644]
snappy/snappy-1.0.5/framing_format.txt [new file with mode: 0644]
snappy/snappy-1.0.5/install-sh [new file with mode: 0755]
snappy/snappy-1.0.5/libsnappy.la [new file with mode: 0644]
snappy/snappy-1.0.5/libtool [new file with mode: 0755]
snappy/snappy-1.0.5/ltmain.sh [new file with mode: 0755]
snappy/snappy-1.0.5/m4/gtest.m4 [new file with mode: 0644]
snappy/snappy-1.0.5/missing [new file with mode: 0755]
snappy/snappy-1.0.5/snappy-c.cc [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-c.h [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-c.lo [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-internal.h [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-sinksource.cc [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-sinksource.h [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-sinksource.lo [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-stubs-internal.cc [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-stubs-internal.h [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-stubs-internal.lo [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-stubs-public.h [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-stubs-public.h.in [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-test.cc [new file with mode: 0644]
snappy/snappy-1.0.5/snappy-test.h [new file with mode: 0644]
snappy/snappy-1.0.5/snappy.cc [new file with mode: 0644]
snappy/snappy-1.0.5/snappy.h [new file with mode: 0644]
snappy/snappy-1.0.5/snappy.lo [new file with mode: 0644]
snappy/snappy-1.0.5/snappy_unittest [new file with mode: 0755]
snappy/snappy-1.0.5/snappy_unittest.cc [new file with mode: 0644]
snappy/snappy-1.0.5/stamp-h1 [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/alice29.txt [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/asyoulik.txt [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/baddata1.snappy [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/baddata2.snappy [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/baddata3.snappy [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/cp.html [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/fields.c [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/geo.protodata [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/grammar.lsp [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/house.jpg [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/html [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/html_x_4 [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/kennedy.xls [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/kppkn.gtb [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/lcet10.txt [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/mapreduce-osdi-1.pdf [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/plrabn12.txt [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/ptt5 [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/sum [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/urls.10K [new file with mode: 0644]
snappy/snappy-1.0.5/testdata/xargs.1 [new file with mode: 0644]
snappy/snappy-stubs-public.h [new symlink]
snappy/snappy.h [new symlink]
static/facebookcode.png [new file with mode: 0644]
static/favicon.ico [new file with mode: 0644]
static/fbos.css [new file with mode: 0644]
static/rocksdb.css [new file with mode: 0644]
static/rocksdb.png [new file with mode: 0644]
static/rocksdbhero.png [new file with mode: 0644]
table/block.cc [new file with mode: 0644]
table/block.h [new file with mode: 0644]
table/block_based_table_builder.cc [new file with mode: 0644]
table/block_based_table_builder.h [new file with mode: 0644]
table/block_based_table_factory.cc [new file with mode: 0644]
table/block_based_table_factory.h [new file with mode: 0644]
table/block_based_table_reader.cc [new file with mode: 0644]
table/block_based_table_reader.h [new file with mode: 0644]
table/block_builder.cc [new file with mode: 0644]
table/block_builder.h [new file with mode: 0644]
table/block_test.cc [new file with mode: 0644]
table/filter_block.cc [new file with mode: 0644]
table/filter_block.h [new file with mode: 0644]
table/filter_block_test.cc [new file with mode: 0644]
table/flush_block_policy.cc [new file with mode: 0644]
table/format.cc [new file with mode: 0644]
table/format.h [new file with mode: 0644]
table/iter_heap.h [new file with mode: 0644]
table/iterator.cc [new file with mode: 0644]
table/iterator_wrapper.h [new file with mode: 0644]
table/merger.cc [new file with mode: 0644]
table/merger.h [new file with mode: 0644]
table/table_reader_bench.cc [new file with mode: 0644]
table/table_test.cc [new file with mode: 0644]
table/two_level_iterator.cc [new file with mode: 0644]
table/two_level_iterator.h [new file with mode: 0644]
tools/blob_store_bench.cc [new file with mode: 0644]
tools/db_crashtest.py [new file with mode: 0644]
tools/db_crashtest2.py [new file with mode: 0644]
tools/db_repl_stress.cc [new file with mode: 0644]
tools/db_stress.cc [new file with mode: 0644]
tools/ldb.cc [new file with mode: 0644]
tools/ldb_test.py [new file with mode: 0644]
tools/reduce_levels_test.cc [new file with mode: 0644]
tools/shell/DBClientProxy.cpp [new file with mode: 0644]
tools/shell/DBClientProxy.h [new file with mode: 0644]
tools/shell/LeveldbShell.cpp [new file with mode: 0644]
tools/shell/ShellContext.cpp [new file with mode: 0644]
tools/shell/ShellContext.h [new file with mode: 0644]
tools/shell/ShellState.cpp [new file with mode: 0644]
tools/shell/ShellState.h [new file with mode: 0644]
tools/shell/test/DBClientProxyTest.cpp [new file with mode: 0644]
tools/sst_dump.cc [new file with mode: 0644]
util/arena_impl.cc [new file with mode: 0644]
util/arena_impl.h [new file with mode: 0644]
util/arena_test.cc [new file with mode: 0644]
util/auto_roll_logger.cc [new file with mode: 0644]
util/auto_roll_logger.h [new file with mode: 0644]
util/auto_roll_logger_test.cc [new file with mode: 0755]
util/bit_set.h [new file with mode: 0644]
util/blob_store.cc [new file with mode: 0644]
util/blob_store.h [new file with mode: 0644]
util/blob_store_test.cc [new file with mode: 0644]
util/bloom.cc [new file with mode: 0644]
util/bloom_test.cc [new file with mode: 0644]
util/build_version.h [new file with mode: 0644]
util/cache.cc [new file with mode: 0644]
util/cache_test.cc [new file with mode: 0644]
util/coding.cc [new file with mode: 0644]
util/coding.h [new file with mode: 0644]
util/coding_test.cc [new file with mode: 0644]
util/comparator.cc [new file with mode: 0644]
util/crc32c.cc [new file with mode: 0644]
util/crc32c.h [new file with mode: 0644]
util/crc32c_test.cc [new file with mode: 0644]
util/env.cc [new file with mode: 0644]
util/env_hdfs.cc [new file with mode: 0644]
util/env_posix.cc [new file with mode: 0644]
util/env_test.cc [new file with mode: 0644]
util/filelock_test.cc [new file with mode: 0644]
util/filter_policy.cc [new file with mode: 0644]
util/hash.cc [new file with mode: 0644]
util/hash.h [new file with mode: 0644]
util/hash_skiplist_rep.cc [new file with mode: 0644]
util/histogram.cc [new file with mode: 0644]
util/histogram.h [new file with mode: 0644]
util/histogram_test.cc [new file with mode: 0644]
util/ldb_cmd.cc [new file with mode: 0644]
util/ldb_cmd.h [new file with mode: 0644]
util/ldb_cmd_execute_result.h [new file with mode: 0644]
util/ldb_tool.cc [new file with mode: 0644]
util/logging.cc [new file with mode: 0644]
util/logging.h [new file with mode: 0644]
util/manual_compaction_test.cc [new file with mode: 0644]
util/murmurhash.cc [new file with mode: 0644]
util/murmurhash.h [new file with mode: 0644]
util/mutexlock.h [new file with mode: 0644]
util/options.cc [new file with mode: 0644]
util/perf_context.cc [new file with mode: 0644]
util/perf_context_imp.h [new file with mode: 0644]
util/posix_logger.h [new file with mode: 0644]
util/random.h [new file with mode: 0644]
util/signal_test.cc [new file with mode: 0644]
util/skiplistrep.cc [new file with mode: 0644]
util/slice.cc [new file with mode: 0644]
util/stack_trace.h [new file with mode: 0644]
util/statistics.cc [new file with mode: 0644]
util/stats_logger.h [new file with mode: 0644]
util/status.cc [new file with mode: 0644]
util/stl_wrappers.h [new file with mode: 0644]
util/stop_watch.h [new file with mode: 0644]
util/string_util.cc [new file with mode: 0644]
util/string_util.h [new file with mode: 0644]
util/testharness.cc [new file with mode: 0644]
util/testharness.h [new file with mode: 0644]
util/testutil.cc [new file with mode: 0644]
util/testutil.h [new file with mode: 0644]
util/transformrep.cc [new file with mode: 0644]
util/vectorrep.cc [new file with mode: 0644]
utilities/.DS_Store [new file with mode: 0644]
utilities/merge_operators.h [new file with mode: 0644]
utilities/merge_operators/.DS_Store [new file with mode: 0644]
utilities/merge_operators/put.cc [new file with mode: 0644]
utilities/merge_operators/string_append/stringappend.cc [new file with mode: 0644]
utilities/merge_operators/string_append/stringappend.h [new file with mode: 0644]
utilities/merge_operators/string_append/stringappend2.cc [new file with mode: 0644]
utilities/merge_operators/string_append/stringappend2.h [new file with mode: 0644]
utilities/merge_operators/string_append/stringappend_test.cc [new file with mode: 0644]
utilities/merge_operators/uint64add.cc [new file with mode: 0644]
utilities/redis/README [new file with mode: 0644]
utilities/redis/redis_list_exception.h [new file with mode: 0644]
utilities/redis/redis_list_iterator.h [new file with mode: 0644]
utilities/redis/redis_lists.cc [new file with mode: 0644]
utilities/redis/redis_lists.h [new file with mode: 0644]
utilities/redis/redis_lists_test.cc [new file with mode: 0644]
utilities/ttl/db_ttl.cc [new file with mode: 0644]
utilities/ttl/db_ttl.h [new file with mode: 0644]
utilities/ttl/ttl_test.cc [new file with mode: 0644]

diff --git a/.arcconfig b/.arcconfig
new file mode 100644 (file)
index 0000000..82d1771
--- /dev/null
@@ -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 (file)
index 0000000..1c2d2b3
--- /dev/null
@@ -0,0 +1,23 @@
+build_config.mk
+
+*.a
+*.arc
+*.d
+*.dylib*
+*.gcda
+*.gcno
+*.o
+*.so
+*.so.*
+*_test
+*_bench
+*_stress
+
+ldb
+manifest_dump
+sst_dump
+util/build_version.cc
+build_tools/VALGRIND_LOGS/
+coverage/COVERAGE_REPORT
+util/build_version.cc.tmp
+.gdbhistory
diff --git a/CNAME b/CNAME
new file mode 100644 (file)
index 0000000..827d1c0
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+rocksdb.org
\ No newline at end of file
diff --git a/Facebook_Mutual_NDA_2012.pdf b/Facebook_Mutual_NDA_2012.pdf
new file mode 100644 (file)
index 0000000..59de829
Binary files /dev/null and b/Facebook_Mutual_NDA_2012.pdf differ
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..716ad9e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,35 @@
+BSD License
+
+For rocksdb software
+
+Copyright (c) 2013, Facebook, Inc.
+All rights reserved.
+---------------------------------------------------------------------
+
+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 (file)
index 0000000..f7b114f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,380 @@
+# 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 (export ROCKSDB_ROOT=$(CURDIR); $(CURDIR)/build_tools/build_detect_platform $(CURDIR)/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
+CFLAGS += -g $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CCFLAGS) $(OPT)
+CXXFLAGS += -g $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) -std=gnu++0x -Woverloaded-virtual
+
+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 = build_tools/VALGRIND_LOGS
+VALGRIND_VER := $(join $(VALGRIND_VER),valgrind)
+VALGRIND_OPTS = --error-exitcode=$(VALGRIND_ERROR) --leak-check=full
+
+TESTS = \
+       table_stats_collector_test \
+       arena_test \
+       auto_roll_logger_test \
+       block_test \
+       bloom_test \
+       c_test \
+       cache_test \
+       coding_test \
+       corruption_test \
+       crc32c_test \
+       db_test \
+       dbformat_test \
+       env_test \
+       blob_store_test \
+       filelock_test \
+       filename_test \
+       filter_block_test \
+       histogram_test \
+       log_test \
+       manual_compaction_test \
+       memenv_test \
+       merge_test \
+       redis_test \
+       reduce_levels_test \
+       simple_table_db_test \
+       skiplist_test \
+       stringappend_test \
+       table_test \
+       ttl_test \
+       version_edit_test \
+       version_set_test \
+       write_batch_test\
+       deletefile_test
+
+TOOLS = \
+        sst_dump \
+        db_stress \
+        ldb \
+                               db_repl_stress \
+                               blob_store_bench
+
+PROGRAMS = db_bench signal_test $(TESTS) $(TOOLS)
+BENCHMARKS = db_bench_sqlite3 db_bench_tree_db table_reader_bench
+
+# The library name is configurable since we are maintaining libraries of both
+# debug/release mode.
+LIBNAME = librocksdb
+LIBRARY = ${LIBNAME}.a
+MEMENVLIBRARY = libmemenv.a
+
+default: all
+
+#-----------------------------------------------
+# Create platform independent shared libraries.
+#-----------------------------------------------
+ifneq ($(PLATFORM_SHARED_EXT),)
+
+ifneq ($(PLATFORM_SHARED_VERSIONED),true)
+SHARED1 = ${LIBNAME}.$(PLATFORM_SHARED_EXT)
+SHARED2 = $(SHARED1)
+SHARED3 = $(SHARED1)
+SHARED = $(SHARED1)
+else
+# Update db.h if you change these.
+SHARED_MAJOR = 2
+SHARED_MINOR = 0
+SHARED1 = ${LIBNAME}.$(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) $(COVERAGEFLAGS) $(PLATFORM_SHARED_CFLAGS) $(SOURCES) -o $(SHARED3)
+
+endif  # PLATFORM_SHARED_EXT
+
+all: $(LIBRARY) $(PROGRAMS)
+
+.PHONY: blackbox_crash_test check clean coverage crash_test ldb_tests \
+       release tags valgrind_check whitebox_crash_test
+
+release:
+       $(MAKE) clean
+       OPT=-DNDEBUG $(MAKE) -j32
+
+coverage:
+       $(MAKE) clean
+       COVERAGEFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS+="-lgcov" $(MAKE) all check
+       (cd coverage; ./coverage_test.sh)
+       # Delete intermediate files
+       find . -type f -regex ".*\.\(\(gcda\)\|\(gcno\)\)" -exec rm {} \;
+
+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
+
+crash_test: blackbox_crash_test whitebox_crash_test
+
+blackbox_crash_test: db_stress
+       python -u tools/db_crashtest.py
+
+whitebox_crash_test: db_stress
+       python -u tools/db_crashtest2.py
+
+valgrind_check: all $(PROGRAMS) $(TESTS)
+       mkdir -p $(VALGRIND_DIR)
+       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) build_config.mk
+       -rm -rf ios-x86/* ios-arm/*
+       -find . -name "*.[od]" -exec rm {} \;
+       -find . -type f -regex ".*\.\(\(gcda\)\|\(gcno\)\)" -exec rm {} \;
+tags:
+       ctags * -R
+       cscope -b `find . -name '*.cc'` `find . -name '*.h'`
+
+# ---------------------------------------------------------------------------
+#      Unit tests and tools
+# ---------------------------------------------------------------------------
+$(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) $(COVERAGEFLAGS)
+
+db_stress: tools/db_stress.o $(LIBOBJECTS) $(TESTUTIL)
+       $(CXX) tools/db_stress.o $(LIBOBJECTS) $(TESTUTIL) $(EXEC_LDFLAGS) -o $@  $(LDFLAGS) $(COVERAGEFLAGS)
+
+db_repl_stress: tools/db_repl_stress.o $(LIBOBJECTS) $(TESTUTIL)
+       $(CXX) tools/db_repl_stress.o $(LIBOBJECTS) $(TESTUTIL) $(EXEC_LDFLAGS) -o $@  $(LDFLAGS) $(COVERAGEFLAGS)
+
+blob_store_bench: tools/blob_store_bench.o $(LIBOBJECTS) $(TESTUTIL)
+       $(CXX) tools/blob_store_bench.o $(LIBOBJECTS) $(TESTUTIL) $(EXEC_LDFLAGS) -o $@  $(LDFLAGS) $(COVERAGEFLAGS)
+
+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 $(COVERAGEFLAGS)
+
+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 $(COVERAGEFLAGS)
+
+signal_test: util/signal_test.o $(LIBOBJECTS)
+       $(CXX) util/signal_test.o $(LIBOBJECTS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+arena_test: util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+table_stats_collector_test: db/table_stats_collector_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/table_stats_collector_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+bloom_test: util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+c_test: db/c_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+cache_test: util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+coding_test: util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+blob_store_test: util/blob_store_test.o $(LIBOBJECTS) $(TESTHARNESS) $(TESTUTIL)
+       $(CXX) util/blob_store_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o$@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+stringappend_test: utilities/merge_operators/string_append/stringappend_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) utilities/merge_operators/string_append/stringappend_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+redis_test: utilities/redis/redis_lists_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) utilities/redis/redis_lists_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+histogram_test: util/histogram_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) util/histogram_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o$@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+corruption_test: db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+crc32c_test: util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+db_test: db/db_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+simple_table_db_test: db/simple_table_db_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/simple_table_db_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+table_reader_bench: table/table_reader_bench.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) table/table_reader_bench.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+perf_context_test: db/perf_context_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/perf_context_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS)
+
+prefix_test: db/prefix_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/prefix_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS)
+
+ttl_test: utilities/ttl/ttl_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) utilities/ttl/ttl_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@  $(LDFLAGS) $(COVERAGEFLAGS)
+
+dbformat_test: db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+env_test: util/env_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+filename_test: db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+filter_block_test: table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+log_test: db/log_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+table_test: table/table_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+block_test: table/block_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) table/block_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+skiplist_test: db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+version_edit_test: db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+version_set_test: db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+reduce_levels_test: tools/reduce_levels_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) tools/reduce_levels_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+merge_test: db/merge_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/merge_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+deletefile_test: db/deletefile_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) db/deletefile_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) $(COVERAGEFLAGS)
+
+manual_compaction_test: util/manual_compaction_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) util/manual_compaction_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+rocksdb_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) $(COVERAGEFLAGS)
+
+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) $(COVERAGEFLAGS)
+
+filelock_test: util/filelock_test.o $(LIBOBJECTS) $(TESTHARNESS)
+       $(CXX) util/filelock_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+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) $(COVERAGEFLAGS)
+
+sst_dump: tools/sst_dump.o $(LIBOBJECTS)
+       $(CXX) tools/sst_dump.o $(LIBOBJECTS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+ldb: tools/ldb.o $(LIBOBJECTS)
+       $(CXX) tools/ldb.o $(LIBOBJECTS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
+
+# ---------------------------------------------------------------------------
+#      Platform-specific compilation
+# ---------------------------------------------------------------------------
+
+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/$@ $(COVERAGEFLAGS)
+       mkdir -p ios-arm/$(dir $@)
+       $(DEVICEROOT)/usr/bin/$(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@ $(COVERAGEFLAGS)
+       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) -c $< -o $@ $(COVERAGEFLAGS)
+
+.c.o:
+       $(CC) $(CFLAGS) -c $< -o $@
+endif
+
+# ---------------------------------------------------------------------------
+#      Source files dependencies detection
+# ---------------------------------------------------------------------------
+
+# Add proper dependency support so changing a .h file forces a .cc file to
+# rebuild.
+
+# The .d file indicates .cc file's dependencies on .h files. We generate such
+# dependency by g++'s -MM option, whose output is a make dependency rule.
+# The sed command makes sure the "target" file in the generated .d file has
+# the correct path prefix.
+%.d: %.cc
+       $(CXX) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) -MM $< -o $@
+       @sed -i -e 's|.*:|$*.o:|' $@
+
+DEPFILES = $(filter-out util/build_version.d,$(SOURCES:.cc=.d))
+
+depend: $(DEPFILES)
+
+ifneq ($(MAKECMDGOALS),clean)
+-include $(DEPFILES)
+endif
diff --git a/PATENTS b/PATENTS
new file mode 100644 (file)
index 0000000..8a6fca4
--- /dev/null
+++ b/PATENTS
@@ -0,0 +1,23 @@
+Additional Grant of Patent Rights
+
+“Software” means the rocksdb software distributed by Facebook, Inc.
+
+Facebook hereby grants you a perpetual, worldwide, royalty-free,
+non-exclusive, irrevocable (subject to the termination provision below)
+license under any rights in any patent claims owned by Facebook, to make,
+have made, use, sell, offer to sell, import, and otherwise transfer the
+Software. For avoidance of doubt, no license is granted under Facebook’s
+rights in any patent claims that are infringed by (i) modifications to the
+Software made by you or a third party, or (ii) the Software in combination
+with any software or other technology provided by you or a third party.
+
+The license granted hereunder will terminate, automatically and without
+notice, for anyone that makes any claim (including by filing any lawsuit,
+assertion or other action) alleging (a) direct, indirect, or contributory
+infringement or inducement to infringe any patent: (i) by Facebook or any
+of its subsidiaries or affiliates, whether or not such claim is related
+to the Software, (ii) by any party if such claim arises in whole or in
+part from any software, product or service of Facebook or any of its
+subsidiaries or affiliates, whether or not such claim is related to the
+Software, or (iii) by any party relating to the Software; or (b) that
+any right in any patent claim of Facebook is invalid or unenforceable.
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..61857a2
--- /dev/null
+++ b/README
@@ -0,0 +1,82 @@
+rocksdb: A persistent key-value store for flash storage
+Authors: * The Facebook Database Engineering Team
+         * Build on earlier work on leveldb by Sanjay Ghemawat
+           (sanjay@google.com) and Jeff Dean (jeff@google.com)
+
+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/*.  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/rocksdb/db.h
+    Main interface to the DB: Start here
+
+include/rocksdb/options.h
+    Control over the behavior of an entire database, and also
+    control over the behavior of individual reads and writes.
+
+include/rocksdb/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/rocksdb/iterator.h
+    Interface for iterating over data. You can get an iterator
+    from a DB object.
+
+include/rocksdb/write_batch.h
+    Interface for atomically applying multiple updates to a database.
+
+include/rocksdb/slice.h
+    A simple module for maintaining a pointer and a length into some
+    other byte array.
+
+include/rocksdb/status.h
+    Status is returned from many of the public interfaces and is used
+    to report success and various kinds of errors.
+
+include/rocksdb/env.h
+    Abstraction of the OS environment.  A posix implementation of
+    this interface is in util/env_posix.cc
+
+include/rocksdb/table_builder.h
+    Lower-level modules that most clients probably won't use directly
+
+include/rocksdb/cache.h
+    An API for the block cache.
+
+include/rocksdb/compaction_filter.h
+    An API for a application filter invoked on every compaction.
+
+include/rocksdb/filter_policy.h
+    An API for configuring a bloom filter.
+
+include/rocksdb/memtablerep.h
+    An API for implementing a memtable.
+
+include/rocksdb/statistics.h
+    An API to retrieve various database statistics.
+
+include/rocksdb/transaction_log.h
+    An API to retrieve transaction logs from a database.
+
+
diff --git a/README.fb b/README.fb
new file mode 100644 (file)
index 0000000..d17eed8
--- /dev/null
+++ b/README.fb
@@ -0,0 +1,3 @@
+* Detailed instructions on how to compile using fbcode and jemalloc
+
+* Latest release is 2.5.fb
diff --git a/benchmark_results.html b/benchmark_results.html
new file mode 100644 (file)
index 0000000..b9beb40
--- /dev/null
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html prefix="og: http://ogp.me/ns#">
+<head>
+    <meta charset='utf-8'>
+    <title>RocksDB | A persistent key-value store for fast storage environments</title>
+    <link rel='stylesheet' href='static/rocksdb.css' type='text/css'/>
+    <link rel='shortcut icon' href='static/favicon.ico'>
+    <meta name='viewport' content='width=device-width'>
+    <meta property='og:type' content='website'>
+    <meta property='og:title' content='RocksDB | A persistent key-value store for fast storage environments'>
+    <meta property='og:description' content='A persistent key-value store for fast storage environments'>
+    <meta property='og:image' content='http://rocksdb.org/static/rocksdb.png'>
+</head>
+<body>
+
+<header class='topbar'><nav class='width'>
+    <a href='index.html'><h1>RocksDB</h1></a>
+    <ul>
+        <li><a href='overview.html' class='active'>Overview</a></li>
+        <li><a href='https://github.com/facebook/rocksdb/wiki/_pages'>Wiki</a></li>
+        <li><a href='https://github.com/facebook/rocksdb'>GitHub</a>
+    </ul>
+</nav></header>
+
+<header class='hero'><div class='width'>
+    <hgroup>
+        <h1>
+            Performance Benchmark Results.
+        </h1>
+    </hgroup>
+</div></header>
+
+<section class='content'><div class='width'>
+
+    <article>
+
+<h2>The goal of having a unified benchmark</h2>
+
+<p> 
+The main focus for RocksDB is <it>performance</it>. The vision for RocksDB is to make it scale
+linearly with storage hardware. This page is here to document, in one place, the 
+performance of rocksdb on various
+hardware platforms. We would like hardware vendors to run the RocksDB benchmark on their 
+hardware and contribute their results to this page.
+</p>
+
+<p>
+We have run RocksDB benchmark on a single platform and documented it 
+<a href='https://github.com/facebook/rocksdb/wiki/Performance-Benchmarks'>here</a>.
+We would like vendors to run the same benchmark, create a replica of the
+above page with the numbers that they achieve, and then post a pointer 
+to their page in the RocksDB 
+<a href='https://www.facebook.com/groups/rocksdb.dev/'> developers group.</a>
+After the community vets the results, this page will be updated.
+</p>
+
+
+<h2>Participating Vendors</h2>
+
+<ul>
+<li><a href='http://diablosystems.com/xxx.html'> XXX Sytems </a></li>
+<li><a href='http:/violinmemory.html/yyy.com'> YYY Memory</a></li>
+</ul>
+
+    </article>
+
+</div></section>
+
+<footer><div class='width'>
+    &copy; Copyright 2013, Facebook
+</div></footer>
+
+</body>
+</html>
diff --git a/build_tools/build_detect_platform b/build_tools/build_detect_platform
new file mode 100755 (executable)
index 0000000..c134b81
--- /dev/null
@@ -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 <output-filename>" >&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 $PWD/build_tools/fbcode.gcc471.sh
+    else
+        source $PWD/build_tools/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
+
+# generic port files (working on all platform by #ifdef) go directly in /port
+GENERIC_PORT_FILES=`find $ROCKSDB_ROOT/port -name '*.cc' | tr "\n" " "`
+
+# 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 -DOS_MACOSX"
+        PLATFORM_SHARED_EXT=dylib
+        PLATFORM_SHARED_LDFLAGS="-dynamiclib -install_name "
+        # PORT_FILES=port/darwin/darwin_specific.cc
+        ;;
+    Linux)
+        PLATFORM=OS_LINUX
+        COMMON_FLAGS="$COMMON_FLAGS -DOS_LINUX"
+        if [ -z "$USE_CLANG" ]; then
+            COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp"
+        fi
+        PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread -lrt"
+        # PORT_FILES=port/linux/linux_specific.cc
+        ;;
+    SunOS)
+        PLATFORM=OS_SOLARIS
+        COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_SOLARIS"
+        PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread -lrt"
+        # PORT_FILES=port/sunos/sunos_specific.cc
+        ;;
+    FreeBSD)
+        PLATFORM=OS_FREEBSD
+        COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_FREEBSD"
+        PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread"
+        # PORT_FILES=port/freebsd/freebsd_specific.cc
+        ;;
+    NetBSD)
+        PLATFORM=OS_NETBSD
+        COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_NETBSD"
+        PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread -lgcc_s"
+        # PORT_FILES=port/netbsd/netbsd_specific.cc
+        ;;
+    OpenBSD)
+        PLATFORM=OS_OPENBSD
+        COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_OPENBSD"
+        PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -pthread"
+        # PORT_FILES=port/openbsd/openbsd_specific.cc
+        ;;
+    DragonFly)
+        PLATFORM=OS_DRAGONFLYBSD
+        COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_DRAGONFLYBSD"
+        PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread"
+        # PORT_FILES=port/dragonfly/dragonfly_specific.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_FILES=port/android/android.cc
+        CROSS_COMPILE=true
+        ;;
+    *)
+        echo "Unknown platform!" >&2
+        exit 1
+esac
+
+$PWD/build_tools/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 utilities"
+
+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=`cd $ROCKSDB_ROOT; find $DIRS $PRUNE_TEST -o $PRUNE_BENCH -o -name '*.cc' -print | sort | tr "\n" " "`
+PORTABLE_CPP=`cd $ROCKSDB_ROOT; 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 $GENERIC_PORT_FILES $PORT_FILES" >> $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 <cstdatomic>.  Otherwise use port_posix.h.
+    $CXX $CFLAGS -std=c++0x -x c++ - -o /dev/null 2>/dev/null  <<EOF
+      #include <cstdatomic>
+      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  <<EOF
+      #include <snappy.h>
+      int main() {}
+EOF
+    if [ "$?" = 0 ]; then
+        COMMON_FLAGS="$COMMON_FLAGS -DSNAPPY"
+        PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS ${SNAPPY_LDFLAGS:-./snappy/libs/libsnappy.a}"
+    fi
+
+
+    # Test whether gflags library is installed
+    # http://code.google.com/p/gflags/
+    $CXX $CFLAGS -x c++ - -o /dev/null 2>/dev/null  <<EOF
+      #include <gflags/gflags.h>
+      int main() {}
+EOF
+    if [ "$?" = 0 ]; then
+        COMMON_FLAGS="$COMMON_FLAGS -DGFLAGS"
+    fi
+
+    # Test whether zlib library is installed
+    $CXX $CFLAGS $COMMON_FLAGS -x c++ - -o /dev/null 2>/dev/null  <<EOF
+      #include <zlib.h>
+      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  <<EOF
+      #include <bzlib.h>
+      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  <<EOF
+      int main() {}
+EOF
+    if [ "$?" = 0 ]; then
+        PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -ltcmalloc"
+    fi
+fi
+
+# shall we use HDFS?
+
+if test "$USE_HDFS"; then
+  if test -z "$JAVA_HOME"; then
+    echo "JAVA_HOME has to be set for HDFS usage."
+    exit 1
+  fi
+  HDFS_CCFLAGS="$HDFS_CCFLAGS -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -DUSE_HDFS"
+  HDFS_LDFLAGS="$HDFS_LDFLAGS -Wl,--no-whole-archive hdfs/libhdfs.a -L$JAVA_HOME/jre/lib/amd64"
+  HDFS_LDFLAGS="$HDFS_LDFLAGS -L$JAVA_HOME/jre/lib/amd64/server -L$GLIBC_RUNTIME_PATH/lib"
+  HDFS_LDFLAGS="$HDFS_LDFLAGS -ldl -lverify -ljava -ljvm"
+  COMMON_FLAGS="$COMMON_FLAGS $HDFS_CCFLAGS"
+  PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS $HDFS_LDFLAGS"
+fi
+
+# if Intel SSE instruction set is supported, set USE_SSE=" -msse -msse4.2 "
+COMMON_FLAGS="$COMMON_FLAGS $USE_SSE"
+
+PLATFORM_CCFLAGS="$PLATFORM_CCFLAGS $COMMON_FLAGS"
+PLATFORM_CXXFLAGS="$PLATFORM_CXXFLAGS $COMMON_FLAGS"
+
+VALGRIND_VER="$VALGRIND_VER"
+
+echo "CC=$CC" >> $OUTPUT
+echo "CXX=$CXX" >> $OUTPUT
+echo "PLATFORM=$PLATFORM" >> $OUTPUT
+echo "PLATFORM_LDFLAGS=$PLATFORM_LDFLAGS" >> $OUTPUT
+echo "VALGRIND_VER=$VALGRIND_VER" >> $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 "EXEC_LDFLAGS=$EXEC_LDFLAGS" >> $OUTPUT
diff --git a/build_tools/build_detect_version b/build_tools/build_detect_version
new file mode 100755 (executable)
index 0000000..ae9e391
--- /dev/null
@@ -0,0 +1,42 @@
+#!/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=$ROCKSDB_ROOT/util/build_version.cc.tmp
+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\"\n"
+  }
+  { print "const char* rocksdb_build_git_sha = \"rocksdb_build_git_sha:" $0"\";" }
+  ' >  ${VFILE}
+else
+  echo "git not found" |
+  awk '
+    BEGIN {
+      print "#include \"build_version.h\""
+    }
+    { print "const char* rocksdb_build_git_sha = \"rocksdb_build_git_sha:git not found\";" }
+    ' > ${VFILE}
+fi
+
+echo "const char* rocksdb_build_git_datetime = \"rocksdb_build_git_datetime:$(date)\";" >> ${VFILE}
+echo "const char* rocksdb_build_compile_date = __DATE__;" >> ${VFILE}
+echo "const char* rocksdb_build_compile_time = __TIME__;" >> ${VFILE}
+
+OUTFILE=$ROCKSDB_ROOT/util/build_version.cc
+if [ ! -e $OUTFILE ] || ! cmp -s $VFILE $OUTFILE; then
+    cp $VFILE $OUTFILE
+fi
diff --git a/build_tools/fbcode.clang31.sh b/build_tools/fbcode.clang31.sh
new file mode 100644 (file)
index 0000000..b2df8cd
--- /dev/null
@@ -0,0 +1,49 @@
+#!/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=fbe3b095a4cc4a3713730050d182b7b4a80c342f
+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.3.1/9202ce3
+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 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"
+
+# location of gflags headers and libraries
+GFLAGS_INCLUDE=" -I $TOOLCHAIN_LIB_BASE/gflags/gflags-1.6/91ddd43/include"
+GFLAGS_LIBS=" $TOOLCHAIN_LIB_BASE/gflags/gflags-1.6/91ddd43/lib/libgflags.a"
+
+# 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 $LIBEVENT_INCLUDE $GFLAGS_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/350336c/lib/libunwind.a"
+EXEC_LDFLAGS+=" $HDFSLIB $SNAPPY_LIBS $LIBEVENT_LIBS $GFLAGS_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 $ZLIB_LIBS $GFLAGS_LIBS"
+SNAPPY_LDFLAGS="$SNAPPY_LIBS"
+
+export CC CXX AR RANLIB CFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED SNAPPY_LDFLAGS
diff --git a/build_tools/fbcode.gcc471.sh b/build_tools/fbcode.gcc471.sh
new file mode 100644 (file)
index 0000000..3f2e38f
--- /dev/null
@@ -0,0 +1,60 @@
+#!/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=fbe3b095a4cc4a3713730050d182b7b4a80c342f
+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.3.1/9202ce3
+
+# 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 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"
+
+# location of gflags headers and libraries
+GFLAGS_INCLUDE=" -I $TOOLCHAIN_LIB_BASE/gflags/gflags-1.6/91ddd43/include"
+GFLAGS_LIBS=" $TOOLCHAIN_LIB_BASE/gflags/gflags-1.6/91ddd43/lib/libgflags.a"
+
+# 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 $LIBEVENT_INCLUDE $GFLAGS_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-1.0.1/350336c/lib/libunwind.a"
+EXEC_LDFLAGS+=" $HDFSLIB $SNAPPY_LIBS $ZLIB_LIBS $LIBEVENT_LIBS $GFLAGS_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 $GFLAGS_LIBS"
+SNAPPY_LDFLAGS="$SNAPPY_LIBS $ZLIB_LIBS"
+
+VALGRIND_VER="$TOOLCHAIN_LIB_BASE/valgrind/valgrind-3.8.1/91ddd43/bin/"
+
+export CC CXX AR RANLIB CFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED SNAPPY_LDFLAGS VALGRIND_VER
diff --git a/build_tools/regression_build_test.sh b/build_tools/regression_build_test.sh
new file mode 100755 (executable)
index 0000000..25a96d6
--- /dev/null
@@ -0,0 +1,100 @@
+#!/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 -t -d rocksdb_XXXX)}
+STAT_FILE=${STAT_FILE:-$(mktemp -t -u rocksdb_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" \
+    --connect-timeout 60
+}
+
+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/build_tools/valgrind_test.sh b/build_tools/valgrind_test.sh
new file mode 100755 (executable)
index 0000000..8c7e521
--- /dev/null
@@ -0,0 +1,15 @@
+#!/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=build_tools/VALGRIND_LOGS
+make clean
+make -j$(nproc) valgrind_check
+NUM_FAILED_TESTS=$((`wc -l $VALGRIND_DIR/valgrind_failed_tests | awk '{print $1}'` - 1))
+if [ $NUM_FAILED_TESTS -lt 1 ]; then
+  echo No tests have valgrind errors
+  exit 0
+else
+  cat $VALGRIND_DIR/valgrind_failed_tests
+  exit 1
+fi
diff --git a/coverage/coverage_test.sh b/coverage/coverage_test.sh
new file mode 100755 (executable)
index 0000000..7a8b5e0
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+# Exit on error.
+set -e
+
+if [ -n "$USE_CLANG" ]; then
+  echo "Error: Coverage test is supported only for gcc."
+  exit 1
+fi
+
+ROOT=".."
+# Fetch right version of gcov
+if [ -d /mnt/gvfs/third-party -a -z "$CXX" ]; then
+  source $ROOT/build_tools/fbcode.gcc471.sh
+  GCOV=$TOOLCHAIN_EXECUTABLES/gcc/gcc-4.7.1/cc6c9dc/bin/gcov
+else
+  GCOV=$(which gcov)
+fi
+
+COVERAGE_DIR="$PWD/COVERAGE_REPORT"
+mkdir -p $COVERAGE_DIR
+
+# Find all gcno files to generate the coverage report
+
+GCNO_FILES=`find $ROOT -name "*.gcno"`
+$GCOV --preserve-paths --relative-only --no-output $GCNO_FILES 2>/dev/null |
+  # Parse the raw gcov report to more human readable form.
+  python $ROOT/coverage/parse_gcov_output.py |
+  # Write the output to both stdout and report file.
+  tee $COVERAGE_DIR/coverage_report_all.txt &&
+echo -e "Generated coverage report for all files: $COVERAGE_DIR/coverage_report_all.txt\n"
+
+# TODO: we also need to get the files of the latest commits.
+# Get the most recently committed files.
+LATEST_FILES=`
+  git show --pretty="format:" --name-only HEAD |
+  grep -v "^$" |
+  paste -s -d,`
+RECENT_REPORT=$COVERAGE_DIR/coverage_report_recent.txt
+
+echo -e "Recently updated files: $LATEST_FILES\n" > $RECENT_REPORT
+$GCOV --preserve-paths --relative-only --no-output $GCNO_FILES 2>/dev/null |
+  python $ROOT/coverage/parse_gcov_output.py -interested-files $LATEST_FILES |
+  tee -a $RECENT_REPORT &&
+echo -e "Generated coverage report for recently updated files: $RECENT_REPORT\n"
+
+# Generate the html report. If we cannot find lcov in this machine, we'll simply
+# skip this step.
+echo "Generating the html coverage report..."
+
+LCOV=$(which lcov || true 2>/dev/null)
+if [ -z $LCOV ]
+then
+  echo "Skip: Cannot find lcov to generate the html report."
+  exit 0
+fi
+
+LCOV_VERSION=$(lcov -v | grep 1.1 || true)
+if [ $LCOV_VERSION ]
+then
+  echo "Not supported lcov version. Expect lcov 1.1."
+  exit 0
+fi
+
+(cd $ROOT; lcov --no-external \
+     --capture  \
+     --directory $PWD \
+     --gcov-tool $GCOV \
+     --output-file $COVERAGE_DIR/coverage.info)
+
+genhtml $COVERAGE_DIR/coverage.info -o $COVERAGE_DIR
+
+echo "HTML Coverage report is generated in $COVERAGE_DIR"
diff --git a/coverage/parse_gcov_output.py b/coverage/parse_gcov_output.py
new file mode 100644 (file)
index 0000000..72e8b07
--- /dev/null
@@ -0,0 +1,118 @@
+import optparse
+import re
+import sys
+
+from optparse import OptionParser
+
+# the gcov report follows certain pattern. Each file will have two lines
+# of report, from which we can extract the file name, total lines and coverage
+# percentage.
+def parse_gcov_report(gcov_input):
+    per_file_coverage = {}
+    total_coverage = None
+
+    for line in sys.stdin:
+        line = line.strip()
+
+        # --First line of the coverage report (with file name in it)?
+        match_obj = re.match("^File '(.*)'$", line)
+        if match_obj:
+            # fetch the file name from the first line of the report.
+            current_file = match_obj.group(1)
+            continue
+
+        # -- Second line of the file report (with coverage percentage)
+        match_obj = re.match("^Lines executed:(.*)% of (.*)", line)
+
+        if match_obj:
+            coverage = float(match_obj.group(1))
+            lines = int(match_obj.group(2))
+
+            if current_file is not None:
+                per_file_coverage[current_file] = (coverage, lines)
+                current_file = None
+            else:
+                # If current_file is not set, we reach the last line of report,
+                # which contains the summarized coverage percentage.
+                total_coverage = (coverage, lines)
+            continue
+
+        # If the line's pattern doesn't fall into the above categories. We
+        # can simply ignore them since they're either empty line or doesn't
+        # find executable lines of the given file.
+        current_file = None
+
+    return per_file_coverage, total_coverage
+
+def get_option_parser():
+    usage = "Parse the gcov output and generate more human-readable code " +\
+            "coverage report."
+    parser = OptionParser(usage)
+
+    parser.add_option(
+        "--interested-files", "-i",
+        dest="filenames",
+        help="Comma separated files names. if specified, we will display " +
+             "the coverage report only for interested source files. " +
+             "Otherwise we will display the coverage report for all " +
+             "source files."
+    )
+    return parser
+
+def display_file_coverage(per_file_coverage, total_coverage):
+    # To print out auto-adjustable column, we need to know the longest
+    # length of file names.
+    max_file_name_length = max(
+        len(fname) for fname in per_file_coverage.keys()
+    )
+
+    # -- Print header
+    # size of separator is determined by 3 column sizes:
+    # file name, coverage percentage and lines.
+    header_template = \
+        "%" + str(max_file_name_length) + "s\t%s\t%s"
+    separator = "-" * (max_file_name_length + 10 + 20)
+    print header_template % ("Filename", "Coverage", "Lines")
+    print separator
+
+    # -- Print body
+    # template for printing coverage report for each file.
+    record_template = "%" + str(max_file_name_length) + "s\t%5.2f%%\t%10d"
+
+    for fname, coverage_info in per_file_coverage.items():
+        coverage, lines = coverage_info
+        print record_template % (fname, coverage, lines)
+
+    # -- Print footer
+    if total_coverage:
+        print separator
+        print record_template % ("Total", total_coverage[0], total_coverage[1])
+
+def report_coverage():
+    parser = get_option_parser()
+    (options, args) = parser.parse_args()
+
+    interested_files = set()
+    if options.filenames is not None:
+        interested_files = set(f.strip() for f in options.filenames.split(','))
+
+    # To make things simple, right now we only read gcov report from the input
+    per_file_coverage, total_coverage = parse_gcov_report(sys.stdin)
+
+    # Check if we need to display coverage info for interested files.
+    if len(interested_files):
+        per_file_coverage = dict(
+            (fname, per_file_coverage[fname]) for fname in interested_files
+            if fname in per_file_coverage
+        )
+        # If we only interested in several files, it makes no sense to report
+        # the total_coverage
+        total_coverage = None
+
+    if not len(per_file_coverage):
+        print >> sys.stderr, "Cannot find coverage info for the given files."
+        return
+    display_file_coverage(per_file_coverage, total_coverage)
+
+if __name__ == "__main__":
+    report_coverage()
diff --git a/db/builder.cc b/db/builder.cc
new file mode 100644 (file)
index 0000000..b3bf894
--- /dev/null
@@ -0,0 +1,226 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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/merge_helper.h"
+#include "db/table_cache.h"
+#include "db/version_edit.h"
+#include "rocksdb/db.h"
+#include "rocksdb/table.h"
+#include "rocksdb/env.h"
+#include "rocksdb/iterator.h"
+#include "rocksdb/options.h"
+#include "table/block_based_table_builder.h"
+#include "util/stop_watch.h"
+
+namespace rocksdb {
+
+class TableFactory;
+
+TableBuilder* GetTableBuilder(const Options& options, WritableFile* file,
+                              CompressionType compression_type) {
+  return options.table_factory->GetTableBuilder(options, file,
+                                                compression_type);
+}
+
+Status BuildTable(const std::string& dbname,
+                  Env* env,
+                  const Options& options,
+                  const EnvOptions& soptions,
+                  TableCache* table_cache,
+                  Iterator* iter,
+                  FileMetaData* meta,
+                  const Comparator* user_comparator,
+                  const SequenceNumber newest_snapshot,
+                  const SequenceNumber earliest_seqno_in_memtable,
+                  const bool enable_compression) {
+  Status s;
+  meta->file_size = 0;
+  meta->smallest_seqno = meta->largest_seqno = 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<WritableFile> file;
+    s = env->NewWritableFile(fname, &file, soptions);
+    if (!s.ok()) {
+      return s;
+    }
+
+    TableBuilder* builder = GetTableBuilder(options, file.get(),
+                                            options.compression);
+
+    // the first key is the smallest key
+    Slice key = iter->key();
+    meta->smallest.DecodeFrom(key);
+    meta->smallest_seqno = GetInternalKeySeqno(key);
+    meta->largest_seqno = meta->smallest_seqno;
+
+    MergeHelper merge(user_comparator, options.merge_operator.get(),
+                      options.info_log.get(),
+                      true /* internal key corruption is not ok */);
+
+    if (purge) {
+      // Ugly walkaround to avoid compiler error for release build
+      bool ok __attribute__((unused)) = true;
+
+      // Will write to builder if current key != prev key
+      ParsedInternalKey prev_ikey;
+      std::string prev_key;
+      bool is_first_key = true;    // Also write if this is the very first key
+
+      while (iter->Valid()) {
+        bool iterator_at_next = false;
+
+        // Get current key
+        ParsedInternalKey this_ikey;
+        Slice key = iter->key();
+        Slice value = iter->value();
+
+        // In-memory key corruption is not ok;
+        // TODO: find a clean way to treat in memory key corruption
+        ok = ParseInternalKey(key, &this_ikey);
+        assert(ok);
+        assert(this_ikey.sequence >= earliest_seqno_in_memtable);
+
+        // If the key is the same as the previous key (and it is not the
+        // first key), then we skip it, since it is an older version.
+        // Otherwise we output the key and mark it as the "new" previous key.
+        if (!is_first_key && !user_comparator->Compare(prev_ikey.user_key,
+                                                       this_ikey.user_key)) {
+          // seqno within the same key are in decreasing order
+          assert(this_ikey.sequence < prev_ikey.sequence);
+        } else {
+          is_first_key = false;
+
+          if (this_ikey.type == kTypeMerge) {
+            // Handle merge-type keys using the MergeHelper
+            merge.MergeUntil(iter, 0 /* don't worry about snapshot */);
+            iterator_at_next = true;
+            if (merge.IsSuccess()) {
+              // Merge completed correctly.
+              // Add the resulting merge key/value and continue to next
+              builder->Add(merge.key(), merge.value());
+              prev_key.assign(merge.key().data(), merge.key().size());
+              ok = ParseInternalKey(Slice(prev_key), &prev_ikey);
+              assert(ok);
+            } else {
+              // Merge did not find a Put/Delete.
+              // Can not compact these merges into a kValueType.
+              // Write them out one-by-one. (Proceed back() to front())
+              const std::deque<std::string>& keys = merge.keys();
+              const std::deque<std::string>& values = merge.values();
+              assert(keys.size() == values.size() && keys.size() >= 1);
+              std::deque<std::string>::const_reverse_iterator key_iter;
+              std::deque<std::string>::const_reverse_iterator value_iter;
+              for (key_iter=keys.rbegin(), value_iter = values.rbegin();
+                   key_iter != keys.rend() && value_iter != values.rend();
+                   ++key_iter, ++value_iter) {
+
+                builder->Add(Slice(*key_iter), Slice(*value_iter));
+              }
+
+              // Sanity check. Both iterators should end at the same time
+              assert(key_iter == keys.rend() && value_iter == values.rend());
+
+              prev_key.assign(keys.front());
+              ok = ParseInternalKey(Slice(prev_key), &prev_ikey);
+              assert(ok);
+            }
+          } else {
+            // Handle Put/Delete-type keys by simply writing them
+            builder->Add(key, value);
+            prev_key.assign(key.data(), key.size());
+            ok = ParseInternalKey(Slice(prev_key), &prev_ikey);
+            assert(ok);
+          }
+        }
+
+        if (!iterator_at_next) iter->Next();
+      }
+
+      // The last key is the largest key
+      meta->largest.DecodeFrom(Slice(prev_key));
+      SequenceNumber seqno = GetInternalKeySeqno(Slice(prev_key));
+      meta->smallest_seqno = std::min(meta->smallest_seqno, seqno);
+      meta->largest_seqno = std::max(meta->largest_seqno, seqno);
+
+    } else {
+      for (; iter->Valid(); iter->Next()) {
+        Slice key = iter->key();
+        meta->largest.DecodeFrom(key);
+        builder->Add(key, iter->value());
+        SequenceNumber seqno = GetInternalKeySeqno(key);
+        meta->smallest_seqno = std::min(meta->smallest_seqno, seqno);
+        meta->largest_seqno = std::max(meta->largest_seqno, seqno);
+      }
+    }
+
+    // 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) {
+        StopWatch sw(env, options.statistics, TABLE_SYNC_MICROS);
+        s = file->Fsync();
+      } else {
+        StopWatch sw(env, options.statistics, TABLE_SYNC_MICROS);
+        s = file->Sync();
+      }
+    }
+    if (s.ok()) {
+      s = file->Close();
+    }
+
+    if (s.ok()) {
+      // Verify that the table is usable
+      Iterator* it = table_cache->NewIterator(ReadOptions(),
+                                              soptions,
+                                              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 rocksdb
diff --git a/db/builder.h b/db/builder.h
new file mode 100644 (file)
index 0000000..8c525bd
--- /dev/null
@@ -0,0 +1,48 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+// 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.
+#pragma once
+#include "rocksdb/comparator.h"
+#include "rocksdb/status.h"
+#include "rocksdb/types.h"
+#include "rocksdb/options.h"
+
+namespace rocksdb {
+
+struct Options;
+struct FileMetaData;
+
+class Env;
+struct EnvOptions;
+class Iterator;
+class TableCache;
+class VersionEdit;
+class TableBuilder;
+class WritableFile;
+
+
+extern TableBuilder* GetTableBuilder(const Options& options, WritableFile* file,
+                                     CompressionType compression_type);
+
+// 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,
+                         const EnvOptions& soptions,
+                         TableCache* table_cache,
+                         Iterator* iter,
+                         FileMetaData* meta,
+                         const Comparator* user_comparator,
+                         const SequenceNumber newest_snapshot,
+                         const SequenceNumber earliest_seqno_in_memtable,
+                         const bool enable_compression);
+
+}  // namespace rocksdb
diff --git a/db/c.cc b/db/c.cc
new file mode 100644 (file)
index 0000000..0d99c44
--- /dev/null
+++ b/db/c.cc
@@ -0,0 +1,691 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/c.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "rocksdb/cache.h"
+#include "rocksdb/comparator.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/filter_policy.h"
+#include "rocksdb/iterator.h"
+#include "rocksdb/options.h"
+#include "rocksdb/status.h"
+#include "rocksdb/write_batch.h"
+
+using rocksdb::Cache;
+using rocksdb::Comparator;
+using rocksdb::CompressionType;
+using rocksdb::DB;
+using rocksdb::Env;
+using rocksdb::FileLock;
+using rocksdb::FilterPolicy;
+using rocksdb::Iterator;
+using rocksdb::Logger;
+using rocksdb::NewBloomFilterPolicy;
+using rocksdb::NewLRUCache;
+using rocksdb::Options;
+using rocksdb::RandomAccessFile;
+using rocksdb::Range;
+using rocksdb::ReadOptions;
+using rocksdb::SequentialFile;
+using rocksdb::Slice;
+using rocksdb::Snapshot;
+using rocksdb::Status;
+using rocksdb::WritableFile;
+using rocksdb::WriteBatch;
+using rocksdb::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<Logger>  rep; };
+struct leveldb_cache_t        { shared_ptr<Cache>   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<const char*> key_pointers(n);
+    std::vector<size_t> 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<char*>(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<CompressionType>(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<CompressionType>(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;
+}
+
+void leveldb_options_set_WAL_size_limit_MB(
+    leveldb_options_t* opt, uint64_t limit) {
+  opt->rep.WAL_size_limit_MB = limit;
+}
+
+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 (file)
index 0000000..abbe1dd
--- /dev/null
@@ -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 "rocksdb/c.h"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+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, "rocksdb.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 (file)
index 0000000..e7b7b4c
--- /dev/null
@@ -0,0 +1,378 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/db.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "rocksdb/cache.h"
+#include "rocksdb/env.h"
+#include "rocksdb/table.h"
+#include "rocksdb/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 rocksdb {
+
+static const int kValueSize = 1000;
+
+class CorruptionTest {
+ public:
+  test::ErrorEnv env_;
+  std::string dbname_;
+  shared_ptr<Cache> 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;
+    options_.block_size_deviation = 0; // make unit test pass for now
+    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_;
+    opt.block_size_deviation = 0;
+    opt.arena_block_size = 4096;
+    return DB::Open(opt, dbname_, &db_);
+  }
+
+  void Reopen(Options* options = nullptr) {
+    ASSERT_OK(TryReopen(options));
+  }
+
+  void RepairDB() {
+    delete db_;
+    db_ = nullptr;
+    ASSERT_OK(::rocksdb::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<std::string> 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;
+  bool failed = false;
+  for (int i = 0; i < num; i++) {
+    WriteBatch batch;
+    batch.Put("a", Value(100, &value_storage));
+    s = db_->Write(WriteOptions(), &batch);
+    if (!s.ok()) {
+      failed = true;
+    }
+    ASSERT_TRUE(!failed || !s.ok());
+  }
+  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<DBImpl*>(db_);
+  dbi->TEST_FlushMemTable();
+  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<DBImpl*>(db_);
+  dbi->TEST_FlushMemTable();
+
+  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<DBImpl*>(db_);
+  dbi->TEST_FlushMemTable();
+  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<DBImpl*>(db_);
+  dbi->TEST_FlushMemTable();
+  const int last = dbi->MaxMemCompactionLevel();
+  ASSERT_EQ(1, Property("rocksdb.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<DBImpl*>(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_FlushMemTable();
+  }
+
+  Build(10);
+  dbi->TEST_FlushMemTable();
+  dbi->TEST_WaitForCompact();
+  ASSERT_EQ(1, Property("rocksdb.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;
+  bool failed = false;
+  for (int i = 0; i < 10000 && s.ok(); i++) {
+    s = db_->Put(WriteOptions(), Key(i, &tmp1), Value(i, &tmp2));
+    if (!s.ok()) {
+      failed = true;
+    }
+    // if one write failed, every subsequent write must fail, too
+    ASSERT_TRUE(!failed || !s.ok()) << "write did not fail in a corrupted db";
+  }
+  ASSERT_TRUE(!s.ok()) << "write did not fail in corrupted paranoid db";
+}
+
+TEST(CorruptionTest, UnrelatedKeys) {
+  Build(10);
+  DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
+  dbi->TEST_FlushMemTable();
+  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_FlushMemTable();
+  ASSERT_OK(db_->Get(ReadOptions(), Key(1000, &tmp1), &v));
+  ASSERT_EQ(Value(1000, &tmp2).ToString(), v);
+}
+
+}  // namespace rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/db/db_bench.cc b/db/db_bench.cc
new file mode 100644 (file)
index 0000000..89ccd97
--- /dev/null
@@ -0,0 +1,2461 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <cstddef>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <gflags/gflags.h>
+#include "db/db_impl.h"
+#include "db/version_set.h"
+#include "db/db_statistics.h"
+#include "rocksdb/options.h"
+#include "rocksdb/cache.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/memtablerep.h"
+#include "rocksdb/write_batch.h"
+#include "rocksdb/statistics.h"
+#include "port/port.h"
+#include "util/bit_set.h"
+#include "util/crc32c.h"
+#include "util/histogram.h"
+#include "util/mutexlock.h"
+#include "util/random.h"
+#include "util/stack_trace.h"
+#include "util/string_util.h"
+#include "util/testutil.h"
+#include "hdfs/env_hdfs.h"
+#include "utilities/merge_operators.h"
+
+
+DEFINE_string(benchmarks,
+
+              "fillseq,"
+              "fillsync,"
+              "fillrandom,"
+              "overwrite,"
+              "readrandom,"
+              "readrandom,"
+              "readseq,"
+              "readreverse,"
+              "compact,"
+              "readrandom,"
+              "readseq,"
+              "readreverse,"
+              "readwhilewriting,"
+              "readrandomwriterandom,"
+              "updaterandom,"
+              "randomwithverify,"
+              "fill100K,"
+              "crc32c,"
+              "snappycomp,"
+              "snappyuncomp,"
+              "acquireload,"
+              "fillfromstdin,",
+
+              "Comma-separated list of operations to run in the specified order"
+              "Actual benchmarks:\n"
+              "\tfillseq       -- write N values in sequential key"
+              " order in async mode\n"
+              "\tfillrandom    -- write N values in random key order in async"
+              " mode\n"
+              "\toverwrite     -- overwrite N values in random key order in"
+              " async mode\n"
+              "\tfillsync      -- write N/100 values in random key order in "
+              "sync mode\n"
+              "\tfill100K      -- write N/1000 100K values in random order in"
+              " async mode\n"
+              "\tdeleteseq     -- delete N keys in sequential order\n"
+              "\tdeleterandom  -- delete N keys in random order\n"
+              "\treadseq       -- read N times sequentially\n"
+              "\treadreverse   -- read N times in reverse order\n"
+              "\treadrandom    -- read N times in random order\n"
+              "\treadmissing   -- read N missing keys in random order\n"
+              "\treadhot       -- read N times in random order from 1% section "
+              "of DB\n"
+              "\treadwhilewriting      -- 1 writer, N threads doing random "
+              "reads\n"
+              "\treadrandomwriterandom -- N threads doing random-read, "
+              "random-write\n"
+              "\tprefixscanrandom      -- prefix scan N times in random order\n"
+              "\tupdaterandom  -- N threads doing read-modify-write for random "
+              "keys\n"
+              "\tappendrandom  -- N threads doing read-modify-write with "
+              "growing values\n"
+              "\tmergerandom   -- same as updaterandom/appendrandom using merge"
+              " operator. "
+              "Must be used with merge_operator\n"
+              "\tseekrandom    -- N random seeks\n"
+              "\tcrc32c        -- repeated crc32c of 4K of data\n"
+              "\tacquireload   -- load N*1000 times\n"
+              "Meta operations:\n"
+              "\tcompact     -- Compact the entire DB\n"
+              "\tstats       -- Print DB stats\n"
+              "\tlevelstats  -- Print the number of files and bytes per level\n"
+              "\tsstables    -- Print sstable info\n"
+              "\theapprofile -- Dump a heap profile (if supported by this"
+              " port)\n");
+
+DEFINE_int64(num, 1000000, "Number of key/values to place in database");
+
+DEFINE_int64(numdistinct, 1000,
+             "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");
+
+DEFINE_int64(reads, -1, "Number of read operations to do.  "
+             "If negative, do FLAGS_num reads.");
+
+DEFINE_int64(read_range, 1, "When ==1 reads use ::Get, when >1 reads use"
+             " an iterator");
+
+DEFINE_bool(use_prefix_blooms, false, "Whether to place prefixes in blooms");
+
+DEFINE_bool(use_prefix_api, false, "Whether to set ReadOptions.prefix for"
+            " prefixscanrandom. If true, use_prefix_blooms must also be true.");
+
+DEFINE_int64(seed, 0, "Seed base for random number generators. "
+             "When 0 it is deterministic.");
+
+DEFINE_int32(threads, 1, "Number of concurrent threads to run.");
+
+DEFINE_int32(duration, 0, "Time in seconds for the random-ops tests to run."
+             " When 0 then num & reads determine the test duration");
+
+DEFINE_int32(value_size, 100, "Size of each value");
+
+
+// the maximum size of key in bytes
+static const int kMaxKeySize = 128;
+static bool ValidateKeySize(const char* flagname, int32_t value) {
+  if (value > kMaxKeySize) {
+    fprintf(stderr, "Invalid value for --%s: %d, must be < %d\n",
+            flagname, value, kMaxKeySize);
+    return false;
+  }
+  return true;
+}
+DEFINE_int32(key_size, 16, "size of each key");
+static const bool FLAGS_key_size_dummy =
+  google::RegisterFlagValidator(&FLAGS_key_size, &ValidateKeySize);
+
+DEFINE_double(compression_ratio, 0.5, "Arrange to generate values that shrink"
+              " to this fraction of their original size after compression");
+
+DEFINE_bool(histogram, false, "Print histogram of operation timings");
+
+DEFINE_int32(write_buffer_size, rocksdb::Options().write_buffer_size,
+             "Number of bytes to buffer in memtable before compacting");
+
+DEFINE_int32(max_write_buffer_number,
+             rocksdb::Options().max_write_buffer_number,
+             "The number of in-memory memtables. Each memtable is of size"
+             "write_buffer_size.");
+
+DEFINE_int32(min_write_buffer_number_to_merge,
+             rocksdb::Options().min_write_buffer_number_to_merge,
+             "The minimum number of write buffers that will be merged together"
+             "before writing to storage. This is cheap because it is an"
+             "in-memory merge. If this feature is not enabled, then all these"
+             "write buffers are flushed to L0 as separate files and this "
+             "increases read amplification because a get request has to check"
+             " in all of these files. Also, an in-memory merge may result in"
+             " writing less data to storage if there are duplicate records "
+             " in each of these individual write buffers.");
+
+DEFINE_int32(max_background_compactions,
+             rocksdb::Options().max_background_compactions,
+             "The maximum number of concurrent background compactions"
+             " that can occur in parallel.");
+
+static rocksdb::CompactionStyle FLAGS_compaction_style_e;
+DEFINE_int32(compaction_style, (int32_t) rocksdb::Options().compaction_style,
+             "style of compaction: level-based vs universal");
+
+DEFINE_int32(universal_size_ratio, 0,
+             "Percentage flexibility while comparing file size"
+             " (for universal compaction only).");
+
+DEFINE_int32(universal_min_merge_width, 0, "The minimum number of files in a"
+             " single compaction run (for universal compaction only).");
+
+DEFINE_int32(universal_max_merge_width, 0, "The max number of files to compact"
+             " in universal style compaction");
+
+DEFINE_int32(universal_max_size_amplification_percent, 0,
+             "The max size amplification for universal style compaction");
+
+DEFINE_int64(cache_size, -1, "Number of bytes to use as a cache of uncompressed"
+             "data. Negative means use default settings.");
+
+DEFINE_int32(block_size, rocksdb::Options().block_size,
+             "Number of bytes in a block.");
+
+DEFINE_int64(compressed_cache_size, -1,
+             "Number of bytes to use as a cache of compressed data.");
+
+DEFINE_int32(open_files, rocksdb::Options().max_open_files,
+             "Maximum number of files to keep open at the same time"
+             " (use default if == 0)");
+
+DEFINE_int32(bloom_bits, -1, "Bloom filter bits per key. Negative means"
+             " use default settings.");
+
+DEFINE_bool(use_existing_db, false, "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.");
+
+DEFINE_string(db, "", "Use the db with the following name.");
+
+static bool ValidateCacheNumshardbits(const char* flagname, int32_t value) {
+  if (value >= 20) {
+    fprintf(stderr, "Invalid value for --%s: %d, must be < 20\n",
+            flagname, value);
+    return false;
+  }
+  return true;
+}
+DEFINE_int32(cache_numshardbits, -1, "Number of shards for the block cache"
+             " is 2 ** cache_numshardbits. Negative means use default settings."
+             " This is applied only if FLAGS_cache_size is non-negative.");
+static const bool FLAGS_cache_numshardbits_dummy =
+  google::RegisterFlagValidator(&FLAGS_cache_numshardbits,
+                                &ValidateCacheNumshardbits);
+
+DEFINE_int32(cache_remove_scan_count_limit, 32, "");
+
+DEFINE_bool(verify_checksum, false, "Verify checksum for every block read"
+            " from storage");
+
+DEFINE_bool(statistics, false, "Database statistics");
+static class std::shared_ptr<rocksdb::Statistics> dbstats;
+
+DEFINE_int64(writes, -1, "Number of write operations to do. If negative, do"
+             " --num reads.");
+
+DEFINE_int32(writes_per_second, 0, "Per-thread rate limit on writes per second."
+             " No limit when <= 0. Only for the readwhilewriting test.");
+
+DEFINE_bool(sync, false, "Sync all writes to disk");
+
+DEFINE_bool(disable_data_sync, false, "If true, do not wait until data is"
+            " synced to disk.");
+
+DEFINE_bool(use_fsync, false, "If true, issue fsync instead of fdatasync");
+
+DEFINE_bool(disable_wal, false, "If true, do not write WAL for write.");
+
+DEFINE_bool(use_snapshot, false, "If true, create a snapshot per query when"
+            " randomread benchmark is used");
+
+DEFINE_bool(get_approx, false, "If true, call GetApproximateSizes per query"
+            " when read_range is > 1 and randomread benchmark is used");
+
+DEFINE_int32(num_levels, 7, "The total number of levels");
+
+DEFINE_int32(target_file_size_base, 2 * 1048576, "Target file size at level-1");
+
+DEFINE_int32(target_file_size_multiplier, 1,
+             "A multiplier to compute target level-N file size (N >= 2)");
+
+DEFINE_uint64(max_bytes_for_level_base,  10 * 1048576, "Max bytes for level-1");
+
+DEFINE_int32(max_bytes_for_level_multiplier, 10,
+             "A multiplier to compute max bytes for level-N (N >= 2)");
+
+static std::vector<int> FLAGS_max_bytes_for_level_multiplier_additional_v;
+DEFINE_string(max_bytes_for_level_multiplier_additional, "",
+              "A vector that specifies additional fanout per level");
+
+DEFINE_int32(level0_stop_writes_trigger, 12, "Number of files in level-0"
+             " that will trigger put stop.");
+
+DEFINE_int32(level0_slowdown_writes_trigger, 8, "Number of files in level-0"
+             " that will slow down writes.");
+
+DEFINE_int32(level0_file_num_compaction_trigger, 4, "Number of files in level-0"
+             " when compactions start");
+
+static bool ValidateInt32Percent(const char* flagname, int32_t value) {
+  if (value <= 0 || value>=100) {
+    fprintf(stderr, "Invalid value for --%s: %d, 0< pct <100 \n",
+            flagname, value);
+    return false;
+  }
+  return true;
+}
+DEFINE_int32(readwritepercent, 90, "Ratio of reads to reads/writes (expressed"
+             " as percentage) for the ReadRandomWriteRandom workload. The "
+             "default value 90 means 90% operations out of all reads and writes"
+             " operations are reads. In other words, 9 gets for every 1 put.");
+static const bool FLAGS_readwritepercent_dummy =
+  google::RegisterFlagValidator(&FLAGS_readwritepercent, &ValidateInt32Percent);
+
+DEFINE_int32(deletepercent, 2, "Percentage of deletes out of reads/writes/"
+             "deletes (used in RandomWithVerify only). RandomWithVerify "
+             "calculates writepercent as (100 - FLAGS_readwritepercent - "
+             "deletepercent), so deletepercent must be smaller than (100 - "
+             "FLAGS_readwritepercent)");
+static const bool FLAGS_deletepercent_dummy =
+  google::RegisterFlagValidator(&FLAGS_deletepercent, &ValidateInt32Percent);
+
+DEFINE_int32(disable_seek_compaction, false, "Option to disable compaction"
+             " triggered by read.");
+
+DEFINE_uint64(delete_obsolete_files_period_micros, 0, "Option to delete "
+              "obsolete files periodically. 0 means that obsolete files are"
+              " deleted after every compaction run.");
+
+enum rocksdb::CompressionType StringToCompressionType(const char* ctype) {
+  assert(ctype);
+
+  if (!strcasecmp(ctype, "none"))
+    return rocksdb::kNoCompression;
+  else if (!strcasecmp(ctype, "snappy"))
+    return rocksdb::kSnappyCompression;
+  else if (!strcasecmp(ctype, "zlib"))
+    return rocksdb::kZlibCompression;
+  else if (!strcasecmp(ctype, "bzip2"))
+    return rocksdb::kBZip2Compression;
+
+  fprintf(stdout, "Cannot parse compression type '%s'\n", ctype);
+  return rocksdb::kSnappyCompression; //default value
+}
+DEFINE_string(compression_type, "snappy",
+              "Algorithm to use to compress the database");
+static enum rocksdb::CompressionType FLAGS_compression_type_e =
+    rocksdb::kSnappyCompression;
+
+DEFINE_int32(min_level_to_compress, -1, "If non-negative, compression starts"
+             " from this level. Levels with number < min_level_to_compress are"
+             " not compressed. Otherwise, apply compression_type to "
+             "all levels.");
+
+static bool ValidateTableCacheNumshardbits(const char* flagname,
+                                           int32_t value) {
+  if (0 >= value || value > 20) {
+    fprintf(stderr, "Invalid value for --%s: %d, must be  0 < val <= 20\n",
+            flagname, value);
+    return false;
+  }
+  return true;
+}
+DEFINE_int32(table_cache_numshardbits, 4, "");
+static const bool FLAGS_table_cache_numshardbits_dummy =
+  google::RegisterFlagValidator(&FLAGS_table_cache_numshardbits,
+                                &ValidateTableCacheNumshardbits);
+
+DEFINE_string(hdfs, "", "Name of hdfs environment");
+// posix or hdfs environment
+static rocksdb::Env* FLAGS_env = rocksdb::Env::Default();
+
+DEFINE_int64(stats_interval, 0, "Stats are reported every N operations when "
+             "this is greater than zero. When 0 the interval grows over time.");
+
+DEFINE_int32(stats_per_interval, 0, "Reports additional stats per interval when"
+             " this is greater than 0.");
+
+static bool ValidateRateLimit(const char* flagname, double value) {
+  static constexpr double EPSILON = 1e-10;
+  if ( value < -EPSILON ) {
+    fprintf(stderr, "Invalid value for --%s: %12.6f, must be >= 0.0\n",
+            flagname, value);
+    return false;
+  }
+  return true;
+}
+DEFINE_double(soft_rate_limit, 0.0, "");
+static const bool FLAGS_soft_rate_limit_dummy =
+  google::RegisterFlagValidator(&FLAGS_soft_rate_limit, &ValidateRateLimit);
+
+DEFINE_double(hard_rate_limit, 0.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 const bool FLAGS_hard_rate_limit_dummy =
+  google::RegisterFlagValidator(&FLAGS_hard_rate_limit, &ValidateRateLimit);
+
+DEFINE_int32(rate_limit_delay_max_milliseconds, 1000,
+             "When hard_rate_limit is set then this is the max time a put will"
+             " be stalled.");
+
+DEFINE_int32(max_grandparent_overlap_factor, 10, "Control maximum bytes of "
+             "overlaps in grandparent (i.e., level+2) before we stop building a"
+             " single file in a level->level+1 compaction.");
+
+DEFINE_bool(readonly, false, "Run read only benchmarks.");
+
+DEFINE_bool(disable_auto_compactions, false, "Do not auto trigger compactions");
+
+DEFINE_int32(source_compaction_factor, 1, "Cap the size of data in level-K for"
+             " a compaction run that compacts Level-K with Level-(K+1) (for"
+             " K >= 1)");
+
+DEFINE_uint64(wal_ttl_seconds, 0, "Set the TTL for the WAL Files in seconds.");
+DEFINE_uint64(wal_size_limit_MB, 0, "Set the size limit for the WAL Files"
+              " in MB.");
+
+DEFINE_bool(bufferedio, rocksdb::EnvOptions().use_os_buffer,
+            "Allow buffered io using OS buffers");
+
+DEFINE_bool(mmap_read, rocksdb::EnvOptions().use_mmap_reads,
+            "Allow reads to occur via mmap-ing files");
+
+DEFINE_bool(mmap_write, rocksdb::EnvOptions().use_mmap_writes,
+            "Allow writes to occur via mmap-ing files");
+
+DEFINE_bool(advise_random_on_open, rocksdb::Options().advise_random_on_open,
+            "Advise random access on table file open");
+
+DEFINE_string(compaction_fadvice, "NORMAL",
+              "Access pattern advice when a file is compacted");
+static auto FLAGS_compaction_fadvice_e =
+  rocksdb::Options().access_hint_on_compaction_start;
+
+DEFINE_bool(use_multiget, false,
+            "Use multiget to access a series of keys instead of get");
+
+DEFINE_int64(keys_per_multiget, 90, "If use_multiget is true, determines number"
+             " of keys to group per call Arbitrary default is good because it"
+             " agrees with readwritepercent");
+
+// TODO: Apply this flag to generic Get calls too. Currently only with Multiget
+DEFINE_bool(warn_missing_keys, true, "Print a message to user when a key is"
+            " missing in a Get/MultiGet call");
+
+DEFINE_bool(use_adaptive_mutex, rocksdb::Options().use_adaptive_mutex,
+            "Use adaptive mutex");
+
+DEFINE_uint64(bytes_per_sync,  rocksdb::Options().bytes_per_sync,
+              "Allows OS to incrementally sync files to disk while they are"
+              " being written, in the background. Issue one request for every"
+              " bytes_per_sync written. 0 turns it off.");
+DEFINE_bool(filter_deletes, false, " On true, deletes use bloom-filter and drop"
+            " the delete if key not present");
+
+static bool ValidatePrefixSize(const char* flagname, int32_t value) {
+  if (value < 0 || value>=2000000000) {
+    fprintf(stderr, "Invalid value for --%s: %d. 0<= PrefixSize <=2000000000\n",
+            flagname, value);
+    return false;
+  }
+  return true;
+}
+DEFINE_int32(prefix_size, 0, "Control the prefix size for PrefixHashRep");
+static const bool FLAGS_prefix_size_dummy =
+  google::RegisterFlagValidator(&FLAGS_prefix_size, &ValidatePrefixSize);
+
+enum RepFactory {
+  kSkipList,
+  kPrefixHash,
+  kUnsorted,
+  kVectorRep
+};
+enum RepFactory StringToRepFactory(const char* ctype) {
+  assert(ctype);
+
+  if (!strcasecmp(ctype, "skip_list"))
+    return kSkipList;
+  else if (!strcasecmp(ctype, "prefix_hash"))
+    return kPrefixHash;
+  else if (!strcasecmp(ctype, "unsorted"))
+    return kUnsorted;
+  else if (!strcasecmp(ctype, "vector"))
+    return kVectorRep;
+
+  fprintf(stdout, "Cannot parse memreptable %s\n", ctype);
+  return kSkipList;
+}
+static enum RepFactory FLAGS_rep_factory;
+DEFINE_string(memtablerep, "skip_list", "");
+
+DEFINE_string(merge_operator, "", "The merge operator to use with the database."
+              "If a new merge operator is specified, be sure to use fresh"
+              " database The possible merge operators are defined in"
+              " utilities/merge_operators.h");
+
+namespace rocksdb {
+
+// 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() < (unsigned)std::max(1048576, FLAGS_value_size)) {
+      // 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(unsigned 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 long done_;
+  long long last_report_done_;
+  long long next_report_;
+  int64_t bytes_;
+  double last_op_finish_;
+  double last_report_finish_;
+  HistogramImpl hist_;
+  std::string message_;
+  bool exclude_from_merge_;
+
+ 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();
+    // When set, stats from this thread won't be merged with others.
+    exclude_from_merge_ = false;
+  }
+
+  void Merge(const Stats& other) {
+    if (other.exclude_from_merge_)
+      return;
+
+    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 SetExcludeFromMerge() { exclude_from_merge_ = true; }
+
+  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 %lld ops%30s\r", done_, "");
+        fflush(stderr);
+      } else {
+        double now = FLAGS_env->NowMicros();
+        fprintf(stderr,
+                "%s ... thread %d: (%lld,%lld) 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("rocksdb.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(),
+            elapsed * 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
+  Random64 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 Duration {
+ public:
+  Duration(int max_seconds, long long max_ops) {
+    max_seconds_ = max_seconds;
+    max_ops_= max_ops;
+    ops_ = 0;
+    start_at_ = FLAGS_env->NowMicros();
+  }
+
+  bool Done(int increment) {
+    if (increment <= 0) increment = 1;    // avoid Done(0) and infinite loops
+    ops_ += increment;
+
+    if (max_seconds_) {
+      // Recheck every appx 1000 ops (exact iff increment is factor of 1000)
+      if ((ops_/1000) != ((ops_-increment)/1000)) {
+        double now = FLAGS_env->NowMicros();
+        return ((now - start_at_) / 1000000.0) >= max_seconds_;
+      } else {
+        return false;
+      }
+    } else {
+      return ops_ > max_ops_;
+    }
+  }
+
+ private:
+  int max_seconds_;
+  long long max_ops_;
+  long long ops_;
+  double start_at_;
+};
+
+class Benchmark {
+ private:
+  shared_ptr<Cache> cache_;
+  shared_ptr<Cache> compressed_cache_;
+  const FilterPolicy* filter_policy_;
+  const SliceTransform* prefix_extractor_;
+  DB* db_;
+  long long num_;
+  int value_size_;
+  int key_size_;
+  int entries_per_batch_;
+  WriteOptions write_options_;
+  long long reads_;
+  long long writes_;
+  long long readwrites_;
+  int heap_counter_;
+  char keyFormat_[100]; // 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<int>(FLAGS_value_size * FLAGS_compression_ratio + 0.5));
+    fprintf(stdout, "Entries:    %lld\n", num_);
+    fprintf(stdout, "RawSize:    %.1f MB (estimated)\n",
+            ((static_cast<int64_t>(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));
+    fprintf(stdout, "Write rate limit: %d\n", FLAGS_writes_per_second);
+    switch (FLAGS_compression_type_e) {
+      case rocksdb::kNoCompression:
+        fprintf(stdout, "Compression: none\n");
+        break;
+      case rocksdb::kSnappyCompression:
+        fprintf(stdout, "Compression: snappy\n");
+        break;
+      case rocksdb::kZlibCompression:
+        fprintf(stdout, "Compression: zlib\n");
+        break;
+      case rocksdb::kBZip2Compression:
+        fprintf(stdout, "Compression: bzip2\n");
+        break;
+    }
+
+    switch (FLAGS_rep_factory) {
+      case kPrefixHash:
+        fprintf(stdout, "Memtablerep: prefix_hash\n");
+        break;
+      case kSkipList:
+        fprintf(stdout, "Memtablerep: skip_list\n");
+        break;
+      case kUnsorted:
+        fprintf(stdout, "Memtablerep: unsorted\n");
+        break;
+      case kVectorRep:
+        fprintf(stdout, "Memtablerep: vector\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_e != rocksdb::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_e) {
+        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
+  }
+
+ public:
+  Benchmark()
+  : cache_(FLAGS_cache_size >= 0 ?
+           (FLAGS_cache_numshardbits >= 1 ?
+            NewLRUCache(FLAGS_cache_size, FLAGS_cache_numshardbits,
+                        FLAGS_cache_remove_scan_count_limit) :
+            NewLRUCache(FLAGS_cache_size)) : nullptr),
+    compressed_cache_(FLAGS_compressed_cache_size >= 0 ?
+           (FLAGS_cache_numshardbits >= 1 ?
+            NewLRUCache(FLAGS_compressed_cache_size, FLAGS_cache_numshardbits) :
+            NewLRUCache(FLAGS_compressed_cache_size)) : nullptr),
+    filter_policy_(FLAGS_bloom_bits >= 0
+                   ? NewBloomFilterPolicy(FLAGS_bloom_bits)
+                   : nullptr),
+    prefix_extractor_(NewFixedPrefixTransform(FLAGS_key_size-1)),
+    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<std::string> 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(FLAGS_db + "/" + files[i]);
+      }
+    }
+    if (!FLAGS_use_existing_db) {
+      DestroyDB(FLAGS_db, Options());
+    }
+  }
+
+  ~Benchmark() {
+    delete db_;
+    delete filter_policy_;
+    delete prefix_extractor_;
+  }
+
+  //this function will construct string format for key. e.g "%016lld"
+  void ConstructStrFormatForKey(char* str, int keySize) {
+    str[0] = '%';
+    str[1] = '0';
+    sprintf(str+2, "%dlld%s", keySize, "%s");
+  }
+
+  unique_ptr<char []> GenerateKeyFromInt(long long v, const char* suffix = "") {
+    unique_ptr<char []> keyInStr(new char[kMaxKeySize]);
+    snprintf(keyInStr.get(), kMaxKeySize, keyFormat_, v, suffix);
+    return keyInStr;
+  }
+
+  void Run() {
+    PrintHeader();
+    Open();
+    const char* benchmarks = FLAGS_benchmarks.c_str();
+    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;
+      }
+
+      // Sanitize parameters
+      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("fillfromstdin")) {
+        fresh_db = true;
+        method = &Benchmark::WriteFromStdin;
+      } else if (name == Slice("filluniquerandom")) {
+        fresh_db = true;
+        if (num_threads > 1) {
+          fprintf(stderr, "filluniquerandom multithreaded not supported"
+                           " set --threads=1");
+          exit(1);
+        }
+        method = &Benchmark::WriteUniqueRandom;
+      } 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("prefixscanrandom")) {
+        method = &Benchmark::PrefixScanRandom;
+      } 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("updaterandom")) {
+        method = &Benchmark::UpdateRandom;
+      } else if (name == Slice("appendrandom")) {
+        method = &Benchmark::AppendRandom;
+      } else if (name == Slice("mergerandom")) {
+        if (FLAGS_merge_operator.empty()) {
+          fprintf(stdout, "%-12s : skipped (--merge_operator is unknown)\n",
+                  name.ToString().c_str());
+          method = nullptr;
+        } else {
+          method = &Benchmark::MergeRandom;
+        }
+      } 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("rocksdb.stats");
+      } else if (name == Slice("levelstats")) {
+        PrintStats("rocksdb.levelstats");
+      } else if (name == Slice("sstables")) {
+        PrintStats("rocksdb.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) {
+        fprintf(stdout, "DB path: [%s]\n", FLAGS_db.c_str());
+        RunBenchmark(num_threads, name, method);
+      }
+    }
+    if (FLAGS_statistics) {
+     fprintf(stdout, "STATISTICS:\n%s\n", dbstats->ToString().c_str());
+    }
+  }
+
+ private:
+  struct ThreadArg {
+    Benchmark* bm;
+    SharedState* shared;
+    ThreadState* thread;
+    void (Benchmark::*method)(ThreadState*);
+  };
+
+  static void ThreadBody(void* v) {
+    ThreadArg* arg = reinterpret_cast<ThreadArg*>(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();
+
+    // Stats for some threads can be excluded.
+    Stats merge_stats;
+    for (int i = 0; i < n; i++) {
+      merge_stats.Merge(arg[i].thread->stats);
+    }
+    merge_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<unsigned int>(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_;
+    options.block_cache_compressed = compressed_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.min_write_buffer_number_to_merge =
+      FLAGS_min_write_buffer_number_to_merge;
+    options.max_background_compactions = FLAGS_max_background_compactions;
+    options.compaction_style = FLAGS_compaction_style_e;
+    options.block_size = FLAGS_block_size;
+    options.filter_policy = filter_policy_;
+    options.prefix_extractor = FLAGS_use_prefix_blooms ? prefix_extractor_
+                                                       : nullptr;
+    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.filter_deletes = FLAGS_filter_deletes;
+    if ((FLAGS_prefix_size == 0) == (FLAGS_rep_factory == kPrefixHash)) {
+      fprintf(stderr,
+            "prefix_size should be non-zero iff memtablerep == prefix_hash\n");
+      exit(1);
+    }
+    switch (FLAGS_rep_factory) {
+      case kPrefixHash:
+        options.memtable_factory.reset(
+          new PrefixHashRepFactory(NewFixedPrefixTransform(FLAGS_prefix_size))
+        );
+        break;
+      case kUnsorted:
+        options.memtable_factory.reset(
+          new UnsortedRepFactory
+        );
+        break;
+      case kSkipList:
+        // no need to do anything
+        break;
+      case kVectorRep:
+        options.memtable_factory.reset(
+          new VectorRepFactory
+        );
+        break;
+    }
+    if (FLAGS_max_bytes_for_level_multiplier_additional_v.size() > 0) {
+      if (FLAGS_max_bytes_for_level_multiplier_additional_v.size() !=
+          (unsigned int)FLAGS_num_levels) {
+        fprintf(stderr, "Insufficient number of fanouts specified %d\n",
+                (int)FLAGS_max_bytes_for_level_multiplier_additional_v.size());
+        exit(1);
+      }
+      options.max_bytes_for_level_multiplier_additional =
+        FLAGS_max_bytes_for_level_multiplier_additional_v;
+    }
+    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_e;
+    options.WAL_ttl_seconds = FLAGS_wal_ttl_seconds;
+    options.WAL_size_limit_MB = FLAGS_wal_size_limit_MB;
+    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 (int i = FLAGS_min_level_to_compress;
+           i < FLAGS_num_levels; i++) {
+        options.compression_per_level[i] = FLAGS_compression_type_e;
+      }
+    }
+    options.disable_seek_compaction = FLAGS_disable_seek_compaction;
+    options.delete_obsolete_files_period_micros =
+      FLAGS_delete_obsolete_files_period_micros;
+    options.soft_rate_limit = FLAGS_soft_rate_limit;
+    options.hard_rate_limit = FLAGS_hard_rate_limit;
+    options.rate_limit_delay_max_milliseconds =
+      FLAGS_rate_limit_delay_max_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;
+
+    // fill storage options
+    options.allow_os_buffer = FLAGS_bufferedio;
+    options.allow_mmap_reads = FLAGS_mmap_read;
+    options.allow_mmap_writes = FLAGS_mmap_write;
+    options.advise_random_on_open = FLAGS_advise_random_on_open;
+    options.access_hint_on_compaction_start = FLAGS_compaction_fadvice_e;
+    options.use_adaptive_mutex = FLAGS_use_adaptive_mutex;
+    options.bytes_per_sync = FLAGS_bytes_per_sync;
+
+    // merge operator options
+    options.merge_operator = MergeOperators::CreateFromStringId(
+        FLAGS_merge_operator);
+    if (options.merge_operator == nullptr && !FLAGS_merge_operator.empty()) {
+      fprintf(stderr, "invalid merge operator: %s\n",
+              FLAGS_merge_operator.c_str());
+      exit(1);
+    }
+
+    // set universal style compaction configurations, if applicable
+    if (FLAGS_universal_size_ratio != 0) {
+      options.compaction_options_universal.size_ratio =
+        FLAGS_universal_size_ratio;
+    }
+    if (FLAGS_universal_min_merge_width != 0) {
+      options.compaction_options_universal.min_merge_width =
+        FLAGS_universal_min_merge_width;
+    }
+    if (FLAGS_universal_max_merge_width != 0) {
+      options.compaction_options_universal.max_merge_width =
+        FLAGS_universal_max_merge_width;
+    }
+    if (FLAGS_universal_max_size_amplification_percent != 0) {
+      options.compaction_options_universal.max_size_amplification_percent =
+        FLAGS_universal_max_size_amplification_percent;
+    }
+
+    Status s;
+    if(FLAGS_readonly) {
+      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();
+    }
+  }
+
+  enum WriteMode {
+    RANDOM, SEQUENTIAL, UNIQUE_RANDOM
+  };
+
+  void WriteSeq(ThreadState* thread) {
+    DoWrite(thread, SEQUENTIAL);
+  }
+
+  void WriteRandom(ThreadState* thread) {
+    DoWrite(thread, RANDOM);
+  }
+
+  void WriteUniqueRandom(ThreadState* thread) {
+    DoWrite(thread, UNIQUE_RANDOM);
+  }
+
+  void writeOrFail(WriteBatch& batch) {
+    Status s = db_->Write(write_options_, &batch);
+    if (!s.ok()) {
+      fprintf(stderr, "put error: %s\n", s.ToString().c_str());
+      exit(1);
+    }
+  }
+
+  void WriteFromStdin(ThreadState* thread) {
+    size_t count = 0;
+    WriteBatch batch;
+    const size_t bufferLen = 32 << 20;
+    unique_ptr<char[]> line = unique_ptr<char[]>(new char[bufferLen]);
+    char* linep = line.get();
+    const int batchSize = 100 << 10;
+    const char columnSeparator = '\t';
+    const char lineSeparator = '\n';
+
+    while (fgets(linep, bufferLen, stdin) != nullptr) {
+      ++count;
+      char* tab = std::find(linep, linep + bufferLen, columnSeparator);
+      if (tab == linep + bufferLen) {
+        fprintf(stderr, "[Error] No Key delimiter TAB at line %ld\n", count);
+        continue;
+      }
+      Slice key(linep, tab - linep);
+      tab++;
+      char* endLine = std::find(tab, linep + bufferLen, lineSeparator);
+      if (endLine  == linep + bufferLen) {
+        fprintf(stderr, "[Error] No ENTER at end of line # %ld\n", count);
+        continue;
+      }
+      Slice value(tab, endLine - tab);
+      thread->stats.FinishedSingleOp(db_);
+      thread->stats.AddBytes(endLine - linep - 1);
+
+      if (batch.Count() < batchSize) {
+        batch.Put(key, value);
+        continue;
+      }
+      writeOrFail(batch);
+      batch.Clear();
+    }
+    if (batch.Count() > 0) {
+      writeOrFail(batch);
+    }
+  }
+
+  void DoWrite(ThreadState* thread, WriteMode write_mode) {
+    const int test_duration = write_mode == RANDOM ? FLAGS_duration : 0;
+    const int num_ops = writes_ == 0 ? num_ : writes_ ;
+    Duration duration(test_duration, num_ops);
+    unique_ptr<BitSet> bit_set;
+
+    if (write_mode == UNIQUE_RANDOM) {
+      bit_set.reset(new BitSet(num_ops));
+    }
+
+    if (num_ != FLAGS_num) {
+      char msg[100];
+      snprintf(msg, sizeof(msg), "(%lld ops)", num_);
+      thread->stats.AddMessage(msg);
+    }
+
+    RandomGenerator gen;
+    WriteBatch batch;
+    Status s;
+    int64_t bytes = 0;
+    int i = 0;
+    while (!duration.Done(entries_per_batch_)) {
+      batch.Clear();
+      for (int j = 0; j < entries_per_batch_; j++) {
+        long long k = 0;
+        switch(write_mode) {
+          case SEQUENTIAL:
+            k = i +j;
+            break;
+          case RANDOM:
+            k = thread->rand.Next() % FLAGS_num;
+            break;
+          case UNIQUE_RANDOM:
+            {
+              const long long t = thread->rand.Next() % FLAGS_num;
+              if (!bit_set->test(t)) {
+                // best case
+                k = t;
+              } else {
+                bool found = false;
+                // look forward
+                for (size_t i = t + 1; i < bit_set->size(); ++i) {
+                  if (!bit_set->test(i)) {
+                    found = true;
+                    k = i;
+                    break;
+                  }
+                }
+                if (!found) {
+                  for (size_t i = t; i-- > 0;) {
+                    if (!bit_set->test(i)) {
+                      found = true;
+                      k = i;
+                      break;
+                    }
+                  }
+                }
+              }
+              bit_set->set(k);
+              break;
+            }
+        };
+        unique_ptr<char []> 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);
+      }
+      i += entries_per_batch_;
+    }
+    thread->stats.AddBytes(bytes);
+  }
+
+  void ReadSequential(ThreadState* thread) {
+    Iterator* iter = db_->NewIterator(ReadOptions(FLAGS_verify_checksum, true));
+    long 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 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);
+  }
+
+  // Calls MultiGet over a list of keys from a random distribution.
+  // Returns the total number of keys found.
+  long MultiGetRandom(ReadOptions& options, int num_keys,
+                     Random64& rand, long long range, const char* suffix) {
+    assert(num_keys > 0);
+    std::vector<Slice> keys(num_keys);
+    std::vector<std::string> values(num_keys);
+    std::vector<unique_ptr<char []> > gen_keys(num_keys);
+
+    int i;
+    long long k;
+
+    // Fill the keys vector
+    for(i=0; i<num_keys; ++i) {
+      k = rand.Next() % range;
+      gen_keys[i] = GenerateKeyFromInt(k,suffix);
+      keys[i] = gen_keys[i].get();
+    }
+
+    if (FLAGS_use_snapshot) {
+      options.snapshot = db_->GetSnapshot();
+    }
+
+    // Apply the operation
+    std::vector<Status> statuses = db_->MultiGet(options, keys, &values);
+    assert((long)statuses.size() == num_keys);
+    assert((long)keys.size() == num_keys);  // Should always be the case.
+    assert((long)values.size() == num_keys);
+
+    if (FLAGS_use_snapshot) {
+      db_->ReleaseSnapshot(options.snapshot);
+      options.snapshot = nullptr;
+    }
+
+    // Count number found
+    long found = 0;
+    for(i=0; i<num_keys; ++i) {
+      if (statuses[i].ok()){
+        ++found;
+      } else if (FLAGS_warn_missing_keys == true) {
+        // Key not found, or error.
+        fprintf(stderr, "get error: %s\n", statuses[i].ToString().c_str());
+      }
+    }
+
+    return found;
+  }
+
+  void ReadRandom(ThreadState* thread) {
+    ReadOptions options(FLAGS_verify_checksum, true);
+    Duration duration(FLAGS_duration, reads_);
+
+    long long found = 0;
+
+    if (FLAGS_use_multiget) {   // MultiGet
+      const long& kpg = FLAGS_keys_per_multiget;  // keys per multiget group
+      long keys_left = reads_;
+
+      // Recalculate number of keys per group, and call MultiGet until done
+      long num_keys;
+      while(num_keys = std::min(keys_left, kpg), !duration.Done(num_keys)) {
+        found += MultiGetRandom(options, num_keys, thread->rand, FLAGS_num, "");
+        thread->stats.FinishedSingleOp(db_);
+        keys_left -= num_keys;
+      }
+    } else {    // Regular case. Do one "get" at a time Get
+      Iterator* iter = db_->NewIterator(options);
+      std::string value;
+      while (!duration.Done(1)) {
+        const long long k = thread->rand.Next() % FLAGS_num;
+        unique_ptr<char []> key = GenerateKeyFromInt(k);
+        if (FLAGS_use_snapshot) {
+          options.snapshot = db_->GetSnapshot();
+        }
+
+        if (FLAGS_read_range < 2) {
+          if (db_->Get(options, key.get(), &value).ok()) {
+            found++;
+          }
+        } else {
+          Slice skey(key.get());
+          int count = 1;
+
+          if (FLAGS_get_approx) {
+            unique_ptr<char []> key2 =
+                GenerateKeyFromInt(k + (int) FLAGS_read_range);
+            Slice skey2(key2.get());
+            Range range(skey, skey2);
+            uint64_t sizes;
+            db_->GetApproximateSizes(&range, 1, &sizes);
+          }
+
+          for (iter->Seek(skey);
+               iter->Valid() && count <= FLAGS_read_range;
+               ++count, iter->Next()) {
+            found++;
+          }
+        }
+
+        if (FLAGS_use_snapshot) {
+          db_->ReleaseSnapshot(options.snapshot);
+          options.snapshot = nullptr;
+        }
+
+        thread->stats.FinishedSingleOp(db_);
+      }
+
+      delete iter;
+    }
+
+    char msg[100];
+    snprintf(msg, sizeof(msg), "(%lld of %lld found)", found, reads_);
+    thread->stats.AddMessage(msg);
+  }
+
+  void PrefixScanRandom(ThreadState* thread) {
+    if (FLAGS_use_prefix_api) {
+      assert(FLAGS_use_prefix_blooms);
+      assert(FLAGS_bloom_bits >= 1);
+    }
+
+    ReadOptions options(FLAGS_verify_checksum, true);
+    Duration duration(FLAGS_duration, reads_);
+
+    long long found = 0;
+
+    while (!duration.Done(1)) {
+      std::string value;
+      const int k = thread->rand.Next() % FLAGS_num;
+      unique_ptr<char []> key = GenerateKeyFromInt(k);
+      Slice skey(key.get());
+      Slice prefix = prefix_extractor_->Transform(skey);
+      options.prefix = FLAGS_use_prefix_api ? &prefix : nullptr;
+
+      Iterator* iter = db_->NewIterator(options);
+      for (iter->Seek(skey);
+           iter->Valid() && iter->key().starts_with(prefix);
+           iter->Next()) {
+        found++;
+      }
+      delete iter;
+
+      thread->stats.FinishedSingleOp(db_);
+    }
+
+    char msg[100];
+    snprintf(msg, sizeof(msg), "(%lld of %lld found)", found, reads_);
+    thread->stats.AddMessage(msg);
+  }
+
+  void ReadMissing(ThreadState* thread) {
+    FLAGS_warn_missing_keys = false;    // Never warn about missing keys
+
+    Duration duration(FLAGS_duration, reads_);
+    ReadOptions options(FLAGS_verify_checksum, true);
+
+    if (FLAGS_use_multiget) {
+      const long& kpg = FLAGS_keys_per_multiget;  // keys per multiget group
+      long keys_left = reads_;
+
+      // Recalculate number of keys per group, and call MultiGet until done
+      long num_keys;
+      long found;
+      while(num_keys = std::min(keys_left, kpg), !duration.Done(num_keys)) {
+        found = MultiGetRandom(options, num_keys, thread->rand, FLAGS_num, ".");
+
+        // We should not find any key since the key we try to get has a
+        // different suffix
+        if (found) {
+          assert(false);
+        }
+
+        thread->stats.FinishedSingleOp(db_);
+        keys_left -= num_keys;
+      }
+    } else {  // Regular case (not MultiGet)
+      std::string value;
+      Status s;
+      while (!duration.Done(1)) {
+        const long long k = thread->rand.Next() % FLAGS_num;
+        unique_ptr<char []> key = GenerateKeyFromInt(k, ".");
+        s = db_->Get(options, key.get(), &value);
+        assert(!s.ok() && s.IsNotFound());
+        thread->stats.FinishedSingleOp(db_);
+      }
+    }
+  }
+
+  void ReadHot(ThreadState* thread) {
+    Duration duration(FLAGS_duration, reads_);
+    ReadOptions options(FLAGS_verify_checksum, true);
+    const long long range = (FLAGS_num + 99) / 100;
+    long long found = 0;
+
+    if (FLAGS_use_multiget) {
+      const long long kpg = FLAGS_keys_per_multiget;  // keys per multiget group
+      long long keys_left = reads_;
+
+      // Recalculate number of keys per group, and call MultiGet until done
+      long num_keys;
+      while(num_keys = std::min(keys_left, kpg), !duration.Done(num_keys)) {
+        found += MultiGetRandom(options, num_keys, thread->rand, range, "");
+        thread->stats.FinishedSingleOp(db_);
+        keys_left -= num_keys;
+      }
+    } else {
+      std::string value;
+      while (!duration.Done(1)) {
+        const long long k = thread->rand.Next() % range;
+        unique_ptr<char []> key = GenerateKeyFromInt(k);
+        if (db_->Get(options, key.get(), &value).ok()){
+          ++found;
+        }
+        thread->stats.FinishedSingleOp(db_);
+      }
+    }
+
+    char msg[100];
+    snprintf(msg, sizeof(msg), "(%lld of %lld found)", found, reads_);
+    thread->stats.AddMessage(msg);
+  }
+
+  void SeekRandom(ThreadState* thread) {
+    Duration duration(FLAGS_duration, reads_);
+    ReadOptions options(FLAGS_verify_checksum, true);
+    std::string value;
+    long long found = 0;
+    while (!duration.Done(1)) {
+      Iterator* iter = db_->NewIterator(options);
+      const long long k = thread->rand.Next() % FLAGS_num;
+      unique_ptr<char []> 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), "(%lld of %lld found)", found, num_);
+    thread->stats.AddMessage(msg);
+  }
+
+  void DoDelete(ThreadState* thread, bool seq) {
+    WriteBatch batch;
+    Status s;
+    Duration duration(seq ? 0 : FLAGS_duration, num_);
+    long i = 0;
+    while (!duration.Done(entries_per_batch_)) {
+      batch.Clear();
+      for (int j = 0; j < entries_per_batch_; j++) {
+        const long long k = seq ? i+j : (thread->rand.Next() % FLAGS_num);
+        unique_ptr<char []> 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);
+      }
+      ++i;
+    }
+  }
+
+  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;
+      double last = FLAGS_env->NowMicros();
+      int writes_per_second_by_10 = 0;
+      int num_writes = 0;
+
+      // --writes_per_second rate limit is enforced per 100 milliseconds
+      // intervals to avoid a burst of writes at the start of each second.
+
+      if (FLAGS_writes_per_second > 0)
+        writes_per_second_by_10 = FLAGS_writes_per_second / 10;
+
+      // Don't merge stats from this thread with the readers.
+      thread->stats.SetExcludeFromMerge();
+
+      while (true) {
+        {
+          MutexLock l(&thread->shared->mu);
+          if (thread->shared->num_done + 1 >= thread->shared->num_initialized) {
+            // Other threads have finished
+            break;
+          }
+        }
+
+        const long long k = thread->rand.Next() % FLAGS_num;
+        unique_ptr<char []> 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);
+        }
+        thread->stats.FinishedSingleOp(db_);
+
+        ++num_writes;
+        if (writes_per_second_by_10 && num_writes >= writes_per_second_by_10) {
+          double now = FLAGS_env->NowMicros();
+          double usecs_since_last = now - last;
+
+          num_writes = 0;
+          last = now;
+
+          if (usecs_since_last < 100000.0) {
+            FLAGS_env->SleepForMicroseconds(100000.0 - usecs_since_last);
+            last = FLAGS_env->NowMicros();
+          }
+        }
+      }
+    }
+  }
+
+  // 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 GetMany.
+  Status PutMany(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 GetMany.
+  Status DeleteMany(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 PutMany was used to put (K, V) into the DB.
+  Status GetMany(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 GetMany/PutMany 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.
+  // (d) Does not have a MultiGet option.
+  void RandomWithVerify(ThreadState* thread) {
+    ReadOptions options(FLAGS_verify_checksum, true);
+    RandomGenerator gen;
+    std::string value;
+    long long found = 0;
+    int get_weight = 0;
+    int put_weight = 0;
+    int delete_weight = 0;
+    long long gets_done = 0;
+    long long puts_done = 0;
+    long long deletes_done = 0;
+
+    // the number of iterations is the larger of read_ or write_
+    for (long long i = 0; i < readwrites_; i++) {
+      const long long k = thread->rand.Next() % (FLAGS_numdistinct);
+      unique_ptr<char []> key = GenerateKeyFromInt(k);
+      if (get_weight == 0 && put_weight == 0 && delete_weight == 0) {
+        // one batch completed, 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 = GetMany(options, key.get(), &value);
+        if (!s.ok() && !s.IsNotFound()) {
+          fprintf(stderr, "getmany 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 = PutMany(write_options_, key.get(),
+                           gen.Generate(value_size_));
+        if (!s.ok()) {
+          fprintf(stderr, "putmany error: %s\n", s.ToString().c_str());
+          exit(1);
+        }
+        put_weight--;
+        puts_done++;
+      } else if (delete_weight > 0) {
+        Status s = DeleteMany(write_options_, key.get());
+        if (!s.ok()) {
+          fprintf(stderr, "deletemany 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:%lld put:%lld del:%lld total:%lld found:%lld)",
+             gets_done, puts_done, deletes_done, readwrites_, found);
+    thread->stats.AddMessage(msg);
+  }
+
+  // This is different from ReadWhileWriting because it does not use
+  // an extra thread.
+  void ReadRandomWriteRandom(ThreadState* thread) {
+    if (FLAGS_use_multiget){
+      // Separate function for multiget (for ease of reading)
+      ReadRandomWriteRandomMultiGet(thread);
+      return;
+    }
+
+    ReadOptions options(FLAGS_verify_checksum, true);
+    RandomGenerator gen;
+    std::string value;
+    long long found = 0;
+    int get_weight = 0;
+    int put_weight = 0;
+    long long reads_done = 0;
+    long long writes_done = 0;
+    Duration duration(FLAGS_duration, readwrites_);
+
+    // the number of iterations is the larger of read_ or write_
+    while (!duration.Done(1)) {
+      const long long k = thread->rand.Next() % FLAGS_num;
+      unique_ptr<char []> key = GenerateKeyFromInt(k);
+      if (get_weight == 0 && put_weight == 0) {
+        // one batch completed, reinitialize for next batch
+        get_weight = FLAGS_readwritepercent;
+        put_weight = 100 - get_weight;
+      }
+      if (get_weight > 0) {
+
+        if (FLAGS_use_snapshot) {
+          options.snapshot = db_->GetSnapshot();
+        }
+
+        if (FLAGS_get_approx) {
+          char key2[100];
+          snprintf(key2, sizeof(key2), "%016lld", k + 1);
+          Slice skey2(key2);
+          Slice skey(key2);
+          Range range(skey, skey2);
+          uint64_t sizes;
+          db_->GetApproximateSizes(&range, 1, &sizes);
+        }
+
+        // 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++;
+        }
+
+        get_weight--;
+        reads_done++;
+
+        if (FLAGS_use_snapshot) {
+          db_->ReleaseSnapshot(options.snapshot);
+        }
+
+      } 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:%lld writes:%lld total:%lld found:%lld)",
+             reads_done, writes_done, readwrites_, found);
+    thread->stats.AddMessage(msg);
+  }
+
+  // ReadRandomWriteRandom (with multiget)
+  // Does FLAGS_keys_per_multiget reads (per multiget), followed by some puts.
+  // FLAGS_readwritepercent will specify the ratio of gets to puts.
+  // e.g.: If FLAGS_keys_per_multiget == 100 and FLAGS_readwritepercent == 75
+  // Then each block will do 100 multigets and 33 puts
+  // So there are 133 operations in-total: 100 of them (75%) are gets, and 33
+  // of them (25%) are puts.
+  void ReadRandomWriteRandomMultiGet(ThreadState* thread) {
+    ReadOptions options(FLAGS_verify_checksum, true);
+    RandomGenerator gen;
+
+    // For multiget
+    const long& kpg = FLAGS_keys_per_multiget;  // keys per multiget group
+
+    long keys_left = readwrites_;  // number of keys still left to read
+    long num_keys;                  // number of keys to read in current group
+    long num_put_keys;              // number of keys to put in current group
+
+    long found = 0;
+    long reads_done = 0;
+    long writes_done = 0;
+    long multigets_done = 0;
+
+    // the number of iterations is the larger of read_ or write_
+    Duration duration(FLAGS_duration, readwrites_);
+    while(true) {
+      // Read num_keys keys, then write num_put_keys keys.
+      // The ratio of num_keys to num_put_keys is always FLAGS_readwritepercent
+      // And num_keys is set to be FLAGS_keys_per_multiget (kpg)
+      // num_put_keys is calculated accordingly (to maintain the ratio)
+      // Note: On the final iteration, num_keys and num_put_keys will be smaller
+      num_keys = std::min(keys_left*(FLAGS_readwritepercent + 99)/100, kpg);
+      num_put_keys = num_keys * (100-FLAGS_readwritepercent)
+                     / FLAGS_readwritepercent;
+
+      // This will break the loop when duration is complete
+      if (duration.Done(num_keys + num_put_keys)) {
+        break;
+      }
+
+      // A quick check to make sure our formula doesn't break on edge cases
+      assert(num_keys >= 1);
+      assert(num_keys + num_put_keys <= keys_left);
+
+      // Apply the MultiGet operations
+      found += MultiGetRandom(options, num_keys, thread->rand, FLAGS_num, "");
+      ++multigets_done;
+      reads_done+=num_keys;
+      thread->stats.FinishedSingleOp(db_);
+
+      // Now do the puts
+      int i;
+      long long k;
+      for(i=0; i<num_put_keys; ++i) {
+        k = thread->rand.Next() % FLAGS_num;
+        unique_ptr<char []> 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);
+        }
+        writes_done++;
+        thread->stats.FinishedSingleOp(db_);
+      }
+
+      keys_left -= (num_keys + num_put_keys);
+    }
+    char msg[100];
+    snprintf(msg, sizeof(msg),
+             "( reads:%ld writes:%ld total:%lld multiget_ops:%ld found:%ld)",
+             reads_done, writes_done, readwrites_, multigets_done, found);
+    thread->stats.AddMessage(msg);
+  }
+
+  //
+  // Read-modify-write for random keys
+  void UpdateRandom(ThreadState* thread) {
+    ReadOptions options(FLAGS_verify_checksum, true);
+    RandomGenerator gen;
+    std::string value;
+    long long found = 0;
+    Duration duration(FLAGS_duration, readwrites_);
+
+    // the number of iterations is the larger of read_ or write_
+    while (!duration.Done(1)) {
+      const long long k = thread->rand.Next() % FLAGS_num;
+      unique_ptr<char []> key = GenerateKeyFromInt(k);
+
+      if (FLAGS_use_snapshot) {
+        options.snapshot = db_->GetSnapshot();
+      }
+
+      if (FLAGS_get_approx) {
+        char key2[100];
+        snprintf(key2, sizeof(key2), "%016lld", k + 1);
+        Slice skey2(key2);
+        Slice skey(key2);
+        Range range(skey, skey2);
+        uint64_t sizes;
+        db_->GetApproximateSizes(&range, 1, &sizes);
+      }
+
+      if (db_->Get(options, key.get(), &value).ok()) {
+        found++;
+      }
+
+      if (FLAGS_use_snapshot) {
+        db_->ReleaseSnapshot(options.snapshot);
+      }
+
+      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);
+      }
+      thread->stats.FinishedSingleOp(db_);
+    }
+    char msg[100];
+    snprintf(msg, sizeof(msg),
+             "( updates:%lld found:%lld)", readwrites_, found);
+    thread->stats.AddMessage(msg);
+  }
+
+  // Read-modify-write for random keys.
+  // Each operation causes the key grow by value_size (simulating an append).
+  // Generally used for benchmarking against merges of similar type
+  void AppendRandom(ThreadState* thread) {
+    ReadOptions options(FLAGS_verify_checksum, true);
+    RandomGenerator gen;
+    std::string value;
+    long found = 0;
+
+    // The number of iterations is the larger of read_ or write_
+    Duration duration(FLAGS_duration, readwrites_);
+    while (!duration.Done(1)) {
+      const long long k = thread->rand.Next() % FLAGS_num;
+      unique_ptr<char []> key = GenerateKeyFromInt(k);
+
+      if (FLAGS_use_snapshot) {
+        options.snapshot = db_->GetSnapshot();
+      }
+
+      if (FLAGS_get_approx) {
+        char key2[100];
+        snprintf(key2, sizeof(key2), "%016lld", k + 1);
+        Slice skey2(key2);
+        Slice skey(key2);
+        Range range(skey, skey2);
+        uint64_t sizes;
+        db_->GetApproximateSizes(&range, 1, &sizes);
+      }
+
+      // Get the existing value
+      if (db_->Get(options, key.get(), &value).ok()) {
+        found++;
+      } else {
+        // If not existing, then just assume an empty string of data
+        value.clear();
+      }
+
+      if (FLAGS_use_snapshot) {
+        db_->ReleaseSnapshot(options.snapshot);
+      }
+
+      // Update the value (by appending data)
+      Slice operand = gen.Generate(value_size_);
+      if (value.size() > 0) {
+        // Use a delimeter to match the semantics for StringAppendOperator
+        value.append(1,',');
+      }
+      value.append(operand.data(), operand.size());
+
+      // Write back to the database
+      Status s = db_->Put(write_options_, key.get(), value);
+      if (!s.ok()) {
+        fprintf(stderr, "put error: %s\n", s.ToString().c_str());
+        exit(1);
+      }
+      thread->stats.FinishedSingleOp(db_);
+    }
+    char msg[100];
+    snprintf(msg, sizeof(msg), "( updates:%lld found:%ld)", readwrites_, found);
+    thread->stats.AddMessage(msg);
+  }
+
+  // Read-modify-write for random keys (using MergeOperator)
+  // The merge operator to use should be defined by FLAGS_merge_operator
+  // Adjust FLAGS_value_size so that the keys are reasonable for this operator
+  // Assumes that the merge operator is non-null (i.e.: is well-defined)
+  //
+  // For example, use FLAGS_merge_operator="uint64add" and FLAGS_value_size=8
+  // to simulate random additions over 64-bit integers using merge.
+  void MergeRandom(ThreadState* thread) {
+    RandomGenerator gen;
+
+    // The number of iterations is the larger of read_ or write_
+    Duration duration(FLAGS_duration, readwrites_);
+    while (!duration.Done(1)) {
+      const long long k = thread->rand.Next() % FLAGS_num;
+      unique_ptr<char []> key = GenerateKeyFromInt(k);
+
+      Status s = db_->Merge(write_options_, key.get(),
+                            gen.Generate(value_size_));
+
+      if (!s.ok()) {
+        fprintf(stderr, "merge error: %s\n", s.ToString().c_str());
+        exit(1);
+      }
+      thread->stats.FinishedSingleOp(db_);
+    }
+
+    // Print some statistics
+    char msg[100];
+    snprintf(msg, sizeof(msg), "( updates:%lld)", readwrites_);
+    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<WritableFile*>(arg)->Append(Slice(buf, n));
+  }
+
+  void HeapProfile() {
+    char fname[100];
+    EnvOptions soptions;
+    snprintf(fname, sizeof(fname), "%s/heap-%04d", FLAGS_db.c_str(),
+             ++heap_counter_);
+    unique_ptr<WritableFile> file;
+    Status s = FLAGS_env->NewWritableFile(fname, &file, soptions);
+    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 rocksdb
+
+
+int main(int argc, char** argv) {
+  rocksdb::InstallStackTraceHandler();
+  google::SetUsageMessage(std::string("\nUSAGE:\n") + std::string(argv[0]) +
+                          " [OPTIONS]...");
+  google::ParseCommandLineFlags(&argc, &argv, true);
+
+  FLAGS_compaction_style_e = (rocksdb::CompactionStyle) FLAGS_compaction_style;
+  if (FLAGS_statistics) {
+    dbstats = rocksdb::CreateDBStatistics();
+  }
+
+  std::vector<std::string> fanout =
+    rocksdb::stringSplit(FLAGS_max_bytes_for_level_multiplier_additional, ',');
+  for (unsigned int j= 0; j < fanout.size(); j++) {
+    FLAGS_max_bytes_for_level_multiplier_additional_v.push_back(
+      std::stoi(fanout[j]));
+  }
+
+  FLAGS_compression_type_e =
+    StringToCompressionType(FLAGS_compression_type.c_str());
+
+  if (!FLAGS_hdfs.empty()) {
+    FLAGS_env  = new rocksdb::HdfsEnv(FLAGS_hdfs);
+  }
+
+  if (!strcasecmp(FLAGS_compaction_fadvice.c_str(), "NONE"))
+    FLAGS_compaction_fadvice_e = rocksdb::Options::NONE;
+  else if (!strcasecmp(FLAGS_compaction_fadvice.c_str(), "NORMAL"))
+    FLAGS_compaction_fadvice_e = rocksdb::Options::NORMAL;
+  else if (!strcasecmp(FLAGS_compaction_fadvice.c_str(), "SEQUENTIAL"))
+    FLAGS_compaction_fadvice_e = rocksdb::Options::SEQUENTIAL;
+  else if (!strcasecmp(FLAGS_compaction_fadvice.c_str(), "WILLNEED"))
+    FLAGS_compaction_fadvice_e = rocksdb::Options::WILLNEED;
+  else {
+    fprintf(stdout, "Unknown compaction fadvice:%s\n",
+            FLAGS_compaction_fadvice.c_str());
+  }
+
+  FLAGS_rep_factory = StringToRepFactory(FLAGS_memtablerep.c_str());
+
+  // 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=<path>
+  if (FLAGS_db.empty()) {
+    std::string default_db_path;
+    rocksdb::Env::Default()->GetTestDirectory(&default_db_path);
+    default_db_path += "/dbbench";
+    FLAGS_db = default_db_path;
+  }
+
+  rocksdb::Benchmark benchmark;
+  benchmark.Run();
+  return 0;
+}
diff --git a/db/db_filesnapshot.cc b/db/db_filesnapshot.cc
new file mode 100644 (file)
index 0000000..7b9c5dd
--- /dev/null
@@ -0,0 +1,100 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <algorithm>
+#include <string>
+#include <stdint.h>
+#include "db/db_impl.h"
+#include "db/filename.h"
+#include "db/version_set.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "port/port.h"
+#include "util/mutexlock.h"
+
+namespace rocksdb {
+
+Status DBImpl::DisableFileDeletions() {
+  MutexLock l(&mutex_);
+  disable_delete_obsolete_files_ = true;
+  Log(options_.info_log, "File Deletions Disabled");
+  return Status::OK();
+}
+
+Status DBImpl::EnableFileDeletions() {
+  DeletionState deletion_state;
+  {
+    MutexLock l(&mutex_);
+    disable_delete_obsolete_files_ = false;
+    Log(options_.info_log, "File Deletions Enabled");
+    FindObsoleteFiles(deletion_state, true);
+  }
+  PurgeObsoleteFiles(deletion_state);
+  LogFlush(options_.info_log);
+  return Status::OK();
+}
+
+Status DBImpl::GetLiveFiles(std::vector<std::string>& ret,
+                            uint64_t* manifest_file_size,
+                            bool flush_memtable) {
+
+  *manifest_file_size = 0;
+
+  if (flush_memtable) {
+    // 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<uint64_t> live;
+  versions_->AddLiveFilesCurrentVersion(&live);
+
+  ret.clear();
+  ret.reserve(live.size() + 2); //*.sst + CURRENT + MANIFEST
+
+  // create names of the live files. The names are not absolute
+  // paths, instead they are relative to dbname_;
+  for (auto live_file : live) {
+    ret.push_back(TableFileName("", live_file));
+  }
+
+  ret.push_back(CurrentFileName(""));
+  ret.push_back(DescriptorFileName("", versions_->ManifestFileNumber()));
+
+  // find length of manifest file while holding the mutex lock
+  *manifest_file_size = versions_->ManifestFileSize();
+
+  return Status::OK();
+}
+
+Status DBImpl::GetSortedWalFiles(VectorLogPtr& files) {
+  // First get sorted files in archive dir, then append sorted files from main
+  // dir to maintain sorted order
+
+  // list wal files in archive dir.
+  Status s;
+  std::string archivedir = ArchivalDirectory(options_.wal_dir);
+  if (env_->FileExists(archivedir)) {
+    s = AppendSortedWalsOfType(archivedir, files, kArchivedLogFile);
+    if (!s.ok()) {
+      return s;
+    }
+  }
+  // list wal files in main db dir.
+  return AppendSortedWalsOfType(options_.wal_dir, files, kAliveLogFile);
+}
+
+}
diff --git a/db/db_impl.cc b/db/db_impl.cc
new file mode 100644 (file)
index 0000000..6ce7a74
--- /dev/null
@@ -0,0 +1,3595 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <algorithm>
+#include <climits>
+#include <cstdio>
+#include <set>
+#include <stdexcept>
+#include <stdint.h>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include "db/builder.h"
+#include "db/dbformat.h"
+#include "db/db_iter.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/merge_helper.h"
+#include "db/prefix_filter_iterator.h"
+#include "db/table_cache.h"
+#include "db/table_stats_collector.h"
+#include "db/transaction_log_impl.h"
+#include "db/version_set.h"
+#include "db/write_batch_internal.h"
+#include "port/port.h"
+#include "rocksdb/compaction_filter.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/merge_operator.h"
+#include "rocksdb/statistics.h"
+#include "rocksdb/status.h"
+#include "rocksdb/table.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/perf_context_imp.h"
+#include "util/stop_watch.h"
+
+namespace rocksdb {
+
+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<SequenceNumber> existing_snapshots;
+
+  // Files produced by compaction
+  struct Output {
+    uint64_t number;
+    uint64_t file_size;
+    InternalKey smallest, largest;
+    SequenceNumber smallest_seqno, largest_seqno;
+  };
+  std::vector<Output> outputs;
+  std::list<uint64_t> allocated_file_numbers;
+
+  // State kept for output being generated
+  unique_ptr<WritableFile> outfile;
+  unique_ptr<TableBuilder> builder;
+
+  uint64_t total_bytes;
+
+  Output* current_output() { return &outputs[outputs.size()-1]; }
+
+  explicit CompactionState(Compaction* c)
+      : compaction(c),
+        total_bytes(0) {
+  }
+
+  // Create a client visible context of this compaction
+  CompactionFilter::Context GetFilterContext() {
+    CompactionFilter::Context context;
+    context.is_full_compaction = compaction->IsFullCompaction();
+    return context;
+  }
+};
+
+// Fix user-supplied options to be reasonable
+template <class T, class V>
+static void ClipToRange(T* ptr, V minvalue, V maxvalue) {
+  if (static_cast<V>(*ptr) > maxvalue) *ptr = maxvalue;
+  if (static_cast<V>(*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,         ((size_t)64)<<10,
+                                                 ((size_t)64)<<30);
+  ClipToRange(&result.block_size,                1<<10,  4<<20);
+
+  // if user sets arena_block_size, we trust user to use this value. Otherwise,
+  // calculate a proper value from writer_buffer_size;
+  if (result.arena_block_size <= 0) {
+    result.arena_block_size = result.write_buffer_size / 10;
+  }
+
+  result.min_write_buffer_number_to_merge = std::min(
+    result.min_write_buffer_number_to_merge, result.max_write_buffer_number-1);
+  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;
+  if (result.block_size_deviation < 0 || result.block_size_deviation > 100) {
+    result.block_size_deviation = 0;
+  }
+  if (result.max_mem_compaction_level >= result.num_levels) {
+    result.max_mem_compaction_level = result.num_levels - 1;
+  }
+  if (result.soft_rate_limit > result.hard_rate_limit) {
+    result.soft_rate_limit = result.hard_rate_limit;
+  }
+  if (result.compaction_filter) {
+    Log(result.info_log, "Compaction filter specified, ignore factory");
+  }
+  if (result.prefix_extractor) {
+    // If a prefix extractor has been supplied and a PrefixHashRepFactory is
+    // being used, make sure that the latter uses the former as its transform
+    // function.
+    auto factory = dynamic_cast<PrefixHashRepFactory*>(
+      result.memtable_factory.get());
+    if (factory &&
+        factory->GetTransform() != result.prefix_extractor) {
+      Log(result.info_log, "A prefix hash representation factory was supplied "
+          "whose prefix extractor does not match options.prefix_extractor. "
+          "Falling back to skip list representation factory");
+      result.memtable_factory = std::make_shared<SkipListFactory>();
+    } else if (factory) {
+      Log(result.info_log, "Prefix hash memtable rep is in use.");
+    }
+  }
+
+  if (result.wal_dir.empty()) {
+    // Use dbname as default
+    result.wal_dir = dbname;
+  }
+
+  // -- Sanitize the table stats collector
+  // All user defined stats collectors will be wrapped by
+  // UserKeyTableStatsCollector since for them they only have the knowledge of
+  // the user keys; internal keys are invisible to them.
+  auto& collectors = result.table_stats_collectors;
+  for (size_t i = 0; i < result.table_stats_collectors.size(); ++i) {
+    assert(collectors[i]);
+    collectors[i] =
+      std::make_shared<UserKeyTableStatsCollector>(collectors[i]);
+  }
+
+  // Add collector to collect internal key statistics
+  collectors.push_back(
+      std::make_shared<InternalKeyStatsCollector>()
+  );
+
+  if (!result.flush_block_policy_factory) {
+    result.SetUpDefaultFlushBlockPolicyFactory();
+  }
+
+  return result;
+}
+
+CompressionType GetCompressionType(const Options& options, int level,
+                                   const bool enable_compression) {
+  if (!enable_compression) {
+    // disable compression
+    return kNoCompression;
+  }
+  // If the use has specified a different compression level for each level,
+  // then pick the compresison for that level.
+  if (!options.compression_per_level.empty()) {
+    const int n = options.compression_per_level.size() - 1;
+    // 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.
+    return options.compression_per_level[std::max(0, std::min(level, n))];
+  } else {
+    return options.compression;
+  }
+}
+
+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),
+      mutex_(options.use_adaptive_mutex),
+      shutting_down_(nullptr),
+      bg_cv_(&mutex_),
+      mem_rep_factory_(options_.memtable_factory),
+      mem_(new MemTable(internal_comparator_, mem_rep_factory_,
+        NumberLevels(), options_)),
+      logfile_number_(0),
+      tmp_batch_(),
+      bg_compaction_scheduled_(0),
+      bg_flush_scheduled_(0),
+      bg_logstats_scheduled_(false),
+      manual_compaction_(nullptr),
+      logger_(nullptr),
+      disable_delete_obsolete_files_(false),
+      delete_obsolete_files_last_run_(options.env->NowMicros()),
+      purge_wal_files_last_run_(0),
+      last_stats_dump_time_microsec_(0),
+      default_interval_to_delete_obsolete_WAL_(600),
+      stall_level0_slowdown_(0),
+      stall_memtable_compaction_(0),
+      stall_level0_num_files_(0),
+      stall_level0_slowdown_count_(0),
+      stall_memtable_compaction_count_(0),
+      stall_level0_num_files_count_(0),
+      started_at_(options.env->NowMicros()),
+      flush_on_destroy_(false),
+      stats_(options.num_levels),
+      delayed_writes_(0),
+      storage_options_(options),
+      bg_work_gate_closed_(false),
+      refitting_level_(false) {
+
+  mem_->Ref();
+
+  env_->GetAbsolutePath(dbname, &db_absolute_path_);
+
+  stall_leveln_slowdown_.resize(options.num_levels);
+  stall_leveln_slowdown_count_.resize(options.num_levels);
+  for (int i = 0; i < options.num_levels; ++i) {
+    stall_leveln_slowdown_[i] = 0;
+    stall_leveln_slowdown_count_[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_,
+                                    storage_options_, table_cache_size));
+
+  versions_.reset(new VersionSet(dbname_, &options_, storage_options_,
+                                 table_cache_.get(), &internal_comparator_));
+
+  dumpLeveldbBuildVersion(options_.info_log.get());
+  options_.Dump(options_.info_log.get());
+
+  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;
+
+  LogFlush(options_.info_log);
+}
+
+DBImpl::~DBImpl() {
+  // Wait for background work to finish
+  if (flush_on_destroy_ && mem_->GetFirstSequenceNumber() != 0) {
+    FlushMemTable(FlushOptions());
+  }
+  mutex_.Lock();
+  shutting_down_.Release_Store(this);  // Any non-nullptr value is ok
+  while (bg_compaction_scheduled_ ||
+         bg_flush_scheduled_ ||
+         bg_logstats_scheduled_) {
+    bg_cv_.Wait();
+  }
+  mutex_.Unlock();
+
+  if (db_lock_ != nullptr) {
+    env_->UnlockFile(db_lock_);
+  }
+
+  if (mem_ != nullptr) mem_->Unref();
+  imm_.UnrefAll();
+  LogFlush(options_.info_log);
+}
+
+// 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_flush_scheduled_ ||
+         bg_logstats_scheduled_) {
+    bg_cv_.Wait();
+  }
+
+  // Prevent new compactions from occuring.
+  bg_work_gate_closed_ = true;
+  const int LargeNumber = 10000000;
+  bg_compaction_scheduled_ += LargeNumber;
+
+  mutex_.Unlock();
+  LogFlush(options_.info_log);
+
+  // 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<WritableFile> file;
+  Status s = env_->NewWritableFile(manifest, &file, storage_options_);
+  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 || options_.WAL_size_limit_MB > 0) {
+    std::string archivalPath = ArchivalDirectory(options_.wal_dir);
+    return env_->CreateDirIfMissing(archivalPath);
+  }
+  return Status::OK();
+}
+
+void DBImpl::PrintStatistics() {
+  auto dbstats = options_.statistics;
+  if (dbstats) {
+    Log(options_.info_log,
+        "STATISTCS:\n %s",
+        dbstats->ToString().c_str());
+  }
+}
+
+void DBImpl::MaybeDumpStats() {
+  if (options_.stats_dump_period_sec == 0) return;
+
+  const uint64_t now_micros = env_->NowMicros();
+
+  if (last_stats_dump_time_microsec_ +
+      options_.stats_dump_period_sec * 1000000
+      <= now_micros) {
+    // Multiple threads could race in here simultaneously.
+    // However, the last one will update last_stats_dump_time_microsec_
+    // atomically. We could see more than one dump during one dump
+    // period in rare cases.
+    last_stats_dump_time_microsec_ = now_micros;
+    std::string stats;
+    GetProperty("rocksdb.stats", &stats);
+    Log(options_.info_log, "%s", stats.c_str());
+    PrintStatistics();
+  }
+}
+
+// Returns the list of live files in 'sst_live' and the list
+// of all files in the filesystem in 'all_files'.
+// no_full_scan = true -- never do the full scan using GetChildren()
+// force = false -- don't force the full scan, except every
+//  options_.delete_obsolete_files_period_micros
+// force = true -- force the full scan
+void DBImpl::FindObsoleteFiles(DeletionState& deletion_state,
+                               bool force,
+                               bool no_full_scan) {
+  mutex_.AssertHeld();
+
+  // if deletion is disabled, do nothing
+  if (disable_delete_obsolete_files_) {
+    return;
+  }
+
+  bool doing_the_full_scan = false;
+
+  // logic for figurint out if we're doing the full scan
+  if (no_full_scan) {
+    doing_the_full_scan = false;
+  } else if (force || options_.delete_obsolete_files_period_micros == 0) {
+    doing_the_full_scan = true;
+  } else {
+    const uint64_t now_micros = env_->NowMicros();
+    if (delete_obsolete_files_last_run_ +
+        options_.delete_obsolete_files_period_micros < now_micros) {
+      doing_the_full_scan = true;
+      delete_obsolete_files_last_run_ = now_micros;
+    }
+  }
+
+  // get obsolete files
+  versions_->GetObsoleteFiles(&deletion_state.sst_delete_files);
+
+  // store the current filenum, lognum, etc
+  deletion_state.manifest_file_number = versions_->ManifestFileNumber();
+  deletion_state.log_number = versions_->LogNumber();
+  deletion_state.prev_log_number = versions_->PrevLogNumber();
+
+  if (!doing_the_full_scan && !deletion_state.HaveSomethingToDelete()) {
+    // avoid filling up sst_live if we're sure that we
+    // are not going to do the full scan and that we don't have
+    // anything to delete at the moment
+    return;
+  }
+
+  // don't delete live files
+  deletion_state.sst_live.assign(pending_outputs_.begin(),
+                                 pending_outputs_.end());
+  versions_->AddLiveFiles(&deletion_state.sst_live);
+
+  if (doing_the_full_scan) {
+    // set of all files in the directory
+    env_->GetChildren(dbname_, &deletion_state.all_files); // Ignore errors
+
+    //Add log files in wal_dir
+    if (options_.wal_dir != dbname_) {
+      std::vector<std::string> log_files;
+      env_->GetChildren(options_.wal_dir, &log_files); // Ignore errors
+      deletion_state.all_files.insert(
+        deletion_state.all_files.end(),
+        log_files.begin(),
+        log_files.end()
+      );
+    }
+  }
+}
+
+// Diffs the files listed in filenames and those that do not
+// belong to live files are posibly removed. Also, removes all the
+// files in sst_delete_files and log_delete_files.
+// It is not necessary to hold the mutex when invoking this method.
+void DBImpl::PurgeObsoleteFiles(DeletionState& state) {
+  // this checks if FindObsoleteFiles() was run before. If not, don't do
+  // PurgeObsoleteFiles(). If FindObsoleteFiles() was run, we need to also
+  // run PurgeObsoleteFiles(), even if disable_delete_obsolete_files_ is true
+  if (state.manifest_file_number == 0) {
+    return;
+  }
+
+  uint64_t number;
+  FileType type;
+  std::vector<std::string> old_log_files;
+
+  // Now, convert live list to an unordered set, WITHOUT mutex held;
+  // set is slow.
+  std::unordered_set<uint64_t> live_set(state.sst_live.begin(),
+                                        state.sst_live.end());
+
+  state.all_files.reserve(state.all_files.size() +
+      state.sst_delete_files.size());
+  for (auto file : state.sst_delete_files) {
+    state.all_files.push_back(TableFileName("", file->number).substr(1));
+    delete file;
+  }
+
+  state.all_files.reserve(state.all_files.size() +
+      state.log_delete_files.size());
+  for (auto filenum : state.log_delete_files) {
+    if (filenum > 0) {
+      state.all_files.push_back(LogFileName("", filenum).substr(1));
+    }
+  }
+
+  // dedup state.all_files so we don't try to delete the same
+  // file twice
+  sort(state.all_files.begin(), state.all_files.end());
+  auto unique_end = unique(state.all_files.begin(), state.all_files.end());
+
+  for (size_t i = 0; state.all_files.begin() + i < unique_end; i++) {
+    if (ParseFileName(state.all_files[i], &number, &type)) {
+      bool keep = true;
+      switch (type) {
+        case kLogFile:
+          keep = ((number >= state.log_number) ||
+                  (number == state.prev_log_number));
+          break;
+        case kDescriptorFile:
+          // Keep my manifest file, and any newer incarnations'
+          // (in case there is a race that allows other incarnations)
+          keep = (number >= state.manifest_file_number);
+          break;
+        case kTableFile:
+          keep = (live_set.find(number) != live_set.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 = (live_set.find(number) != live_set.end());
+          break;
+        case kInfoLogFile:
+          keep = true;
+          if (number != 0) {
+            old_log_files.push_back(state.all_files[i]);
+          }
+          break;
+        case kCurrentFile:
+        case kDBLockFile:
+        case kIdentityFile:
+        case kMetaDatabase:
+          keep = true;
+          break;
+      }
+
+      if (!keep) {
+        if (type == kTableFile) {
+          // evict from cache
+          table_cache_->Evict(number);
+        }
+        std::string fname = ((type == kLogFile) ? options_.wal_dir : dbname_) +
+            "/" + state.all_files[i];
+        Log(options_.info_log,
+            "Delete type=%d #%lu",
+            int(type),
+            (unsigned long)number);
+
+        Status st;
+        if (type == kLogFile && (options_.WAL_ttl_seconds > 0 ||
+              options_.WAL_size_limit_MB > 0)) {
+            st = env_->RenameFile(fname,
+                ArchivedLogFileName(options_.wal_dir, number));
+            if (!st.ok()) {
+              Log(options_.info_log,
+                  "RenameFile logfile #%lu FAILED -- %s\n",
+                  (unsigned long)number, st.ToString().c_str());
+            }
+        } else {
+          st = env_->DeleteFile(fname);
+          if (!st.ok()) {
+            Log(options_.info_log, "Delete type=%d #%lu FAILED -- %s\n",
+                int(type), (unsigned long)number, st.ToString().c_str());
+          }
+        }
+      }
+    }
+  }
+
+  // Delete old info 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 (unsigned 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);
+    }
+  }
+  PurgeObsoleteWALFiles();
+  LogFlush(options_.info_log);
+}
+
+void DBImpl::DeleteObsoleteFiles() {
+  mutex_.AssertHeld();
+  DeletionState deletion_state;
+  FindObsoleteFiles(deletion_state, true);
+  PurgeObsoleteFiles(deletion_state);
+}
+
+// 1. Go through all archived files and
+//    a. if ttl is enabled, delete outdated files
+//    b. if archive size limit is enabled, delete empty files,
+//        compute file number and size.
+// 2. If size limit is enabled:
+//    a. compute how many files should be deleted
+//    b. get sorted non-empty archived logs
+//    c. delete what should be deleted
+void DBImpl::PurgeObsoleteWALFiles() {
+  bool const ttl_enabled = options_.WAL_ttl_seconds > 0;
+  bool const size_limit_enabled =  options_.WAL_size_limit_MB > 0;
+  if (!ttl_enabled && !size_limit_enabled) {
+    return;
+  }
+
+  int64_t current_time;
+  Status s = env_->GetCurrentTime(&current_time);
+  if (!s.ok()) {
+    Log(options_.info_log, "Can't get current time: %s", s.ToString().c_str());
+    assert(false);
+    return;
+  }
+  uint64_t const now_seconds = static_cast<uint64_t>(current_time);
+  uint64_t const time_to_check = (ttl_enabled && !size_limit_enabled) ?
+    options_.WAL_ttl_seconds / 2 : default_interval_to_delete_obsolete_WAL_;
+
+  if (purge_wal_files_last_run_ + time_to_check > now_seconds) {
+    return;
+  }
+
+  purge_wal_files_last_run_ = now_seconds;
+
+  std::string archival_dir = ArchivalDirectory(options_.wal_dir);
+  std::vector<std::string> files;
+  s = env_->GetChildren(archival_dir, &files);
+  if (!s.ok()) {
+    Log(options_.info_log, "Can't get archive files: %s", s.ToString().c_str());
+    assert(false);
+    return;
+  }
+
+  size_t log_files_num = 0;
+  uint64_t log_file_size = 0;
+
+  for (auto& f : files) {
+    uint64_t number;
+    FileType type;
+    if (ParseFileName(f, &number, &type) && type == kLogFile) {
+      std::string const file_path = archival_dir + "/" + f;
+      if (ttl_enabled) {
+        uint64_t file_m_time;
+        Status const s = env_->GetFileModificationTime(file_path,
+          &file_m_time);
+        if (!s.ok()) {
+          Log(options_.info_log, "Can't get file mod time: %s: %s",
+              file_path.c_str(), s.ToString().c_str());
+          continue;
+        }
+        if (now_seconds - file_m_time > options_.WAL_ttl_seconds) {
+          Status const s = env_->DeleteFile(file_path);
+          if (!s.ok()) {
+            Log(options_.info_log, "Can't delete file: %s: %s",
+                file_path.c_str(), s.ToString().c_str());
+            continue;
+          }
+          continue;
+        }
+      }
+
+      if (size_limit_enabled) {
+        uint64_t file_size;
+        Status const s = env_->GetFileSize(file_path, &file_size);
+        if (!s.ok()) {
+          Log(options_.info_log, "Can't get file size: %s: %s",
+              file_path.c_str(), s.ToString().c_str());
+          return;
+        } else {
+          if (file_size > 0) {
+            log_file_size = std::max(log_file_size, file_size);
+            ++log_files_num;
+          } else {
+            Status s = env_->DeleteFile(file_path);
+            if (!s.ok()) {
+              Log(options_.info_log, "Can't delete file: %s: %s",
+                  file_path.c_str(), s.ToString().c_str());
+              continue;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  if (0 == log_files_num || !size_limit_enabled) {
+    return;
+  }
+
+  size_t const files_keep_num = options_.WAL_size_limit_MB *
+    1024 * 1024 / log_file_size;
+  if (log_files_num <= files_keep_num) {
+    return;
+  }
+
+  size_t files_del_num = log_files_num - files_keep_num;
+  VectorLogPtr archived_logs;
+  AppendSortedWalsOfType(archival_dir, archived_logs, kArchivedLogFile);
+
+  if (files_del_num > archived_logs.size()) {
+    Log(options_.info_log, "Trying to delete more archived log files than "
+        "exist. Deleting all");
+    files_del_num = archived_logs.size();
+  }
+
+  for (size_t i = 0; i < files_del_num; ++i) {
+    std::string const file_path = archived_logs[i]->PathName();
+    Status const s = DeleteFile(file_path);
+    if (!s.ok()) {
+      Log(options_.info_log, "Can't delete file: %s: %s",
+          file_path.c_str(), s.ToString().c_str());
+      continue;
+    }
+  }
+}
+
+// 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) {
+        // TODO: add merge_operator name check
+        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)");
+      }
+    }
+    // Check for the IDENTITY file and create it if not there
+    if (!env_->FileExists(IdentityFileName(dbname_))) {
+      s = SetIdentityFile(env_, dbname_);
+      if (!s.ok()) {
+        return s;
+      }
+    }
+  }
+
+  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 rocksdb.
+    const uint64_t min_log = versions_->LogNumber();
+    const uint64_t prev_log = versions_->PrevLogNumber();
+    std::vector<std::string> filenames;
+    s = env_->GetChildren(options_.wal_dir, &filenames);
+    if (!s.ok()) {
+      return s;
+    }
+    uint64_t number;
+    FileType type;
+    std::vector<uint64_t> 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]);
+    }
+
+    if (s.ok()) {
+      if (versions_->LastSequence() < max_sequence) {
+        versions_->SetLastSequence(max_sequence);
+      }
+      SetTickerCount(options_.statistics, SEQUENCE_NUMBER,
+                     versions_->LastSequence());
+    }
+  }
+
+  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 or
+                     //            options_.skip_log_error_on_recovery==true
+    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<int>(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(options_.wal_dir, log_number);
+  unique_ptr<SequentialFile> file;
+  Status status = env_->NewSequentialFile(fname, &file, storage_options_);
+  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 &&
+                     !options_.skip_log_error_on_recovery ? &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 #%lu",
+      (unsigned 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_, mem_rep_factory_,
+        NumberLevels(), options_);
+      mem->Ref();
+    }
+    status = WriteBatchInternal::InsertInto(&batch, mem, &options_);
+    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 #%lu: started",
+      (unsigned long) meta.number);
+
+  Status s;
+  {
+    mutex_.Unlock();
+    s = BuildTable(dbname_, env_, options_, storage_options_,
+                   table_cache_.get(), iter, &meta,
+                   user_comparator(), newest_snapshot,
+                   earliest_seqno_in_memtable, true);
+    LogFlush(options_.info_log);
+    mutex_.Lock();
+  }
+
+  Log(options_.info_log, "Level-0 table #%lu: %lu bytes %s",
+      (unsigned long) meta.number,
+      (unsigned 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,
+                  meta.smallest_seqno, meta.largest_seqno);
+  }
+
+  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(std::vector<MemTable*> &mems, 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);
+
+  std::vector<Iterator*> list;
+  for (MemTable* m : mems) {
+    Log(options_.info_log,
+        "Flushing memtable with log file: %lu\n",
+        (unsigned long)m->GetLogNumber());
+    list.push_back(m->NewIterator());
+  }
+  Iterator* iter = NewMergingIterator(&internal_comparator_, &list[0],
+                                      list.size());
+  const SequenceNumber newest_snapshot = snapshots_.GetNewest();
+  const SequenceNumber earliest_seqno_in_memtable =
+    mems[0]->GetFirstSequenceNumber();
+  Log(options_.info_log,
+      "Level-0 flush table #%lu: started",
+      (unsigned long)meta.number);
+
+  Version* base = versions_->current();
+  base->Ref();          // it is likely that we do not need this reference
+  Status s;
+  {
+    mutex_.Unlock();
+    // We skip compression if universal compression is used and the size
+    // threshold is set for compression.
+    bool enable_compression = (options_.compaction_style
+        != kCompactionStyleUniversal ||
+        options_.compaction_options_universal.compression_size_percent < 0);
+    s = BuildTable(dbname_, env_, options_, storage_options_,
+                   table_cache_.get(), iter, &meta,
+                   user_comparator(), newest_snapshot,
+                   earliest_seqno_in_memtable, enable_compression);
+    LogFlush(options_.info_log);
+    mutex_.Lock();
+  }
+  base->Unref();
+
+  Log(options_.info_log, "Level-0 flush table #%lu: %lu bytes %s",
+      (unsigned long) meta.number,
+      (unsigned 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 &&
+        options_.compaction_style == kCompactionStyleLevel) {
+      level = base->PickLevelForMemTableOutput(min_user_key, max_user_key);
+    }
+    edit->AddFile(level, meta.number, meta.file_size,
+                  meta.smallest, meta.largest,
+                  meta.smallest_seqno, meta.largest_seqno);
+  }
+
+  CompactionStats stats;
+  stats.micros = env_->NowMicros() - start_micros;
+  stats.bytes_written = meta.file_size;
+  stats_[level].Add(stats);
+  return s;
+}
+
+Status DBImpl::FlushMemTableToOutputFile(bool* madeProgress,
+                                         DeletionState& deletion_state) {
+  mutex_.AssertHeld();
+  assert(imm_.size() != 0);
+
+  if (!imm_.IsFlushPending(options_.min_write_buffer_number_to_merge)) {
+    Log(options_.info_log, "FlushMemTableToOutputFile already in progress");
+    Status s = Status::IOError("FlushMemTableToOutputFile already in progress");
+    return s;
+  }
+
+  // Save the contents of the earliest memtable as a new Table
+  uint64_t file_number;
+  std::vector<MemTable*> mems;
+  imm_.PickMemtablesToFlush(&mems);
+  if (mems.empty()) {
+    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
+  // entries mems are (implicitly) sorted in ascending order by their created
+  // time. We will use the first memtable's `edit` to keep the meta info for
+  // this flush.
+  MemTable* m = mems[0];
+  VersionEdit* edit = m->GetEdits();
+  edit->SetPrevLogNumber(0);
+  // SetLogNumber(log_num) indicates logs with number smaller than log_num
+  // will no longer be picked up for recovery.
+  edit->SetLogNumber(
+      mems.back()->GetNextLogNumber()
+  );
+
+  std::vector<uint64_t> logs_to_delete;
+  for (auto mem : mems) {
+    logs_to_delete.push_back(mem->GetLogNumber());
+  }
+
+  // This will release and re-acquire the mutex.
+  Status s = WriteLevel0Table(mems, edit, &file_number);
+
+  if (s.ok() && shutting_down_.Acquire_Load()) {
+    s = Status::IOError(
+      "Database shutdown started during memtable compaction"
+    );
+  }
+
+  // Replace immutable memtable with the generated Table
+  s = imm_.InstallMemtableFlushResults(
+    mems, versions_.get(), s, &mutex_, options_.info_log.get(),
+    file_number, pending_outputs_);
+
+  if (s.ok()) {
+    if (madeProgress) {
+      *madeProgress = 1;
+    }
+
+    MaybeScheduleLogDBDeployStats();
+
+    if (!disable_delete_obsolete_files_) {
+      // add to deletion state
+      deletion_state.log_delete_files.insert(
+          deletion_state.log_delete_files.end(),
+          logs_to_delete.begin(),
+          logs_to_delete.end());
+    }
+  }
+  return s;
+}
+
+void DBImpl::CompactRange(const Slice* begin, const Slice* end,
+                          bool reduce_level, int target_level) {
+  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_FlushMemTable(); // TODO(sanjay): Skip if memtable does not overlap
+  for (int level = 0; level < max_level_with_files; level++) {
+    TEST_CompactRange(level, begin, end);
+  }
+
+  if (reduce_level) {
+    ReFitLevel(max_level_with_files, target_level);
+  }
+  LogFlush(options_.info_log);
+}
+
+// return the same level if it cannot be moved
+int DBImpl::FindMinimumEmptyLevelFitting(int level) {
+  mutex_.AssertHeld();
+  int minimum_level = level;
+  for (int i = level - 1; i > 0; --i) {
+    // stop if level i is not empty
+    if (versions_->NumLevelFiles(i) > 0) break;
+
+    // stop if level i is too small (cannot fit the level files)
+    if (versions_->MaxBytesForLevel(i) < versions_->NumLevelBytes(level)) break;
+
+    minimum_level = i;
+  }
+  return minimum_level;
+}
+
+void DBImpl::ReFitLevel(int level, int target_level) {
+  assert(level < NumberLevels());
+
+  MutexLock l(&mutex_);
+
+  // only allow one thread refitting
+  if (refitting_level_) {
+    Log(options_.info_log, "ReFitLevel: another thread is refitting");
+    return;
+  }
+  refitting_level_ = true;
+
+  // wait for all background threads to stop
+  bg_work_gate_closed_ = true;
+  while (bg_compaction_scheduled_ > 0 || bg_flush_scheduled_) {
+    Log(options_.info_log,
+        "RefitLevel: waiting for background threads to stop: %d %d",
+        bg_compaction_scheduled_, bg_flush_scheduled_);
+    bg_cv_.Wait();
+  }
+
+  // move to a smaller level
+  int to_level = target_level;
+  if (target_level < 0) {
+    to_level = FindMinimumEmptyLevelFitting(level);
+  }
+
+  assert(to_level <= level);
+
+  if (to_level < level) {
+    Log(options_.info_log, "Before refitting:\n%s",
+        versions_->current()->DebugString().data());
+
+    VersionEdit edit(NumberLevels());
+    for (const auto& f : versions_->current()->files_[level]) {
+      edit.DeleteFile(level, f->number);
+      edit.AddFile(to_level, f->number, f->file_size, f->smallest, f->largest,
+                   f->smallest_seqno, f->largest_seqno);
+    }
+    Log(options_.info_log, "Apply version edit:\n%s",
+        edit.DebugString().data());
+
+    auto status = versions_->LogAndApply(&edit, &mutex_);
+
+    Log(options_.info_log, "LogAndApply: %s\n", status.ToString().data());
+
+    if (status.ok()) {
+      Log(options_.info_log, "After refitting:\n%s",
+          versions_->current()->DebugString().data());
+    }
+  }
+
+  refitting_level_ = false;
+  bg_work_gate_closed_ = false;
+}
+
+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() const {
+  return versions_->LastSequence();
+}
+
+Status DBImpl::GetUpdatesSince(SequenceNumber seq,
+                               unique_ptr<TransactionLogIterator>* iter) {
+
+  RecordTick(options_.statistics, GET_UPDATES_SINCE_CALLS);
+  if (seq > versions_->LastSequence()) {
+    return Status::IOError("Requested sequence not yet written in the db");
+  }
+  //  Get all sorted Wal Files.
+  //  Do binary search and open files and find the seq number.
+
+  std::unique_ptr<VectorLogPtr> wal_files(new VectorLogPtr);
+  Status s = GetSortedWalFiles(*wal_files);
+  if (!s.ok()) {
+    return s;
+  }
+
+  s = RetainProbableWalFiles(*wal_files, seq);
+  if (!s.ok()) {
+    return s;
+  }
+  iter->reset(
+    new TransactionLogIteratorImpl(options_.wal_dir,
+                                   &options_,
+                                   storage_options_,
+                                   seq,
+                                   std::move(wal_files),
+                                   this));
+  return (*iter)->status();
+}
+
+Status DBImpl::RetainProbableWalFiles(VectorLogPtr& all_logs,
+                                      const SequenceNumber target) {
+  long start = 0; // signed to avoid overflow when target is < first file.
+  long end = static_cast<long>(all_logs.size()) - 1;
+  // Binary Search. avoid opening all files.
+  while (end >= start) {
+    long mid = start + (end - start) / 2;  // Avoid overflow.
+    SequenceNumber current_seq_num = all_logs.at(mid)->StartSequence();
+    if (current_seq_num == target) {
+      end = mid;
+      break;
+    } else if (current_seq_num < target) {
+      start = mid + 1;
+    } else {
+      end = mid - 1;
+    }
+  }
+  size_t start_index = std::max(0l, end); // end could be -ve.
+  // The last wal file is always included
+  all_logs.erase(all_logs.begin(), all_logs.begin() + start_index);
+  return Status::OK();
+}
+
+bool DBImpl::CheckWalFileExistsAndEmpty(const WalFileType type,
+                                        const uint64_t number) {
+  const std::string fname = (type == kAliveLogFile) ?
+    LogFileName(options_.wal_dir, number) :
+    ArchivedLogFileName(options_.wal_dir, number);
+  uint64_t file_size;
+  Status s = env_->GetFileSize(fname, &file_size);
+  return (s.ok() && (file_size == 0));
+}
+
+Status DBImpl::ReadFirstRecord(const WalFileType type, const uint64_t number,
+                               WriteBatch* const result) {
+
+  if (type == kAliveLogFile) {
+    std::string fname = LogFileName(options_.wal_dir, number);
+    Status status = ReadFirstLine(fname, result);
+    if (!status.ok()) {
+      //  check if the file got moved to archive.
+      std::string archived_file =
+        ArchivedLogFileName(options_.wal_dir, number);
+      Status s = ReadFirstLine(archived_file, result);
+      if (!s.ok()) {
+        return Status::IOError("Log File has been deleted: " + archived_file);
+      }
+    }
+    return Status::OK();
+  } else if (type == kArchivedLogFile) {
+    std::string fname = ArchivedLogFileName(options_.wal_dir, number);
+    Status status = ReadFirstLine(fname, result);
+    return status;
+  }
+  return Status::NotSupported("File Type Not Known: " + std::to_string(type));
+}
+
+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<int>(bytes), s.ToString().c_str());
+      if (this->status != nullptr && this->status->ok()) *this->status = s;
+    }
+  };
+
+  unique_ptr<SequentialFile> file;
+  Status status = env_->NewSequentialFile(fname, &file, storage_options_);
+
+  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);
+}
+
+struct CompareLogByPointer {
+  bool operator() (const unique_ptr<LogFile>& a,
+                   const unique_ptr<LogFile>& b) {
+    LogFileImpl* a_impl = dynamic_cast<LogFileImpl*>(a.get());
+    LogFileImpl* b_impl = dynamic_cast<LogFileImpl*>(b.get());
+    return *a_impl < *b_impl;
+  }
+};
+
+Status DBImpl::AppendSortedWalsOfType(const std::string& path,
+    VectorLogPtr& log_files, WalFileType log_type) {
+  std::vector<std::string> all_files;
+  const Status status = env_->GetChildren(path, &all_files);
+  if (!status.ok()) {
+    return status;
+  }
+  log_files.reserve(log_files.size() + all_files.size());
+  VectorLogPtr::iterator pos_start;
+  if (!log_files.empty()) {
+    pos_start = log_files.end() - 1;
+  } else {
+    pos_start = log_files.begin();
+  }
+  for (const auto& f : all_files) {
+    uint64_t number;
+    FileType type;
+    if (ParseFileName(f, &number, &type) && type == kLogFile){
+
+      WriteBatch batch;
+      Status s = ReadFirstRecord(log_type, number, &batch);
+      if (!s.ok()) {
+        if (CheckWalFileExistsAndEmpty(log_type, number)) {
+          continue;
+        }
+        return s;
+      }
+
+      uint64_t size_bytes;
+      s = env_->GetFileSize(LogFileName(path, number), &size_bytes);
+      if (!s.ok()) {
+        return s;
+      }
+
+      log_files.push_back(std::move(unique_ptr<LogFile>(new LogFileImpl(
+        number, log_type, WriteBatchInternal::Sequence(&batch), size_bytes))));
+    }
+  }
+  CompareLogByPointer compare_log_files;
+  std::sort(pos_start, log_files.end(), compare_log_files);
+  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;
+  // For universal compaction, we enforce every manual compaction to compact
+  // all files.
+  if (begin == nullptr ||
+      options_.compaction_style == kCompactionStyleUniversal) {
+    manual.begin = nullptr;
+  } else {
+    begin_storage = InternalKey(*begin, kMaxSequenceNumber, kValueTypeForSeek);
+    manual.begin = &begin_storage;
+  }
+  if (end == nullptr ||
+      options_.compaction_style == kCompactionStyleUniversal) {
+    manual.end = nullptr;
+  } else {
+    end_storage = InternalKey(*end, 0, static_cast<ValueType>(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;
+    }
+    MaybeScheduleFlushOrCompaction();
+    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 = WaitForFlushMemTable();
+  }
+  return s;
+}
+
+Status DBImpl::WaitForFlushMemTable() {
+  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_FlushMemTable() {
+  return FlushMemTable(FlushOptions());
+}
+
+Status DBImpl::TEST_WaitForFlushMemTable() {
+  return WaitForFlushMemTable();
+}
+
+Status DBImpl::TEST_WaitForCompact() {
+  // Wait until the compaction completes
+
+  // TODO: a bug here. This function actually does not necessarily
+  // wait for compact. It actually waits for scheduled compaction
+  // OR flush to finish.
+
+  MutexLock l(&mutex_);
+  while ((bg_compaction_scheduled_ || bg_flush_scheduled_) &&
+         bg_error_.ok()) {
+    bg_cv_.Wait();
+  }
+  return bg_error_;
+}
+
+void DBImpl::MaybeScheduleFlushOrCompaction() {
+  mutex_.AssertHeld();
+  if (bg_work_gate_closed_) {
+    // gate closed for backgrond work
+  } else if (shutting_down_.Acquire_Load()) {
+    // DB is being deleted; no more background compactions
+  } else {
+    bool is_flush_pending =
+      imm_.IsFlushPending(options_.min_write_buffer_number_to_merge);
+    if (is_flush_pending &&
+        (bg_flush_scheduled_ < options_.max_background_flushes)) {
+      // memtable flush needed
+      bg_flush_scheduled_++;
+      env_->Schedule(&DBImpl::BGWorkFlush, this, Env::Priority::HIGH);
+    }
+
+    if ((manual_compaction_ ||
+         versions_->NeedsCompaction() ||
+         (is_flush_pending && (options_.max_background_flushes <= 0))) &&
+        bg_compaction_scheduled_ < options_.max_background_compactions) {
+      // compaction needed, or memtable flush needed but HIGH pool not enabled.
+      bg_compaction_scheduled_++;
+      env_->Schedule(&DBImpl::BGWorkCompaction, this, Env::Priority::LOW);
+    }
+  }
+}
+
+void DBImpl::BGWorkFlush(void* db) {
+  reinterpret_cast<DBImpl*>(db)->BackgroundCallFlush();
+}
+
+void DBImpl::BGWorkCompaction(void* db) {
+  reinterpret_cast<DBImpl*>(db)->BackgroundCallCompaction();
+}
+
+Status DBImpl::BackgroundFlush(bool* madeProgress,
+                               DeletionState& deletion_state) {
+  Status stat;
+  while (stat.ok() &&
+         imm_.IsFlushPending(options_.min_write_buffer_number_to_merge)) {
+    Log(options_.info_log,
+        "BackgroundCallFlush doing FlushMemTableToOutputFile, flush slots available %d",
+        options_.max_background_flushes - bg_flush_scheduled_);
+    stat = FlushMemTableToOutputFile(madeProgress, deletion_state);
+  }
+  return stat;
+}
+
+void DBImpl::BackgroundCallFlush() {
+  bool madeProgress = false;
+  DeletionState deletion_state;
+  assert(bg_flush_scheduled_);
+  MutexLock l(&mutex_);
+
+  Status s;
+  if (!shutting_down_.Acquire_Load()) {
+    s = BackgroundFlush(&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 flush error: %s",
+          s.ToString().c_str());
+      mutex_.Unlock();
+      LogFlush(options_.info_log);
+      env_->SleepForMicroseconds(1000000);
+      mutex_.Lock();
+    }
+  }
+
+  // If !s.ok(), this means that Flush failed. In that case, we want
+  // to delete all obsolete files and we force FindObsoleteFiles()
+  FindObsoleteFiles(deletion_state, !s.ok());
+  // delete unnecessary files if any, this is done outside the mutex
+  if (deletion_state.HaveSomethingToDelete()) {
+    mutex_.Unlock();
+    PurgeObsoleteFiles(deletion_state);
+    mutex_.Lock();
+  }
+
+  bg_flush_scheduled_--;
+  if (madeProgress) {
+    MaybeScheduleFlushOrCompaction();
+  }
+  bg_cv_.SignalAll();
+}
+
+
+void DBImpl::TEST_PurgeObsoleteteWAL() {
+  PurgeObsoleteWALFiles();
+}
+
+void DBImpl::BackgroundCallCompaction() {
+  bool madeProgress = false;
+  DeletionState deletion_state;
+
+  MaybeDumpStats();
+
+  MutexLock l(&mutex_);
+  // Log(options_.info_log, "XXX BG Thread %llx process new work item", pthread_self());
+  assert(bg_compaction_scheduled_);
+  Status s;
+  if (!shutting_down_.Acquire_Load()) {
+    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();
+      LogFlush(options_.info_log);
+      env_->SleepForMicroseconds(1000000);
+      mutex_.Lock();
+    }
+  }
+
+  // If !s.ok(), this means that Compaction failed. In that case, we want
+  // to delete all obsolete files we might have created and we force
+  // FindObsoleteFiles(). This is because deletion_state does not catch
+  // all created files if compaction failed.
+  FindObsoleteFiles(deletion_state, !s.ok());
+  // delete unnecessary files if any, this is done outside the mutex
+  if (deletion_state.HaveSomethingToDelete()) {
+    mutex_.Unlock();
+    PurgeObsoleteFiles(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) {
+    MaybeScheduleFlushOrCompaction();
+  }
+  bg_cv_.SignalAll();
+
+}
+
+Status DBImpl::BackgroundCompaction(bool* madeProgress,
+  DeletionState& deletion_state) {
+  *madeProgress = false;
+  mutex_.AssertHeld();
+
+  // TODO: remove memtable flush from formal compaction
+  while (imm_.IsFlushPending(options_.min_write_buffer_number_to_merge)) {
+    Log(options_.info_log,
+        "BackgroundCompaction doing FlushMemTableToOutputFile, compaction slots "
+        "available %d",
+        options_.max_background_compactions - bg_compaction_scheduled_);
+    Status stat = FlushMemTableToOutputFile(madeProgress, deletion_state);
+    if (!stat.ok()) {
+      return stat;
+    }
+  }
+
+  unique_ptr<Compaction> 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,
+                       f->smallest_seqno, f->largest_seqno);
+    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<unsigned long long>(f->number),
+        c->level() + 1,
+        static_cast<unsigned long long>(f->file_size),
+        status.ToString().c_str(),
+        versions_->LevelSummary(&tmp));
+    versions_->ReleaseCompactionFiles(c.get(), status);
+    *madeProgress = true;
+  } else {
+    MaybeScheduleFlushOrCompaction(); // do more compaction work in parallel.
+    CompactionState* compact = new CompactionState(c.get());
+    status = DoCompactionWork(compact, deletion_state);
+    CleanupCompaction(compact, status);
+    versions_->ReleaseCompactionFiles(c.get(), status);
+    c->ReleaseInputs();
+    *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;
+    }
+    // For universal compaction:
+    //   Because universal compaction always happens at level 0, so one
+    //   compaction will pick up all overlapped files. No files will be
+    //   filtered out due to size limit and left for a successive compaction.
+    //   So we can safely conclude the current compaction.
+    //
+    //   Also note that, if we don't stop here, then the current compaction
+    //   writes a new file back to level 0, which will be used in successive
+    //   compaction. Hence the manual compaction will never finish.
+    if (options_.compaction_style == kCompactionStyleUniversal) {
+      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, Status status) {
+  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);
+
+    // If this file was inserted into the table cache then remove
+    // them here because this compaction was not committed.
+    if (!status.ok()) {
+      table_cache_->Evict(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 (const auto file_number : compact->allocated_file_numbers) {
+    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();
+  out.smallest_seqno = out.largest_seqno = 0;
+  compact->outputs.push_back(out);
+
+  // Make the output file
+  std::string fname = TableFileName(dbname_, file_number);
+  Status s = env_->NewWritableFile(fname, &compact->outfile, storage_options_);
+
+  if (s.ok()) {
+    // Over-estimate slightly so we don't end up just barely crossing
+    // the threshold.
+    compact->outfile->SetPreallocationBlockSize(
+      1.1 * versions_->MaxFileSizeForLevel(compact->compaction->output_level()));
+
+    CompressionType compression_type = GetCompressionType(
+        options_, compact->compaction->output_level(),
+        compact->compaction->enable_compression());
+
+    compact->builder.reset(
+        GetTableBuilder(options_, compact->outfile.get(), compression_type));
+  }
+  LogFlush(options_.info_log);
+  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) {
+      StopWatch sw(env_, options_.statistics, COMPACTION_OUTFILE_SYNC_MICROS);
+      s = compact->outfile->Fsync();
+    } else {
+      StopWatch sw(env_, options_.statistics, COMPACTION_OUTFILE_SYNC_MICROS);
+      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(),
+                                               storage_options_,
+                                               output_number,
+                                               current_bytes);
+    s = iter->status();
+    delete iter;
+    if (s.ok()) {
+      Log(options_.info_log,
+          "Generated table #%lu: %lu keys, %lu bytes",
+          (unsigned long) output_number,
+          (unsigned long) current_entries,
+          (unsigned 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<long long>(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(
+        (options_.compaction_style == kCompactionStyleUniversal) ?
+          level : level + 1,
+        out.number, out.file_size, out.smallest, out.largest,
+        out.smallest_seqno, out.largest_seqno);
+  }
+  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<SequenceNumber>& snapshots,
+  SequenceNumber* prev_snapshot) {
+  SequenceNumber prev __attribute__((unused)) = 0;
+  for (const auto cur : snapshots) {
+    assert(prev <= cur);
+    if (cur >= in) {
+      *prev_snapshot = prev;
+      return cur;
+    }
+    prev = cur; // assignment
+    assert(prev);
+  }
+  Log(options_.info_log,
+      "Looking for seqid %lu but maxseqid is %lu",
+      (unsigned long)in,
+      (unsigned long)snapshots[snapshots.size()-1]);
+  assert(0);
+  return 0;
+}
+
+Status DBImpl::DoCompactionWork(CompactionState* compact,
+                                DeletionState& deletion_state) {
+  assert(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;
+  SequenceNumber latest_snapshot = 0;
+  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 {
+    latest_snapshot = compact->existing_snapshots.back();
+    // 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 = compact->compaction->BottomMostLevel();
+
+  // 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<Iterator> 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;
+  std::string compaction_filter_value;
+  std::vector<char> delete_key; // for compaction filter
+  MergeHelper merge(user_comparator(), options_.merge_operator.get(),
+                    options_.info_log.get(),
+                    false /* internal key corruption is expected */);
+  auto compaction_filter = options_.compaction_filter;
+  std::unique_ptr<CompactionFilter> compaction_filter_from_factory = nullptr;
+  if (!compaction_filter) {
+    auto context = compact->GetFilterContext();
+    compaction_filter_from_factory =
+      options_.compaction_filter_factory->CreateCompactionFilter(context);
+    compaction_filter = compaction_filter_from_factory.get();
+  }
+
+  for (; input->Valid() && !shutting_down_.Acquire_Load(); ) {
+    // Prioritize immutable compaction work
+    // TODO: remove memtable flush from normal compaction work
+    if (imm_.imm_flush_needed.NoBarrier_Load() != nullptr) {
+      const uint64_t imm_start = env_->NowMicros();
+      LogFlush(options_.info_log);
+      mutex_.Lock();
+      if (imm_.IsFlushPending(options_.min_write_buffer_number_to_merge)) {
+        FlushMemTableToOutputFile(nullptr, deletion_state);
+        bg_cv_.SignalAll();  // Wakeup MakeRoomForWrite() if necessary
+      }
+      mutex_.Unlock();
+      imm_micros += (env_->NowMicros() - imm_start);
+    }
+
+    Slice key = input->key();
+    Slice value = input->value();
+
+    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;
+    bool current_entry_is_merging = false;
+    if (!ParseInternalKey(key, &ikey)) {
+      // Do not hide error keys
+      // TODO: error key stays in db forever? Figure out the intention/rationale
+      // v10 error v8 : we cannot hide v8 even though it's pretty obvious.
+      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;
+
+        // apply the compaction filter to the first occurrence of the user key
+        if (compaction_filter &&
+            ikey.type == kTypeValue &&
+            (visible_at_tip || ikey.sequence > latest_snapshot)) {
+          // If the user has specified a compaction filter and the sequence
+          // number is greater than any external snapshot, then invoke the
+          // filter.
+          // If the return value of the compaction filter is true, replace
+          // the entry with a delete marker.
+          bool value_changed = false;
+          compaction_filter_value.clear();
+          bool to_delete =
+            compaction_filter->Filter(compact->compaction->level(),
+                                               ikey.user_key, value,
+                                               &compaction_filter_value,
+                                               &value_changed);
+          if (to_delete) {
+            // make a copy of the original key
+            delete_key.assign(key.data(), key.data() + key.size());
+            // convert it to a delete
+            UpdateInternalKey(&delete_key[0], delete_key.size(),
+                              ikey.sequence, kTypeDeletion);
+            // anchor the key again
+            key = Slice(&delete_key[0], delete_key.size());
+            // needed because ikey is backed by key
+            ParseInternalKey(key, &ikey);
+            // no value associated with delete
+            value.clear();
+            RecordTick(options_.statistics, COMPACTION_KEY_DROP_USER);
+          } else if (value_changed) {
+            value = compaction_filter_value;
+          }
+        }
+
+      }
+
+      // 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 prev_snapshot = 0; // 0 means no previous snapshot
+      SequenceNumber visible = visible_at_tip ?
+        visible_at_tip :
+        findEarliestVisibleSnapshot(ikey.sequence,
+                                    compact->existing_snapshots,
+                                    &prev_snapshot);
+
+      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
+        // TODO: why not > ?
+        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 (ikey.type == kTypeMerge) {
+        // We know the merge type entry is not hidden, otherwise we would
+        // have hit (A)
+        // We encapsulate the merge related state machine in a different
+        // object to minimize change to the existing flow. Turn out this
+        // logic could also be nicely re-used for memtable flush purge
+        // optimization in BuildTable.
+        merge.MergeUntil(input.get(), prev_snapshot, bottommost_level,
+                         options_.statistics);
+        current_entry_is_merging = true;
+        if (merge.IsSuccess()) {
+          // Successfully found Put/Delete/(end-of-key-range) while merging
+          // Get the merge result
+          key = merge.key();
+          ParseInternalKey(key, &ikey);
+          value = merge.value();
+        } else {
+          // Did not find a Put/Delete/(end-of-key-range) while merging
+          // We now have some stack of merge operands to write out.
+          // NOTE: key,value, and ikey are now referring to old entries.
+          //       These will be correctly set below.
+          assert(!merge.keys().empty());
+          assert(merge.keys().size() == merge.values().size());
+
+          // Hack to make sure last_sequence_for_key is correct
+          ParseInternalKey(merge.keys().front(), &ikey);
+        }
+      }
+
+      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) {
+      // We may write a single key (e.g.: for Put/Delete or successful merge).
+      // Or we may instead have to write a sequence/list of keys.
+      // We have to write a sequence iff we have an unsuccessful merge
+      bool has_merge_list = current_entry_is_merging && !merge.IsSuccess();
+      const std::deque<std::string>* keys = nullptr;
+      const std::deque<std::string>* values = nullptr;
+      std::deque<std::string>::const_reverse_iterator key_iter;
+      std::deque<std::string>::const_reverse_iterator value_iter;
+      if (has_merge_list) {
+        keys = &merge.keys();
+        values = &merge.values();
+        key_iter = keys->rbegin();    // The back (*rbegin()) is the first key
+        value_iter = values->rbegin();
+
+        key = Slice(*key_iter);
+        value = Slice(*value_iter);
+      }
+
+      // If we have a list of keys to write, traverse the list.
+      // If we have a single key to write, simply write that key.
+      while (true) {
+        // Invariant: key,value,ikey will always be the next entry to write
+        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 (options_.compaction_style == kCompactionStyleLevel &&
+            bottommost_level && ikey.sequence < earliest_snapshot &&
+            ikey.type != kTypeMerge) {
+          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;
+          }
+        }
+
+        SequenceNumber seqno = GetInternalKeySeqno(newkey);
+        if (compact->builder->NumEntries() == 0) {
+          compact->current_output()->smallest.DecodeFrom(newkey);
+          compact->current_output()->smallest_seqno = seqno;
+        } else {
+          compact->current_output()->smallest_seqno =
+            std::min(compact->current_output()->smallest_seqno, seqno);
+        }
+        compact->current_output()->largest.DecodeFrom(newkey);
+        compact->builder->Add(newkey, value);
+        compact->current_output()->largest_seqno =
+          std::max(compact->current_output()->largest_seqno, seqno);
+
+        // Close output file if it is big enough
+        if (compact->builder->FileSize() >=
+            compact->compaction->MaxOutputFileSize()) {
+          status = FinishCompactionOutputFile(compact, input.get());
+          if (!status.ok()) {
+            break;
+          }
+        }
+
+        // If we have a list of entries, move to next element
+        // If we only had one entry, then break the loop.
+        if (has_merge_list) {
+          ++key_iter;
+          ++value_iter;
+
+          // If at end of list
+          if (key_iter == keys->rend() || value_iter == values->rend()) {
+            // Sanity Check: if one ends, then both end
+            assert(key_iter == keys->rend() && value_iter == values->rend());
+            break;
+          }
+
+          // Otherwise not at end of list. Update key, value, and ikey.
+          key = Slice(*key_iter);
+          value = Slice(*value_iter);
+          ParseInternalKey(key, &ikey);
+
+        } else{
+          // Only had one item to begin with (Put/Delete)
+          break;
+        }
+      }
+    }
+
+    // MergeUntil has moved input to the next entry
+    if (!current_entry_is_merging) {
+      input->Next();
+    }
+  }
+
+  if (status.ok() && shutting_down_.Acquire_Load()) {
+    status = Status::IOError("Database shutdown started 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;
+  }
+
+  LogFlush(options_.info_log);
+  mutex_.Lock();
+  stats_[compact->compaction->output_level()].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), read-write-amplify(%.1f) "
+      "write-amplify(%.1f) %s\n",
+      versions_->LevelSummary(&tmp),
+      (stats.bytes_readn + stats.bytes_readnp1 + stats.bytes_written) /
+          (double) stats.micros,
+      compact->compaction->output_level(),
+      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 + stats.bytes_readn) /
+          (double) stats.bytes_readn,
+      stats.bytes_written / (double) stats.bytes_readn,
+      status.ToString().c_str());
+
+  return status;
+}
+
+namespace {
+struct IterState {
+  port::Mutex* mu;
+  Version* version;
+  std::vector<MemTable*> mem; // includes both mem_ and imm_
+  DBImpl *db;
+};
+
+static void CleanupIteratorState(void* arg1, void* arg2) {
+  IterState* state = reinterpret_cast<IterState*>(arg1);
+  state->mu->Lock();
+  for (unsigned int i = 0; i < state->mem.size(); i++) {
+    state->mem[i]->Unref();
+  }
+  state->version->Unref();
+  // delete only the sst obsolete files
+  DBImpl::DeletionState deletion_state;
+  // fast path FindObsoleteFiles
+  state->db->FindObsoleteFiles(deletion_state, false, true);
+  state->mu->Unlock();
+  state->db->PurgeObsoleteFiles(deletion_state);
+  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<Iterator*> list;
+  mem_->Ref();
+  list.push_back(mem_->NewIterator(options));
+
+  cleanup->mem.push_back(mem_);
+
+  // Collect together all needed child iterators for imm_
+  std::vector<MemTable*> immutables;
+  imm_.GetMemTables(&immutables);
+  for (unsigned int i = 0; i < immutables.size(); i++) {
+    MemTable* m = immutables[i];
+    m->Ref();
+    list.push_back(m->NewIterator(options));
+    cleanup->mem.push_back(m);
+  }
+
+  // Collect iterators for files in L0 - Ln
+  versions_->current()->AddIterators(options, storage_options_, &list);
+  Iterator* internal_iter =
+      NewMergingIterator(&internal_comparator_, &list[0], list.size());
+  versions_->current()->Ref();
+
+  cleanup->mu = &mutex_;
+  cleanup->db = this;
+  cleanup->version = versions_->current();
+  internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, nullptr);
+
+  mutex_.Unlock();
+  LogFlush(options_.info_log);
+  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) {
+  return GetImpl(options, key, value);
+}
+
+Status DBImpl::GetImpl(const ReadOptions& options,
+                       const Slice& key,
+                       std::string* value,
+                       bool* value_found) {
+  Status s;
+
+  StopWatch sw(env_, options_.statistics, DB_GET);
+  SequenceNumber snapshot;
+  mutex_.Lock();
+  if (options.snapshot != nullptr) {
+    snapshot = reinterpret_cast<const SnapshotImpl*>(options.snapshot)->number_;
+  } else {
+    snapshot = versions_->LastSequence();
+  }
+
+  MemTable* mem = mem_;
+  MemTableList imm = imm_;
+  Version* current = versions_->current();
+  mem->Ref();
+  imm.RefAll();
+  current->Ref();
+
+  // Unlock while reading from files and memtables
+  mutex_.Unlock();
+  bool have_stat_update = false;
+  Version::GetStats stats;
+
+
+  // Prepare to store a list of merge operations if merge occurs.
+  std::deque<std::string> merge_operands;
+
+  // First look in the memtable, then in the immutable memtable (if any).
+  // s is both in/out. When in, s could either be OK or MergeInProgress.
+  // merge_operands will contain the sequence of merges in the latter case.
+  LookupKey lkey(key, snapshot);
+  if (mem->Get(lkey, value, &s, &merge_operands, options_)) {
+    // Done
+  } else if (imm.Get(lkey, value, &s, &merge_operands, options_)) {
+    // Done
+  } else {
+    current->Get(options, lkey, value, &s, &merge_operands, &stats,
+                 options_, value_found);
+    have_stat_update = true;
+  }
+  mutex_.Lock();
+
+  if (!options_.disable_seek_compaction &&
+      have_stat_update && current->UpdateStats(stats)) {
+    MaybeScheduleFlushOrCompaction();
+  }
+  mem->Unref();
+  imm.UnrefAll();
+  current->Unref();
+  mutex_.Unlock();
+
+  LogFlush(options_.info_log);
+  // Note, tickers are atomic now - no lock protection needed any more.
+  RecordTick(options_.statistics, NUMBER_KEYS_READ);
+  RecordTick(options_.statistics, BYTES_READ, value->size());
+  return s;
+}
+
+std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
+                                     const std::vector<Slice>& keys,
+                                     std::vector<std::string>* values) {
+
+  StopWatch sw(env_, options_.statistics, DB_MULTIGET);
+  SequenceNumber snapshot;
+  mutex_.Lock();
+  if (options.snapshot != nullptr) {
+    snapshot = reinterpret_cast<const SnapshotImpl*>(options.snapshot)->number_;
+  } else {
+    snapshot = versions_->LastSequence();
+  }
+
+  MemTable* mem = mem_;
+  MemTableList imm = imm_;
+  Version* current = versions_->current();
+  mem->Ref();
+  imm.RefAll();
+  current->Ref();
+
+  // Unlock while reading from files and memtables
+
+  mutex_.Unlock();
+  bool have_stat_update = false;
+  Version::GetStats stats;
+
+  // Prepare to store a list of merge operations if merge occurs.
+  std::deque<std::string> merge_operands;
+
+  // Note: this always resizes the values array
+  int numKeys = keys.size();
+  std::vector<Status> statList(numKeys);
+  values->resize(numKeys);
+
+  // Keep track of bytes that we read for statistics-recording later
+  uint64_t bytesRead = 0;
+
+  // For each of the given keys, apply the entire "get" process as follows:
+  // First look in the memtable, then in the immutable memtable (if any).
+  // s is both in/out. When in, s could either be OK or MergeInProgress.
+  // merge_operands will contain the sequence of merges in the latter case.
+  for (int i=0; i<numKeys; ++i) {
+    merge_operands.clear();
+    Status& s = statList[i];
+    std::string* value = &(*values)[i];
+
+    LookupKey lkey(keys[i], snapshot);
+    if (mem->Get(lkey, value, &s, &merge_operands, options_)) {
+      // Done
+    } else if (imm.Get(lkey, value, &s, &merge_operands, options_)) {
+      // Done
+    } else {
+      current->Get(options, lkey, value, &s, &merge_operands, &stats, options_);
+      have_stat_update = true;
+    }
+
+    if (s.ok()) {
+      bytesRead += value->size();
+    }
+  }
+
+  // Post processing (decrement reference counts and record statistics)
+  mutex_.Lock();
+  if (!options_.disable_seek_compaction &&
+      have_stat_update && current->UpdateStats(stats)) {
+    MaybeScheduleFlushOrCompaction();
+  }
+  mem->Unref();
+  imm.UnrefAll();
+  current->Unref();
+  mutex_.Unlock();
+
+  LogFlush(options_.info_log);
+  RecordTick(options_.statistics, NUMBER_MULTIGET_CALLS);
+  RecordTick(options_.statistics, NUMBER_MULTIGET_KEYS_READ, numKeys);
+  RecordTick(options_.statistics, NUMBER_MULTIGET_BYTES_READ, bytesRead);
+
+  return statList;
+}
+
+bool DBImpl::KeyMayExist(const ReadOptions& options,
+                         const Slice& key,
+                         std::string* value,
+                         bool* value_found) {
+  if (value_found != nullptr) {
+    *value_found = true; // falsify later if key-may-exist but can't fetch value
+  }
+  ReadOptions roptions = options;
+  roptions.read_tier = kBlockCacheTier; // read from block cache only
+  return GetImpl(roptions, key, value, value_found).ok();
+}
+
+Iterator* DBImpl::NewIterator(const ReadOptions& options) {
+  SequenceNumber latest_snapshot;
+  Iterator* iter = NewInternalIterator(options, &latest_snapshot);
+  iter = NewDBIterator(
+             &dbname_, env_, options_, user_comparator(), iter,
+             (options.snapshot != nullptr
+              ? reinterpret_cast<const SnapshotImpl*>(options.snapshot)->number_
+              : latest_snapshot));
+  if (options.prefix) {
+    // use extra wrapper to exclude any keys from the results which
+    // don't begin with the prefix
+    iter = new PrefixFilterIterator(iter, *options.prefix,
+                                    options_.prefix_extractor);
+  }
+  return iter;
+}
+
+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<const SnapshotImpl*>(s));
+}
+
+// Convenience methods
+Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) {
+  return DB::Put(o, key, val);
+}
+
+Status DBImpl::Merge(const WriteOptions& o, const Slice& key,
+                     const Slice& val) {
+  if (!options_.merge_operator) {
+    return Status::NotSupported("Provide a merge_operator when opening DB");
+  } else {
+    return DB::Merge(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;
+
+  StopWatch sw(env_, options_.statistics, DB_WRITE);
+  MutexLock l(&mutex_);
+  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
+    // TODO: BuildBatchGroup physically concatenate/copy all write batches into
+    // a new one. Mem copy is done with the lock held. Ideally, we only need
+    // the lock to obtain the last_writer and the references to all batches.
+    // Creation (copy) of the merged batch could have been done outside of the
+    // lock protected region.
+    WriteBatch* updates = BuildBatchGroup(&last_writer);
+
+    // 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();
+      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));
+      if (options.disableWAL) {
+        flush_on_destroy_ = true;
+      }
+
+      if (!options.disableWAL) {
+        StopWatchNano timer(env_);
+        StartPerfTimer(&timer);
+        status = log_->AddRecord(WriteBatchInternal::Contents(updates));
+        BumpPerfTime(&perf_context.wal_write_time, &timer);
+        if (status.ok() && options.sync) {
+          if (options_.use_fsync) {
+            StopWatch(env_, options_.statistics, WAL_FILE_SYNC_MICROS);
+            status = log_->file()->Fsync();
+          } else {
+            StopWatch(env_, options_.statistics, WAL_FILE_SYNC_MICROS);
+            status = log_->file()->Sync();
+          }
+        }
+      }
+      if (status.ok()) {
+        status = WriteBatchInternal::InsertInto(updates, mem_, &options_, this,
+                                                options_.filter_deletes);
+        if (!status.ok()) {
+          // Panic for in-memory corruptions
+          // Note that existing logic was not sound. Any partial failure writing
+          // into the memtable would result in a state that some write ops might
+          // have succeeded in memtable but Status reports error for all writes.
+          throw std::runtime_error("In memory WriteBatch corruption!");
+        }
+        SetTickerCount(options_.statistics, SEQUENCE_NUMBER, last_sequence);
+      }
+      LogFlush(options_.info_log);
+      mutex_.Lock();
+      if (status.ok()) {
+        versions_->SetLastSequence(last_sequence);
+      }
+    }
+    if (updates == &tmp_batch_) tmp_batch_.Clear();
+  }
+  if (options_.paranoid_checks && !status.ok() && bg_error_.ok()) {
+    bg_error_ = status; // stop compaction & fail any further writes
+  }
+
+  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<Writer*>::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;
+}
+
+// This function computes the amount of time in microseconds by which a write
+// should be delayed based on the number of level-0 files according to the
+// following formula:
+// if n < bottom, return 0;
+// if n >= top, return 1000;
+// otherwise, let r = (n - bottom) /
+//                    (top - bottom)
+//  and return r^2 * 1000.
+// The goal of this formula is to gradually increase the rate at which writes
+// are slowed. We also tried linear delay (r * 1000), but it seemed to do
+// slightly worse. There is no other particular reason for choosing quadratic.
+uint64_t DBImpl::SlowdownAmount(int n, int top, int bottom) {
+  uint64_t delay;
+  if (n >= top) {
+    delay = 1000;
+  }
+  else if (n < bottom) {
+    delay = 0;
+  }
+  else {
+    // If we are here, we know that:
+    //   level0_start_slowdown <= n < level0_slowdown
+    // since the previous two conditions are false.
+    float how_much =
+      (float) (n - bottom) /
+              (top - bottom);
+    delay = how_much * how_much * 1000;
+  }
+  assert(delay <= 1000);
+  return delay;
+}
+
+// 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_hard_rate_limit_delay = !force;
+  bool allow_soft_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 0-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 delayed;
+      {
+        StopWatch sw(env_, options_.statistics, STALL_L0_SLOWDOWN_COUNT);
+        env_->SleepForMicroseconds(
+          SlowdownAmount(versions_->NumLevelFiles(0),
+                         options_.level0_slowdown_writes_trigger,
+                         options_.level0_stop_writes_trigger)
+        );
+        delayed = sw.ElapsedMicros();
+      }
+      RecordTick(options_.statistics, STALL_L0_SLOWDOWN_MICROS, delayed);
+      stall_level0_slowdown_ += delayed;
+      stall_level0_slowdown_count_++;
+      allow_delay = false;  // Do not delay a single write more than once
+      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 stall;
+      {
+        StopWatch sw(env_, options_.statistics,
+          STALL_MEMTABLE_COMPACTION_COUNT);
+        bg_cv_.Wait();
+        stall = sw.ElapsedMicros();
+      }
+      RecordTick(options_.statistics, STALL_MEMTABLE_COMPACTION_MICROS, stall);
+      stall_memtable_compaction_ += stall;
+      stall_memtable_compaction_count_++;
+    } else if (versions_->NumLevelFiles(0) >=
+               options_.level0_stop_writes_trigger) {
+      // There are too many level-0 files.
+      DelayLoggingAndReset();
+      Log(options_.info_log, "wait for fewer level0 files...\n");
+      uint64_t stall;
+      {
+        StopWatch sw(env_, options_.statistics, STALL_L0_NUM_FILES_COUNT);
+        bg_cv_.Wait();
+        stall = sw.ElapsedMicros();
+      }
+      RecordTick(options_.statistics, STALL_L0_NUM_FILES_MICROS, stall);
+      stall_level0_num_files_ += stall;
+      stall_level0_num_files_count_++;
+    } else if (
+        allow_hard_rate_limit_delay &&
+        options_.hard_rate_limit > 1.0 &&
+        (score = versions_->MaxCompactionScore()) > options_.hard_rate_limit) {
+      // Delay a write when the compaction score for any level is too large.
+      int max_level = versions_->MaxCompactionScoreLevel();
+      mutex_.Unlock();
+      uint64_t delayed;
+      {
+        StopWatch sw(env_, options_.statistics, HARD_RATE_LIMIT_DELAY_COUNT);
+        env_->SleepForMicroseconds(1000);
+        delayed = sw.ElapsedMicros();
+      }
+      stall_leveln_slowdown_[max_level] += delayed;
+      stall_leveln_slowdown_count_[max_level]++;
+      // Make sure the following value doesn't round to zero.
+      uint64_t rate_limit = std::max((delayed / 1000), (uint64_t) 1);
+      rate_limit_delay_millis += rate_limit;
+      RecordTick(options_.statistics, RATE_LIMIT_DELAY_MILLIS, rate_limit);
+      if (options_.rate_limit_delay_max_milliseconds > 0 &&
+          rate_limit_delay_millis >=
+          (unsigned)options_.rate_limit_delay_max_milliseconds) {
+        allow_hard_rate_limit_delay = false;
+      }
+      mutex_.Lock();
+    } else if (
+        allow_soft_rate_limit_delay &&
+        options_.soft_rate_limit > 0.0 &&
+        (score = versions_->MaxCompactionScore()) > options_.soft_rate_limit) {
+      // Delay a write when the compaction score for any level is too large.
+      // TODO: add statistics
+      mutex_.Unlock();
+      {
+        StopWatch sw(env_, options_.statistics, SOFT_RATE_LIMIT_DELAY_COUNT);
+        env_->SleepForMicroseconds(SlowdownAmount(
+          score,
+          options_.soft_rate_limit,
+          options_.hard_rate_limit)
+        );
+        rate_limit_delay_millis += sw.ElapsedMicros();
+      }
+      allow_soft_rate_limit_delay = false;
+      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<WritableFile> lfile;
+      EnvOptions soptions(storage_options_);
+      soptions.use_mmap_writes = false;
+      s = env_->NewWritableFile(
+            LogFileName(options_.wal_dir, new_log_number),
+            &lfile,
+            soptions
+          );
+      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)));
+      mem_->SetNextLogNumber(logfile_number_);
+      imm_.Add(mem_);
+      if (force) {
+        imm_.FlushRequested();
+      }
+      mem_ = new MemTable(
+          internal_comparator_, mem_rep_factory_, NumberLevels(), options_);
+      mem_->Ref();
+      Log(options_.info_log,
+          "New memtable created with log file: #%lu\n",
+          (unsigned long)logfile_number_);
+      mem_->SetLogNumber(logfile_number_);
+      force = false;   // Do not force another compaction if have room
+      MaybeScheduleFlushOrCompaction();
+    }
+  }
+  return s;
+}
+
+bool DBImpl::GetProperty(const Slice& property, std::string* value) {
+  value->clear();
+
+  MutexLock l(&mutex_);
+  Slice in = property;
+  Slice prefix("rocksdb.");
+  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<int>(level)));
+      *value = buf;
+      return true;
+    }
+  } else if (in == "levelstats") {
+    char buf[1000];
+    snprintf(buf, sizeof(buf),
+             "Level Files Size(MB)\n"
+             "--------------------\n");
+    value->append(buf);
+
+    for (int level = 0; level < NumberLevels(); level++) {
+      snprintf(buf, sizeof(buf),
+               "%3d %8d %8.0f\n",
+               level,
+               versions_->NumLevelFiles(level),
+               versions_->NumLevelBytes(level) / 1048576.0);
+      value->append(buf);
+    }
+    return true;
+
+  } else if (in == "stats") {
+    char buf[1000];
+    uint64_t total_bytes_written = 0;
+    uint64_t total_bytes_read = 0;
+    uint64_t micros_up = env_->NowMicros() - started_at_;
+    // Add "+1" to make sure seconds_up is > 0 and avoid NaN later
+    double seconds_up = (micros_up + 1) / 1000000.0;
+    uint64_t total_slowdown = 0;
+    uint64_t total_slowdown_count = 0;
+    uint64_t interval_bytes_written = 0;
+    uint64_t interval_bytes_read = 0;
+    uint64_t interval_bytes_new = 0;
+    double   interval_seconds_up = 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) Score Time(sec)  Read(MB) Write(MB)    Rn(MB)  Rnp1(MB)  Wnew(MB) RW-Amplify Read(MB/s) Write(MB/s)      Rn     Rnp1     Wnp1     NewW    Count  Ln-stall Stall-cnt\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 +
+               stats_[level].bytes_readn) /
+                (double) stats_[level].bytes_readn;
+
+        total_bytes_read += bytes_read;
+        total_bytes_written += stats_[level].bytes_written;
+
+        snprintf(
+            buf, sizeof(buf),
+            "%3d %8d %8.0f %5.1f %9.0f %9.0f %9.0f %9.0f %9.0f %9.0f %10.1f %9.1f %11.1f %8d %8d %8d %8d %8d %9.1f %9lu\n",
+            level,
+            files,
+            versions_->NumLevelBytes(level) / 1048576.0,
+            versions_->NumLevelBytes(level) /
+                versions_->MaxBytesForLevel(level),
+            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,
+            // +1 to avoid division by 0
+            (bytes_read / 1048576.0) / ((stats_[level].micros+1) / 1000000.0),
+            (stats_[level].bytes_written / 1048576.0) /
+                ((stats_[level].micros+1) / 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,
+            (unsigned long) stall_leveln_slowdown_count_[level]);
+        total_slowdown += stall_leveln_slowdown_[level];
+        total_slowdown_count += stall_leveln_slowdown_count_[level];
+        value->append(buf);
+      }
+    }
+
+    interval_bytes_new = stats_[0].bytes_written - last_stats_.bytes_new_;
+    interval_bytes_read = total_bytes_read - last_stats_.bytes_read_;
+    interval_bytes_written = total_bytes_written - last_stats_.bytes_written_;
+    interval_seconds_up = seconds_up - last_stats_.seconds_up_;
+
+    snprintf(buf, sizeof(buf), "Uptime(secs): %.1f total, %.1f interval\n",
+             seconds_up, interval_seconds_up);
+    value->append(buf);
+
+    snprintf(buf, sizeof(buf),
+             "Compaction IO cumulative (GB): "
+             "%.2f new, %.2f read, %.2f write, %.2f read+write\n",
+             stats_[0].bytes_written / (1048576.0 * 1024),
+             total_bytes_read / (1048576.0 * 1024),
+             total_bytes_written / (1048576.0 * 1024),
+             (total_bytes_read + total_bytes_written) / (1048576.0 * 1024));
+    value->append(buf);
+
+    snprintf(buf, sizeof(buf),
+             "Compaction IO cumulative (MB/sec): "
+             "%.1f new, %.1f read, %.1f write, %.1f read+write\n",
+             stats_[0].bytes_written / 1048576.0 / seconds_up,
+             total_bytes_read / 1048576.0 / seconds_up,
+             total_bytes_written / 1048576.0 / seconds_up,
+             (total_bytes_read + total_bytes_written) / 1048576.0 / seconds_up);
+    value->append(buf);
+
+    // +1 to avoid divide by 0 and NaN
+    snprintf(buf, sizeof(buf),
+             "Amplification cumulative: %.1f write, %.1f compaction\n",
+             (double) total_bytes_written / (stats_[0].bytes_written+1),
+             (double) (total_bytes_written + total_bytes_read)
+                  / (stats_[0].bytes_written+1));
+    value->append(buf);
+
+    snprintf(buf, sizeof(buf),
+             "Compaction IO interval (MB): "
+             "%.2f new, %.2f read, %.2f write, %.2f read+write\n",
+             interval_bytes_new / 1048576.0,
+             interval_bytes_read/ 1048576.0,
+             interval_bytes_written / 1048576.0,
+             (interval_bytes_read + interval_bytes_written) / 1048576.0);
+    value->append(buf);
+
+    snprintf(buf, sizeof(buf),
+             "Compaction IO interval (MB/sec): "
+             "%.1f new, %.1f read, %.1f write, %.1f read+write\n",
+             interval_bytes_new / 1048576.0 / interval_seconds_up,
+             interval_bytes_read / 1048576.0 / interval_seconds_up,
+             interval_bytes_written / 1048576.0 / interval_seconds_up,
+             (interval_bytes_read + interval_bytes_written)
+                 / 1048576.0 / interval_seconds_up);
+    value->append(buf);
+
+    // +1 to avoid divide by 0 and NaN
+    snprintf(buf, sizeof(buf),
+             "Amplification interval: %.1f write, %.1f compaction\n",
+             (double) interval_bytes_written / (interval_bytes_new+1),
+             (double) (interval_bytes_written + interval_bytes_read) /
+                  (interval_bytes_new+1));
+    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);
+
+    snprintf(buf, sizeof(buf),
+            "Stalls(count): %lu level0_slowdown, %lu level0_numfiles, "
+            "%lu memtable_compaction, %lu leveln_slowdown\n",
+            (unsigned long) stall_level0_slowdown_count_,
+            (unsigned long) stall_level0_num_files_count_,
+            (unsigned long) stall_memtable_compaction_count_,
+            (unsigned long) total_slowdown_count);
+    value->append(buf);
+
+    last_stats_.bytes_read_ = total_bytes_read;
+    last_stats_.bytes_written_ = total_bytes_written;
+    last_stats_.bytes_new_ = stats_[0].bytes_written;
+    last_stats_.seconds_up_ = seconds_up;
+
+    return true;
+  } else if (in == "sstables") {
+    *value = versions_->current()->DebugString();
+    return true;
+  } else if (in == "num-immutable-mem-table") {
+    *value = std::to_string(imm_.size());
+    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;
+  }
+}
+
+Status DBImpl::DeleteFile(std::string name) {
+  uint64_t number;
+  FileType type;
+  WalFileType log_type;
+  if (!ParseFileName(name, &number, &type, &log_type) ||
+      (type != kTableFile && type != kLogFile)) {
+    Log(options_.info_log, "DeleteFile %s failed.\n", name.c_str());
+    return Status::InvalidArgument("Invalid file name");
+  }
+
+  Status status;
+  if (type == kLogFile) {
+    // Only allow deleting archived log files
+    if (log_type != kArchivedLogFile) {
+      Log(options_.info_log, "DeleteFile %s failed.\n", name.c_str());
+      return Status::NotSupported("Delete only supported for archived logs");
+    }
+    status = env_->DeleteFile(options_.wal_dir + "/" + name.c_str());
+    if (!status.ok()) {
+      Log(options_.info_log, "DeleteFile %s failed.\n", name.c_str());
+    }
+    return status;
+  }
+
+  int level;
+  FileMetaData metadata;
+  int maxlevel = NumberLevels();
+  VersionEdit edit(maxlevel);
+  DeletionState deletion_state;
+  {
+    MutexLock l(&mutex_);
+    status = versions_->GetMetadataForFile(number, &level, &metadata);
+    if (!status.ok()) {
+      Log(options_.info_log, "DeleteFile %s failed. File not found\n",
+                             name.c_str());
+      return Status::InvalidArgument("File not found");
+    }
+    assert((level > 0) && (level < maxlevel));
+
+    // If the file is being compacted no need to delete.
+    if (metadata.being_compacted) {
+      Log(options_.info_log,
+          "DeleteFile %s Skipped. File about to be compacted\n", name.c_str());
+      return Status::OK();
+    }
+
+    // Only the files in the last level can be deleted externally.
+    // This is to make sure that any deletion tombstones are not
+    // lost. Check that the level passed is the last level.
+    for (int i = level + 1; i < maxlevel; i++) {
+      if (versions_->NumLevelFiles(i) != 0) {
+        Log(options_.info_log,
+            "DeleteFile %s FAILED. File not in last level\n", name.c_str());
+        return Status::InvalidArgument("File not in last level");
+      }
+    }
+    edit.DeleteFile(level, number);
+    status = versions_->LogAndApply(&edit, &mutex_);
+    FindObsoleteFiles(deletion_state, false);
+  } // lock released here
+  LogFlush(options_.info_log);
+
+  if (status.ok()) {
+    // remove files outside the db-lock
+    PurgeObsoleteFiles(deletion_state);
+  }
+  return status;
+}
+
+void DBImpl::GetLiveFilesMetaData(std::vector<LiveFileMetaData> *metadata) {
+  MutexLock l(&mutex_);
+  return versions_->GetLiveFilesMetaData(metadata);
+}
+
+// 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);
+}
+
+Status DB::Merge(const WriteOptions& opt, const Slice& key,
+                 const Slice& value) {
+  WriteBatch batch;
+  batch.Merge(key, value);
+  return Write(opt, &batch);
+}
+
+DB::~DB() { }
+
+Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) {
+  *dbptr = nullptr;
+  EnvOptions soptions;
+
+  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->env_->CreateDirIfMissing(impl->options_.wal_dir);
+  if (!s.ok()) {
+    delete impl;
+    return s;
+  }
+
+  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<WritableFile> lfile;
+    soptions.use_mmap_writes = false;
+    s = options.env->NewWritableFile(
+      LogFileName(impl->options_.wal_dir, new_log_number),
+      &lfile,
+      soptions
+    );
+    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->mem_->SetLogNumber(impl->logfile_number_);
+      impl->DeleteObsoleteFiles();
+      impl->MaybeScheduleFlushOrCompaction();
+      impl->MaybeScheduleLogDBDeployStats();
+    }
+  }
+  impl->mutex_.Unlock();
+
+  if (options.compaction_style == kCompactionStyleUniversal) {
+    int num_files;
+    for (int i = 1; i < impl->NumberLevels(); i++) {
+      num_files = impl->versions_->NumLevelFiles(i);
+      if (num_files > 0) {
+        s = Status::InvalidArgument("Not all files are at level 0. Cannot "
+          "open with universal compaction style.");
+        break;
+      }
+    }
+  }
+
+  if (s.ok()) {
+    *dbptr = impl;
+  } else {
+    delete impl;
+  }
+  return s;
+}
+
+Snapshot::~Snapshot() {
+}
+
+Status DestroyDB(const std::string& dbname, const Options& options) {
+  const InternalKeyComparator comparator(options.comparator);
+  const InternalFilterPolicy filter_policy(options.filter_policy);
+  const Options& soptions(SanitizeOptions(
+    dbname, &comparator, &filter_policy, options));
+  Env* env = soptions.env;
+  std::vector<std::string> filenames;
+  std::vector<std::string> archiveFiles;
+
+  std::string archivedir = ArchivalDirectory(dbname);
+  // Ignore error in case directory does not exist
+  env->GetChildren(dbname, &filenames);
+
+  if (dbname != soptions.wal_dir) {
+    std::vector<std::string> logfilenames;
+    env->GetChildren(soptions.wal_dir, &logfilenames);
+    filenames.insert(filenames.end(), logfilenames.begin(), logfilenames.end());
+    archivedir = ArchivalDirectory(soptions.wal_dir);
+  }
+
+  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 if (type == kLogFile) {
+          del = env->DeleteFile(soptions.wal_dir + "/" + filenames[i]);
+        } else {
+          del = env->DeleteFile(dbname + "/" + filenames[i]);
+        }
+        if (result.ok() && !del.ok()) {
+          result = del;
+        }
+      }
+    }
+
+    env->GetChildren(archivedir, &archiveFiles);
+    // Delete archival files.
+    for (size_t i = 0; i < archiveFiles.size(); ++i) {
+      if (ParseFileName(archiveFiles[i], &number, &type) &&
+          type == kLogFile) {
+        Status del = env->DeleteFile(archivedir + "/" + archiveFiles[i]);
+        if (result.ok() && !del.ok()) {
+          result = del;
+        }
+      }
+    }
+    // ignore case where no archival directory is present.
+    env->DeleteDir(archivedir);
+
+    env->UnlockFile(lock);  // Ignore error since state is already gone
+    env->DeleteFile(lockname);
+    env->DeleteDir(dbname);  // Ignore error in case dir contains other files
+    env->DeleteDir(soptions.wal_dir);
+  }
+  return result;
+}
+
+//
+// A global method that can dump out the build version
+void dumpLeveldbBuildVersion(Logger * log) {
+  Log(log, "Git sha %s", rocksdb_build_git_sha);
+  Log(log, "Compile time %s %s",
+      rocksdb_build_compile_time, rocksdb_build_compile_date);
+}
+
+}  // namespace rocksdb
diff --git a/db/db_impl.h b/db/db_impl.h
new file mode 100644 (file)
index 0000000..dc4c20a
--- /dev/null
@@ -0,0 +1,497 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+#pragma once
+#include <atomic>
+#include <deque>
+#include <set>
+#include <vector>
+#include "db/dbformat.h"
+#include "db/log_writer.h"
+#include "db/snapshot.h"
+#include "db/version_edit.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/memtablerep.h"
+#include "rocksdb/transaction_log.h"
+#include "port/port.h"
+#include "util/stats_logger.h"
+#include "memtablelist.h"
+
+namespace rocksdb {
+
+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 Merge(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 std::vector<Status> MultiGet(const ReadOptions& options,
+                                       const std::vector<Slice>& keys,
+                                       std::vector<std::string>* values);
+
+  // Returns false if key doesn't exist in the database and true if it may.
+  // If value_found is not passed in as null, then return the value if found in
+  // memory. On return, if value was found, then value_found will be set to true
+  // , otherwise false.
+  virtual bool KeyMayExist(const ReadOptions& options,
+                           const Slice& key,
+                           std::string* value,
+                           bool* value_found = nullptr);
+  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,
+                            bool reduce_level = false, int target_level = -1);
+  virtual int NumberLevels();
+  virtual int MaxMemCompactionLevel();
+  virtual int Level0StopWriteTrigger();
+  virtual Status Flush(const FlushOptions& options);
+  virtual Status DisableFileDeletions();
+  virtual Status EnableFileDeletions();
+  // All the returned filenames start with "/"
+  virtual Status GetLiveFiles(std::vector<std::string>&,
+                              uint64_t* manifest_file_size,
+                              bool flush_memtable = true);
+  virtual Status GetSortedWalFiles(VectorLogPtr& files);
+  virtual SequenceNumber GetLatestSequenceNumber() const;
+  virtual Status GetUpdatesSince(SequenceNumber seq_number,
+                                 unique_ptr<TransactionLogIterator>* iter);
+  virtual Status DeleteFile(std::string name);
+
+  virtual void GetLiveFilesMetaData(
+    std::vector<LiveFileMetaData> *metadata);
+
+  // 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 flushed.
+  Status TEST_FlushMemTable();
+
+  // Wait for memtable compaction
+  Status TEST_WaitForFlushMemTable();
+
+  // 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();
+
+  // Trigger's a background call for testing.
+  void TEST_PurgeObsoleteteWAL();
+
+  // get total level0 file size. Only for testing.
+  uint64_t TEST_GetLevel0TotalSize() { return versions_->NumLevelBytes(0);}
+
+  void TEST_SetDefaultTimeToCheck(uint64_t default_interval_to_delete_obsolete_WAL)
+  {
+    default_interval_to_delete_obsolete_WAL_ = default_interval_to_delete_obsolete_WAL;
+  }
+
+  // needed for CleanupIteratorState
+
+  struct DeletionState {
+    inline bool HaveSomethingToDelete() const {
+      return all_files.size() ||
+        sst_delete_files.size() ||
+        log_delete_files.size();
+    }
+    // a list of all files that we'll consider deleting
+    // (every once in a while this is filled up with all files
+    // in the DB directory)
+    std::vector<std::string> all_files;
+
+    // the list of all live sst files that cannot be deleted
+    std::vector<uint64_t> sst_live;
+
+    // a list of sst files that we need to delete
+    std::vector<FileMetaData*> sst_delete_files;
+
+    // a list of log files that we need to delete
+    std::vector<uint64_t> log_delete_files;
+
+    // the current manifest_file_number, log_number and prev_log_number
+    // that corresponds to the set of files in 'live'.
+    uint64_t manifest_file_number, log_number, prev_log_number;
+
+    DeletionState() {
+      manifest_file_number = 0;
+      log_number = 0;
+      prev_log_number = 0;
+    }
+  };
+
+  // Returns the list of live files in 'live' and the list
+  // of all files in the filesystem in 'all_files'.
+  // If force == false and the last call was less than
+  // options_.delete_obsolete_files_period_micros microseconds ago,
+  // it will not fill up the deletion_state
+  void FindObsoleteFiles(DeletionState& deletion_state,
+                         bool force,
+                         bool no_full_scan = false);
+
+  // Diffs the files listed in filenames and those that do not
+  // belong to live files are posibly removed. Also, removes all the
+  // files in sst_delete_files and log_delete_files.
+  // It is not necessary to hold the mutex when invoking this method.
+  void PurgeObsoleteFiles(DeletionState& deletion_state);
+
+ protected:
+  Env* const env_;
+  const std::string dbname_;
+  unique_ptr<VersionSet> 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;
+
+  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();
+
+  // Flush the in-memory write buffer to storage.  Switches to a new
+  // log-file/memtable and writes a new descriptor iff successful.
+  Status FlushMemTableToOutputFile(bool* madeProgress,
+                                   DeletionState& deletion_state);
+
+  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(std::vector<MemTable*> &mems, VersionEdit* edit,
+                                uint64_t* filenumber);
+
+  uint64_t SlowdownAmount(int n, int top, int bottom);
+  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 flushed
+  Status WaitForFlushMemTable();
+
+  void MaybeScheduleLogDBDeployStats();
+  static void BGLogDBDeployStats(void* db);
+  void LogDBDeployStats();
+
+  void MaybeScheduleFlushOrCompaction();
+  static void BGWorkCompaction(void* db);
+  static void BGWorkFlush(void* db);
+  void BackgroundCallCompaction();
+  void BackgroundCallFlush();
+  Status BackgroundCompaction(bool* madeProgress,DeletionState& deletion_state);
+  Status BackgroundFlush(bool* madeProgress, DeletionState& deletion_state);
+  void CleanupCompaction(CompactionState* compact, Status status);
+  Status DoCompactionWork(CompactionState* compact,
+                          DeletionState& deletion_state);
+
+  Status OpenCompactionOutputFile(CompactionState* compact);
+  Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input);
+  Status InstallCompactionResults(CompactionState* compact);
+  void AllocateCompactionOutputFileNumbers(CompactionState* compact);
+  void ReleaseCompactionUnusedFileNumbers(CompactionState* compact);
+
+  void PurgeObsoleteWALFiles();
+
+  Status AppendSortedWalsOfType(const std::string& path,
+                                VectorLogPtr& log_files,
+                                WalFileType type);
+
+  // Requires: all_logs should be sorted with earliest log file first
+  // Retains all log files in all_logs which contain updates with seq no.
+  // Greater Than or Equal to the requested SequenceNumber.
+  Status RetainProbableWalFiles(VectorLogPtr& all_logs,
+                                const SequenceNumber target);
+  //  return true if
+  bool CheckWalFileExistsAndEmpty(const WalFileType type,
+                                  const uint64_t number);
+
+  Status ReadFirstRecord(const WalFileType type, const uint64_t number,
+                         WriteBatch* const result);
+
+  Status ReadFirstLine(const std::string& fname, WriteBatch* const batch);
+
+  void PrintStatistics();
+
+  // dump rocksdb.stats to LOG
+  void MaybeDumpStats();
+
+  // Return the minimum empty level that could hold the total data in the
+  // input level. Return the input level, if such level could not be found.
+  int FindMinimumEmptyLevelFitting(int level);
+
+  // Move the files in the input level to the target level.
+  // If target_level < 0, automatically calculate the minimum level that could
+  // hold the data set.
+  void ReFitLevel(int level, int target_level = -1);
+
+  // Constant after construction
+  const InternalFilterPolicy internal_filter_policy_;
+  bool owns_info_log_;
+
+  // table_cache_ provides its own synchronization
+  unique_ptr<TableCache> 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
+  std::shared_ptr<MemTableRepFactory> mem_rep_factory_;
+  MemTable* mem_;
+  MemTableList imm_;             // Memtable that are not changing
+  uint64_t logfile_number_;
+  unique_ptr<log::Writer> log_;
+
+  std::string host_name_;
+
+  // Queue of writers.
+  std::deque<Writer*> writers_;
+  WriteBatch tmp_batch_;
+
+  SnapshotList snapshots_;
+
+  // Set of table files to protect from deletion because they are
+  // part of ongoing compactions.
+  std::set<uint64_t> pending_outputs_;
+
+  // count how many background compaction been scheduled or is running?
+  int bg_compaction_scheduled_;
+
+  // number of background memtable flush jobs, submitted to the HIGH pool
+  int bg_flush_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_;
+
+  std::unique_ptr<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_;
+
+  // last time when PurgeObsoleteWALFiles ran.
+  uint64_t purge_wal_files_last_run_;
+
+  // last time stats were dumped to LOG
+  std::atomic<uint64_t> last_stats_dump_time_microsec_;
+
+  // obsolete files will be deleted every this seconds if ttl deletion is
+  // enabled and archive size_limit is disabled.
+  uint64_t default_interval_to_delete_obsolete_WAL_;
+
+  // 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<uint64_t> stall_leveln_slowdown_;
+  uint64_t stall_level0_slowdown_count_;
+  uint64_t stall_memtable_compaction_count_;
+  uint64_t stall_level0_num_files_count_;
+  std::vector<uint64_t> stall_leveln_slowdown_count_;
+
+  // 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;
+    }
+  };
+
+  std::vector<CompactionStats> stats_;
+
+  // Used to compute per-interval statistics
+  struct StatsSnapshot {
+    uint64_t bytes_read_;
+    uint64_t bytes_written_;
+    uint64_t bytes_new_;
+    double   seconds_up_;
+
+    StatsSnapshot() : bytes_read_(0), bytes_written_(0),
+                      bytes_new_(0), seconds_up_(0) {}
+  };
+
+  StatsSnapshot last_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_;
+
+  // The options to access storage files
+  const EnvOptions storage_options_;
+
+  // A value of true temporarily disables scheduling of background work
+  bool bg_work_gate_closed_;
+
+  // Guard against multiple concurrent refitting
+  bool refitting_level_;
+
+  // No copying allowed
+  DBImpl(const DBImpl&);
+  void operator=(const DBImpl&);
+
+  // dump the delayed_writes_ to the log file and reset counter.
+  void DelayLoggingAndReset();
+
+  // Return the earliest snapshot where seqno is visible.
+  // Store the snapshot right before that, if any, in prev_snapshot
+  inline SequenceNumber findEarliestVisibleSnapshot(
+    SequenceNumber in,
+    std::vector<SequenceNumber>& snapshots,
+    SequenceNumber* prev_snapshot);
+
+  // Function that Get and KeyMayExist call with no_io true or false
+  // Note: 'value_found' from KeyMayExist propagates here
+  Status GetImpl(const ReadOptions& options,
+                 const Slice& key,
+                 std::string* value,
+                 bool* value_found = nullptr);
+};
+
+// 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);
+
+
+// Determine compression type, based on user options, level of the output
+// file and whether compression is disabled.
+// If enable_compression is false, then compression is always disabled no
+// matter what the values of the other two parameters are.
+// Otherwise, the compression type is determined based on options and level.
+CompressionType GetCompressionType(const Options& options, int level,
+                                   const bool enable_compression);
+
+}  // namespace rocksdb
diff --git a/db/db_impl_readonly.cc b/db/db_impl_readonly.cc
new file mode 100644 (file)
index 0000000..27d5c31
--- /dev/null
@@ -0,0 +1,99 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <algorithm>
+#include <set>
+#include <string>
+#include <stdint.h>
+#include <stdio.h>
+#include <vector>
+#include <algorithm>
+#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 "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/status.h"
+#include "rocksdb/table.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 rocksdb {
+
+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();
+  std::deque<std::string> merge_operands;
+  LookupKey lkey(key, snapshot);
+  if (mem->Get(lkey, value, &s, &merge_operands, options_)) {
+  } else {
+    Version::GetStats stats;
+    current->Get(options, lkey, value, &s, &merge_operands, &stats, options_);
+  }
+  return s;
+}
+
+Iterator* DBImplReadOnly::NewIterator(const ReadOptions& options) {
+  SequenceNumber latest_snapshot;
+  Iterator* internal_iter = NewInternalIterator(options, &latest_snapshot);
+  return NewDBIterator(
+    &dbname_, env_, options_,  user_comparator(),internal_iter,
+      (options.snapshot != nullptr
+      ? reinterpret_cast<const SnapshotImpl*>(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 (file)
index 0000000..af9c79e
--- /dev/null
@@ -0,0 +1,78 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include "db/db_impl.h"
+
+#include <deque>
+#include <set>
+#include "db/dbformat.h"
+#include "db/log_writer.h"
+#include "db/snapshot.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "port/port.h"
+#include "util/stats_logger.h"
+
+namespace rocksdb {
+
+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);
+
+ // TODO: Implement ReadOnly MultiGet?
+
+ 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 Merge(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,
+                           bool reduce_level = false, int target_level = -1) {
+ }
+ 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<std::string>&,
+                             uint64_t* manifest_file_size,
+                             bool flush_memtable = true) {
+   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&);
+};
+
+}
diff --git a/db/db_iter.cc b/db/db_iter.cc
new file mode 100644 (file)
index 0000000..4e3c52c
--- /dev/null
@@ -0,0 +1,481 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <stdexcept>
+#include <deque>
+
+#include "db/filename.h"
+#include "db/dbformat.h"
+#include "rocksdb/env.h"
+#include "rocksdb/options.h"
+#include "rocksdb/iterator.h"
+#include "rocksdb/merge_operator.h"
+#include "port/port.h"
+#include "util/logging.h"
+#include "util/mutexlock.h"
+#include "util/perf_context_imp.h"
+
+namespace rocksdb {
+
+#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:
+  // The following is grossly complicated. TODO: clean it up
+  // 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 Options& options,
+         const Comparator* cmp, Iterator* iter, SequenceNumber s)
+      : dbname_(dbname),
+        env_(env),
+        logger_(options.info_log),
+        user_comparator_(cmp),
+        user_merge_operator_(options.merge_operator.get()),
+        iter_(iter),
+        sequence_(s),
+        direction_(kForward),
+        valid_(false),
+        current_entry_is_merged_(false),
+        statistics_(options.statistics) {
+    RecordTick(statistics_, NO_ITERATORS, 1);
+    max_skip_ = options.max_sequential_skip_in_iterations;
+  }
+  virtual ~DBIter() {
+    RecordTick(statistics_, NO_ITERATORS, -1);
+    delete iter_;
+  }
+  virtual bool Valid() const { return valid_; }
+  virtual Slice key() const {
+    assert(valid_);
+    return saved_key_;
+  }
+  virtual Slice value() const {
+    assert(valid_);
+    return (direction_ == kForward && !current_entry_is_merged_) ?
+      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);
+  void FindPrevUserEntry();
+  bool ParseKey(ParsedInternalKey* key);
+  void MergeValuesNewToOld();
+
+  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_;
+  shared_ptr<Logger> logger_;
+  const Comparator* const user_comparator_;
+  const MergeOperator* const user_merge_operator_;
+  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
+  std::string skip_key_;
+  Direction direction_;
+  bool valid_;
+  bool current_entry_is_merged_;
+  std::shared_ptr<Statistics> statistics_;
+  uint64_t max_skip_;
+
+  // 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");
+    Log(logger_, "corrupted internal key in DBIter: %s",
+        iter_->key().ToString(true).c_str());
+    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;
+    }
+  }
+
+  // If the current value is merged, we might already hit end of iter_
+  if (!iter_->Valid()) {
+    valid_ = false;
+    return;
+  }
+  FindNextUserEntry(true /* skipping the current user key */);
+}
+
+
+// PRE: saved_key_ has the current user key if skipping
+// POST: saved_key_ should have the next user key if valid_,
+//       if the current entry is a result of merge
+//           current_entry_is_merged_ => true
+//           saved_value_             => the merged value
+//
+// NOTE: In between, saved_key_ can point to a user key that has
+//       a delete marker
+void DBIter::FindNextUserEntry(bool skipping) {
+  // Loop until we hit an acceptable entry to yield
+  assert(iter_->Valid());
+  assert(direction_ == kForward);
+  current_entry_is_merged_ = false;
+  uint64_t num_skipped = 0;
+  do {
+    ParsedInternalKey ikey;
+    if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
+      if (skipping &&
+          user_comparator_->Compare(ikey.user_key, saved_key_) <= 0) {
+        num_skipped++; // skip this entry
+        BumpPerfCount(&perf_context.internal_key_skipped_count);
+      } else {
+        skipping = false;
+        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, &saved_key_);
+            skipping = true;
+            num_skipped = 0;
+            BumpPerfCount(&perf_context.internal_delete_skipped_count);
+            break;
+          case kTypeValue:
+            valid_ = true;
+            SaveKey(ikey.user_key, &saved_key_);
+            return;
+          case kTypeMerge:
+            // By now, we are sure the current ikey is going to yield a value
+            SaveKey(ikey.user_key, &saved_key_);
+            current_entry_is_merged_ = true;
+            valid_ = true;
+            MergeValuesNewToOld();  // Go to a different state machine
+            return;
+          case kTypeLogData:
+            assert(false);
+            break;
+        }
+      }
+    }
+    // If we have sequentially iterated via numerous keys and still not
+    // found the next user-key, then it is better to seek so that we can
+    // avoid too many key comparisons. We seek to the last occurence of
+    // our current key by looking for sequence number 0.
+    if (skipping && num_skipped > max_skip_) {
+      num_skipped = 0;
+      std::string last_key;
+      AppendInternalKey(&last_key,
+        ParsedInternalKey(Slice(saved_key_), 0, kValueTypeForSeek));
+      iter_->Seek(last_key);
+      RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
+    } else {
+      iter_->Next();
+    }
+  } while (iter_->Valid());
+  valid_ = false;
+}
+
+// Merge values of the same user key starting from the current iter_ position
+// Scan from the newer entries to older entries.
+// PRE: iter_->key() points to the first merge type entry
+//      saved_key_ stores the user key
+// POST: saved_value_ has the merged value for the user key
+//       iter_ points to the next entry (or invalid)
+void DBIter::MergeValuesNewToOld() {
+  if (!user_merge_operator_) {
+    Log(logger_, "Options::merge_operator is null.");
+    throw std::logic_error("DBIter::MergeValuesNewToOld() with"
+                           " Options::merge_operator null");
+  }
+
+  // Start the merge process by pushing the first operand
+  std::deque<std::string> operands;
+  operands.push_front(iter_->value().ToString());
+
+  std::string merge_result;   // Temporary string to hold merge result later
+  ParsedInternalKey ikey;
+  for (iter_->Next(); iter_->Valid(); iter_->Next()) {
+    if (!ParseKey(&ikey)) {
+      // skip corrupted key
+      continue;
+    }
+
+    if (user_comparator_->Compare(ikey.user_key, saved_key_) != 0) {
+      // hit the next user key, stop right here
+      break;
+    }
+
+    if (kTypeDeletion == ikey.type) {
+      // hit a delete with the same user key, stop right here
+      // iter_ is positioned after delete
+      iter_->Next();
+      break;
+    }
+
+    if (kTypeValue == ikey.type) {
+      // hit a put, merge the put value with operands and store the
+      // final result in saved_value_. We are done!
+      // ignore corruption if there is any.
+      const Slice value = iter_->value();
+      user_merge_operator_->FullMerge(ikey.user_key, &value, operands,
+                                      &saved_value_, logger_.get());
+      // iter_ is positioned after put
+      iter_->Next();
+      return;
+    }
+
+    if (kTypeMerge == ikey.type) {
+      // hit a merge, add the value as an operand and run associative merge.
+      // when complete, add result to operands and continue.
+      const Slice& value = iter_->value();
+      operands.push_front(value.ToString());
+      while(operands.size() >= 2) {
+        // Call user associative-merge until it returns false
+        if (user_merge_operator_->PartialMerge(ikey.user_key,
+                                               Slice(operands[0]),
+                                               Slice(operands[1]),
+                                               &merge_result,
+                                               logger_.get())) {
+          operands.pop_front();
+          swap(operands.front(), merge_result);
+        } else {
+          // Associative merge returns false ==> stack the operands
+          break;
+        }
+      }
+
+    }
+  }
+
+  // we either exhausted all internal keys under this user key, or hit
+  // a deletion marker.
+  // feed null as the existing value to the merge operator, such that
+  // client can differentiate this scenario and do things accordingly.
+  user_merge_operator_->FullMerge(saved_key_, nullptr, operands,
+                                  &saved_value_, logger_.get());
+}
+
+void DBIter::Prev() {
+  assert(valid_);
+
+  // Throw an exception now if merge_operator is provided
+  // TODO: support backward iteration
+  if (user_merge_operator_) {
+    Log(logger_, "Prev not supported yet if merge_operator is provided");
+    throw std::logic_error("DBIter::Prev backward iteration not supported"
+                           " if merge_operator is provided");
+  }
+
+  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);
+  uint64_t num_skipped = 0;
+
+  ValueType value_type = kTypeDeletion;
+  if (iter_->Valid()) {
+    do {
+      ParsedInternalKey ikey;
+      bool saved_key_cleared = false;
+      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();
+          saved_key_cleared = true;
+        } 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());
+        }
+      }
+      num_skipped++;
+      // If we have sequentially iterated via numerous keys and still not
+      // found the prev user-key, then it is better to seek so that we can
+      // avoid too many key comparisons. We seek to the first occurence of
+      // our current key by looking for max sequence number.
+      if (!saved_key_cleared && num_skipped > max_skip_) {
+        num_skipped = 0;
+        std::string last_key;
+        AppendInternalKey(&last_key,
+          ParsedInternalKey(Slice(saved_key_), kMaxSequenceNumber,
+                            kValueTypeForSeek));
+        iter_->Seek(last_key);
+        RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
+      } else {
+        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 /*not skipping */);
+  } else {
+    valid_ = false;
+  }
+}
+
+void DBIter::SeekToFirst() {
+  direction_ = kForward;
+  ClearSavedValue();
+  iter_->SeekToFirst();
+  if (iter_->Valid()) {
+    FindNextUserEntry(false /* not skipping */);
+  } else {
+    valid_ = false;
+  }
+}
+
+void DBIter::SeekToLast() {
+  // Throw an exception for now if merge_operator is provided
+  // TODO: support backward iteration
+  if (user_merge_operator_) {
+    Log(logger_, "SeekToLast not supported yet if merge_operator is provided");
+    throw std::logic_error("DBIter::SeekToLast: backward iteration not"
+                           " supported if merge_operator is provided");
+  }
+
+  direction_ = kReverse;
+  ClearSavedValue();
+  iter_->SeekToLast();
+  FindPrevUserEntry();
+}
+
+}  // anonymous namespace
+
+Iterator* NewDBIterator(
+    const std::string* dbname,
+    Env* env,
+    const Options& options,
+    const Comparator *user_key_comparator,
+    Iterator* internal_iter,
+    const SequenceNumber& sequence) {
+  return new DBIter(dbname, env, options, user_key_comparator,
+                    internal_iter, sequence);
+}
+
+}  // namespace rocksdb
diff --git a/db/db_iter.h b/db/db_iter.h
new file mode 100644 (file)
index 0000000..b44e674
--- /dev/null
@@ -0,0 +1,28 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <stdint.h>
+#include "rocksdb/db.h"
+#include "db/dbformat.h"
+
+namespace rocksdb {
+
+// 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 Options& options,
+    const Comparator *user_key_comparator,
+    Iterator* internal_iter,
+    const SequenceNumber& sequence);
+
+}  // namespace rocksdb
diff --git a/db/db_statistics.h b/db/db_statistics.h
new file mode 100644 (file)
index 0000000..87bc863
--- /dev/null
@@ -0,0 +1,65 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <cassert>
+#include <stdlib.h>
+#include <vector>
+#include <memory>
+
+#include "rocksdb/statistics.h"
+#include "util/histogram.h"
+#include "port/port.h"
+#include "util/mutexlock.h"
+
+
+namespace rocksdb {
+
+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 setTickerCount(Tickers tickerType, uint64_t count) {
+    assert(tickerType < TICKER_ENUM_MAX);
+    allTickers_[tickerType].setTickerCount(count);
+  }
+
+  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 histogramData(Histograms histogramType,
+                             HistogramData * const data) {
+    assert(histogramType < HISTOGRAM_ENUM_MAX);
+    allHistograms_[histogramType].Data(data);
+  }
+
+  std::vector<Ticker> allTickers_;
+  std::vector<HistogramImpl> allHistograms_;
+};
+
+std::shared_ptr<Statistics> CreateDBStatistics() {
+  return std::make_shared<DBStatistics>();
+}
+
+} // namespace rocksdb
diff --git a/db/db_stats_logger.cc b/db/db_stats_logger.cc
new file mode 100644 (file)
index 0000000..91810ab
--- /dev/null
@@ -0,0 +1,93 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <string>
+#include <stdint.h>
+#include <stdio.h>
+#include "db/version_set.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "port/port.h"
+#include "util/mutexlock.h"
+
+namespace rocksdb {
+
+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(&current_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<DBImpl*>(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 (file)
index 0000000..0482565
--- /dev/null
@@ -0,0 +1,4914 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <algorithm>
+#include <set>
+
+#include "rocksdb/db.h"
+#include "rocksdb/filter_policy.h"
+#include "db/db_impl.h"
+#include "db/filename.h"
+#include "db/version_set.h"
+#include "db/write_batch_internal.h"
+#include "db/db_statistics.h"
+#include "rocksdb/cache.h"
+#include "rocksdb/compaction_filter.h"
+#include "rocksdb/env.h"
+#include "rocksdb/table.h"
+#include "util/hash.h"
+#include "util/logging.h"
+#include "util/mutexlock.h"
+#include "util/testharness.h"
+#include "util/testutil.h"
+#include "utilities/merge_operators.h"
+
+namespace rocksdb {
+
+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;
+}
+
+static std::string CompressibleString(Random* rnd, int len) {
+  std::string r;
+  test::CompressibleString(rnd, 0.8, 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_;
+
+  // Force write to log files to fail while this pointer is non-nullptr
+  port::AtomicPointer log_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);
+    log_write_error_.Release_Store(nullptr);
+   }
+
+  Status NewWritableFile(const std::string& f, unique_ptr<WritableFile>* r,
+                         const EnvOptions& soptions) {
+    class SSTableFile : public WritableFile {
+     private:
+      SpecialEnv* env_;
+      unique_ptr<WritableFile> base_;
+
+     public:
+      SSTableFile(SpecialEnv* env, unique_ptr<WritableFile>&& 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<WritableFile> base_;
+     public:
+      ManifestFile(SpecialEnv* env, unique_ptr<WritableFile>&& 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();
+        }
+      }
+    };
+    class LogFile : public WritableFile {
+     private:
+      SpecialEnv* env_;
+      unique_ptr<WritableFile> base_;
+     public:
+      LogFile(SpecialEnv* env, unique_ptr<WritableFile>&& b)
+          : env_(env), base_(std::move(b)) { }
+      Status Append(const Slice& data) {
+        if (env_->log_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() { return base_->Sync(); }
+    };
+
+    if (non_writable_.Acquire_Load() != nullptr) {
+      return Status::IOError("simulated write error");
+    }
+
+    Status s = target()->NewWritableFile(f, r, soptions);
+    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)));
+      } else if (strstr(f.c_str(), "log") != nullptr) {
+        r->reset(new LogFile(this, std::move(*r)));
+      }
+    }
+    return s;
+  }
+
+  Status NewRandomAccessFile(const std::string& f,
+                             unique_ptr<RandomAccessFile>* r,
+                             const EnvOptions& soptions) {
+    class CountingFile : public RandomAccessFile {
+     private:
+      unique_ptr<RandomAccessFile> target_;
+      anon::AtomicCounter* counter_;
+     public:
+      CountingFile(unique_ptr<RandomAccessFile>&& 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, soptions);
+    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_;
+
+ protected:
+  // Sequence of option configurations to try
+  enum OptionConfig {
+    kDefault,
+    kVectorRep,
+    kUnsortedRep,
+    kMergePut,
+    kFilter,
+    kUncompressed,
+    kNumLevel_3,
+    kDBLogDir,
+    kWalDir,
+    kManifestFileSize,
+    kCompactOnFlush,
+    kPerfOptions,
+    kDeletesFilterFirst,
+    kPrefixHashRep,
+    kUniversalCompaction,
+    kCompressedBlockCache,
+    kEnd
+  };
+  int option_config_;
+
+ public:
+  std::string dbname_;
+  SpecialEnv* env_;
+  DB* db_;
+
+  Options last_options_;
+
+  // Skip some options, as they may not be applicable to a specific test.
+  // To add more skip constants, use values 4, 8, 16, etc.
+  enum OptionSkip {
+    kNoSkip = 0,
+    kSkipDeletesFilterFirst = 1,
+    kSkipUniversalCompaction = 2,
+    kSkipMergePut = 4
+  };
+
+  DBTest() : option_config_(kDefault),
+             env_(new SpecialEnv(Env::Default())) {
+    filter_policy_ = NewBloomFilterPolicy(10);
+    dbname_ = test::TmpDir() + "/db_test";
+    ASSERT_OK(DestroyDB(dbname_, Options()));
+    db_ = nullptr;
+    Reopen();
+  }
+
+  ~DBTest() {
+    delete db_;
+    ASSERT_OK(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(int skip_mask = kNoSkip) {
+    option_config_++;
+
+    // skip some options
+    if (skip_mask & kSkipDeletesFilterFirst &&
+        option_config_ == kDeletesFilterFirst) {
+      option_config_++;
+    }
+    if (skip_mask & kSkipUniversalCompaction &&
+        option_config_ == kUniversalCompaction) {
+      option_config_++;
+    }
+    if (skip_mask & kSkipMergePut && option_config_ == kMergePut) {
+      option_config_++;
+    }
+    if (option_config_ >= kEnd) {
+      Destroy(&last_options_);
+      return false;
+    } else {
+      DestroyAndReopen();
+      return true;
+    }
+  }
+
+  // Switch between different compaction styles (we have only 2 now).
+  bool ChangeCompactOptions(Options* prev_options = nullptr) {
+    if (option_config_ == kDefault) {
+      option_config_ = kUniversalCompaction;
+      if (prev_options == nullptr) {
+        prev_options = &last_options_;
+      }
+      Destroy(prev_options);
+      TryReopen();
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  // Return the current option configuration.
+  Options CurrentOptions() {
+    Options options;
+    switch (option_config_) {
+      case kPrefixHashRep:
+        options.memtable_factory.reset(new
+          PrefixHashRepFactory(NewFixedPrefixTransform(1)));
+        break;
+      case kMergePut:
+        options.merge_operator = MergeOperators::CreatePutOperator();
+        break;
+      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 kWalDir:
+        options.wal_dir = "/tmp/wal";
+        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.hard_rate_limit = 2.0;
+        options.rate_limit_delay_max_milliseconds = 2;
+        // TODO -- test more options
+        break;
+      case kDeletesFilterFirst:
+        options.filter_deletes = true;
+        break;
+      case kUnsortedRep:
+        options.memtable_factory.reset(new UnsortedRepFactory);
+        break;
+      case kVectorRep:
+        options.memtable_factory.reset(new VectorRepFactory(100));
+        break;
+      case kUniversalCompaction:
+        options.compaction_style = kCompactionStyleUniversal;
+        break;
+      case kCompressedBlockCache:
+        options.block_cache_compressed = NewLRUCache(8*1024*1024);
+        break;
+      default:
+        break;
+    }
+    return options;
+  }
+
+  DBImpl* dbfull() {
+    return reinterpret_cast<DBImpl*>(db_);
+  }
+
+  void Reopen(Options* options = nullptr) {
+    ASSERT_OK(TryReopen(options));
+  }
+
+  void Close() {
+    delete db_;
+    db_ = nullptr;
+  }
+
+  void DestroyAndReopen(Options* options = nullptr) {
+    //Destroy using last options
+    Destroy(&last_options_);
+    ASSERT_OK(TryReopen(options));
+  }
+
+  void Destroy(Options* options) {
+    delete db_;
+    db_ = nullptr;
+    ASSERT_OK(DestroyDB(dbname_, *options));
+  }
+
+  Status PureReopen(Options* options, DB** db) {
+    return DB::Open(*options, dbname_, db);
+  }
+
+  Status TryReopen(Options* options = nullptr) {
+    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 Slice& k, const Slice& v, WriteOptions wo = WriteOptions()) {
+    if (kMergePut == option_config_ ) {
+      return db_->Merge(wo, k, v);
+    } else {
+      return db_->Put(wo, 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.verify_checksums = true;
+    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<std::string> 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 kTypeMerge:
+              // keep it the same as kTypeValue for testing kMergePut
+              result += iter->value().ToString();
+              break;
+            case kTypeDeletion:
+              result += "DEL";
+              break;
+            case kTypeLogData:
+              assert(false);
+              break;
+          }
+        }
+        iter->Next();
+      }
+      if (!first) {
+        result += " ";
+      }
+      result += "]";
+    }
+    delete iter;
+    return result;
+  }
+
+  int NumTableFilesAtLevel(int level) {
+    std::string property;
+    ASSERT_TRUE(
+        db_->GetProperty("rocksdb.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<std::string> files;
+    env_->GetChildren(dbname_, &files);
+
+    std::vector<std::string> logfiles;
+    if (dbname_ != last_options_.wal_dir) {
+      env_->GetChildren(last_options_.wal_dir, &logfiles);
+    }
+
+    return static_cast<int>(files.size() + logfiles.size());
+  }
+
+  int CountLiveFiles() {
+    std::vector<std::string> 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_FlushMemTable();
+    }
+  }
+
+  // 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<long long>(
+                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("rocksdb.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;
+  }
+
+  Options OptionsForLogIterTest() {
+    Options options = CurrentOptions();
+    options.create_if_missing = true;
+    options.WAL_ttl_seconds = 1000;
+    return options;
+  }
+
+  std::unique_ptr<TransactionLogIterator> OpenTransactionLogIter(
+      const SequenceNumber seq) {
+    unique_ptr<TransactionLogIterator> iter;
+    Status status = dbfull()->GetUpdatesSince(seq, &iter);
+    ASSERT_OK(status);
+    ASSERT_TRUE(iter->Valid());
+    return std::move(iter);
+  }
+
+  std::string DummyString(size_t len, char c = 'a') {
+    return std::string(len, c);
+  }
+
+  void VerifyIterLast(std::string expected_key) {
+    Iterator* iter = db_->NewIterator(ReadOptions());
+    iter->SeekToLast();
+    ASSERT_EQ(IterStatus(iter), expected_key);
+    delete iter;
+  }
+};
+
+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());
+}
+
+// Make sure that when options.block_cache is set, after a new table is
+// created its index/filter blocks are added to block cache.
+TEST(DBTest, IndexAndFilterBlocksOfNewTableAddedToCache) {
+  Options options = CurrentOptions();
+  std::unique_ptr<const FilterPolicy> filter_policy(NewBloomFilterPolicy(20));
+  options.filter_policy = filter_policy.get();
+  options.create_if_missing = true;
+  options.statistics = rocksdb::CreateDBStatistics();
+  DestroyAndReopen(&options);
+
+  ASSERT_OK(db_->Put(WriteOptions(), "key", "val"));
+  // Create a new talbe.
+  dbfull()->Flush(FlushOptions());
+
+  // index/filter blocks added to block cache right after table creation.
+  ASSERT_EQ(1,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_INDEX_MISS));
+  ASSERT_EQ(1,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_FILTER_MISS));
+  ASSERT_EQ(2, /* only index/filter were added */
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD));
+  ASSERT_EQ(0,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_DATA_MISS));
+
+  // Make sure filter block is in cache.
+  std::string value;
+  ReadOptions ropt;
+  db_->KeyMayExist(ReadOptions(), "key", &value);
+
+  // Miss count should remain the same.
+  ASSERT_EQ(1,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_FILTER_MISS));
+  ASSERT_EQ(1,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_FILTER_HIT));
+
+  db_->KeyMayExist(ReadOptions(), "key", &value);
+  ASSERT_EQ(1,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_FILTER_MISS));
+  ASSERT_EQ(2,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_FILTER_HIT));
+
+  // Make sure index block is in cache.
+  auto index_block_hit =
+    options.statistics.get()->getTickerCount(BLOCK_CACHE_FILTER_HIT);
+  value = Get("key");
+  ASSERT_EQ(1,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_FILTER_MISS));
+  ASSERT_EQ(index_block_hit + 1,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_FILTER_HIT));
+
+  value = Get("key");
+  ASSERT_EQ(1,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_FILTER_MISS));
+  ASSERT_EQ(index_block_hit + 2,
+            options.statistics.get()->getTickerCount(BLOCK_CACHE_FILTER_HIT));
+}
+
+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;
+  options.max_bytes_for_level_multiplier_additional.resize(1, 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;
+  options.max_bytes_for_level_multiplier_additional.resize(10, 1);
+  ASSERT_OK(TryReopen(&options));
+}
+
+TEST(DBTest, Preallocation) {
+  const std::string src = dbname_ + "/alloc_test";
+  unique_ptr<WritableFile> srcfile;
+  const EnvOptions soptions;
+  ASSERT_OK(env_->NewWritableFile(src, &srcfile, soptions));
+  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_FlushMemTable();
+    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_FlushMemTable();
+      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_FlushMemTable();
+    ASSERT_OK(Put("foo", "v2"));
+    dbfull()->TEST_FlushMemTable();
+    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_FlushMemTable();
+    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_FlushMemTable();
+    }
+
+    // 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(kSkipUniversalCompaction));
+}
+
+// KeyMayExist can lead to a few false positives, but not false negatives.
+// To make test deterministic, use a much larger number of bits per key-20 than
+// bits in the key, so that false positives are eliminated
+TEST(DBTest, KeyMayExist) {
+  do {
+    ReadOptions ropts;
+    std::string value;
+    Options options = CurrentOptions();
+    options.filter_policy = NewBloomFilterPolicy(20);
+    options.statistics = rocksdb::CreateDBStatistics();
+    Reopen(&options);
+
+    ASSERT_TRUE(!db_->KeyMayExist(ropts, "a", &value));
+
+    ASSERT_OK(db_->Put(WriteOptions(), "a", "b"));
+    bool value_found = false;
+    ASSERT_TRUE(db_->KeyMayExist(ropts, "a", &value, &value_found));
+    ASSERT_TRUE(value_found);
+    ASSERT_EQ("b", value);
+
+    dbfull()->Flush(FlushOptions());
+    value.clear();
+
+    long numopen = options.statistics.get()->getTickerCount(NO_FILE_OPENS);
+    long cache_added =
+      options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD);
+    ASSERT_TRUE(db_->KeyMayExist(ropts, "a", &value, &value_found));
+    ASSERT_TRUE(!value_found);
+    // assert that no new files were opened and no new blocks were
+    // read into block cache.
+    ASSERT_EQ(numopen, options.statistics.get()->getTickerCount(NO_FILE_OPENS));
+    ASSERT_EQ(cache_added,
+              options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD));
+
+    ASSERT_OK(db_->Delete(WriteOptions(), "a"));
+
+    numopen = options.statistics.get()->getTickerCount(NO_FILE_OPENS);
+    cache_added =
+      options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD);
+    ASSERT_TRUE(!db_->KeyMayExist(ropts, "a", &value));
+    ASSERT_EQ(numopen, options.statistics.get()->getTickerCount(NO_FILE_OPENS));
+    ASSERT_EQ(cache_added,
+              options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD));
+
+    dbfull()->Flush(FlushOptions());
+    dbfull()->CompactRange(nullptr, nullptr);
+
+    numopen = options.statistics.get()->getTickerCount(NO_FILE_OPENS);
+    cache_added =
+      options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD);
+    ASSERT_TRUE(!db_->KeyMayExist(ropts, "a", &value));
+    ASSERT_EQ(numopen, options.statistics.get()->getTickerCount(NO_FILE_OPENS));
+    ASSERT_EQ(cache_added,
+              options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD));
+
+    ASSERT_OK(db_->Delete(WriteOptions(), "c"));
+
+    numopen = options.statistics.get()->getTickerCount(NO_FILE_OPENS);
+    cache_added =
+      options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD);
+    ASSERT_TRUE(!db_->KeyMayExist(ropts, "c", &value));
+    ASSERT_EQ(numopen, options.statistics.get()->getTickerCount(NO_FILE_OPENS));
+    ASSERT_EQ(cache_added,
+              options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD));
+
+    delete options.filter_policy;
+  } while (ChangeOptions());
+}
+
+TEST(DBTest, NonBlockingIteration) {
+  do {
+    ReadOptions non_blocking_opts, regular_opts;
+    Options options = CurrentOptions();
+    options.statistics = rocksdb::CreateDBStatistics();
+    non_blocking_opts.read_tier = kBlockCacheTier;
+    Reopen(&options);
+    // write one kv to the database.
+    ASSERT_OK(db_->Put(WriteOptions(), "a", "b"));
+
+    // scan using non-blocking iterator. We should find it because
+    // it is in memtable.
+    Iterator* iter = db_->NewIterator(non_blocking_opts);
+    int count = 0;
+    for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
+      ASSERT_OK(iter->status());
+      count++;
+    }
+    ASSERT_EQ(count, 1);
+    delete iter;
+
+    // flush memtable to storage. Now, the key should not be in the
+    // memtable neither in the block cache.
+    dbfull()->Flush(FlushOptions());
+
+    // verify that a non-blocking iterator does not find any
+    // kvs. Neither does it do any IOs to storage.
+    long numopen = options.statistics.get()->getTickerCount(NO_FILE_OPENS);
+    long cache_added =
+      options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD);
+    iter = db_->NewIterator(non_blocking_opts);
+    count = 0;
+    for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
+      count++;
+    }
+    ASSERT_EQ(count, 0);
+    ASSERT_TRUE(iter->status().IsIncomplete());
+    ASSERT_EQ(numopen, options.statistics.get()->getTickerCount(NO_FILE_OPENS));
+    ASSERT_EQ(cache_added,
+              options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD));
+    delete iter;
+
+    // read in the specified block via a regular get
+    ASSERT_EQ(Get("a"), "b");
+
+    // verify that we can find it via a non-blocking scan
+    numopen = options.statistics.get()->getTickerCount(NO_FILE_OPENS);
+    cache_added =
+      options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD);
+    iter = db_->NewIterator(non_blocking_opts);
+    count = 0;
+    for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
+      ASSERT_OK(iter->status());
+      count++;
+    }
+    ASSERT_EQ(count, 1);
+    ASSERT_EQ(numopen, options.statistics.get()->getTickerCount(NO_FILE_OPENS));
+    ASSERT_EQ(cache_added,
+              options.statistics.get()->getTickerCount(BLOCK_CACHE_ADD));
+    delete iter;
+
+  } while (ChangeOptions());
+}
+
+// A delete is skipped for key if KeyMayExist(key) returns False
+// Tests Writebatch consistency and proper delete behaviour
+TEST(DBTest, FilterDeletes) {
+  do {
+    Options options = CurrentOptions();
+    options.filter_policy = NewBloomFilterPolicy(20);
+    options.filter_deletes = true;
+    Reopen(&options);
+    WriteBatch batch;
+
+    batch.Delete("a");
+    dbfull()->Write(WriteOptions(), &batch);
+    ASSERT_EQ(AllEntriesFor("a"), "[ ]"); // Delete skipped
+    batch.Clear();
+
+    batch.Put("a", "b");
+    batch.Delete("a");
+    dbfull()->Write(WriteOptions(), &batch);
+    ASSERT_EQ(Get("a"), "NOT_FOUND");
+    ASSERT_EQ(AllEntriesFor("a"), "[ DEL, b ]"); // Delete issued
+    batch.Clear();
+
+    batch.Delete("c");
+    batch.Put("c", "d");
+    dbfull()->Write(WriteOptions(), &batch);
+    ASSERT_EQ(Get("c"), "d");
+    ASSERT_EQ(AllEntriesFor("c"), "[ d ]"); // Delete skipped
+    batch.Clear();
+
+    dbfull()->Flush(FlushOptions()); // A stray Flush
+
+    batch.Delete("c");
+    dbfull()->Write(WriteOptions(), &batch);
+    ASSERT_EQ(AllEntriesFor("c"), "[ DEL, d ]"); // Delete issued
+    batch.Clear();
+
+    delete options.filter_policy;
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, IterEmpty) {
+  do {
+    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;
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, IterSingle) {
+  do {
+    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;
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, IterMulti) {
+  do {
+    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;
+  } while (ChangeCompactOptions());
+}
+
+// Check that we can skip over a run of user keys
+// by using reseek rather than sequential scan
+TEST(DBTest, IterReseek) {
+  Options options = CurrentOptions();
+  options.max_sequential_skip_in_iterations = 3;
+  options.create_if_missing = true;
+  options.statistics = rocksdb::CreateDBStatistics();
+  DestroyAndReopen(&options);
+
+  // insert two keys with same userkey and verify that
+  // reseek is not invoked. For each of these test cases,
+  // verify that we can find the next key "b".
+  ASSERT_OK(Put("a",  "one"));
+  ASSERT_OK(Put("a",  "two"));
+  ASSERT_OK(Put("b",  "bone"));
+  Iterator* iter = db_->NewIterator(ReadOptions());
+  iter->SeekToFirst();
+  ASSERT_EQ(options.statistics.get()->getTickerCount(
+            NUMBER_OF_RESEEKS_IN_ITERATION), 0);
+  ASSERT_EQ(IterStatus(iter), "a->two");
+  iter->Next();
+  ASSERT_EQ(options.statistics.get()->getTickerCount(
+            NUMBER_OF_RESEEKS_IN_ITERATION), 0);
+  ASSERT_EQ(IterStatus(iter), "b->bone");
+  delete iter;
+
+  // insert a total of three keys with same userkey and verify
+  // that reseek is still not invoked.
+  ASSERT_OK(Put("a",  "three"));
+  iter = db_->NewIterator(ReadOptions());
+  iter->SeekToFirst();
+  ASSERT_EQ(IterStatus(iter), "a->three");
+  iter->Next();
+  ASSERT_EQ(options.statistics.get()->getTickerCount(
+            NUMBER_OF_RESEEKS_IN_ITERATION), 0);
+  ASSERT_EQ(IterStatus(iter), "b->bone");
+  delete iter;
+
+  // insert a total of four keys with same userkey and verify
+  // that reseek is invoked.
+  ASSERT_OK(Put("a",  "four"));
+  iter = db_->NewIterator(ReadOptions());
+  iter->SeekToFirst();
+  ASSERT_EQ(IterStatus(iter), "a->four");
+  ASSERT_EQ(options.statistics.get()->getTickerCount(
+            NUMBER_OF_RESEEKS_IN_ITERATION), 0);
+  iter->Next();
+  ASSERT_EQ(options.statistics.get()->getTickerCount(
+            NUMBER_OF_RESEEKS_IN_ITERATION), 1);
+  ASSERT_EQ(IterStatus(iter), "b->bone");
+  delete iter;
+
+  // Testing reverse iterator
+  // At this point, we have three versions of "a" and one version of "b".
+  // The reseek statistics is already at 1.
+  int num_reseeks = (int)options.statistics.get()->getTickerCount(
+                 NUMBER_OF_RESEEKS_IN_ITERATION);
+
+  // Insert another version of b and assert that reseek is not invoked
+  ASSERT_OK(Put("b",  "btwo"));
+  iter = db_->NewIterator(ReadOptions());
+  iter->SeekToLast();
+  ASSERT_EQ(IterStatus(iter), "b->btwo");
+  ASSERT_EQ(options.statistics.get()->getTickerCount(
+            NUMBER_OF_RESEEKS_IN_ITERATION), num_reseeks);
+  iter->Prev();
+  ASSERT_EQ(options.statistics.get()->getTickerCount(
+            NUMBER_OF_RESEEKS_IN_ITERATION), num_reseeks+1);
+  ASSERT_EQ(IterStatus(iter), "a->four");
+  delete iter;
+
+  // insert two more versions of b. This makes a total of 4 versions
+  // of b and 4 versions of a.
+  ASSERT_OK(Put("b",  "bthree"));
+  ASSERT_OK(Put("b",  "bfour"));
+  iter = db_->NewIterator(ReadOptions());
+  iter->SeekToLast();
+  ASSERT_EQ(IterStatus(iter), "b->bfour");
+  ASSERT_EQ(options.statistics.get()->getTickerCount(
+            NUMBER_OF_RESEEKS_IN_ITERATION), num_reseeks + 2);
+  iter->Prev();
+
+  // the previous Prev call should have invoked reseek
+  ASSERT_EQ(options.statistics.get()->getTickerCount(
+            NUMBER_OF_RESEEKS_IN_ITERATION), num_reseeks + 3);
+  ASSERT_EQ(IterStatus(iter), "a->four");
+  delete iter;
+}
+
+TEST(DBTest, IterSmallAndLargeMix) {
+  do {
+    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;
+  } while (ChangeCompactOptions());
+}
+
+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");
+    if (!CurrentOptions().merge_operator) {
+      // TODO: merge operator does not support backward iteration yet
+      iter->Prev();
+      ASSERT_EQ(IterStatus(iter), "a->va");
+    }
+    delete iter;
+  } while (ChangeOptions());
+}
+
+TEST(DBTest, IterPrevMaxSkip) {
+  do {
+    for (int i = 0; i < 2; i++) {
+      db_->Put(WriteOptions(), "key1", "v1");
+      db_->Put(WriteOptions(), "key2", "v2");
+      db_->Put(WriteOptions(), "key3", "v3");
+      db_->Put(WriteOptions(), "key4", "v4");
+      db_->Put(WriteOptions(), "key5", "v5");
+    }
+
+    VerifyIterLast("key5->v5");
+
+    ASSERT_OK(db_->Delete(WriteOptions(), "key5"));
+    VerifyIterLast("key4->v4");
+
+    ASSERT_OK(db_->Delete(WriteOptions(), "key4"));
+    VerifyIterLast("key3->v3");
+
+    ASSERT_OK(db_->Delete(WriteOptions(), "key3"));
+    VerifyIterLast("key2->v2");
+
+    ASSERT_OK(db_->Delete(WriteOptions(), "key2"));
+    VerifyIterLast("key1->v1");
+
+    ASSERT_OK(db_->Delete(WriteOptions(), "key1"));
+    VerifyIterLast("(invalid)");
+  } while (ChangeOptions(kSkipMergePut));
+}
+
+TEST(DBTest, IterWithSnapshot) {
+  do {
+    ASSERT_OK(Put("key1", "val1"));
+    ASSERT_OK(Put("key2", "val2"));
+    ASSERT_OK(Put("key3", "val3"));
+    ASSERT_OK(Put("key4", "val4"));
+    ASSERT_OK(Put("key5", "val5"));
+
+    const Snapshot *snapshot = db_->GetSnapshot();
+    ReadOptions options;
+    options.snapshot = snapshot;
+    Iterator* iter = db_->NewIterator(options);
+
+    // Put more values after the snapshot
+    ASSERT_OK(Put("key100", "val100"));
+    ASSERT_OK(Put("key101", "val101"));
+
+    iter->Seek("key5");
+    ASSERT_EQ(IterStatus(iter), "key5->val5");
+    if (!CurrentOptions().merge_operator) {
+      // TODO: merge operator does not support backward iteration yet
+      iter->Prev();
+      ASSERT_EQ(IterStatus(iter), "key4->val4");
+      iter->Prev();
+      ASSERT_EQ(IterStatus(iter), "key3->val3");
+
+      iter->Next();
+      ASSERT_EQ(IterStatus(iter), "key4->val4");
+      iter->Next();
+      ASSERT_EQ(IterStatus(iter), "key5->val5");
+      iter->Next();
+      ASSERT_TRUE(!iter->Valid());
+    }
+    db_->ReleaseSnapshot(snapshot);
+    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) {
+  do {
+    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"));
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, CheckLock) {
+  do {
+    DB* localdb;
+    Options options = CurrentOptions();
+    ASSERT_OK(TryReopen(&options));
+
+    // second open should fail
+    ASSERT_TRUE(!(PureReopen(&options, &localdb)).ok());
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, FlushMultipleMemtable) {
+  do {
+    Options options = CurrentOptions();
+    WriteOptions writeOpt = WriteOptions();
+    writeOpt.disableWAL = true;
+    options.max_write_buffer_number = 4;
+    options.min_write_buffer_number_to_merge = 3;
+    Reopen(&options);
+    ASSERT_OK(dbfull()->Put(writeOpt, "foo", "v1"));
+    dbfull()->Flush(FlushOptions());
+    ASSERT_OK(dbfull()->Put(writeOpt, "bar", "v1"));
+
+    ASSERT_EQ("v1", Get("foo"));
+    ASSERT_EQ("v1", Get("bar"));
+    dbfull()->Flush(FlushOptions());
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, NumImmutableMemTable) {
+  do {
+    Options options = CurrentOptions();
+    WriteOptions writeOpt = WriteOptions();
+    writeOpt.disableWAL = true;
+    options.max_write_buffer_number = 4;
+    options.min_write_buffer_number_to_merge = 3;
+    options.write_buffer_size = 1000000;
+    Reopen(&options);
+
+    std::string big_value(1000000, 'x');
+    std::string num;
+
+    ASSERT_OK(dbfull()->Put(writeOpt, "k1", big_value));
+    ASSERT_TRUE(dbfull()->GetProperty("rocksdb.num-immutable-mem-table", &num));
+    ASSERT_EQ(num, "0");
+
+    ASSERT_OK(dbfull()->Put(writeOpt, "k2", big_value));
+    ASSERT_TRUE(dbfull()->GetProperty("rocksdb.num-immutable-mem-table", &num));
+    ASSERT_EQ(num, "1");
+
+    ASSERT_OK(dbfull()->Put(writeOpt, "k3", big_value));
+    ASSERT_TRUE(dbfull()->GetProperty("rocksdb.num-immutable-mem-table", &num));
+    ASSERT_EQ(num, "2");
+
+    dbfull()->Flush(FlushOptions());
+    ASSERT_TRUE(dbfull()->GetProperty("rocksdb.num-immutable-mem-table", &num));
+    ASSERT_EQ(num, "0");
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, FLUSH) {
+  do {
+    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"));
+  } while (ChangeCompactOptions());
+}
+
+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) {
+  do {
+    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)));
+    }
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, ManifestRollOver) {
+  do {
+    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_flush =
+        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_flush);
+      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"));
+    }
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, IdentityAcrossRestarts) {
+  do {
+    std::string idfilename = IdentityFileName(dbname_);
+    unique_ptr<SequentialFile> idfile;
+    const EnvOptions soptions;
+    ASSERT_OK(env_->NewSequentialFile(idfilename, &idfile, soptions));
+    char buffer1[100];
+    Slice id1;
+    ASSERT_OK(idfile->Read(100, &id1, buffer1));
+
+    Options options = CurrentOptions();
+    Reopen(&options);
+    char buffer2[100];
+    Slice id2;
+    ASSERT_OK(env_->NewSequentialFile(idfilename, &idfile, soptions));
+    ASSERT_OK(idfile->Read(100, &id2, buffer2));
+    // id1 should match id2 because identity was not regenerated
+    ASSERT_EQ(id1.ToString(), id2.ToString());
+
+    ASSERT_OK(env_->DeleteFile(idfilename));
+    Reopen(&options);
+    char buffer3[100];
+    Slice id3;
+    ASSERT_OK(env_->NewSequentialFile(idfilename, &idfile, soptions));
+    ASSERT_OK(idfile->Read(100, &id3, buffer3));
+    // id1 should NOT match id2 because identity was regenerated
+    ASSERT_NE(id1.ToString(0), id3.ToString());
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, RecoverWithLargeLog) {
+  do {
+    {
+      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);
+  } while (ChangeCompactOptions());
+}
+
+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<std::string> 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, CompressedCache) {
+  int num_iter = 80;
+
+  // Run this test three iterations.
+  // Iteration 1: only a uncompressed block cache
+  // Iteration 2: only a compressed block cache
+  // Iteration 3: both block cache and compressed cache
+  for (int iter = 0; iter < 3; iter++) {
+    Options options = CurrentOptions();
+    options.write_buffer_size = 64*1024;        // small write buffer
+    options.statistics = rocksdb::CreateDBStatistics();
+
+    switch (iter) {
+      case 0:
+        // only uncompressed block cache
+        options.block_cache = NewLRUCache(8*1024);
+        options.block_cache_compressed = nullptr;
+        break;
+      case 1:
+        // no block cache, only compressed cache
+        options.no_block_cache = true;
+        options.block_cache = nullptr;
+        options.block_cache_compressed = NewLRUCache(8*1024);
+        break;
+      case 2:
+        // both compressed and uncompressed block cache
+        options.block_cache = NewLRUCache(1024);
+        options.block_cache_compressed = NewLRUCache(8*1024);
+        break;
+      default:
+        ASSERT_TRUE(false);
+    }
+    Reopen(&options);
+
+    Random rnd(301);
+
+    // Write 8MB (80 values, each 100K)
+    ASSERT_EQ(NumTableFilesAtLevel(0), 0);
+    std::vector<std::string> values;
+    std::string str;
+    for (int i = 0; i < num_iter; i++) {
+      if (i % 4 == 0) {        // high compression ratio
+        str = RandomString(&rnd, 1000);
+      }
+      values.push_back(str);
+      ASSERT_OK(Put(Key(i), values[i]));
+    }
+
+    // flush all data from memtable so that reads are from block cache
+    dbfull()->Flush(FlushOptions());
+
+    for (int i = 0; i < num_iter; i++) {
+      ASSERT_EQ(Get(Key(i)), values[i]);
+    }
+
+    // check that we triggered the appropriate code paths in the cache
+    switch (iter) {
+      case 0:
+        // only uncompressed block cache
+        ASSERT_GT(options.statistics.get()->getTickerCount(BLOCK_CACHE_MISS),
+                  0);
+        ASSERT_EQ(options.statistics.get()->getTickerCount
+                  (BLOCK_CACHE_COMPRESSED_MISS), 0);
+        break;
+      case 1:
+        // no block cache, only compressed cache
+        ASSERT_EQ(options.statistics.get()->getTickerCount(BLOCK_CACHE_MISS),
+                  0);
+        ASSERT_GT(options.statistics.get()->getTickerCount
+                  (BLOCK_CACHE_COMPRESSED_MISS), 0);
+        break;
+      case 2:
+        // both compressed and uncompressed block cache
+        ASSERT_GT(options.statistics.get()->getTickerCount(BLOCK_CACHE_MISS),
+                  0);
+        ASSERT_GT(options.statistics.get()->getTickerCount
+                  (BLOCK_CACHE_COMPRESSED_MISS), 0);
+        break;
+      default:
+        ASSERT_TRUE(false);
+    }
+  }
+}
+
+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<std::string> 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_WaitForFlushMemTable();
+    ASSERT_EQ(NumTableFilesAtLevel(0), num + 1);
+  }
+
+  //generate one more file in level-0, and should trigger level-0 compaction
+  std::vector<std::string> 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);
+}
+
+TEST(DBTest, UniversalCompactionTrigger) {
+  Options options = CurrentOptions();
+  options.compaction_style = kCompactionStyleUniversal;
+  options.write_buffer_size = 100<<10; //100KB
+  // trigger compaction if there are >= 4 files
+  options.level0_file_num_compaction_trigger = 4;
+  Reopen(&options);
+
+  Random rnd(301);
+  int key_idx = 0;
+
+  // Stage 1:
+  //   Generate a set of files at level 0, but don't trigger level-0
+  //   compaction.
+  for (int num = 0;
+       num < options.level0_file_num_compaction_trigger-1;
+       num++) {
+    // Write 120KB (12 values, each 10K)
+    for (int i = 0; i < 12; i++) {
+      ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
+      key_idx++;
+    }
+    dbfull()->TEST_WaitForFlushMemTable();
+    ASSERT_EQ(NumTableFilesAtLevel(0), num + 1);
+  }
+
+  // Generate one more file at level-0, which should trigger level-0
+  // compaction.
+  for (int i = 0; i < 12; i++) {
+    ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
+    key_idx++;
+  }
+  dbfull()->TEST_WaitForCompact();
+  // Suppose each file flushed from mem table has size 1. Now we compact
+  // (level0_file_num_compaction_trigger+1)=4 files and should have a big
+  // file of size 4.
+  ASSERT_EQ(NumTableFilesAtLevel(0), 1);
+  for (int i = 1; i < options.num_levels ; i++) {
+    ASSERT_EQ(NumTableFilesAtLevel(i), 0);
+  }
+
+  // Stage 2:
+  //   Now we have one file at level 0, with size 4. We also have some data in
+  //   mem table. Let's continue generating new files at level 0, but don't
+  //   trigger level-0 compaction.
+  //   First, clean up memtable before inserting new data. This will generate
+  //   a level-0 file, with size around 0.4 (according to previously written
+  //   data amount).
+  dbfull()->Flush(FlushOptions());
+  for (int num = 0;
+       num < options.level0_file_num_compaction_trigger-3;
+       num++) {
+    // Write 120KB (12 values, each 10K)
+    for (int i = 0; i < 12; i++) {
+      ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
+      key_idx++;
+    }
+    dbfull()->TEST_WaitForFlushMemTable();
+    ASSERT_EQ(NumTableFilesAtLevel(0), num + 3);
+  }
+
+  // Generate one more file at level-0, which should trigger level-0
+  // compaction.
+  for (int i = 0; i < 12; i++) {
+    ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
+    key_idx++;
+  }
+  dbfull()->TEST_WaitForCompact();
+  // Before compaction, we have 4 files at level 0, with size 4, 0.4, 1, 1.
+  // After comapction, we should have 2 files, with size 4, 2.4.
+  ASSERT_EQ(NumTableFilesAtLevel(0), 2);
+  for (int i = 1; i < options.num_levels ; i++) {
+    ASSERT_EQ(NumTableFilesAtLevel(i), 0);
+  }
+
+  // Stage 3:
+  //   Now we have 2 files at level 0, with size 4 and 2.4. Continue
+  //   generating new files at level 0.
+  for (int num = 0;
+       num < options.level0_file_num_compaction_trigger-3;
+       num++) {
+    // Write 120KB (12 values, each 10K)
+    for (int i = 0; i < 12; i++) {
+      ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
+      key_idx++;
+    }
+    dbfull()->TEST_WaitForFlushMemTable();
+    ASSERT_EQ(NumTableFilesAtLevel(0), num + 3);
+  }
+
+  // Generate one more file at level-0, which should trigger level-0
+  // compaction.
+  for (int i = 0; i < 12; i++) {
+    ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
+    key_idx++;
+  }
+  dbfull()->TEST_WaitForCompact();
+  // Before compaction, we have 4 files at level 0, with size 4, 2.4, 1, 1.
+  // After comapction, we should have 3 files, with size 4, 2.4, 2.
+  ASSERT_EQ(NumTableFilesAtLevel(0), 3);
+  for (int i = 1; i < options.num_levels ; i++) {
+    ASSERT_EQ(NumTableFilesAtLevel(i), 0);
+  }
+
+  // Stage 4:
+  //   Now we have 3 files at level 0, with size 4, 2.4, 2. Let's generate a
+  //   new file of size 1.
+  for (int i = 0; i < 12; i++) {
+    ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
+    key_idx++;
+  }
+  dbfull()->TEST_WaitForCompact();
+  // Level-0 compaction is triggered, but no file will be picked up.
+  ASSERT_EQ(NumTableFilesAtLevel(0), 4);
+  for (int i = 1; i < options.num_levels ; i++) {
+    ASSERT_EQ(NumTableFilesAtLevel(i), 0);
+  }
+
+  // Stage 5:
+  //   Now we have 4 files at level 0, with size 4, 2.4, 2, 1. Let's generate
+  //   a new file of size 1.
+  for (int i = 0; i < 12; i++) {
+    ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
+    key_idx++;
+  }
+  dbfull()->TEST_WaitForCompact();
+  // All files at level 0 will be compacted into a single one.
+  ASSERT_EQ(NumTableFilesAtLevel(0), 1);
+  for (int i = 1; i < options.num_levels ; i++) {
+    ASSERT_EQ(NumTableFilesAtLevel(i), 0);
+  }
+}
+
+TEST(DBTest, UniversalCompactionSizeAmplification) {
+  Options options = CurrentOptions();
+  options.compaction_style = kCompactionStyleUniversal;
+  options.write_buffer_size = 100<<10; //100KB
+  options.level0_file_num_compaction_trigger = 3;
+
+  // Trigger compaction if size amplification exceeds 110%
+  options.compaction_options_universal.
+    max_size_amplification_percent = 110;
+  Reopen(&options);
+
+  Random rnd(301);
+  int key_idx = 0;
+
+  //   Generate two files in Level 0. Both files are approx the same size.
+  for (int num = 0;
+       num < options.level0_file_num_compaction_trigger-1;
+       num++) {
+    // Write 120KB (12 values, each 10K)
+    for (int i = 0; i < 12; i++) {
+      ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
+      key_idx++;
+    }
+    dbfull()->TEST_WaitForFlushMemTable();
+    ASSERT_EQ(NumTableFilesAtLevel(0), num + 1);
+  }
+  ASSERT_EQ(NumTableFilesAtLevel(0), 2);
+
+  // Flush whatever is remaining in memtable. This is typically
+  // small, which should not trigger size ratio based compaction
+  // but will instead trigger size amplification.
+  dbfull()->Flush(FlushOptions());
+
+  dbfull()->TEST_WaitForCompact();
+
+  // Verify that size amplification did occur
+  ASSERT_EQ(NumTableFilesAtLevel(0), 1);
+}
+
+TEST(DBTest, UniversalCompactionOptions) {
+  Options options = CurrentOptions();
+  options.compaction_style = kCompactionStyleUniversal;
+  options.write_buffer_size = 100<<10; //100KB
+  options.level0_file_num_compaction_trigger = 4;
+  options.num_levels = 1;
+  options.compaction_options_universal.compression_size_percent = -1;
+  Reopen(&options);
+
+  Random rnd(301);
+  int key_idx = 0;
+
+  for (int num = 0;
+       num < options.level0_file_num_compaction_trigger;
+       num++) {
+    // Write 120KB (12 values, each 10K)
+    for (int i = 0; i < 12; i++) {
+      ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
+      key_idx++;
+    }
+    dbfull()->TEST_WaitForFlushMemTable();
+
+    if (num < options.level0_file_num_compaction_trigger - 1) {
+      ASSERT_EQ(NumTableFilesAtLevel(0), num + 1);
+    }
+  }
+
+  dbfull()->TEST_WaitForCompact();
+  ASSERT_EQ(NumTableFilesAtLevel(0), 1);
+  for (int i = 1; i < options.num_levels ; i++) {
+    ASSERT_EQ(NumTableFilesAtLevel(i), 0);
+  }
+}
+
+TEST(DBTest, UniversalCompactionCompressRatio1) {
+  Options options = CurrentOptions();
+  options.compaction_style = kCompactionStyleUniversal;
+  options.write_buffer_size = 100<<10; //100KB
+  options.level0_file_num_compaction_trigger = 2;
+  options.num_levels = 1;
+  options.compaction_options_universal.compression_size_percent = 70;
+  Reopen(&options);
+
+  Random rnd(301);
+  int key_idx = 0;
+
+  // The first compaction (2) is compressed.
+  for (int num = 0; num < 2; num++) {
+    // Write 120KB (12 values, each 10K)
+    for (int i = 0; i < 12; i++) {
+      ASSERT_OK(Put(Key(key_idx), CompressibleString(&rnd, 10000)));
+      key_idx++;
+    }
+    dbfull()->TEST_WaitForFlushMemTable();
+    dbfull()->TEST_WaitForCompact();
+  }
+  ASSERT_LT((int ) dbfull()->TEST_GetLevel0TotalSize(), 120000 * 2 * 0.9);
+
+  // The second compaction (4) is compressed
+  for (int num = 0; num < 2; num++) {
+    // Write 120KB (12 values, each 10K)
+    for (int i = 0; i < 12; i++) {
+      ASSERT_OK(Put(Key(key_idx), CompressibleString(&rnd, 10000)));
+      key_idx++;
+    }
+    dbfull()->TEST_WaitForFlushMemTable();
+    dbfull()->TEST_WaitForCompact();
+  }
+  ASSERT_LT((int ) dbfull()->TEST_GetLevel0TotalSize(), 120000 * 4 * 0.9);
+
+  // The third compaction (2 4) is compressed since this time it is
+  // (1 1 3.2) and 3.2/5.2 doesn't reach ratio.
+  for (int num = 0; num < 2; num++) {
+    // Write 120KB (12 values, each 10K)
+    for (int i = 0; i < 12; i++) {
+      ASSERT_OK(Put(Key(key_idx), CompressibleString(&rnd, 10000)));
+      key_idx++;
+    }
+    dbfull()->TEST_WaitForFlushMemTable();
+    dbfull()->TEST_WaitForCompact();
+  }
+  ASSERT_LT((int ) dbfull()->TEST_GetLevel0TotalSize(), 120000 * 6 * 0.9);
+
+  // When we start for the compaction up to (2 4 8), the latest
+  // compressed is not compressed.
+  for (int num = 0; num < 8; num++) {
+    // Write 120KB (12 values, each 10K)
+    for (int i = 0; i < 12; i++) {
+      ASSERT_OK(Put(Key(key_idx), CompressibleString(&rnd, 10000)));
+      key_idx++;
+    }
+    dbfull()->TEST_WaitForFlushMemTable();
+    dbfull()->TEST_WaitForCompact();
+  }
+  ASSERT_GT((int ) dbfull()->TEST_GetLevel0TotalSize(),
+            120000 * 12 * 0.8 + 110000 * 2);
+}
+
+TEST(DBTest, UniversalCompactionCompressRatio2) {
+  Options options = CurrentOptions();
+  options.compaction_style = kCompactionStyleUniversal;
+  options.write_buffer_size = 100<<10; //100KB
+  options.level0_file_num_compaction_trigger = 2;
+  options.num_levels = 1;
+  options.compaction_options_universal.compression_size_percent = 95;
+  Reopen(&options);
+
+  Random rnd(301);
+  int key_idx = 0;
+
+  // When we start for the compaction up to (2 4 8), the latest
+  // compressed is compressed given the size ratio to compress.
+  for (int num = 0; num < 14; num++) {
+    // Write 120KB (12 values, each 10K)
+    for (int i = 0; i < 12; i++) {
+      ASSERT_OK(Put(Key(key_idx), CompressibleString(&rnd, 10000)));
+      key_idx++;
+    }
+    dbfull()->TEST_WaitForFlushMemTable();
+    dbfull()->TEST_WaitForCompact();
+  }
+  ASSERT_LT((int ) dbfull()->TEST_GetLevel0TotalSize(),
+            120000 * 12 * 0.8 + 110000 * 2);
+}
+
+TEST(DBTest, ConvertCompactionStyle) {
+  Random rnd(301);
+  int max_key_level_insert = 200;
+  int max_key_universal_insert = 600;
+
+  // Stage 1: generate a db with level compaction
+  Options options = CurrentOptions();
+  options.write_buffer_size = 100<<10; //100KB
+  options.num_levels = 4;
+  options.level0_file_num_compaction_trigger = 3;
+  options.max_bytes_for_level_base = 500<<10; // 500KB
+  options.max_bytes_for_level_multiplier = 1;
+  options.target_file_size_base = 200<<10; // 200KB
+  options.target_file_size_multiplier = 1;
+  Reopen(&options);
+
+  for (int i = 0; i <= max_key_level_insert; i++) {
+    // each value is 10K
+    ASSERT_OK(Put(Key(i), RandomString(&rnd, 10000)));
+  }
+  dbfull()->Flush(FlushOptions());
+  dbfull()->TEST_WaitForCompact();
+
+  ASSERT_GT(TotalTableFiles(), 1);
+  int non_level0_num_files = 0;
+  for (int i = 1; i < dbfull()->NumberLevels(); i++) {
+    non_level0_num_files += NumTableFilesAtLevel(i);
+  }
+  ASSERT_GT(non_level0_num_files, 0);
+
+  // Stage 2: reopen with universal compaction - should fail
+  options = CurrentOptions();
+  options.compaction_style = kCompactionStyleUniversal;
+  Status s = TryReopen(&options);
+  ASSERT_TRUE(s.IsInvalidArgument());
+
+  // Stage 3: compact into a single file and move the file to level 0
+  options = CurrentOptions();
+  options.disable_auto_compactions = true;
+  options.target_file_size_base = INT_MAX;
+  options.target_file_size_multiplier = 1;
+  options.max_bytes_for_level_base = INT_MAX;
+  options.max_bytes_for_level_multiplier = 1;
+  Reopen(&options);
+
+  dbfull()->CompactRange(nullptr, nullptr,
+                         true /* reduce level */,
+                         0    /* reduce to level 0 */);
+
+  for (int i = 0; i < dbfull()->NumberLevels(); i++) {
+    int num = NumTableFilesAtLevel(i);
+    if (i == 0) {
+      ASSERT_EQ(num, 1);
+    } else {
+      ASSERT_EQ(num, 0);
+    }
+  }
+
+  // Stage 4: re-open in universal compaction style and do some db operations
+  options = CurrentOptions();
+  options.compaction_style = kCompactionStyleUniversal;
+  options.write_buffer_size = 100<<10; //100KB
+  options.level0_file_num_compaction_trigger = 3;
+  Reopen(&options);
+
+  for (int i = max_key_level_insert / 2; i <= max_key_universal_insert; i++) {
+    ASSERT_OK(Put(Key(i), RandomString(&rnd, 10000)));
+  }
+  dbfull()->Flush(FlushOptions());
+  dbfull()->TEST_WaitForCompact();
+
+  for (int i = 1; i < dbfull()->NumberLevels(); i++) {
+    ASSERT_EQ(NumTableFilesAtLevel(i), 0);
+  }
+
+  // verify keys inserted in both level compaction style and universal
+  // compaction style
+  std::string keys_in_db;
+  Iterator* iter = dbfull()->NewIterator(ReadOptions());
+  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
+    keys_in_db.append(iter->key().ToString());
+    keys_in_db.push_back(',');
+  }
+  delete iter;
+
+  std::string expected_keys;
+  for (int i = 0; i <= max_key_universal_insert; i++) {
+    expected_keys.append(Key(i));
+    expected_keys.push_back(',');
+  }
+
+  ASSERT_EQ(keys_in_db, expected_keys);
+}
+
+void MinLevelHelper(DBTest* self, Options& options) {
+  Random rnd(301);
+
+  for (int num = 0;
+    num < options.level0_file_num_compaction_trigger - 1;
+    num++)
+  {
+    std::vector<std::string> 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_WaitForFlushMemTable();
+    ASSERT_EQ(self->NumTableFilesAtLevel(0), num + 1);
+  }
+
+  //generate one more file in level-0, and should trigger level-0 compaction
+  std::vector<std::string> 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) {
+  do {
+    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);
+    }
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, InPlaceUpdate) {
+  do {
+    Options options = CurrentOptions();
+    options.create_if_missing = true;
+    options.inplace_update_support = true;
+    options.env = env_;
+    options.write_buffer_size = 100000;
+
+    // Update key with values of smaller size
+    Reopen(&options);
+    int numValues = 10;
+    for (int i = numValues; i > 0; i--) {
+      std::string value = DummyString(i, 'a');
+      ASSERT_OK(Put("key", value));
+      ASSERT_EQ(value, Get("key"));
+    }
+
+    int count = 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);
+      count++;
+      // All updates with the same sequence number.
+      ASSERT_EQ(ikey.sequence, (unsigned)1);
+      iter->Next();
+    }
+    // Only 1 instance for that key.
+    ASSERT_EQ(count, 1);
+    delete iter;
+
+    // Update key with values of larger size
+    DestroyAndReopen(&options);
+    numValues = 10;
+    for (int i = 0; i < numValues; i++) {
+      std::string value = DummyString(i, 'a');
+      ASSERT_OK(Put("key", value));
+      ASSERT_EQ(value, Get("key"));
+    }
+
+    count = 0;
+    iter = dbfull()->TEST_NewInternalIterator();
+    iter->SeekToFirst();
+    ASSERT_EQ(iter->status().ok(), true);
+    int seq = numValues;
+    while (iter->Valid()) {
+      ParsedInternalKey ikey;
+      ikey.sequence = -1;
+      ASSERT_EQ(ParseInternalKey(iter->key(), &ikey), true);
+      count++;
+      // No inplace updates. All updates are puts with new seq number
+      ASSERT_EQ(ikey.sequence, (unsigned)seq--);
+      iter->Next();
+    }
+    // All 10 updates exist in the internal iterator
+    ASSERT_EQ(count, numValues);
+    delete iter;
+
+
+  } while (ChangeCompactOptions());
+}
+
+// This is a static filter used for filtering
+// kvs during the compaction process.
+static int cfilter_count;
+static std::string NEW_VALUE = "NewValue";
+
+class KeepFilter : public CompactionFilter {
+ public:
+  virtual bool Filter(int level, const Slice& key,
+                      const Slice& value, std::string* new_value,
+                      bool* value_changed) const override {
+    cfilter_count++;
+    return false;
+  }
+
+  virtual const char* Name() const override {
+    return "KeepFilter";
+  }
+
+};
+
+class DeleteFilter : public CompactionFilter {
+ public:
+  virtual bool Filter(int level, const Slice& key,
+                      const Slice& value, std::string* new_value,
+                      bool* value_changed) const override {
+    cfilter_count++;
+    return true;
+  }
+
+  virtual const char* Name() const override {
+    return "DeleteFilter";
+  }
+};
+
+class ChangeFilter : public CompactionFilter {
+ public:
+  explicit ChangeFilter(int argv) : argv_(argv) {}
+
+  virtual bool Filter(int level, const Slice& key,
+                      const Slice& value, std::string* new_value,
+                      bool* value_changed) const override {
+    assert(argv_ == 100);
+    assert(new_value != nullptr);
+    *new_value = NEW_VALUE;
+    *value_changed = true;
+    return false;
+  }
+
+  virtual const char* Name() const override {
+    return "ChangeFilter";
+  }
+
+ private:
+  const int argv_;
+};
+
+class KeepFilterFactory : public CompactionFilterFactory {
+  public:
+    virtual std::unique_ptr<CompactionFilter>
+    CreateCompactionFilter(const CompactionFilter::Context& context) override {
+      return std::unique_ptr<CompactionFilter>(new KeepFilter());
+    }
+
+    virtual const char* Name() const override {
+      return "KeepFilterFactory";
+    }
+};
+
+class DeleteFilterFactory : public CompactionFilterFactory {
+  public:
+    virtual std::unique_ptr<CompactionFilter>
+    CreateCompactionFilter(const CompactionFilter::Context& context) override {
+      return std::unique_ptr<CompactionFilter>(new DeleteFilter());
+    }
+
+    virtual const char* Name() const override {
+      return "DeleteFilterFactory";
+    }
+};
+
+class ChangeFilterFactory : public CompactionFilterFactory {
+  public:
+    explicit ChangeFilterFactory(int argv) : argv_(argv) {}
+
+    virtual std::unique_ptr<CompactionFilter>
+    CreateCompactionFilter(const CompactionFilter::Context& context) override {
+      return std::unique_ptr<CompactionFilter>(new ChangeFilter(argv_));
+    }
+
+    virtual const char* Name() const override {
+      return "ChangeFilterFactory";
+    }
+
+  private:
+    const int argv_;
+};
+
+TEST(DBTest, CompactionFilter) {
+  Options options = CurrentOptions();
+  options.num_levels = 3;
+  options.max_mem_compaction_level = 0;
+  options.compaction_filter_factory = std::make_shared<KeepFilterFactory>();
+  Reopen(&options);
+
+  // Write 100K keys, these are written to a few files in L0.
+  const std::string value(10, 'x');
+  for (int i = 0; i < 100000; i++) {
+    char key[100];
+    snprintf(key, sizeof(key), "B%010d", i);
+    Put(key, value);
+  }
+  dbfull()->TEST_FlushMemTable();
+
+  // 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.
+  // TODO: figure out sequence number squashtoo
+  int count = 0;
+  int total = 0;
+  Iterator* iter = dbfull()->TEST_NewInternalIterator();
+  iter->SeekToFirst();
+  ASSERT_OK(iter->status());
+  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, 100000);
+  ASSERT_EQ(count, 1);
+  delete iter;
+
+  // overwrite all the 100K keys once again.
+  for (int i = 0; i < 100000; i++) {
+    char key[100];
+    snprintf(key, sizeof(key), "B%010d", i);
+    Put(key, value);
+  }
+  dbfull()->TEST_FlushMemTable();
+
+  // 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.compaction_filter_factory = std::make_shared<DeleteFilterFactory>();
+  options.create_if_missing = true;
+  DestroyAndReopen(&options);
+
+  // write all the keys once again.
+  for (int i = 0; i < 100000; i++) {
+    char key[100];
+    snprintf(key, sizeof(key), "B%010d", i);
+    Put(key, value);
+  }
+  dbfull()->TEST_FlushMemTable();
+  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 nothing is left
+  iter = db_->NewIterator(ReadOptions());
+  iter->SeekToFirst();
+  count = 0;
+  while (iter->Valid()) {
+    count++;
+    iter->Next();
+  }
+  ASSERT_EQ(count, 0);
+  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
+  // TODO: remove the following or design a different
+  // test
+  count = 0;
+  iter = dbfull()->TEST_NewInternalIterator();
+  iter->SeekToFirst();
+  ASSERT_OK(iter->status());
+  while (iter->Valid()) {
+    ParsedInternalKey ikey;
+    ASSERT_EQ(ParseInternalKey(iter->key(), &ikey), true);
+    ASSERT_NE(ikey.sequence, (unsigned)0);
+    count++;
+    iter->Next();
+  }
+  ASSERT_EQ(count, 0);
+  delete iter;
+}
+
+TEST(DBTest, CompactionFilterWithValueChange) {
+  do {
+    Options options = CurrentOptions();
+    options.num_levels = 3;
+    options.max_mem_compaction_level = 0;
+    options.compaction_filter_factory =
+      std::make_shared<ChangeFilterFactory>(100);
+    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_FlushMemTable();
+    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_FlushMemTable();
+    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);
+    }
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, SparseMerge) {
+  do {
+    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_FlushMemTable();
+    dbfull()->TEST_CompactRange(0, nullptr, nullptr);
+
+    // Make sparse update
+    Put("A",    "va2");
+    Put("B100", "bvalue2");
+    Put("C",    "vc2");
+    dbfull()->TEST_FlushMemTable();
+
+    // 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);
+  } while (ChangeCompactOptions());
+}
+
+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(kSkipUniversalCompaction));
+}
+
+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) {
+  do {
+    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;
+  } while (ChangeCompactOptions());
+}
+
+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_FlushMemTable());
+    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(kSkipUniversalCompaction));
+}
+
+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_FlushMemTable());
+    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_FlushMemTable());
+  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_FlushMemTable();
+  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_FlushMemTable());  // 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_FlushMemTable());
+  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_FlushMemTable();
+  ASSERT_EQ(NumTableFilesAtLevel(last), 1);
+  ASSERT_EQ(NumTableFilesAtLevel(last-1), 1);
+
+  Delete("foo");
+  ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]");
+  ASSERT_OK(dbfull()->TEST_FlushMemTable());  // 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_FlushMemTable();
+    ASSERT_OK(Delete("100"));
+    ASSERT_OK(Delete("999"));
+    dbfull()->TEST_FlushMemTable();
+    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_FlushMemTable();
+    ASSERT_OK(Put("200", "v200"));
+    ASSERT_OK(Put("600", "v600"));
+    ASSERT_OK(Put("900", "v900"));
+    dbfull()->TEST_FlushMemTable();
+    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_FlushMemTable();
+    ASSERT_EQ("3", FilesPerLevel());
+    ASSERT_EQ("NOT_FOUND", Get("600"));
+  } while (ChangeOptions(kSkipUniversalCompaction));
+}
+
+TEST(DBTest, L0_CompactionBug_Issue44_a) {
+  do {
+    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());
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, L0_CompactionBug_Issue44_b) {
+  do {
+    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());
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, ComparatorCheck) {
+  class NewComparator : public Comparator {
+   public:
+    virtual const char* Name() const { return "rocksdb.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);
+    }
+  };
+  Options new_options;
+  NewComparator cmp;
+  do {
+    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();
+  } while (ChangeCompactOptions(&new_options));
+}
+
+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;
+    }
+  };
+  Options new_options;
+  NumberComparator cmp;
+  do {
+    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]");
+    }
+  } while (ChangeCompactOptions(&new_options));
+}
+
+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";
+  ASSERT_OK(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";
+  ASSERT_OK(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.
+  ASSERT_OK(DestroyDB(metametadbname, Options()));
+  ASSERT_OK(DestroyDB(metadbname, Options()));
+  ASSERT_OK(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
+  ASSERT_OK(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) {
+  do {
+    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);
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, NonWritableFileSystem) {
+  do {
+    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);
+  } while (ChangeCompactOptions());
+}
+
+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_FlushMemTable();
+    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, PutFailsParanoid) {
+  // Test the following:
+  // (a) A random put fails in paranoid mode (simulate by sync fail)
+  // (b) All other puts have to fail, even if writes would succeed
+  // (c) All of that should happen ONLY if paranoid_checks = true
+
+  Options options = CurrentOptions();
+  options.env = env_;
+  options.create_if_missing = true;
+  options.error_if_exists = false;
+  options.paranoid_checks = true;
+  DestroyAndReopen(&options);
+  Status s;
+
+  ASSERT_OK(Put("foo", "bar"));
+  ASSERT_OK(Put("foo1", "bar1"));
+  // simulate error
+  env_->log_write_error_.Release_Store(env_);
+  s = Put("foo2", "bar2");
+  ASSERT_TRUE(!s.ok());
+  env_->log_write_error_.Release_Store(nullptr);
+  s = Put("foo3", "bar3");
+  // the next put should fail, too
+  ASSERT_TRUE(!s.ok());
+  // but we're still able to read
+  ASSERT_EQ("bar", Get("foo"));
+
+  // do the same thing with paranoid checks off
+  options.paranoid_checks = false;
+  DestroyAndReopen(&options);
+
+  ASSERT_OK(Put("foo", "bar"));
+  ASSERT_OK(Put("foo1", "bar1"));
+  // simulate error
+  env_->log_write_error_.Release_Store(env_);
+  s = Put("foo2", "bar2");
+  ASSERT_TRUE(!s.ok());
+  env_->log_write_error_.Release_Store(nullptr);
+  s = Put("foo3", "bar3");
+  // the next put should NOT fail
+  ASSERT_TRUE(s.ok());
+}
+
+TEST(DBTest, FilesDeletedAfterCompaction) {
+  do {
+    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);
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, BloomFilter) {
+  do {
+    env_->count_random_reads_ = true;
+    Options options = CurrentOptions();
+    options.env = env_;
+    options.no_block_cache = true;
+    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_FlushMemTable();
+
+    // 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;
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, SnapshotFiles) {
+  do {
+    Options options = CurrentOptions();
+    const EnvOptions soptions;
+    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<std::string> 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<std::string> 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++) {
+      // our clients require that GetLiveFiles returns
+      // files with "/" as first character!
+      ASSERT_EQ(files[i][0], '/');
+      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<SequentialFile> srcfile;
+      ASSERT_OK(env_->NewSequentialFile(src, &srcfile, soptions));
+      unique_ptr<WritableFile> destfile;
+      ASSERT_OK(env_->NewWritableFile(dest, &destfile, soptions));
+
+      char buffer[4096];
+      Slice slice;
+      while (size > 0) {
+        uint64_t one = std::min(uint64_t(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<std::string> 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_OK(stat);
+
+    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<std::string> 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();
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, CompactOnFlush) {
+  do {
+    Options options = CurrentOptions();
+    options.purge_redundant_kvs_while_flush = true;
+    options.disable_auto_compactions = true;
+    Reopen(&options);
+
+    Put("foo", "v1");
+    ASSERT_OK(dbfull()->TEST_FlushMemTable());
+    ASSERT_EQ(AllEntriesFor("foo"), "[ v1 ]");
+
+    // Write two new keys
+    Put("a", "begin");
+    Put("z", "end");
+    dbfull()->TEST_FlushMemTable();
+
+    // 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_FlushMemTable());
+    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_FlushMemTable());
+    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_FlushMemTable());
+    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_FlushMemTable());
+    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_FlushMemTable());
+    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_FlushMemTable());
+    ASSERT_EQ(AllEntriesFor("foo"), "[ v9 ]");
+    db_->ReleaseSnapshot(snapshot1);
+  } while (ChangeCompactOptions());
+}
+
+std::vector<std::uint64_t> ListLogFiles(Env* env, const std::string& path) {
+  std::vector<std::string> files;
+  std::vector<uint64_t> log_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) {
+        log_files.push_back(number);
+      }
+    }
+  }
+  return std::move(log_files);
+}
+
+TEST(DBTest, WALArchivalTtl) {
+  do {
+    Options options = CurrentOptions();
+    options.create_if_missing = true;
+    options.WAL_ttl_seconds = 1000;
+    DestroyAndReopen(&options);
+
+    //  TEST : Create DB with a ttl and no size limit.
+    //  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".
+    //  Reopen db with small ttl.
+    //  Assert that archive was removed.
+
+    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), DummyString(1024)));
+      }
+
+      std::vector<uint64_t> log_files = ListLogFiles(env_, dbname_);
+
+      options.create_if_missing = false;
+      Reopen(&options);
+
+      std::vector<uint64_t> logs = ListLogFiles(env_, archiveDir);
+      std::set<uint64_t> archivedFiles(logs.begin(), logs.end());
+
+      for (auto& log : log_files) {
+        ASSERT_TRUE(archivedFiles.find(log) != archivedFiles.end());
+      }
+    }
+
+    std::vector<uint64_t> log_files = ListLogFiles(env_, archiveDir);
+    ASSERT_TRUE(log_files.size() > 0);
+
+    options.WAL_ttl_seconds = 1;
+    env_->SleepForMicroseconds(2 * 1000 * 1000);
+    Reopen(&options);
+
+    log_files = ListLogFiles(env_, archiveDir);
+    ASSERT_TRUE(log_files.empty());
+  } while (ChangeCompactOptions());
+}
+
+uint64_t GetLogDirSize(std::string dir_path, SpecialEnv* env) {
+  uint64_t dir_size = 0;
+  std::vector<std::string> files;
+  env->GetChildren(dir_path, &files);
+  for (auto& f : files) {
+    uint64_t number;
+    FileType type;
+    if (ParseFileName(f, &number, &type) && type == kLogFile) {
+      std::string const file_path = dir_path + "/" + f;
+      uint64_t file_size;
+      env->GetFileSize(file_path, &file_size);
+      dir_size += file_size;
+    }
+  }
+  return dir_size;
+}
+
+TEST(DBTest, WALArchivalSizeLimit) {
+  do {
+    Options options = CurrentOptions();
+    options.create_if_missing = true;
+    options.WAL_ttl_seconds = 0;
+    options.WAL_size_limit_MB = 1000;
+
+    // TEST : Create DB with huge size limit and no ttl.
+    // Put some keys. Count the archived log files present in the DB
+    // just after insert. Assert that there are many enough.
+    // Change size limit. Re-open db.
+    // Assert that archive is not greater than WAL_size_limit_MB.
+    // Set ttl and time_to_check_ to small values. Re-open db.
+    // Assert that there are no archived logs left.
+
+    DestroyAndReopen(&options);
+    for (int i = 0; i < 128 * 128; ++i) {
+      ASSERT_OK(Put(Key(i), DummyString(1024)));
+    }
+    Reopen(&options);
+
+    std::string archive_dir = ArchivalDirectory(dbname_);
+    std::vector<std::uint64_t> log_files = ListLogFiles(env_, archive_dir);
+    ASSERT_TRUE(log_files.size() > 2);
+
+    options.WAL_size_limit_MB = 8;
+    Reopen(&options);
+    dbfull()->TEST_PurgeObsoleteteWAL();
+
+    uint64_t archive_size = GetLogDirSize(archive_dir, env_);
+    ASSERT_TRUE(archive_size <= options.WAL_size_limit_MB * 1024 * 1024);
+
+    options.WAL_ttl_seconds = 1;
+    dbfull()->TEST_SetDefaultTimeToCheck(1);
+    env_->SleepForMicroseconds(2 * 1000 * 1000);
+    Reopen(&options);
+    dbfull()->TEST_PurgeObsoleteteWAL();
+
+    log_files = ListLogFiles(env_, archive_dir);
+    ASSERT_TRUE(log_files.empty());
+  } while (ChangeCompactOptions());
+}
+
+SequenceNumber ReadRecords(
+    std::unique_ptr<TransactionLogIterator>& iter,
+    int& count) {
+  count = 0;
+  SequenceNumber lastSequence = 0;
+  BatchResult res;
+  while (iter->Valid()) {
+    res = iter->GetBatch();
+    ASSERT_TRUE(res.sequence > lastSequence);
+    ++count;
+    lastSequence = res.sequence;
+    ASSERT_OK(iter->status());
+    iter->Next();
+  }
+  return res.sequence;
+}
+
+void ExpectRecords(
+    const int expected_no_records,
+    std::unique_ptr<TransactionLogIterator>& iter) {
+  int num_records;
+  ReadRecords(iter, num_records);
+  ASSERT_EQ(num_records, expected_no_records);
+}
+
+TEST(DBTest, TransactionLogIterator) {
+  do {
+    Options options = OptionsForLogIterTest();
+    DestroyAndReopen(&options);
+    Put("key1", DummyString(1024));
+    Put("key2", DummyString(1024));
+    Put("key2", DummyString(1024));
+    ASSERT_EQ(dbfull()->GetLatestSequenceNumber(), 3U);
+    {
+      auto iter = OpenTransactionLogIter(0);
+      ExpectRecords(3, iter);
+    }
+    Reopen(&options);
+      env_->SleepForMicroseconds(2 * 1000 * 1000);{
+      Put("key4", DummyString(1024));
+      Put("key5", DummyString(1024));
+      Put("key6", DummyString(1024));
+    }
+    {
+      auto iter = OpenTransactionLogIter(0);
+      ExpectRecords(6, iter);
+    }
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, TransactionLogIteratorMoveOverZeroFiles) {
+  do {
+    Options options = OptionsForLogIterTest();
+    DestroyAndReopen(&options);
+    // Do a plain Reopen.
+    Put("key1", DummyString(1024));
+    // Two reopens should create a zero record WAL file.
+    Reopen(&options);
+    Reopen(&options);
+
+    Put("key2", DummyString(1024));
+
+    auto iter = OpenTransactionLogIter(0);
+    ExpectRecords(2, iter);
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, TransactionLogIteratorStallAtLastRecord) {
+  do {
+    Options options = OptionsForLogIterTest();
+    DestroyAndReopen(&options);
+    Put("key1", DummyString(1024));
+    auto iter = OpenTransactionLogIter(0);
+    ASSERT_OK(iter->status());
+    ASSERT_TRUE(iter->Valid());
+    iter->Next();
+    ASSERT_TRUE(!iter->Valid());
+    ASSERT_OK(iter->status());
+    Put("key2", DummyString(1024));
+    iter->Next();
+    ASSERT_OK(iter->status());
+    ASSERT_TRUE(iter->Valid());
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, TransactionLogIteratorJustEmptyFile) {
+  do {
+    Options options = OptionsForLogIterTest();
+    DestroyAndReopen(&options);
+    unique_ptr<TransactionLogIterator> iter;
+    Status status = dbfull()->GetUpdatesSince(0, &iter);
+    // Check that an empty iterator is returned
+    ASSERT_TRUE(!iter->Valid());
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, TransactionLogIteratorCheckAfterRestart) {
+  do {
+    Options options = OptionsForLogIterTest();
+    DestroyAndReopen(&options);
+    Put("key1", DummyString(1024));
+    Put("key2", DummyString(1023));
+    dbfull()->Flush(FlushOptions());
+    Reopen(&options);
+    auto iter = OpenTransactionLogIter(0);
+    ExpectRecords(2, iter);
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, TransactionLogIteratorCorruptedLog) {
+  do {
+    Options options = OptionsForLogIterTest();
+    DestroyAndReopen(&options);
+    for (int i = 0; i < 1024; i++) {
+      Put("key"+std::to_string(i), DummyString(10));
+    }
+    dbfull()->Flush(FlushOptions());
+    // Corrupt this log to create a gap
+    rocksdb::VectorLogPtr wal_files;
+    ASSERT_OK(dbfull()->GetSortedWalFiles(wal_files));
+    const auto logfilePath = dbname_ + "/" + wal_files.front()->PathName();
+    ASSERT_EQ(
+      0,
+      truncate(logfilePath.c_str(), wal_files.front()->SizeFileBytes() / 2));
+    // Insert a new entry to a new log file
+    Put("key1025", DummyString(10));
+    // Try to read from the beginning. Should stop before the gap and read less
+    // than 1025 entries
+    auto iter = OpenTransactionLogIter(0);
+    int count;
+    int last_sequence_read = ReadRecords(iter, count);
+    ASSERT_LT(last_sequence_read, 1025);
+    // Try to read past the gap, should be able to seek to key1025
+    auto iter2 = OpenTransactionLogIter(last_sequence_read + 1);
+    ExpectRecords(1, iter2);
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, TransactionLogIteratorBatchOperations) {
+  do {
+    Options options = OptionsForLogIterTest();
+    DestroyAndReopen(&options);
+    WriteBatch batch;
+    batch.Put("key1", DummyString(1024));
+    batch.Put("key2", DummyString(1024));
+    batch.Put("key3", DummyString(1024));
+    batch.Delete("key2");
+    dbfull()->Write(WriteOptions(), &batch);
+    dbfull()->Flush(FlushOptions());
+    Reopen(&options);
+    Put("key4", DummyString(1024));
+    auto iter = OpenTransactionLogIter(3);
+    ExpectRecords(2, iter);
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, TransactionLogIteratorBlobs) {
+  Options options = OptionsForLogIterTest();
+  DestroyAndReopen(&options);
+  {
+    WriteBatch batch;
+    batch.Put("key1", DummyString(1024));
+    batch.Put("key2", DummyString(1024));
+    batch.PutLogData(Slice("blob1"));
+    batch.Put("key3", DummyString(1024));
+    batch.PutLogData(Slice("blob2"));
+    batch.Delete("key2");
+    dbfull()->Write(WriteOptions(), &batch);
+    Reopen(&options);
+  }
+
+  auto res = OpenTransactionLogIter(0)->GetBatch();
+  struct Handler : public WriteBatch::Handler {
+    std::string seen;
+    virtual void Put(const Slice& key, const Slice& value) {
+      seen += "Put(" + key.ToString() + ", " + std::to_string(value.size()) +
+        ")";
+    }
+    virtual void Merge(const Slice& key, const Slice& value) {
+      seen += "Merge(" + key.ToString() + ", " + std::to_string(value.size()) +
+        ")";
+    }
+    virtual void LogData(const Slice& blob) {
+      seen += "LogData(" + blob.ToString() + ")";
+    }
+    virtual void Delete(const Slice& key) {
+      seen += "Delete(" + key.ToString() + ")";
+    }
+  } handler;
+  res.writeBatchPtr->Iterate(&handler);
+  ASSERT_EQ("Put(key1, 1024)"
+            "Put(key2, 1024)"
+            "LogData(blob1)"
+            "Put(key3, 1024)"
+            "LogData(blob2)"
+            "Delete(key2)", handler.seen);
+}
+
+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.no_block_cache = true;
+
+    Reopen(&options);
+
+    // Write 8MB (2000 values, each 4K)
+    ASSERT_EQ(NumTableFilesAtLevel(0), 0);
+    std::vector<std::string> values;
+    for (int i = 0; i < 2000; i++) {
+      ASSERT_OK(Put(Key(i), value));
+    }
+
+    // clear level 0 and 1 if necessary.
+    dbfull()->TEST_FlushMemTable();
+    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<MTThread*>(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<void*>(counter));
+
+    int key = rnd.Uniform(kNumKeys);
+    char keybuf[20];
+    snprintf(keybuf, sizeof(keybuf), "%016d", key);
+
+    if (rnd.OneIn(2)) {
+      // Write values of the form <key, my id, counter>.
+      // We add some padding for force compactions.
+      snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d",
+               key, id, static_cast<int>(counter));
+      ASSERT_OK(t->state->test->Put(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<uintptr_t>(
+            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<std::string, std::string> 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 Merge(const WriteOptions& o, const Slice& k, const Slice& v) {
+    return DB::Merge(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) {
+    return Status::NotSupported(key);
+  }
+
+  virtual std::vector<Status> MultiGet(const ReadOptions& options,
+                                       const std::vector<Slice>& keys,
+                                       std::vector<std::string>* values) {
+    std::vector<Status> s(keys.size(),
+                          Status::NotSupported("Not implemented."));
+    return s;
+  }
+  virtual bool KeyMayExist(const ReadOptions& options,
+                           const Slice& key,
+                           std::string* value,
+                           bool* value_found = nullptr) {
+    if (value_found != nullptr) {
+      *value_found = false;
+    }
+    return true; // Not Supported directly
+  }
+  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<const ModelSnapshot*>(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<const ModelSnapshot*>(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 Merge(const Slice& key, const Slice& value) {
+        // ignore merge for now
+        //(*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,
+                            bool reduce_level, int target_level) {
+  }
+
+  virtual int NumberLevels()
+  {
+  return 1;
+  }
+
+  virtual int MaxMemCompactionLevel()
+  {
+  return 1;
+  }
+
+  virtual int Level0StopWriteTrigger()
+  {
+  return -1;
+  }
+
+  virtual Status Flush(const rocksdb::FlushOptions& options) {
+    Status ret;
+    return ret;
+  }
+
+  virtual Status DisableFileDeletions() {
+    return Status::OK();
+  }
+  virtual Status EnableFileDeletions() {
+    return Status::OK();
+  }
+  virtual Status GetLiveFiles(std::vector<std::string>&, uint64_t* size,
+                              bool flush_memtable = true) {
+    return Status::OK();
+  }
+
+  virtual Status GetSortedWalFiles(VectorLogPtr& files) {
+    return Status::OK();
+  }
+
+  virtual Status DeleteFile(std::string name) {
+    return Status::OK();
+  }
+
+  virtual SequenceNumber GetLatestSequenceNumber() const {
+    return 0;
+  }
+  virtual Status GetUpdatesSince(rocksdb::SequenceNumber,
+                                 unique_ptr<rocksdb::TransactionLogIterator>*) {
+    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 minimum = 0) {
+  int len;
+  do {
+    len = (rnd->OneIn(3)
+           ? 1                // Short sometimes to encourage collisions
+           : (rnd->OneIn(100) ? rnd->Skewed(10) : rnd->Uniform(10)));
+  } while (len < minimum);
+  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);
+      int minimum = 0;
+      if (option_config_ == kPrefixHashRep) {
+        minimum = 1;
+      }
+      if (p < 45) {                               // Put
+        k = RandomKey(&rnd, minimum);
+        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, minimum);
+        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, minimum);
+          } 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(kSkipDeletesFilterFirst));
+}
+
+TEST(DBTest, MultiGetSimple) {
+  do {
+    ASSERT_OK(db_->Put(WriteOptions(),"k1","v1"));
+    ASSERT_OK(db_->Put(WriteOptions(),"k2","v2"));
+    ASSERT_OK(db_->Put(WriteOptions(),"k3","v3"));
+    ASSERT_OK(db_->Put(WriteOptions(),"k4","v4"));
+    ASSERT_OK(db_->Delete(WriteOptions(),"k4"));
+    ASSERT_OK(db_->Put(WriteOptions(),"k5","v5"));
+    ASSERT_OK(db_->Delete(WriteOptions(),"no_key"));
+
+    std::vector<Slice> keys(6);
+    keys[0] = "k1";
+    keys[1] = "k2";
+    keys[2] = "k3";
+    keys[3] = "k4";
+    keys[4] = "k5";
+    keys[5] = "no_key";
+
+    std::vector<std::string> values(20,"Temporary data to be overwritten");
+
+    std::vector<Status> s =  db_->MultiGet(ReadOptions(),keys,&values);
+    ASSERT_EQ(values.size(),keys.size());
+    ASSERT_EQ(values[0], "v1");
+    ASSERT_EQ(values[1], "v2");
+    ASSERT_EQ(values[2], "v3");
+    ASSERT_EQ(values[4], "v5");
+
+    ASSERT_OK(s[0]);
+    ASSERT_OK(s[1]);
+    ASSERT_OK(s[2]);
+    ASSERT_TRUE(s[3].IsNotFound());
+    ASSERT_OK(s[4]);
+    ASSERT_TRUE(s[5].IsNotFound());
+  } while (ChangeCompactOptions());
+}
+
+TEST(DBTest, MultiGetEmpty) {
+  do {
+    // Empty Key Set
+    std::vector<Slice> keys;
+    std::vector<std::string> values;
+    std::vector<Status> s = db_->MultiGet(ReadOptions(),keys,&values);
+    ASSERT_EQ((int)s.size(),0);
+
+    // Empty Database, Empty Key Set
+    DestroyAndReopen();
+    s = db_->MultiGet(ReadOptions(), keys, &values);
+    ASSERT_EQ((int)s.size(),0);
+
+    // Empty Database, Search for Keys
+    keys.resize(2);
+    keys[0] = "a";
+    keys[1] = "b";
+    s = db_->MultiGet(ReadOptions(),keys,&values);
+    ASSERT_EQ((int)s.size(), 2);
+    ASSERT_TRUE(s[0].IsNotFound() && s[1].IsNotFound());
+  } while (ChangeCompactOptions());
+}
+
+void PrefixScanInit(DBTest *dbtest) {
+  char buf[100];
+  std::string keystr;
+  const int small_range_sstfiles = 5;
+  const int big_range_sstfiles = 5;
+
+  // Generate 11 sst files with the following prefix ranges.
+  // GROUP 0: [0,10]                              (level 1)
+  // GROUP 1: [1,2], [2,3], [3,4], [4,5], [5, 6]  (level 0)
+  // GROUP 2: [0,6], [0,7], [0,8], [0,9], [0,10]  (level 0)
+  //
+  // A seek with the previous API would do 11 random I/Os (to all the
+  // files).  With the new API and a prefix filter enabled, we should
+  // only do 2 random I/O, to the 2 files containing the key.
+
+  // GROUP 0
+  snprintf(buf, sizeof(buf), "%02d______:start", 0);
+  keystr = std::string(buf);
+  ASSERT_OK(dbtest->Put(keystr, keystr));
+  snprintf(buf, sizeof(buf), "%02d______:end", 10);
+  keystr = std::string(buf);
+  ASSERT_OK(dbtest->Put(keystr, keystr));
+  dbtest->dbfull()->TEST_FlushMemTable();
+  dbtest->dbfull()->CompactRange(nullptr, nullptr); // move to level 1
+
+  // GROUP 1
+  for (int i = 1; i <= small_range_sstfiles; i++) {
+    snprintf(buf, sizeof(buf), "%02d______:start", i);
+    keystr = std::string(buf);
+    ASSERT_OK(dbtest->Put(keystr, keystr));
+    snprintf(buf, sizeof(buf), "%02d______:end", i+1);
+    keystr = std::string(buf);
+    ASSERT_OK(dbtest->Put(keystr, keystr));
+    dbtest->dbfull()->TEST_FlushMemTable();
+  }
+
+  // GROUP 2
+  for (int i = 1; i <= big_range_sstfiles; i++) {
+    std::string keystr;
+    snprintf(buf, sizeof(buf), "%02d______:start", 0);
+    keystr = std::string(buf);
+    ASSERT_OK(dbtest->Put(keystr, keystr));
+    snprintf(buf, sizeof(buf), "%02d______:end",
+             small_range_sstfiles+i+1);
+    keystr = std::string(buf);
+    ASSERT_OK(dbtest->Put(keystr, keystr));
+    dbtest->dbfull()->TEST_FlushMemTable();
+  }
+}
+
+TEST(DBTest, PrefixScan) {
+  for (int it = 0; it < 2; ++it) {
+    ReadOptions ro = ReadOptions();
+    int count;
+    Slice prefix;
+    Slice key;
+    char buf[100];
+    Iterator* iter;
+    snprintf(buf, sizeof(buf), "03______:");
+    prefix = Slice(buf, 8);
+    key = Slice(buf, 9);
+    auto prefix_extractor = NewFixedPrefixTransform(8);
+    // db configs
+    env_->count_random_reads_ = true;
+    Options options = CurrentOptions();
+    options.env = env_;
+    options.no_block_cache = true;
+    options.filter_policy =  NewBloomFilterPolicy(10);
+    options.prefix_extractor = prefix_extractor;
+    options.whole_key_filtering = false;
+    options.disable_auto_compactions = true;
+    options.max_background_compactions = 2;
+    options.create_if_missing = true;
+    options.disable_seek_compaction = true;
+    if (it == 0) {
+      options.memtable_factory.reset(NewHashSkipListRepFactory(
+            prefix_extractor));
+    } else {
+      options.memtable_factory = std::make_shared<PrefixHashRepFactory>(
+          prefix_extractor);
+    }
+
+    // prefix specified, with blooms: 2 RAND I/Os
+    // SeekToFirst
+    DestroyAndReopen(&options);
+    PrefixScanInit(this);
+    count = 0;
+    env_->random_read_counter_.Reset();
+    ro.prefix = &prefix;
+    iter = db_->NewIterator(ro);
+    for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
+      assert(iter->key().starts_with(prefix));
+      count++;
+    }
+    ASSERT_OK(iter->status());
+    delete iter;
+    ASSERT_EQ(count, 2);
+    ASSERT_EQ(env_->random_read_counter_.Read(), 2);
+
+    // prefix specified, with blooms: 2 RAND I/Os
+    // Seek
+    DestroyAndReopen(&options);
+    PrefixScanInit(this);
+    count = 0;
+    env_->random_read_counter_.Reset();
+    ro.prefix = &prefix;
+    iter = db_->NewIterator(ro);
+    for (iter->Seek(key); iter->Valid(); iter->Next()) {
+      assert(iter->key().starts_with(prefix));
+      count++;
+    }
+    ASSERT_OK(iter->status());
+    delete iter;
+    ASSERT_EQ(count, 2);
+    ASSERT_EQ(env_->random_read_counter_.Read(), 2);
+
+    // no prefix specified: 11 RAND I/Os
+    DestroyAndReopen(&options);
+    PrefixScanInit(this);
+    count = 0;
+    env_->random_read_counter_.Reset();
+    iter = db_->NewIterator(ReadOptions());
+    for (iter->Seek(prefix); iter->Valid(); iter->Next()) {
+      if (! iter->key().starts_with(prefix)) {
+        break;
+      }
+      count++;
+    }
+    ASSERT_OK(iter->status());
+    delete iter;
+    ASSERT_EQ(count, 2);
+    ASSERT_EQ(env_->random_read_counter_.Read(), 11);
+    Close();
+    delete options.filter_policy;
+  }
+}
+
+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() + "/rocksdb_test_benchmark";
+  ASSERT_OK(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;
+  EnvOptions sopt;
+  VersionSet vset(dbname, &options, sopt, 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, 1, 1);
+  }
+  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, 1, 1);
+    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 rocksdb
+
+int main(int argc, char** argv) {
+  if (argc > 1 && std::string(argv[1]) == "--benchmark") {
+    rocksdb::BM_LogAndApply(1000, 1);
+    rocksdb::BM_LogAndApply(1000, 100);
+    rocksdb::BM_LogAndApply(1000, 10000);
+    rocksdb::BM_LogAndApply(100, 100000);
+    return 0;
+  }
+
+  return rocksdb::test::RunAllTests();
+}
diff --git a/db/dbformat.cc b/db/dbformat.cc
new file mode 100644 (file)
index 0000000..3d7e610
--- /dev/null
@@ -0,0 +1,147 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <stdio.h>
+#include "db/dbformat.h"
+#include "port/port.h"
+#include "util/coding.h"
+#include "util/perf_context_imp.h"
+
+namespace rocksdb {
+
+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 name_.c_str();
+}
+
+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));
+  BumpPerfCount(&perf_context.user_key_comparison_count);
+  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<Slice*>(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 rocksdb
diff --git a/db/dbformat.h b/db/dbformat.h
new file mode 100644 (file)
index 0000000..64a2c9f
--- /dev/null
@@ -0,0 +1,229 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <stdio.h>
+#include "rocksdb/comparator.h"
+#include "rocksdb/db.h"
+#include "rocksdb/filter_policy.h"
+#include "rocksdb/slice.h"
+#include "rocksdb/table.h"
+#include "rocksdb/types.h"
+#include "util/coding.h"
+#include "util/logging.h"
+
+namespace rocksdb {
+
+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,
+  kTypeMerge = 0x2,
+  kTypeLogData = 0x3
+};
+// 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 = kTypeMerge;
+
+// 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<ValueType>(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_;
+  std::string name_;
+ public:
+  explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c),
+    name_("rocksdb.InternalKeyComparator:" +
+          std::string(user_comparator_->Name())) {
+  }
+
+  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<ValueType>(c);
+  result->user_key = Slice(internal_key.data(), n - 8);
+  return (c <= static_cast<unsigned char>(kValueTypeForSeek));
+}
+
+// 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);
+}
+
+// Get the sequence number from the internal key
+inline uint64_t GetInternalKeySeqno(const Slice& internal_key) {
+  const size_t n = internal_key.size();
+  assert(n >= 8);
+  uint64_t num = DecodeFixed64(internal_key.data() + n - 8);
+  return num >> 8;
+}
+
+
+// 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 rocksdb
diff --git a/db/dbformat_test.cc b/db/dbformat_test.cc
new file mode 100644 (file)
index 0000000..b520f3c
--- /dev/null
@@ -0,0 +1,117 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 rocksdb {
+
+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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/db/deletefile_test.cc b/db/deletefile_test.cc
new file mode 100644 (file)
index 0000000..8048bd4
--- /dev/null
@@ -0,0 +1,283 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/db.h"
+#include "db/db_impl.h"
+#include "db/filename.h"
+#include "db/version_set.h"
+#include "db/write_batch_internal.h"
+#include "util/testharness.h"
+#include "util/testutil.h"
+#include "rocksdb/env.h"
+#include "rocksdb/transaction_log.h"
+#include <vector>
+#include <stdlib.h>
+#include <map>
+#include <string>
+
+namespace rocksdb {
+
+class DeleteFileTest {
+ public:
+  std::string dbname_;
+  Options options_;
+  DB* db_;
+  Env* env_;
+  int numlevels_;
+
+  DeleteFileTest() {
+    db_ = nullptr;
+    env_ = Env::Default();
+    options_.write_buffer_size = 1024*1024*1000;
+    options_.target_file_size_base = 1024*1024*1000;
+    options_.max_bytes_for_level_base = 1024*1024*1000;
+    options_.WAL_ttl_seconds = 300; // Used to test log files
+    options_.WAL_size_limit_MB = 1024; // Used to test log files
+    dbname_ = test::TmpDir() + "/deletefile_test";
+    options_.wal_dir = dbname_ + "/wal_files";
+    DestroyDB(dbname_, options_);
+    numlevels_ = 7;
+    ASSERT_OK(ReopenDB(true));
+  }
+
+  Status ReopenDB(bool create) {
+    delete db_;
+    if (create) {
+      DestroyDB(dbname_, options_);
+    }
+    db_ = nullptr;
+    options_.create_if_missing = create;
+    return DB::Open(options_, dbname_, &db_);
+  }
+
+  void CloseDB() {
+    delete db_;
+  }
+
+  void AddKeys(int numkeys, int startkey = 0) {
+    WriteOptions options;
+    options.sync = false;
+    ReadOptions roptions;
+    for (int i = startkey; i < (numkeys + startkey) ; i++) {
+      std::string temp = std::to_string(i);
+      Slice key(temp);
+      Slice value(temp);
+      ASSERT_OK(db_->Put(options, key, value));
+    }
+  }
+
+  int numKeysInLevels(
+    std::vector<LiveFileMetaData> &metadata,
+    std::vector<int> *keysperlevel = nullptr) {
+
+    if (keysperlevel != nullptr) {
+      keysperlevel->resize(numlevels_);
+    }
+
+    int numKeys = 0;
+    for (size_t i = 0; i < metadata.size(); i++) {
+      int startkey = atoi(metadata[i].smallestkey.c_str());
+      int endkey = atoi(metadata[i].largestkey.c_str());
+      int numkeysinfile = (endkey - startkey + 1);
+      numKeys += numkeysinfile;
+      if (keysperlevel != nullptr) {
+        (*keysperlevel)[(int)metadata[i].level] += numkeysinfile;
+      }
+      fprintf(stderr, "level %d name %s smallest %s largest %s\n",
+              metadata[i].level, metadata[i].name.c_str(),
+              metadata[i].smallestkey.c_str(),
+              metadata[i].largestkey.c_str());
+    }
+    return numKeys;
+  }
+
+  void CreateTwoLevels() {
+    AddKeys(50000, 10000);
+    DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
+    ASSERT_OK(dbi->TEST_FlushMemTable());
+    ASSERT_OK(dbi->TEST_WaitForFlushMemTable());
+
+    AddKeys(50000, 10000);
+    ASSERT_OK(dbi->TEST_FlushMemTable());
+    ASSERT_OK(dbi->TEST_WaitForFlushMemTable());
+  }
+
+  void CheckFileTypeCounts(std::string& dir,
+                            int required_log,
+                            int required_sst,
+                            int required_manifest) {
+    std::vector<std::string> filenames;
+    env_->GetChildren(dir, &filenames);
+
+    int log_cnt = 0, sst_cnt = 0, manifest_cnt = 0;
+    for (auto file : filenames) {
+      uint64_t number;
+      FileType type;
+      if (ParseFileName(file, &number, &type)) {
+        log_cnt += (type == kLogFile);
+        sst_cnt += (type == kTableFile);
+        manifest_cnt += (type == kDescriptorFile);
+      }
+    }
+    ASSERT_EQ(required_log, log_cnt);
+    ASSERT_EQ(required_sst, sst_cnt);
+    ASSERT_EQ(required_manifest, manifest_cnt);
+  }
+
+};
+
+TEST(DeleteFileTest, AddKeysAndQueryLevels) {
+  CreateTwoLevels();
+  std::vector<LiveFileMetaData> metadata;
+  std::vector<int> keysinlevel;
+  db_->GetLiveFilesMetaData(&metadata);
+
+  std::string level1file = "";
+  int level1keycount = 0;
+  std::string level2file = "";
+  int level2keycount = 0;
+  int level1index = 0;
+  int level2index = 1;
+
+  ASSERT_EQ((int)metadata.size(), 2);
+  if (metadata[0].level == 2) {
+    level1index = 1;
+    level2index = 0;
+  }
+
+  level1file = metadata[level1index].name;
+  int startkey = atoi(metadata[level1index].smallestkey.c_str());
+  int endkey = atoi(metadata[level1index].largestkey.c_str());
+  level1keycount = (endkey - startkey + 1);
+  level2file = metadata[level2index].name;
+  startkey = atoi(metadata[level2index].smallestkey.c_str());
+  endkey = atoi(metadata[level2index].largestkey.c_str());
+  level2keycount = (endkey - startkey + 1);
+
+  // COntrolled setup. Levels 1 and 2 should both have 50K files.
+  // This is a little fragile as it depends on the current
+  // compaction heuristics.
+  ASSERT_EQ(level1keycount, 50000);
+  ASSERT_EQ(level2keycount, 50000);
+
+  Status status = db_->DeleteFile("0.sst");
+  ASSERT_TRUE(status.IsInvalidArgument());
+
+  // intermediate level files cannot be deleted.
+  status = db_->DeleteFile(level1file);
+  ASSERT_TRUE(status.IsInvalidArgument());
+
+  // Lowest level file deletion should succeed.
+  ASSERT_OK(db_->DeleteFile(level2file));
+
+  CloseDB();
+}
+
+TEST(DeleteFileTest, PurgeObsoleteFilesTest) {
+  CreateTwoLevels();
+  // there should be only one (empty) log file because CreateTwoLevels()
+  // flushes the memtables to disk
+  CheckFileTypeCounts(options_.wal_dir, 1, 0, 0);
+  // 2 ssts, 1 manifest
+  CheckFileTypeCounts(dbname_, 0, 2, 1);
+  std::string first("0"), last("999999");
+  Slice first_slice(first), last_slice(last);
+  db_->CompactRange(&first_slice, &last_slice, true, 2);
+  // 1 sst after compaction
+  CheckFileTypeCounts(dbname_, 0, 1, 1);
+
+  // this time, we keep an iterator alive
+  ReopenDB(true);
+  Iterator *itr = 0;
+  CreateTwoLevels();
+  itr = db_->NewIterator(ReadOptions());
+  db_->CompactRange(&first_slice, &last_slice, true, 2);
+  // 3 sst after compaction with live iterator
+  CheckFileTypeCounts(dbname_, 0, 3, 1);
+  delete itr;
+  // 1 sst after iterator deletion
+  CheckFileTypeCounts(dbname_, 0, 1, 1);
+
+  CloseDB();
+}
+
+TEST(DeleteFileTest, DeleteFileWithIterator) {
+  CreateTwoLevels();
+  ReadOptions options;
+  Iterator* it = db_->NewIterator(options);
+  std::vector<LiveFileMetaData> metadata;
+  db_->GetLiveFilesMetaData(&metadata);
+
+  std::string level2file = "";
+
+  ASSERT_EQ((int)metadata.size(), 2);
+  if (metadata[0].level == 1) {
+    level2file = metadata[1].name;
+  } else {
+    level2file = metadata[0].name;
+  }
+
+  Status status = db_->DeleteFile(level2file);
+  fprintf(stdout, "Deletion status %s: %s\n",
+          level2file.c_str(), status.ToString().c_str());
+  ASSERT_TRUE(status.ok());
+  it->SeekToFirst();
+  int numKeysIterated = 0;
+  while(it->Valid()) {
+    numKeysIterated++;
+    it->Next();
+  }
+  ASSERT_EQ(numKeysIterated, 50000);
+  delete it;
+  CloseDB();
+}
+
+TEST(DeleteFileTest, DeleteLogFiles) {
+  AddKeys(10, 0);
+  VectorLogPtr logfiles;
+  db_->GetSortedWalFiles(logfiles);
+  ASSERT_GT(logfiles.size(), 0UL);
+  // Take the last log file which is expected to be alive and try to delete it
+  // Should not succeed because live logs are not allowed to be deleted
+  std::unique_ptr<LogFile> alive_log = std::move(logfiles.back());
+  ASSERT_EQ(alive_log->Type(), kAliveLogFile);
+  ASSERT_TRUE(env_->FileExists(options_.wal_dir + "/" + alive_log->PathName()));
+  fprintf(stdout, "Deleting alive log file %s\n",
+          alive_log->PathName().c_str());
+  ASSERT_TRUE(!db_->DeleteFile(alive_log->PathName()).ok());
+  ASSERT_TRUE(env_->FileExists(options_.wal_dir + "/" + alive_log->PathName()));
+  logfiles.clear();
+
+  // Call Flush to bring about a new working log file and add more keys
+  // Call Flush again to flush out memtable and move alive log to archived log
+  // and try to delete the archived log file
+  FlushOptions fopts;
+  db_->Flush(fopts);
+  AddKeys(10, 0);
+  db_->Flush(fopts);
+  db_->GetSortedWalFiles(logfiles);
+  ASSERT_GT(logfiles.size(), 0UL);
+  std::unique_ptr<LogFile> archived_log = std::move(logfiles.front());
+  ASSERT_EQ(archived_log->Type(), kArchivedLogFile);
+  ASSERT_TRUE(env_->FileExists(options_.wal_dir + "/" +
+        archived_log->PathName()));
+  fprintf(stdout, "Deleting archived log file %s\n",
+          archived_log->PathName().c_str());
+  ASSERT_OK(db_->DeleteFile(archived_log->PathName()));
+  ASSERT_TRUE(!env_->FileExists(options_.wal_dir + "/" +
+        archived_log->PathName()));
+  CloseDB();
+}
+
+} //namespace rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
+
diff --git a/db/filename.cc b/db/filename.cc
new file mode 100644 (file)
index 0000000..cdbd1bc
--- /dev/null
@@ -0,0 +1,266 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <ctype.h>
+#include <stdio.h>
+#include "db/dbformat.h"
+#include "rocksdb/env.h"
+#include "util/logging.h"
+
+namespace rocksdb {
+
+// 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<unsigned long long>(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& dir) {
+  return dir + "/" + ARCHIVAL_DIR;
+}
+std::string ArchivedLogFileName(const std::string& name, uint64_t number) {
+  assert(number > 0);
+  return MakeFileName(name + "/" + ARCHIVAL_DIR, 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<unsigned long long>(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<unsigned long long>(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<unsigned long long>(number));
+  return dbname + buf;
+}
+
+std::string IdentityFileName(const std::string& dbname) {
+  return dbname + "/IDENTITY";
+}
+
+// Owned filenames have the form:
+//    dbname/IDENTITY
+//    dbname/CURRENT
+//    dbname/LOCK
+//    dbname/LOG
+//    dbname/LOG.old.[0-9]+
+//    dbname/MANIFEST-[0-9]+
+//    dbname/[0-9]+.(log|sst)
+//    dbname/METADB-[0-9]+
+//    Disregards / at the beginning
+bool ParseFileName(const std::string& fname,
+                   uint64_t* number,
+                   FileType* type,
+                   WalFileType* log_type) {
+  Slice rest(fname);
+  if (fname.length() > 1 && fname[0] == '/') {
+    rest.remove_prefix(1);
+  }
+  if (rest == "IDENTITY") {
+    *number = 0;
+    *type = kIdentityFile;
+  } else 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
+    bool archive_dir_found = false;
+    if (rest.starts_with(ARCHIVAL_DIR)) {
+      if (rest.size() <= ARCHIVAL_DIR.size()) {
+        return false;
+      }
+      rest.remove_prefix(ARCHIVAL_DIR.size() + 1); // Add 1 to remove / also
+      if (log_type) {
+        *log_type = kArchivedLogFile;
+      }
+      archive_dir_found = true;
+    }
+    uint64_t num;
+    if (!ConsumeDecimalNumber(&rest, &num)) {
+      return false;
+    }
+    Slice suffix = rest;
+    if (suffix == Slice(".log")) {
+      *type = kLogFile;
+      if (log_type && !archive_dir_found) {
+        *log_type = kAliveLogFile;
+      }
+    } else if (archive_dir_found) {
+      return false; // Archive dir can contain only log files
+    } 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;
+}
+
+Status SetIdentityFile(Env* env, const std::string& dbname) {
+  std::string id = env->GenerateUniqueId();
+  assert(!id.empty());
+  // Reserve the filename dbname/000000.dbtmp for the temporary identity file
+  std::string tmp = TempFileName(dbname, 0);
+  Status s = WriteStringToFileSync(env, id, tmp);
+  if (s.ok()) {
+    s = env->RenameFile(tmp, IdentityFileName(dbname));
+  }
+  if (!s.ok()) {
+    env->DeleteFile(tmp);
+  }
+  return s;
+}
+
+}  // namespace rocksdb
diff --git a/db/filename.h b/db/filename.h
new file mode 100644 (file)
index 0000000..8e55f11
--- /dev/null
@@ -0,0 +1,108 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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
+
+#pragma once
+#include <stdint.h>
+#include <string>
+#include "rocksdb/slice.h"
+#include "rocksdb/status.h"
+#include "rocksdb/transaction_log.h"
+#include "port/port.h"
+
+namespace rocksdb {
+
+class Env;
+
+enum FileType {
+  kLogFile,
+  kDBLockFile,
+  kTableFile,
+  kDescriptorFile,
+  kCurrentFile,
+  kTempFile,
+  kInfoLogFile,  // Either the current one, or an old one
+  kMetaDatabase,
+  kIdentityFile
+};
+
+// 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);
+
+// Return the name of the Identity file which stores a unique number for the db
+// that will get regenerated if the db loses all its data and is recreated fresh
+// either from a backup-image or empty
+extern std::string IdentityFileName(const std::string& dbname);
+
+// If filename is a rocksdb 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,
+                          WalFileType* log_type = nullptr);
+
+// 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);
+
+// Make the IDENTITY file for the db
+extern Status SetIdentityFile(Env* env, const std::string& dbname);
+
+}  // namespace rocksdb
diff --git a/db/filename_test.cc b/db/filename_test.cc
new file mode 100644 (file)
index 0000000..0baa7fd
--- /dev/null
@@ -0,0 +1,140 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 rocksdb {
+
+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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/db/log_format.h b/db/log_format.h
new file mode 100644 (file)
index 0000000..10a31ba
--- /dev/null
@@ -0,0 +1,36 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+namespace rocksdb {
+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 unsigned int kBlockSize = 32768;
+
+// Header is checksum (4 bytes), type (1 byte), length (2 bytes).
+static const int kHeaderSize = 4 + 1 + 2;
+
+}  // namespace log
+}  // namespace rocksdb
diff --git a/db/log_reader.cc b/db/log_reader.cc
new file mode 100644 (file)
index 0000000..6596cd8
--- /dev/null
@@ -0,0 +1,264 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <stdio.h>
+#include "rocksdb/env.h"
+#include "util/coding.h"
+#include "util/crc32c.h"
+
+namespace rocksdb {
+namespace log {
+
+Reader::Reporter::~Reporter() {
+}
+
+Reader::Reader(unique_ptr<SequentialFile>&& 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<uint32_t>(header[4]) & 0xff;
+    const uint32_t b = static_cast<uint32_t>(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 rocksdb
diff --git a/db/log_reader.h b/db/log_reader.h
new file mode 100644 (file)
index 0000000..8e277c8
--- /dev/null
@@ -0,0 +1,124 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <memory>
+#include <stdint.h>
+
+#include "db/log_format.h"
+#include "rocksdb/slice.h"
+#include "rocksdb/status.h"
+
+namespace rocksdb {
+
+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<SequentialFile>&& 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();
+
+  // returns true if the reader has encountered an eof condition.
+  bool IsEOF() {
+    return eof_;
+  }
+
+  // when we know more data has been written to the file. we can use this
+  // function to force the reader to look again in the file.
+  void UnmarkEOF() {
+    eof_ = false;
+  }
+
+  SequentialFile* file() { return file_.get(); }
+
+ private:
+  const unique_ptr<SequentialFile> 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 rocksdb
diff --git a/db/log_test.cc b/db/log_test.cc
new file mode 100644 (file)
index 0000000..dedbff0
--- /dev/null
@@ -0,0 +1,528 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/env.h"
+#include "util/coding.h"
+#include "util/crc32c.h"
+#include "util/random.h"
+#include "util/testharness.h"
+
+namespace rocksdb {
+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<StringDest*>(writer_.file());
+    assert(dest);
+    return dest->contents_;
+  }
+
+  const std::string& dest_contents() const {
+    auto dest = dynamic_cast<const StringDest*>(writer_.file());
+    assert(dest);
+    return dest->contents_;
+  }
+
+  void reset_source_contents() {
+    auto src = dynamic_cast<StringSource*>(reader_.file());
+    assert(src);
+    src->contents_ = dest_contents();
+  }
+
+  unique_ptr<StringDest> dest_holder_;
+  unique_ptr<StringSource> 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<StringSource*>(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<char>('a' + i));
+      Write(record);
+    }
+  }
+
+  void CheckOffsetPastEndReturnsNoRecords(uint64_t offset_past_end) {
+    WriteInitialOffsetLog();
+    reading_ = true;
+    unique_ptr<StringSource> source(new StringSource);
+    source->contents_ = dest_contents();
+    unique_ptr<Reader> 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<StringSource> source(new StringSource);
+    source->contents_ = dest_contents();
+    unique_ptr<Reader> 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 (unsigned int offset = kBlockSize; offset < 2*kBlockSize; offset++) {
+    SetByte(offset, 'x');
+  }
+
+  ASSERT_EQ("correct", Read());
+  ASSERT_EQ("EOF", Read());
+  const unsigned 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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/db/log_writer.cc b/db/log_writer.cc
new file mode 100644 (file)
index 0000000..df601a4
--- /dev/null
@@ -0,0 +1,108 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <stdint.h>
+#include "rocksdb/env.h"
+#include "util/coding.h"
+#include "util/crc32c.h"
+
+namespace rocksdb {
+namespace log {
+
+Writer::Writer(unique_ptr<WritableFile>&& dest)
+    : dest_(std::move(dest)),
+      block_offset_(0) {
+  for (int i = 0; i <= kMaxRecordType; i++) {
+    char t = static_cast<char>(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<char>(n & 0xff);
+  buf[5] = static_cast<char>(n >> 8);
+  buf[6] = static_cast<char>(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 rocksdb
diff --git a/db/log_writer.h b/db/log_writer.h
new file mode 100644 (file)
index 0000000..d7b7aff
--- /dev/null
@@ -0,0 +1,55 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <memory>
+#include <stdint.h>
+#include "db/log_format.h"
+#include "rocksdb/slice.h"
+#include "rocksdb/status.h"
+
+namespace rocksdb {
+
+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<WritableFile>&& dest);
+  ~Writer();
+
+  Status AddRecord(const Slice& slice);
+
+  WritableFile* file() { return dest_.get(); }
+  const WritableFile* file() const { return dest_.get(); }
+
+ private:
+  unique_ptr<WritableFile> 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 rocksdb
diff --git a/db/memtable.cc b/db/memtable.cc
new file mode 100644 (file)
index 0000000..291899c
--- /dev/null
@@ -0,0 +1,330 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <memory>
+
+#include "db/dbformat.h"
+#include "rocksdb/comparator.h"
+#include "rocksdb/env.h"
+#include "rocksdb/iterator.h"
+#include "rocksdb/merge_operator.h"
+#include "util/coding.h"
+#include "util/mutexlock.h"
+#include "util/murmurhash.h"
+
+namespace std {
+template <>
+struct hash<rocksdb::Slice> {
+  size_t operator()(const rocksdb::Slice& slice) const {
+    return MurmurHash(slice.data(), slice.size(), 0);
+  }
+};
+}
+
+namespace rocksdb {
+
+MemTable::MemTable(const InternalKeyComparator& cmp,
+                   std::shared_ptr<MemTableRepFactory> table_factory,
+                   int numlevel,
+                   const Options& options)
+    : comparator_(cmp),
+      refs_(0),
+      arena_impl_(options.arena_block_size),
+      table_(table_factory->CreateMemTableRep(comparator_, &arena_impl_)),
+      flush_in_progress_(false),
+      flush_completed_(false),
+      file_number_(0),
+      edit_(numlevel),
+      first_seqno_(0),
+      mem_next_logfile_number_(0),
+      mem_logfile_number_(0),
+      locks_(options.inplace_update_support
+             ? options.inplace_update_num_locks
+             : 0) { }
+
+MemTable::~MemTable() {
+  assert(refs_ == 0);
+}
+
+size_t MemTable::ApproximateMemoryUsage() {
+  return arena_impl_.ApproximateMemoryUsage() +
+    table_->ApproximateMemoryUsage();
+}
+
+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);
+}
+
+Slice MemTableRep::UserKey(const char* key) const {
+  Slice slice = GetLengthPrefixedSlice(key);
+  return Slice(slice.data(), slice.size() - 8);
+}
+
+// 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:
+  MemTableIterator(MemTableRep* table, const ReadOptions& options)
+    : iter_() {
+    if (options.prefix) {
+      iter_ = table->GetPrefixIterator(*options.prefix);
+    } else if (options.prefix_seek) {
+      iter_ = table->GetDynamicPrefixIterator();
+    } else {
+      iter_ = table->GetIterator();
+    }
+  }
+
+  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:
+  std::shared_ptr<MemTableRep::Iterator> iter_;
+  std::string tmp_;       // For passing to EncodeKey
+
+  // No copying allowed
+  MemTableIterator(const MemTableIterator&);
+  void operator=(const MemTableIterator&);
+};
+
+Iterator* MemTable::NewIterator(const ReadOptions& options) {
+  return new MemTableIterator(table_.get(), options);
+}
+
+port::RWMutex* MemTable::GetLock(const Slice& key) {
+  return &locks_[std::hash<Slice>()(key) % locks_.size()];
+}
+
+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_impl_.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,
+                   std::deque<std::string>* operands, const Options& options) {
+  Slice memkey = key.memtable_key();
+  std::shared_ptr<MemTableRep::Iterator> iter(
+    table_->GetIterator(key.user_key()));
+  iter->Seek(memkey.data());
+
+  // It is the caller's responsibility to allocate/delete operands list
+  assert(operands != nullptr);
+
+  bool merge_in_progress = s->IsMergeInProgress();
+  auto merge_operator = options.merge_operator.get();
+  auto logger = options.info_log;
+  std::string merge_result;
+
+  for (; iter->Valid(); iter->Next()) {
+    // 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<ValueType>(tag & 0xff)) {
+        case kTypeValue: {
+          if (options.inplace_update_support) {
+            GetLock(key.user_key())->ReadLock();
+          }
+          Slice v = GetLengthPrefixedSlice(key_ptr + key_length);
+          *s = Status::OK();
+          if (merge_in_progress) {
+            assert(merge_operator);
+            if (!merge_operator->FullMerge(key.user_key(), &v, *operands,
+                                           value, logger.get())) {
+              RecordTick(options.statistics, NUMBER_MERGE_FAILURES);
+              *s = Status::Corruption("Error: Could not perform merge.");
+            }
+          } else {
+            value->assign(v.data(), v.size());
+          }
+          if (options.inplace_update_support) {
+            GetLock(key.user_key())->Unlock();
+          }
+          return true;
+        }
+        case kTypeDeletion: {
+          if (merge_in_progress) {
+            assert(merge_operator);
+            *s = Status::OK();
+            if (!merge_operator->FullMerge(key.user_key(), nullptr, *operands,
+                                           value, logger.get())) {
+              RecordTick(options.statistics, NUMBER_MERGE_FAILURES);
+              *s = Status::Corruption("Error: Could not perform merge.");
+            }
+          } else {
+            *s = Status::NotFound(Slice());
+          }
+          return true;
+        }
+        case kTypeMerge: {
+          Slice v = GetLengthPrefixedSlice(key_ptr + key_length);
+          merge_in_progress = true;
+          operands->push_front(v.ToString());
+          while(operands->size() >= 2) {
+            // Attempt to associative merge. (Returns true if successful)
+            if (merge_operator->PartialMerge(key.user_key(),
+                                             Slice((*operands)[0]),
+                                             Slice((*operands)[1]),
+                                             &merge_result,
+                                             logger.get())) {
+              operands->pop_front();
+              swap(operands->front(), merge_result);
+            } else {
+              // Stack them because user can't associative merge
+              break;
+            }
+          }
+          break;
+        }
+        case kTypeLogData:
+          assert(false);
+          break;
+      }
+    } else {
+      // exit loop if user key does not match
+      break;
+    }
+  }
+
+  // No change to value, since we have not yet found a Put/Delete
+
+  if (merge_in_progress) {
+    *s = Status::MergeInProgress("");
+  }
+  return false;
+}
+
+bool MemTable::Update(SequenceNumber seq, ValueType type,
+                      const Slice& key,
+                      const Slice& value) {
+  LookupKey lkey(key, seq);
+  Slice memkey = lkey.memtable_key();
+
+  std::shared_ptr<MemTableRep::Iterator> iter(
+    table_.get()->GetIterator(lkey.user_key()));
+  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), lkey.user_key()) == 0) {
+      // Correct user key
+      const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
+      switch (static_cast<ValueType>(tag & 0xff)) {
+        case kTypeValue: {
+          uint32_t vlength;
+          GetVarint32Ptr(key_ptr + key_length,
+                         key_ptr + key_length+5, &vlength);
+          // Update value, if newValue size  <= curValue size
+          if (value.size() <= vlength) {
+            char* p = EncodeVarint32(const_cast<char*>(key_ptr) + key_length,
+                                     value.size());
+            WriteLock wl(GetLock(lkey.user_key()));
+            memcpy(p, value.data(), value.size());
+            assert(
+              (p + value.size()) - entry ==
+              (unsigned) (VarintLength(key_length) +
+                          key_length +
+                          VarintLength(value.size()) +
+                          value.size())
+            );
+            return true;
+          }
+        }
+        default:
+          // If the latest value is kTypeDeletion, kTypeMerge or kTypeLogData
+          // then we probably don't have enough space to update in-place
+          // Maybe do something later
+          // Return false, and do normal Add()
+          return false;
+      }
+    }
+  }
+
+  // Key doesn't exist
+  return false;
+}
+}  // namespace rocksdb
diff --git a/db/memtable.h b/db/memtable.h
new file mode 100644 (file)
index 0000000..93b9b7e
--- /dev/null
@@ -0,0 +1,172 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <string>
+#include <memory>
+#include <deque>
+#include "db/dbformat.h"
+#include "db/skiplist.h"
+#include "db/version_set.h"
+#include "rocksdb/db.h"
+#include "rocksdb/memtablerep.h"
+#include "util/arena_impl.h"
+
+namespace rocksdb {
+
+class Mutex;
+class MemTableIterator;
+
+class MemTable {
+ public:
+  struct KeyComparator : public MemTableRep::KeyComparator {
+    const InternalKeyComparator comparator;
+    explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) { }
+    virtual int operator()(const char* a, const char* b) const;
+  };
+
+  // MemTables are reference counted.  The initial reference count
+  // is zero and the caller must call Ref() at least once.
+  explicit MemTable(
+    const InternalKeyComparator& comparator,
+    std::shared_ptr<MemTableRepFactory> table_factory,
+    int numlevel = 7,
+    const Options& options = Options());
+
+  // 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.
+  //
+  // If options.prefix is supplied, it is passed to the underlying MemTableRep
+  // as a hint that the iterator only need to support access to keys with that
+  // specific prefix.
+  // If options.prefix is not supplied and options.prefix_seek is set, the
+  // iterator is not bound to a specific prefix. However, the semantics of
+  // Seek is changed - the result might only include keys with the same prefix
+  // as the seek-key.
+  Iterator* NewIterator(const ReadOptions& options = ReadOptions());
+
+  // 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.
+  // If memtable contains Merge operation as the most recent entry for a key,
+  //   and the merge process does not stop (not reaching a value or delete),
+  //   prepend the current merge operand to *operands.
+  //   store MergeInProgress in s, and return false.
+  // Else, return false.
+  bool Get(const LookupKey& key, std::string* value, Status* s,
+           std::deque<std::string>* operands, const Options& options);
+
+  // Update the value and return status ok,
+  //   if key exists in current memtable
+  //     if new sizeof(new_value) <= sizeof(old_value) &&
+  //       old_value for that key is a put i.e. kTypeValue
+  //     else return false, and status - NotUpdatable()
+  //   else return false, and status - NotFound()
+  bool Update(SequenceNumber seq, ValueType type,
+              const Slice& key,
+              const Slice& value);
+
+  // 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_; }
+
+  // Returns the next active logfile number when this memtable is about to
+  // be flushed to storage
+  uint64_t GetNextLogNumber() { return mem_next_logfile_number_; }
+
+  // Sets the next active logfile number when this memtable is about to
+  // be flushed to storage
+  void SetNextLogNumber(uint64_t num) { mem_next_logfile_number_ = num; }
+
+  // Returns the logfile number that can be safely deleted when this
+  // memstore is flushed to storage
+  uint64_t GetLogNumber() { return mem_logfile_number_; }
+
+  // Sets the logfile number that can be safely deleted when this
+  // memstore is flushed to storage
+  void SetLogNumber(uint64_t num) { mem_logfile_number_ = num; }
+
+  // Notify the underlying storage that no more items will be added
+  void MarkImmutable() { table_->MarkReadOnly(); }
+
+ private:
+  ~MemTable();  // Private since only Unref() should be used to delete it
+  friend class MemTableIterator;
+  friend class MemTableBackwardIterator;
+  friend class MemTableList;
+
+  KeyComparator comparator_;
+  int refs_;
+  ArenaImpl arena_impl_;
+  shared_ptr<MemTableRep> 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_;
+
+  // The log files earlier than this number can be deleted.
+  uint64_t mem_next_logfile_number_;
+
+  // The log file that backs this memtable (to be deleted when
+  // memtable flush is done)
+  uint64_t mem_logfile_number_;
+
+  // rw locks for inplace updates
+  std::vector<port::RWMutex> locks_;
+
+  // No copying allowed
+  MemTable(const MemTable&);
+  void operator=(const MemTable&);
+
+  // Get the lock associated for the key
+  port::RWMutex* GetLock(const Slice& key);
+};
+
+}  // namespace rocksdb
diff --git a/db/memtablelist.cc b/db/memtablelist.cc
new file mode 100644 (file)
index 0000000..3f2a885
--- /dev/null
@@ -0,0 +1,215 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "db/memtablelist.h"
+
+#include <string>
+#include "rocksdb/db.h"
+#include "db/memtable.h"
+#include "rocksdb/env.h"
+#include "rocksdb/iterator.h"
+#include "util/coding.h"
+
+namespace rocksdb {
+
+class InternalKeyComparator;
+class Mutex;
+class MemTableListIterator;
+class VersionSet;
+
+using std::list;
+
+// Increase reference count on all underling memtables
+void MemTableList::RefAll() {
+  for (auto &memtable : memlist_) {
+    memtable->Ref();
+  }
+}
+
+// Drop reference count on all underling memtables
+void MemTableList::UnrefAll() {
+  for (auto &memtable : memlist_) {
+    memtable->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(int min_write_buffer_number_to_merge) {
+  if ((flush_requested_ && num_flush_not_started_ >= 1) ||
+      (num_flush_not_started_ >= min_write_buffer_number_to_merge)) {
+    assert(imm_flush_needed.NoBarrier_Load() != nullptr);
+    return true;
+  }
+  return false;
+}
+
+// Returns the memtables that need to be flushed.
+void MemTableList::PickMemtablesToFlush(std::vector<MemTable*>* ret) {
+  for (auto 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
+      ret->push_back(m);
+    }
+  }
+  flush_requested_ = false; // start-flush request is complete
+}
+
+// Record a successful flush in the manifest file
+Status MemTableList::InstallMemtableFlushResults(
+                      const std::vector<MemTable*> &mems,
+                      VersionSet* vset, Status flushStatus,
+                      port::Mutex* mu, Logger* info_log,
+                      uint64_t file_number,
+                      std::set<uint64_t>& pending_outputs) {
+  mu->AssertHeld();
+
+  // If the flush was not successful, then just reset state.
+  // Maybe a suceeding attempt to flush will be successful.
+  if (!flushStatus.ok()) {
+    for (MemTable* m : mems) {
+      assert(m->flush_in_progress_);
+      assert(m->file_number_ == 0);
+
+      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
+  for (size_t i = 0; i < mems.size(); ++i) {
+    // All the edits are associated with the first memtable of this batch.
+    assert(i == 0 || mems[i]->GetEdits()->NumEntries() == 0);
+
+    mems[i]->flush_completed_ = true;
+    mems[i]->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. Memetables
+  // are always committed in the order that they were created.
+  while (!memlist_.empty() && s.ok()) {
+    MemTable* m = memlist_.back(); // get the last element
+    if (!m->flush_completed_) {
+      break;
+    }
+
+    Log(info_log,
+        "Level-0 commit table #%lu started",
+        (unsigned long)m->file_number_);
+
+    // this can release and reacquire the mutex.
+    s = vset->LogAndApply(&m->edit_, mu);
+
+    // All the later memtables that have the same filenum
+    // are part of the same batch. They can be committed now.
+    uint64_t mem_id = 1;  // how many memtables has been flushed.
+    do {
+      if (s.ok()) { // commit new state
+        Log(info_log,
+            "Level-0 commit table #%lu: memtable #%lu done",
+            (unsigned long)m->file_number_,
+            (unsigned long)mem_id);
+        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 #%lu: memtable #%lu failed",
+            (unsigned long)m->file_number_,
+            (unsigned long)mem_id);
+        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");
+      }
+      ++mem_id;
+    } while (!memlist_.empty() && (m = memlist_.back()) &&
+             m->file_number_ == file_number);
+  }
+  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);
+  m->MarkImmutable();
+  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 (auto &memtable : memlist_) {
+    size += memtable->ApproximateMemoryUsage();
+  }
+  return size;
+}
+
+// Search all the memtables starting from the most recent one.
+// Return the most recent value found, if any.
+// Operands stores the list of merge operations to apply, so far.
+bool MemTableList::Get(const LookupKey& key, std::string* value, Status* s,
+                       std::deque<std::string>* operands,
+                       const Options& options) {
+  for (auto &memtable : memlist_) {
+    if (memtable->Get(key, value, s, operands, options)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void MemTableList::GetMemTables(std::vector<MemTable*>* output) {
+  for (auto &memtable : memlist_) {
+    output->push_back(memtable);
+  }
+}
+
+}  // namespace rocksdb
diff --git a/db/memtablelist.h b/db/memtablelist.h
new file mode 100644 (file)
index 0000000..20ea9ec
--- /dev/null
@@ -0,0 +1,105 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+
+#pragma once
+#include <string>
+#include <list>
+#include <deque>
+#include "rocksdb/db.h"
+#include "db/dbformat.h"
+#include "db/skiplist.h"
+#include "memtable.h"
+
+namespace rocksdb {
+
+class InternalKeyComparator;
+class Mutex;
+class MemTableListIterator;
+
+//
+// This class stores references 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),
+    flush_requested_(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(int min_write_buffer_number_to_merge);
+
+  // Returns the earliest memtables that needs to be flushed. The returned
+  // memtables are guaranteed to be in the ascending order of created time.
+  void PickMemtablesToFlush(std::vector<MemTable*>* mems);
+
+  // Commit a successful flush in the manifest file
+  Status InstallMemtableFlushResults(const std::vector<MemTable*> &m,
+                      VersionSet* vset, Status flushStatus,
+                      port::Mutex* mu, Logger* info_log,
+                      uint64_t file_number,
+                      std::set<uint64_t>& 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,
+           std::deque<std::string>* operands, const Options& options);
+
+  // Returns the list of underlying memtables.
+  void GetMemTables(std::vector<MemTable*>* list);
+
+  // Request a flush of all existing memtables to storage
+  void FlushRequested() { flush_requested_ = true; }
+
+  // Copying allowed
+  // MemTableList(const MemTableList&);
+  // void operator=(const MemTableList&);
+
+ private:
+  std::list<MemTable*> memlist_;
+  int size_;
+
+  // the number of elements that still need flushing
+  int num_flush_not_started_;
+
+  // committing in progress
+  bool commit_in_progress_;
+
+  // Requested a flush of all memtables to storage
+  bool flush_requested_;
+
+};
+
+}  // namespace rocksdb
diff --git a/db/merge_helper.cc b/db/merge_helper.cc
new file mode 100644 (file)
index 0000000..9d757a5
--- /dev/null
@@ -0,0 +1,197 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "merge_helper.h"
+#include "db/dbformat.h"
+#include "rocksdb/comparator.h"
+#include "rocksdb/db.h"
+#include "rocksdb/merge_operator.h"
+#include <string>
+#include <stdio.h>
+
+namespace rocksdb {
+
+// PRE:  iter points to the first merge type entry
+// POST: iter points to the first entry beyond the merge process (or the end)
+//       keys_, operands_ are updated to reflect the merge result.
+//       keys_ stores the list of keys encountered while merging.
+//       operands_ stores the list of merge operands encountered while merging.
+//       keys_[i] corresponds to operands_[i] for each i.
+void MergeHelper::MergeUntil(Iterator* iter, SequenceNumber stop_before,
+                             bool at_bottom, shared_ptr<Statistics> stats) {
+  // Get a copy of the internal key, before it's invalidated by iter->Next()
+  // Also maintain the list of merge operands seen.
+  keys_.clear();
+  operands_.clear();
+  keys_.push_front(iter->key().ToString());
+  operands_.push_front(iter->value().ToString());
+
+  success_ = false;   // Will become true if we hit Put/Delete or bottom
+
+  // We need to parse the internal key again as the parsed key is
+  // backed by the internal key!
+  // Assume no internal key corruption as it has been successfully parsed
+  // by the caller.
+  // Invariant: keys_.back() will not change. Hence, orig_ikey is always valid.
+  ParsedInternalKey orig_ikey;
+  ParseInternalKey(keys_.back(), &orig_ikey);
+
+  bool hit_the_next_user_key = false;
+  ParsedInternalKey ikey;
+  std::string merge_result;  // Temporary value for merge results
+  for (iter->Next(); iter->Valid(); iter->Next()) {
+    assert(operands_.size() >= 1);        // Should be invariants!
+    assert(keys_.size() == operands_.size());
+
+    if (!ParseInternalKey(iter->key(), &ikey)) {
+      // stop at corrupted key
+      if (assert_valid_internal_key_) {
+        assert(!"corrupted internal key is not expected");
+      }
+      break;
+    }
+
+    if (user_comparator_->Compare(ikey.user_key, orig_ikey.user_key) != 0) {
+      // hit a different user key, stop right here
+      hit_the_next_user_key = true;
+      break;
+    }
+
+    if (stop_before && ikey.sequence <= stop_before) {
+      // hit an entry that's visible by the previous snapshot, can't touch that
+      break;
+    }
+
+    // At this point we are guaranteed that we need to process this key.
+
+    if (kTypeDeletion == ikey.type) {
+      // hit a delete
+      //   => merge nullptr with operands_
+      //   => store result in operands_.back() (and update keys_.back())
+      //   => change the entry type to kTypeValue for keys_.back()
+      // We are done! Return a success if the merge passes.
+      success_ = user_merge_operator_->FullMerge(ikey.user_key, nullptr,
+                                                 operands_, &merge_result,
+                                                 logger_);
+
+      // We store the result in keys_.back() and operands_.back()
+      // if nothing went wrong (i.e.: no operand corruption on disk)
+      if (success_) {
+        std::string& key = keys_.back();  // The original key encountered
+        orig_ikey.type = kTypeValue;
+        UpdateInternalKey(&key[0], key.size(),
+                          orig_ikey.sequence, orig_ikey.type);
+        swap(operands_.back(), merge_result);
+      } else {
+        RecordTick(stats, NUMBER_MERGE_FAILURES);
+      }
+
+      // move iter to the next entry (before doing anything else)
+      iter->Next();
+      return;
+    }
+
+    if (kTypeValue == ikey.type) {
+      // hit a put
+      //   => merge the put value with operands_
+      //   => store result in operands_.back() (and update keys_.back())
+      //   => change the entry type to kTypeValue for keys_.back()
+      // We are done! Success!
+      const Slice value = iter->value();
+      success_ = user_merge_operator_->FullMerge(ikey.user_key, &value,
+                                                 operands_, &merge_result,
+                                                 logger_);
+
+      // We store the result in keys_.back() and operands_.back()
+      // if nothing went wrong (i.e.: no operand corruption on disk)
+      if (success_) {
+        std::string& key = keys_.back();  // The original key encountered
+        orig_ikey.type = kTypeValue;
+        UpdateInternalKey(&key[0], key.size(),
+                          orig_ikey.sequence, orig_ikey.type);
+        swap(operands_.back(), merge_result);
+      } else {
+        RecordTick(stats, NUMBER_MERGE_FAILURES);
+      }
+
+      // move iter to the next entry
+      iter->Next();
+      return;
+    }
+
+    if (kTypeMerge == ikey.type) {
+      // hit a merge
+      //   => merge the operand into the front of the operands_ list
+      //   => use the user's associative merge function to determine how.
+      //   => then continue because we haven't yet seen a Put/Delete.
+      assert(!operands_.empty()); // Should have at least one element in it
+
+      keys_.push_front(iter->key().ToString());
+      operands_.push_front(iter->value().ToString());
+      while (operands_.size() >= 2) {
+        // Returns false when the merge_operator can no longer process it
+        if (user_merge_operator_->PartialMerge(ikey.user_key,
+                                               Slice(operands_[0]),
+                                               Slice(operands_[1]),
+                                               &merge_result,
+                                               logger_)) {
+          // Merging of operands (associative merge) was successful.
+          // Replace these frontmost two operands with the merge result
+          keys_.pop_front();
+          operands_.pop_front();
+          swap(operands_.front(), merge_result);
+        } else {
+          // Merging of operands (associative merge) returned false.
+          // The user merge_operator does not know how to merge these operands.
+          // So we just stack them up until we find a Put/Delete or end of key.
+          break;
+        }
+      }
+      continue;
+    }
+  }
+
+  // We are sure we have seen this key's entire history if we are at the
+  // last level and exhausted all internal keys of this user key.
+  // NOTE: !iter->Valid() does not necessarily mean we hit the
+  // beginning of a user key, as versions of a user key might be
+  // split into multiple files (even files on the same level)
+  // and some files might not be included in the compaction/merge.
+  //
+  // There are also cases where we have seen the root of history of this
+  // key without being sure of it. Then, we simply miss the opportunity
+  // to combine the keys. Since VersionSet::SetupOtherInputs() always makes
+  // sure that all merge-operands on the same level get compacted together,
+  // this will simply lead to these merge operands moving to the next level.
+  //
+  // So, we only perform the following logic (to merge all operands together
+  // without a Put/Delete) if we are certain that we have seen the end of key.
+  bool surely_seen_the_beginning = hit_the_next_user_key && at_bottom;
+  if (surely_seen_the_beginning) {
+    // do a final merge with nullptr as the existing value and say
+    // bye to the merge type (it's now converted to a Put)
+    assert(kTypeMerge == orig_ikey.type);
+    assert(operands_.size() >= 1);
+    assert(operands_.size() == keys_.size());
+    success_ = user_merge_operator_->FullMerge(orig_ikey.user_key, nullptr,
+                                               operands_, &merge_result,
+                                               logger_);
+
+    if (success_) {
+      std::string& key = keys_.back();  // The original key encountered
+      orig_ikey.type = kTypeValue;
+      UpdateInternalKey(&key[0], key.size(),
+                        orig_ikey.sequence, orig_ikey.type);
+
+      // The final value() is always stored in operands_.back()
+      swap(operands_.back(),merge_result);
+    } else {
+      RecordTick(stats, NUMBER_MERGE_FAILURES);
+      // Do nothing if not success_. Leave keys() and operands() as they are.
+    }
+  }
+}
+
+} // namespace rocksdb
diff --git a/db/merge_helper.h b/db/merge_helper.h
new file mode 100644 (file)
index 0000000..34e2edd
--- /dev/null
@@ -0,0 +1,102 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#ifndef MERGE_HELPER_H
+#define MERGE_HELPER_H
+
+#include "db/dbformat.h"
+#include "rocksdb/slice.h"
+#include "rocksdb/statistics.h"
+#include <string>
+#include <deque>
+
+namespace rocksdb {
+
+class Comparator;
+class Iterator;
+class Logger;
+class MergeOperator;
+
+class MergeHelper {
+ public:
+  MergeHelper(const Comparator* user_comparator,
+              const MergeOperator* user_merge_operator,
+              Logger* logger,
+              bool assert_valid_internal_key)
+      : user_comparator_(user_comparator),
+        user_merge_operator_(user_merge_operator),
+        logger_(logger),
+        assert_valid_internal_key_(assert_valid_internal_key),
+        keys_(),
+        operands_(),
+        success_(false) {}
+
+  // Merge entries until we hit
+  //     - a corrupted key
+  //     - a Put/Delete,
+  //     - a different user key,
+  //     - a specific sequence number (snapshot boundary),
+  //  or - the end of iteration
+  // iter: (IN)  points to the first merge type entry
+  //       (OUT) points to the first entry not included in the merge process
+  // stop_before: (IN) a sequence number that merge should not cross.
+  //                   0 means no restriction
+  // at_bottom:   (IN) true if the iterator covers the bottem level, which means
+  //                   we could reach the start of the history of this user key.
+  void MergeUntil(Iterator* iter, SequenceNumber stop_before = 0,
+                  bool at_bottom = false, shared_ptr<Statistics> stats=nullptr);
+
+  // Query the merge result
+  // These are valid until the next MergeUntil call
+  // If the merging was successful:
+  //   - IsSuccess() will be true
+  //   - key() will have the latest sequence number of the merges.
+  //           The type will be Put or Merge. See IMPORTANT 1 note, below.
+  //   - value() will be the result of merging all the operands together
+  //   - The user should ignore keys() and values().
+  //
+  //   IMPORTANT 1: the key type could change after the MergeUntil call.
+  //        Put/Delete + Merge + ... + Merge => Put
+  //        Merge + ... + Merge => Merge
+  //
+  // If the merge operator is not associative, and if a Put/Delete is not found
+  // then the merging will be unsuccessful. In this case:
+  //   - IsSuccess() will be false
+  //   - keys() contains the list of internal keys seen in order of iteration.
+  //   - values() contains the list of values (merges) seen in the same order.
+  //              values() is parallel to keys() so that the first entry in
+  //              keys() is the key associated with the first entry in values()
+  //              and so on. These lists will be the same length.
+  //              All of these pairs will be merges over the same user key.
+  //              See IMPORTANT 2 note below.
+  //   - The user should ignore key() and value().
+  //
+  //   IMPORTANT 2: The entries were traversed in order from BACK to FRONT.
+  //                So keys().back() was the first key seen by iterator.
+  // TODO: Re-style this comment to be like the first one
+  bool IsSuccess() { return success_; }
+  Slice key() { assert(success_); return Slice(keys_.back()); }
+  Slice value() { assert(success_); return Slice(operands_.back()); }
+  const std::deque<std::string>& keys() { assert(!success_); return keys_; }
+  const std::deque<std::string>& values() {
+    assert(!success_); return operands_;
+  }
+
+ private:
+  const Comparator* user_comparator_;
+  const MergeOperator* user_merge_operator_;
+  Logger* logger_;
+  bool assert_valid_internal_key_; // enforce no internal key corruption?
+
+  // the scratch area that holds the result of MergeUntil
+  // valid up to the next MergeUntil call
+  std::deque<std::string> keys_;    // Keeps track of the sequence of keys seen
+  std::deque<std::string> operands_;  // Parallel with keys_; stores the values
+  bool success_;
+};
+
+} // namespace rocksdb
+
+#endif
diff --git a/db/merge_operator.cc b/db/merge_operator.cc
new file mode 100644 (file)
index 0000000..7d1ee4e
--- /dev/null
@@ -0,0 +1,53 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+/**
+ * Back-end implementation details specific to the Merge Operator.
+ */
+
+#include "rocksdb/merge_operator.h"
+
+namespace rocksdb {
+
+// Given a "real" merge from the library, call the user's
+// associative merge function one-by-one on each of the operands.
+// NOTE: It is assumed that the client's merge-operator will handle any errors.
+bool AssociativeMergeOperator::FullMerge(
+    const Slice& key,
+    const Slice* existing_value,
+    const std::deque<std::string>& operand_list,
+    std::string* new_value,
+    Logger* logger) const {
+
+  // Simply loop through the operands
+  Slice temp_existing;
+  std::string temp_value;
+  for (const auto& operand : operand_list) {
+    Slice value(operand);
+    if (!Merge(key, existing_value, value, &temp_value, logger)) {
+      return false;
+    }
+    swap(temp_value, *new_value);
+    temp_existing = Slice(*new_value);
+    existing_value = &temp_existing;
+  }
+
+  // The result will be in *new_value. All merges succeeded.
+  return true;
+}
+
+// Call the user defined simple merge on the operands;
+// NOTE: It is assumed that the client's merge-operator will handle any errors.
+bool AssociativeMergeOperator::PartialMerge(
+    const Slice& key,
+    const Slice& left_operand,
+    const Slice& right_operand,
+    std::string* new_value,
+    Logger* logger) const {
+
+  return Merge(key, &left_operand, right_operand, new_value, logger);
+}
+
+} // namespace rocksdb
diff --git a/db/merge_test.cc b/db/merge_test.cc
new file mode 100644 (file)
index 0000000..0c14aff
--- /dev/null
@@ -0,0 +1,275 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include <assert.h>
+#include <memory>
+#include <iostream>
+
+#include "rocksdb/cache.h"
+#include "rocksdb/comparator.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/merge_operator.h"
+#include "db/dbformat.h"
+#include "db/db_impl.h"
+#include "utilities/merge_operators.h"
+#include "util/testharness.h"
+#include "utilities/utility_db.h"
+
+using namespace std;
+using namespace rocksdb;
+
+
+std::shared_ptr<DB> OpenDb(const string& dbname, const bool ttl = false) {
+  DB* db;
+  StackableDB* sdb;
+  Options options;
+  options.create_if_missing = true;
+  options.merge_operator = MergeOperators::CreateUInt64AddOperator();
+  Status s;
+  DestroyDB(dbname, Options());
+  if (ttl) {
+    cout << "Opening database with TTL\n";
+    s = UtilityDB::OpenTtlDB(options, dbname, &sdb);
+    db = sdb;
+  } else {
+    s = DB::Open(options, dbname, &db);
+  }
+  if (!s.ok()) {
+    cerr << s.ToString() << endl;
+    assert(false);
+  }
+  return std::shared_ptr<DB>(db);
+}
+
+// Imagine we are maintaining a set of uint64 counters.
+// Each counter has a distinct name. And we would like
+// to support four high level operations:
+// set, add, get and remove
+// This is a quick implementation without a Merge operation.
+class Counters {
+
+ protected:
+  std::shared_ptr<DB> db_;
+
+  WriteOptions put_option_;
+  ReadOptions get_option_;
+  WriteOptions delete_option_;
+
+  uint64_t default_;
+
+ public:
+  explicit Counters(std::shared_ptr<DB> db, uint64_t defaultCount = 0)
+      : db_(db),
+        put_option_(),
+        get_option_(),
+        delete_option_(),
+        default_(defaultCount) {
+    assert(db_);
+  }
+
+  virtual ~Counters() {}
+
+  // public interface of Counters.
+  // All four functions return false
+  // if the underlying level db operation failed.
+
+  // mapped to a levedb Put
+  bool set(const string& key, uint64_t value) {
+    // just treat the internal rep of int64 as the string
+    Slice slice((char *)&value, sizeof(value));
+    auto s = db_->Put(put_option_, key, slice);
+
+    if (s.ok()) {
+      return true;
+    } else {
+      cerr << s.ToString() << endl;
+      return false;
+    }
+  }
+
+  // mapped to a rocksdb Delete
+  bool remove(const string& key) {
+    auto s = db_->Delete(delete_option_, key);
+
+    if (s.ok()) {
+      return true;
+    } else {
+      cerr << s.ToString() << std::endl;
+      return false;
+    }
+  }
+
+  // mapped to a rocksdb Get
+  bool get(const string& key, uint64_t *value) {
+    string str;
+    auto s = db_->Get(get_option_, key, &str);
+
+    if (s.IsNotFound()) {
+      // return default value if not found;
+      *value = default_;
+      return true;
+    } else if (s.ok()) {
+      // deserialization
+      if (str.size() != sizeof(uint64_t)) {
+        cerr << "value corruption\n";
+        return false;
+      }
+      *value = DecodeFixed64(&str[0]);
+      return true;
+    } else {
+      cerr << s.ToString() << std::endl;
+      return false;
+    }
+  }
+
+  // 'add' is implemented as get -> modify -> set
+  // An alternative is a single merge operation, see MergeBasedCounters
+  virtual bool add(const string& key, uint64_t value) {
+    uint64_t base = default_;
+    return get(key, &base) && set(key, base + value);
+  }
+
+
+  // convenience functions for testing
+  void assert_set(const string& key, uint64_t value) {
+    assert(set(key, value));
+  }
+
+  void assert_remove(const string& key) {
+    assert(remove(key));
+  }
+
+  uint64_t assert_get(const string& key) {
+    uint64_t value = default_;
+    assert(get(key, &value));
+    return value;
+  }
+
+  void assert_add(const string& key, uint64_t value) {
+    assert(add(key, value));
+  }
+};
+
+// Implement 'add' directly with the new Merge operation
+class MergeBasedCounters : public Counters {
+ private:
+  WriteOptions merge_option_; // for merge
+
+ public:
+  explicit MergeBasedCounters(std::shared_ptr<DB> db, uint64_t defaultCount = 0)
+      : Counters(db, defaultCount),
+        merge_option_() {
+  }
+
+  // mapped to a rocksdb Merge operation
+  virtual bool add(const string& key, uint64_t value) override {
+    char encoded[sizeof(uint64_t)];
+    EncodeFixed64(encoded, value);
+    Slice slice(encoded, sizeof(uint64_t));
+    auto s = db_->Merge(merge_option_, key, slice);
+
+    if (s.ok()) {
+      return true;
+    } else {
+      cerr << s.ToString() << endl;
+      return false;
+    }
+  }
+};
+
+void dumpDb(DB* db) {
+  auto it = unique_ptr<Iterator>(db->NewIterator(ReadOptions()));
+  for (it->SeekToFirst(); it->Valid(); it->Next()) {
+    uint64_t value = DecodeFixed64(it->value().data());
+    cout << it->key().ToString() << ": "  << value << endl;
+  }
+  assert(it->status().ok());  // Check for any errors found during the scan
+}
+
+void testCounters(Counters& counters, DB* db, bool test_compaction) {
+
+  FlushOptions o;
+  o.wait = true;
+
+  counters.assert_set("a", 1);
+
+  if (test_compaction) db->Flush(o);
+
+  assert(counters.assert_get("a") == 1);
+
+  counters.assert_remove("b");
+
+  // defaut value is 0 if non-existent
+  assert(counters.assert_get("b") == 0);
+
+  counters.assert_add("a", 2);
+
+  if (test_compaction) db->Flush(o);
+
+  // 1+2 = 3
+  assert(counters.assert_get("a")== 3);
+
+  dumpDb(db);
+
+  std::cout << "1\n";
+
+  // 1+...+49 = ?
+  uint64_t sum = 0;
+  for (int i = 1; i < 50; i++) {
+    counters.assert_add("b", i);
+    sum += i;
+  }
+  assert(counters.assert_get("b") == sum);
+
+  std::cout << "2\n";
+  dumpDb(db);
+
+  std::cout << "3\n";
+
+  if (test_compaction) {
+    db->Flush(o);
+
+    cout << "Compaction started ...\n";
+    db->CompactRange(nullptr, nullptr);
+    cout << "Compaction ended\n";
+
+    dumpDb(db);
+
+    assert(counters.assert_get("a")== 3);
+    assert(counters.assert_get("b") == sum);
+  }
+}
+
+void runTest(int argc, const string& dbname, const bool use_ttl = false) {
+  auto db = OpenDb(dbname, use_ttl);
+
+  {
+    cout << "Test read-modify-write counters... \n";
+    Counters counters(db, 0);
+    testCounters(counters, db.get(), true);
+  }
+
+  bool compact = false;
+  if (argc > 1) {
+    compact = true;
+    cout << "Turn on Compaction\n";
+  }
+
+  {
+    cout << "Test merge-based counters... \n";
+    MergeBasedCounters counters(db, 0);
+    testCounters(counters, db.get(), compact);
+  }
+
+  DestroyDB(dbname, Options());
+}
+
+int main(int argc, char *argv[]) {
+  //TODO: Make this test like a general rocksdb unit-test
+  runTest(argc, test::TmpDir() + "/merge_testdb");
+  runTest(argc, test::TmpDir() + "/merge_testdbttl", true); // Run test on TTL database
+  return 0;
+}
diff --git a/db/perf_context_test.cc b/db/perf_context_test.cc
new file mode 100644 (file)
index 0000000..0541674
--- /dev/null
@@ -0,0 +1,328 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include <algorithm>
+#include <iostream>
+#include <vector>
+#include "/usr/include/valgrind/callgrind.h"
+
+#include "rocksdb/db.h"
+#include "rocksdb/perf_context.h"
+#include "util/histogram.h"
+#include "util/stop_watch.h"
+#include "util/testharness.h"
+
+
+bool FLAGS_random_key = false;
+bool FLAGS_use_set_based_memetable = false;
+int FLAGS_total_keys = 100;
+int FLAGS_write_buffer_size = 1000000000;
+int FLAGS_max_write_buffer_number = 8;
+int FLAGS_min_write_buffer_number_to_merge = 7;
+
+// Path to the database on file system
+const std::string kDbName = rocksdb::test::TmpDir() + "/perf_context_test";
+
+namespace rocksdb {
+
+std::shared_ptr<DB> OpenDb() {
+    DB* db;
+    Options options;
+    options.create_if_missing = true;
+    options.write_buffer_size = FLAGS_write_buffer_size;
+    options.max_write_buffer_number = FLAGS_max_write_buffer_number;
+    options.min_write_buffer_number_to_merge =
+      FLAGS_min_write_buffer_number_to_merge;
+
+    if (FLAGS_use_set_based_memetable) {
+      auto prefix_extractor = rocksdb::NewFixedPrefixTransform(0);
+      options.memtable_factory =
+        std::make_shared<rocksdb::PrefixHashRepFactory>(prefix_extractor);
+    }
+
+    Status s = DB::Open(options, kDbName,  &db);
+    ASSERT_OK(s);
+    return std::shared_ptr<DB>(db);
+}
+
+class PerfContextTest { };
+
+TEST(PerfContextTest, SeekIntoDeletion) {
+  DestroyDB(kDbName, Options());
+  auto db = OpenDb();
+  WriteOptions write_options;
+  ReadOptions read_options;
+
+  for (int i = 0; i < FLAGS_total_keys; ++i) {
+    std::string key = "k" + std::to_string(i);
+    std::string value = "v" + std::to_string(i);
+
+    db->Put(write_options, key, value);
+  }
+
+  for (int i = 0; i < FLAGS_total_keys -1 ; ++i) {
+    std::string key = "k" + std::to_string(i);
+    db->Delete(write_options, key);
+  }
+
+  HistogramImpl hist_get;
+  HistogramImpl hist_get_time;
+  for (int i = 0; i < FLAGS_total_keys - 1; ++i) {
+    std::string key = "k" + std::to_string(i);
+    std::string value;
+
+    perf_context.Reset();
+    StopWatchNano timer(Env::Default(), true);
+    auto status = db->Get(read_options, key, &value);
+    auto elapsed_nanos = timer.ElapsedNanos();
+    ASSERT_TRUE(status.IsNotFound());
+    hist_get.Add(perf_context.user_key_comparison_count);
+    hist_get_time.Add(elapsed_nanos);
+  }
+
+  std::cout << "Get uesr key comparison: \n" << hist_get.ToString()
+            << "Get time: \n" << hist_get_time.ToString();
+
+  HistogramImpl hist_seek_to_first;
+  std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
+
+  perf_context.Reset();
+  StopWatchNano timer(Env::Default(), true);
+  iter->SeekToFirst();
+  hist_seek_to_first.Add(perf_context.user_key_comparison_count);
+  auto elapsed_nanos = timer.ElapsedNanos();
+
+  std::cout << "SeekToFirst uesr key comparison: \n" << hist_seek_to_first.ToString()
+            << "ikey skipped: " << perf_context.internal_key_skipped_count << "\n"
+            << "idelete skipped: " << perf_context.internal_delete_skipped_count << "\n"
+            << "elapsed: " << elapsed_nanos << "\n";
+
+  HistogramImpl hist_seek;
+  for (int i = 0; i < FLAGS_total_keys; ++i) {
+    std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
+    std::string key = "k" + std::to_string(i);
+
+    perf_context.Reset();
+    StopWatchNano timer(Env::Default(), true);
+    iter->Seek(key);
+    auto elapsed_nanos = timer.ElapsedNanos();
+    hist_seek.Add(perf_context.user_key_comparison_count);
+    std::cout << "seek cmp: " << perf_context.user_key_comparison_count
+              << " ikey skipped " << perf_context.internal_key_skipped_count
+              << " idelete skipped " << perf_context.internal_delete_skipped_count
+              << " elapsed: " << elapsed_nanos << "ns\n";
+
+    perf_context.Reset();
+    ASSERT_TRUE(iter->Valid());
+    StopWatchNano timer2(Env::Default(), true);
+    iter->Next();
+    auto elapsed_nanos2 = timer2.ElapsedNanos();
+    std::cout << "next cmp: " << perf_context.user_key_comparison_count
+              << "elapsed: " << elapsed_nanos2 << "ns\n";
+  }
+
+  std::cout << "Seek uesr key comparison: \n" << hist_seek.ToString();
+}
+
+TEST(PerfContextTest, StopWatchNanoOverhead) {
+  // profile the timer cost by itself!
+  const int kTotalIterations = 1000000;
+  std::vector<uint64_t> timings(kTotalIterations);
+
+  StopWatchNano timer(Env::Default(), true);
+  for (auto& timing : timings) {
+    timing = timer.ElapsedNanos(true /* reset */);
+  }
+
+  HistogramImpl histogram;
+  for (const auto timing : timings) {
+    histogram.Add(timing);
+  }
+
+  std::cout << histogram.ToString();
+}
+
+TEST(PerfContextTest, StopWatchOverhead) {
+  // profile the timer cost by itself!
+  const int kTotalIterations = 1000000;
+  std::vector<uint64_t> timings(kTotalIterations);
+
+  StopWatch timer(Env::Default());
+  for (auto& timing : timings) {
+    timing = timer.ElapsedMicros();
+  }
+
+  HistogramImpl histogram;
+  uint64_t prev_timing = 0;
+  for (const auto timing : timings) {
+    histogram.Add(timing - prev_timing);
+    prev_timing = timing;
+  }
+
+  std::cout << histogram.ToString();
+}
+
+void ProfileKeyComparison() {
+  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
+
+  auto db = OpenDb();
+
+  WriteOptions write_options;
+  ReadOptions read_options;
+
+  HistogramImpl hist_put;
+  HistogramImpl hist_get;
+
+  std::cout << "Inserting " << FLAGS_total_keys << " key/value pairs\n...\n";
+
+  std::vector<int> keys;
+  for (int i = 0; i < FLAGS_total_keys; ++i) {
+    keys.push_back(i);
+  }
+
+  if (FLAGS_random_key) {
+    std::random_shuffle(keys.begin(), keys.end());
+  }
+
+  for (const int i : keys) {
+    std::string key = "k" + std::to_string(i);
+    std::string value = "v" + std::to_string(i);
+
+    perf_context.Reset();
+    db->Put(write_options, key, value);
+    hist_put.Add(perf_context.user_key_comparison_count);
+
+    perf_context.Reset();
+    db->Get(read_options, key, &value);
+    hist_get.Add(perf_context.user_key_comparison_count);
+  }
+
+  std::cout << "Put uesr key comparison: \n" << hist_put.ToString()
+            << "Get uesr key comparison: \n" << hist_get.ToString();
+
+}
+
+TEST(PerfContextTest, KeyComparisonCount) {
+  SetPerfLevel(kEnableCount);
+  ProfileKeyComparison();
+
+  SetPerfLevel(kDisable);
+  ProfileKeyComparison();
+
+  SetPerfLevel(kEnableTime);
+  ProfileKeyComparison();
+}
+
+// make perf_context_test
+// export ROCKSDB_TESTS=PerfContextTest.SeekKeyComparison
+// For one memtable:
+// ./perf_context_test --write_buffer_size=500000 --total_keys=10000
+// For two memtables:
+// ./perf_context_test --write_buffer_size=250000 --total_keys=10000
+// Specify --random_key=1 to shuffle the key before insertion
+// Results show that, for sequential insertion, worst-case Seek Key comparison
+// is close to the total number of keys (linear), when there is only one
+// memtable. When there are two memtables, even the avg Seek Key comparison
+// starts to become linear to the input size.
+
+TEST(PerfContextTest, SeekKeyComparison) {
+  DestroyDB(kDbName, Options());
+  auto db = OpenDb();
+  WriteOptions write_options;
+  ReadOptions read_options;
+
+  std::cout << "Inserting " << FLAGS_total_keys << " key/value pairs\n...\n";
+
+  std::vector<int> keys;
+  for (int i = 0; i < FLAGS_total_keys; ++i) {
+    keys.push_back(i);
+  }
+
+  if (FLAGS_random_key) {
+    std::random_shuffle(keys.begin(), keys.end());
+  }
+
+  HistogramImpl hist_put_time;
+  HistogramImpl hist_wal_time;
+  HistogramImpl hist_time_diff;
+
+  SetPerfLevel(kEnableTime);
+  StopWatchNano timer(Env::Default());
+  for (const int i : keys) {
+    std::string key = "k" + std::to_string(i);
+    std::string value = "v" + std::to_string(i);
+
+    perf_context.Reset();
+    timer.Start();
+    db->Put(write_options, key, value);
+    auto put_time = timer.ElapsedNanos();
+    hist_put_time.Add(put_time);
+    hist_wal_time.Add(perf_context.wal_write_time);
+    hist_time_diff.Add(put_time - perf_context.wal_write_time);
+  }
+
+  std::cout << "Put time:\n" << hist_put_time.ToString()
+            << "WAL time:\n" << hist_wal_time.ToString()
+            << "time diff:\n" << hist_time_diff.ToString();
+
+  HistogramImpl hist_seek;
+  HistogramImpl hist_next;
+
+  for (int i = 0; i < FLAGS_total_keys; ++i) {
+    std::string key = "k" + std::to_string(i);
+    std::string value = "v" + std::to_string(i);
+
+    std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
+    perf_context.Reset();
+    iter->Seek(key);
+    ASSERT_TRUE(iter->Valid());
+    ASSERT_EQ(iter->value().ToString(), value);
+    hist_seek.Add(perf_context.user_key_comparison_count);
+  }
+
+  std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
+  for (iter->SeekToFirst(); iter->Valid();) {
+    perf_context.Reset();
+    iter->Next();
+    hist_next.Add(perf_context.user_key_comparison_count);
+  }
+
+  std::cout << "Seek:\n" << hist_seek.ToString()
+            << "Next:\n" << hist_next.ToString();
+}
+
+}
+
+int main(int argc, char** argv) {
+
+  for (int i = 1; i < argc; i++) {
+    int n;
+    char junk;
+
+    if (sscanf(argv[i], "--write_buffer_size=%d%c", &n, &junk) == 1) {
+      FLAGS_write_buffer_size = n;
+    }
+
+    if (sscanf(argv[i], "--total_keys=%d%c", &n, &junk) == 1) {
+      FLAGS_total_keys = n;
+    }
+
+    if (sscanf(argv[i], "--random_key=%d%c", &n, &junk) == 1 &&
+        (n == 0 || n == 1)) {
+      FLAGS_random_key = n;
+    }
+
+    if (sscanf(argv[i], "--use_set_based_memetable=%d%c", &n, &junk) == 1 &&
+        (n == 0 || n == 1)) {
+      FLAGS_use_set_based_memetable = n;
+    }
+
+  }
+
+  std::cout << kDbName << "\n";
+
+  rocksdb::test::RunAllTests();
+  return 0;
+}
diff --git a/db/prefix_filter_iterator.h b/db/prefix_filter_iterator.h
new file mode 100644 (file)
index 0000000..f448837
--- /dev/null
@@ -0,0 +1,73 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// Wrap an underlying iterator, but exclude any results not starting
+// with a given prefix.  Seeking to keys not beginning with the prefix
+// is invalid, and SeekToLast is not implemented (that would be
+// non-trivial), but otherwise this iterator will behave just like the
+// underlying iterator would if there happened to be no non-matching
+// keys in the dataset.
+
+#pragma once
+#include "rocksdb/iterator.h"
+
+namespace rocksdb {
+
+class PrefixFilterIterator : public Iterator {
+ private:
+  Iterator* iter_;
+  const Slice &prefix_;
+  const SliceTransform *prefix_extractor_;
+  Status status_;
+
+ public:
+  PrefixFilterIterator(Iterator* iter,
+                       const Slice &prefix,
+                       const SliceTransform* prefix_extractor)
+                             : iter_(iter), prefix_(prefix),
+                               prefix_extractor_(prefix_extractor),
+                               status_(Status::OK()) {
+    if (prefix_extractor == nullptr) {
+      status_ = Status::InvalidArgument("A prefix filter may not be used "
+                                        "unless a function is also defined "
+                                        "for extracting prefixes");
+    } else if (!prefix_extractor_->InRange(prefix)) {
+      status_ = Status::InvalidArgument("Must provide a slice for prefix which"
+                                        "is a prefix for some key");
+    }
+  }
+  ~PrefixFilterIterator() {
+    delete iter_;
+  }
+  Slice key() const { return iter_->key(); }
+  Slice value() const { return iter_->value(); }
+  Status status() const {
+    if (!status_.ok()) {
+      return status_;
+    }
+    return iter_->status();
+  }
+  void Next() { iter_->Next(); }
+  void Prev() { iter_->Prev(); }
+  void Seek(const Slice& k) {
+    if (prefix_extractor_->Transform(k) == prefix_) {
+      iter_->Seek(k);
+    } else {
+      status_ = Status::InvalidArgument("Seek must begin with target prefix");
+    }
+  }
+  void SeekToFirst() {
+    Seek(prefix_);
+  }
+  void SeekToLast() {
+    status_ = Status::NotSupported("SeekToLast is incompatible with prefixes");
+  }
+  bool Valid() const {
+    return (status_.ok() && iter_->Valid() &&
+            prefix_extractor_->Transform(iter_->key()) == prefix_);
+  }
+};
+
+}  // namespace rocksdb
diff --git a/db/prefix_test.cc b/db/prefix_test.cc
new file mode 100644 (file)
index 0000000..7101661
--- /dev/null
@@ -0,0 +1,319 @@
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <gflags/gflags.h>
+#include "rocksdb/comparator.h"
+#include "rocksdb/db.h"
+#include "rocksdb/perf_context.h"
+#include "util/histogram.h"
+#include "util/stop_watch.h"
+#include "util/testharness.h"
+
+DEFINE_bool(use_prefix_hash_memtable, true, "");
+DEFINE_bool(use_nolock_version, true, "");
+DEFINE_bool(trigger_deadlock, false,
+            "issue delete in range scan to trigger PrefixHashMap deadlock");
+DEFINE_uint64(bucket_count, 100000, "number of buckets");
+DEFINE_uint64(num_locks, 10001, "number of locks");
+DEFINE_bool(random_prefix, false, "randomize prefix");
+DEFINE_uint64(total_prefixes, 1000, "total number of prefixes");
+DEFINE_uint64(items_per_prefix, 10, "total number of values per prefix");
+DEFINE_int64(write_buffer_size, 1000000000, "");
+DEFINE_int64(max_write_buffer_number, 8, "");
+DEFINE_int64(min_write_buffer_number_to_merge, 7, "");
+
+// Path to the database on file system
+const std::string kDbName = rocksdb::test::TmpDir() + "/prefix_test";
+
+namespace rocksdb {
+
+struct TestKey {
+  uint64_t prefix;
+  uint64_t sorted;
+
+  TestKey(uint64_t prefix, uint64_t sorted) : prefix(prefix), sorted(sorted) {}
+};
+
+// return a slice backed by test_key
+inline Slice TestKeyToSlice(const TestKey& test_key) {
+  return Slice((const char*)&test_key, sizeof(test_key));
+}
+
+inline const TestKey* SliceToTestKey(const Slice& slice) {
+  assert(slice.size() == sizeof(TestKey));
+  return (const TestKey*)slice.data();
+}
+
+class TestKeyComparator : public Comparator {
+ public:
+  virtual int Compare(const Slice& a, const Slice& b) const {
+    const TestKey* key_a = SliceToTestKey(a);
+    const TestKey* key_b = SliceToTestKey(b);
+    if (key_a->prefix != key_b->prefix) {
+      if (key_a->prefix < key_b->prefix) return -1;
+      if (key_a->prefix > key_b->prefix) return 1;
+      assert(false);
+    } else {
+      if (key_a->sorted < key_b->sorted) return -1;
+      if (key_a->sorted > key_b->sorted) return 1;
+      if (key_a->sorted == key_b->sorted) return 0;
+      assert(false);
+    }
+    assert(false);
+    return 0;
+  }
+
+  virtual const char* Name() const override {
+    return "TestKeyComparator";
+  }
+
+  virtual void FindShortestSeparator(
+      std::string* start,
+      const Slice& limit) const {
+  }
+
+  virtual void FindShortSuccessor(std::string* key) const {}
+
+};
+
+class PrefixTest {
+ public:
+  std::shared_ptr<DB> OpenDb() {
+    DB* db;
+
+    options.create_if_missing = true;
+    options.write_buffer_size = FLAGS_write_buffer_size;
+    options.max_write_buffer_number = FLAGS_max_write_buffer_number;
+    options.min_write_buffer_number_to_merge =
+      FLAGS_min_write_buffer_number_to_merge;
+
+    options.comparator = new TestKeyComparator();
+    if (FLAGS_use_prefix_hash_memtable) {
+      auto prefix_extractor = NewFixedPrefixTransform(8);
+      options.prefix_extractor = prefix_extractor;
+      if (FLAGS_use_nolock_version) {
+        options.memtable_factory.reset(NewHashSkipListRepFactory(
+            prefix_extractor, FLAGS_bucket_count));
+      } else {
+        options.memtable_factory =
+          std::make_shared<rocksdb::PrefixHashRepFactory>(
+            prefix_extractor, FLAGS_bucket_count, FLAGS_num_locks);
+      }
+    }
+
+    Status s = DB::Open(options, kDbName,  &db);
+    ASSERT_OK(s);
+    return std::shared_ptr<DB>(db);
+  }
+  ~PrefixTest() {
+    delete options.comparator;
+  }
+ protected:
+  Options options;
+};
+
+TEST(PrefixTest, DynamicPrefixIterator) {
+
+  DestroyDB(kDbName, Options());
+  auto db = OpenDb();
+  WriteOptions write_options;
+  ReadOptions read_options;
+
+  std::vector<uint64_t> prefixes;
+  for (uint64_t i = 0; i < FLAGS_total_prefixes; ++i) {
+    prefixes.push_back(i);
+  }
+
+  if (FLAGS_random_prefix) {
+    std::random_shuffle(prefixes.begin(), prefixes.end());
+  }
+
+  // insert x random prefix, each with y continuous element.
+  for (auto prefix : prefixes) {
+     for (uint64_t sorted = 0; sorted < FLAGS_items_per_prefix; sorted++) {
+      TestKey test_key(prefix, sorted);
+
+      Slice key = TestKeyToSlice(test_key);
+      std::string value = "v" + std::to_string(sorted);
+
+      ASSERT_OK(db->Put(write_options, key, value));
+    }
+  }
+
+  // test seek existing keys
+  HistogramImpl hist_seek_time;
+  HistogramImpl hist_seek_comparison;
+
+  if (FLAGS_use_prefix_hash_memtable) {
+    read_options.prefix_seek = true;
+  }
+  std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
+
+  for (auto prefix : prefixes) {
+    TestKey test_key(prefix, FLAGS_items_per_prefix / 2);
+    Slice key = TestKeyToSlice(test_key);
+    std::string value = "v" + std::to_string(0);
+
+    perf_context.Reset();
+    StopWatchNano timer(Env::Default(), true);
+    uint64_t total_keys = 0;
+    for (iter->Seek(key); iter->Valid(); iter->Next()) {
+      if (FLAGS_trigger_deadlock) {
+        std::cout << "Behold the deadlock!\n";
+        db->Delete(write_options, iter->key());
+      }
+      auto test_key = SliceToTestKey(iter->key());
+      if (test_key->prefix != prefix) break;
+      total_keys++;
+    }
+    hist_seek_time.Add(timer.ElapsedNanos());
+    hist_seek_comparison.Add(perf_context.user_key_comparison_count);
+    ASSERT_EQ(total_keys, FLAGS_items_per_prefix - FLAGS_items_per_prefix/2);
+  }
+
+  std::cout << "Seek key comparison: \n"
+            << hist_seek_comparison.ToString()
+            << "Seek time: \n"
+            << hist_seek_time.ToString();
+
+  // test non-existing keys
+  HistogramImpl hist_no_seek_time;
+  HistogramImpl hist_no_seek_comparison;
+
+  for (auto prefix = FLAGS_total_prefixes;
+       prefix < FLAGS_total_prefixes + 100;
+       prefix++) {
+    TestKey test_key(prefix, 0);
+    Slice key = TestKeyToSlice(test_key);
+
+    perf_context.Reset();
+    StopWatchNano timer(Env::Default(), true);
+    iter->Seek(key);
+    hist_no_seek_time.Add(timer.ElapsedNanos());
+    hist_no_seek_comparison.Add(perf_context.user_key_comparison_count);
+    ASSERT_TRUE(!iter->Valid());
+  }
+
+  std::cout << "non-existing Seek key comparison: \n"
+            << hist_no_seek_comparison.ToString()
+            << "non-existing Seek time: \n"
+            << hist_no_seek_time.ToString();
+}
+
+TEST(PrefixTest, PrefixHash) {
+
+  DestroyDB(kDbName, Options());
+  auto db = OpenDb();
+  WriteOptions write_options;
+  ReadOptions read_options;
+
+  std::vector<uint64_t> prefixes;
+  for (uint64_t i = 0; i < FLAGS_total_prefixes; ++i) {
+    prefixes.push_back(i);
+  }
+
+  if (FLAGS_random_prefix) {
+    std::random_shuffle(prefixes.begin(), prefixes.end());
+  }
+
+  // insert x random prefix, each with y continuous element.
+  HistogramImpl hist_put_time;
+  HistogramImpl hist_put_comparison;
+
+  for (auto prefix : prefixes) {
+     for (uint64_t sorted = 0; sorted < FLAGS_items_per_prefix; sorted++) {
+      TestKey test_key(prefix, sorted);
+
+      Slice key = TestKeyToSlice(test_key);
+      std::string value = "v" + std::to_string(sorted);
+
+      perf_context.Reset();
+      StopWatchNano timer(Env::Default(), true);
+      ASSERT_OK(db->Put(write_options, key, value));
+      hist_put_time.Add(timer.ElapsedNanos());
+      hist_put_comparison.Add(perf_context.user_key_comparison_count);
+    }
+  }
+
+  std::cout << "Put key comparison: \n" << hist_put_comparison.ToString()
+            << "Put time: \n" << hist_put_time.ToString();
+
+
+  // test seek existing keys
+  HistogramImpl hist_seek_time;
+  HistogramImpl hist_seek_comparison;
+
+  for (auto prefix : prefixes) {
+    TestKey test_key(prefix, 0);
+    Slice key = TestKeyToSlice(test_key);
+    std::string value = "v" + std::to_string(0);
+
+    Slice key_prefix;
+    if (FLAGS_use_prefix_hash_memtable) {
+      key_prefix = options.prefix_extractor->Transform(key);
+      read_options.prefix = &key_prefix;
+    }
+    std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
+
+    perf_context.Reset();
+    StopWatchNano timer(Env::Default(), true);
+    uint64_t total_keys = 0;
+    for (iter->Seek(key); iter->Valid(); iter->Next()) {
+      if (FLAGS_trigger_deadlock) {
+        std::cout << "Behold the deadlock!\n";
+        db->Delete(write_options, iter->key());
+      }
+      auto test_key = SliceToTestKey(iter->key());
+      if (test_key->prefix != prefix) break;
+      total_keys++;
+    }
+    hist_seek_time.Add(timer.ElapsedNanos());
+    hist_seek_comparison.Add(perf_context.user_key_comparison_count);
+    ASSERT_EQ(total_keys, FLAGS_items_per_prefix);
+  }
+
+  std::cout << "Seek key comparison: \n"
+            << hist_seek_comparison.ToString()
+            << "Seek time: \n"
+            << hist_seek_time.ToString();
+
+  // test non-existing keys
+  HistogramImpl hist_no_seek_time;
+  HistogramImpl hist_no_seek_comparison;
+
+  for (auto prefix = FLAGS_total_prefixes;
+       prefix < FLAGS_total_prefixes + 100;
+       prefix++) {
+    TestKey test_key(prefix, 0);
+    Slice key = TestKeyToSlice(test_key);
+
+    if (FLAGS_use_prefix_hash_memtable) {
+      Slice key_prefix = options.prefix_extractor->Transform(key);
+      read_options.prefix = &key_prefix;
+    }
+    std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
+
+    perf_context.Reset();
+    StopWatchNano timer(Env::Default(), true);
+    iter->Seek(key);
+    hist_no_seek_time.Add(timer.ElapsedNanos());
+    hist_no_seek_comparison.Add(perf_context.user_key_comparison_count);
+    ASSERT_TRUE(!iter->Valid());
+  }
+
+  std::cout << "non-existing Seek key comparison: \n"
+            << hist_no_seek_comparison.ToString()
+            << "non-existing Seek time: \n"
+            << hist_no_seek_time.ToString();
+}
+
+}
+
+int main(int argc, char** argv) {
+  google::ParseCommandLineFlags(&argc, &argv, true);
+  std::cout << kDbName << "\n";
+
+  rocksdb::test::RunAllTests();
+  return 0;
+}
diff --git a/db/repair.cc b/db/repair.cc
new file mode 100644 (file)
index 0000000..66aa95a
--- /dev/null
@@ -0,0 +1,390 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/comparator.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+
+namespace rocksdb {
+
+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_, storage_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 rocksdb %s; "
+          "recovered %d files; %llu bytes. "
+          "Some data may have been lost. "
+          "****",
+          dbname_.c_str(),
+          static_cast<int>(tables_.size()),
+          bytes);
+    }
+    return status;
+  }
+
+ private:
+  struct TableInfo {
+    FileMetaData meta;
+    SequenceNumber min_sequence;
+    SequenceNumber max_sequence;
+  };
+
+  std::string const dbname_;
+  Env* const env_;
+  InternalKeyComparator const icmp_;
+  InternalFilterPolicy const ipolicy_;
+  Options const options_;
+  TableCache* table_cache_;
+  VersionEdit* edit_;
+
+  std::vector<std::string> manifests_;
+  std::vector<uint64_t> table_numbers_;
+  std::vector<uint64_t> logs_;
+  std::vector<TableInfo> tables_;
+  uint64_t next_file_number_;
+  const EnvOptions storage_options_;
+
+  Status FindFiles() {
+    std::vector<std::string> 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<Logger> 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<int>(bytes),
+            s.ToString().c_str());
+      }
+    };
+
+    // Open the log file
+    std::string logname = LogFileName(dbname_, log);
+    unique_ptr<SequentialFile> lfile;
+    Status status = env_->NewSequentialFile(logname, &lfile, storage_options_);
+    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_.memtable_factory,
+      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, &options_);
+      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_, storage_options_,
+                        table_cache_, iter, &meta,
+                        icmp_.user_comparator(), 0, 0, true);
+    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<TableInfo> 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(), storage_options_, t->meta.number, t->meta.file_size);
+      bool empty = true;
+      ParsedInternalKey parsed;
+      t->min_sequence = 0;
+      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->min_sequence) {
+          t->min_sequence = parsed.sequence;
+        }
+        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<WritableFile> file;
+    Status status = env_->NewWritableFile(tmp, &file, storage_options_);
+    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,
+                    t.min_sequence, t.max_sequence);
+    }
+
+    //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 rocksdb
diff --git a/db/simple_table_db_test.cc b/db/simple_table_db_test.cc
new file mode 100644 (file)
index 0000000..f705646
--- /dev/null
@@ -0,0 +1,793 @@
+// 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.
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <algorithm>
+#include <set>
+
+#include "rocksdb/db.h"
+#include "rocksdb/filter_policy.h"
+#include "db/db_impl.h"
+#include "db/filename.h"
+#include "db/version_set.h"
+#include "db/write_batch_internal.h"
+#include "db/db_statistics.h"
+#include "rocksdb/cache.h"
+#include "rocksdb/compaction_filter.h"
+#include "rocksdb/env.h"
+#include "rocksdb/table.h"
+#include "util/hash.h"
+#include "util/logging.h"
+#include "util/mutexlock.h"
+#include "util/testharness.h"
+#include "util/testutil.h"
+#include "utilities/merge_operators.h"
+
+using std::unique_ptr;
+
+namespace rocksdb {
+
+// SimpleTable is a simple table format for UNIT TEST ONLY. It is not built
+// as production quality.
+// SimpleTable requires the input key size to be fixed 16 bytes, value cannot
+// be longer than 150000 bytes and stored data on disk in this format:
+// +--------------------------------------------+  <= key1 offset
+// | key1            | value_size (4 bytes) |   |
+// +----------------------------------------+   |
+// | value1                                     |
+// |                                            |
+// +----------------------------------------+---+  <= key2 offset
+// | key2            | value_size (4 bytes) |   |
+// +----------------------------------------+   |
+// | value2                                     |
+// |                                            |
+// |        ......                              |
+// +-----------------+--------------------------+   <= index_block_offset
+// | key1            | key1 offset (8 bytes)    |
+// +-----------------+--------------------------+
+// | key2            | key2 offset (8 bytes)    |
+// +-----------------+--------------------------+
+// | key3            | key3 offset (8 bytes)    |
+// +-----------------+--------------------------+
+// |        ......                              |
+// +-----------------+------------+-------------+
+// | index_block_offset (8 bytes) |
+// +------------------------------+
+
+// SimpleTable is a simple table format for UNIT TEST ONLY. It is not built
+// as production quality.
+class SimpleTableReader: public TableReader {
+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, const EnvOptions& soptions,
+                     unique_ptr<RandomAccessFile> && file, uint64_t file_size,
+                     unique_ptr<TableReader>* table_reader);
+
+  bool PrefixMayMatch(const Slice& internal_prefix) override;
+
+  Iterator* NewIterator(const ReadOptions&) override;
+
+  Status Get(
+      const ReadOptions&, const Slice& key, void* arg,
+      bool (*handle_result)(void* arg, const Slice& k, const Slice& v, bool),
+      void (*mark_key_may_exist)(void*) = nullptr) override;
+
+  uint64_t ApproximateOffsetOf(const Slice& key) override;
+
+  bool TEST_KeyInCache(const ReadOptions& options, const Slice& key) override;
+
+  void SetupForCompaction() override;
+
+  TableStats& GetTableStats() override;
+
+  ~SimpleTableReader();
+
+private:
+  struct Rep;
+  Rep* rep_;
+
+  explicit SimpleTableReader(Rep* rep) {
+    rep_ = rep;
+  }
+  friend class TableCache;
+  friend class SimpleTableIterator;
+
+  Status GetOffset(const Slice& target, uint64_t* offset);
+
+  // No copying allowed
+  explicit SimpleTableReader(const TableReader&) = delete;
+  void operator=(const TableReader&) = delete;
+};
+
+// Iterator to iterate SimpleTable
+class SimpleTableIterator: public Iterator {
+public:
+  explicit SimpleTableIterator(SimpleTableReader* table);
+  ~SimpleTableIterator();
+
+  bool Valid() const;
+
+  void SeekToFirst();
+
+  void SeekToLast();
+
+  void Seek(const Slice& target);
+
+  void Next();
+
+  void Prev();
+
+  Slice key() const;
+
+  Slice value() const;
+
+  Status status() const;
+
+private:
+  SimpleTableReader* table_;
+  uint64_t offset_;
+  uint64_t next_offset_;
+  Slice key_;
+  Slice value_;
+  char tmp_str_[4];
+  char* key_str_;
+  char* value_str_;
+  int value_str_len_;
+  Status status_;
+  // No copying allowed
+  SimpleTableIterator(const SimpleTableIterator&) = delete;
+  void operator=(const Iterator&) = delete;
+};
+
+struct SimpleTableReader::Rep {
+  ~Rep() {
+  }
+  Rep(const EnvOptions& storage_options, uint64_t index_start_offset,
+      int num_entries) :
+      soptions(storage_options), index_start_offset(index_start_offset),
+      num_entries(num_entries) {
+  }
+
+  Options options;
+  const EnvOptions& soptions;
+  Status status;
+  unique_ptr<RandomAccessFile> file;
+  uint64_t index_start_offset;
+  int num_entries;
+  TableStats table_stats;
+
+  const static int user_key_size = 16;
+  const static int offset_length = 8;
+  const static int key_footer_len = 8;
+
+  static int GetInternalKeyLength() {
+    return user_key_size + key_footer_len;
+  }
+};
+
+SimpleTableReader::~SimpleTableReader() {
+  delete rep_;
+}
+
+Status SimpleTableReader::Open(const Options& options,
+                               const EnvOptions& soptions,
+                               unique_ptr<RandomAccessFile> && file,
+                               uint64_t size,
+                               unique_ptr<TableReader>* table_reader) {
+  char footer_space[Rep::offset_length];
+  Slice footer_input;
+  Status s = file->Read(size - Rep::offset_length, Rep::offset_length,
+                        &footer_input, footer_space);
+  if (s.ok()) {
+    uint64_t index_start_offset = DecodeFixed64(footer_space);
+
+    int num_entries = (size - Rep::offset_length - index_start_offset)
+        / (Rep::GetInternalKeyLength() + Rep::offset_length);
+    SimpleTableReader::Rep* rep = new SimpleTableReader::Rep(soptions,
+                                                             index_start_offset,
+                                                             num_entries);
+
+    rep->file = std::move(file);
+    rep->options = options;
+    table_reader->reset(new SimpleTableReader(rep));
+  }
+  return s;
+}
+
+void SimpleTableReader::SetupForCompaction() {
+}
+
+TableStats& SimpleTableReader::GetTableStats() {
+  return rep_->table_stats;
+}
+
+bool SimpleTableReader::PrefixMayMatch(const Slice& internal_prefix) {
+  return true;
+}
+
+Iterator* SimpleTableReader::NewIterator(const ReadOptions& options) {
+  return new SimpleTableIterator(this);
+}
+
+Status SimpleTableReader::GetOffset(const Slice& target, uint64_t* offset) {
+  uint32_t left = 0;
+  uint32_t right = rep_->num_entries - 1;
+  char key_chars[Rep::GetInternalKeyLength()];
+  Slice tmp_slice;
+
+  uint32_t target_offset = 0;
+  while (left <= right) {
+    uint32_t mid = (left + right + 1) / 2;
+
+    uint64_t offset_to_read = rep_->index_start_offset
+        + (Rep::GetInternalKeyLength() + Rep::offset_length) * mid;
+    Status s = rep_->file->Read(offset_to_read, Rep::GetInternalKeyLength(),
+                                &tmp_slice, key_chars);
+    if (!s.ok()) {
+      return s;
+    }
+
+    int compare_result = rep_->options.comparator->Compare(tmp_slice, target);
+
+    if (compare_result < 0) {
+      if (left == right) {
+        target_offset = right + 1;
+        break;
+      }
+      left = mid;
+    } else {
+      if (left == right) {
+        target_offset = left;
+        break;
+      }
+      right = mid - 1;
+    }
+  }
+
+  if (target_offset >= (uint32_t) rep_->num_entries) {
+    *offset = rep_->index_start_offset;
+    return Status::OK();
+  }
+
+  char value_offset_chars[Rep::offset_length];
+
+  int64_t offset_for_value_offset = rep_->index_start_offset
+      + (Rep::GetInternalKeyLength() + Rep::offset_length) * target_offset
+      + Rep::GetInternalKeyLength();
+  Status s = rep_->file->Read(offset_for_value_offset, Rep::offset_length,
+                              &tmp_slice, value_offset_chars);
+  if (s.ok()) {
+    *offset = DecodeFixed64(value_offset_chars);
+  }
+  return s;
+}
+
+Status SimpleTableReader::Get(
+    const ReadOptions& options, const Slice& k, void* arg,
+    bool (*saver)(void*, const Slice&, const Slice&, bool),
+    void (*mark_key_may_exist)(void*)) {
+  Status s;
+  SimpleTableIterator* iter = new SimpleTableIterator(this);
+  for (iter->Seek(k); iter->Valid(); iter->Next()) {
+    if (!(*saver)(arg, iter->key(), iter->value(), true)) {
+      break;
+    }
+  }
+  s = iter->status();
+  delete iter;
+  return s;
+}
+
+bool SimpleTableReader::TEST_KeyInCache(const ReadOptions& options,
+                                        const Slice& key) {
+  return false;
+}
+
+uint64_t SimpleTableReader::ApproximateOffsetOf(const Slice& key) {
+  return 0;
+}
+
+SimpleTableIterator::SimpleTableIterator(SimpleTableReader* table) :
+    table_(table) {
+  key_str_ = new char[SimpleTableReader::Rep::GetInternalKeyLength()];
+  value_str_len_ = -1;
+  SeekToFirst();
+}
+
+SimpleTableIterator::~SimpleTableIterator() {
+ delete[] key_str_;
+ if (value_str_len_ >= 0) {
+   delete[] value_str_;
+ }
+}
+
+bool SimpleTableIterator::Valid() const {
+  return offset_ < table_->rep_->index_start_offset;
+}
+
+void SimpleTableIterator::SeekToFirst() {
+  next_offset_ = 0;
+  Next();
+}
+
+void SimpleTableIterator::SeekToLast() {
+  assert(false);
+}
+
+void SimpleTableIterator::Seek(const Slice& target) {
+  Status s = table_->GetOffset(target, &next_offset_);
+  if (!s.ok()) {
+    status_ = s;
+  }
+  Next();
+}
+
+void SimpleTableIterator::Next() {
+  offset_ = next_offset_;
+  if (offset_ >= table_->rep_->index_start_offset) {
+    return;
+  }
+  Slice result;
+  int internal_key_size = SimpleTableReader::Rep::GetInternalKeyLength();
+
+  Status s = table_->rep_->file->Read(next_offset_, internal_key_size, &result,
+                                      key_str_);
+  next_offset_ += internal_key_size;
+  key_ = result;
+
+  Slice value_size_slice;
+  s = table_->rep_->file->Read(next_offset_, 4, &value_size_slice, tmp_str_);
+  next_offset_ += 4;
+  uint32_t value_size = DecodeFixed32(tmp_str_);
+
+  Slice value_slice;
+  if ((int) value_size > value_str_len_) {
+    if (value_str_len_ >= 0) {
+      delete[] value_str_;
+    }
+    value_str_ = new char[value_size];
+    value_str_len_ = value_size;
+  }
+  s = table_->rep_->file->Read(next_offset_, value_size, &value_slice,
+                               value_str_);
+  next_offset_ += value_size;
+  value_ = value_slice;
+}
+
+void SimpleTableIterator::Prev() {
+  assert(false);
+}
+
+Slice SimpleTableIterator::key() const {
+  Log(table_->rep_->options.info_log, "key!!!!");
+  return key_;
+}
+
+Slice SimpleTableIterator::value() const {
+  return value_;
+}
+
+Status SimpleTableIterator::status() const {
+  return status_;
+}
+
+class SimpleTableBuilder: public 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.
+  SimpleTableBuilder(const Options& options, WritableFile* file,
+                     CompressionType compression_type);
+
+  // REQUIRES: Either Finish() or Abandon() has been called.
+  ~SimpleTableBuilder();
+
+  // 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) override;
+
+  // Return non-ok iff some error has been detected.
+  Status status() const override;
+
+  // 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() override;
+
+  // 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() override;
+
+  // Number of calls to Add() so far.
+  uint64_t NumEntries() const override;
+
+  // 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 override;
+
+private:
+  struct Rep;
+  Rep* rep_;
+
+  // No copying allowed
+  SimpleTableBuilder(const SimpleTableBuilder&) = delete;
+  void operator=(const SimpleTableBuilder&) = delete;
+};
+
+struct SimpleTableBuilder::Rep {
+  Options options;
+  WritableFile* file;
+  uint64_t offset = 0;
+  Status status;
+
+  uint64_t num_entries = 0;
+
+  bool closed = false;  // Either Finish() or Abandon() has been called.
+
+  const static int user_key_size = 16;
+  const static int offset_length = 8;
+  const static int key_footer_len = 8;
+
+  static int GetInternalKeyLength() {
+    return user_key_size + key_footer_len;
+  }
+
+  std::string index;
+
+  Rep(const Options& opt, WritableFile* f) :
+      options(opt), file(f) {
+  }
+  ~Rep() {
+  }
+};
+
+SimpleTableBuilder::SimpleTableBuilder(const Options& options,
+                                       WritableFile* file,
+                                       CompressionType compression_type) :
+    rep_(new SimpleTableBuilder::Rep(options, file)) {
+}
+
+SimpleTableBuilder::~SimpleTableBuilder() {
+  delete (rep_);
+}
+
+void SimpleTableBuilder::Add(const Slice& key, const Slice& value) {
+  assert((int ) key.size() == Rep::GetInternalKeyLength());
+
+  // Update index
+  rep_->index.append(key.data(), key.size());
+  PutFixed64(&(rep_->index), rep_->offset);
+
+  // Write key-value pair
+  rep_->file->Append(key);
+  rep_->offset += Rep::GetInternalKeyLength();
+
+  std::string size;
+  int value_size = value.size();
+  PutFixed32(&size, value_size);
+  Slice sizeSlice(size);
+  rep_->file->Append(sizeSlice);
+  rep_->file->Append(value);
+  rep_->offset += value_size + 4;
+
+  rep_->num_entries++;
+}
+
+Status SimpleTableBuilder::status() const {
+  return Status::OK();
+}
+
+Status SimpleTableBuilder::Finish() {
+  Rep* r = rep_;
+  assert(!r->closed);
+  r->closed = true;
+
+  uint64_t index_offset = rep_->offset;
+  Slice index_slice(rep_->index);
+  rep_->file->Append(index_slice);
+  rep_->offset += index_slice.size();
+
+  std::string index_offset_str;
+  PutFixed64(&index_offset_str, index_offset);
+  Slice foot_slice(index_offset_str);
+  rep_->file->Append(foot_slice);
+  rep_->offset += foot_slice.size();
+
+  return Status::OK();
+}
+
+void SimpleTableBuilder::Abandon() {
+  rep_->closed = true;
+}
+
+uint64_t SimpleTableBuilder::NumEntries() const {
+  return rep_->num_entries;
+}
+
+uint64_t SimpleTableBuilder::FileSize() const {
+  return rep_->offset;
+}
+
+class SimpleTableFactory: public TableFactory {
+public:
+  ~SimpleTableFactory() {
+  }
+  SimpleTableFactory() {
+  }
+  const char* Name() const override {
+    return "SimpleTable";
+  }
+  Status GetTableReader(const Options& options, const EnvOptions& soptions,
+                        unique_ptr<RandomAccessFile> && file,
+                        uint64_t file_size,
+                        unique_ptr<TableReader>* table_reader) const;
+
+  TableBuilder* GetTableBuilder(const Options& options, WritableFile* file,
+                                CompressionType compression_type) const;
+};
+
+Status SimpleTableFactory::GetTableReader(
+    const Options& options, const EnvOptions& soptions,
+    unique_ptr<RandomAccessFile> && file, uint64_t file_size,
+    unique_ptr<TableReader>* table_reader) const {
+
+  return SimpleTableReader::Open(options, soptions, std::move(file), file_size,
+                                 table_reader);
+}
+
+TableBuilder* SimpleTableFactory::GetTableBuilder(
+    const Options& options, WritableFile* file,
+    CompressionType compression_type) const {
+  return new SimpleTableBuilder(options, file, compression_type);
+}
+
+class SimpleTableDBTest {
+protected:
+public:
+  std::string dbname_;
+  Env* env_;
+  DB* db_;
+
+  Options last_options_;
+
+  SimpleTableDBTest() :
+      env_(Env::Default()) {
+    dbname_ = test::TmpDir() + "/simple_table_db_test";
+    ASSERT_OK(DestroyDB(dbname_, Options()));
+    db_ = nullptr;
+    Reopen();
+  }
+
+  ~SimpleTableDBTest() {
+    delete db_;
+    ASSERT_OK(DestroyDB(dbname_, Options()));
+  }
+
+  // Return the current option configuration.
+  Options CurrentOptions() {
+    Options options;
+    options.table_factory.reset(new SimpleTableFactory());
+    return options;
+  }
+
+  DBImpl* dbfull() {
+    return reinterpret_cast<DBImpl*>(db_);
+  }
+
+  void Reopen(Options* options = nullptr) {
+    ASSERT_OK(TryReopen(options));
+  }
+
+  void Close() {
+    delete db_;
+    db_ = nullptr;
+  }
+
+  void DestroyAndReopen(Options* options = nullptr) {
+    //Destroy using last options
+    Destroy(&last_options_);
+    ASSERT_OK(TryReopen(options));
+  }
+
+  void Destroy(Options* options) {
+    delete db_;
+    db_ = nullptr;
+    ASSERT_OK(DestroyDB(dbname_, *options));
+  }
+
+  Status PureReopen(Options* options, DB** db) {
+    return DB::Open(*options, dbname_, db);
+  }
+
+  Status TryReopen(Options* options = nullptr) {
+    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 Slice& k, const Slice& 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;
+  }
+
+
+  int NumTableFilesAtLevel(int level) {
+    std::string property;
+    ASSERT_TRUE(
+        db_->GetProperty("rocksdb.num-files-at-level" + NumberToString(level),
+                         &property));
+    return atoi(property.c_str());
+  }
+
+  // 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;
+  }
+
+  std::string IterStatus(Iterator* iter) {
+    std::string result;
+    if (iter->Valid()) {
+      result = iter->key().ToString() + "->" + iter->value().ToString();
+    } else {
+      result = "(invalid)";
+    }
+    return result;
+  }
+};
+
+TEST(SimpleTableDBTest, Empty) {
+  ASSERT_TRUE(db_ != nullptr);
+  ASSERT_EQ("NOT_FOUND", Get("0000000000000foo"));
+}
+
+TEST(SimpleTableDBTest, ReadWrite) {
+  ASSERT_OK(Put("0000000000000foo", "v1"));
+  ASSERT_EQ("v1", Get("0000000000000foo"));
+  ASSERT_OK(Put("0000000000000bar", "v2"));
+  ASSERT_OK(Put("0000000000000foo", "v3"));
+  ASSERT_EQ("v3", Get("0000000000000foo"));
+  ASSERT_EQ("v2", Get("0000000000000bar"));
+}
+
+TEST(SimpleTableDBTest, Flush) {
+  ASSERT_OK(Put("0000000000000foo", "v1"));
+  ASSERT_OK(Put("0000000000000bar", "v2"));
+  ASSERT_OK(Put("0000000000000foo", "v3"));
+  dbfull()->TEST_FlushMemTable();
+  ASSERT_EQ("v3", Get("0000000000000foo"));
+  ASSERT_EQ("v2", Get("0000000000000bar"));
+}
+
+TEST(SimpleTableDBTest, Flush2) {
+  ASSERT_OK(Put("0000000000000bar", "b"));
+  ASSERT_OK(Put("0000000000000foo", "v1"));
+  dbfull()->TEST_FlushMemTable();
+
+  ASSERT_OK(Put("0000000000000foo", "v2"));
+  dbfull()->TEST_FlushMemTable();
+  ASSERT_EQ("v2", Get("0000000000000foo"));
+
+  ASSERT_OK(Put("0000000000000eee", "v3"));
+  dbfull()->TEST_FlushMemTable();
+  ASSERT_EQ("v3", Get("0000000000000eee"));
+
+  ASSERT_OK(Delete("0000000000000bar"));
+  dbfull()->TEST_FlushMemTable();
+  ASSERT_EQ("NOT_FOUND", Get("0000000000000bar"));
+
+  ASSERT_OK(Put("0000000000000eee", "v5"));
+  dbfull()->TEST_FlushMemTable();
+  ASSERT_EQ("v5", Get("0000000000000eee"));
+}
+
+static std::string Key(int i) {
+  char buf[100];
+  snprintf(buf, sizeof(buf), "key_______%06d", i);
+  return std::string(buf);
+}
+
+static std::string RandomString(Random* rnd, int len) {
+  std::string r;
+  test::RandomString(rnd, len, &r);
+  return r;
+}
+
+TEST(SimpleTableDBTest, 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<std::string> 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_WaitForFlushMemTable();
+    ASSERT_EQ(NumTableFilesAtLevel(0), num + 1);
+  }
+
+  //generate one more file in level-0, and should trigger level-0 compaction
+  std::vector<std::string> 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);
+}
+
+}  // namespace rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/db/skiplist.h b/db/skiplist.h
new file mode 100644 (file)
index 0000000..06a35d9
--- /dev/null
@@ -0,0 +1,416 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 ...
+//
+
+#pragma once
+#include <assert.h>
+#include <stdlib.h>
+#include "port/port.h"
+#include "util/random.h"
+
+namespace rocksdb {
+
+template<typename Key, class Comparator>
+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);
+
+    // Change the underlying skiplist used for this iterator
+    // This enables us not changing the iterator without deallocating
+    // an old one and then allocating a new one
+    void SetList(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];
+  int   prev_height_;
+
+  inline int GetMaxHeight() const {
+    return static_cast<int>(
+        reinterpret_cast<intptr_t>(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<typename Key, class Comparator>
+struct SkipList<Key,Comparator>::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<Node*>(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<Node*>(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 Key, class Comparator>
+typename SkipList<Key,Comparator>::Node*
+SkipList<Key,Comparator>::NewNode(const Key& key, int height) {
+  char* mem = arena_->AllocateAligned(
+      sizeof(Node) + sizeof(port::AtomicPointer) * (height - 1));
+  return new (mem) Node(key);
+}
+
+template<typename Key, class Comparator>
+inline SkipList<Key,Comparator>::Iterator::Iterator(const SkipList* list) {
+  SetList(list);
+}
+
+template<typename Key, class Comparator>
+inline void SkipList<Key,Comparator>::Iterator::SetList(const SkipList* list) {
+  list_ = list;
+  node_ = nullptr;
+}
+
+template<typename Key, class Comparator>
+inline bool SkipList<Key,Comparator>::Iterator::Valid() const {
+  return node_ != nullptr;
+}
+
+template<typename Key, class Comparator>
+inline const Key& SkipList<Key,Comparator>::Iterator::key() const {
+  assert(Valid());
+  return node_->key;
+}
+
+template<typename Key, class Comparator>
+inline void SkipList<Key,Comparator>::Iterator::Next() {
+  assert(Valid());
+  node_ = node_->Next(0);
+}
+
+template<typename Key, class Comparator>
+inline void SkipList<Key,Comparator>::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<typename Key, class Comparator>
+inline void SkipList<Key,Comparator>::Iterator::Seek(const Key& target) {
+  node_ = list_->FindGreaterOrEqual(target, nullptr);
+}
+
+template<typename Key, class Comparator>
+inline void SkipList<Key,Comparator>::Iterator::SeekToFirst() {
+  node_ = list_->head_->Next(0);
+}
+
+template<typename Key, class Comparator>
+inline void SkipList<Key,Comparator>::Iterator::SeekToLast() {
+  node_ = list_->FindLast();
+  if (node_ == list_->head_) {
+    node_ = nullptr;
+  }
+}
+
+template<typename Key, class Comparator>
+int SkipList<Key,Comparator>::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<typename Key, class Comparator>
+bool SkipList<Key,Comparator>::KeyIsAfterNode(const Key& key, Node* n) const {
+  // nullptr n is considered infinite
+  return (n != nullptr) && (compare_(n->key, key) < 0);
+}
+
+template<typename Key, class Comparator>
+typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::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)) {
+      // Adjust all relevant insertion points to the previous entry
+      for (int i = 1; i < prev_height_; i++) {
+        prev[i] = x;
+      }
+      return next;
+    }
+  }
+  // Normal lookup
+  Node* x = head_;
+  int level = GetMaxHeight() - 1;
+  while (true) {
+    Node* next = x->Next(level);
+    // Make sure the lists are sorted.
+    // If x points to head_ or next points nullptr, it is trivially satisfied.
+    assert((x == head_) || (next == nullptr) || KeyIsAfterNode(next->key, x));
+    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 Key, class Comparator>
+typename SkipList<Key,Comparator>::Node*
+SkipList<Key,Comparator>::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 Key, class Comparator>
+typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::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<typename Key, class Comparator>
+SkipList<Key,Comparator>::SkipList(Comparator cmp, Arena* arena)
+    : compare_(cmp),
+      arena_(arena),
+      head_(NewNode(0 /* any key will do */, kMaxHeight)),
+      max_height_(reinterpret_cast<void*>(1)),
+      prev_height_(1),
+      rnd_(0xdeadbeef) {
+  for (int i = 0; i < kMaxHeight; i++) {
+    head_->SetNext(i, nullptr);
+    prev_[i] = head_;
+  }
+}
+
+template<typename Key, class Comparator>
+void SkipList<Key,Comparator>::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<void*>(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;
+  prev_height_ = height;
+}
+
+template<typename Key, class Comparator>
+bool SkipList<Key,Comparator>::Contains(const Key& key) const {
+  Node* x = FindGreaterOrEqual(key, nullptr);
+  if (x != nullptr && Equal(key, x->key)) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+}  // namespace rocksdb
diff --git a/db/skiplist_test.cc b/db/skiplist_test.cc
new file mode 100644 (file)
index 0000000..dcbaf0a
--- /dev/null
@@ -0,0 +1,383 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <set>
+#include "rocksdb/env.h"
+#include "util/arena_impl.h"
+#include "util/hash.h"
+#include "util/random.h"
+#include "util/testharness.h"
+
+namespace rocksdb {
+
+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) {
+  ArenaImpl arena_impl;
+  TestComparator cmp;
+  SkipList<Key, TestComparator> list(cmp, &arena_impl);
+  ASSERT_TRUE(!list.Contains(10));
+
+  SkipList<Key, TestComparator>::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<Key> keys;
+  ArenaImpl arena_impl;
+  TestComparator cmp;
+  SkipList<Key, TestComparator> list(cmp, &arena_impl);
+  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<Key, TestComparator>::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<Key, TestComparator>::Iterator iter(&list);
+    iter.Seek(i);
+
+    // Compare against model iterator
+    std::set<Key>::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<Key, TestComparator>::Iterator iter(&list);
+    iter.SeekToLast();
+
+    // Compare against model iterator
+    for (std::set<Key>::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:
+//     <key,gen,hash>
+// 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<char*>(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<void*>(v));
+    }
+    intptr_t Get(int k) {
+      return reinterpret_cast<intptr_t>(generation[k].Acquire_Load());
+    }
+
+    State() {
+      for (unsigned int k = 0; k < K; k++) {
+        Set(k, 0);
+      }
+    }
+  };
+
+  // Current state of the test
+  State current_;
+
+  ArenaImpl arena_impl_;
+
+  // SkipList is not protected by mu_.  We just use a single writer
+  // thread to modify it.
+  SkipList<Key, TestComparator> list_;
+
+ public:
+  ConcurrentTest() : list_(TestComparator(), &arena_impl_) { }
+
+  // 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<Key, TestComparator>::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<TestState*>(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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/db/snapshot.h b/db/snapshot.h
new file mode 100644 (file)
index 0000000..2c2e3ea
--- /dev/null
@@ -0,0 +1,86 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include "rocksdb/db.h"
+
+namespace rocksdb {
+
+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<SequenceNumber>& ret) {
+    if (empty()) return;
+    SnapshotImpl* s = &list_;
+    while (s->next_ != &list_) {
+      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 rocksdb
diff --git a/db/table_cache.cc b/db/table_cache.cc
new file mode 100644 (file)
index 0000000..a1f466b
--- /dev/null
@@ -0,0 +1,173 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/statistics.h"
+#include "rocksdb/table.h"
+#include "util/coding.h"
+#include "util/stop_watch.h"
+
+namespace rocksdb {
+
+static void DeleteEntry(const Slice& key, void* value) {
+  TableReader* table_reader = reinterpret_cast<TableReader*>(value);
+  delete table_reader;
+}
+
+static void UnrefEntry(void* arg1, void* arg2) {
+  Cache* cache = reinterpret_cast<Cache*>(arg1);
+  Cache::Handle* h = reinterpret_cast<Cache::Handle*>(arg2);
+  cache->Release(h);
+}
+
+TableCache::TableCache(const std::string& dbname,
+                       const Options* options,
+                       const EnvOptions& storage_options,
+                       int entries)
+    : env_(options->env),
+      dbname_(dbname),
+      options_(options),
+      storage_options_(storage_options),
+      cache_(
+        NewLRUCache(entries, options->table_cache_numshardbits,
+                    options->table_cache_remove_scan_count_limit)) {
+}
+
+TableCache::~TableCache() {
+}
+
+Status TableCache::FindTable(const EnvOptions& toptions,
+                             uint64_t file_number, uint64_t file_size,
+                             Cache::Handle** handle, bool* table_io,
+                             const bool no_io) {
+  Status s;
+  char buf[sizeof(file_number)];
+  EncodeFixed64(buf, file_number);
+  Slice key(buf, sizeof(buf));
+  *handle = cache_->Lookup(key);
+  if (*handle == nullptr) {
+    if (no_io) { // Dont do IO and return a not-found status
+      return Status::Incomplete("Table not found in table_cache, no_io is set");
+    }
+    if (table_io != nullptr) {
+      *table_io = true;    // we had to do IO from storage
+    }
+    std::string fname = TableFileName(dbname_, file_number);
+    unique_ptr<RandomAccessFile> file;
+    unique_ptr<TableReader> table_reader;
+    s = env_->NewRandomAccessFile(fname, &file, toptions);
+    RecordTick(options_->statistics, NO_FILE_OPENS);
+    if (s.ok()) {
+      if (options_->advise_random_on_open) {
+        file->Hint(RandomAccessFile::RANDOM);
+      }
+      StopWatch sw(env_, options_->statistics, TABLE_OPEN_IO_MICROS);
+      s = options_->table_factory->GetTableReader(*options_, toptions,
+                                                  std::move(file), file_size,
+                                                  &table_reader);
+    }
+
+    if (!s.ok()) {
+      assert(table_reader == 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 {
+      assert(file.get() == nullptr);
+      *handle = cache_->Insert(key, table_reader.release(), 1, &DeleteEntry);
+    }
+  }
+  return s;
+}
+
+Iterator* TableCache::NewIterator(const ReadOptions& options,
+                                  const EnvOptions& toptions,
+                                  uint64_t file_number,
+                                  uint64_t file_size,
+                                  TableReader** table_reader_ptr,
+                                  bool for_compaction) {
+  if (table_reader_ptr != nullptr) {
+    *table_reader_ptr = nullptr;
+  }
+
+  Cache::Handle* handle = nullptr;
+  Status s = FindTable(toptions, file_number, file_size, &handle,
+                       nullptr, options.read_tier == kBlockCacheTier);
+  if (!s.ok()) {
+    return NewErrorIterator(s);
+  }
+
+  TableReader* table_reader =
+    reinterpret_cast<TableReader*>(cache_->Value(handle));
+  Iterator* result = table_reader->NewIterator(options);
+  result->RegisterCleanup(&UnrefEntry, cache_.get(), handle);
+  if (table_reader_ptr != nullptr) {
+    *table_reader_ptr = table_reader;
+  }
+
+  if (for_compaction) {
+    table_reader->SetupForCompaction();
+  }
+
+  return result;
+}
+
+Status TableCache::Get(const ReadOptions& options,
+                       uint64_t file_number,
+                       uint64_t file_size,
+                       const Slice& k,
+                       void* arg,
+                       bool (*saver)(void*, const Slice&, const Slice&, bool),
+                       bool* table_io,
+                       void (*mark_key_may_exist)(void*)) {
+  Cache::Handle* handle = nullptr;
+  Status s = FindTable(storage_options_, file_number, file_size,
+                       &handle, table_io,
+                       options.read_tier == kBlockCacheTier);
+  if (s.ok()) {
+    TableReader* t =
+      reinterpret_cast<TableReader*>(cache_->Value(handle));
+    s = t->Get(options, k, arg, saver, mark_key_may_exist);
+    cache_->Release(handle);
+  } else if (options.read_tier && s.IsIncomplete()) {
+    // Couldnt find Table in cache but treat as kFound if no_io set
+    (*mark_key_may_exist)(arg);
+    return Status::OK();
+  }
+  return s;
+}
+
+bool TableCache::PrefixMayMatch(const ReadOptions& options,
+                                uint64_t file_number,
+                                uint64_t file_size,
+                                const Slice& internal_prefix,
+                                bool* table_io) {
+  Cache::Handle* handle = nullptr;
+  Status s = FindTable(storage_options_, file_number,
+                       file_size, &handle, table_io);
+  bool may_match = true;
+  if (s.ok()) {
+    TableReader* t =
+      reinterpret_cast<TableReader*>(cache_->Value(handle));
+    may_match = t->PrefixMayMatch(internal_prefix);
+    cache_->Release(handle);
+  }
+  return may_match;
+}
+
+void TableCache::Evict(uint64_t file_number) {
+  char buf[sizeof(file_number)];
+  EncodeFixed64(buf, file_number);
+  cache_->Erase(Slice(buf, sizeof(buf)));
+}
+
+}  // namespace rocksdb
diff --git a/db/table_cache.h b/db/table_cache.h
new file mode 100644 (file)
index 0000000..4b225af
--- /dev/null
@@ -0,0 +1,78 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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)
+
+#pragma once
+#include <string>
+#include <stdint.h>
+#include "db/dbformat.h"
+#include "rocksdb/env.h"
+#include "rocksdb/cache.h"
+#include "port/port.h"
+#include "rocksdb/table.h"
+
+namespace rocksdb {
+
+class Env;
+
+class TableCache {
+ public:
+  TableCache(const std::string& dbname, const Options* options,
+             const EnvOptions& storage_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,
+                        const EnvOptions& toptions,
+                        uint64_t file_number,
+                        uint64_t file_size,
+                        TableReader** table_reader_ptr = nullptr,
+                        bool for_compaction = false);
+
+  // If a seek to internal key "k" in specified file finds an entry,
+  // call (*handle_result)(arg, found_key, found_value) repeatedly until
+  // it returns false.
+  Status Get(const ReadOptions& options,
+             uint64_t file_number,
+             uint64_t file_size,
+             const Slice& k,
+             void* arg,
+             bool (*handle_result)(void*, const Slice&, const Slice&, bool),
+             bool* table_io,
+             void (*mark_key_may_exist)(void*) = nullptr);
+
+  // Determine whether the table may contain the specified prefix.  If
+  // the table index of blooms are not in memory, this may cause an I/O
+  bool PrefixMayMatch(const ReadOptions& options, uint64_t file_number,
+                      uint64_t file_size, const Slice& internal_prefix,
+                      bool* table_io);
+
+  // 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_;
+  const EnvOptions& storage_options_;
+  std::shared_ptr<Cache> cache_;
+
+  Status FindTable(const EnvOptions& toptions, uint64_t file_number,
+                   uint64_t file_size, Cache::Handle**, bool* table_io=nullptr,
+                   const bool no_io = false);
+};
+
+}  // namespace rocksdb
diff --git a/db/table_stats_collector.cc b/db/table_stats_collector.cc
new file mode 100644 (file)
index 0000000..91e89ce
--- /dev/null
@@ -0,0 +1,55 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+
+#include "db/table_stats_collector.h"
+
+#include "db/dbformat.h"
+#include "util/coding.h"
+
+namespace rocksdb {
+
+Status InternalKeyStatsCollector::Add(const Slice& key, const Slice& value) {
+  ParsedInternalKey ikey;
+  if (!ParseInternalKey(key, &ikey)) {
+    return Status::InvalidArgument("Invalid internal key");
+  }
+
+  if (ikey.type == ValueType::kTypeDeletion) {
+    ++deleted_keys_;
+  }
+
+  return Status::OK();
+}
+
+Status InternalKeyStatsCollector::Finish(
+    TableStats::UserCollectedStats* stats) {
+  assert(stats);
+  assert(stats->find(InternalKeyTableStatsNames::kDeletedKeys) == stats->end());
+  std::string val;
+
+  PutVarint64(&val, deleted_keys_);
+  stats->insert(std::make_pair(InternalKeyTableStatsNames::kDeletedKeys, val));
+
+  return Status::OK();
+}
+
+Status UserKeyTableStatsCollector::Add(const Slice& key, const Slice& value) {
+  ParsedInternalKey ikey;
+  if (!ParseInternalKey(key, &ikey)) {
+    return Status::InvalidArgument("Invalid internal key");
+  }
+
+  return collector_->Add(ikey.user_key, value);
+}
+
+Status UserKeyTableStatsCollector::Finish(
+    TableStats::UserCollectedStats* stats) {
+  return collector_->Finish(stats);
+}
+
+const std::string InternalKeyTableStatsNames::kDeletedKeys
+  = "rocksdb.deleted.keys";
+
+}  // namespace rocksdb
diff --git a/db/table_stats_collector.h b/db/table_stats_collector.h
new file mode 100644 (file)
index 0000000..e4e3685
--- /dev/null
@@ -0,0 +1,58 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// This file defines a collection of statistics collectors.
+#pragma once
+
+#include "rocksdb/table_stats.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace rocksdb {
+
+struct InternalKeyTableStatsNames {
+  static const std::string kDeletedKeys;
+};
+
+// Collecting the statistics for internal keys. Visible only by internal
+// rocksdb modules.
+class InternalKeyStatsCollector : public TableStatsCollector {
+ public:
+  virtual Status Add(const Slice& key, const Slice& value);
+  virtual Status Finish(TableStats::UserCollectedStats* stats);
+  virtual const char* Name() const { return "InternalKeyStatsCollector"; }
+
+ private:
+  uint64_t deleted_keys_ = 0;
+};
+
+// When rocksdb creates a new table, it will encode all "user keys" into
+// "internal keys", which contains meta information of a given entry.
+//
+// This class extracts user key from the encoded internal key when Add() is
+// invoked.
+class UserKeyTableStatsCollector : public TableStatsCollector {
+ public:
+  explicit UserKeyTableStatsCollector(TableStatsCollector* collector):
+    UserKeyTableStatsCollector(
+        std::shared_ptr<TableStatsCollector>(collector)
+    ) {
+  }
+
+  explicit UserKeyTableStatsCollector(
+      std::shared_ptr<TableStatsCollector> collector) : collector_(collector) {
+  }
+  virtual ~UserKeyTableStatsCollector() { }
+  virtual Status Add(const Slice& key, const Slice& value);
+  virtual Status Finish(TableStats::UserCollectedStats* stats);
+  virtual const char* Name() const { return collector_->Name(); }
+
+ protected:
+  std::shared_ptr<TableStatsCollector> collector_;
+};
+
+}  // namespace rocksdb
diff --git a/db/table_stats_collector_test.cc b/db/table_stats_collector_test.cc
new file mode 100644 (file)
index 0000000..0f92de3
--- /dev/null
@@ -0,0 +1,261 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "db/dbformat.h"
+#include "db/db_impl.h"
+#include "db/table_stats_collector.h"
+#include "rocksdb/table_stats.h"
+#include "rocksdb/table.h"
+#include "util/coding.h"
+#include "util/testharness.h"
+#include "util/testutil.h"
+
+namespace rocksdb {
+
+class TableStatsTest {
+ private:
+  unique_ptr<TableReader> table_reader_;
+};
+
+// TODO(kailiu) the following classes should be moved to some more general
+// places, so that other tests can also make use of them.
+// `FakeWritableFile` and `FakeRandomeAccessFile` bypass the real file system
+// and therefore enable us to quickly setup the tests.
+class FakeWritableFile : public WritableFile {
+ public:
+  ~FakeWritableFile() { }
+
+  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 FakeRandomeAccessFile : public RandomAccessFile {
+ public:
+  explicit FakeRandomeAccessFile(const Slice& contents)
+      : contents_(contents.data(), contents.size()) {
+  }
+
+  virtual ~FakeRandomeAccessFile() { }
+
+  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();
+  }
+
+ private:
+  std::string contents_;
+};
+
+
+class DumbLogger : public Logger {
+ public:
+  virtual void Logv(const char* format, va_list ap) { }
+  virtual size_t GetLogFileSize() const { return 0; }
+};
+
+// Utilities test functions
+void MakeBuilder(
+    Options options,
+    std::unique_ptr<FakeWritableFile>* writable,
+    std::unique_ptr<TableBuilder>* builder) {
+  writable->reset(new FakeWritableFile);
+  if (!options.flush_block_policy_factory) {
+    options.SetUpDefaultFlushBlockPolicyFactory();
+  }
+  builder->reset(
+      options.table_factory->GetTableBuilder(options, writable->get(),
+                                             options.compression));
+}
+
+void OpenTable(
+    const Options& options,
+    const std::string& contents,
+    std::unique_ptr<TableReader>* table_reader) {
+  std::unique_ptr<RandomAccessFile> file(new FakeRandomeAccessFile(contents));
+  auto s = options.table_factory->GetTableReader(
+      options,
+      EnvOptions(),
+      std::move(file),
+      contents.size(),
+      table_reader
+  );
+  ASSERT_OK(s);
+}
+
+// Collects keys that starts with "A" in a table.
+class RegularKeysStartWithA: public TableStatsCollector {
+ public:
+   const char* Name() const { return "RegularKeysStartWithA"; }
+
+   Status Finish(TableStats::UserCollectedStats* stats) {
+     std::string encoded;
+     PutVarint32(&encoded, count_);
+     *stats = TableStats::UserCollectedStats {
+       { "TableStatsTest", "Rocksdb" },
+       { "Count", encoded }
+     };
+     return Status::OK();
+   }
+
+   Status Add(const Slice& user_key, const Slice& value) {
+     // simply asssume all user keys are not empty.
+     if (user_key.data()[0] == 'A') {
+       ++count_;
+     }
+     return Status::OK();
+   }
+
+ private:
+  uint32_t count_ = 0;
+};
+
+TEST(TableStatsTest, CustomizedTableStatsCollector) {
+  Options options;
+
+  // make sure the entries will be inserted with order.
+  std::map<std::string, std::string> kvs = {
+    {"About",     "val5"},  // starts with 'A'
+    {"Abstract",  "val2"},  // starts with 'A'
+    {"Around",    "val7"},  // starts with 'A'
+    {"Beyond",    "val3"},
+    {"Builder",   "val1"},
+    {"Cancel",    "val4"},
+    {"Find",      "val6"},
+  };
+
+  // Test stats collectors with internal keys or regular keys
+  for (bool encode_as_internal : { true, false }) {
+    // -- Step 1: build table
+    auto collector = new RegularKeysStartWithA();
+    if (encode_as_internal) {
+      options.table_stats_collectors = {
+        std::make_shared<UserKeyTableStatsCollector>(collector)
+      };
+    } else {
+      options.table_stats_collectors.resize(1);
+      options.table_stats_collectors[0].reset(collector);
+    }
+    std::unique_ptr<TableBuilder> builder;
+    std::unique_ptr<FakeWritableFile> writable;
+    MakeBuilder(options, &writable, &builder);
+
+    for (const auto& kv : kvs) {
+      if (encode_as_internal) {
+        InternalKey ikey(kv.first, 0, ValueType::kTypeValue);
+        builder->Add(ikey.Encode(), kv.second);
+      } else {
+        builder->Add(kv.first, kv.second);
+      }
+    }
+    ASSERT_OK(builder->Finish());
+
+    // -- Step 2: Open table
+    std::unique_ptr<TableReader> table_reader;
+    OpenTable(options, writable->contents(), &table_reader);
+    const auto& stats = table_reader->GetTableStats().user_collected_stats;
+
+    ASSERT_EQ("Rocksdb", stats.at("TableStatsTest"));
+
+    uint32_t starts_with_A = 0;
+    Slice key(stats.at("Count"));
+    ASSERT_TRUE(GetVarint32(&key, &starts_with_A));
+    ASSERT_EQ(3u, starts_with_A);
+  }
+}
+
+TEST(TableStatsTest, InternalKeyStatsCollector) {
+  InternalKey keys[] = {
+    InternalKey("A", 0, ValueType::kTypeValue),
+    InternalKey("B", 0, ValueType::kTypeValue),
+    InternalKey("C", 0, ValueType::kTypeValue),
+    InternalKey("W", 0, ValueType::kTypeDeletion),
+    InternalKey("X", 0, ValueType::kTypeDeletion),
+    InternalKey("Y", 0, ValueType::kTypeDeletion),
+    InternalKey("Z", 0, ValueType::kTypeDeletion),
+  };
+
+  for (bool sanitized : { false, true }) {
+    std::unique_ptr<TableBuilder> builder;
+    std::unique_ptr<FakeWritableFile> writable;
+    Options options;
+    if (sanitized) {
+      options.table_stats_collectors = {
+        std::make_shared<RegularKeysStartWithA>()
+      };
+      // with sanitization, even regular stats collector will be able to
+      // handle internal keys.
+      auto comparator = options.comparator;
+      // HACK: Set options.info_log to avoid writing log in
+      // SanitizeOptions().
+      options.info_log = std::make_shared<DumbLogger>();
+      options = SanitizeOptions(
+          "db",  // just a place holder
+          nullptr,  // with skip internal key comparator
+          nullptr,  // don't care filter policy
+          options
+      );
+      options.comparator = comparator;
+    } else {
+      options.table_stats_collectors = {
+        std::make_shared<InternalKeyStatsCollector>()
+      };
+    }
+
+    MakeBuilder(options, &writable, &builder);
+    for (const auto& k : keys) {
+      builder->Add(k.Encode(), "val");
+    }
+
+    ASSERT_OK(builder->Finish());
+
+    std::unique_ptr<TableReader> table_reader;
+    OpenTable(options, writable->contents(), &table_reader);
+    const auto& stats = table_reader->GetTableStats().user_collected_stats;
+
+    uint64_t deleted = 0;
+    Slice key(stats.at(InternalKeyTableStatsNames::kDeletedKeys));
+    ASSERT_TRUE(GetVarint64(&key, &deleted));
+    ASSERT_EQ(4u, deleted);
+
+    if (sanitized) {
+      uint32_t starts_with_A = 0;
+      Slice key(stats.at("Count"));
+      ASSERT_TRUE(GetVarint32(&key, &starts_with_A));
+      ASSERT_EQ(1u, starts_with_A);
+    }
+  }
+}
+
+}  // namespace rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/db/transaction_log_impl.cc b/db/transaction_log_impl.cc
new file mode 100644 (file)
index 0000000..092d88c
--- /dev/null
@@ -0,0 +1,264 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "db/transaction_log_impl.h"
+#include "db/write_batch_internal.h"
+
+namespace rocksdb {
+
+TransactionLogIteratorImpl::TransactionLogIteratorImpl(
+                           const std::string& dir,
+                           const Options* options,
+                           const EnvOptions& soptions,
+                           const SequenceNumber seq,
+                           std::unique_ptr<VectorLogPtr> files,
+                           DBImpl const * const dbimpl) :
+    dir_(dir),
+    options_(options),
+    soptions_(soptions),
+    startingSequenceNumber_(seq),
+    files_(std::move(files)),
+    started_(false),
+    isValid_(false),
+    currentFileIndex_(0),
+    currentBatchSeq_(0),
+    currentLastSeq_(0),
+    dbimpl_(dbimpl) {
+  assert(files_ != nullptr);
+  assert(dbimpl_ != nullptr);
+
+  reporter_.env = options_->env;
+  reporter_.info_log = options_->info_log.get();
+  SeekToStartSequence(); // Seek till starting sequence
+}
+
+Status TransactionLogIteratorImpl::OpenLogFile(
+    const LogFile* logFile,
+    unique_ptr<SequentialFile>* file) {
+  Env* env = options_->env;
+  if (logFile->Type() == kArchivedLogFile) {
+    std::string fname = ArchivedLogFileName(dir_, logFile->LogNumber());
+    return env->NewSequentialFile(fname, file, soptions_);
+  } else {
+    std::string fname = LogFileName(dir_, logFile->LogNumber());
+    Status status = env->NewSequentialFile(fname, file, soptions_);
+    if (!status.ok()) {
+      //  If cannot open file in DB directory.
+      //  Try the archive dir, as it could have moved in the meanwhile.
+      fname = ArchivedLogFileName(dir_, logFile->LogNumber());
+      status = env->NewSequentialFile(fname, file, soptions_);
+      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 = currentBatchSeq_;
+  result.writeBatchPtr = std::move(currentBatch_);
+  return result;
+}
+
+Status TransactionLogIteratorImpl::status() {
+  return currentStatus_;
+}
+
+bool TransactionLogIteratorImpl::Valid() {
+  return started_ && isValid_;
+}
+
+bool TransactionLogIteratorImpl::RestrictedRead(
+    Slice* record,
+    std::string* scratch) {
+  // Don't read if no more complete entries to read from logs
+  if (currentLastSeq_ >= dbimpl_->GetLatestSequenceNumber()) {
+    return false;
+  }
+  return currentLogReader_->ReadRecord(record, scratch);
+}
+
+void TransactionLogIteratorImpl::SeekToStartSequence(
+    uint64_t startFileIndex,
+    bool strict) {
+  std::string scratch;
+  Slice record;
+  started_ = false;
+  isValid_ = false;
+  if (files_->size() <= startFileIndex) {
+    return;
+  }
+  Status s = OpenLogReader(files_->at(startFileIndex).get());
+  if (!s.ok()) {
+    currentStatus_ = s;
+    return;
+  }
+  while (RestrictedRead(&record, &scratch)) {
+    if (record.size() < 12) {
+      reporter_.Corruption(
+        record.size(), Status::Corruption("very small log record"));
+      continue;
+    }
+    UpdateCurrentWriteBatch(record);
+    if (currentLastSeq_ >= startingSequenceNumber_) {
+      if (strict && currentBatchSeq_ != startingSequenceNumber_) {
+        currentStatus_ = Status::Corruption("Gap in sequence number. Could not "
+                                            "seek to required sequence number");
+        reporter_.Info(currentStatus_.ToString().c_str());
+        return;
+      } else if (strict) {
+        reporter_.Info("Could seek required sequence number. Iterator will "
+                       "continue.");
+      }
+      isValid_ = true;
+      started_ = true; // set started_ as we could seek till starting sequence
+      return;
+    } else {
+      isValid_ = false;
+    }
+  }
+
+  // Could not find start sequence in first file. Normally this must be the
+  // only file. Otherwise log the error and let the iterator return next entry
+  // If strict is set, we want to seek exactly till the start sequence and it
+  // should have been present in the file we scanned above
+  if (strict) {
+    currentStatus_ = Status::Corruption("Gap in sequence number. Could not "
+                                        "seek to required sequence number");
+    reporter_.Info(currentStatus_.ToString().c_str());
+  } else if (files_->size() != 1) {
+    currentStatus_ = Status::Corruption("Start sequence was not found, "
+                                        "skipping to the next available");
+    reporter_.Info(currentStatus_.ToString().c_str());
+    // Let NextImpl find the next available entry. started_ remains false
+    // because we don't want to check for gaps while moving to start sequence
+    NextImpl(true);
+  }
+}
+
+void TransactionLogIteratorImpl::Next() {
+  return NextImpl(false);
+}
+
+void TransactionLogIteratorImpl::NextImpl(bool internal) {
+  std::string scratch;
+  Slice record;
+  isValid_ = false;
+  if (!internal && !started_) {
+    // Runs every time until we can seek to the start sequence
+    return SeekToStartSequence();
+  }
+  while(true) {
+    assert(currentLogReader_);
+    if (currentLogReader_->IsEOF()) {
+      currentLogReader_->UnmarkEOF();
+    }
+    while (RestrictedRead(&record, &scratch)) {
+      if (record.size() < 12) {
+        reporter_.Corruption(
+          record.size(), Status::Corruption("very small log record"));
+        continue;
+      } else {
+        // started_ should be true if called by application
+        assert(internal || started_);
+        // started_ should be false if called internally
+        assert(!internal || !started_);
+        UpdateCurrentWriteBatch(record);
+        if (internal && !started_) {
+          started_ = true;
+        }
+        return;
+      }
+    }
+
+    // Open the next file
+    if (currentFileIndex_ < files_->size() - 1) {
+      ++currentFileIndex_;
+      Status status =OpenLogReader(files_->at(currentFileIndex_).get());
+      if (!status.ok()) {
+        isValid_ = false;
+        currentStatus_ = status;
+        return;
+      }
+    } else {
+      isValid_ = false;
+      if (currentLastSeq_ == dbimpl_->GetLatestSequenceNumber()) {
+        currentStatus_ = Status::OK();
+      } else {
+        currentStatus_ = Status::IOError("NO MORE DATA LEFT");
+      }
+      return;
+    }
+  }
+}
+
+bool TransactionLogIteratorImpl::IsBatchExpected(
+    const WriteBatch* batch,
+    const SequenceNumber expectedSeq) {
+  assert(batch);
+  SequenceNumber batchSeq = WriteBatchInternal::Sequence(batch);
+  if (batchSeq != expectedSeq) {
+    char buf[200];
+    snprintf(buf, sizeof(buf),
+             "Discontinuity in log records. Got seq=%lu, Expected seq=%lu, "
+             "Last flushed seq=%lu.Log iterator will reseek the correct "
+             "batch.",
+             (unsigned long)batchSeq,
+             (unsigned long)expectedSeq,
+             (unsigned long)dbimpl_->GetLatestSequenceNumber());
+    reporter_.Info(buf);
+    return false;
+  }
+  return true;
+}
+
+void TransactionLogIteratorImpl::UpdateCurrentWriteBatch(const Slice& record) {
+  std::unique_ptr<WriteBatch> batch(new WriteBatch());
+  WriteBatchInternal::SetContents(batch.get(), record);
+
+  SequenceNumber expectedSeq = currentLastSeq_ + 1;
+  // If the iterator has started, then confirm that we get continuous batches
+  if (started_ && !IsBatchExpected(batch.get(), expectedSeq)) {
+    // Seek to the batch having expected sequence number
+    if (expectedSeq < files_->at(currentFileIndex_)->StartSequence()) {
+      // Expected batch must lie in the previous log file
+      // Avoid underflow.
+      if (currentFileIndex_ != 0) {
+        currentFileIndex_--;
+      }
+    }
+    startingSequenceNumber_ = expectedSeq;
+    // currentStatus_ will be set to Ok if reseek succeeds
+    currentStatus_ = Status::NotFound("Gap in sequence numbers");
+    return SeekToStartSequence(currentFileIndex_, true);
+  }
+
+  currentBatchSeq_ = WriteBatchInternal::Sequence(batch.get());
+  currentLastSeq_ = currentBatchSeq_ +
+                    WriteBatchInternal::Count(batch.get()) - 1;
+  // currentBatchSeq_ can only change here
+  assert(currentLastSeq_ <= dbimpl_->GetLatestSequenceNumber());
+
+  currentBatch_ = move(batch);
+  isValid_ = true;
+  currentStatus_ = Status::OK();
+}
+
+Status TransactionLogIteratorImpl::OpenLogReader(const LogFile* logFile) {
+  unique_ptr<SequentialFile> file;
+  Status status = OpenLogFile(logFile, &file);
+  if (!status.ok()) {
+    return status;
+  }
+  assert(file);
+  currentLogReader_.reset(
+    new log::Reader(std::move(file), &reporter_, true, 0)
+  );
+  return Status::OK();
+}
+}  //  namespace rocksdb
diff --git a/db/transaction_log_impl.h b/db/transaction_log_impl.h
new file mode 100644 (file)
index 0000000..f3f4ce2
--- /dev/null
@@ -0,0 +1,118 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+#include <vector>
+
+#include "rocksdb/env.h"
+#include "rocksdb/options.h"
+#include "rocksdb/types.h"
+#include "rocksdb/transaction_log.h"
+#include "db/db_impl.h"
+#include "db/log_reader.h"
+#include "db/filename.h"
+
+namespace rocksdb {
+
+struct LogReporter : public log::Reader::Reporter {
+  Env* env;
+  Logger* info_log;
+  virtual void Corruption(size_t bytes, const Status& s) {
+    Log(info_log, "dropping %zu bytes; %s", bytes, s.ToString().c_str());
+  }
+  virtual void Info(const char* s) {
+    Log(info_log, "%s", s);
+  }
+};
+
+class LogFileImpl : public LogFile {
+ public:
+  LogFileImpl(uint64_t logNum, WalFileType logType, SequenceNumber startSeq,
+              uint64_t sizeBytes) :
+    logNumber_(logNum),
+    type_(logType),
+    startSequence_(startSeq),
+    sizeFileBytes_(sizeBytes) {
+  }
+
+  std::string PathName() const {
+    if (type_ == kArchivedLogFile) {
+      return ArchivedLogFileName("", logNumber_);
+    }
+    return LogFileName("", logNumber_);
+  }
+
+  uint64_t LogNumber() const { return logNumber_; }
+
+  WalFileType Type() const { return type_; }
+
+  SequenceNumber StartSequence() const { return startSequence_; }
+
+  uint64_t SizeFileBytes() const { return sizeFileBytes_; }
+
+  bool operator < (const LogFile& that) const {
+    return LogNumber() < that.LogNumber();
+  }
+
+ private:
+  uint64_t logNumber_;
+  WalFileType type_;
+  SequenceNumber startSequence_;
+  uint64_t sizeFileBytes_;
+
+};
+
+class TransactionLogIteratorImpl : public TransactionLogIterator {
+ public:
+  TransactionLogIteratorImpl(const std::string& dir,
+                             const Options* options,
+                             const EnvOptions& soptions,
+                             const SequenceNumber seqNum,
+                             std::unique_ptr<VectorLogPtr> files,
+                             DBImpl const * const dbimpl);
+
+  virtual bool Valid();
+
+  virtual void Next();
+
+  virtual Status status();
+
+  virtual BatchResult GetBatch();
+
+ private:
+  const std::string& dir_;
+  const Options* options_;
+  const EnvOptions& soptions_;
+  SequenceNumber startingSequenceNumber_;
+  std::unique_ptr<VectorLogPtr> files_;
+  bool started_;
+  bool isValid_;  // not valid when it starts of.
+  Status currentStatus_;
+  size_t currentFileIndex_;
+  std::unique_ptr<WriteBatch> currentBatch_;
+  unique_ptr<log::Reader> currentLogReader_;
+  Status OpenLogFile(const LogFile* logFile, unique_ptr<SequentialFile>* file);
+  LogReporter reporter_;
+  SequenceNumber currentBatchSeq_; // sequence number at start of current batch
+  SequenceNumber currentLastSeq_; // last sequence in the current batch
+  DBImpl const * const dbimpl_; // The db on whose log files this iterates
+
+  // Reads from transaction log only if the writebatch record has been written
+  bool RestrictedRead(Slice* record, std::string* scratch);
+  // Seeks to startingSequenceNumber reading from startFileIndex in files_.
+  // If strict is set,then must get a batch starting with startingSequenceNumber
+  void SeekToStartSequence(uint64_t startFileIndex = 0, bool strict = false);
+  // Implementation of Next. SeekToStartSequence calls it internally with
+  // internal=true to let it find next entry even if it has to jump gaps because
+  // the iterator may start off from the first available entry but promises to
+  // be continuous after that
+  void NextImpl(bool internal = false);
+  // Check if batch is expected, else return false
+  bool IsBatchExpected(const WriteBatch* batch, SequenceNumber expectedSeq);
+  // Update current batch if a continuous batch is found, else return false
+  void UpdateCurrentWriteBatch(const Slice& record);
+  Status OpenLogReader(const LogFile* file);
+};
+}  //  namespace rocksdb
diff --git a/db/version_edit.cc b/db/version_edit.cc
new file mode 100644 (file)
index 0000000..9f23fab
--- /dev/null
@@ -0,0 +1,301 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 rocksdb {
+
+// 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,
+
+  // these are new formats divergent from open source leveldb
+  kNewFile2             = 100  // store smallest & largest seqno
+};
+
+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, kNewFile2);
+    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());
+    PutVarint64(dst, f.smallest_seqno);
+    PutVarint64(dst, f.largest_seqno);
+  }
+}
+
+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;
+
+      case kNewFile2:
+        if (GetLevel(&input, &level, &msg) &&
+            GetVarint64(&input, &f.number) &&
+            GetVarint64(&input, &f.file_size) &&
+            GetInternalKey(&input, &f.smallest) &&
+            GetInternalKey(&input, &f.largest) &&
+            GetVarint64(&input, &f.smallest_seqno) &&
+            GetVarint64(&input, &f.largest_seqno) ) {
+          new_files_.push_back(std::make_pair(level, f));
+        } else {
+          if (!msg) {
+            msg = "new-file2 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(bool hex_key) 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(hex_key));
+  }
+  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(hex_key));
+    r.append(" .. ");
+    r.append(f.largest.DebugString(hex_key));
+  }
+  r.append("\n}\n");
+  return r;
+}
+
+}  // namespace rocksdb
diff --git a/db/version_edit.h b/db/version_edit.h
new file mode 100644 (file)
index 0000000..196914e
--- /dev/null
@@ -0,0 +1,128 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <set>
+#include <utility>
+#include <vector>
+#include "db/dbformat.h"
+
+namespace rocksdb {
+
+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?
+  SequenceNumber smallest_seqno;// The smallest seqno in this file
+  SequenceNumber largest_seqno; // The largest seqno in this file
+
+  FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0),
+                   being_compacted(false) { }
+};
+
+class VersionEdit {
+ public:
+  explicit 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,
+               const SequenceNumber& smallest_seqno,
+               const SequenceNumber& largest_seqno) {
+    FileMetaData f;
+    f.number = file;
+    f.file_size = file_size;
+    f.smallest = smallest;
+    f.largest = largest;
+    f.smallest_seqno = smallest_seqno;
+    f.largest_seqno = largest_seqno;
+    assert(smallest_seqno <= largest_seqno);
+    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));
+  }
+
+  // Number of edits
+  int NumEntries() {
+    return new_files_.size() + deleted_files_.size();
+  }
+
+  void EncodeTo(std::string* dst) const;
+  Status DecodeFrom(const Slice& src);
+
+  std::string DebugString(bool hex_key = false) const;
+
+ private:
+  friend class VersionSet;
+
+  typedef std::set< std::pair<int, uint64_t> > 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<int, InternalKey> > compact_pointers_;
+  DeletedFileSet deleted_files_;
+  std::vector< std::pair<int, FileMetaData> > new_files_;
+};
+
+}  // namespace rocksdb
diff --git a/db/version_edit_test.cc b/db/version_edit_test.cc
new file mode 100644 (file)
index 0000000..4a00822
--- /dev/null
@@ -0,0 +1,53 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 rocksdb {
+
+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),
+                 kBig + 500 + i,
+                 kBig + 600 + i);
+    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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/db/version_set.cc b/db/version_set.cc
new file mode 100644 (file)
index 0000000..d554657
--- /dev/null
@@ -0,0 +1,3152 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <algorithm>
+#include <climits>
+#include <stdio.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 "rocksdb/env.h"
+#include "rocksdb/merge_operator.h"
+#include "rocksdb/table.h"
+#include "table/merger.h"
+#include "table/two_level_iterator.h"
+#include "util/coding.h"
+#include "util/logging.h"
+#include "util/stop_watch.h"
+
+namespace rocksdb {
+
+static uint64_t TotalFileSize(const std::vector<FileMetaData*>& files) {
+  uint64_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) {
+        vset_->obsolete_files_.push_back(f);
+      }
+    }
+  }
+  delete[] files_;
+}
+
+int FindFile(const InternalKeyComparator& icmp,
+             const std::vector<FileMetaData*>& 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<FileMetaData*>& 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<FileMetaData*>* 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<FileMetaData*>* 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 EnvOptions& soptions,
+                                 const Slice& file_value,
+                                 bool for_compaction) {
+  TableCache* cache = reinterpret_cast<TableCache*>(arg);
+  if (file_value.size() != 16) {
+    return NewErrorIterator(
+        Status::Corruption("FileReader invoked with unexpected value"));
+  } else {
+    ReadOptions options_copy;
+    if (options.prefix) {
+      // suppress prefix filtering since we have already checked the
+      // filters once at this point
+      options_copy = options;
+      options_copy.prefix = nullptr;
+    }
+    return cache->NewIterator(options.prefix ? options_copy : options,
+                              soptions,
+                              DecodeFixed64(file_value.data()),
+                              DecodeFixed64(file_value.data() + 8),
+                              nullptr /* don't need reference to table*/,
+                              for_compaction);
+  }
+}
+
+bool Version::PrefixMayMatch(const ReadOptions& options,
+                             const EnvOptions& soptions,
+                             const Slice& internal_prefix,
+                             Iterator* level_iter) const {
+  bool may_match = true;
+  level_iter->Seek(internal_prefix);
+  if (!level_iter->Valid()) {
+    // we're past end of level
+    may_match = false;
+  } else if (ExtractUserKey(level_iter->key()).starts_with(
+                                             ExtractUserKey(internal_prefix))) {
+    // TODO(tylerharter): do we need this case?  Or are we guaranteed
+    // key() will always be the biggest value for this SST?
+    may_match = true;
+  } else {
+    may_match = vset_->table_cache_->PrefixMayMatch(
+                           options,
+                           DecodeFixed64(level_iter->value().data()),
+                           DecodeFixed64(level_iter->value().data() + 8),
+                           internal_prefix, nullptr);
+  }
+  return may_match;
+}
+
+Iterator* Version::NewConcatenatingIterator(const ReadOptions& options,
+                                            const EnvOptions& soptions,
+                                            int level) const {
+  Iterator* level_iter = new LevelFileNumIterator(vset_->icmp_, &files_[level]);
+  if (options.prefix) {
+    InternalKey internal_prefix(*options.prefix, 0, kTypeValue);
+    if (!PrefixMayMatch(options, soptions,
+                        internal_prefix.Encode(), level_iter)) {
+      delete level_iter;
+      // nothing in this level can match the prefix
+      return NewEmptyIterator();
+    }
+  }
+  return NewTwoLevelIterator(level_iter, &GetFileIterator,
+                             vset_->table_cache_, options, soptions);
+}
+
+void Version::AddIterators(const ReadOptions& options,
+                           const EnvOptions& soptions,
+                           std::vector<Iterator*>* iters) {
+  // Merge all level zero files together since they may overlap
+  for (const FileMetaData* file : files_[0]) {
+    iters->push_back(
+        vset_->table_cache_->NewIterator(
+            options, soptions, file->number, file->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, soptions, level));
+    }
+  }
+}
+
+// Callback from TableCache::Get()
+namespace {
+enum SaverState {
+  kNotFound,
+  kFound,
+  kDeleted,
+  kCorrupt,
+  kMerge // saver contains the current merge result (the operands)
+};
+struct Saver {
+  SaverState state;
+  const Comparator* ucmp;
+  Slice user_key;
+  bool* value_found; // Is value set correctly? Used by KeyMayExist
+  std::string* value;
+  const MergeOperator* merge_operator;
+  std::deque<std::string>* merge_operands;  // the merge operations encountered
+  Logger* logger;
+  bool didIO;    // did we do any disk io?
+  shared_ptr<Statistics> statistics;
+};
+}
+
+// Called from TableCache::Get and Table::Get when file/block in which
+// key may  exist are not there in TableCache/BlockCache respectively. In this
+// case we  can't guarantee that key does not exist and are not permitted to do
+// IO to be  certain.Set the status=kFound and value_found=false to let the
+// caller know that key may exist but is not there in memory
+static void MarkKeyMayExist(void* arg) {
+  Saver* s = reinterpret_cast<Saver*>(arg);
+  s->state = kFound;
+  if (s->value_found != nullptr) {
+    *(s->value_found) = false;
+  }
+}
+
+static bool SaveValue(void* arg, const Slice& ikey, const Slice& v, bool didIO){
+  Saver* s = reinterpret_cast<Saver*>(arg);
+  std::deque<std::string>* const ops = s->merge_operands; // shorter alias
+  std::string merge_result;  // temporary area for merge results later
+
+  assert(s != nullptr && ops != nullptr);
+
+  ParsedInternalKey parsed_key;
+  // TODO: didIO and Merge?
+  s->didIO = didIO;
+  if (!ParseInternalKey(ikey, &parsed_key)) {
+    // TODO: what about corrupt during Merge?
+    s->state = kCorrupt;
+  } else {
+    if (s->ucmp->Compare(parsed_key.user_key, s->user_key) == 0) {
+      // Key matches. Process it
+      switch (parsed_key.type) {
+        case kTypeValue:
+          if (kNotFound == s->state) {
+            s->state = kFound;
+            s->value->assign(v.data(), v.size());
+          } else if (kMerge == s->state) {
+            assert(s->merge_operator != nullptr);
+            s->state = kFound;
+            if (!s->merge_operator->FullMerge(s->user_key, &v, *ops,
+                                              s->value, s->logger)) {
+              RecordTick(s->statistics, NUMBER_MERGE_FAILURES);
+              s->state = kCorrupt;
+            }
+          } else {
+            assert(false);
+          }
+          return false;
+
+        case kTypeDeletion:
+          if (kNotFound == s->state) {
+            s->state = kDeleted;
+          } else if (kMerge == s->state) {
+            s->state = kFound;
+            if (!s->merge_operator->FullMerge(s->user_key, nullptr, *ops,
+                                              s->value, s->logger)) {
+              RecordTick(s->statistics, NUMBER_MERGE_FAILURES);
+              s->state = kCorrupt;
+            }
+          } else {
+            assert(false);
+          }
+          return false;
+
+        case kTypeMerge:
+          assert(s->state == kNotFound || s->state == kMerge);
+          s->state = kMerge;
+          ops->push_front(v.ToString());
+          while (ops->size() >= 2) {
+            // Attempt to merge operands together via user associateive merge
+            if (s->merge_operator->PartialMerge(s->user_key,
+                                                Slice((*ops)[0]),
+                                                Slice((*ops)[1]),
+                                                &merge_result,
+                                                s->logger)) {
+              ops->pop_front();
+              swap(ops->front(), merge_result);
+            } else {
+              // Associative merge returns false ==> stack the operands
+              break;
+            }
+          }
+          return true;
+
+        case kTypeLogData:
+          assert(false);
+          break;
+      }
+    }
+  }
+
+  // s->state could be Corrupt, merge or notfound
+
+  return false;
+}
+
+static bool NewestFirst(FileMetaData* a, FileMetaData* b) {
+  return a->number > b->number;
+}
+static bool NewestFirstBySeqNo(FileMetaData* a, FileMetaData* b) {
+  if (a->smallest_seqno > b->smallest_seqno) {
+    assert(a->largest_seqno > b->largest_seqno);
+    return true;
+  }
+  assert(a->largest_seqno <= b->largest_seqno);
+  return false;
+}
+
+Version::Version(VersionSet* vset, uint64_t version_number)
+    : vset_(vset), next_(this), prev_(this), refs_(0),
+      files_(new std::vector<FileMetaData*>[vset->NumberLevels()]),
+      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) {
+}
+
+void Version::Get(const ReadOptions& options,
+                  const LookupKey& k,
+                  std::string* value,
+                  Status* status,
+                  std::deque<std::string>* operands,
+                  GetStats* stats,
+                  const Options& db_options,
+                  bool* value_found) {
+  Slice ikey = k.internal_key();
+  Slice user_key = k.user_key();
+  const Comparator* ucmp = vset_->icmp_.user_comparator();
+
+  auto merge_operator = db_options.merge_operator.get();
+  auto logger = db_options.info_log;
+
+  assert(status->ok() || status->IsMergeInProgress());
+  Saver saver;
+  saver.state = status->ok()? kNotFound : kMerge;
+  saver.ucmp = ucmp;
+  saver.user_key = user_key;
+  saver.value_found = value_found;
+  saver.value = value;
+  saver.merge_operator = merge_operator;
+  saver.merge_operands = operands;
+  saver.logger = logger.get();
+  saver.didIO = false;
+  saver.statistics = db_options.statistics;
+
+  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 (unless we
+  // are MergeInProgress).
+  std::vector<FileMetaData*> important_files;
+  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];
+    important_files.clear();
+    important_files.reserve(num_files);
+
+    // Some files may overlap each other. We find
+    // all files that overlap user_key and process them in order from
+    // newest to oldest. In the context of merge-operator,
+    // this can occur at any level. Otherwise, it only occurs
+    // at Level-0 (since Put/Deletes are always compacted into a single entry).
+    uint32_t start_index;
+    if (level == 0) {
+      // On Level-0, we read through all files to check for overlap.
+      start_index = 0;
+    } else {
+      // On Level-n (n>=1), files are sorted.
+      // Binary search to find earliest index whose largest key >= ikey.
+      // We will also stop when the file no longer overlaps ikey
+      start_index = FindFile(vset_->icmp_, files_[level], ikey);
+    }
+
+    // Traverse the list, finding all overlapping files.
+    for (uint32_t i = start_index; 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) {
+        important_files.push_back(f);
+      } else if (level > 0) {
+        // If on Level-n (n>=1) then the files are sorted.
+        // So we can stop looking when we are past the ikey.
+        break;
+      }
+    }
+
+    if (important_files.empty()) continue;
+
+    if (level == 0) {
+      if (vset_->options_->compaction_style == kCompactionStyleUniversal) {
+        std::sort(important_files.begin(), important_files.end(), NewestFirstBySeqNo);
+      } else {
+        std::sort(important_files.begin(), important_files.end(), NewestFirst);
+      }
+    } else {
+      // Sanity check to make sure that the files are correctly sorted
+#ifndef NDEBUG
+      num_files = important_files.size();
+      for (uint32_t i = 1; i < num_files; ++i) {
+        FileMetaData* a = important_files[i-1];
+        FileMetaData* b = important_files[i];
+        int comp_sign = vset_->icmp_.Compare(a->largest, b->smallest);
+        assert(comp_sign < 0);
+      }
+#endif
+    }
+
+    // Traverse each relevant file to find the desired key
+    num_files = important_files.size();
+    for (uint32_t i = 0; i < num_files; ++i) {
+      FileMetaData* f = important_files[i];
+      bool tableIO = false;
+      *status = vset_->table_cache_->Get(options, f->number, f->file_size,
+                                         ikey, &saver, SaveValue, &tableIO,
+                                         MarkKeyMayExist);
+      // TODO: examine the behavior for corrupted key
+      if (!status->ok()) {
+        return;
+      }
+
+      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;
+        case kDeleted:
+          *status = Status::NotFound(Slice());  // Use empty error message for speed
+          return;
+        case kCorrupt:
+          *status = Status::Corruption("corrupted key for ", user_key);
+          return;
+        case kMerge:
+          break;
+      }
+    }
+  }
+
+
+  if (kMerge == saver.state) {
+    // merge_operands are in saver and we hit the beginning of the key history
+    // do a final merge of nullptr and operands;
+    if (merge_operator->FullMerge(user_key, nullptr, *saver.merge_operands,
+                                  value, logger.get())) {
+      *status = Status::OK();
+    } else {
+      RecordTick(db_options.statistics, NUMBER_MERGE_FAILURES);
+      *status = Status::Corruption("could not perform end-of-key merge for ",
+                                   user_key);
+    }
+  } else {
+    *status = 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<ValueType>(0));
+    std::vector<FileMetaData*> 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 uint64_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<FileMetaData*>* 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<FileMetaData*>* 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<FileMetaData*>* inputs,
+    unsigned 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);
+  }
+}
+
+// Returns true iff the first or last file in inputs contains
+// an overlapping user key to the file "just outside" of it (i.e.
+// just after the last file, or just before the first file)
+// REQUIRES: "*inputs" is a sorted list of non-overlapping files
+bool Version::HasOverlappingUserKey(
+    const std::vector<FileMetaData*>* inputs,
+    int level) {
+
+  // If inputs empty, there is no overlap.
+  // If level == 0, it is assumed that all needed files were already included.
+  if (inputs->empty() || level == 0){
+    return false;
+  }
+
+  const Comparator* user_cmp = vset_->icmp_.user_comparator();
+  const std::vector<FileMetaData*>& files = files_[level];
+  const size_t kNumFiles = files.size();
+
+  // Check the last file in inputs against the file after it
+  size_t last_file = FindFile(vset_->icmp_, files,
+                              inputs->back()->largest.Encode());
+  assert(0 <= last_file && last_file < kNumFiles);  // File should exist!
+  if (last_file < kNumFiles-1) {                    // If not the last file
+    const Slice last_key_in_input = files[last_file]->largest.user_key();
+    const Slice first_key_after = files[last_file+1]->smallest.user_key();
+    if (user_cmp->Compare(last_key_in_input, first_key_after) == 0) {
+      // The last user key in input overlaps with the next file's first key
+      return true;
+    }
+  }
+
+  // Check the first file in inputs against the file just before it
+  size_t first_file = FindFile(vset_->icmp_, files,
+                               inputs->front()->smallest.Encode());
+  assert(0 <= first_file && first_file <= last_file);   // File should exist!
+  if (first_file > 0) {                                 // If not first file
+    const Slice& first_key_in_input = files[first_file]->smallest.user_key();
+    const Slice& last_key_before = files[first_file-1]->largest.user_key();
+    if (user_cmp->Compare(first_key_in_input, last_key_before) == 0) {
+      // The first user key in input overlaps with the previous file's last key
+      return true;
+    }
+  }
+
+  return false;
+}
+
+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<FileMetaData*>& 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<FileMetaData*, BySmallestKey> FileSet;
+  struct LevelState {
+    std::set<uint64_t> 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<FileMetaData*> 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,
+    unsigned 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<FileMetaData*>& base_files = base_->files_[l];
+        for (unsigned 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<FileMetaData*>& base_files = base_->files_[level];
+      std::vector<FileMetaData*>::const_iterator base_iter = base_files.begin();
+      std::vector<FileMetaData*>::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<FileMetaData*>::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<FileMetaData*>* 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,
+                       const EnvOptions& storage_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),
+      storage_options_(storage_options),
+      storage_options_compactions_(storage_options_)  {
+  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
+  for (auto file : obsolete_files_) {
+    delete file;
+  }
+  obsolete_files_.clear();
+  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 == 0 && options_->compaction_style == kCompactionStyleUniversal) {
+      max_file_size_[i] = ULLONG_MAX;
+      level_max_bytes_[i] = options_->max_bytes_for_level_base;
+    } else 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 *
+        options_->max_bytes_for_level_multiplier_additional[i-1];
+    } 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<VersionEdit*> 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<ManifestWriter*>::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;
+  // we will need this if we are creating new manifest
+  uint64_t old_manifest_file_number = manifest_file_number_;
+
+  //  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 (new_descriptor_log) {
+    new_manifest_file = DescriptorFileName(dbname_, manifest_file_number_);
+    edit->SetNextFile(next_file_number_);
+  }
+
+  // Unlock during expensive MANIFEST log write. New writes cannot get here
+  // because &w is ensuring that all new writes get queued.
+  {
+    // calculate the amount of data being compacted at every level
+    std::vector<uint64_t> size_being_compacted(NumberLevels()-1);
+    SizeBeingCompacted(size_being_compacted);
+
+    mu->Unlock();
+
+    // This is fine because everything inside of this block is serialized --
+    // only one thread can be here at the same time
+    if (!new_manifest_file.empty()) {
+      unique_ptr<WritableFile> descriptor_file;
+      s = env_->NewWritableFile(new_manifest_file, &descriptor_file,
+                                storage_options_);
+      if (s.ok()) {
+        descriptor_log_.reset(new log::Writer(std::move(descriptor_file)));
+        s = WriteSnapshot(descriptor_log_.get());
+      }
+    }
+
+    // The calls to Finalize and UpdateFilesBySize are cpu-heavy
+    // and is best called outside the mutex.
+    Finalize(v, size_being_compacted);
+    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) {
+          StopWatch sw(env_, options_->statistics, MANIFEST_FILE_SYNC_MICROS);
+          s = descriptor_log_->file()->Fsync();
+        } else {
+          StopWatch sw(env_, options_->statistics, MANIFEST_FILE_SYNC_MICROS);
+          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_);
+      if (s.ok() && old_manifest_file_number < manifest_file_number_) {
+        // delete old manifest file
+        Log(options_->info_log,
+            "Deleting manifest %lu current manifest %lu\n",
+            (unsigned long)old_manifest_file_number,
+            (unsigned long)manifest_file_number_);
+        // we don't care about an error here, PurgeObsoleteFiles will take care
+        // of it later
+        env_->DeleteFile(DescriptorFileName(dbname_, old_manifest_file_number));
+      }
+    }
+
+    // find offset in manifest file where this version is stored.
+    new_manifest_file_size = descriptor_log_->file()->GetFileSize();
+
+    LogFlush(options_->info_log);
+    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 %lu",
+        (unsigned long)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_), &current);
+  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<SequentialFile> file;
+  s = env_->NewSequentialFile(dscname, &file, storage_options_);
+  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(icmp_.user_comparator()->Name(),
+                                      "does not match existing comparator " +
+                                      edit.comparator_);
+        }
+      }
+
+      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
+    std::vector<uint64_t> size_being_compacted(NumberLevels()-1);
+    SizeBeingCompacted(size_being_compacted);
+    Finalize(v, size_being_compacted);
+
+    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 %lu, next_file_number is %lu, "
+        "last_sequence is %lu, log_number is %lu,"
+        "prev_log_number is %lu\n",
+        current.c_str(),
+        (unsigned long)manifest_file_number_,
+        (unsigned long)next_file_number_,
+        (unsigned long)last_sequence_,
+        (unsigned long)log_number_,
+        (unsigned long)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<SequentialFile> file;
+  Status s = options.env->NewSequentialFile(dscname, &file, storage_options_);
+  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(icmp_.user_comparator()->Name(),
+                                      "does not match existing comparator " +
+                                      edit.comparator_);
+        }
+      }
+
+      // Write out each individual edit
+      if (verbose) {
+        printf("*************************Edit[%d] = %s\n",
+                count, edit.DebugString(hex).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
+    std::vector<uint64_t> size_being_compacted(NumberLevels()-1);
+    SizeBeingCompacted(size_being_compacted);
+    Finalize(v, size_being_compacted);
+
+    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 %lu next_file_number %lu last_sequence "
+           "%lu log_number %lu  prev_log_number %lu\n",
+           (unsigned long)manifest_file_number_,
+           (unsigned long)next_file_number_,
+           (unsigned long)last_sequence,
+           (unsigned long)log_number,
+           (unsigned long)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,
+  std::vector<uint64_t>& size_being_compacted) {
+
+  double max_score = 0;
+  int max_score_level = 0;
+
+  int num_levels_to_check =
+      (options_->compaction_style != kCompactionStyleUniversal) ?
+          NumberLevels() - 1 : 1;
+
+  for (int level = 0; level < num_levels_to_check; 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<double>(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]) -
+                                   size_being_compacted[level];
+      score = static_cast<double>(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
+// In normal mode: descending size
+static bool compareSizeDescending(const VersionSet::Fsize& first,
+  const VersionSet::Fsize& second) {
+  return (first.file->file_size > second.file->file_size);
+}
+// A static compator used to sort files based on their seqno
+// In universal style : descending seqno
+static bool compareSeqnoDescending(const VersionSet::Fsize& first,
+  const VersionSet::Fsize& second) {
+  if (first.file->smallest_seqno > second.file->smallest_seqno) {
+    assert(first.file->largest_seqno > second.file->largest_seqno);
+    return true;
+  }
+  assert(first.file->largest_seqno <= second.file->largest_seqno);
+  return false;
+}
+
+// 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.
+  int max_level = (options_->compaction_style == kCompactionStyleUniversal) ?
+                  NumberLevels() : NumberLevels() - 1;
+
+  for (int level = 0; level < max_level; level++) {
+
+    const std::vector<FileMetaData*>& files = v->files_[level];
+    std::vector<int>& 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<Fsize> 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
+    if (options_->compaction_style == kCompactionStyleUniversal) {
+      int num = temp.size();
+      std::partial_sort(temp.begin(),  temp.begin() + num,
+                        temp.end(), compareSeqnoDescending);
+    } else {
+      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(), compareSizeDescending);
+    }
+    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<FileMetaData*>& 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,
+                   f->smallest_seqno, f->largest_seqno);
+    }
+  }
+
+  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, "%lu ",
+        (unsigned long)NumLevelBytes(i));
+    if (ret < 0 || ret >= sz)
+      break;
+    len += ret;
+  }
+  snprintf(scratch->buffer + len, sizeof(scratch->buffer) - len, "]");
+  return scratch->buffer;
+}
+
+const char* VersionSet::LevelFileSummary(
+    FileSummaryStorage* scratch, int level) const {
+  int len = snprintf(scratch->buffer, sizeof(scratch->buffer), "files_size[");
+  for (unsigned int i = 0; i < current_->files_[level].size(); i++) {
+    FileMetaData* f = current_->files_[level][i];
+    int sz = sizeof(scratch->buffer) - len;
+    int ret = snprintf(scratch->buffer + len, sz,
+                       "#%lu(seq=%lu,sz=%lu,%lu) ",
+                       (unsigned long)f->number,
+                       (unsigned long)f->smallest_seqno,
+                       (unsigned long)f->file_size,
+                       (unsigned long)f->being_compacted);
+    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<SequentialFile> file;
+  Status s = env_->NewSequentialFile(fname, &file, storage_options_);
+  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<FileMetaData*>& 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.
+        TableReader* table_reader_ptr;
+        Iterator* iter = table_cache_->NewIterator(
+            ReadOptions(), storage_options_, files[i]->number,
+            files[i]->file_size, &table_reader_ptr);
+        if (table_reader_ptr != nullptr) {
+          result += table_reader_ptr->ApproximateOffsetOf(ikey.Encode());
+        }
+        delete iter;
+      }
+    }
+  }
+  return result;
+}
+
+void VersionSet::AddLiveFiles(std::vector<uint64_t>* live_list) {
+  // pre-calculate space requirement
+  int64_t total_files = 0;
+  for (Version* v = dummy_versions_.next_;
+       v != &dummy_versions_;
+       v = v->next_) {
+    for (int level = 0; level < NumberLevels(); level++) {
+      total_files += v->files_[level].size();
+    }
+  }
+
+  // just one time extension to the right size
+  live_list->reserve(live_list->size() + total_files);
+
+  for (Version* v = dummy_versions_.next_;
+       v != &dummy_versions_;
+       v = v->next_) {
+    for (int level = 0; level < NumberLevels(); level++) {
+      for (const auto& f : v->files_[level]) {
+        live_list->push_back(f->number);
+      }
+    }
+  }
+}
+
+void VersionSet::AddLiveFilesCurrentVersion(std::set<uint64_t>* live) {
+  Version* v = current_;
+  for (int level = 0; level < NumberLevels(); level++) {
+    const std::vector<FileMetaData*>& 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());
+  assert(current_);
+  return TotalFileSize(current_->files_[level]);
+}
+
+int64_t VersionSet::MaxNextLevelOverlappingBytes() {
+  uint64_t result = 0;
+  std::vector<FileMetaData*> 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 uint64_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<FileMetaData*>& 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<FileMetaData*>& inputs1,
+                           const std::vector<FileMetaData*>& inputs2,
+                           InternalKey* smallest,
+                           InternalKey* largest) {
+  std::vector<FileMetaData*> 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<FileMetaData*>& files = c->inputs_[which];
+        for (size_t i = 0; i < files.size(); i++) {
+          list[num++] = table_cache_->NewIterator(
+              options, storage_options_compactions_,
+              files[i]->number, files[i]->file_size, nullptr,
+              true /* for compaction */);
+        }
+      } else {
+        // Create concatenating iterator for the files from this level
+        list[num++] = NewTwoLevelIterator(
+            new Version::LevelFileNumIterator(icmp_, &c->inputs_[which]),
+            &GetFileIterator, table_cache_, options, storage_options_,
+            true /* for compaction */);
+      }
+    }
+  }
+  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];
+}
+
+uint64_t VersionSet::ExpandedCompactionByteSizeLimit(int level) {
+  uint64_t result = MaxFileSizeForLevel(level);
+  result *= options_->expanded_compaction_factor;
+  return result;
+}
+
+uint64_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
+// at at every level upto the penultimate level.
+void VersionSet::SizeBeingCompacted(std::vector<uint64_t>& sizes) {
+  for (int level = 0; level < NumberLevels()-1; level++) {
+    uint64_t total = 0;
+    for (std::set<Compaction*>::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;
+      }
+    }
+    sizes[level] = total;
+  }
+}
+
+//
+// Look at overall size amplification. If size amplification
+// exceeeds the configured value, then do a compaction
+// of the candidate files all the way upto the earliest
+// base file (overrides configured values of file-size ratios,
+// min_merge_width and max_merge_width).
+//
+Compaction* VersionSet::PickCompactionUniversalSizeAmp(
+    int level, double score) {
+  assert (level == 0);
+
+  // percentage flexibilty while reducing size amplification
+  uint64_t ratio = options_->compaction_options_universal.
+                     max_size_amplification_percent;
+
+  // The files are sorted from newest first to oldest last.
+  std::vector<int>& file_by_time = current_->files_by_size_[level];
+  assert(file_by_time.size() == current_->files_[level].size());
+
+  unsigned int candidate_count = 0;
+  uint64_t candidate_size = 0;
+  unsigned int start_index = 0;
+  FileMetaData* f = nullptr;
+
+  // Skip files that are already being compacted
+  for (unsigned int loop = 0; loop < file_by_time.size() - 1; loop++) {
+    int index = file_by_time[loop];
+    f = current_->files_[level][index];
+    if (!f->being_compacted) {
+      start_index = loop;         // Consider this as the first candidate.
+      break;
+    }
+    Log(options_->info_log, "Universal: skipping file %lu[%d] compacted %s",
+        (unsigned long)f->number,
+        loop,
+        " cannot be a candidate to reduce size amp.\n");
+    f = nullptr;
+  }
+  if (f == nullptr) {
+    return nullptr;             // no candidate files
+  }
+
+  Log(options_->info_log, "Universal: First candidate file %lu[%d] %s",
+      (unsigned long)f->number,
+      start_index,
+      " to reduce size amp.\n");
+
+  // keep adding up all the remaining files
+  for (unsigned int loop = start_index; loop < file_by_time.size() - 1;
+       loop++) {
+    int index = file_by_time[loop];
+    f = current_->files_[level][index];
+    if (f->being_compacted) {
+      Log(options_->info_log,
+          "Universal: Possible candidate file %lu[%d] %s.",
+          (unsigned long)f->number,
+          loop,
+          " is already being compacted. No size amp reduction possible.\n");
+      return nullptr;
+    }
+    candidate_size += f->file_size;
+    candidate_count++;
+  }
+  if (candidate_count == 0) {
+    return nullptr;
+  }
+
+  // size of earliest file
+  int index = file_by_time[file_by_time.size() - 1];
+  uint64_t earliest_file_size = current_->files_[level][index]->file_size;
+
+  // size amplification = percentage of additional size
+  if (candidate_size * 100 < ratio * earliest_file_size) {
+    Log(options_->info_log,
+        "Universal: size amp not needed. newer-files-total-size %lu "
+        "earliest-file-size %lu",
+        (unsigned long)candidate_size,
+        (unsigned long)earliest_file_size);
+    return nullptr;
+  } else {
+    Log(options_->info_log,
+        "Universal: size amp needed. newer-files-total-size %lu "
+        "earliest-file-size %lu",
+        (unsigned long)candidate_size,
+        (unsigned long)earliest_file_size);
+  }
+  assert(start_index >= 0 && start_index < file_by_time.size() - 1);
+
+  // create a compaction request
+  // We always compact all the files, so always compress.
+  Compaction* c = new Compaction(level, level, MaxFileSizeForLevel(level),
+                                 LLONG_MAX, NumberLevels(), false,
+                                 true);
+  c->score_ = score;
+  for (unsigned int loop = start_index; loop < file_by_time.size(); loop++) {
+    int index = file_by_time[loop];
+    f = current_->files_[level][index];
+    c->inputs_[0].push_back(f);
+    Log(options_->info_log,
+        "Universal: size amp picking file %lu[%d] with size %lu",
+        (unsigned long)f->number,
+        index,
+        (unsigned long)f->file_size);
+  }
+  return c;
+}
+
+//
+// Consider compaction files based on their size differences with
+// the next file in time order.
+//
+Compaction* VersionSet::PickCompactionUniversalReadAmp(
+    int level, double score, unsigned int ratio,
+    unsigned int max_number_of_files_to_compact) {
+
+  unsigned int min_merge_width =
+    options_->compaction_options_universal.min_merge_width;
+  unsigned int max_merge_width =
+    options_->compaction_options_universal.max_merge_width;
+
+  // The files are sorted from newest first to oldest last.
+  std::vector<int>& file_by_time = current_->files_by_size_[level];
+  FileMetaData* f = nullptr;
+  bool done = false;
+  int start_index = 0;
+  unsigned int candidate_count;
+  assert(file_by_time.size() == current_->files_[level].size());
+
+  unsigned int max_files_to_compact = std::min(max_merge_width,
+                                       max_number_of_files_to_compact);
+  min_merge_width = std::max(min_merge_width, 2U);
+
+  // Considers a candidate file only if it is smaller than the
+  // total size accumulated so far.
+  for (unsigned int loop = 0; loop < file_by_time.size(); loop++) {
+
+    candidate_count = 0;
+
+    // Skip files that are already being compacted
+    for (f = nullptr; loop < file_by_time.size(); loop++) {
+      int index = file_by_time[loop];
+      f = current_->files_[level][index];
+
+      if (!f->being_compacted) {
+        candidate_count = 1;
+        break;
+      }
+      Log(options_->info_log,
+          "Universal: file %lu[%d] being compacted, skipping",
+          (unsigned long)f->number, loop);
+      f = nullptr;
+    }
+
+    // This file is not being compacted. Consider it as the
+    // first candidate to be compacted.
+    uint64_t candidate_size =  f != nullptr? f->file_size : 0;
+    if (f != nullptr) {
+      Log(options_->info_log, "Universal: Possible candidate file %lu[%d].",
+          (unsigned long)f->number, loop);
+    }
+
+    // Check if the suceeding files need compaction.
+    for (unsigned int i = loop+1;
+         candidate_count < max_files_to_compact && i < file_by_time.size();
+         i++) {
+      int index = file_by_time[i];
+      FileMetaData* f = current_->files_[level][index];
+      if (f->being_compacted) {
+        break;
+      }
+      // pick files if the total candidate file size (increased by the
+      // specified ratio) is still larger than the next candidate file.
+      uint64_t sz = (candidate_size * (100L + ratio)) /100;
+      if (sz < f->file_size) {
+        break;
+      }
+      candidate_count++;
+      candidate_size += f->file_size;
+    }
+
+    // Found a series of consecutive files that need compaction.
+    if (candidate_count >= (unsigned int)min_merge_width) {
+      start_index = loop;
+      done = true;
+      break;
+    } else {
+      for (unsigned int i = loop;
+           i < loop + candidate_count && i < file_by_time.size(); i++) {
+       int index = file_by_time[i];
+       FileMetaData* f = current_->files_[level][index];
+       Log(options_->info_log,
+           "Universal: Skipping file %lu[%d] with size %lu %d\n",
+           (unsigned long)f->number,
+           i,
+           (unsigned long)f->file_size,
+           f->being_compacted);
+      }
+    }
+  }
+  if (!done || candidate_count <= 1) {
+    return nullptr;
+  }
+  unsigned int first_index_after = start_index + candidate_count;
+  // Compression is enabled if files compacted earlier already reached
+  // size ratio of compression.
+  bool enable_compression = true;
+  int ratio_to_compress =
+      options_->compaction_options_universal.compression_size_percent;
+  if (ratio_to_compress >= 0) {
+    uint64_t total_size = TotalFileSize(current_->files_[level]);
+    uint64_t older_file_size = 0;
+    for (unsigned int i = file_by_time.size() - 1; i >= first_index_after;
+        i--) {
+      older_file_size += current_->files_[level][file_by_time[i]]->file_size;
+      if (older_file_size * 100L >= total_size * (long) ratio_to_compress) {
+        enable_compression = false;
+        break;
+      }
+    }
+  }
+  Compaction* c = new Compaction(level, level, MaxFileSizeForLevel(level),
+                                 LLONG_MAX, NumberLevels(), false,
+                                 enable_compression);
+  c->score_ = score;
+
+  for (unsigned int i = start_index; i < first_index_after; i++) {
+    int index = file_by_time[i];
+    FileMetaData* f = current_->files_[level][index];
+    c->inputs_[0].push_back(f);
+    Log(options_->info_log, "Universal: Picking file %lu[%d] with size %lu\n",
+        (unsigned long)f->number,
+        i,
+        (unsigned long)f->file_size);
+  }
+  return c;
+}
+
+//
+// Universal style of compaction. Pick files that are contiguous in
+// time-range to compact.
+//
+Compaction* VersionSet::PickCompactionUniversal(int level, double score) {
+  assert (level == 0);
+
+  if ((current_->files_[level].size() <
+      (unsigned int)options_->level0_file_num_compaction_trigger)) {
+    Log(options_->info_log, "Universal: nothing to do\n");
+    return nullptr;
+  }
+  VersionSet::FileSummaryStorage tmp;
+  Log(options_->info_log, "Universal: candidate files(%lu): %s\n",
+      current_->files_[level].size(),
+      LevelFileSummary(&tmp, 0));
+
+  // Check for size amplification first.
+  Compaction* c = PickCompactionUniversalSizeAmp(level, score);
+  if (c == nullptr) {
+
+    // Size amplification is within limits. Try reducing read
+    // amplification while maintaining file size ratios.
+    unsigned int ratio = options_->compaction_options_universal.size_ratio;
+    c = PickCompactionUniversalReadAmp(level, score, ratio, UINT_MAX);
+
+    // Size amplification and file size ratios are within configured limits.
+    // If max read amplification is exceeding configured limits, then force
+    // compaction without looking at filesize ratios and try to reduce
+    // the number of files to fewer than level0_file_num_compaction_trigger.
+    if (c == nullptr) {
+      unsigned int num_files = current_->files_[level].size() -
+                               options_->level0_file_num_compaction_trigger;
+      c = PickCompactionUniversalReadAmp(level, score, UINT_MAX, num_files);
+    }
+  }
+  if (c == nullptr) {
+    return nullptr;
+  }
+  assert(c->inputs_[0].size() > 1);
+
+  // validate that all the chosen files are non overlapping in time
+  FileMetaData* newerfile __attribute__((unused)) = nullptr;
+  for (unsigned int i = 0; i < c->inputs_[0].size(); i++) {
+    FileMetaData* f = c->inputs_[0][i];
+    assert (f->smallest_seqno <= f->largest_seqno);
+    assert(newerfile == nullptr ||
+           newerfile->smallest_seqno > f->largest_seqno);
+    newerfile = f;
+  }
+
+  // The files are sorted from newest first to oldest last.
+  std::vector<int>& file_by_time = current_->files_by_size_[level];
+
+  // Is the earliest file part of this compaction?
+  int last_index = file_by_time[file_by_time.size()-1];
+  FileMetaData* last_file = current_->files_[level][last_index];
+  if (c->inputs_[0][c->inputs_[0].size()-1] == last_file) {
+    c->bottommost_level_ = true;
+  }
+
+  // update statistics
+  if (options_->statistics != nullptr) {
+    options_->statistics->measureTime(NUM_FILES_IN_SINGLE_COMPACTION,
+                                      c->inputs_[0].size());
+  }
+
+  c->input_version_ = current_;
+  c->input_version_->Ref();
+
+  // mark all the files that are being compacted
+  c->MarkFilesBeingCompacted(true);
+
+  // remember this currently undergoing compaction
+  compactions_in_progress_[level].insert(c);
+
+  // Record whether this compaction includes all sst files.
+  // For now, it is only relevant in universal compaction mode.
+  c->is_full_compaction_ = (c->inputs_[0].size() == current_->files_[0].size());
+
+  return c;
+}
+
+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, level+1, MaxFileSizeForLevel(level+1),
+      MaxGrandParentOverlapBytes(level), NumberLevels());
+  c->score_ = score;
+
+  // Pick the largest file in this level that is not already
+  // being compacted
+  std::vector<int>& 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.
+  std::vector<uint64_t> size_being_compacted(NumberLevels()-1);
+  current_->vset_->SizeBeingCompacted(size_being_compacted);
+  Finalize(current_, size_being_compacted);
+
+  // In universal style of compaction, compact L0 files back into L0.
+  if (options_->compaction_style ==  kCompactionStyleUniversal) {
+    int level = 0;
+    c = PickCompactionUniversal(level, current_->compaction_score_[level]);
+    return c;
+  }
+
+  // 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]);
+      ExpandWhileOverlapping(c);
+      if (c != nullptr) {
+        break;
+      }
+    }
+  }
+
+  // Find compactions needed by seeks
+  FileMetaData* f = current_->file_to_compact_;
+  if (c == nullptr && f != nullptr && !f->being_compacted) {
+
+    level = current_->file_to_compact_level_;
+    int parent_index = -1;
+
+    // Only allow one level 0 compaction at a time.
+    // Do not pick this file if its parents at level+1 are being compacted.
+    if (level != 0 || compactions_in_progress_[0].empty()) {
+      if(!ParentRangeInCompaction(&f->smallest, &f->largest, level,
+                                  &parent_index)) {
+        c = new Compaction(level, level+1, MaxFileSizeForLevel(level+1),
+                MaxGrandParentOverlapBytes(level), NumberLevels(), true);
+        c->inputs_[0].push_back(f);
+        c->parent_index_ = parent_index;
+        current_->file_to_compact_ = nullptr;
+        ExpandWhileOverlapping(c);
+      }
+    }
+  }
+
+  if (c == nullptr) {
+    return nullptr;
+  }
+
+  c->input_version_ = current_;
+  c->input_version_->Ref();
+
+  // 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 we include more L0 files in the same compaction run it can
+    // cause the 'smallest' and 'largest' key to get extended to a
+    // larger range. So, re-invoke GetRange to get the new key range
+    GetRange(c->inputs_[0], &smallest, &largest);
+    if (ParentRangeInCompaction(&smallest, &largest,
+                                level, &c->parent_index_)) {
+      delete c;
+      return nullptr;
+    }
+    assert(!c->inputs_[0].empty());
+  }
+
+  // Setup "level+1" files (inputs_[1])
+  SetupOtherInputs(c);
+
+  // mark all the files that are being compacted
+  c->MarkFilesBeingCompacted(true);
+
+  // Is this compaction creating a file at the bottommost level
+  c->SetupBottomMostLevel(false);
+
+  // 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<FileMetaData*> 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<FileMetaData*>& files) {
+  for (unsigned int i = 0; i < files.size(); i++) {
+    if (files[i]->being_compacted) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Add more files to the inputs on "level" to make sure that
+// no newer version of a key is compacted to "level+1" while leaving an older
+// version in a "level". Otherwise, any Get() will search "level" first,
+// and will likely return an old/stale value for the key, since it always
+// searches in increasing order of level to find the value. This could
+// also scramble the order of merge operands. This function should be
+// called any time a new Compaction is created, and its inputs_[0] are
+// populated.
+//
+// Will set c to nullptr if it is impossible to apply this compaction.
+void VersionSet::ExpandWhileOverlapping(Compaction* c) {
+  // If inputs are empty then there is nothing to expand.
+  if (!c || c->inputs_[0].empty()) {
+    return;
+  }
+
+  // GetOverlappingInputs will always do the right thing for level-0.
+  // So we don't need to do any expansion if level == 0.
+  if (c->level() == 0) {
+    return;
+  }
+
+  const int level = c->level();
+  InternalKey smallest, largest;
+
+  // Keep expanding c->inputs_[0] until we are sure that there is a
+  // "clean cut" boundary between the files in input and the surrounding files.
+  // This will ensure that no parts of a key are lost during compaction.
+  int hint_index = -1;
+  size_t old_size;
+  do {
+    old_size = c->inputs_[0].size();
+    GetRange(c->inputs_[0], &smallest, &largest);
+    c->inputs_[0].clear();
+    current_->GetOverlappingInputs(level, &smallest, &largest, &c->inputs_[0],
+                                   hint_index, &hint_index);
+  } while(c->inputs_[0].size() > old_size);
+
+  // Get the new range
+  GetRange(c->inputs_[0], &smallest, &largest);
+
+  // If, after the expansion, there are files that are already under
+  // compaction, then we must drop/cancel this compaction.
+  int parent_index = -1;
+  if (FilesInCompaction(c->inputs_[0]) ||
+      ParentRangeInCompaction(&smallest, &largest, level, &parent_index)) {
+    c->inputs_[0].clear();
+    c->inputs_[1].clear();
+    delete c;
+    c = nullptr;
+  }
+}
+
+// Populates the set of inputs from "level+1" that overlap with "level".
+// Will also attempt to expand "level" if that doesn't expand "level+1"
+// or cause "level" to include a file for compaction that has an overlapping
+// user-key with another file.
+void VersionSet::SetupOtherInputs(Compaction* c) {
+  // If inputs are empty, then there is nothing to expand.
+  if (c->inputs_[0].empty()) {
+    return;
+  }
+
+  const int level = c->level();
+  InternalKey smallest, largest;
+
+  // Get the range one last time.
+  GetRange(c->inputs_[0], &smallest, &largest);
+
+  // Populate the set of next-level files (inputs_[1]) to include in compaction
+  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 further grow the number of inputs in "level" without
+  // changing the number of "level+1" files we pick up. We also choose NOT
+  // to expand if this would cause "level" to include some entries for some
+  // user key, while excluding other entries for the same user key. This
+  // can happen when one user key spans multiple files.
+  if (!c->inputs_[1].empty()) {
+    std::vector<FileMetaData*> expanded0;
+    current_->GetOverlappingInputs(level, &all_start, &all_limit, &expanded0,
+                                   c->base_index_, nullptr);
+    const uint64_t inputs0_size = TotalFileSize(c->inputs_[0]);
+    const uint64_t inputs1_size = TotalFileSize(c->inputs_[1]);
+    const uint64_t expanded0_size = TotalFileSize(expanded0);
+    uint64_t limit = ExpandedCompactionByteSizeLimit(level);
+    if (expanded0.size() > c->inputs_[0].size() &&
+        inputs1_size + expanded0_size < limit &&
+        !FilesInCompaction(expanded0) &&
+        !current_->HasOverlappingUserKey(&expanded0, level)) {
+      InternalKey new_start, new_limit;
+      GetRange(expanded0, &new_start, &new_limit);
+      std::vector<FileMetaData*> 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@%lu %lu+%lu (%lu+%lu bytes) to %lu+%lu (%lu+%lu bytes)"
+            "\n",
+            (unsigned long)level,
+            (unsigned long)(c->inputs_[0].size()),
+            (unsigned long)(c->inputs_[1].size()),
+            (unsigned long)inputs0_size,
+            (unsigned long)inputs1_size,
+            (unsigned long)(expanded0.size()),
+            (unsigned long)(expanded1.size()),
+            (unsigned long)expanded0_size,
+            (unsigned 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);
+}
+
+Status VersionSet::GetMetadataForFile(
+    uint64_t number,
+    int *filelevel,
+    FileMetaData *meta) {
+  for (int level = 0; level < NumberLevels(); level++) {
+    const std::vector<FileMetaData*>& files = current_->files_[level];
+    for (size_t i = 0; i < files.size(); i++) {
+      if (files[i]->number == number) {
+        *meta = *files[i];
+        *filelevel = level;
+        return Status::OK();
+      }
+    }
+  }
+  return Status::NotFound("File not present in any level");
+}
+
+void VersionSet::GetLiveFilesMetaData(
+    std::vector<LiveFileMetaData> * metadata) {
+  for (int level = 0; level < NumberLevels(); level++) {
+    const std::vector<FileMetaData*>& files = current_->files_[level];
+    for (size_t i = 0; i < files.size(); i++) {
+      LiveFileMetaData filemetadata;
+      filemetadata.name = TableFileName("", files[i]->number);
+      filemetadata.level = level;
+      filemetadata.size = files[i]->file_size;
+      filemetadata.smallestkey = files[i]->smallest.user_key().ToString();
+      filemetadata.largestkey = files[i]->largest.user_key().ToString();
+      filemetadata.smallest_seqno = files[i]->smallest_seqno;
+      filemetadata.largest_seqno = files[i]->largest_seqno;
+      metadata->push_back(filemetadata);
+    }
+  }
+}
+
+void VersionSet::GetObsoleteFiles(std::vector<FileMetaData*>* files) {
+  files->insert(files->end(),
+                obsolete_files_.begin(),
+                obsolete_files_.end());
+  obsolete_files_.clear();
+}
+
+Compaction* VersionSet::CompactRange(
+    int level,
+    const InternalKey* begin,
+    const InternalKey* end) {
+  std::vector<FileMetaData*> inputs;
+
+  // All files are 'overlapping' in universal style compaction.
+  // We have to compact the entire range in one shot.
+  if (options_->compaction_style == kCompactionStyleUniversal) {
+    begin = nullptr;
+    end = nullptr;
+  }
+  current_->GetOverlappingInputs(level, begin, end, &inputs);
+  if (inputs.empty()) {
+    return nullptr;
+  }
+
+  // Avoid compacting too much in one shot in case the range is large.
+  // But we cannot do this for level-0 since level-0 files can overlap
+  // and we must not pick one file and drop another older file if the
+  // two files overlap.
+  if (level > 0) {
+    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;
+      }
+    }
+  }
+  int out_level = (options_->compaction_style == kCompactionStyleUniversal) ?
+                  level : level+1;
+
+  Compaction* c = new Compaction(level, out_level, MaxFileSizeForLevel(out_level),
+    MaxGrandParentOverlapBytes(level), NumberLevels());
+
+  c->inputs_[0] = inputs;
+  ExpandWhileOverlapping(c);
+  if (c == nullptr) {
+    Log(options_->info_log, "Could not compact due to expansion failure.\n");
+    return nullptr;
+  }
+
+  c->input_version_ = current_;
+  c->input_version_->Ref();
+  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);
+
+  // Is this compaction creating a file at the bottommost level
+  c->SetupBottomMostLevel(true);
+  return c;
+}
+
+Compaction::Compaction(int level, int out_level, uint64_t target_file_size,
+  uint64_t max_grandparent_overlap_bytes, int number_levels,
+  bool seek_compaction, bool enable_compression)
+    : level_(level),
+      out_level_(out_level),
+      max_output_file_size_(target_file_size),
+      maxGrandParentOverlapBytes_(max_grandparent_overlap_bytes),
+      input_version_(nullptr),
+      number_levels_(number_levels),
+      seek_compaction_(seek_compaction),
+      enable_compression_(enable_compression),
+      grandparent_index_(0),
+      seen_key_(false),
+      overlapped_bytes_(0),
+      base_index_(-1),
+      parent_index_(-1),
+      score_(0),
+      bottommost_level_(false),
+      is_full_compaction_(false),
+      level_ptrs_(std::vector<size_t>(number_levels)) {
+  edit_ = new VersionEdit(number_levels_);
+  for (int i = 0; i < number_levels_; i++) {
+    level_ptrs_[i] = 0;
+  }
+}
+
+Compaction::~Compaction() {
+  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) {
+  if (input_version_->vset_->options_->compaction_style ==
+      kCompactionStyleUniversal) {
+    return bottommost_level_;
+  }
+  // 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<FileMetaData*>& 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<FileMetaData*> 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;
+    }
+  }
+}
+
+// Is this compaction producing files at the bottommost level?
+void Compaction::SetupBottomMostLevel(bool isManual) {
+  if (input_version_->vset_->options_->compaction_style  ==
+         kCompactionStyleUniversal) {
+    // If universal compaction style is used and manual
+    // compaction is occuring, then we are guaranteed that
+    // all files will be picked in a single compaction
+    // run. We can safely set bottommost_level_ = true.
+    // If it is not manual compaction, then bottommost_level_
+    // is already set when the Compaction was created.
+    if (isManual) {
+      bottommost_level_ = true;
+    }
+    return;
+  }
+  bottommost_level_ = true;
+  int num_levels = input_version_->vset_->NumberLevels();
+  for (int i = level() + 2; i < num_levels; i++) {
+    if (input_version_->vset_->NumLevelFiles(i) > 0) {
+      bottommost_level_ = false;
+      break;
+    }
+  }
+}
+
+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<FileMetaData*>& 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) ",
+        (unsigned long)files.at(i)->number,
+        (unsigned long)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 %lu Base level %d, seek compaction:%d, inputs:",
+      (unsigned long)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 rocksdb
diff --git a/db/version_set.h b/db/version_set.h
new file mode 100644 (file)
index 0000000..3841517
--- /dev/null
@@ -0,0 +1,654 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <map>
+#include <memory>
+#include <set>
+#include <vector>
+#include <deque>
+#include "db/dbformat.h"
+#include "db/version_edit.h"
+#include "port/port.h"
+#include "db/table_cache.h"
+
+namespace rocksdb {
+
+namespace log { class Writer; }
+
+class Compaction;
+class Iterator;
+class MemTable;
+class TableCache;
+class Version;
+class VersionSet;
+
+// 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<FileMetaData*>& 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<FileMetaData*>& 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&, const EnvOptions& soptions,
+                    std::vector<Iterator*>* iters);
+
+  // Lookup the value for key.  If found, store it in *val and
+  // return OK.  Else return a non-OK status.  Fills *stats.
+  // Uses *operands to store merge_operator operations to apply later
+  // REQUIRES: lock is not held
+  struct GetStats {
+    FileMetaData* seek_file;
+    int seek_file_level;
+  };
+  void Get(const ReadOptions&, const LookupKey& key, std::string* val,
+           Status* status, std::deque<std::string>* operands, GetStats* stats,
+           const Options& db_option,
+           bool* value_found = nullptr);
+
+  // 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<FileMetaData*>* 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<FileMetaData*>* 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<FileMetaData*>* inputs,
+      unsigned 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);
+
+  // Returns true iff the first or last file in inputs contains
+  // an overlapping user key to the file "just outside" of it (i.e.
+  // just after the last file, or just before the first file)
+  // REQUIRES: "*inputs" is a sorted list of non-overlapping files
+  bool HasOverlappingUserKey(const std::vector<FileMetaData*>* inputs,
+                             int level);
+
+
+  // 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;
+  friend class DBImpl;
+
+  class LevelFileNumIterator;
+  Iterator* NewConcatenatingIterator(const ReadOptions&,
+                                     const EnvOptions& soptions,
+                                     int level) const;
+  bool PrefixMayMatch(const ReadOptions& options, const EnvOptions& soptions,
+                      const Slice& internal_prefix, Iterator* level_iter) 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<FileMetaData*>* 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<int> > files_by_size_;
+
+  // An index into files_by_size_ that specifies the first
+  // file that is not yet compacted
+  std::vector<int> 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<double> compaction_score_;
+  std::vector<int> 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,
+             const EnvOptions& storage_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 {
+    // In universal compaction case, this check doesn't really
+    // check the compaction condition, but checks num of files threshold
+    // only. We are not going to miss any compaction opportunity
+    // but it's likely that more compactions are scheduled but
+    // ending up with nothing to do. We can improve it later.
+    // TODO: improve this function to be accurate for universal
+    //       compactions.
+    int num_levels_to_check =
+        (options_->compaction_style != kCompactionStyleUniversal) ?
+            NumberLevels() - 1 : 1;
+    for (int i = 0; i < num_levels_to_check; 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.
+  void AddLiveFiles(std::vector<uint64_t>* live_list);
+
+  // Add all files listed in the current version to *live.
+  void AddLiveFilesCurrentVersion(std::set<uint64_t>* 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];
+  };
+  struct FileSummaryStorage {
+    char buffer[1000];
+  };
+  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 a human-readable short (single-line) summary of files
+  // in a specified level.  Uses *scratch as backing store.
+  const char* LevelFileSummary(FileSummaryStorage* scratch, int level) 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);
+
+  // Pick files to compact in Universal mode
+  Compaction* PickCompactionUniversal(int level, double score);
+
+  // Pick Universal compaction to limit read amplification
+  Compaction* PickCompactionUniversalReadAmp(int level, double score,
+                unsigned int ratio, unsigned int num_files);
+
+  // Pick Universal compaction to limit space amplification.
+  Compaction* PickCompactionUniversalSizeAmp(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);
+
+  double MaxBytesForLevel(int level);
+
+  Status GetMetadataForFile(
+    uint64_t number, int *filelevel, FileMetaData *metadata);
+
+  void GetLiveFilesMetaData(
+    std::vector<LiveFileMetaData> *metadata);
+
+  void GetObsoleteFiles(std::vector<FileMetaData*>* files);
+
+ private:
+  class Builder;
+  struct ManifestWriter;
+
+  friend class Compaction;
+  friend class Version;
+
+  void Init(int num_levels);
+
+  void Finalize(Version* v, std::vector<uint64_t>&);
+
+  void GetRange(const std::vector<FileMetaData*>& inputs,
+                InternalKey* smallest,
+                InternalKey* largest);
+
+  void GetRange2(const std::vector<FileMetaData*>& inputs1,
+                 const std::vector<FileMetaData*>& inputs2,
+                 InternalKey* smallest,
+                 InternalKey* largest);
+
+  void ExpandWhileOverlapping(Compaction* c);
+
+  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;
+
+  uint64_t ExpandedCompactionByteSizeLimit(int level);
+
+  uint64_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<log::Writer> 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<std::set<Compaction*> > 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<ManifestWriter*> 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_;
+
+  std::vector<FileMetaData*> obsolete_files_;
+
+  // storage options for all reads and writes except compactions
+  const EnvOptions& storage_options_;
+
+  // storage options used for compactions. This is a copy of
+  // storage_options_ but with readaheads set to readahead_compactions_.
+  const EnvOptions storage_options_compactions_;
+
+  // No copying allowed
+  VersionSet(const VersionSet&);
+  void operator=(const VersionSet&);
+
+  // Return the total amount of data that is undergoing
+  // compactions per level
+  void SizeBeingCompacted(std::vector<uint64_t>&);
+
+  // 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<FileMetaData*>& 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"
+  // will be merged.
+  int level() const { return level_; }
+
+  // Outputs will go to this level
+  int output_level() const { return out_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_; }
+
+  // Whether compression will be enabled for compaction outputs
+  bool enable_compression() const { return enable_compression_; }
+
+  // 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_; }
+
+  // Is this compaction creating a file in the bottom most level?
+  bool BottomMostLevel() { return bottommost_level_; }
+
+  // Does this compaction include all sst files?
+  bool IsFullCompaction() { return is_full_compaction_; }
+
+ private:
+  friend class Version;
+  friend class VersionSet;
+
+  explicit Compaction(int level, int out_level, uint64_t target_file_size,
+    uint64_t max_grandparent_overlap_bytes, int number_levels,
+    bool seek_compaction = false, bool enable_compression = true);
+
+  int level_;
+  int out_level_; // levels to which output files are stored
+  uint64_t max_output_file_size_;
+  uint64_t maxGrandParentOverlapBytes_;
+  Version* input_version_;
+  VersionEdit* edit_;
+  int number_levels_;
+
+  bool seek_compaction_;
+  bool enable_compression_;
+
+  // Each compaction reads inputs from "level_" and "level_+1"
+  std::vector<FileMetaData*> 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<FileMetaData*> grandparents_;
+  size_t grandparent_index_;  // Index in grandparent_starts_
+  bool seen_key_;             // Some output key has been seen
+  uint64_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.
+
+  // Is this compaction creating a file in the bottom most level?
+  bool bottommost_level_;
+  // Does this compaction include all sst files?
+  bool is_full_compaction_;
+
+  // 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).
+  std::vector<size_t> level_ptrs_;
+
+  // mark (or clear) all files that are being compacted
+  void MarkFilesBeingCompacted(bool);
+
+  // Initialize whether compaction producing files at the bottommost level
+  void SetupBottomMostLevel(bool isManual);
+
+  // 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 rocksdb
diff --git a/db/version_set_reduce_num_levels.cc b/db/version_set_reduce_num_levels.cc
new file mode 100644 (file)
index 0000000..d13a4ae
--- /dev/null
@@ -0,0 +1,80 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <algorithm>
+#include <stdio.h>
+#include "db/log_reader.h"
+#include "db/log_writer.h"
+#include "util/logging.h"
+
+namespace rocksdb {
+
+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<FileMetaData*>*  old_files_list = current_version->files_;
+  std::vector<FileMetaData*>* new_files_list =
+      new std::vector<FileMetaData*>[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);
+  VersionEdit ve(new_levels);
+  st = LogAndApply(&ve , mu, true);
+  return st;
+}
+
+}
diff --git a/db/version_set_test.cc b/db/version_set_test.cc
new file mode 100644 (file)
index 0000000..1af95dd
--- /dev/null
@@ -0,0 +1,184 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 rocksdb {
+
+class FindFileTest {
+ public:
+  std::vector<FileMetaData*> 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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/db/write_batch.cc b/db/write_batch.cc
new file mode 100644 (file)
index 0000000..134cfb6
--- /dev/null
@@ -0,0 +1,247 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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
+//    kTypeMerge varstring varstring
+//    kTypeDeletion varstring
+// varstring :=
+//    len: varint32
+//    data: uint8[len]
+
+#include "rocksdb/write_batch.h"
+
+#include "rocksdb/options.h"
+#include "rocksdb/statistics.h"
+#include "db/dbformat.h"
+#include "db/db_impl.h"
+#include "db/memtable.h"
+#include "db/snapshot.h"
+#include "db/write_batch_internal.h"
+#include "util/coding.h"
+#include <stdexcept>
+
+namespace rocksdb {
+
+// 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::Handler::Merge(const Slice& key, const Slice& value) {
+  throw std::runtime_error("Handler::Merge not implemented!");
+}
+
+void WriteBatch::Handler::LogData(const Slice& blob) {
+  // If the user has not specified something to do with blobs, then we ignore
+  // them.
+}
+
+bool WriteBatch::Handler::Continue() {
+  return true;
+}
+
+void WriteBatch::Clear() {
+  rep_.clear();
+  rep_.resize(kHeader);
+}
+
+int WriteBatch::Count() const {
+  return WriteBatchInternal::Count(this);
+}
+
+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, blob;
+  int found = 0;
+  while (!input.empty() && handler->Continue()) {
+    char tag = input[0];
+    input.remove_prefix(1);
+    switch (tag) {
+      case kTypeValue:
+        if (GetLengthPrefixedSlice(&input, &key) &&
+            GetLengthPrefixedSlice(&input, &value)) {
+          handler->Put(key, value);
+          found++;
+        } else {
+          return Status::Corruption("bad WriteBatch Put");
+        }
+        break;
+      case kTypeDeletion:
+        if (GetLengthPrefixedSlice(&input, &key)) {
+          handler->Delete(key);
+          found++;
+        } else {
+          return Status::Corruption("bad WriteBatch Delete");
+        }
+        break;
+      case kTypeMerge:
+        if (GetLengthPrefixedSlice(&input, &key) &&
+            GetLengthPrefixedSlice(&input, &value)) {
+          handler->Merge(key, value);
+          found++;
+        } else {
+          return Status::Corruption("bad WriteBatch Merge");
+        }
+        break;
+      case kTypeLogData:
+        if (GetLengthPrefixedSlice(&input, &blob)) {
+          handler->LogData(blob);
+        } else {
+          return Status::Corruption("bad WriteBatch Blob");
+        }
+        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<char>(kTypeValue));
+  PutLengthPrefixedSlice(&rep_, key);
+  PutLengthPrefixedSlice(&rep_, value);
+}
+
+void WriteBatch::Put(const SliceParts& key, const SliceParts& value) {
+  WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
+  rep_.push_back(static_cast<char>(kTypeValue));
+  PutLengthPrefixedSliceParts(&rep_, key);
+  PutLengthPrefixedSliceParts(&rep_, value);
+}
+
+void WriteBatch::Delete(const Slice& key) {
+  WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
+  rep_.push_back(static_cast<char>(kTypeDeletion));
+  PutLengthPrefixedSlice(&rep_, key);
+}
+
+void WriteBatch::Merge(const Slice& key, const Slice& value) {
+  WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
+  rep_.push_back(static_cast<char>(kTypeMerge));
+  PutLengthPrefixedSlice(&rep_, key);
+  PutLengthPrefixedSlice(&rep_, value);
+}
+
+void WriteBatch::PutLogData(const Slice& blob) {
+  rep_.push_back(static_cast<char>(kTypeLogData));
+  PutLengthPrefixedSlice(&rep_, blob);
+}
+
+namespace {
+class MemTableInserter : public WriteBatch::Handler {
+ public:
+  SequenceNumber sequence_;
+  MemTable* mem_;
+  const Options* options_;
+  DBImpl* db_;
+  const bool filter_deletes_;
+
+  MemTableInserter(SequenceNumber sequence, MemTable* mem, const Options* opts,
+                   DB* db, const bool filter_deletes)
+    : sequence_(sequence),
+      mem_(mem),
+      options_(opts),
+      db_(reinterpret_cast<DBImpl*>(db)),
+      filter_deletes_(filter_deletes) {
+    assert(mem_);
+    if (filter_deletes_) {
+      assert(options_);
+      assert(db_);
+    }
+  }
+
+  virtual void Put(const Slice& key, const Slice& value) {
+    if (options_->inplace_update_support
+        && mem_->Update(sequence_, kTypeValue, key, value)) {
+      RecordTick(options_->statistics, NUMBER_KEYS_UPDATED);
+    } else {
+      mem_->Add(sequence_, kTypeValue, key, value);
+    }
+    sequence_++;
+  }
+  virtual void Merge(const Slice& key, const Slice& value) {
+    mem_->Add(sequence_, kTypeMerge, key, value);
+    sequence_++;
+  }
+  virtual void Delete(const Slice& key) {
+    if (filter_deletes_) {
+      SnapshotImpl read_from_snapshot;
+      read_from_snapshot.number_ = sequence_;
+      ReadOptions ropts;
+      ropts.snapshot = &read_from_snapshot;
+      std::string value;
+      if (!db_->KeyMayExist(ropts, key, &value)) {
+        RecordTick(options_->statistics, NUMBER_FILTERED_DELETES);
+        return;
+      }
+    }
+    mem_->Add(sequence_, kTypeDeletion, key, Slice());
+    sequence_++;
+  }
+};
+}  // namespace
+
+Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* mem,
+                                      const Options* opts, DB* db,
+                                      const bool filter_deletes) {
+  MemTableInserter inserter(WriteBatchInternal::Sequence(b), mem, opts, db,
+                            filter_deletes);
+  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 rocksdb
diff --git a/db/write_batch_internal.h b/db/write_batch_internal.h
new file mode 100644 (file)
index 0000000..b899173
--- /dev/null
@@ -0,0 +1,57 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include "rocksdb/types.h"
+#include "rocksdb/write_batch.h"
+#include "rocksdb/db.h"
+#include "rocksdb/options.h"
+
+namespace rocksdb {
+
+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);
+
+  // Inserts batch entries into memtable
+  // Drops deletes in batch if filter_del is set to true and
+  // db->KeyMayExist returns false
+  static Status InsertInto(const WriteBatch* batch, MemTable* memtable,
+                           const Options* opts, DB* db = nullptr,
+                           const bool filter_del = false);
+
+  static void Append(WriteBatch* dst, const WriteBatch* src);
+};
+
+}  // namespace rocksdb
diff --git a/db/write_batch_test.cc b/db/write_batch_test.cc
new file mode 100644 (file)
index 0000000..4aba21c
--- /dev/null
@@ -0,0 +1,262 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/db.h"
+
+#include <memory>
+#include "db/memtable.h"
+#include "db/write_batch_internal.h"
+#include "rocksdb/env.h"
+#include "rocksdb/memtablerep.h"
+#include "util/logging.h"
+#include "util/testharness.h"
+
+namespace rocksdb {
+
+static std::string PrintContents(WriteBatch* b) {
+  InternalKeyComparator cmp(BytewiseComparator());
+  auto factory = std::make_shared<SkipListFactory>();
+  MemTable* mem = new MemTable(cmp, factory);
+  mem->Ref();
+  std::string state;
+  Options options;
+  Status s = WriteBatchInternal::InsertInto(b, mem, &options);
+  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 kTypeMerge:
+        state.append("Merge(");
+        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;
+      case kTypeLogData:
+        assert(false);
+        break;
+    }
+    state.append("@");
+    state.append(NumberToString(ikey.sequence));
+  }
+  delete iter;
+  if (!s.ok()) {
+    state.append(s.ToString());
+  } 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));
+  ASSERT_EQ(0, batch.Count());
+}
+
+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));
+  ASSERT_EQ(3, batch.Count());
+}
+
+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"
+            "Corruption: bad WriteBatch Delete",
+            PrintContents(&batch));
+}
+
+TEST(WriteBatchTest, Append) {
+  WriteBatch b1, b2;
+  WriteBatchInternal::SetSequence(&b1, 200);
+  WriteBatchInternal::SetSequence(&b2, 300);
+  WriteBatchInternal::Append(&b1, &b2);
+  ASSERT_EQ("",
+            PrintContents(&b1));
+  ASSERT_EQ(0, b1.Count());
+  b2.Put("a", "va");
+  WriteBatchInternal::Append(&b1, &b2);
+  ASSERT_EQ("Put(a, va)@200",
+            PrintContents(&b1));
+  ASSERT_EQ(1, b1.Count());
+  b2.Clear();
+  b2.Put("b", "vb");
+  WriteBatchInternal::Append(&b1, &b2);
+  ASSERT_EQ("Put(a, va)@200"
+            "Put(b, vb)@201",
+            PrintContents(&b1));
+  ASSERT_EQ(2, b1.Count());
+  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));
+  ASSERT_EQ(4, b1.Count());
+}
+
+namespace {
+  struct TestHandler : public WriteBatch::Handler {
+    std::string seen;
+    virtual void Put(const Slice& key, const Slice& value) {
+      seen += "Put(" + key.ToString() + ", " + value.ToString() + ")";
+    }
+    virtual void Merge(const Slice& key, const Slice& value) {
+      seen += "Merge(" + key.ToString() + ", " + value.ToString() + ")";
+    }
+    virtual void LogData(const Slice& blob) {
+      seen += "LogData(" + blob.ToString() + ")";
+    }
+    virtual void Delete(const Slice& key) {
+      seen += "Delete(" + key.ToString() + ")";
+    }
+  };
+}
+
+TEST(WriteBatchTest, Blob) {
+  WriteBatch batch;
+  batch.Put(Slice("k1"), Slice("v1"));
+  batch.Put(Slice("k2"), Slice("v2"));
+  batch.Put(Slice("k3"), Slice("v3"));
+  batch.PutLogData(Slice("blob1"));
+  batch.Delete(Slice("k2"));
+  batch.PutLogData(Slice("blob2"));
+  batch.Merge(Slice("foo"), Slice("bar"));
+  ASSERT_EQ(5, batch.Count());
+  ASSERT_EQ("Merge(foo, bar)@4"
+            "Put(k1, v1)@0"
+            "Delete(k2)@3"
+            "Put(k2, v2)@1"
+            "Put(k3, v3)@2",
+            PrintContents(&batch));
+
+  TestHandler handler;
+  batch.Iterate(&handler);
+  ASSERT_EQ(
+            "Put(k1, v1)"
+            "Put(k2, v2)"
+            "Put(k3, v3)"
+            "LogData(blob1)"
+            "Delete(k2)"
+            "LogData(blob2)"
+            "Merge(foo, bar)",
+            handler.seen);
+}
+
+TEST(WriteBatchTest, Continue) {
+  WriteBatch batch;
+
+  struct Handler : public TestHandler {
+    int num_seen = 0;
+    virtual void Put(const Slice& key, const Slice& value) {
+      ++num_seen;
+      TestHandler::Put(key, value);
+    }
+    virtual void Merge(const Slice& key, const Slice& value) {
+      ++num_seen;
+      TestHandler::Merge(key, value);
+    }
+    virtual void LogData(const Slice& blob) {
+      ++num_seen;
+      TestHandler::LogData(blob);
+    }
+    virtual void Delete(const Slice& key) {
+      ++num_seen;
+      TestHandler::Delete(key);
+    }
+    virtual bool Continue() override {
+      return num_seen < 3;
+    }
+  } handler;
+
+  batch.Put(Slice("k1"), Slice("v1"));
+  batch.PutLogData(Slice("blob1"));
+  batch.Delete(Slice("k1"));
+  batch.PutLogData(Slice("blob2"));
+  batch.Merge(Slice("foo"), Slice("bar"));
+  batch.Iterate(&handler);
+  ASSERT_EQ(
+            "Put(k1, v1)"
+            "LogData(blob1)"
+            "Delete(k1)",
+            handler.seen);
+}
+
+TEST(WriteBatchTest, PutGatherSlices) {
+  WriteBatch batch;
+  batch.Put(Slice("foo"), Slice("bar"));
+
+  {
+    // Try a write where the key is one slice but the value is two
+    Slice key_slice("baz");
+    Slice value_slices[2] = { Slice("header"), Slice("payload") };
+    batch.Put(SliceParts(&key_slice, 1),
+              SliceParts(value_slices, 2));
+  }
+
+  {
+    // One where the key is composite but the value is a single slice
+    Slice key_slices[3] = { Slice("key"), Slice("part2"), Slice("part3") };
+    Slice value_slice("value");
+    batch.Put(SliceParts(key_slices, 3),
+              SliceParts(&value_slice, 1));
+  }
+
+  WriteBatchInternal::SetSequence(&batch, 100);
+  ASSERT_EQ("Put(baz, headerpayload)@101"
+            "Put(foo, bar)@100"
+            "Put(keypart2part3, value)@102",
+            PrintContents(&batch));
+  ASSERT_EQ(3, batch.Count());
+}
+
+}  // namespace rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/doc/doc.css b/doc/doc.css
new file mode 100644 (file)
index 0000000..700c564
--- /dev/null
@@ -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/index.html b/doc/index.html
new file mode 100644 (file)
index 0000000..088a737
--- /dev/null
@@ -0,0 +1,831 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" type="text/css" href="doc.css" />
+<title>RocksDB</title>
+</head>
+
+<body>
+<h1>RocksDB</h1>
+<address>The Facebook Database Engineering Team</address>
+<address>Build on earlier work on leveldb by Sanjay Ghemawat
+               (sanjay@google.com) and Jeff Dean (jeff@google.com)</address>
+<p>
+The <code>rocksdb</code> 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.
+
+<p>
+<h1>Opening A Database</h1>
+<p>
+A <code>rocksdb</code> 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:
+<p>
+<pre>
+  #include &lt;assert&gt;
+  #include "rocksdb/db.h"
+
+  rocksdb::DB* db;
+  rocksdb::Options options;
+  options.create_if_missing = true;
+  rocksdb::Status status = rocksdb::DB::Open(options, "/tmp/testdb", &amp;db);
+  assert(status.ok());
+  ...
+</pre>
+If you want to raise an error if the database already exists, add
+the following line before the <code>rocksdb::DB::Open</code> call:
+<pre>
+  options.error_if_exists = true;
+</pre>
+<h1>Status</h1>
+<p>
+You may have noticed the <code>rocksdb::Status</code> type above.  Values of this
+type are returned by most functions in <code>rocksdb</code> that may encounter an
+error.  You can check if such a result is ok, and also print an
+associated error message:
+<p>
+<pre>
+   rocksdb::Status s = ...;
+   if (!s.ok()) cerr &lt;&lt; s.ToString() &lt;&lt; endl;
+</pre>
+<h1>Closing A Database</h1>
+<p>
+When you are done with a database, just delete the database object.
+Example:
+<p>
+<pre>
+  ... open the db as described above ...
+  ... do something with db ...
+  delete db;
+</pre>
+<h1>Reads And Writes</h1>
+<p>
+The database provides <code>Put</code>, <code>Delete</code>, and <code>Get</code> methods to
+modify/query the database.  For example, the following code
+moves the value stored under key1 to key2.
+<pre>
+  std::string value;
+  rocksdb::Status s = db-&gt;Get(rocksdb::ReadOptions(), key1, &amp;value);
+  if (s.ok()) s = db-&gt;Put(rocksdb::WriteOptions(), key2, value);
+  if (s.ok()) s = db-&gt;Delete(rocksdb::WriteOptions(), key1);
+</pre>
+
+<h1>Atomic Updates</h1>
+<p>
+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 <code>WriteBatch</code> class to
+atomically apply a set of updates:
+<p>
+<pre>
+  #include "leveldb/write_batch.h"
+  ...
+  std::string value;
+  rocksdb::Status s = db-&gt;Get(rocksdb::ReadOptions(), key1, &amp;value);
+  if (s.ok()) {
+    rocksdb::WriteBatch batch;
+    batch.Delete(key1);
+    batch.Put(key2, value);
+    s = db-&gt;Write(rocksdb::WriteOptions(), &amp;batch);
+  }
+</pre>
+The <code>WriteBatch</code> 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 <code>Delete</code> before <code>Put</code> so that if <code>key1</code> is identical to <code>key2</code>,
+we do not end up erroneously dropping the value entirely.
+<p>
+Apart from its atomicity benefits, <code>WriteBatch</code> may also be used to
+speed up bulk updates by placing lots of individual mutations into the
+same batch.
+
+<h1>Synchronous Writes</h1>
+By default, each write to <code>leveldb</code> 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 <code>sync</code> 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 <code>fsync(...)</code> or <code>fdatasync(...)</code> or
+<code>msync(..., MS_SYNC)</code> before the write operation returns.)
+<pre>
+  rocksdb::WriteOptions write_options;
+  write_options.sync = true;
+  db-&gt;Put(write_options, ...);
+</pre>
+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 <code>sync</code> is false, an update
+is pushed from the process memory into the operating system before it
+is considered done.
+
+<p>
+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.)
+
+<p>
+<code>WriteBatch</code> provides an alternative to asynchronous writes.
+Multiple updates may be placed in the same <code>WriteBatch</code> and
+applied together using a synchronous write (i.e.,
+<code>write_options.sync</code> is set to true).  The extra cost of
+the synchronous write will be amortized across all of the writes in
+the batch.
+
+<p>
+We also provide a way to completely disable Write Ahead Log for a
+particular write. If you set write_option.disableWAL to true, the
+write will not go to the log at all and may be lost in an event of
+process crash.
+
+<p>
+When opening a DB, you can disable syncing of data files by setting
+Options::disableDataSync to true. This can be useful when doing
+bulk-loading or big idempotent operations. Once the operation is
+finished, you can manually call sync() to flush all dirty buffers
+to stable storage.
+
+<p>
+RocksDB by default uses faster fdatasync() to sync files. If you want
+to use fsync(), you can set Options::use_fsync to true. You should set
+this to true on filesystems like ext3 that can lose files after a
+reboot.
+
+<p>
+<h1>Concurrency</h1>
+<p>
+A database may only be opened by one process at a time.
+The <code>rocksdb</code> implementation acquires a lock from the
+operating system to prevent misuse.  Within a single process, the
+same <code>rocksdb::DB</code> object may be safely shared by multiple
+concurrent threads.  I.e., different threads may write into or fetch
+iterators or call <code>Get</code> 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.
+
+<p>
+<h1>Merge operators</h1>
+<p>
+Merge operators provide efficient support for read-modify-write operation.
+More on the interface and implementation can be found on:
+<p>
+<a href="https://github.com/facebook/rocksdb/wiki/Merge-Operator">
+    Merge Operator</a>
+<p>
+<a href="https://github.com/facebook/rocksdb/wiki/Merge-Operator-Implementation">
+    Merge Operator Implementation</a>
+
+<p>
+<h1>Iteration</h1>
+<p>
+The following example demonstrates how to print all key,value pairs
+in a database.
+<p>
+<pre>
+  rocksdb::Iterator* it = db-&gt;NewIterator(rocksdb::ReadOptions());
+  for (it-&gt;SeekToFirst(); it-&gt;Valid(); it-&gt;Next()) {
+    cout &lt;&lt; it-&gt;key().ToString() &lt;&lt; ": "  &lt;&lt; it-&gt;value().ToString() &lt;&lt; endl;
+  }
+  assert(it-&gt;status().ok());  // Check for any errors found during the scan
+  delete it;
+</pre>
+The following variation shows how to process just the keys in the
+range <code>[start,limit)</code>:
+<p>
+<pre>
+  for (it-&gt;Seek(start);
+       it-&gt;Valid() &amp;&amp; it-&gt;key().ToString() &lt; limit;
+       it-&gt;Next()) {
+    ...
+  }
+</pre>
+You can also process entries in reverse order.  (Caveat: reverse
+iteration may be somewhat slower than forward iteration.)
+<p>
+<pre>
+  for (it-&gt;SeekToLast(); it-&gt;Valid(); it-&gt;Prev()) {
+    ...
+  }
+</pre>
+<h1>Snapshots</h1>
+<p>
+Snapshots provide consistent read-only views over the entire state of
+the key-value store.  <code>ReadOptions::snapshot</code> may be non-NULL to indicate
+that a read should operate on a particular version of the DB state.
+If <code>ReadOptions::snapshot</code> is NULL, the read will operate on an
+implicit snapshot of the current state.
+<p>
+Snapshots are created by the DB::GetSnapshot() method:
+<p>
+<pre>
+  rocksdb::ReadOptions options;
+  options.snapshot = db-&gt;GetSnapshot();
+  ... apply some updates to db ...
+  rocksdb::Iterator* iter = db-&gt;NewIterator(options);
+  ... read using iter to view the state when the snapshot was created ...
+  delete iter;
+  db-&gt;ReleaseSnapshot(options.snapshot);
+</pre>
+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.
+<h1>Slice</h1>
+<p>
+The return value of the <code>it->key()</code> and <code>it->value()</code> calls above
+are instances of the <code>rocksdb::Slice</code> type.  <code>Slice</code> is a simple
+structure that contains a length and a pointer to an external byte
+array.  Returning a <code>Slice</code> is a cheaper alternative to returning a
+<code>std::string</code> since we do not need to copy potentially large keys and
+values.  In addition, <code>rocksdb</code> methods do not return null-terminated
+C-style strings since <code>rocksdb</code> keys and values are allowed to
+contain '\0' bytes.
+<p>
+C++ strings and null-terminated C-style strings can be easily converted
+to a Slice:
+<p>
+<pre>
+   rocksdb::Slice s1 = "hello";
+
+   std::string str("world");
+   rocksdb::Slice s2 = str;
+</pre>
+A Slice can be easily converted back to a C++ string:
+<pre>
+   std::string str = s1.ToString();
+   assert(str == std::string("hello"));
+</pre>
+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:
+<p>
+<pre>
+   rocksdb::Slice slice;
+   if (...) {
+     std::string str = ...;
+     slice = str;
+   }
+   Use(slice);
+</pre>
+When the <code>if</code> statement goes out of scope, <code>str</code> will be destroyed and the
+backing storage for <code>slice</code> will disappear.
+<p>
+<h1>Comparators</h1>
+<p>
+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 <code>rocksdb::Comparator</code> that expresses these rules:
+<p>
+<pre>
+  class TwoPartComparator : public rocksdb::Comparator {
+   public:
+    // Three-way comparison function:
+    //   if a &lt; b: negative result
+    //   if a &gt; b: positive result
+    //   else: zero result
+    int Compare(const rocksdb::Slice&amp; a, const rocksdb::Slice&amp; b) const {
+      int a1, a2, b1, b2;
+      ParseKey(a, &amp;a1, &amp;a2);
+      ParseKey(b, &amp;b1, &amp;b2);
+      if (a1 &lt; b1) return -1;
+      if (a1 &gt; b1) return +1;
+      if (a2 &lt; b2) return -1;
+      if (a2 &gt; b2) return +1;
+      return 0;
+    }
+
+    // Ignore the following methods for now:
+    const char* Name() const { return "TwoPartComparator"; }
+    void FindShortestSeparator(std::string*, const rocksdb::Slice&amp;) const { }
+    void FindShortSuccessor(std::string*) const { }
+  };
+</pre>
+Now create a database using this custom comparator:
+<p>
+<pre>
+  TwoPartComparator cmp;
+  rocksdb::DB* db;
+  rocksdb::Options options;
+  options.create_if_missing = true;
+  options.comparator = &amp;cmp;
+  rocksdb::Status status = rocksdb::DB::Open(options, "/tmp/testdb", &amp;db);
+  ...
+</pre>
+<h2>Backwards compatibility</h2>
+<p>
+The result of the comparator's <code>Name</code> method is attached to the
+database when it is created, and is checked on every subsequent
+database open.  If the name changes, the <code>rocksdb::DB::Open</code> 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.
+<p>
+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 <code>TwoPartComparator</code>),
+(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.
+
+
+<p>
+<h1>MemTable and Table factories</h1>
+<p>
+By default, we keep the data in memory in skiplist memtable and the data
+on disk in a table format described here:
+<a href="https://github.com/facebook/rocksdb/wiki/Rocksdb-Table-Format">
+    RocksDB Table Format</a>.
+<p>
+Since one of the goals of RocksDB is to have
+different parts of the system easily pluggable, we support different
+implementations of both memtable and table format. You can supply
+your own memtable factory by setting <code>Options::memtable_factory</code>
+and your own table factory by setting <code>Options::table_factory</code>.
+For available memtable factories, please refer to
+<code>rocksdb/memtablerep.h</code> and for table factores to
+<code>rocksdb/table.h</code>. These features are both in active development
+and please be wary of any API changes that might break your application
+going forward.
+<p>
+You can also read more about memtables here:
+<a href="https://github.com/facebook/rocksdb/wiki/Rocksdb-Architecture-Guide#memtables">
+Memtables wiki
+</a>
+
+<p>
+<h1>Performance</h1>
+<p>
+Performance can be tuned by changing the default values of the
+types defined in <code>include/rocksdb/options.h</code>.
+
+<p>
+<h2>Block size</h2>
+<p>
+<code>rocksdb</code> 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. To change block size parameter, use
+<code>Options::block_size</code>.
+<p>
+<h2>Write buffer</h2>
+<p>
+<code>Options::write_buffer_size</code> specifies the amount of data
+to build up in memory 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.
+Related option is
+<code>Options::max_write_buffer_number</code>, which is 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.
+<code>Options::min_write_buffer_number_to_merge</code> is the minimum number
+of write buffers that will be merged together before writing to storage.
+If set to 1, then all write buffers are fushed to L0 as individual files and
+this increases read amplification because a get request has to check in all
+of these files. Also, an in-memory merge may result in writing lesser
+data to storage if there are duplicate records in each of these
+individual write buffers.  Default: 1
+<p>
+<h2>Compression</h2>
+<p>
+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:
+<p>
+<pre>
+  rocksdb::Options options;
+  options.compression = rocksdb::kNoCompression;
+  ... rocksdb::DB::Open(options, name, ...) ....
+</pre>
+<h2>Cache</h2>
+<p>
+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
+<code>options.block_cache</code> is non-NULL, it is used to cache frequently
+used uncompressed block contents. If <code>options.block_cache_compressed</code>
+is non-NULL, it is used to cache frequently used compressed blocks. Compressed
+cache is an alternative to OS cache, which also caches compressed blocks. If
+compressed cache is used, the OS cache will be disabled automatically by setting
+<code>options.allow_os_buffer</code> to false.
+<p>
+<pre>
+  #include "rocksdb/cache.h"
+
+  rocksdb::Options options;
+  options.block_cache = rocksdb::NewLRUCache(100 * 1048576);  // 100MB uncompressed cache
+  options.block_cache_compressed = rocksdb::NewLRUCache(100 * 1048576);  // 100MB compressed cache
+  rocksdb::DB* db;
+  rocksdb::DB::Open(options, name, &db);
+  ... use the db ...
+  delete db
+  delete options.block_cache;
+  delete options.block_cache_compressed;
+</pre>
+<p>
+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:
+<p>
+<pre>
+  rocksdb::ReadOptions options;
+  options.fill_cache = false;
+  rocksdb::Iterator* it = db-&gt;NewIterator(options);
+  for (it-&gt;SeekToFirst(); it-&gt;Valid(); it-&gt;Next()) {
+    ...
+  }
+</pre>
+<p>
+You can also disable block cache by setting <code>options.no_block_cache</code>
+to true.
+<h2>Key Layout</h2>
+<p>
+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.
+<p>
+For example, suppose we are implementing a simple file system on top
+of <code>rocksdb</code>.  The types of entries we might wish to store are:
+<p>
+<pre>
+   filename -&gt; permission-bits, length, list of file_block_ids
+   file_block_id -&gt; data
+</pre>
+We might want to prefix <code>filename</code> keys with one letter (say '/') and the
+<code>file_block_id</code> 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.
+<p>
+<h2>Filters</h2>
+<p>
+Because of the way <code>rocksdb</code> data is organized on disk,
+a single <code>Get()</code> call may involve multiple reads from disk.
+The optional <code>FilterPolicy</code> mechanism can be used to reduce
+the number of disk reads substantially.
+<pre>
+   rocksdb::Options options;
+   options.filter_policy = NewBloomFilter(10);
+   rocksdb::DB* db;
+   rocksdb::DB::Open(options, "/tmp/testdb", &amp;db);
+   ... use the database ...
+   delete db;
+   delete options.filter_policy;
+</pre>
+The preceding code associates a
+<a href="http://en.wikipedia.org/wiki/Bloom_filter">Bloom filter</a>
+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 <code>Get()</code> 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.
+<p>
+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.
+<code>NewBloomFilter</code> must not be used with such a comparator.
+Instead, the application should provide a custom filter policy that
+also ignores trailing spaces.  For example:
+<pre>
+  class CustomFilterPolicy : public rocksdb::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&lt;Slice&gt; trimmed(n);
+      for (int i = 0; i &lt; n; i++) {
+        trimmed[i] = RemoveTrailingSpaces(keys[i]);
+      }
+      return builtin_policy_-&gt;CreateFilter(&amp;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_-&gt;KeyMayMatch(RemoveTrailingSpaces(key), filter);
+    }
+  };
+</pre>
+<p>
+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 <code>rocksdb/filter_policy.h</code> for detail.
+<p>
+<h1>Checksums</h1>
+<p>
+<code>rocksdb</code> associates checksums with all data it stores in the file system.
+There are two separate controls provided over how aggressively these
+checksums are verified:
+<p>
+<ul>
+<li> <code>ReadOptions::verify_checksums</code> 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.
+<p>
+<li> <code>Options::paranoid_checks</code> 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.
+<p>
+  If a database is corrupted (perhaps it cannot be opened when
+  paranoid checking is turned on), the <code>rocksdb::RepairDB</code> function
+  may be used to recover as much of the data as possible.
+<p>
+</ul>
+
+<p>
+<h1>Compaction</h1>
+<p>
+You can read more on Compactions here:
+<a href="https://github.com/facebook/rocksdb/wiki/Rocksdb-Architecture-Guide#multi-threaded-compactions">
+    Multi-threaded compactions
+</a>
+<p>
+Here we give overview of the options that impact behavior of Compactions:
+<ul>
+<p>
+<li><code>Options::compaction_style</code> - RocksDB currently supports two
+compaction algorithms - Universal  style and Level style. This option switches
+between the two.  Can be kCompactionStyleUniversal or kCompactionStyleLevel.
+If this is kCompactionStyleUniversal, then you can configure universal style
+parameters with <code>Options::compaction_options_universal</code>.
+<p>
+<li><code>Options::disable_auto_compactions</code> - Disable automatic compactions.
+Manual compactions can still be issued on this database.
+<p>
+<li><code>Options::compaction_filter</code> - Allows an application to modify/delete
+a key-value during background compaction. The client must provide
+compaction_filter_factory if it requires a new compaction filter to be used
+for different compaction processes. Client should specify only one of filter
+or factory.
+<p>
+<li><code>Options::compaction_filter_factory</code> - a factory that provides
+compaction filter objects which allow an application to modify/delete a
+key-value during background compaction.
+</ul>
+<p>
+Other options impacting performance of compactions and when they get triggered
+are: 
+<ul>
+<p>
+<li> <code>Options::access_hint_on_compaction_start</code> - Specify the file access 
+pattern once a compaction is started. It will be applied to all input files of a compaction. Default: NORMAL
+<p>
+<li> <code>Options::level0_file_num_compaction_trigger</code> -  Number of files to trigger level-0 compaction. 
+A negative value means that level-0 compaction will not be triggered by number of files at all.
+<p>
+<li> <code>Options::max_mem_compaction_level</code> -  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.
+<p>
+<li> <code>Options::target_file_size_base</code> and <code>Options::target_file_size_multiplier</code> - 
+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. Default target_file_size_base is 2MB
+and default target_file_size_multiplier is 1.
+<p>
+<li> <code>Options::expanded_compaction_factor</code> -  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.
+<p>
+<li> <code>Options::source_compaction_factor</code> -    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.
+<p>
+<li> <code>Options::max_grandparent_overlap_factor</code> -   Control maximum bytes of overlaps in grandparent (i.e., level+2) before we
+stop building a single file in a level->level+1 compaction.
+<p>
+<li> <code>Options::disable_seek_compaction</code> -  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).
+<p>
+<li> <code>Options::max_background_compactions</code> - Maximum number of concurrent background jobs, submitted to
+the default LOW priority thread pool
+</ul>
+
+<p>
+You can learn more about all of those options in <code>rocksdb/options.h</code>
+
+<h2> Universal style compaction specific settings</h2>
+<p>
+If you're using Universal style compaction, there is an object <code>CompactionOptionsUniversal</code>
+that hold all the different options for that compaction. The exact definition is in
+<code>rocksdb/universal_compaction.h</code> and you can set it in <code>Options::compaction_options_universal</code>.
+Here we give short overview of options in <code>CompactionOptionsUniversal</code>:
+<ul>
+<p>
+<li> <code>CompactionOptionsUniversal::size_ratio</code> - Percentage flexibilty while comparing file size. If the candidate file(s)
+   size is 1% smaller than the next file's size, then include next file into
+   this candidate set.  Default: 1
+<p>
+<li> <code>CompactionOptionsUniversal::min_merge_width</code> - The minimum number of files in a single compaction run. Default: 2
+<p>
+<li> <code>CompactionOptionsUniversal::max_merge_width</code> - The maximum number of files in a single compaction run. Default: UINT_MAX
+<p>
+<li> <code>CompactionOptionsUniversal::max_size_amplification_percent</code> - The size amplification is defined as the amount (in percentage) of
+additional storage needed to store a single byte of data in the database.  For example, a size amplification of 2% means that a database that
+contains 100 bytes of user-data may occupy upto 102 bytes of physical storage. By this definition, a fully compacted database has
+a size amplification of 0%. Rocksdb uses the following heuristic to calculate size amplification: it assumes that all files excluding
+the earliest file contribute to the size amplification.  Default: 200, which means that a 100 byte database could require upto
+300 bytes of storage.
+<p>
+<li> <code>CompactionOptionsUniversal::compression_size_percent</code> - If this option is set to be -1 (the default value), all the output files
+will follow compression type specified.  If this option is not negative, we will try to make sure compressed
+size is just above this value. In normal cases, at least this percentage
+of data will be compressed.
+When we are compacting to a new file, here is the criteria whether
+it needs to be compressed: assuming here are the list of files sorted
+by generation time: [ A1...An B1...Bm C1...Ct ],
+where A1 is the newest and Ct is the oldest, and we are going to compact
+B1...Bm, we calculate the total size of all the files as total_size, as
+well as  the total size of C1...Ct as total_C, the compaction output file
+will be compressed iff total_C / total_size < this percentage
+<p>
+<li> <code>CompactionOptionsUniversal::stop_style</code> - The algorithm used to stop picking files into a single compaction run.
+Can be kCompactionStopStyleSimilarSize (pick files of similar size) or kCompactionStopStyleTotalSize (total size of picked files > next file).
+Default: kCompactionStopStyleTotalSize
+</ul>
+
+<h1>Thread pools</h1>
+<p>
+A thread pool is associated with Env environment object. The client has to create a thread pool by setting the number of background
+threads using method <code>Env::SetBackgroundThreads()</code> defined in <code>rocksdb/env.h</code>.
+We use the thread pool for compactions and memtable flushes.
+Since memtable flushes are in critical code path (stalling memtable flush can stall writes, increasing p99), we suggest 
+having two thread pools - with priorities HIGH and LOW. Memtable flushes can be set up to be scheduled on HIGH thread pool.
+There are two options available for configuration of background compactions and flushes:
+<ul>
+<p>
+<li> <code>Options::max_background_compactions</code> - Maximum number of concurrent background jobs,
+submitted to the default LOW priority thread pool
+<p>
+<li> <code>Options::max_background_flushes</code> - Maximum number of concurrent background memtable flush jobs, submitted to
+the HIGH priority thread pool.  By default, all background jobs (major compaction and memtable flush) go
+to the LOW priority pool. If this option is set to a positive number, memtable flush jobs will be submitted to the HIGH priority pool.
+It is important when the same Env is shared by multiple db instances.  Without a separate pool, long running major compaction jobs could
+potentially block memtable flush jobs of other db instances, leading to unnecessary Put stalls.
+</ul>
+<p>
+<pre>
+  #include "rocksdb/env.h"
+  #include "rocksdb/db.h"
+
+  auto env = rocksdb::Env::Default();
+  env->SetBackgroundThreads(2, rocksdb::Env::LOW);
+  env->SetBackgroundThreads(1, rocksdb::Env::HIGH);
+  rocksdb::DB* db;
+  rocksdb::Options options;
+  options.env = env;
+  options.max_background_compactions = 2;
+  options.max_background_flushes = 1;
+  rocksdb::Status status = rocksdb::DB::Open(options, "/tmp/testdb", &amp;db);
+  assert(status.ok());
+  ...
+</pre>
+<h1>Approximate Sizes</h1>
+<p>
+The <code>GetApproximateSizes</code> method can used to get the approximate
+number of bytes of file system space used by one or more key ranges.
+<p>
+<pre>
+   rocksdb::Range ranges[2];
+   ranges[0] = rocksdb::Range("a", "c");
+   ranges[1] = rocksdb::Range("x", "z");
+   uint64_t sizes[2];
+   rocksdb::Status s = db-&gt;GetApproximateSizes(ranges, 2, sizes);
+</pre>
+The preceding call will set <code>sizes[0]</code> to the approximate number of
+bytes of file system space used by the key range <code>[a..c)</code> and
+<code>sizes[1]</code> to the approximate number of bytes used by the key range
+<code>[x..z)</code>.
+<p>
+<h1>Environment</h1>
+<p>
+All file operations (and other operating system calls) issued by the
+<code>rocksdb</code> implementation are routed through a <code>rocksdb::Env</code> object.
+Sophisticated clients may wish to provide their own <code>Env</code>
+implementation to get better control.  For example, an application may
+introduce artificial delays in the file IO paths to limit the impact
+of <code>rocksdb</code> on other activities in the system.
+<p>
+<pre>
+  class SlowEnv : public rocksdb::Env {
+    .. implementation of the Env interface ...
+  };
+
+  SlowEnv env;
+  rocksdb::Options options;
+  options.env = &amp;env;
+  Status s = rocksdb::DB::Open(options, ...);
+</pre>
+<h1>Porting</h1>
+<p>
+<code>rocksdb</code> may be ported to a new platform by providing platform
+specific implementations of the types/methods/functions exported by
+<code>rocksdb/port/port.h</code>.  See <code>rocksdb/port/port_example.h</code> for more
+details.
+<p>
+In addition, the new platform may need a new default <code>rocksdb::Env</code>
+implementation.  See <code>rocksdb/util/env_posix.h</code> for an example.
+
+<h1>Statistics</h1>
+<p>
+To be able to efficiently tune your application, it is always helpful if you
+have access to usage statistics. You can collect those statistics by setting
+<code>Options::table_stats_collectors</code> or
+<code>Options::statistics</code>. For more information, refer to
+<code>rocksdb/table_stats.h</code> and <code>rocksdb/statistics.h</code>.
+These should not add significant overhead to your application and we
+recommend exporting them to other monitoring tools.
+
+<h1>Purging WAL files</h1>
+<p>
+By default, old write-ahead logs are deleted automatically when they fall out
+of scope and application doesn't need them anymore. There are options that
+enable the user to archive the logs and then delete them lazily, either in
+TTL fashion or based on size limit.
+
+The options are <code>Options::WAL_ttl_seconds</code> and
+<code>Options::WAL_size_limit_MB</code>. Here is how they can be used:
+<ul>
+<li>
+<p>
+If both set to 0, logs will be deleted asap and will never get into the archive.
+<li>
+<p>
+If <code>WAL_ttl_seconds</code> is 0 and WAL_size_limit_MB is not 0, WAL
+files will be checked every 10 min and if total size is greater then
+<code>WAL_size_limit_MB</code>, they will be deleted starting with the
+earliest until size_limit is met. All empty files will be deleted.
+<li>
+<p>
+If <code>WAL_ttl_seconds</code> is not 0 and WAL_size_limit_MB is 0, then
+WAL files will be checked every <code>WAL_ttl_seconds / 2</code> and those
+that are older than WAL_ttl_seconds will be deleted.
+<li>
+<p>
+If both are not 0, WAL files will be checked every 10 min and both
+checks will be performed with ttl being first.
+</ul>
+
+<h1>Other Information</h1>
+<p>
+Details about the <code>rocksdb</code> implementation may be found in
+the following documents:
+<ul>
+<li> <a href="https://github.com/facebook/rocksdb/wiki/Rocksdb-Architecture-Guide">
+  RocksDB Architecture Guide</a>
+<li> <a href="https://github.com/facebook/rocksdb/wiki/Rocksdb-Table-Format">
+    Format of an immutable Table file</a>
+<li> <a href="log_format.txt">Format of a log file</a>
+</ul>
+
+</body>
+</html>
diff --git a/doc/log_format.txt b/doc/log_format.txt
new file mode 100644 (file)
index 0000000..3a0414b
--- /dev/null
@@ -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/rockslogo.jpg b/doc/rockslogo.jpg
new file mode 100644 (file)
index 0000000..363905a
Binary files /dev/null and b/doc/rockslogo.jpg differ
diff --git a/doc/rockslogo.png b/doc/rockslogo.png
new file mode 100644 (file)
index 0000000..1961360
Binary files /dev/null and b/doc/rockslogo.png differ
diff --git a/hdfs/README b/hdfs/README
new file mode 100644 (file)
index 0000000..9b7d0a6
--- /dev/null
@@ -0,0 +1,26 @@
+This directory contains the hdfs extensions needed to make rocksdb 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 rocksdb.
+
+The env_hdfs.h file defines the rocksdb objects that are needed to talk to an
+underlying filesystem. 
+
+If you want to compile rocksdb 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 (file)
index 0000000..cb8ca62
--- /dev/null
@@ -0,0 +1,302 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+
+#pragma once
+#include <algorithm>
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+#include <iostream>
+#include "rocksdb/env.h"
+#include "rocksdb/status.h"
+
+#ifdef USE_HDFS
+#include "hdfs/hdfs.h"
+
+namespace rocksdb {
+
+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 rocksdb. 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 Status NewRandomRWFile(const std::string& fname,
+                                 unique_ptr<RandomRWFile>* result,
+                                 const EnvOptions& options);
+
+  virtual bool FileExists(const std::string& fname);
+
+  virtual Status GetChildren(const std::string& path,
+                             std::vector<std::string>* 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,
+                        Priority pri = LOW) {
+    posixEnv->Schedule(function, arg, pri);
+  }
+
+  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, Priority pri = LOW) {
+    posixEnv->SetBackgroundThreads(number, pri);
+  }
+
+  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 <std::string> 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<std::string> &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 rocksdb
+
+#else // USE_HDFS
+
+
+namespace rocksdb {
+
+static const Status notsup;
+
+class HdfsEnv : public Env {
+
+ public:
+  HdfsEnv(const std::string& fsname) {
+    fprintf(stderr, "You have not build rocksdb 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<SequentialFile>* result,
+                                   const EnvOptions& options);
+
+  virtual Status NewRandomAccessFile(const std::string& fname,
+                                     unique_ptr<RandomAccessFile>* result,
+                                     const EnvOptions& options) {
+    return notsup;
+  }
+
+  virtual Status NewWritableFile(const std::string& fname,
+                                 unique_ptr<WritableFile>* result,
+                                 const EnvOptions& options) {
+    return notsup;
+  }
+
+  virtual Status NewRandomRWFile(const std::string& fname,
+                                 unique_ptr<RandomRWFile>* result,
+                                 const EnvOptions& options) {
+    return notsup;
+  }
+
+  virtual bool FileExists(const std::string& fname){return false;}
+
+  virtual Status GetChildren(const std::string& path,
+                             std::vector<std::string>* 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<Logger>* result){return notsup;}
+
+  virtual void Schedule(void (*function)(void* arg), void* arg,
+                        Priority pri = LOW) {}
+
+  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, Priority pri = LOW) {}
+
+  virtual std::string TimeToString(uint64_t number) { return "";}
+};
+}
+
+#endif // USE_HDFS
diff --git a/hdfs/hdfs.h b/hdfs/hdfs.h
new file mode 100644 (file)
index 0000000..8e8dfec
--- /dev/null
@@ -0,0 +1,477 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#ifndef LIBHDFS_HDFS_H
+#define LIBHDFS_HDFS_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+
+#include <jni.h>
+
+#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 (file)
index 0000000..4d1f19f
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 (file)
index 0000000..15f1383
--- /dev/null
@@ -0,0 +1,386 @@
+// 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 "rocksdb/env.h"
+#include "rocksdb/status.h"
+#include "port/port.h"
+#include "util/mutexlock.h"
+#include <map>
+#include <string.h>
+#include <string>
+#include <vector>
+
+namespace rocksdb {
+
+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<char*>::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<char*> 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<SequentialFile>* result,
+                                   const EnvOptions& soptions) {
+    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<RandomAccessFile>* result,
+                                     const EnvOptions& soptions) {
+    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<WritableFile>* result,
+                                 const EnvOptions& soptions) {
+    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<std::string>* 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<std::string, FileState*> FileSystem;
+  port::Mutex mutex_;
+  FileSystem file_map_;  // Protected by mutex_.
+};
+
+}  // namespace
+
+Env* NewMemEnv(Env* base_env) {
+  return new InMemoryEnv(base_env);
+}
+
+}  // namespace rocksdb
diff --git a/helpers/memenv/memenv.h b/helpers/memenv/memenv.h
new file mode 100644 (file)
index 0000000..2126441
--- /dev/null
@@ -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_ROCKSDB_HELPERS_MEMENV_MEMENV_H_
+#define STORAGE_ROCKSDB_HELPERS_MEMENV_MEMENV_H_
+namespace rocksdb {
+
+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 rocksdb
+
+#endif  // STORAGE_ROCKSDB_HELPERS_MEMENV_MEMENV_H_
diff --git a/helpers/memenv/memenv_test.cc b/helpers/memenv/memenv_test.cc
new file mode 100644 (file)
index 0000000..19fc8ff
--- /dev/null
@@ -0,0 +1,233 @@
+// 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 "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "util/testharness.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace rocksdb {
+
+class MemEnvTest {
+ public:
+  Env* env_;
+  const EnvOptions soptions_;
+
+  MemEnvTest()
+      : env_(NewMemEnv(Env::Default())) {
+  }
+  ~MemEnvTest() {
+    delete env_;
+  }
+};
+
+TEST(MemEnvTest, Basics) {
+  uint64_t file_size;
+  unique_ptr<WritableFile> writable_file;
+  std::vector<std::string> 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, soptions_));
+  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, soptions_));
+  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<SequentialFile> seq_file;
+  unique_ptr<RandomAccessFile> rand_file;
+  ASSERT_TRUE(!env_->NewSequentialFile("/dir/non_existent", &seq_file,
+                                       soptions_).ok());
+  ASSERT_TRUE(!seq_file);
+  ASSERT_TRUE(!env_->NewRandomAccessFile("/dir/non_existent", &rand_file,
+                                         soptions_).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<WritableFile> writable_file;
+  unique_ptr<SequentialFile> seq_file;
+  unique_ptr<RandomAccessFile> rand_file;
+  Slice result;
+  char scratch[100];
+
+  ASSERT_OK(env_->CreateDir("/dir"));
+
+  ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file, soptions_));
+  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, soptions_));
+  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, soptions_));
+  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<WritableFile> writable_file;
+  ASSERT_OK(env_->NewWritableFile("/a/b", &writable_file, soptions_));
+
+  // 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<char>(i));
+  }
+
+  unique_ptr<WritableFile> writable_file;
+  ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file, soptions_));
+  ASSERT_OK(writable_file->Append("foo"));
+  ASSERT_OK(writable_file->Append(write_data));
+  writable_file.reset();
+
+  unique_ptr<SequentialFile> seq_file;
+  Slice result;
+  ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file, soptions_));
+  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<DBImpl*>(db);
+  ASSERT_OK(dbi->TEST_FlushMemTable());
+
+  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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/include/rocksdb/arena.h b/include/rocksdb/arena.h
new file mode 100644 (file)
index 0000000..c0a0ac2
--- /dev/null
@@ -0,0 +1,41 @@
+// 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.
+//
+// Arena class defines memory allocation methods. It's used by memtable and
+// skiplist.
+
+#ifndef STORAGE_ROCKSDB_INCLUDE_ARENA_H_
+#define STORAGE_ROCKSDB_INCLUDE_ARENA_H_
+
+#include <limits>
+#include <memory>
+
+namespace rocksdb {
+
+class Arena {
+ public:
+  Arena() {};
+  virtual ~Arena() {};
+
+  // Return a pointer to a newly allocated memory block of "bytes" bytes.
+  virtual char* Allocate(size_t bytes) = 0;
+
+  // Allocate memory with the normal alignment guarantees provided by malloc.
+  virtual char* AllocateAligned(size_t bytes) = 0;
+
+  // Returns an estimate of the total memory used by arena.
+  virtual const size_t ApproximateMemoryUsage() = 0;
+
+  // Returns the total number of bytes in all blocks allocated so far.
+  virtual const size_t MemoryAllocatedBytes() = 0;
+
+ private:
+  // No copying allowed
+  Arena(const Arena&);
+  void operator=(const Arena&);
+};
+
+}  // namespace rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_ARENA_H_
diff --git a/include/rocksdb/c.h b/include/rocksdb/c.h
new file mode 100644 (file)
index 0000000..b7c536f
--- /dev/null
@@ -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_ROCKSDB_INCLUDE_C_H_
+#define STORAGE_ROCKSDB_INCLUDE_C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* 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_ROCKSDB_INCLUDE_C_H_ */
diff --git a/include/rocksdb/cache.h b/include/rocksdb/cache.h
new file mode 100644 (file)
index 0000000..c912c9c
--- /dev/null
@@ -0,0 +1,118 @@
+// 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_ROCKSDB_INCLUDE_CACHE_H_
+#define STORAGE_ROCKSDB_INCLUDE_CACHE_H_
+
+#include <memory>
+#include <stdint.h>
+#include "rocksdb/slice.h"
+
+namespace rocksdb {
+
+using std::shared_ptr;
+
+class Cache;
+
+// Create a new cache with a fixed size capacity. The cache is sharded
+// to 2^numShardBits shards, by hash of the key. The total capacity
+// is divided and evenly assigned to each shard. Inside each shard,
+// the eviction is done in two passes: first try to free spaces by
+// evicting entries that are among the most least used removeScanCountLimit
+// entries and do not have reference other than by the cache itself, in
+// the least-used order. If not enough space is freed, further free the
+// entries in least used order.
+//
+// The functions without parameter numShardBits and/or removeScanCountLimit
+// use default values. removeScanCountLimit's default value is 0, which
+// means a strict LRU order inside each shard.
+extern shared_ptr<Cache> NewLRUCache(size_t capacity);
+extern shared_ptr<Cache> NewLRUCache(size_t capacity, int numShardBits);
+extern shared_ptr<Cache> NewLRUCache(size_t capacity, int numShardBits,
+                                     int removeScanCountLimit);
+
+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 rocksdb
+
+#endif  // STORAGE_ROCKSDB_UTIL_CACHE_H_
diff --git a/include/rocksdb/compaction_filter.h b/include/rocksdb/compaction_filter.h
new file mode 100644 (file)
index 0000000..2aaddec
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright (c) 2013 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_ROCKSDB_INCLUDE_COMPACTION_FILTER_H_
+#define STORAGE_ROCKSDB_INCLUDE_COMPACTION_FILTER_H_
+
+#include <string>
+
+namespace rocksdb {
+
+class Slice;
+
+// CompactionFilter allows an application to modify/delete a key-value at
+// the time of compaction.
+
+class CompactionFilter {
+ public:
+
+  // Context information of a compaction run
+  struct Context {
+    // Does this compaction run include all data files
+    bool is_full_compaction;
+  };
+
+  virtual ~CompactionFilter() {}
+
+  // The compaction process invokes this
+  // method for 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 and make decision based on it.
+  //
+  // When the value is to be preserved, the application has the option
+  // to modify the existing_value and pass it back through new_value.
+  // value_changed needs to be set to true in this case.
+  virtual bool Filter(int level,
+                      const Slice& key,
+                      const Slice& existing_value,
+                      std::string* new_value,
+                      bool* value_changed) const = 0;
+
+  // Returns a name that identifies this compaction filter.
+  // The name will be printed to LOG file on start up for diagnosis.
+  virtual const char* Name() const = 0;
+};
+
+// Each compaction will create a new CompactionFilter allowing the
+// application to know about different campactions
+class CompactionFilterFactory {
+ public:
+  virtual ~CompactionFilterFactory() { };
+
+  virtual std::unique_ptr<CompactionFilter> CreateCompactionFilter(
+    const CompactionFilter::Context& context) = 0;
+
+  // Returns a name that identifies this compaction filter factory.
+  virtual const char* Name() const = 0;
+};
+
+// Default implementaion of CompactionFilterFactory which does not
+// return any filter
+class DefaultCompactionFilterFactory : public CompactionFilterFactory {
+ public:
+  virtual std::unique_ptr<CompactionFilter>
+  CreateCompactionFilter(const CompactionFilter::Context& context) override {
+    return std::unique_ptr<CompactionFilter>(nullptr);
+  }
+
+  virtual const char* Name() const override {
+    return "DefaultCompactionFilterFactory";
+  }
+};
+
+}  // namespace rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_COMPACTION_FILTER_H_
diff --git a/include/rocksdb/comparator.h b/include/rocksdb/comparator.h
new file mode 100644 (file)
index 0000000..f131627
--- /dev/null
@@ -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_ROCKSDB_INCLUDE_COMPARATOR_H_
+#define STORAGE_ROCKSDB_INCLUDE_COMPARATOR_H_
+
+#include <string>
+
+namespace rocksdb {
+
+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 rocksdb 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 "rocksdb." 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 rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_COMPARATOR_H_
diff --git a/include/rocksdb/db.h b/include/rocksdb/db.h
new file mode 100644 (file)
index 0000000..3d7bc3a
--- /dev/null
@@ -0,0 +1,303 @@
+// 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_ROCKSDB_INCLUDE_DB_H_
+#define STORAGE_ROCKSDB_INCLUDE_DB_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <memory>
+#include <vector>
+#include "rocksdb/iterator.h"
+#include "rocksdb/options.h"
+#include "rocksdb/types.h"
+#include "rocksdb/transaction_log.h"
+
+namespace rocksdb {
+
+using std::unique_ptr;
+
+// Update Makefile if you change these
+static const int kMajorVersion = 2;
+static const int kMinorVersion = 0;
+
+struct Options;
+struct ReadOptions;
+struct WriteOptions;
+struct FlushOptions;
+class WriteBatch;
+
+// Metadata associated with each SST file.
+struct LiveFileMetaData {
+  std::string name;        // Name of the file
+  int level;               // Level at which this file resides.
+  size_t size;             // File size in bytes.
+  std::string smallestkey; // Smallest user defined key in the file.
+  std::string largestkey;  // Largest user defined key in the file.
+  SequenceNumber smallest_seqno; // smallest seqno in file
+  SequenceNumber largest_seqno;  // largest seqno in file
+};
+
+// 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;
+
+  // Merge the database entry for "key" with "value".  Returns OK on success,
+  // and a non-OK status on error. The semantics of this operation is
+  // determined by the user provided merge_operator when opening DB.
+  // Note: consider setting options.sync = true.
+  virtual Status Merge(const WriteOptions& options,
+                       const Slice& key,
+                       const Slice& value) = 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;
+
+  // If keys[i] does not exist in the database, then the i'th returned
+  // status will be one for which Status::IsNotFound() is true, and
+  // (*values)[i] will be set to some arbitrary value (often ""). Otherwise,
+  // the i'th returned status will have Status::ok() true, and (*values)[i]
+  // will store the value associated with keys[i].
+  //
+  // (*values) will always be resized to be the same size as (keys).
+  // Similarly, the number of returned statuses will be the number of keys.
+  // Note: keys will not be "de-duplicated". Duplicate keys will return
+  // duplicate values in order.
+  virtual std::vector<Status> MultiGet(const ReadOptions& options,
+                                       const std::vector<Slice>& keys,
+                                       std::vector<std::string>* values) = 0;
+
+  // If the key definitely does not exist in the database, then this method
+  // returns false, else true. If the caller wants to obtain value when the key
+  // is found in memory, a bool for 'value_found' must be passed. 'value_found'
+  // will be true on return if value has been set properly.
+  // This check is potentially lighter-weight than invoking DB::Get(). One way
+  // to make this lighter weight is to avoid doing any IOs.
+  // Default implementation here returns true and sets 'value_found' to false
+  virtual bool KeyMayExist(const ReadOptions& options,
+                           const Slice& key,
+                           std::string* value,
+                           bool* value_found = nullptr) {
+    if (value_found != nullptr) {
+      *value_found = false;
+    }
+    return true;
+  }
+
+  // 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:
+  //
+  //  "rocksdb.num-files-at-level<N>" - return the number of files at level <N>,
+  //     where <N> is an ASCII representation of a level number (e.g. "0").
+  //  "rocksdb.stats" - returns a multi-line string that describes statistics
+  //     about the internal operation of the DB.
+  //  "rocksdb.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);
+  // Note that after the entire database is compacted, all data are pushed
+  // down to the last level containing any data. If the total data size
+  // after compaction is reduced, that level might not be appropriate for
+  // hosting all the files. In this case, client could set reduce_level
+  // to true, to move the files back to the minimum level capable of holding
+  // the data set or a given level (specified by non-negative target_level).
+  virtual void CompactRange(const Slice* begin, const Slice* end,
+                            bool reduce_level = false,
+                            int target_level = -1) = 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;
+
+  // GetLiveFiles followed by GetSortedWalFiles can generate a lossless backup
+
+  // THIS METHOD IS DEPRECATED. Use the GetTableMetaData to get more
+  // detailed information on the live files.
+  // Retrieve the list of all files in the database. The files are
+  // relative to the dbname and are not absolute paths. 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.
+  // Setting flush_memtable to true does Flush before recording the live files.
+  // Setting flush_memtable to false is useful when we don't want to wait for
+  // flush which may have to wait for compaction to complete taking an
+  // indeterminate time. But this will have to use GetSortedWalFiles after
+  // GetLiveFiles to compensate for memtables missed in this snapshot due to the
+  // absence of Flush, by WAL files to recover the database consistently later
+  virtual Status GetLiveFiles(std::vector<std::string>&,
+                              uint64_t* manifest_file_size,
+                              bool flush_memtable = true) = 0;
+
+  // Retrieve the sorted list of all wal files with earliest file first
+  virtual Status GetSortedWalFiles(VectorLogPtr& files) = 0;
+
+  // The sequence number of the most recent transaction.
+  virtual SequenceNumber GetLatestSequenceNumber() const = 0;
+
+  // Sets iter to an iterator that is positioned at a write-batch containing
+  // seq_number. If the sequence number is non existent, it returns an iterator
+  // at the first available seq_no after the requested seq_no
+  // Returns Status::Ok if iterator is valid
+  // Must set WAL_ttl_seconds or WAL_size_limit_MB to large values 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<TransactionLogIterator>* iter) = 0;
+
+  // Delete the file name from the db directory and update the internal state to
+  // reflect that. Supports deletion of sst and log files only. 'name' must be
+  // path relative to the db directory. eg. 000001.sst, /archive/000003.log
+  virtual Status DeleteFile(std::string name) = 0;
+
+  // Returns a list of all table files with their level, start key
+  // and end key
+  virtual void GetLiveFilesMetaData(
+    std::vector<LiveFileMetaData> *metadata) {
+  }
+
+ 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 rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_DB_H_
diff --git a/include/rocksdb/env.h b/include/rocksdb/env.h
new file mode 100644 (file)
index 0000000..89dd099
--- /dev/null
@@ -0,0 +1,646 @@
+// 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 rocksdb 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_ROCKSDB_INCLUDE_ENV_H_
+#define STORAGE_ROCKSDB_INCLUDE_ENV_H_
+
+#include <cstdarg>
+#include <string>
+#include <memory>
+#include <vector>
+#include <stdint.h>
+#include "rocksdb/status.h"
+
+namespace rocksdb {
+
+class FileLock;
+class Logger;
+class RandomAccessFile;
+class SequentialFile;
+class Slice;
+class WritableFile;
+class RandomRWFile;
+struct Options;
+
+using std::unique_ptr;
+using std::shared_ptr;
+
+
+// Options while opening a file to read/write
+struct EnvOptions {
+
+  // construct with default Options
+  EnvOptions();
+
+  // construct from Options
+  explicit EnvOptions(const Options& options);
+
+  // If true, then allow caching of data in environment buffers
+  bool use_os_buffer;
+
+   // If true, then use mmap to read data
+  bool use_mmap_reads;
+
+   // If true, then use mmap to write data
+  bool use_mmap_writes;
+
+  // If true, set the FD_CLOEXEC on open fd.
+  bool set_fd_cloexec;
+
+  // Allows OS to incrementally sync files to disk while they are being
+  // written, in the background. Issue one request for every bytes_per_sync
+  // written. 0 turns it off.
+  // Default: 0
+  uint64_t bytes_per_sync;
+
+};
+
+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 rocksdb 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<SequentialFile>* result,
+                                   const EnvOptions& options)
+                                   = 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<RandomAccessFile>* result,
+                                     const EnvOptions& options)
+                                     = 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<WritableFile>* result,
+                                 const EnvOptions& options) = 0;
+
+  // Create an object that both reads and writes to a file on
+  // specified offsets (random access). If file already exists,
+  // does not overwrite it. On success, stores a pointer to the
+  // new file in *result and returns OK. On failure stores nullptr
+  // in *result and returns non-OK.
+  virtual Status NewRandomRWFile(const std::string& fname,
+                                 unique_ptr<RandomRWFile>* result,
+                                 const EnvOptions& options) = 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<std::string>* 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;
+
+  enum Priority { LOW, HIGH, TOTAL };
+
+  // Arrange to run "(*function)(arg)" once in a background thread, in
+  // the thread pool specified by pri. By default, jobs go to the 'LOW'
+  // priority thread pool.
+
+  // "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,
+      Priority pri = LOW) = 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<Logger>* 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;
+
+  // Returns the number of nano-seconds since some fixed point in time. Only
+  // useful for computing deltas of time in one run.
+  // Default implementation simply relies on NowMicros
+  virtual uint64_t NowNanos() {
+    return NowMicros() * 1000;
+  }
+
+  // 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 of a specific thread pool
+  // for this environment. 'LOW' is the default pool.
+  // default number: 1
+  virtual void SetBackgroundThreads(int number, Priority pri = LOW) = 0;
+
+  // Converts seconds-since-Jan-01-1970 to a printable string
+  virtual std::string TimeToString(uint64_t time) = 0;
+
+  // Generates a unique id that can be used to identify a db
+  virtual std::string GenerateUniqueId();
+
+ 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;
+
+  // Remove any kind of caching of data from the offset to offset+length
+  // of this file. If the length is 0, then it refers to the end of file.
+  // If the system is not caching the file contents, then this is a noop.
+  virtual Status InvalidateCache(size_t offset, size_t length) {
+    return Status::NotSupported("InvalidateCache not supported.");
+  }
+};
+
+// 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 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.
+  };
+
+
+  enum AccessPattern { NORMAL, RANDOM, SEQUENTIAL, WILLNEED, DONTNEED };
+
+  virtual void Hint(AccessPattern pattern) {}
+
+  // Remove any kind of caching of data from the offset to offset+length
+  // of this file. If the length is 0, then it refers to the end of file.
+  // If the system is not caching the file contents, then this is a noop.
+  virtual Status InvalidateCache(size_t offset, size_t length) {
+    return Status::NotSupported("InvalidateCache not supported.");
+  }
+};
+
+// 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 data.
+   * 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_;
+  }
+
+  // For documentation, refer to RandomAccessFile::GetUniqueId()
+  virtual size_t GetUniqueId(char* id, size_t max_size) const {
+    return 0; // Default implementation to prevent issues with backwards
+  }
+
+  // Remove any kind of caching of data from the offset to offset+length
+  // of this file. If the length is 0, then it refers to the end of file.
+  // If the system is not caching the file contents, then this is a noop.
+  // This call has no effect on dirty pages in the cache.
+  virtual Status InvalidateCache(size_t offset, size_t length) {
+    return Status::NotSupported("InvalidateCache not supported.");
+  }
+
+ 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();
+  }
+
+  // Sync a file range with disk.
+  // offset is the starting byte of the file range to be synchronized.
+  // nbytes specifies the length of the range to be synchronized.
+  // This asks the OS to initiate flushing the cached data to disk,
+  // without waiting for completion.
+  // Default implementation does nothing.
+  virtual Status RangeSync(off_t offset, off_t nbytes) {
+    return Status::OK();
+  }
+
+ private:
+  size_t last_preallocated_block_;
+  size_t preallocation_block_size_;
+  // No copying allowed
+  WritableFile(const WritableFile&);
+  void operator=(const WritableFile&);
+};
+
+// A file abstraction for random reading and writing.
+class RandomRWFile {
+ public:
+  RandomRWFile() {}
+  virtual ~RandomRWFile() {}
+
+  // Write data from Slice data to file starting from offset
+  // Returns IOError on failure, but does not guarantee
+  // atomicity of a write.  Returns OK status on success.
+  //
+  // Safe for concurrent use.
+  virtual Status Write(uint64_t offset, const Slice& data) = 0;
+  // 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;
+  virtual Status Close() = 0; // closes the file
+  virtual Status Sync() = 0; // sync data
+
+  /*
+   * Sync data and/or metadata as well.
+   * By default, sync only data.
+   * Override this method for environments where we need to sync
+   * metadata as well.
+   */
+  virtual Status Fsync() {
+    return Sync();
+  }
+
+  /*
+   * Pre-allocate space for a file.
+   */
+  virtual Status Allocate(off_t offset, off_t len) {
+    return Status::OK();
+  }
+
+ private:
+  // No copying allowed
+  RandomRWFile(const RandomRWFile&);
+  void operator=(const RandomRWFile&);
+};
+
+// 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;
+  }
+  // Flush to the OS buffers
+  virtual void Flush() {}
+
+ 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&);
+};
+
+
+extern void LogFlush(const shared_ptr<Logger>& info_log);
+
+// Log the specified data to *info_log if info_log is non-nullptr.
+extern void Log(const shared_ptr<Logger>& info_log, const char* format, ...)
+#   if defined(__GNUC__) || defined(__clang__)
+    __attribute__((__format__ (__printf__, 2, 3)))
+#   endif
+    ;
+
+extern void LogFlush(Logger *info_log);
+
+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<SequentialFile>* r,
+                           const EnvOptions& options) {
+    return target_->NewSequentialFile(f, r, options);
+  }
+  Status NewRandomAccessFile(const std::string& f,
+                             unique_ptr<RandomAccessFile>* r,
+                             const EnvOptions& options) {
+    return target_->NewRandomAccessFile(f, r, options);
+  }
+  Status NewWritableFile(const std::string& f, unique_ptr<WritableFile>* r,
+                         const EnvOptions& options) {
+    return target_->NewWritableFile(f, r, options);
+  }
+  Status NewRandomRWFile(const std::string& f, unique_ptr<RandomRWFile>* r,
+                         const EnvOptions& options) {
+    return target_->NewRandomRWFile(f, r, options);
+  }
+  bool FileExists(const std::string& f) { return target_->FileExists(f); }
+  Status GetChildren(const std::string& dir, std::vector<std::string>* 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, Priority pri) {
+    return target_->Schedule(f, a, pri);
+  }
+  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<Logger>* 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, Priority pri) {
+    return target_->SetBackgroundThreads(num, pri);
+  }
+  std::string TimeToString(uint64_t time) {
+    return target_->TimeToString(time);
+  }
+
+ private:
+  Env* target_;
+};
+
+}  // namespace rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_ENV_H_
diff --git a/include/rocksdb/filter_policy.h b/include/rocksdb/filter_policy.h
new file mode 100644 (file)
index 0000000..605b3c4
--- /dev/null
@@ -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 rocksdb and are consulted
+// automatically by rocksdb 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_ROCKSDB_INCLUDE_FILTER_POLICY_H_
+#define STORAGE_ROCKSDB_INCLUDE_FILTER_POLICY_H_
+
+#include <string>
+
+namespace rocksdb {
+
+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_ROCKSDB_INCLUDE_FILTER_POLICY_H_
diff --git a/include/rocksdb/flush_block_policy.h b/include/rocksdb/flush_block_policy.h
new file mode 100644 (file)
index 0000000..776f476
--- /dev/null
@@ -0,0 +1,64 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+
+#pragma once
+
+#include <string>
+
+namespace rocksdb {
+
+class Slice;
+class BlockBuilder;
+
+// FlushBlockPolicy provides a configurable way to determine when to flush a
+// block in the block based tables,
+class FlushBlockPolicy {
+ public:
+  // Keep track of the key/value sequences and return the boolean value to
+  // determine if table builder should flush current data block.
+  virtual bool Update(const Slice& key,
+                      const Slice& value) = 0;
+
+  virtual ~FlushBlockPolicy() { }
+};
+
+class FlushBlockPolicyFactory {
+ public:
+  // Return the name of the flush block policy.
+  virtual const char* Name() const = 0;
+
+  // Return a new block flush policy that flushes data blocks by data size.
+  // FlushBlockPolicy may need to access the metadata of the data block
+  // builder to determine when to flush the blocks.
+  //
+  // Callers must delete the result after any database that is using the
+  // result has been closed.
+  virtual FlushBlockPolicy* NewFlushBlockPolicy(
+      const BlockBuilder& data_block_builder) const = 0;
+
+  virtual ~FlushBlockPolicyFactory() { }
+};
+
+class FlushBlockBySizePolicyFactory : public FlushBlockPolicyFactory {
+ public:
+  FlushBlockBySizePolicyFactory(const uint64_t block_size,
+                                const uint64_t block_size_deviation) :
+      block_size_(block_size),
+      block_size_deviation_(block_size_deviation) {
+  }
+
+  virtual const char* Name() const override {
+    return "FlushBlockBySizePolicyFactory";
+  }
+
+  virtual FlushBlockPolicy* NewFlushBlockPolicy(
+      const BlockBuilder& data_block_builder) const override;
+
+ private:
+  const uint64_t block_size_;
+  const uint64_t block_size_deviation_;
+};
+
+}  // rocksdb
diff --git a/include/rocksdb/iterator.h b/include/rocksdb/iterator.h
new file mode 100644 (file)
index 0000000..f729e39
--- /dev/null
@@ -0,0 +1,102 @@
+// 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_ROCKSDB_INCLUDE_ITERATOR_H_
+#define STORAGE_ROCKSDB_INCLUDE_ITERATOR_H_
+
+#include "rocksdb/slice.h"
+#include "rocksdb/status.h"
+
+namespace rocksdb {
+
+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.
+  // If non-blocking IO is requested and this operation cannot be
+  // satisfied without doing some IO, then this returns Status::Incomplete().
+  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 rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_ITERATOR_H_
diff --git a/include/rocksdb/ldb_tool.h b/include/rocksdb/ldb_tool.h
new file mode 100644 (file)
index 0000000..0a234b9
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2008-present Facebook. All Rights Reserved.
+#ifndef STORAGE_ROCKSDB_INCLUDE_LDB_TOOL_H
+#define STORAGE_ROCKSDB_INCLUDE_LDB_TOOL_H
+#include "rocksdb/options.h"
+
+namespace rocksdb {
+
+class LDBTool {
+ public:
+  void Run(int argc, char** argv, Options = Options());
+};
+
+} // namespace rocksdb
+
+#endif // STORAGE_ROCKSDB_INCLUDE_LDB_TOOL_H
diff --git a/include/rocksdb/memtablerep.h b/include/rocksdb/memtablerep.h
new file mode 100644 (file)
index 0000000..db51813
--- /dev/null
@@ -0,0 +1,271 @@
+// This file contains the interface that must be implemented by any collection
+// to be used as the backing store for a MemTable. Such a collection must
+// satisfy the following properties:
+//  (1) It does not store duplicate items.
+//  (2) It uses MemTableRep::KeyComparator to compare items for iteration and
+//     equality.
+//  (3) It can be accessed concurrently by multiple readers and can support
+//     during reads. However, it needn't support multiple concurrent writes.
+//  (4) Items are never deleted.
+// The liberal use of assertions is encouraged to enforce (1).
+//
+// The factory will be passed an Arena object when a new MemTableRep is
+// requested. The API for this object is in rocksdb/arena.h.
+//
+// Users can implement their own memtable representations. We include four
+// types built in:
+//  - SkipListRep: This is the default; it is backed by a skip list.
+//  - TransformRep: This is backed by an custom hash map.
+// On construction, they are given a SliceTransform object. This
+// object is applied to the user key of stored items which indexes into the
+// hash map to yield a skiplist containing all records that share the same
+// user key under the transform function.
+//  - UnsortedRep: A subclass of TransformRep where the transform function is
+// the identity function. Optimized for point lookups.
+//  - PrefixHashRep: A subclass of TransformRep where the transform function is
+// a fixed-size prefix extractor. If you use PrefixHashRepFactory, the transform
+// must be identical to options.prefix_extractor, otherwise it will be discarded
+// and the default will be used. It is optimized for ranged scans over a
+// prefix.
+//  - VectorRep: This is backed by an unordered std::vector. On iteration, the
+// vector is sorted. It is intelligent about sorting; once the MarkReadOnly()
+// has been called, the vector will only be sorted once. It is optimized for
+// random-write-heavy workloads.
+//
+// The last four implementations are designed for situations in which
+// iteration over the entire collection is rare since doing so requires all the
+// keys to be copied into a sorted data structure.
+
+#ifndef STORAGE_ROCKSDB_DB_MEMTABLEREP_H_
+#define STORAGE_ROCKSDB_DB_MEMTABLEREP_H_
+
+#include <memory>
+#include "rocksdb/arena.h"
+#include "rocksdb/slice.h"
+#include "rocksdb/slice_transform.h"
+
+namespace rocksdb {
+
+class MemTableRep {
+ public:
+  // KeyComparator provides a means to compare keys, which are internal keys
+  // concatenated with values.
+  class KeyComparator {
+   public:
+    // Compare a and b. Return a negative value if a is less than b, 0 if they
+    // are equal, and a positive value if a is greater than b
+    virtual int operator()(const char* a, const char* b) const = 0;
+
+    virtual ~KeyComparator() { }
+  };
+
+  // Insert key into the collection. (The caller will pack key and value into a
+  // single buffer and pass that in as the parameter to Insert)
+  // REQUIRES: nothing that compares equal to key is currently in the
+  // collection.
+  virtual void Insert(const char* key) = 0;
+
+  // Returns true iff an entry that compares equal to key is in the collection.
+  virtual bool Contains(const char* key) const = 0;
+
+  // Notify this table rep that it will no longer be added to. By default, does
+  // nothing.
+  virtual void MarkReadOnly() { }
+
+  // Report an approximation of how much memory has been used other than memory
+  // that was allocated through the arena.
+  virtual size_t ApproximateMemoryUsage() = 0;
+
+  virtual ~MemTableRep() { }
+
+  // Iteration over the contents of a skip collection
+  class Iterator {
+   public:
+    // Initialize an iterator over the specified collection.
+    // The returned iterator is not valid.
+    // explicit Iterator(const MemTableRep* collection);
+    virtual ~Iterator() { };
+
+    // Returns true iff the iterator is positioned at a valid node.
+    virtual bool Valid() const = 0;
+
+    // Returns the key at the current position.
+    // REQUIRES: Valid()
+    virtual const char* key() const = 0;
+
+    // Advances to the next position.
+    // REQUIRES: Valid()
+    virtual void Next() = 0;
+
+    // Advances to the previous position.
+    // REQUIRES: Valid()
+    virtual void Prev() = 0;
+
+    // Advance to the first entry with a key >= target
+    virtual void Seek(const char* target) = 0;
+
+    // Position at the first entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToFirst() = 0;
+
+    // Position at the last entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToLast() = 0;
+  };
+
+  // Return an iterator over the keys in this representation.
+  virtual std::shared_ptr<Iterator> GetIterator() = 0;
+
+  // Return an iterator over at least the keys with the specified user key. The
+  // iterator may also allow access to other keys, but doesn't have to. Default:
+  // GetIterator().
+  virtual std::shared_ptr<Iterator> GetIterator(const Slice& user_key) {
+    return GetIterator();
+  }
+
+  // Return an iterator over at least the keys with the specified prefix. The
+  // iterator may also allow access to other keys, but doesn't have to. Default:
+  // GetIterator().
+  virtual std::shared_ptr<Iterator> GetPrefixIterator(const Slice& prefix) {
+    return GetIterator();
+  }
+
+  // Return an iterator that has a special Seek semantics. The result of
+  // a Seek might only include keys with the same prefix as the target key.
+  virtual std::shared_ptr<Iterator> GetDynamicPrefixIterator() {
+    return GetIterator();
+  }
+
+ protected:
+  // When *key is an internal key concatenated with the value, returns the
+  // user key.
+  virtual Slice UserKey(const char* key) const;
+};
+
+// This is the base class for all factories that are used by RocksDB to create
+// new MemTableRep objects
+class MemTableRepFactory {
+ public:
+  virtual ~MemTableRepFactory() { };
+  virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
+    MemTableRep::KeyComparator&, Arena*) = 0;
+  virtual const char* Name() const = 0;
+};
+
+// This creates MemTableReps that are backed by an std::vector. On iteration,
+// the vector is sorted. This is useful for workloads where iteration is very
+// rare and writes are generally not issued after reads begin.
+//
+// Parameters:
+//   count: Passed to the constructor of the underlying std::vector of each
+//     VectorRep. On initialization, the underlying array will be at least count
+//     bytes reserved for usage.
+class VectorRepFactory : public MemTableRepFactory {
+  const size_t count_;
+public:
+  explicit VectorRepFactory(size_t count = 0) : count_(count) { }
+  virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
+    MemTableRep::KeyComparator&, Arena*) override;
+  virtual const char* Name() const override {
+    return "VectorRepFactory";
+  }
+};
+
+// This uses a skip list to store keys. It is the default.
+class SkipListFactory : public MemTableRepFactory {
+public:
+  virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
+    MemTableRep::KeyComparator&, Arena*) override;
+  virtual const char* Name() const override {
+    return "SkipListFactory";
+  }
+};
+
+// TransformReps are backed by an unordered map of buffers to buckets. When
+// looking up a key, the user key is extracted and a user-supplied transform
+// function (see rocksdb/slice_transform.h) is applied to get the key into the
+// unordered map. This allows the user to bin user keys based on arbitrary
+// criteria. Two example implementations are UnsortedRepFactory and
+// PrefixHashRepFactory.
+//
+// Iteration over the entire collection is implemented by dumping all the keys
+// into an std::set. Thus, these data structures are best used when iteration
+// over the entire collection is rare.
+//
+// Parameters:
+//   transform: The SliceTransform to bucket user keys on. TransformRepFactory
+//     owns the pointer.
+//   bucket_count: Passed to the constructor of the underlying
+//     std::unordered_map of each TransformRep. On initialization, the
+//     underlying array will be at least bucket_count size.
+//   num_locks: Number of read-write locks to have for the rep. Each bucket is
+//     hashed onto a read-write lock which controls access to that lock. More
+//     locks means finer-grained concurrency but more memory overhead.
+class TransformRepFactory : public MemTableRepFactory {
+ public:
+  explicit TransformRepFactory(const SliceTransform* transform,
+    size_t bucket_count, size_t num_locks = 1000)
+    : transform_(transform),
+      bucket_count_(bucket_count),
+      num_locks_(num_locks) { }
+
+  virtual ~TransformRepFactory() { delete transform_; }
+
+  virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
+    MemTableRep::KeyComparator&, Arena*) override;
+
+  virtual const char* Name() const override {
+    return "TransformRepFactory";
+  }
+
+  const SliceTransform* GetTransform() { return transform_; }
+
+ protected:
+  const SliceTransform* transform_;
+  const size_t bucket_count_;
+  const size_t num_locks_;
+};
+
+// UnsortedReps bin user keys based on an identity function transform -- that
+// is, transform(key) = key. This optimizes for point look-ups.
+//
+// Parameters: See TransformRepFactory.
+class UnsortedRepFactory : public TransformRepFactory {
+public:
+  explicit UnsortedRepFactory(size_t bucket_count = 0, size_t num_locks = 1000)
+    : TransformRepFactory(NewNoopTransform(),
+                          bucket_count,
+                          num_locks) { }
+  virtual const char* Name() const override {
+    return "UnsortedRepFactory";
+  }
+};
+
+// PrefixHashReps bin user keys based on a fixed-size prefix. This optimizes for
+// short ranged scans over a given prefix.
+//
+// Parameters: See TransformRepFactory.
+class PrefixHashRepFactory : public TransformRepFactory {
+public:
+  explicit PrefixHashRepFactory(const SliceTransform* prefix_extractor,
+    size_t bucket_count = 0, size_t num_locks = 1000)
+    : TransformRepFactory(prefix_extractor, bucket_count, num_locks)
+    { }
+
+  virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
+    MemTableRep::KeyComparator&, Arena*) override;
+
+  virtual const char* Name() const override {
+    return "PrefixHashRepFactory";
+  }
+};
+
+// The same as TransformRepFactory except it doesn't use locks.
+// Experimental, will replace TransformRepFactory once we are sure
+// it performs better
+extern MemTableRepFactory* NewHashSkipListRepFactory(
+    const SliceTransform* transform, size_t bucket_count = 1000000);
+
+}
+
+#endif // STORAGE_ROCKSDB_DB_MEMTABLEREP_H_
diff --git a/include/rocksdb/merge_operator.h b/include/rocksdb/merge_operator.h
new file mode 100644 (file)
index 0000000..19e02d2
--- /dev/null
@@ -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.
+
+#ifndef STORAGE_ROCKSDB_INCLUDE_MERGE_OPERATOR_H_
+#define STORAGE_ROCKSDB_INCLUDE_MERGE_OPERATOR_H_
+
+#include <string>
+#include <deque>
+#include "rocksdb/slice.h"
+
+namespace rocksdb {
+
+class Slice;
+class Logger;
+
+// The Merge Operator
+//
+// Essentially, a MergeOperator specifies the SEMANTICS of a merge, which only
+// client knows. It could be numeric addition, list append, string
+// concatenation, edit data structure, ... , anything.
+// The library, on the other hand, is concerned with the exercise of this
+// interface, at the right time (during get, iteration, compaction...)
+//
+// To use merge, the client needs to provide an object implementing one of
+// the following interfaces:
+//  a) AssociativeMergeOperator - for most simple semantics (always take
+//    two values, and merge them into one value, which is then put back
+//    into rocksdb); numeric addition and string concatenation are examples;
+//
+//  b) MergeOperator - the generic class for all the more abstract / complex
+//    operations; one method (FullMerge) to merge a Put/Delete value with a
+//    merge operand; and another method (PartialMerge) that merges two
+//    operands together. this is especially useful if your key values have a
+//    complex structure but you would still like to support client-specific
+//    incremental updates.
+//
+// AssociativeMergeOperator is simpler to implement. MergeOperator is simply
+// more powerful.
+//
+// Refer to rocksdb-merge wiki for more details and example implementations.
+//
+class MergeOperator {
+ public:
+  virtual ~MergeOperator() {}
+
+  // Gives the client a way to express the read -> modify -> write semantics
+  // key:      (IN)    The key that's associated with this merge operation.
+  //                   Client could multiplex the merge operator based on it
+  //                   if the key space is partitioned and different subspaces
+  //                   refer to different types of data which have different
+  //                   merge operation semantics
+  // existing: (IN)    null indicates that the key does not exist before this op
+  // operand_list:(IN) the sequence of merge operations to apply, front() first.
+  // new_value:(OUT)   Client is responsible for filling the merge result here
+  // logger:   (IN)    Client could use this to log errors during merge.
+  //
+  // Return true on success.
+  // All values passed in will be client-specific values. So if this method
+  // returns false, it is because client specified bad data or there was
+  // internal corruption. This will be treated as an error by the library.
+  //
+  // Also make use of the *logger for error messages.
+  virtual bool FullMerge(const Slice& key,
+                         const Slice* existing_value,
+                         const std::deque<std::string>& operand_list,
+                         std::string* new_value,
+                         Logger* logger) const = 0;
+
+  // This function performs merge(left_op, right_op)
+  // when both the operands are themselves merge operation types
+  // that you would have passed to a DB::Merge() call in the same order
+  // (i.e.: DB::Merge(key,left_op), followed by DB::Merge(key,right_op)).
+  //
+  // PartialMerge should combine them into a single merge operation that is
+  // saved into *new_value, and then it should return true.
+  // *new_value should be constructed such that a call to
+  // DB::Merge(key, *new_value) would yield the same result as a call
+  // to DB::Merge(key, left_op) followed by DB::Merge(key, right_op).
+  //
+  // If it is impossible or infeasible to combine the two operations,
+  // leave new_value unchanged and return false. The library will
+  // internally keep track of the operations, and apply them in the
+  // correct order once a base-value (a Put/Delete/End-of-Database) is seen.
+  //
+  // TODO: Presently there is no way to differentiate between error/corruption
+  // and simply "return false". For now, the client should simply return
+  // false in any case it cannot perform partial-merge, regardless of reason.
+  // If there is corruption in the data, handle it in the FullMerge() function,
+  // and return false there.
+  virtual bool PartialMerge(const Slice& key,
+                            const Slice& left_operand,
+                            const Slice& right_operand,
+                            std::string* new_value,
+                            Logger* logger) const = 0;
+
+  // The name of the MergeOperator. Used to check for MergeOperator
+  // mismatches (i.e., a DB created with one MergeOperator is
+  // accessed using a different MergeOperator)
+  // TODO: the name is currently not stored persistently and thus
+  //       no checking is enforced. Client is responsible for providing
+  //       consistent MergeOperator between DB opens.
+  virtual const char* Name() const = 0;
+};
+
+// The simpler, associative merge operator.
+class AssociativeMergeOperator : public MergeOperator {
+ public:
+  virtual ~AssociativeMergeOperator() {}
+
+  // Gives the client a way to express the read -> modify -> write semantics
+  // key:           (IN) The key that's associated with this merge operation.
+  // existing_value:(IN) null indicates the key does not exist before this op
+  // value:         (IN) the value to update/merge the existing_value with
+  // new_value:    (OUT) Client is responsible for filling the merge result here
+  // logger:        (IN) Client could use this to log errors during merge.
+  //
+  // Return true on success.
+  // All values passed in will be client-specific values. So if this method
+  // returns false, it is because client specified bad data or there was
+  // internal corruption. The client should assume that this will be treated
+  // as an error by the library.
+  virtual bool Merge(const Slice& key,
+                     const Slice* existing_value,
+                     const Slice& value,
+                     std::string* new_value,
+                     Logger* logger) const = 0;
+
+
+ private:
+  // Default implementations of the MergeOperator functions
+  virtual bool FullMerge(const Slice& key,
+                         const Slice* existing_value,
+                         const std::deque<std::string>& operand_list,
+                         std::string* new_value,
+                         Logger* logger) const override;
+
+  virtual bool PartialMerge(const Slice& key,
+                            const Slice& left_operand,
+                            const Slice& right_operand,
+                            std::string* new_value,
+                            Logger* logger) const override;
+};
+
+}  // namespace rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_MERGE_OPERATOR_H_
diff --git a/include/rocksdb/options.h b/include/rocksdb/options.h
new file mode 100644 (file)
index 0000000..45edb85
--- /dev/null
@@ -0,0 +1,752 @@
+// 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_ROCKSDB_INCLUDE_OPTIONS_H_
+#define STORAGE_ROCKSDB_INCLUDE_OPTIONS_H_
+
+#include <stddef.h>
+#include <string>
+#include <memory>
+#include <vector>
+#include <stdint.h>
+
+#include "rocksdb/memtablerep.h"
+#include "rocksdb/memtablerep.h"
+#include "rocksdb/slice.h"
+#include "rocksdb/slice_transform.h"
+#include "rocksdb/slice_transform.h"
+#include "rocksdb/statistics.h"
+#include "rocksdb/table_stats.h"
+#include "rocksdb/universal_compaction.h"
+
+namespace rocksdb {
+
+class Cache;
+class CompactionFilter;
+class CompactionFilterFactory;
+class Comparator;
+class Env;
+class FilterPolicy;
+class FlushBlockPolicyFactory;
+class Logger;
+class MergeOperator;
+class Snapshot;
+class TableFactory;
+
+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 : char {
+  // 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
+};
+
+enum CompactionStyle : char {
+  kCompactionStyleLevel       = 0x0, // level based compaction style
+  kCompactionStyleUniversal   = 0x1  // Universal compaction style
+};
+
+// 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;
+
+  // REQUIRES: The client must provide a merge operator if Merge operation
+  // needs to be accessed. Calling Merge on a DB without a merge operator
+  // would result in Status::NotSupported. The client must ensure that the
+  // merge operator supplied here has the same name and *exactly* the same
+  // semantics as the merge operator provided to previous open calls on
+  // the same DB. The only exception is reserved for upgrade, where a DB
+  // previously without a merge operator is introduced to Merge operation
+  // for the first time. It's necessary to specify a merge operator when
+  // openning the DB in this case.
+  // Default: nullptr
+  shared_ptr<MergeOperator> merge_operator;
+
+  // The client must provide compaction_filter_factory if it requires a new
+  // compaction filter to be used for different compaction processes
+  // Allows an application to modify/delete a key-value during background
+  // compaction.
+  // Ideally, client should specify only one of filter or factory.
+  // compaction_filter takes precedence over compaction_filter_factory if
+  // client specifies both.
+  // Default: nullptr
+  const CompactionFilter* compaction_filter;
+
+  // 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.
+  // If any of the  writes to the database fails (Put, Delete, Merge, Write),
+  // the database will switch to read-only mode and fail all other
+  // Write operations.
+  // 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<Logger> 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;
+
+  // The minimum number of write buffers that will be merged together
+  // before writing to storage.  If set to 1, then
+  // all write buffers are fushed to L0 as individual files and this increases
+  // read amplification because a get request has to check in all of these
+  // files. Also, an in-memory merge may result in writing lesser
+  // data to storage if there are duplicate records in each of these
+  // individual write buffers.  Default: 1
+  int min_write_buffer_number_to_merge;
+
+  // 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, rocksdb will automatically create and use an 8MB internal cache.
+  // Default: nullptr
+  shared_ptr<Cache> block_cache;
+
+  // If non-NULL use the specified cache for compressed blocks.
+  // If NULL, rocksdb will not use a compressed block cache.
+  // Default: nullptr
+  shared_ptr<Cache> block_cache_compressed;
+
+  // 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<CompressionType> 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;
+
+  // If non-nullptr, use the specified function to determine the
+  // prefixes for keys.  These prefixes will be placed in the filter.
+  // Depending on the workload, this can reduce the number of read-IOP
+  // cost for scans when a prefix is passed via ReadOptions to
+  // db.NewIterator().  For prefix filtering to work properly,
+  // "prefix_extractor" and "comparator" must be such that the following
+  // properties hold:
+  //
+  // 1) key.starts_with(prefix(key))
+  // 2) Compare(prefix(key), key) <= 0.
+  // 3) If Compare(k1, k2) <= 0, then Compare(prefix(k1), prefix(k2)) <= 0
+  // 4) prefix(prefix(key)) == prefix(key)
+  //
+  // Default: nullptr
+  const SliceTransform* prefix_extractor;
+
+  // If true, place whole keys in the filter (not just prefixes).
+  // This must generally be true for gets to be efficient.
+  //
+  // Default: true
+  bool whole_key_filtering;
+
+  // 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 start slowing 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;
+
+  // Different max-size multipliers for different levels.
+  // These are multiplied by max_bytes_for_level_multiplier to arrive
+  // at the max-size of each level.
+  // Default: 1
+  std::vector<int> max_bytes_for_level_multiplier_additional;
+
+  // 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.
+  shared_ptr<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 that 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 info 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;
+
+  // This specifies the absolute dir path for write-ahead logs (WAL).
+  // If it is empty, the log files will be in the same dir as data,
+  //   dbname is used as the data dir by default
+  // If it is non empty, the log files will be in kept the specified dir.
+  // When destroying the db,
+  //   all log files in wal_dir and the dir itself is deleted
+  std::string wal_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 6 hours. The files that get out of scope by compaction
+  // process will still get automatically delete on every compaction,
+  // regardless of this setting
+  uint64_t delete_obsolete_files_period_micros;
+
+  // Maximum number of concurrent background jobs, submitted to
+  // the default LOW priority thread pool
+  // Default: 1
+  int max_background_compactions;
+
+  // Maximum number of concurrent background memtable flush jobs, submitted to
+  // the HIGH priority thread pool.
+  // By default, all background jobs (major compaction and memtable flush) go
+  // to the LOW priority pool. If this option is set to a positive number,
+  // memtable flush jobs will be submitted to the HIGH priority pool.
+  // It is important when the same Env is shared by multiple db instances.
+  // Without a separate pool, long running major compaction jobs could
+  // potentially block memtable flush jobs of other db instances, leading to
+  // unnecessary Put stalls.
+  // Default: 0
+  int max_background_flushes;
+
+  // 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 0-1 ms when any level has a compaction score that exceeds
+  // soft_rate_limit. This is ignored when == 0.0.
+  // CONSTRAINT: soft_rate_limit <= hard_rate_limit. If this constraint does not
+  // hold, RocksDB will set soft_rate_limit = hard_rate_limit
+  // Default: 0 (disabled)
+  double soft_rate_limit;
+
+  // Puts are delayed 1ms at a time when any level has a compaction score that
+  // exceeds hard_rate_limit. This is ignored when <= 1.0.
+  // Default: 0 (disabled)
+  double hard_rate_limit;
+
+  // Max time a put will be stalled when hard_rate_limit is enforced. If 0, then
+  // there is no limit.
+  // Default: 1000
+  unsigned int rate_limit_delay_max_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 true,
+  // then no block cache should be used, and the block_cache should
+  // point to a nullptr object.
+  // Default: false
+  bool no_block_cache;
+
+  // Number of shards used for table cache.
+  int table_cache_numshardbits;
+
+  // During data eviction of table's LRU cache, it would be inefficient
+  // to strictly follow LRU because this piece of memory will not really
+  // be released unless its refcount falls to zero. Instead, make two
+  // passes: the first pass will release items with refcount = 1,
+  // and if not enough space releases after scanning the number of
+  // elements specified by this parameter, we will remove items in LRU
+  // order.
+  int table_cache_remove_scan_count_limit;
+
+  // size of one block in arena memory allocation.
+  // If <= 0, a proper value is automatically calculated (usually 1/10 of
+  // writer_buffer_size).
+  //
+  // Default: 0
+  size_t arena_block_size;
+
+  // 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
+  // constructor 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();
+
+  // Set up the default flush-block policy factory. By default, we'll use
+  // `FlushBlockBySizePolicyFactory` as the policy factory.
+  // Note: Please call this method after block_size and block_size_deviation
+  //       is set.
+  // REQUIRES: flush_block_policy_factory is not set.
+  Options* SetUpDefaultFlushBlockPolicyFactory();
+
+  // Disable automatic compactions. Manual compactions can still
+  // be issued on this database.
+  bool disable_auto_compactions;
+
+  // The following two fields affect how archived logs will be deleted.
+  // 1. If both set to 0, logs will be deleted asap and will not get into
+  //    the archive.
+  // 2. If WAL_ttl_seconds is 0 and WAL_size_limit_MB is not 0,
+  //    WAL files will be checked every 10 min and if total size is greater
+  //    then WAL_size_limit_MB, they will be deleted starting with the
+  //    earliest until size_limit is met. All empty files will be deleted.
+  // 3. If WAL_ttl_seconds is not 0 and WAL_size_limit_MB is 0, then
+  //    WAL files will be checked every WAL_ttl_secondsi / 2 and those that
+  //    are older than WAL_ttl_seconds will be deleted.
+  // 4. If both are not 0, WAL files will be checked every 10 min and both
+  //    checks will be performed with ttl being first.
+  uint64_t WAL_ttl_seconds;
+  uint64_t WAL_size_limit_MB;
+
+  // 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;
+
+  // Data being read from file storage may be buffered in the OS
+  // Default: true
+  bool allow_os_buffer;
+
+  // Allow the OS to mmap file for reading sst tables. Default: false
+  bool allow_mmap_reads;
+
+  // Allow the OS to mmap file for writing. Default: true
+  bool allow_mmap_writes;
+
+  // Disable child process inherit open files. Default: true
+  bool is_fd_close_on_exec;
+
+  // Skip log corruption error on recovery (If client is ok with
+  // losing most recent changes)
+  // Default: false
+  bool skip_log_error_on_recovery;
+
+  // if not zero, dump rocksdb.stats to LOG every stats_dump_period_sec
+  // Default: 3600 (1 hour)
+  unsigned int stats_dump_period_sec;
+
+  // This is used to close a block before it reaches the configured
+  // 'block_size'. If the percentage of free space in the current block is less
+  // than this specified number and adding a new record to the block will
+  // exceed the configured block size, then this block will be closed and the
+  // new record will be written to the next block.
+  // Default is 10.
+  int block_size_deviation;
+
+  // If set true, will hint the underlying file system that the file
+  // access pattern is random, when a sst file is opened.
+  // Default: true
+  bool advise_random_on_open;
+
+  // Specify the file access pattern once a compaction is started.
+  // It will be applied to all input files of a compaction.
+  // Default: NORMAL
+  enum { NONE, NORMAL, SEQUENTIAL, WILLNEED } access_hint_on_compaction_start;
+
+  // Use adaptive mutex, which spins in the user space before resorting
+  // to kernel. This could reduce context switch when the mutex is not
+  // heavily contended. However, if the mutex is hot, we could end up
+  // wasting spin time.
+  // Default: false
+  bool use_adaptive_mutex;
+
+  // Allows OS to incrementally sync files to disk while they are being
+  // written, asynchronously, in the background.
+  // Issue one request for every bytes_per_sync written. 0 turns it off.
+  // Default: 0
+  uint64_t bytes_per_sync;
+
+  // The compaction style. Default: kCompactionStyleLevel
+  CompactionStyle compaction_style;
+
+  // The options needed to support Universal Style compactions
+  CompactionOptionsUniversal compaction_options_universal;
+
+  // Use KeyMayExist API to filter deletes when this is true.
+  // If KeyMayExist returns false, i.e. the key definitely does not exist, then
+  // the delete is a noop. KeyMayExist only incurs in-memory look up.
+  // This optimization avoids writing the delete to storage when appropriate.
+  // Default: false
+  bool filter_deletes;
+
+  // An iteration->Next() sequentially skips over keys with the same
+  // user-key unless this option is set. This number specifies the number
+  // of keys (with the same userkey) that will be sequentially
+  // skipped before a reseek is issued.
+  // Default: 8
+  uint64_t max_sequential_skip_in_iterations;
+
+  // This is a factory that provides MemTableRep objects.
+  // Default: a factory that provides a skip-list-based implementation of
+  // MemTableRep.
+  std::shared_ptr<MemTableRepFactory> memtable_factory;
+
+  // This is a factory that provides TableFactory objects.
+  // Default: a factory that provides a default implementation of
+  // Table and TableBuilder.
+  std::shared_ptr<TableFactory> table_factory;
+
+  // This is a factory that provides compaction filter objects which allow
+  // an application to modify/delete a key-value during background compaction.
+  // Default: a factory that doesn't provide any object
+  std::shared_ptr<CompactionFilterFactory> compaction_filter_factory;
+
+  // This option allows user to to collect their own interested statistics of
+  // the tables.
+  // Default: emtpy vector -- no user-defined statistics collection will be
+  // performed.
+  std::vector<std::shared_ptr<TableStatsCollector>> table_stats_collectors;
+
+  // Allows thread-safe inplace updates. Requires Updates iff
+  // * key exists in current memtable
+  // * new sizeof(new_value) <= sizeof(old_value)
+  // * old_value for that key is a put i.e. kTypeValue
+  // Default: false.
+  bool inplace_update_support;
+
+  // Number of locks used for inplace update
+  // Default: 10000, if inplace_update_support = true, else 0.
+  size_t inplace_update_num_locks;
+
+  // Creates the instances of flush block policy.
+  // A flush-block policy provides a configurable way to determine when to
+  // flush a block in the block based tables,
+  // Default: nullptr. User can call FlushBlockBySizePolicyFactory() to set
+  // up default policy factory (`FlushBlockBySizePolicyFactory`).
+  std::shared_ptr<FlushBlockPolicyFactory> flush_block_policy_factory;
+};
+
+//
+// An application can issue a read request (via Get/Iterators) and specify
+// if that read should process data that ALREADY resides on a specified cache
+// level. For example, if an application specifies kBlockCacheTier then the
+// Get call will process data that is already processed in the memtable or
+// the block cache. It will not page in data from the OS cache or data that
+// resides in storage.
+enum ReadTier {
+  kReadAllTier    = 0x0, // data in memtable, block cache, OS cache or storage
+  kBlockCacheTier = 0x1  // data in memtable or block cache
+};
+
+// 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 block"/"index block"/"filter block" 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 this option is set and memtable implementation allows, Seek
+  // might only return keys with the same prefix as the seek-key
+  bool prefix_seek;
+
+  // 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;
+
+  // If "prefix" is non-nullptr, and ReadOptions is being passed to
+  // db.NewIterator, only return results when the key begins with this
+  // prefix.  This field is ignored by other calls (e.g., Get).
+  // Options.prefix_extractor must also be set, and
+  // prefix_extractor.InRange(prefix) must be true.  The iterator
+  // returned by NewIterator when this option is set will behave just
+  // as if the underlying store did not contain any non-matching keys,
+  // with two exceptions.  Seek() only accepts keys starting with the
+  // prefix, and SeekToLast() is not supported.  prefix filter with this
+  // option will sometimes reduce the number of read IOPs.
+  // Default: nullptr
+  const Slice* prefix;
+
+  // Specify if this read request should process data that ALREADY
+  // resides on a particular cache. If the required data is not
+  // found at the specified cache, then Status::Incomplete is returned.
+  // Default: kReadAllTier
+  ReadTier read_tier;
+
+  ReadOptions()
+      : verify_checksums(false),
+        fill_cache(true),
+        prefix_seek(false),
+        snapshot(nullptr),
+        prefix(nullptr),
+        read_tier(kReadAllTier) {
+  }
+  ReadOptions(bool cksum, bool cache) :
+              verify_checksums(cksum), fill_cache(cache),
+              prefix_seek(false), snapshot(nullptr), prefix(nullptr),
+              read_tier(kReadAllTier) {
+  }
+};
+
+// 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 "fdatasync()".
+  //
+  // 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 rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_OPTIONS_H_
diff --git a/include/rocksdb/perf_context.h b/include/rocksdb/perf_context.h
new file mode 100644 (file)
index 0000000..9142008
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef STORAGE_ROCKSDB_INCLUDE_PERF_CONTEXT_H
+#define STORAGE_ROCKSDB_INCLUDE_PERF_CONTEXT_H
+
+#include <stdint.h>
+
+namespace rocksdb {
+
+enum PerfLevel {
+  kDisable        = 0,  // disable perf stats
+  kEnableCount    = 1,  // enable only count stats
+  kEnableTime     = 2   // enable time stats too
+};
+
+// set the perf stats level
+void SetPerfLevel(PerfLevel level);
+
+// A thread local context for gathering performance counter efficiently
+// and transparently.
+
+struct PerfContext {
+
+  void Reset(); // reset all performance counters to zero
+
+  uint64_t user_key_comparison_count; // total number of user key comparisons
+  uint64_t block_cache_hit_count;     // total number of block cache hits
+  uint64_t block_read_count;          // total number of block reads (with IO)
+  uint64_t block_read_byte;           // total number of bytes from block reads
+  uint64_t block_read_time;           // total time spent on block reads
+  uint64_t block_checksum_time;       // total time spent on block checksum
+  uint64_t block_decompress_time;     // total time spent on block decompression
+  // total number of internal keys skipped over during iteration (overwritten or
+  // deleted, to be more specific, hidden by a put or delete of the same key)
+  uint64_t internal_key_skipped_count;
+  // total number of deletes skipped over during iteration
+  uint64_t internal_delete_skipped_count;
+  uint64_t wal_write_time;            // total time spent on writing to WAL
+};
+
+extern __thread PerfContext perf_context;
+
+}
+
+#endif
diff --git a/include/rocksdb/slice.h b/include/rocksdb/slice.h
new file mode 100644 (file)
index 0000000..8619986
--- /dev/null
@@ -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.
+//
+// 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_ROCKSDB_INCLUDE_SLICE_H_
+#define STORAGE_ROCKSDB_INCLUDE_SLICE_H_
+
+#include <assert.h>
+#include <stddef.h>
+#include <string.h>
+#include <string>
+
+namespace rocksdb {
+
+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"
+  /* implicit */
+  Slice(const std::string& s) : data_(s.data()), size_(s.size()) { }
+
+  // Create a slice that refers to s[0,strlen(s)-1]
+  /* implicit */
+  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 rocksdbjni access
+  const char* data_;
+  size_t size_;
+
+  // Intentionally copyable
+};
+
+// A set of Slices that are virtually concatenated together.  'parts' points
+// to an array of Slices.  The number of elements in the array is 'num_parts'.
+struct SliceParts {
+  SliceParts(const Slice* parts, int num_parts) :
+      parts(parts), num_parts(num_parts) { }
+
+  const Slice* parts;
+  int num_parts;
+};
+
+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 rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_SLICE_H_
diff --git a/include/rocksdb/slice_transform.h b/include/rocksdb/slice_transform.h
new file mode 100644 (file)
index 0000000..f22e226
--- /dev/null
@@ -0,0 +1,43 @@
+// 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.
+//
+// Class for specifying user-defined functions which perform a
+// transformation on a slice.  It is not required that every slice
+// belong to the domain and/or range of a function.  Subclasses should
+// define InDomain and InRange to determine which slices are in either
+// of these sets respectively.
+
+#ifndef STORAGE_ROCKSDB_INCLUDE_SLICE_TRANSFORM_H_
+#define STORAGE_ROCKSDB_INCLUDE_SLICE_TRANSFORM_H_
+
+#include <string>
+
+namespace rocksdb {
+
+class Slice;
+
+class SliceTransform {
+ public:
+  virtual ~SliceTransform() {};
+
+  // Return the name of this transformation.
+  virtual const char* Name() const = 0;
+
+  // transform a src in domain to a dst in the range
+  virtual Slice Transform(const Slice& src) const = 0;
+
+  // determine whether this is a valid src upon the function applies
+  virtual bool InDomain(const Slice& src) const = 0;
+
+  // determine whether dst=Transform(src) for some src
+  virtual bool InRange(const Slice& dst) const = 0;
+};
+
+extern const SliceTransform* NewFixedPrefixTransform(size_t prefix_len);
+
+extern const SliceTransform* NewNoopTransform();
+
+}
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_SLICE_TRANSFORM_H_
diff --git a/include/rocksdb/statistics.h b/include/rocksdb/statistics.h
new file mode 100644 (file)
index 0000000..dd273af
--- /dev/null
@@ -0,0 +1,301 @@
+// 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_ROCKSDB_INCLUDE_STATISTICS_H_
+#define STORAGE_ROCKSDB_INCLUDE_STATISTICS_H_
+
+#include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <string>
+#include <memory>
+#include <vector>
+
+namespace rocksdb {
+
+/**
+ * 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
+ * Add a string representation in TickersNameMap below.
+ * And incrementing TICKER_ENUM_MAX.
+ */
+enum Tickers {
+  // total block cache misses
+  // REQUIRES: BLOCK_CACHE_MISS == BLOCK_CACHE_INDEX_MISS +
+  //                               BLOCK_CACHE_FILTER_MISS +
+  //                               BLOCK_CACHE_DATA_MISS;
+  BLOCK_CACHE_MISS,
+  // total block cache hit
+  // REQUIRES: BLOCK_CACHE_HIT == BLOCK_CACHE_INDEX_HIT +
+  //                              BLOCK_CACHE_FILTER_HIT +
+  //                              BLOCK_CACHE_DATA_HIT;
+  BLOCK_CACHE_HIT,
+  // # of blocks added to block cache.
+  BLOCK_CACHE_ADD,
+  // # of times cache miss when accessing index block from block cache.
+  BLOCK_CACHE_INDEX_MISS,
+  // # of times cache hit when accessing index block from block cache.
+  BLOCK_CACHE_INDEX_HIT,
+  // # of times cache miss when accessing filter block from block cache.
+  BLOCK_CACHE_FILTER_MISS,
+  // # of times cache hit when accessing filter block from block cache.
+  BLOCK_CACHE_FILTER_HIT,
+  // # of times cache miss when accessing data block from block cache.
+  BLOCK_CACHE_DATA_MISS,
+  // # of times cache hit when accessing data block from block cache.
+  BLOCK_CACHE_DATA_HIT,
+  // # of times bloom filter has avoided file reads.
+  BLOOM_FILTER_USEFUL,
+
+  /**
+   * COMPACTION_KEY_DROP_* count the reasons for key drop during compaction
+   * There are 3 reasons currently.
+   */
+  COMPACTION_KEY_DROP_NEWER_ENTRY, // key was written with a newer value.
+  COMPACTION_KEY_DROP_OBSOLETE, // The key is obsolete.
+  COMPACTION_KEY_DROP_USER, // user compaction function has dropped the key.
+
+  // Number of keys written to the database via the Put and Write call's
+  NUMBER_KEYS_WRITTEN,
+  // Number of Keys read,
+  NUMBER_KEYS_READ,
+  // Number keys updated, if inplace update is enabled
+  NUMBER_KEYS_UPDATED,
+  // Bytes written / read
+  BYTES_WRITTEN,
+  BYTES_READ,
+  NO_FILE_CLOSES,
+  NO_FILE_OPENS,
+  NO_FILE_ERRORS,
+  // Time system had to wait to do LO-L1 compactions
+  STALL_L0_SLOWDOWN_MICROS,
+  // Time system had to wait to move memtable to L1.
+  STALL_MEMTABLE_COMPACTION_MICROS,
+  // write throttle because of too many files in L0
+  STALL_L0_NUM_FILES_MICROS,
+  RATE_LIMIT_DELAY_MILLIS,
+
+  NO_ITERATORS, // number of iterators currently open
+
+  // Number of MultiGet calls, keys read, and bytes read
+  NUMBER_MULTIGET_CALLS,
+  NUMBER_MULTIGET_KEYS_READ,
+  NUMBER_MULTIGET_BYTES_READ,
+
+  // Number of deletes records that were not required to be
+  // written to storage because key does not exist
+  NUMBER_FILTERED_DELETES,
+  NUMBER_MERGE_FAILURES,
+  SEQUENCE_NUMBER,
+
+  // number of times bloom was checked before creating iterator on a
+  // file, and the number of times the check was useful in avoiding
+  // iterator creation (and thus likely IOPs).
+  BLOOM_FILTER_PREFIX_CHECKED,
+  BLOOM_FILTER_PREFIX_USEFUL,
+
+  // Number of times we had to reseek inside an iteration to skip
+  // over large number of keys with same userkey.
+  NUMBER_OF_RESEEKS_IN_ITERATION,
+
+  // Record the number of calls to GetUpadtesSince. Useful to keep track of
+  // transaction log iterator refreshes
+  GET_UPDATES_SINCE_CALLS,
+
+  BLOCK_CACHE_COMPRESSED_MISS, // miss in the compressed block cache
+  BLOCK_CACHE_COMPRESSED_HIT,  // hit in the compressed block cache
+
+  TICKER_ENUM_MAX
+};
+
+// The order of items listed in  Tickers should be the same as
+// the order listed in TickersNameMap
+const std::vector<std::pair<Tickers, std::string>> TickersNameMap = {
+  { BLOCK_CACHE_MISS, "rocksdb.block.cache.miss" },
+  { BLOCK_CACHE_HIT, "rocksdb.block.cache.hit" },
+  { BLOCK_CACHE_ADD, "rocksdb.block.cache.add" },
+  { BLOCK_CACHE_INDEX_MISS, "rocksdb.block.cache.index.miss" },
+  { BLOCK_CACHE_INDEX_HIT, "rocksdb.block.cache.index.hit" },
+  { BLOCK_CACHE_FILTER_MISS, "rocksdb.block.cache.filter.miss" },
+  { BLOCK_CACHE_FILTER_HIT, "rocksdb.block.cache.filter.hit" },
+  { BLOCK_CACHE_DATA_MISS, "rocksdb.block.cache.data.miss" },
+  { BLOCK_CACHE_DATA_HIT, "rocksdb.block.cache.data.hit" },
+  { BLOOM_FILTER_USEFUL, "rocksdb.bloom.filter.useful" },
+  { COMPACTION_KEY_DROP_NEWER_ENTRY, "rocksdb.compaction.key.drop.new" },
+  { COMPACTION_KEY_DROP_OBSOLETE, "rocksdb.compaction.key.drop.obsolete" },
+  { COMPACTION_KEY_DROP_USER, "rocksdb.compaction.key.drop.user" },
+  { NUMBER_KEYS_WRITTEN, "rocksdb.number.keys.written" },
+  { NUMBER_KEYS_READ, "rocksdb.number.keys.read" },
+  { NUMBER_KEYS_UPDATED, "rocksdb.number.keys.updated" },
+  { BYTES_WRITTEN, "rocksdb.bytes.written" },
+  { BYTES_READ, "rocksdb.bytes.read" },
+  { NO_FILE_CLOSES, "rocksdb.no.file.closes" },
+  { NO_FILE_OPENS, "rocksdb.no.file.opens" },
+  { NO_FILE_ERRORS, "rocksdb.no.file.errors" },
+  { STALL_L0_SLOWDOWN_MICROS, "rocksdb.l0.slowdown.micros" },
+  { STALL_MEMTABLE_COMPACTION_MICROS, "rocksdb.memtable.compaction.micros" },
+  { STALL_L0_NUM_FILES_MICROS, "rocksdb.l0.num.files.stall.micros" },
+  { RATE_LIMIT_DELAY_MILLIS, "rocksdb.rate.limit.delay.millis" },
+  { NO_ITERATORS, "rocksdb.num.iterators" },
+  { NUMBER_MULTIGET_CALLS, "rocksdb.number.multiget.get" },
+  { NUMBER_MULTIGET_KEYS_READ, "rocksdb.number.multiget.keys.read" },
+  { NUMBER_MULTIGET_BYTES_READ, "rocksdb.number.multiget.bytes.read" },
+  { NUMBER_FILTERED_DELETES, "rocksdb.number.deletes.filtered" },
+  { NUMBER_MERGE_FAILURES, "rocksdb.number.merge.failures" },
+  { SEQUENCE_NUMBER, "rocksdb.sequence.number" },
+  { BLOOM_FILTER_PREFIX_CHECKED, "rocksdb.bloom.filter.prefix.checked" },
+  { BLOOM_FILTER_PREFIX_USEFUL, "rocksdb.bloom.filter.prefix.useful" },
+  { NUMBER_OF_RESEEKS_IN_ITERATION, "rocksdb.number.reseeks.iteration" },
+  { GET_UPDATES_SINCE_CALLS, "rocksdb.getupdatessince.calls" },
+  { BLOCK_CACHE_COMPRESSED_MISS, "rocksdb.block.cachecompressed.miss" },
+  { BLOCK_CACHE_COMPRESSED_HIT, "rocksdb.block.cachecompressed.hit" }
+};
+
+/**
+ * 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
+ * Add a string representation in HistogramsNameMap below
+ * And increment HISTOGRAM_ENUM_MAX
+ */
+enum Histograms {
+  DB_GET,
+  DB_WRITE,
+  COMPACTION_TIME,
+  TABLE_SYNC_MICROS,
+  COMPACTION_OUTFILE_SYNC_MICROS,
+  WAL_FILE_SYNC_MICROS,
+  MANIFEST_FILE_SYNC_MICROS,
+  // TIME SPENT IN IO DURING TABLE OPEN
+  TABLE_OPEN_IO_MICROS,
+  DB_MULTIGET,
+  READ_BLOCK_COMPACTION_MICROS,
+  READ_BLOCK_GET_MICROS,
+  WRITE_RAW_BLOCK_MICROS,
+
+  STALL_L0_SLOWDOWN_COUNT,
+  STALL_MEMTABLE_COMPACTION_COUNT,
+  STALL_L0_NUM_FILES_COUNT,
+  HARD_RATE_LIMIT_DELAY_COUNT,
+  SOFT_RATE_LIMIT_DELAY_COUNT,
+  NUM_FILES_IN_SINGLE_COMPACTION,
+  HISTOGRAM_ENUM_MAX,
+};
+
+const std::vector<std::pair<Histograms, std::string>> HistogramsNameMap = {
+  { DB_GET, "rocksdb.db.get.micros" },
+  { DB_WRITE, "rocksdb.db.write.micros" },
+  { COMPACTION_TIME, "rocksdb.compaction.times.micros" },
+  { TABLE_SYNC_MICROS, "rocksdb.table.sync.micros" },
+  { COMPACTION_OUTFILE_SYNC_MICROS, "rocksdb.compaction.outfile.sync.micros" },
+  { WAL_FILE_SYNC_MICROS, "rocksdb.wal.file.sync.micros" },
+  { MANIFEST_FILE_SYNC_MICROS, "rocksdb.manifest.file.sync.micros" },
+  { TABLE_OPEN_IO_MICROS, "rocksdb.table.open.io.micros" },
+  { DB_MULTIGET, "rocksdb.db.multiget.micros" },
+  { READ_BLOCK_COMPACTION_MICROS, "rocksdb.read.block.compaction.micros" },
+  { READ_BLOCK_GET_MICROS, "rocksdb.read.block.get.micros" },
+  { WRITE_RAW_BLOCK_MICROS, "rocksdb.write.raw.block.micros" },
+  { STALL_L0_SLOWDOWN_COUNT, "rocksdb.l0.slowdown.count"},
+  { STALL_MEMTABLE_COMPACTION_COUNT, "rocksdb.memtable.compaction.count"},
+  { STALL_L0_NUM_FILES_COUNT, "rocksdb.num.files.stall.count"},
+  { HARD_RATE_LIMIT_DELAY_COUNT, "rocksdb.hard.rate.limit.delay.count"},
+  { SOFT_RATE_LIMIT_DELAY_COUNT, "rocksdb.soft.rate.limit.delay.count"},
+  { NUM_FILES_IN_SINGLE_COMPACTION, "rocksdb.numfiles.in.singlecompaction" },
+};
+
+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 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.
+ * Thread safe. Locking managed by implementation of this interface.
+ */
+class Ticker {
+ public:
+  Ticker() : count_(0) { }
+
+  inline void setTickerCount(uint64_t count) {
+    count_ = count;
+  }
+
+  inline void recordTick(int count = 1) {
+    count_ += count;
+  }
+
+  inline uint64_t getCount() {
+    return count_;
+  }
+
+ private:
+  std::atomic_uint_fast64_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 setTickerCount(Tickers tickerType, uint64_t count) = 0;
+  virtual void measureTime(Histograms histogramType, uint64_t time) = 0;
+
+  virtual void histogramData(Histograms type, HistogramData * const data) = 0;
+  // String representation of the statistic object.
+  std::string ToString();
+};
+
+// Create a concrete DBStatistics object
+std::shared_ptr<Statistics> CreateDBStatistics();
+
+// Ease of Use functions
+inline void RecordTick(std::shared_ptr<Statistics> statistics,
+                       Tickers ticker,
+                       uint64_t count = 1) {
+  assert(HistogramsNameMap.size() == HISTOGRAM_ENUM_MAX);
+  assert(TickersNameMap.size() == TICKER_ENUM_MAX);
+  if (statistics) {
+    statistics->recordTick(ticker, count);
+  }
+}
+
+inline void SetTickerCount(std::shared_ptr<Statistics> statistics,
+                           Tickers ticker,
+                           uint64_t count) {
+  assert(HistogramsNameMap.size() == HISTOGRAM_ENUM_MAX);
+  assert(TickersNameMap.size() == TICKER_ENUM_MAX);
+  if (statistics) {
+    statistics->setTickerCount(ticker, count);
+  }
+}
+
+}  // namespace rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_STATISTICS_H_
diff --git a/include/rocksdb/status.h b/include/rocksdb/status.h
new file mode 100644 (file)
index 0000000..dabf771
--- /dev/null
@@ -0,0 +1,126 @@
+// 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_ROCKSDB_INCLUDE_STATUS_H_
+#define STORAGE_ROCKSDB_INCLUDE_STATUS_H_
+
+#include <string>
+#include "rocksdb/slice.h"
+
+namespace rocksdb {
+
+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);
+  }
+  static Status MergeInProgress(const Slice& msg, const Slice& msg2 = Slice()) {
+    return Status(kMergeInProgress, msg, msg2);
+  }
+  static Status Incomplete(const Slice& msg, const Slice& msg2 = Slice()) {
+    return Status(kIncomplete, 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; }
+
+  // Returns true iff the status indicates an MergeInProgress.
+  bool IsMergeInProgress() const { return code() == kMergeInProgress; }
+
+  // Returns true iff the status indicates Incomplete
+  bool IsIncomplete() const { return code() == kIncomplete; }
+
+  // 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,
+    kMergeInProgress = 6,
+    kIncomplete = 7
+  };
+
+  Code code() const {
+    return (state_ == nullptr) ? kOk : static_cast<Code>(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 rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_STATUS_H_
diff --git a/include/rocksdb/table.h b/include/rocksdb/table.h
new file mode 100644 (file)
index 0000000..f1b3632
--- /dev/null
@@ -0,0 +1,180 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <memory>
+#include <stdint.h>
+#include "rocksdb/env.h"
+#include "rocksdb/iterator.h"
+#include "rocksdb/table_stats.h"
+#include "rocksdb/options.h"
+
+namespace rocksdb {
+
+struct Options;
+class RandomAccessFile;
+struct ReadOptions;
+class TableCache;
+class WritableFile;
+
+using std::unique_ptr;
+
+// 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.
+class TableBuilder {
+ public:
+  // REQUIRES: Either Finish() or Abandon() has been called.
+  virtual ~TableBuilder() {}
+
+  // 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
+  virtual void Add(const Slice& key, const Slice& value) = 0;
+
+  // Return non-ok iff some error has been detected.
+  virtual Status status() const = 0;
+
+  // Finish building the table.
+  // REQUIRES: Finish(), Abandon() have not been called
+  virtual Status Finish() = 0;
+
+  // Indicate that the contents of this builder should be abandoned.
+  // If the caller is not going to call Finish(), it must call Abandon()
+  // before destroying this builder.
+  // REQUIRES: Finish(), Abandon() have not been called
+  virtual void Abandon() = 0;
+
+  // Number of calls to Add() so far.
+  virtual uint64_t NumEntries() const = 0;
+
+  // Size of the file generated so far.  If invoked after a successful
+  // Finish() call, returns the size of the final generated file.
+  virtual uint64_t FileSize() const = 0;
+};
+
+// 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 TableReader {
+ public:
+  virtual ~TableReader() {}
+
+  // Determine whether there is a chance that the current table file
+  // contains the key a key starting with iternal_prefix. The specific
+  // table implementation can use bloom filter and/or other heuristic
+  // to filter out this table as a whole.
+  virtual bool PrefixMayMatch(const Slice& internal_prefix) = 0;
+
+  // 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).
+  virtual Iterator* NewIterator(const ReadOptions&) = 0;
+
+  // 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.
+  virtual uint64_t ApproximateOffsetOf(const Slice& key) = 0;
+
+  // Returns true if the block for the specified key is in cache.
+  // REQUIRES: key is in this table.
+  virtual bool TEST_KeyInCache(const ReadOptions& options,
+                               const Slice& key) = 0;
+
+  // Set up the table for Compaction. Might change some parameters with
+  // posix_fadvise
+  virtual void SetupForCompaction() = 0;
+
+  virtual TableStats& GetTableStats() = 0;
+
+  // Calls (*result_handler)(handle_context, ...) repeatedly, starting with
+  // the entry found after a call to Seek(key), until result_handler returns
+  // false, where k is the actual internal key for a row found and v as the
+  // value of the key. didIO is true if I/O is involved in the operation. May
+  // not make such a call if filter policy says that key is not present.
+  //
+  // mark_key_may_exist_handler needs to be called when it is configured to be
+  // memory only and the key is not found in the block cache, with
+  // the parameter to be handle_context.
+  //
+  // readOptions is the options for the read
+  // key is the key to search for
+  virtual Status Get(
+      const ReadOptions& readOptions,
+      const Slice& key,
+      void* handle_context,
+      bool (*result_handler)(void* handle_context, const Slice& k,
+                             const Slice& v, bool didIO),
+      void (*mark_key_may_exist_handler)(void* handle_context) = nullptr) = 0;
+};
+
+// A base class for table factories
+class TableFactory {
+ public:
+  virtual ~TableFactory() {}
+
+  // The type of the table.
+  //
+  // The client of this package should switch to a new name whenever
+  // the table format implementation changes.
+  //
+  // Names starting with "rocksdb." are reserved and should not be used
+  // by any clients of this package.
+  virtual const char* Name() const = 0;
+
+  // Returns a Table object table that can fetch data from file specified
+  // in parameter file. It's the caller's responsibility to make sure
+  // file is in the correct format.
+  //
+  // GetTableReader() is called in two places:
+  // (1) TableCache::FindTable() calls the function when table cache miss
+  //     and cache the table object returned.
+  // (1) SstFileReader (for SST Dump) opens the table and dump the table
+  //     contents using the interator of the table.
+  // options and soptions are options. options is the general options.
+  // Multiple configured can be accessed from there, including and not
+  // limited to block cache and key comparators.
+  // file is a file handler to handle the file for the table
+  // file_size is the physical file size of the file
+  // table_reader is the output table reader
+  virtual Status GetTableReader(
+      const Options& options, const EnvOptions& soptions,
+      unique_ptr<RandomAccessFile> && file, uint64_t file_size,
+      unique_ptr<TableReader>* table_reader) const = 0;
+
+  // Return a table builder to write to a file for this table type.
+  //
+  // It is called in several places:
+  // (1) When flushing memtable to a level-0 output file, it creates a table
+  //     builder (In DBImpl::WriteLevel0Table(), by calling BuildTable())
+  // (2) During compaction, it gets the builder for writing compaction output
+  //     files in DBImpl::OpenCompactionOutputFile().
+  // (3) When recovering from transaction logs, it creates a table builder to
+  //     write to a level-0 output file (In DBImpl::WriteLevel0TableForRecovery,
+  //     by calling BuildTable())
+  // (4) When running Repairer, it creates a table builder to convert logs to
+  //     SST files (In Repairer::ConvertLogToTable() by calling BuildTable())
+  //
+  // options is the general options. Multiple configured can be acceseed from
+  // there, including and not limited to compression options.
+  // file is a handle of a writable file. It is the caller's responsibility to
+  // keep the file open and close the file after closing the table builder.
+  // compression_type is the compression type to use in this table.
+  virtual TableBuilder* GetTableBuilder(
+      const Options& options, WritableFile* file,
+      CompressionType compression_type) const = 0;
+};
+}  // namespace rocksdb
diff --git a/include/rocksdb/table_stats.h b/include/rocksdb/table_stats.h
new file mode 100644 (file)
index 0000000..4c3437a
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (c) 2013 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.
+#pragma once
+
+#include <string>
+#include <unordered_map>
+
+#include "rocksdb/status.h"
+
+namespace rocksdb {
+
+// TableStats contains a bunch of read-only stats of its associated
+// table.
+struct TableStats {
+ public:
+  // Other than basic table stats, each table may also have the user
+  // collected stats.
+  // The value of the user-collected stats are encoded as raw bytes --
+  // users have to interprete these values by themselves.
+  typedef
+    std::unordered_map<std::string, std::string>
+    UserCollectedStats;
+
+  // the total size of all data blocks.
+  uint64_t data_size = 0;
+  // the total size of all index blocks.
+  uint64_t index_size = 0;
+  // total raw key size
+  uint64_t raw_key_size = 0;
+  // total raw value size
+  uint64_t raw_value_size = 0;
+  // the number of blocks in this table
+  uint64_t num_data_blocks = 0;
+  // the number of entries in this table
+  uint64_t num_entries = 0;
+
+  // The name of the filter policy used in this table.
+  // If no filter policy is used, `filter_policy_name` will be an empty string.
+  std::string filter_policy_name;
+
+  // user collected stats
+  UserCollectedStats user_collected_stats;
+};
+
+// `TableStatsCollector` provides the mechanism for users to collect their own
+// interested stats. This class is essentially a collection of callback
+// functions that will be invoked during table building.
+class TableStatsCollector {
+ public:
+  virtual ~TableStatsCollector() { }
+  // Add() will be called when a new key/value pair is inserted into the table.
+  // @params key    the original key that is inserted into the table.
+  // @params value  the original value that is inserted into the table.
+  virtual Status Add(const Slice& key, const Slice& value) = 0;
+
+  // Finish() will be called when a table has already been built and is ready
+  // for writing the stats block.
+  // @params stats  User will add their collected statistics to `stats`.
+  virtual Status Finish(TableStats::UserCollectedStats* stats) = 0;
+
+  // The name of the stats collector can be used for debugging purpose.
+  virtual const char* Name() const = 0;
+};
+
+}  // namespace rocksdb
diff --git a/include/rocksdb/transaction_log.h b/include/rocksdb/transaction_log.h
new file mode 100644 (file)
index 0000000..30105b5
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright 2008-present Facebook. All Rights Reserved.
+#ifndef STORAGE_ROCKSDB_INCLUDE_TRANSACTION_LOG_ITERATOR_H_
+#define STORAGE_ROCKSDB_INCLUDE_TRANSACTION_LOG_ITERATOR_H_
+
+#include "rocksdb/status.h"
+#include "rocksdb/types.h"
+#include "rocksdb/write_batch.h"
+#include <memory>
+#include <vector>
+
+namespace rocksdb {
+
+class LogFile;
+typedef std::vector<std::unique_ptr<LogFile>> VectorLogPtr;
+
+enum  WalFileType {
+  /* Indicates that WAL file is in archive directory. WAL files are moved from
+   * the main db directory to archive directory once they are not live and stay
+   * there until cleaned up. Files are cleaned depending on archive size
+   * (Options::WAL_size_limit_MB) and time since last cleaning
+   * (Options::WAL_ttl_seconds).
+   */
+  kArchivedLogFile = 0,
+
+  /* Indicates that WAL file is live and resides in the main db directory */
+  kAliveLogFile = 1
+} ;
+
+class LogFile {
+ public:
+  LogFile() {}
+  virtual ~LogFile() {}
+
+  // Returns log file's pathname relative to the main db dir
+  // Eg. For a live-log-file = /000003.log
+  //     For an archived-log-file = /archive/000003.log
+  virtual std::string PathName() const = 0;
+
+
+  // Primary identifier for log file.
+  // This is directly proportional to creation time of the log file
+  virtual uint64_t LogNumber() const = 0;
+
+  // Log file can be either alive or archived
+  virtual WalFileType Type() const = 0;
+
+  // Starting sequence number of writebatch written in this log file
+  virtual SequenceNumber StartSequence() const = 0;
+
+  // Size of log file on disk in Bytes
+  virtual uint64_t SizeFileBytes() const = 0;
+};
+
+struct BatchResult {
+  SequenceNumber sequence = SequenceNumber();
+  std::unique_ptr<WriteBatch> writeBatchPtr;
+};
+
+// A TransactionLogIterator is used to iterate over the transactions in a db.
+// One run of the iterator is continuous, i.e. the iterator will stop at the
+// beginning of any gap in sequences
+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;
+
+  // Returns ok if the iterator is valid.
+  // Returns 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
+  // earliest transaction contained in the batch.
+  // ONLY use if Valid() is true and status() is OK.
+  virtual BatchResult GetBatch() = 0;
+};
+} //  namespace rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_TRANSACTION_LOG_ITERATOR_H_
diff --git a/include/rocksdb/types.h b/include/rocksdb/types.h
new file mode 100644 (file)
index 0000000..36cc85f
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef STORAGE_ROCKSDB_INCLUDE_TYPES_H_
+#define STORAGE_ROCKSDB_INCLUDE_TYPES_H_
+
+#include <stdint.h>
+
+namespace rocksdb {
+
+// Define all public custom types here.
+
+// Represents a sequence number in a WAL file.
+typedef uint64_t SequenceNumber;
+
+}  //  namespace rocksdb
+
+#endif //  STORAGE_ROCKSDB_INCLUDE_TYPES_H_
diff --git a/include/rocksdb/universal_compaction.h b/include/rocksdb/universal_compaction.h
new file mode 100644 (file)
index 0000000..46de688
--- /dev/null
@@ -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_ROCKSDB_UNIVERSAL_COMPACTION_OPTIONS_H
+#define STORAGE_ROCKSDB_UNIVERSAL_COMPACTION_OPTIONS_H
+
+#include <stddef.h>
+#include <string>
+#include <memory>
+#include <vector>
+#include <stdint.h>
+#include <climits>
+#include "rocksdb/slice.h"
+#include "rocksdb/statistics.h"
+
+namespace rocksdb {
+
+//
+// Algorithm used to make a compaction request stop picking new files
+// into a single compaction run
+//
+enum CompactionStopStyle {
+  kCompactionStopStyleSimilarSize, // pick files of similar size
+  kCompactionStopStyleTotalSize    // total size of picked files > next file
+};
+
+class CompactionOptionsUniversal {
+ public:
+
+  // Percentage flexibilty while comparing file size. If the candidate file(s)
+  // size is 1% smaller than the next file's size, then include next file into
+  // this candidate set. // Default: 1
+  unsigned int size_ratio;
+
+  // The minimum number of files in a single compaction run. Default: 2
+  unsigned int min_merge_width;
+
+  // The maximum number of files in a single compaction run. Default: UINT_MAX
+  unsigned int max_merge_width;
+
+  // The size amplification is defined as the amount (in percentage) of
+  // additional storage needed to store a single byte of data in the database.
+  // For example, a size amplification of 2% means that a database that
+  // contains 100 bytes of user-data may occupy upto 102 bytes of
+  // physical storage. By this definition, a fully compacted database has
+  // a size amplification of 0%. Rocksdb uses the following heuristic
+  // to calculate size amplification: it assumes that all files excluding
+  // the earliest file contribute to the size amplification.
+  // Default: 200, which means that a 100 byte database could require upto
+  // 300 bytes of storage.
+  unsigned int max_size_amplification_percent;
+
+  // If this option is set to be -1 (the default value), all the output files
+  // will follow compression type specified.
+  //
+  // If this option is not negative, we will try to make sure compressed
+  // size is just above this value. In normal cases, at least this percentage
+  // of data will be compressed.
+  // When we are compacting to a new file, here is the criteria whether
+  // it needs to be compressed: assuming here are the list of files sorted
+  // by generation time:
+  //    A1...An B1...Bm C1...Ct
+  // where A1 is the newest and Ct is the oldest, and we are going to compact
+  // B1...Bm, we calculate the total size of all the files as total_size, as
+  // well as  the total size of C1...Ct as total_C, the compaction output file
+  // will be compressed iff
+  //   total_C / total_size < this percentage
+  int compression_size_percent;
+
+  // The algorithm used to stop picking files into a single compaction run
+  // Default: kCompactionStopStyleTotalSize
+  CompactionStopStyle stop_style;
+
+  // Default set of parameters
+  CompactionOptionsUniversal() :
+    size_ratio(1),
+    min_merge_width(2),
+    max_merge_width(UINT_MAX),
+    max_size_amplification_percent(200),
+    compression_size_percent(-1),
+    stop_style(kCompactionStopStyleTotalSize) {
+  }
+};
+
+}  // namespace rocksdb
+
+#endif  // STORAGE_ROCKSDB_UNIVERSAL_COMPACTION_OPTIONS_H
diff --git a/include/rocksdb/write_batch.h b/include/rocksdb/write_batch.h
new file mode 100644 (file)
index 0000000..028e10d
--- /dev/null
@@ -0,0 +1,105 @@
+// 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_ROCKSDB_INCLUDE_WRITE_BATCH_H_
+#define STORAGE_ROCKSDB_INCLUDE_WRITE_BATCH_H_
+
+#include <string>
+#include "rocksdb/status.h"
+
+namespace rocksdb {
+
+class Slice;
+struct SliceParts;
+
+class WriteBatch {
+ public:
+  WriteBatch();
+  ~WriteBatch();
+
+  // Store the mapping "key->value" in the database.
+  void Put(const Slice& key, const Slice& value);
+
+  // Variant of Put() that gathers output like writev(2).  The key and value
+  // that will be written to the database are concatentations of arrays of
+  // slices.
+  void Put(const SliceParts& key, const SliceParts& value);
+
+  // Merge "value" with the existing value of "key" in the database.
+  // "key->merge(existing, value)"
+  void Merge(const Slice& key, const Slice& value);
+
+  // If the database contains a mapping for "key", erase it.  Else do nothing.
+  void Delete(const Slice& key);
+
+  // Append a blob of arbitrary size to the records in this batch. The blob will
+  // be stored in the transaction log but not in any other file. In particular,
+  // it will not be persisted to the SST files. When iterating over this
+  // WriteBatch, WriteBatch::Handler::LogData will be called with the contents
+  // of the blob as it is encountered. Blobs, puts, deletes, and merges will be
+  // encountered in the same order in thich they were inserted. The blob will
+  // NOT consume sequence number(s) and will NOT increase the count of the batch
+  //
+  // Example application: add timestamps to the transaction log for use in
+  // replication.
+  void PutLogData(const Slice& blob);
+
+  // 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;
+    // Merge and LogData are not pure virtual. Otherwise, we would break
+    // existing clients of Handler on a source code level. The default
+    // implementation of Merge simply throws a runtime exception.
+    virtual void Merge(const Slice& key, const Slice& value);
+    // The default implementation of LogData does nothing.
+    virtual void LogData(const Slice& blob);
+    virtual void Delete(const Slice& key) = 0;
+    // Continue is called by WriteBatch::Iterate. If it returns false,
+    // iteration is halted. Otherwise, it continues iterating. The default
+    // implementation always returns true.
+    virtual bool Continue();
+  };
+  Status Iterate(Handler* handler) const;
+
+  // Retrieve the serialized version of this batch.
+  std::string Data() { return rep_; }
+
+  // Returns the number of updates in the batch
+  int Count() const;
+
+  // Constructor with a serialized string object
+  explicit 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 rocksdb
+
+#endif  // STORAGE_ROCKSDB_INCLUDE_WRITE_BATCH_H_
diff --git a/include/utilities/stackable_db.h b/include/utilities/stackable_db.h
new file mode 100644 (file)
index 0000000..f15a22e
--- /dev/null
@@ -0,0 +1,161 @@
+// 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.
+
+#pragma once
+#include "rocksdb/db.h"
+
+namespace rocksdb {
+
+// This class contains APIs to stack rocksdb wrappers.Eg. Stack TTL over base d
+class StackableDB : public DB {
+ public:
+  explicit StackableDB(StackableDB* sdb) : sdb_(sdb) {}
+
+  // Returns the DB object that is the lowermost component in the stack of DBs
+  virtual DB* GetRawDB() {
+    return sdb_->GetRawDB();
+  }
+
+  // convert a DB to StackableDB
+  // TODO: This function does not work yet. Passing nullptr to StackableDB in
+  //       NewStackableDB's constructor will cause segfault on object's usage
+  static StackableDB* DBToStackableDB(DB* db) {
+    class NewStackableDB : public StackableDB {
+     public:
+      NewStackableDB(DB* db)
+        : StackableDB(nullptr),
+          db_(db) {}
+
+      DB* GetRawDB() {
+        return db_;
+      }
+
+     private:
+      DB* db_;
+    };
+    return new NewStackableDB(db);
+  }
+
+  virtual Status Put(const WriteOptions& options,
+                     const Slice& key,
+                     const Slice& val) override {
+    return sdb_->Put(options, key, val);
+  }
+
+  virtual Status Get(const ReadOptions& options,
+                     const Slice& key,
+                     std::string* value) override {
+    return sdb_->Get(options, key, value);
+  }
+
+  virtual std::vector<Status> MultiGet(const ReadOptions& options,
+                                       const std::vector<Slice>& keys,
+                                       std::vector<std::string>* values)
+    override {
+      return sdb_->MultiGet(options, keys, values);
+  }
+
+  virtual bool KeyMayExist(const ReadOptions& options,
+                           const Slice& key,
+                           std::string* value,
+                           bool* value_found = nullptr) override {
+    return sdb_->KeyMayExist(options, key, value, value_found);
+  }
+
+  virtual Status Delete(const WriteOptions& wopts, const Slice& key) override {
+    return sdb_->Delete(wopts, key);
+  }
+
+  virtual Status Merge(const WriteOptions& options,
+                       const Slice& key,
+                       const Slice& value) override {
+    return sdb_->Merge(options, key, value);
+  }
+
+
+  virtual Status Write(const WriteOptions& opts, WriteBatch* updates)
+    override {
+      return sdb_->Write(opts, updates);
+  }
+
+  virtual Iterator* NewIterator(const ReadOptions& opts) override {
+    return sdb_->NewIterator(opts);
+  }
+
+  virtual const Snapshot* GetSnapshot() override {
+    return sdb_->GetSnapshot();
+  }
+
+  virtual void ReleaseSnapshot(const Snapshot* snapshot) override {
+    return sdb_->ReleaseSnapshot(snapshot);
+  }
+
+  virtual bool GetProperty(const Slice& property, std::string* value)
+    override {
+      return sdb_->GetProperty(property, value);
+  }
+
+  virtual void GetApproximateSizes(const Range* r, int n, uint64_t* sizes)
+    override {
+      return sdb_->GetApproximateSizes(r, n, sizes);
+  }
+
+  virtual void CompactRange(const Slice* begin, const Slice* end,
+                            bool reduce_level = false,
+                            int target_level = -1) override {
+    return sdb_->CompactRange(begin, end, reduce_level, target_level);
+  }
+
+  virtual int NumberLevels() override {
+    return sdb_->NumberLevels();
+  }
+
+  virtual int MaxMemCompactionLevel() override {
+    return sdb_->MaxMemCompactionLevel();
+  }
+
+  virtual int Level0StopWriteTrigger() override {
+    return sdb_->Level0StopWriteTrigger();
+  }
+
+  virtual Status Flush(const FlushOptions& fopts) override {
+    return sdb_->Flush(fopts);
+  }
+
+  virtual Status DisableFileDeletions() override {
+    return sdb_->DisableFileDeletions();
+  }
+
+  virtual Status EnableFileDeletions() override {
+    return sdb_->EnableFileDeletions();
+  }
+
+  virtual Status GetLiveFiles(std::vector<std::string>& vec, uint64_t* mfs,
+                              bool flush_memtable = true) override {
+      return sdb_->GetLiveFiles(vec, mfs, flush_memtable);
+  }
+
+  virtual SequenceNumber GetLatestSequenceNumber() const override {
+    return sdb_->GetLatestSequenceNumber();
+  }
+
+  virtual Status GetSortedWalFiles(VectorLogPtr& files) override {
+    return sdb_->GetSortedWalFiles(files);
+  }
+
+  virtual Status DeleteFile(std::string name) override {
+    return sdb_->DeleteFile(name);
+  }
+
+  virtual Status GetUpdatesSince(SequenceNumber seq_number,
+                                 unique_ptr<TransactionLogIterator>* iter)
+    override {
+      return sdb_->GetUpdatesSince(seq_number, iter);
+  }
+
+ protected:
+  StackableDB* sdb_;
+};
+
+} //  namespace rocksdb
diff --git a/include/utilities/utility_db.h b/include/utilities/utility_db.h
new file mode 100644 (file)
index 0000000..1a7a269
--- /dev/null
@@ -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.
+
+#pragma once
+#include "stackable_db.h"
+
+namespace rocksdb {
+
+// This class contains APIs to open rocksdb with specific support eg. TTL
+class UtilityDB {
+
+  public:
+    // Open the database with TTL support.
+    //
+    // USE-CASES:
+    // This API should be used to open the db when key-values inserted are
+    //  meant to be removed from the db in a non-strict 'ttl' amount of time
+    //  Therefore, this guarantees that key-values inserted will remain in the
+    //  db for >= ttl amount of time and the db will make efforts to remove the
+    //  key-values as soon as possible after ttl seconds of their insertion.
+    //
+    // BEHAVIOUR:
+    // TTL is accepted in seconds
+    // (int32_t)Timestamp(creation) is suffixed to values in Put internally
+    // Expired TTL values deleted in compaction only:(Timestamp+ttl<time_now)
+    // Get/Iterator may return expired entries(compaction not run on them yet)
+    // Different TTL may be used during different Opens
+    // Example: Open1 at t=0 with ttl=4 and insert k1,k2, close at t=2
+    //          Open2 at t=3 with ttl=5. Now k1,k2 should be deleted at t>=5
+    // read_only=true opens in the usual read-only mode. Compactions will not be
+    //  triggered(neither manual nor automatic), so no expired entries removed
+    //
+    // CONSTRAINTS:
+    // Not specifying/passing or non-positive TTL behaves like TTL = infinity
+    //
+    // !!!WARNING!!!:
+    // Calling DB::Open directly to re-open a db created by this API will get
+    //  corrupt values(timestamp suffixed) and no ttl effect will be there
+    //  during the second Open, so use this API consistently to open the db
+    // Be careful when passing ttl with a small positive value because the
+    //  whole database may be deleted in a small amount of time
+    static Status OpenTtlDB(const Options& options,
+                            const std::string& name,
+                            StackableDB** dbptr,
+                            int32_t ttl = 0,
+                            bool read_only = false);
+};
+
+} //  namespace rocksdb
diff --git a/index.html b/index.html
new file mode 100644 (file)
index 0000000..1a9f030
--- /dev/null
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<html prefix="og: http://ogp.me/ns#">
+<head>
+    <meta charset='utf-8'>
+    <title>RocksDB | A persistent key-value store for fast storage environments</title>
+    <link rel='stylesheet' href='static/rocksdb.css' type='text/css'/>
+    <link rel='shortcut icon' href='static/favicon.ico'>
+    <meta name='viewport' content='width=device-width'>
+    <meta property='og:type' content='website'>
+    <meta property='og:title' content='RocksDB | A persistent key-value store for fast storage environments'>
+    <meta property='og:description' content='A persistent key-value store for fast storage environments'>
+    <meta property='og:image' content='http://rocksdb.org/static/rocksdb.png'>
+</head>
+<body>
+
+<header class='topbar'><nav class='width'>
+    <a href='index.html'><h1>RocksDB</h1></a>
+    <ul>
+        <li><a href='overview.html'>Overview</a></li>
+        <li><a href='https://github.com/facebook/rocksdb/wiki/_pages'>Wiki</a></li>
+        <li><a href='https://github.com/facebook/rocksdb'>GitHub</a>
+    </ul>
+</nav></header>
+
+<header class='hero'><div class='width'>
+    <hgroup>
+        <h1>
+            A persistent key-value store for fast storage environments
+        </h1>
+        <a class='button' href='overview.html'>Get Started</a>
+    </hgroup>
+    <aside>
+        <a href='overview.html'>
+            <img src='static/rocksdbhero.png' />
+        </a>
+    </aside>
+</div></header>
+
+<section class='content'><div class='width'>
+
+    <article>
+
+<h2>What is RocksDB?</h2>
+
+<p>
+RocksDB is an embeddable persistent key-value store for fast storage. RocksDB
+can also be the foundation for a client-server database but our current focus is
+on embedded workloads.
+</p>
+
+<p>
+RocksDB builds on <a href='https://code.google.com/p/leveldb/'>LevelDB</a> to be
+scalable to run on servers with many CPU cores, to efficiently use fast storage,
+to support IO-bound, in-memory and write-once workloads, and to be flexible to
+allow for innovation.
+</p>
+
+<p>For more background on RocksDB, see <a href="intro.pdf">Dhruba Borthakur's
+introductory talk</a> from the Data @ Scale 2013 conference.</p>
+
+<h2>How does performance compare?</h2>
+
+<p>
+We benchmarked LevelDB and found that it was unsuitable for our server
+workloads. The <a
+href='http://leveldb.googlecode.com/svn/trunk/doc/benchmark.html'> benchmark
+results</a> look awesome at first sight, but we quickly realized that those
+results were for a database whose size was smaller than the size of RAM on the
+test machine - where the entire database could fit in the OS page cache. When we
+performed the same benchmarks on a database that was at least 5 times larger
+than main memory, the performance results were dismal.
+</p>
+
+<p>
+By contrast, we've published the <a
+href='https://github.com/facebook/rocksdb/wiki/Performance-Benchmarks'> RocksDB
+benchmark results</a> for server side workloads on Flash. We also measured the
+performance of LevelDB on these server-workload benchmarks and found that
+RocksDB solidly outperforms LevelDB for these IO bound workloads. We found that
+LevelDB's single-threaded compaction process was insufficient to drive server
+workloads. We saw frequent write-stalls with LevelDB that caused 99-percentile
+latency to be tremendously large. We found that mmap-ing a file into the OS
+cache introduced performance bottlenecks for reads. We could not make LevelDB
+consume all the IOs offered by the underlying Flash storage.
+</p>
+
+<h2>What is RocksDB suitable for?</h2>
+
+<p>
+RocksDB can be used by applications that need low latency database accesses. A
+user-facing application that stores the viewing history and state of users of a
+website can potentially store this content on RocksDB. A spam detection
+application that needs fast access to big data sets can use RocksDB. A
+graph-search query that needs to scan a data set in realtime can use RocksDB.
+RocksDB can be used to cache data from Hadoop, thereby allowing applications to
+query Hadoop data in realtime. A message-queue that supports a high number of
+inserts and deletes can use RocksDB.
+</p>
+
+<h2>Why is RocksDB open sourced?</h2>
+
+<p>
+We are open sourcing this project <a
+href='http://github.com/facebook/rocksdb'>on GitHub</a> because we think it will
+be useful beyond Facebook. We are hoping that software programmers and database
+developers will use, enhance, and customize RocksDB for their use-cases. We
+would also like to engage with the academic community on topics related to
+efficiency for modern database algorithms.
+</p>
+
+    </article>
+
+    <aside>
+        <h3>Quick links</h3>
+        <ul>
+            <li><a href='overview.html'>Overview</a></li>
+            <li><a href='https://github.com/facebook/rocksdb/wiki/_pages'>Wiki</a></li>
+            <li><a href='https://github.com/facebook/rocksdb'>GitHub</a>
+        </ul>
+        <h3>Community</h3>
+        <ul>
+            <li><a href='https://github.com/facebook/rocksdb/issues'>Report an issue</a></li>
+            <li><a href='https://www.facebook.com/groups/rocksdb.dev/'>Facebook Group</a></li>
+            <li><a href='https://www.facebook.com/rocksdb'>Facebook Page</a></li>
+            <li><a href='meetup.html'>Local Meetups</a></li>
+            <li>
+                <div class='fb-like'
+                data-href='https://www.facebook.com/rocksdb'
+                data-layout='button_count' data-action='like'
+                data-show-faces='false' data-share='true'></div>
+            </li>
+        </ul>
+        <h3>Open source</h3>
+        <ul>
+            <li><a href='https://github.com/facebook/rocksdb/blob/master/LICENSE'>BSD license</a></li>
+            <li><a href='https://github.com/facebook/rocksdb/blob/master/CONTRIBUTING.md'>Contributing</a></li>
+            <li><a href='https://github.com/facebook/rocksdb/blob/master/PATENTS'>Patent grant</a></li>
+        </ul>
+    </aside>
+
+</div></section>
+
+<footer><div class='width'>
+    &copy; Copyright 2013, Facebook
+</div></footer>
+
+<div id='fb-root'></div>
+<script>(function(d, s, id) {
+    var js, fjs = d.getElementsByTagName(s)[0];
+    if (d.getElementById(id)) return;
+    js = d.createElement(s); js.id = id;
+    js.src = '//connect.facebook.net/en_US/all.js#xfbml=1';
+    fjs.parentNode.insertBefore(js, fjs);
+}(document, 'script', 'facebook-jssdk'));</script>
+
+</body>
+</html>
diff --git a/intro.pdf b/intro.pdf
new file mode 100644 (file)
index 0000000..ebf9196
Binary files /dev/null and b/intro.pdf differ
diff --git a/linters/src/.phutil_module_cache b/linters/src/.phutil_module_cache
new file mode 100644 (file)
index 0000000..5c93a84
--- /dev/null
@@ -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 (file)
index 0000000..4b8d3d1
--- /dev/null
@@ -0,0 +1,3 @@
+<?php
+
+phutil_register_library('linters', __FILE__);
diff --git a/linters/src/__phutil_library_map__.php b/linters/src/__phutil_library_map__.php
new file mode 100644 (file)
index 0000000..cb10bed
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is automatically generated. Use 'arc liberate' to rebuild it.
+ * @generated
+ * @phutil-library-version 2
+ */
+
+phutil_register_library_map(array(
+  '__library_version__' => 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 (file)
index 0000000..e62d3bb
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+
+class FbcodeCppLinter extends ArcanistLinter {
+  const CPPLINT      = "/home/engshare/tools/cpplint";
+  const LINT_ERROR   = 1;
+  const LINT_WARNING = 2;
+  const C_FLAG = "--c_mode=true";
+  private $rawLintOutput = array();
+
+  public function willLintPaths(array $paths) {
+    $futures = array();
+    $ret_value = 0;
+    $last_line = system("which cpplint", $ret_value);
+    $CPP_LINT = false;
+    if ($ret_value == 0) {
+      $CPP_LINT = $last_line;
+    } else if (file_exists(self::CPPLINT)) {
+      $CPP_LINT = self::CPPLINT;
+    }
+
+    if ($CPP_LINT) {
+      foreach ($paths as $p) {
+        $lpath = $this->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 (file)
index 0000000..6736614
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+// Copyright 2004-present Facebook.  All rights reserved.
+
+class PfffCppLinter extends ArcanistLinter {
+  const PROGRAM      = "/home/engshare/tools/checkCpp";
+
+  public function getLinterName() {
+    return "checkCpp";
+  }
+  public function getLintNameMap() {
+    return array(
+    );
+  }
+
+  public function getLintSeverityMap() {
+    return array(
+    );
+  }
+
+  public function willLintPaths(array $paths) {
+    $program = false;
+    $ret_value = 0;
+    $last_line = system("which checkCpp", $ret_value);
+    if ($ret_value == 0) {
+      $program = $last_line;
+    } else if (file_exists(self::PROGRAM)) {
+      $program = self::PROGRAM;
+    }
+    if ($program) {
+      $futures = array();
+      foreach ($paths as $p) {
+        $futures[$p] = new ExecFuture("%s --lint %s 2>&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 (file)
index 0000000..c34530c
--- /dev/null
@@ -0,0 +1,147 @@
+<?php
+// Copyright 2004-present Facebook.  All rights reserved.
+
+class FacebookFbcodeLintEngine extends ArcanistLintEngine {
+
+  public function buildLinters() {
+    $linters = array();
+    $paths = $this->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/meetup.html b/meetup.html
new file mode 100644 (file)
index 0000000..bdc16dd
--- /dev/null
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html prefix="og: http://ogp.me/ns#">
+<head>
+    <meta charset='utf-8'>
+    <title>RocksDB | A persistent key-value store for fast storage environments</title>
+    <link rel='stylesheet' href='static/rocksdb.css' type='text/css'/>
+    <link rel='shortcut icon' href='static/favicon.ico'>
+    <meta name='viewport' content='width=device-width'>
+    <meta property='og:type' content='website'>
+    <meta property='og:title' content='RocksDB | A persistent key-value store for fast storage environments'>
+    <meta property='og:description' content='A persistent key-value store for fast storage environments'>
+    <meta property='og:image' content='http://rocksdb.org/static/rocksdb.png'>
+</head>
+<body>
+
+<header class='topbar'><nav class='width'>
+    <a href='index.html'><h1>RocksDB</h1></a>
+    <ul>
+        <li><a href='overview.html' class='active'>Overview</a></li>
+        <li><a href='https://github.com/facebook/rocksdb/wiki/_pages'>Wiki</a></li>
+        <li><a href='https://github.com/facebook/rocksdb'>GitHub</a>
+    </ul>
+</nav></header>
+
+<header class='hero'><div class='width'>
+    <hgroup>
+        <h1>
+            Local Meetups (Bay Area)
+        </h1>
+    </hgroup>
+</div></header>
+
+<section class='content'><div class='width'>
+
+    <article>
+
+<h2>Call For Participation</h2>
+
+<p> RocksDB is an embeddable persistent key-value store for fast storage 
+(especially Flash and RAM storage) for server workloads (http://rocksdb.org/). 
+It has highly flexible configurable settings that can be tuned to run on a 
+variety of production environments. Since open sourced by Facebook in 2013 
+Nov, it has accumulated 1700+ stars and 230+ forks on github. </p>
+
+<p> RocksDB team @ Facebook is organizing the 1st meetup with people using 
+or interested in RocksDB technology. We would like to share our recent
+experience on handling varied workloads at Facebook. We would also like to 
+gather community feedback on the design of Column Families. We want to hear 
+about your experience with RocksDB and the issues you are facing. </p>
+
+<h2>Tentative Agenda</h2>
+
+<ul>
+<li><b>Date:</b> Thursday, March 27, 2014 </li>
+<li><b>Time:</b> 6-9:30pm PST </li>
+<li><b>Location:</b> [Room TBD], 1601 Willow Road, Menlo Park, 
+CA 94025 (Facebook HQ) </li>
+</ul>
+
+<ul>
+<li>6:00-6:50pm        &nbsp;&nbsp;&nbsp;&nbsp; Arrival and Refreshments</li>
+<li>6:50-7:00pm        &nbsp;&nbsp;&nbsp;&nbsp; Introduction</li>
+<li>7:00-7:30pm        &nbsp;&nbsp;&nbsp;&nbsp; Enhancements to RocksDB to support a 
+1PB In-Memory Workload at FB  (20-min talk + 10-min Q&A)</li>
+<li>7:30-8:00pm        &nbsp;&nbsp;&nbsp;&nbsp; Invited Talk on Using RocksDB in XXX 
+Company (20-min talk + 10-min Q&A)</li>
+<li>8:00-8:30pm        &nbsp;&nbsp;&nbsp;&nbsp; Deep Dive into Column Family design 
+(20-min talk + 10-min Q&A)</li>
+<li>8:30-9:30pm        &nbsp;&nbsp;&nbsp;&nbsp; Happy Hour</li>
+</ul>
+
+<h2>How to Register?</h2>
+
+<p>
+Please send registration email to Vanessa Nance (vanessan@fb.com), with the 
+following information:
+
+<ul>
+<li>Name:</li>
+<li>Company:</li>
+<li>Email:</li>
+<li>Team:</li>
+<li>Are you an engineer? If not, what’s your position:</li>
+<li>Areas you are working or worked on:</li>
+<li>How much do you know about RocksDB:</li>
+</ul>
+
+Please note that you need to sign 
+<a href='Facebook_Mutual_NDA_2012.pdf'>NDA</a> when you come to the event. 
+It's normal NDA for people visiting FB, nothing special. Please let us know 
+if you have any concern.
+
+</p>
+
+    </article>
+
+</div></section>
+
+<footer><div class='width'>
+    &copy; Copyright 2013, Facebook
+</div></footer>
+
+</body>
+</html>
diff --git a/overview.html b/overview.html
new file mode 100644 (file)
index 0000000..3aa4caa
--- /dev/null
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<html prefix="og: http://ogp.me/ns#">
+<head>
+    <meta charset='utf-8'>
+    <title>RocksDB | A persistent key-value store for fast storage environments</title>
+    <link rel='stylesheet' href='static/rocksdb.css' type='text/css'/>
+    <link rel='shortcut icon' href='static/favicon.ico'>
+    <meta name='viewport' content='width=device-width'>
+    <meta property='og:type' content='website'>
+    <meta property='og:title' content='RocksDB | A persistent key-value store for fast storage environments'>
+    <meta property='og:description' content='A persistent key-value store for fast storage environments'>
+    <meta property='og:image' content='http://rocksdb.org/static/rocksdb.png'>
+</head>
+<body>
+
+<header class='topbar'><nav class='width'>
+    <a href='index.html'><h1>RocksDB</h1></a>
+    <ul>
+        <li><a href='overview.html' class='active'>Overview</a></li>
+        <li><a href='https://github.com/facebook/rocksdb/wiki/_pages'>Wiki</a></li>
+        <li><a href='https://github.com/facebook/rocksdb'>GitHub</a>
+    </ul>
+</nav></header>
+
+<header class='hero'><div class='width'>
+    <hgroup>
+        <h1>
+            Overview
+        </h1>
+    </hgroup>
+</div></header>
+
+<section class='content'><div class='width'>
+
+    <article>
+
+<p> The <code>rocksdb</code> 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. </p>
+
+<p> The library is maintained by the Facebook Database Engineering Team, and is
+based on leveldb, by Sanjay Ghemawat and Jeff Dean at Google. </p>
+
+<p>
+This overview gives some simple examples of how RocksDB is used. For the story
+of why RocksDB was created in the first place, see <a href="intro.pdf">Dhruba
+Borthakur's introductory talk</a> from the Data @ Scale 2013 conference.
+</p>
+
+<h2>Opening A Database</h2>
+
+<p> A <code>rocksdb</code> 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:
+</p>
+
+<pre>#include &lt;assert&gt;
+#include "rocksdb/db.h"
+
+rocksdb::DB* db;
+rocksdb::Options options;
+options.create_if_missing = true;
+rocksdb::Status status =
+  rocksdb::DB::Open(options, "/tmp/testdb", &amp;db);
+assert(status.ok());
+...</pre>
+
+<p>
+If you want to raise an error if the database already exists, add the following
+line before the <code>rocksdb::DB::Open</code> call:
+</p>
+
+<pre>options.error_if_exists = true;</pre>
+
+<h2>Status</h2>
+
+<p>
+You may have noticed the <code>rocksdb::Status</code> type above. Values of this
+type are returned by most functions in <code>rocksdb</code> that may encounter
+an error. You can check if such a result is ok, and also print an associated
+error message:
+</p>
+
+<pre>rocksdb::Status s = ...;
+if (!s.ok()) cerr &lt;&lt; s.ToString() &lt;&lt; endl;</pre>
+
+<h2>Closing A Database</h2>
+
+<p>
+When you are done with a database, just delete the database object. For example:
+</p>
+
+<pre>/* open the db as described above */
+/* do something with db */
+delete db;</pre>
+
+<h2>Reads And Writes</h2>
+
+<p>
+The database provides <code>Put</code>, <code>Delete</code>, and
+<code>Get</code> methods to modify/query the database. For example, the
+following code moves the value stored under <code>key1</code> to
+<code>key2</code>.
+</p>
+
+<pre>std::string value;
+rocksdb::Status s = db-&gt;Get(rocksdb::ReadOptions(), key1, &amp;value);
+if (s.ok()) s = db-&gt;Put(rocksdb::WriteOptions(), key2, value);
+if (s.ok()) s = db-&gt;Delete(rocksdb::WriteOptions(), key1);</pre>
+
+<h2>Further documentation</h2>
+
+<p>
+These are just simple examples of how RocksDB is used. The full documentation is
+available within the
+<a href='https://github.com/facebook/rocksdb/blob/master/doc/'><code>/doc</code></a>
+folder of the project.
+</p>
+
+<p>
+In addition, further details about the RocksDB implementation may be found in
+the following documents:
+</p>
+
+<ul>
+<li><a href='https://github.com/facebook/rocksdb/wiki/_pages'>
+RocksDB Project Wiki</a></li>
+<li><a href='https://github.com/facebook/rocksdb/wiki/Rocksdb-Architecture-Guide'>
+Architecture Guide</a></li>
+<li><a href='https://github.com/facebook/rocksdb/wiki/Rocksdb-Table-Format'>
+Format of an immutable Table file</a></li>
+<li> <a href='https://github.com/facebook/rocksdb/blob/master/doc/log_format.txt'>
+Format of a log file</a></li>
+</ul>
+
+    </article>
+
+</div></section>
+
+<footer><div class='width'>
+    &copy; Copyright 2013, Facebook
+</div></footer>
+
+</body>
+</html>
diff --git a/port/README b/port/README
new file mode 100644 (file)
index 0000000..422563e
--- /dev/null
@@ -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_<platform>.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 (file)
index 0000000..2527ff9
--- /dev/null
@@ -0,0 +1,157 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <cstdatomic>
+//   implementation.  Also, some <cstdatomic> implementations are much
+//   slower than a memory-barrier based implementation (~16ns for
+//   <cstdatomic> 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 <stdint.h>
+#ifdef LEVELDB_CSTDATOMIC_PRESENT
+#include <cstdatomic>
+#endif
+#ifdef OS_WIN
+#include <windows.h>
+#endif
+#ifdef OS_MACOSX
+#include <libkern/OSAtomic.h>
+#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 rocksdb {
+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 <cstdatomic>
+#elif defined(LEVELDB_CSTDATOMIC_PRESENT)
+class AtomicPointer {
+ private:
+  std::atomic<void*> 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 <cstdatomic>
+#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 rocksdb
+
+#endif  // PORT_ATOMIC_POINTER_H_
diff --git a/port/port.h b/port/port.h
new file mode 100644 (file)
index 0000000..53a5816
--- /dev/null
@@ -0,0 +1,24 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <string.h>
+
+// 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_<platform>.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 (file)
index 0000000..64a5791
--- /dev/null
@@ -0,0 +1,140 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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_<platform>.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 rocksdb {
+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 rocksdb
+
+#endif  // STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_
diff --git a/port/port_posix.cc b/port/port_posix.cc
new file mode 100644 (file)
index 0000000..f7025f4
--- /dev/null
@@ -0,0 +1,86 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <cstdlib>
+#include <stdio.h>
+#include <string.h>
+#include "util/logging.h"
+
+namespace rocksdb {
+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(bool adaptive) {
+#ifdef OS_LINUX
+  if (!adaptive) {
+    PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL));
+  } else {
+    pthread_mutexattr_t mutex_attr;
+    PthreadCall("init mutex attr", pthread_mutexattr_init(&mutex_attr));
+    PthreadCall("set mutex attr",
+                pthread_mutexattr_settype(&mutex_attr,
+                                          PTHREAD_MUTEX_ADAPTIVE_NP));
+    PthreadCall("init mutex", pthread_mutex_init(&mu_, &mutex_attr));
+    PthreadCall("destroy mutex attr",
+                pthread_mutexattr_destroy(&mutex_attr));
+  }
+#else // ignore adaptive for non-linux platform
+  PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL));
+#endif // OS_LINUX
+}
+
+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 rocksdb
diff --git a/port/port_posix.h b/port/port_posix.h
new file mode 100644 (file)
index 0000000..84d91e8
--- /dev/null
@@ -0,0 +1,421 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <machine/endian.h>
+  #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 <sys/isa_defs.h>
+  #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 <sys/types.h>
+  #include <sys/endian.h>
+#else
+  #include <endian.h>
+#endif
+#include <pthread.h>
+#ifdef SNAPPY
+#include <snappy.h>
+#endif
+
+#ifdef ZLIB
+#include <zlib.h>
+#endif
+
+#ifdef BZIP2
+#include <bzlib.h>
+#endif
+
+#include <stdint.h>
+#include <string>
+#include <string.h>
+#include "rocksdb/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 rocksdb {
+namespace port {
+
+static const bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN;
+#undef PLATFORM_IS_LITTLE_ENDIAN
+
+class CondVar;
+
+class Mutex {
+ public:
+  /* implicit */ Mutex(bool adaptive = false);
+  ~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, new_sz_delta =0;
+  bool done = false;
+  while (!done) {
+    int st = deflate(&_stream, Z_FINISH);
+    switch (st) {
+      case Z_STREAM_END:
+        done = true;
+        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_delta = (int)(output->size() * 0.2);
+        new_sz = output->size() + (new_sz_delta < 10 ? 10 : new_sz_delta);
+        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 nullptr;
+  }
+
+  _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 = nullptr;
+  int output_len_delta;
+  bool done = false;
+
+  //while(_stream.next_in != nullptr && _stream.avail_in != 0) {
+  while (!done) {
+    int st = inflate(&_stream, Z_SYNC_FLUSH);
+    switch (st) {
+      case Z_STREAM_END:
+        done = true;
+        break;
+      case Z_OK:
+        // No output space. Increase the output space by 20%.
+        old_sz = output_len;
+        output_len_delta = (int)(output_len * 0.2);
+        output_len += output_len_delta < 10 ? 10 : output_len_delta;
+        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 nullptr;
+    }
+  }
+
+  *decompress_size = output_len - _stream.avail_out;
+  inflateEnd(&_stream);
+  return output;
+#endif
+
+  return nullptr;
+}
+
+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 != nullptr && _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 nullptr;
+  }
+
+  _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 = nullptr;
+
+  while(_stream.next_in != nullptr && _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 nullptr;
+    }
+  }
+
+  *decompress_size = output_len - _stream.avail_out;
+  BZ2_bzDecompressEnd(&_stream);
+  return output;
+#endif
+  return nullptr;
+}
+
+inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
+  return false;
+}
+
+} // namespace port
+} // namespace rocksdb
+
+#endif  // STORAGE_LEVELDB_PORT_PORT_POSIX_H_
diff --git a/port/stack_trace.cc b/port/stack_trace.cc
new file mode 100644 (file)
index 0000000..a98f26e
--- /dev/null
@@ -0,0 +1,102 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "util/stack_trace.h"
+
+#ifdef OS_LINUX
+
+#include <execinfo.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+namespace rocksdb {
+
+static const char* GetExecutableName()
+{
+  static char name[1024];
+
+  char link[1024];
+  snprintf(link, sizeof(link), "/proc/%d/exe", getpid());
+  auto read = readlink(link, name, sizeof(name));
+  if (-1 == read) {
+    return nullptr;
+  } else {
+    name[read] = 0;
+    return name;
+  }
+}
+
+static void StackTraceHandler(int sig) {
+  // reset to default handler
+  signal(sig, SIG_DFL);
+
+  fprintf(stderr, "Received signal %d (%s)\n", sig, strsignal(sig));
+
+  const int kMaxFrames = 100;
+  void *frames[kMaxFrames];
+
+  auto num_frames = backtrace(frames, kMaxFrames);
+  auto symbols = backtrace_symbols(frames, num_frames);
+
+  auto executable = GetExecutableName();
+
+  const int kSkip = 2; // skip the top two signal handler related frames
+
+  for (int i = kSkip; i < num_frames; ++i)
+  {
+    fprintf(stderr, "#%-2d %p ", i - kSkip, frames[i]);
+    if (symbols) {
+      fprintf(stderr, "%s ", symbols[i]);
+    }
+    if (executable) {
+      // out source to addr2line, for the address translation
+      const int kLineMax = 256;
+      char cmd[kLineMax];
+      sprintf(cmd,"addr2line %p -e %s 2>&1", frames[i] , executable);
+      auto f = popen(cmd, "r");
+      if (f) {
+        char line[kLineMax];
+        while (fgets(line, sizeof(line), f)) {
+          fprintf(stderr, "%s", line);
+        }
+        pclose(f);
+      } else {
+        fprintf(stderr, "\n");
+      }
+    } else {
+      fprintf(stderr, "\n");
+    }
+  }
+
+  // re-signal to default handler (so we still get core dump if needed...)
+  raise(sig);
+}
+
+void InstallStackTraceHandler() {
+  // just use the plain old signal as it's simple and sufficient
+  // for this use case
+  signal(SIGILL, StackTraceHandler);
+  signal(SIGSEGV, StackTraceHandler);
+  signal(SIGBUS, StackTraceHandler);
+  signal(SIGABRT, StackTraceHandler);
+
+  printf("Installed stack trace handler for SIGILL SIGSEGV SIGBUS SIGABRT\n");
+
+}
+
+}   // namespace rocksdb
+
+#else // no-op for non-linux system for now
+
+namespace rocksdb {
+
+void InstallStackTraceHandler() {}
+
+}
+
+#endif // OS_LINUX
diff --git a/port/win/stdint.h b/port/win/stdint.h
new file mode 100644 (file)
index 0000000..39edd0d
--- /dev/null
@@ -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/snappy/README b/snappy/README
new file mode 100644 (file)
index 0000000..0b6f90a
--- /dev/null
@@ -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 (symlink)
index 0000000..39191d8
--- /dev/null
@@ -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 (file)
index 0000000..c35fd22
--- /dev/null
@@ -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 (file)
index 0000000..242185d
--- /dev/null
@@ -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 (file)
index 0000000..e32b8be
--- /dev/null
@@ -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 (file)
index 0000000..2022daf
--- /dev/null
@@ -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 (file)
index 0000000..49ccf1c
--- /dev/null
@@ -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 (file)
index 0000000..c92b068
--- /dev/null
@@ -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 (file)
index 0000000..c1e8169
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 (symlink)
index 0000000..e51e406
--- /dev/null
@@ -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 (file)
index 0000000..c93ed67
--- /dev/null
@@ -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 (symlink)
index 0000000..74b25e0
--- /dev/null
@@ -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 (symlink)
index 0000000..74b25e0
--- /dev/null
@@ -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 (executable)
index 0000000..27366aa
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 (executable)
index 0000000..3607949
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 (file)
index 0000000..4858b37
--- /dev/null
@@ -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 (file)
index 0000000..8d6bd9f
--- /dev/null
@@ -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 (file)
index 0000000..f79491b
--- /dev/null
@@ -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 <windows.h>, define WIN32_LEAN_AND_MEAN first,
+so we won't pull in macro definitions of things like min() and max(),
+which can conflict with <algorithm>.
+
+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 (file)
index 0000000..7d1c323
--- /dev/null
@@ -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 `<wchar.h>' 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 (file)
index 0000000..cfa7849
--- /dev/null
@@ -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 (file)
index 0000000..f17b2e3
--- /dev/null
@@ -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 (file)
index 0000000..79ac855
--- /dev/null
@@ -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 (file)
index 0000000..79ac855
--- /dev/null
@@ -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 (file)
index 0000000..5849852
--- /dev/null
@@ -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 (file)
index 0000000..60bbd17
--- /dev/null
@@ -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 (file)
index 0000000..3bc8888
--- /dev/null
@@ -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 (file)
index 0000000..2828387
--- /dev/null
@@ -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 <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# 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 <http://www.freedesktop.org/software/pkgconfig>.])],
+               [$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 <conftest.tar])
+    grep GrepMe conftest.dir/file >/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 (executable)
index 0000000..9d0ebe9
--- /dev/null
@@ -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 (file)
index 0000000..4b2d725
--- /dev/null
@@ -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 <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#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<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  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 </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&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 <stdlib.h>
+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 <sys/types.h>
+#include <sys/param.h>
+
+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 <sys/types.h>
+#include <sys/param.h>
+
+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 <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> 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 <limits.h>
+@%:@else
+@%:@ include <assert.h>
+@%:@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 <ac_nonexistent.h>
+_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 <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> 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 <limits.h>
+@%:@else
+@%:@ include <assert.h>
+@%:@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 <ac_nonexistent.h>
+_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 <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.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_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 <string.h>
+
+_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 <stdlib.h>
+
+_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 <ctype.h>
+#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 <limits.h> declares mmap.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define mmap innocuous_mmap
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char mmap (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#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 <bug-autoconf@gnu.org>."
+_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 <<CEOF' >>$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 <<CEOF' >>$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 (file)
index 0000000..4b2d725
--- /dev/null
@@ -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 <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#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<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  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 </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&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 <stdlib.h>
+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 <sys/types.h>
+#include <sys/param.h>
+
+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 <sys/types.h>
+#include <sys/param.h>
+
+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 <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> 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 <limits.h>
+@%:@else
+@%:@ include <assert.h>
+@%:@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 <ac_nonexistent.h>
+_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 <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> 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 <limits.h>
+@%:@else
+@%:@ include <assert.h>
+@%:@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 <ac_nonexistent.h>
+_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 <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.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_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 <string.h>
+
+_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 <stdlib.h>
+
+_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 <ctype.h>
+#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 <limits.h> declares mmap.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define mmap innocuous_mmap
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char mmap (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#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 <bug-autoconf@gnu.org>."
+_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 <<CEOF' >>$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 <<CEOF' >>$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 (file)
index 0000000..69c4b84
--- /dev/null
@@ -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 (file)
index 0000000..f53a76a
--- /dev/null
@@ -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 <http://www.freedesktop.org/software/pkgconfig>.])],
+               [$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 <conftest.tar])
+    grep GrepMe conftest.dir/file >/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 <stdint.h> header file. */
+#undef HAVE_STDINT_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_MMAN_H], [/* Define to 1 if you have the <sys/mman.h> 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 <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_WINDOWS_H], [/* Define to 1 if you have the <windows.h> header file. */
+#undef HAVE_WINDOWS_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_BYTESWAP_H], [/* Define to 1 if you have the <byteswap.h> header file. */
+#undef HAVE_BYTESWAP_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_BYTESWAP_H], [/* Define to 1 if you have the <sys/byteswap.h> 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 <sys/endian.h> 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 <sys/types.h> 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 <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> 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 (file)
index 0000000..bbf4497
--- /dev/null
@@ -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 <stdint.h> header file. */
+#undef HAVE_STDINT_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_MMAN_H], [/* Define to 1 if you have the <sys/mman.h> 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 <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_WINDOWS_H], [/* Define to 1 if you have the <windows.h> header file. */
+#undef HAVE_WINDOWS_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_BYTESWAP_H], [/* Define to 1 if you have the <byteswap.h> header file. */
+#undef HAVE_BYTESWAP_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_BYTESWAP_H], [/* Define to 1 if you have the <sys/byteswap.h> 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 <sys/endian.h> 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 <sys/types.h> 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 <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> 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 (executable)
index 0000000..8f009aa
--- /dev/null
@@ -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 (executable)
index 0000000..e3a2116
--- /dev/null
@@ -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 <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  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 <config-patches@gnu.org>."
+
+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 <stdio.h>  /* 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 <sys/systemcfg.h>
+
+               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 <stdlib.h>
+              #include <unistd.h>
+
+              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 <unistd.h>
+       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 <features.h>
+       #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' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/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 <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # 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 <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#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 <sys/param.h>
+  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 <sys/param.h>
+#  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 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> 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 (file)
index 0000000..895cc7f
--- /dev/null
@@ -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 <byteswap.h> 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 <inttypes.h> 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 <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/byteswap.h> header file. */
+/* #undef HAVE_SYS_BYTESWAP_H */
+
+/* Define to 1 if you have the <sys/endian.h> header file. */
+/* #undef HAVE_SYS_ENDIAN_H */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <windows.h> 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 (file)
index 0000000..d722b0e
--- /dev/null
@@ -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 <byteswap.h> 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 <inttypes.h> 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 <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/byteswap.h> header file. */
+#undef HAVE_SYS_BYTESWAP_H
+
+/* Define to 1 if you have the <sys/endian.h> header file. */
+#undef HAVE_SYS_ENDIAN_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <windows.h> 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 (file)
index 0000000..5399a02
--- /dev/null
@@ -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 </dev/null >&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 </dev/null >&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 </dev/null >&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 <stdlib.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: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 <stdlib.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
+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 <sys/types.h>
+| #include <sys/param.h>
+| 
+| 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 <ac_nonexistent.h>
+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 <ac_nonexistent.h>
+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 <stdio.h>
+| #if HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #if HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #if STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # if HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #if HAVE_STRING_H
+| # if !STDC_HEADERS && HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #if HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #if HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #else
+| # if HAVE_STDINT_H
+| #  include <stdint.h>
+| # endif
+| #endif
+| #if HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <windows.h>
+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 <windows.h>
+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 <stdio.h>
+| #if HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #if HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #if STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # if HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #if HAVE_STRING_H
+| # if !STDC_HEADERS && HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #if HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #if HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #else
+| # if HAVE_STDINT_H
+| #  include <stdint.h>
+| # endif
+| #endif
+| #if HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/byteswap.h>
+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 <sys/byteswap.h>
+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 <stdio.h>
+| #if HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #if HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #if STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # if HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #if HAVE_STRING_H
+| # if !STDC_HEADERS && HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #if HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #if HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #else
+| # if HAVE_STDINT_H
+| #  include <stdint.h>
+| # endif
+| #endif
+| #if HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/endian.h>
+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 <sys/endian.h>
+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 (executable)
index 0000000..93eb95d
--- /dev/null
@@ -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 <bug-autoconf@gnu.org>."
+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 <<CEOF
+/^[     ]*#[    ]*define/!b
+t clr
+: clr
+${ac_dA}PACKAGE_NAME${ac_dB}PACKAGE_NAME${ac_dC}"snappy"${ac_dD}
+${ac_dA}PACKAGE_TARNAME${ac_dB}PACKAGE_TARNAME${ac_dC}"snappy"${ac_dD}
+${ac_dA}PACKAGE_VERSION${ac_dB}PACKAGE_VERSION${ac_dC}"1.0.5"${ac_dD}
+${ac_dA}PACKAGE_STRING${ac_dB}PACKAGE_STRING${ac_dC}"snappy 1.0.5"${ac_dD}
+${ac_dA}PACKAGE_BUGREPORT${ac_dB}PACKAGE_BUGREPORT${ac_dC}""${ac_dD}
+${ac_dA}PACKAGE${ac_dB}PACKAGE${ac_dC}"snappy"${ac_dD}
+${ac_dA}VERSION${ac_dB}VERSION${ac_dC}"1.0.5"${ac_dD}
+${ac_dA}STDC_HEADERS${ac_dB}STDC_HEADERS${ac_dC}1${ac_dD}
+${ac_dA}HAVE_SYS_TYPES_H${ac_dB}HAVE_SYS_TYPES_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_SYS_STAT_H${ac_dB}HAVE_SYS_STAT_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STDLIB_H${ac_dB}HAVE_STDLIB_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STRING_H${ac_dB}HAVE_STRING_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_MEMORY_H${ac_dB}HAVE_MEMORY_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STRINGS_H${ac_dB}HAVE_STRINGS_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_INTTYPES_H${ac_dB}HAVE_INTTYPES_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STDINT_H${ac_dB}HAVE_STDINT_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_UNISTD_H${ac_dB}HAVE_UNISTD_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STDINT_H${ac_dB}HAVE_STDINT_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STDDEF_H${ac_dB}HAVE_STDDEF_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_SYS_MMAN_H${ac_dB}HAVE_SYS_MMAN_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_SYS_RESOURCE_H${ac_dB}HAVE_SYS_RESOURCE_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_BYTESWAP_H${ac_dB}HAVE_BYTESWAP_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_BUILTIN_EXPECT${ac_dB}HAVE_BUILTIN_EXPECT${ac_dC}1${ac_dD}
+${ac_dA}HAVE_BUILTIN_CTZ${ac_dB}HAVE_BUILTIN_CTZ${ac_dC}1${ac_dD}
+${ac_dA}HAVE_LIBZ${ac_dB}HAVE_LIBZ${ac_dC}1${ac_dD}
+CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+
+  fi # grep
+
+  # Handle all the #undef templates
+  cat >$tmp/undefs.sed <<CEOF
+/^[     ]*#[    ]*undef/!b
+t clr
+: clr
+${ac_uA}PACKAGE_NAME${ac_uB}PACKAGE_NAME${ac_uC}"snappy"${ac_uD}
+${ac_uA}PACKAGE_TARNAME${ac_uB}PACKAGE_TARNAME${ac_uC}"snappy"${ac_uD}
+${ac_uA}PACKAGE_VERSION${ac_uB}PACKAGE_VERSION${ac_uC}"1.0.5"${ac_uD}
+${ac_uA}PACKAGE_STRING${ac_uB}PACKAGE_STRING${ac_uC}"snappy 1.0.5"${ac_uD}
+${ac_uA}PACKAGE_BUGREPORT${ac_uB}PACKAGE_BUGREPORT${ac_uC}""${ac_uD}
+${ac_uA}PACKAGE${ac_uB}PACKAGE${ac_uC}"snappy"${ac_uD}
+${ac_uA}VERSION${ac_uB}VERSION${ac_uC}"1.0.5"${ac_uD}
+${ac_uA}STDC_HEADERS${ac_uB}STDC_HEADERS${ac_uC}1${ac_uD}
+${ac_uA}HAVE_SYS_TYPES_H${ac_uB}HAVE_SYS_TYPES_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_SYS_STAT_H${ac_uB}HAVE_SYS_STAT_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STDLIB_H${ac_uB}HAVE_STDLIB_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STRING_H${ac_uB}HAVE_STRING_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_MEMORY_H${ac_uB}HAVE_MEMORY_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STRINGS_H${ac_uB}HAVE_STRINGS_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_INTTYPES_H${ac_uB}HAVE_INTTYPES_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STDINT_H${ac_uB}HAVE_STDINT_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_UNISTD_H${ac_uB}HAVE_UNISTD_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STDINT_H${ac_uB}HAVE_STDINT_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STDDEF_H${ac_uB}HAVE_STDDEF_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_SYS_MMAN_H${ac_uB}HAVE_SYS_MMAN_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_SYS_RESOURCE_H${ac_uB}HAVE_SYS_RESOURCE_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_BYTESWAP_H${ac_uB}HAVE_BYTESWAP_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_BUILTIN_EXPECT${ac_uB}HAVE_BUILTIN_EXPECT${ac_uC}1${ac_uD}
+${ac_uA}HAVE_BUILTIN_CTZ${ac_uB}HAVE_BUILTIN_CTZ${ac_uC}1${ac_uD}
+${ac_uA}HAVE_LIBZ${ac_uB}HAVE_LIBZ${ac_uC}1${ac_uD}
+s,^[    ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$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 (executable)
index 0000000..eb0389a
--- /dev/null
@@ -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 <config-patches@gnu.org>.  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 <config-patches@gnu.org>."
+
+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 (executable)
index 0000000..5fc8a4a
--- /dev/null
@@ -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 <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#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<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  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 </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&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 <stdlib.h>
+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 <sys/types.h>
+#include <sys/param.h>
+
+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 <sys/types.h>
+#include <sys/param.h>
+
+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 <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> 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 <limits.h>
+#else
+# include <assert.h>
+#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 <ac_nonexistent.h>
+_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 <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> 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 <limits.h>
+#else
+# include <assert.h>
+#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 <ac_nonexistent.h>
+_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 <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.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_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 <string.h>
+
+_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 <stdlib.h>
+
+_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 <ctype.h>
+#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 <limits.h> declares mmap.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define mmap innocuous_mmap
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char mmap (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#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 <bug-autoconf@gnu.org>."
+_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 <<CEOF' >>$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 <<CEOF' >>$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 (file)
index 0000000..d193b0b
--- /dev/null
@@ -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 (executable)
index 0000000..df8eea7
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+# 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 <oliva@dcc.unicamp.br>.
+
+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 <bug-automake@gnu.org>.
+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 (file)
index 0000000..183b638
--- /dev/null
@@ -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 (file)
index 0000000..20db66c
--- /dev/null
@@ -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
+
+  <literal: "xab"> <copy: offset=2 length=4>
+
+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 (file)
index 0000000..08fda03
--- /dev/null
@@ -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 (executable)
index 0000000..6781b98
--- /dev/null
@@ -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 (file)
index 0000000..01e3cd0
--- /dev/null
@@ -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 (executable)
index 0000000..33bd9de
--- /dev/null
@@ -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 <gord@gnu.ai.mit.edu>, 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 <bug-libtool@gnu.org>.
+
+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 <<EOF
+$*
+EOF
+  exit $EXIT_SUCCESS
+fi
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+# $mode is unset
+nonopt=
+execute_dlfiles=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+opt_dry_run=false
+opt_duplicate_deps=false
+opt_silent=false
+opt_debug=:
+
+# 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_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
+}
+
+# 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 <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "${write_libobj}"
+    }
+}
+
+# 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)
+          pie_flag="$pie_flag $arg"
+         continue
+         ;;
+
+       -shared | -static | -prefer-pic | -prefer-non-pic)
+         later="$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_quote_for_eval "$arg"
+           lastarg="$lastarg $func_quote_for_eval_result"
+         done
+         IFS="$save_ifs"
+         func_stripname ' ' '' "$lastarg"
+         lastarg=$func_stripname_result
+
+         # Add the arguments to base_compile.
+         base_compile="$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_quote_for_eval "$lastarg"
+      base_compile="$base_compile $func_quote_for_eval_result"
+    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 | *.obj | *.sx)
+      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 "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 >/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 <<EOF
+
+/* $cwrappersource - temporary wrapper executable 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 executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "$SHELL $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+           cat <<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+# define setmode _setmode
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+#  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 <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#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 <<EOF
+
+static const char *script_text_part2 =
+EOF
+           func_emit_wrapper_part2 yes |
+               $SED -e 's/\([\\"]\)/\\\1/g' \
+                    -e 's/^/  "/' -e 's/$/\\n"/'
+           echo ";"
+
+           cat <<EOF
+const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+           if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+              func_to_host_pathlist "$temp_rpath"
+             cat <<EOF
+const char * LIB_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+           else
+             cat <<"EOF"
+const char * LIB_PATH_VALUE   = "";
+EOF
+           fi
+
+           if test -n "$dllsearchpath"; then
+              func_to_host_pathlist "$dllsearchpath:"
+             cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+           else
+             cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE   = "";
+EOF
+           fi
+
+           if test "$fast_install" = yes; then
+             cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+           else
+             cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+           fi
+
+
+           cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX         "--lt-"
+#define LTWRAPPER_OPTION_PREFIX_LENGTH  5
+
+static const size_t opt_prefix_len         = LTWRAPPER_OPTION_PREFIX_LENGTH;
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+
+static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
+
+static const size_t env_set_opt_len     = LTWRAPPER_OPTION_PREFIX_LENGTH + 7;
+static const char *env_set_opt          = LTWRAPPER_OPTION_PREFIX "env-set";
+  /* argument is putenv-style "foo=bar", value of foo is set to bar */
+
+static const size_t env_prepend_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 11;
+static const char *env_prepend_opt      = LTWRAPPER_OPTION_PREFIX "env-prepend";
+  /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */
+
+static const size_t env_append_opt_len  = LTWRAPPER_OPTION_PREFIX_LENGTH + 10;
+static const char *env_append_opt       = LTWRAPPER_OPTION_PREFIX "env-append";
+  /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int  newargc;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *actual_cwrapper_name;
+  char *target_name;
+  char *lt_argv_zero;
+  intptr_t rval = 127;
+
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) argv[0]      : %s\n", argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
+
+  /* very simple arg parsing; don't want to rely on getopt */
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], dumpscript_opt) == 0)
+       {
+EOF
+           case "$host" in
+             *mingw* | *cygwin* )
+               # make stdout use "unix" line endings
+               echo "          setmode(1,_O_BINARY);"
+               ;;
+             esac
+
+           cat <<"EOF"
+         printf ("%s", script_text_part1);
+         printf ("%s", script_text_part2);
+         return 0;
+       }
+    }
+
+  newargz = XMALLOC (char *, argc + 1);
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal ("Couldn't find %s", argv[0]);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
+                         tmp_pathspec));
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
+                         actual_cwrapper_path));
+  XFREE (tmp_pathspec);
+
+  actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+  /* wrapper name transforms */
+  strendzap (actual_cwrapper_name, ".exe");
+  tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+  XFREE (actual_cwrapper_name);
+  actual_cwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  /* target_name transforms -- use actual target program name; might have lt- prefix */
+  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+  strendzap (target_name, ".exe");
+  tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+  XFREE (target_name);
+  target_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
+                         target_name));
+EOF
+
+           cat <<EOF
+  newargz[0] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+                   strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+  strcpy (newargz[0], actual_cwrapper_path);
+  strcat (newargz[0], "$objdir");
+  strcat (newargz[0], "/");
+EOF
+
+           cat <<"EOF"
+  /* stop here, and copy so we don't have to do this twice */
+  tmp_pathspec = xstrdup (newargz[0]);
+
+  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+  strcat (newargz[0], actual_cwrapper_name);
+
+  /* DO want the lt- prefix here if it exists, so use target_name */
+  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+  XFREE (tmp_pathspec);
+  tmp_pathspec = NULL;
+EOF
+
+           case $host_os in
+             mingw*)
+           cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[0], '\\')) != NULL)
+      {
+       *p = '/';
+      }
+    while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+      {
+       *p = '/';
+      }
+  }
+EOF
+           ;;
+           esac
+
+           cat <<"EOF"
+  XFREE (target_name);
+  XFREE (actual_cwrapper_path);
+  XFREE (actual_cwrapper_name);
+
+  lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+  lt_setenv ("DUALCASE", "1");  /* for MSK sh */
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+
+  newargc=0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strncmp (argv[i], env_set_opt, env_set_opt_len) == 0)
+        {
+          if (argv[i][env_set_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_set_opt_len + 1;
+              lt_opt_process_env_set (p);
+            }
+          else if (argv[i][env_set_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_set (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_set_opt);
+          continue;
+        }
+      if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0)
+        {
+          if (argv[i][env_prepend_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_prepend_opt_len + 1;
+              lt_opt_process_env_prepend (p);
+            }
+          else if (argv[i][env_prepend_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_prepend (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_prepend_opt);
+          continue;
+        }
+      if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0)
+        {
+          if (argv[i][env_append_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_append_opt_len + 1;
+              lt_opt_process_env_append (p);
+            }
+          else if (argv[i][env_append_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_append (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_append_opt);
+          continue;
+        }
+      if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal ("Unrecognized option in %s namespace: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
+    }
+  newargz[++newargc] = NULL;
+
+  LTWRAPPER_DEBUGPRINTF     (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>")));
+  for (i = 0; i < newargc; i++)
+    {
+      LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d]   : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>")));
+    }
+
+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 : "<NULL>"),
+                          (value ? value : "<NULL>")));
+  {
+#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 : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  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 : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  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 <<EOF
+         int main() { return 0; }
+EOF
+         $opt_dry_run || $RM conftest
+         if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+           ldd_output=`ldd conftest`
+           for i in $deplibs; do
+             case $i in
+             -l*)
+               func_stripname -l '' "$i"
+               name=$func_stripname_result
+               if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                 case " $predeps $postdeps " in
+                 *" $i "*)
+                   newdeplibs="$newdeplibs $i"
+                   i=""
+                   ;;
+                 esac
+               fi
+               if test -n "$i" ; then
+                 libname=`eval "\\$ECHO \"$libname_spec\""`
+                 deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+                 set dummy $deplib_matches; shift
+                 deplib_match=$1
+                 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                   newdeplibs="$newdeplibs $i"
+                 else
+                   droppeddeps=yes
+                   $ECHO
+                   $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+                   $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 I believe you do not have"
+                   $ECHO "*** because a test_compile did reveal that the linker did not use it for"
+                   $ECHO "*** its dynamic dependency list that programs get resolved with at runtime."
+                 fi
+               fi
+               ;;
+             *)
+               newdeplibs="$newdeplibs $i"
+               ;;
+             esac
+           done
+         else
+           # Error occurred in the first compile.  Let's try to salvage
+           # the situation: Compile a separate program for each library.
+           for i in $deplibs; do
+             case $i in
+             -l*)
+               func_stripname -l '' "$i"
+               name=$func_stripname_result
+               $opt_dry_run || $RM conftest
+               if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+                 ldd_output=`ldd conftest`
+                 if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                   case " $predeps $postdeps " in
+                   *" $i "*)
+                     newdeplibs="$newdeplibs $i"
+                     i=""
+                     ;;
+                   esac
+                 fi
+                 if test -n "$i" ; then
+                   libname=`eval "\\$ECHO \"$libname_spec\""`
+                   deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+                   set dummy $deplib_matches; shift
+                   deplib_match=$1
+                   if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                     newdeplibs="$newdeplibs $i"
+                   else
+                     droppeddeps=yes
+                     $ECHO
+                     $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+                     $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 a test_compile did reveal that the linker did not use this one"
+                     $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime."
+                   fi
+                 fi
+               else
+                 droppeddeps=yes
+                 $ECHO
+                 $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+                 $ECHO "*** make it link in!  You will probably need to install it or some"
+                 $ECHO "*** library that it depends on before this library will be fully"
+                 $ECHO "*** functional.  Installing it before continuing would be even better."
+               fi
+               ;;
+             *)
+               newdeplibs="$newdeplibs $i"
+               ;;
+             esac
+           done
+         fi
+         ;;
+       file_magic*)
+         set dummy $deplibs_check_method; shift
+         file_magic_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
+                     # 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 (executable)
index 0000000..7ed280b
--- /dev/null
@@ -0,0 +1,8413 @@
+# Generated from ltmain.m4sh.
+
+# ltmain.sh (GNU libtool) 2.2.6b
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 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 <bug-libtool@gnu.org>.
+
+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 <<EOF
+$*
+EOF
+  exit $EXIT_SUCCESS
+fi
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+# $mode is unset
+nonopt=
+execute_dlfiles=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+opt_dry_run=false
+opt_duplicate_deps=false
+opt_silent=false
+opt_debug=:
+
+# 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_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
+}
+
+# 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 <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "${write_libobj}"
+    }
+}
+
+# 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)
+          pie_flag="$pie_flag $arg"
+         continue
+         ;;
+
+       -shared | -static | -prefer-pic | -prefer-non-pic)
+         later="$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_quote_for_eval "$arg"
+           lastarg="$lastarg $func_quote_for_eval_result"
+         done
+         IFS="$save_ifs"
+         func_stripname ' ' '' "$lastarg"
+         lastarg=$func_stripname_result
+
+         # Add the arguments to base_compile.
+         base_compile="$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_quote_for_eval "$lastarg"
+      base_compile="$base_compile $func_quote_for_eval_result"
+    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 | *.obj | *.sx)
+      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 "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 >/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 <<EOF
+
+/* $cwrappersource - temporary wrapper executable 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 executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "$SHELL $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+           cat <<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+# define setmode _setmode
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+#  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 <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#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 <<EOF
+
+static const char *script_text_part2 =
+EOF
+           func_emit_wrapper_part2 yes |
+               $SED -e 's/\([\\"]\)/\\\1/g' \
+                    -e 's/^/  "/' -e 's/$/\\n"/'
+           echo ";"
+
+           cat <<EOF
+const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+           if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+              func_to_host_pathlist "$temp_rpath"
+             cat <<EOF
+const char * LIB_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+           else
+             cat <<"EOF"
+const char * LIB_PATH_VALUE   = "";
+EOF
+           fi
+
+           if test -n "$dllsearchpath"; then
+              func_to_host_pathlist "$dllsearchpath:"
+             cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+           else
+             cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE   = "";
+EOF
+           fi
+
+           if test "$fast_install" = yes; then
+             cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+           else
+             cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+           fi
+
+
+           cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX         "--lt-"
+#define LTWRAPPER_OPTION_PREFIX_LENGTH  5
+
+static const size_t opt_prefix_len         = LTWRAPPER_OPTION_PREFIX_LENGTH;
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+
+static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
+
+static const size_t env_set_opt_len     = LTWRAPPER_OPTION_PREFIX_LENGTH + 7;
+static const char *env_set_opt          = LTWRAPPER_OPTION_PREFIX "env-set";
+  /* argument is putenv-style "foo=bar", value of foo is set to bar */
+
+static const size_t env_prepend_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 11;
+static const char *env_prepend_opt      = LTWRAPPER_OPTION_PREFIX "env-prepend";
+  /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */
+
+static const size_t env_append_opt_len  = LTWRAPPER_OPTION_PREFIX_LENGTH + 10;
+static const char *env_append_opt       = LTWRAPPER_OPTION_PREFIX "env-append";
+  /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int  newargc;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *actual_cwrapper_name;
+  char *target_name;
+  char *lt_argv_zero;
+  intptr_t rval = 127;
+
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) argv[0]      : %s\n", argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
+
+  /* very simple arg parsing; don't want to rely on getopt */
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], dumpscript_opt) == 0)
+       {
+EOF
+           case "$host" in
+             *mingw* | *cygwin* )
+               # make stdout use "unix" line endings
+               echo "          setmode(1,_O_BINARY);"
+               ;;
+             esac
+
+           cat <<"EOF"
+         printf ("%s", script_text_part1);
+         printf ("%s", script_text_part2);
+         return 0;
+       }
+    }
+
+  newargz = XMALLOC (char *, argc + 1);
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal ("Couldn't find %s", argv[0]);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
+                         tmp_pathspec));
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
+                         actual_cwrapper_path));
+  XFREE (tmp_pathspec);
+
+  actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+  /* wrapper name transforms */
+  strendzap (actual_cwrapper_name, ".exe");
+  tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+  XFREE (actual_cwrapper_name);
+  actual_cwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  /* target_name transforms -- use actual target program name; might have lt- prefix */
+  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+  strendzap (target_name, ".exe");
+  tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+  XFREE (target_name);
+  target_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
+                         target_name));
+EOF
+
+           cat <<EOF
+  newargz[0] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+                   strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+  strcpy (newargz[0], actual_cwrapper_path);
+  strcat (newargz[0], "$objdir");
+  strcat (newargz[0], "/");
+EOF
+
+           cat <<"EOF"
+  /* stop here, and copy so we don't have to do this twice */
+  tmp_pathspec = xstrdup (newargz[0]);
+
+  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+  strcat (newargz[0], actual_cwrapper_name);
+
+  /* DO want the lt- prefix here if it exists, so use target_name */
+  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+  XFREE (tmp_pathspec);
+  tmp_pathspec = NULL;
+EOF
+
+           case $host_os in
+             mingw*)
+           cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[0], '\\')) != NULL)
+      {
+       *p = '/';
+      }
+    while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+      {
+       *p = '/';
+      }
+  }
+EOF
+           ;;
+           esac
+
+           cat <<"EOF"
+  XFREE (target_name);
+  XFREE (actual_cwrapper_path);
+  XFREE (actual_cwrapper_name);
+
+  lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+  lt_setenv ("DUALCASE", "1");  /* for MSK sh */
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+
+  newargc=0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strncmp (argv[i], env_set_opt, env_set_opt_len) == 0)
+        {
+          if (argv[i][env_set_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_set_opt_len + 1;
+              lt_opt_process_env_set (p);
+            }
+          else if (argv[i][env_set_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_set (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_set_opt);
+          continue;
+        }
+      if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0)
+        {
+          if (argv[i][env_prepend_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_prepend_opt_len + 1;
+              lt_opt_process_env_prepend (p);
+            }
+          else if (argv[i][env_prepend_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_prepend (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_prepend_opt);
+          continue;
+        }
+      if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0)
+        {
+          if (argv[i][env_append_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_append_opt_len + 1;
+              lt_opt_process_env_append (p);
+            }
+          else if (argv[i][env_append_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_append (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_append_opt);
+          continue;
+        }
+      if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal ("Unrecognized option in %s namespace: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
+    }
+  newargz[++newargc] = NULL;
+
+  LTWRAPPER_DEBUGPRINTF     (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>")));
+  for (i = 0; i < newargc; i++)
+    {
+      LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d]   : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>")));
+    }
+
+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 : "<NULL>"),
+                          (value ? value : "<NULL>")));
+  {
+#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 : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  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 : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  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 <<EOF
+         int main() { return 0; }
+EOF
+         $opt_dry_run || $RM conftest
+         if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+           ldd_output=`ldd conftest`
+           for i in $deplibs; do
+             case $i in
+             -l*)
+               func_stripname -l '' "$i"
+               name=$func_stripname_result
+               if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                 case " $predeps $postdeps " in
+                 *" $i "*)
+                   newdeplibs="$newdeplibs $i"
+                   i=""
+                   ;;
+                 esac
+               fi
+               if test -n "$i" ; then
+                 libname=`eval "\\$ECHO \"$libname_spec\""`
+                 deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+                 set dummy $deplib_matches; shift
+                 deplib_match=$1
+                 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                   newdeplibs="$newdeplibs $i"
+                 else
+                   droppeddeps=yes
+                   $ECHO
+                   $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+                   $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 I believe you do not have"
+                   $ECHO "*** because a test_compile did reveal that the linker did not use it for"
+                   $ECHO "*** its dynamic dependency list that programs get resolved with at runtime."
+                 fi
+               fi
+               ;;
+             *)
+               newdeplibs="$newdeplibs $i"
+               ;;
+             esac
+           done
+         else
+           # Error occurred in the first compile.  Let's try to salvage
+           # the situation: Compile a separate program for each library.
+           for i in $deplibs; do
+             case $i in
+             -l*)
+               func_stripname -l '' "$i"
+               name=$func_stripname_result
+               $opt_dry_run || $RM conftest
+               if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+                 ldd_output=`ldd conftest`
+                 if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                   case " $predeps $postdeps " in
+                   *" $i "*)
+                     newdeplibs="$newdeplibs $i"
+                     i=""
+                     ;;
+                   esac
+                 fi
+                 if test -n "$i" ; then
+                   libname=`eval "\\$ECHO \"$libname_spec\""`
+                   deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+                   set dummy $deplib_matches; shift
+                   deplib_match=$1
+                   if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                     newdeplibs="$newdeplibs $i"
+                   else
+                     droppeddeps=yes
+                     $ECHO
+                     $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+                     $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 a test_compile did reveal that the linker did not use this one"
+                     $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime."
+                   fi
+                 fi
+               else
+                 droppeddeps=yes
+                 $ECHO
+                 $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+                 $ECHO "*** make it link in!  You will probably need to install it or some"
+                 $ECHO "*** library that it depends on before this library will be fully"
+                 $ECHO "*** functional.  Installing it before continuing would be even better."
+               fi
+               ;;
+             *)
+               newdeplibs="$newdeplibs $i"
+               ;;
+             esac
+           done
+         fi
+         ;;
+       file_magic*)
+         set dummy $deplibs_check_method; shift
+         file_magic_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
+                     # 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 (file)
index 0000000..98e61f9
--- /dev/null
@@ -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 (executable)
index 0000000..28055d2
--- /dev/null
@@ -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 <pinard@iro.umontreal.ca>, 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 <http://www.gnu.org/licenses/>.
+
+# 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 <bug-automake@gnu.org>."
+    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 (file)
index 0000000..473a0b0
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.
+//
+// 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 (file)
index 0000000..88e1122
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.
+ *
+ * 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 <stddef.h>
+
+/*
+ * 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".
+ *
+ * <compressed_length> 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,
+ * <compressed_length> 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.
+ *
+ * <uncompressed_length> 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, <uncompressed_length>
+ * 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 (file)
index 0000000..9798f64
--- /dev/null
@@ -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 (file)
index 0000000..a32eda5
--- /dev/null
@@ -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 (file)
index 0000000..5844552
--- /dev/null
@@ -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 <string.h>
+
+#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 (file)
index 0000000..faabfa1
--- /dev/null
@@ -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 <stddef.h>
+
+
+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 (file)
index 0000000..4bca40e
--- /dev/null
@@ -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 (file)
index 0000000..6ed3343
--- /dev/null
@@ -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 <algorithm>
+#include <string>
+
+#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 (file)
index 0000000..6033cdf
--- /dev/null
@@ -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 <iostream>
+#include <string>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#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<uint32>(0xFFFFFFFF);
+static const int64 kint64max = static_cast<int64>(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<const uint16 *>(_p))
+#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
+#define UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
+
+#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
+#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
+#define UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_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<const uint16 *>(_p))
+#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
+
+#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
+#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_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<const char *>(src);
+    char *dst_char = reinterpret_cast<char *>(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 <sys/byteorder.h>
+#endif
+
+#ifdef HAVE_SYS_ENDIAN_H
+#include <sys/endian.h>
+#endif
+
+#ifdef _MSC_VER
+#include <stdlib.h>
+#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 <libkern/OSByteOrder.h>
+#define bswap_16(x) OSSwapInt16(x)
+#define bswap_32(x) OSSwapInt32(x)
+#define bswap_64(x) OSSwapInt64(x)
+
+#elif defined(HAVE_BYTESWAP_H)
+#include <byteswap.h>
+
+#elif defined(bswap32)
+// FreeBSD defines bswap{16,32,64} in <sys/endian.h> (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 <sys/byteorder.h> (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<uint32>(n);
+  if (bottombits == 0) {
+    // Bottom bits are zero, so scan in top bits
+    return 32 + FindLSBSetNonZero(static_cast<uint32>(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<const unsigned char*>(p);
+  const unsigned char* limit = reinterpret_cast<const unsigned char*>(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<const char*>(ptr);
+}
+
+inline char* Varint::Encode32(char* sptr, uint32 v) {
+  // Operate on characters as unsigneds
+  unsigned char* ptr = reinterpret_cast<unsigned char*>(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<char*>(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 (file)
index 0000000..52572c4
--- /dev/null
@@ -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 (file)
index 0000000..9ad0dea
--- /dev/null
@@ -0,0 +1,90 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <stdint.h>
+#endif
+
+#if 1
+#include <stddef.h>
+#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 <string>
+
+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 (file)
index 0000000..f0babcb
--- /dev/null
@@ -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 <stdint.h>
+#endif
+
+#if @ac_cv_have_stddef_h@
+#include <stddef.h>
+#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 <string>
+
+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 (file)
index 0000000..223cd92
--- /dev/null
@@ -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 <windows.h>
+#endif
+
+#include <algorithm>
+
+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<double>(
+      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<long long>(real_time_us * 1000 / num_iterations),
+            static_cast<long long>(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<const char *>(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 (file)
index 0000000..ef6a955
--- /dev/null
@@ -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 <stdio.h>
+#include <stdarg.h>
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#include <sys/time.h>
+
+#ifdef HAVE_WINDOWS_H
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include <string>
+
+#ifdef HAVE_GTEST
+
+#include <gtest/gtest.h>
+#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 <gflags/gflags.h>
+
+// 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<uint8>((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<double>(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 (file)
index 0000000..4d4eb42
--- /dev/null
@@ -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 <stdio.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+
+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
+// <src> and <op> patterns marked as intervals:
+//
+//    abxxxxxxxxxxxx
+//    [------]           src
+//      [------]         op
+//
+// a single eight-byte copy from <src> to <op> will repeat the pattern once,
+// after which we can move <op> two bytes without moving <src>:
+//
+//    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<int>(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 <available> bytes from the input buffer,
+//   // whereas Append is allowed to read <length>.
+//   //
+//   // 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 <length> 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<const unsigned char*>(ip));
+      reader_->Skip(1);
+      *result |= static_cast<uint32>(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 <class Writer>
+  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 <ip_limit_ - ip> 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<const unsigned char*>(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<const unsigned char*>(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<uint32>(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 <typename Writer>
+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 <typename Writer>
+static bool InternalUncompressAllTags(SnappyDecompressor* decompressor,
+                                      Writer* writer,
+                                      uint32 uncompressed_len,
+                                      uint32 max_len) {
+  // Protect against possible DoS attack
+  if (static_cast<uint64>(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<size_t>(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<uint64>(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 (file)
index 0000000..93bfd5b
--- /dev/null
@@ -0,0 +1,160 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <stddef.h>
+#include <string>
+
+#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 (file)
index 0000000..cd2ee8f
--- /dev/null
@@ -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 (executable)
index 0000000..d690248
--- /dev/null
@@ -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 (file)
index 0000000..f3b9c83
--- /dev/null
@@ -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 <math.h>
+#include <stdlib.h>
+
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#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 <file>.comp");
+DEFINE_bool(write_uncompressed, false,
+            "Write uncompressed versions of each file to <file>.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<char*>(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<int>(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<Bytef*>(string_as_array(compressed)),
+          &destlen,
+          reinterpret_cast<const Bytef*>(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<const uint8*>(input),
+          input_size,
+          reinterpret_cast<uint8*>(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<Bytef*>(string_as_array(output)),
+          &destlen,
+          reinterpret_cast<const Bytef*>(compressed.data()),
+          compressed.size());
+      CHECK_EQ(Z_OK, ret);
+      CHECK_EQ(static_cast<uLongf>(size), destlen);
+      break;
+    }
+#endif  // ZLIB_VERSION
+
+#ifdef LZO_VERSION
+    case LZO: {
+      output->resize(size);
+      lzo_uint destlen;
+      int ret = lzo1x_decompress(
+          reinterpret_cast<const uint8*>(compressed.data()),
+          compressed.size(),
+          reinterpret_cast<uint8*>(string_as_array(output)),
+          &destlen,
+          NULL);
+      CHECK_EQ(LZO_E_OK, ret);
+      CHECK_EQ(static_cast<lzo_uint>(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<const char*> input(num_blocks);
+    vector<size_t> input_length(num_blocks);
+    vector<string> compressed(num_blocks);
+    vector<string> output(num_blocks);
+    for (int b = 0; b < num_blocks; b++) {
+      int input_start = b * block_size;
+      int input_limit = min<int>((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<int>(length), static_cast<uint32>(compressed_size),
+         (compressed_size * 100.0) / max<int>(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<uint32>(rnd.Next());
+    input.append(reinterpret_cast<char*>(&bytes), sizeof(bytes));
+  }
+  for (int i = 19999; i >= 0; i--) {
+    ACMRandom rnd(i);
+    uint32 bytes = static_cast<uint32>(rnd.Next());
+    input.append(reinterpret_cast<char*>(&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<int>(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<int64>(iters) *
+                             static_cast<int64>(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<int64>(iters) *
+                             static_cast<int64>(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<int64>(iters) *
+                             static_cast<int64>(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<double>(zsize) / std::max<size_t>(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 (file)
index 0000000..4547fe1
--- /dev/null
@@ -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 (file)
index 0000000..7033655
--- /dev/null
@@ -0,0 +1,3609 @@
+\r
+\r
+\r
+\r
+                ALICE'S ADVENTURES IN WONDERLAND\r
+\r
+                          Lewis Carroll\r
+\r
+               THE MILLENNIUM FULCRUM EDITION 2.9\r
+\r
+\r
+\r
+\r
+                            CHAPTER I\r
+\r
+                      Down the Rabbit-Hole\r
+\r
+\r
+  Alice was beginning to get very tired of sitting by her sister\r
+on the bank, and of having nothing to do:  once or twice she had\r
+peeped into the book her sister was reading, but it had no\r
+pictures or conversations in it, `and what is the use of a book,'\r
+thought Alice `without pictures or conversation?'\r
+\r
+  So she was considering in her own mind (as well as she could,\r
+for the hot day made her feel very sleepy and stupid), whether\r
+the pleasure of making a daisy-chain would be worth the trouble\r
+of getting up and picking the daisies, when suddenly a White\r
+Rabbit with pink eyes ran close by her.\r
+\r
+  There was nothing so VERY remarkable in that; nor did Alice\r
+think it so VERY much out of the way to hear the Rabbit say to\r
+itself, `Oh dear!  Oh dear!  I shall be late!'  (when she thought\r
+it over afterwards, it occurred to her that she ought to have\r
+wondered at this, but at the time it all seemed quite natural);\r
+but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-\r
+POCKET, and looked at it, and then hurried on, Alice started to\r
+her feet, for it flashed across her mind that she had never\r
+before seen a rabbit with either a waistcoat-pocket, or a watch to\r
+take out of it, and burning with curiosity, she ran across the\r
+field after it, and fortunately was just in time to see it pop\r
+down a large rabbit-hole under the hedge.\r
+\r
+  In another moment down went Alice after it, never once\r
+considering how in the world she was to get out again.\r
+\r
+  The rabbit-hole went straight on like a tunnel for some way,\r
+and then dipped suddenly down, so suddenly that Alice had not a\r
+moment to think about stopping herself before she found herself\r
+falling down a very deep well.\r
+\r
+  Either the well was very deep, or she fell very slowly, for she\r
+had plenty of time as she went down to look about her and to\r
+wonder what was going to happen next.  First, she tried to look\r
+down and make out what she was coming to, but it was too dark to\r
+see anything; then she looked at the sides of the well, and\r
+noticed that they were filled with cupboards and book-shelves;\r
+here and there she saw maps and pictures hung upon pegs.  She\r
+took down a jar from one of the shelves as she passed; it was\r
+labelled `ORANGE MARMALADE', but to her great disappointment it\r
+was empty:  she did not like to drop the jar for fear of killing\r
+somebody, so managed to put it into one of the cupboards as she\r
+fell past it.\r
+\r
+  `Well!' thought Alice to herself, `after such a fall as this, I\r
+shall think nothing of tumbling down stairs!  How brave they'll\r
+all think me at home!  Why, I wouldn't say anything about it,\r
+even if I fell off the top of the house!' (Which was very likely\r
+true.)\r
+\r
+  Down, down, down.  Would the fall NEVER come to an end!  `I\r
+wonder how many miles I've fallen by this time?' she said aloud.\r
+`I must be getting somewhere near the centre of the earth.  Let\r
+me see:  that would be four thousand miles down, I think--' (for,\r
+you see, Alice had learnt several things of this sort in her\r
+lessons in the schoolroom, and though this was not a VERY good\r
+opportunity for showing off her knowledge, as there was no one to\r
+listen to her, still it was good practice to say it over) `--yes,\r
+that's about the right distance--but then I wonder what Latitude\r
+or Longitude I've got to?'  (Alice had no idea what Latitude was,\r
+or Longitude either, but thought they were nice grand words to\r
+say.)\r
+\r
+  Presently she began again.  `I wonder if I shall fall right\r
+THROUGH the earth!  How funny it'll seem to come out among the\r
+people that walk with their heads downward!  The Antipathies, I\r
+think--' (she was rather glad there WAS no one listening, this\r
+time, as it didn't sound at all the right word) `--but I shall\r
+have to ask them what the name of the country is, you know.\r
+Please, Ma'am, is this New Zealand or Australia?' (and she tried\r
+to curtsey as she spoke--fancy CURTSEYING as you're falling\r
+through the air!  Do you think you could manage it?)  `And what\r
+an ignorant little girl she'll think me for asking!  No, it'll\r
+never do to ask:  perhaps I shall see it written up somewhere.'\r
+\r
+  Down, down, down.  There was nothing else to do, so Alice soon\r
+began talking again.  `Dinah'll miss me very much to-night, I\r
+should think!'  (Dinah was the cat.)  `I hope they'll remember\r
+her saucer of milk at tea-time.  Dinah my dear!  I wish you were\r
+down here with me!  There are no mice in the air, I'm afraid, but\r
+you might catch a bat, and that's very like a mouse, you know.\r
+But do cats eat bats, I wonder?'  And here Alice began to get\r
+rather sleepy, and went on saying to herself, in a dreamy sort of\r
+way, `Do cats eat bats?  Do cats eat bats?' and sometimes, `Do\r
+bats eat cats?' for, you see, as she couldn't answer either\r
+question, it didn't much matter which way she put it.  She felt\r
+that she was dozing off, and had just begun to dream that she\r
+was walking hand in hand with Dinah, and saying to her very\r
+earnestly, `Now, Dinah, tell me the truth:  did you ever eat a\r
+bat?' when suddenly, thump! thump! down she came upon a heap of\r
+sticks and dry leaves, and the fall was over.\r
+\r
+  Alice was not a bit hurt, and she jumped up on to her feet in a\r
+moment:  she looked up, but it was all dark overhead; before her\r
+was another long passage, and the White Rabbit was still in\r
+sight, hurrying down it.  There was not a moment to be lost:\r
+away went Alice like the wind, and was just in time to hear it\r
+say, as it turned a corner, `Oh my ears and whiskers, how late\r
+it's getting!'  She was close behind it when she turned the\r
+corner, but the Rabbit was no longer to be seen:  she found\r
+herself in a long, low hall, which was lit up by a row of lamps\r
+hanging from the roof.\r
+\r
+  There were doors all round the hall, but they were all locked;\r
+and when Alice had been all the way down one side and up the\r
+other, trying every door, she walked sadly down the middle,\r
+wondering how she was ever to get out again.\r
+\r
+  Suddenly she came upon a little three-legged table, all made of\r
+solid glass; there was nothing on it except a tiny golden key,\r
+and Alice's first thought was that it might belong to one of the\r
+doors of the hall; but, alas! either the locks were too large, or\r
+the key was too small, but at any rate it would not open any of\r
+them.  However, on the second time round, she came upon a low\r
+curtain she had not noticed before, and behind it was a little\r
+door about fifteen inches high:  she tried the little golden key\r
+in the lock, and to her great delight it fitted!\r
+\r
+  Alice opened the door and found that it led into a small\r
+passage, not much larger than a rat-hole:  she knelt down and\r
+looked along the passage into the loveliest garden you ever saw.\r
+How she longed to get out of that dark hall, and wander about\r
+among those beds of bright flowers and those cool fountains, but\r
+she could not even get her head though the doorway; `and even if\r
+my head would go through,' thought poor Alice, `it would be of\r
+very little use without my shoulders.  Oh, how I wish\r
+I could shut up like a telescope!  I think I could, if I only\r
+know how to begin.'  For, you see, so many out-of-the-way things\r
+had happened lately, that Alice had begun to think that very few\r
+things indeed were really impossible.\r
+\r
+  There seemed to be no use in waiting by the little door, so she\r
+went back to the table, half hoping she might find another key on\r
+it, or at any rate a book of rules for shutting people up like\r
+telescopes:  this time she found a little bottle on it, (`which\r
+certainly was not here before,' said Alice,) and round the neck\r
+of the bottle was a paper label, with the words `DRINK ME'\r
+beautifully printed on it in large letters.\r
+\r
+  It was all very well to say `Drink me,' but the wise little\r
+Alice was not going to do THAT in a hurry.  `No, I'll look\r
+first,' she said, `and see whether it's marked "poison" or not';\r
+for she had read several nice little histories about children who\r
+had got burnt, and eaten up by wild beasts and other unpleasant\r
+things, all because they WOULD not remember the simple rules\r
+their friends had taught them:  such as, that a red-hot poker\r
+will burn you if you hold it too long; and that if you cut your\r
+finger VERY deeply with a knife, it usually bleeds; and she had\r
+never forgotten that, if you drink much from a bottle marked\r
+`poison,' it is almost certain to disagree with you, sooner or\r
+later.\r
+\r
+  However, this bottle was NOT marked `poison,' so Alice ventured\r
+to taste it, and finding it very nice, (it had, in fact, a sort\r
+of mixed flavour of cherry-tart, custard, pine-apple, roast\r
+turkey, toffee, and hot buttered toast,) she very soon finished\r
+it off.\r
+\r
+     *       *       *       *       *       *       *\r
+\r
+         *       *       *       *       *       *\r
+\r
+     *       *       *       *       *       *       *\r
+\r
+  `What a curious feeling!' said Alice; `I must be shutting up\r
+like a telescope.'\r
+\r
+  And so it was indeed:  she was now only ten inches high, and\r
+her face brightened up at the thought that she was now the right\r
+size for going though the little door into that lovely garden.\r
+First, however, she waited for a few minutes to see if she was\r
+going to shrink any further:  she felt a little nervous about\r
+this; `for it might end, you know,' said Alice to herself, `in my\r
+going out altogether, like a candle.  I wonder what I should be\r
+like then?'  And she tried to fancy what the flame of a candle is\r
+like after the candle is blown out, for she could not remember\r
+ever having seen such a thing.\r
+\r
+  After a while, finding that nothing more happened, she decided\r
+on going into the garden at once; but, alas for poor Alice! when\r
+she got to the door, she found he had forgotten the little golden\r
+key, and when she went back to the table for it, she found she\r
+could not possibly reach it:  she could see it quite plainly\r
+through the glass, and she tried her best to climb up one of the\r
+legs of the table, but it was too slippery; and when she had\r
+tired herself out with trying, the poor little thing sat down and\r
+cried.\r
+\r
+  `Come, there's no use in crying like that!' said Alice to\r
+herself, rather sharply; `I advise you to leave off this minute!'\r
+She generally gave herself very good advice, (though she very\r
+seldom followed it), and sometimes she scolded herself so\r
+severely as to bring tears into her eyes; and once she remembered\r
+trying to box her own ears for having cheated herself in a game\r
+of croquet she was playing against herself, for this curious\r
+child was very fond of pretending to be two people.  `But it's no\r
+use now,' thought poor Alice, `to pretend to be two people!  Why,\r
+there's hardly enough of me left to make ONE respectable\r
+person!'\r
+\r
+  Soon her eye fell on a little glass box that was lying under\r
+the table:  she opened it, and found in it a very small cake, on\r
+which the words `EAT ME' were beautifully marked in currants.\r
+`Well, I'll eat it,' said Alice, `and if it makes me grow larger,\r
+I can reach the key; and if it makes me grow smaller, I can creep\r
+under the door; so either way I'll get into the garden, and I\r
+don't care which happens!'\r
+\r
+  She ate a little bit, and said anxiously to herself, `Which\r
+way?  Which way?', holding her hand on the top of her head to\r
+feel which way it was growing, and she was quite surprised to\r
+find that she remained the same size:  to be sure, this generally\r
+happens when one eats cake, but Alice had got so much into the\r
+way of expecting nothing but out-of-the-way things to happen,\r
+that it seemed quite dull and stupid for life to go on in the\r
+common way.\r
+\r
+  So she set to work, and very soon finished off the cake.\r
+\r
+     *       *       *       *       *       *       *\r
+\r
+         *       *       *       *       *       *\r
+\r
+     *       *       *       *       *       *       *\r
+\r
+\r
+\r
+\r
+                           CHAPTER II\r
+\r
+                        The Pool of Tears\r
+\r
+\r
+  `Curiouser and curiouser!' cried Alice (she was so much\r
+surprised, that for the moment she quite forgot how to speak good\r
+English); `now I'm opening out like the largest telescope that\r
+ever was!  Good-bye, feet!' (for when she looked down at her\r
+feet, they seemed to be almost out of sight, they were getting so\r
+far off).  `Oh, my poor little feet, I wonder who will put on\r
+your shoes and stockings for you now, dears?  I'm sure _I_ shan't\r
+be able!  I shall be a great deal too far off to trouble myself\r
+about you:  you must manage the best way you can; --but I must be\r
+kind to them,' thought Alice, `or perhaps they won't walk the\r
+way I want to go!  Let me see:  I'll give them a new pair of\r
+boots every Christmas.'\r
+\r
+  And she went on planning to herself how she would manage it.\r
+`They must go by the carrier,' she thought; `and how funny it'll\r
+seem, sending presents to one's own feet!  And how odd the\r
+directions will look!\r
+\r
+            ALICE'S RIGHT FOOT, ESQ.\r
+                HEARTHRUG,\r
+                    NEAR THE FENDER,\r
+                        (WITH ALICE'S LOVE).\r
+\r
+Oh dear, what nonsense I'm talking!'\r
+\r
+  Just then her head struck against the roof of the hall:  in\r
+fact she was now more than nine feet high, and she at once took\r
+up the little golden key and hurried off to the garden door.\r
+\r
+  Poor Alice!  It was as much as she could do, lying down on one\r
+side, to look through into the garden with one eye; but to get\r
+through was more hopeless than ever:  she sat down and began to\r
+cry again.\r
+\r
+  `You ought to be ashamed of yourself,' said Alice, `a great\r
+girl like you,' (she might well say this), `to go on crying in\r
+this way!  Stop this moment, I tell you!'  But she went on all\r
+the same, shedding gallons of tears, until there was a large pool\r
+all round her, about four inches deep and reaching half down the\r
+hall.\r
+\r
+  After a time she heard a little pattering of feet in the\r
+distance, and she hastily dried her eyes to see what was coming.\r
+It was the White Rabbit returning, splendidly dressed, with a\r
+pair of white kid gloves in one hand and a large fan in the\r
+other:  he came trotting along in a great hurry, muttering to\r
+himself as he came, `Oh! the Duchess, the Duchess! Oh! won't she\r
+be savage if I've kept her waiting!'  Alice felt so desperate\r
+that she was ready to ask help of any one; so, when the Rabbit\r
+came near her, she began, in a low, timid voice, `If you please,\r
+sir--'  The Rabbit started violently, dropped the white kid\r
+gloves and the fan, and skurried away into the darkness as hard\r
+as he could go.\r
+\r
+  Alice took up the fan and gloves, and, as the hall was very\r
+hot, she kept fanning herself all the time she went on talking:\r
+`Dear, dear!  How queer everything is to-day!  And yesterday\r
+things went on just as usual.  I wonder if I've been changed in\r
+the night?  Let me think:  was I the same when I got up this\r
+morning?  I almost think I can remember feeling a little\r
+different.  But if I'm not the same, the next question is, Who in\r
+the world am I?  Ah, THAT'S the great puzzle!'  And she began\r
+thinking over all the children she knew that were of the same age\r
+as herself, to see if she could have been changed for any of\r
+them.\r
+\r
+  `I'm sure I'm not Ada,' she said, `for her hair goes in such\r
+long ringlets, and mine doesn't go in ringlets at all; and I'm\r
+sure I can't be Mabel, for I know all sorts of things, and she,\r
+oh! she knows such a very little!  Besides, SHE'S she, and I'm I,\r
+and--oh dear, how puzzling it all is!  I'll try if I know all the\r
+things I used to know.  Let me see:  four times five is twelve,\r
+and four times six is thirteen, and four times seven is--oh dear!\r
+I shall never get to twenty at that rate!  However, the\r
+Multiplication Table doesn't signify:  let's try Geography.\r
+London is the capital of Paris, and Paris is the capital of Rome,\r
+and Rome--no, THAT'S all wrong, I'm certain!  I must have been\r
+changed for Mabel!  I'll try and say "How doth the little--"'\r
+and she crossed her hands on her lap as if she were saying lessons,\r
+and began to repeat it, but her voice sounded hoarse and\r
+strange, and the words did not come the same as they used to do:--\r
+\r
+            `How doth the little crocodile\r
+              Improve his shining tail,\r
+            And pour the waters of the Nile\r
+              On every golden scale!\r
+\r
+            `How cheerfully he seems to grin,\r
+              How neatly spread his claws,\r
+            And welcome little fishes in\r
+              With gently smiling jaws!'\r
+\r
+  `I'm sure those are not the right words,' said poor Alice, and\r
+her eyes filled with tears again as she went on, `I must be Mabel\r
+after all, and I shall have to go and live in that poky little\r
+house, and have next to no toys to play with, and oh! ever so\r
+many lessons to learn!  No, I've made up my mind about it; if I'm\r
+Mabel, I'll stay down here!  It'll be no use their putting their\r
+heads down and saying "Come up again, dear!"  I shall only look\r
+up and say "Who am I then?  Tell me that first, and then, if I\r
+like being that person, I'll come up:  if not, I'll stay down\r
+here till I'm somebody else"--but, oh dear!' cried Alice, with a\r
+sudden burst of tears, `I do wish they WOULD put their heads\r
+down!  I am so VERY tired of being all alone here!'\r
+\r
+  As she said this she looked down at her hands, and was\r
+surprised to see that she had put on one of the Rabbit's little\r
+white kid gloves while she was talking.  `How CAN I have done\r
+that?' she thought.  `I must be growing small again.'  She got up\r
+and went to the table to measure herself by it, and found that,\r
+as nearly as she could guess, she was now about two feet high,\r
+and was going on shrinking rapidly:  she soon found out that the\r
+cause of this was the fan she was holding, and she dropped it\r
+hastily, just in time to avoid shrinking away altogether.\r
+\r
+`That WAS a narrow escape!' said Alice, a good deal frightened at\r
+the sudden change, but very glad to find herself still in\r
+existence; `and now for the garden!' and she ran with all speed\r
+back to the little door:  but, alas! the little door was shut\r
+again, and the little golden key was lying on the glass table as\r
+before, `and things are worse than ever,' thought the poor child,\r
+`for I never was so small as this before, never!  And I declare\r
+it's too bad, that it is!'\r
+\r
+  As she said these words her foot slipped, and in another\r
+moment, splash! she was up to her chin in salt water.  He first\r
+idea was that she had somehow fallen into the sea, `and in that\r
+case I can go back by railway,' she said to herself.  (Alice had\r
+been to the seaside once in her life, and had come to the general\r
+conclusion, that wherever you go to on the English coast you find\r
+a number of bathing machines in the sea, some children digging in\r
+the sand with wooden spades, then a row of lodging houses, and\r
+behind them a railway station.)  However, she soon made out that\r
+she was in the pool of tears which she had wept when she was nine\r
+feet high.\r
+\r
+  `I wish I hadn't cried so much!' said Alice, as she swam about,\r
+trying to find her way out.  `I shall be punished for it now, I\r
+suppose, by being drowned in my own tears!  That WILL be a queer\r
+thing, to be sure!  However, everything is queer to-day.'\r
+\r
+  Just then she heard something splashing about in the pool a\r
+little way off, and she swam nearer to make out what it was:  at\r
+first she thought it must be a walrus or hippopotamus, but then\r
+she remembered how small she was now, and she soon made out that\r
+it was only a mouse that had slipped in like herself.\r
+\r
+  `Would it be of any use, now,' thought Alice, `to speak to this\r
+mouse?  Everything is so out-of-the-way down here, that I should\r
+think very likely it can talk:  at any rate, there's no harm in\r
+trying.'  So she began:  `O Mouse, do you know the way out of\r
+this pool?  I am very tired of swimming about here, O Mouse!'\r
+(Alice thought this must be the right way of speaking to a mouse:\r
+she had never done such a thing before, but she remembered having\r
+seen in her brother's Latin Grammar, `A mouse--of a mouse--to a\r
+mouse--a mouse--O mouse!'  The Mouse looked at her rather\r
+inquisitively, and seemed to her to wink with one of its little\r
+eyes, but it said nothing.\r
+\r
+  `Perhaps it doesn't understand English,' thought Alice; `I\r
+daresay it's a French mouse, come over with William the\r
+Conqueror.'  (For, with all her knowledge of history, Alice had\r
+no very clear notion how long ago anything had happened.)  So she\r
+began again:  `Ou est ma chatte?' which was the first sentence in\r
+her French lesson-book.  The Mouse gave a sudden leap out of the\r
+water, and seemed to quiver all over with fright.  `Oh, I beg\r
+your pardon!' cried Alice hastily, afraid that she had hurt the\r
+poor animal's feelings.  `I quite forgot you didn't like cats.'\r
+\r
+  `Not like cats!' cried the Mouse, in a shrill, passionate\r
+voice.  `Would YOU like cats if you were me?'\r
+\r
+  `Well, perhaps not,' said Alice in a soothing tone:  `don't be\r
+angry about it.  And yet I wish I could show you our cat Dinah:\r
+I think you'd take a fancy to cats if you could only see her.\r
+She is such a dear quiet thing,' Alice went on, half to herself,\r
+as she swam lazily about in the pool, `and she sits purring so\r
+nicely by the fire, licking her paws and washing her face--and\r
+she is such a nice soft thing to nurse--and she's such a capital\r
+one for catching mice--oh, I beg your pardon!' cried Alice again,\r
+for this time the Mouse was bristling all over, and she felt\r
+certain it must be really offended.  `We won't talk about her any\r
+more if you'd rather not.'\r
+\r
+  `We indeed!' cried the Mouse, who was trembling down to the end\r
+of his tail.  `As if I would talk on such a subject!  Our family\r
+always HATED cats:  nasty, low, vulgar things!  Don't let me hear\r
+the name again!'\r
+\r
+  `I won't indeed!' said Alice, in a great hurry to change the\r
+subject of conversation.  `Are you--are you fond--of--of dogs?'\r
+The Mouse did not answer, so Alice went on eagerly:  `There is\r
+such a nice little dog near our house I should like to show you!\r
+A little bright-eyed terrier, you know, with oh, such long curly\r
+brown hair!  And it'll fetch things when you throw them, and\r
+it'll sit up and beg for its dinner, and all sorts of things--I\r
+can't remember half of them--and it belongs to a farmer, you\r
+know, and he says it's so useful, it's worth a hundred pounds!\r
+He says it kills all the rats and--oh dear!' cried Alice in a\r
+sorrowful tone, `I'm afraid I've offended it again!'  For the\r
+Mouse was swimming away from her as hard as it could go, and\r
+making quite a commotion in the pool as it went.\r
+\r
+  So she called softly after it, `Mouse dear!  Do come back\r
+again, and we won't talk about cats or dogs either, if you don't\r
+like them!'  When the Mouse heard this, it turned round and swam\r
+slowly back to her:  its face was quite pale (with passion, Alice\r
+thought), and it said in a low trembling voice, `Let us get to\r
+the shore, and then I'll tell you my history, and you'll\r
+understand why it is I hate cats and dogs.'\r
+\r
+  It was high time to go, for the pool was getting quite crowded\r
+with the birds and animals that had fallen into it:  there were a\r
+Duck and a Dodo, a Lory and an Eaglet, and several other curious\r
+creatures.  Alice led the way, and the whole party swam to the\r
+shore.\r
+\r
+\r
+\r
+                           CHAPTER III\r
+\r
+                  A Caucus-Race and a Long Tale\r
+\r
+\r
+  They were indeed a queer-looking party that assembled on the\r
+bank--the birds with draggled feathers, the animals with their\r
+fur clinging close to them, and all dripping wet, cross, and\r
+uncomfortable.\r
+\r
+  The first question of course was, how to get dry again:  they\r
+had a consultation about this, and after a few minutes it seemed\r
+quite natural to Alice to find herself talking familiarly with\r
+them, as if she had known them all her life.  Indeed, she had\r
+quite a long argument with the Lory, who at last turned sulky,\r
+and would only say, `I am older than you, and must know better';\r
+and this Alice would not allow without knowing how old it was,\r
+and, as the Lory positively refused to tell its age, there was no\r
+more to be said.\r
+\r
+  At last the Mouse, who seemed to be a person of authority among\r
+them, called out, `Sit down, all of you, and listen to me!  I'LL\r
+soon make you dry enough!'  They all sat down at once, in a large\r
+ring, with the Mouse in the middle.  Alice kept her eyes\r
+anxiously fixed on it, for she felt sure she would catch a bad\r
+cold if she did not get dry very soon.\r
+\r
+  `Ahem!' said the Mouse with an important air, `are you all ready?\r
+This is the driest thing I know.  Silence all round, if you please!\r
+"William the Conqueror, whose cause was favoured by the pope, was\r
+soon submitted to by the English, who wanted leaders, and had been\r
+of late much accustomed to usurpation and conquest.  Edwin and\r
+Morcar, the earls of Mercia and Northumbria--"'\r
+\r
+  `Ugh!' said the Lory, with a shiver.\r
+\r
+  `I beg your pardon!' said the Mouse, frowning, but very\r
+politely:  `Did you speak?'\r
+\r
+  `Not I!' said the Lory hastily.\r
+\r
+  `I thought you did,' said the Mouse.  `--I proceed.  "Edwin and\r
+Morcar, the earls of Mercia and Northumbria, declared for him:\r
+and even Stigand, the patriotic archbishop of Canterbury, found\r
+it advisable--"'\r
+\r
+  `Found WHAT?' said the Duck.\r
+\r
+  `Found IT,' the Mouse replied rather crossly:  `of course you\r
+know what "it" means.'\r
+\r
+  `I know what "it" means well enough, when I find a thing,' said\r
+the Duck:  `it's generally a frog or a worm.  The question is,\r
+what did the archbishop find?'\r
+\r
+  The Mouse did not notice this question, but hurriedly went on,\r
+`"--found it advisable to go with Edgar Atheling to meet William\r
+and offer him the crown.  William's conduct at first was\r
+moderate.  But the insolence of his Normans--"  How are you\r
+getting on now, my dear?' it continued, turning to Alice as it\r
+spoke.\r
+\r
+  `As wet as ever,' said Alice in a melancholy tone:  `it doesn't\r
+seem to dry me at all.'\r
+\r
+  `In that case,' said the Dodo solemnly, rising to its feet, `I\r
+move that the meeting adjourn, for the immediate adoption of more\r
+energetic remedies--'\r
+\r
+  `Speak English!' said the Eaglet.  `I don't know the meaning of\r
+half those long words, and, what's more, I don't believe you do\r
+either!'  And the Eaglet bent down its head to hide a smile:\r
+some of the other birds tittered audibly.\r
+\r
+  `What I was going to say,' said the Dodo in an offended tone,\r
+`was, that the best thing to get us dry would be a Caucus-race.'\r
+\r
+  `What IS a Caucus-race?' said Alice; not that she wanted much\r
+to know, but the Dodo had paused as if it thought that SOMEBODY\r
+ought to speak, and no one else seemed inclined to say anything.\r
+\r
+  `Why,' said the Dodo, `the best way to explain it is to do it.'\r
+(And, as you might like to try the thing yourself, some winter\r
+day, I will tell you how the Dodo managed it.)\r
+\r
+  First it marked out a race-course, in a sort of circle, (`the\r
+exact shape doesn't matter,' it said,) and then all the party\r
+were placed along the course, here and there.  There was no `One,\r
+two, three, and away,' but they began running when they liked,\r
+and left off when they liked, so that it was not easy to know\r
+when the race was over.  However, when they had been running half\r
+an hour or so, and were quite dry again, the Dodo suddenly called\r
+out `The race is over!' and they all crowded round it, panting,\r
+and asking, `But who has won?'\r
+\r
+  This question the Dodo could not answer without a great deal of\r
+thought, and it sat for a long time with one finger pressed upon\r
+its forehead (the position in which you usually see Shakespeare,\r
+in the pictures of him), while the rest waited in silence.  At\r
+last the Dodo said, `EVERYBODY has won, and all must have\r
+prizes.'\r
+\r
+  `But who is to give the prizes?' quite a chorus of voices\r
+asked.\r
+\r
+  `Why, SHE, of course,' said the Dodo, pointing to Alice with\r
+one finger; and the whole party at once crowded round her,\r
+calling out in a confused way, `Prizes! Prizes!'\r
+\r
+  Alice had no idea what to do, and in despair she put her hand\r
+in her pocket, and pulled out a box of comfits, (luckily the salt\r
+water had not got into it), and handed them round as prizes.\r
+There was exactly one a-piece all round.\r
+\r
+  `But she must have a prize herself, you know,' said the Mouse.\r
+\r
+  `Of course,' the Dodo replied very gravely.  `What else have\r
+you got in your pocket?' he went on, turning to Alice.\r
+\r
+  `Only a thimble,' said Alice sadly.\r
+\r
+  `Hand it over here,' said the Dodo.\r
+\r
+  Then they all crowded round her once more, while the Dodo\r
+solemnly presented the thimble, saying `We beg your acceptance of\r
+this elegant thimble'; and, when it had finished this short\r
+speech, they all cheered.\r
+\r
+  Alice thought the whole thing very absurd, but they all looked\r
+so grave that she did not dare to laugh; and, as she could not\r
+think of anything to say, she simply bowed, and took the thimble,\r
+looking as solemn as she could.\r
+\r
+  The next thing was to eat the comfits:  this caused some noise\r
+and confusion, as the large birds complained that they could not\r
+taste theirs, and the small ones choked and had to be patted on\r
+the back.  However, it was over at last, and they sat down again\r
+in a ring, and begged the Mouse to tell them something more.\r
+\r
+  `You promised to tell me your history, you know,' said Alice,\r
+`and why it is you hate--C and D,' she added in a whisper, half\r
+afraid that it would be offended again.\r
+\r
+  `Mine is a long and a sad tale!' said the Mouse, turning to\r
+Alice, and sighing.\r
+\r
+  `It IS a long tail, certainly,' said Alice, looking down with\r
+wonder at the Mouse's tail; `but why do you call it sad?'  And\r
+she kept on puzzling about it while the Mouse was speaking, so\r
+that her idea of the tale was something like this:--\r
+\r
+                    `Fury said to a\r
+                   mouse, That he\r
+                 met in the\r
+               house,\r
+            "Let us\r
+              both go to\r
+                law:  I will\r
+                  prosecute\r
+                    YOU.  --Come,\r
+                       I'll take no\r
+                        denial; We\r
+                     must have a\r
+                 trial:  For\r
+              really this\r
+           morning I've\r
+          nothing\r
+         to do."\r
+           Said the\r
+             mouse to the\r
+               cur, "Such\r
+                 a trial,\r
+                   dear Sir,\r
+                         With\r
+                     no jury\r
+                  or judge,\r
+                would be\r
+              wasting\r
+             our\r
+              breath."\r
+               "I'll be\r
+                 judge, I'll\r
+                   be jury,"\r
+                         Said\r
+                    cunning\r
+                      old Fury:\r
+                     "I'll\r
+                      try the\r
+                         whole\r
+                          cause,\r
+                             and\r
+                        condemn\r
+                       you\r
+                      to\r
+                       death."'\r
+\r
+\r
+  `You are not attending!' said the Mouse to Alice severely.\r
+`What are you thinking of?'\r
+\r
+  `I beg your pardon,' said Alice very humbly:  `you had got to\r
+the fifth bend, I think?'\r
+\r
+  `I had NOT!' cried the Mouse, sharply and very angrily.\r
+\r
+  `A knot!' said Alice, always ready to make herself useful, and\r
+looking anxiously about her.  `Oh, do let me help to undo it!'\r
+\r
+  `I shall do nothing of the sort,' said the Mouse, getting up\r
+and walking away.  `You insult me by talking such nonsense!'\r
+\r
+  `I didn't mean it!' pleaded poor Alice.  `But you're so easily\r
+offended, you know!'\r
+\r
+  The Mouse only growled in reply.\r
+\r
+  `Please come back and finish your story!' Alice called after\r
+it; and the others all joined in chorus, `Yes, please do!' but\r
+the Mouse only shook its head impatiently, and walked a little\r
+quicker.\r
+\r
+  `What a pity it wouldn't stay!' sighed the Lory, as soon as it\r
+was quite out of sight; and an old Crab took the opportunity of\r
+saying to her daughter `Ah, my dear!  Let this be a lesson to you\r
+never to lose YOUR temper!'  `Hold your tongue, Ma!' said the\r
+young Crab, a little snappishly.  `You're enough to try the\r
+patience of an oyster!'\r
+\r
+  `I wish I had our Dinah here, I know I do!' said Alice aloud,\r
+addressing nobody in particular.  `She'd soon fetch it back!'\r
+\r
+  `And who is Dinah, if I might venture to ask the question?'\r
+said the Lory.\r
+\r
+  Alice replied eagerly, for she was always ready to talk about\r
+her pet:  `Dinah's our cat.  And she's such a capital one for\r
+catching mice you can't think!  And oh, I wish you could see her\r
+after the birds!  Why, she'll eat a little bird as soon as look\r
+at it!'\r
+\r
+  This speech caused a remarkable sensation among the party.\r
+Some of the birds hurried off at once:  one the old Magpie began\r
+wrapping itself up very carefully, remarking, `I really must be\r
+getting home; the night-air doesn't suit my throat!' and a Canary\r
+called out in a trembling voice to its children, `Come away, my\r
+dears!  It's high time you were all in bed!'  On various pretexts\r
+they all moved off, and Alice was soon left alone.\r
+\r
+  `I wish I hadn't mentioned Dinah!' she said to herself in a\r
+melancholy tone.  `Nobody seems to like her, down here, and I'm\r
+sure she's the best cat in the world!  Oh, my dear Dinah!  I\r
+wonder if I shall ever see you any more!'  And here poor Alice\r
+began to cry again, for she felt very lonely and low-spirited.\r
+In a little while, however, she again heard a little pattering of\r
+footsteps in the distance, and she looked up eagerly, half hoping\r
+that the Mouse had changed his mind, and was coming back to\r
+finish his story.\r
+\r
+\r
+\r
+                           CHAPTER IV\r
+\r
+                The Rabbit Sends in a Little Bill\r
+\r
+\r
+  It was the White Rabbit, trotting slowly back again, and\r
+looking anxiously about as it went, as if it had lost something;\r
+and she heard it muttering to itself `The Duchess!  The Duchess!\r
+Oh my dear paws!  Oh my fur and whiskers!  She'll get me\r
+executed, as sure as ferrets are ferrets!  Where CAN I have\r
+dropped them, I wonder?'  Alice guessed in a moment that it was\r
+looking for the fan and the pair of white kid gloves, and she\r
+very good-naturedly began hunting about for them, but they were\r
+nowhere to be seen--everything seemed to have changed since her\r
+swim in the pool, and the great hall, with the glass table and\r
+the little door, had vanished completely.\r
+\r
+  Very soon the Rabbit noticed Alice, as she went hunting about,\r
+and called out to her in an angry tone, `Why, Mary Ann, what ARE\r
+you doing out here?  Run home this moment, and fetch me a pair of\r
+gloves and a fan!  Quick, now!'  And Alice was so much frightened\r
+that she ran off at once in the direction it pointed to, without\r
+trying to explain the mistake it had made.\r
+\r
+  `He took me for his housemaid,' she said to herself as she ran.\r
+`How surprised he'll be when he finds out who I am!  But I'd\r
+better take him his fan and gloves--that is, if I can find them.'\r
+As she said this, she came upon a neat little house, on the door\r
+of which was a bright brass plate with the name `W. RABBIT'\r
+engraved upon it.  She went in without knocking, and hurried\r
+upstairs, in great fear lest she should meet the real Mary Ann,\r
+and be turned out of the house before she had found the fan and\r
+gloves.\r
+\r
+  `How queer it seems,' Alice said to herself, `to be going\r
+messages for a rabbit!  I suppose Dinah'll be sending me on\r
+messages next!'  And she began fancying the sort of thing that\r
+would happen:  `"Miss Alice!  Come here directly, and get ready\r
+for your walk!" "Coming in a minute, nurse!  But I've got to see\r
+that the mouse doesn't get out."  Only I don't think,' Alice went\r
+on, `that they'd let Dinah stop in the house if it began ordering\r
+people about like that!'\r
+\r
+  By this time she had found her way into a tidy little room with\r
+a table in the window, and on it (as she had hoped) a fan and two\r
+or three pairs of tiny white kid gloves:  she took up the fan and\r
+a pair of the gloves, and was just going to leave the room, when\r
+her eye fell upon a little bottle that stood near the looking-\r
+glass.  There was no label this time with the words `DRINK ME,'\r
+but nevertheless she uncorked it and put it to her lips.  `I know\r
+SOMETHING interesting is sure to happen,' she said to herself,\r
+`whenever I eat or drink anything; so I'll just see what this\r
+bottle does.  I do hope it'll make me grow large again, for\r
+really I'm quite tired of being such a tiny little thing!'\r
+\r
+  It did so indeed, and much sooner than she had expected:\r
+before she had drunk half the bottle, she found her head pressing\r
+against the ceiling, and had to stoop to save her neck from being\r
+broken.  She hastily put down the bottle, saying to herself\r
+`That's quite enough--I hope I shan't grow any more--As it is, I\r
+can't get out at the door--I do wish I hadn't drunk quite so\r
+much!'\r
+\r
+  Alas! it was too late to wish that!  She went on growing, and\r
+growing, and very soon had to kneel down on the floor:  in\r
+another minute there was not even room for this, and she tried\r
+the effect of lying down with one elbow against the door, and the\r
+other arm curled round her head.  Still she went on growing, and,\r
+as a last resource, she put one arm out of the window, and one\r
+foot up the chimney, and said to herself `Now I can do no more,\r
+whatever happens.  What WILL become of me?'\r
+\r
+  Luckily for Alice, the little magic bottle had now had its full\r
+effect, and she grew no larger:  still it was very uncomfortable,\r
+and, as there seemed to be no sort of chance of her ever getting\r
+out of the room again, no wonder she felt unhappy.\r
+\r
+  `It was much pleasanter at home,' thought poor Alice, `when one\r
+wasn't always growing larger and smaller, and being ordered about\r
+by mice and rabbits.  I almost wish I hadn't gone down that\r
+rabbit-hole--and yet--and yet--it's rather curious, you know,\r
+this sort of life!  I do wonder what CAN have happened to me!\r
+When I used to read fairy-tales, I fancied that kind of thing\r
+never happened, and now here I am in the middle of one!  There\r
+ought to be a book written about me, that there ought!  And when\r
+I grow up, I'll write one--but I'm grown up now,' she added in a\r
+sorrowful tone; `at least there's no room to grow up any more\r
+HERE.'\r
+\r
+  `But then,' thought Alice, `shall I NEVER get any older than I\r
+am now?  That'll be a comfort, one way--never to be an old woman-\r
+-but then--always to have lessons to learn!  Oh, I shouldn't like\r
+THAT!'\r
+\r
+  `Oh, you foolish Alice!' she answered herself.  `How can you\r
+learn lessons in here?  Why, there's hardly room for YOU, and no\r
+room at all for any lesson-books!'\r
+\r
+  And so she went on, taking first one side and then the other,\r
+and making quite a conversation of it altogether; but after a few\r
+minutes she heard a voice outside, and stopped to listen.\r
+\r
+  `Mary Ann!  Mary Ann!' said the voice.  `Fetch me my gloves\r
+this moment!'  Then came a little pattering of feet on the\r
+stairs.  Alice knew it was the Rabbit coming to look for her, and\r
+she trembled till she shook the house, quite forgetting that she\r
+was now about a thousand times as large as the Rabbit, and had no\r
+reason to be afraid of it.\r
+\r
+  Presently the Rabbit came up to the door, and tried to open it;\r
+but, as the door opened inwards, and Alice's elbow was pressed\r
+hard against it, that attempt proved a failure.  Alice heard it\r
+say to itself `Then I'll go round and get in at the window.'\r
+\r
+  `THAT you won't' thought Alice, and, after waiting till she\r
+fancied she heard the Rabbit just under the window, she suddenly\r
+spread out her hand, and made a snatch in the air.  She did not\r
+get hold of anything, but she heard a little shriek and a fall,\r
+and a crash of broken glass, from which she concluded that it was\r
+just possible it had fallen into a cucumber-frame, or something\r
+of the sort.\r
+\r
+  Next came an angry voice--the Rabbit's--`Pat! Pat!  Where are\r
+you?'  And then a voice she had never heard before, `Sure then\r
+I'm here!  Digging for apples, yer honour!'\r
+\r
+  `Digging for apples, indeed!' said the Rabbit angrily.  `Here!\r
+Come and help me out of THIS!'  (Sounds of more broken glass.)\r
+\r
+  `Now tell me, Pat, what's that in the window?'\r
+\r
+  `Sure, it's an arm, yer honour!'  (He pronounced it `arrum.')\r
+\r
+  `An arm, you goose!   Who ever saw one that size?  Why, it\r
+fills the whole window!'\r
+\r
+  `Sure, it does, yer honour:  but it's an arm for all that.'\r
+\r
+  `Well, it's got no business there, at any rate:  go and take it\r
+away!'\r
+\r
+  There was a long silence after this, and Alice could only hear\r
+whispers now and then; such as, `Sure, I don't like it, yer\r
+honour, at all, at all!'  `Do as I tell you, you coward!' and at\r
+last she spread out her hand again, and made another snatch in\r
+the air.  This time there were TWO little shrieks, and more\r
+sounds of broken glass.  `What a number of cucumber-frames there\r
+must be!' thought Alice.  `I wonder what they'll do next!  As for\r
+pulling me out of the window, I only wish they COULD!  I'm sure I\r
+don't want to stay in here any longer!'\r
+\r
+  She waited for some time without hearing anything more:  at\r
+last came a rumbling of little cartwheels, and the sound of a\r
+good many voice all talking together:  she made out the words:\r
+`Where's the other ladder?--Why, I hadn't to bring but one;\r
+Bill's got the other--Bill! fetch it here, lad!--Here, put 'em up\r
+at this corner--No, tie 'em together first--they don't reach half\r
+high enough yet--Oh! they'll do well enough; don't be particular-\r
+-Here, Bill! catch hold of this rope--Will the roof bear?--Mind\r
+that loose slate--Oh, it's coming down!  Heads below!' (a loud\r
+crash)--`Now, who did that?--It was Bill, I fancy--Who's to go\r
+down the chimney?--Nay, I shan't! YOU do it!--That I won't,\r
+then!--Bill's to go down--Here, Bill! the master says you're to\r
+go down the chimney!'\r
+\r
+  `Oh! So Bill's got to come down the chimney, has he?' said\r
+Alice to herself.  `Shy, they seem to put everything upon Bill!\r
+I wouldn't be in Bill's place for a good deal:  this fireplace is\r
+narrow, to be sure; but I THINK I can kick a little!'\r
+\r
+  She drew her foot as far down the chimney as she could, and\r
+waited till she heard a little animal (she couldn't guess of what\r
+sort it was) scratching and scrambling about in the chimney close\r
+above her:  then, saying to herself `This is Bill,' she gave one\r
+sharp kick, and waited to see what would happen next.\r
+\r
+  The first thing she heard was a general chorus of `There goes\r
+Bill!' then the Rabbit's voice along--`Catch him, you by the\r
+hedge!' then silence, and then another confusion of voices--`Hold\r
+up his head--Brandy now--Don't choke him--How was it, old fellow?\r
+What happened to you?  Tell us all about it!'\r
+\r
+  Last came a little feeble, squeaking voice, (`That's Bill,'\r
+thought Alice,) `Well, I hardly know--No more, thank ye; I'm\r
+better now--but I'm a deal too flustered to tell you--all I know\r
+is, something comes at me like a Jack-in-the-box, and up I goes\r
+like a sky-rocket!'\r
+\r
+  `So you did, old fellow!' said the others.\r
+\r
+  `We must burn the house down!' said the Rabbit's voice; and\r
+Alice called out as loud as she could, `If you do.  I'll set\r
+Dinah at you!'\r
+\r
+  There was a dead silence instantly, and Alice thought to\r
+herself, `I wonder what they WILL do next!  If they had any\r
+sense, they'd take the roof off.'  After a minute or two, they\r
+began moving about again, and Alice heard the Rabbit say, `A\r
+barrowful will do, to begin with.'\r
+\r
+  `A barrowful of WHAT?' thought Alice; but she had not long to\r
+doubt, for the next moment a shower of little pebbles came\r
+rattling in at the window, and some of them hit her in the face.\r
+`I'll put a stop to this,' she said to herself, and shouted out,\r
+`You'd better not do that again!' which produced another dead\r
+silence.\r
+\r
+  Alice noticed with some surprise that the pebbles were all\r
+turning into little cakes as they lay on the floor, and a bright\r
+idea came into her head.  `If I eat one of these cakes,' she\r
+thought, `it's sure to make SOME change in my size; and as it\r
+can't possibly make me larger, it must make me smaller, I\r
+suppose.'\r
+\r
+  So she swallowed one of the cakes, and was delighted to find\r
+that she began shrinking directly.  As soon as she was small\r
+enough to get through the door, she ran out of the house, and\r
+found quite a crowd of little animals and birds waiting outside.\r
+The poor little Lizard, Bill, was in the middle, being held up by\r
+two guinea-pigs, who were giving it something out of a bottle.\r
+They all made a rush at Alice the moment she appeared; but she\r
+ran off as hard as she could, and soon found herself safe in a\r
+thick wood.\r
+\r
+  `The first thing I've got to do,' said Alice to herself, as she\r
+wandered about in the wood, `is to grow to my right size again;\r
+and the second thing is to find my way into that lovely garden.\r
+I think that will be the best plan.'\r
+\r
+  It sounded an excellent plan, no doubt, and very neatly and\r
+simply arranged; the only difficulty was, that she had not the\r
+smallest idea how to set about it; and while she was peering\r
+about anxiously among the trees, a little sharp bark just over\r
+her head made her look up in a great hurry.\r
+\r
+  An enormous puppy was looking down at her with large round\r
+eyes, and feebly stretching out one paw, trying to touch her.\r
+`Poor little thing!' said Alice, in a coaxing tone, and she tried\r
+hard to whistle to it; but she was terribly frightened all the\r
+time at the thought that it might be hungry, in which case it\r
+would be very likely to eat her up in spite of all her coaxing.\r
+\r
+  Hardly knowing what she did, she picked up a little bit of\r
+stick, and held it out to the puppy; whereupon the puppy jumped\r
+into the air off all its feet at once, with a yelp of delight,\r
+and rushed at the stick, and made believe to worry it; then Alice\r
+dodged behind a great thistle, to keep herself from being run\r
+over; and the moment she appeared on the other side, the puppy\r
+made another rush at the stick, and tumbled head over heels in\r
+its hurry to get hold of it; then Alice, thinking it was very\r
+like having a game of play with a cart-horse, and expecting every\r
+moment to be trampled under its feet, ran round the thistle\r
+again; then the puppy began a series of short charges at the\r
+stick, running a very little way forwards each time and a long\r
+way back, and barking hoarsely all the while, till at last it sat\r
+down a good way off, panting, with its tongue hanging out of its\r
+mouth, and its great eyes half shut.\r
+\r
+  This seemed to Alice a good opportunity for making her escape;\r
+so she set off at once, and ran till she was quite tired and out\r
+of breath, and till the puppy's bark sounded quite faint in the\r
+distance.\r
+\r
+  `And yet what a dear little puppy it was!' said Alice, as she\r
+leant against a buttercup to rest herself, and fanned herself\r
+with one of the leaves:  `I should have liked teaching it tricks\r
+very much, if--if I'd only been the right size to do it!  Oh\r
+dear!  I'd nearly forgotten that I've got to grow up again!  Let\r
+me see--how IS it to be managed?  I suppose I ought to eat or\r
+drink something or other; but the great question is, what?'\r
+\r
+  The great question certainly was, what?  Alice looked all round\r
+her at the flowers and the blades of grass, but she did not see\r
+anything that looked like the right thing to eat or drink under\r
+the circumstances.  There was a large mushroom growing near her,\r
+about the same height as herself; and when she had looked under\r
+it, and on both sides of it, and behind it, it occurred to her\r
+that she might as well look and see what was on the top of it.\r
+\r
+  She stretched herself up on tiptoe, and peeped over the edge of\r
+the mushroom, and her eyes immediately met those of a large\r
+caterpillar, that was sitting on the top with its arms folded,\r
+quietly smoking a long hookah, and taking not the smallest notice\r
+of her or of anything else.\r
+\r
+\r
+\r
+                            CHAPTER V\r
+\r
+                    Advice from a Caterpillar\r
+\r
+\r
+  The Caterpillar and Alice looked at each other for some time in\r
+silence:  at last the Caterpillar took the hookah out of its\r
+mouth, and addressed her in a languid, sleepy voice.\r
+\r
+  `Who are YOU?' said the Caterpillar.\r
+\r
+  This was not an encouraging opening for a conversation.  Alice\r
+replied, rather shyly, `I--I hardly know, sir, just at present--\r
+at least I know who I WAS when I got up this morning, but I think\r
+I must have been changed several times since then.'\r
+\r
+  `What do you mean by that?' said the Caterpillar sternly.\r
+`Explain yourself!'\r
+\r
+  `I can't explain MYSELF, I'm afraid, sir' said Alice, `because\r
+I'm not myself, you see.'\r
+\r
+  `I don't see,' said the Caterpillar.\r
+\r
+  `I'm afraid I can't put it more clearly,' Alice replied very\r
+politely, `for I can't understand it myself to begin with; and\r
+being so many different sizes in a day is very confusing.'\r
+\r
+  `It isn't,' said the Caterpillar.\r
+\r
+  `Well, perhaps you haven't found it so yet,' said Alice; `but\r
+when you have to turn into a chrysalis--you will some day, you\r
+know--and then after that into a butterfly, I should think you'll\r
+feel it a little queer, won't you?'\r
+\r
+  `Not a bit,' said the Caterpillar.\r
+\r
+  `Well, perhaps your feelings may be different,' said Alice;\r
+`all I know is, it would feel very queer to ME.'\r
+\r
+  `You!' said the Caterpillar contemptuously.  `Who are YOU?'\r
+\r
+  Which brought them back again to the beginning of the\r
+conversation.  Alice felt a little irritated at the Caterpillar's\r
+making such VERY short remarks, and she drew herself up and said,\r
+very gravely, `I think, you ought to tell me who YOU are, first.'\r
+\r
+  `Why?' said the Caterpillar.\r
+\r
+  Here was another puzzling question; and as Alice could not\r
+think of any good reason, and as the Caterpillar seemed to be in\r
+a VERY unpleasant state of mind, she turned away.\r
+\r
+  `Come back!' the Caterpillar called after her.  `I've something\r
+important to say!'\r
+\r
+  This sounded promising, certainly:  Alice turned and came back\r
+again.\r
+\r
+  `Keep your temper,' said the Caterpillar.\r
+\r
+  `Is that all?' said Alice, swallowing down her anger as well as\r
+she could.\r
+\r
+  `No,' said the Caterpillar.\r
+\r
+  Alice thought she might as well wait, as she had nothing else\r
+to do, and perhaps after all it might tell her something worth\r
+hearing.  For some minutes it puffed away without speaking, but\r
+at last it unfolded its arms, took the hookah out of its mouth\r
+again, and said, `So you think you're changed, do you?'\r
+\r
+  `I'm afraid I am, sir,' said Alice; `I can't remember things as\r
+I used--and I don't keep the same size for ten minutes together!'\r
+\r
+  `Can't remember WHAT things?' said the Caterpillar.\r
+\r
+  `Well, I've tried to say "HOW DOTH THE LITTLE BUSY BEE," but it\r
+all came different!' Alice replied in a very melancholy voice.\r
+\r
+  `Repeat, "YOU ARE OLD, FATHER WILLIAM,"' said the Caterpillar.\r
+\r
+  Alice folded her hands, and began:--\r
+\r
+    `You are old, Father William,' the young man said,\r
+      `And your hair has become very white;\r
+    And yet you incessantly stand on your head--\r
+      Do you think, at your age, it is right?'\r
+\r
+    `In my youth,' Father William replied to his son,\r
+      `I feared it might injure the brain;\r
+    But, now that I'm perfectly sure I have none,\r
+      Why, I do it again and again.'\r
+\r
+    `You are old,' said the youth, `as I mentioned before,\r
+      And have grown most uncommonly fat;\r
+    Yet you turned a back-somersault in at the door--\r
+      Pray, what is the reason of that?'\r
+\r
+    `In my youth,' said the sage, as he shook his grey locks,\r
+      `I kept all my limbs very supple\r
+    By the use of this ointment--one shilling the box--\r
+      Allow me to sell you a couple?'\r
+\r
+    `You are old,' said the youth, `and your jaws are too weak\r
+      For anything tougher than suet;\r
+    Yet you finished the goose, with the bones and the beak--\r
+      Pray how did you manage to do it?'\r
+\r
+    `In my youth,' said his father, `I took to the law,\r
+      And argued each case with my wife;\r
+    And the muscular strength, which it gave to my jaw,\r
+      Has lasted the rest of my life.'\r
+\r
+    `You are old,' said the youth, `one would hardly suppose\r
+      That your eye was as steady as ever;\r
+    Yet you balanced an eel on the end of your nose--\r
+      What made you so awfully clever?'\r
+\r
+    `I have answered three questions, and that is enough,'\r
+      Said his father; `don't give yourself airs!\r
+    Do you think I can listen all day to such stuff?\r
+      Be off, or I'll kick you down stairs!'\r
+\r
+\r
+  `That is not said right,' said the Caterpillar.\r
+\r
+  `Not QUITE right, I'm afraid,' said Alice, timidly; `some of the\r
+words have got altered.'\r
+\r
+  `It is wrong from beginning to end,' said the Caterpillar\r
+decidedly, and there was silence for some minutes.\r
+\r
+  The Caterpillar was the first to speak.\r
+\r
+  `What size do you want to be?' it asked.\r
+\r
+  `Oh, I'm not particular as to size,' Alice hastily replied;\r
+`only one doesn't like changing so often, you know.'\r
+\r
+  `I DON'T know,' said the Caterpillar.\r
+\r
+  Alice said nothing:  she had never been so much contradicted in\r
+her life before, and she felt that she was losing her temper.\r
+\r
+  `Are you content now?' said the Caterpillar.\r
+\r
+  `Well, I should like to be a LITTLE larger, sir, if you\r
+wouldn't mind,' said Alice:  `three inches is such a wretched\r
+height to be.'\r
+\r
+  `It is a very good height indeed!' said the Caterpillar\r
+angrily, rearing itself upright as it spoke (it was exactly three\r
+inches high).\r
+\r
+  `But I'm not used to it!' pleaded poor Alice in a piteous tone.\r
+And she thought of herself, `I wish the creatures wouldn't be so\r
+easily offended!'\r
+\r
+  `You'll get used to it in time,' said the Caterpillar; and it\r
+put the hookah into its mouth and began smoking again.\r
+\r
+  This time Alice waited patiently until it chose to speak again.\r
+In a minute or two the Caterpillar took the hookah out of its\r
+mouth and yawned once or twice, and shook itself.  Then it got\r
+down off the mushroom, and crawled away in the grass, merely\r
+remarking as it went, `One side will make you grow taller, and\r
+the other side will make you grow shorter.'\r
+\r
+  `One side of WHAT?  The other side of WHAT?' thought Alice to\r
+herself.\r
+\r
+  `Of the mushroom,' said the Caterpillar, just as if she had\r
+asked it aloud; and in another moment it was out of sight.\r
+\r
+  Alice remained looking thoughtfully at the mushroom for a\r
+minute, trying to make out which were the two sides of it; and as\r
+it was perfectly round, she found this a very difficult question.\r
+However, at last she stretched her arms round it as far as they\r
+would go, and broke off a bit of the edge with each hand.\r
+\r
+  `And now which is which?' she said to herself, and nibbled a\r
+little of the right-hand bit to try the effect:  the next moment\r
+she felt a violent blow underneath her chin:  it had struck her\r
+foot!\r
+\r
+  She was a good deal frightened by this very sudden change, but\r
+she felt that there was no time to be lost, as she was shrinking\r
+rapidly; so she set to work at once to eat some of the other bit.\r
+Her chin was pressed so closely against her foot, that there was\r
+hardly room to open her mouth; but she did it at last, and\r
+managed to swallow a morsel of the lefthand bit.\r
+\r
+\r
+     *       *       *       *       *       *       *\r
+\r
+         *       *       *       *       *       *\r
+\r
+     *       *       *       *       *       *       *\r
+\r
+  `Come, my head's free at last!' said Alice in a tone of\r
+delight, which changed into alarm in another moment, when she\r
+found that her shoulders were nowhere to be found:  all she could\r
+see, when she looked down, was an immense length of neck, which\r
+seemed to rise like a stalk out of a sea of green leaves that lay\r
+far below her.\r
+\r
+  `What CAN all that green stuff be?' said Alice.  `And where\r
+HAVE my shoulders got to?  And oh, my poor hands, how is it I\r
+can't see you?'  She was moving them about as she spoke, but no\r
+result seemed to follow, except a little shaking among the\r
+distant green leaves.\r
+\r
+  As there seemed to be no chance of getting her hands up to her\r
+head, she tried to get her head down to them, and was delighted\r
+to find that her neck would bend about easily in any direction,\r
+like a serpent.  She had just succeeded in curving it down into a\r
+graceful zigzag, and was going to dive in among the leaves, which\r
+she found to be nothing but the tops of the trees under which she\r
+had been wandering, when a sharp hiss made her draw back in a\r
+hurry:  a large pigeon had flown into her face, and was beating\r
+her violently with its wings.\r
+\r
+  `Serpent!' screamed the Pigeon.\r
+\r
+  `I'm NOT a serpent!' said Alice indignantly.  `Let me alone!'\r
+\r
+  `Serpent, I say again!' repeated the Pigeon, but in a more\r
+subdued tone, and added with a kind of sob, `I've tried every\r
+way, and nothing seems to suit them!'\r
+\r
+  `I haven't the least idea what you're talking about,' said\r
+Alice.\r
+\r
+  `I've tried the roots of trees, and I've tried banks, and I've\r
+tried hedges,' the Pigeon went on, without attending to her; `but\r
+those serpents!  There's no pleasing them!'\r
+\r
+  Alice was more and more puzzled, but she thought there was no\r
+use in saying anything more till the Pigeon had finished.\r
+\r
+  `As if it wasn't trouble enough hatching the eggs,' said the\r
+Pigeon; `but I must be on the look-out for serpents night and\r
+day!  Why, I haven't had a wink of sleep these three weeks!'\r
+\r
+  `I'm very sorry you've been annoyed,' said Alice, who was\r
+beginning to see its meaning.\r
+\r
+  `And just as I'd taken the highest tree in the wood,' continued\r
+the Pigeon, raising its voice to a shriek, `and just as I was\r
+thinking I should be free of them at last, they must needs come\r
+wriggling down from the sky!  Ugh, Serpent!'\r
+\r
+  `But I'm NOT a serpent, I tell you!' said Alice.  `I'm a--I'm\r
+a--'\r
+\r
+  `Well!  WHAT are you?' said the Pigeon.  `I can see you're\r
+trying to invent something!'\r
+\r
+  `I--I'm a little girl,' said Alice, rather doubtfully, as she\r
+remembered the number of changes she had gone through that day.\r
+\r
+  `A likely story indeed!' said the Pigeon in a tone of the\r
+deepest contempt.  `I've seen a good many little girls in my\r
+time, but never ONE with such a neck as that!  No, no!  You're a\r
+serpent; and there's no use denying it.  I suppose you'll be\r
+telling me next that you never tasted an egg!'\r
+\r
+  `I HAVE tasted eggs, certainly,' said Alice, who was a very\r
+truthful child; `but little girls eat eggs quite as much as\r
+serpents do, you know.'\r
+\r
+  `I don't believe it,' said the Pigeon; `but if they do, why\r
+then they're a kind of serpent, that's all I can say.'\r
+\r
+  This was such a new idea to Alice, that she was quite silent\r
+for a minute or two, which gave the Pigeon the opportunity of\r
+adding, `You're looking for eggs, I know THAT well enough; and\r
+what does it matter to me whether you're a little girl or a\r
+serpent?'\r
+\r
+  `It matters a good deal to ME,' said Alice hastily; `but I'm\r
+not looking for eggs, as it happens; and if I was, I shouldn't\r
+want YOURS:  I don't like them raw.'\r
+\r
+  `Well, be off, then!' said the Pigeon in a sulky tone, as it\r
+settled down again into its nest.  Alice crouched down among the\r
+trees as well as she could, for her neck kept getting entangled\r
+among the branches, and every now and then she had to stop and\r
+untwist it.  After a while she remembered that she still held the\r
+pieces of mushroom in her hands, and she set to work very\r
+carefully, nibbling first at one and then at the other, and\r
+growing sometimes taller and sometimes shorter, until she had\r
+succeeded in bringing herself down to her usual height.\r
+\r
+  It was so long since she had been anything near the right size,\r
+that it felt quite strange at first; but she got used to it in a\r
+few minutes, and began talking to herself, as usual.  `Come,\r
+there's half my plan done now!  How puzzling all these changes\r
+are!  I'm never sure what I'm going to be, from one minute to\r
+another!  However, I've got back to my right size:  the next\r
+thing is, to get into that beautiful garden--how IS that to be\r
+done, I wonder?'  As she said this, she came suddenly upon an\r
+open place, with a little house in it about four feet high.\r
+`Whoever lives there,' thought Alice, `it'll never do to come\r
+upon them THIS size:  why, I should frighten them out of their\r
+wits!'  So she began nibbling at the righthand bit again, and did\r
+not venture to go near the house till she had brought herself\r
+down to nine inches high.\r
+\r
+\r
+\r
+                           CHAPTER VI\r
+\r
+                         Pig and Pepper\r
+\r
+\r
+  For a minute or two she stood looking at the house, and\r
+wondering what to do next, when suddenly a footman in livery came\r
+running out of the wood--(she considered him to be a footman\r
+because he was in livery:  otherwise, judging by his face only,\r
+she would have called him a fish)--and rapped loudly at the door\r
+with his knuckles.  It was opened by another footman in livery,\r
+with a round face, and large eyes like a frog; and both footmen,\r
+Alice noticed, had powdered hair that curled all over their\r
+heads.  She felt very curious to know what it was all about, and\r
+crept a little way out of the wood to listen.\r
+\r
+  The Fish-Footman began by producing from under his arm a great\r
+letter, nearly as large as himself, and this he handed over to\r
+the other, saying, in a solemn tone, `For the Duchess.  An\r
+invitation from the Queen to play croquet.'  The Frog-Footman\r
+repeated, in the same solemn tone, only changing the order of the\r
+words a little, `From the Queen.  An invitation for the Duchess\r
+to play croquet.'\r
+\r
+  Then they both bowed low, and their curls got entangled\r
+together.\r
+\r
+  Alice laughed so much at this, that she had to run back into\r
+the wood for fear of their hearing her; and when she next peeped\r
+out the Fish-Footman was gone, and the other was sitting on the\r
+ground near the door, staring stupidly up into the sky.\r
+\r
+  Alice went timidly up to the door, and knocked.\r
+\r
+  `There's no sort of use in knocking,' said the Footman, `and\r
+that for two reasons.  First, because I'm on the same side of the\r
+door as you are; secondly, because they're making such a noise\r
+inside, no one could possibly hear you.'  And certainly there was\r
+a most extraordinary noise going on within--a constant howling\r
+and sneezing, and every now and then a great crash, as if a dish\r
+or kettle had been broken to pieces.\r
+\r
+  `Please, then,' said Alice, `how am I to get in?'\r
+\r
+  `There might be some sense in your knocking,' the Footman went\r
+on without attending to her, `if we had the door between us.  For\r
+instance, if you were INSIDE, you might knock, and I could let\r
+you out, you know.'  He was looking up into the sky all the time\r
+he was speaking, and this Alice thought decidedly uncivil.  `But\r
+perhaps he can't help it,' she said to herself; `his eyes are so\r
+VERY nearly at the top of his head.  But at any rate he might\r
+answer questions.--How am I to get in?' she repeated, aloud.\r
+\r
+  `I shall sit here,' the Footman remarked, `till tomorrow--'\r
+\r
+  At this moment the door of the house opened, and a large plate\r
+came skimming out, straight at the Footman's head:  it just\r
+grazed his nose, and broke to pieces against one of the trees\r
+behind him.\r
+\r
+  `--or next day, maybe,' the Footman continued in the same tone,\r
+exactly as if nothing had happened.\r
+\r
+  `How am I to get in?' asked Alice again, in a louder tone.\r
+\r
+  `ARE you to get in at all?' said the Footman.  `That's the\r
+first question, you know.'\r
+\r
+  It was, no doubt:  only Alice did not like to be told so.\r
+`It's really dreadful,' she muttered to herself, `the way all the\r
+creatures argue.  It's enough to drive one crazy!'\r
+\r
+  The Footman seemed to think this a good opportunity for\r
+repeating his remark, with variations.  `I shall sit here,' he\r
+said, `on and off, for days and days.'\r
+\r
+  `But what am I to do?' said Alice.\r
+\r
+  `Anything you like,' said the Footman, and began whistling.\r
+\r
+  `Oh, there's no use in talking to him,' said Alice desperately:\r
+`he's perfectly idiotic!'  And she opened the door and went in.\r
+\r
+  The door led right into a large kitchen, which was full of\r
+smoke from one end to the other:  the Duchess was sitting on a\r
+three-legged stool in the middle, nursing a baby; the cook was\r
+leaning over the fire, stirring a large cauldron which seemed to\r
+be full of soup.\r
+\r
+  `There's certainly too much pepper in that soup!' Alice said to\r
+herself, as well as she could for sneezing.\r
+\r
+  There was certainly too much of it in the air.  Even the\r
+Duchess sneezed occasionally; and as for the baby, it was\r
+sneezing and howling alternately without a moment's pause.  The\r
+only things in the kitchen that did not sneeze, were the cook,\r
+and a large cat which was sitting on the hearth and grinning from\r
+ear to ear.\r
+\r
+  `Please would you tell me,' said Alice, a little timidly, for\r
+she was not quite sure whether it was good manners for her to\r
+speak first, `why your cat grins like that?'\r
+\r
+  `It's a Cheshire cat,' said the Duchess, `and that's why.\r
+Pig!'\r
+\r
+  She said the last word with such sudden violence that Alice\r
+quite jumped; but she saw in another moment that it was addressed\r
+to the baby, and not to her, so she took courage, and went on\r
+again:--\r
+\r
+  `I didn't know that Cheshire cats always grinned; in fact, I\r
+didn't know that cats COULD grin.'\r
+\r
+  `They all can,' said the Duchess; `and most of 'em do.'\r
+\r
+  `I don't know of any that do,' Alice said very politely,\r
+feeling quite pleased to have got into a conversation.\r
+\r
+  `You don't know much,' said the Duchess; `and that's a fact.'\r
+\r
+  Alice did not at all like the tone of this remark, and thought\r
+it would be as well to introduce some other subject of\r
+conversation.  While she was trying to fix on one, the cook took\r
+the cauldron of soup off the fire, and at once set to work\r
+throwing everything within her reach at the Duchess and the baby\r
+--the fire-irons came first; then followed a shower of saucepans,\r
+plates, and dishes.  The Duchess took no notice of them even when\r
+they hit her; and the baby was howling so much already, that it\r
+was quite impossible to say whether the blows hurt it or not.\r
+\r
+  `Oh, PLEASE mind what you're doing!' cried Alice, jumping up\r
+and down in an agony of terror.  `Oh, there goes his PRECIOUS\r
+nose'; as an unusually large saucepan flew close by it, and very\r
+nearly carried it off.\r
+\r
+  `If everybody minded their own business,' the Duchess said in a\r
+hoarse growl, `the world would go round a deal faster than it\r
+does.'\r
+\r
+  `Which would NOT be an advantage,' said Alice, who felt very\r
+glad to get an opportunity of showing off a little of her\r
+knowledge.  `Just think of what work it would make with the day\r
+and night!  You see the earth takes twenty-four hours to turn\r
+round on its axis--'\r
+\r
+  `Talking of axes,' said the Duchess, `chop off her head!'\r
+\r
+  Alice glanced rather anxiously at the cook, to see if she meant\r
+to take the hint; but the cook was busily stirring the soup, and\r
+seemed not to be listening, so she went on again:  `Twenty-four\r
+hours, I THINK; or is it twelve?  I--'\r
+\r
+  `Oh, don't bother ME,' said the Duchess; `I never could abide\r
+figures!'  And with that she began nursing her child again,\r
+singing a sort of lullaby to it as she did so, and giving it a\r
+violent shake at the end of every line:\r
+\r
+        `Speak roughly to your little boy,\r
+          And beat him when he sneezes:\r
+        He only does it to annoy,\r
+          Because he knows it teases.'\r
+\r
+                    CHORUS.\r
+\r
+    (In which the cook and the baby joined):--\r
+\r
+                `Wow! wow! wow!'\r
+\r
+  While the Duchess sang the second verse of the song, she kept\r
+tossing the baby violently up and down, and the poor little thing\r
+howled so, that Alice could hardly hear the words:--\r
+\r
+        `I speak severely to my boy,\r
+          I beat him when he sneezes;\r
+        For he can thoroughly enjoy\r
+          The pepper when he pleases!'\r
+\r
+                    CHORUS.\r
+\r
+                `Wow! wow! wow!'\r
+\r
+  `Here! you may nurse it a bit, if you like!' the Duchess said\r
+to Alice, flinging the baby at her as she spoke.  `I must go and\r
+get ready to play croquet with the Queen,' and she hurried out of\r
+the room.  The cook threw a frying-pan after her as she went out,\r
+but it just missed her.\r
+\r
+  Alice caught the baby with some difficulty, as it was a queer-\r
+shaped little creature, and held out its arms and legs in all\r
+directions, `just like a star-fish,' thought Alice.  The poor\r
+little thing was snorting like a steam-engine when she caught it,\r
+and kept doubling itself up and straightening itself out again,\r
+so that altogether, for the first minute or two, it was as much\r
+as she could do to hold it.\r
+\r
+  As soon as she had made out the proper way of nursing it,\r
+(which was to twist it up into a sort of knot, and then keep\r
+tight hold of its right ear and left foot, so as to prevent its\r
+undoing itself,) she carried it out into the open air.  `IF I\r
+don't take this child away with me,' thought Alice, `they're sure\r
+to kill it in a day or two:  wouldn't it be murder to leave it\r
+behind?'  She said the last words out loud, and the little thing\r
+grunted in reply (it had left off sneezing by this time).  `Don't\r
+grunt,' said Alice; `that's not at all a proper way of expressing\r
+yourself.'\r
+\r
+  The baby grunted again, and Alice looked very anxiously into\r
+its face to see what was the matter with it.  There could be no\r
+doubt that it had a VERY turn-up nose, much more like a snout\r
+than a real nose; also its eyes were getting extremely small for\r
+a baby:  altogether Alice did not like the look of the thing at\r
+all.  `But perhaps it was only sobbing,' she thought, and looked\r
+into its eyes again, to see if there were any tears.\r
+\r
+  No, there were no tears.  `If you're going to turn into a pig,\r
+my dear,' said Alice, seriously, `I'll have nothing more to do\r
+with you.  Mind now!'  The poor little thing sobbed again (or\r
+grunted, it was impossible to say which), and they went on for\r
+some while in silence.\r
+\r
+  Alice was just beginning to think to herself, `Now, what am I\r
+to do with this creature when I get it home?' when it grunted\r
+again, so violently, that she looked down into its face in some\r
+alarm.  This time there could be NO mistake about it:  it was\r
+neither more nor less than a pig, and she felt that it would be\r
+quite absurd for her to carry it further.\r
+\r
+  So she set the little creature down, and felt quite relieved to\r
+see it trot away quietly into the wood.  `If it had grown up,'\r
+she said to herself, `it would have made a dreadfully ugly child:\r
+but it makes rather a handsome pig, I think.'  And she began\r
+thinking over other children she knew, who might do very well as\r
+pigs, and was just saying to herself, `if one only knew the right\r
+way to change them--' when she was a little startled by seeing\r
+the Cheshire Cat sitting on a bough of a tree a few yards off.\r
+\r
+  The Cat only grinned when it saw Alice.  It looked good-\r
+natured, she thought:  still it had VERY long claws and a great\r
+many teeth, so she felt that it ought to be treated with respect.\r
+\r
+  `Cheshire Puss,' she began, rather timidly, as she did not at\r
+all know whether it would like the name:  however, it only\r
+grinned a little wider.  `Come, it's pleased so far,' thought\r
+Alice, and she went on.  `Would you tell me, please, which way I\r
+ought to go from here?'\r
+\r
+  `That depends a good deal on where you want to get to,' said\r
+the Cat.\r
+\r
+  `I don't much care where--' said Alice.\r
+\r
+  `Then it doesn't matter which way you go,' said the Cat.\r
+\r
+  `--so long as I get SOMEWHERE,' Alice added as an explanation.\r
+\r
+  `Oh, you're sure to do that,' said the Cat, `if you only walk\r
+long enough.'\r
+\r
+  Alice felt that this could not be denied, so she tried another\r
+question.  `What sort of people live about here?'\r
+\r
+  `In THAT direction,' the Cat said, waving its right paw round,\r
+`lives a Hatter:  and in THAT direction,' waving the other paw,\r
+`lives a March Hare.  Visit either you like:  they're both mad.'\r
+\r
+  `But I don't want to go among mad people,' Alice remarked.\r
+\r
+  `Oh, you can't help that,' said the Cat:  `we're all mad here.\r
+I'm mad.  You're mad.'\r
+\r
+  `How do you know I'm mad?' said Alice.\r
+\r
+  `You must be,' said the Cat, `or you wouldn't have come here.'\r
+\r
+  Alice didn't think that proved it at all; however, she went on\r
+`And how do you know that you're mad?'\r
+\r
+  `To begin with,' said the Cat, `a dog's not mad.  You grant\r
+that?'\r
+\r
+  `I suppose so,' said Alice.\r
+\r
+  `Well, then,' the Cat went on, `you see, a dog growls when it's\r
+angry, and wags its tail when it's pleased.  Now I growl when I'm\r
+pleased, and wag my tail when I'm angry.  Therefore I'm mad.'\r
+\r
+  `I call it purring, not growling,' said Alice.\r
+\r
+  `Call it what you like,' said the Cat.  `Do you play croquet\r
+with the Queen to-day?'\r
+\r
+  `I should like it very much,' said Alice, `but I haven't been\r
+invited yet.'\r
+\r
+  `You'll see me there,' said the Cat, and vanished.\r
+\r
+  Alice was not much surprised at this, she was getting so used\r
+to queer things happening.  While she was looking at the place\r
+where it had been, it suddenly appeared again.\r
+\r
+  `By-the-bye, what became of the baby?' said the Cat.  `I'd\r
+nearly forgotten to ask.'\r
+\r
+  `It turned into a pig,' Alice quietly said, just as if it had\r
+come back in a natural way.\r
+\r
+  `I thought it would,' said the Cat, and vanished again.\r
+\r
+  Alice waited a little, half expecting to see it again, but it\r
+did not appear, and after a minute or two she walked on in the\r
+direction in which the March Hare was said to live.  `I've seen\r
+hatters before,' she said to herself; `the March Hare will be\r
+much the most interesting, and perhaps as this is May it won't be\r
+raving mad--at least not so mad as it was in March.'  As she said\r
+this, she looked up, and there was the Cat again, sitting on a\r
+branch of a tree.\r
+\r
+  `Did you say pig, or fig?' said the Cat.\r
+\r
+  `I said pig,' replied Alice; `and I wish you wouldn't keep\r
+appearing and vanishing so suddenly:  you make one quite giddy.'\r
+\r
+  `All right,' said the Cat; and this time it vanished quite\r
+slowly, beginning with the end of the tail, and ending with the\r
+grin, which remained some time after the rest of it had gone.\r
+\r
+  `Well!  I've often seen a cat without a grin,' thought Alice;\r
+`but a grin without a cat!  It's the most curious thing I ever\r
+say in my life!'\r
+\r
+  She had not gone much farther before she came in sight of the\r
+house of the March Hare:  she thought it must be the right house,\r
+because the chimneys were shaped like ears and the roof was\r
+thatched with fur.  It was so large a house, that she did not\r
+like to go nearer till she had nibbled some more of the lefthand\r
+bit of mushroom, and raised herself to about two feet high:  even\r
+then she walked up towards it rather timidly, saying to herself\r
+`Suppose it should be raving mad after all!  I almost wish I'd\r
+gone to see the Hatter instead!'\r
+\r
+\r
+\r
+                           CHAPTER VII\r
+\r
+                         A Mad Tea-Party\r
+\r
+\r
+  There was a table set out under a tree in front of the house,\r
+and the March Hare and the Hatter were having tea at it:  a\r
+Dormouse was sitting between them, fast asleep, and the other two\r
+were using it as a cushion, resting their elbows on it, and the\r
+talking over its head.  `Very uncomfortable for the Dormouse,'\r
+thought Alice; `only, as it's asleep, I suppose it doesn't mind.'\r
+\r
+  The table was a large one, but the three were all crowded\r
+together at one corner of it:  `No room!  No room!' they cried\r
+out when they saw Alice coming.  `There's PLENTY of room!' said\r
+Alice indignantly, and she sat down in a large arm-chair at one\r
+end of the table.\r
+\r
+  `Have some wine,' the March Hare said in an encouraging tone.\r
+\r
+  Alice looked all round the table, but there was nothing on it\r
+but tea.  `I don't see any wine,' she remarked.\r
+\r
+  `There isn't any,' said the March Hare.\r
+\r
+  `Then it wasn't very civil of you to offer it,' said Alice\r
+angrily.\r
+\r
+  `It wasn't very civil of you to sit down without being\r
+invited,' said the March Hare.\r
+\r
+  `I didn't know it was YOUR table,' said Alice; `it's laid for a\r
+great many more than three.'\r
+\r
+  `Your hair wants cutting,' said the Hatter.  He had been\r
+looking at Alice for some time with great curiosity, and this was\r
+his first speech.\r
+\r
+  `You should learn not to make personal remarks,' Alice said\r
+with some severity; `it's very rude.'\r
+\r
+  The Hatter opened his eyes very wide on hearing this; but all\r
+he SAID was, `Why is a raven like a writing-desk?'\r
+\r
+  `Come, we shall have some fun now!' thought Alice.  `I'm glad\r
+they've begun asking riddles.--I believe I can guess that,' she\r
+added aloud.\r
+\r
+  `Do you mean that you think you can find out the answer to it?'\r
+said the March Hare.\r
+\r
+  `Exactly so,' said Alice.\r
+\r
+  `Then you should say what you mean,' the March Hare went on.\r
+\r
+  `I do,' Alice hastily replied; `at least--at least I mean what\r
+I say--that's the same thing, you know.'\r
+\r
+  `Not the same thing a bit!' said the Hatter.  `You might just\r
+as well say that "I see what I eat" is the same thing as "I eat\r
+what I see"!'\r
+\r
+  `You might just as well say,' added the March Hare, `that "I\r
+like what I get" is the same thing as "I get what I like"!'\r
+\r
+  `You might just as well say,' added the Dormouse, who seemed to\r
+be talking in his sleep, `that "I breathe when I sleep" is the\r
+same thing as "I sleep when I breathe"!'\r
+\r
+  `It IS the same thing with you,' said the Hatter, and here the\r
+conversation dropped, and the party sat silent for a minute,\r
+while Alice thought over all she could remember about ravens and\r
+writing-desks, which wasn't much.\r
+\r
+  The Hatter was the first to break the silence.  `What day of\r
+the month is it?' he said, turning to Alice:  he had taken his\r
+watch out of his pocket, and was looking at it uneasily, shaking\r
+it every now and then, and holding it to his ear.\r
+\r
+  Alice considered a little, and then said `The fourth.'\r
+\r
+  `Two days wrong!' sighed the Hatter.  `I told you butter\r
+wouldn't suit the works!' he added looking angrily at the March\r
+Hare.\r
+\r
+  `It was the BEST butter,' the March Hare meekly replied.\r
+\r
+  `Yes, but some crumbs must have got in as well,' the Hatter\r
+grumbled:  `you shouldn't have put it in with the bread-knife.'\r
+\r
+  The March Hare took the watch and looked at it gloomily:  then\r
+he dipped it into his cup of tea, and looked at it again:  but he\r
+could think of nothing better to say than his first remark, `It\r
+was the BEST butter, you know.'\r
+\r
+  Alice had been looking over his shoulder with some curiosity.\r
+`What a funny watch!' she remarked.  `It tells the day of the\r
+month, and doesn't tell what o'clock it is!'\r
+\r
+  `Why should it?' muttered the Hatter.  `Does YOUR watch tell\r
+you what year it is?'\r
+\r
+  `Of course not,' Alice replied very readily:  `but that's\r
+because it stays the same year for such a long time together.'\r
+\r
+  `Which is just the case with MINE,' said the Hatter.\r
+\r
+  Alice felt dreadfully puzzled.  The Hatter's remark seemed to\r
+have no sort of meaning in it, and yet it was certainly English.\r
+`I don't quite understand you,' she said, as politely as she\r
+could.\r
+\r
+  `The Dormouse is asleep again,' said the Hatter, and he poured\r
+a little hot tea upon its nose.\r
+\r
+  The Dormouse shook its head impatiently, and said, without\r
+opening its eyes, `Of course, of course; just what I was going to\r
+remark myself.'\r
+\r
+  `Have you guessed the riddle yet?' the Hatter said, turning to\r
+Alice again.\r
+\r
+  `No, I give it up,' Alice replied:  `what's the answer?'\r
+\r
+  `I haven't the slightest idea,' said the Hatter.\r
+\r
+  `Nor I,' said the March Hare.\r
+\r
+  Alice sighed wearily.  `I think you might do something better\r
+with the time,' she said, `than waste it in asking riddles that\r
+have no answers.'\r
+\r
+  `If you knew Time as well as I do,' said the Hatter, `you\r
+wouldn't talk about wasting IT.  It's HIM.'\r
+\r
+  `I don't know what you mean,' said Alice.\r
+\r
+  `Of course you don't!' the Hatter said, tossing his head\r
+contemptuously.  `I dare say you never even spoke to Time!'\r
+\r
+  `Perhaps not,' Alice cautiously replied:  `but I know I have to\r
+beat time when I learn music.'\r
+\r
+  `Ah! that accounts for it,' said the Hatter.  `He won't stand\r
+beating.  Now, if you only kept on good terms with him, he'd do\r
+almost anything you liked with the clock.  For instance, suppose\r
+it were nine o'clock in the morning, just time to begin lessons:\r
+you'd only have to whisper a hint to Time, and round goes the\r
+clock in a twinkling!  Half-past one, time for dinner!'\r
+\r
+  (`I only wish it was,' the March Hare said to itself in a\r
+whisper.)\r
+\r
+  `That would be grand, certainly,' said Alice thoughtfully:\r
+`but then--I shouldn't be hungry for it, you know.'\r
+\r
+  `Not at first, perhaps,' said the Hatter:  `but you could keep\r
+it to half-past one as long as you liked.'\r
+\r
+  `Is that the way YOU manage?' Alice asked.\r
+\r
+  The Hatter shook his head mournfully.  `Not I!' he replied.\r
+`We quarrelled last March--just before HE went mad, you know--'\r
+(pointing with his tea spoon at the March Hare,) `--it was at the\r
+great concert given by the Queen of Hearts, and I had to sing\r
+\r
+            "Twinkle, twinkle, little bat!\r
+            How I wonder what you're at!"\r
+\r
+You know the song, perhaps?'\r
+\r
+  `I've heard something like it,' said Alice.\r
+\r
+  `It goes on, you know,' the Hatter continued, `in this way:--\r
+\r
+            "Up above the world you fly,\r
+            Like a tea-tray in the sky.\r
+                    Twinkle, twinkle--"'\r
+\r
+Here the Dormouse shook itself, and began singing in its sleep\r
+`Twinkle, twinkle, twinkle, twinkle--' and went on so long that\r
+they had to pinch it to make it stop.\r
+\r
+  `Well, I'd hardly finished the first verse,' said the Hatter,\r
+`when the Queen jumped up and bawled out, "He's murdering the\r
+time!  Off with his head!"'\r
+\r
+  `How dreadfully savage!' exclaimed Alice.\r
+\r
+  `And ever since that,' the Hatter went on in a mournful tone,\r
+`he won't do a thing I ask!  It's always six o'clock now.'\r
+\r
+  A bright idea came into Alice's head.  `Is that the reason so\r
+many tea-things are put out here?' she asked.\r
+\r
+  `Yes, that's it,' said the Hatter with a sigh:  `it's always\r
+tea-time, and we've no time to wash the things between whiles.'\r
+\r
+  `Then you keep moving round, I suppose?' said Alice.\r
+\r
+  `Exactly so,' said the Hatter:  `as the things get used up.'\r
+\r
+  `But what happens when you come to the beginning again?' Alice\r
+ventured to ask.\r
+\r
+  `Suppose we change the subject,' the March Hare interrupted,\r
+yawning.  `I'm getting tired of this.  I vote the young lady\r
+tells us a story.'\r
+\r
+  `I'm afraid I don't know one,' said Alice, rather alarmed at\r
+the proposal.\r
+\r
+  `Then the Dormouse shall!' they both cried.  `Wake up,\r
+Dormouse!'  And they pinched it on both sides at once.\r
+\r
+  The Dormouse slowly opened his eyes.  `I wasn't asleep,' he\r
+said in a hoarse, feeble voice:  `I heard every word you fellows\r
+were saying.'\r
+\r
+  `Tell us a story!' said the March Hare.\r
+\r
+  `Yes, please do!' pleaded Alice.\r
+\r
+  `And be quick about it,' added the Hatter, `or you'll be asleep\r
+again before it's done.'\r
+\r
+  `Once upon a time there were three little sisters,' the\r
+Dormouse began in a great hurry; `and their names were Elsie,\r
+Lacie, and Tillie; and they lived at the bottom of a well--'\r
+\r
+  `What did they live on?' said Alice, who always took a great\r
+interest in questions of eating and drinking.\r
+\r
+  `They lived on treacle,' said the Dormouse, after thinking a\r
+minute or two.\r
+\r
+  `They couldn't have done that, you know,' Alice gently\r
+remarked; `they'd have been ill.'\r
+\r
+  `So they were,' said the Dormouse; `VERY ill.'\r
+\r
+  Alice tried to fancy to herself what such an extraordinary ways\r
+of living would be like, but it puzzled her too much, so she went\r
+on:  `But why did they live at the bottom of a well?'\r
+\r
+  `Take some more tea,' the March Hare said to Alice, very\r
+earnestly.\r
+\r
+  `I've had nothing yet,' Alice replied in an offended tone, `so\r
+I can't take more.'\r
+\r
+  `You mean you can't take LESS,' said the Hatter:  `it's very\r
+easy to take MORE than nothing.'\r
+\r
+  `Nobody asked YOUR opinion,' said Alice.\r
+\r
+  `Who's making personal remarks now?' the Hatter asked\r
+triumphantly.\r
+\r
+  Alice did not quite know what to say to this:  so she helped\r
+herself to some tea and bread-and-butter, and then turned to the\r
+Dormouse, and repeated her question.  `Why did they live at the\r
+bottom of a well?'\r
+\r
+  The Dormouse again took a minute or two to think about it, and\r
+then said, `It was a treacle-well.'\r
+\r
+  `There's no such thing!'  Alice was beginning very angrily, but\r
+the Hatter and the March Hare went `Sh! sh!' and the Dormouse\r
+sulkily remarked, `If you can't be civil, you'd better finish the\r
+story for yourself.'\r
+\r
+  `No, please go on!' Alice said very humbly; `I won't interrupt\r
+again.  I dare say there may be ONE.'\r
+\r
+  `One, indeed!' said the Dormouse indignantly.  However, he\r
+consented to go on.  `And so these three little sisters--they\r
+were learning to draw, you know--'\r
+\r
+  `What did they draw?' said Alice, quite forgetting her promise.\r
+\r
+  `Treacle,' said the Dormouse, without considering at all this\r
+time.\r
+\r
+  `I want a clean cup,' interrupted the Hatter:  `let's all move\r
+one place on.'\r
+\r
+  He moved on as he spoke, and the Dormouse followed him:  the\r
+March Hare moved into the Dormouse's place, and Alice rather\r
+unwillingly took the place of the March Hare.  The Hatter was the\r
+only one who got any advantage from the change:  and Alice was a\r
+good deal worse off than before, as the March Hare had just upset\r
+the milk-jug into his plate.\r
+\r
+  Alice did not wish to offend the Dormouse again, so she began\r
+very cautiously:  `But I don't understand.  Where did they draw\r
+the treacle from?'\r
+\r
+  `You can draw water out of a water-well,' said the Hatter; `so\r
+I should think you could draw treacle out of a treacle-well--eh,\r
+stupid?'\r
+\r
+  `But they were IN the well,' Alice said to the Dormouse, not\r
+choosing to notice this last remark.\r
+\r
+  `Of course they were', said the Dormouse; `--well in.'\r
+\r
+  This answer so confused poor Alice, that she let the Dormouse\r
+go on for some time without interrupting it.\r
+\r
+  `They were learning to draw,' the Dormouse went on, yawning and\r
+rubbing its eyes, for it was getting very sleepy; `and they drew\r
+all manner of things--everything that begins with an M--'\r
+\r
+  `Why with an M?' said Alice.\r
+\r
+  `Why not?' said the March Hare.\r
+\r
+  Alice was silent.\r
+\r
+  The Dormouse had closed its eyes by this time, and was going\r
+off into a doze; but, on being pinched by the Hatter, it woke up\r
+again with a little shriek, and went on:  `--that begins with an\r
+M, such as mouse-traps, and the moon, and memory, and muchness--\r
+you know you say things are "much of a muchness"--did you ever\r
+see such a thing as a drawing of a muchness?'\r
+\r
+  `Really, now you ask me,' said Alice, very much confused, `I\r
+don't think--'\r
+\r
+  `Then you shouldn't talk,' said the Hatter.\r
+\r
+  This piece of rudeness was more than Alice could bear:  she got\r
+up in great disgust, and walked off; the Dormouse fell asleep\r
+instantly, and neither of the others took the least notice of her\r
+going, though she looked back once or twice, half hoping that\r
+they would call after her:  the last time she saw them, they were\r
+trying to put the Dormouse into the teapot.\r
+\r
+  `At any rate I'll never go THERE again!' said Alice as she\r
+picked her way through the wood.  `It's the stupidest tea-party I\r
+ever was at in all my life!'\r
+\r
+  Just as she said this, she noticed that one of the trees had a\r
+door leading right into it.  `That's very curious!' she thought.\r
+`But everything's curious today.  I think I may as well go in at\r
+once.'  And in she went.\r
+\r
+  Once more she found herself in the long hall, and close to the\r
+little glass table.  `Now, I'll manage better this time,' she\r
+said to herself, and began by taking the little golden key, and\r
+unlocking the door that led into the garden.  Then she went to\r
+work nibbling at the mushroom (she had kept a piece of it in her\r
+pocked) till she was about a foot high:  then she walked down the\r
+little passage:  and THEN--she found herself at last in the\r
+beautiful garden, among the bright flower-beds and the cool\r
+fountains.\r
+\r
+\r
+\r
+                          CHAPTER VIII\r
+\r
+                   The Queen's Croquet-Ground\r
+\r
+\r
+  A large rose-tree stood near the entrance of the garden:  the\r
+roses growing on it were white, but there were three gardeners at\r
+it, busily painting them red.  Alice thought this a very curious\r
+thing, and she went nearer to watch them, and just as she came up\r
+to them she heard one of them say, `Look out now, Five!  Don't go\r
+splashing paint over me like that!'\r
+\r
+  `I couldn't help it,' said Five, in a sulky tone; `Seven jogged\r
+my elbow.'\r
+\r
+  On which Seven looked up and said, `That's right, Five!  Always\r
+lay the blame on others!'\r
+\r
+  `YOU'D better not talk!' said Five.  `I heard the Queen say only\r
+yesterday you deserved to be beheaded!'\r
+\r
+  `What for?' said the one who had spoken first.\r
+\r
+  `That's none of YOUR business, Two!' said Seven.\r
+\r
+  `Yes, it IS his business!' said Five, `and I'll tell him--it\r
+was for bringing the cook tulip-roots instead of onions.'\r
+\r
+  Seven flung down his brush, and had just begun `Well, of all\r
+the unjust things--' when his eye chanced to fall upon Alice, as\r
+she stood watching them, and he checked himself suddenly:  the\r
+others looked round also, and all of them bowed low.\r
+\r
+  `Would you tell me,' said Alice, a little timidly, `why you are\r
+painting those roses?'\r
+\r
+  Five and Seven said nothing, but looked at Two.  Two began in a\r
+low voice, `Why the fact is, you see, Miss, this here ought to\r
+have been a RED rose-tree, and we put a white one in by mistake;\r
+and if the Queen was to find it out, we should all have our heads\r
+cut off, you know.  So you see, Miss, we're doing our best, afore\r
+she comes, to--'  At this moment Five, who had been anxiously\r
+looking across the garden, called out `The Queen!  The Queen!'\r
+and the three gardeners instantly threw themselves flat upon\r
+their faces.  There was a sound of many footsteps, and Alice\r
+looked round, eager to see the Queen.\r
+\r
+  First came ten soldiers carrying clubs; these were all shaped\r
+like the three gardeners, oblong and flat, with their hands and\r
+feet at the corners:  next the ten courtiers; these were\r
+ornamented all over with diamonds, and walked two and two, as the\r
+soldiers did.  After these came the royal children; there were\r
+ten of them, and the little dears came jumping merrily along hand\r
+in hand, in couples:  they were all ornamented with hearts.  Next\r
+came the guests, mostly Kings and Queens, and among them Alice\r
+recognised the White Rabbit:  it was talking in a hurried nervous\r
+manner, smiling at everything that was said, and went by without\r
+noticing her.  Then followed the Knave of Hearts, carrying the\r
+King's crown on a crimson velvet cushion; and, last of all this\r
+grand procession, came THE KING AND QUEEN OF HEARTS.\r
+\r
+  Alice was rather doubtful whether she ought not to lie down on\r
+her face like the three gardeners, but she could not remember\r
+every having heard of such a rule at processions; `and besides,\r
+what would be the use of a procession,' thought she, `if people\r
+had all to lie down upon their faces, so that they couldn't see\r
+it?'  So she stood still where she was, and waited.\r
+\r
+  When the procession came opposite to Alice, they all stopped\r
+and looked at her, and the Queen said severely `Who is this?'\r
+She said it to the Knave of Hearts, who only bowed and smiled in\r
+reply.\r
+\r
+  `Idiot!' said the Queen, tossing her head impatiently; and,\r
+turning to Alice, she went on, `What's your name, child?'\r
+\r
+  `My name is Alice, so please your Majesty,' said Alice very\r
+politely; but she added, to herself, `Why, they're only a pack of\r
+cards, after all.  I needn't be afraid of them!'\r
+\r
+  `And who are THESE?' said the Queen, pointing to the three\r
+gardeners who were lying round the rosetree; for, you see, as\r
+they were lying on their faces, and the pattern on their backs\r
+was the same as the rest of the pack, she could not tell whether\r
+they were gardeners, or soldiers, or courtiers, or three of her\r
+own children.\r
+\r
+  `How should I know?' said Alice, surprised at her own courage.\r
+`It's no business of MINE.'\r
+\r
+  The Queen turned crimson with fury, and, after glaring at her\r
+for a moment like a wild beast, screamed `Off with her head!\r
+Off--'\r
+\r
+  `Nonsense!' said Alice, very loudly and decidedly, and the\r
+Queen was silent.\r
+\r
+  The King laid his hand upon her arm, and timidly said\r
+`Consider, my dear:  she is only a child!'\r
+\r
+  The Queen turned angrily away from him, and said to the Knave\r
+`Turn them over!'\r
+\r
+  The Knave did so, very carefully, with one foot.\r
+\r
+  `Get up!' said the Queen, in a shrill, loud voice, and the\r
+three gardeners instantly jumped up, and began bowing to the\r
+King, the Queen, the royal children, and everybody else.\r
+\r
+  `Leave off that!' screamed the Queen.  `You make me giddy.'\r
+And then, turning to the rose-tree, she went on, `What HAVE you\r
+been doing here?'\r
+\r
+  `May it please your Majesty,' said Two, in a very humble tone,\r
+going down on one knee as he spoke, `we were trying--'\r
+\r
+  `I see!' said the Queen, who had meanwhile been examining the\r
+roses.  `Off with their heads!' and the procession moved on,\r
+three of the soldiers remaining behind to execute the unfortunate\r
+gardeners, who ran to Alice for protection.\r
+\r
+  `You shan't be beheaded!' said Alice, and she put them into a\r
+large flower-pot that stood near.  The three soldiers wandered\r
+about for a minute or two, looking for them, and then quietly\r
+marched off after the others.\r
+\r
+  `Are their heads off?' shouted the Queen.\r
+\r
+  `Their heads are gone, if it please your Majesty!' the soldiers\r
+shouted in reply.\r
+\r
+  `That's right!' shouted the Queen.  `Can you play croquet?'\r
+\r
+  The soldiers were silent, and looked at Alice, as the question\r
+was evidently meant for her.\r
+\r
+  `Yes!' shouted Alice.\r
+\r
+  `Come on, then!' roared the Queen, and Alice joined the\r
+procession, wondering very much what would happen next.\r
+\r
+  `It's--it's a very fine day!' said a timid voice at her side.\r
+She was walking by the White Rabbit, who was peeping anxiously\r
+into her face.\r
+\r
+  `Very,' said Alice:  `--where's the Duchess?'\r
+\r
+  `Hush!  Hush!' said the Rabbit in a low, hurried tone.  He\r
+looked anxiously over his shoulder as he spoke, and then raised\r
+himself upon tiptoe, put his mouth close to her ear, and\r
+whispered `She's under sentence of execution.'\r
+\r
+  `What for?' said Alice.\r
+\r
+  `Did you say "What a pity!"?' the Rabbit asked.\r
+\r
+  `No, I didn't,' said Alice:  `I don't think it's at all a pity.\r
+I said "What for?"'\r
+\r
+  `She boxed the Queen's ears--' the Rabbit began.  Alice gave a\r
+little scream of laughter.  `Oh, hush!' the Rabbit whispered in a\r
+frightened tone.  `The Queen will hear you!  You see, she came\r
+rather late, and the Queen said--'\r
+\r
+  `Get to your places!' shouted the Queen in a voice of thunder,\r
+and people began running about in all directions, tumbling up\r
+against each other; however, they got settled down in a minute or\r
+two, and the game began.  Alice thought she had never seen such a\r
+curious croquet-ground in her life; it was all ridges and\r
+furrows; the balls were live hedgehogs, the mallets live\r
+flamingoes, and the soldiers had to double themselves up and to\r
+stand on their hands and feet, to make the arches.\r
+\r
+  The chief difficulty Alice found at first was in managing her\r
+flamingo:  she succeeded in getting its body tucked away,\r
+comfortably enough, under her arm, with its legs hanging down,\r
+but generally, just as she had got its neck nicely straightened\r
+out, and was going to give the hedgehog a blow with its head, it\r
+WOULD twist itself round and look up in her face, with such a\r
+puzzled expression that she could not help bursting out laughing:\r
+and when she had got its head down, and was going to begin again,\r
+it was very provoking to find that the hedgehog had unrolled\r
+itself, and was in the act of crawling away:  besides all this,\r
+there was generally a ridge or furrow in the way wherever she\r
+wanted to send the hedgehog to, and, as the doubled-up soldiers\r
+were always getting up and walking off to other parts of the\r
+ground, Alice soon came to the conclusion that it was a very\r
+difficult game indeed.\r
+\r
+  The players all played at once without waiting for turns,\r
+quarrelling all the while, and fighting for the hedgehogs; and in\r
+a very short time the Queen was in a furious passion, and went\r
+stamping about, and shouting `Off with his head!' or `Off with\r
+her head!' about once in a minute.\r
+\r
+  Alice began to feel very uneasy:  to be sure, she had not as\r
+yet had any dispute with the Queen, but she knew that it might\r
+happen any minute, `and then,' thought she, `what would become of\r
+me?  They're dreadfully fond of beheading people here; the great\r
+wonder is, that there's any one left alive!'\r
+\r
+  She was looking about for some way of escape, and wondering\r
+whether she could get away without being seen, when she noticed a\r
+curious appearance in the air:  it puzzled her very much at\r
+first, but, after watching it a minute or two, she made it out to\r
+be a grin, and she said to herself `It's the Cheshire Cat:  now I\r
+shall have somebody to talk to.'\r
+\r
+  `How are you getting on?' said the Cat, as soon as there was\r
+mouth enough for it to speak with.\r
+\r
+  Alice waited till the eyes appeared, and then nodded.  `It's no\r
+use speaking to it,' she thought, `till its ears have come, or at\r
+least one of them.'  In another minute the whole head appeared,\r
+and then Alice put down her flamingo, and began an account of the\r
+game, feeling very glad she had someone to listen to her.  The\r
+Cat seemed to think that there was enough of it now in sight, and\r
+no more of it appeared.\r
+\r
+  `I don't think they play at all fairly,' Alice began, in rather\r
+a complaining tone, `and they all quarrel so dreadfully one can't\r
+hear oneself speak--and they don't seem to have any rules in\r
+particular; at least, if there are, nobody attends to them--and\r
+you've no idea how confusing it is all the things being alive;\r
+for instance, there's the arch I've got to go through next\r
+walking about at the other end of the ground--and I should have\r
+croqueted the Queen's hedgehog just now, only it ran away when it\r
+saw mine coming!'\r
+\r
+  `How do you like the Queen?' said the Cat in a low voice.\r
+\r
+  `Not at all,' said Alice:  `she's so extremely--'  Just then\r
+she noticed that the Queen was close behind her, listening:  so\r
+she went on, `--likely to win, that it's hardly worth while\r
+finishing the game.'\r
+\r
+  The Queen smiled and passed on.\r
+\r
+  `Who ARE you talking to?' said the King, going up to Alice, and\r
+looking at the Cat's head with great curiosity.\r
+\r
+  `It's a friend of mine--a Cheshire Cat,' said Alice:  `allow me\r
+to introduce it.'\r
+\r
+  `I don't like the look of it at all,' said the King:  `however,\r
+it may kiss my hand if it likes.'\r
+\r
+  `I'd rather not,' the Cat remarked.\r
+\r
+  `Don't be impertinent,' said the King, `and don't look at me\r
+like that!'  He got behind Alice as he spoke.\r
+\r
+  `A cat may look at a king,' said Alice.  `I've read that in\r
+some book, but I don't remember where.'\r
+\r
+  `Well, it must be removed,' said the King very decidedly, and\r
+he called the Queen, who was passing at the moment, `My dear!  I\r
+wish you would have this cat removed!'\r
+\r
+  The Queen had only one way of settling all difficulties, great\r
+or small.  `Off with his head!' she said, without even looking\r
+round.\r
+\r
+  `I'll fetch the executioner myself,' said the King eagerly, and\r
+he hurried off.\r
+\r
+  Alice thought she might as well go back, and see how the game\r
+was going on, as she heard the Queen's voice in the distance,\r
+screaming with passion.  She had already heard her sentence three\r
+of the players to be executed for having missed their turns, and\r
+she did not like the look of things at all, as the game was in\r
+such confusion that she never knew whether it was her turn or\r
+not.  So she went in search of her hedgehog.\r
+\r
+  The hedgehog was engaged in a fight with another hedgehog,\r
+which seemed to Alice an excellent opportunity for croqueting one\r
+of them with the other:  the only difficulty was, that her\r
+flamingo was gone across to the other side of the garden, where\r
+Alice could see it trying in a helpless sort of way to fly up\r
+into a tree.\r
+\r
+  By the time she had caught the flamingo and brought it back,\r
+the fight was over, and both the hedgehogs were out of sight:\r
+`but it doesn't matter much,' thought Alice, `as all the arches\r
+are gone from this side of the ground.'  So she tucked it away\r
+under her arm, that it might not escape again, and went back for\r
+a little more conversation with her friend.\r
+\r
+  When she got back to the Cheshire Cat, she was surprised to\r
+find quite a large crowd collected round it:  there was a dispute\r
+going on between the executioner, the King, and the Queen, who\r
+were all talking at once, while all the rest were quite silent,\r
+and looked very uncomfortable.\r
+\r
+  The moment Alice appeared, she was appealed to by all three to\r
+settle the question, and they repeated their arguments to her,\r
+though, as they all spoke at once, she found it very hard indeed\r
+to make out exactly what they said.\r
+\r
+  The executioner's argument was, that you couldn't cut off a\r
+head unless there was a body to cut it off from:  that he had\r
+never had to do such a thing before, and he wasn't going to begin\r
+at HIS time of life.\r
+\r
+  The King's argument was, that anything that had a head could be\r
+beheaded, and that you weren't to talk nonsense.\r
+\r
+  The Queen's argument was, that if something wasn't done about\r
+it in less than no time she'd have everybody executed, all round.\r
+(It was this last remark that had made the whole party look so\r
+grave and anxious.)\r
+\r
+  Alice could think of nothing else to say but `It belongs to the\r
+Duchess:  you'd better ask HER about it.'\r
+\r
+  `She's in prison,' the Queen said to the executioner:  `fetch\r
+her here.'  And the executioner went off like an arrow.\r
+\r
+   The Cat's head began fading away the moment he was gone, and,\r
+by the time he had come back with the Dutchess, it had entirely\r
+disappeared; so the King and the executioner ran wildly up and\r
+down looking for it, while the rest of the party went back to the game.\r
+\r
+\r
+\r
+                           CHAPTER IX\r
+\r
+                     The Mock Turtle's Story\r
+\r
+\r
+  `You can't think how glad I am to see you again, you dear old\r
+thing!' said the Duchess, as she tucked her arm affectionately\r
+into Alice's, and they walked off together.\r
+\r
+  Alice was very glad to find her in such a pleasant temper, and\r
+thought to herself that perhaps it was only the pepper that had\r
+made her so savage when they met in the kitchen.\r
+\r
+  `When I'M a Duchess,' she said to herself, (not in a very\r
+hopeful tone though), `I won't have any pepper in my kitchen AT\r
+ALL.  Soup does very well without--Maybe it's always pepper that\r
+makes people hot-tempered,' she went on, very much pleased at\r
+having found out a new kind of rule, `and vinegar that makes them\r
+sour--and camomile that makes them bitter--and--and barley-sugar\r
+and such things that make children sweet-tempered.  I only wish\r
+people knew that:  then they wouldn't be so stingy about it, you\r
+know--'\r
+\r
+  She had quite forgotten the Duchess by this time, and was a\r
+little startled when she heard her voice close to her ear.\r
+`You're thinking about something, my dear, and that makes you\r
+forget to talk.  I can't tell you just now what the moral of that\r
+is, but I shall remember it in a bit.'\r
+\r
+  `Perhaps it hasn't one,' Alice ventured to remark.\r
+\r
+  `Tut, tut, child!' said the Duchess.  `Everything's got a\r
+moral, if only you can find it.'  And she squeezed herself up\r
+closer to Alice's side as she spoke.\r
+\r
+  Alice did not much like keeping so close to her:  first,\r
+because the Duchess was VERY ugly; and secondly, because she was\r
+exactly the right height to rest her chin upon Alice's shoulder,\r
+and it was an uncomfortably sharp chin.  However, she did not\r
+like to be rude, so she bore it as well as she could.\r
+\r
+  `The game's going on rather better now,' she said, by way of\r
+keeping up the conversation a little.\r
+\r
+  `'Tis so,' said the Duchess:  `and the moral of that is--"Oh,\r
+'tis love, 'tis love, that makes the world go round!"'\r
+\r
+  `Somebody said,' Alice whispered, `that it's done by everybody\r
+minding their own business!'\r
+\r
+  `Ah, well!  It means much the same thing,' said the Duchess,\r
+digging her sharp little chin into Alice's shoulder as she added,\r
+`and the moral of THAT is--"Take care of the sense, and the\r
+sounds will take care of themselves."'\r
+\r
+  `How fond she is of finding morals in things!' Alice thought to\r
+herself.\r
+\r
+  `I dare say you're wondering why I don't put my arm round your\r
+waist,' the Duchess said after a pause:  `the reason is, that I'm\r
+doubtful about the temper of your flamingo.  Shall I try the\r
+experiment?'\r
+\r
+  `HE might bite,' Alice cautiously replied, not feeling at all\r
+anxious to have the experiment tried.\r
+\r
+  `Very true,' said the Duchess:  `flamingoes and mustard both\r
+bite.  And the moral of that is--"Birds of a feather flock\r
+together."'\r
+\r
+  `Only mustard isn't a bird,' Alice remarked.\r
+\r
+  `Right, as usual,' said the Duchess:  `what a clear way you\r
+have of putting things!'\r
+\r
+  `It's a mineral, I THINK,' said Alice.\r
+\r
+  `Of course it is,' said the Duchess, who seemed ready to agree\r
+to everything that Alice said; `there's a large mustard-mine near\r
+here.  And the moral of that is--"The more there is of mine, the\r
+less there is of yours."'\r
+\r
+  `Oh, I know!' exclaimed Alice, who had not attended to this\r
+last remark, `it's a vegetable.  It doesn't look like one, but it\r
+is.'\r
+\r
+  `I quite agree with you,' said the Duchess; `and the moral of\r
+that is--"Be what you would seem to be"--or if you'd like it put\r
+more simply--"Never imagine yourself not to be otherwise than\r
+what it might appear to others that what you were or might have\r
+been was not otherwise than what you had been would have appeared\r
+to them to be otherwise."'\r
+\r
+  `I think I should understand that better,' Alice said very\r
+politely, `if I had it written down:  but I can't quite follow it\r
+as you say it.'\r
+\r
+  `That's nothing to what I could say if I chose,' the Duchess\r
+replied, in a pleased tone.\r
+\r
+  `Pray don't trouble yourself to say it any longer than that,'\r
+said Alice.\r
+\r
+  `Oh, don't talk about trouble!' said the Duchess.  `I make you\r
+a present of everything I've said as yet.'\r
+\r
+  `A cheap sort of present!' thought Alice.  `I'm glad they don't\r
+give birthday presents like that!'  But she did not venture to\r
+say it out loud.\r
+\r
+  `Thinking again?' the Duchess asked, with another dig of her\r
+sharp little chin.\r
+\r
+  `I've a right to think,' said Alice sharply, for she was\r
+beginning to feel a little worried.\r
+\r
+  `Just about as much right,' said the Duchess, `as pigs have to\r
+fly; and the m--'\r
+\r
+  But here, to Alice's great surprise, the Duchess's voice died\r
+away, even in the middle of her favourite word `moral,' and the\r
+arm that was linked into hers began to tremble.  Alice looked up,\r
+and there stood the Queen in front of them, with her arms folded,\r
+frowning like a thunderstorm.\r
+\r
+  `A fine day, your Majesty!' the Duchess began in a low, weak\r
+voice.\r
+\r
+  `Now, I give you fair warning,' shouted the Queen, stamping on\r
+the ground as she spoke; `either you or your head must be off,\r
+and that in about half no time!  Take your choice!'\r
+\r
+  The Duchess took her choice, and was gone in a moment.\r
+\r
+  `Let's go on with the game,' the Queen said to Alice; and Alice\r
+was too much frightened to say a word, but slowly followed her\r
+back to the croquet-ground.\r
+\r
+  The other guests had taken advantage of the Queen's absence,\r
+and were resting in the shade:  however, the moment they saw her,\r
+they hurried back to the game, the Queen merely remarking that a\r
+moment's delay would cost them their lives.\r
+\r
+  All the time they were playing the Queen never left off\r
+quarrelling with the other players, and shouting `Off with his\r
+head!' or `Off with her head!'  Those whom she sentenced were\r
+taken into custody by the soldiers, who of course had to leave\r
+off being arches to do this, so that by the end of half an hour\r
+or so there were no arches left, and all the players, except the\r
+King, the Queen, and Alice, were in custody and under sentence of\r
+execution.\r
+\r
+  Then the Queen left off, quite out of breath, and said to\r
+Alice, `Have you seen the Mock Turtle yet?'\r
+\r
+  `No,' said Alice.  `I don't even know what a Mock Turtle is.'\r
+\r
+  `It's the thing Mock Turtle Soup is made from,' said the Queen.\r
+\r
+  `I never saw one, or heard of one,' said Alice.\r
+\r
+  `Come on, then,' said the Queen, `and he shall tell you his\r
+history,'\r
+\r
+  As they walked off together, Alice heard the King say in a low\r
+voice, to the company generally, `You are all pardoned.'  `Come,\r
+THAT'S a good thing!' she said to herself, for she had felt quite\r
+unhappy at the number of executions the Queen had ordered.\r
+\r
+  They very soon came upon a Gryphon, lying fast asleep in the\r
+sun.  (IF you don't know what a Gryphon is, look at the picture.)\r
+`Up, lazy thing!' said the Queen, `and take this young lady to\r
+see the Mock Turtle, and to hear his history.  I must go back and\r
+see after some executions I have ordered'; and she walked off,\r
+leaving Alice alone with the Gryphon.  Alice did not quite like\r
+the look of the creature, but on the whole she thought it would\r
+be quite as safe to stay with it as to go after that savage\r
+Queen:  so she waited.\r
+\r
+  The Gryphon sat up and rubbed its eyes:  then it watched the\r
+Queen till she was out of sight:  then it chuckled.  `What fun!'\r
+said the Gryphon, half to itself, half to Alice.\r
+\r
+  `What IS the fun?' said Alice.\r
+\r
+  `Why, SHE,' said the Gryphon.  `It's all her fancy, that:  they\r
+never executes nobody, you know.  Come on!'\r
+\r
+  `Everybody says "come on!" here,' thought Alice, as she went\r
+slowly after it:  `I never was so ordered about in all my life,\r
+never!'\r
+\r
+  They had not gone far before they saw the Mock Turtle in the\r
+distance, sitting sad and lonely on a little ledge of rock, and,\r
+as they came nearer, Alice could hear him sighing as if his heart\r
+would break.  She pitied him deeply.  `What is his sorrow?' she\r
+asked the Gryphon, and the Gryphon answered, very nearly in the\r
+same words as before, `It's all his fancy, that:  he hasn't got\r
+no sorrow, you know.  Come on!'\r
+\r
+  So they went up to the Mock Turtle, who looked at them with\r
+large eyes full of tears, but said nothing.\r
+\r
+  `This here young lady,' said the Gryphon, `she wants for to\r
+know your history, she do.'\r
+\r
+  `I'll tell it her,' said the Mock Turtle in a deep, hollow\r
+tone:  `sit down, both of you, and don't speak a word till I've\r
+finished.'\r
+\r
+  So they sat down, and nobody spoke for some minutes.  Alice\r
+thought to herself, `I don't see how he can EVEN finish, if he\r
+doesn't begin.'  But she waited patiently.\r
+\r
+  `Once,' said the Mock Turtle at last, with a deep sigh, `I was\r
+a real Turtle.'\r
+\r
+  These words were followed by a very long silence, broken only\r
+by an occasional exclamation of `Hjckrrh!' from the Gryphon, and\r
+the constant heavy sobbing of the Mock Turtle.  Alice was very\r
+nearly getting up and saying, `Thank you, sir, for your\r
+interesting story,' but she could not help thinking there MUST be\r
+more to come, so she sat still and said nothing.\r
+\r
+  `When we were little,' the Mock Turtle went on at last, more\r
+calmly, though still sobbing a little now and then, `we went to\r
+school in the sea.  The master was an old Turtle--we used to call\r
+him Tortoise--'\r
+\r
+  `Why did you call him Tortoise, if he wasn't one?' Alice asked.\r
+\r
+  `We called him Tortoise because he taught us,' said the Mock\r
+Turtle angrily:  `really you are very dull!'\r
+\r
+  `You ought to be ashamed of yourself for asking such a simple\r
+question,' added the Gryphon; and then they both sat silent and\r
+looked at poor Alice, who felt ready to sink into the earth.  At\r
+last the Gryphon said to the Mock Turtle, `Drive on, old fellow!\r
+Don't be all day about it!' and he went on in these words:\r
+\r
+  `Yes, we went to school in the sea, though you mayn't believe\r
+it--'\r
+\r
+  `I never said I didn't!' interrupted Alice.\r
+\r
+  `You did,' said the Mock Turtle.\r
+\r
+  `Hold your tongue!' added the Gryphon, before Alice could speak\r
+again.  The Mock Turtle went on.\r
+\r
+  `We had the best of educations--in fact, we went to school\r
+every day--'\r
+\r
+  `I'VE been to a day-school, too,' said Alice; `you needn't be\r
+so proud as all that.'\r
+\r
+  `With extras?' asked the Mock Turtle a little anxiously.\r
+\r
+  `Yes,' said Alice, `we learned French and music.'\r
+\r
+  `And washing?' said the Mock Turtle.\r
+\r
+  `Certainly not!' said Alice indignantly.\r
+\r
+  `Ah! then yours wasn't a really good school,' said the Mock\r
+Turtle in a tone of great relief.  `Now at OURS they had at the\r
+end of the bill, "French, music, AND WASHING--extra."'\r
+\r
+  `You couldn't have wanted it much,' said Alice; `living at the\r
+bottom of the sea.'\r
+\r
+  `I couldn't afford to learn it.' said the Mock Turtle with a\r
+sigh.  `I only took the regular course.'\r
+\r
+  `What was that?' inquired Alice.\r
+\r
+  `Reeling and Writhing, of course, to begin with,' the Mock\r
+Turtle replied; `and then the different branches of Arithmetic--\r
+Ambition, Distraction, Uglification, and Derision.'\r
+\r
+  `I never heard of "Uglification,"' Alice ventured to say.  `What\r
+is it?'\r
+\r
+  The Gryphon lifted up both its paws in surprise.  `What!  Never\r
+heard of uglifying!' it exclaimed.  `You know what to beautify\r
+is, I suppose?'\r
+\r
+  `Yes,' said Alice doubtfully:  `it means--to--make--anything--\r
+prettier.'\r
+\r
+  `Well, then,' the Gryphon went on, `if you don't know what to\r
+uglify is, you ARE a simpleton.'\r
+\r
+  Alice did not feel encouraged to ask any more questions about\r
+it, so she turned to the Mock Turtle, and said `What else had you\r
+to learn?'\r
+\r
+  `Well, there was Mystery,' the Mock Turtle replied, counting\r
+off the subjects on his flappers, `--Mystery, ancient and modern,\r
+with Seaography:  then Drawling--the Drawling-master was an old\r
+conger-eel, that used to come once a week:  HE taught us\r
+Drawling, Stretching, and Fainting in Coils.'\r
+\r
+  `What was THAT like?' said Alice.\r
+\r
+  `Well, I can't show it you myself,' the Mock Turtle said:  `I'm\r
+too stiff.  And the Gryphon never learnt it.'\r
+\r
+  `Hadn't time,' said the Gryphon:  `I went to the Classics\r
+master, though.  He was an old crab, HE was.'\r
+\r
+  `I never went to him,' the Mock Turtle said with a sigh:  `he\r
+taught Laughing and Grief, they used to say.'\r
+\r
+  `So he did, so he did,' said the Gryphon, sighing in his turn;\r
+and both creatures hid their faces in their paws.\r
+\r
+  `And how many hours a day did you do lessons?' said Alice, in a\r
+hurry to change the subject.\r
+\r
+  `Ten hours the first day,' said the Mock Turtle: `nine the\r
+next, and so on.'\r
+\r
+  `What a curious plan!' exclaimed Alice.\r
+\r
+  `That's the reason they're called lessons,' the Gryphon\r
+remarked:  `because they lessen from day to day.'\r
+\r
+  This was quite a new idea to Alice, and she thought it over a\r
+little before she made her next remark.  `Then the eleventh day\r
+must have been a holiday?'\r
+\r
+  `Of course it was,' said the Mock Turtle.\r
+\r
+  `And how did you manage on the twelfth?' Alice went on eagerly.\r
+\r
+  `That's enough about lessons,' the Gryphon interrupted in a\r
+very decided tone:  `tell her something about the games now.'\r
+\r
+\r
+\r
+                            CHAPTER X\r
+\r
+                      The Lobster Quadrille\r
+\r
+\r
+  The Mock Turtle sighed deeply, and drew the back of one flapper\r
+across his eyes.  He looked at Alice, and tried to speak, but for\r
+a minute or two sobs choked his voice.  `Same as if he had a bone\r
+in his throat,' said the Gryphon:  and it set to work shaking him\r
+and punching him in the back.  At last the Mock Turtle recovered\r
+his voice, and, with tears running down his cheeks, he went on\r
+again:--\r
+\r
+  `You may not have lived much under the sea--' (`I haven't,'\r
+said Alice)--`and perhaps you were never even introduced to a lobster--'\r
+(Alice began to say `I once tasted--' but checked herself hastily,\r
+and said `No, never') `--so you can have no idea what a delightful\r
+thing a Lobster Quadrille is!'\r
+\r
+  `No, indeed,' said Alice.  `What sort of a dance is it?'\r
+\r
+  `Why,' said the Gryphon, `you first form into a line along the\r
+sea-shore--'\r
+\r
+  `Two lines!' cried the Mock Turtle.  `Seals, turtles, salmon,\r
+and so on; then, when you've cleared all the jelly-fish out of\r
+the way--'\r
+\r
+  `THAT generally takes some time,' interrupted the Gryphon.\r
+\r
+  `--you advance twice--'\r
+\r
+  `Each with a lobster as a partner!' cried the Gryphon.\r
+\r
+  `Of course,' the Mock Turtle said:  `advance twice, set to\r
+partners--'\r
+\r
+  `--change lobsters, and retire in same order,' continued the\r
+Gryphon.\r
+\r
+  `Then, you know,' the Mock Turtle went on, `you throw the--'\r
+\r
+  `The lobsters!' shouted the Gryphon, with a bound into the air.\r
+\r
+  `--as far out to sea as you can--'\r
+\r
+  `Swim after them!' screamed the Gryphon.\r
+\r
+  `Turn a somersault in the sea!' cried the Mock Turtle,\r
+capering wildly about.\r
+\r
+  `Back to land again, and that's all the first figure,' said the\r
+Mock Turtle, suddenly dropping his voice; and the two creatures,\r
+who had been jumping about like mad things all this time, sat\r
+down again very sadly and quietly, and looked at Alice.\r
+\r
+  `It must be a very pretty dance,' said Alice timidly.\r
+\r
+  `Would you like to see a little of it?' said the Mock Turtle.\r
+\r
+  `Very much indeed,' said Alice.\r
+\r
+  `Come, let's try the first figure!' said the Mock Turtle to the\r
+Gryphon.  `We can do without lobsters, you know.  Which shall\r
+sing?'\r
+\r
+  `Oh, YOU sing,' said the Gryphon.  `I've forgotten the words.'\r
+\r
+  So they began solemnly dancing round and round Alice, every now\r
+and then treading on her toes when they passed too close, and\r
+waving their forepaws to mark the time, while the Mock Turtle\r
+sang this, very slowly and sadly:--\r
+\r
+\r
+`"Will you walk a little faster?" said a whiting to a snail.\r
+"There's a porpoise close behind us, and he's treading on my\r
+ tail.\r
+See how eagerly the lobsters and the turtles all advance!\r
+They are waiting on the shingle--will you come and join the\r
+dance?\r
+\r
+Will you, won't you, will you, won't you, will you join the\r
+dance?\r
+Will you, won't you, will you, won't you, won't you join the\r
+dance?\r
+\r
+\r
+"You can really have no notion how delightful it will be\r
+When they take us up and throw us, with the lobsters, out to\r
+                                                      sea!"\r
+But the snail replied "Too far, too far!" and gave a look\r
+                                                       askance--\r
+Said he thanked the whiting kindly, but he would not join the\r
+   dance.\r
+    Would not, could not, would not, could not, would not join\r
+        the dance.\r
+    Would not, could not, would not, could not, could not join\r
+        the dance.\r
+\r
+`"What matters it how far we go?" his scaly friend replied.\r
+"There is another shore, you know, upon the other side.\r
+The further off from England the nearer is to France--\r
+Then turn not pale, beloved snail, but come and join the dance.\r
+\r
+    Will you, won't you, will you, won't you, will you join the\r
+         dance?\r
+    Will you, won't you, will you, won't you, won't you join the\r
+         dance?"'\r
+\r
+\r
+\r
+  `Thank you, it's a very interesting dance to watch,' said\r
+Alice, feeling very glad that it was over at last:  `and I do so\r
+like that curious song about the whiting!'\r
+\r
+  `Oh, as to the whiting,' said the Mock Turtle, `they--you've\r
+seen them, of course?'\r
+\r
+  `Yes,' said Alice, `I've often seen them at dinn--' she\r
+checked herself hastily.\r
+\r
+  `I don't know where Dinn may be,' said the Mock Turtle, `but\r
+if you've seen them so often, of course you know what they're\r
+like.'\r
+\r
+  `I believe so,' Alice replied thoughtfully.  `They have their\r
+tails in their mouths--and they're all over crumbs.'\r
+\r
+  `You're wrong about the crumbs,' said the Mock Turtle:\r
+`crumbs would all wash off in the sea.  But they HAVE their tails\r
+in their mouths; and the reason is--' here the Mock Turtle\r
+yawned and shut his eyes.--`Tell her about the reason and all\r
+that,' he said to the Gryphon.\r
+\r
+  `The reason is,' said the Gryphon, `that they WOULD go with\r
+the lobsters to the dance.  So they got thrown out to sea.  So\r
+they had to fall a long way.  So they got their tails fast in\r
+their mouths.  So they couldn't get them out again.  That's all.'\r
+\r
+  `Thank you,' said Alice, `it's very interesting.  I never knew\r
+so much about a whiting before.'\r
+\r
+  `I can tell you more than that, if you like,' said the\r
+Gryphon.  `Do you know why it's called a whiting?'\r
+\r
+  `I never thought about it,' said Alice.  `Why?'\r
+\r
+  `IT DOES THE BOOTS AND SHOES.' the Gryphon replied very\r
+solemnly.\r
+\r
+  Alice was thoroughly puzzled.  `Does the boots and shoes!' she\r
+repeated in a wondering tone.\r
+\r
+  `Why, what are YOUR shoes done with?' said the Gryphon.  `I\r
+mean, what makes them so shiny?'\r
+\r
+  Alice looked down at them, and considered a little before she\r
+gave her answer.  `They're done with blacking, I believe.'\r
+\r
+  `Boots and shoes under the sea,' the Gryphon went on in a deep\r
+voice, `are done with a whiting.  Now you know.'\r
+\r
+  `And what are they made of?' Alice asked in a tone of great\r
+curiosity.\r
+\r
+  `Soles and eels, of course,' the Gryphon replied rather\r
+impatiently:  `any shrimp could have told you that.'\r
+\r
+  `If I'd been the whiting,' said Alice, whose thoughts were\r
+still running on the song, `I'd have said to the porpoise, "Keep\r
+back, please:  we don't want YOU with us!"'\r
+\r
+  `They were obliged to have him with them,' the Mock Turtle\r
+said:  `no wise fish would go anywhere without a porpoise.'\r
+\r
+  `Wouldn't it really?' said Alice in a tone of great surprise.\r
+\r
+  `Of course not,' said the Mock Turtle:  `why, if a fish came\r
+to ME, and told me he was going a journey, I should say "With\r
+what porpoise?"'\r
+\r
+  `Don't you mean "purpose"?' said Alice.\r
+\r
+  `I mean what I say,' the Mock Turtle replied in an offended\r
+tone.  And the Gryphon added `Come, let's hear some of YOUR\r
+adventures.'\r
+\r
+  `I could tell you my adventures--beginning from this morning,'\r
+said Alice a little timidly:  `but it's no use going back to\r
+yesterday, because I was a different person then.'\r
+\r
+  `Explain all that,' said the Mock Turtle.\r
+\r
+  `No, no!  The adventures first,' said the Gryphon in an\r
+impatient tone:  `explanations take such a dreadful time.'\r
+\r
+  So Alice began telling them her adventures from the time when\r
+she first saw the White Rabbit.  She was a little nervous about\r
+it just at first, the two creatures got so close to her, one on\r
+each side, and opened their eyes and mouths so VERY wide, but she\r
+gained courage as she went on.  Her listeners were perfectly\r
+quiet till she got to the part about her repeating `YOU ARE OLD,\r
+FATHER WILLIAM,' to the Caterpillar, and the words all coming\r
+different, and then the Mock Turtle drew a long breath, and said\r
+`That's very curious.'\r
+\r
+  `It's all about as curious as it can be,' said the Gryphon.\r
+\r
+  `It all came different!' the Mock Turtle repeated\r
+thoughtfully.  `I should like to hear her try and repeat\r
+something now.  Tell her to begin.'  He looked at the Gryphon as\r
+if he thought it had some kind of authority over Alice.\r
+\r
+  `Stand up and repeat "'TIS THE VOICE OF THE SLUGGARD,"' said\r
+the Gryphon.\r
+\r
+  `How the creatures order one about, and make one repeat\r
+lessons!' thought Alice; `I might as well be at school at once.'\r
+However, she got up, and began to repeat it, but her head was so\r
+full of the Lobster Quadrille, that she hardly knew what she was\r
+saying, and the words came very queer indeed:--\r
+\r
+    `'Tis the voice of the Lobster; I heard him declare,\r
+    "You have baked me too brown, I must sugar my hair."\r
+    As a duck with its eyelids, so he with his nose\r
+    Trims his belt and his buttons, and turns out his toes.'\r
+\r
+              [later editions continued as follows\r
+    When the sands are all dry, he is gay as a lark,\r
+    And will talk in contemptuous tones of the Shark,\r
+    But, when the tide rises and sharks are around,\r
+    His voice has a timid and tremulous sound.]\r
+\r
+  `That's different from what I used to say when I was a child,'\r
+said the Gryphon.\r
+\r
+  `Well, I never heard it before,' said the Mock Turtle; `but it\r
+sounds uncommon nonsense.'\r
+\r
+  Alice said nothing; she had sat down with her face in her\r
+hands, wondering if anything would EVER happen in a natural way\r
+again.\r
+\r
+  `I should like to have it explained,' said the Mock Turtle.\r
+\r
+  `She can't explain it,' said the Gryphon hastily.  `Go on with\r
+the next verse.'\r
+\r
+  `But about his toes?' the Mock Turtle persisted.  `How COULD\r
+he turn them out with his nose, you know?'\r
+\r
+  `It's the first position in dancing.' Alice said; but was\r
+dreadfully puzzled by the whole thing, and longed to change the\r
+subject.\r
+\r
+  `Go on with the next verse,' the Gryphon repeated impatiently:\r
+`it begins "I passed by his garden."'\r
+\r
+  Alice did not dare to disobey, though she felt sure it would\r
+all come wrong, and she went on in a trembling voice:--\r
+\r
+    `I passed by his garden, and marked, with one eye,\r
+    How the Owl and the Panther were sharing a pie--'\r
+\r
+        [later editions continued as follows\r
+    The Panther took pie-crust, and gravy, and meat,\r
+    While the Owl had the dish as its share of the treat.\r
+    When the pie was all finished, the Owl, as a boon,\r
+    Was kindly permitted to pocket the spoon:\r
+    While the Panther received knife and fork with a growl,\r
+    And concluded the banquet--]\r
+\r
+  `What IS the use of repeating all that stuff,' the Mock Turtle\r
+interrupted, `if you don't explain it as you go on?  It's by far\r
+the most confusing thing I ever heard!'\r
+\r
+  `Yes, I think you'd better leave off,' said the Gryphon:  and\r
+Alice was only too glad to do so.\r
+\r
+  `Shall we try another figure of the Lobster Quadrille?' the\r
+Gryphon went on.  `Or would you like the Mock Turtle to sing you\r
+a song?'\r
+\r
+  `Oh, a song, please, if the Mock Turtle would be so kind,'\r
+Alice replied, so eagerly that the Gryphon said, in a rather\r
+offended tone, `Hm! No accounting for tastes!  Sing her "Turtle\r
+Soup," will you, old fellow?'\r
+\r
+  The Mock Turtle sighed deeply, and began, in a voice sometimes\r
+choked with sobs, to sing this:--\r
+\r
+\r
+    `Beautiful Soup, so rich and green,\r
+    Waiting in a hot tureen!\r
+    Who for such dainties would not stoop?\r
+    Soup of the evening, beautiful Soup!\r
+    Soup of the evening, beautiful Soup!\r
+        Beau--ootiful Soo--oop!\r
+        Beau--ootiful Soo--oop!\r
+    Soo--oop of the e--e--evening,\r
+        Beautiful, beautiful Soup!\r
+\r
+    `Beautiful Soup!  Who cares for fish,\r
+    Game, or any other dish?\r
+    Who would not give all else for two p\r
+    ennyworth only of beautiful Soup?\r
+    Pennyworth only of beautiful Soup?\r
+        Beau--ootiful Soo--oop!\r
+        Beau--ootiful Soo--oop!\r
+    Soo--oop of the e--e--evening,\r
+        Beautiful, beauti--FUL SOUP!'\r
+\r
+  `Chorus again!' cried the Gryphon, and the Mock Turtle had\r
+just begun to repeat it, when a cry of `The trial's beginning!'\r
+was heard in the distance.\r
+\r
+  `Come on!' cried the Gryphon, and, taking Alice by the hand,\r
+it hurried off, without waiting for the end of the song.\r
+\r
+  `What trial is it?' Alice panted as she ran; but the Gryphon\r
+only answered `Come on!' and ran the faster, while more and more\r
+faintly came, carried on the breeze that followed them, the\r
+melancholy words:--\r
+\r
+    `Soo--oop of the e--e--evening,\r
+        Beautiful, beautiful Soup!'\r
+\r
+\r
+\r
+                           CHAPTER XI\r
+\r
+                      Who Stole the Tarts?\r
+\r
+\r
+  The King and Queen of Hearts were seated on their throne when\r
+they arrived, with a great crowd assembled about them--all sorts\r
+of little birds and beasts, as well as the whole pack of cards:\r
+the Knave was standing before them, in chains, with a soldier on\r
+each side to guard him; and near the King was the White Rabbit,\r
+with a trumpet in one hand, and a scroll of parchment in the\r
+other.  In the very middle of the court was a table, with a large\r
+dish of tarts upon it:  they looked so good, that it made Alice\r
+quite hungry to look at them--`I wish they'd get the trial done,'\r
+she thought, `and hand round the refreshments!'  But there seemed\r
+to be no chance of this, so she began looking at everything about\r
+her, to pass away the time.\r
+\r
+  Alice had never been in a court of justice before, but she had\r
+read about them in books, and she was quite pleased to find that\r
+she knew the name of nearly everything there.  `That's the\r
+judge,' she said to herself, `because of his great wig.'\r
+\r
+  The judge, by the way, was the King; and as he wore his crown\r
+over the wig, (look at the frontispiece if you want to see how he\r
+did it,) he did not look at all comfortable, and it was certainly\r
+not becoming.\r
+\r
+  `And that's the jury-box,' thought Alice, `and those twelve\r
+creatures,' (she was obliged to say `creatures,' you see, because\r
+some of them were animals, and some were birds,) `I suppose they\r
+are the jurors.'  She said this last word two or three times over\r
+to herself, being rather proud of it:  for she thought, and\r
+rightly too, that very few little girls of her age knew the\r
+meaning of it at all.  However, `jury-men' would have done just\r
+as well.\r
+\r
+  The twelve jurors were all writing very busily on slates.\r
+`What are they doing?'  Alice whispered to the Gryphon.  `They\r
+can't have anything to put down yet, before the trial's begun.'\r
+\r
+  `They're putting down their names,' the Gryphon whispered in\r
+reply, `for fear they should forget them before the end of the\r
+trial.'\r
+\r
+  `Stupid things!' Alice began in a loud, indignant voice, but\r
+she stopped hastily, for the White Rabbit cried out, `Silence in\r
+the court!' and the King put on his spectacles and looked\r
+anxiously round, to make out who was talking.\r
+\r
+  Alice could see, as well as if she were looking over their\r
+shoulders, that all the jurors were writing down `stupid things!'\r
+on their slates, and she could even make out that one of them\r
+didn't know how to spell `stupid,' and that he had to ask his\r
+neighbour to tell him.  `A nice muddle their slates'll be in\r
+before the trial's over!' thought Alice.\r
+\r
+  One of the jurors had a pencil that squeaked.  This of course,\r
+Alice could not stand, and she went round the court and got\r
+behind him, and very soon found an opportunity of taking it\r
+away.  She did it so quickly that the poor little juror (it was\r
+Bill, the Lizard) could not make out at all what had become of\r
+it; so, after hunting all about for it, he was obliged to write\r
+with one finger for the rest of the day; and this was of very\r
+little use, as it left no mark on the slate.\r
+\r
+  `Herald, read the accusation!' said the King.\r
+\r
+  On this the White Rabbit blew three blasts on the trumpet, and\r
+then unrolled the parchment scroll, and read as follows:--\r
+\r
+    `The Queen of Hearts, she made some tarts,\r
+          All on a summer day:\r
+      The Knave of Hearts, he stole those tarts,\r
+          And took them quite away!'\r
+\r
+  `Consider your verdict,' the King said to the jury.\r
+\r
+  `Not yet, not yet!' the Rabbit hastily interrupted.  `There's\r
+a great deal to come before that!'\r
+\r
+  `Call the first witness,' said the King; and the White Rabbit\r
+blew three blasts on the trumpet, and called out, `First\r
+witness!'\r
+\r
+  The first witness was the Hatter.  He came in with a teacup in\r
+one hand and a piece of bread-and-butter in the other.  `I beg\r
+pardon, your Majesty,' he began, `for bringing these in:  but I\r
+hadn't quite finished my tea when I was sent for.'\r
+\r
+  `You ought to have finished,' said the King.  `When did you\r
+begin?'\r
+\r
+  The Hatter looked at the March Hare, who had followed him into\r
+the court, arm-in-arm with the Dormouse.  `Fourteenth of March, I\r
+think it was,' he said.\r
+\r
+  `Fifteenth,' said the March Hare.\r
+\r
+  `Sixteenth,' added the Dormouse.\r
+\r
+  `Write that down,' the King said to the jury, and the jury\r
+eagerly wrote down all three dates on their slates, and then\r
+added them up, and reduced the answer to shillings and pence.\r
+\r
+  `Take off your hat,' the King said to the Hatter.\r
+\r
+  `It isn't mine,' said the Hatter.\r
+\r
+  `Stolen!' the King exclaimed, turning to the jury, who\r
+instantly made a memorandum of the fact.\r
+\r
+  `I keep them to sell,' the Hatter added as an explanation;\r
+`I've none of my own.  I'm a hatter.'\r
+\r
+  Here the Queen put on her spectacles, and began staring at the\r
+Hatter, who turned pale and fidgeted.\r
+\r
+  `Give your evidence,' said the King; `and don't be nervous, or\r
+I'll have you executed on the spot.'\r
+\r
+  This did not seem to encourage the witness at all:  he kept\r
+shifting from one foot to the other, looking uneasily at the\r
+Queen, and in his confusion he bit a large piece out of his\r
+teacup instead of the bread-and-butter.\r
+\r
+  Just at this moment Alice felt a very curious sensation, which\r
+puzzled her a good deal until she made out what it was:  she was\r
+beginning to grow larger again, and she thought at first she\r
+would get up and leave the court; but on second thoughts she\r
+decided to remain where she was as long as there was room for\r
+her.\r
+\r
+  `I wish you wouldn't squeeze so.' said the Dormouse, who was\r
+sitting next to her.  `I can hardly breathe.'\r
+\r
+  `I can't help it,' said Alice very meekly:  `I'm growing.'\r
+\r
+  `You've no right to grow here,' said the Dormouse.\r
+\r
+  `Don't talk nonsense,' said Alice more boldly:  `you know\r
+you're growing too.'\r
+\r
+  `Yes, but I grow at a reasonable pace,' said the Dormouse:\r
+`not in that ridiculous fashion.'  And he got up very sulkily\r
+and crossed over to the other side of the court.\r
+\r
+  All this time the Queen had never left off staring at the\r
+Hatter, and, just as the Dormouse crossed the court, she said to\r
+one of the officers of the court, `Bring me the list of the\r
+singers in the last concert!' on which the wretched Hatter\r
+trembled so, that he shook both his shoes off.\r
+\r
+  `Give your evidence,' the King repeated angrily, `or I'll have\r
+you executed, whether you're nervous or not.'\r
+\r
+  `I'm a poor man, your Majesty,' the Hatter began, in a\r
+trembling voice, `--and I hadn't begun my tea--not above a week\r
+or so--and what with the bread-and-butter getting so thin--and\r
+the twinkling of the tea--'\r
+\r
+  `The twinkling of the what?' said the King.\r
+\r
+  `It began with the tea,' the Hatter replied.\r
+\r
+  `Of course twinkling begins with a T!' said the King sharply.\r
+`Do you take me for a dunce?  Go on!'\r
+\r
+  `I'm a poor man,' the Hatter went on, `and most things\r
+twinkled after that--only the March Hare said--'\r
+\r
+  `I didn't!' the March Hare interrupted in a great hurry.\r
+\r
+  `You did!' said the Hatter.\r
+\r
+  `I deny it!' said the March Hare.\r
+\r
+  `He denies it,' said the King:  `leave out that part.'\r
+\r
+  `Well, at any rate, the Dormouse said--' the Hatter went on,\r
+looking anxiously round to see if he would deny it too:  but the\r
+Dormouse denied nothing, being fast asleep.\r
+\r
+  `After that,' continued the Hatter, `I cut some more bread-\r
+and-butter--'\r
+\r
+  `But what did the Dormouse say?' one of the jury asked.\r
+\r
+  `That I can't remember,' said the Hatter.\r
+\r
+  `You MUST remember,' remarked the King, `or I'll have you\r
+executed.'\r
+\r
+  The miserable Hatter dropped his teacup and bread-and-butter,\r
+and went down on one knee.  `I'm a poor man, your Majesty,' he\r
+began.\r
+\r
+  `You're a very poor speaker,' said the King.\r
+\r
+  Here one of the guinea-pigs cheered, and was immediately\r
+suppressed by the officers of the court.  (As that is rather a\r
+hard word, I will just explain to you how it was done.  They had\r
+a large canvas bag, which tied up at the mouth with strings:\r
+into this they slipped the guinea-pig, head first, and then sat\r
+upon it.)\r
+\r
+  `I'm glad I've seen that done,' thought Alice.  `I've so often\r
+read in the newspapers, at the end of trials, "There was some\r
+attempts at applause, which was immediately suppressed by the\r
+officers of the court," and I never understood what it meant\r
+till now.'\r
+\r
+  `If that's all you know about it, you may stand down,'\r
+continued the King.\r
+\r
+  `I can't go no lower,' said the Hatter:  `I'm on the floor, as\r
+it is.'\r
+\r
+  `Then you may SIT down,' the King replied.\r
+\r
+  Here the other guinea-pig cheered, and was suppressed.\r
+\r
+  `Come, that finished the guinea-pigs!' thought Alice.  `Now we\r
+shall get on better.'\r
+\r
+  `I'd rather finish my tea,' said the Hatter, with an anxious\r
+look at the Queen, who was reading the list of singers.\r
+\r
+  `You may go,' said the King, and the Hatter hurriedly left the\r
+court, without even waiting to put his shoes on.\r
+\r
+  `--and just take his head off outside,' the Queen added to one\r
+of the officers:  but the Hatter was out of sight before the\r
+officer could get to the door.\r
+\r
+  `Call the next witness!' said the King.\r
+\r
+  The next witness was the Duchess's cook.  She carried the\r
+pepper-box in her hand, and Alice guessed who it was, even before\r
+she got into the court, by the way the people near the door began\r
+sneezing all at once.\r
+\r
+  `Give your evidence,' said the King.\r
+\r
+  `Shan't,' said the cook.\r
+\r
+  The King looked anxiously at the White Rabbit, who said in a\r
+low voice, `Your Majesty must cross-examine THIS witness.'\r
+\r
+  `Well, if I must, I must,' the King said, with a melancholy\r
+air, and, after folding his arms and frowning at the cook till\r
+his eyes were nearly out of sight, he said in a deep voice, `What\r
+are tarts made of?'\r
+\r
+  `Pepper, mostly,' said the cook.\r
+\r
+  `Treacle,' said a sleepy voice behind her.\r
+\r
+  `Collar that Dormouse,' the Queen shrieked out.  `Behead that\r
+Dormouse!  Turn that Dormouse out of court!  Suppress him!  Pinch\r
+him!  Off with his whiskers!'\r
+\r
+  For some minutes the whole court was in confusion, getting the\r
+Dormouse turned out, and, by the time they had settled down\r
+again, the cook had disappeared.\r
+\r
+  `Never mind!' said the King, with an air of great relief.\r
+`Call the next witness.'  And he added in an undertone to the\r
+Queen, `Really, my dear, YOU must cross-examine the next witness.\r
+It quite makes my forehead ache!'\r
+\r
+  Alice watched the White Rabbit as he fumbled over the list,\r
+feeling very curious to see what the next witness would be like,\r
+`--for they haven't got much evidence YET,' she said to herself.\r
+Imagine her surprise, when the White Rabbit read out, at the top\r
+of his shrill little voice, the name `Alice!'\r
+\r
+\r
+\r
+                           CHAPTER XII\r
+\r
+                        Alice's Evidence\r
+\r
+\r
+  `Here!' cried Alice, quite forgetting in the flurry of the\r
+moment how large she had grown in the last few minutes, and she\r
+jumped up in such a hurry that she tipped over the jury-box with\r
+the edge of her skirt, upsetting all the jurymen on to the heads\r
+of the crowd below, and there they lay sprawling about, reminding\r
+her very much of a globe of goldfish she had accidentally upset\r
+the week before.\r
+\r
+  `Oh, I BEG your pardon!' she exclaimed in a tone of great\r
+dismay, and began picking them up again as quickly as she could,\r
+for the accident of the goldfish kept running in her head, and\r
+she had a vague sort of idea that they must be collected at once\r
+and put back into the jury-box, or they would die.\r
+\r
+  `The trial cannot proceed,' said the King in a very grave\r
+voice, `until all the jurymen are back in their proper places--\r
+ALL,' he repeated with great emphasis, looking hard at Alice as\r
+he said do.\r
+\r
+  Alice looked at the jury-box, and saw that, in her haste, she\r
+had put the Lizard in head downwards, and the poor little thing\r
+was waving its tail about in a melancholy way, being quite unable\r
+to move.  She soon got it out again, and put it right; `not that\r
+it signifies much,' she said to herself; `I should think it\r
+would be QUITE as much use in the trial one way up as the other.'\r
+\r
+  As soon as the jury had a little recovered from the shock of\r
+being upset, and their slates and pencils had been found and\r
+handed back to them, they set to work very diligently to write\r
+out a history of the accident, all except the Lizard, who seemed\r
+too much overcome to do anything but sit with its mouth open,\r
+gazing up into the roof of the court.\r
+\r
+  `What do you know about this business?' the King said to\r
+Alice.\r
+\r
+  `Nothing,' said Alice.\r
+\r
+  `Nothing WHATEVER?' persisted the King.\r
+\r
+  `Nothing whatever,' said Alice.\r
+\r
+  `That's very important,' the King said, turning to the jury.\r
+They were just beginning to write this down on their slates, when\r
+the White Rabbit interrupted:  `UNimportant, your Majesty means,\r
+of course,' he said in a very respectful tone, but frowning and\r
+making faces at him as he spoke.\r
+\r
+  `UNimportant, of course, I meant,' the King hastily said, and\r
+went on to himself in an undertone, `important--unimportant--\r
+unimportant--important--' as if he were trying which word\r
+sounded best.\r
+\r
+  Some of the jury wrote it down `important,' and some\r
+`unimportant.'  Alice could see this, as she was near enough to\r
+look over their slates; `but it doesn't matter a bit,' she\r
+thought to herself.\r
+\r
+  At this moment the King, who had been for some time busily\r
+writing in his note-book, cackled out `Silence!' and read out\r
+from his book, `Rule Forty-two.  ALL PERSONS MORE THAN A MILE\r
+HIGH TO LEAVE THE COURT.'\r
+\r
+  Everybody looked at Alice.\r
+\r
+  `I'M not a mile high,' said Alice.\r
+\r
+  `You are,' said the King.\r
+\r
+  `Nearly two miles high,' added the Queen.\r
+\r
+  `Well, I shan't go, at any rate,' said Alice:  `besides,\r
+that's not a regular rule:  you invented it just now.'\r
+\r
+  `It's the oldest rule in the book,' said the King.\r
+\r
+  `Then it ought to be Number One,' said Alice.\r
+\r
+  The King turned pale, and shut his note-book hastily.\r
+`Consider your verdict,' he said to the jury, in a low, trembling\r
+voice.\r
+\r
+  `There's more evidence to come yet, please your Majesty,' said\r
+the White Rabbit, jumping up in a great hurry; `this paper has\r
+just been picked up.'\r
+\r
+  `What's in it?' said the Queen.\r
+\r
+  `I haven't opened it yet,' said the White Rabbit, `but it seems\r
+to be a letter, written by the prisoner to--to somebody.'\r
+\r
+  `It must have been that,' said the King, `unless it was\r
+written to nobody, which isn't usual, you know.'\r
+\r
+  `Who is it directed to?' said one of the jurymen.\r
+\r
+  `It isn't directed at all,' said the White Rabbit; `in fact,\r
+there's nothing written on the OUTSIDE.'  He unfolded the paper\r
+as he spoke, and added `It isn't a letter, after all:  it's a set\r
+of verses.'\r
+\r
+  `Are they in the prisoner's handwriting?' asked another of\r
+they jurymen.\r
+\r
+  `No, they're not,' said the White Rabbit, `and that's the\r
+queerest thing about it.'  (The jury all looked puzzled.)\r
+\r
+  `He must have imitated somebody else's hand,' said the King.\r
+(The jury all brightened up again.)\r
+\r
+  `Please your Majesty,' said the Knave, `I didn't write it, and\r
+they can't prove I did:  there's no name signed at the end.'\r
+\r
+  `If you didn't sign it,' said the King, `that only makes the\r
+matter worse.  You MUST have meant some mischief, or else you'd\r
+have signed your name like an honest man.'\r
+\r
+  There was a general clapping of hands at this:  it was the\r
+first really clever thing the King had said that day.\r
+\r
+  `That PROVES his guilt,' said the Queen.\r
+\r
+  `It proves nothing of the sort!' said Alice.  `Why, you don't\r
+even know what they're about!'\r
+\r
+  `Read them,' said the King.\r
+\r
+  The White Rabbit put on his spectacles.  `Where shall I begin,\r
+please your Majesty?' he asked.\r
+\r
+  `Begin at the beginning,' the King said gravely, `and go on\r
+till you come to the end:  then stop.'\r
+\r
+  These were the verses the White Rabbit read:--\r
+\r
+        `They told me you had been to her,\r
+          And mentioned me to him:\r
+        She gave me a good character,\r
+          But said I could not swim.\r
+\r
+        He sent them word I had not gone\r
+          (We know it to be true):\r
+        If she should push the matter on,\r
+          What would become of you?\r
+\r
+        I gave her one, they gave him two,\r
+          You gave us three or more;\r
+        They all returned from him to you,\r
+          Though they were mine before.\r
+\r
+        If I or she should chance to be\r
+          Involved in this affair,\r
+        He trusts to you to set them free,\r
+          Exactly as we were.\r
+\r
+        My notion was that you had been\r
+          (Before she had this fit)\r
+        An obstacle that came between\r
+          Him, and ourselves, and it.\r
+\r
+        Don't let him know she liked them best,\r
+          For this must ever be\r
+        A secret, kept from all the rest,\r
+          Between yourself and me.'\r
+\r
+  `That's the most important piece of evidence we've heard yet,'\r
+said the King, rubbing his hands; `so now let the jury--'\r
+\r
+  `If any one of them can explain it,' said Alice, (she had\r
+grown so large in the last few minutes that she wasn't a bit\r
+afraid of interrupting him,) `I'll give him sixpence.  _I_ don't\r
+believe there's an atom of meaning in it.'\r
+\r
+  The jury all wrote down on their slates, `SHE doesn't believe\r
+there's an atom of meaning in it,' but none of them attempted to\r
+explain the paper.\r
+\r
+  `If there's no meaning in it,' said the King, `that saves a\r
+world of trouble, you know, as we needn't try to find any.  And\r
+yet I don't know,' he went on, spreading out the verses on his\r
+knee, and looking at them with one eye; `I seem to see some\r
+meaning in them, after all.  "--SAID I COULD NOT SWIM--" you\r
+can't swim, can you?' he added, turning to the Knave.\r
+\r
+  The Knave shook his head sadly.  `Do I look like it?' he said.\r
+(Which he certainly did NOT, being made entirely of cardboard.)\r
+\r
+  `All right, so far,' said the King, and he went on muttering\r
+over the verses to himself:  `"WE KNOW IT TO BE TRUE--" that's\r
+the jury, of course-- "I GAVE HER ONE, THEY GAVE HIM TWO--" why,\r
+that must be what he did with the tarts, you know--'\r
+\r
+  `But, it goes on "THEY ALL RETURNED FROM HIM TO YOU,"' said\r
+Alice.\r
+\r
+  `Why, there they are!' said the King triumphantly, pointing to\r
+the tarts on the table.  `Nothing can be clearer than THAT.\r
+Then again--"BEFORE SHE HAD THIS FIT--"  you never had fits, my\r
+dear, I think?' he said to the Queen.\r
+\r
+  `Never!' said the Queen furiously, throwing an inkstand at the\r
+Lizard as she spoke.  (The unfortunate little Bill had left off\r
+writing on his slate with one finger, as he found it made no\r
+mark; but he now hastily began again, using the ink, that was\r
+trickling down his face, as long as it lasted.)\r
+\r
+  `Then the words don't FIT you,' said the King, looking round\r
+the court with a smile.  There was a dead silence.\r
+\r
+  `It's a pun!' the King added in an offended tone, and\r
+everybody laughed, `Let the jury consider their verdict,' the\r
+King said, for about the twentieth time that day.\r
+\r
+  `No, no!' said the Queen.  `Sentence first--verdict afterwards.'\r
+\r
+  `Stuff and nonsense!' said Alice loudly.  `The idea of having\r
+the sentence first!'\r
+\r
+  `Hold your tongue!' said the Queen, turning purple.\r
+\r
+  `I won't!' said Alice.\r
+\r
+  `Off with her head!' the Queen shouted at the top of her voice.\r
+Nobody moved.\r
+\r
+  `Who cares for you?' said Alice, (she had grown to her full\r
+size by this time.)  `You're nothing but a pack of cards!'\r
+\r
+  At this the whole pack rose up into the air, and came flying\r
+down upon her:  she gave a little scream, half of fright and half\r
+of anger, and tried to beat them off, and found herself lying on\r
+the bank, with her head in the lap of her sister, who was gently\r
+brushing away some dead leaves that had fluttered down from the\r
+trees upon her face.\r
+\r
+  `Wake up, Alice dear!' said her sister; `Why, what a long\r
+sleep you've had!'\r
+\r
+  `Oh, I've had such a curious dream!' said Alice, and she told\r
+her sister, as well as she could remember them, all these strange\r
+Adventures of hers that you have just been reading about; and\r
+when she had finished, her sister kissed her, and said, `It WAS a\r
+curious dream, dear, certainly:  but now run in to your tea; it's\r
+getting late.'  So Alice got up and ran off, thinking while she\r
+ran, as well she might, what a wonderful dream it had been.\r
+\r
+  But her sister sat still just as she left her, leaning her\r
+head on her hand, watching the setting sun, and thinking of\r
+little Alice and all her wonderful Adventures, till she too began\r
+dreaming after a fashion, and this was her dream:--\r
+\r
+  First, she dreamed of little Alice herself, and once again the\r
+tiny hands were clasped upon her knee, and the bright eager eyes\r
+were looking up into hers--she could hear the very tones of her\r
+voice, and see that queer little toss of her head to keep back\r
+the wandering hair that WOULD always get into her eyes--and\r
+still as she listened, or seemed to listen, the whole place\r
+around her became alive the strange creatures of her little\r
+sister's dream.\r
+\r
+  The long grass rustled at her feet as the White Rabbit hurried\r
+by--the frightened Mouse splashed his way through the\r
+neighbouring pool--she could hear the rattle of the teacups as\r
+the March Hare and his friends shared their never-ending meal,\r
+and the shrill voice of the Queen ordering off her unfortunate\r
+guests to execution--once more the pig-baby was sneezing on the\r
+Duchess's knee, while plates and dishes crashed around it--once\r
+more the shriek of the Gryphon, the squeaking of the Lizard's\r
+slate-pencil, and the choking of the suppressed guinea-pigs,\r
+filled the air, mixed up with the distant sobs of the miserable\r
+Mock Turtle.\r
+\r
+  So she sat on, with closed eyes, and half believed herself in\r
+Wonderland, though she knew she had but to open them again, and\r
+all would change to dull reality--the grass would be only\r
+rustling in the wind, and the pool rippling to the waving of the\r
+reeds--the rattling teacups would change to tinkling sheep-\r
+bells, and the Queen's shrill cries to the voice of the shepherd\r
+boy--and the sneeze of the baby, the shriek of the Gryphon, and\r
+all thy other queer noises, would change (she knew) to the\r
+confused clamour of the busy farm-yard--while the lowing of the\r
+cattle in the distance would take the place of the Mock Turtle's\r
+heavy sobs.\r
+\r
+  Lastly, she pictured to herself how this same little sister of\r
+hers would, in the after-time, be herself a grown woman; and how\r
+she would keep, through all her riper years, the simple and\r
+loving heart of her childhood:  and how she would gather about\r
+her other little children, and make THEIR eyes bright and eager\r
+with many a strange tale, perhaps even with the dream of\r
+Wonderland of long ago:  and how she would feel with all their\r
+simple sorrows, and find a pleasure in all their simple joys,\r
+remembering her own child-life, and the happy summer days.\r
+\r
+                             THE END\r
+\1a
\ 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 (file)
index 0000000..88dc7b6
--- /dev/null
@@ -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 (file)
index 0000000..99d970f
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 (file)
index 0000000..8f5cb13
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 (file)
index 0000000..774aead
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 (file)
index 0000000..1d0ca37
--- /dev/null
@@ -0,0 +1,645 @@
+<head>
+<title>Compression Pointers</title>
+<META HTTP-EQUIV="Keywords" CONTENT="compression, compression, compression">
+</head>
+<body>
+<BODY BGCOLOR=#FFFFFF>
+
+<center>
+<H1> Compression Pointers </h1>
+
+
+
+</center>
+
+<p>
+<a href="#Resources">Compression resources</a>, <a href="#Conferences">conferences</a>, and some <a href="#Research">research
+groups and companies</a>, are listed towards the end of this page. <p>
+
+Use this <a href="form.html">handy form</a> to add something to this page, or to simply say you liked this page<i> <img src="new.gif">
+<p>
+
+</i>
+
+
+
+<p>
+
+<h2>What's New?</h2><p>
+
+
+<a href="http://www.teaser.fr/~jlgailly/">Jean-loup Gailly</a> -- <i>Mr. gzip,
+PNG, CCR (1996-06-10)</i>
+<img src="new.gif">
+<br>
+
+<a href="http://www.creative.net/~tristan/MPEG">MPEG Pointers and Resources</a>
+<img src="new.gif">
+<br>
+
+<a href="http://www-isl.stanford.edu/~gray/">Robert M. Gray</a> -- <i>Signal
+compression, VQ, image quality evaluation (1996-04-22)</i><img src="new.gif">
+<br>
+
+<a href="http://www-isl.stanford.edu/~gray/compression.html">Compression and
+Classification Group</a> -- <i>ISL,EE,Stanford (1996-04-22)</i><img src="new.gif">
+<br>
+
+<a href="http://www-isl.stanford.edu/~gray/iii.html">Signal Processing
+and the International Information Infrastructure</a> -- <i>Web sites (1996-04-22)</i> <img src="new.gif">
+<br>
+
+<a href="http://www.cs.sc.edu:80/~valenta/">Valenta, Vladimir</a> -- <i>(1996-04-22)</i>
+<br>
+
+
+<a href="http://patpwww.epfl.ch:80/~jordan/Subjects/Parallel/parallel.html">Jordan, Frederic</a> -- <i>Parallel Image Compression (1996-04-12)</i> <img src="new.gif">
+<br>
+<a href="http://www.garlic.com/biz/eotek">Electro-Optical Technologies, Inc.</a> -- <i>Consultant (1996-04-12)</i> <img src="new.gif">
+<br>
+<a href="http://quicktime.apple.com">quicktime.apple.com</a> -- <i>Quicktime site (1996-03-11)</i> <img src="new.gif">
+<br>
+<a href="http://www.chips.ibm.com/products/aldc/index.html">IBM Hardware</a> -- <i>Compression chips (1996-03-11)</i> <img src="new.gif">
+<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<!---
+
+<img src="new.gif"><i>Do you have, or know of, a research position where an image compression guru with a Ph.D. would feel at
+home?  Let me know if you do...<a
+href="mailto:singlis@cs.waikato.ac.nz"><b>send me some email!</b></a>, or <a
+href="http://www.cs.waikato.ac.nz/~singlis/cv.html"><b>check out my
+c.v.</b>
+</a> 
+</i>
+
+-->
+
+<p>
+
+
+<p>
+
+
+<h2><i>People</i></h2>
+<h2>A</h2>
+
+<a href="http://quest.jpl.nasa.gov/Mark.Adler/">Adler, Mark</a> -- <i>Info-ZIP; Zip, UnZip, gzip and zlib co-author; PNG group</i>
+<p>
+
+<h2>B</h2>
+
+<a href="http://www.eese.qut.edu.au/~mbaker/">Baker, Matthew</a> -- <i>Region based video compression</i>
+<p>
+<a href="http://www.eecs.wsu.edu/~bamberg/">Bamberger, Roberto H.</a>
+<p>
+<a href="http://sutherland.eese.qut.edu.au/~dbell">Bell, Daniel</a> -- <i>Region based image compression</i>
+<p>
+<a href="http://www.cosc.canterbury.ac.nz/~tim">Bell, Tim</a> -- <i>compression, computer science for children, and computers and music.</i> 
+<p>
+<a href="http://www.polytechnique.fr/poly/~bellard/">Bellard, Fabrice</a> -- <i>Author of LZEXE</I>
+<p>
+<a href="http://www.cevis.uni-bremen.de/~willy/">Berghorn, Willy </a>
+<p>
+<a href="http://www.best.com/~bhaskara">Bhaskaran, Vasudev</a> -- <i>Image and Video compression</i> 
+<p>
+<a href="http://wwwvms.utexas.edu/~cbloom/index.html">Bloom, Charles</a> -- <i>text compression, LZ methods, PPM methods...</i>
+<p>
+<a href="http://www.ime.usp.br/~rbrito">Brito, Roger</a> -- <i>Arithmetic Coding, LZW, Text Compression</i>
+<p>
+<a href="http://www.engineering.usu.edu/ece/faculty/scottb.html">Budge, Scott E.</a> -- <i>medical/lossy image compression</i>
+<p>
+<a href="http://www.elec.uow.edu.au/people/staff/burnett/biography.html">Burnett, Ian</a> -- <i>Speech coding, prototype waveform techniques</I> <img src="new.gif">
+<p>
+
+
+<h2>C</h2>
+
+<a href="http://gabor.eecs.berkeley.edu/~wychan/">Chan, Christopher</a> -- <i>universal lossy source coding, adaptive VQ</i>
+<p>
+<a href="http://www.compsci.com/~chao">Chao, Hong-yang</a> -- <I>Lightning strike image compressor </i> 
+<p>
+<a href="http://monet.uwaterloo.ca:80/schao/">Chao, Stewart</a>
+<p>
+<a href="http://diana.ecs.soton.ac.uk/~pjc94r/">Cherriman, Peter</a>
+<p>
+<a href="http://www-video.eecs.berkeley.edu/erl/sccheung.html">Cheung, S.C.</a> -- <i>Scalable video compression algorithms (18th Feb 1996)</i> <img src="new.gif">
+<p>
+
+<a href="http://etro.vub.ac.be/chchrist.html">Christopoulos, Charilaos</a> -- <i> Image and Video compression </i>
+<p>
+<a href="http://sipi.usc.edu/~chrysafi/">Chrysafis, Christos</a> 
+<p>
+<a href="http://www.ee.gatech.edu/research/DSP/students/wchung/index.html">Chung, Wilson C.</a> -- <i>R-D image and video coding, subband/wavelet, filter banks</i> 
+<p>
+<a href="mailto:aclark@hayes.com">Clark, Alan</a> -- <i>primary contact for V.42bis. Developed BTLZ variant of LZW</i>
+<p>
+<a href="http://www.cs.waikato.ac.nz/cs/Staff/jgc.html">Cleary, John</a> -- <i>PPM, PPM*, K*</i>
+<p>
+<a href="http://www.cs.brandeis.edu/dept/faculty/cohn/">Cohn, Martin</a>
+<p>
+
+<a href="http://plg.uwaterloo.ca/~gvcormac">Cormack, Gordon V.</a> -- <I>DMC</i>
+<p>
+<a href="http://www.ee.duke.edu/~cec/index.html">Cramer, Chris</a> -- <i>neural network image compression</i>
+<p>
+
+<h2>D</h2>
+<a href="http://www.cs.dartmouth.edu/~jmd/">Danskin, John</a> -- <i>Protocol compression, document compression (9th Feb 1996)</i> 
+<p>
+<a href="http://www.cs.dartmouth.edu/~gdavis">Davis, Geoff</a> -- <i>wavelets, image compression, medical</i>
+<p>
+<a href="http://www-mddsp.enel.ucalgary.ca/People/adilger/">Dilger, Andreas</a> -- <i>fractal block coding of video sequences</i>
+<p>
+
+
+<h2>E</h2>
+<a href="http://info.cipic.ucdavis.edu/~estes/index.html">Estes, Robert</a>
+<p>
+
+
+
+<h2>F</h2>
+<a href="http://inls.ucsd.edu/y/Fractals/">Fisher, Yuval</a> -- <i>Fractal Image Compression</i>
+<p>
+<a href="http://www.wmin.ac.uk/~ajoec1/homepage.html">Ford, Adrian</a> -- <i>Subjective and Objective Compression quality (5th Mar 1996)</i> <img src="new.gif">
+<p>
+
+<h2>G</h2> 
+<a href="http://www.teaser.fr/~jlgailly/">Jean-loup Gailly</a> --
+<i>Mr. gzip, PNG, CCR (1996-06-10)</i>
+<p>
+
+<a href="http://www.ece.ucsb.edu/faculty/gersho/default.html">Gersho, Allen</a> -- <i>Vector Quantisation, Image Compression</i>
+<p>
+<a href="http://life.anu.edu.au/ci/vol1/goertzel.html">Goertzel, Ben</a>
+<p>
+<a href="http://info.lut.ac.uk/departments/el/research/sys/compression.html">Gooch, Mark</a> -- <i>High Performance Hardware Compression (7th Feb 1996)</i> 
+<p>
+<a href="http://robotics.eecs.berkeley.edu/~vkgoyal/">Goyal, Vivek</a> -- <i>overcomplete representations, adaptive transform coding, VQ</i>
+<p> 
+<a href="http://www-isl.stanford.edu/~gray/">Robert M. Gray</a> -- <i>Signal
+compression, VQ, image quality evaluation</i><img src="new.gif">
+<p>
+
+<h2>H</h2>
+<a href="http://cork.informatik.uni-wuerzburg.de/mitarbeiter/ulli">Hafner, Ullrich</a> -- <i>WFA image compression</i>
+<p>
+<a href="http://www.ics.uci.edu/~dan/">Hirschberg, Dan</a> -- <i>algorithm theory, compression</i> 
+<p>
+<a href="http://wolfpack.larc.nasa.gov/holland.html">Holland, Scott</a>
+<p>
+<a href="http://www.csc.uvic.ca/home/nigelh/nigelh.html">Horspool, R. Nigel</a> -- <i>text compression, ECG compression</i>
+
+<h2>I</h2>
+<a href="http://www.cs.waikato.ac.nz/~singlis">Inglis, Stuart</a> -- <i>image compression, OCR, lossy/lossless document compression</I>
+<p>
+
+<h2>J</h2>
+<a href="http://www.cs.uiowa.edu/~jones/compress/index.html">Jones, Douglas</a> -- <i>splay-tree based compression and encryption</i>
+<p>
+<a href="http://info.lut.ac.uk/departments/el/research/sys/compression.html">Jones, Simon</a> -- <i>Lossless compression, High Performance Hardware (7th Feb 1996) </i> 
+<p>
+<a href="http://patpwww.epfl.ch:80/~jordan/Subjects/Parallel/parallel.html">Jordan, Frederic</a> -- <i>Parallel Image Compression (12th April 1996)</i> <img src="new.gif">
+<p>
+<a href="mailto:robjung@world.std.com">Jung, Robert K.</a> -- <i><a href="http://www.info.fundp.ac.be/~fta/arj.html">ARJ</a> </i>
+<p>
+<a href="http://www.cs.tu-berlin.de/~jutta/toast.html">jutta</a>
+<p>
+
+
+
+<h2>K</h2>
+<a href="http://links.uwaterloo.ca">Kominek, John</a> -- <I>Fractal and spline based compression</i>
+<p>
+<a href="http://info.lut.ac.uk/departments/el/research/sys/elmk3.html">Kjelso, Morten</a> -- <i>Main memory compression, High performance hardware</i> 
+<p>
+<a href="http://wwwcip.informatik.uni-erlangen.de/user/mskuhn">Kuhn, Markus</a> -- <i>JBIG implementation</i> <img src="new.gif">
+<p>
+<a href="http://sipi.usc.edu/faculty/Kuo.html">Kuo, C.-C. Jay</a>
+<p>
+<a href="http://kaarna.cc.jyu.fi:80/~kuru/">Kuru, Esa</a>
+<p>
+<a href="http://www.prz.tu-berlin.de:80/~teo/">Kyfonidis, Theodoros</a>
+<p>
+
+<h2>L</h2>
+<a href="http://www.icsi.berkeley.edu/~lampart/">Lamparter, Bernd</a>
+<p>
+<a href="http://www.cse.ucsc.edu/cgi-bin/faculty?langdon">Langdon, Glen</a>
+<p>
+<a href="http://www.dna.lth.se/~jesper/">Larsson, Jesper</a> -- <i>algorithms and data structures, text compression</i> <img src="new.gif">
+<p>
+
+
+<h2>M</h2>
+<a href="http://glimpse.cs.arizona.edu:1994/udi.html">Manber, Udi</a>
+<p>
+<a href="http://www.elec.rma.ac.be/~jma/compression.html">Mangen, Jean-Michel</a> -- <i>image compression, wavelets, satellite</I>
+<p>
+<a href="http://www.cs.mu.oz.au/~alistair">Moffat, Alistair</a> -- <i>text and index compression, coding methods, information retrieval, document databases</i>
+<p>
+<a href="http://deskfish.cs.titech.ac.jp/squish/squish_index.html">Montgomery, Christopher</a> -- <i>OggSquish, audio compression</i>
+<p>
+<a href="mailto:umueller@amiga.physik.unizh.ch">Mueller, Urban Dominik</a> -- <i>XPK system</I>
+<p>
+<h2>N</h2>
+<a href="ftp://ai.toronto.edu/pub/radford/www/index.html">Neal, Radford</a>
+<p>
+<a href="http://www.cs.waikato.ac.nz/~cgn">Nevill-Manning, Craig</a>
+<p>
+<a href="http://phoenix.bath.ac.uk/jez/jez.html">Nicholls, Jeremy</a>
+<p>
+<a href="http://www.acti.com/matt/">Noah, Matt</a> -- <i>speech, ATC, ACELP and IMBE</i>
+<p>
+<a href="http://www.eecs.wsu.edu/~vnuri/">Nuri, Veyis</a> -- <i>wavelets, data compression, DSP (speech & image)</I>
+
+<h2>O</h2>
+<a href="ftp://replicant.csci.unt.edu/pub/oleg/README.html">Oleg</a> -- <i>Lots of code</i>
+<p>
+<a href="http://sipi.usc.edu/faculty/Ortega/Ortega.html">Ortega, Antonio</a> -- <i>Video compression, Packet video, Adaptive quantization</i>
+<p>
+<a href="http://www.cs.dartmouth.edu:80/~cowen/">Owen, Charles</a>
+<p>
+
+<h2>P</h2>
+<a
+href="http://www-mddsp.enel.ucalgary.ca/People/provine/compression.html">Provine,
+Joseph</a> -- <i>Model based coding</i>
+<p>
+
+<h2>R</h2>
+<a href="http://monet.uwaterloo.ca/~john/btpc.html">Robinson, John</a> -- <i>Binary Tree Predictive Coding</i>
+<p>
+<a href="http://quest.jpl.nasa.gov/Info-ZIP/people/greg/">Roelofs, Greg</a> -- <i>Info-ZIP; primary UnZip author; PNG group</i>
+<p>
+<a href="http://www.ece.ucsb.edu/faculty/rose/default.html">Rose, Kenneth</a>
+<p>
+<a href="http://www.nettuno.it/fiera/telvox/telvox.htm">Russo, Roberto Maria</a> -- <I>Multiplatform Data Compression</i>
+<p>
+
+<h2>S</h2>
+<a href="http://harc.edu:80/~schmidt/">Schmidt, Bill</a>
+<p>
+<a href="http://koa.ifa.hawaii.edu/~shaw/shaw.html">Shaw, Sandy C.</a>
+<p>
+<a href="http://www.comm.toronto.edu/~kamran/kamran.html">Sharifi, Kamran</a> -- <i>Video over ATM networks</i>
+<p>
+<a href="http://calypso.unl.edu/~sunil/">Shende, Sunil M.</a>
+<p>
+<a href="http://viewprint2.berkeley.edu/KleinLab/Amnon/Amnon.html">Silverstein, D. Amnon</a>
+<p>
+<a href="http://www-plateau.cs.berkeley.edu/people/smoot">Smoot, Steve</a> -- <i>MPEG</i>
+<p>
+<a href="http://www.cs.brandeis.edu/dept/faculty/storer/">Storer, James A.</a>
+<p>
+<a href="http://rice.ecs.soton.ac.uk/index.html">Streit, Jurgen</a> -- <i>Low bitrate coding</i>
+<p>
+<a href="http://www_nt.e-technik.uni-rostock.de/~ts/index.html">Strutz, Tilo</a> -- <i>Wavelet image compressor, demonstration execs</i> <img src="new.gif">
+<p>
+
+
+<h2>T</h2>
+<a href="http://zaphod.csci.unt.edu:80/~srt/">Tate, Steve</a>
+<p>
+<a href="http://www.cs.waikato.ac.nz/~wjt">Teahan, Bill</a> -- <i>PPM, PPM*, master of the Calgary Corpus</i>
+<p>
+<a href="http://lightning.eee.strath.ac.uk/~duncan/">Thomson, Duncan</a> -- <i>ECG compression with ANNs</i>
+<p>
+<a href="http://outside.gsfc.nasa.gov/GRSS/">Tilton, James C.</a>
+<p>
+<a href="http://www.uni-karlsruhe.de/~un55/">Tomczyk, Marek</a>
+<p>
+<a href="http://munkora.cs.mu.oz.au/~aht">Turpin, Andrew</a> -- <i>Prefix Codes</i> 
+<p>
+
+<h2>V</h2>
+<a href="http://gabor.eecs.berkeley.edu/~martin/">Vetterli, Martin</a> -- <i>wavelets, subband coding, video compression, computational complexity</i>
+<p>
+<a href="http://www.cs.duke.edu/~jsv/HomePage.html">Vitter, Jeff</a>
+<p>
+<a href="http://www.eee.strath.ac.uk/~stathis/home.html">Voukelatos, Stathis</a>
+<p>
+<a href="http://www.xs4all.nl/~aipnl">de Vries, Nico</a> -- <i>AIP-NL, UltraCompressor II development</i> <img src="new.gif">
+<p>
+
+<h2>W</h2>
+
+<a href="http://ipcl.ee.queensu.ca/wareham/wareham.html">Wareham, Paul</a> -- <i>Region-oriented video coding</I>
+<p>
+<a href="mailto://Wegs59@aol.com">Wegener, Al</a> -- <i>DSP, lossless audio compression and AC-2</i> 
+<p>
+<a href="http://www-dsp.rice.edu:80/~weid/">Wei, Dong</a> -- <i>Wavelet compression</i>
+<p>
+<a href="http://www.rocksoft.com/~ross">Williams, Ross</a>
+<p>
+<a href="http://www.cs.waikato.ac.nz/~ihw">Witten, Ian</a> -- <i>PPM, mg, arithmetic coding</i>
+<p>
+<a href="http://www.sees.bangor.ac.uk/~gerry/sp_summary.html">Wolff, Gerry</a>
+<p>
+<a href="http://sipi.usc.edu/~wwoo/">Woo, Woon-Tack</a> -- <i>stereo image and video compression (12th Feb 1996)</i>
+<p>
+<a href="http://www.csd.uwo.ca/faculty/wu/">Wu, Xiaolin</a> -- <i>CALIC</i>
+<P>
+
+
+<h2>Z</h2>
+<a href="http://www.cs.rmit.edu.au/~jz">Zobel, Justin</a> -- <i>index compression, database compression</i>
+<p>
+
+<br>
+<br>
+
+
+<a name="Conferences">
+
+<h2><i>Conferences</i></h2>
+<a href="http://www.cs.brandeis.edu:80/~dcc/index.html"><b>Data Compression Conference (DCC), Snowbird, Utah, USA.</b></a><br>
+<p>
+
+<a name="Resources">
+
+<h2><i>Resources</i></h2>
+<dt>
+<i><b>Where to get answers...</b></i>
+<dd>
+<dd><a href="http://info.itu.ch/">International Telecommunication Union (ITU)</a> -- <i>standards documents (CCITT)</i>
+<br>
+<dd><a href="http://www.cis.ohio-state.edu/hypertext/faq/usenet/compression-faq/top.html">comp.compression -- Frequently Asked Questions</a> -- <i>Come here 1st!</i>
+<dd>
+<a href="http://www.cis.ohio-state.edu/hypertext/faq/usenet/jpeg-faq/faq.html">JPEG - Frequently Asked Questions</a>
+<dd>
+<a href="http://www.crs4.it/HTML/LUIGI/MPEG/mpegfaq.html">MPEG - Frequently Asked Questions</a>
+<dd>
+<a href="ftp://rtfm.mit.edu:/pub/usenet/news.answers/standards-faq">Standards - Frequenty Asked Questions</a>
+<dd>
+<a href="news:comp.compression.research">usenet newsgroup: comp.compression.research</a>
+<br>
+<dd>
+<a href="http://www.mi.net/act/act.html">Archive Compression Test</a> -- <i>Summary of all archivers</i> 
+<br>
+<dd>
+<a href="http://dip1.ee.uct.ac.za/fractal.bib.html">Fractal compression bibliography</a> -- <i>bibtex file</i>
+<br>
+<dd>
+<a href="http://goethe.ira.uka.de/edu/proseminar.html">LZ/Complexity Seminars</a> -- <i>(in German)</i>
+<br>
+<dd>
+<a href="http://www.cs.waikato.ac.nz/~singlis/ratios.html">Comparitive Compression Ratios</a> -- <i>Sofar...B&W, Gray Scale, Text Compression</i>
+<br>
+<dd>
+<a href="http://www.cs.ucl.ac.uk/mice/mpeggloss.html">VCN (Video, Compression, Networking)
+Glossary</a>
+<br>
+<dd>
+<a href="http://www.cs.waikato.ac.nz/~nzdl/">Digital Library -- search for compression</a>
+<br>
+</dt>
+
+<br>
+<dt>
+<i><b>Reports/Ph.D. Theses</b></i>
+<dd>
+<a href="http://www.cs.brown.edu/publications/techreports/reports/CS-93-28.html">Paul Howards Ph.D. thesis</a><br>
+<dd><i>The Design and Analysis of Efficient Lossless Data Compression Systems</i>
+<br>
+</dt>
+
+
+
+<br>
+<dt>
+<i><b>Source code</b></i>
+<dd>
+<a href="ftp://munnari.oz.au/pub/arith_coder">Arithmetic coding routines</a> 
+<dd><i>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp(from Moffat, Neal and Witten, Proc. DCC, April 1995)</i>
+<br>
+<dd>
+<a href="ftp://ftp.cpsc.ucalgary.ca/pub/projects/ar.cod">CACM Arithmetic coding package</a>
+<dd><i>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp(Witten, Neal and Cleary, CACM 30:520-541, June 1987)</i>
+<br>
+<dd>
+<a href="ftp://nic.funet.fi/pub/graphics/misc/test-images/jbig.tar.gz">JBIG Source code</a> <i>Includes a Q-coder</i>
+<br>
+<dd><a href="http://wwwcip.informatik.uni-erlangen.de/user/mskuhn">Markus Kuhn's JBIG implementation</a> 
+<br>
+<dd>
+<a href="ftp://media-lab.media.mit.edu/pub/k-arith-code/">k-arithmetic coder</a>
+<br>
+<dd>
+<a href="ftp://garbo.uwasa.fi/pc/programming/lds_11.zip">Lossless Data Compression toolkit 1.1</a>
+<br>
+<dd>
+<a href="http://www.cs.uiowa.edu/~jones/compress/index.html">Splay Trees Code</a> -- <i>by Douglas W. Jones</i>
+<br>
+<dd><a href="ftp://ftp.cl.cam.ac.uk/users/djw3">Block compression code</a> -- <i>Excellent text compressor</i>
+<br>
+
+</dt>
+
+<br>
+<dt>
+<i><b>Test Files</b></i>
+<dd>
+<a href="ftp://nic.funet.fi/pub/graphics/misc/test-images/">Test Images</a> -- <i>CCITT images (pbm), Lena etc. (Sun raster)</i>
+<br>
+<dd>
+Stockholm test images -- <i>You have to buy a CDROM, thats all I know! :-(</i>
+<dd>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp mail me at <a href="mailto:singlis@cs.waikato.ac.nz">singlis@cs.waikato.ac.nz</a> if you know anything about them.
+<br>
+<dd>
+<a href="ftp://ftp.cpsc.ucalgary.ca/pub/projects/text.compression.corpus/">Calgary Text Compression Corpus</a><i> (Text Compression, Bell, Cleary and Witten, 1990)</i>
+<br>
+</dt>
+
+<br>
+
+<a name="Research">
+
+
+<h2><i>Research Projects, Standards & Companies</i></h2>
+
+<p>
+<dt>
+<i><b>Research/Free software Groups</b></i>
+<dd><a href="http://www-isl.stanford.edu/~gray/compression.html">Compression and
+Classification Group</a> -- <i>ISL,EE,Stanford (22th April 1996)</i><img src="new.gif">
+
+<dd><a href="http://www.bonzi.com">Voice email</a> -- <i>Lossless audio compression (18th Feb 1996)</i> 
+
+
+<dd><a href="http://www.garlic.com/biz/eotek">Electro-Optical Technologies, Inc.</a> -- <i>Consultant (12th April 1996)</i> <img src="new.gif">
+
+<dd><a href="http://quicktime.apple.com">quicktime.apple.com</a> -- <i>Quicktime site (11th Mar 1996)</i>
+
+<dd><a href="http://www.atinternet.fr/image/">IMAGE etc.</a> -- <i>Commercial image compression software (Fractals/Wavelets) (29th Feb 1996)</i> <img src="new.gif">
+
+<dd><a href="http://re7alpha.epm.ornl.gov/CcmDemo/">NCAR CCM Compression and Visualisation</a> -- <i>(18th Feb 1996)</i> <img src="new.gif">
+<br>
+<dd><a href="http://ipl.rpi.edu/SPIHT/">SPIHT</a> -- <I>Wavelet Natural Image Compressor (12th Feb 1996)</i> <img src="new.gif">
+<br>
+<dd><a href="http://info.lut.ac.uk/departments/el/research/sys/compression.html">Real-Time Lossless Compression Systems</a> -- <i>Loughborough University</i> <img src="new.gif">
+<br>
+<dd><a href="http://saigon.ece.wisc.edu/~waveweb/QMF.html">Web site for Multirate Signal Processing</a> -- <i>University of Wisconsin, Madison</i>
+<br>
+<dd><a href="http://quest.jpl.nasa.gov/Info-ZIP/">Info-ZIP</a> -- <i>free,
+portable Zip and UnZip utilities</i>
+<br>
+<dd><a href="http://cesdis.gsfc.nasa.gov/">CEDIS</a> -- <i>NASA, Maryland, Image/data compression</i>
+<br>
+<dd><a href="http://www.c3.lanl.gov/~brislawn/ftp.html">CIC-3 Image Compression</a> -- <i>FBI Fingerprints</i>
+<br>
+<dd><a href="http://rainbow.ece.ucsb.edu/scl.html">Signal Compression Lab at UCSB</a>
+<br>
+<dd><a href="http://isdl.ee.washington.edu/COMPRESSION/homepage.html">University of
+Washington compression lab</a> -- <I>VQ, Wavelets, Shlomo</i>
+<br>
+</dt>
+
+
+<p>
+<dt>
+<i><b>Snippets</b></i>
+<dd><a href="http://www-isl.stanford.edu/~gray/iii.html">Signal Processing
+and the International Information Infrastructure</a> -- <i>Web sites (22th April 1996)</i> <img src="new.gif">
+<dd><a href="http://www.scu.edu.au/ausweb95/papers/management/vanzyl/">Increasing Web bandwith</a> -- <i>comparing GIF, JPEG, Fractal compression</i>
+<br>
+<dd><a href="http://www.yahoo.com/Art/Computer_Generated/Fractals">Fractal Links on Yahoo</a>
+<br>
+<dd><a href="http://www.ddj.com/old/ddjw001d.htm">Digital Speech Compression GSM 06.10 RPE-LTP</a> -- <i>DDJ</i>
+<br>
+<dd><a href="http://www.crc.ricoh.com/CREW/">CREW</a> -- <i>Continuous tone loss(y/less) wavelet compression</i>
+<br>
+<dd><a href="ftp://ftp.csd.uwo.ca/pub/from_wu/">CALIC -- Context-based adaptive lossless image compressor</a>
+<br>
+<dd><a href="http://www-plateau.cs.berkeley.edu/mpeg/index.html">Berkeley MPEG</a> -- <i>MPEG tools</i>
+<br>
+<dd><a href="http://www.creative.net/~tristan/MPEG">MPEG Pointers and Resources</a>
+<BR>
+</dt>
+
+
+
+
+
+<p>
+<dt>
+<i><b>Wavelets</b></i>
+<dd>
+<a href="http://www.cis.upenn.edu/~eero/epic.html">
+     EPIC (Efficient Pyramid Image Coder)</a> -- <i>by Eero Simoncelli</i>
+<br>
+<dd>
+<a href="mailto://72234.2617@compuserve.com">Tucker, Michael</a> -- <i>FASTWAVE, audio/image compression</i>
+<br>
+<dd>
+<a href="http://www.harc.edu">HARC</a> -- <i>Lossy Wavelet Compression technology</i>
+<br>
+<dd>
+<a href="http://gabor.eecs.berkeley.edu/">UC Berkeley Wavelet Group</a>
+<br>
+<dd>
+<a href="http://www.c3.lanl.gov/~cjhamil/Wavelets/main.html">Khoros Wavetlet and Compression Toolbox</a>
+<br>
+<dd>
+<a href="http://arabigo.math.scarolina.edu:80/~wavelet/">The Wavelet Digest</a>
+<br>
+<dd>
+<a href="http://jazz.rice.edu/publications.html">Rice DSP Publications Archive</a> -- <i>Wavelets, Time Frequency/Scale</i>
+<br>
+</dt>
+
+<p>
+<dt>
+<i><b>Fractals</b></i>
+<dd>
+<a href="http://inls.ucsd.edu/y/Fractals/">Fractal Image Compression</a> -- <i>Software, Pointers, Conferences</i>
+<br>
+<dd>
+<a href="http://www.fractal.com/">Fractal Design Corporation</a>
+<br>
+<dd>
+<a href="http://www.webcom.com/~verrando/university/ifs.html">New Fractal Image Compression program</a>
+<br>
+</dt>
+
+<p>
+<dt>
+<i><b>Companies</b></i>
+<dd><a href="http://www.chips.ibm.com/products/aldc/index.html">IBM Hardware</a> -- <i>Compression chips (11th Mar 1996)</i> <img src="new.gif">
+
+<dd><a href="http://www.summus.com">Summus Wavelet Technology</a> -- <i>Wavelet image and video compressors (11th Mar 1996)</i> <img src="new.gif">
+<dd><a href="http://www.mitsubishi.co.jp/jp/fractal/fractal.html">Fractal Image Compression</a> -- <I>Mitsubishi (18th Feb 1996)</i> <img src="new.gif">
+
+<dd><a href="http://www.terran-int.com/">Terran Interactive</a> -- <i>Video compression for the Mac (1st Feb 1996)</i> <img src="new.gif">
+<br>
+
+<dd><a href="http://darvision.kaist.ac.kr/dvmpeg.html">DV Mpeg</a> -- <i>Windows drivers (18th Feb 1996)</I> <img src="new.gif">
+<br>
+
+<dd><a href="http://www.crawford.com/cs/welcome.html">Crawford Compression Services</a> -- <i>MPEG post-production (18th Feb 1996)</i> <img src="new.gif">
+<br>
+
+<dd><a href="http://www.shore.net/~ict">Intelligent Compression Technologies</a> <i>(18th Feb 1996)</i> <img src="new.gif">
+<br>
+
+<dd><a href="http://www.jpg.com">Pegasus Imaging</a> -- <i>Compression software/dev. kits (12th Feb 1996)</i> <img src="new.gif">
+<br>
+<dd><a href="http://www.aladdinsys.com/">Aladdin Systems</a> -- <i>StuffIt compression products</i>
+<br>
+<dd><a href="http://www.stac.com/">Stac Electronics</a> 
+<br>
+<dd><a href="http://www.ccinet.ab.ca/dcp.html">DCP Research</a> -- <i>Hardware solutions</i>
+<br>
+<dd><a href="http://www.aware.com/product_info/compression_overview.html">Aware Inc.</a> -- <i>Specialised compression company</i>
+<br>
+<dd><a href="http://www.inria.fr/rodeo/ivs.html">IVS - INRIA Videoconferencing System</a>
+<br>
+<dd><a href="http://sp25.ianus.cineca.it/telvox/telvoxen.htm">Telvox Teleinformatica</a> -- <i>Multiplatform Data Compressor</i>
+<br>
+<dd><a href="http://www.compression.com">Compression Technologies,
+Inc</a> -- <i>Canada</i>
+<br>
+<dd><a href="http://www.optivision.com/">Optivision</a> -- <i>MPEG</i>
+<br>
+<dd><a href="http://www.pkware.com/">PKWARE</a> -- <i>Makers of PKZIP</i>
+<br>
+<dd><a href="http://www.infoanalytic.com/tayson/index.html">Multimedia Imaging Services</a>
+<br>
+</dt>
+
+<p>
+<dt>
+<i><b>Audio compression</b></i>
+<dd><a href="http://www.iis.fhg.de/departs/amm/index.html"> Fraunhofer Institut für Integrierte Schaltungen</a> 
+<br>
+<dd><a href="http://svr-www.eng.cam.ac.uk/~ajr/speechCoding.html">Shorten</a>
+<br>
+<dd><a href="http://www.ddj.com/old/ddjw001d.htm">digital speech compression</a> 
+<br>
+<dd><a href="http://www.cs.tu-berlin.de/~phade/audiowww.html">Audio compression references</a> 
+<br>
+<dd><a href="http://www.fourmilab.ch/speakfree/windows/doc/compress.html">SpeakFreely - compression</a> 
+<br>
+<dd><a href="http://www.fourmilab.ch/speakfree/windows/speak_freely.html#contents">SpeakFreely - Contents</a> 
+<br>
diff --git a/snappy/snappy-1.0.5/testdata/fields.c b/snappy/snappy-1.0.5/testdata/fields.c
new file mode 100644 (file)
index 0000000..63cdc03
--- /dev/null
@@ -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 <stdio.h>
+#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 (file)
index 0000000..c4e3e0d
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 (file)
index 0000000..c60a993
--- /dev/null
@@ -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 (file)
index 0000000..6b3aae8
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 (file)
index 0000000..ef768cc
--- /dev/null
@@ -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        <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\r\n<BASE target=\"_top\">\r\n\n<TITLE>Micro Achat : Ordinateurs, PDA -  Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux</TITLE>\r\n<META NAME=\"Description\" CONTENT=\"Micro Achat : Ordinateurs, PDA\">\r\n<META NAME=\"Keywords\" CONTENT=\"Micro Achat : Ordinateurs, PDA -  Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\">\r\n<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"http://www.01net.com/styles/01net.css\">\r\n<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"http://www.01net.com/styles/tableau_autre.css\">\r\n<STYLE type=text/css>\r\nA{TEXT-DECORATION: none;color:#000000;}\r\nA:visited{TEXT-DECORATION: none;color:#000000;}\r\n</STYLE>\r\n<SCRIPT LANGUAGE=\"JavaScript1.1\">\r\nvar sameAsBigDay = new Date();\r\nvar ord = (sameAsBigDay.getTime());\r\nvar pubsMotsCles = \"\";\r\nvar exc;\r\nvar lienhautdepage = \"\";\r\nvar etatmessage = false;\r\nvar enchainement = false;\r\nsas_tmstp=Math.round(Math.random()*10000000000);\r\nfunction SmartAdServer(sas_pageid,sas_formatid,sas_master,sas_target) {\r\n if ((sas_master!=\'M\')&&(sas_master!=\'S\')) {sas_master=\'S\'};\r\n document.write(\'<SCR\'+\'IPT SRC=\"http://www.smartadserver.com/call/pubj/\' + sas_pageid + \'/\' + sas_formatid + \'/\'+sas_master + \'/\' + sas_tmstp + \'/\' + escape(sas_target) + \'?\"></SCR\'+\'IPT>\');\r\n}\r\n</SCRIPT>\r\n<SCRIPT LANGUAGE=\"JAVASCRIPT\" SRC=\"http://www.01net.com/js/exc.js\"></SCRIPT>\r\n<script language=\"javascript\" src=\"http://telecharger.01net.com/shopping/js/headservicesV4.js\"></script>\r\n<noscript>\r\n<a href=\"http://cinema.01net.com\">T\351l\351charger des bandes-annonces, des teasers, des extraits et des making of de vos films cin\351ma pr\351f\351r\351s</a>,\r\n<a href=\"http://www.01net.com/BusinessTechnologies/\">Portail leader de l\'information sur les nouvelles technologies - Actualites et enquetes sur l\'informatique et les NTIC (nouvelles technologies de l\'information et la communication). Exemples de sujets : e-business, telecoms, CRM, VPN, 3G, DSL, fournisseurs d\'acces, Linux, piratage, securite informatique, progiciel...</a><br>\r\n<a href=\"http://www.01net.com/securite_informatique.html\">s\351curit\351 informatique</a>,\r\n<a href=\"http://www.01net.com/strategies_ntic.html\">strat\351gies NTIC</a>,\r\n<a href=\"http://www.01net.com/piratage_informatique.html\">piratage informatique</a>,\r\n<a href=\"http://www.01net.com/technologie_dsl.html\">technologie DSL</a>,\r\n<a href=\"http://www.01net.com/solutions_vpn.html\">solutions VPN</a>,\r\n<a href=\"http://www.01net.com/strategie_e-business.html\">strat\351gies</a>,\r\n<a href=\"http://www.01net.com/outils_crm.html\">outils CRM</a>,\r\n<a href=\"http://www.01net.com/logiciel_linux.html\">logiciel Linux</a>,\r\n<a href=\"http://www.01net.com/fournisseur_d_acces.html\">fournisseur d\'acc\350s</a>,\r\n<a href=\"http://www.01net.com/progiciel.html\">progiciel</a>,\r\n<a href=\"http://www.01net.com/stockage_de_donnees.html\">stockage de donn\351es</a>,\r\n<a href=\"http://www.01net.com/etudes_solution_informatique.html\">\351tudes solution informatique</a>,\r\n<a href=\"http://www.01net.com/NTIC.html\">NTIC</a>,\r\n<a href=\"http://www.01net.com/actualite_technologie.html\">actualit\351 technologie</a>,\r\n<a href=\"http://www.01net.com/etude_materiel_informatique.html\">\351tude mat\351riel informatique</a>,\r\n<a href=\"http://www.01net.com/actus/\">actualit\351s des nouvelles technologies</a>,\r\n<a href=\"http://www.01net.com/MicroPerso/\">enqu\352tes et trucs et astuces sur le mat\351riel informatique, les logiciels, les fournisseurs d\'acc\350s...</a>,\r\n<a href=\"http://www.01net.com/emploi/\">emploi et formations informatiques : offres d\'emploi informatique...</a>,\r\n<a href=\"http://www.01net.com/produits/\">fiches, tests mat\351riels et logiciels en informatique</a>,\r\n<a href=\"http://www.01net.com/01informatique\">01 Informatique</a>,\r\n<a href=\"http://www.caractere.net\">Caract\350re, le site des professionnels de l\'imprim\351 - communication imprim\351e, \351dition, emballage, encres, finition, flexographie, h\351liogravure, impression, imprimerie, imprimeur, industries graphiques, num\351rique, offset, papier, pr\351presse, presse, print, reprographie, s\351rigraphie, typographie</a>,\r\n<a href=\"http://www.01net.com/decisionmicro\">Decision Micro</a>,\r\n<a href=\"http://www.01net.com/decisioninformatique\">D\351cision Informatique</a>,\r\n<a href=\"http://www.01net.com/01reseaux\">01 R\351seaux</a>,\r\n<a href=\"http://logiciel.telecharger.01net.com/\">logiciel</a>,\r\n<a href=\"http://developpeur.telecharger.01net.com/windows/Programmation/\">d\351veloppeur programmation</a>,\r\n<a href=\"http://anti-virus.telecharger.01net.com\">anti-virus</a>,\r\n<a href=\"http://gravure-cd-dvd.telecharger.01net.com/windows/Utilitaire/gravure/\">gravure cd dvd</a>,\r\n<a href=\"http://codec.telecharger.01net.com/windows/Multimedia/encodeurs_et_decodeurs/\">codec encodeur d\351codeur</a>,\r\n<a href=\"http://software.telecharger.01net.com/\">software</a>,\r\n<a href=\"http://logiciels.telecharger.01net.com/\">logiciels</a>,\r\n<a href=\"http://gratuit.telecharger.01net.com/\">gratuit</a>,\r\n<a href=\"http://p2p.telecharger.01net.com/windows/Internet/partage/\">p2p peer to peer partage de fichiers</a>,\r\n<a href=\"http://securite.telecharger.01net.com/windows/Utilitaire/cryptage_et_securite/\">s\351curit\351</a>,\r\n<a href=\"http://compression-decompression.telecharger.01net.com/windows/Utilitaire/compression_et_decompression/\">compression et d\351compression</a>,\r\n<a href=\"http://divx.telecharger.01net.com/\">divx</a>,\r\n<a href=\"http://utilitaire.telecharger.01net.com/windows/Utilitaire/\">utilitaire</a>,\r\n<a href=\"http://jeux.telecharger.01net.com/windows/Jeux/\">jeux</a>,\r\n<a href=\"http://loisirs.telecharger.01net.com/windows/Loisirs/\">loisirs</a>,\r\n<a href=\"http://mac.telecharger.01net.com/mac/\">mac</a>,\r\n<a href=\"http://linux.telecharger.01net.com/linux/\">linux</a>,\r\n<a href=\"http://shareware.telecharger.01net.com/\">shareware</a>,\r\n<a href=\"http://video-dvd.telecharger.01net.com/windows/Multimedia/lecteurs_video_dvd/\">vid\351o dvd</a>,\r\n<a href=\"http://multimedia.telecharger.01net.com/\">multim\351dia</a>,\r\n<a href=\"http://traduction.telecharger.01net.com/windows/Bureautique/traducteur/\">traduction</a>,\r\n<a href=\"http://mp3.telecharger.01net.com/windows/Multimedia/lecteurs_audio_mp3_cd/\">mp3</a>,\r\n<a href=\"http://tchat.telecharger.01net.com/windows/Internet/communication/\">tchat</a>\r\n<a href=\"http://chat.telecharger.01net.com/windows/Internet/communication/\">chat</a>,\r\n<a href=\"http://musique.telecharger.01net.com/\">musique</a>,\r\n<a href=\"http://mobile.telecharger.01net.com/mobile/\">mobile</a>,\r\n<a href=\"http://telephone_portable.telecharger.01net.com/mobile/\">t\351l\351phone portable</a>,\r\n<a href=\"http://telephone_mobile.telecharger.01net.com/mobile/\">t\351l\351phone mobile</a>\r\n</noscript>\r\n</head>\r\n</head>\r\n<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#000000\" marginwidth=0 marginheight=0 topmargin=0 leftmargin=0>\r\n<!-- + ZONE TETE -->\r\n<!-- ********** DEBUT MODELE INTERNE TETES MHA-tetev4 //-->\r\n<table width=100% height=66 cellspacing=0 cellpadding=0 border=0 bgcolor=#ffffff>\r\n\t<tr>\r\n\t\t<td height=8 colspan=2><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=8></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td valign=bottom><a href=\"http://microachat.01net.com\"><img src=\"http://www.01net.com/img/v4/logos_tete/tet_gauche-mha.gif\" border=0></a></td>\r\n\t\t<td valign=bottom bgcolor=#FFFFFF bbackground=\"http://www.01net.com/img/v4/tet_droite.gif\" width=100% style=\"background-image:url(/img/v4/tet_droite-mha.gif);background-position:bottom;background-repeat:repeat-x\"><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=66 align=left hspace=0 vspace=0></td>\r\n\t</tr>\r\n</table>\r\n<table width=100% cellspacing=0 cellpadding=0 border=0 bgcolor=#ffffff>\r\n\t<tr>\r\n\t\t<td valign=top background=\"http://www.01net.com/img/v4/fond_date-mha.gif\" height=18 width=500><img src=\"http://www.01net.com/img/dot.gif\" width=500 height=1><br><img src=\"http://www.01net.com/img/dot.gif\" width=19 height=1><font face=\"Arial\" size=1 color=#666666 style=\"font-size: 11px;\"><b>Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004&nbsp;&nbsp;|&nbsp;&nbsp;16:45</b></font></td>\r\n\t\t<td width=100% background=\"http://www.01net.com/img/v4/fond_date2-mha.gif\" height=18></td>\r\n\t</tr>\r\n</table>\r\n<!-- ********** FIN MODELE INTERNE TETES MHA-tetev4 //--> <!-- - ZONE TETE -->\r\n<!-- ***************************************************************************************************************************************************************************************************************************** //-->\r\n<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n<!-- DEBUT PARTIE PUB //-->\r\n\t<tr>\r\n<td align=center valign=middle colspan=2 background=\"http://www.01net.com/img/v4/fond_bann.gif\"><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br>\r\n<!-- + ZONE Z0 -->\r\n<SCRIPT LANGUAGE=\"JAVASCRIPT\">\r\nvar fa = \"\";\r\nvar fab = document.URL.toString();\r\nif (fab.indexOf(\"?fa\") != -1 || fab.indexOf(\"&fa\") != -1)\r\n{\r\nfa = \";!category=fai\";\r\n}\r\nvar etatmessage = false;\r\nvar enchainement = false;\r\n</SCRIPT>\r\n<SCRIPT LANGUAGE=\"JavaScript1.1\">\r\nsas_pageid=\'167/3872\';\r\nsas_formatid=95;\t\t\t// Format : Banner/Scope 468x60\r\nsas_master=\'M\';\t\t\t// Master : M=master or S=slave\r\nsas_target=exc + \'rubrique\';\t\t\t// Targeting\r\nSmartAdServer(sas_pageid,sas_formatid,sas_master,sas_target);\r\n</SCRIPT>\r\n <!-- - ZONE Z0 --></td>\r\n\t\t<td valign=top width=23 background=\"http://www.01net.com/img/v4/sep_verticale.gif\" ><img src=\"http://www.01net.com/img/dot.gif\" width=23 height=1><br></td>\r\n<td valign=top width=100% bgcolor=\"ffffff\" rowspan=3><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=125><br>\r\n<!-- +ZONE_Dn -->\r\n<!-- + ZONE D0 -->\r\n<!-- DEBUT MA_ColD -->\r\n<div style=\"background-color : #ffffff; width : 150px; padding-left : 5px; padding-right : 5px; font-family : Arial, Helvetica;\">\n\t\t\t\t\t<table style=\"border-spacing : 0; width : 146px; margin-top : 0px;\" cellspacing=\"0\">\n\t\t\t\t\t<tr><th colspan=\"2\" style=\"padding : 0;\"><img src=\"http://micro-achat.01net.com/img/utils/micro-achat/tete-produitsrecherches.gif\" alt=\"\" /></th></tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Imagerie&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/12537-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/imagerie/moniteurs-lcd/l1720b/\">LG L1720B</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">332.89 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Ordinateurs&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/4043-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/desktops/veriton-7600g/\">Acer Veriton 7600G</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">705 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Ordinateurs&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/1903-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/sn95g5/\">Shuttle SN95G5</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">375 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Composants&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/1259-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/composants/cartes-meres/a7n8x-e-deluxe/\">Asus A7N8X-E Deluxe</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">91.99 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Composants&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/4687-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/composants/ventilateur/sp-94/\">Thermalright SP-94</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">49 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr></table>\n\t\t\t\t<table style=\"border-spacing : 0px 1px; width : 146px; margin-top : 15px;\" cellspacing=\"0\">\n\t\t\t\t<tr><th colspan=\"2\" style=\"padding : 0;\"><img src=\"http://micro-achat.01net.com/img/utils/micro-achat/tete-revendeurmisajour.gif\" alt=\"\" /></th></tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">1 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Rhone-Alpes/Ain/pc-look\" style=\"color : #000000; text-decoration : none;\">PC Look</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">2 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Nord-Pas-de-Calais/Pas-de-Calais/atelier-informatique\" style=\"color : #000000; text-decoration : none;\">Atelier Informatique</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">3 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Val-de-Marne/zanax-multimedia\" style=\"color : #000000; text-decoration : none;\">Zanax Multim\351dia</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">4 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Hauts-de-Seine/misteroops\" style=\"color : #000000; text-decoration : none;\">MISTEROOPS</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">5 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/12/168-golden-avenue\" style=\"color : #000000; text-decoration : none;\">168 Golden Avenue</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">6 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Seine-Saint-Denis/microchoix\" style=\"color : #000000; text-decoration : none;\">microchoix</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">7 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/12/e-soph\" style=\"color : #000000; text-decoration : none;\">e-Soph</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">8 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/13/pc-price-club\" style=\"color : #000000; text-decoration : none;\">PC Price Club</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">9 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Seine-et-Marne/pc-77\" style=\"color : #000000; text-decoration : none;\">PC 77</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">10 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Alsace/Bas-Rhin/web-in-informatique\" style=\"color : #000000; text-decoration : none;\">Web In Informatique</a></td>\n\t\t\t\t</tr></table>\n\t\t\t\t</div>\n\t\t\t\t<br>\r\n<!-- FIN MA_ColD --> <!-- - ZONE D0 -->\r\n<!-- + ZONE D1 -->\r\n<!-- - ZONE D1 -->\r\n<!-- + ZONE D2 -->\r\n<!-- - ZONE D2 -->\r\n<!-- -ZONE_Dn -->\r\n</td>\r\n\t</tr>\r\n<!-- FIN PARTIE PUB //-->\r\n\t<tr>\r\n\t\t<td valign=top width=193 height=100% background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n\t\t<!-- contenu colonne de gauche //-->\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0  background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n<!-- +ZONE_Gn -->\r\n<!-- + ZONE G0 -->\r\n<tr><!-- ********** DEBUT MHA_MenusChainesV4 //-->\r\n<td valign=top>\n<table border=0 cellpadding=0 cellspacing=0 width=193 bgcolor=#FFFFFF>\n<tr>\n<td background=\"/img/v4/menus/motifgauche_menus.gif\" width=20 rowspan=2><img src=\"/img/dot.gif\" width=20 height=20></td>\n<td width=173 colspan=2 bgcolor=#FFFFFF><img src=\"/img/dot.gif\" width=173 height=20></td>\n</tr>\n<tr>\n<td valign=top width=159>\n\n<a href=\"http://www.01net.com\"><img src=\"/img/v4/menus/mha/home01net-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com\"><img src=\"/img/v4/menus/mha/home-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4317.html\"><img src=\"/img/v4/menus/mha/ordinateurs-2.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4318.html\"><img src=\"/img/v4/menus/mha/composants-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4319.html\"><img src=\"/img/v4/menus/mha/stockage-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4320.html\"><img src=\"/img/v4/menus/mha/image-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4321.html\"><img src=\"/img/v4/menus/mha/peripheriques-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4322.html\"><img src=\"/img/v4/menus/mha/reseaux-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4323.html\"><img src=\"/img/v4/menus/mha/accessoires-1.gif\" width=159 border=0></a><br>\n<a href=\"http://micro-achat.01net.com/guide-produits/\"><img src=\"/img/v4/menus/mha/comparateur-1.gif\" width=159 border=0></a><br>\n<a href=\"http://micro-achat.01net.com/annuaire/\"><img src=\"/img/v4/menus/mha/annuaire-1.gif\" width=159 border=0></a><br></td>\n<td width=14><img src=\"/img/dot.gif\" width=14 height=14></td>\n</tr>\n<tr>\n<td colspan=3><img src=\"/img/v4/menus/bas_menus.gif\" width=193 height=31></td>\n</tr>\n</table></td><!-- ********** FIN MHA_MenusChainesV4 //--> </tr><!-- - ZONE G0 -->\r\n<!-- + ZONE G1 -->\r\n<tr><!-- DEBUT MODELE RUBRIQUE V4ColGaucheMHA //-->\r\n<!-- ********** DEBUT BLOC DernieresNewsTC //-->\r\n<td valign=top>\r\n<!-- DEBUT RECHERCHE MHA -->\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n\t\t\t<td valign=top background=\"http://microachat.01net.com/img/v4/fond_rech_mha.gif\" height=98 style=\"background-repeat:no-repeat;\"><form method=\"get\" name=\"chercher\" action=\"http://www.01net.com/aiguillage_recherche/1,6138,,00.html\"><img src=\"http://microachat.01net.com/img/dot.gif\" width=193 height=17><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><input type=\"text\" name=\"fullText\" style=\"width:130px;font:12px;\"><br><img src=\"http://microachat.01net.com/img/dot.gif\" width=1 height=6><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><select name=\"sousArbo\" style=\"width:130px;font:12px;\">\r\n\t\t\t<option value=\"mha\">dans Micro Achat\r\n\t\t\t<option value=\"cmp\">les prix\r\n\t\t\t<option value=\"ann\">les revendeurs\r\n\t\t\t<option value=\"2641\">tout 01net.\r\n\t\t\t<option value=\"emploi\">les offres d\'emploi\r\n\t\t\t<option value=\"telecharger\"> telecharger.com\r\n\t\t\t<option value=\"web\">le web\r\n\t\t\t</select><br><img src=\"http://microachat.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"http://microachat.01net.com/img/v4/ok_bloc_recher_mha.gif\" border=\"0\"></form>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=10 vspace=0>\r\n<!-- FIN RECHERCHE MHA -->\r\n      <!-- modele TCFilColgTitV4 //-->\r\n    <table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top>\r\n\t\t<table width=155 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=2><img src=\"http://www.01net.com/img/ban/Ban_v4_DernieresNews01net.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4></td>\r\n\t\t\t</tr>\r\n\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/256059.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">CD et DVD bient\364t insensibles aux rayures<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/255796.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">OpenOffice gagne son service<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/255731.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">La messagerie en cinq minutes selon Ipswitch<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top colspan=2><A HREF=\"http://www.01net.com/actus/\" style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\">> toutes les news<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t\t<tr>\r\n\t\t\t\t<td colspan=2><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/crochet_bleuhaut_155.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20> <!-- ********** FIN BLOC DernieresNewsTC //-->\r\n<!-- ********** DEBUT BLOC  NL_MHA //-->\r\n<SCRIPT language=\"javascript\" src=\"http://www.01net.com/js/lib.js\"></SCRIPT>\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<FORM name=\"formgen\" method=\"get\" action=\"http://microachat.01net.com/outils/newsletter_MicroAchat.html\" onSubmit=\"return validateForm(this)\">\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=155 colspan=4><img src=\"http://www.01net.com/img/ban/Ban_V4_Newslett.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=10><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=1 bgcolor=#CC0000><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t<td width=153>\r\n\t\t<table width=153 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=10><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t\t\t<td valign=top><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefinefd_ffffff.gif\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Recevez chaque jour l\'actualit\351 des produits et des promos<br></font>\r\n\t\t\t\t<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td><input type=\"text\" name=\"email\" size=\"14\" style=\"width:130px;font:12px;\" value=\"entrez votre e-mail\" onFocus=\"javascript:document.formgen.email.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"http://www.01net.com/img/v4/ok_bloc_recher.gif\" border=\"0\"></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td width=1 bgcolor=#CC0000><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=155 colspan=4><img src=\"http://www.01net.com/img/v4/base_newsletters.gif\"></td>\r\n\t\t</FORM>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20>\r\n<SCRIPT language=\"Javascript\">\r\ndocument.formgen.email.validator= \'notNullEmailPat\';\r\ndocument.formgen.email.nomvalidator= \'E-mail\';\r\n</SCRIPT>\r\n<!-- ********** FIN BLOC NL_MHA //-->\r\n</td>\r\n</tr>\r\n<tr>\r\n<!-- ********** DEBUT BLOC Actus ActusUneV4 //-->\r\n<td valign=top background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n<table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top>\r\n\t\t<table width=155 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/ban/Ban_v4_LaUne.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/entreprise/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Entreprise</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://www.01net.com/article/255737.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">Quand le billet papier s\'envole vers la d\351mat\351rialisation</font></a></td>\r\n\t\t\t\t<td valign=top width=2><img src=\"http://www.01net.com/img/dot.gif\" width=2 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/article/255737.html\"><img src=\"http://www.01net.com/img/MEA_v4/billet_virtuel-65.jpg\" border=0></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/pratique/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Trucs et astuces</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255698.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">D\351pannez Windows XP</font></a></td>\r\n\t\t\t\t<td valign=top width=2><img src=\"http://www.01net.com/img/dot.gif\" width=2 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/article/255698.html\"><img src=\"http://www.01net.com/img/MEA_v4/depannez_XP-65.jpg\" border=0 ></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t</tr>\r\n\t\t    <tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top colspan=3><a href=\"http://www.01net.com/conso/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Conso</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255524.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">Vos photos sur papier imprimante ou labo ?<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t<!-- exemple de lien avec pseudorub pour produits et tests -->\r\n\t\t<!-- <a href=\"/outils/PseudoRub.php?base=test-comp&rub=1730&pseudo=test-comp20041005\"> -->\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top colspan=3><a href=\"http://www.01net.com/produits/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Produits &amp; Tests</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255782.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">5 programmes d\222encodage vid\351o gratuits<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20>\r\n</td>\r\n<!-- ********** FIN BLOC Actus ActusUneV4 //-->    </tr>\r\n<tr>\r\n<td>\r\n<table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top><a href=\"mailto:s.cohen@micro-achat.fr\"><img border=0 src=\"http://www.01net.com/img/v4/espace-revendeurs.gif\"></td>\r\n\t</tr>\r\n</table>\r\n<br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20></td>\r\n<!-- FIN MODELE RUBRIQUE V4ColGaucheMHA //-->  </tr><!-- - ZONE G1 -->\r\n<!-- + ZONE G2 -->\r\n<!-- - ZONE G2 -->\r\n<!-- + ZONE G3 -->\r\n<!-- - ZONE G3 -->\r\n<!-- + ZONE G4 -->\r\n<!-- - ZONE G4 -->\r\n<!-- + ZONE G5 -->\r\n<!-- - ZONE G5 -->\r\n<!-- + ZONE G6 -->\r\n<!-- - ZONE G6 -->\r\n<!-- + ZONE G7 -->\r\n<!-- - ZONE G7 -->\r\n<!-- + ZONE G8 -->\r\n<!-- - ZONE G8 -->\r\n<!-- + ZONE G9 -->\r\n<!-- - ZONE G9 -->\r\n<!-- + ZONE GA -->\r\n<!-- - ZONE GA -->\r\n<!-- + ZONE GB -->\r\n<!-- - ZONE GB -->\r\n<!-- + ZONE GC -->\r\n<!-- - ZONE GC -->\r\n<!-- + ZONE GD -->\r\n<!-- - ZONE GD -->\r\n<!-- + ZONE GE -->\r\n<!-- - ZONE GE -->\r\n<!-- + ZONE GF -->\r\n<!-- - ZONE GF -->\r\n<!-- -ZONE_Gn -->\r\n\t\t</table>\r\n\t\t<!-- fin contenu colonne de gauche //-->\r\n\t\t</td>\r\n<!-- ***************************************************************** DEBUT VENTRE*********************************************************************************************************************************************** //-->\r\n<!-- DEBUT WORK -->\r\n\t\t<td valign=top width=625 bgcolor=#ffffff><img src=\"http://www.01net.com/img/dot.gif\" width=625 height=1><br>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_hn -->\r\n<!-- + ZONE h0 -->\r\n<!-- MA_ban_int -->\r\n<td valign=\"top\">\r\n<img src=\"/img/dot.gif\" height=\"18\"><br>\r\n<!-- pour ordipda -->\r\n<table width=\"625\" cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"/img/v4/MA/Ban_MA_ordis.gif\"></td>\r\n\t</tr>\r\n</table>\r\n\t</td>\r\n<!-- /MA_ban_int -->     <!-- - ZONE h0 -->\r\n<!-- + ZONE h1 -->\r\n<!-- - ZONE h1 -->\r\n<!-- + ZONE h2 -->\r\n<!-- - ZONE h2 -->\r\n<!-- -ZONE_hn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_Hn -->\r\n<!-- + ZONE H0 -->\r\n<!-- Ma_int_Leader -->\r\n    <td valign=top>\r\n<img src=\"/img/dot.gif\" width=1 height=18><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=320>\r\n<tr>\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<td width=144 valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=143 height=1 vspace=0><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:11px;>Portable</font><br>\r\n<A HREF=\"/article/256198.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=font-size:14px;><b>Un nouvel ultra portable r\351alis\351 par Nec</b></font></a><br>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/256198.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67509.jpg.res_100-100.jpg\" border=0 hspace=0 vspace=0></a><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n<font face=arial,helvetica size=2 color=#000000 style=font-size:12px;><img src=\"/img/v4/flechefine_fondtransp.gif\">Le Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.</font><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:12px;>\340 partir de 1663&#160;\200</font>\r\n</td>\r\n<td width=17 background=\"/img/v4/MA/v4-fond-sep-mea-leader.gif\"><img src=\"/img/dot.gif\" width=17 height=1></td>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<td width=144 valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=143 height=1 vspace=0><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:11px;>Portable</font><br>\r\n<A HREF=\"/article/255194.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=font-size:14px;><b>Asus pr\351sente trois petits nouveaux dans la gamme A3N</b></font></a><br>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255194.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67168.jpg.res_100-100.jpg\" border=0 hspace=0 vspace=0></a><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n<font face=arial,helvetica size=2 color=#000000 style=font-size:12px;><img src=\"/img/v4/flechefine_fondtransp.gif\">Ces trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.</font><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:12px;>\340 partir de 1346&#160;\200</font>\r\n</td>\r\n<td width=15><img src=\"/img/dot.gif\" width=15 height=1></td>\r\n\t\t\t\t</tr>\r\n</table>\r\n</td>\r\n<!-- /Ma_int_Leader -->    <!-- - ZONE H0 -->\r\n<!-- + ZONE H1 -->\r\n<!-- - ZONE H1 -->\r\n<!-- + ZONE H2 -->\r\n<!-- MA_BP_MP -->\r\n<td valign=\"top\" width=\"100%\">\r\n\t<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\r\n\t<tr>\r\n\t<td width=\"50%\" valign=\"top\">\r\n\t<!-- DEBUT MicroAchat MA_BonPlan -->\r\n<td valign=top>\r\n<img src=\"/img/dot.gif\" width=1 height=18><br>\r\n<table border=0 cellpadding=1 cellspacing=0 width=145 bgcolor=#CC0000>\r\n<tr>\r\n<td align=center><font face=arial,helvetica size=1 color=#FFFFFF style=\"font-size:11px;\">BON PLAN</a></font></td>\r\n</tr>\r\n<tr>\r\n<td  width=145>\r\n<div style=\"padding:5px;padding-left:5px;padding-fight:5px;margin:0px;margin-left:1px;margin-right:1px;background-color:#FFFFFF;\">\r\n<img src=\"/img/microachat/logo_shuttle_SB83G5.gif\" border=0><br>\r\n<font face=arial,helvetica size=2 color=#CC0000 style=\"font-size:12px;\">Les derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.<br></font>\r\n<center><a href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/sb83g5/?fabriquant=1&page=1&tri=titre\"><img src=\"/img/microachat/mea_shuttle_SB83G5.gif\" border=0 vspace=5></a><br></center>\r\n<center>\r\n<font face=arial,helvetica size=2 color=#CC0000 style=\"font-size:13px;\"><b>\340 partir de</b><br>\r\n<div style=\"border:solid 2px #CC0000;width:100px;background-color:#FFCC00;\"><b>415 \200</b></div>\r\n</center>\r\n</div>\r\n</td>\r\n</tr>\r\n<tr>\r\n<td align=center><font face=arial,helvetica size=1 color=#FFFFFF style=\"font-size:11px;\">publicit\351</a></font></td>\r\n</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_BonPlan -->  \t</td>\r\n\t<td width=\"15\"><img src=\"/img/dot.gif\" width=\"15\"></td>\r\n\t<td width=\"50%\" valign=\"top\">\r\n\t<!-- DEBUT MicroAchat MA_MeillPrixAct //-->\r\n<td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=145 height=1><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=18><br>\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<FORM name=\"prix\" action=\"http://www.micro-achat.01net.com/guide-produits/recherche.php\" method=\"post\">\r\n\t\t<td width=145 colspan=3><img src=\"http://www.01net.com/img/ban/Ban_v4_MeillPrix_MA.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=1 bgcolor=#FFCC00><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t<td width=143>\r\n\t\t<table width=143 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=6><img src=\"http://www.01net.com/img/dot.gif\" width=6 height=1></td>\r\n\t\t\t\t<td valign=top><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=15><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<img src=\"http://www.01net.com/img/ban/Ban_MA_trouv_ordi.gif\"><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/desktops/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Desktops</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/portables/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Portables</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Mini-PC</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/pda---tablets-pc/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Pda / Tablets-PC</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/apple/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Apple</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/gps/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">GPS</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20><br>\r\n\t\t\t\t\t\t\t\t<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td><input type=\"text\" name=\"recherchedirecte\" size=\"14\" style=\"width:130px;font:12px;\" value=\"     recherche directe\" onFocus=\"javascript:document.prix.recherchedirecte.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"/img/v4/MA/ok_bloc_recher_MA.gif\" border=\"0\"></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td width=1 bgcolor=#FFCC00><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=145 colspan=3><img src=\"http://www.01net.com/img/v4/MA/base_meillPrix.gif\"></td>\r\n\t\t</FORM>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_MeillPrixAct //-->  \t</td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n<!-- /MA_BP_MP -->  <!-- - ZONE H2 -->\r\n<!-- -ZONE_Hn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_Tn -->\r\n<!-- + ZONE T0 -->\r\n    <td valign=\"top\">\r\n<img src=\"http://www.01net.com/img/dot.gif\" height=13><br>\r\n<table border=0 width=320 cellpadding=0 cellspacing=0>\r\n<tr>\r\n<td width=305><img src=\"http://www.01net.com/img/ban/Ban_v4_DernNews_MA.gif\"><br><img src=\"http://www.01net.com/img/v4/MA/v4-tiret-hauts-mha.gif\"></td>\r\n<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n</tr>\r\n<tr>\r\n<td bgcolor=\"#FEF9E0\">\r\n\t<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Portable&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255149.html\" style=\"color:#000000;text-decoration:none;\">Toshiba consacre deux gammes de machines au multim\351dia</a></b><br>\r\n\t<font color=\"#000000\">Equipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Ordinateur&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254686.html\" style=\"color:#000000;text-decoration:none;\">Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme</a></b><br>\r\n\t<font color=\"#000000\">La firme \340 la pomme propose une station de travail \351volutive et relativement abordable.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>PC&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254549.html\" style=\"color:#000000;text-decoration:none;\">Alienware propose deux machines au look \351trange</a></b><br>\r\n\t<font color=\"#000000\">Aurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Portable&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254501.html\" style=\"color:#000000;text-decoration:none;\">Trois nouveaux iBook G4 chez Apple</a></b><br>\r\n\t<font color=\"#000000\">Chez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t\t<tr>\r\n\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=10></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-red-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td align=\"right\">\r\n\t\t\t\t<A HREF=\"http://microachat.01net.com/rubrique/4365.html\"  style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 10px;\">> toutes les news</font></a>\r\n\t\t\t</td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n</td> <!-- - ZONE T0 -->\r\n<!-- + ZONE T1 -->\r\n<!-- Ma_derpromo  -->\r\n    <td valign=\"top\">\r\n<img src=\"/img/dot.gif\" height=13><br>\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td bgcolor=\"#ffffff\"><img src=\"/img/v4/MA/v4-lespromos-mha.gif\"><br><img src=\"/img/v4/MA/v4-tiret-hauts-mha.gif\"></td>\r\n</tr>\r\n</table>\r\n<!-- DEBUT MODELE D\'AFFICHAGE POUR LES n PREMIERS ARTICLES //-->\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255806.html\" class=\"nodeco\"><img src=\"/images/67462.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255806.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>Asus A3N15-C Pro</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>1170&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255688.html\" class=\"nodeco\"><img src=\"/images/67381.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255688.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>Soltek EQ3702A Miroir</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>559&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255513.html\" class=\"nodeco\"><img src=\"/images/67319.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255513.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>IBM ThinkPad R51</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Voici un portable complet et pourtant relativement l\351ger.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>1299&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t\t<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td><img src=\"http://www.01net.com/img/dot.gif\" height=10></td>\r\n</tr>\r\n<tr>\r\n<td background=\"/img/v4/MA/v4-sep-red-mha.gif\"><img src=\"/img/dot.gif\" height=1></td>\r\n</tr>\r\n<tr>\r\n<td align=\"right\" valign=\"top\">\r\n\t\t\t\t<A HREF=\"http://microachat.01net.com/rubrique/4366.html\"  style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 10px;\">> toutes les promos</font></a>\r\n\t\t</td>\r\n</tr>\r\n</table>\r\n</td>\r\n<!-- /Ma_derpromo  -->   <!-- - ZONE T1 -->\r\n<!-- + ZONE T2 -->\r\n<!-- - ZONE T2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE T3 -->\r\n<!-- DEBUT MicroAchat MA_PubG -->\r\n<td valign=top align=center>\r\n<table border=0 width=320 cellpadding=0 cellspacing=0>\r\n\t<tr>\r\n\t\t<td width=305><img src=\"/img/dot.gif\" width=1 height=12><br><a href=\"http://www.smartadserver.com/call/cliccommand/45590/[timestamp]?\" target=_blank><img src=\"/img/microachat/Bandeau_FX6021.jpg\" border=0></a></td>\r\n\t\t<td><img src=\"/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_PubG -->  <!-- - ZONE T3 -->\r\n<!-- + ZONE T4 -->\r\n<!-- DEBUT MicroAchat MA_PubD -->\r\n<td valign=top align=center>\r\n<table border=0 width=305 cellpadding=0 cellspacing=0>\r\n\t<tr>\r\n\t\t<td width=305><img src=\"/img/dot.gif\" width=1 height=12><br><a href=\"http://www.smartadserver.com/call/cliccommand/45591/[timestamp]?\" target=_blank><img src=\"/img/microachat/twc_305x125.jpg\" border=0></a></td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN  MicroAchat MA_PubD --> <!-- - ZONE T4 -->\r\n<!-- + ZONE T5 -->\r\n<!-- - ZONE T5 -->\r\n<!-- -ZONE_Tn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n\t\t\t<td valign=top>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n<!-- +ZONE_gn -->\r\n<!-- + ZONE g0 -->\r\n<!-- - ZONE g0 -->\r\n<!-- + ZONE g1 -->\r\n<!-- - ZONE g1 -->\r\n<!-- + ZONE g2 -->\r\n<!-- - ZONE g2 -->\r\n<!-- + ZONE g3 -->\r\n<!-- - ZONE g3 -->\r\n<!-- + ZONE g4 -->\r\n<!-- - ZONE g4 -->\r\n<!-- + ZONE g5 -->\r\n<!-- - ZONE g5 -->\r\n<!-- + ZONE g6 -->\r\n<!-- - ZONE g6 -->\r\n<!-- + ZONE g7 -->\r\n<!-- - ZONE g7 -->\r\n<!-- + ZONE g8 -->\r\n<!-- - ZONE g8 -->\r\n<!-- + ZONE g9 -->\r\n<!-- - ZONE g9 -->\r\n<!-- -ZONE_gn -->\r\n\t\t\t</table>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t\t\t<tr>\r\n<!-- +ZONE_Mn -->\r\n<!-- + ZONE M0 -->\r\n<!-- modele Ma_GuideAch //-->\r\n    <td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" height=13><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t<tr>\r\n\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_GuideAchat_MA.gif\" vspace=1></td>\r\n\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<div style=\"border:solid 1px #FFCC00;width:100%\">\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<center>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"http://microachat.01net.com/article/254561.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67088.jpg.res_121-111.jpg\" border=0 hspace=0 vspace=0></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n</center>\r\n<div style=\"padding:5px;\">\r\n<a href=\"http://microachat.01net.com/article/254561.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\"><b>Les graveurs de DVD</b><br></font></a>\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">Quel graveur choisir&#160;? Quel type de format&#160;? Quelle vitesse&#160;? Double couche ou simple couche&#160;? Voici tout ce qu\'il faut savoir pour faire le bon choix.</font></div>\r\n\t\t\t\t\t\t</div>\r\n\t\t</td>\r\n\t</tr>\r\n</table>\r\n</td> <!-- - ZONE M0 -->\r\n<!-- + ZONE M1 -->\r\n<!-- modele Ma_DirectLab //-->\r\n    <td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t<tr>\r\n\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_DirectLab_MA.gif\" vspace=1></td>\r\n\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<div style=\"border:solid 1px #FFCC00;width:100%\">\r\n\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255744.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>Kodak EasyShare Printer Dock Plus&#160;:</b>\r\n\t\t\t\t\t\tvos photos 10&#160;x&#160;15&#160;cm en 60&#160;secondes</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255780.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>3DMark05&#160;:</b>\r\n\t\t\t\t\t\tun labo 3D \340 domicile</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255691.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>DVDInfoPro 2.6</b>\r\n\t\t\t\t\t\treconna\356t CD et DVD</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255722.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>Scaleo PA D3008, de Fujitsu-Siemens&#160;:</b>\r\n\t\t\t\t\t\tune impression d\'inachev\351</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255514.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">Carbon 5&#160;Go&#160;: 2&#160;500&#160;chansons dans le creux de la main</font></a></div>\r\n\t\t\t</div></td>\r\n\t</tr>\r\n</table>\r\n</td> <!-- - ZONE M1 -->\r\n<!-- + ZONE M2 -->\r\n<!-- DEBUT MicroAchat MA_AnnTelec -->\r\n<td valign=top>\r\n<script type=\"text/javascript\">\r\nfunction regionChange()\r\n{\r\ndocument.selection.departement.options.length=0;\r\nswitch(document.selection.region.value)\r\n\t{\r\n\t\tcase \"aucun\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Nord-Pas-de-Calais\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pas-de-Calais\", \"Pas-de-Calais\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Nord\", \"Nord\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Haute-Normandie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Eure\", \"Eure\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-Maritime\", \"Seine-Maritime\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Basse-Normandie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Manche\", \"Manche\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Calvados\", \"Calvados\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Orne\", \"Orne\");\r\n\t\tbreak;\r\n\t\tcase \"Picardie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Somme\", \"Somme\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Oise\", \"Oise\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aisne\", \"Aisne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Bretagne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Finistere\", \"Finistere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cotes-dArmor\", \"Cotes-dArmor\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Morbihan\", \"Morbihan\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ille-et-Vilaine\", \"Ille-et-Vilaine\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Pays-de-Loire\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loire-Atlantique\", \"Loire-Atlantique\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vendee\", \"Vendee\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Maine-et-Loire\", \"Maine-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Mayenne\", \"Mayenne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Sarthe\", \"Sarthe\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Centre\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Eure-et-Loir\", \"Eure-et-Loir\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loiret\", \"Loiret\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loir-et-Cher\", \"Loir-et-Cher\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Indre-et-Loire\", \"Indre-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Indre\", \"Indre\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cher\", \"Cher\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Ile-de-France\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Val-dOise\", \"Val-dOise\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Yvelines\", \"Yvelines\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Essonne\", \"Essonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-et-Marne\", \"Seine-et-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hauts-de-Seine\", \"Hauts-de-Seine\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-Saint-Denis\", \"Seine-Saint-Denis\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Val-de-Marne\", \"Val-de-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Paris\", \"Paris\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Champagnes-Ardennes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ardennes\", \"Ardennes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Marne\", \"Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aube\", \"Aube\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Marne\", \"Haute-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Lorraine\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vosges\", \"Vosges\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Meurthe-et-Moselle\", \"Meurthe-et-Moselle\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Meuse\", \"Meuse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Moselle\", \"Moselle\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Alsace\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Bas-Rhin\", \"Bas-Rhin\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haut-Rhin\", \"Haut-Rhin\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Franche-Compte\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Jura\", \"Jura\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Doubs\", \"Doubs\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Saone\", \"Haute-Saone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Territoire-de-Belfort\", \"Territoire-de-Belfort\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Bourgogne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Yonne\", \"Yonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Nievre\", \"Nievre\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cote-dOr\", \"Cote-dOr\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Saone-et-Loire\", \"Saone-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Poitou-Charentes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Deux-Sevres\", \"Deux-Sevres\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Charente-Maritime\", \"Charente-Maritime\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Charente\", \"Charente\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vienne\", \"Vienne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Limousin\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Vienne\", \"Haute-Vienne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Correze\", \"Correze\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Creuse\", \"Creuse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Auvergne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Allier\", \"Allier\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Puy-de-Dome\", \"Puy-de-Dome\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cantal\", \"Cantal\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Loire\", \"Haute-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Rhone-Alpes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loire\", \"Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Rhone\", \"Rhone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ain\", \"Ain\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ardeche\", \"Ardeche\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Drome\", \"Drome\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Isere\", \"Isere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Savoie\", \"Savoie\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Savoie\", \"Haute-Savoie\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Aquitaine\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gironde\", \"Gironde\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Landes\", \"Landes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pyrenees-Atlantiques\", \"Pyrenees-Atlantiques\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lot-et-Garonne\", \"Lot-et-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Dordogne\", \"Dordogne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Midi-Pyrenees\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lot\", \"Lot\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Tarn-et-Garonne\", \"Tarn-et-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gers\", \"Gers\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hautes-Pyrenees\", \"Hautes-Pyrenees\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Garonne\", \"Haute-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ariege\", \"Ariege\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Tarn\", \"Tarn\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aveyron\", \"Aveyron\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Languedoc-Roussillon\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pyrenees-Orientales\", \"Pyrenees-Orientales\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aude\", \"Aude\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Herault\", \"Herault\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gard\", \"Gard\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lozere\", \"Lozere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Provence-Alpes-Cote-dazur\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Bouches-du-Rhone\", \"Bouches-du-Rhone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vaucluse\", \"Vaucluse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Alpes-de-haute-Provence\", \"Alpes-de-haute-Provence\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hautes-Alpes\", \"Hautes-Alpes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Var\", \"Var\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Alpes-Maritimes\", \"Alpes-Maritimes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Corse\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Corse-du-Sud\", \"Corse-du-Sud\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Corse\", \"Haute-Corse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"DomTom\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Guadeloupe\", \"Guadeloupe\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Guyane\", \"Guyane\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"La-Reunion\", \"La-Reunion\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Martinique\", \"Martinique\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Mayotte\", \"Mayotte\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"St-Pierre-et-Miquelon\", \"St-Pierre-et-Miquelon\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t}\r\n}\r\nfunction deptChange()\r\n{\r\nif (document.selection.departement.value == \'Paris\')\r\n\tdocument.getElementById(\'arrondissement\').style.display = \'inline\';\r\nelse\r\n\tdocument.getElementById(\'arrondissement\').style.display = \'none\';\r\n}\r\n</script>\r\n<table width=305 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td valign=top>\r\n\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_AnnuaiRev_MA.gif\" vspace=1></td>\r\n\t\t\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr><form action=\"http://micro-achat.01net.com/annuaire/recherche.php\" method=\"post\" name=\"selection\">\r\n\t\t\t\t<td bgcolor=#FFFFDD>\r\n\t\t\t\t<div style=\"border:solid 1px #FFCC00;width:100%\"><div style=\"padding:2px;\"><img src=\"http://www.01net.com/img/v4/MA/carte_revend.gif\"><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Choisir une r\351gion</b><br></font>\r\n<select name=\"region\" onChange=\"regionChange()\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"aucun\">-------------</option>\r\n<option value=\"Nord-Pas-de-Calais\">Nord-Pas-de-Calais</option>\r\n<option value=\"Haute-Normandie\">Haute-Normandie</option>\r\n<option value=\"Basse-Normandie\">Basse-Normandie</option>\r\n<option value=\"Picardie\">Picardie</option>\r\n<option value=\"Bretagne\">Bretagne</option>\r\n<option value=\"Pays-de-Loire\">Pays-de-Loire</option>\r\n<option value=\"Centre\">Centre</option>\r\n<option value=\"Ile-de-France\">Ile-de-France</option>\r\n<option value=\"Champagnes-Ardennes\">Champagne ardennes</option>\r\n<option value=\"Lorraine\">Lorraine</option>\r\n<option value=\"Alsace\">Alsace</option>\r\n<option value=\"Franche-Compte\">Franche-Compte</option>\r\n<option value=\"Bourgogne\">Bourgogne</option>\r\n<option value=\"Poitou-Charentes\">Poitou-Charentes</option>\r\n<option value=\"Limousin\">Limousin</option>\r\n<option value=\"Auvergne\">Auvergne</option>\r\n<option value=\"Rhone-Alpes\">Rhone-Alpes</option>\r\n<option value=\"Aquitaine\">Aquitaine</option>\r\n<option value=\"Midi-Pyrenees\">Midi-Pyrenees</option>\r\n<option value=\"Languedoc-Roussillon\">Languedoc roussillon</option>\r\n<option value=\"Provence-Alpes-Cote-dazur\">PACA</option>\r\n<option value=\"Corse\">Corse</option>\r\n<option value=\"DomTom\">DomTom</option>\r\n</select>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Un d\351partement</b><br></font>\r\n<select name=\"departement\" onChange=\"deptChange()\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"aucun\">-------------</option>\r\n</select>\r\n<div id=\"arrondissement\" style=\"display : none;\">\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Un arrondissement</b><br></font>\r\n<select name=\"arrondissement\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"0\">-------------</option>\r\n<option value=\"1\">I</option>\r\n<option value=\"2\">II</option>\r\n<option value=\"3\">III</option>\r\n<option value=\"4\">IV</option>\r\n<option value=\"5\">V</option>\r\n<option value=\"6\">VI</option>\r\n<option value=\"7\">VII</option>\r\n<option value=\"8\">VIII</option>\r\n<option value=\"9\">IX</option>\r\n<option value=\"10\">X</option>\r\n<option value=\"11\">XI</option>\r\n<option value=\"12\">XII</option>\r\n<option value=\"13\">XIII</option>\r\n<option value=\"14\">XIV</option>\r\n<option value=\"15\">XV</option>\r\n<option value=\"16\">XVI</option>\r\n<option value=\"17\">XVII</option>\r\n<option value=\"18\">XVIII</option>\r\n<option value=\"19\">XIX</option>\r\n<option value=\"20\">XX</option>\r\n</select>\r\n</div>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=10><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Recherche directe</b><br></font>\r\n\t\t\t\t<font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\"><img src=\"http://www.01net.com/img/dot.gif\" width=8 height=1>rechercher une ville<br><img src=\"http://www.01net.com/img/dot.gif\" width=8 height=1>et/ou une boutique<br></font>\r\n\t\t\t\t<input type=\"text\" name=\"recherchedirecte\" size=\"14\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;width:130px;\" value=\"\" onFocus=\"javascript:document.selection.recherchedirecte.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=3><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1>&nbsp;<input type=\"image\" src=\"http://www.01net.com/img/v4/MA/ok_bloc_recher_MA.gif\" border=\"0\">\r\n\t\t\t\t<table height=23 width=135 cellspacing=0 cellpadding=0 border=0 bgcolor=#FFEE77>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td bgcolor=#FFEE77 valign=middle align=center><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://micro-achat.01net.com/annuaire/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Recherche avanc\351e</b></font></a></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t</div>\r\n\t\t\t\t</div>\r\n\t\t\t\t</td>\r\n\t\t\t</tr></form>\r\n\t\t</table>\r\n\t\t</td>\r\n<!-- DEBUT MicroAchat MA_Telecharg //-->\r\n<td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n<table width=\"145\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/v4/MA/Ban_v4_MA_telec.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<table width=\"145\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#DFECF6\">\r\n\t\t\t<tr>\r\n\t\t\t\t<td rowspan=\"17\"><img src=\"http://www.01net.com/img/dot.gif\" width=\"6\"></td>\r\n\t\t\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"></td>\r\n\t\t\t\t<td rowspan=\"17\"><img src=\"http://www.01net.com/img/dot.gif\" width=\"6\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Bureautique\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Bureautique</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Traducteur, organiseur...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Multimedia\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Multim\351dia</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Photo, audio, vid\351o...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Utilitaire\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Utilitaires</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Antivirus, pilotes, gravure...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Personnaliser\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Personnaliser son PC</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Ecrans de veille, th\350mes...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Programmation\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>D\351veloppement</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Cr\351ation de logiciels, BDD...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Jeux\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Jeux</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Action, simulation...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Internet\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Internet</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Utilitaires, email, FTP...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Loisirs\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Loisirs</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Humour, culture...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_Telecharg //-->  \t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_AnnTelec --> <!-- - ZONE M2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE M3 -->\r\n<!-- - ZONE M3 -->\r\n<!-- + ZONE M4 -->\r\n<!-- - ZONE M4 -->\r\n<!-- + ZONE M5 -->\r\n<!-- - ZONE M5 -->\r\n<!-- -ZONE_Mn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t<tr>\r\n<!-- +ZONE_tn -->\r\n<!-- + ZONE t0 -->\r\n<!-- - ZONE t0 -->\r\n<!-- + ZONE t1 -->\r\n<!-- - ZONE t1 -->\r\n<!-- + ZONE t2 -->\r\n<!-- - ZONE t2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE t3 -->\r\n<!-- - ZONE t3 -->\r\n<!-- + ZONE t4 -->\r\n<!-- - ZONE t4 -->\r\n<!-- + ZONE t5 -->\r\n<!-- - ZONE t5 -->\r\n<!-- -ZONE_tn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td valign=top>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t<tr>\r\n<!-- +ZONE_dn -->\r\n<!-- + ZONE d0 -->\r\n<!-- - ZONE d0 -->\r\n<!-- + ZONE d1 -->\r\n<!-- - ZONE d1 -->\r\n<!-- + ZONE d2 -->\r\n<!-- - ZONE d2 -->\r\n<!-- + ZONE d3 -->\r\n<!-- - ZONE d3 -->\r\n<!-- + ZONE d4 -->\r\n<!-- - ZONE d4 -->\r\n<!-- + ZONE d5 -->\r\n<!-- - ZONE d5 -->\r\n<!-- + ZONE d6 -->\r\n<!-- - ZONE d6 -->\r\n<!-- + ZONE d7 -->\r\n<!-- - ZONE d7 -->\r\n<!-- + ZONE d8 -->\r\n<!-- - ZONE d8 -->\r\n<!-- + ZONE d9 -->\r\n<!-- - ZONE d9 -->\r\n<!-- -ZONE_dn -->\r\n\t\t\t\t</tr>\r\n\t\t\t</table>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n\t\t</table>\r\n<!-- FIN WORK -->\r\n\t\t</td>\r\n<!-- *********************************************************************FIN VENTRE********************************************************************************************************************************************** //-->\r\n\t\t<td rowspan=2 valign=top width=23 background=\"http://www.01net.com/img/v4/sep_verticale.gif\"><img src=\"http://www.01net.com/img/dot.gif\" width=23 height=1><br></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t\t<td colspan=2>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=100%>\r\n<!-- +ZONE_Bn -->\r\n<!-- + ZONE B0 -->\r\n<!-- - ZONE B0 -->\r\n<!-- + ZONE B1 -->\r\n<tr><!-- ********** DEBUT BLOC Home NosJournauxV4 //-->\r\n<td valign=top bgcolor=#FFFFFF>\r\n<img src=\"http://www.01net.com/img/ban/Ban_v4_jx.gif\"><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=15><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1>\r\n<a href=\"http://www.01net.com/rubrique/3339.html\"><img src=\"http://www.01net.com/img/journaux/01I-small.gif\" border=0 vspace=0 hspace=12 align=top></a>\r\n<a href=\"http://www.01net.com/rubrique/4051.html\"><img src=\"http://www.01net.com/img/journaux/DSI-small.gif\" border=0 vspace=0 hspace=12 align=top></a>\r\n<a href=\"http://www.01net.com/rubrique/3345.html\"><img src=\"http://www.01net.com/img/journaux/DIN-small.gif
\ No newline at end of file
diff --git a/snappy/snappy-1.0.5/testdata/html_x_4 b/snappy/snappy-1.0.5/testdata/html_x_4
new file mode 100644 (file)
index 0000000..3fe87dc
--- /dev/null
@@ -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        <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\r\n<BASE target=\"_top\">\r\n\n<TITLE>Micro Achat : Ordinateurs, PDA -  Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux</TITLE>\r\n<META NAME=\"Description\" CONTENT=\"Micro Achat : Ordinateurs, PDA\">\r\n<META NAME=\"Keywords\" CONTENT=\"Micro Achat : Ordinateurs, PDA -  Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\">\r\n<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"http://www.01net.com/styles/01net.css\">\r\n<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"http://www.01net.com/styles/tableau_autre.css\">\r\n<STYLE type=text/css>\r\nA{TEXT-DECORATION: none;color:#000000;}\r\nA:visited{TEXT-DECORATION: none;color:#000000;}\r\n</STYLE>\r\n<SCRIPT LANGUAGE=\"JavaScript1.1\">\r\nvar sameAsBigDay = new Date();\r\nvar ord = (sameAsBigDay.getTime());\r\nvar pubsMotsCles = \"\";\r\nvar exc;\r\nvar lienhautdepage = \"\";\r\nvar etatmessage = false;\r\nvar enchainement = false;\r\nsas_tmstp=Math.round(Math.random()*10000000000);\r\nfunction SmartAdServer(sas_pageid,sas_formatid,sas_master,sas_target) {\r\n if ((sas_master!=\'M\')&&(sas_master!=\'S\')) {sas_master=\'S\'};\r\n document.write(\'<SCR\'+\'IPT SRC=\"http://www.smartadserver.com/call/pubj/\' + sas_pageid + \'/\' + sas_formatid + \'/\'+sas_master + \'/\' + sas_tmstp + \'/\' + escape(sas_target) + \'?\"></SCR\'+\'IPT>\');\r\n}\r\n</SCRIPT>\r\n<SCRIPT LANGUAGE=\"JAVASCRIPT\" SRC=\"http://www.01net.com/js/exc.js\"></SCRIPT>\r\n<script language=\"javascript\" src=\"http://telecharger.01net.com/shopping/js/headservicesV4.js\"></script>\r\n<noscript>\r\n<a href=\"http://cinema.01net.com\">T\351l\351charger des bandes-annonces, des teasers, des extraits et des making of de vos films cin\351ma pr\351f\351r\351s</a>,\r\n<a href=\"http://www.01net.com/BusinessTechnologies/\">Portail leader de l\'information sur les nouvelles technologies - Actualites et enquetes sur l\'informatique et les NTIC (nouvelles technologies de l\'information et la communication). Exemples de sujets : e-business, telecoms, CRM, VPN, 3G, DSL, fournisseurs d\'acces, Linux, piratage, securite informatique, progiciel...</a><br>\r\n<a href=\"http://www.01net.com/securite_informatique.html\">s\351curit\351 informatique</a>,\r\n<a href=\"http://www.01net.com/strategies_ntic.html\">strat\351gies NTIC</a>,\r\n<a href=\"http://www.01net.com/piratage_informatique.html\">piratage informatique</a>,\r\n<a href=\"http://www.01net.com/technologie_dsl.html\">technologie DSL</a>,\r\n<a href=\"http://www.01net.com/solutions_vpn.html\">solutions VPN</a>,\r\n<a href=\"http://www.01net.com/strategie_e-business.html\">strat\351gies</a>,\r\n<a href=\"http://www.01net.com/outils_crm.html\">outils CRM</a>,\r\n<a href=\"http://www.01net.com/logiciel_linux.html\">logiciel Linux</a>,\r\n<a href=\"http://www.01net.com/fournisseur_d_acces.html\">fournisseur d\'acc\350s</a>,\r\n<a href=\"http://www.01net.com/progiciel.html\">progiciel</a>,\r\n<a href=\"http://www.01net.com/stockage_de_donnees.html\">stockage de donn\351es</a>,\r\n<a href=\"http://www.01net.com/etudes_solution_informatique.html\">\351tudes solution informatique</a>,\r\n<a href=\"http://www.01net.com/NTIC.html\">NTIC</a>,\r\n<a href=\"http://www.01net.com/actualite_technologie.html\">actualit\351 technologie</a>,\r\n<a href=\"http://www.01net.com/etude_materiel_informatique.html\">\351tude mat\351riel informatique</a>,\r\n<a href=\"http://www.01net.com/actus/\">actualit\351s des nouvelles technologies</a>,\r\n<a href=\"http://www.01net.com/MicroPerso/\">enqu\352tes et trucs et astuces sur le mat\351riel informatique, les logiciels, les fournisseurs d\'acc\350s...</a>,\r\n<a href=\"http://www.01net.com/emploi/\">emploi et formations informatiques : offres d\'emploi informatique...</a>,\r\n<a href=\"http://www.01net.com/produits/\">fiches, tests mat\351riels et logiciels en informatique</a>,\r\n<a href=\"http://www.01net.com/01informatique\">01 Informatique</a>,\r\n<a href=\"http://www.caractere.net\">Caract\350re, le site des professionnels de l\'imprim\351 - communication imprim\351e, \351dition, emballage, encres, finition, flexographie, h\351liogravure, impression, imprimerie, imprimeur, industries graphiques, num\351rique, offset, papier, pr\351presse, presse, print, reprographie, s\351rigraphie, typographie</a>,\r\n<a href=\"http://www.01net.com/decisionmicro\">Decision Micro</a>,\r\n<a href=\"http://www.01net.com/decisioninformatique\">D\351cision Informatique</a>,\r\n<a href=\"http://www.01net.com/01reseaux\">01 R\351seaux</a>,\r\n<a href=\"http://logiciel.telecharger.01net.com/\">logiciel</a>,\r\n<a href=\"http://developpeur.telecharger.01net.com/windows/Programmation/\">d\351veloppeur programmation</a>,\r\n<a href=\"http://anti-virus.telecharger.01net.com\">anti-virus</a>,\r\n<a href=\"http://gravure-cd-dvd.telecharger.01net.com/windows/Utilitaire/gravure/\">gravure cd dvd</a>,\r\n<a href=\"http://codec.telecharger.01net.com/windows/Multimedia/encodeurs_et_decodeurs/\">codec encodeur d\351codeur</a>,\r\n<a href=\"http://software.telecharger.01net.com/\">software</a>,\r\n<a href=\"http://logiciels.telecharger.01net.com/\">logiciels</a>,\r\n<a href=\"http://gratuit.telecharger.01net.com/\">gratuit</a>,\r\n<a href=\"http://p2p.telecharger.01net.com/windows/Internet/partage/\">p2p peer to peer partage de fichiers</a>,\r\n<a href=\"http://securite.telecharger.01net.com/windows/Utilitaire/cryptage_et_securite/\">s\351curit\351</a>,\r\n<a href=\"http://compression-decompression.telecharger.01net.com/windows/Utilitaire/compression_et_decompression/\">compression et d\351compression</a>,\r\n<a href=\"http://divx.telecharger.01net.com/\">divx</a>,\r\n<a href=\"http://utilitaire.telecharger.01net.com/windows/Utilitaire/\">utilitaire</a>,\r\n<a href=\"http://jeux.telecharger.01net.com/windows/Jeux/\">jeux</a>,\r\n<a href=\"http://loisirs.telecharger.01net.com/windows/Loisirs/\">loisirs</a>,\r\n<a href=\"http://mac.telecharger.01net.com/mac/\">mac</a>,\r\n<a href=\"http://linux.telecharger.01net.com/linux/\">linux</a>,\r\n<a href=\"http://shareware.telecharger.01net.com/\">shareware</a>,\r\n<a href=\"http://video-dvd.telecharger.01net.com/windows/Multimedia/lecteurs_video_dvd/\">vid\351o dvd</a>,\r\n<a href=\"http://multimedia.telecharger.01net.com/\">multim\351dia</a>,\r\n<a href=\"http://traduction.telecharger.01net.com/windows/Bureautique/traducteur/\">traduction</a>,\r\n<a href=\"http://mp3.telecharger.01net.com/windows/Multimedia/lecteurs_audio_mp3_cd/\">mp3</a>,\r\n<a href=\"http://tchat.telecharger.01net.com/windows/Internet/communication/\">tchat</a>\r\n<a href=\"http://chat.telecharger.01net.com/windows/Internet/communication/\">chat</a>,\r\n<a href=\"http://musique.telecharger.01net.com/\">musique</a>,\r\n<a href=\"http://mobile.telecharger.01net.com/mobile/\">mobile</a>,\r\n<a href=\"http://telephone_portable.telecharger.01net.com/mobile/\">t\351l\351phone portable</a>,\r\n<a href=\"http://telephone_mobile.telecharger.01net.com/mobile/\">t\351l\351phone mobile</a>\r\n</noscript>\r\n</head>\r\n</head>\r\n<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#000000\" marginwidth=0 marginheight=0 topmargin=0 leftmargin=0>\r\n<!-- + ZONE TETE -->\r\n<!-- ********** DEBUT MODELE INTERNE TETES MHA-tetev4 //-->\r\n<table width=100% height=66 cellspacing=0 cellpadding=0 border=0 bgcolor=#ffffff>\r\n\t<tr>\r\n\t\t<td height=8 colspan=2><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=8></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td valign=bottom><a href=\"http://microachat.01net.com\"><img src=\"http://www.01net.com/img/v4/logos_tete/tet_gauche-mha.gif\" border=0></a></td>\r\n\t\t<td valign=bottom bgcolor=#FFFFFF bbackground=\"http://www.01net.com/img/v4/tet_droite.gif\" width=100% style=\"background-image:url(/img/v4/tet_droite-mha.gif);background-position:bottom;background-repeat:repeat-x\"><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=66 align=left hspace=0 vspace=0></td>\r\n\t</tr>\r\n</table>\r\n<table width=100% cellspacing=0 cellpadding=0 border=0 bgcolor=#ffffff>\r\n\t<tr>\r\n\t\t<td valign=top background=\"http://www.01net.com/img/v4/fond_date-mha.gif\" height=18 width=500><img src=\"http://www.01net.com/img/dot.gif\" width=500 height=1><br><img src=\"http://www.01net.com/img/dot.gif\" width=19 height=1><font face=\"Arial\" size=1 color=#666666 style=\"font-size: 11px;\"><b>Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004&nbsp;&nbsp;|&nbsp;&nbsp;16:45</b></font></td>\r\n\t\t<td width=100% background=\"http://www.01net.com/img/v4/fond_date2-mha.gif\" height=18></td>\r\n\t</tr>\r\n</table>\r\n<!-- ********** FIN MODELE INTERNE TETES MHA-tetev4 //--> <!-- - ZONE TETE -->\r\n<!-- ***************************************************************************************************************************************************************************************************************************** //-->\r\n<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n<!-- DEBUT PARTIE PUB //-->\r\n\t<tr>\r\n<td align=center valign=middle colspan=2 background=\"http://www.01net.com/img/v4/fond_bann.gif\"><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br>\r\n<!-- + ZONE Z0 -->\r\n<SCRIPT LANGUAGE=\"JAVASCRIPT\">\r\nvar fa = \"\";\r\nvar fab = document.URL.toString();\r\nif (fab.indexOf(\"?fa\") != -1 || fab.indexOf(\"&fa\") != -1)\r\n{\r\nfa = \";!category=fai\";\r\n}\r\nvar etatmessage = false;\r\nvar enchainement = false;\r\n</SCRIPT>\r\n<SCRIPT LANGUAGE=\"JavaScript1.1\">\r\nsas_pageid=\'167/3872\';\r\nsas_formatid=95;\t\t\t// Format : Banner/Scope 468x60\r\nsas_master=\'M\';\t\t\t// Master : M=master or S=slave\r\nsas_target=exc + \'rubrique\';\t\t\t// Targeting\r\nSmartAdServer(sas_pageid,sas_formatid,sas_master,sas_target);\r\n</SCRIPT>\r\n <!-- - ZONE Z0 --></td>\r\n\t\t<td valign=top width=23 background=\"http://www.01net.com/img/v4/sep_verticale.gif\" ><img src=\"http://www.01net.com/img/dot.gif\" width=23 height=1><br></td>\r\n<td valign=top width=100% bgcolor=\"ffffff\" rowspan=3><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=125><br>\r\n<!-- +ZONE_Dn -->\r\n<!-- + ZONE D0 -->\r\n<!-- DEBUT MA_ColD -->\r\n<div style=\"background-color : #ffffff; width : 150px; padding-left : 5px; padding-right : 5px; font-family : Arial, Helvetica;\">\n\t\t\t\t\t<table style=\"border-spacing : 0; width : 146px; margin-top : 0px;\" cellspacing=\"0\">\n\t\t\t\t\t<tr><th colspan=\"2\" style=\"padding : 0;\"><img src=\"http://micro-achat.01net.com/img/utils/micro-achat/tete-produitsrecherches.gif\" alt=\"\" /></th></tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Imagerie&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/12537-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/imagerie/moniteurs-lcd/l1720b/\">LG L1720B</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">332.89 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Ordinateurs&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/4043-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/desktops/veriton-7600g/\">Acer Veriton 7600G</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">705 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Ordinateurs&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/1903-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/sn95g5/\">Shuttle SN95G5</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">375 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Composants&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/1259-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/composants/cartes-meres/a7n8x-e-deluxe/\">Asus A7N8X-E Deluxe</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">91.99 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Composants&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/4687-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/composants/ventilateur/sp-94/\">Thermalright SP-94</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">49 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr></table>\n\t\t\t\t<table style=\"border-spacing : 0px 1px; width : 146px; margin-top : 15px;\" cellspacing=\"0\">\n\t\t\t\t<tr><th colspan=\"2\" style=\"padding : 0;\"><img src=\"http://micro-achat.01net.com/img/utils/micro-achat/tete-revendeurmisajour.gif\" alt=\"\" /></th></tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">1 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Rhone-Alpes/Ain/pc-look\" style=\"color : #000000; text-decoration : none;\">PC Look</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">2 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Nord-Pas-de-Calais/Pas-de-Calais/atelier-informatique\" style=\"color : #000000; text-decoration : none;\">Atelier Informatique</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">3 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Val-de-Marne/zanax-multimedia\" style=\"color : #000000; text-decoration : none;\">Zanax Multim\351dia</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">4 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Hauts-de-Seine/misteroops\" style=\"color : #000000; text-decoration : none;\">MISTEROOPS</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">5 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/12/168-golden-avenue\" style=\"color : #000000; text-decoration : none;\">168 Golden Avenue</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">6 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Seine-Saint-Denis/microchoix\" style=\"color : #000000; text-decoration : none;\">microchoix</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">7 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/12/e-soph\" style=\"color : #000000; text-decoration : none;\">e-Soph</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">8 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/13/pc-price-club\" style=\"color : #000000; text-decoration : none;\">PC Price Club</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">9 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Seine-et-Marne/pc-77\" style=\"color : #000000; text-decoration : none;\">PC 77</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">10 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Alsace/Bas-Rhin/web-in-informatique\" style=\"color : #000000; text-decoration : none;\">Web In Informatique</a></td>\n\t\t\t\t</tr></table>\n\t\t\t\t</div>\n\t\t\t\t<br>\r\n<!-- FIN MA_ColD --> <!-- - ZONE D0 -->\r\n<!-- + ZONE D1 -->\r\n<!-- - ZONE D1 -->\r\n<!-- + ZONE D2 -->\r\n<!-- - ZONE D2 -->\r\n<!-- -ZONE_Dn -->\r\n</td>\r\n\t</tr>\r\n<!-- FIN PARTIE PUB //-->\r\n\t<tr>\r\n\t\t<td valign=top width=193 height=100% background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n\t\t<!-- contenu colonne de gauche //-->\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0  background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n<!-- +ZONE_Gn -->\r\n<!-- + ZONE G0 -->\r\n<tr><!-- ********** DEBUT MHA_MenusChainesV4 //-->\r\n<td valign=top>\n<table border=0 cellpadding=0 cellspacing=0 width=193 bgcolor=#FFFFFF>\n<tr>\n<td background=\"/img/v4/menus/motifgauche_menus.gif\" width=20 rowspan=2><img src=\"/img/dot.gif\" width=20 height=20></td>\n<td width=173 colspan=2 bgcolor=#FFFFFF><img src=\"/img/dot.gif\" width=173 height=20></td>\n</tr>\n<tr>\n<td valign=top width=159>\n\n<a href=\"http://www.01net.com\"><img src=\"/img/v4/menus/mha/home01net-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com\"><img src=\"/img/v4/menus/mha/home-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4317.html\"><img src=\"/img/v4/menus/mha/ordinateurs-2.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4318.html\"><img src=\"/img/v4/menus/mha/composants-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4319.html\"><img src=\"/img/v4/menus/mha/stockage-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4320.html\"><img src=\"/img/v4/menus/mha/image-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4321.html\"><img src=\"/img/v4/menus/mha/peripheriques-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4322.html\"><img src=\"/img/v4/menus/mha/reseaux-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4323.html\"><img src=\"/img/v4/menus/mha/accessoires-1.gif\" width=159 border=0></a><br>\n<a href=\"http://micro-achat.01net.com/guide-produits/\"><img src=\"/img/v4/menus/mha/comparateur-1.gif\" width=159 border=0></a><br>\n<a href=\"http://micro-achat.01net.com/annuaire/\"><img src=\"/img/v4/menus/mha/annuaire-1.gif\" width=159 border=0></a><br></td>\n<td width=14><img src=\"/img/dot.gif\" width=14 height=14></td>\n</tr>\n<tr>\n<td colspan=3><img src=\"/img/v4/menus/bas_menus.gif\" width=193 height=31></td>\n</tr>\n</table></td><!-- ********** FIN MHA_MenusChainesV4 //--> </tr><!-- - ZONE G0 -->\r\n<!-- + ZONE G1 -->\r\n<tr><!-- DEBUT MODELE RUBRIQUE V4ColGaucheMHA //-->\r\n<!-- ********** DEBUT BLOC DernieresNewsTC //-->\r\n<td valign=top>\r\n<!-- DEBUT RECHERCHE MHA -->\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n\t\t\t<td valign=top background=\"http://microachat.01net.com/img/v4/fond_rech_mha.gif\" height=98 style=\"background-repeat:no-repeat;\"><form method=\"get\" name=\"chercher\" action=\"http://www.01net.com/aiguillage_recherche/1,6138,,00.html\"><img src=\"http://microachat.01net.com/img/dot.gif\" width=193 height=17><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><input type=\"text\" name=\"fullText\" style=\"width:130px;font:12px;\"><br><img src=\"http://microachat.01net.com/img/dot.gif\" width=1 height=6><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><select name=\"sousArbo\" style=\"width:130px;font:12px;\">\r\n\t\t\t<option value=\"mha\">dans Micro Achat\r\n\t\t\t<option value=\"cmp\">les prix\r\n\t\t\t<option value=\"ann\">les revendeurs\r\n\t\t\t<option value=\"2641\">tout 01net.\r\n\t\t\t<option value=\"emploi\">les offres d\'emploi\r\n\t\t\t<option value=\"telecharger\"> telecharger.com\r\n\t\t\t<option value=\"web\">le web\r\n\t\t\t</select><br><img src=\"http://microachat.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"http://microachat.01net.com/img/v4/ok_bloc_recher_mha.gif\" border=\"0\"></form>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=10 vspace=0>\r\n<!-- FIN RECHERCHE MHA -->\r\n      <!-- modele TCFilColgTitV4 //-->\r\n    <table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top>\r\n\t\t<table width=155 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=2><img src=\"http://www.01net.com/img/ban/Ban_v4_DernieresNews01net.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4></td>\r\n\t\t\t</tr>\r\n\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/256059.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">CD et DVD bient\364t insensibles aux rayures<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/255796.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">OpenOffice gagne son service<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/255731.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">La messagerie en cinq minutes selon Ipswitch<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top colspan=2><A HREF=\"http://www.01net.com/actus/\" style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\">> toutes les news<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t\t<tr>\r\n\t\t\t\t<td colspan=2><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/crochet_bleuhaut_155.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20> <!-- ********** FIN BLOC DernieresNewsTC //-->\r\n<!-- ********** DEBUT BLOC  NL_MHA //-->\r\n<SCRIPT language=\"javascript\" src=\"http://www.01net.com/js/lib.js\"></SCRIPT>\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<FORM name=\"formgen\" method=\"get\" action=\"http://microachat.01net.com/outils/newsletter_MicroAchat.html\" onSubmit=\"return validateForm(this)\">\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=155 colspan=4><img src=\"http://www.01net.com/img/ban/Ban_V4_Newslett.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=10><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=1 bgcolor=#CC0000><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t<td width=153>\r\n\t\t<table width=153 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=10><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t\t\t<td valign=top><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefinefd_ffffff.gif\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Recevez chaque jour l\'actualit\351 des produits et des promos<br></font>\r\n\t\t\t\t<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td><input type=\"text\" name=\"email\" size=\"14\" style=\"width:130px;font:12px;\" value=\"entrez votre e-mail\" onFocus=\"javascript:document.formgen.email.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"http://www.01net.com/img/v4/ok_bloc_recher.gif\" border=\"0\"></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td width=1 bgcolor=#CC0000><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=155 colspan=4><img src=\"http://www.01net.com/img/v4/base_newsletters.gif\"></td>\r\n\t\t</FORM>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20>\r\n<SCRIPT language=\"Javascript\">\r\ndocument.formgen.email.validator= \'notNullEmailPat\';\r\ndocument.formgen.email.nomvalidator= \'E-mail\';\r\n</SCRIPT>\r\n<!-- ********** FIN BLOC NL_MHA //-->\r\n</td>\r\n</tr>\r\n<tr>\r\n<!-- ********** DEBUT BLOC Actus ActusUneV4 //-->\r\n<td valign=top background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n<table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top>\r\n\t\t<table width=155 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/ban/Ban_v4_LaUne.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/entreprise/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Entreprise</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://www.01net.com/article/255737.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">Quand le billet papier s\'envole vers la d\351mat\351rialisation</font></a></td>\r\n\t\t\t\t<td valign=top width=2><img src=\"http://www.01net.com/img/dot.gif\" width=2 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/article/255737.html\"><img src=\"http://www.01net.com/img/MEA_v4/billet_virtuel-65.jpg\" border=0></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/pratique/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Trucs et astuces</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255698.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">D\351pannez Windows XP</font></a></td>\r\n\t\t\t\t<td valign=top width=2><img src=\"http://www.01net.com/img/dot.gif\" width=2 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/article/255698.html\"><img src=\"http://www.01net.com/img/MEA_v4/depannez_XP-65.jpg\" border=0 ></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t</tr>\r\n\t\t    <tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top colspan=3><a href=\"http://www.01net.com/conso/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Conso</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255524.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">Vos photos sur papier imprimante ou labo ?<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t<!-- exemple de lien avec pseudorub pour produits et tests -->\r\n\t\t<!-- <a href=\"/outils/PseudoRub.php?base=test-comp&rub=1730&pseudo=test-comp20041005\"> -->\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top colspan=3><a href=\"http://www.01net.com/produits/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Produits &amp; Tests</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255782.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">5 programmes d\222encodage vid\351o gratuits<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20>\r\n</td>\r\n<!-- ********** FIN BLOC Actus ActusUneV4 //-->    </tr>\r\n<tr>\r\n<td>\r\n<table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top><a href=\"mailto:s.cohen@micro-achat.fr\"><img border=0 src=\"http://www.01net.com/img/v4/espace-revendeurs.gif\"></td>\r\n\t</tr>\r\n</table>\r\n<br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20></td>\r\n<!-- FIN MODELE RUBRIQUE V4ColGaucheMHA //-->  </tr><!-- - ZONE G1 -->\r\n<!-- + ZONE G2 -->\r\n<!-- - ZONE G2 -->\r\n<!-- + ZONE G3 -->\r\n<!-- - ZONE G3 -->\r\n<!-- + ZONE G4 -->\r\n<!-- - ZONE G4 -->\r\n<!-- + ZONE G5 -->\r\n<!-- - ZONE G5 -->\r\n<!-- + ZONE G6 -->\r\n<!-- - ZONE G6 -->\r\n<!-- + ZONE G7 -->\r\n<!-- - ZONE G7 -->\r\n<!-- + ZONE G8 -->\r\n<!-- - ZONE G8 -->\r\n<!-- + ZONE G9 -->\r\n<!-- - ZONE G9 -->\r\n<!-- + ZONE GA -->\r\n<!-- - ZONE GA -->\r\n<!-- + ZONE GB -->\r\n<!-- - ZONE GB -->\r\n<!-- + ZONE GC -->\r\n<!-- - ZONE GC -->\r\n<!-- + ZONE GD -->\r\n<!-- - ZONE GD -->\r\n<!-- + ZONE GE -->\r\n<!-- - ZONE GE -->\r\n<!-- + ZONE GF -->\r\n<!-- - ZONE GF -->\r\n<!-- -ZONE_Gn -->\r\n\t\t</table>\r\n\t\t<!-- fin contenu colonne de gauche //-->\r\n\t\t</td>\r\n<!-- ***************************************************************** DEBUT VENTRE*********************************************************************************************************************************************** //-->\r\n<!-- DEBUT WORK -->\r\n\t\t<td valign=top width=625 bgcolor=#ffffff><img src=\"http://www.01net.com/img/dot.gif\" width=625 height=1><br>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_hn -->\r\n<!-- + ZONE h0 -->\r\n<!-- MA_ban_int -->\r\n<td valign=\"top\">\r\n<img src=\"/img/dot.gif\" height=\"18\"><br>\r\n<!-- pour ordipda -->\r\n<table width=\"625\" cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"/img/v4/MA/Ban_MA_ordis.gif\"></td>\r\n\t</tr>\r\n</table>\r\n\t</td>\r\n<!-- /MA_ban_int -->     <!-- - ZONE h0 -->\r\n<!-- + ZONE h1 -->\r\n<!-- - ZONE h1 -->\r\n<!-- + ZONE h2 -->\r\n<!-- - ZONE h2 -->\r\n<!-- -ZONE_hn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_Hn -->\r\n<!-- + ZONE H0 -->\r\n<!-- Ma_int_Leader -->\r\n    <td valign=top>\r\n<img src=\"/img/dot.gif\" width=1 height=18><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=320>\r\n<tr>\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<td width=144 valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=143 height=1 vspace=0><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:11px;>Portable</font><br>\r\n<A HREF=\"/article/256198.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=font-size:14px;><b>Un nouvel ultra portable r\351alis\351 par Nec</b></font></a><br>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/256198.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67509.jpg.res_100-100.jpg\" border=0 hspace=0 vspace=0></a><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n<font face=arial,helvetica size=2 color=#000000 style=font-size:12px;><img src=\"/img/v4/flechefine_fondtransp.gif\">Le Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.</font><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:12px;>\340 partir de 1663&#160;\200</font>\r\n</td>\r\n<td width=17 background=\"/img/v4/MA/v4-fond-sep-mea-leader.gif\"><img src=\"/img/dot.gif\" width=17 height=1></td>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<td width=144 valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=143 height=1 vspace=0><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:11px;>Portable</font><br>\r\n<A HREF=\"/article/255194.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=font-size:14px;><b>Asus pr\351sente trois petits nouveaux dans la gamme A3N</b></font></a><br>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255194.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67168.jpg.res_100-100.jpg\" border=0 hspace=0 vspace=0></a><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n<font face=arial,helvetica size=2 color=#000000 style=font-size:12px;><img src=\"/img/v4/flechefine_fondtransp.gif\">Ces trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.</font><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:12px;>\340 partir de 1346&#160;\200</font>\r\n</td>\r\n<td width=15><img src=\"/img/dot.gif\" width=15 height=1></td>\r\n\t\t\t\t</tr>\r\n</table>\r\n</td>\r\n<!-- /Ma_int_Leader -->    <!-- - ZONE H0 -->\r\n<!-- + ZONE H1 -->\r\n<!-- - ZONE H1 -->\r\n<!-- + ZONE H2 -->\r\n<!-- MA_BP_MP -->\r\n<td valign=\"top\" width=\"100%\">\r\n\t<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\r\n\t<tr>\r\n\t<td width=\"50%\" valign=\"top\">\r\n\t<!-- DEBUT MicroAchat MA_BonPlan -->\r\n<td valign=top>\r\n<img src=\"/img/dot.gif\" width=1 height=18><br>\r\n<table border=0 cellpadding=1 cellspacing=0 width=145 bgcolor=#CC0000>\r\n<tr>\r\n<td align=center><font face=arial,helvetica size=1 color=#FFFFFF style=\"font-size:11px;\">BON PLAN</a></font></td>\r\n</tr>\r\n<tr>\r\n<td  width=145>\r\n<div style=\"padding:5px;padding-left:5px;padding-fight:5px;margin:0px;margin-left:1px;margin-right:1px;background-color:#FFFFFF;\">\r\n<img src=\"/img/microachat/logo_shuttle_SB83G5.gif\" border=0><br>\r\n<font face=arial,helvetica size=2 color=#CC0000 style=\"font-size:12px;\">Les derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.<br></font>\r\n<center><a href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/sb83g5/?fabriquant=1&page=1&tri=titre\"><img src=\"/img/microachat/mea_shuttle_SB83G5.gif\" border=0 vspace=5></a><br></center>\r\n<center>\r\n<font face=arial,helvetica size=2 color=#CC0000 style=\"font-size:13px;\"><b>\340 partir de</b><br>\r\n<div style=\"border:solid 2px #CC0000;width:100px;background-color:#FFCC00;\"><b>415 \200</b></div>\r\n</center>\r\n</div>\r\n</td>\r\n</tr>\r\n<tr>\r\n<td align=center><font face=arial,helvetica size=1 color=#FFFFFF style=\"font-size:11px;\">publicit\351</a></font></td>\r\n</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_BonPlan -->  \t</td>\r\n\t<td width=\"15\"><img src=\"/img/dot.gif\" width=\"15\"></td>\r\n\t<td width=\"50%\" valign=\"top\">\r\n\t<!-- DEBUT MicroAchat MA_MeillPrixAct //-->\r\n<td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=145 height=1><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=18><br>\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<FORM name=\"prix\" action=\"http://www.micro-achat.01net.com/guide-produits/recherche.php\" method=\"post\">\r\n\t\t<td width=145 colspan=3><img src=\"http://www.01net.com/img/ban/Ban_v4_MeillPrix_MA.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=1 bgcolor=#FFCC00><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t<td width=143>\r\n\t\t<table width=143 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=6><img src=\"http://www.01net.com/img/dot.gif\" width=6 height=1></td>\r\n\t\t\t\t<td valign=top><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=15><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<img src=\"http://www.01net.com/img/ban/Ban_MA_trouv_ordi.gif\"><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/desktops/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Desktops</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/portables/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Portables</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Mini-PC</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/pda---tablets-pc/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Pda / Tablets-PC</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/apple/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Apple</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/gps/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">GPS</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20><br>\r\n\t\t\t\t\t\t\t\t<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td><input type=\"text\" name=\"recherchedirecte\" size=\"14\" style=\"width:130px;font:12px;\" value=\"     recherche directe\" onFocus=\"javascript:document.prix.recherchedirecte.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"/img/v4/MA/ok_bloc_recher_MA.gif\" border=\"0\"></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td width=1 bgcolor=#FFCC00><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=145 colspan=3><img src=\"http://www.01net.com/img/v4/MA/base_meillPrix.gif\"></td>\r\n\t\t</FORM>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_MeillPrixAct //-->  \t</td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n<!-- /MA_BP_MP -->  <!-- - ZONE H2 -->\r\n<!-- -ZONE_Hn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_Tn -->\r\n<!-- + ZONE T0 -->\r\n    <td valign=\"top\">\r\n<img src=\"http://www.01net.com/img/dot.gif\" height=13><br>\r\n<table border=0 width=320 cellpadding=0 cellspacing=0>\r\n<tr>\r\n<td width=305><img src=\"http://www.01net.com/img/ban/Ban_v4_DernNews_MA.gif\"><br><img src=\"http://www.01net.com/img/v4/MA/v4-tiret-hauts-mha.gif\"></td>\r\n<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n</tr>\r\n<tr>\r\n<td bgcolor=\"#FEF9E0\">\r\n\t<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Portable&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255149.html\" style=\"color:#000000;text-decoration:none;\">Toshiba consacre deux gammes de machines au multim\351dia</a></b><br>\r\n\t<font color=\"#000000\">Equipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Ordinateur&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254686.html\" style=\"color:#000000;text-decoration:none;\">Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme</a></b><br>\r\n\t<font color=\"#000000\">La firme \340 la pomme propose une station de travail \351volutive et relativement abordable.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>PC&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254549.html\" style=\"color:#000000;text-decoration:none;\">Alienware propose deux machines au look \351trange</a></b><br>\r\n\t<font color=\"#000000\">Aurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Portable&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254501.html\" style=\"color:#000000;text-decoration:none;\">Trois nouveaux iBook G4 chez Apple</a></b><br>\r\n\t<font color=\"#000000\">Chez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t\t<tr>\r\n\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=10></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-red-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td align=\"right\">\r\n\t\t\t\t<A HREF=\"http://microachat.01net.com/rubrique/4365.html\"  style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 10px;\">> toutes les news</font></a>\r\n\t\t\t</td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n</td> <!-- - ZONE T0 -->\r\n<!-- + ZONE T1 -->\r\n<!-- Ma_derpromo  -->\r\n    <td valign=\"top\">\r\n<img src=\"/img/dot.gif\" height=13><br>\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td bgcolor=\"#ffffff\"><img src=\"/img/v4/MA/v4-lespromos-mha.gif\"><br><img src=\"/img/v4/MA/v4-tiret-hauts-mha.gif\"></td>\r\n</tr>\r\n</table>\r\n<!-- DEBUT MODELE D\'AFFICHAGE POUR LES n PREMIERS ARTICLES //-->\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255806.html\" class=\"nodeco\"><img src=\"/images/67462.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255806.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>Asus A3N15-C Pro</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>1170&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255688.html\" class=\"nodeco\"><img src=\"/images/67381.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255688.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>Soltek EQ3702A Miroir</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>559&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255513.html\" class=\"nodeco\"><img src=\"/images/67319.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255513.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>IBM ThinkPad R51</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Voici un portable complet et pourtant relativement l\351ger.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>1299&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t\t<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td><img src=\"http://www.01net.com/img/dot.gif\" height=10></td>\r\n</tr>\r\n<tr>\r\n<td background=\"/img/v4/MA/v4-sep-red-mha.gif\"><img src=\"/img/dot.gif\" height=1></td>\r\n</tr>\r\n<tr>\r\n<td align=\"right\" valign=\"top\">\r\n\t\t\t\t<A HREF=\"http://microachat.01net.com/rubrique/4366.html\"  style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 10px;\">> toutes les promos</font></a>\r\n\t\t</td>\r\n</tr>\r\n</table>\r\n</td>\r\n<!-- /Ma_derpromo  -->   <!-- - ZONE T1 -->\r\n<!-- + ZONE T2 -->\r\n<!-- - ZONE T2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE T3 -->\r\n<!-- DEBUT MicroAchat MA_PubG -->\r\n<td valign=top align=center>\r\n<table border=0 width=320 cellpadding=0 cellspacing=0>\r\n\t<tr>\r\n\t\t<td width=305><img src=\"/img/dot.gif\" width=1 height=12><br><a href=\"http://www.smartadserver.com/call/cliccommand/45590/[timestamp]?\" target=_blank><img src=\"/img/microachat/Bandeau_FX6021.jpg\" border=0></a></td>\r\n\t\t<td><img src=\"/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_PubG -->  <!-- - ZONE T3 -->\r\n<!-- + ZONE T4 -->\r\n<!-- DEBUT MicroAchat MA_PubD -->\r\n<td valign=top align=center>\r\n<table border=0 width=305 cellpadding=0 cellspacing=0>\r\n\t<tr>\r\n\t\t<td width=305><img src=\"/img/dot.gif\" width=1 height=12><br><a href=\"http://www.smartadserver.com/call/cliccommand/45591/[timestamp]?\" target=_blank><img src=\"/img/microachat/twc_305x125.jpg\" border=0></a></td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN  MicroAchat MA_PubD --> <!-- - ZONE T4 -->\r\n<!-- + ZONE T5 -->\r\n<!-- - ZONE T5 -->\r\n<!-- -ZONE_Tn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n\t\t\t<td valign=top>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n<!-- +ZONE_gn -->\r\n<!-- + ZONE g0 -->\r\n<!-- - ZONE g0 -->\r\n<!-- + ZONE g1 -->\r\n<!-- - ZONE g1 -->\r\n<!-- + ZONE g2 -->\r\n<!-- - ZONE g2 -->\r\n<!-- + ZONE g3 -->\r\n<!-- - ZONE g3 -->\r\n<!-- + ZONE g4 -->\r\n<!-- - ZONE g4 -->\r\n<!-- + ZONE g5 -->\r\n<!-- - ZONE g5 -->\r\n<!-- + ZONE g6 -->\r\n<!-- - ZONE g6 -->\r\n<!-- + ZONE g7 -->\r\n<!-- - ZONE g7 -->\r\n<!-- + ZONE g8 -->\r\n<!-- - ZONE g8 -->\r\n<!-- + ZONE g9 -->\r\n<!-- - ZONE g9 -->\r\n<!-- -ZONE_gn -->\r\n\t\t\t</table>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t\t\t<tr>\r\n<!-- +ZONE_Mn -->\r\n<!-- + ZONE M0 -->\r\n<!-- modele Ma_GuideAch //-->\r\n    <td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" height=13><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t<tr>\r\n\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_GuideAchat_MA.gif\" vspace=1></td>\r\n\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<div style=\"border:solid 1px #FFCC00;width:100%\">\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<center>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"http://microachat.01net.com/article/254561.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67088.jpg.res_121-111.jpg\" border=0 hspace=0 vspace=0></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n</center>\r\n<div style=\"padding:5px;\">\r\n<a href=\"http://microachat.01net.com/article/254561.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\"><b>Les graveurs de DVD</b><br></font></a>\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">Quel graveur choisir&#160;? Quel type de format&#160;? Quelle vitesse&#160;? Double couche ou simple couche&#160;? Voici tout ce qu\'il faut savoir pour faire le bon choix.</font></div>\r\n\t\t\t\t\t\t</div>\r\n\t\t</td>\r\n\t</tr>\r\n</table>\r\n</td> <!-- - ZONE M0 -->\r\n<!-- + ZONE M1 -->\r\n<!-- modele Ma_DirectLab //-->\r\n    <td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t<tr>\r\n\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_DirectLab_MA.gif\" vspace=1></td>\r\n\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<div style=\"border:solid 1px #FFCC00;width:100%\">\r\n\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255744.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>Kodak EasyShare Printer Dock Plus&#160;:</b>\r\n\t\t\t\t\t\tvos photos 10&#160;x&#160;15&#160;cm en 60&#160;secondes</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255780.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>3DMark05&#160;:</b>\r\n\t\t\t\t\t\tun labo 3D \340 domicile</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255691.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>DVDInfoPro 2.6</b>\r\n\t\t\t\t\t\treconna\356t CD et DVD</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255722.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>Scaleo PA D3008, de Fujitsu-Siemens&#160;:</b>\r\n\t\t\t\t\t\tune impression d\'inachev\351</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255514.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">Carbon 5&#160;Go&#160;: 2&#160;500&#160;chansons dans le creux de la main</font></a></div>\r\n\t\t\t</div></td>\r\n\t</tr>\r\n</table>\r\n</td> <!-- - ZONE M1 -->\r\n<!-- + ZONE M2 -->\r\n<!-- DEBUT MicroAchat MA_AnnTelec -->\r\n<td valign=top>\r\n<script type=\"text/javascript\">\r\nfunction regionChange()\r\n{\r\ndocument.selection.departement.options.length=0;\r\nswitch(document.selection.region.value)\r\n\t{\r\n\t\tcase \"aucun\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Nord-Pas-de-Calais\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pas-de-Calais\", \"Pas-de-Calais\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Nord\", \"Nord\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Haute-Normandie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Eure\", \"Eure\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-Maritime\", \"Seine-Maritime\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Basse-Normandie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Manche\", \"Manche\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Calvados\", \"Calvados\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Orne\", \"Orne\");\r\n\t\tbreak;\r\n\t\tcase \"Picardie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Somme\", \"Somme\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Oise\", \"Oise\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aisne\", \"Aisne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Bretagne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Finistere\", \"Finistere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cotes-dArmor\", \"Cotes-dArmor\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Morbihan\", \"Morbihan\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ille-et-Vilaine\", \"Ille-et-Vilaine\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Pays-de-Loire\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loire-Atlantique\", \"Loire-Atlantique\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vendee\", \"Vendee\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Maine-et-Loire\", \"Maine-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Mayenne\", \"Mayenne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Sarthe\", \"Sarthe\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Centre\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Eure-et-Loir\", \"Eure-et-Loir\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loiret\", \"Loiret\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loir-et-Cher\", \"Loir-et-Cher\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Indre-et-Loire\", \"Indre-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Indre\", \"Indre\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cher\", \"Cher\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Ile-de-France\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Val-dOise\", \"Val-dOise\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Yvelines\", \"Yvelines\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Essonne\", \"Essonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-et-Marne\", \"Seine-et-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hauts-de-Seine\", \"Hauts-de-Seine\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-Saint-Denis\", \"Seine-Saint-Denis\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Val-de-Marne\", \"Val-de-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Paris\", \"Paris\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Champagnes-Ardennes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ardennes\", \"Ardennes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Marne\", \"Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aube\", \"Aube\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Marne\", \"Haute-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Lorraine\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vosges\", \"Vosges\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Meurthe-et-Moselle\", \"Meurthe-et-Moselle\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Meuse\", \"Meuse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Moselle\", \"Moselle\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Alsace\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Bas-Rhin\", \"Bas-Rhin\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haut-Rhin\", \"Haut-Rhin\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Franche-Compte\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Jura\", \"Jura\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Doubs\", \"Doubs\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Saone\", \"Haute-Saone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Territoire-de-Belfort\", \"Territoire-de-Belfort\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Bourgogne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Yonne\", \"Yonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Nievre\", \"Nievre\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cote-dOr\", \"Cote-dOr\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Saone-et-Loire\", \"Saone-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Poitou-Charentes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Deux-Sevres\", \"Deux-Sevres\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Charente-Maritime\", \"Charente-Maritime\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Charente\", \"Charente\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vienne\", \"Vienne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Limousin\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Vienne\", \"Haute-Vienne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Correze\", \"Correze\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Creuse\", \"Creuse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Auvergne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Allier\", \"Allier\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Puy-de-Dome\", \"Puy-de-Dome\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cantal\", \"Cantal\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Loire\", \"Haute-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Rhone-Alpes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loire\", \"Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Rhone\", \"Rhone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ain\", \"Ain\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ardeche\", \"Ardeche\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Drome\", \"Drome\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Isere\", \"Isere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Savoie\", \"Savoie\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Savoie\", \"Haute-Savoie\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Aquitaine\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gironde\", \"Gironde\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Landes\", \"Landes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pyrenees-Atlantiques\", \"Pyrenees-Atlantiques\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lot-et-Garonne\", \"Lot-et-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Dordogne\", \"Dordogne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Midi-Pyrenees\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lot\", \"Lot\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Tarn-et-Garonne\", \"Tarn-et-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gers\", \"Gers\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hautes-Pyrenees\", \"Hautes-Pyrenees\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Garonne\", \"Haute-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ariege\", \"Ariege\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Tarn\", \"Tarn\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aveyron\", \"Aveyron\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Languedoc-Roussillon\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pyrenees-Orientales\", \"Pyrenees-Orientales\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aude\", \"Aude\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Herault\", \"Herault\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gard\", \"Gard\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lozere\", \"Lozere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Provence-Alpes-Cote-dazur\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Bouches-du-Rhone\", \"Bouches-du-Rhone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vaucluse\", \"Vaucluse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Alpes-de-haute-Provence\", \"Alpes-de-haute-Provence\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hautes-Alpes\", \"Hautes-Alpes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Var\", \"Var\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Alpes-Maritimes\", \"Alpes-Maritimes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Corse\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Corse-du-Sud\", \"Corse-du-Sud\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Corse\", \"Haute-Corse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"DomTom\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Guadeloupe\", \"Guadeloupe\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Guyane\", \"Guyane\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"La-Reunion\", \"La-Reunion\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Martinique\", \"Martinique\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Mayotte\", \"Mayotte\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"St-Pierre-et-Miquelon\", \"St-Pierre-et-Miquelon\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t}\r\n}\r\nfunction deptChange()\r\n{\r\nif (document.selection.departement.value == \'Paris\')\r\n\tdocument.getElementById(\'arrondissement\').style.display = \'inline\';\r\nelse\r\n\tdocument.getElementById(\'arrondissement\').style.display = \'none\';\r\n}\r\n</script>\r\n<table width=305 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td valign=top>\r\n\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_AnnuaiRev_MA.gif\" vspace=1></td>\r\n\t\t\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr><form action=\"http://micro-achat.01net.com/annuaire/recherche.php\" method=\"post\" name=\"selection\">\r\n\t\t\t\t<td bgcolor=#FFFFDD>\r\n\t\t\t\t<div style=\"border:solid 1px #FFCC00;width:100%\"><div style=\"padding:2px;\"><img src=\"http://www.01net.com/img/v4/MA/carte_revend.gif\"><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Choisir une r\351gion</b><br></font>\r\n<select name=\"region\" onChange=\"regionChange()\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"aucun\">-------------</option>\r\n<option value=\"Nord-Pas-de-Calais\">Nord-Pas-de-Calais</option>\r\n<option value=\"Haute-Normandie\">Haute-Normandie</option>\r\n<option value=\"Basse-Normandie\">Basse-Normandie</option>\r\n<option value=\"Picardie\">Picardie</option>\r\n<option value=\"Bretagne\">Bretagne</option>\r\n<option value=\"Pays-de-Loire\">Pays-de-Loire</option>\r\n<option value=\"Centre\">Centre</option>\r\n<option value=\"Ile-de-France\">Ile-de-France</option>\r\n<option value=\"Champagnes-Ardennes\">Champagne ardennes</option>\r\n<option value=\"Lorraine\">Lorraine</option>\r\n<option value=\"Alsace\">Alsace</option>\r\n<option value=\"Franche-Compte\">Franche-Compte</option>\r\n<option value=\"Bourgogne\">Bourgogne</option>\r\n<option value=\"Poitou-Charentes\">Poitou-Charentes</option>\r\n<option value=\"Limousin\">Limousin</option>\r\n<option value=\"Auvergne\">Auvergne</option>\r\n<option value=\"Rhone-Alpes\">Rhone-Alpes</option>\r\n<option value=\"Aquitaine\">Aquitaine</option>\r\n<option value=\"Midi-Pyrenees\">Midi-Pyrenees</option>\r\n<option value=\"Languedoc-Roussillon\">Languedoc roussillon</option>\r\n<option value=\"Provence-Alpes-Cote-dazur\">PACA</option>\r\n<option value=\"Corse\">Corse</option>\r\n<option value=\"DomTom\">DomTom</option>\r\n</select>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Un d\351partement</b><br></font>\r\n<select name=\"departement\" onChange=\"deptChange()\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"aucun\">-------------</option>\r\n</select>\r\n<div id=\"arrondissement\" style=\"display : none;\">\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Un arrondissement</b><br></font>\r\n<select name=\"arrondissement\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"0\">-------------</option>\r\n<option value=\"1\">I</option>\r\n<option value=\"2\">II</option>\r\n<option value=\"3\">III</option>\r\n<option value=\"4\">IV</option>\r\n<option value=\"5\">V</option>\r\n<option value=\"6\">VI</option>\r\n<option value=\"7\">VII</option>\r\n<option value=\"8\">VIII</option>\r\n<option value=\"9\">IX</option>\r\n<option value=\"10\">X</option>\r\n<option value=\"11\">XI</option>\r\n<option value=\"12\">XII</option>\r\n<option value=\"13\">XIII</option>\r\n<option value=\"14\">XIV</option>\r\n<option value=\"15\">XV</option>\r\n<option value=\"16\">XVI</option>\r\n<option value=\"17\">XVII</option>\r\n<option value=\"18\">XVIII</option>\r\n<option value=\"19\">XIX</option>\r\n<option value=\"20\">XX</option>\r\n</select>\r\n</div>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=10><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Recherche directe</b><br></font>\r\n\t\t\t\t<font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\"><img src=\"http://www.01net.com/img/dot.gif\" width=8 height=1>rechercher une ville<br><img src=\"http://www.01net.com/img/dot.gif\" width=8 height=1>et/ou une boutique<br></font>\r\n\t\t\t\t<input type=\"text\" name=\"recherchedirecte\" size=\"14\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;width:130px;\" value=\"\" onFocus=\"javascript:document.selection.recherchedirecte.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=3><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1>&nbsp;<input type=\"image\" src=\"http://www.01net.com/img/v4/MA/ok_bloc_recher_MA.gif\" border=\"0\">\r\n\t\t\t\t<table height=23 width=135 cellspacing=0 cellpadding=0 border=0 bgcolor=#FFEE77>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td bgcolor=#FFEE77 valign=middle align=center><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://micro-achat.01net.com/annuaire/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Recherche avanc\351e</b></font></a></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t</div>\r\n\t\t\t\t</div>\r\n\t\t\t\t</td>\r\n\t\t\t</tr></form>\r\n\t\t</table>\r\n\t\t</td>\r\n<!-- DEBUT MicroAchat MA_Telecharg //-->\r\n<td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n<table width=\"145\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/v4/MA/Ban_v4_MA_telec.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<table width=\"145\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#DFECF6\">\r\n\t\t\t<tr>\r\n\t\t\t\t<td rowspan=\"17\"><img src=\"http://www.01net.com/img/dot.gif\" width=\"6\"></td>\r\n\t\t\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"></td>\r\n\t\t\t\t<td rowspan=\"17\"><img src=\"http://www.01net.com/img/dot.gif\" width=\"6\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Bureautique\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Bureautique</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Traducteur, organiseur...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Multimedia\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Multim\351dia</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Photo, audio, vid\351o...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Utilitaire\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Utilitaires</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Antivirus, pilotes, gravure...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Personnaliser\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Personnaliser son PC</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Ecrans de veille, th\350mes...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Programmation\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>D\351veloppement</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Cr\351ation de logiciels, BDD...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Jeux\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Jeux</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Action, simulation...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Internet\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Internet</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Utilitaires, email, FTP...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Loisirs\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Loisirs</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Humour, culture...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_Telecharg //-->  \t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_AnnTelec --> <!-- - ZONE M2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE M3 -->\r\n<!-- - ZONE M3 -->\r\n<!-- + ZONE M4 -->\r\n<!-- - ZONE M4 -->\r\n<!-- + ZONE M5 -->\r\n<!-- - ZONE M5 -->\r\n<!-- -ZONE_Mn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t<tr>\r\n<!-- +ZONE_tn -->\r\n<!-- + ZONE t0 -->\r\n<!-- - ZONE t0 -->\r\n<!-- + ZONE t1 -->\r\n<!-- - ZONE t1 -->\r\n<!-- + ZONE t2 -->\r\n<!-- - ZONE t2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE t3 -->\r\n<!-- - ZONE t3 -->\r\n<!-- + ZONE t4 -->\r\n<!-- - ZONE t4 -->\r\n<!-- + ZONE t5 -->\r\n<!-- - ZONE t5 -->\r\n<!-- -ZONE_tn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td valign=top>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t<tr>\r\n<!-- +ZONE_dn -->\r\n<!-- + ZONE d0 -->\r\n<!-- - ZONE d0 -->\r\n<!-- + ZONE d1 -->\r\n<!-- - ZONE d1 -->\r\n<!-- + ZONE d2 -->\r\n<!-- - ZONE d2 -->\r\n<!-- + ZONE d3 -->\r\n<!-- - ZONE d3 -->\r\n<!-- + ZONE d4 -->\r\n<!-- - ZONE d4 -->\r\n<!-- + ZONE d5 -->\r\n<!-- - ZONE d5 -->\r\n<!-- + ZONE d6 -->\r\n<!-- - ZONE d6 -->\r\n<!-- + ZONE d7 -->\r\n<!-- - ZONE d7 -->\r\n<!-- + ZONE d8 -->\r\n<!-- - ZONE d8 -->\r\n<!-- + ZONE d9 -->\r\n<!-- - ZONE d9 -->\r\n<!-- -ZONE_dn -->\r\n\t\t\t\t</tr>\r\n\t\t\t</table>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n\t\t</table>\r\n<!-- FIN WORK -->\r\n\t\t</td>\r\n<!-- *********************************************************************FIN VENTRE********************************************************************************************************************************************** //-->\r\n\t\t<td rowspan=2 valign=top width=23 background=\"http://www.01net.com/img/v4/sep_verticale.gif\"><img src=\"http://www.01net.com/img/dot.gif\" width=23 height=1><br></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t\t<td colspan=2>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=100%>\r\n<!-- +ZONE_Bn -->\r\n<!-- + ZONE B0 -->\r\n<!-- - ZONE B0 -->\r\n<!-- + ZONE B1 -->\r\n<tr><!-- ********** DEBUT BLOC Home NosJournauxV4 //-->\r\n<td valign=top bgcolor=#FFFFFF>\r\n<img src=\"http://www.01net.com/img/ban/Ban_v4_jx.gif\"><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=15><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1>\r\n<a href=\"http://www.01net.com/rubrique/3339.html\"><img src=\"http://www.01net.com/img/journaux/01I-small.gif\" border=0 vspace=0 hspace=12 align=top></a>\r\n<a href=\"http://www.01net.com/rubrique/4051.html\"><img src=\"http://www.01net.com/img/journaux/DSI-small.gif\" border=0 vspace=0 hspace=12 align=top></a>\r\n<a href=\"http://www.01net.com/rubrique/3345.html\"><img src=\"http://www.01net.com/img/journaux/DIN-small.gif  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        <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\r\n<BASE target=\"_top\">\r\n\n<TITLE>Micro Achat : Ordinateurs, PDA -  Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux</TITLE>\r\n<META NAME=\"Description\" CONTENT=\"Micro Achat : Ordinateurs, PDA\">\r\n<META NAME=\"Keywords\" CONTENT=\"Micro Achat : Ordinateurs, PDA -  Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\">\r\n<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"http://www.01net.com/styles/01net.css\">\r\n<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"http://www.01net.com/styles/tableau_autre.css\">\r\n<STYLE type=text/css>\r\nA{TEXT-DECORATION: none;color:#000000;}\r\nA:visited{TEXT-DECORATION: none;color:#000000;}\r\n</STYLE>\r\n<SCRIPT LANGUAGE=\"JavaScript1.1\">\r\nvar sameAsBigDay = new Date();\r\nvar ord = (sameAsBigDay.getTime());\r\nvar pubsMotsCles = \"\";\r\nvar exc;\r\nvar lienhautdepage = \"\";\r\nvar etatmessage = false;\r\nvar enchainement = false;\r\nsas_tmstp=Math.round(Math.random()*10000000000);\r\nfunction SmartAdServer(sas_pageid,sas_formatid,sas_master,sas_target) {\r\n if ((sas_master!=\'M\')&&(sas_master!=\'S\')) {sas_master=\'S\'};\r\n document.write(\'<SCR\'+\'IPT SRC=\"http://www.smartadserver.com/call/pubj/\' + sas_pageid + \'/\' + sas_formatid + \'/\'+sas_master + \'/\' + sas_tmstp + \'/\' + escape(sas_target) + \'?\"></SCR\'+\'IPT>\');\r\n}\r\n</SCRIPT>\r\n<SCRIPT LANGUAGE=\"JAVASCRIPT\" SRC=\"http://www.01net.com/js/exc.js\"></SCRIPT>\r\n<script language=\"javascript\" src=\"http://telecharger.01net.com/shopping/js/headservicesV4.js\"></script>\r\n<noscript>\r\n<a href=\"http://cinema.01net.com\">T\351l\351charger des bandes-annonces, des teasers, des extraits et des making of de vos films cin\351ma pr\351f\351r\351s</a>,\r\n<a href=\"http://www.01net.com/BusinessTechnologies/\">Portail leader de l\'information sur les nouvelles technologies - Actualites et enquetes sur l\'informatique et les NTIC (nouvelles technologies de l\'information et la communication). Exemples de sujets : e-business, telecoms, CRM, VPN, 3G, DSL, fournisseurs d\'acces, Linux, piratage, securite informatique, progiciel...</a><br>\r\n<a href=\"http://www.01net.com/securite_informatique.html\">s\351curit\351 informatique</a>,\r\n<a href=\"http://www.01net.com/strategies_ntic.html\">strat\351gies NTIC</a>,\r\n<a href=\"http://www.01net.com/piratage_informatique.html\">piratage informatique</a>,\r\n<a href=\"http://www.01net.com/technologie_dsl.html\">technologie DSL</a>,\r\n<a href=\"http://www.01net.com/solutions_vpn.html\">solutions VPN</a>,\r\n<a href=\"http://www.01net.com/strategie_e-business.html\">strat\351gies</a>,\r\n<a href=\"http://www.01net.com/outils_crm.html\">outils CRM</a>,\r\n<a href=\"http://www.01net.com/logiciel_linux.html\">logiciel Linux</a>,\r\n<a href=\"http://www.01net.com/fournisseur_d_acces.html\">fournisseur d\'acc\350s</a>,\r\n<a href=\"http://www.01net.com/progiciel.html\">progiciel</a>,\r\n<a href=\"http://www.01net.com/stockage_de_donnees.html\">stockage de donn\351es</a>,\r\n<a href=\"http://www.01net.com/etudes_solution_informatique.html\">\351tudes solution informatique</a>,\r\n<a href=\"http://www.01net.com/NTIC.html\">NTIC</a>,\r\n<a href=\"http://www.01net.com/actualite_technologie.html\">actualit\351 technologie</a>,\r\n<a href=\"http://www.01net.com/etude_materiel_informatique.html\">\351tude mat\351riel informatique</a>,\r\n<a href=\"http://www.01net.com/actus/\">actualit\351s des nouvelles technologies</a>,\r\n<a href=\"http://www.01net.com/MicroPerso/\">enqu\352tes et trucs et astuces sur le mat\351riel informatique, les logiciels, les fournisseurs d\'acc\350s...</a>,\r\n<a href=\"http://www.01net.com/emploi/\">emploi et formations informatiques : offres d\'emploi informatique...</a>,\r\n<a href=\"http://www.01net.com/produits/\">fiches, tests mat\351riels et logiciels en informatique</a>,\r\n<a href=\"http://www.01net.com/01informatique\">01 Informatique</a>,\r\n<a href=\"http://www.caractere.net\">Caract\350re, le site des professionnels de l\'imprim\351 - communication imprim\351e, \351dition, emballage, encres, finition, flexographie, h\351liogravure, impression, imprimerie, imprimeur, industries graphiques, num\351rique, offset, papier, pr\351presse, presse, print, reprographie, s\351rigraphie, typographie</a>,\r\n<a href=\"http://www.01net.com/decisionmicro\">Decision Micro</a>,\r\n<a href=\"http://www.01net.com/decisioninformatique\">D\351cision Informatique</a>,\r\n<a href=\"http://www.01net.com/01reseaux\">01 R\351seaux</a>,\r\n<a href=\"http://logiciel.telecharger.01net.com/\">logiciel</a>,\r\n<a href=\"http://developpeur.telecharger.01net.com/windows/Programmation/\">d\351veloppeur programmation</a>,\r\n<a href=\"http://anti-virus.telecharger.01net.com\">anti-virus</a>,\r\n<a href=\"http://gravure-cd-dvd.telecharger.01net.com/windows/Utilitaire/gravure/\">gravure cd dvd</a>,\r\n<a href=\"http://codec.telecharger.01net.com/windows/Multimedia/encodeurs_et_decodeurs/\">codec encodeur d\351codeur</a>,\r\n<a href=\"http://software.telecharger.01net.com/\">software</a>,\r\n<a href=\"http://logiciels.telecharger.01net.com/\">logiciels</a>,\r\n<a href=\"http://gratuit.telecharger.01net.com/\">gratuit</a>,\r\n<a href=\"http://p2p.telecharger.01net.com/windows/Internet/partage/\">p2p peer to peer partage de fichiers</a>,\r\n<a href=\"http://securite.telecharger.01net.com/windows/Utilitaire/cryptage_et_securite/\">s\351curit\351</a>,\r\n<a href=\"http://compression-decompression.telecharger.01net.com/windows/Utilitaire/compression_et_decompression/\">compression et d\351compression</a>,\r\n<a href=\"http://divx.telecharger.01net.com/\">divx</a>,\r\n<a href=\"http://utilitaire.telecharger.01net.com/windows/Utilitaire/\">utilitaire</a>,\r\n<a href=\"http://jeux.telecharger.01net.com/windows/Jeux/\">jeux</a>,\r\n<a href=\"http://loisirs.telecharger.01net.com/windows/Loisirs/\">loisirs</a>,\r\n<a href=\"http://mac.telecharger.01net.com/mac/\">mac</a>,\r\n<a href=\"http://linux.telecharger.01net.com/linux/\">linux</a>,\r\n<a href=\"http://shareware.telecharger.01net.com/\">shareware</a>,\r\n<a href=\"http://video-dvd.telecharger.01net.com/windows/Multimedia/lecteurs_video_dvd/\">vid\351o dvd</a>,\r\n<a href=\"http://multimedia.telecharger.01net.com/\">multim\351dia</a>,\r\n<a href=\"http://traduction.telecharger.01net.com/windows/Bureautique/traducteur/\">traduction</a>,\r\n<a href=\"http://mp3.telecharger.01net.com/windows/Multimedia/lecteurs_audio_mp3_cd/\">mp3</a>,\r\n<a href=\"http://tchat.telecharger.01net.com/windows/Internet/communication/\">tchat</a>\r\n<a href=\"http://chat.telecharger.01net.com/windows/Internet/communication/\">chat</a>,\r\n<a href=\"http://musique.telecharger.01net.com/\">musique</a>,\r\n<a href=\"http://mobile.telecharger.01net.com/mobile/\">mobile</a>,\r\n<a href=\"http://telephone_portable.telecharger.01net.com/mobile/\">t\351l\351phone portable</a>,\r\n<a href=\"http://telephone_mobile.telecharger.01net.com/mobile/\">t\351l\351phone mobile</a>\r\n</noscript>\r\n</head>\r\n</head>\r\n<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#000000\" marginwidth=0 marginheight=0 topmargin=0 leftmargin=0>\r\n<!-- + ZONE TETE -->\r\n<!-- ********** DEBUT MODELE INTERNE TETES MHA-tetev4 //-->\r\n<table width=100% height=66 cellspacing=0 cellpadding=0 border=0 bgcolor=#ffffff>\r\n\t<tr>\r\n\t\t<td height=8 colspan=2><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=8></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td valign=bottom><a href=\"http://microachat.01net.com\"><img src=\"http://www.01net.com/img/v4/logos_tete/tet_gauche-mha.gif\" border=0></a></td>\r\n\t\t<td valign=bottom bgcolor=#FFFFFF bbackground=\"http://www.01net.com/img/v4/tet_droite.gif\" width=100% style=\"background-image:url(/img/v4/tet_droite-mha.gif);background-position:bottom;background-repeat:repeat-x\"><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=66 align=left hspace=0 vspace=0></td>\r\n\t</tr>\r\n</table>\r\n<table width=100% cellspacing=0 cellpadding=0 border=0 bgcolor=#ffffff>\r\n\t<tr>\r\n\t\t<td valign=top background=\"http://www.01net.com/img/v4/fond_date-mha.gif\" height=18 width=500><img src=\"http://www.01net.com/img/dot.gif\" width=500 height=1><br><img src=\"http://www.01net.com/img/dot.gif\" width=19 height=1><font face=\"Arial\" size=1 color=#666666 style=\"font-size: 11px;\"><b>Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004&nbsp;&nbsp;|&nbsp;&nbsp;16:45</b></font></td>\r\n\t\t<td width=100% background=\"http://www.01net.com/img/v4/fond_date2-mha.gif\" height=18></td>\r\n\t</tr>\r\n</table>\r\n<!-- ********** FIN MODELE INTERNE TETES MHA-tetev4 //--> <!-- - ZONE TETE -->\r\n<!-- ***************************************************************************************************************************************************************************************************************************** //-->\r\n<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n<!-- DEBUT PARTIE PUB //-->\r\n\t<tr>\r\n<td align=center valign=middle colspan=2 background=\"http://www.01net.com/img/v4/fond_bann.gif\"><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br>\r\n<!-- + ZONE Z0 -->\r\n<SCRIPT LANGUAGE=\"JAVASCRIPT\">\r\nvar fa = \"\";\r\nvar fab = document.URL.toString();\r\nif (fab.indexOf(\"?fa\") != -1 || fab.indexOf(\"&fa\") != -1)\r\n{\r\nfa = \";!category=fai\";\r\n}\r\nvar etatmessage = false;\r\nvar enchainement = false;\r\n</SCRIPT>\r\n<SCRIPT LANGUAGE=\"JavaScript1.1\">\r\nsas_pageid=\'167/3872\';\r\nsas_formatid=95;\t\t\t// Format : Banner/Scope 468x60\r\nsas_master=\'M\';\t\t\t// Master : M=master or S=slave\r\nsas_target=exc + \'rubrique\';\t\t\t// Targeting\r\nSmartAdServer(sas_pageid,sas_formatid,sas_master,sas_target);\r\n</SCRIPT>\r\n <!-- - ZONE Z0 --></td>\r\n\t\t<td valign=top width=23 background=\"http://www.01net.com/img/v4/sep_verticale.gif\" ><img src=\"http://www.01net.com/img/dot.gif\" width=23 height=1><br></td>\r\n<td valign=top width=100% bgcolor=\"ffffff\" rowspan=3><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=125><br>\r\n<!-- +ZONE_Dn -->\r\n<!-- + ZONE D0 -->\r\n<!-- DEBUT MA_ColD -->\r\n<div style=\"background-color : #ffffff; width : 150px; padding-left : 5px; padding-right : 5px; font-family : Arial, Helvetica;\">\n\t\t\t\t\t<table style=\"border-spacing : 0; width : 146px; margin-top : 0px;\" cellspacing=\"0\">\n\t\t\t\t\t<tr><th colspan=\"2\" style=\"padding : 0;\"><img src=\"http://micro-achat.01net.com/img/utils/micro-achat/tete-produitsrecherches.gif\" alt=\"\" /></th></tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Imagerie&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/12537-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/imagerie/moniteurs-lcd/l1720b/\">LG L1720B</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">332.89 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Ordinateurs&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/4043-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/desktops/veriton-7600g/\">Acer Veriton 7600G</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">705 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Ordinateurs&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/1903-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/sn95g5/\">Shuttle SN95G5</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">375 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Composants&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/1259-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/composants/cartes-meres/a7n8x-e-deluxe/\">Asus A7N8X-E Deluxe</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">91.99 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Composants&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/4687-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/composants/ventilateur/sp-94/\">Thermalright SP-94</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">49 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr></table>\n\t\t\t\t<table style=\"border-spacing : 0px 1px; width : 146px; margin-top : 15px;\" cellspacing=\"0\">\n\t\t\t\t<tr><th colspan=\"2\" style=\"padding : 0;\"><img src=\"http://micro-achat.01net.com/img/utils/micro-achat/tete-revendeurmisajour.gif\" alt=\"\" /></th></tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">1 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Rhone-Alpes/Ain/pc-look\" style=\"color : #000000; text-decoration : none;\">PC Look</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">2 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Nord-Pas-de-Calais/Pas-de-Calais/atelier-informatique\" style=\"color : #000000; text-decoration : none;\">Atelier Informatique</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">3 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Val-de-Marne/zanax-multimedia\" style=\"color : #000000; text-decoration : none;\">Zanax Multim\351dia</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">4 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Hauts-de-Seine/misteroops\" style=\"color : #000000; text-decoration : none;\">MISTEROOPS</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">5 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/12/168-golden-avenue\" style=\"color : #000000; text-decoration : none;\">168 Golden Avenue</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">6 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Seine-Saint-Denis/microchoix\" style=\"color : #000000; text-decoration : none;\">microchoix</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">7 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/12/e-soph\" style=\"color : #000000; text-decoration : none;\">e-Soph</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">8 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/13/pc-price-club\" style=\"color : #000000; text-decoration : none;\">PC Price Club</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">9 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Seine-et-Marne/pc-77\" style=\"color : #000000; text-decoration : none;\">PC 77</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">10 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Alsace/Bas-Rhin/web-in-informatique\" style=\"color : #000000; text-decoration : none;\">Web In Informatique</a></td>\n\t\t\t\t</tr></table>\n\t\t\t\t</div>\n\t\t\t\t<br>\r\n<!-- FIN MA_ColD --> <!-- - ZONE D0 -->\r\n<!-- + ZONE D1 -->\r\n<!-- - ZONE D1 -->\r\n<!-- + ZONE D2 -->\r\n<!-- - ZONE D2 -->\r\n<!-- -ZONE_Dn -->\r\n</td>\r\n\t</tr>\r\n<!-- FIN PARTIE PUB //-->\r\n\t<tr>\r\n\t\t<td valign=top width=193 height=100% background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n\t\t<!-- contenu colonne de gauche //-->\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0  background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n<!-- +ZONE_Gn -->\r\n<!-- + ZONE G0 -->\r\n<tr><!-- ********** DEBUT MHA_MenusChainesV4 //-->\r\n<td valign=top>\n<table border=0 cellpadding=0 cellspacing=0 width=193 bgcolor=#FFFFFF>\n<tr>\n<td background=\"/img/v4/menus/motifgauche_menus.gif\" width=20 rowspan=2><img src=\"/img/dot.gif\" width=20 height=20></td>\n<td width=173 colspan=2 bgcolor=#FFFFFF><img src=\"/img/dot.gif\" width=173 height=20></td>\n</tr>\n<tr>\n<td valign=top width=159>\n\n<a href=\"http://www.01net.com\"><img src=\"/img/v4/menus/mha/home01net-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com\"><img src=\"/img/v4/menus/mha/home-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4317.html\"><img src=\"/img/v4/menus/mha/ordinateurs-2.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4318.html\"><img src=\"/img/v4/menus/mha/composants-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4319.html\"><img src=\"/img/v4/menus/mha/stockage-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4320.html\"><img src=\"/img/v4/menus/mha/image-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4321.html\"><img src=\"/img/v4/menus/mha/peripheriques-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4322.html\"><img src=\"/img/v4/menus/mha/reseaux-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4323.html\"><img src=\"/img/v4/menus/mha/accessoires-1.gif\" width=159 border=0></a><br>\n<a href=\"http://micro-achat.01net.com/guide-produits/\"><img src=\"/img/v4/menus/mha/comparateur-1.gif\" width=159 border=0></a><br>\n<a href=\"http://micro-achat.01net.com/annuaire/\"><img src=\"/img/v4/menus/mha/annuaire-1.gif\" width=159 border=0></a><br></td>\n<td width=14><img src=\"/img/dot.gif\" width=14 height=14></td>\n</tr>\n<tr>\n<td colspan=3><img src=\"/img/v4/menus/bas_menus.gif\" width=193 height=31></td>\n</tr>\n</table></td><!-- ********** FIN MHA_MenusChainesV4 //--> </tr><!-- - ZONE G0 -->\r\n<!-- + ZONE G1 -->\r\n<tr><!-- DEBUT MODELE RUBRIQUE V4ColGaucheMHA //-->\r\n<!-- ********** DEBUT BLOC DernieresNewsTC //-->\r\n<td valign=top>\r\n<!-- DEBUT RECHERCHE MHA -->\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n\t\t\t<td valign=top background=\"http://microachat.01net.com/img/v4/fond_rech_mha.gif\" height=98 style=\"background-repeat:no-repeat;\"><form method=\"get\" name=\"chercher\" action=\"http://www.01net.com/aiguillage_recherche/1,6138,,00.html\"><img src=\"http://microachat.01net.com/img/dot.gif\" width=193 height=17><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><input type=\"text\" name=\"fullText\" style=\"width:130px;font:12px;\"><br><img src=\"http://microachat.01net.com/img/dot.gif\" width=1 height=6><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><select name=\"sousArbo\" style=\"width:130px;font:12px;\">\r\n\t\t\t<option value=\"mha\">dans Micro Achat\r\n\t\t\t<option value=\"cmp\">les prix\r\n\t\t\t<option value=\"ann\">les revendeurs\r\n\t\t\t<option value=\"2641\">tout 01net.\r\n\t\t\t<option value=\"emploi\">les offres d\'emploi\r\n\t\t\t<option value=\"telecharger\"> telecharger.com\r\n\t\t\t<option value=\"web\">le web\r\n\t\t\t</select><br><img src=\"http://microachat.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"http://microachat.01net.com/img/v4/ok_bloc_recher_mha.gif\" border=\"0\"></form>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=10 vspace=0>\r\n<!-- FIN RECHERCHE MHA -->\r\n      <!-- modele TCFilColgTitV4 //-->\r\n    <table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top>\r\n\t\t<table width=155 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=2><img src=\"http://www.01net.com/img/ban/Ban_v4_DernieresNews01net.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4></td>\r\n\t\t\t</tr>\r\n\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/256059.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">CD et DVD bient\364t insensibles aux rayures<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/255796.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">OpenOffice gagne son service<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/255731.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">La messagerie en cinq minutes selon Ipswitch<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top colspan=2><A HREF=\"http://www.01net.com/actus/\" style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\">> toutes les news<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t\t<tr>\r\n\t\t\t\t<td colspan=2><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/crochet_bleuhaut_155.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20> <!-- ********** FIN BLOC DernieresNewsTC //-->\r\n<!-- ********** DEBUT BLOC  NL_MHA //-->\r\n<SCRIPT language=\"javascript\" src=\"http://www.01net.com/js/lib.js\"></SCRIPT>\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<FORM name=\"formgen\" method=\"get\" action=\"http://microachat.01net.com/outils/newsletter_MicroAchat.html\" onSubmit=\"return validateForm(this)\">\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=155 colspan=4><img src=\"http://www.01net.com/img/ban/Ban_V4_Newslett.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=10><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=1 bgcolor=#CC0000><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t<td width=153>\r\n\t\t<table width=153 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=10><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t\t\t<td valign=top><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefinefd_ffffff.gif\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Recevez chaque jour l\'actualit\351 des produits et des promos<br></font>\r\n\t\t\t\t<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td><input type=\"text\" name=\"email\" size=\"14\" style=\"width:130px;font:12px;\" value=\"entrez votre e-mail\" onFocus=\"javascript:document.formgen.email.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"http://www.01net.com/img/v4/ok_bloc_recher.gif\" border=\"0\"></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td width=1 bgcolor=#CC0000><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=155 colspan=4><img src=\"http://www.01net.com/img/v4/base_newsletters.gif\"></td>\r\n\t\t</FORM>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20>\r\n<SCRIPT language=\"Javascript\">\r\ndocument.formgen.email.validator= \'notNullEmailPat\';\r\ndocument.formgen.email.nomvalidator= \'E-mail\';\r\n</SCRIPT>\r\n<!-- ********** FIN BLOC NL_MHA //-->\r\n</td>\r\n</tr>\r\n<tr>\r\n<!-- ********** DEBUT BLOC Actus ActusUneV4 //-->\r\n<td valign=top background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n<table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top>\r\n\t\t<table width=155 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/ban/Ban_v4_LaUne.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/entreprise/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Entreprise</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://www.01net.com/article/255737.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">Quand le billet papier s\'envole vers la d\351mat\351rialisation</font></a></td>\r\n\t\t\t\t<td valign=top width=2><img src=\"http://www.01net.com/img/dot.gif\" width=2 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/article/255737.html\"><img src=\"http://www.01net.com/img/MEA_v4/billet_virtuel-65.jpg\" border=0></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/pratique/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Trucs et astuces</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255698.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">D\351pannez Windows XP</font></a></td>\r\n\t\t\t\t<td valign=top width=2><img src=\"http://www.01net.com/img/dot.gif\" width=2 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/article/255698.html\"><img src=\"http://www.01net.com/img/MEA_v4/depannez_XP-65.jpg\" border=0 ></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t</tr>\r\n\t\t    <tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top colspan=3><a href=\"http://www.01net.com/conso/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Conso</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255524.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">Vos photos sur papier imprimante ou labo ?<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t<!-- exemple de lien avec pseudorub pour produits et tests -->\r\n\t\t<!-- <a href=\"/outils/PseudoRub.php?base=test-comp&rub=1730&pseudo=test-comp20041005\"> -->\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top colspan=3><a href=\"http://www.01net.com/produits/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Produits &amp; Tests</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255782.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">5 programmes d\222encodage vid\351o gratuits<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20>\r\n</td>\r\n<!-- ********** FIN BLOC Actus ActusUneV4 //-->    </tr>\r\n<tr>\r\n<td>\r\n<table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top><a href=\"mailto:s.cohen@micro-achat.fr\"><img border=0 src=\"http://www.01net.com/img/v4/espace-revendeurs.gif\"></td>\r\n\t</tr>\r\n</table>\r\n<br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20></td>\r\n<!-- FIN MODELE RUBRIQUE V4ColGaucheMHA //-->  </tr><!-- - ZONE G1 -->\r\n<!-- + ZONE G2 -->\r\n<!-- - ZONE G2 -->\r\n<!-- + ZONE G3 -->\r\n<!-- - ZONE G3 -->\r\n<!-- + ZONE G4 -->\r\n<!-- - ZONE G4 -->\r\n<!-- + ZONE G5 -->\r\n<!-- - ZONE G5 -->\r\n<!-- + ZONE G6 -->\r\n<!-- - ZONE G6 -->\r\n<!-- + ZONE G7 -->\r\n<!-- - ZONE G7 -->\r\n<!-- + ZONE G8 -->\r\n<!-- - ZONE G8 -->\r\n<!-- + ZONE G9 -->\r\n<!-- - ZONE G9 -->\r\n<!-- + ZONE GA -->\r\n<!-- - ZONE GA -->\r\n<!-- + ZONE GB -->\r\n<!-- - ZONE GB -->\r\n<!-- + ZONE GC -->\r\n<!-- - ZONE GC -->\r\n<!-- + ZONE GD -->\r\n<!-- - ZONE GD -->\r\n<!-- + ZONE GE -->\r\n<!-- - ZONE GE -->\r\n<!-- + ZONE GF -->\r\n<!-- - ZONE GF -->\r\n<!-- -ZONE_Gn -->\r\n\t\t</table>\r\n\t\t<!-- fin contenu colonne de gauche //-->\r\n\t\t</td>\r\n<!-- ***************************************************************** DEBUT VENTRE*********************************************************************************************************************************************** //-->\r\n<!-- DEBUT WORK -->\r\n\t\t<td valign=top width=625 bgcolor=#ffffff><img src=\"http://www.01net.com/img/dot.gif\" width=625 height=1><br>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_hn -->\r\n<!-- + ZONE h0 -->\r\n<!-- MA_ban_int -->\r\n<td valign=\"top\">\r\n<img src=\"/img/dot.gif\" height=\"18\"><br>\r\n<!-- pour ordipda -->\r\n<table width=\"625\" cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"/img/v4/MA/Ban_MA_ordis.gif\"></td>\r\n\t</tr>\r\n</table>\r\n\t</td>\r\n<!-- /MA_ban_int -->     <!-- - ZONE h0 -->\r\n<!-- + ZONE h1 -->\r\n<!-- - ZONE h1 -->\r\n<!-- + ZONE h2 -->\r\n<!-- - ZONE h2 -->\r\n<!-- -ZONE_hn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_Hn -->\r\n<!-- + ZONE H0 -->\r\n<!-- Ma_int_Leader -->\r\n    <td valign=top>\r\n<img src=\"/img/dot.gif\" width=1 height=18><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=320>\r\n<tr>\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<td width=144 valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=143 height=1 vspace=0><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:11px;>Portable</font><br>\r\n<A HREF=\"/article/256198.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=font-size:14px;><b>Un nouvel ultra portable r\351alis\351 par Nec</b></font></a><br>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/256198.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67509.jpg.res_100-100.jpg\" border=0 hspace=0 vspace=0></a><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n<font face=arial,helvetica size=2 color=#000000 style=font-size:12px;><img src=\"/img/v4/flechefine_fondtransp.gif\">Le Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.</font><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:12px;>\340 partir de 1663&#160;\200</font>\r\n</td>\r\n<td width=17 background=\"/img/v4/MA/v4-fond-sep-mea-leader.gif\"><img src=\"/img/dot.gif\" width=17 height=1></td>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<td width=144 valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=143 height=1 vspace=0><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:11px;>Portable</font><br>\r\n<A HREF=\"/article/255194.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=font-size:14px;><b>Asus pr\351sente trois petits nouveaux dans la gamme A3N</b></font></a><br>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255194.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67168.jpg.res_100-100.jpg\" border=0 hspace=0 vspace=0></a><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n<font face=arial,helvetica size=2 color=#000000 style=font-size:12px;><img src=\"/img/v4/flechefine_fondtransp.gif\">Ces trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.</font><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:12px;>\340 partir de 1346&#160;\200</font>\r\n</td>\r\n<td width=15><img src=\"/img/dot.gif\" width=15 height=1></td>\r\n\t\t\t\t</tr>\r\n</table>\r\n</td>\r\n<!-- /Ma_int_Leader -->    <!-- - ZONE H0 -->\r\n<!-- + ZONE H1 -->\r\n<!-- - ZONE H1 -->\r\n<!-- + ZONE H2 -->\r\n<!-- MA_BP_MP -->\r\n<td valign=\"top\" width=\"100%\">\r\n\t<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\r\n\t<tr>\r\n\t<td width=\"50%\" valign=\"top\">\r\n\t<!-- DEBUT MicroAchat MA_BonPlan -->\r\n<td valign=top>\r\n<img src=\"/img/dot.gif\" width=1 height=18><br>\r\n<table border=0 cellpadding=1 cellspacing=0 width=145 bgcolor=#CC0000>\r\n<tr>\r\n<td align=center><font face=arial,helvetica size=1 color=#FFFFFF style=\"font-size:11px;\">BON PLAN</a></font></td>\r\n</tr>\r\n<tr>\r\n<td  width=145>\r\n<div style=\"padding:5px;padding-left:5px;padding-fight:5px;margin:0px;margin-left:1px;margin-right:1px;background-color:#FFFFFF;\">\r\n<img src=\"/img/microachat/logo_shuttle_SB83G5.gif\" border=0><br>\r\n<font face=arial,helvetica size=2 color=#CC0000 style=\"font-size:12px;\">Les derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.<br></font>\r\n<center><a href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/sb83g5/?fabriquant=1&page=1&tri=titre\"><img src=\"/img/microachat/mea_shuttle_SB83G5.gif\" border=0 vspace=5></a><br></center>\r\n<center>\r\n<font face=arial,helvetica size=2 color=#CC0000 style=\"font-size:13px;\"><b>\340 partir de</b><br>\r\n<div style=\"border:solid 2px #CC0000;width:100px;background-color:#FFCC00;\"><b>415 \200</b></div>\r\n</center>\r\n</div>\r\n</td>\r\n</tr>\r\n<tr>\r\n<td align=center><font face=arial,helvetica size=1 color=#FFFFFF style=\"font-size:11px;\">publicit\351</a></font></td>\r\n</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_BonPlan -->  \t</td>\r\n\t<td width=\"15\"><img src=\"/img/dot.gif\" width=\"15\"></td>\r\n\t<td width=\"50%\" valign=\"top\">\r\n\t<!-- DEBUT MicroAchat MA_MeillPrixAct //-->\r\n<td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=145 height=1><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=18><br>\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<FORM name=\"prix\" action=\"http://www.micro-achat.01net.com/guide-produits/recherche.php\" method=\"post\">\r\n\t\t<td width=145 colspan=3><img src=\"http://www.01net.com/img/ban/Ban_v4_MeillPrix_MA.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=1 bgcolor=#FFCC00><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t<td width=143>\r\n\t\t<table width=143 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=6><img src=\"http://www.01net.com/img/dot.gif\" width=6 height=1></td>\r\n\t\t\t\t<td valign=top><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=15><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<img src=\"http://www.01net.com/img/ban/Ban_MA_trouv_ordi.gif\"><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/desktops/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Desktops</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/portables/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Portables</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Mini-PC</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/pda---tablets-pc/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Pda / Tablets-PC</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/apple/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Apple</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/gps/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">GPS</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20><br>\r\n\t\t\t\t\t\t\t\t<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td><input type=\"text\" name=\"recherchedirecte\" size=\"14\" style=\"width:130px;font:12px;\" value=\"     recherche directe\" onFocus=\"javascript:document.prix.recherchedirecte.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"/img/v4/MA/ok_bloc_recher_MA.gif\" border=\"0\"></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td width=1 bgcolor=#FFCC00><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=145 colspan=3><img src=\"http://www.01net.com/img/v4/MA/base_meillPrix.gif\"></td>\r\n\t\t</FORM>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_MeillPrixAct //-->  \t</td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n<!-- /MA_BP_MP -->  <!-- - ZONE H2 -->\r\n<!-- -ZONE_Hn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_Tn -->\r\n<!-- + ZONE T0 -->\r\n    <td valign=\"top\">\r\n<img src=\"http://www.01net.com/img/dot.gif\" height=13><br>\r\n<table border=0 width=320 cellpadding=0 cellspacing=0>\r\n<tr>\r\n<td width=305><img src=\"http://www.01net.com/img/ban/Ban_v4_DernNews_MA.gif\"><br><img src=\"http://www.01net.com/img/v4/MA/v4-tiret-hauts-mha.gif\"></td>\r\n<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n</tr>\r\n<tr>\r\n<td bgcolor=\"#FEF9E0\">\r\n\t<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Portable&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255149.html\" style=\"color:#000000;text-decoration:none;\">Toshiba consacre deux gammes de machines au multim\351dia</a></b><br>\r\n\t<font color=\"#000000\">Equipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Ordinateur&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254686.html\" style=\"color:#000000;text-decoration:none;\">Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme</a></b><br>\r\n\t<font color=\"#000000\">La firme \340 la pomme propose une station de travail \351volutive et relativement abordable.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>PC&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254549.html\" style=\"color:#000000;text-decoration:none;\">Alienware propose deux machines au look \351trange</a></b><br>\r\n\t<font color=\"#000000\">Aurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Portable&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254501.html\" style=\"color:#000000;text-decoration:none;\">Trois nouveaux iBook G4 chez Apple</a></b><br>\r\n\t<font color=\"#000000\">Chez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t\t<tr>\r\n\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=10></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-red-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td align=\"right\">\r\n\t\t\t\t<A HREF=\"http://microachat.01net.com/rubrique/4365.html\"  style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 10px;\">> toutes les news</font></a>\r\n\t\t\t</td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n</td> <!-- - ZONE T0 -->\r\n<!-- + ZONE T1 -->\r\n<!-- Ma_derpromo  -->\r\n    <td valign=\"top\">\r\n<img src=\"/img/dot.gif\" height=13><br>\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td bgcolor=\"#ffffff\"><img src=\"/img/v4/MA/v4-lespromos-mha.gif\"><br><img src=\"/img/v4/MA/v4-tiret-hauts-mha.gif\"></td>\r\n</tr>\r\n</table>\r\n<!-- DEBUT MODELE D\'AFFICHAGE POUR LES n PREMIERS ARTICLES //-->\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255806.html\" class=\"nodeco\"><img src=\"/images/67462.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255806.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>Asus A3N15-C Pro</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>1170&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255688.html\" class=\"nodeco\"><img src=\"/images/67381.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255688.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>Soltek EQ3702A Miroir</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>559&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255513.html\" class=\"nodeco\"><img src=\"/images/67319.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255513.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>IBM ThinkPad R51</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Voici un portable complet et pourtant relativement l\351ger.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>1299&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t\t<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td><img src=\"http://www.01net.com/img/dot.gif\" height=10></td>\r\n</tr>\r\n<tr>\r\n<td background=\"/img/v4/MA/v4-sep-red-mha.gif\"><img src=\"/img/dot.gif\" height=1></td>\r\n</tr>\r\n<tr>\r\n<td align=\"right\" valign=\"top\">\r\n\t\t\t\t<A HREF=\"http://microachat.01net.com/rubrique/4366.html\"  style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 10px;\">> toutes les promos</font></a>\r\n\t\t</td>\r\n</tr>\r\n</table>\r\n</td>\r\n<!-- /Ma_derpromo  -->   <!-- - ZONE T1 -->\r\n<!-- + ZONE T2 -->\r\n<!-- - ZONE T2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE T3 -->\r\n<!-- DEBUT MicroAchat MA_PubG -->\r\n<td valign=top align=center>\r\n<table border=0 width=320 cellpadding=0 cellspacing=0>\r\n\t<tr>\r\n\t\t<td width=305><img src=\"/img/dot.gif\" width=1 height=12><br><a href=\"http://www.smartadserver.com/call/cliccommand/45590/[timestamp]?\" target=_blank><img src=\"/img/microachat/Bandeau_FX6021.jpg\" border=0></a></td>\r\n\t\t<td><img src=\"/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_PubG -->  <!-- - ZONE T3 -->\r\n<!-- + ZONE T4 -->\r\n<!-- DEBUT MicroAchat MA_PubD -->\r\n<td valign=top align=center>\r\n<table border=0 width=305 cellpadding=0 cellspacing=0>\r\n\t<tr>\r\n\t\t<td width=305><img src=\"/img/dot.gif\" width=1 height=12><br><a href=\"http://www.smartadserver.com/call/cliccommand/45591/[timestamp]?\" target=_blank><img src=\"/img/microachat/twc_305x125.jpg\" border=0></a></td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN  MicroAchat MA_PubD --> <!-- - ZONE T4 -->\r\n<!-- + ZONE T5 -->\r\n<!-- - ZONE T5 -->\r\n<!-- -ZONE_Tn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n\t\t\t<td valign=top>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n<!-- +ZONE_gn -->\r\n<!-- + ZONE g0 -->\r\n<!-- - ZONE g0 -->\r\n<!-- + ZONE g1 -->\r\n<!-- - ZONE g1 -->\r\n<!-- + ZONE g2 -->\r\n<!-- - ZONE g2 -->\r\n<!-- + ZONE g3 -->\r\n<!-- - ZONE g3 -->\r\n<!-- + ZONE g4 -->\r\n<!-- - ZONE g4 -->\r\n<!-- + ZONE g5 -->\r\n<!-- - ZONE g5 -->\r\n<!-- + ZONE g6 -->\r\n<!-- - ZONE g6 -->\r\n<!-- + ZONE g7 -->\r\n<!-- - ZONE g7 -->\r\n<!-- + ZONE g8 -->\r\n<!-- - ZONE g8 -->\r\n<!-- + ZONE g9 -->\r\n<!-- - ZONE g9 -->\r\n<!-- -ZONE_gn -->\r\n\t\t\t</table>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t\t\t<tr>\r\n<!-- +ZONE_Mn -->\r\n<!-- + ZONE M0 -->\r\n<!-- modele Ma_GuideAch //-->\r\n    <td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" height=13><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t<tr>\r\n\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_GuideAchat_MA.gif\" vspace=1></td>\r\n\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<div style=\"border:solid 1px #FFCC00;width:100%\">\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<center>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"http://microachat.01net.com/article/254561.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67088.jpg.res_121-111.jpg\" border=0 hspace=0 vspace=0></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n</center>\r\n<div style=\"padding:5px;\">\r\n<a href=\"http://microachat.01net.com/article/254561.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\"><b>Les graveurs de DVD</b><br></font></a>\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">Quel graveur choisir&#160;? Quel type de format&#160;? Quelle vitesse&#160;? Double couche ou simple couche&#160;? Voici tout ce qu\'il faut savoir pour faire le bon choix.</font></div>\r\n\t\t\t\t\t\t</div>\r\n\t\t</td>\r\n\t</tr>\r\n</table>\r\n</td> <!-- - ZONE M0 -->\r\n<!-- + ZONE M1 -->\r\n<!-- modele Ma_DirectLab //-->\r\n    <td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t<tr>\r\n\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_DirectLab_MA.gif\" vspace=1></td>\r\n\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<div style=\"border:solid 1px #FFCC00;width:100%\">\r\n\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255744.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>Kodak EasyShare Printer Dock Plus&#160;:</b>\r\n\t\t\t\t\t\tvos photos 10&#160;x&#160;15&#160;cm en 60&#160;secondes</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255780.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>3DMark05&#160;:</b>\r\n\t\t\t\t\t\tun labo 3D \340 domicile</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255691.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>DVDInfoPro 2.6</b>\r\n\t\t\t\t\t\treconna\356t CD et DVD</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255722.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>Scaleo PA D3008, de Fujitsu-Siemens&#160;:</b>\r\n\t\t\t\t\t\tune impression d\'inachev\351</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255514.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">Carbon 5&#160;Go&#160;: 2&#160;500&#160;chansons dans le creux de la main</font></a></div>\r\n\t\t\t</div></td>\r\n\t</tr>\r\n</table>\r\n</td> <!-- - ZONE M1 -->\r\n<!-- + ZONE M2 -->\r\n<!-- DEBUT MicroAchat MA_AnnTelec -->\r\n<td valign=top>\r\n<script type=\"text/javascript\">\r\nfunction regionChange()\r\n{\r\ndocument.selection.departement.options.length=0;\r\nswitch(document.selection.region.value)\r\n\t{\r\n\t\tcase \"aucun\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Nord-Pas-de-Calais\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pas-de-Calais\", \"Pas-de-Calais\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Nord\", \"Nord\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Haute-Normandie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Eure\", \"Eure\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-Maritime\", \"Seine-Maritime\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Basse-Normandie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Manche\", \"Manche\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Calvados\", \"Calvados\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Orne\", \"Orne\");\r\n\t\tbreak;\r\n\t\tcase \"Picardie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Somme\", \"Somme\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Oise\", \"Oise\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aisne\", \"Aisne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Bretagne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Finistere\", \"Finistere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cotes-dArmor\", \"Cotes-dArmor\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Morbihan\", \"Morbihan\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ille-et-Vilaine\", \"Ille-et-Vilaine\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Pays-de-Loire\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loire-Atlantique\", \"Loire-Atlantique\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vendee\", \"Vendee\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Maine-et-Loire\", \"Maine-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Mayenne\", \"Mayenne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Sarthe\", \"Sarthe\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Centre\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Eure-et-Loir\", \"Eure-et-Loir\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loiret\", \"Loiret\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loir-et-Cher\", \"Loir-et-Cher\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Indre-et-Loire\", \"Indre-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Indre\", \"Indre\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cher\", \"Cher\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Ile-de-France\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Val-dOise\", \"Val-dOise\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Yvelines\", \"Yvelines\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Essonne\", \"Essonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-et-Marne\", \"Seine-et-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hauts-de-Seine\", \"Hauts-de-Seine\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-Saint-Denis\", \"Seine-Saint-Denis\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Val-de-Marne\", \"Val-de-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Paris\", \"Paris\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Champagnes-Ardennes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ardennes\", \"Ardennes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Marne\", \"Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aube\", \"Aube\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Marne\", \"Haute-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Lorraine\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vosges\", \"Vosges\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Meurthe-et-Moselle\", \"Meurthe-et-Moselle\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Meuse\", \"Meuse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Moselle\", \"Moselle\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Alsace\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Bas-Rhin\", \"Bas-Rhin\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haut-Rhin\", \"Haut-Rhin\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Franche-Compte\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Jura\", \"Jura\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Doubs\", \"Doubs\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Saone\", \"Haute-Saone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Territoire-de-Belfort\", \"Territoire-de-Belfort\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Bourgogne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Yonne\", \"Yonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Nievre\", \"Nievre\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cote-dOr\", \"Cote-dOr\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Saone-et-Loire\", \"Saone-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Poitou-Charentes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Deux-Sevres\", \"Deux-Sevres\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Charente-Maritime\", \"Charente-Maritime\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Charente\", \"Charente\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vienne\", \"Vienne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Limousin\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Vienne\", \"Haute-Vienne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Correze\", \"Correze\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Creuse\", \"Creuse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Auvergne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Allier\", \"Allier\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Puy-de-Dome\", \"Puy-de-Dome\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cantal\", \"Cantal\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Loire\", \"Haute-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Rhone-Alpes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loire\", \"Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Rhone\", \"Rhone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ain\", \"Ain\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ardeche\", \"Ardeche\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Drome\", \"Drome\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Isere\", \"Isere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Savoie\", \"Savoie\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Savoie\", \"Haute-Savoie\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Aquitaine\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gironde\", \"Gironde\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Landes\", \"Landes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pyrenees-Atlantiques\", \"Pyrenees-Atlantiques\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lot-et-Garonne\", \"Lot-et-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Dordogne\", \"Dordogne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Midi-Pyrenees\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lot\", \"Lot\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Tarn-et-Garonne\", \"Tarn-et-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gers\", \"Gers\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hautes-Pyrenees\", \"Hautes-Pyrenees\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Garonne\", \"Haute-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ariege\", \"Ariege\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Tarn\", \"Tarn\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aveyron\", \"Aveyron\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Languedoc-Roussillon\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pyrenees-Orientales\", \"Pyrenees-Orientales\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aude\", \"Aude\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Herault\", \"Herault\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gard\", \"Gard\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lozere\", \"Lozere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Provence-Alpes-Cote-dazur\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Bouches-du-Rhone\", \"Bouches-du-Rhone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vaucluse\", \"Vaucluse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Alpes-de-haute-Provence\", \"Alpes-de-haute-Provence\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hautes-Alpes\", \"Hautes-Alpes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Var\", \"Var\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Alpes-Maritimes\", \"Alpes-Maritimes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Corse\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Corse-du-Sud\", \"Corse-du-Sud\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Corse\", \"Haute-Corse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"DomTom\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Guadeloupe\", \"Guadeloupe\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Guyane\", \"Guyane\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"La-Reunion\", \"La-Reunion\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Martinique\", \"Martinique\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Mayotte\", \"Mayotte\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"St-Pierre-et-Miquelon\", \"St-Pierre-et-Miquelon\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t}\r\n}\r\nfunction deptChange()\r\n{\r\nif (document.selection.departement.value == \'Paris\')\r\n\tdocument.getElementById(\'arrondissement\').style.display = \'inline\';\r\nelse\r\n\tdocument.getElementById(\'arrondissement\').style.display = \'none\';\r\n}\r\n</script>\r\n<table width=305 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td valign=top>\r\n\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_AnnuaiRev_MA.gif\" vspace=1></td>\r\n\t\t\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr><form action=\"http://micro-achat.01net.com/annuaire/recherche.php\" method=\"post\" name=\"selection\">\r\n\t\t\t\t<td bgcolor=#FFFFDD>\r\n\t\t\t\t<div style=\"border:solid 1px #FFCC00;width:100%\"><div style=\"padding:2px;\"><img src=\"http://www.01net.com/img/v4/MA/carte_revend.gif\"><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Choisir une r\351gion</b><br></font>\r\n<select name=\"region\" onChange=\"regionChange()\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"aucun\">-------------</option>\r\n<option value=\"Nord-Pas-de-Calais\">Nord-Pas-de-Calais</option>\r\n<option value=\"Haute-Normandie\">Haute-Normandie</option>\r\n<option value=\"Basse-Normandie\">Basse-Normandie</option>\r\n<option value=\"Picardie\">Picardie</option>\r\n<option value=\"Bretagne\">Bretagne</option>\r\n<option value=\"Pays-de-Loire\">Pays-de-Loire</option>\r\n<option value=\"Centre\">Centre</option>\r\n<option value=\"Ile-de-France\">Ile-de-France</option>\r\n<option value=\"Champagnes-Ardennes\">Champagne ardennes</option>\r\n<option value=\"Lorraine\">Lorraine</option>\r\n<option value=\"Alsace\">Alsace</option>\r\n<option value=\"Franche-Compte\">Franche-Compte</option>\r\n<option value=\"Bourgogne\">Bourgogne</option>\r\n<option value=\"Poitou-Charentes\">Poitou-Charentes</option>\r\n<option value=\"Limousin\">Limousin</option>\r\n<option value=\"Auvergne\">Auvergne</option>\r\n<option value=\"Rhone-Alpes\">Rhone-Alpes</option>\r\n<option value=\"Aquitaine\">Aquitaine</option>\r\n<option value=\"Midi-Pyrenees\">Midi-Pyrenees</option>\r\n<option value=\"Languedoc-Roussillon\">Languedoc roussillon</option>\r\n<option value=\"Provence-Alpes-Cote-dazur\">PACA</option>\r\n<option value=\"Corse\">Corse</option>\r\n<option value=\"DomTom\">DomTom</option>\r\n</select>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Un d\351partement</b><br></font>\r\n<select name=\"departement\" onChange=\"deptChange()\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"aucun\">-------------</option>\r\n</select>\r\n<div id=\"arrondissement\" style=\"display : none;\">\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Un arrondissement</b><br></font>\r\n<select name=\"arrondissement\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"0\">-------------</option>\r\n<option value=\"1\">I</option>\r\n<option value=\"2\">II</option>\r\n<option value=\"3\">III</option>\r\n<option value=\"4\">IV</option>\r\n<option value=\"5\">V</option>\r\n<option value=\"6\">VI</option>\r\n<option value=\"7\">VII</option>\r\n<option value=\"8\">VIII</option>\r\n<option value=\"9\">IX</option>\r\n<option value=\"10\">X</option>\r\n<option value=\"11\">XI</option>\r\n<option value=\"12\">XII</option>\r\n<option value=\"13\">XIII</option>\r\n<option value=\"14\">XIV</option>\r\n<option value=\"15\">XV</option>\r\n<option value=\"16\">XVI</option>\r\n<option value=\"17\">XVII</option>\r\n<option value=\"18\">XVIII</option>\r\n<option value=\"19\">XIX</option>\r\n<option value=\"20\">XX</option>\r\n</select>\r\n</div>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=10><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Recherche directe</b><br></font>\r\n\t\t\t\t<font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\"><img src=\"http://www.01net.com/img/dot.gif\" width=8 height=1>rechercher une ville<br><img src=\"http://www.01net.com/img/dot.gif\" width=8 height=1>et/ou une boutique<br></font>\r\n\t\t\t\t<input type=\"text\" name=\"recherchedirecte\" size=\"14\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;width:130px;\" value=\"\" onFocus=\"javascript:document.selection.recherchedirecte.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=3><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1>&nbsp;<input type=\"image\" src=\"http://www.01net.com/img/v4/MA/ok_bloc_recher_MA.gif\" border=\"0\">\r\n\t\t\t\t<table height=23 width=135 cellspacing=0 cellpadding=0 border=0 bgcolor=#FFEE77>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td bgcolor=#FFEE77 valign=middle align=center><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://micro-achat.01net.com/annuaire/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Recherche avanc\351e</b></font></a></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t</div>\r\n\t\t\t\t</div>\r\n\t\t\t\t</td>\r\n\t\t\t</tr></form>\r\n\t\t</table>\r\n\t\t</td>\r\n<!-- DEBUT MicroAchat MA_Telecharg //-->\r\n<td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n<table width=\"145\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/v4/MA/Ban_v4_MA_telec.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<table width=\"145\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#DFECF6\">\r\n\t\t\t<tr>\r\n\t\t\t\t<td rowspan=\"17\"><img src=\"http://www.01net.com/img/dot.gif\" width=\"6\"></td>\r\n\t\t\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"></td>\r\n\t\t\t\t<td rowspan=\"17\"><img src=\"http://www.01net.com/img/dot.gif\" width=\"6\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Bureautique\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Bureautique</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Traducteur, organiseur...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Multimedia\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Multim\351dia</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Photo, audio, vid\351o...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Utilitaire\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Utilitaires</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Antivirus, pilotes, gravure...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Personnaliser\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Personnaliser son PC</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Ecrans de veille, th\350mes...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Programmation\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>D\351veloppement</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Cr\351ation de logiciels, BDD...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Jeux\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Jeux</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Action, simulation...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Internet\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Internet</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Utilitaires, email, FTP...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Loisirs\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Loisirs</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Humour, culture...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_Telecharg //-->  \t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_AnnTelec --> <!-- - ZONE M2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE M3 -->\r\n<!-- - ZONE M3 -->\r\n<!-- + ZONE M4 -->\r\n<!-- - ZONE M4 -->\r\n<!-- + ZONE M5 -->\r\n<!-- - ZONE M5 -->\r\n<!-- -ZONE_Mn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t<tr>\r\n<!-- +ZONE_tn -->\r\n<!-- + ZONE t0 -->\r\n<!-- - ZONE t0 -->\r\n<!-- + ZONE t1 -->\r\n<!-- - ZONE t1 -->\r\n<!-- + ZONE t2 -->\r\n<!-- - ZONE t2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE t3 -->\r\n<!-- - ZONE t3 -->\r\n<!-- + ZONE t4 -->\r\n<!-- - ZONE t4 -->\r\n<!-- + ZONE t5 -->\r\n<!-- - ZONE t5 -->\r\n<!-- -ZONE_tn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td valign=top>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t<tr>\r\n<!-- +ZONE_dn -->\r\n<!-- + ZONE d0 -->\r\n<!-- - ZONE d0 -->\r\n<!-- + ZONE d1 -->\r\n<!-- - ZONE d1 -->\r\n<!-- + ZONE d2 -->\r\n<!-- - ZONE d2 -->\r\n<!-- + ZONE d3 -->\r\n<!-- - ZONE d3 -->\r\n<!-- + ZONE d4 -->\r\n<!-- - ZONE d4 -->\r\n<!-- + ZONE d5 -->\r\n<!-- - ZONE d5 -->\r\n<!-- + ZONE d6 -->\r\n<!-- - ZONE d6 -->\r\n<!-- + ZONE d7 -->\r\n<!-- - ZONE d7 -->\r\n<!-- + ZONE d8 -->\r\n<!-- - ZONE d8 -->\r\n<!-- + ZONE d9 -->\r\n<!-- - ZONE d9 -->\r\n<!-- -ZONE_dn -->\r\n\t\t\t\t</tr>\r\n\t\t\t</table>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n\t\t</table>\r\n<!-- FIN WORK -->\r\n\t\t</td>\r\n<!-- *********************************************************************FIN VENTRE********************************************************************************************************************************************** //-->\r\n\t\t<td rowspan=2 valign=top width=23 background=\"http://www.01net.com/img/v4/sep_verticale.gif\"><img src=\"http://www.01net.com/img/dot.gif\" width=23 height=1><br></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t\t<td colspan=2>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=100%>\r\n<!-- +ZONE_Bn -->\r\n<!-- + ZONE B0 -->\r\n<!-- - ZONE B0 -->\r\n<!-- + ZONE B1 -->\r\n<tr><!-- ********** DEBUT BLOC Home NosJournauxV4 //-->\r\n<td valign=top bgcolor=#FFFFFF>\r\n<img src=\"http://www.01net.com/img/ban/Ban_v4_jx.gif\"><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=15><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1>\r\n<a href=\"http://www.01net.com/rubrique/3339.html\"><img src=\"http://www.01net.com/img/journaux/01I-small.gif\" border=0 vspace=0 hspace=12 align=top></a>\r\n<a href=\"http://www.01net.com/rubrique/4051.html\"><img src=\"http://www.01net.com/img/journaux/DSI-small.gif\" border=0 vspace=0 hspace=12 align=top></a>\r\n<a href=\"http://www.01net.com/rubrique/3345.html\"><img src=\"http://www.01net.com/img/journaux/DIN-small.gif  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        <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\r\n<BASE target=\"_top\">\r\n\n<TITLE>Micro Achat : Ordinateurs, PDA -  Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux</TITLE>\r\n<META NAME=\"Description\" CONTENT=\"Micro Achat : Ordinateurs, PDA\">\r\n<META NAME=\"Keywords\" CONTENT=\"Micro Achat : Ordinateurs, PDA -  Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\">\r\n<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"http://www.01net.com/styles/01net.css\">\r\n<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"http://www.01net.com/styles/tableau_autre.css\">\r\n<STYLE type=text/css>\r\nA{TEXT-DECORATION: none;color:#000000;}\r\nA:visited{TEXT-DECORATION: none;color:#000000;}\r\n</STYLE>\r\n<SCRIPT LANGUAGE=\"JavaScript1.1\">\r\nvar sameAsBigDay = new Date();\r\nvar ord = (sameAsBigDay.getTime());\r\nvar pubsMotsCles = \"\";\r\nvar exc;\r\nvar lienhautdepage = \"\";\r\nvar etatmessage = false;\r\nvar enchainement = false;\r\nsas_tmstp=Math.round(Math.random()*10000000000);\r\nfunction SmartAdServer(sas_pageid,sas_formatid,sas_master,sas_target) {\r\n if ((sas_master!=\'M\')&&(sas_master!=\'S\')) {sas_master=\'S\'};\r\n document.write(\'<SCR\'+\'IPT SRC=\"http://www.smartadserver.com/call/pubj/\' + sas_pageid + \'/\' + sas_formatid + \'/\'+sas_master + \'/\' + sas_tmstp + \'/\' + escape(sas_target) + \'?\"></SCR\'+\'IPT>\');\r\n}\r\n</SCRIPT>\r\n<SCRIPT LANGUAGE=\"JAVASCRIPT\" SRC=\"http://www.01net.com/js/exc.js\"></SCRIPT>\r\n<script language=\"javascript\" src=\"http://telecharger.01net.com/shopping/js/headservicesV4.js\"></script>\r\n<noscript>\r\n<a href=\"http://cinema.01net.com\">T\351l\351charger des bandes-annonces, des teasers, des extraits et des making of de vos films cin\351ma pr\351f\351r\351s</a>,\r\n<a href=\"http://www.01net.com/BusinessTechnologies/\">Portail leader de l\'information sur les nouvelles technologies - Actualites et enquetes sur l\'informatique et les NTIC (nouvelles technologies de l\'information et la communication). Exemples de sujets : e-business, telecoms, CRM, VPN, 3G, DSL, fournisseurs d\'acces, Linux, piratage, securite informatique, progiciel...</a><br>\r\n<a href=\"http://www.01net.com/securite_informatique.html\">s\351curit\351 informatique</a>,\r\n<a href=\"http://www.01net.com/strategies_ntic.html\">strat\351gies NTIC</a>,\r\n<a href=\"http://www.01net.com/piratage_informatique.html\">piratage informatique</a>,\r\n<a href=\"http://www.01net.com/technologie_dsl.html\">technologie DSL</a>,\r\n<a href=\"http://www.01net.com/solutions_vpn.html\">solutions VPN</a>,\r\n<a href=\"http://www.01net.com/strategie_e-business.html\">strat\351gies</a>,\r\n<a href=\"http://www.01net.com/outils_crm.html\">outils CRM</a>,\r\n<a href=\"http://www.01net.com/logiciel_linux.html\">logiciel Linux</a>,\r\n<a href=\"http://www.01net.com/fournisseur_d_acces.html\">fournisseur d\'acc\350s</a>,\r\n<a href=\"http://www.01net.com/progiciel.html\">progiciel</a>,\r\n<a href=\"http://www.01net.com/stockage_de_donnees.html\">stockage de donn\351es</a>,\r\n<a href=\"http://www.01net.com/etudes_solution_informatique.html\">\351tudes solution informatique</a>,\r\n<a href=\"http://www.01net.com/NTIC.html\">NTIC</a>,\r\n<a href=\"http://www.01net.com/actualite_technologie.html\">actualit\351 technologie</a>,\r\n<a href=\"http://www.01net.com/etude_materiel_informatique.html\">\351tude mat\351riel informatique</a>,\r\n<a href=\"http://www.01net.com/actus/\">actualit\351s des nouvelles technologies</a>,\r\n<a href=\"http://www.01net.com/MicroPerso/\">enqu\352tes et trucs et astuces sur le mat\351riel informatique, les logiciels, les fournisseurs d\'acc\350s...</a>,\r\n<a href=\"http://www.01net.com/emploi/\">emploi et formations informatiques : offres d\'emploi informatique...</a>,\r\n<a href=\"http://www.01net.com/produits/\">fiches, tests mat\351riels et logiciels en informatique</a>,\r\n<a href=\"http://www.01net.com/01informatique\">01 Informatique</a>,\r\n<a href=\"http://www.caractere.net\">Caract\350re, le site des professionnels de l\'imprim\351 - communication imprim\351e, \351dition, emballage, encres, finition, flexographie, h\351liogravure, impression, imprimerie, imprimeur, industries graphiques, num\351rique, offset, papier, pr\351presse, presse, print, reprographie, s\351rigraphie, typographie</a>,\r\n<a href=\"http://www.01net.com/decisionmicro\">Decision Micro</a>,\r\n<a href=\"http://www.01net.com/decisioninformatique\">D\351cision Informatique</a>,\r\n<a href=\"http://www.01net.com/01reseaux\">01 R\351seaux</a>,\r\n<a href=\"http://logiciel.telecharger.01net.com/\">logiciel</a>,\r\n<a href=\"http://developpeur.telecharger.01net.com/windows/Programmation/\">d\351veloppeur programmation</a>,\r\n<a href=\"http://anti-virus.telecharger.01net.com\">anti-virus</a>,\r\n<a href=\"http://gravure-cd-dvd.telecharger.01net.com/windows/Utilitaire/gravure/\">gravure cd dvd</a>,\r\n<a href=\"http://codec.telecharger.01net.com/windows/Multimedia/encodeurs_et_decodeurs/\">codec encodeur d\351codeur</a>,\r\n<a href=\"http://software.telecharger.01net.com/\">software</a>,\r\n<a href=\"http://logiciels.telecharger.01net.com/\">logiciels</a>,\r\n<a href=\"http://gratuit.telecharger.01net.com/\">gratuit</a>,\r\n<a href=\"http://p2p.telecharger.01net.com/windows/Internet/partage/\">p2p peer to peer partage de fichiers</a>,\r\n<a href=\"http://securite.telecharger.01net.com/windows/Utilitaire/cryptage_et_securite/\">s\351curit\351</a>,\r\n<a href=\"http://compression-decompression.telecharger.01net.com/windows/Utilitaire/compression_et_decompression/\">compression et d\351compression</a>,\r\n<a href=\"http://divx.telecharger.01net.com/\">divx</a>,\r\n<a href=\"http://utilitaire.telecharger.01net.com/windows/Utilitaire/\">utilitaire</a>,\r\n<a href=\"http://jeux.telecharger.01net.com/windows/Jeux/\">jeux</a>,\r\n<a href=\"http://loisirs.telecharger.01net.com/windows/Loisirs/\">loisirs</a>,\r\n<a href=\"http://mac.telecharger.01net.com/mac/\">mac</a>,\r\n<a href=\"http://linux.telecharger.01net.com/linux/\">linux</a>,\r\n<a href=\"http://shareware.telecharger.01net.com/\">shareware</a>,\r\n<a href=\"http://video-dvd.telecharger.01net.com/windows/Multimedia/lecteurs_video_dvd/\">vid\351o dvd</a>,\r\n<a href=\"http://multimedia.telecharger.01net.com/\">multim\351dia</a>,\r\n<a href=\"http://traduction.telecharger.01net.com/windows/Bureautique/traducteur/\">traduction</a>,\r\n<a href=\"http://mp3.telecharger.01net.com/windows/Multimedia/lecteurs_audio_mp3_cd/\">mp3</a>,\r\n<a href=\"http://tchat.telecharger.01net.com/windows/Internet/communication/\">tchat</a>\r\n<a href=\"http://chat.telecharger.01net.com/windows/Internet/communication/\">chat</a>,\r\n<a href=\"http://musique.telecharger.01net.com/\">musique</a>,\r\n<a href=\"http://mobile.telecharger.01net.com/mobile/\">mobile</a>,\r\n<a href=\"http://telephone_portable.telecharger.01net.com/mobile/\">t\351l\351phone portable</a>,\r\n<a href=\"http://telephone_mobile.telecharger.01net.com/mobile/\">t\351l\351phone mobile</a>\r\n</noscript>\r\n</head>\r\n</head>\r\n<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#000000\" marginwidth=0 marginheight=0 topmargin=0 leftmargin=0>\r\n<!-- + ZONE TETE -->\r\n<!-- ********** DEBUT MODELE INTERNE TETES MHA-tetev4 //-->\r\n<table width=100% height=66 cellspacing=0 cellpadding=0 border=0 bgcolor=#ffffff>\r\n\t<tr>\r\n\t\t<td height=8 colspan=2><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=8></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td valign=bottom><a href=\"http://microachat.01net.com\"><img src=\"http://www.01net.com/img/v4/logos_tete/tet_gauche-mha.gif\" border=0></a></td>\r\n\t\t<td valign=bottom bgcolor=#FFFFFF bbackground=\"http://www.01net.com/img/v4/tet_droite.gif\" width=100% style=\"background-image:url(/img/v4/tet_droite-mha.gif);background-position:bottom;background-repeat:repeat-x\"><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=66 align=left hspace=0 vspace=0></td>\r\n\t</tr>\r\n</table>\r\n<table width=100% cellspacing=0 cellpadding=0 border=0 bgcolor=#ffffff>\r\n\t<tr>\r\n\t\t<td valign=top background=\"http://www.01net.com/img/v4/fond_date-mha.gif\" height=18 width=500><img src=\"http://www.01net.com/img/dot.gif\" width=500 height=1><br><img src=\"http://www.01net.com/img/dot.gif\" width=19 height=1><font face=\"Arial\" size=1 color=#666666 style=\"font-size: 11px;\"><b>Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004&nbsp;&nbsp;|&nbsp;&nbsp;16:45</b></font></td>\r\n\t\t<td width=100% background=\"http://www.01net.com/img/v4/fond_date2-mha.gif\" height=18></td>\r\n\t</tr>\r\n</table>\r\n<!-- ********** FIN MODELE INTERNE TETES MHA-tetev4 //--> <!-- - ZONE TETE -->\r\n<!-- ***************************************************************************************************************************************************************************************************************************** //-->\r\n<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n<!-- DEBUT PARTIE PUB //-->\r\n\t<tr>\r\n<td align=center valign=middle colspan=2 background=\"http://www.01net.com/img/v4/fond_bann.gif\"><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br>\r\n<!-- + ZONE Z0 -->\r\n<SCRIPT LANGUAGE=\"JAVASCRIPT\">\r\nvar fa = \"\";\r\nvar fab = document.URL.toString();\r\nif (fab.indexOf(\"?fa\") != -1 || fab.indexOf(\"&fa\") != -1)\r\n{\r\nfa = \";!category=fai\";\r\n}\r\nvar etatmessage = false;\r\nvar enchainement = false;\r\n</SCRIPT>\r\n<SCRIPT LANGUAGE=\"JavaScript1.1\">\r\nsas_pageid=\'167/3872\';\r\nsas_formatid=95;\t\t\t// Format : Banner/Scope 468x60\r\nsas_master=\'M\';\t\t\t// Master : M=master or S=slave\r\nsas_target=exc + \'rubrique\';\t\t\t// Targeting\r\nSmartAdServer(sas_pageid,sas_formatid,sas_master,sas_target);\r\n</SCRIPT>\r\n <!-- - ZONE Z0 --></td>\r\n\t\t<td valign=top width=23 background=\"http://www.01net.com/img/v4/sep_verticale.gif\" ><img src=\"http://www.01net.com/img/dot.gif\" width=23 height=1><br></td>\r\n<td valign=top width=100% bgcolor=\"ffffff\" rowspan=3><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=125><br>\r\n<!-- +ZONE_Dn -->\r\n<!-- + ZONE D0 -->\r\n<!-- DEBUT MA_ColD -->\r\n<div style=\"background-color : #ffffff; width : 150px; padding-left : 5px; padding-right : 5px; font-family : Arial, Helvetica;\">\n\t\t\t\t\t<table style=\"border-spacing : 0; width : 146px; margin-top : 0px;\" cellspacing=\"0\">\n\t\t\t\t\t<tr><th colspan=\"2\" style=\"padding : 0;\"><img src=\"http://micro-achat.01net.com/img/utils/micro-achat/tete-produitsrecherches.gif\" alt=\"\" /></th></tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Imagerie&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/12537-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/imagerie/moniteurs-lcd/l1720b/\">LG L1720B</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">332.89 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Ordinateurs&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/4043-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/desktops/veriton-7600g/\">Acer Veriton 7600G</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">705 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Ordinateurs&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/1903-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/sn95g5/\">Shuttle SN95G5</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">375 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Composants&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/1259-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/composants/cartes-meres/a7n8x-e-deluxe/\">Asus A7N8X-E Deluxe</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">91.99 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Composants&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/4687-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/composants/ventilateur/sp-94/\">Thermalright SP-94</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">49 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr></table>\n\t\t\t\t<table style=\"border-spacing : 0px 1px; width : 146px; margin-top : 15px;\" cellspacing=\"0\">\n\t\t\t\t<tr><th colspan=\"2\" style=\"padding : 0;\"><img src=\"http://micro-achat.01net.com/img/utils/micro-achat/tete-revendeurmisajour.gif\" alt=\"\" /></th></tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">1 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Rhone-Alpes/Ain/pc-look\" style=\"color : #000000; text-decoration : none;\">PC Look</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">2 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Nord-Pas-de-Calais/Pas-de-Calais/atelier-informatique\" style=\"color : #000000; text-decoration : none;\">Atelier Informatique</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">3 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Val-de-Marne/zanax-multimedia\" style=\"color : #000000; text-decoration : none;\">Zanax Multim\351dia</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">4 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Hauts-de-Seine/misteroops\" style=\"color : #000000; text-decoration : none;\">MISTEROOPS</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">5 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/12/168-golden-avenue\" style=\"color : #000000; text-decoration : none;\">168 Golden Avenue</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">6 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Seine-Saint-Denis/microchoix\" style=\"color : #000000; text-decoration : none;\">microchoix</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">7 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/12/e-soph\" style=\"color : #000000; text-decoration : none;\">e-Soph</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">8 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/13/pc-price-club\" style=\"color : #000000; text-decoration : none;\">PC Price Club</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">9 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Seine-et-Marne/pc-77\" style=\"color : #000000; text-decoration : none;\">PC 77</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">10 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Alsace/Bas-Rhin/web-in-informatique\" style=\"color : #000000; text-decoration : none;\">Web In Informatique</a></td>\n\t\t\t\t</tr></table>\n\t\t\t\t</div>\n\t\t\t\t<br>\r\n<!-- FIN MA_ColD --> <!-- - ZONE D0 -->\r\n<!-- + ZONE D1 -->\r\n<!-- - ZONE D1 -->\r\n<!-- + ZONE D2 -->\r\n<!-- - ZONE D2 -->\r\n<!-- -ZONE_Dn -->\r\n</td>\r\n\t</tr>\r\n<!-- FIN PARTIE PUB //-->\r\n\t<tr>\r\n\t\t<td valign=top width=193 height=100% background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n\t\t<!-- contenu colonne de gauche //-->\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0  background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n<!-- +ZONE_Gn -->\r\n<!-- + ZONE G0 -->\r\n<tr><!-- ********** DEBUT MHA_MenusChainesV4 //-->\r\n<td valign=top>\n<table border=0 cellpadding=0 cellspacing=0 width=193 bgcolor=#FFFFFF>\n<tr>\n<td background=\"/img/v4/menus/motifgauche_menus.gif\" width=20 rowspan=2><img src=\"/img/dot.gif\" width=20 height=20></td>\n<td width=173 colspan=2 bgcolor=#FFFFFF><img src=\"/img/dot.gif\" width=173 height=20></td>\n</tr>\n<tr>\n<td valign=top width=159>\n\n<a href=\"http://www.01net.com\"><img src=\"/img/v4/menus/mha/home01net-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com\"><img src=\"/img/v4/menus/mha/home-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4317.html\"><img src=\"/img/v4/menus/mha/ordinateurs-2.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4318.html\"><img src=\"/img/v4/menus/mha/composants-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4319.html\"><img src=\"/img/v4/menus/mha/stockage-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4320.html\"><img src=\"/img/v4/menus/mha/image-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4321.html\"><img src=\"/img/v4/menus/mha/peripheriques-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4322.html\"><img src=\"/img/v4/menus/mha/reseaux-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4323.html\"><img src=\"/img/v4/menus/mha/accessoires-1.gif\" width=159 border=0></a><br>\n<a href=\"http://micro-achat.01net.com/guide-produits/\"><img src=\"/img/v4/menus/mha/comparateur-1.gif\" width=159 border=0></a><br>\n<a href=\"http://micro-achat.01net.com/annuaire/\"><img src=\"/img/v4/menus/mha/annuaire-1.gif\" width=159 border=0></a><br></td>\n<td width=14><img src=\"/img/dot.gif\" width=14 height=14></td>\n</tr>\n<tr>\n<td colspan=3><img src=\"/img/v4/menus/bas_menus.gif\" width=193 height=31></td>\n</tr>\n</table></td><!-- ********** FIN MHA_MenusChainesV4 //--> </tr><!-- - ZONE G0 -->\r\n<!-- + ZONE G1 -->\r\n<tr><!-- DEBUT MODELE RUBRIQUE V4ColGaucheMHA //-->\r\n<!-- ********** DEBUT BLOC DernieresNewsTC //-->\r\n<td valign=top>\r\n<!-- DEBUT RECHERCHE MHA -->\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n\t\t\t<td valign=top background=\"http://microachat.01net.com/img/v4/fond_rech_mha.gif\" height=98 style=\"background-repeat:no-repeat;\"><form method=\"get\" name=\"chercher\" action=\"http://www.01net.com/aiguillage_recherche/1,6138,,00.html\"><img src=\"http://microachat.01net.com/img/dot.gif\" width=193 height=17><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><input type=\"text\" name=\"fullText\" style=\"width:130px;font:12px;\"><br><img src=\"http://microachat.01net.com/img/dot.gif\" width=1 height=6><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><select name=\"sousArbo\" style=\"width:130px;font:12px;\">\r\n\t\t\t<option value=\"mha\">dans Micro Achat\r\n\t\t\t<option value=\"cmp\">les prix\r\n\t\t\t<option value=\"ann\">les revendeurs\r\n\t\t\t<option value=\"2641\">tout 01net.\r\n\t\t\t<option value=\"emploi\">les offres d\'emploi\r\n\t\t\t<option value=\"telecharger\"> telecharger.com\r\n\t\t\t<option value=\"web\">le web\r\n\t\t\t</select><br><img src=\"http://microachat.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"http://microachat.01net.com/img/v4/ok_bloc_recher_mha.gif\" border=\"0\"></form>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=10 vspace=0>\r\n<!-- FIN RECHERCHE MHA -->\r\n      <!-- modele TCFilColgTitV4 //-->\r\n    <table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top>\r\n\t\t<table width=155 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=2><img src=\"http://www.01net.com/img/ban/Ban_v4_DernieresNews01net.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4></td>\r\n\t\t\t</tr>\r\n\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/256059.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">CD et DVD bient\364t insensibles aux rayures<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/255796.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">OpenOffice gagne son service<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/255731.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">La messagerie en cinq minutes selon Ipswitch<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top colspan=2><A HREF=\"http://www.01net.com/actus/\" style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\">> toutes les news<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t\t<tr>\r\n\t\t\t\t<td colspan=2><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/crochet_bleuhaut_155.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20> <!-- ********** FIN BLOC DernieresNewsTC //-->\r\n<!-- ********** DEBUT BLOC  NL_MHA //-->\r\n<SCRIPT language=\"javascript\" src=\"http://www.01net.com/js/lib.js\"></SCRIPT>\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<FORM name=\"formgen\" method=\"get\" action=\"http://microachat.01net.com/outils/newsletter_MicroAchat.html\" onSubmit=\"return validateForm(this)\">\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=155 colspan=4><img src=\"http://www.01net.com/img/ban/Ban_V4_Newslett.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=10><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=1 bgcolor=#CC0000><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t<td width=153>\r\n\t\t<table width=153 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=10><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t\t\t<td valign=top><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefinefd_ffffff.gif\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Recevez chaque jour l\'actualit\351 des produits et des promos<br></font>\r\n\t\t\t\t<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td><input type=\"text\" name=\"email\" size=\"14\" style=\"width:130px;font:12px;\" value=\"entrez votre e-mail\" onFocus=\"javascript:document.formgen.email.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"http://www.01net.com/img/v4/ok_bloc_recher.gif\" border=\"0\"></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td width=1 bgcolor=#CC0000><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=155 colspan=4><img src=\"http://www.01net.com/img/v4/base_newsletters.gif\"></td>\r\n\t\t</FORM>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20>\r\n<SCRIPT language=\"Javascript\">\r\ndocument.formgen.email.validator= \'notNullEmailPat\';\r\ndocument.formgen.email.nomvalidator= \'E-mail\';\r\n</SCRIPT>\r\n<!-- ********** FIN BLOC NL_MHA //-->\r\n</td>\r\n</tr>\r\n<tr>\r\n<!-- ********** DEBUT BLOC Actus ActusUneV4 //-->\r\n<td valign=top background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n<table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top>\r\n\t\t<table width=155 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/ban/Ban_v4_LaUne.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/entreprise/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Entreprise</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://www.01net.com/article/255737.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">Quand le billet papier s\'envole vers la d\351mat\351rialisation</font></a></td>\r\n\t\t\t\t<td valign=top width=2><img src=\"http://www.01net.com/img/dot.gif\" width=2 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/article/255737.html\"><img src=\"http://www.01net.com/img/MEA_v4/billet_virtuel-65.jpg\" border=0></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/pratique/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Trucs et astuces</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255698.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">D\351pannez Windows XP</font></a></td>\r\n\t\t\t\t<td valign=top width=2><img src=\"http://www.01net.com/img/dot.gif\" width=2 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/article/255698.html\"><img src=\"http://www.01net.com/img/MEA_v4/depannez_XP-65.jpg\" border=0 ></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t</tr>\r\n\t\t    <tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top colspan=3><a href=\"http://www.01net.com/conso/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Conso</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255524.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">Vos photos sur papier imprimante ou labo ?<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t<!-- exemple de lien avec pseudorub pour produits et tests -->\r\n\t\t<!-- <a href=\"/outils/PseudoRub.php?base=test-comp&rub=1730&pseudo=test-comp20041005\"> -->\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top colspan=3><a href=\"http://www.01net.com/produits/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Produits &amp; Tests</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255782.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">5 programmes d\222encodage vid\351o gratuits<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20>\r\n</td>\r\n<!-- ********** FIN BLOC Actus ActusUneV4 //-->    </tr>\r\n<tr>\r\n<td>\r\n<table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top><a href=\"mailto:s.cohen@micro-achat.fr\"><img border=0 src=\"http://www.01net.com/img/v4/espace-revendeurs.gif\"></td>\r\n\t</tr>\r\n</table>\r\n<br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20></td>\r\n<!-- FIN MODELE RUBRIQUE V4ColGaucheMHA //-->  </tr><!-- - ZONE G1 -->\r\n<!-- + ZONE G2 -->\r\n<!-- - ZONE G2 -->\r\n<!-- + ZONE G3 -->\r\n<!-- - ZONE G3 -->\r\n<!-- + ZONE G4 -->\r\n<!-- - ZONE G4 -->\r\n<!-- + ZONE G5 -->\r\n<!-- - ZONE G5 -->\r\n<!-- + ZONE G6 -->\r\n<!-- - ZONE G6 -->\r\n<!-- + ZONE G7 -->\r\n<!-- - ZONE G7 -->\r\n<!-- + ZONE G8 -->\r\n<!-- - ZONE G8 -->\r\n<!-- + ZONE G9 -->\r\n<!-- - ZONE G9 -->\r\n<!-- + ZONE GA -->\r\n<!-- - ZONE GA -->\r\n<!-- + ZONE GB -->\r\n<!-- - ZONE GB -->\r\n<!-- + ZONE GC -->\r\n<!-- - ZONE GC -->\r\n<!-- + ZONE GD -->\r\n<!-- - ZONE GD -->\r\n<!-- + ZONE GE -->\r\n<!-- - ZONE GE -->\r\n<!-- + ZONE GF -->\r\n<!-- - ZONE GF -->\r\n<!-- -ZONE_Gn -->\r\n\t\t</table>\r\n\t\t<!-- fin contenu colonne de gauche //-->\r\n\t\t</td>\r\n<!-- ***************************************************************** DEBUT VENTRE*********************************************************************************************************************************************** //-->\r\n<!-- DEBUT WORK -->\r\n\t\t<td valign=top width=625 bgcolor=#ffffff><img src=\"http://www.01net.com/img/dot.gif\" width=625 height=1><br>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_hn -->\r\n<!-- + ZONE h0 -->\r\n<!-- MA_ban_int -->\r\n<td valign=\"top\">\r\n<img src=\"/img/dot.gif\" height=\"18\"><br>\r\n<!-- pour ordipda -->\r\n<table width=\"625\" cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"/img/v4/MA/Ban_MA_ordis.gif\"></td>\r\n\t</tr>\r\n</table>\r\n\t</td>\r\n<!-- /MA_ban_int -->     <!-- - ZONE h0 -->\r\n<!-- + ZONE h1 -->\r\n<!-- - ZONE h1 -->\r\n<!-- + ZONE h2 -->\r\n<!-- - ZONE h2 -->\r\n<!-- -ZONE_hn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_Hn -->\r\n<!-- + ZONE H0 -->\r\n<!-- Ma_int_Leader -->\r\n    <td valign=top>\r\n<img src=\"/img/dot.gif\" width=1 height=18><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=320>\r\n<tr>\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<td width=144 valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=143 height=1 vspace=0><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:11px;>Portable</font><br>\r\n<A HREF=\"/article/256198.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=font-size:14px;><b>Un nouvel ultra portable r\351alis\351 par Nec</b></font></a><br>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/256198.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67509.jpg.res_100-100.jpg\" border=0 hspace=0 vspace=0></a><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n<font face=arial,helvetica size=2 color=#000000 style=font-size:12px;><img src=\"/img/v4/flechefine_fondtransp.gif\">Le Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.</font><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:12px;>\340 partir de 1663&#160;\200</font>\r\n</td>\r\n<td width=17 background=\"/img/v4/MA/v4-fond-sep-mea-leader.gif\"><img src=\"/img/dot.gif\" width=17 height=1></td>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<td width=144 valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=143 height=1 vspace=0><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:11px;>Portable</font><br>\r\n<A HREF=\"/article/255194.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=font-size:14px;><b>Asus pr\351sente trois petits nouveaux dans la gamme A3N</b></font></a><br>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255194.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67168.jpg.res_100-100.jpg\" border=0 hspace=0 vspace=0></a><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n<font face=arial,helvetica size=2 color=#000000 style=font-size:12px;><img src=\"/img/v4/flechefine_fondtransp.gif\">Ces trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.</font><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:12px;>\340 partir de 1346&#160;\200</font>\r\n</td>\r\n<td width=15><img src=\"/img/dot.gif\" width=15 height=1></td>\r\n\t\t\t\t</tr>\r\n</table>\r\n</td>\r\n<!-- /Ma_int_Leader -->    <!-- - ZONE H0 -->\r\n<!-- + ZONE H1 -->\r\n<!-- - ZONE H1 -->\r\n<!-- + ZONE H2 -->\r\n<!-- MA_BP_MP -->\r\n<td valign=\"top\" width=\"100%\">\r\n\t<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\r\n\t<tr>\r\n\t<td width=\"50%\" valign=\"top\">\r\n\t<!-- DEBUT MicroAchat MA_BonPlan -->\r\n<td valign=top>\r\n<img src=\"/img/dot.gif\" width=1 height=18><br>\r\n<table border=0 cellpadding=1 cellspacing=0 width=145 bgcolor=#CC0000>\r\n<tr>\r\n<td align=center><font face=arial,helvetica size=1 color=#FFFFFF style=\"font-size:11px;\">BON PLAN</a></font></td>\r\n</tr>\r\n<tr>\r\n<td  width=145>\r\n<div style=\"padding:5px;padding-left:5px;padding-fight:5px;margin:0px;margin-left:1px;margin-right:1px;background-color:#FFFFFF;\">\r\n<img src=\"/img/microachat/logo_shuttle_SB83G5.gif\" border=0><br>\r\n<font face=arial,helvetica size=2 color=#CC0000 style=\"font-size:12px;\">Les derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.<br></font>\r\n<center><a href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/sb83g5/?fabriquant=1&page=1&tri=titre\"><img src=\"/img/microachat/mea_shuttle_SB83G5.gif\" border=0 vspace=5></a><br></center>\r\n<center>\r\n<font face=arial,helvetica size=2 color=#CC0000 style=\"font-size:13px;\"><b>\340 partir de</b><br>\r\n<div style=\"border:solid 2px #CC0000;width:100px;background-color:#FFCC00;\"><b>415 \200</b></div>\r\n</center>\r\n</div>\r\n</td>\r\n</tr>\r\n<tr>\r\n<td align=center><font face=arial,helvetica size=1 color=#FFFFFF style=\"font-size:11px;\">publicit\351</a></font></td>\r\n</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_BonPlan -->  \t</td>\r\n\t<td width=\"15\"><img src=\"/img/dot.gif\" width=\"15\"></td>\r\n\t<td width=\"50%\" valign=\"top\">\r\n\t<!-- DEBUT MicroAchat MA_MeillPrixAct //-->\r\n<td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=145 height=1><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=18><br>\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<FORM name=\"prix\" action=\"http://www.micro-achat.01net.com/guide-produits/recherche.php\" method=\"post\">\r\n\t\t<td width=145 colspan=3><img src=\"http://www.01net.com/img/ban/Ban_v4_MeillPrix_MA.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=1 bgcolor=#FFCC00><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t<td width=143>\r\n\t\t<table width=143 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=6><img src=\"http://www.01net.com/img/dot.gif\" width=6 height=1></td>\r\n\t\t\t\t<td valign=top><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=15><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<img src=\"http://www.01net.com/img/ban/Ban_MA_trouv_ordi.gif\"><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/desktops/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Desktops</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/portables/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Portables</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Mini-PC</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/pda---tablets-pc/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Pda / Tablets-PC</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/apple/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Apple</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/gps/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">GPS</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20><br>\r\n\t\t\t\t\t\t\t\t<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td><input type=\"text\" name=\"recherchedirecte\" size=\"14\" style=\"width:130px;font:12px;\" value=\"     recherche directe\" onFocus=\"javascript:document.prix.recherchedirecte.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"/img/v4/MA/ok_bloc_recher_MA.gif\" border=\"0\"></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td width=1 bgcolor=#FFCC00><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=145 colspan=3><img src=\"http://www.01net.com/img/v4/MA/base_meillPrix.gif\"></td>\r\n\t\t</FORM>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_MeillPrixAct //-->  \t</td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n<!-- /MA_BP_MP -->  <!-- - ZONE H2 -->\r\n<!-- -ZONE_Hn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_Tn -->\r\n<!-- + ZONE T0 -->\r\n    <td valign=\"top\">\r\n<img src=\"http://www.01net.com/img/dot.gif\" height=13><br>\r\n<table border=0 width=320 cellpadding=0 cellspacing=0>\r\n<tr>\r\n<td width=305><img src=\"http://www.01net.com/img/ban/Ban_v4_DernNews_MA.gif\"><br><img src=\"http://www.01net.com/img/v4/MA/v4-tiret-hauts-mha.gif\"></td>\r\n<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n</tr>\r\n<tr>\r\n<td bgcolor=\"#FEF9E0\">\r\n\t<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Portable&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255149.html\" style=\"color:#000000;text-decoration:none;\">Toshiba consacre deux gammes de machines au multim\351dia</a></b><br>\r\n\t<font color=\"#000000\">Equipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Ordinateur&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254686.html\" style=\"color:#000000;text-decoration:none;\">Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme</a></b><br>\r\n\t<font color=\"#000000\">La firme \340 la pomme propose une station de travail \351volutive et relativement abordable.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>PC&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254549.html\" style=\"color:#000000;text-decoration:none;\">Alienware propose deux machines au look \351trange</a></b><br>\r\n\t<font color=\"#000000\">Aurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Portable&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254501.html\" style=\"color:#000000;text-decoration:none;\">Trois nouveaux iBook G4 chez Apple</a></b><br>\r\n\t<font color=\"#000000\">Chez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t\t<tr>\r\n\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=10></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-red-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td align=\"right\">\r\n\t\t\t\t<A HREF=\"http://microachat.01net.com/rubrique/4365.html\"  style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 10px;\">> toutes les news</font></a>\r\n\t\t\t</td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n</td> <!-- - ZONE T0 -->\r\n<!-- + ZONE T1 -->\r\n<!-- Ma_derpromo  -->\r\n    <td valign=\"top\">\r\n<img src=\"/img/dot.gif\" height=13><br>\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td bgcolor=\"#ffffff\"><img src=\"/img/v4/MA/v4-lespromos-mha.gif\"><br><img src=\"/img/v4/MA/v4-tiret-hauts-mha.gif\"></td>\r\n</tr>\r\n</table>\r\n<!-- DEBUT MODELE D\'AFFICHAGE POUR LES n PREMIERS ARTICLES //-->\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255806.html\" class=\"nodeco\"><img src=\"/images/67462.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255806.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>Asus A3N15-C Pro</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>1170&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255688.html\" class=\"nodeco\"><img src=\"/images/67381.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255688.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>Soltek EQ3702A Miroir</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>559&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255513.html\" class=\"nodeco\"><img src=\"/images/67319.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255513.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>IBM ThinkPad R51</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Voici un portable complet et pourtant relativement l\351ger.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>1299&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t\t<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td><img src=\"http://www.01net.com/img/dot.gif\" height=10></td>\r\n</tr>\r\n<tr>\r\n<td background=\"/img/v4/MA/v4-sep-red-mha.gif\"><img src=\"/img/dot.gif\" height=1></td>\r\n</tr>\r\n<tr>\r\n<td align=\"right\" valign=\"top\">\r\n\t\t\t\t<A HREF=\"http://microachat.01net.com/rubrique/4366.html\"  style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 10px;\">> toutes les promos</font></a>\r\n\t\t</td>\r\n</tr>\r\n</table>\r\n</td>\r\n<!-- /Ma_derpromo  -->   <!-- - ZONE T1 -->\r\n<!-- + ZONE T2 -->\r\n<!-- - ZONE T2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE T3 -->\r\n<!-- DEBUT MicroAchat MA_PubG -->\r\n<td valign=top align=center>\r\n<table border=0 width=320 cellpadding=0 cellspacing=0>\r\n\t<tr>\r\n\t\t<td width=305><img src=\"/img/dot.gif\" width=1 height=12><br><a href=\"http://www.smartadserver.com/call/cliccommand/45590/[timestamp]?\" target=_blank><img src=\"/img/microachat/Bandeau_FX6021.jpg\" border=0></a></td>\r\n\t\t<td><img src=\"/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_PubG -->  <!-- - ZONE T3 -->\r\n<!-- + ZONE T4 -->\r\n<!-- DEBUT MicroAchat MA_PubD -->\r\n<td valign=top align=center>\r\n<table border=0 width=305 cellpadding=0 cellspacing=0>\r\n\t<tr>\r\n\t\t<td width=305><img src=\"/img/dot.gif\" width=1 height=12><br><a href=\"http://www.smartadserver.com/call/cliccommand/45591/[timestamp]?\" target=_blank><img src=\"/img/microachat/twc_305x125.jpg\" border=0></a></td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN  MicroAchat MA_PubD --> <!-- - ZONE T4 -->\r\n<!-- + ZONE T5 -->\r\n<!-- - ZONE T5 -->\r\n<!-- -ZONE_Tn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n\t\t\t<td valign=top>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n<!-- +ZONE_gn -->\r\n<!-- + ZONE g0 -->\r\n<!-- - ZONE g0 -->\r\n<!-- + ZONE g1 -->\r\n<!-- - ZONE g1 -->\r\n<!-- + ZONE g2 -->\r\n<!-- - ZONE g2 -->\r\n<!-- + ZONE g3 -->\r\n<!-- - ZONE g3 -->\r\n<!-- + ZONE g4 -->\r\n<!-- - ZONE g4 -->\r\n<!-- + ZONE g5 -->\r\n<!-- - ZONE g5 -->\r\n<!-- + ZONE g6 -->\r\n<!-- - ZONE g6 -->\r\n<!-- + ZONE g7 -->\r\n<!-- - ZONE g7 -->\r\n<!-- + ZONE g8 -->\r\n<!-- - ZONE g8 -->\r\n<!-- + ZONE g9 -->\r\n<!-- - ZONE g9 -->\r\n<!-- -ZONE_gn -->\r\n\t\t\t</table>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t\t\t<tr>\r\n<!-- +ZONE_Mn -->\r\n<!-- + ZONE M0 -->\r\n<!-- modele Ma_GuideAch //-->\r\n    <td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" height=13><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t<tr>\r\n\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_GuideAchat_MA.gif\" vspace=1></td>\r\n\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<div style=\"border:solid 1px #FFCC00;width:100%\">\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<center>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"http://microachat.01net.com/article/254561.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67088.jpg.res_121-111.jpg\" border=0 hspace=0 vspace=0></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n</center>\r\n<div style=\"padding:5px;\">\r\n<a href=\"http://microachat.01net.com/article/254561.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\"><b>Les graveurs de DVD</b><br></font></a>\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">Quel graveur choisir&#160;? Quel type de format&#160;? Quelle vitesse&#160;? Double couche ou simple couche&#160;? Voici tout ce qu\'il faut savoir pour faire le bon choix.</font></div>\r\n\t\t\t\t\t\t</div>\r\n\t\t</td>\r\n\t</tr>\r\n</table>\r\n</td> <!-- - ZONE M0 -->\r\n<!-- + ZONE M1 -->\r\n<!-- modele Ma_DirectLab //-->\r\n    <td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t<tr>\r\n\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_DirectLab_MA.gif\" vspace=1></td>\r\n\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<div style=\"border:solid 1px #FFCC00;width:100%\">\r\n\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255744.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>Kodak EasyShare Printer Dock Plus&#160;:</b>\r\n\t\t\t\t\t\tvos photos 10&#160;x&#160;15&#160;cm en 60&#160;secondes</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255780.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>3DMark05&#160;:</b>\r\n\t\t\t\t\t\tun labo 3D \340 domicile</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255691.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>DVDInfoPro 2.6</b>\r\n\t\t\t\t\t\treconna\356t CD et DVD</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255722.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>Scaleo PA D3008, de Fujitsu-Siemens&#160;:</b>\r\n\t\t\t\t\t\tune impression d\'inachev\351</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255514.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">Carbon 5&#160;Go&#160;: 2&#160;500&#160;chansons dans le creux de la main</font></a></div>\r\n\t\t\t</div></td>\r\n\t</tr>\r\n</table>\r\n</td> <!-- - ZONE M1 -->\r\n<!-- + ZONE M2 -->\r\n<!-- DEBUT MicroAchat MA_AnnTelec -->\r\n<td valign=top>\r\n<script type=\"text/javascript\">\r\nfunction regionChange()\r\n{\r\ndocument.selection.departement.options.length=0;\r\nswitch(document.selection.region.value)\r\n\t{\r\n\t\tcase \"aucun\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Nord-Pas-de-Calais\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pas-de-Calais\", \"Pas-de-Calais\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Nord\", \"Nord\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Haute-Normandie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Eure\", \"Eure\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-Maritime\", \"Seine-Maritime\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Basse-Normandie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Manche\", \"Manche\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Calvados\", \"Calvados\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Orne\", \"Orne\");\r\n\t\tbreak;\r\n\t\tcase \"Picardie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Somme\", \"Somme\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Oise\", \"Oise\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aisne\", \"Aisne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Bretagne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Finistere\", \"Finistere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cotes-dArmor\", \"Cotes-dArmor\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Morbihan\", \"Morbihan\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ille-et-Vilaine\", \"Ille-et-Vilaine\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Pays-de-Loire\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loire-Atlantique\", \"Loire-Atlantique\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vendee\", \"Vendee\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Maine-et-Loire\", \"Maine-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Mayenne\", \"Mayenne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Sarthe\", \"Sarthe\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Centre\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Eure-et-Loir\", \"Eure-et-Loir\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loiret\", \"Loiret\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loir-et-Cher\", \"Loir-et-Cher\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Indre-et-Loire\", \"Indre-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Indre\", \"Indre\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cher\", \"Cher\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Ile-de-France\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Val-dOise\", \"Val-dOise\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Yvelines\", \"Yvelines\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Essonne\", \"Essonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-et-Marne\", \"Seine-et-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hauts-de-Seine\", \"Hauts-de-Seine\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-Saint-Denis\", \"Seine-Saint-Denis\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Val-de-Marne\", \"Val-de-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Paris\", \"Paris\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Champagnes-Ardennes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ardennes\", \"Ardennes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Marne\", \"Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aube\", \"Aube\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Marne\", \"Haute-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Lorraine\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vosges\", \"Vosges\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Meurthe-et-Moselle\", \"Meurthe-et-Moselle\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Meuse\", \"Meuse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Moselle\", \"Moselle\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Alsace\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Bas-Rhin\", \"Bas-Rhin\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haut-Rhin\", \"Haut-Rhin\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Franche-Compte\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Jura\", \"Jura\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Doubs\", \"Doubs\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Saone\", \"Haute-Saone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Territoire-de-Belfort\", \"Territoire-de-Belfort\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Bourgogne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Yonne\", \"Yonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Nievre\", \"Nievre\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cote-dOr\", \"Cote-dOr\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Saone-et-Loire\", \"Saone-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Poitou-Charentes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Deux-Sevres\", \"Deux-Sevres\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Charente-Maritime\", \"Charente-Maritime\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Charente\", \"Charente\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vienne\", \"Vienne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Limousin\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Vienne\", \"Haute-Vienne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Correze\", \"Correze\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Creuse\", \"Creuse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Auvergne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Allier\", \"Allier\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Puy-de-Dome\", \"Puy-de-Dome\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cantal\", \"Cantal\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Loire\", \"Haute-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Rhone-Alpes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loire\", \"Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Rhone\", \"Rhone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ain\", \"Ain\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ardeche\", \"Ardeche\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Drome\", \"Drome\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Isere\", \"Isere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Savoie\", \"Savoie\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Savoie\", \"Haute-Savoie\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Aquitaine\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gironde\", \"Gironde\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Landes\", \"Landes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pyrenees-Atlantiques\", \"Pyrenees-Atlantiques\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lot-et-Garonne\", \"Lot-et-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Dordogne\", \"Dordogne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Midi-Pyrenees\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lot\", \"Lot\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Tarn-et-Garonne\", \"Tarn-et-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gers\", \"Gers\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hautes-Pyrenees\", \"Hautes-Pyrenees\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Garonne\", \"Haute-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ariege\", \"Ariege\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Tarn\", \"Tarn\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aveyron\", \"Aveyron\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Languedoc-Roussillon\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pyrenees-Orientales\", \"Pyrenees-Orientales\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aude\", \"Aude\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Herault\", \"Herault\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gard\", \"Gard\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lozere\", \"Lozere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Provence-Alpes-Cote-dazur\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Bouches-du-Rhone\", \"Bouches-du-Rhone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vaucluse\", \"Vaucluse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Alpes-de-haute-Provence\", \"Alpes-de-haute-Provence\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hautes-Alpes\", \"Hautes-Alpes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Var\", \"Var\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Alpes-Maritimes\", \"Alpes-Maritimes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Corse\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Corse-du-Sud\", \"Corse-du-Sud\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Corse\", \"Haute-Corse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"DomTom\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Guadeloupe\", \"Guadeloupe\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Guyane\", \"Guyane\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"La-Reunion\", \"La-Reunion\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Martinique\", \"Martinique\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Mayotte\", \"Mayotte\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"St-Pierre-et-Miquelon\", \"St-Pierre-et-Miquelon\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t}\r\n}\r\nfunction deptChange()\r\n{\r\nif (document.selection.departement.value == \'Paris\')\r\n\tdocument.getElementById(\'arrondissement\').style.display = \'inline\';\r\nelse\r\n\tdocument.getElementById(\'arrondissement\').style.display = \'none\';\r\n}\r\n</script>\r\n<table width=305 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td valign=top>\r\n\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_AnnuaiRev_MA.gif\" vspace=1></td>\r\n\t\t\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr><form action=\"http://micro-achat.01net.com/annuaire/recherche.php\" method=\"post\" name=\"selection\">\r\n\t\t\t\t<td bgcolor=#FFFFDD>\r\n\t\t\t\t<div style=\"border:solid 1px #FFCC00;width:100%\"><div style=\"padding:2px;\"><img src=\"http://www.01net.com/img/v4/MA/carte_revend.gif\"><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Choisir une r\351gion</b><br></font>\r\n<select name=\"region\" onChange=\"regionChange()\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"aucun\">-------------</option>\r\n<option value=\"Nord-Pas-de-Calais\">Nord-Pas-de-Calais</option>\r\n<option value=\"Haute-Normandie\">Haute-Normandie</option>\r\n<option value=\"Basse-Normandie\">Basse-Normandie</option>\r\n<option value=\"Picardie\">Picardie</option>\r\n<option value=\"Bretagne\">Bretagne</option>\r\n<option value=\"Pays-de-Loire\">Pays-de-Loire</option>\r\n<option value=\"Centre\">Centre</option>\r\n<option value=\"Ile-de-France\">Ile-de-France</option>\r\n<option value=\"Champagnes-Ardennes\">Champagne ardennes</option>\r\n<option value=\"Lorraine\">Lorraine</option>\r\n<option value=\"Alsace\">Alsace</option>\r\n<option value=\"Franche-Compte\">Franche-Compte</option>\r\n<option value=\"Bourgogne\">Bourgogne</option>\r\n<option value=\"Poitou-Charentes\">Poitou-Charentes</option>\r\n<option value=\"Limousin\">Limousin</option>\r\n<option value=\"Auvergne\">Auvergne</option>\r\n<option value=\"Rhone-Alpes\">Rhone-Alpes</option>\r\n<option value=\"Aquitaine\">Aquitaine</option>\r\n<option value=\"Midi-Pyrenees\">Midi-Pyrenees</option>\r\n<option value=\"Languedoc-Roussillon\">Languedoc roussillon</option>\r\n<option value=\"Provence-Alpes-Cote-dazur\">PACA</option>\r\n<option value=\"Corse\">Corse</option>\r\n<option value=\"DomTom\">DomTom</option>\r\n</select>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Un d\351partement</b><br></font>\r\n<select name=\"departement\" onChange=\"deptChange()\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"aucun\">-------------</option>\r\n</select>\r\n<div id=\"arrondissement\" style=\"display : none;\">\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Un arrondissement</b><br></font>\r\n<select name=\"arrondissement\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"0\">-------------</option>\r\n<option value=\"1\">I</option>\r\n<option value=\"2\">II</option>\r\n<option value=\"3\">III</option>\r\n<option value=\"4\">IV</option>\r\n<option value=\"5\">V</option>\r\n<option value=\"6\">VI</option>\r\n<option value=\"7\">VII</option>\r\n<option value=\"8\">VIII</option>\r\n<option value=\"9\">IX</option>\r\n<option value=\"10\">X</option>\r\n<option value=\"11\">XI</option>\r\n<option value=\"12\">XII</option>\r\n<option value=\"13\">XIII</option>\r\n<option value=\"14\">XIV</option>\r\n<option value=\"15\">XV</option>\r\n<option value=\"16\">XVI</option>\r\n<option value=\"17\">XVII</option>\r\n<option value=\"18\">XVIII</option>\r\n<option value=\"19\">XIX</option>\r\n<option value=\"20\">XX</option>\r\n</select>\r\n</div>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=10><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Recherche directe</b><br></font>\r\n\t\t\t\t<font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\"><img src=\"http://www.01net.com/img/dot.gif\" width=8 height=1>rechercher une ville<br><img src=\"http://www.01net.com/img/dot.gif\" width=8 height=1>et/ou une boutique<br></font>\r\n\t\t\t\t<input type=\"text\" name=\"recherchedirecte\" size=\"14\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;width:130px;\" value=\"\" onFocus=\"javascript:document.selection.recherchedirecte.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=3><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1>&nbsp;<input type=\"image\" src=\"http://www.01net.com/img/v4/MA/ok_bloc_recher_MA.gif\" border=\"0\">\r\n\t\t\t\t<table height=23 width=135 cellspacing=0 cellpadding=0 border=0 bgcolor=#FFEE77>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td bgcolor=#FFEE77 valign=middle align=center><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://micro-achat.01net.com/annuaire/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Recherche avanc\351e</b></font></a></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t</div>\r\n\t\t\t\t</div>\r\n\t\t\t\t</td>\r\n\t\t\t</tr></form>\r\n\t\t</table>\r\n\t\t</td>\r\n<!-- DEBUT MicroAchat MA_Telecharg //-->\r\n<td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n<table width=\"145\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/v4/MA/Ban_v4_MA_telec.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<table width=\"145\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#DFECF6\">\r\n\t\t\t<tr>\r\n\t\t\t\t<td rowspan=\"17\"><img src=\"http://www.01net.com/img/dot.gif\" width=\"6\"></td>\r\n\t\t\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"></td>\r\n\t\t\t\t<td rowspan=\"17\"><img src=\"http://www.01net.com/img/dot.gif\" width=\"6\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Bureautique\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Bureautique</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Traducteur, organiseur...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Multimedia\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Multim\351dia</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Photo, audio, vid\351o...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Utilitaire\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Utilitaires</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Antivirus, pilotes, gravure...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Personnaliser\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Personnaliser son PC</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Ecrans de veille, th\350mes...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Programmation\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>D\351veloppement</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Cr\351ation de logiciels, BDD...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Jeux\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Jeux</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Action, simulation...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Internet\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Internet</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Utilitaires, email, FTP...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Loisirs\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Loisirs</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Humour, culture...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_Telecharg //-->  \t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_AnnTelec --> <!-- - ZONE M2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE M3 -->\r\n<!-- - ZONE M3 -->\r\n<!-- + ZONE M4 -->\r\n<!-- - ZONE M4 -->\r\n<!-- + ZONE M5 -->\r\n<!-- - ZONE M5 -->\r\n<!-- -ZONE_Mn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t<tr>\r\n<!-- +ZONE_tn -->\r\n<!-- + ZONE t0 -->\r\n<!-- - ZONE t0 -->\r\n<!-- + ZONE t1 -->\r\n<!-- - ZONE t1 -->\r\n<!-- + ZONE t2 -->\r\n<!-- - ZONE t2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE t3 -->\r\n<!-- - ZONE t3 -->\r\n<!-- + ZONE t4 -->\r\n<!-- - ZONE t4 -->\r\n<!-- + ZONE t5 -->\r\n<!-- - ZONE t5 -->\r\n<!-- -ZONE_tn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td valign=top>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t<tr>\r\n<!-- +ZONE_dn -->\r\n<!-- + ZONE d0 -->\r\n<!-- - ZONE d0 -->\r\n<!-- + ZONE d1 -->\r\n<!-- - ZONE d1 -->\r\n<!-- + ZONE d2 -->\r\n<!-- - ZONE d2 -->\r\n<!-- + ZONE d3 -->\r\n<!-- - ZONE d3 -->\r\n<!-- + ZONE d4 -->\r\n<!-- - ZONE d4 -->\r\n<!-- + ZONE d5 -->\r\n<!-- - ZONE d5 -->\r\n<!-- + ZONE d6 -->\r\n<!-- - ZONE d6 -->\r\n<!-- + ZONE d7 -->\r\n<!-- - ZONE d7 -->\r\n<!-- + ZONE d8 -->\r\n<!-- - ZONE d8 -->\r\n<!-- + ZONE d9 -->\r\n<!-- - ZONE d9 -->\r\n<!-- -ZONE_dn -->\r\n\t\t\t\t</tr>\r\n\t\t\t</table>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n\t\t</table>\r\n<!-- FIN WORK -->\r\n\t\t</td>\r\n<!-- *********************************************************************FIN VENTRE********************************************************************************************************************************************** //-->\r\n\t\t<td rowspan=2 valign=top width=23 background=\"http://www.01net.com/img/v4/sep_verticale.gif\"><img src=\"http://www.01net.com/img/dot.gif\" width=23 height=1><br></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t\t<td colspan=2>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=100%>\r\n<!-- +ZONE_Bn -->\r\n<!-- + ZONE B0 -->\r\n<!-- - ZONE B0 -->\r\n<!-- + ZONE B1 -->\r\n<tr><!-- ********** DEBUT BLOC Home NosJournauxV4 //-->\r\n<td valign=top bgcolor=#FFFFFF>\r\n<img src=\"http://www.01net.com/img/ban/Ban_v4_jx.gif\"><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=15><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1>\r\n<a href=\"http://www.01net.com/rubrique/3339.html\"><img src=\"http://www.01net.com/img/journaux/01I-small.gif\" border=0 vspace=0 hspace=12 align=top></a>\r\n<a href=\"http://www.01net.com/rubrique/4051.html\"><img src=\"http://www.01net.com/img/journaux/DSI-small.gif\" border=0 vspace=0 hspace=12 align=top></a>\r\n<a href=\"http://www.01net.com/rubrique/3345.html\"><img src=\"http://www.01net.com/img/journaux/DIN-small.gif  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        <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\r\n<BASE target=\"_top\">\r\n\n<TITLE>Micro Achat : Ordinateurs, PDA -  Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux</TITLE>\r\n<META NAME=\"Description\" CONTENT=\"Micro Achat : Ordinateurs, PDA\">\r\n<META NAME=\"Keywords\" CONTENT=\"Micro Achat : Ordinateurs, PDA -  Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\">\r\n<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"http://www.01net.com/styles/01net.css\">\r\n<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"http://www.01net.com/styles/tableau_autre.css\">\r\n<STYLE type=text/css>\r\nA{TEXT-DECORATION: none;color:#000000;}\r\nA:visited{TEXT-DECORATION: none;color:#000000;}\r\n</STYLE>\r\n<SCRIPT LANGUAGE=\"JavaScript1.1\">\r\nvar sameAsBigDay = new Date();\r\nvar ord = (sameAsBigDay.getTime());\r\nvar pubsMotsCles = \"\";\r\nvar exc;\r\nvar lienhautdepage = \"\";\r\nvar etatmessage = false;\r\nvar enchainement = false;\r\nsas_tmstp=Math.round(Math.random()*10000000000);\r\nfunction SmartAdServer(sas_pageid,sas_formatid,sas_master,sas_target) {\r\n if ((sas_master!=\'M\')&&(sas_master!=\'S\')) {sas_master=\'S\'};\r\n document.write(\'<SCR\'+\'IPT SRC=\"http://www.smartadserver.com/call/pubj/\' + sas_pageid + \'/\' + sas_formatid + \'/\'+sas_master + \'/\' + sas_tmstp + \'/\' + escape(sas_target) + \'?\"></SCR\'+\'IPT>\');\r\n}\r\n</SCRIPT>\r\n<SCRIPT LANGUAGE=\"JAVASCRIPT\" SRC=\"http://www.01net.com/js/exc.js\"></SCRIPT>\r\n<script language=\"javascript\" src=\"http://telecharger.01net.com/shopping/js/headservicesV4.js\"></script>\r\n<noscript>\r\n<a href=\"http://cinema.01net.com\">T\351l\351charger des bandes-annonces, des teasers, des extraits et des making of de vos films cin\351ma pr\351f\351r\351s</a>,\r\n<a href=\"http://www.01net.com/BusinessTechnologies/\">Portail leader de l\'information sur les nouvelles technologies - Actualites et enquetes sur l\'informatique et les NTIC (nouvelles technologies de l\'information et la communication). Exemples de sujets : e-business, telecoms, CRM, VPN, 3G, DSL, fournisseurs d\'acces, Linux, piratage, securite informatique, progiciel...</a><br>\r\n<a href=\"http://www.01net.com/securite_informatique.html\">s\351curit\351 informatique</a>,\r\n<a href=\"http://www.01net.com/strategies_ntic.html\">strat\351gies NTIC</a>,\r\n<a href=\"http://www.01net.com/piratage_informatique.html\">piratage informatique</a>,\r\n<a href=\"http://www.01net.com/technologie_dsl.html\">technologie DSL</a>,\r\n<a href=\"http://www.01net.com/solutions_vpn.html\">solutions VPN</a>,\r\n<a href=\"http://www.01net.com/strategie_e-business.html\">strat\351gies</a>,\r\n<a href=\"http://www.01net.com/outils_crm.html\">outils CRM</a>,\r\n<a href=\"http://www.01net.com/logiciel_linux.html\">logiciel Linux</a>,\r\n<a href=\"http://www.01net.com/fournisseur_d_acces.html\">fournisseur d\'acc\350s</a>,\r\n<a href=\"http://www.01net.com/progiciel.html\">progiciel</a>,\r\n<a href=\"http://www.01net.com/stockage_de_donnees.html\">stockage de donn\351es</a>,\r\n<a href=\"http://www.01net.com/etudes_solution_informatique.html\">\351tudes solution informatique</a>,\r\n<a href=\"http://www.01net.com/NTIC.html\">NTIC</a>,\r\n<a href=\"http://www.01net.com/actualite_technologie.html\">actualit\351 technologie</a>,\r\n<a href=\"http://www.01net.com/etude_materiel_informatique.html\">\351tude mat\351riel informatique</a>,\r\n<a href=\"http://www.01net.com/actus/\">actualit\351s des nouvelles technologies</a>,\r\n<a href=\"http://www.01net.com/MicroPerso/\">enqu\352tes et trucs et astuces sur le mat\351riel informatique, les logiciels, les fournisseurs d\'acc\350s...</a>,\r\n<a href=\"http://www.01net.com/emploi/\">emploi et formations informatiques : offres d\'emploi informatique...</a>,\r\n<a href=\"http://www.01net.com/produits/\">fiches, tests mat\351riels et logiciels en informatique</a>,\r\n<a href=\"http://www.01net.com/01informatique\">01 Informatique</a>,\r\n<a href=\"http://www.caractere.net\">Caract\350re, le site des professionnels de l\'imprim\351 - communication imprim\351e, \351dition, emballage, encres, finition, flexographie, h\351liogravure, impression, imprimerie, imprimeur, industries graphiques, num\351rique, offset, papier, pr\351presse, presse, print, reprographie, s\351rigraphie, typographie</a>,\r\n<a href=\"http://www.01net.com/decisionmicro\">Decision Micro</a>,\r\n<a href=\"http://www.01net.com/decisioninformatique\">D\351cision Informatique</a>,\r\n<a href=\"http://www.01net.com/01reseaux\">01 R\351seaux</a>,\r\n<a href=\"http://logiciel.telecharger.01net.com/\">logiciel</a>,\r\n<a href=\"http://developpeur.telecharger.01net.com/windows/Programmation/\">d\351veloppeur programmation</a>,\r\n<a href=\"http://anti-virus.telecharger.01net.com\">anti-virus</a>,\r\n<a href=\"http://gravure-cd-dvd.telecharger.01net.com/windows/Utilitaire/gravure/\">gravure cd dvd</a>,\r\n<a href=\"http://codec.telecharger.01net.com/windows/Multimedia/encodeurs_et_decodeurs/\">codec encodeur d\351codeur</a>,\r\n<a href=\"http://software.telecharger.01net.com/\">software</a>,\r\n<a href=\"http://logiciels.telecharger.01net.com/\">logiciels</a>,\r\n<a href=\"http://gratuit.telecharger.01net.com/\">gratuit</a>,\r\n<a href=\"http://p2p.telecharger.01net.com/windows/Internet/partage/\">p2p peer to peer partage de fichiers</a>,\r\n<a href=\"http://securite.telecharger.01net.com/windows/Utilitaire/cryptage_et_securite/\">s\351curit\351</a>,\r\n<a href=\"http://compression-decompression.telecharger.01net.com/windows/Utilitaire/compression_et_decompression/\">compression et d\351compression</a>,\r\n<a href=\"http://divx.telecharger.01net.com/\">divx</a>,\r\n<a href=\"http://utilitaire.telecharger.01net.com/windows/Utilitaire/\">utilitaire</a>,\r\n<a href=\"http://jeux.telecharger.01net.com/windows/Jeux/\">jeux</a>,\r\n<a href=\"http://loisirs.telecharger.01net.com/windows/Loisirs/\">loisirs</a>,\r\n<a href=\"http://mac.telecharger.01net.com/mac/\">mac</a>,\r\n<a href=\"http://linux.telecharger.01net.com/linux/\">linux</a>,\r\n<a href=\"http://shareware.telecharger.01net.com/\">shareware</a>,\r\n<a href=\"http://video-dvd.telecharger.01net.com/windows/Multimedia/lecteurs_video_dvd/\">vid\351o dvd</a>,\r\n<a href=\"http://multimedia.telecharger.01net.com/\">multim\351dia</a>,\r\n<a href=\"http://traduction.telecharger.01net.com/windows/Bureautique/traducteur/\">traduction</a>,\r\n<a href=\"http://mp3.telecharger.01net.com/windows/Multimedia/lecteurs_audio_mp3_cd/\">mp3</a>,\r\n<a href=\"http://tchat.telecharger.01net.com/windows/Internet/communication/\">tchat</a>\r\n<a href=\"http://chat.telecharger.01net.com/windows/Internet/communication/\">chat</a>,\r\n<a href=\"http://musique.telecharger.01net.com/\">musique</a>,\r\n<a href=\"http://mobile.telecharger.01net.com/mobile/\">mobile</a>,\r\n<a href=\"http://telephone_portable.telecharger.01net.com/mobile/\">t\351l\351phone portable</a>,\r\n<a href=\"http://telephone_mobile.telecharger.01net.com/mobile/\">t\351l\351phone mobile</a>\r\n</noscript>\r\n</head>\r\n</head>\r\n<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#000000\" marginwidth=0 marginheight=0 topmargin=0 leftmargin=0>\r\n<!-- + ZONE TETE -->\r\n<!-- ********** DEBUT MODELE INTERNE TETES MHA-tetev4 //-->\r\n<table width=100% height=66 cellspacing=0 cellpadding=0 border=0 bgcolor=#ffffff>\r\n\t<tr>\r\n\t\t<td height=8 colspan=2><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=8></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td valign=bottom><a href=\"http://microachat.01net.com\"><img src=\"http://www.01net.com/img/v4/logos_tete/tet_gauche-mha.gif\" border=0></a></td>\r\n\t\t<td valign=bottom bgcolor=#FFFFFF bbackground=\"http://www.01net.com/img/v4/tet_droite.gif\" width=100% style=\"background-image:url(/img/v4/tet_droite-mha.gif);background-position:bottom;background-repeat:repeat-x\"><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=66 align=left hspace=0 vspace=0></td>\r\n\t</tr>\r\n</table>\r\n<table width=100% cellspacing=0 cellpadding=0 border=0 bgcolor=#ffffff>\r\n\t<tr>\r\n\t\t<td valign=top background=\"http://www.01net.com/img/v4/fond_date-mha.gif\" height=18 width=500><img src=\"http://www.01net.com/img/dot.gif\" width=500 height=1><br><img src=\"http://www.01net.com/img/dot.gif\" width=19 height=1><font face=\"Arial\" size=1 color=#666666 style=\"font-size: 11px;\"><b>Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004&nbsp;&nbsp;|&nbsp;&nbsp;16:45</b></font></td>\r\n\t\t<td width=100% background=\"http://www.01net.com/img/v4/fond_date2-mha.gif\" height=18></td>\r\n\t</tr>\r\n</table>\r\n<!-- ********** FIN MODELE INTERNE TETES MHA-tetev4 //--> <!-- - ZONE TETE -->\r\n<!-- ***************************************************************************************************************************************************************************************************************************** //-->\r\n<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n<!-- DEBUT PARTIE PUB //-->\r\n\t<tr>\r\n<td align=center valign=middle colspan=2 background=\"http://www.01net.com/img/v4/fond_bann.gif\"><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br>\r\n<!-- + ZONE Z0 -->\r\n<SCRIPT LANGUAGE=\"JAVASCRIPT\">\r\nvar fa = \"\";\r\nvar fab = document.URL.toString();\r\nif (fab.indexOf(\"?fa\") != -1 || fab.indexOf(\"&fa\") != -1)\r\n{\r\nfa = \";!category=fai\";\r\n}\r\nvar etatmessage = false;\r\nvar enchainement = false;\r\n</SCRIPT>\r\n<SCRIPT LANGUAGE=\"JavaScript1.1\">\r\nsas_pageid=\'167/3872\';\r\nsas_formatid=95;\t\t\t// Format : Banner/Scope 468x60\r\nsas_master=\'M\';\t\t\t// Master : M=master or S=slave\r\nsas_target=exc + \'rubrique\';\t\t\t// Targeting\r\nSmartAdServer(sas_pageid,sas_formatid,sas_master,sas_target);\r\n</SCRIPT>\r\n <!-- - ZONE Z0 --></td>\r\n\t\t<td valign=top width=23 background=\"http://www.01net.com/img/v4/sep_verticale.gif\" ><img src=\"http://www.01net.com/img/dot.gif\" width=23 height=1><br></td>\r\n<td valign=top width=100% bgcolor=\"ffffff\" rowspan=3><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=125><br>\r\n<!-- +ZONE_Dn -->\r\n<!-- + ZONE D0 -->\r\n<!-- DEBUT MA_ColD -->\r\n<div style=\"background-color : #ffffff; width : 150px; padding-left : 5px; padding-right : 5px; font-family : Arial, Helvetica;\">\n\t\t\t\t\t<table style=\"border-spacing : 0; width : 146px; margin-top : 0px;\" cellspacing=\"0\">\n\t\t\t\t\t<tr><th colspan=\"2\" style=\"padding : 0;\"><img src=\"http://micro-achat.01net.com/img/utils/micro-achat/tete-produitsrecherches.gif\" alt=\"\" /></th></tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Imagerie&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/12537-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/imagerie/moniteurs-lcd/l1720b/\">LG L1720B</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">332.89 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Ordinateurs&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/4043-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/desktops/veriton-7600g/\">Acer Veriton 7600G</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">705 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Ordinateurs&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/1903-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/sn95g5/\">Shuttle SN95G5</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">375 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Composants&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/1259-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/composants/cartes-meres/a7n8x-e-deluxe/\">Asus A7N8X-E Deluxe</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">91.99 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr><tr>\n\t\t\t\t\t\t\t<td style=\"height : 12px; vertical-align : top; padding : 0; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/point.gif); background-repeat: repeat-x; background-position : 0px 3px;\" colspan=\"2\"><span style=\"float : left; position : relative; font-size : 10px; color : #cc0003; background-color : #ffffff;\">Composants&nbsp;</span></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"width : 65px; vertical-align : top;\"><img src=\"http://micro-achat.01net.com/img/photoproduit/4687-vignette.png\" alt=\"\" style=\"border : 1px solid #000000;\" /></td>\n\t\t\t\t\t\t\t<td style=\"width : 75px; font-size : 11px; font-weight : 700;\">\n\t\t\t\t\t\t\t\t<a style=\"color : #cc0003; text-decoration : none;\" href=\"http://micro-achat.01net.com/guide-produits/composants/ventilateur/sp-94/\">Thermalright SP-94</a>\n\t\t\t\t\t\t\t\t<div style=\"text-align : center; width : 100%; font-size : 9px; font-weight : 100; margin-top : 5px;\">\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t<div style=\"width : 75px; height : 21px; color : #ffffff; font-size : 12px; font-weight : 700; background-image : url(http://micro-achat.01net.com/img/utils/micro-achat/fond-prix.gif);\"><span style=\"position : relative; top : 3px;\">49 &#128;</span></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr></table>\n\t\t\t\t<table style=\"border-spacing : 0px 1px; width : 146px; margin-top : 15px;\" cellspacing=\"0\">\n\t\t\t\t<tr><th colspan=\"2\" style=\"padding : 0;\"><img src=\"http://micro-achat.01net.com/img/utils/micro-achat/tete-revendeurmisajour.gif\" alt=\"\" /></th></tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">1 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Rhone-Alpes/Ain/pc-look\" style=\"color : #000000; text-decoration : none;\">PC Look</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">2 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Nord-Pas-de-Calais/Pas-de-Calais/atelier-informatique\" style=\"color : #000000; text-decoration : none;\">Atelier Informatique</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">3 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Val-de-Marne/zanax-multimedia\" style=\"color : #000000; text-decoration : none;\">Zanax Multim\351dia</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">4 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Hauts-de-Seine/misteroops\" style=\"color : #000000; text-decoration : none;\">MISTEROOPS</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">5 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/12/168-golden-avenue\" style=\"color : #000000; text-decoration : none;\">168 Golden Avenue</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">6 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Seine-Saint-Denis/microchoix\" style=\"color : #000000; text-decoration : none;\">microchoix</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">7 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/12/e-soph\" style=\"color : #000000; text-decoration : none;\">e-Soph</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">8 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Paris/13/pc-price-club\" style=\"color : #000000; text-decoration : none;\">PC Price Club</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ddeeee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">9 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Ile-de-France/Seine-et-Marne/pc-77\" style=\"color : #000000; text-decoration : none;\">PC 77</a></td>\n\t\t\t\t</tr><tr style=\"background-color : #ccddee; font-size : 10px; font-weight : 700; color : #cc0003;\">\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 32px;\">10 <img src=\"http://micro-achat.01net.com/img/utils/micro-achat/flechefine_fondtransp.gif\" alt=\"&gt;\" /></td>\n\t\t\t\t\t<td style=\"border-top : 1px solid #ffffff; width : 110px;\"><a href=\"http://micro-achat.01net.com/annuaire/Alsace/Bas-Rhin/web-in-informatique\" style=\"color : #000000; text-decoration : none;\">Web In Informatique</a></td>\n\t\t\t\t</tr></table>\n\t\t\t\t</div>\n\t\t\t\t<br>\r\n<!-- FIN MA_ColD --> <!-- - ZONE D0 -->\r\n<!-- + ZONE D1 -->\r\n<!-- - ZONE D1 -->\r\n<!-- + ZONE D2 -->\r\n<!-- - ZONE D2 -->\r\n<!-- -ZONE_Dn -->\r\n</td>\r\n\t</tr>\r\n<!-- FIN PARTIE PUB //-->\r\n\t<tr>\r\n\t\t<td valign=top width=193 height=100% background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n\t\t<!-- contenu colonne de gauche //-->\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0  background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n<!-- +ZONE_Gn -->\r\n<!-- + ZONE G0 -->\r\n<tr><!-- ********** DEBUT MHA_MenusChainesV4 //-->\r\n<td valign=top>\n<table border=0 cellpadding=0 cellspacing=0 width=193 bgcolor=#FFFFFF>\n<tr>\n<td background=\"/img/v4/menus/motifgauche_menus.gif\" width=20 rowspan=2><img src=\"/img/dot.gif\" width=20 height=20></td>\n<td width=173 colspan=2 bgcolor=#FFFFFF><img src=\"/img/dot.gif\" width=173 height=20></td>\n</tr>\n<tr>\n<td valign=top width=159>\n\n<a href=\"http://www.01net.com\"><img src=\"/img/v4/menus/mha/home01net-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com\"><img src=\"/img/v4/menus/mha/home-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4317.html\"><img src=\"/img/v4/menus/mha/ordinateurs-2.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4318.html\"><img src=\"/img/v4/menus/mha/composants-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4319.html\"><img src=\"/img/v4/menus/mha/stockage-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4320.html\"><img src=\"/img/v4/menus/mha/image-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4321.html\"><img src=\"/img/v4/menus/mha/peripheriques-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4322.html\"><img src=\"/img/v4/menus/mha/reseaux-1.gif\" width=159 border=0></a><br>\n<a href=\"http://microachat.01net.com/rubrique/4323.html\"><img src=\"/img/v4/menus/mha/accessoires-1.gif\" width=159 border=0></a><br>\n<a href=\"http://micro-achat.01net.com/guide-produits/\"><img src=\"/img/v4/menus/mha/comparateur-1.gif\" width=159 border=0></a><br>\n<a href=\"http://micro-achat.01net.com/annuaire/\"><img src=\"/img/v4/menus/mha/annuaire-1.gif\" width=159 border=0></a><br></td>\n<td width=14><img src=\"/img/dot.gif\" width=14 height=14></td>\n</tr>\n<tr>\n<td colspan=3><img src=\"/img/v4/menus/bas_menus.gif\" width=193 height=31></td>\n</tr>\n</table></td><!-- ********** FIN MHA_MenusChainesV4 //--> </tr><!-- - ZONE G0 -->\r\n<!-- + ZONE G1 -->\r\n<tr><!-- DEBUT MODELE RUBRIQUE V4ColGaucheMHA //-->\r\n<!-- ********** DEBUT BLOC DernieresNewsTC //-->\r\n<td valign=top>\r\n<!-- DEBUT RECHERCHE MHA -->\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n\t\t\t<td valign=top background=\"http://microachat.01net.com/img/v4/fond_rech_mha.gif\" height=98 style=\"background-repeat:no-repeat;\"><form method=\"get\" name=\"chercher\" action=\"http://www.01net.com/aiguillage_recherche/1,6138,,00.html\"><img src=\"http://microachat.01net.com/img/dot.gif\" width=193 height=17><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><input type=\"text\" name=\"fullText\" style=\"width:130px;font:12px;\"><br><img src=\"http://microachat.01net.com/img/dot.gif\" width=1 height=6><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><select name=\"sousArbo\" style=\"width:130px;font:12px;\">\r\n\t\t\t<option value=\"mha\">dans Micro Achat\r\n\t\t\t<option value=\"cmp\">les prix\r\n\t\t\t<option value=\"ann\">les revendeurs\r\n\t\t\t<option value=\"2641\">tout 01net.\r\n\t\t\t<option value=\"emploi\">les offres d\'emploi\r\n\t\t\t<option value=\"telecharger\"> telecharger.com\r\n\t\t\t<option value=\"web\">le web\r\n\t\t\t</select><br><img src=\"http://microachat.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t<img src=\"http://microachat.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"http://microachat.01net.com/img/v4/ok_bloc_recher_mha.gif\" border=\"0\"></form>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=10 vspace=0>\r\n<!-- FIN RECHERCHE MHA -->\r\n      <!-- modele TCFilColgTitV4 //-->\r\n    <table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top>\r\n\t\t<table width=155 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=2><img src=\"http://www.01net.com/img/ban/Ban_v4_DernieresNews01net.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4></td>\r\n\t\t\t</tr>\r\n\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/256059.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">CD et DVD bient\364t insensibles aux rayures<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/255796.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">OpenOffice gagne son service<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"></td>\r\n\t\t\t\t<td valign=top><A HREF=\"http://www.01net.com/article/255731.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">La messagerie en cinq minutes selon Ipswitch<br></font></a><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=2></td>\r\n\t\t\t</tr>\r\n\t\t\t\t\t\t\t\t<tr>\r\n\t\t\t\t<td valign=top colspan=2><A HREF=\"http://www.01net.com/actus/\" style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\">> toutes les news<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t\t<tr>\r\n\t\t\t\t<td colspan=2><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/crochet_bleuhaut_155.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20> <!-- ********** FIN BLOC DernieresNewsTC //-->\r\n<!-- ********** DEBUT BLOC  NL_MHA //-->\r\n<SCRIPT language=\"javascript\" src=\"http://www.01net.com/js/lib.js\"></SCRIPT>\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<FORM name=\"formgen\" method=\"get\" action=\"http://microachat.01net.com/outils/newsletter_MicroAchat.html\" onSubmit=\"return validateForm(this)\">\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=155 colspan=4><img src=\"http://www.01net.com/img/ban/Ban_V4_Newslett.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=10><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=1 bgcolor=#CC0000><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t<td width=153>\r\n\t\t<table width=153 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=10><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t\t\t<td valign=top><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefinefd_ffffff.gif\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Recevez chaque jour l\'actualit\351 des produits et des promos<br></font>\r\n\t\t\t\t<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td><input type=\"text\" name=\"email\" size=\"14\" style=\"width:130px;font:12px;\" value=\"entrez votre e-mail\" onFocus=\"javascript:document.formgen.email.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"http://www.01net.com/img/v4/ok_bloc_recher.gif\" border=\"0\"></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td width=1 bgcolor=#CC0000><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td width=155 colspan=4><img src=\"http://www.01net.com/img/v4/base_newsletters.gif\"></td>\r\n\t\t</FORM>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20>\r\n<SCRIPT language=\"Javascript\">\r\ndocument.formgen.email.validator= \'notNullEmailPat\';\r\ndocument.formgen.email.nomvalidator= \'E-mail\';\r\n</SCRIPT>\r\n<!-- ********** FIN BLOC NL_MHA //-->\r\n</td>\r\n</tr>\r\n<tr>\r\n<!-- ********** DEBUT BLOC Actus ActusUneV4 //-->\r\n<td valign=top background=\"http://www.01net.com/img/v4/sepgrisedroite.gif\">\r\n<table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top>\r\n\t\t<table width=155 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/ban/Ban_v4_LaUne.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/entreprise/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Entreprise</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://www.01net.com/article/255737.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">Quand le billet papier s\'envole vers la d\351mat\351rialisation</font></a></td>\r\n\t\t\t\t<td valign=top width=2><img src=\"http://www.01net.com/img/dot.gif\" width=2 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/article/255737.html\"><img src=\"http://www.01net.com/img/MEA_v4/billet_virtuel-65.jpg\" border=0></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/pratique/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Trucs et astuces</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255698.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">D\351pannez Windows XP</font></a></td>\r\n\t\t\t\t<td valign=top width=2><img src=\"http://www.01net.com/img/dot.gif\" width=2 height=1></td>\r\n\t\t\t\t<td valign=top><a href=\"http://www.01net.com/article/255698.html\"><img src=\"http://www.01net.com/img/MEA_v4/depannez_XP-65.jpg\" border=0 ></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t</tr>\r\n\t\t    <tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top colspan=3><a href=\"http://www.01net.com/conso/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Conso</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255524.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">Vos photos sur papier imprimante ou labo ?<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t<!-- exemple de lien avec pseudorub pour produits et tests -->\r\n\t\t<!-- <a href=\"/outils/PseudoRub.php?base=test-comp&rub=1730&pseudo=test-comp20041005\"> -->\r\n\t\t\t<tr>\r\n\t\t\t\t<td valign=top width=1><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t\t\t<td valign=top colspan=3><a href=\"http://www.01net.com/produits/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b><u>Produits &amp; Tests</u></b><br></font></a>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"/article/255782.html\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 11px; text-decoration:none;\">5 programmes d\222encodage vid\351o gratuits<br></font></a></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td colspan=4><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/LaUne_Sep.gif\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t</tr>\r\n</table>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20>\r\n</td>\r\n<!-- ********** FIN BLOC Actus ActusUneV4 //-->    </tr>\r\n<tr>\r\n<td>\r\n<table width=193 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" width=10 height=1></td>\r\n\t\t<td valign=top><a href=\"mailto:s.cohen@micro-achat.fr\"><img border=0 src=\"http://www.01net.com/img/v4/espace-revendeurs.gif\"></td>\r\n\t</tr>\r\n</table>\r\n<br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20></td>\r\n<!-- FIN MODELE RUBRIQUE V4ColGaucheMHA //-->  </tr><!-- - ZONE G1 -->\r\n<!-- + ZONE G2 -->\r\n<!-- - ZONE G2 -->\r\n<!-- + ZONE G3 -->\r\n<!-- - ZONE G3 -->\r\n<!-- + ZONE G4 -->\r\n<!-- - ZONE G4 -->\r\n<!-- + ZONE G5 -->\r\n<!-- - ZONE G5 -->\r\n<!-- + ZONE G6 -->\r\n<!-- - ZONE G6 -->\r\n<!-- + ZONE G7 -->\r\n<!-- - ZONE G7 -->\r\n<!-- + ZONE G8 -->\r\n<!-- - ZONE G8 -->\r\n<!-- + ZONE G9 -->\r\n<!-- - ZONE G9 -->\r\n<!-- + ZONE GA -->\r\n<!-- - ZONE GA -->\r\n<!-- + ZONE GB -->\r\n<!-- - ZONE GB -->\r\n<!-- + ZONE GC -->\r\n<!-- - ZONE GC -->\r\n<!-- + ZONE GD -->\r\n<!-- - ZONE GD -->\r\n<!-- + ZONE GE -->\r\n<!-- - ZONE GE -->\r\n<!-- + ZONE GF -->\r\n<!-- - ZONE GF -->\r\n<!-- -ZONE_Gn -->\r\n\t\t</table>\r\n\t\t<!-- fin contenu colonne de gauche //-->\r\n\t\t</td>\r\n<!-- ***************************************************************** DEBUT VENTRE*********************************************************************************************************************************************** //-->\r\n<!-- DEBUT WORK -->\r\n\t\t<td valign=top width=625 bgcolor=#ffffff><img src=\"http://www.01net.com/img/dot.gif\" width=625 height=1><br>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_hn -->\r\n<!-- + ZONE h0 -->\r\n<!-- MA_ban_int -->\r\n<td valign=\"top\">\r\n<img src=\"/img/dot.gif\" height=\"18\"><br>\r\n<!-- pour ordipda -->\r\n<table width=\"625\" cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td><img src=\"/img/v4/MA/Ban_MA_ordis.gif\"></td>\r\n\t</tr>\r\n</table>\r\n\t</td>\r\n<!-- /MA_ban_int -->     <!-- - ZONE h0 -->\r\n<!-- + ZONE h1 -->\r\n<!-- - ZONE h1 -->\r\n<!-- + ZONE h2 -->\r\n<!-- - ZONE h2 -->\r\n<!-- -ZONE_hn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_Hn -->\r\n<!-- + ZONE H0 -->\r\n<!-- Ma_int_Leader -->\r\n    <td valign=top>\r\n<img src=\"/img/dot.gif\" width=1 height=18><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=320>\r\n<tr>\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<td width=144 valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=143 height=1 vspace=0><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:11px;>Portable</font><br>\r\n<A HREF=\"/article/256198.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=font-size:14px;><b>Un nouvel ultra portable r\351alis\351 par Nec</b></font></a><br>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/256198.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67509.jpg.res_100-100.jpg\" border=0 hspace=0 vspace=0></a><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n<font face=arial,helvetica size=2 color=#000000 style=font-size:12px;><img src=\"/img/v4/flechefine_fondtransp.gif\">Le Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.</font><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:12px;>\340 partir de 1663&#160;\200</font>\r\n</td>\r\n<td width=17 background=\"/img/v4/MA/v4-fond-sep-mea-leader.gif\"><img src=\"/img/dot.gif\" width=17 height=1></td>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<td width=144 valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=143 height=1 vspace=0><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:11px;>Portable</font><br>\r\n<A HREF=\"/article/255194.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=font-size:14px;><b>Asus pr\351sente trois petits nouveaux dans la gamme A3N</b></font></a><br>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255194.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67168.jpg.res_100-100.jpg\" border=0 hspace=0 vspace=0></a><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n<font face=arial,helvetica size=2 color=#000000 style=font-size:12px;><img src=\"/img/v4/flechefine_fondtransp.gif\">Ces trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.</font><br>\r\n<font face=arial,helvetica size=1 color=#CC0000 style=font-size:12px;>\340 partir de 1346&#160;\200</font>\r\n</td>\r\n<td width=15><img src=\"/img/dot.gif\" width=15 height=1></td>\r\n\t\t\t\t</tr>\r\n</table>\r\n</td>\r\n<!-- /Ma_int_Leader -->    <!-- - ZONE H0 -->\r\n<!-- + ZONE H1 -->\r\n<!-- - ZONE H1 -->\r\n<!-- + ZONE H2 -->\r\n<!-- MA_BP_MP -->\r\n<td valign=\"top\" width=\"100%\">\r\n\t<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\r\n\t<tr>\r\n\t<td width=\"50%\" valign=\"top\">\r\n\t<!-- DEBUT MicroAchat MA_BonPlan -->\r\n<td valign=top>\r\n<img src=\"/img/dot.gif\" width=1 height=18><br>\r\n<table border=0 cellpadding=1 cellspacing=0 width=145 bgcolor=#CC0000>\r\n<tr>\r\n<td align=center><font face=arial,helvetica size=1 color=#FFFFFF style=\"font-size:11px;\">BON PLAN</a></font></td>\r\n</tr>\r\n<tr>\r\n<td  width=145>\r\n<div style=\"padding:5px;padding-left:5px;padding-fight:5px;margin:0px;margin-left:1px;margin-right:1px;background-color:#FFFFFF;\">\r\n<img src=\"/img/microachat/logo_shuttle_SB83G5.gif\" border=0><br>\r\n<font face=arial,helvetica size=2 color=#CC0000 style=\"font-size:12px;\">Les derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.<br></font>\r\n<center><a href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/sb83g5/?fabriquant=1&page=1&tri=titre\"><img src=\"/img/microachat/mea_shuttle_SB83G5.gif\" border=0 vspace=5></a><br></center>\r\n<center>\r\n<font face=arial,helvetica size=2 color=#CC0000 style=\"font-size:13px;\"><b>\340 partir de</b><br>\r\n<div style=\"border:solid 2px #CC0000;width:100px;background-color:#FFCC00;\"><b>415 \200</b></div>\r\n</center>\r\n</div>\r\n</td>\r\n</tr>\r\n<tr>\r\n<td align=center><font face=arial,helvetica size=1 color=#FFFFFF style=\"font-size:11px;\">publicit\351</a></font></td>\r\n</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_BonPlan -->  \t</td>\r\n\t<td width=\"15\"><img src=\"/img/dot.gif\" width=\"15\"></td>\r\n\t<td width=\"50%\" valign=\"top\">\r\n\t<!-- DEBUT MicroAchat MA_MeillPrixAct //-->\r\n<td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=145 height=1><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=18><br>\r\n<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<FORM name=\"prix\" action=\"http://www.micro-achat.01net.com/guide-produits/recherche.php\" method=\"post\">\r\n\t\t<td width=145 colspan=3><img src=\"http://www.01net.com/img/ban/Ban_v4_MeillPrix_MA.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=1 bgcolor=#FFCC00><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t\t<td width=143>\r\n\t\t<table width=143 cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=6><img src=\"http://www.01net.com/img/dot.gif\" width=6 height=1></td>\r\n\t\t\t\t<td valign=top><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=15><br>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<img src=\"http://www.01net.com/img/ban/Ban_MA_trouv_ordi.gif\"><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/desktops/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Desktops</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/portables/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Portables</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/mini-pc/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Mini-PC</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/pda---tablets-pc/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Pda / Tablets-PC</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/apple/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">Apple</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/MA/fleche_rouge_maigre.gif\"><a style=\"font-size: 10px; text-decoration:none;\" href=\"http://micro-achat.01net.com/guide-produits/ordinateurs/gps/\"><font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\">GPS</a><br></font>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=20><br>\r\n\t\t\t\t\t\t\t\t<table width=* cellspacing=0 cellpadding=0 border=0>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td><input type=\"text\" name=\"recherchedirecte\" size=\"14\" style=\"width:130px;font:12px;\" value=\"     recherche directe\" onFocus=\"javascript:document.prix.recherchedirecte.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=9><br>\r\n\t\t\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1><input type=\"image\" src=\"/img/v4/MA/ok_bloc_recher_MA.gif\" border=\"0\"></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td width=1 bgcolor=#FFCC00><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td width=145 colspan=3><img src=\"http://www.01net.com/img/v4/MA/base_meillPrix.gif\"></td>\r\n\t\t</FORM>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_MeillPrixAct //-->  \t</td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n<!-- /MA_BP_MP -->  <!-- - ZONE H2 -->\r\n<!-- -ZONE_Hn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- +ZONE_Tn -->\r\n<!-- + ZONE T0 -->\r\n    <td valign=\"top\">\r\n<img src=\"http://www.01net.com/img/dot.gif\" height=13><br>\r\n<table border=0 width=320 cellpadding=0 cellspacing=0>\r\n<tr>\r\n<td width=305><img src=\"http://www.01net.com/img/ban/Ban_v4_DernNews_MA.gif\"><br><img src=\"http://www.01net.com/img/v4/MA/v4-tiret-hauts-mha.gif\"></td>\r\n<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n</tr>\r\n<tr>\r\n<td bgcolor=\"#FEF9E0\">\r\n\t<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Portable&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255149.html\" style=\"color:#000000;text-decoration:none;\">Toshiba consacre deux gammes de machines au multim\351dia</a></b><br>\r\n\t<font color=\"#000000\">Equipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Ordinateur&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254686.html\" style=\"color:#000000;text-decoration:none;\">Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme</a></b><br>\r\n\t<font color=\"#000000\">La firme \340 la pomme propose une station de travail \351volutive et relativement abordable.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>PC&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254549.html\" style=\"color:#000000;text-decoration:none;\">Alienware propose deux machines au look \351trange</a></b><br>\r\n\t<font color=\"#000000\">Aurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t<tr>\r\n\t<td><div style=\"padding:2px;width:100%;\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#CC0000\" style=\"font-size:11px;\"><b>Portable&nbsp;<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/254501.html\" style=\"color:#000000;text-decoration:none;\">Trois nouveaux iBook G4 chez Apple</a></b><br>\r\n\t<font color=\"#000000\">Chez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.<br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=4><br></font></td>\r\n\t</tr>\r\n\t\t\t\t\t<tr>\r\n\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=10></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-red-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td align=\"right\">\r\n\t\t\t\t<A HREF=\"http://microachat.01net.com/rubrique/4365.html\"  style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 10px;\">> toutes les news</font></a>\r\n\t\t\t</td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n</td> <!-- - ZONE T0 -->\r\n<!-- + ZONE T1 -->\r\n<!-- Ma_derpromo  -->\r\n    <td valign=\"top\">\r\n<img src=\"/img/dot.gif\" height=13><br>\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td bgcolor=\"#ffffff\"><img src=\"/img/v4/MA/v4-lespromos-mha.gif\"><br><img src=\"/img/v4/MA/v4-tiret-hauts-mha.gif\"></td>\r\n</tr>\r\n</table>\r\n<!-- DEBUT MODELE D\'AFFICHAGE POUR LES n PREMIERS ARTICLES //-->\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255806.html\" class=\"nodeco\"><img src=\"/images/67462.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255806.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>Asus A3N15-C Pro</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>1170&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255688.html\" class=\"nodeco\"><img src=\"/images/67381.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255688.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>Soltek EQ3702A Miroir</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>559&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td colspan=\"5\"><img src=\"/img/dot.gif\" width=\"9\"></td>\r\n</tr>\r\n<tr>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"42\" valign=\"top\">\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"/article/255513.html\" class=\"nodeco\"><img src=\"/images/67319.jpg\" border=0 hspace=0 vspace=0 width=\"42\" height=\"42\"></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t</td>\r\n<td width=\"16\"><img src=\"/img/dot.gif\" width=\"16\"></td>\r\n<td width=\"*\"  valign=\"top\"><A HREF=\"/article/255513.html\" class=\"nodeco\"><font face=\"arial,helvetica\" size=2 color=\"#000000\" style=\"font-size:11px;\"><b>IBM ThinkPad R51</b></a><br>\r\n&nbsp;<img src=\"/img/v4/flechefine_fondtransp.gif\">Voici un portable complet et pourtant relativement l\351ger.<br></font></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"5\" align=\"right\">\r\n\t<table width=\"80\" border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t<td width=\"76\" align=\"center\" bgcolor=\"#CC0000\">\r\n\t<font face=\"arial,helvetica\" size=2 color=\"#ffffff\" style=\"font-size:11px;\"><b>1299&#160;\200</b></font></td>\r\n\t<td><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t<tr>\r\n\t<td colspan=\"3\"><img src=\"/img/dot.gif\" width=2></td>\r\n\t</tr>\r\n\t</table>\r\n</td>\r\n</tr>\r\n</table>\r\n\t\t\t\t<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"305\" bgcolor=\"#E9EDFC\">\r\n<tr>\r\n<td><img src=\"http://www.01net.com/img/dot.gif\" height=10></td>\r\n</tr>\r\n<tr>\r\n<td background=\"/img/v4/MA/v4-sep-red-mha.gif\"><img src=\"/img/dot.gif\" height=1></td>\r\n</tr>\r\n<tr>\r\n<td align=\"right\" valign=\"top\">\r\n\t\t\t\t<A HREF=\"http://microachat.01net.com/rubrique/4366.html\"  style=\"text-decoration:none;\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 10px;\">> toutes les promos</font></a>\r\n\t\t</td>\r\n</tr>\r\n</table>\r\n</td>\r\n<!-- /Ma_derpromo  -->   <!-- - ZONE T1 -->\r\n<!-- + ZONE T2 -->\r\n<!-- - ZONE T2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE T3 -->\r\n<!-- DEBUT MicroAchat MA_PubG -->\r\n<td valign=top align=center>\r\n<table border=0 width=320 cellpadding=0 cellspacing=0>\r\n\t<tr>\r\n\t\t<td width=305><img src=\"/img/dot.gif\" width=1 height=12><br><a href=\"http://www.smartadserver.com/call/cliccommand/45590/[timestamp]?\" target=_blank><img src=\"/img/microachat/Bandeau_FX6021.jpg\" border=0></a></td>\r\n\t\t<td><img src=\"/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_PubG -->  <!-- - ZONE T3 -->\r\n<!-- + ZONE T4 -->\r\n<!-- DEBUT MicroAchat MA_PubD -->\r\n<td valign=top align=center>\r\n<table border=0 width=305 cellpadding=0 cellspacing=0>\r\n\t<tr>\r\n\t\t<td width=305><img src=\"/img/dot.gif\" width=1 height=12><br><a href=\"http://www.smartadserver.com/call/cliccommand/45591/[timestamp]?\" target=_blank><img src=\"/img/microachat/twc_305x125.jpg\" border=0></a></td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN  MicroAchat MA_PubD --> <!-- - ZONE T4 -->\r\n<!-- + ZONE T5 -->\r\n<!-- - ZONE T5 -->\r\n<!-- -ZONE_Tn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n\t\t\t<td valign=top>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n<!-- +ZONE_gn -->\r\n<!-- + ZONE g0 -->\r\n<!-- - ZONE g0 -->\r\n<!-- + ZONE g1 -->\r\n<!-- - ZONE g1 -->\r\n<!-- + ZONE g2 -->\r\n<!-- - ZONE g2 -->\r\n<!-- + ZONE g3 -->\r\n<!-- - ZONE g3 -->\r\n<!-- + ZONE g4 -->\r\n<!-- - ZONE g4 -->\r\n<!-- + ZONE g5 -->\r\n<!-- - ZONE g5 -->\r\n<!-- + ZONE g6 -->\r\n<!-- - ZONE g6 -->\r\n<!-- + ZONE g7 -->\r\n<!-- - ZONE g7 -->\r\n<!-- + ZONE g8 -->\r\n<!-- - ZONE g8 -->\r\n<!-- + ZONE g9 -->\r\n<!-- - ZONE g9 -->\r\n<!-- -ZONE_gn -->\r\n\t\t\t</table>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t\t\t<tr>\r\n<!-- +ZONE_Mn -->\r\n<!-- + ZONE M0 -->\r\n<!-- modele Ma_GuideAch //-->\r\n    <td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" height=13><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t<tr>\r\n\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_GuideAchat_MA.gif\" vspace=1></td>\r\n\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<div style=\"border:solid 1px #FFCC00;width:100%\">\r\n\t<!-- ****DEBUT EXTRACTION OBJET XML *********** //-->\r\n<!-- ****FIN EXTRACTION OBJET XML *********** //-->\r\n<center>\r\n<!--debut  insertion image //-->\r\n\t\t\t\t\t       \t   \t\t\t\t\t\t\t\t\t\t\t\t\t<A HREF=\"http://microachat.01net.com/article/254561.html\" style=\"text-decoration:none;color:#000000;\"><img src=\"/images/67088.jpg.res_121-111.jpg\" border=0 hspace=0 vspace=0></a>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \t   \t<!-- fin insertion image //-->\r\n</center>\r\n<div style=\"padding:5px;\">\r\n<a href=\"http://microachat.01net.com/article/254561.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\"><b>Les graveurs de DVD</b><br></font></a>\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">Quel graveur choisir&#160;? Quel type de format&#160;? Quelle vitesse&#160;? Double couche ou simple couche&#160;? Voici tout ce qu\'il faut savoir pour faire le bon choix.</font></div>\r\n\t\t\t\t\t\t</div>\r\n\t\t</td>\r\n\t</tr>\r\n</table>\r\n</td> <!-- - ZONE M0 -->\r\n<!-- + ZONE M1 -->\r\n<!-- modele Ma_DirectLab //-->\r\n    <td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t<tr>\r\n\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_DirectLab_MA.gif\" vspace=1></td>\r\n\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<div style=\"border:solid 1px #FFCC00;width:100%\">\r\n\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255744.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>Kodak EasyShare Printer Dock Plus&#160;:</b>\r\n\t\t\t\t\t\tvos photos 10&#160;x&#160;15&#160;cm en 60&#160;secondes</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255780.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>3DMark05&#160;:</b>\r\n\t\t\t\t\t\tun labo 3D \340 domicile</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255691.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>DVDInfoPro 2.6</b>\r\n\t\t\t\t\t\treconna\356t CD et DVD</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255722.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">\t\t\t\t\t\t\t<b>Scaleo PA D3008, de Fujitsu-Siemens&#160;:</b>\r\n\t\t\t\t\t\tune impression d\'inachev\351</font></a></div>\r\n\t\t\t\t<div style=\"padding:4px;\">\r\n<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://microachat.01net.com/article/255514.html\" style=\"text-decoration:none;color:#000000;\"><font face=arial,helvetica size=2 color=#000000 style=\"font-size:12px;\">Carbon 5&#160;Go&#160;: 2&#160;500&#160;chansons dans le creux de la main</font></a></div>\r\n\t\t\t</div></td>\r\n\t</tr>\r\n</table>\r\n</td> <!-- - ZONE M1 -->\r\n<!-- + ZONE M2 -->\r\n<!-- DEBUT MicroAchat MA_AnnTelec -->\r\n<td valign=top>\r\n<script type=\"text/javascript\">\r\nfunction regionChange()\r\n{\r\ndocument.selection.departement.options.length=0;\r\nswitch(document.selection.region.value)\r\n\t{\r\n\t\tcase \"aucun\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Nord-Pas-de-Calais\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pas-de-Calais\", \"Pas-de-Calais\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Nord\", \"Nord\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Haute-Normandie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Eure\", \"Eure\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-Maritime\", \"Seine-Maritime\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Basse-Normandie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Manche\", \"Manche\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Calvados\", \"Calvados\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Orne\", \"Orne\");\r\n\t\tbreak;\r\n\t\tcase \"Picardie\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Somme\", \"Somme\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Oise\", \"Oise\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aisne\", \"Aisne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Bretagne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Finistere\", \"Finistere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cotes-dArmor\", \"Cotes-dArmor\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Morbihan\", \"Morbihan\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ille-et-Vilaine\", \"Ille-et-Vilaine\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Pays-de-Loire\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loire-Atlantique\", \"Loire-Atlantique\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vendee\", \"Vendee\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Maine-et-Loire\", \"Maine-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Mayenne\", \"Mayenne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Sarthe\", \"Sarthe\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Centre\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Eure-et-Loir\", \"Eure-et-Loir\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loiret\", \"Loiret\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loir-et-Cher\", \"Loir-et-Cher\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Indre-et-Loire\", \"Indre-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Indre\", \"Indre\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cher\", \"Cher\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Ile-de-France\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Val-dOise\", \"Val-dOise\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Yvelines\", \"Yvelines\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Essonne\", \"Essonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-et-Marne\", \"Seine-et-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hauts-de-Seine\", \"Hauts-de-Seine\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Seine-Saint-Denis\", \"Seine-Saint-Denis\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Val-de-Marne\", \"Val-de-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Paris\", \"Paris\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Champagnes-Ardennes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ardennes\", \"Ardennes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Marne\", \"Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aube\", \"Aube\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Marne\", \"Haute-Marne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Lorraine\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vosges\", \"Vosges\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Meurthe-et-Moselle\", \"Meurthe-et-Moselle\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Meuse\", \"Meuse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Moselle\", \"Moselle\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Alsace\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Bas-Rhin\", \"Bas-Rhin\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haut-Rhin\", \"Haut-Rhin\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Franche-Compte\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Jura\", \"Jura\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Doubs\", \"Doubs\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Saone\", \"Haute-Saone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Territoire-de-Belfort\", \"Territoire-de-Belfort\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Bourgogne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Yonne\", \"Yonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Nievre\", \"Nievre\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cote-dOr\", \"Cote-dOr\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Saone-et-Loire\", \"Saone-et-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Poitou-Charentes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Deux-Sevres\", \"Deux-Sevres\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Charente-Maritime\", \"Charente-Maritime\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Charente\", \"Charente\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vienne\", \"Vienne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Limousin\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Vienne\", \"Haute-Vienne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Correze\", \"Correze\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Creuse\", \"Creuse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Auvergne\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Allier\", \"Allier\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Puy-de-Dome\", \"Puy-de-Dome\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Cantal\", \"Cantal\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Loire\", \"Haute-Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Rhone-Alpes\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Loire\", \"Loire\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Rhone\", \"Rhone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ain\", \"Ain\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ardeche\", \"Ardeche\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Drome\", \"Drome\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Isere\", \"Isere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Savoie\", \"Savoie\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Savoie\", \"Haute-Savoie\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Aquitaine\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gironde\", \"Gironde\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Landes\", \"Landes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pyrenees-Atlantiques\", \"Pyrenees-Atlantiques\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lot-et-Garonne\", \"Lot-et-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Dordogne\", \"Dordogne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Midi-Pyrenees\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lot\", \"Lot\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Tarn-et-Garonne\", \"Tarn-et-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gers\", \"Gers\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hautes-Pyrenees\", \"Hautes-Pyrenees\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Garonne\", \"Haute-Garonne\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Ariege\", \"Ariege\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Tarn\", \"Tarn\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aveyron\", \"Aveyron\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Languedoc-Roussillon\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Pyrenees-Orientales\", \"Pyrenees-Orientales\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Aude\", \"Aude\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Herault\", \"Herault\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Gard\", \"Gard\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Lozere\", \"Lozere\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Provence-Alpes-Cote-dazur\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Bouches-du-Rhone\", \"Bouches-du-Rhone\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Vaucluse\", \"Vaucluse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Alpes-de-haute-Provence\", \"Alpes-de-haute-Provence\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Hautes-Alpes\", \"Hautes-Alpes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Var\", \"Var\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Alpes-Maritimes\", \"Alpes-Maritimes\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"Corse\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Corse-du-Sud\", \"Corse-du-Sud\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Haute-Corse\", \"Haute-Corse\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t\tcase \"DomTom\" :\r\n\t\t\tvar o=new Option(\"D\351partement\", \"aucun\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Guadeloupe\", \"Guadeloupe\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Guyane\", \"Guyane\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"La-Reunion\", \"La-Reunion\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Martinique\", \"Martinique\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"Mayotte\", \"Mayotte\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\t\tvar o=new Option(\"St-Pierre-et-Miquelon\", \"St-Pierre-et-Miquelon\");\r\n\t\t\tdocument.selection.departement.options[document.selection.departement.options.length]=o;\r\n\t\tbreak;\r\n\t}\r\n}\r\nfunction deptChange()\r\n{\r\nif (document.selection.departement.value == \'Paris\')\r\n\tdocument.getElementById(\'arrondissement\').style.display = \'inline\';\r\nelse\r\n\tdocument.getElementById(\'arrondissement\').style.display = \'none\';\r\n}\r\n</script>\r\n<table width=305 cellspacing=0 cellpadding=0 border=0>\r\n\t<tr>\r\n\t\t<td valign=top>\r\n\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=160>\r\n\t\t\t<tr>\r\n\t\t\t\t<td width=145><img src=\"http://www.01net.com/img/ban/Ban_v4_AnnuaiRev_MA.gif\" vspace=1></td>\r\n\t\t\t\t<td rowspan=2 width=15><img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr><form action=\"http://micro-achat.01net.com/annuaire/recherche.php\" method=\"post\" name=\"selection\">\r\n\t\t\t\t<td bgcolor=#FFFFDD>\r\n\t\t\t\t<div style=\"border:solid 1px #FFCC00;width:100%\"><div style=\"padding:2px;\"><img src=\"http://www.01net.com/img/v4/MA/carte_revend.gif\"><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Choisir une r\351gion</b><br></font>\r\n<select name=\"region\" onChange=\"regionChange()\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"aucun\">-------------</option>\r\n<option value=\"Nord-Pas-de-Calais\">Nord-Pas-de-Calais</option>\r\n<option value=\"Haute-Normandie\">Haute-Normandie</option>\r\n<option value=\"Basse-Normandie\">Basse-Normandie</option>\r\n<option value=\"Picardie\">Picardie</option>\r\n<option value=\"Bretagne\">Bretagne</option>\r\n<option value=\"Pays-de-Loire\">Pays-de-Loire</option>\r\n<option value=\"Centre\">Centre</option>\r\n<option value=\"Ile-de-France\">Ile-de-France</option>\r\n<option value=\"Champagnes-Ardennes\">Champagne ardennes</option>\r\n<option value=\"Lorraine\">Lorraine</option>\r\n<option value=\"Alsace\">Alsace</option>\r\n<option value=\"Franche-Compte\">Franche-Compte</option>\r\n<option value=\"Bourgogne\">Bourgogne</option>\r\n<option value=\"Poitou-Charentes\">Poitou-Charentes</option>\r\n<option value=\"Limousin\">Limousin</option>\r\n<option value=\"Auvergne\">Auvergne</option>\r\n<option value=\"Rhone-Alpes\">Rhone-Alpes</option>\r\n<option value=\"Aquitaine\">Aquitaine</option>\r\n<option value=\"Midi-Pyrenees\">Midi-Pyrenees</option>\r\n<option value=\"Languedoc-Roussillon\">Languedoc roussillon</option>\r\n<option value=\"Provence-Alpes-Cote-dazur\">PACA</option>\r\n<option value=\"Corse\">Corse</option>\r\n<option value=\"DomTom\">DomTom</option>\r\n</select>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Un d\351partement</b><br></font>\r\n<select name=\"departement\" onChange=\"deptChange()\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"aucun\">-------------</option>\r\n</select>\r\n<div id=\"arrondissement\" style=\"display : none;\">\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=5><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Un arrondissement</b><br></font>\r\n<select name=\"arrondissement\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;\">\r\n<option value=\"0\">-------------</option>\r\n<option value=\"1\">I</option>\r\n<option value=\"2\">II</option>\r\n<option value=\"3\">III</option>\r\n<option value=\"4\">IV</option>\r\n<option value=\"5\">V</option>\r\n<option value=\"6\">VI</option>\r\n<option value=\"7\">VII</option>\r\n<option value=\"8\">VIII</option>\r\n<option value=\"9\">IX</option>\r\n<option value=\"10\">X</option>\r\n<option value=\"11\">XI</option>\r\n<option value=\"12\">XII</option>\r\n<option value=\"13\">XIII</option>\r\n<option value=\"14\">XIV</option>\r\n<option value=\"15\">XV</option>\r\n<option value=\"16\">XVI</option>\r\n<option value=\"17\">XVII</option>\r\n<option value=\"18\">XVIII</option>\r\n<option value=\"19\">XIX</option>\r\n<option value=\"20\">XX</option>\r\n</select>\r\n</div>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=10><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Recherche directe</b><br></font>\r\n\t\t\t\t<font face=\"Arial\" size=1 color=#000000 style=\"font-size: 10px; text-decoration:none;\"><img src=\"http://www.01net.com/img/dot.gif\" width=8 height=1>rechercher une ville<br><img src=\"http://www.01net.com/img/dot.gif\" width=8 height=1>et/ou une boutique<br></font>\r\n\t\t\t\t<input type=\"text\" name=\"recherchedirecte\" size=\"14\" style=\"display : block; font-size:9px;font-variant:arial,helvetica,sans-serif;width:130px;\" value=\"\" onFocus=\"javascript:document.selection.recherchedirecte.value=\'\'\"><br><img src=\"http://www.01net.com/img/dot.gif\" width=1 height=3><br>\r\n\t\t\t\t<img src=\"http://www.01net.com/img/dot.gif\" width=28 height=1>&nbsp;<input type=\"image\" src=\"http://www.01net.com/img/v4/MA/ok_bloc_recher_MA.gif\" border=\"0\">\r\n\t\t\t\t<table height=23 width=135 cellspacing=0 cellpadding=0 border=0 bgcolor=#FFEE77>\r\n\t\t\t\t\t<tr>\r\n\t\t\t\t\t\t<td bgcolor=#FFEE77 valign=middle align=center><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://micro-achat.01net.com/annuaire/\"><font face=\"Arial\" size=1 color=#CC0000 style=\"font-size: 11px; text-decoration:none;\"><b>Recherche avanc\351e</b></font></a></td>\r\n\t\t\t\t\t</tr>\r\n\t\t\t\t</table>\r\n\t\t\t\t</div>\r\n\t\t\t\t</div>\r\n\t\t\t\t</td>\r\n\t\t\t</tr></form>\r\n\t\t</table>\r\n\t\t</td>\r\n<!-- DEBUT MicroAchat MA_Telecharg //-->\r\n<td valign=top>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=13><br>\r\n<table width=\"145\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/v4/MA/Ban_v4_MA_telec.gif\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t<td>\r\n\t\t<table width=\"145\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#DFECF6\">\r\n\t\t\t<tr>\r\n\t\t\t\t<td rowspan=\"17\"><img src=\"http://www.01net.com/img/dot.gif\" width=\"6\"></td>\r\n\t\t\t\t<td><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"></td>\r\n\t\t\t\t<td rowspan=\"17\"><img src=\"http://www.01net.com/img/dot.gif\" width=\"6\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Bureautique\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Bureautique</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Traducteur, organiseur...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Multimedia\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Multim\351dia</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Photo, audio, vid\351o...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Utilitaire\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Utilitaires</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Antivirus, pilotes, gravure...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Personnaliser\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Personnaliser son PC</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Ecrans de veille, th\350mes...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Programmation\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>D\351veloppement</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Cr\351ation de logiciels, BDD...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Jeux\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Jeux</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Action, simulation...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Internet\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Internet</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Utilitaires, email, FTP...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br><img src=\"http://www.01net.com/img/v4/flechefine_fondtransp.gif\"><a href=\"http://telecharger.01net.com/windows/Loisirs\" class=\"nodeco\"><font face=\"Arial,Helvetica\" size=\"2\" color=\"#124478\" style=\"font-size: 12px;\"><b>Loisirs</b></a><br></font>\r\n\t\t\t\t<font face=\"Arial,Helvetica\" size=\"2\" color=\"#000000\" style=\"font-size: 10px;\">Humour, culture...<br></font><img src=\"http://www.01net.com/img/dot.gif\" height=\"3\"><br>\r\n\t\t\t\t</td>\r\n\t\t\t</tr>\r\n\t\t\t<tr>\r\n\t\t\t\t<td background=\"http://www.01net.com/img/v4/MA/v4-sep-blue-mha.gif\"><img src=\"http://www.01net.com/img/dot.gif\" height=\"1\"></td>\r\n\t\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_Telecharg //-->  \t</tr>\r\n</table>\r\n</td>\r\n<!-- FIN MicroAchat MA_AnnTelec --> <!-- - ZONE M2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE M3 -->\r\n<!-- - ZONE M3 -->\r\n<!-- + ZONE M4 -->\r\n<!-- - ZONE M4 -->\r\n<!-- + ZONE M5 -->\r\n<!-- - ZONE M5 -->\r\n<!-- -ZONE_Mn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t<tr>\r\n<!-- +ZONE_tn -->\r\n<!-- + ZONE t0 -->\r\n<!-- - ZONE t0 -->\r\n<!-- + ZONE t1 -->\r\n<!-- - ZONE t1 -->\r\n<!-- + ZONE t2 -->\r\n<!-- - ZONE t2 -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t<table width=100% cellspacing=0 cellpadding=0 border=0>\r\n\t\t<tr>\r\n<!-- + ZONE t3 -->\r\n<!-- - ZONE t3 -->\r\n<!-- + ZONE t4 -->\r\n<!-- - ZONE t4 -->\r\n<!-- + ZONE t5 -->\r\n<!-- - ZONE t5 -->\r\n<!-- -ZONE_tn -->\r\n\t\t</tr>\r\n\t\t</table>\r\n\t\t</td>\r\n\t\t<td valign=top>\r\n\t\t<table border=0 cellpadding=0 cellspacing=0 width=*>\r\n\t\t<tr>\r\n<!-- +ZONE_dn -->\r\n<!-- + ZONE d0 -->\r\n<!-- - ZONE d0 -->\r\n<!-- + ZONE d1 -->\r\n<!-- - ZONE d1 -->\r\n<!-- + ZONE d2 -->\r\n<!-- - ZONE d2 -->\r\n<!-- + ZONE d3 -->\r\n<!-- - ZONE d3 -->\r\n<!-- + ZONE d4 -->\r\n<!-- - ZONE d4 -->\r\n<!-- + ZONE d5 -->\r\n<!-- - ZONE d5 -->\r\n<!-- + ZONE d6 -->\r\n<!-- - ZONE d6 -->\r\n<!-- + ZONE d7 -->\r\n<!-- - ZONE d7 -->\r\n<!-- + ZONE d8 -->\r\n<!-- - ZONE d8 -->\r\n<!-- + ZONE d9 -->\r\n<!-- - ZONE d9 -->\r\n<!-- -ZONE_dn -->\r\n\t\t\t\t</tr>\r\n\t\t\t</table>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n\t\t</table>\r\n<!-- FIN WORK -->\r\n\t\t</td>\r\n<!-- *********************************************************************FIN VENTRE********************************************************************************************************************************************** //-->\r\n\t\t<td rowspan=2 valign=top width=23 background=\"http://www.01net.com/img/v4/sep_verticale.gif\"><img src=\"http://www.01net.com/img/dot.gif\" width=23 height=1><br></td>\r\n\t</tr>\r\n\t<tr>\r\n\t\t\t<td colspan=2>\r\n\t\t\t<table border=0 cellpadding=0 cellspacing=0 width=100%>\r\n<!-- +ZONE_Bn -->\r\n<!-- + ZONE B0 -->\r\n<!-- - ZONE B0 -->\r\n<!-- + ZONE B1 -->\r\n<tr><!-- ********** DEBUT BLOC Home NosJournauxV4 //-->\r\n<td valign=top bgcolor=#FFFFFF>\r\n<img src=\"http://www.01net.com/img/ban/Ban_v4_jx.gif\"><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=1 height=15><br>\r\n<img src=\"http://www.01net.com/img/dot.gif\" width=15 height=1>\r\n<a href=\"http://www.01net.com/rubrique/3339.html\"><img src=\"http://www.01net.com/img/journaux/01I-small.gif\" border=0 vspace=0 hspace=12 align=top></a>\r\n<a href=\"http://www.01net.com/rubrique/4051.html\"><img src=\"http://www.01net.com/img/journaux/DSI-small.gif\" border=0 vspace=0 hspace=12 align=top></a>\r\n<a href=\"http://www.01net.com/rubrique/3345.html\"><img src=\"http://www.01net.com/img/journaux/DIN-small.gif
\ No newline at end of file
diff --git a/snappy/snappy-1.0.5/testdata/kennedy.xls b/snappy/snappy-1.0.5/testdata/kennedy.xls
new file mode 100644 (file)
index 0000000..9a85115
Binary files /dev/null and b/snappy/snappy-1.0.5/testdata/kennedy.xls differ
diff --git a/snappy/snappy-1.0.5/testdata/kppkn.gtb b/snappy/snappy-1.0.5/testdata/kppkn.gtb
new file mode 100644 (file)
index 0000000..8ccea79
Binary files /dev/null and b/snappy/snappy-1.0.5/testdata/kppkn.gtb differ
diff --git a/snappy/snappy-1.0.5/testdata/lcet10.txt b/snappy/snappy-1.0.5/testdata/lcet10.txt
new file mode 100644 (file)
index 0000000..25dda6b
--- /dev/null
@@ -0,0 +1,7519 @@
+\r
+\r
+The Project Gutenberg Etext of LOC WORKSHOP ON ELECTRONIC TEXTS\r
+\r
+\r
+\r
+\r
+                      WORKSHOP ON ELECTRONIC TEXTS\r
+\r
+                               PROCEEDINGS\r
+\r
+\r
+\r
+                          Edited by James Daly\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+                             9-10 June 1992\r
+\r
+\r
+                           Library of Congress\r
+                            Washington, D.C.\r
+\r
+\r
+\r
+    Supported by a Grant from the David and Lucile Packard Foundation\r
+\r
+\r
+               ***   ***   ***   ******   ***   ***   ***\r
+\r
+\r
+                            TABLE OF CONTENTS\r
+\r
+\r
+Acknowledgements\r
+\r
+Introduction\r
+\r
+Proceedings\r
+   Welcome\r
+      Prosser Gifford and Carl Fleischhauer\r
+\r
+   Session I.  Content in a New Form:  Who Will Use It and What Will They Do?\r
+      James Daly (Moderator)\r
+      Avra Michelson, Overview\r
+      Susan H. Veccia, User Evaluation\r
+      Joanne Freeman, Beyond the Scholar\r
+         Discussion\r
+\r
+   Session II.  Show and Tell\r
+      Jacqueline Hess (Moderator)\r
+      Elli Mylonas, Perseus Project\r
+         Discussion\r
+      Eric M. Calaluca, Patrologia Latina Database\r
+      Carl Fleischhauer and Ricky Erway, American Memory\r
+         Discussion\r
+      Dorothy Twohig, The Papers of George Washington\r
+         Discussion\r
+      Maria L. Lebron, The Online Journal of Current Clinical Trials\r
+         Discussion\r
+      Lynne K. Personius, Cornell mathematics books\r
+         Discussion\r
+\r
+   Session III.  Distribution, Networks, and Networking:  \r
+                 Options for Dissemination\r
+      Robert G. Zich (Moderator)\r
+      Clifford A. Lynch\r
+         Discussion\r
+      Howard Besser\r
+         Discussion\r
+      Ronald L. Larsen\r
+      Edwin B. Brownrigg\r
+         Discussion\r
+\r
+   Session IV.  Image Capture, Text Capture, Overview of Text and\r
+                Image Storage Formats\r
+         William L. Hooton (Moderator)\r
+      A) Principal Methods for Image Capture of Text:  \r
+            direct scanning, use of microform\r
+         Anne R. Kenney\r
+         Pamela Q.J. Andre\r
+         Judith A. Zidar\r
+         Donald J. Waters\r
+            Discussion\r
+      B) Special Problems:  bound volumes, conservation,\r
+                            reproducing printed halftones\r
+         George Thoma\r
+         Carl Fleischhauer\r
+            Discussion\r
+      C) Image Standards and Implications for Preservation\r
+         Jean Baronas\r
+         Patricia Battin\r
+            Discussion\r
+      D) Text Conversion:  OCR vs. rekeying, standards of accuracy\r
+                           and use of imperfect texts, service bureaus\r
+         Michael Lesk\r
+         Ricky Erway\r
+         Judith A. Zidar\r
+            Discussion\r
+\r
+   Session V.  Approaches to Preparing Electronic Texts\r
+      Susan Hockey (Moderator)\r
+      Stuart Weibel\r
+         Discussion\r
+      C.M. Sperberg-McQueen\r
+         Discussion\r
+      Eric M. Calaluca\r
+         Discussion\r
+\r
+   Session VI.  Copyright Issues\r
+      Marybeth Peters\r
+\r
+   Session VII.  Conclusion\r
+      Prosser Gifford (Moderator)\r
+      General discussion\r
+\r
+Appendix I:  Program\r
+\r
+Appendix II:  Abstracts\r
+\r
+Appendix III:  Directory of Participants\r
+\r
+\r
+               ***   ***   ***   ******   ***   ***   ***\r
+\r
+\r
+                            Acknowledgements\r
+\r
+I would like to thank Carl Fleischhauer and Prosser Gifford for the\r
+opportunity to learn about areas of human activity unknown to me a scant\r
+ten months ago, and the David and Lucile Packard Foundation for\r
+supporting that opportunity.  The help given by others is acknowledged on\r
+a separate page.\r
+\r
+                                                          19 October 1992\r
+\r
+\r
+               ***   ***   ***   ******   ***   ***   ***\r
+\r
+\r
+                              INTRODUCTION\r
+\r
+The Workshop on Electronic Texts (1) drew together representatives of\r
+various projects and interest groups to compare ideas, beliefs,\r
+experiences, and, in particular, methods of placing and presenting\r
+historical textual materials in computerized form.  Most attendees gained\r
+much in insight and outlook from the event.  But the assembly did not\r
+form a new nation, or, to put it another way, the diversity of projects\r
+and interests was too great to draw the representatives into a cohesive,\r
+action-oriented body.(2)\r
+\r
+Everyone attending the Workshop shared an interest in preserving and\r
+providing access to historical texts.  But within this broad field the\r
+attendees represented a variety of formal, informal, figurative, and\r
+literal groups, with many individuals belonging to more than one.  These\r
+groups may be defined roughly according to the following topics or\r
+activities:\r
+\r
+* Imaging\r
+* Searchable coded texts\r
+* National and international computer networks\r
+* CD-ROM production and dissemination\r
+* Methods and technology for converting older paper materials into\r
+electronic form\r
+* Study of the use of digital materials by scholars and others\r
+\r
+This summary is arranged thematically and does not follow the actual\r
+sequence of presentations.\r
+\r
+NOTES:\r
+     (1)  In this document, the phrase electronic text is used to mean\r
+     any computerized reproduction or version of a document, book,\r
+     article, or manuscript (including images), and not merely a machine-\r
+     readable or machine-searchable text.\r
+\r
+     (2)  The Workshop was held at the Library of Congress on 9-10 June\r
+     1992, with funding from the David and Lucile Packard Foundation. \r
+     The document that follows represents a summary of the presentations\r
+     made at the Workshop and was compiled by James DALY.  This\r
+     introduction was written by DALY and Carl FLEISCHHAUER.\r
+\r
+\r
+PRESERVATION AND IMAGING\r
+\r
+Preservation, as that term is used by archivists,(3) was most explicitly\r
+discussed in the context of imaging.  Anne KENNEY and Lynne PERSONIUS\r
+explained how the concept of a faithful copy and the user-friendliness of\r
+the traditional book have guided their project at Cornell University.(4) \r
+Although interested in computerized dissemination, participants in the\r
+Cornell project are creating digital image sets of older books in the\r
+public domain as a source for a fresh paper facsimile or, in a future\r
+phase, microfilm.  The books returned to the library shelves are\r
+high-quality and useful replacements on acid-free paper that should last\r
+a long time.  To date, the Cornell project has placed little or no\r
+emphasis on creating searchable texts; one would not be surprised to find\r
+that the project participants view such texts as new editions, and thus\r
+not as faithful reproductions. \r
+\r
+In her talk on preservation, Patricia BATTIN struck an ecumenical and\r
+flexible note as she endorsed the creation and dissemination of a variety\r
+of types of digital copies.  Do not be too narrow in defining what counts\r
+as a preservation element, BATTIN counseled; for the present, at least,\r
+digital copies made with preservation in mind cannot be as narrowly\r
+standardized as, say, microfilm copies with the same objective.  Setting\r
+standards precipitously can inhibit creativity, but delay can result in\r
+chaos, she advised.\r
+\r
+In part, BATTIN's position reflected the unsettled nature of image-format\r
+standards, and attendees could hear echoes of this unsettledness in the\r
+comments of various speakers.  For example, Jean BARONAS reviewed the\r
+status of several formal standards moving through committees of experts;\r
+and Clifford LYNCH encouraged the use of a new guideline for transmitting\r
+document images on Internet.  Testimony from participants in the National\r
+Agricultural Library's (NAL) Text Digitization Program and LC's American\r
+Memory project highlighted some of the challenges to the actual creation\r
+or interchange of images, including difficulties in converting\r
+preservation microfilm to digital form.  Donald WATERS reported on the\r
+progress of a master plan for a project at Yale University to convert\r
+books on microfilm to digital image sets, Project Open Book (POB).\r
+\r
+The Workshop offered rather less of an imaging practicum than planned,\r
+but "how-to" hints emerge at various points, for example, throughout\r
+KENNEY's presentation and in the discussion of arcana such as\r
+thresholding and dithering offered by George THOMA and FLEISCHHAUER.\r
+\r
+NOTES:\r
+     (3)  Although there is a sense in which any reproductions of\r
+     historical materials preserve the human record, specialists in the\r
+     field have developed particular guidelines for the creation of\r
+     acceptable preservation copies.\r
+\r
+     (4)  Titles and affiliations of presenters are given at the\r
+     beginning of their respective talks and in the Directory of\r
+     Participants (Appendix III).\r
+\r
+\r
+THE MACHINE-READABLE TEXT:  MARKUP AND USE\r
+\r
+The sections of the Workshop that dealt with machine-readable text tended\r
+to be more concerned with access and use than with preservation, at least\r
+in the narrow technical sense.  Michael SPERBERG-McQUEEN made a forceful\r
+presentation on the Text Encoding Initiative's (TEI) implementation of\r
+the Standard Generalized Markup Language (SGML).  His ideas were echoed\r
+by Susan HOCKEY, Elli MYLONAS, and Stuart WEIBEL.  While the\r
+presentations made by the TEI advocates contained no practicum, their\r
+discussion focused on the value of the finished product, what the\r
+European Community calls reusability, but what may also be termed\r
+durability.  They argued that marking up--that is, coding--a text in a\r
+well-conceived way will permit it to be moved from one computer\r
+environment to another, as well as to be used by various users.  Two\r
+kinds of markup were distinguished:  1) procedural markup, which\r
+describes the features of a text (e.g., dots on a page), and 2)\r
+descriptive markup, which describes the structure or elements of a\r
+document (e.g., chapters, paragraphs, and front matter).\r
+\r
+The TEI proponents emphasized the importance of texts to scholarship. \r
+They explained how heavily coded (and thus analyzed and annotated) texts\r
+can underlie research, play a role in scholarly communication, and\r
+facilitate classroom teaching.  SPERBERG-McQUEEN reminded listeners that\r
+a written or printed item (e.g., a particular edition of a book) is\r
+merely a representation of the abstraction we call a text.  To concern\r
+ourselves with faithfully reproducing a printed instance of the text,\r
+SPERBERG-McQUEEN argued, is to concern ourselves with the representation\r
+of a representation ("images as simulacra for the text").  The TEI proponents'\r
+interest in images tends to focus on corollary materials for use in teaching,\r
+for example, photographs of the Acropolis to accompany a Greek text.\r
+\r
+By the end of the Workshop, SPERBERG-McQUEEN confessed to having been\r
+converted to a limited extent to the view that electronic images\r
+constitute a promising alternative to microfilming; indeed, an\r
+alternative probably superior to microfilming.  But he was not convinced\r
+that electronic images constitute a serious attempt to represent text in\r
+electronic form.  HOCKEY and MYLONAS also conceded that their experience\r
+at the Pierce Symposium the previous week at Georgetown University and\r
+the present conference at the Library of Congress had compelled them to\r
+reevaluate their perspective on the usefulness of text as images. \r
+Attendees could see that the text and image advocates were in\r
+constructive tension, so to say.\r
+\r
+Three nonTEI presentations described approaches to preparing\r
+machine-readable text that are less rigorous and thus less expensive.  In\r
+the case of the Papers of George Washington, Dorothy TWOHIG explained\r
+that the digital version will provide a not-quite-perfect rendering of\r
+the transcribed text--some 135,000 documents, available for research\r
+during the decades while the perfect or print version is completed. \r
+Members of the American Memory team and the staff of NAL's Text\r
+Digitization Program (see below) also outlined a middle ground concerning\r
+searchable texts.  In the case of American Memory, contractors produce\r
+texts with about 99-percent accuracy that serve as "browse" or\r
+"reference" versions of written or printed originals.  End users who need\r
+faithful copies or perfect renditions must refer to accompanying sets of\r
+digital facsimile images or consult copies of the originals in a nearby\r
+library or archive.  American Memory staff argued that the high cost of\r
+producing 100-percent accurate copies would prevent LC from offering\r
+access to large parts of its collections.\r
+\r
+\r
+THE MACHINE-READABLE TEXT:  METHODS OF CONVERSION\r
+\r
+Although the Workshop did not include a systematic examination of the\r
+methods for converting texts from paper (or from facsimile images) into\r
+machine-readable form, nevertheless, various speakers touched upon this\r
+matter.  For example, WEIBEL reported that OCLC has experimented with a\r
+merging of multiple optical character recognition systems that will\r
+reduce errors from an unacceptable rate of 5 characters out of every\r
+l,000 to an unacceptable rate of 2 characters out of every l,000.\r
+\r
+Pamela ANDRE presented an overview of NAL's Text Digitization Program and\r
+Judith ZIDAR discussed the technical details.  ZIDAR explained how NAL\r
+purchased hardware and software capable of performing optical character\r
+recognition (OCR) and text conversion and used its own staff to convert\r
+texts.  The process, ZIDAR said, required extensive editing and project\r
+staff found themselves considering alternatives, including rekeying\r
+and/or creating abstracts or summaries of texts.  NAL reckoned costs at\r
+$7 per page.  By way of contrast, Ricky ERWAY explained that American\r
+Memory had decided from the start to contract out conversion to external\r
+service bureaus.  The criteria used to select these contractors were cost\r
+and quality of results, as opposed to methods of conversion.  ERWAY noted\r
+that historical documents or books often do not lend themselves to OCR. \r
+Bound materials represent a special problem.  In her experience, quality\r
+control--inspecting incoming materials, counting errors in samples--posed\r
+the most time-consuming aspect of contracting out conversion.  ERWAY\r
+reckoned American Memory's costs at $4 per page, but cautioned that fewer\r
+cost-elements had been included than in NAL's figure.\r
+\r
+\r
+OPTIONS FOR DISSEMINATION\r
+\r
+The topic of dissemination proper emerged at various points during the\r
+Workshop.  At the session devoted to national and international computer\r
+networks, LYNCH, Howard BESSER, Ronald LARSEN, and Edwin BROWNRIGG\r
+highlighted the virtues of Internet today and of the network that will\r
+evolve from Internet.  Listeners could discern in these narratives a\r
+vision of an information democracy in which millions of citizens freely\r
+find and use what they need.  LYNCH noted that a lack of standards\r
+inhibits disseminating multimedia on the network, a topic also discussed\r
+by BESSER.  LARSEN addressed the issues of network scalability and\r
+modularity and commented upon the difficulty of anticipating the effects\r
+of growth in orders of magnitude.  BROWNRIGG talked about the ability of\r
+packet radio to provide certain links in a network without the need for\r
+wiring.  However, the presenters also called attention to the\r
+shortcomings and incongruities of present-day computer networks.  For\r
+example:  1) Network use is growing dramatically, but much network\r
+traffic consists of personal communication (E-mail).  2) Large bodies of\r
+information are available, but a user's ability to search across their\r
+entirety is limited.  3) There are significant resources for science and\r
+technology, but few network sources provide content in the humanities. \r
+4) Machine-readable texts are commonplace, but the capability of the\r
+system to deal with images (let alone other media formats) lags behind. \r
+A glimpse of a multimedia future for networks, however, was provided by\r
+Maria LEBRON in her overview of the Online Journal of Current Clinical\r
+Trials (OJCCT), and the process of scholarly publishing on-line.   \r
+\r
+The contrasting form of the CD-ROM disk was never systematically\r
+analyzed, but attendees could glean an impression from several of the\r
+show-and-tell presentations.  The Perseus and American Memory examples\r
+demonstrated recently published disks, while the descriptions of the\r
+IBYCUS version of the Papers of George Washington and Chadwyck-Healey's\r
+Patrologia Latina Database (PLD) told of disks to come.  According to\r
+Eric CALALUCA, PLD's principal focus has been on converting Jacques-Paul\r
+Migne's definitive collection of Latin texts to machine-readable form. \r
+Although everyone could share the network advocates' enthusiasm for an\r
+on-line future, the possibility of rolling up one's sleeves for a session\r
+with a CD-ROM containing both textual materials and a powerful retrieval\r
+engine made the disk seem an appealing vessel indeed.  The overall\r
+discussion suggested that the transition from CD-ROM to on-line networked\r
+access may prove far slower and more difficult than has been anticipated.\r
+\r
+\r
+WHO ARE THE USERS AND WHAT DO THEY DO?\r
+\r
+Although concerned with the technicalities of production, the Workshop\r
+never lost sight of the purposes and uses of electronic versions of\r
+textual materials.  As noted above, those interested in imaging discussed\r
+the problematical matter of digital preservation, while the TEI proponents\r
+described how machine-readable texts can be used in research.  This latter\r
+topic received thorough treatment in the paper read by Avra MICHELSON.\r
+She placed the phenomenon of electronic texts within the context of\r
+broader trends in information technology and scholarly communication.\r
+\r
+Among other things, MICHELSON described on-line conferences that\r
+represent a vigorous and important intellectual forum for certain\r
+disciplines.  Internet now carries more than 700 conferences, with about\r
+80 percent of these devoted to topics in the social sciences and the\r
+humanities.  Other scholars use on-line networks for "distance learning." \r
+Meanwhile, there has been a tremendous growth in end-user computing;\r
+professors today are less likely than their predecessors to ask the\r
+campus computer center to process their data.  Electronic texts are one\r
+key to these sophisticated applications, MICHELSON reported, and more and\r
+more scholars in the humanities now work in an on-line environment. \r
+Toward the end of the Workshop, Michael LESK presented a corollary to\r
+MICHELSON's talk, reporting the results of an experiment that compared\r
+the work of one group of chemistry students using traditional printed\r
+texts and two groups using electronic sources.  The experiment\r
+demonstrated that in the event one does not know what to read, one needs\r
+the electronic systems; the electronic systems hold no advantage at the\r
+moment if one knows what to read, but neither do they impose a penalty.\r
+\r
+DALY provided an anecdotal account of the revolutionizing impact of the\r
+new technology on his previous methods of research in the field of classics.\r
+His account, by extrapolation, served to illustrate in part the arguments\r
+made by MICHELSON concerning the positive effects of the sudden and radical\r
+transformation being wrought in the ways scholars work.\r
+\r
+Susan VECCIA and Joanne FREEMAN delineated the use of electronic\r
+materials outside the university.  The most interesting aspect of their\r
+use, FREEMAN said, could be seen as a paradox:  teachers in elementary\r
+and secondary schools requested access to primary source materials but,\r
+at the same time, found that "primariness" itself made these materials\r
+difficult for their students to use.\r
+\r
+\r
+OTHER TOPICS\r
+\r
+Marybeth PETERS reviewed copyright law in the United States and offered\r
+advice during a lively discussion of this subject.  But uncertainty\r
+remains concerning the price of copyright in a digital medium, because a\r
+solution remains to be worked out concerning management and synthesis of\r
+copyrighted and out-of-copyright pieces of a database.\r
+\r
+As moderator of the final session of the Workshop, Prosser GIFFORD directed\r
+discussion to future courses of action and the potential role of LC in\r
+advancing them.  Among the recommendations that emerged were the following:\r
+\r
+     * Workshop participants should 1) begin to think about working\r
+     with image material, but structure and digitize it in such a\r
+     way that at a later stage it can be interpreted into text, and\r
+     2) find a common way to build text and images together so that\r
+     they can be used jointly at some stage in the future, with\r
+     appropriate network support, because that is how users will want\r
+     to access these materials.  The Library might encourage attempts\r
+     to bring together people who are working on texts and images.\r
+\r
+     * A network version of American Memory should be developed or\r
+     consideration should be given to making the data in it\r
+     available to people interested in doing network multimedia. \r
+     Given the current dearth of digital data that is appealing and\r
+     unencumbered by extremely complex rights problems, developing a\r
+     network version of American Memory could do much to help make\r
+     network multimedia a reality.\r
+\r
+     * Concerning the thorny issue of electronic deposit, LC should\r
+     initiate a catalytic process in terms of distributed\r
+     responsibility, that is, bring together the distributed\r
+     organizations and set up a study group to look at all the\r
+     issues related to electronic deposit and see where we as a\r
+     nation should move.  For example, LC might attempt to persuade\r
+     one major library in each state to deal with its state\r
+     equivalent publisher, which might produce a cooperative project\r
+     that would be equitably distributed around the country, and one\r
+     in which LC would be dealing with a minimal number of publishers\r
+     and minimal copyright problems.  LC must also deal with the\r
+     concept of on-line publishing, determining, among other things,\r
+     how serials such as OJCCT might be deposited for copyright.\r
+\r
+     * Since a number of projects are planning to carry out\r
+     preservation by creating digital images that will end up in\r
+     on-line or near-line storage at some institution, LC might play\r
+     a helpful role, at least in the near term, by accelerating how\r
+     to catalog that information into the Research Library Information\r
+     Network (RLIN) and then into OCLC, so that it would be accessible.\r
+     This would reduce the possibility of multiple institutions digitizing\r
+     the same work. \r
+\r
+\r
+CONCLUSION\r
+\r
+The Workshop was valuable because it brought together partisans from\r
+various groups and provided an occasion to compare goals and methods. \r
+The more committed partisans frequently communicate with others in their\r
+groups, but less often across group boundaries.  The Workshop was also\r
+valuable to attendees--including those involved with American Memory--who\r
+came less committed to particular approaches or concepts.  These\r
+attendees learned a great deal, and plan to select and employ elements of\r
+imaging, text-coding, and networked distribution that suit their\r
+respective projects and purposes.\r
+\r
+Still, reality rears its ugly head:  no breakthrough has been achieved. \r
+On the imaging side, one confronts a proliferation of competing\r
+data-interchange standards and a lack of consensus on the role of digital\r
+facsimiles in preservation.  In the realm of machine-readable texts, one\r
+encounters a reasonably mature standard but methodological difficulties\r
+and high costs.  These latter problems, of course, represent a special\r
+impediment to the desire, as it is sometimes expressed in the popular\r
+press, "to put the [contents of the] Library of Congress on line."  In\r
+the words of one participant, there was "no solution to the economic\r
+problems--the projects that are out there are surviving, but it is going\r
+to be a lot of work to transform the information industry, and so far the\r
+investment to do that is not forthcoming" (LESK, per litteras).\r
+\r
+\r
+               ***   ***   ***   ******   ***   ***   ***\r
+\r
+\r
+                               PROCEEDINGS\r
+\r
+\r
+WELCOME\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+GIFFORD * Origin of Workshop in current Librarian's desire to make LC's\r
+collections more widely available * Desiderata arising from the prospect\r
+of greater interconnectedness *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+After welcoming participants on behalf of the Library of Congress,\r
+American Memory (AM), and the National Demonstration Lab, Prosser\r
+GIFFORD, director for scholarly programs, Library of Congress, located\r
+the origin of the Workshop on Electronic Texts in a conversation he had\r
+had considerably more than a year ago with Carl FLEISCHHAUER concerning\r
+some of the issues faced by AM.  On the assumption that numerous other\r
+people were asking the same questions, the decision was made to bring\r
+together as many of these people as possible to ask the same questions\r
+together.  In a deeper sense, GIFFORD said, the origin of the Workshop\r
+lay in the desire of the current Librarian of Congress, James H. \r
+Billington, to make the collections of the Library, especially those\r
+offering unique or unusual testimony on aspects of the American\r
+experience, available to a much wider circle of users than those few\r
+people who can come to Washington to use them.  This meant that the\r
+emphasis of AM, from the outset, has been on archival collections of the\r
+basic material, and on making these collections themselves available,\r
+rather than selected or heavily edited products.\r
+\r
+From AM's emphasis followed the questions with which the Workshop began: \r
+who will use these materials, and in what form will they wish to use\r
+them.  But an even larger issue deserving mention, in GIFFORD's view, was\r
+the phenomenal growth in Internet connectivity.  He expressed the hope\r
+that the prospect of greater interconnectedness than ever before would\r
+lead to:  1) much more cooperative and mutually supportive endeavors; 2)\r
+development of systems of shared and distributed responsibilities to\r
+avoid duplication and to ensure accuracy and preservation of unique\r
+materials; and 3) agreement on the necessary standards and development of\r
+the appropriate directories and indices to make navigation\r
+straightforward among the varied resources that are, and increasingly\r
+will be, available.  In this connection, GIFFORD requested that\r
+participants reflect from the outset upon the sorts of outcomes they\r
+thought the Workshop might have.  Did those present constitute a group\r
+with sufficient common interests to propose a next step or next steps,\r
+and if so, what might those be?  They would return to these questions the\r
+following afternoon.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+FLEISCHHAUER * Core of Workshop concerns preparation and production of\r
+materials * Special challenge in conversion of textual materials *\r
+Quality versus quantity * Do the several groups represented share common\r
+interests? *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Carl FLEISCHHAUER, coordinator, American Memory, Library of Congress,\r
+emphasized that he would attempt to represent the people who perform some\r
+of the work of converting or preparing  materials and that the core of\r
+the Workshop had to do with preparation and production.  FLEISCHHAUER\r
+then drew a distinction between the long term, when many things would be\r
+available and connected in the ways that GIFFORD described, and the short\r
+term, in which AM not only has wrestled with the issue of what is the\r
+best course to pursue but also has faced a variety of technical\r
+challenges.\r
+\r
+FLEISCHHAUER remarked AM's endeavors to deal with a wide range of library\r
+formats, such as motion picture collections, sound-recording collections,\r
+and pictorial collections of various sorts, especially collections of\r
+photographs.  In the course of these efforts, AM kept coming back to\r
+textual materials--manuscripts or rare printed matter, bound materials,\r
+etc.  Text posed the greatest conversion challenge of all.  Thus, the\r
+genesis of the Workshop, which reflects the problems faced by AM.  These\r
+problems include physical problems.  For example, those in the library\r
+and archive business deal with collections made up of fragile and rare\r
+manuscript items, bound materials, especially the notoriously brittle\r
+bound materials of the late nineteenth century.  These are precious\r
+cultural artifacts, however, as well as interesting sources of\r
+information, and LC desires to retain and conserve them.  AM needs to\r
+handle things without damaging them.  Guillotining a book to run it\r
+through a sheet feeder must be avoided at all costs.\r
+\r
+Beyond physical problems, issues pertaining to quality arose.  For\r
+example, the desire to provide users with a searchable text is affected\r
+by the question of acceptable level of accuracy.  One hundred percent\r
+accuracy is tremendously expensive.  On the other hand, the output of\r
+optical character recognition (OCR) can be tremendously inaccurate. \r
+Although AM has attempted to find a middle ground, uncertainty persists\r
+as to whether or not it has discovered the right solution.\r
+\r
+Questions of quality arose concerning images as well.  FLEISCHHAUER\r
+contrasted the extremely high level of quality of the digital images in\r
+the Cornell Xerox Project with AM's efforts to provide a browse-quality\r
+or access-quality image, as opposed to an archival or preservation image. \r
+FLEISCHHAUER therefore welcomed the opportunity to compare notes.\r
+\r
+FLEISCHHAUER observed in passing that conversations he had had about\r
+networks have begun to signal that for various forms of media a\r
+determination may be made that there is a browse-quality item, or a\r
+distribution-and-access-quality item that may coexist in some systems\r
+with a higher quality archival item that would be inconvenient to send\r
+through the network because of its size.  FLEISCHHAUER referred, of\r
+course, to images more than to searchable text.\r
+\r
+As AM considered those questions, several conceptual issues arose:  ought\r
+AM occasionally to reproduce materials entirely through an image set, at\r
+other times, entirely through a text set, and in some cases, a mix? \r
+There probably would be times when the historical authenticity of an\r
+artifact would require that its image be used.  An image might be\r
+desirable as a recourse for users if one could not provide 100-percent\r
+accurate text.  Again, AM wondered, as a practical matter, if a\r
+distinction could be drawn between rare printed matter that might exist\r
+in multiple collections--that is, in ten or fifteen libraries.  In such\r
+cases, the need for perfect reproduction would be less than for unique\r
+items.  Implicit in his remarks, FLEISCHHAUER conceded, was the admission\r
+that AM has been tilting strongly towards quantity and drawing back a\r
+little from perfect quality.  That is, it seemed to AM that society would\r
+be better served if more things were distributed by LC--even if they were\r
+not quite perfect--than if fewer things, perfectly represented, were\r
+distributed.  This was stated as a proposition to be tested, with\r
+responses to be gathered from users.\r
+\r
+In thinking about issues related to reproduction of materials and seeing\r
+other people engaged in parallel activities, AM deemed it useful to\r
+convene a conference.  Hence, the Workshop.  FLEISCHHAUER thereupon\r
+surveyed the several groups represented:  1) the world of images (image\r
+users and image makers); 2) the world of text and scholarship and, within\r
+this group, those concerned with language--FLEISCHHAUER confessed to finding\r
+delightful irony in the fact that some of the most advanced thinkers on\r
+computerized texts are those dealing with ancient Greek and Roman materials;\r
+3) the network world; and 4) the general world of library science, which\r
+includes people interested in preservation and cataloging.\r
+\r
+FLEISCHHAUER concluded his remarks with special thanks to the David and\r
+Lucile Packard Foundation for its support of the meeting, the American\r
+Memory group, the Office for Scholarly Programs, the National\r
+Demonstration Lab, and the Office of Special Events.  He expressed the\r
+hope that David Woodley Packard might be able to attend, noting that\r
+Packard's work and the work of the foundation had sponsored a number of\r
+projects in the text area.\r
+\r
+                                 ******\r
+\r
+SESSION I.  CONTENT IN A NEW FORM:   WHO WILL USE IT AND WHAT WILL THEY DO?\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DALY * Acknowledgements * A new Latin authors disk *  Effects of the new\r
+technology on previous methods of research *       \r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Serving as moderator, James DALY acknowledged the generosity of all the\r
+presenters for giving of their time, counsel, and patience in planning\r
+the Workshop, as well as of members of the American Memory project and\r
+other Library of Congress staff, and the David and Lucile Packard\r
+Foundation and its executive director, Colburn S. Wilbur.\r
+\r
+DALY then recounted his visit in March to the Center for Electronic Texts\r
+in the Humanities (CETH) and the Department of Classics at Rutgers\r
+University, where an old friend, Lowell Edmunds, introduced him to the\r
+department's IBYCUS scholarly personal computer, and, in particular, the\r
+new Latin CD-ROM, containing, among other things, almost all classical\r
+Latin literary texts through A.D. 200.  Packard Humanities Institute\r
+(PHI), Los Altos, California, released this disk late in 1991, with a\r
+nominal triennial licensing fee.\r
+\r
+Playing with the disk for an hour or so at Rutgers brought home to DALY\r
+at once the revolutionizing impact of the new technology on his previous\r
+methods of research.  Had this disk been available two or three years\r
+earlier, DALY contended, when he was engaged in preparing a commentary on\r
+Book 10 of Virgil's Aeneid for Cambridge University Press, he would not\r
+have required a forty-eight-square-foot table on which to spread the\r
+numerous, most frequently consulted items, including some ten or twelve\r
+concordances to key Latin authors, an almost equal number of lexica to\r
+authors who lacked concordances, and where either lexica or concordances\r
+were lacking, numerous editions of authors antedating and postdating Virgil.\r
+\r
+Nor, when checking each of the average six to seven words contained in\r
+the Virgilian hexameter for its usage elsewhere in Virgil's works or\r
+other Latin authors, would DALY have had to maintain the laborious\r
+mechanical process of flipping through these concordances, lexica, and\r
+editions each time.  Nor would he have had to frequent as often the\r
+Milton S. Eisenhower Library at the Johns Hopkins University to consult\r
+the Thesaurus Linguae Latinae.  Instead of devoting countless hours, or\r
+the bulk of his research time, to gathering data concerning Virgil's use\r
+of words, DALY--now freed by PHI's Latin authors disk from the\r
+tyrannical, yet in some ways paradoxically happy scholarly drudgery--\r
+would have been able to devote that same bulk of time to analyzing and\r
+interpreting Virgilian verbal usage.\r
+\r
+Citing Theodore Brunner, Gregory Crane, Elli MYLONAS, and Avra MICHELSON,\r
+DALY argued that this reversal in his style of work, made possible by the\r
+new technology, would perhaps have resulted in better, more productive\r
+research.  Indeed, even in the course of his browsing the Latin authors\r
+disk at Rutgers, its powerful search, retrieval, and highlighting\r
+capabilities suggested to him several new avenues of research into\r
+Virgil's use of sound effects.  This anecdotal account, DALY maintained,\r
+may serve to illustrate in part the sudden and radical transformation\r
+being wrought in the ways scholars work.\r
+\r
+                                 ******\r
+\r
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+MICHELSON * Elements related to scholarship and technology * Electronic\r
+texts within the context of broader trends within information technology\r
+and scholarly communication * Evaluation of the prospects for the use of\r
+electronic texts * Relationship of electronic texts to processes of\r
+scholarly communication in humanities research * New exchange formats\r
+created by scholars * Projects initiated to increase scholarly access to\r
+converted text * Trend toward making electronic resources available\r
+through research and education networks * Changes taking place in\r
+scholarly communication among humanities scholars * Network-mediated\r
+scholarship transforming traditional scholarly practices * Key\r
+information technology trends affecting the conduct of scholarly\r
+communication over the next decade * The trend toward end-user computing\r
+* The trend toward greater connectivity * Effects of these trends * Key\r
+transformations taking place * Summary of principal arguments *\r
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Avra MICHELSON, Archival Research and Evaluation Staff, National Archives\r
+and Records Administration (NARA), argued that establishing who will use\r
+electronic texts and what they will use them for involves a consideration\r
+of both information technology and scholarship trends.  This\r
+consideration includes several elements related to scholarship and\r
+technology:  1) the key trends in information technology that are most\r
+relevant to scholarship; 2) the key trends in the use of currently\r
+available technology by scholars in the nonscientific community; and 3)\r
+the relationship between these two very distinct but interrelated trends. \r
+The investment in understanding this relationship being made by\r
+information providers, technologists, and public policy developers, as\r
+well as by scholars themselves, seems to be pervasive and growing,\r
+MICHELSON contended.  She drew on collaborative work with Jeff Rothenberg\r
+on the scholarly use of technology.\r
+\r
+MICHELSON sought to place the phenomenon of electronic texts within the\r
+context of broader trends within information technology and scholarly\r
+communication.  She argued that electronic texts are of most use to\r
+researchers to the extent that the researchers' working context (i.e.,\r
+their relevant bibliographic sources, collegial feedback, analytic tools,\r
+notes, drafts, etc.), along with their field's primary and secondary\r
+sources, also is accessible in electronic form and can be integrated in\r
+ways that are unique to the on-line environment.\r
+\r
+Evaluation of the prospects for the use of electronic texts includes two\r
+elements:  1) an examination of the ways in which researchers currently\r
+are using electronic texts along with other electronic resources, and 2)\r
+an analysis of key information technology trends that are affecting the\r
+long-term conduct of scholarly communication.  MICHELSON limited her\r
+discussion of the use of electronic texts to the practices of humanists\r
+and noted that the scientific community was outside the panel's overview.\r
+\r
+MICHELSON examined the nature of the current relationship of electronic\r
+texts in particular, and electronic resources in general, to what she\r
+maintained were, essentially, five processes of scholarly communication\r
+in humanities research.  Researchers 1) identify sources, 2) communicate\r
+with their colleagues, 3) interpret and analyze data, 4) disseminate\r
+their research findings, and 5) prepare curricula to instruct the next\r
+generation of scholars and students.  This examination would produce a\r
+clearer understanding of the synergy among these five processes that\r
+fuels the tendency of the use of electronic resources for one process to\r
+stimulate its use for other processes of scholarly communication.\r
+\r
+For the first process of scholarly communication, the identification of\r
+sources, MICHELSON remarked the opportunity scholars now enjoy to\r
+supplement traditional word-of-mouth searches for sources among their\r
+colleagues with new forms of electronic searching.  So, for example,\r
+instead of having to visit the library, researchers are able to explore\r
+descriptions of holdings in their offices.  Furthermore, if their own\r
+institutions' holdings prove insufficient, scholars can access more than\r
+200 major American library catalogues over Internet, including the\r
+universities of California, Michigan, Pennsylvania, and Wisconsin. \r
+Direct access to the bibliographic databases offers intellectual\r
+empowerment to scholars by presenting a comprehensive means of browsing\r
+through libraries from their homes and offices at their convenience.\r
+\r
+The second process of communication involves communication among\r
+scholars.  Beyond the most common methods of communication, scholars are\r
+using E-mail and a variety of new electronic communications formats\r
+derived from it for further academic interchange.  E-mail exchanges are\r
+growing at an astonishing rate, reportedly 15 percent a month.  They\r
+currently constitute approximately half the traffic on research and\r
+education networks.  Moreover, the global spread of E-mail has been so\r
+rapid that it is now possible for American scholars to use it to\r
+communicate with colleagues in close to 140 other countries.\r
+\r
+Other new exchange formats created by scholars and operating on Internet\r
+include more than 700 conferences, with about 80 percent of these devoted\r
+to topics in the social sciences and humanities.  The rate of growth of\r
+these scholarly electronic conferences also is astonishing.  From l990 to\r
+l991, 200 new conferences were identified on Internet.  From October 1991\r
+to June 1992, an additional 150 conferences in the social sciences and\r
+humanities were added to this directory of listings.  Scholars have\r
+established conferences in virtually every field, within every different\r
+discipline.  For example, there are currently close to 600 active social\r
+science and humanities  conferences on topics such as art and\r
+architecture, ethnomusicology, folklore, Japanese culture, medical\r
+education, and gifted and talented education.  The appeal to scholars of\r
+communicating through these conferences is that, unlike any other medium,\r
+electronic conferences today provide a forum for global communication\r
+with peers at the front end of the research process.\r
+\r
+Interpretation and analysis of sources constitutes the third process of\r
+scholarly communication that MICHELSON discussed in terms of texts and\r
+textual resources.  The methods used to analyze sources fall somewhere on\r
+a continuum from quantitative analysis to qualitative analysis. \r
+Typically, evidence is culled and evaluated using methods drawn from both\r
+ends of this continuum.  At one end, quantitative analysis involves the\r
+use of mathematical processes such as a count of frequencies and\r
+distributions of occurrences or, on a higher level, regression analysis. \r
+At the other end of the continuum, qualitative analysis typically\r
+involves nonmathematical processes oriented toward language\r
+interpretation or the building of theory.  Aspects of this work involve\r
+the processing--either manual or computational--of large and sometimes\r
+massive amounts of textual sources, although the use of nontextual\r
+sources as evidence, such as photographs, sound recordings, film footage,\r
+and artifacts, is significant as well.\r
+\r
+Scholars have discovered that many of the methods of interpretation and\r
+analysis that are related to both quantitative and qualitative methods\r
+are processes that can be performed by computers.  For example, computers\r
+can count.  They can count brush strokes used in a Rembrandt painting or\r
+perform regression analysis for understanding cause and effect.  By means\r
+of advanced technologies, computers can recognize patterns, analyze text,\r
+and model concepts.  Furthermore, computers can complete these processes\r
+faster with more sources and with greater precision than scholars who\r
+must rely on manual interpretation of data.  But if scholars are to use\r
+computers for these processes, source materials must be in a form\r
+amenable to computer-assisted analysis.  For this reason many scholars,\r
+once they have identified the sources that are key to their research, are\r
+converting them to machine-readable form.  Thus, a representative example\r
+of the numerous textual conversion projects organized by scholars around\r
+the world in recent years to support computational text analysis is the\r
+TLG, the Thesaurus Linguae Graecae.  This project is devoted to\r
+converting the extant ancient texts of classical Greece.  (Editor's note: \r
+according to the TLG Newsletter of May l992, TLG was in use in thirty-two\r
+different countries.  This figure updates MICHELSON's previous count by one.)\r
+\r
+The scholars performing these conversions have been asked to recognize\r
+that the electronic sources they are converting for one use possess value\r
+for other research purposes as well.  As a result, during the past few\r
+years, humanities scholars have initiated a number of projects to\r
+increase scholarly access to converted text.  So, for example, the Text\r
+Encoding Initiative (TEI), about which more is said later in the program,\r
+was established as an effort by scholars to determine standard elements\r
+and methods for encoding machine-readable text for electronic exchange. \r
+In a second effort to facilitate the sharing of converted text, scholars\r
+have created a new institution, the Center for Electronic Texts in the\r
+Humanities (CETH).  The center estimates that there are 8,000 series of\r
+source texts in the humanities that have been converted to\r
+machine-readable form worldwide.  CETH is undertaking an international\r
+search for converted text in the humanities, compiling it into an\r
+electronic library, and preparing bibliographic descriptions of the\r
+sources for the Research Libraries Information Network's (RLIN)\r
+machine-readable data file.  The library profession has begun to initiate\r
+large conversion projects as well, such as American Memory.\r
+\r
+While scholars have been making converted text available to one another,\r
+typically on disk or on CD-ROM, the clear trend is toward making these\r
+resources available through research and education networks.  Thus, the\r
+American and French Research on the Treasury of the French Language\r
+(ARTFL) and the Dante Project are already available on Internet. \r
+MICHELSON summarized this section on interpretation and analysis by\r
+noting that:  1) increasing numbers of humanities scholars in the library\r
+community are recognizing the importance to the advancement of\r
+scholarship of retrospective conversion of source materials in the arts\r
+and humanities; and 2) there is a growing realization that making the\r
+sources available on research and education networks maximizes their\r
+usefulness for the analysis performed by humanities scholars.\r
+\r
+The fourth process of scholarly communication is dissemination of\r
+research findings, that is, publication.  Scholars are using existing\r
+research and education networks to engineer a new type of publication: \r
+scholarly-controlled journals that are electronically produced and\r
+disseminated.  Although such journals are still emerging as a\r
+communication format, their number has grown, from approximately twelve\r
+to thirty-six during the past year (July 1991 to June 1992).  Most of\r
+these electronic scholarly journals are devoted to topics in the\r
+humanities.  As with network conferences, scholarly enthusiasm for these\r
+electronic journals stems from the medium's unique ability to advance\r
+scholarship in a way that no other medium can do by supporting global\r
+feedback and interchange, practically in real time, early in the research\r
+process.  Beyond scholarly journals, MICHELSON remarked the delivery of\r
+commercial full-text products, such as articles in professional journals,\r
+newsletters, magazines, wire services, and reference sources.  These are\r
+being delivered via on-line local library catalogues, especially through\r
+CD-ROMs.  Furthermore, according to MICHELSON, there is general optimism\r
+that the copyright and fees issues impeding the delivery of full text on\r
+existing research and education networks soon will be resolved.\r
+\r
+The final process of scholarly communication is curriculum development\r
+and instruction, and this involves the use of computer information\r
+technologies in two areas.  The first is the development of\r
+computer-oriented instructional tools, which includes simulations,\r
+multimedia applications, and computer tools that are used to assist in\r
+the analysis of sources in the classroom, etc.  The Perseus Project, a\r
+database that provides a multimedia curriculum on classical Greek\r
+civilization, is a good example of the way in which entire curricula are\r
+being recast using information technologies.  It is anticipated that the\r
+current difficulty in exchanging electronically computer-based\r
+instructional software, which in turn makes it difficult for one scholar\r
+to build upon the work of others, will be resolved before too long. \r
+Stand-alone curricular applications that involve electronic text will be\r
+sharable through networks, reinforcing their significance as intellectual\r
+products as well as instructional tools.\r
+\r
+The second aspect of electronic learning involves the use of research and\r
+education networks for distance education programs.  Such programs\r
+interactively link teachers with students in geographically scattered\r
+locations and rely on the availability of electronic instructional\r
+resources.  Distance education programs are gaining wide appeal among\r
+state departments of education because of their demonstrated capacity to\r
+bring advanced specialized course work and an array of experts to many\r
+classrooms.  A recent report found that at least 32 states operated at\r
+least one statewide network for education in 1991, with networks under\r
+development in many of the remaining states.\r
+\r
+MICHELSON summarized this section by noting two striking changes taking\r
+place in scholarly communication among humanities scholars.  First is the\r
+extent to which electronic text in particular, and electronic resources\r
+in general, are being infused into each of the five processes described\r
+above.  As mentioned earlier, there is a certain synergy at work here. \r
+The use of electronic resources for one process tends to stimulate its\r
+use for other processes, because the chief course of movement is toward a\r
+comprehensive on-line working context for humanities scholars that\r
+includes on-line availability of key bibliographies, scholarly feedback,\r
+sources, analytical tools, and publications.  MICHELSON noted further\r
+that the movement toward a comprehensive on-line working context for\r
+humanities scholars is not new.  In fact, it has been underway for more\r
+than forty years in the humanities, since Father Roberto Busa began\r
+developing an electronic concordance of the works of Saint Thomas Aquinas\r
+in 1949.  What we are witnessing today, MICHELSON contended, is not the\r
+beginning of this on-line transition but, for at least some humanities\r
+scholars, the turning point in the transition from a print to an\r
+electronic working context.  Coinciding with the on-line transition, the\r
+second striking change is the extent to which research and education\r
+networks are becoming the new medium of scholarly communication.  The\r
+existing Internet and the pending National Education and Research Network\r
+(NREN) represent the new meeting ground where scholars are going for\r
+bibliographic information, scholarly dialogue and feedback, the most\r
+current publications in their field, and high-level educational\r
+offerings.  Traditional scholarly practices are undergoing tremendous\r
+transformations as a result of the emergence and growing prominence of\r
+what is called network-mediated scholarship.\r
+\r
+MICHELSON next turned to the second element of the framework she proposed\r
+at the outset of her talk for evaluating the prospects for electronic\r
+text, namely the key information technology trends affecting the conduct\r
+of scholarly communication over the next decade:  1) end-user computing\r
+and 2) connectivity.\r
+\r
+End-user computing means that the person touching the keyboard, or\r
+performing computations, is the same as the person who initiates or\r
+consumes the computation.  The emergence of personal computers, along\r
+with a host of other forces, such as ubiquitous computing, advances in\r
+interface design, and the on-line transition, is prompting the consumers\r
+of computation to do their own computing, and is thus rendering obsolete\r
+the traditional distinction between end users and ultimate users.\r
+\r
+The trend toward end-user computing is significant to consideration of\r
+the prospects for electronic texts because it means that researchers are\r
+becoming more adept at doing their own computations and, thus, more\r
+competent in the use of electronic media.  By avoiding programmer\r
+intermediaries, computation is becoming central to the researcher's\r
+thought process.  This direct involvement in computing is changing the\r
+researcher's perspective on the nature of research itself, that is, the\r
+kinds of questions that can be posed, the analytical methodologies that\r
+can be used, the types and amount of sources that are appropriate for\r
+analyses, and the form in which findings are presented.  The trend toward\r
+end-user computing means that, increasingly, electronic media and\r
+computation are being infused into all processes of humanities\r
+scholarship, inspiring remarkable transformations in scholarly\r
+communication.\r
+\r
+The trend toward greater connectivity suggests that researchers are using\r
+computation increasingly in network environments.  Connectivity is\r
+important to scholarship because it erases the distance that separates\r
+students from teachers and scholars from their colleagues, while allowing\r
+users to access remote databases, share information in many different\r
+media, connect to their working context wherever they are, and\r
+collaborate in all phases of research.\r
+\r
+The combination of the trend toward end-user computing and the trend\r
+toward connectivity suggests that the scholarly use of electronic\r
+resources, already evident among some researchers, will soon become an\r
+established feature of scholarship.  The effects of these trends, along\r
+with ongoing changes in scholarly practices, point to a future in which\r
+humanities researchers will use computation and electronic communication\r
+to help them formulate ideas, access sources, perform research,\r
+collaborate with colleagues, seek peer review, publish and disseminate\r
+results, and engage in many other professional and educational activities.\r
+\r
+In summary, MICHELSON emphasized four points:  1) A portion of humanities\r
+scholars already consider electronic texts the preferred format for\r
+analysis and dissemination.  2) Scholars are using these electronic\r
+texts, in conjunction with other electronic resources, in all the\r
+processes of scholarly communication.  3) The humanities scholars'\r
+working context is in the process of changing from print technology to\r
+electronic technology, in many ways mirroring transformations that have\r
+occurred or are occurring within the scientific community.  4) These\r
+changes are occurring in conjunction with the development of a new\r
+communication medium:  research and education networks that are\r
+characterized by their capacity to advance scholarship in a wholly unique\r
+way.\r
+\r
+MICHELSON also reiterated her three principal arguments:  l) Electronic\r
+texts are best understood in terms of the relationship to other\r
+electronic resources and the growing prominence of network-mediated\r
+scholarship.  2) The prospects for electronic texts lie in their capacity\r
+to be integrated into the on-line network of electronic resources that\r
+comprise the new working context for scholars.  3) Retrospective conversion\r
+of portions of the scholarly record should be a key strategy as information\r
+providers respond to changes in scholarly communication practices.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+VECCIA * AM's evaluation project and public users of electronic resources\r
+* AM and its design * Site selection and evaluating the Macintosh\r
+implementation of AM * Characteristics of the six public libraries\r
+selected * Characteristics of AM's users in these libraries * Principal\r
+ways AM is being used *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Susan VECCIA, team leader, and Joanne FREEMAN, associate coordinator,\r
+American Memory, Library of Congress, gave a joint presentation.  First,\r
+by way of introduction, VECCIA explained her and FREEMAN's roles in\r
+American Memory (AM).  Serving principally as an observer, VECCIA has\r
+assisted with the evaluation project of AM, placing AM collections in a\r
+variety of different sites around the country and helping to organize and\r
+implement that project.  FREEMAN has been an associate coordinator of AM\r
+and has been involved principally with the interpretative materials,\r
+preparing some of the electronic exhibits and printed historical\r
+information that accompanies AM and that is requested by users.  VECCIA\r
+and FREEMAN shared anecdotal observations concerning AM with public users\r
+of electronic resources.  Notwithstanding a fairly structured evaluation\r
+in progress, both VECCIA and FREEMAN chose not to report on specifics in\r
+terms of numbers, etc., because they felt it was too early in the\r
+evaluation project to do so.\r
+\r
+AM is an electronic archive of primary source materials from the Library\r
+of Congress, selected collections representing a variety of formats--\r
+photographs, graphic arts, recorded sound, motion pictures, broadsides,\r
+and soon, pamphlets and books.  In terms of the design of this system,\r
+the interpretative exhibits have been kept separate from the primary\r
+resources, with good reason.  Accompanying this collection are printed\r
+documentation and user guides, as well as guides that FREEMAN prepared for\r
+teachers so that they may begin using the content of the system at once.\r
+\r
+VECCIA described the evaluation project before talking about the public\r
+users of AM, limiting her remarks to public libraries, because FREEMAN\r
+would talk more specifically about schools from kindergarten to twelfth\r
+grade (K-12).   Having started in spring 1991, the evaluation currently\r
+involves testing of the Macintosh implementation of AM.  Since the\r
+primary goal of this evaluation is to determine the most appropriate\r
+audience or audiences for AM, very different sites were selected.  This\r
+makes evaluation difficult because of the varying degrees of technology\r
+literacy among the sites.  AM is situated in forty-four locations, of\r
+which six are public libraries and sixteen are schools.  Represented\r
+among the schools are elementary, junior high, and high schools.\r
+District offices also are involved in the evaluation, which will\r
+conclude in summer 1993.\r
+\r
+VECCIA focused the remainder of her talk on the six public libraries, one\r
+of which doubles as a state library.  They represent a range of\r
+geographic areas and a range of demographic characteristics.  For\r
+example, three are located in urban settings, two in rural settings, and\r
+one in a suburban setting.  A range of technical expertise is to be found\r
+among these facilities as well.  For example, one is an "Apple library of\r
+the future," while two others are rural one-room libraries--in one, AM\r
+sits at the front desk next to a tractor manual.\r
+\r
+All public libraries have been extremely enthusiastic, supportive, and\r
+appreciative of the work that AM has been doing.  VECCIA characterized\r
+various users:  Most users in public libraries describe themselves as\r
+general readers; of the students who use AM in the public libraries,\r
+those in fourth grade and above seem most interested.  Public libraries\r
+in rural sites tend to attract retired people, who have been highly\r
+receptive to AM.  Users tend to fall into two additional categories: \r
+people interested in the content and historical connotations of these\r
+primary resources, and those fascinated by the technology.  The format\r
+receiving the most comments has been motion pictures.  The adult users in\r
+public libraries are more comfortable with IBM computers, whereas young\r
+people seem comfortable with either IBM or Macintosh, although most of\r
+them seem to come from a Macintosh background.  This same tendency is\r
+found in the schools.\r
+\r
+What kinds of things do users do with AM?  In a public library there are\r
+two main goals or ways that AM is being used:  as an individual learning\r
+tool, and as a leisure activity.  Adult learning was one area that VECCIA\r
+would highlight as a possible application for a tool such as AM.  She\r
+described a patron of a rural public library who comes in every day on\r
+his lunch hour and literally reads AM, methodically going through the\r
+collection image by image.  At the end of his hour he makes an electronic\r
+bookmark, puts it in his pocket, and returns to work.  The next day he\r
+comes in and resumes where he left off.  Interestingly, this man had\r
+never been in the library before he used AM.  In another small, rural\r
+library, the coordinator reports that AM is a popular activity for some\r
+of the older, retired people in the community, who ordinarily would not\r
+use "those things,"--computers.  Another example of adult learning in\r
+public libraries is book groups, one of which, in particular, is using AM\r
+as part of its reading on industrialization, integration, and urbanization\r
+in the early 1900s.\r
+\r
+One library reports that a family is using AM to help educate their\r
+children.  In another instance, individuals from a local museum came in\r
+to use AM to prepare an exhibit on toys of the past.  These two examples\r
+emphasize the mission of the public library as a cultural institution,\r
+reaching out to people who do not have the same resources available to\r
+those who live in a metropolitan area or have access to a major library. \r
+One rural library reports that junior high school students in large\r
+numbers came in one afternoon to use AM for entertainment.  A number of\r
+public libraries reported great interest among postcard collectors in the\r
+Detroit collection, which was essentially a collection of images used on\r
+postcards around the turn of the century.  Train buffs are similarly\r
+interested because that was a time of great interest in railroading. \r
+People, it was found, relate to things that they know of firsthand.  For\r
+example, in both rural public libraries where AM was made available,\r
+observers reported that the older people with personal remembrances of\r
+the turn of the century were gravitating to the Detroit collection. \r
+These examples served to underscore MICHELSON's observation re the\r
+integration of electronic tools and ideas--that people learn best when\r
+the material relates to something they know.\r
+\r
+VECCIA made the final point that in many cases AM serves as a\r
+public-relations tool for the public libraries that are testing it.  In\r
+one case, AM is being used as a vehicle to secure additional funding for\r
+the library.  In another case, AM has served as an inspiration to the\r
+staff of a major local public library in the South to think about ways to\r
+make its own collection of photographs more accessible to the public.\r
+\r
+                                  ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+FREEMAN * AM and archival electronic resources in a school environment *\r
+Questions concerning context * Questions concerning the electronic format\r
+itself * Computer anxiety * Access and availability of the system *\r
+Hardware * Strengths gained through the use of archival resources in\r
+schools *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Reiterating an observation made by VECCIA, that AM is an archival\r
+resource made up of primary materials with very little interpretation,\r
+FREEMAN stated that the project has attempted to bridge the gap between\r
+these bare primary materials and a school environment, and in that cause\r
+has created guided introductions to AM collections.  Loud demand from the\r
+educational community,  chiefly from teachers working with the upper\r
+grades of elementary school through high school, greeted the announcement\r
+that AM would be tested around the country.\r
+\r
+FREEMAN reported not only on what was learned about AM in a school\r
+environment, but also on several universal questions that were raised\r
+concerning archival electronic resources in schools.  She discussed\r
+several strengths of this type of material in a school environment as\r
+opposed to a highly structured resource that offers a limited number of\r
+paths to follow.\r
+\r
+FREEMAN first raised several questions about using AM in a school\r
+environment.  There is often some difficulty in developing a sense of\r
+what the system contains.  Many students sit down at a computer resource\r
+and assume that, because AM comes from the Library of Congress, all of\r
+American history is now at their fingertips.  As a result of that sort of\r
+mistaken judgment, some students are known to conclude that AM contains\r
+nothing of use to them when they look for one or two things and do not\r
+find them.  It is difficult to discover that middle ground where one has\r
+a sense of what the system contains.  Some students grope toward the idea\r
+of an archive, a new idea to them, since they have not previously\r
+experienced what it means to have access to a vast body of somewhat\r
+random information.\r
+\r
+Other questions raised by FREEMAN concerned the electronic format itself. \r
+For instance, in a school environment it is often difficult both for\r
+teachers and students to gain a sense of what it is they are viewing. \r
+They understand that it is a visual image, but they do not necessarily\r
+know that it is a postcard from the turn of the century, a panoramic\r
+photograph, or even machine-readable text of an eighteenth-century\r
+broadside, a twentieth-century printed book, or a nineteenth-century\r
+diary.  That distinction is often difficult for people in a school\r
+environment to grasp.  Because of that, it occasionally becomes difficult\r
+to draw conclusions from what one is viewing.\r
+\r
+FREEMAN also noted the obvious fear of the computer, which constitutes a\r
+difficulty in using an electronic resource.  Though students in general\r
+did not suffer from this anxiety, several older students feared that they\r
+were computer-illiterate, an assumption that became self-fulfilling when\r
+they searched for something but failed to find it.  FREEMAN said she\r
+believed that some teachers also fear computer resources, because they\r
+believe they lack complete control.  FREEMAN related the example of\r
+teachers shooing away students because it was not their time to use the\r
+system.  This was a case in which the situation had to be extremely\r
+structured so that the teachers would not feel that they had lost their\r
+grasp on what the system contained.\r
+\r
+A final question raised by FREEMAN concerned access and availability of\r
+the system.  She noted the occasional existence of a gap in communication\r
+between school librarians and teachers.  Often AM sits in a school\r
+library and the librarian is the person responsible for monitoring the\r
+system.  Teachers do not always take into their world new library\r
+resources about which the librarian is excited.  Indeed, at the sites\r
+where AM had been used most effectively within a library, the librarian\r
+was required to go to specific teachers and instruct them in its use.  As\r
+a result, several AM sites will have in-service sessions over a summer,\r
+in the hope that perhaps, with a more individualized link, teachers will\r
+be more likely to use the resource.\r
+\r
+A related issue in the school context concerned the number of\r
+workstations available at any one location.  Centralization of equipment\r
+at the district level, with teachers invited to download things and walk\r
+away with them, proved unsuccessful because the hours these offices were\r
+open were also school hours.\r
+\r
+Another issue was hardware.  As VECCIA observed, a range of sites exists,\r
+some technologically advanced and others essentially acquiring their\r
+first computer for the primary purpose of using it in conjunction with\r
+AM's testing.  Users at technologically sophisticated sites want even\r
+more sophisticated hardware, so that they can perform even more\r
+sophisticated tasks with the materials in AM.  But once they acquire a\r
+newer piece of hardware, they must learn how to use that also; at an\r
+unsophisticated site it takes an extremely long time simply to become\r
+accustomed to the computer, not to mention the program offered with the\r
+computer.  All of these small issues raise one large question, namely,\r
+are systems like AM truly rewarding in a school environment, or do they\r
+simply act as innovative toys that do little more than spark interest?\r
+\r
+FREEMAN contended that the evaluation project has revealed several strengths\r
+that were gained through the use of archival resources in schools, including:\r
+\r
+     * Psychic rewards from using AM as a vast, rich database, with\r
+     teachers assigning various projects to students--oral presentations,\r
+     written reports, a documentary, a turn-of-the-century newspaper--\r
+     projects that start with the materials in AM but are completed using\r
+     other resources; AM thus is used as a research tool in conjunction\r
+     with other electronic resources, as well as with books and items in\r
+     the library where the system is set up.\r
+\r
+     * Students are acquiring computer literacy in a humanities context.\r
+\r
+     * This sort of system is overcoming the isolation between disciplines\r
+     that often exists in schools.  For example, many English teachers are\r
+     requiring their students to write papers on historical topics\r
+     represented in AM.  Numerous teachers have reported that their\r
+     students are learning critical thinking skills using the system.\r
+\r
+     * On a broader level, AM is introducing primary materials, not only\r
+     to students but also to teachers, in an environment where often\r
+     simply none exist--an exciting thing for the students because it\r
+     helps them learn to conduct research, to interpret, and to draw\r
+     their own conclusions.  In learning to conduct research and what it\r
+     means, students are motivated to seek knowledge.  That relates to\r
+     another positive outcome--a high level of personal involvement of\r
+     students with the materials in this system and greater motivation to\r
+     conduct their own research and draw their own conclusions.\r
+\r
+     * Perhaps the most ironic strength of these kinds of archival\r
+     electronic resources is that many of the teachers AM interviewed\r
+     were desperate, it is no exaggeration to say, not only for primary\r
+     materials but for unstructured primary materials.  These would, they\r
+     thought, foster personally motivated research, exploration, and\r
+     excitement in their students.  Indeed, these materials have done\r
+     just that.  Ironically, however, this lack of structure produces\r
+     some of the confusion to which the newness of these kinds of\r
+     resources may also contribute.  The key to effective use of archival\r
+     products in a school environment is a clear, effective introduction\r
+     to the system and to what it contains. \r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Nothing known, quantitatively, about the number of\r
+humanities scholars who must see the original versus those who would\r
+settle for an edited transcript, or about the ways in which humanities\r
+scholars are using information technology * Firm conclusions concerning\r
+the manner and extent of the use of supporting materials in print\r
+provided by AM to await completion of evaluative study * A listener's\r
+reflections on additional applications of electronic texts * Role of\r
+electronic resources in teaching elementary research skills to students *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+During the discussion that followed the presentations by MICHELSON,\r
+VECCIA, and FREEMAN, additional points emerged.\r
+\r
+LESK asked if MICHELSON could give any quantitative estimate of the\r
+number of humanities scholars who must see or want to see the original,\r
+or the best possible version of the material, versus those who typically\r
+would settle for an edited transcript.  While unable to provide a figure,\r
+she offered her impressions as an archivist who has done some reference\r
+work and has discussed this issue with other archivists who perform\r
+reference, that those who use archives and those who use primary sources\r
+for what would be considered very high-level scholarly research, as\r
+opposed to, say, undergraduate papers, were few in number, especially\r
+given the public interest in using primary sources to conduct\r
+genealogical or avocational research and the kind of professional\r
+research done by people in private industry or the federal government. \r
+More important in MICHELSON's view was that, quantitatively, nothing is\r
+known about the ways in which, for example, humanities scholars are using\r
+information technology.  No studies exist to offer guidance in creating\r
+strategies.  The most recent study was conducted in 1985 by the American\r
+Council of Learned Societies (ACLS), and what it showed was that 50\r
+percent of humanities scholars at that time were using computers.  That\r
+constitutes the extent of our knowledge.\r
+\r
+Concerning AM's strategy for orienting people toward the scope of\r
+electronic resources, FREEMAN could offer no hard conclusions at this\r
+point, because she and her colleagues were still waiting to see,\r
+particularly in the schools, what has been made of their efforts.  Within\r
+the system, however, AM has provided what are called electronic exhibits-\r
+-such as introductions to time periods and materials--and these are\r
+intended to offer a student user a sense of what a broadside is  and what\r
+it might tell her or him.  But FREEMAN conceded that the project staff\r
+would have to talk with students next year, after teachers have had a\r
+summer to use the materials, and attempt to discover what the students\r
+were learning from the materials.  In addition, FREEMAN described\r
+supporting materials in print provided by AM at the request of local\r
+teachers during a meeting held at LC.  These included time lines,\r
+bibliographies, and other materials that could be reproduced on a\r
+photocopier in a classroom.  Teachers could walk away with and use these,\r
+and in this way gain a better understanding of the contents.  But again,\r
+reaching firm conclusions concerning the manner and extent of their use\r
+would have to wait until next year.\r
+\r
+As to the changes she saw occurring at the National Archives and Records\r
+Administration (NARA) as a result of the increasing emphasis on\r
+technology in scholarly research, MICHELSON stated that NARA at this\r
+point was absorbing the report by her and Jeff Rothenberg addressing\r
+strategies for the archival profession in general, although not for the\r
+National Archives specifically.  NARA is just beginning to establish its\r
+role and what it can do.  In terms of changes and initiatives that NARA\r
+can take, no clear response could be given at this time.\r
+\r
+GREENFIELD remarked two trends mentioned in the session.  Reflecting on\r
+DALY's opening comments on how he could have used a Latin collection of\r
+text in an electronic form, he said that at first he thought most scholars\r
+would be unwilling to do that.  But as he thought of that in terms of the\r
+original meaning of research--that is, having already mastered these texts,\r
+researching them for critical and comparative purposes--for the first time,\r
+the electronic format made a lot of sense.  GREENFIELD could envision\r
+growing numbers of scholars learning the new technologies for that very\r
+aspect of their scholarship and for convenience's sake.\r
+\r
+Listening to VECCIA and FREEMAN, GREENFIELD thought of an additional\r
+application of electronic texts.  He realized that AM could be used as a\r
+guide to lead someone to original sources.  Students cannot be expected\r
+to have mastered these sources, things they have never known about\r
+before.  Thus, AM is leading them, in theory, to a vast body of\r
+information and giving them a superficial overview of it, enabling them\r
+to select parts of it.  GREENFIELD asked if any evidence exists that this\r
+resource will indeed teach the new user, the K-12 students, how to do\r
+research.  Scholars already know how to do research and are applying\r
+these new tools.  But he wondered why students would go beyond picking\r
+out things that were most exciting to them.\r
+\r
+FREEMAN conceded the correctness of GREENFIELD's observation as applied\r
+to a school environment.  The risk is that a student would sit down at a\r
+system, play with it, find some things of interest, and then walk away. \r
+But in the relatively controlled situation of a school library, much will\r
+depend on the instructions a teacher or a librarian gives a student.  She\r
+viewed the situation not as one of fine-tuning research skills but of\r
+involving students at a personal level in understanding and researching\r
+things.  Given the guidance one can receive at school, it then becomes\r
+possible to teach elementary research skills to students, which in fact\r
+one particular librarian said she was teaching her fifth graders. \r
+FREEMAN concluded that introducing the idea of following one's own path\r
+of inquiry, which is essentially what research entails, involves more\r
+than teaching specific skills.  To these comments VECCIA added the\r
+observation that the individual teacher and the use of a creative\r
+resource, rather than AM itself, seemed to make the key difference.\r
+Some schools and some teachers are making excellent use of the nature\r
+of critical thinking and teaching skills, she said.\r
+\r
+Concurring with these remarks, DALY closed the session with the thought that\r
+the more that producers produced for teachers and for scholars to use with\r
+their students, the more successful their electronic products would prove.\r
+\r
+                                 ******\r
+\r
+SESSION II.  SHOW AND TELL\r
+\r
+Jacqueline HESS, director, National Demonstration Laboratory, served as\r
+moderator of the "show-and-tell" session.  She noted that a\r
+question-and-answer period would follow each presentation.\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+MYLONAS * Overview and content of Perseus * Perseus' primary materials\r
+exist in a system-independent, archival form * A concession * Textual\r
+aspects of Perseus * Tools to use with the Greek text * Prepared indices\r
+and full-text searches in Perseus * English-Greek word search leads to\r
+close study of words and concepts * Navigating Perseus by tracing down\r
+indices * Using the iconography to perform research *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Elli MYLONAS, managing editor, Perseus Project, Harvard University, first\r
+gave an overview of Perseus, a large, collaborative effort based at\r
+Harvard University but with contributors and collaborators located at\r
+numerous universities and colleges in the United States (e.g., Bowdoin,\r
+Maryland, Pomona, Chicago, Virginia).  Funded primarily by the\r
+Annenberg/CPB Project, with additional funding from Apple, Harvard, and\r
+the Packard Humanities Institute, among others, Perseus is a multimedia,\r
+hypertextual database for teaching and research on classical Greek\r
+civilization, which was released in February 1992 in version 1.0 and\r
+distributed by Yale University Press.\r
+\r
+Consisting entirely of primary materials, Perseus includes ancient Greek\r
+texts and translations of those texts; catalog entries--that is, museum\r
+catalog entries, not library catalog entries--on vases, sites, coins,\r
+sculpture, and archaeological objects; maps; and a dictionary, among\r
+other sources.  The number of objects and the objects for which catalog\r
+entries exist are accompanied by thousands of color images, which\r
+constitute a major feature of the database.  Perseus contains\r
+approximately 30 megabytes of text, an amount that will double in\r
+subsequent versions.  In addition to these primary materials, the Perseus\r
+Project has been building tools for using them, making access and\r
+navigation easier, the goal being to build part of the electronic\r
+environment discussed earlier in the morning in which students or\r
+scholars can work with their sources.\r
+\r
+The demonstration of Perseus will show only a fraction of the real work\r
+that has gone into it, because the project had to face the dilemma of\r
+what to enter when putting something into machine-readable form:  should\r
+one aim for very high quality or make concessions in order to get the\r
+material in?  Since Perseus decided to opt for very high quality, all of\r
+its primary materials exist in a system-independent--insofar as it is\r
+possible to be system-independent--archival form.  Deciding what that\r
+archival form would be and attaining it required much work and thought. \r
+For example, all the texts are marked up in SGML, which will be made\r
+compatible with the guidelines of the Text Encoding Initiative (TEI) when\r
+they are issued.\r
+\r
+Drawings are postscript files, not meeting international standards, but\r
+at least designed to go across platforms.  Images, or rather the real\r
+archival forms, consist of the best available slides, which are being\r
+digitized.  Much of the catalog material exists in database form--a form\r
+that the average user could use, manipulate, and display on a personal\r
+computer, but only at great cost.  Thus, this is where the concession\r
+comes in:  All of this rich, well-marked-up information is stripped of\r
+much of its content; the images are converted into bit-maps and the text\r
+into small formatted chunks.  All this information can then be imported\r
+into HyperCard and run on a mid-range Macintosh, which is what Perseus\r
+users have.  This fact has made it possible for Perseus to attain wide\r
+use fairly rapidly.  Without those archival forms the HyperCard version\r
+being demonstrated could not be made easily, and the project could not\r
+have the potential to move to other forms and machines and software as\r
+they appear, none of which information is in Perseus on the CD.\r
+\r
+Of the numerous multimedia aspects of Perseus, MYLONAS focused on the\r
+textual.  Part of what makes Perseus such a pleasure to use, MYLONAS\r
+said, is this effort at seamless integration and the ability to move\r
+around both visual and textual material.  Perseus also made the decision\r
+not to attempt to interpret its material any more than one interprets by\r
+selecting.  But, MYLONAS emphasized, Perseus is not courseware:  No\r
+syllabus exists.  There is no effort to define how one teaches a topic\r
+using Perseus, although the project may eventually collect papers by\r
+people who have used it to teach.  Rather, Perseus aims to provide\r
+primary material in a kind of electronic library, an electronic sandbox,\r
+so to say, in which students and scholars who are working on this\r
+material can explore by themselves.  With that, MYLONAS demonstrated\r
+Perseus, beginning with the Perseus gateway, the first thing one sees\r
+upon opening Perseus--an effort in part to solve the contextualizing\r
+problem--which tells the user what the system contains.\r
+\r
+MYLONAS demonstrated only a very small portion, beginning with primary\r
+texts and running off the CD-ROM.  Having selected Aeschylus' Prometheus\r
+Bound, which was viewable in Greek and English pretty much in the same\r
+segments together, MYLONAS demonstrated tools to use with the Greek text,\r
+something not possible with a book:  looking up the dictionary entry form\r
+of an unfamiliar word in Greek after subjecting it to Perseus'\r
+morphological analysis for all the texts.  After finding out about a\r
+word, a user may then decide to see if it is used anywhere else in Greek. \r
+Because vast amounts of indexing support all of the primary material, one\r
+can find out where else all forms of a particular Greek word appear--\r
+often not a trivial matter because Greek is highly inflected.  Further,\r
+since the story of Prometheus has to do with the origins of sacrifice, a\r
+user may wish to study and explore sacrifice in Greek literature; by\r
+typing sacrifice into a small window, a user goes to the English-Greek\r
+word list--something one cannot do without the computer (Perseus has\r
+indexed the definitions of its dictionary)--the string sacrifice appears\r
+in the definitions of these sixty-five words.  One may then find out\r
+where any of those words is used in the work(s) of a particular author. \r
+The English definitions are not lemmatized.\r
+\r
+All of the indices driving this kind of usage were originally devised for\r
+speed, MYLONAS observed; in other words, all that kind of information--\r
+all forms of all words, where they exist, the dictionary form they belong\r
+to--were collected into databases, which will expedite searching.  Then\r
+it was discovered that one can do things searching in these databases\r
+that could not be done searching in the full texts.  Thus, although there\r
+are full-text searches in Perseus, much of the work is done behind the\r
+scenes, using prepared indices.  Re the indexing that is done behind the\r
+scenes, MYLONAS pointed out that without the SGML forms of the text, it\r
+could not be done effectively.  Much of this indexing is based on the\r
+structures that are made explicit by the SGML tagging.\r
+\r
+It was found that one of the things many of Perseus' non-Greek-reading\r
+users do is start from the dictionary and then move into the close study\r
+of words and concepts via this kind of English-Greek word search, by which\r
+means they might select a concept.  This exercise has been assigned to\r
+students in core courses at Harvard--to study a concept by looking for the\r
+English word in the dictionary, finding the Greek words, and then finding\r
+the words in the Greek but, of course, reading across in the English.\r
+That tells them a great deal about what a translation means as well.\r
+\r
+Should one also wish to see images that have to do with sacrifice, that\r
+person would go to the object key word search, which allows one to\r
+perform a similar kind of index retrieval on the database of\r
+archaeological objects.  Without words, pictures are useless; Perseus has\r
+not reached the point where it can do much with images that are not\r
+cataloged.  Thus, although it is possible in Perseus with text and images\r
+to navigate by knowing where one wants to end up--for example, a\r
+red-figure vase from the Boston Museum of Fine Arts--one can perform this\r
+kind of navigation very easily by tracing down indices.  MYLONAS\r
+illustrated several generic scenes of sacrifice on vases.  The features\r
+demonstrated derived from Perseus 1.0; version 2.0 will implement even\r
+better means of retrieval.\r
+\r
+MYLONAS closed by looking at one of the pictures and noting again that\r
+one can do a great deal of research using the iconography as well as the\r
+texts.  For instance, students in a core course at Harvard this year were\r
+highly interested in Greek concepts of foreigners and representations of\r
+non-Greeks.  So they performed a great deal of research, both with texts\r
+(e.g., Herodotus) and with iconography on vases and coins, on how the\r
+Greeks portrayed non-Greeks.  At the same time, art historians who study\r
+iconography were also interested, and were able to use this material.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Indexing and searchability of all English words in Perseus *\r
+Several features of Perseus 1.0 * Several levels of customization\r
+possible * Perseus used for general education * Perseus' effects on\r
+education * Contextual information in Perseus * Main challenge and\r
+emphasis of Perseus *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Several points emerged in the discussion that followed MYLONAS's presentation.\r
+\r
+Although MYLONAS had not demonstrated Perseus' ability to cross-search\r
+documents, she confirmed that all English words in Perseus are indexed\r
+and can be searched.  So, for example, sacrifice could have been searched\r
+in all texts, the historical essay, and all the catalogue entries with\r
+their descriptions--in short, in all of Perseus.\r
+\r
+Boolean logic is not in Perseus 1.0 but will be added to the next\r
+version, although an effort is being made not to restrict Perseus to a\r
+database in which one just performs searching, Boolean or otherwise.  It\r
+is possible to move laterally through the documents by selecting a word\r
+one is interested in and selecting an area of information one is\r
+interested in and trying to look that word up in that area.\r
+\r
+Since Perseus was developed in HyperCard, several levels of customization\r
+are possible.  Simple authoring tools exist that allow one to create\r
+annotated paths through the information, which are useful for note-taking\r
+and for guided tours for teaching purposes and for expository writing. \r
+With a little more ingenuity it is possible to begin to add or substitute\r
+material in Perseus.\r
+\r
+Perseus has not been used so much for classics education as for general\r
+education, where it seemed to have an impact on the students in the core\r
+course at Harvard (a general required course that students must take in\r
+certain areas).  Students were able to use primary material much more.\r
+\r
+The Perseus Project has an evaluation team at the University of Maryland\r
+that has been documenting Perseus' effects on education.  Perseus is very\r
+popular, and anecdotal evidence indicates that it is having an effect at\r
+places other than Harvard, for example, test sites at Ball State\r
+University, Drury College, and numerous small places where opportunities\r
+to use vast amounts of primary data may not exist.  One documented effect\r
+is that archaeological, anthropological, and philological research is\r
+being done by the same person instead of by three different people.\r
+\r
+The contextual information in Perseus includes an overview essay, a\r
+fairly linear historical essay on the fifth century B.C. that provides\r
+links into the primary material (e.g., Herodotus, Thucydides, and\r
+Plutarch), via small gray underscoring (on the screen) of linked\r
+passages.  These are handmade links into other material.\r
+\r
+To different extents, most of the production work was done at Harvard,\r
+where the people and the equipment are located.  Much of the\r
+collaborative activity involved data collection and structuring, because\r
+the main challenge and the emphasis of Perseus is the gathering of\r
+primary material, that is, building a useful environment for studying\r
+classical Greece, collecting data, and making it useful. \r
+Systems-building is definitely not the main concern.  Thus, much of the\r
+work has involved writing essays, collecting information, rewriting it,\r
+and tagging it.  That can be done off site.  The creative link for the\r
+overview essay as well as for both systems and data was collaborative,\r
+and was forged via E-mail and paper mail with professors at Pomona and\r
+Bowdoin.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+CALALUCA * PLD's principal focus and contribution to scholarship *\r
+Various questions preparatory to beginning the project * Basis for\r
+project * Basic rule in converting PLD * Concerning the images in PLD *\r
+Running PLD under a variety of retrieval softwares * Encoding the\r
+database a hard-fought issue * Various features demonstrated * Importance\r
+of user documentation * Limitations of the CD-ROM version *   \r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Eric CALALUCA, vice president, Chadwyck-Healey, Inc., demonstrated a\r
+software interpretation of the Patrologia Latina Database (PLD).  PLD's\r
+principal focus from the beginning of the project about three-and-a-half\r
+years ago was on converting Migne's Latin series, and in the end,\r
+CALALUCA suggested, conversion of the text will be the major contribution\r
+to scholarship.  CALALUCA stressed that, as possibly the only private\r
+publishing organization at the Workshop, Chadwyck-Healey had sought no\r
+federal funds or national foundation support before embarking upon the\r
+project, but instead had relied upon a great deal of homework and\r
+marketing to accomplish the task of conversion.\r
+\r
+Ever since the possibilities of computer-searching have emerged, scholars\r
+in the field of late ancient and early medieval studies (philosophers,\r
+theologians, classicists, and those studying the history of natural law\r
+and the history of the legal development of Western civilization) have\r
+been longing for a fully searchable version of Western literature, for\r
+example, all the texts of Augustine and Bernard of Clairvaux and\r
+Boethius, not to mention all the secondary and tertiary authors.\r
+\r
+Various questions arose, CALALUCA said.  Should one convert Migne? \r
+Should the database be encoded?  Is it necessary to do that?  How should\r
+it be delivered?  What about CD-ROM?  Since this is a transitional\r
+medium, why even bother to create software to run on a CD-ROM?  Since\r
+everybody knows people will be networking information, why go to the\r
+trouble--which is far greater with CD-ROM than with the production of\r
+magnetic data?  Finally, how does one make the data available?  Can many\r
+of the hurdles to using electronic information that some publishers have\r
+imposed upon databases be eliminated?\r
+\r
+The PLD project was based on the principle that computer-searching of\r
+texts is most effective when it is done with a large database.  Because\r
+PLD represented a collection that serves so many disciplines across so\r
+many periods, it was irresistible.\r
+\r
+The basic rule in converting PLD was to do no harm, to avoid the sins of\r
+intrusion in such a database:  no introduction of newer editions, no\r
+on-the-spot changes, no eradicating of all possible falsehoods from an\r
+edition.  Thus, PLD is not the final act in electronic publishing for\r
+this discipline, but simply the beginning.  The conversion of PLD has\r
+evoked numerous unanticipated questions:  How will information be used? \r
+What about networking?  Can the rights of a database be protected? \r
+Should one protect the rights of a database?  How can it be made\r
+available?\r
+\r
+Those converting PLD also tried to avoid the sins of omission, that is,\r
+excluding portions of the collections or whole sections.  What about the\r
+images?  PLD is full of images, some are extremely pious\r
+nineteenth-century representations of the Fathers, while others contain\r
+highly interesting elements.  The goal was to cover all the text of Migne\r
+(including notes, in Greek and in Hebrew, the latter of which, in\r
+particular, causes problems in creating a search structure), all the\r
+indices, and even the images, which are being scanned in separately\r
+searchable files.\r
+\r
+Several North American institutions that have placed acquisition requests\r
+for the PLD database have requested it in magnetic form without software,\r
+which means they are already running it without software, without\r
+anything demonstrated at the Workshop.\r
+\r
+What cannot practically be done is go back and reconvert and re-encode\r
+data, a time-consuming and extremely costly enterprise.  CALALUCA sees\r
+PLD as a database that can, and should, be run under a variety of\r
+retrieval softwares.  This will permit the widest possible searches. \r
+Consequently, the need to produce a CD-ROM of PLD, as well as to develop\r
+software that could handle some 1.3 gigabyte of heavily encoded text,\r
+developed out of conversations with collection development and reference\r
+librarians who wanted software both compassionate enough for the\r
+pedestrian but also capable of incorporating the most detailed\r
+lexicographical studies that a user desires to conduct.  In the end, the\r
+encoding and conversion of the data will prove the most enduring\r
+testament to the value of the project.\r
+\r
+The encoding of the database was also a hard-fought issue:  Did the\r
+database need to be encoded? Were there normative structures for encoding\r
+humanist texts?  Should it be SGML?  What about the TEI--will it last,\r
+will it prove useful?  CALALUCA expressed some minor doubts as to whether\r
+a data bank can be fully TEI-conformant.  Every effort can be made, but\r
+in the end to be TEI-conformant means to accept the need to make some\r
+firm encoding decisions that can, indeed, be disputed.  The TEI points\r
+the publisher in a proper direction but does not presume to make all the\r
+decisions for him or her.  Essentially, the goal of encoding was to\r
+eliminate, as much as possible, the hindrances to information-networking,\r
+so that if an institution acquires a database, everybody associated with\r
+the institution can have access to it.\r
+\r
+CALALUCA demonstrated a portion of Volume 160, because it had the most\r
+anomalies in it.  The software was created by Electronic Book\r
+Technologies of Providence, RI, and is called Dynatext.  The software\r
+works only with SGML-coded data.\r
+\r
+Viewing a table of contents on the screen, the audience saw how Dynatext\r
+treats each element as a book and attempts to simplify movement through a\r
+volume.  Familiarity with the Patrologia in print (i.e., the text, its\r
+source, and the editions) will make the machine-readable versions highly\r
+useful.  (Software with a Windows application was sought for PLD,\r
+CALALUCA said, because this was the main trend for scholarly use.)\r
+\r
+CALALUCA also demonstrated how a user can perform a variety of searches\r
+and quickly move to any part of a volume; the look-up screen provides\r
+some basic, simple word-searching. \r
+\r
+CALALUCA argued that one of the major difficulties is not the software. \r
+Rather, in creating a product that will be used by scholars representing\r
+a broad spectrum of computer sophistication,  user documentation proves\r
+to be the most important service one can provide.\r
+\r
+CALALUCA next illustrated a truncated search under mysterium within ten\r
+words of virtus and how one would be able to find its contents throughout\r
+the entire database.  He said that the exciting thing about PLD is that\r
+many of the applications in the retrieval software being written for it\r
+will exceed the capabilities of the software employed now for the CD-ROM\r
+version.  The CD-ROM faces genuine limitations, in terms of speed and\r
+comprehensiveness, in the creation of a retrieval software to run it. \r
+CALALUCA said he hoped that individual scholars will download the data,\r
+if they wish, to their personal computers, and have ready access to\r
+important texts on a constant basis, which they will be able to use in\r
+their research and from which they might even be able to publish.\r
+\r
+(CALALUCA explained that the blue numbers represented Migne's column numbers,\r
+which are the standard scholarly references.  Pulling up a note, he stated\r
+that these texts were heavily edited and the image files would appear simply\r
+as a note as well, so that one could quickly access an image.)\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+FLEISCHHAUER/ERWAY * Several problems with which AM is still wrestling *\r
+Various search and retrieval capabilities * Illustration of automatic\r
+stemming and a truncated search * AM's attempt to find ways to connect\r
+cataloging to the texts * AM's gravitation towards SGML * Striking a\r
+balance between quantity and quality * How AM furnishes users recourse to\r
+images * Conducting a search in a full-text environment * Macintosh and\r
+IBM prototypes of AM * Multimedia aspects of AM *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+A demonstration of American Memory by its coordinator, Carl FLEISCHHAUER,\r
+and Ricky ERWAY, associate coordinator, Library of Congress, concluded\r
+the morning session.  Beginning with a collection of broadsides from the\r
+Continental Congress and the Constitutional Convention, the only text\r
+collection in a presentable form at the time of the Workshop, FLEISCHHAUER\r
+highlighted several of the problems with which AM is still wrestling.\r
+(In its final form, the disk will contain two collections, not only the\r
+broadsides but also the full text with illustrations of a set of\r
+approximately 300 African-American pamphlets from the period 1870 to 1910.)\r
+\r
+As FREEMAN had explained earlier, AM has attempted to use a small amount\r
+of interpretation to introduce collections.  In the present case, the\r
+contractor, a company named Quick Source, in Silver Spring, MD., used\r
+software called Toolbook and put together a modestly interactive\r
+introduction to the collection.  Like the two preceding speakers,\r
+FLEISCHHAUER argued that the real asset was the underlying collection.\r
+\r
+FLEISCHHAUER proceeded to describe various search and retrieval\r
+capabilities while ERWAY worked the computer.  In this particular package\r
+the "go to" pull-down allowed the user in effect to jump out of Toolbook,\r
+where the interactive program was located, and enter the third-party\r
+software used by AM for this text collection, which is called Personal\r
+Librarian.  This was the Windows version of Personal Librarian, a\r
+software application put together by a company in Rockville, Md.\r
+\r
+Since the broadsides came from the Revolutionary War period, a search was\r
+conducted using the words British or war, with the default operator reset\r
+as or.  FLEISCHHAUER demonstrated both automatic stemming (which finds\r
+other forms of the same root) and a truncated search.  One of Personal\r
+Librarian's strongest features, the relevance ranking, was represented by\r
+a chart that indicated how often words being sought appeared in\r
+documents, with the one receiving the most "hits" obtaining the highest\r
+score.  The "hit list" that is supplied takes the relevance ranking into\r
+account, making the first hit, in effect, the one the software has\r
+selected as the most relevant example.\r
+\r
+While in the text of one of the broadside documents, FLEISCHHAUER\r
+remarked AM's attempt to find ways to connect cataloging to the texts,\r
+which it does in different ways in different manifestations.  In the case\r
+shown, the cataloging was pasted on:  AM took MARC records that were\r
+written as on-line records right into one of the Library's mainframe\r
+retrieval programs, pulled them out, and handed them off to the contractor,\r
+who massaged them somewhat to display them in the manner shown.  One of\r
+AM's questions is, Does the cataloguing normally performed in the mainframe\r
+work in this context, or had AM ought to think through adjustments?\r
+\r
+FLEISCHHAUER made the additional point that, as far as the text goes, AM\r
+has gravitated towards SGML (he pointed to the boldface in the upper part\r
+of the screen).  Although extremely limited in its ability to translate\r
+or interpret SGML, Personal Librarian will furnish both bold and italics\r
+on screen; a fairly easy thing to do, but it is one of the ways in which\r
+SGML is useful.\r
+\r
+Striking a balance between quantity and quality has been a major concern\r
+of AM, with accuracy being one of the places where project staff have\r
+felt that less than 100-percent accuracy was not unacceptable. \r
+FLEISCHHAUER cited the example of the standard of the rekeying industry,\r
+namely 99.95 percent; as one service bureau informed him, to go from\r
+99.95 to 100 percent would double the cost.\r
+\r
+FLEISCHHAUER next demonstrated how AM furnishes users recourse to images,\r
+and at the same time recalled LESK's pointed question concerning the\r
+number of people who would look at those images and the number who would\r
+work only with the text.  If the implication of LESK's question was\r
+sound, FLEISCHHAUER said, it raised the stakes for text accuracy and\r
+reduced the value of the strategy for images.\r
+\r
+Contending that preservation is always a bugaboo, FLEISCHHAUER\r
+demonstrated several images derived from a scan of a preservation\r
+microfilm that AM had made.  He awarded a grade of C at best, perhaps a\r
+C minus or a C plus, for how well it worked out.  Indeed, the matter of\r
+learning if other people had better ideas about scanning in general, and,\r
+in particular, scanning from microfilm, was one of the factors that drove\r
+AM to attempt to think through the agenda for the Workshop.  Skew, for\r
+example, was one of the issues that AM in its ignorance had not reckoned\r
+would prove so difficult.\r
+\r
+Further, the handling of images of the sort shown, in a desktop computer\r
+environment, involved a considerable amount of zooming and scrolling. \r
+Ultimately, AM staff feel that perhaps the paper copy that is printed out\r
+might be the most useful one, but they remain uncertain as to how much\r
+on-screen reading users will do.\r
+\r
+Returning to the text, FLEISCHHAUER asked viewers to imagine a person who\r
+might be conducting a search in a full-text environment.  With this\r
+scenario, he proceeded to illustrate other features of Personal Librarian\r
+that he considered helpful; for example, it provides the ability to\r
+notice words as one reads.  Clicking the "include" button on the bottom\r
+of the search window pops the words that have been highlighted into the\r
+search.  Thus, a user can refine the search as he or she reads,\r
+re-executing the search and continuing to find things in the quest for\r
+materials.  This software not only contains relevance ranking, Boolean\r
+operators, and truncation, it also permits one to perform word algebra,\r
+so to say, where one puts two or three words in parentheses and links\r
+them with one Boolean operator and then a couple of words in another set\r
+of parentheses and asks for things within so many words of others.\r
+\r
+Until they became acquainted recently with some of the work being done in\r
+classics, the AM staff had not realized that a large number of the\r
+projects that involve electronic texts were being done by people with a\r
+profound interest in language and linguistics.  Their search strategies\r
+and thinking are oriented to those fields, as is shown in particular by\r
+the Perseus example.  As amateur historians, the AM staff were thinking\r
+more of searching for concepts and ideas than for particular words. \r
+Obviously, FLEISCHHAUER conceded, searching for concepts and ideas and\r
+searching for words may be two rather closely related things.\r
+\r
+While displaying several images, FLEISCHHAUER observed that the Macintosh\r
+prototype built by AM contains a greater diversity of formats.  Echoing a\r
+previous speaker, he said that it was easier to stitch things together in\r
+the Macintosh, though it tended to be a little more anemic in search and\r
+retrieval.  AM, therefore, increasingly has been investigating\r
+sophisticated retrieval engines in the IBM format.\r
+\r
+FLEISCHHAUER demonstrated several additional examples of the prototype\r
+interfaces:  One was AM's metaphor for the network future, in which a\r
+kind of reading-room graphic suggests how one would be able to go around\r
+to different materials.  AM contains a large number of photographs in\r
+analog video form worked up from a videodisc, which enable users to make\r
+copies to print or incorporate in digital documents.  A frame-grabber is\r
+built into the system, making it possible to bring an image into a window\r
+and digitize or print it out.\r
+\r
+FLEISCHHAUER next demonstrated sound recording, which included texts. \r
+Recycled from a previous project, the collection included sixty 78-rpm\r
+phonograph records of political speeches that were made during and\r
+immediately after World War I.  These constituted approximately three\r
+hours of audio, as AM has digitized it, which occupy 150 megabytes on a\r
+CD.  Thus, they are considerably compressed.  From the catalogue card,\r
+FLEISCHHAUER proceeded to a transcript of a speech with the audio\r
+available and with highlighted text following it as it played.\r
+A photograph has been added and a transcription made.\r
+\r
+Considerable value has been added beyond what the Library of Congress\r
+normally would do in cataloguing a sound recording, which raises several\r
+questions for AM concerning where to draw lines about how much value it can\r
+afford to add and at what point, perhaps, this becomes more than AM could\r
+reasonably do or reasonably wish to do.  FLEISCHHAUER also demonstrated\r
+a motion picture.  As FREEMAN had reported earlier, the motion picture\r
+materials have proved the most popular, not surprisingly.  This says more\r
+about the medium, he thought, than about AM's presentation of it.\r
+\r
+Because AM's goal was to bring together things that could be used by\r
+historians or by people who were curious about history,\r
+turn-of-the-century footage seemed to represent the most appropriate\r
+collections from the Library of Congress in motion pictures. These were\r
+the very first films made by Thomas Edison's company and some others at\r
+that time.  The particular example illustrated was a Biograph film,\r
+brought in with a frame-grabber into a window.  A single videodisc\r
+contains about fifty titles and pieces of film from that period, all of\r
+New York City.  Taken together, AM believes, they provide an interesting\r
+documentary resource.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Using the frame-grabber in AM * Volume of material processed\r
+and to be processed * Purpose of AM within LC * Cataloguing and the\r
+nature of AM's material * SGML coding and the question of quality versus\r
+quantity *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+During the question-and-answer period that followed FLEISCHHAUER's\r
+presentation, several clarifications were made.\r
+\r
+AM is bringing in motion pictures from a videodisc.  The frame-grabber\r
+devices create a window on a computer screen, which permits users to\r
+digitize a single frame of the movie or one of the photographs.  It\r
+produces a crude, rough-and-ready image that high school students can\r
+incorporate into papers, and that has worked very nicely in this way.\r
+\r
+Commenting on FLEISCHHAUER's assertion that AM was looking more at\r
+searching ideas than words, MYLONAS argued that without words an idea\r
+does not exist.  FLEISCHHAUER conceded that he ought to have articulated\r
+his point more clearly.  MYLONAS stated that they were in fact both\r
+talking about the same thing.  By searching for words and by forcing\r
+people to focus on the word, the Perseus Project felt that they would get\r
+them to the idea.  The way one reviews results is tailored more to one\r
+kind of user than another.\r
+\r
+Concerning the total volume of material that has been processed in this\r
+way, AM at this point has in retrievable form seven or eight collections,\r
+all of them photographic.  In the Macintosh environment, for example,\r
+there probably are 35,000-40,000 photographs.  The sound recordings\r
+number sixty items.  The broadsides number about 300 items.  There are\r
+500 political cartoons in the form of drawings.  The motion pictures, as\r
+individual items, number sixty to seventy.\r
+\r
+AM also has a manuscript collection, the life history portion of one of\r
+the federal project series, which will contain 2,900 individual\r
+documents, all first-person narratives.  AM has in process about 350\r
+African-American pamphlets, or about 12,000 printed pages for the period\r
+1870-1910.  Also in the works are some 4,000 panoramic photographs.  AM\r
+has recycled a fair amount of the work done by LC's Prints and\r
+Photographs Division during the Library's optical disk pilot project in\r
+the 1980s.  For example, a special division of LC has tooled up and\r
+thought through all the ramifications of electronic presentation of\r
+photographs.  Indeed, they are wheeling them out in great barrel loads. \r
+The purpose of AM within the Library, it is hoped, is to catalyze several\r
+of the other special collection divisions which have no particular\r
+experience with, in some cases, mixed feelings about, an activity such as\r
+AM.  Moreover, in many cases the divisions may be characterized as not\r
+only lacking experience in "electronifying" things but also in automated\r
+cataloguing.  MARC cataloguing as practiced in the United States is\r
+heavily weighted toward the description of monograph and serial\r
+materials, but is much thinner when one enters the world of manuscripts\r
+and things that are held in the Library's music collection and other\r
+units.  In response to a comment by LESK, that AM's material is very\r
+heavily photographic, and is so primarily because individual records have\r
+been made for each photograph, FLEISCHHAUER observed that an item-level\r
+catalog record exists, for example, for each photograph in the Detroit\r
+Publishing collection of 25,000 pictures.  In the case of the Federal\r
+Writers Project, for which nearly 3,000 documents exist, representing\r
+information from twenty-six different states, AM with the assistance of\r
+Karen STUART of the Manuscript Division will attempt to find some way not\r
+only to have a collection-level record but perhaps a MARC record for each\r
+state, which will then serve as an umbrella for the 100-200 documents\r
+that come under it.  But that drama remains to be enacted.  The AM staff\r
+is conservative and clings to cataloguing, though of course visitors tout\r
+artificial intelligence and neural networks in a manner that suggests that\r
+perhaps one need not have cataloguing or that much of it could be put aside.\r
+\r
+The matter of SGML coding, FLEISCHHAUER conceded, returned the discussion\r
+to the earlier treated question of quality versus quantity in the Library\r
+of Congress.  Of course, text conversion can be done with 100-percent\r
+accuracy, but it means that when one's holdings are as vast as LC's only\r
+a tiny amount will be exposed, whereas permitting lower levels of\r
+accuracy can lead to exposing or sharing larger amounts, but with the\r
+quality correspondingly impaired.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+TWOHIG * A contrary experience concerning electronic options * Volume of\r
+material in the Washington papers and a suggestion of David Packard *\r
+Implications of Packard's suggestion * Transcribing the documents for the\r
+CD-ROM * Accuracy of transcriptions * The CD-ROM edition of the Founding\r
+Fathers documents *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Finding encouragement in a comment of MICHELSON's from the morning\r
+session--that numerous people in the humanities were choosing electronic\r
+options to do their work--Dorothy TWOHIG, editor, The Papers of George\r
+Washington, opened her illustrated talk by noting that her experience\r
+with literary scholars and numerous people in editing was contrary to\r
+MICHELSON's.  TWOHIG emphasized literary scholars' complete ignorance of\r
+the technological options available to them or their reluctance or, in\r
+some cases, their downright hostility toward these options.\r
+\r
+After providing an overview of the five Founding Fathers projects\r
+(Jefferson at Princeton, Franklin at Yale, John Adams at the\r
+Massachusetts Historical Society, and Madison down the hall from her at\r
+the University of Virginia), TWOHIG observed that the Washington papers,\r
+like all of the projects, include both sides of the Washington\r
+correspondence and deal with some 135,000 documents to be published with\r
+extensive annotation in eighty to eighty-five volumes, a project that\r
+will not be completed until well into the next century.  Thus, it was\r
+with considerable enthusiasm several years ago that the Washington Papers\r
+Project (WPP) greeted David Packard's suggestion that the papers of the\r
+Founding Fathers could be published easily and inexpensively, and to the\r
+great benefit of American scholarship, via CD-ROM.\r
+\r
+In pragmatic terms, funding from the Packard Foundation would expedite\r
+the transcription of thousands of documents waiting to be put on disk in\r
+the WPP offices.  Further, since the costs of collecting, editing, and\r
+converting the Founding Fathers documents into letterpress editions were\r
+running into the millions of dollars, and the considerable staffs\r
+involved in all of these projects were devoting their careers to\r
+producing the work, the Packard Foundation's suggestion had a\r
+revolutionary aspect:  Transcriptions of the entire corpus of the\r
+Founding Fathers papers would be available on CD-ROM to public and\r
+college libraries, even high schools, at a fraction of the cost--\r
+$100-$150 for the annual license fee--to produce a limited university\r
+press run of 1,000 of each volume of the published papers at $45-$150 per\r
+printed volume.  Given the current budget crunch in educational systems\r
+and the corresponding constraints on librarians in smaller institutions\r
+who wish to add these volumes to their collections, producing the\r
+documents on CD-ROM would likely open a greatly expanded audience for the\r
+papers.  TWOHIG stressed, however, that development of the Founding\r
+Fathers CD-ROM is still in its infancy.  Serious software problems remain\r
+to be resolved before the material can be put into readable form.  \r
+\r
+Funding from the Packard Foundation resulted in a major push to\r
+transcribe the 75,000 or so documents of the Washington papers remaining\r
+to be transcribed onto computer disks.  Slides illustrated several of the\r
+problems encountered, for example, the present inability of CD-ROM to\r
+indicate the cross-outs (deleted material) in eighteenth century\r
+documents.  TWOHIG next described documents from various periods in the\r
+eighteenth century that have been transcribed in chronological order and\r
+delivered to the Packard offices in California, where they are converted\r
+to the CD-ROM, a process that is expected to consume five years to\r
+complete (that is, reckoning from David Packard's suggestion made several\r
+years ago, until about July 1994).  TWOHIG found an encouraging\r
+indication of the project's benefits in the ongoing use made by scholars\r
+of the search functions of the CD-ROM, particularly in reducing the time\r
+spent in manually turning the pages of the Washington papers.\r
+\r
+TWOHIG next furnished details concerning the accuracy of transcriptions. \r
+For instance, the insertion of thousands of documents on the CD-ROM\r
+currently does not permit each document to be verified against the\r
+original manuscript several times as in the case of documents that appear\r
+in the published edition.  However, the transcriptions receive a cursory\r
+check for obvious typos, the misspellings of proper names, and other\r
+errors from the WPP CD-ROM editor.  Eventually, all documents that appear\r
+in the electronic version will be checked by project editors.  Although\r
+this process has met with opposition from some of the editors on the\r
+grounds that imperfect work may leave their offices, the advantages in\r
+making this material available as a research tool outweigh  fears about the\r
+misspelling of proper names and other relatively minor editorial matters.\r
+\r
+Completion of all five Founding Fathers projects (i.e., retrievability\r
+and searchability of all of the documents by proper names, alternate\r
+spellings, or varieties of subjects) will provide one of the richest\r
+sources of this size for the history of the United States in the latter\r
+part of the eighteenth century.  Further, publication on CD-ROM will\r
+allow editors to include even minutiae, such as laundry lists, not\r
+included in the printed volumes.\r
+\r
+It seems possible that the extensive annotation provided in the printed\r
+volumes eventually will be added to the CD-ROM edition, pending\r
+negotiations with the publishers of the papers.  At the moment, the\r
+Founding Fathers CD-ROM is accessible only on the IBYCUS, a computer\r
+developed out of the Thesaurus Linguae Graecae project and designed for\r
+the use of classical scholars.  There are perhaps 400 IBYCUS computers in\r
+the country, most of which are in university classics departments. \r
+Ultimately, it is anticipated that the CD-ROM edition of the Founding\r
+Fathers documents will run on any IBM-compatible or Macintosh computer\r
+with a CD-ROM drive.  Numerous changes in the software will also occur\r
+before the project is completed.  (Editor's note: an IBYCUS was\r
+unavailable to demonstrate the CD-ROM.)\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Several additional features of WPP clarified *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Discussion following TWOHIG's presentation served to clarify several\r
+additional features, including (1) that the project's primary\r
+intellectual product consists in the electronic transcription of the\r
+material; (2) that the text transmitted to the CD-ROM people is not\r
+marked up; (3) that cataloging and subject-indexing of the material\r
+remain to be worked out (though at this point material can be retrieved\r
+by name); and (4) that because all the searching is done in the hardware,\r
+the IBYCUS is designed to read a CD-ROM which contains only sequential\r
+text files.  Technically, it then becomes very easy to read the material\r
+off and put it on another device.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+LEBRON * Overview of the history of the joint project between AAAS and\r
+OCLC * Several practices the on-line environment shares with traditional\r
+publishing on hard copy * Several technical and behavioral barriers to\r
+electronic publishing * How AAAS and OCLC arrived at the subject of\r
+clinical trials * Advantages of the electronic format and other features\r
+of OJCCT * An illustrated tour of the journal *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Maria LEBRON, managing editor, The Online Journal of Current Clinical\r
+Trials (OJCCT), presented an illustrated overview of the history of the\r
+joint project between the American Association for the Advancement of\r
+Science (AAAS) and the Online Computer Library Center, Inc. (OCLC).  The\r
+joint venture between AAAS and OCLC owes its beginning to a\r
+reorganization launched by the new chief executive officer at OCLC about\r
+three years ago and combines the strengths of these two disparate\r
+organizations.  In short, OJCCT represents the process of scholarly\r
+publishing on line.\r
+\r
+LEBRON next discussed several practices the on-line environment shares\r
+with traditional publishing on hard copy--for example, peer review of\r
+manuscripts--that are highly important in the academic world.  LEBRON\r
+noted in particular the implications of citation counts for tenure\r
+committees and grants committees.  In the traditional hard-copy\r
+environment, citation counts are readily demonstrable, whereas the\r
+on-line environment represents an ethereal medium to most academics.\r
+\r
+LEBRON remarked several technical and behavioral barriers to electronic\r
+publishing, for instance, the problems in transmission created by special\r
+characters or by complex graphics and halftones.  In addition, she noted\r
+economic limitations such as the storage costs of maintaining back issues\r
+and market or audience education.\r
+\r
+Manuscripts cannot be uploaded to OJCCT, LEBRON explained, because it is\r
+not a bulletin board or E-mail, forms of electronic transmission of\r
+information that have created an ambience clouding people's understanding\r
+of what the journal is attempting to do.  OJCCT, which publishes\r
+peer-reviewed medical articles dealing with the subject of clinical\r
+trials, includes text, tabular material, and graphics, although at this\r
+time it can transmit only line illustrations.\r
+\r
+Next, LEBRON described how AAAS and OCLC arrived at the subject of\r
+clinical trials:  It is 1) a highly statistical discipline that 2) does\r
+not require halftones but can satisfy the needs of its audience with line\r
+illustrations and graphic material, and 3) there is a need for the speedy\r
+dissemination of high-quality research results.  Clinical trials are\r
+research activities that involve the administration of a test treatment\r
+to some experimental unit in order to test its usefulness before it is\r
+made available to the general population.  LEBRON proceeded to give\r
+additional information on OJCCT concerning its editor-in-chief, editorial\r
+board, editorial content, and the types of articles it publishes\r
+(including peer-reviewed research reports and reviews), as well as\r
+features shared by other traditional hard-copy journals.\r
+\r
+Among the advantages of the electronic format are faster dissemination of\r
+information, including raw data, and the absence of space constraints\r
+because pages do not exist.  (This latter fact creates an interesting\r
+situation when it comes to citations.)  Nor are there any issues.  AAAS's\r
+capacity to download materials directly from the journal to a\r
+subscriber's printer, hard drive, or floppy disk helps ensure highly\r
+accurate transcription.  Other features of OJCCT include on-screen alerts\r
+that allow linkage of subsequently published documents to the original\r
+documents; on-line searching by subject, author, title, etc.; indexing of\r
+every single word that appears in an article; viewing access to an\r
+article by component (abstract, full text, or graphs); numbered\r
+paragraphs to replace page counts; publication in Science every thirty\r
+days of indexing of all articles published in the journal;\r
+typeset-quality screens; and Hypertext links that enable subscribers to\r
+bring up Medline abstracts directly without leaving the journal.\r
+\r
+After detailing the two primary ways to gain access to the journal,\r
+through the OCLC network and Compuserv if one desires graphics or through\r
+the Internet if just an ASCII file is desired, LEBRON illustrated the\r
+speedy editorial process and the coding of the document using SGML tags\r
+after it has been accepted for publication.  She also gave an illustrated\r
+tour of the journal, its search-and-retrieval capabilities in particular,\r
+but also including problems associated with scanning in illustrations,\r
+and the importance of on-screen alerts to the medical profession re\r
+retractions or corrections, or more frequently, editorials, letters to\r
+the editors, or follow-up reports.  She closed by inviting the audience\r
+to join AAAS on 1 July, when OJCCT was scheduled to go on-line.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Additional features of OJCCT *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+In the lengthy discussion that followed LEBRON's presentation, these\r
+points emerged:\r
+\r
+     * The SGML text can be tailored as users wish.\r
+\r
+     * All these articles have a fairly simple document definition.\r
+\r
+     * Document-type definitions (DTDs) were developed and given to OJCCT\r
+     for coding.\r
+\r
+     * No articles will be removed from the journal.  (Because there are\r
+     no back issues, there are no lost issues either.  Once a subscriber\r
+     logs onto the journal he or she has access not only to the currently\r
+     published materials, but retrospectively to everything that has been\r
+     published in it.  Thus the table of contents grows bigger.  The date\r
+     of publication serves to distinguish between currently published\r
+     materials and older materials.)\r
+\r
+     * The pricing system for the journal resembles that for most medical\r
+     journals:  for 1992, $95 for a year, plus telecommunications charges\r
+     (there are no connect time charges);    for 1993, $110 for the\r
+     entire year for single users, though the journal can be put on a\r
+     local area network (LAN).  However, only one person can access the\r
+     journal at a time.  Site licenses may come in the future.\r
+\r
+     * AAAS is working closely with colleagues at OCLC to display\r
+     mathematical equations on screen.\r
+\r
+     * Without compromising any steps in the editorial process, the\r
+     technology has reduced the time lag between when a manuscript is\r
+     originally submitted and the time it is accepted; the review process\r
+     does not differ greatly from the standard six-to-eight weeks\r
+     employed by many of the hard-copy journals.  The process still\r
+     depends on people.\r
+\r
+     * As far as a preservation copy is concerned, articles will be\r
+     maintained on the computer permanently and subscribers, as part of\r
+     their subscription, will receive a microfiche-quality archival copy\r
+     of everything published during that year; in addition, reprints can\r
+     be purchased in much the same way as in a hard-copy environment. \r
+     Hard copies are prepared but are not the primary medium for the\r
+     dissemination of the information.\r
+\r
+     * Because OJCCT is not yet on line, it is difficult to know how many\r
+     people would simply browse through the journal on the screen as\r
+     opposed to downloading the whole thing and printing it out; a mix of\r
+     both types of users likely will result.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+PERSONIUS * Developments in technology over the past decade * The CLASS\r
+Project * Advantages for technology and for the CLASS Project *\r
+Developing a network application an underlying assumption of the project\r
+* Details of the scanning process * Print-on-demand copies of books *\r
+Future plans include development of a browsing tool *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Lynne PERSONIUS, assistant director, Cornell Information Technologies for\r
+Scholarly Information Services, Cornell University, first commented on\r
+the tremendous impact that developments in technology over the past ten\r
+years--networking, in particular--have had on the way information is\r
+handled, and how, in her own case, these developments have counterbalanced\r
+Cornell's relative geographical isolation.  Other significant technologies\r
+include scanners, which are much more sophisticated than they were ten years\r
+ago; mass storage and the dramatic savings that result from it in terms of\r
+both space and money relative to twenty or thirty years ago; new and\r
+improved printing technologies, which have greatly affected the distribution\r
+of information; and, of course, digital technologies, whose applicability to\r
+library preservation remains at issue.\r
+\r
+Given that context, PERSONIUS described the College Library Access and\r
+Storage System (CLASS) Project, a library preservation project,\r
+primarily, and what has been accomplished.  Directly funded by the\r
+Commission on Preservation and Access and by the Xerox Corporation, which\r
+has provided a significant amount of hardware, the CLASS Project has been\r
+working with a development team at Xerox to develop a software\r
+application tailored to library preservation requirements.  Within\r
+Cornell, participants in the project have been working jointly with both\r
+library and information technologies.  The focus of the project has been\r
+on reformatting and saving books that are in brittle condition. \r
+PERSONIUS showed Workshop participants a brittle book, and described how\r
+such books were the result of developments in papermaking around the\r
+beginning of the Industrial Revolution.  The papermaking process was\r
+changed so that a significant amount of acid was introduced into the\r
+actual paper itself, which deteriorates as it sits on library shelves.\r
+\r
+One of the advantages for technology and for the CLASS Project is that\r
+the information in brittle books is mostly out of copyright and thus\r
+offers an opportunity to work with material that requires library\r
+preservation, and to create and work on an infrastructure to save the\r
+material.  Acknowledging the familiarity of those working in preservation\r
+with this information, PERSONIUS noted that several things are being\r
+done:  the primary preservation technology used today is photocopying of\r
+brittle material.  Saving the intellectual content of the material is the\r
+main goal.  With microfilm copy, the intellectual content is preserved on\r
+the assumption that in the future the image can be reformatted in any\r
+other way that then exists.\r
+\r
+An underlying assumption of the CLASS Project from the beginning was\r
+that it would develop a network application.  Project staff scan books\r
+at a workstation located in the library, near the brittle material.\r
+An image-server filing system is located at a distance from that\r
+workstation, and a printer is located in another building.  All of the\r
+materials digitized and stored on the image-filing system are cataloged\r
+in the on-line catalogue.  In fact, a record for each of these electronic\r
+books is stored in the RLIN database so that a record exists of what is\r
+in the digital library throughout standard catalogue procedures.  In the\r
+future, researchers working from their own workstations in their offices,\r
+or their networks, will have access--wherever they might be--through a\r
+request server being built into the new digital library.  A second\r
+assumption is that the preferred means of finding the material will be by\r
+looking through a catalogue.  PERSONIUS described the scanning process,\r
+which uses a prototype scanner being developed by Xerox and which scans a\r
+very high resolution image at great speed.  Another significant feature,\r
+because this is a preservation application, is the placing of the pages\r
+that fall apart one for one on the platen.  Ordinarily, a scanner could\r
+be used with some sort of a document feeder, but because of this\r
+application that is not feasible.  Further, because CLASS is a\r
+preservation application, after the paper replacement is made there, a\r
+very careful quality control check is performed.  An original book is\r
+compared to the printed copy and verification is made, before proceeding,\r
+that all of the image, all of the information, has been captured.  Then,\r
+a new library book is produced:  The printed images are rebound by a\r
+commercial binder and a new book is returned to the shelf. \r
+Significantly, the books returned to the library shelves are beautiful\r
+and useful replacements on acid-free paper that should last a long time,\r
+in effect, the equivalent of preservation photocopies.  Thus, the project\r
+has a library of digital books.  In essence, CLASS is scanning and\r
+storing books as 600 dot-per-inch bit-mapped images, compressed using\r
+Group 4 CCITT (i.e., the French acronym for International Consultative\r
+Committee for Telegraph and Telephone) compression.  They are stored as\r
+TIFF files on an optical filing system that is composed of a database\r
+used for searching and locating the books and an optical jukebox that\r
+stores 64 twelve-inch platters.  A very-high-resolution printed copy of\r
+these books at 600 dots per inch is created, using a Xerox DocuTech\r
+printer to make the paper replacements on acid-free paper.\r
+\r
+PERSONIUS maintained that the CLASS Project presents an opportunity to\r
+introduce people to books as digital images by using a paper medium. \r
+Books are returned to the shelves while people are also given the ability\r
+to print on demand--to make their own copies of books.  (PERSONIUS\r
+distributed copies of an engineering journal published by engineering\r
+students at Cornell around 1900 as an example of what a print-on-demand\r
+copy of material might be like.  This very cheap copy would be available\r
+to people to use for their own research purposes and would bridge the gap\r
+between an electronic work and the paper that readers like to have.) \r
+PERSONIUS then attempted to illustrate a very early prototype of\r
+networked access to this digital library.  Xerox Corporation has\r
+developed a prototype of a view station that can send images across the\r
+network to be viewed.\r
+\r
+The particular library brought down for demonstration contained two\r
+mathematics books.  CLASS is developing and will spend the next year\r
+developing an application that allows people at workstations to browse\r
+the books.  Thus, CLASS is developing a browsing tool, on the assumption\r
+that users do not want to read an entire book from a workstation, but\r
+would prefer to be able to look through and decide if they would like to\r
+have a printed copy of it.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Re retrieval software * "Digital file copyright" * Scanning\r
+rate during production * Autosegmentation * Criteria employed in\r
+selecting books for scanning * Compression and decompression of images *\r
+OCR not precluded *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+During the question-and-answer period that followed her presentation,\r
+PERSONIUS made these additional points:\r
+\r
+     * Re retrieval software, Cornell is developing a Unix-based server\r
+     as well as clients for the server that support multiple platforms\r
+     (Macintosh, IBM and Sun workstations), in the hope that people from\r
+     any of those platforms will retrieve books; a further operating\r
+     assumption is that standard interfaces will be used as much as\r
+     possible, where standards can be put in place, because CLASS\r
+     considers this retrieval software a library application and would\r
+     like to be able to look at material not only at Cornell but at other\r
+     institutions.\r
+\r
+     * The phrase "digital file copyright by Cornell University" was\r
+     added at the advice of Cornell's legal staff with the caveat that it\r
+     probably would not hold up in court.  Cornell does not want people\r
+     to copy its books and sell them but would like to keep them\r
+     available for use in a library environment for library purposes.\r
+\r
+     * In production the scanner can scan about 300 pages per hour,\r
+     capturing 600 dots per inch.\r
+\r
+     * The Xerox software has filters to scan halftone material and avoid\r
+     the moire patterns that occur when halftone material is scanned. \r
+     Xerox has been working on hardware and software that would enable\r
+     the scanner itself to recognize this situation and deal with it\r
+     appropriately--a kind of autosegmentation that would enable the\r
+     scanner to handle halftone material as well as text on a single page.\r
+\r
+     * The books subjected to the elaborate process described above were\r
+     selected because CLASS is a preservation project, with the first 500\r
+     books selected coming from Cornell's mathematics collection, because\r
+     they were still being heavily used and because, although they were\r
+     in need of preservation, the mathematics library and the mathematics\r
+     faculty were uncomfortable having them microfilmed.  (They wanted a\r
+     printed copy.)  Thus, these books became a logical choice for this\r
+     project.  Other books were chosen by the project's selection committees\r
+     for experiments with the technology, as well as to meet a demand or need.\r
+\r
+     * Images will be decompressed before they are sent over the line; at\r
+     this time they are compressed and sent to the image filing system\r
+     and then sent to the printer as compressed images; they are returned\r
+     to the workstation as compressed 600-dpi images and the workstation\r
+     decompresses and scales them for display--an inefficient way to\r
+     access the material though it works quite well for printing and\r
+     other purposes.\r
+\r
+     * CLASS is also decompressing on Macintosh and IBM, a slow process\r
+     right now.  Eventually, compression and decompression will take\r
+     place on an image conversion server.  Trade-offs will be made, based\r
+     on future performance testing, concerning where the file is\r
+     compressed and what resolution image is sent.\r
+\r
+     * OCR has not been precluded; images are being stored that have been\r
+     scanned at a high resolution, which presumably would suit them well\r
+     to an OCR process.  Because the material being scanned is about 100\r
+     years old and was printed with less-than-ideal technologies, very\r
+     early and preliminary tests have not produced good results.  But the\r
+     project is capturing an image that is of sufficient resolution to be\r
+     subjected to OCR in the future.  Moreover, the system architecture\r
+     and the system plan have a logical place to store an OCR image if it\r
+     has been captured.  But that is not being done now.\r
+\r
+                                 ******\r
+\r
+SESSION III.  DISTRIBUTION, NETWORKS, AND NETWORKING:  OPTIONS FOR\r
+DISSEMINATION\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ZICH * Issues pertaining to CD-ROMs * Options for publishing in CD-ROM *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Robert ZICH, special assistant to the associate librarian for special\r
+projects, Library of Congress, and moderator of this session, first noted\r
+the blessed but somewhat awkward circumstance of having four very\r
+distinguished people representing networks and networking or at least\r
+leaning in that direction, while lacking anyone to speak from the\r
+strongest possible background in CD-ROMs.  ZICH expressed the hope that\r
+members of the audience would join the discussion.  He stressed the\r
+subtitle of this particular session, "Options for Dissemination," and,\r
+concerning CD-ROMs, the importance of determining when it would be wise\r
+to consider dissemination in CD-ROM versus networks.  A shopping list of\r
+issues pertaining to CD-ROMs included:  the grounds for selecting\r
+commercial publishers, and in-house publication where possible versus\r
+nonprofit or government publication.  A similar list for networks\r
+included:  determining when one should consider dissemination through a\r
+network, identifying the mechanisms or entities that exist to place items\r
+on networks, identifying the pool of existing networks, determining how a\r
+producer  would choose between networks, and identifying the elements of\r
+a business arrangement in a network.\r
+\r
+Options for publishing in CD-ROM:  an outside publisher versus\r
+self-publication.  If an outside publisher is used, it can be nonprofit,\r
+such as the Government Printing Office (GPO) or the National Technical\r
+Information Service (NTIS), in the case of government.  The pros and cons\r
+associated with employing an outside publisher are obvious.  Among the\r
+pros, there is no trouble getting accepted.  One pays the bill and, in\r
+effect, goes one's way.  Among the cons, when one pays an outside\r
+publisher to perform the work, that publisher will perform the work it is\r
+obliged to do, but perhaps without the production expertise and skill in\r
+marketing and dissemination that some would seek.  There is the body of\r
+commercial publishers that do possess that kind of expertise in\r
+distribution and marketing but that obviously are selective.  In\r
+self-publication, one exercises full control, but then one must handle\r
+matters such as distribution and marketing.  Such are some of the options\r
+for publishing in the case of CD-ROM.\r
+\r
+In the case of technical and design issues, which are also important,\r
+there are many matters which many at the Workshop already knew a good\r
+deal about:  retrieval system requirements and costs, what to do about\r
+images, the various capabilities and platforms, the trade-offs between\r
+cost and performance, concerns about local-area networkability,\r
+interoperability, etc.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+LYNCH * Creating networked information is different from using networks\r
+as an access or dissemination vehicle * Networked multimedia on a large\r
+scale does not yet work * Typical CD-ROM publication model a two-edged\r
+sword * Publishing information on a CD-ROM in the present world of\r
+immature standards * Contrast between CD-ROM and network pricing *\r
+Examples demonstrated earlier in the day as a set of insular information\r
+gems * Paramount need to link databases * Layering to become increasingly\r
+necessary * Project NEEDS and the issues of information reuse and active\r
+versus passive use * X-Windows as a way of differentiating between\r
+network access and networked information * Barriers to the distribution\r
+of networked multimedia information * Need for good, real-time delivery\r
+protocols * The question of presentation integrity in client-server\r
+computing in the academic world * Recommendations for producing multimedia\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Clifford LYNCH, director, Library Automation, University of California,\r
+opened his talk with the general observation that networked information\r
+constituted a difficult and elusive topic because it is something just\r
+starting to develop and not yet fully understood.  LYNCH contended that\r
+creating genuinely networked information was different from using\r
+networks as an access or dissemination vehicle and was more sophisticated\r
+and more subtle.  He invited the members of the audience to extrapolate,\r
+from what they heard about the preceding demonstration projects, to what\r
+sort of a world of electronics information--scholarly, archival,\r
+cultural, etc.--they wished to end up with ten or fifteen years from now. \r
+LYNCH suggested that to extrapolate directly from these projects would\r
+produce unpleasant results.\r
+\r
+Putting the issue of CD-ROM in perspective before getting into\r
+generalities on networked information, LYNCH observed that those engaged\r
+in multimedia today who wish to ship a product, so to say, probably do\r
+not have much choice except to use CD-ROM:  networked multimedia on a\r
+large scale basically does not yet work because the technology does not\r
+exist.  For example, anybody who has tried moving images around over the\r
+Internet knows that this is an exciting touch-and-go process, a\r
+fascinating and fertile area for experimentation, research, and\r
+development, but not something that one can become deeply enthusiastic\r
+about committing to production systems at this time.\r
+\r
+This situation will change, LYNCH said.  He differentiated CD-ROM from\r
+the practices that have been followed up to now in distributing data on\r
+CD-ROM.  For LYNCH the problem with CD-ROM is not its portability or its\r
+slowness but the two-edged sword of having the retrieval application and\r
+the user interface inextricably bound up with the data, which is the\r
+typical CD-ROM publication model.  It is not a case of publishing data\r
+but of distributing a typically stand-alone, typically closed system,\r
+all--software, user interface, and data--on a little disk.  Hence, all\r
+the between-disk navigational issues as well as the impossibility in most\r
+cases of integrating data on one disk with that on another.  Most CD-ROM\r
+retrieval software does not network very gracefully at present.  However,\r
+in the present world of immature standards and lack of understanding of\r
+what network information is or what the ground rules are for creating or\r
+using it, publishing information on a CD-ROM does add value in a very\r
+real sense.\r
+\r
+LYNCH drew a contrast between CD-ROM and network pricing and in doing so\r
+highlighted something bizarre in information pricing.  A large\r
+institution such as the University of California has vendors who will\r
+offer to sell information on CD-ROM for a price per year in four digits,\r
+but for the same data (e.g., an abstracting and indexing database) on\r
+magnetic tape, regardless of how many people may use it concurrently,\r
+will quote a price in six digits.\r
+\r
+What is packaged with the CD-ROM in one sense adds value--a complete\r
+access system, not just raw, unrefined information--although it is not\r
+generally perceived that way.  This is because the access software,\r
+although it adds value, is viewed by some people, particularly in the\r
+university environment where there is a very heavy commitment to\r
+networking, as being developed in the wrong direction.\r
+\r
+Given that context, LYNCH described the examples demonstrated as a set of\r
+insular information gems--Perseus, for example, offers nicely linked\r
+information, but would be very difficult to integrate with other\r
+databases, that is, to link together seamlessly with other source files\r
+from other sources.  It resembles an island, and in this respect is\r
+similar to numerous stand-alone projects that are based on videodiscs,\r
+that is, on the single-workstation concept.\r
+\r
+As scholarship evolves in a network environment, the paramount need will\r
+be to link databases.  We must link personal databases to public\r
+databases, to group databases, in fairly seamless ways--which is\r
+extremely difficult in the environments under discussion with copies of\r
+databases proliferating all over the place.\r
+\r
+The notion of layering also struck LYNCH as lurking in several of the\r
+projects demonstrated.  Several databases in a sense constitute\r
+information archives without a significant amount of navigation built in. \r
+Educators, critics, and others will want a layered structure--one that\r
+defines or links paths through the layers to allow users to reach\r
+specific points.  In LYNCH's view, layering will become increasingly\r
+necessary, and not just within a single resource but across resources\r
+(e.g., tracing mythology and cultural themes across several classics\r
+databases as well as a database of Renaissance culture).  This ability to\r
+organize resources, to build things out of multiple other things on the\r
+network or select pieces of it, represented for LYNCH one of the key\r
+aspects of network information.\r
+\r
+Contending that information reuse constituted another significant issue,\r
+LYNCH commended to the audience's attention Project NEEDS (i.e., National\r
+Engineering Education Delivery System).  This project's objective is to\r
+produce a database of engineering courseware as well as the components\r
+that can be used to develop new courseware.  In a number of the existing\r
+applications, LYNCH said, the issue of reuse (how much one can take apart\r
+and reuse in other applications) was not being well considered.  He also\r
+raised the issue of active versus passive use, one aspect of which  is\r
+how much information will be manipulated locally by users.  Most people,\r
+he argued, may do a little browsing and then will wish to print.  LYNCH\r
+was uncertain how these resources would be used by the vast majority of\r
+users in the network environment.\r
+\r
+LYNCH next said a few words about X-Windows as a way of differentiating\r
+between network access and networked information.  A number of the\r
+applications demonstrated at the Workshop could be rewritten to use X\r
+across the network, so that one could run them from any X-capable device-\r
+-a workstation, an X terminal--and transact with a database across the\r
+network.  Although this opens up access a little, assuming one has enough\r
+network to handle it, it does not provide an interface to develop a\r
+program that conveniently integrates information from multiple databases. \r
+X is a viewing technology that has limits.  In a real sense, it is just a\r
+graphical version of remote log-in across the network.  X-type applications\r
+represent only one step in the progression towards real access.\r
+\r
+LYNCH next discussed barriers to the distribution of networked multimedia\r
+information.  The heart of the problem is a lack of standards to provide\r
+the ability for computers to talk to each other, retrieve information,\r
+and shuffle it around fairly casually.  At the moment, little progress is\r
+being made on standards for networked information; for example, present\r
+standards do not cover images, digital voice, and digital video.  A\r
+useful tool kit of exchange formats for basic texts is only now being\r
+assembled.  The synchronization of content streams (i.e., synchronizing a\r
+voice track to a video track, establishing temporal relations between\r
+different components in a multimedia object) constitutes another issue\r
+for networked multimedia that is just beginning to receive attention.\r
+\r
+Underlying network protocols also need some work; good, real-time\r
+delivery protocols on the Internet do not yet exist.  In LYNCH's view,\r
+highly important in this context is the notion of networked digital\r
+object IDs, the ability of one object on the network to point to another\r
+object (or component thereof) on the network.  Serious bandwidth issues\r
+also exist.  LYNCH was uncertain if billion-bit-per-second networks would\r
+prove sufficient if numerous people ran video in parallel.\r
+\r
+LYNCH concluded by offering an issue for database creators to consider,\r
+as well as several comments about what might constitute good trial\r
+multimedia experiments.  In a networked information world the database\r
+builder or service builder (publisher) does not exercise the same\r
+extensive control over the integrity of the presentation; strange\r
+programs "munge" with one's data before the user sees it.  Serious\r
+thought must be given to what guarantees integrity of presentation.  Part\r
+of that is related to where one draws the boundaries around a networked\r
+information service.  This question of presentation integrity in\r
+client-server computing has not been stressed enough in the academic\r
+world, LYNCH argued, though commercial service providers deal with it\r
+regularly.\r
+\r
+Concerning multimedia, LYNCH observed that good multimedia at the moment\r
+is hideously expensive to produce.  He recommended producing multimedia\r
+with either very high sale value, or multimedia with a very long life\r
+span, or multimedia that will have a very broad usage base and whose\r
+costs therefore can be amortized among large numbers of users.  In this\r
+connection, historical and humanistically oriented material may be a good\r
+place to start, because it tends to have a longer life span than much of\r
+the scientific material, as well as a wider user base.  LYNCH noted, for\r
+example, that American Memory fits many of the criteria outlined.  He\r
+remarked the extensive discussion about bringing the Internet or the\r
+National Research and Education Network (NREN) into the K-12 environment\r
+as a way of helping the American educational system.\r
+\r
+LYNCH closed by noting that the kinds of applications demonstrated struck\r
+him as excellent justifications of broad-scale networking for K-12, but\r
+that at this time no "killer" application exists to mobilize the K-12\r
+community to obtain connectivity.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Dearth of genuinely interesting applications on the network\r
+a slow-changing situation * The issue of the integrity of presentation in\r
+a networked environment * Several reasons why CD-ROM software does not\r
+network *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+During the discussion period that followed LYNCH's presentation, several\r
+additional points were made.\r
+\r
+LYNCH reiterated even more strongly his contention that, historically,\r
+once one goes outside high-end science and the group of those who need\r
+access to supercomputers, there is a great dearth of genuinely\r
+interesting applications on the network.  He saw this situation changing\r
+slowly, with some of the scientific databases and scholarly discussion\r
+groups and electronic journals coming on as well as with the availability\r
+of Wide Area Information Servers (WAIS) and some of the databases that\r
+are being mounted there.  However, many of those things do not seem to\r
+have piqued great popular interest.  For instance, most high school\r
+students of LYNCH's acquaintance would not qualify as devotees of serious\r
+molecular biology.\r
+\r
+Concerning the issue of the integrity of presentation, LYNCH believed\r
+that a couple of information providers have laid down the law at least on\r
+certain things.  For example, his recollection was that the National\r
+Library of Medicine feels strongly that one needs to employ the\r
+identifier field if he or she is to mount a database commercially.  The\r
+problem with a real networked environment is that one does not know who\r
+is reformatting and reprocessing one's data when one enters a client\r
+server mode.  It becomes anybody's guess, for example, if the network\r
+uses a Z39.50 server, or what clients are doing with one's data.  A data\r
+provider can say that his contract will only permit clients to have\r
+access to his data after he vets them and their presentation and makes\r
+certain it suits him.  But LYNCH held out little expectation that the\r
+network marketplace would evolve in that way, because it required too\r
+much prior negotiation.\r
+\r
+CD-ROM software does not network for a variety of reasons, LYNCH said. \r
+He speculated that CD-ROM publishers are not eager to have their products\r
+really hook into wide area networks, because they fear it will make their\r
+data suppliers nervous.  Moreover, until relatively recently, one had to\r
+be rather adroit to run a full TCP/IP stack plus applications on a\r
+PC-size machine, whereas nowadays it is becoming easier as PCs grow\r
+bigger and faster.  LYNCH also speculated that software providers had not\r
+heard from their customers until the last year or so, or had not heard\r
+from enough of their customers.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+BESSER * Implications of disseminating images on the network; planning\r
+the distribution of multimedia documents poses two critical\r
+implementation problems * Layered approach represents the way to deal\r
+with users' capabilities * Problems in platform design; file size and its\r
+implications for networking * Transmission of megabyte size images\r
+impractical * Compression and decompression at the user's end * Promising\r
+trends for compression * A disadvantage of using X-Windows * A project at\r
+the Smithsonian that mounts images on several networks *  \r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Howard BESSER, School of Library and Information Science, University of\r
+Pittsburgh, spoke primarily about multimedia, focusing on images and the\r
+broad implications of disseminating them on the network.  He argued that\r
+planning the distribution of multimedia documents posed two critical\r
+implementation problems, which he framed in the form of two questions: \r
+1) What platform will one use and what hardware and software will users\r
+have for viewing of the material?  and 2) How can one deliver a\r
+sufficiently robust set of information in an accessible format in a\r
+reasonable amount of time?  Depending on whether network or CD-ROM is the\r
+medium used, this question raises different issues of storage,\r
+compression, and transmission.\r
+\r
+Concerning the design of platforms (e.g., sound, gray scale, simple\r
+color, etc.) and the various capabilities users may have, BESSER\r
+maintained that a layered approach was the way to deal with users'\r
+capabilities.  A result would be that users with less powerful\r
+workstations would simply have less functionality.  He urged members of\r
+the audience to advocate standards and accompanying software that handle\r
+layered functionality across a wide variety of platforms.\r
+\r
+BESSER also addressed problems in platform design, namely, deciding how\r
+large a machine to design for situations when the largest number of users\r
+have the lowest level of the machine, and one desires higher\r
+functionality.  BESSER then proceeded to the question of file size and\r
+its implications for networking.  He discussed still images in the main. \r
+For example, a digital color image that fills the screen of a standard\r
+mega-pel workstation (Sun or Next) will require one megabyte of storage\r
+for an eight-bit image or three megabytes of storage for a true color or\r
+twenty-four-bit image.  Lossless compression algorithms (that is,\r
+computational procedures in which no data is lost in the process of\r
+compressing [and decompressing] an image--the exact bit-representation is\r
+maintained) might bring storage down to a third of a megabyte per image,\r
+but not much further than that.  The question of size makes it difficult\r
+to fit an appropriately sized set of these images on a single disk or to\r
+transmit them quickly enough on a network.\r
+\r
+With these full screen mega-pel images that constitute a third of a\r
+megabyte, one gets 1,000-3,000 full-screen images on a one-gigabyte disk;\r
+a standard CD-ROM represents approximately 60 percent of that.  Storing\r
+images the size of a PC screen (just 8 bit color) increases storage\r
+capacity to 4,000-12,000 images per gigabyte; 60 percent of that gives\r
+one the size of a CD-ROM, which in turn creates a major problem.  One\r
+cannot have full-screen, full-color images with lossless compression; one\r
+must compress them or use a lower resolution.  For megabyte-size images,\r
+anything slower than a T-1 speed is impractical.  For example, on a\r
+fifty-six-kilobaud line, it takes three minutes to transfer a\r
+one-megabyte file, if it is not compressed; and this speed assumes ideal\r
+circumstances (no other user contending for network bandwidth).  Thus,\r
+questions of disk access, remote display, and current telephone\r
+connection speed make transmission of megabyte-size images impractical.\r
+\r
+BESSER then discussed ways to deal with these large images, for example,\r
+compression and decompression at the user's end.  In this connection, the\r
+issues of how much one is willing to lose in the compression process and\r
+what image quality one needs in the first place are unknown.  But what is\r
+known is that compression entails some loss of data.  BESSER urged that\r
+more studies be conducted on image quality in different situations, for\r
+example, what kind of images are needed for what kind of disciplines, and\r
+what kind of image quality is needed for a browsing tool, an intermediate\r
+viewing tool, and archiving.\r
+\r
+BESSER remarked two promising trends for compression:  from a technical\r
+perspective, algorithms that use what is called subjective redundancy\r
+employ principles from visual psycho-physics to identify and remove\r
+information from the image that the human eye cannot perceive; from an\r
+interchange and interoperability perspective, the JPEG (i.e., Joint\r
+Photographic Experts Group, an ISO standard) compression algorithms also\r
+offer promise.  These issues of compression and decompression, BESSER\r
+argued, resembled those raised earlier concerning the design of different\r
+platforms.  Gauging the capabilities of potential users constitutes a\r
+primary goal.  BESSER advocated layering or separating the images from\r
+the applications that retrieve and display them, to avoid tying them to\r
+particular software.\r
+\r
+BESSER detailed several lessons learned from his work at Berkeley with\r
+Imagequery, especially the advantages and disadvantages of using\r
+X-Windows.  In the latter category, for example, retrieval is tied\r
+directly to one's data, an intolerable situation in the long run on a\r
+networked system.  Finally, BESSER described a project of Jim Wallace at\r
+the Smithsonian Institution, who is mounting images in a extremely\r
+rudimentary way on the Compuserv and Genie networks and is preparing to\r
+mount them on America On Line.  Although the average user takes over\r
+thirty minutes to download these images (assuming a fairly fast modem),\r
+nevertheless, images have been downloaded 25,000 times.\r
+\r
+BESSER concluded his talk with several comments on the business\r
+arrangement between the Smithsonian and Compuserv.  He contended that not\r
+enough is known concerning the value of images.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Creating digitized photographic collections nearly\r
+impossible except with large organizations like museums * Need for study\r
+to determine quality of images users will tolerate *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+During the brief exchange between LESK and BESSER that followed, several\r
+clarifications emerged.\r
+\r
+LESK argued that the photographers were far ahead of BESSER:  It is\r
+almost impossible to create such digitized photographic collections\r
+except with large organizations like museums, because all the\r
+photographic agencies have been going crazy about this and will not sign\r
+licensing agreements on any sort of reasonable terms.  LESK had heard\r
+that National Geographic, for example, had tried to buy the right to use\r
+some image in some kind of educational production for $100 per image, but\r
+the photographers will not touch it.  They want accounting and payment\r
+for each use, which cannot be accomplished within the system.  BESSER\r
+responded that a consortium of photographers, headed by a former National\r
+Geographic photographer, had started assembling its own collection of\r
+electronic reproductions of images, with the money going back to the\r
+cooperative.\r
+\r
+LESK contended that BESSER was unnecessarily pessimistic about multimedia\r
+images, because people are accustomed to low-quality images, particularly\r
+from video.  BESSER urged the launching of a study to determine what\r
+users would tolerate, what they would feel comfortable with, and what\r
+absolutely is the highest quality they would ever need.  Conceding that\r
+he had adopted a dire tone in order to arouse people about the issue,\r
+BESSER closed on a sanguine note by saying that he would not be in this\r
+business if he did not think that things could be accomplished.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+LARSEN * Issues of scalability and modularity * Geometric growth of the\r
+Internet and the role played by layering * Basic functions sustaining\r
+this growth * A library's roles and functions in a network environment *\r
+Effects of implementation of the Z39.50 protocol for information\r
+retrieval on the library system * The trade-off between volumes of data\r
+and its potential usage * A snapshot of current trends *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Ronald LARSEN, associate director for information technology, University\r
+of Maryland at College Park, first addressed the issues of scalability\r
+and modularity.  He noted the difficulty of anticipating the effects of\r
+orders-of-magnitude growth, reflecting on the twenty years of experience\r
+with the Arpanet and Internet.  Recalling the day's demonstrations of\r
+CD-ROM and optical disk material, he went on to ask if the field has yet\r
+learned how to scale new systems to enable delivery and dissemination\r
+across large-scale networks.\r
+\r
+LARSEN focused on the geometric growth of the Internet from its inception\r
+circa 1969 to the present, and the adjustments required to respond to\r
+that rapid growth.  To illustrate the issue of scalability, LARSEN\r
+considered computer networks as including three generic components: \r
+computers, network communication nodes, and communication media.  Each\r
+component scales (e.g., computers range from PCs to supercomputers;\r
+network nodes scale from interface cards in a PC through sophisticated\r
+routers and gateways; and communication media range from 2,400-baud\r
+dial-up facilities through 4.5-Mbps backbone links, and eventually to\r
+multigigabit-per-second communication lines), and architecturally, the\r
+components are organized to scale hierarchically from local area networks\r
+to international-scale networks.  Such growth is made possible by\r
+building layers of communication protocols, as BESSER pointed out.\r
+By layering both physically and logically, a sense of scalability is\r
+maintained from local area networks in offices, across campuses, through\r
+bridges, routers, campus backbones, fiber-optic links, etc., up into\r
+regional networks and ultimately into national and international\r
+networks.\r
+\r
+LARSEN then illustrated the geometric growth over a two-year period--\r
+through September 1991--of the number of networks that comprise the\r
+Internet.  This growth has been sustained largely by the availability of\r
+three basic functions:  electronic mail, file transfer (ftp), and remote\r
+log-on (telnet).  LARSEN also reviewed the growth in the kind of traffic\r
+that occurs on the network.  Network traffic reflects the joint contributions\r
+of a larger population of users and increasing use per user.  Today one sees\r
+serious applications involving moving images across the network--a rarity\r
+ten years ago.  LARSEN recalled and concurred with BESSER's main point\r
+that the interesting problems occur at the application level.\r
+\r
+LARSEN then illustrated a model of a library's roles and functions in a\r
+network environment.  He noted, in particular, the placement of on-line\r
+catalogues onto the network and patrons obtaining access to the library\r
+increasingly through local networks, campus networks, and the Internet. \r
+LARSEN supported LYNCH's earlier suggestion that we need to address\r
+fundamental questions of networked information in order to build\r
+environments that scale in the information sense as well as in the\r
+physical sense.\r
+\r
+LARSEN supported the role of the library system as the access point into\r
+the nation's electronic collections.  Implementation of the Z39.50\r
+protocol for information retrieval would make such access practical and\r
+feasible.  For example, this would enable patrons in Maryland to search\r
+California libraries, or other libraries around the world that are\r
+conformant with Z39.50 in a manner that is familiar to University of\r
+Maryland patrons.  This client-server model also supports moving beyond\r
+secondary content into primary content.  (The notion of how one links\r
+from secondary content to primary content, LARSEN said, represents a\r
+fundamental problem that requires rigorous thought.)  After noting\r
+numerous network experiments in accessing full-text materials, including\r
+projects supporting the ordering of materials across the network, LARSEN\r
+revisited the issue of transmitting high-density, high-resolution color\r
+images across the network and the large amounts of bandwidth they\r
+require.  He went on to address the bandwidth and synchronization\r
+problems inherent in sending full-motion video across the network.\r
+\r
+LARSEN illustrated the trade-off between volumes of data in bytes or\r
+orders of magnitude and the potential usage of that data.  He discussed\r
+transmission rates (particularly, the time it takes to move various forms\r
+of information), and what one could do with a network supporting\r
+multigigabit-per-second transmission.  At the moment, the network\r
+environment includes a composite of data-transmission requirements,\r
+volumes and forms, going from steady to bursty (high-volume) and from\r
+very slow to very fast.  This aggregate must be considered in the design,\r
+construction, and operation of multigigabyte networks.\r
+\r
+LARSEN's objective is to use the networks and library systems now being\r
+constructed to increase access to resources wherever they exist, and\r
+thus, to evolve toward an on-line electronic virtual library.\r
+\r
+LARSEN concluded by offering a snapshot of current trends:  continuing\r
+geometric growth in network capacity and number of users; slower\r
+development of applications; and glacial development and adoption of\r
+standards.  The challenge is to design and develop each new application\r
+system with network access and scalability in mind.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+BROWNRIGG * Access to the Internet cannot be taken for granted * Packet\r
+radio and the development of MELVYL in 1980-81 in the Division of Library\r
+Automation at the University of California  *  Design criteria for packet\r
+radio * A demonstration project in San Diego and future plans * Spread\r
+spectrum * Frequencies at which the radios will run and plans to\r
+reimplement the WAIS server software in the public domain * Need for an\r
+infrastructure of radios that do not move around * \r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Edwin BROWNRIGG, executive director, Memex Research Institute, first\r
+polled the audience in order to seek out regular users of the Internet as\r
+well as those planning to use it some time in the future.  With nearly\r
+everybody in the room falling into one category or the other, BROWNRIGG\r
+made a point re access, namely that numerous individuals, especially those\r
+who use the Internet every day, take for granted their access to it, the\r
+speeds with which they are connected, and how well it all works. \r
+However, as BROWNRIGG discovered between 1987 and 1989 in Australia,\r
+if one wants access to the Internet but cannot afford it or has some\r
+physical boundary that prevents her or him from gaining access, it can\r
+be extremely frustrating.  He suggested that because of economics and\r
+physical barriers we were beginning to create a world of haves and have-nots\r
+in the process of scholarly communication, even in the United States.\r
+\r
+BROWNRIGG detailed the development of MELVYL in academic year 1980-81 in\r
+the Division of Library Automation at the University of California, in\r
+order to underscore the issue of access to the system, which at the\r
+outset was extremely limited.  In short, the project needed to build a\r
+network, which at that time entailed use of satellite technology, that is,\r
+putting earth stations on campus and also acquiring some terrestrial links\r
+from the State of California's microwave system.  The installation of\r
+satellite links, however, did not solve the problem (which actually\r
+formed part of a larger problem involving politics and financial resources).\r
+For while the project team could get a signal onto a campus, it had no means\r
+of distributing the signal throughout the campus.  The solution involved\r
+adopting a recent development in wireless communication called packet radio,\r
+which combined the basic notion of packet-switching with radio.  The project\r
+used this technology to get the signal from a point on campus where it\r
+came down, an earth station for example, into the libraries, because it\r
+found that wiring the libraries, especially the older marble buildings,\r
+would cost $2,000-$5,000 per terminal.\r
+\r
+BROWNRIGG noted that, ten years ago, the project had neither the public\r
+policy nor the technology that would have allowed it to use packet radio\r
+in any meaningful way.  Since then much had changed.  He proceeded to\r
+detail research and development of the technology, how it is being\r
+deployed in California, and what direction he thought it would take.\r
+The design criteria are to produce a high-speed, one-time, low-cost,\r
+high-quality, secure, license-free device (packet radio) that one can\r
+plug in and play today, forget about it, and have access to the Internet. \r
+By high speed, BROWNRIGG meant 1 megabyte and 1.5 megabytes.  Those units\r
+have been built, he continued, and are in the process of being\r
+type-certified by an independent underwriting laboratory so that they can\r
+be type-licensed by the Federal Communications Commission.  As is the\r
+case with citizens band, one will be able to purchase a unit and not have\r
+to worry about applying for a license.\r
+\r
+The basic idea, BROWNRIGG elaborated, is to take high-speed radio data\r
+transmission and create a backbone network that at certain strategic\r
+points in the network will "gateway" into a medium-speed packet radio\r
+(i.e., one that runs at 38.4 kilobytes), so that perhaps by 1994-1995\r
+people, like those in the audience for the price of a VCR could purchase\r
+a medium-speed radio for the office or home, have full network connectivity\r
+to the Internet, and partake of all its services, with no need for an FCC\r
+license and no regular bill from the local common carrier.  BROWNRIGG\r
+presented several details of a demonstration project currently taking\r
+place in San Diego and described plans, pending funding, to install a\r
+full-bore network in the San Francisco area.  This network will have 600\r
+nodes running at backbone speeds, and 100 of these nodes will be libraries,\r
+which in turn will be the gateway ports to the 38.4 kilobyte radios that\r
+will give coverage for the neighborhoods surrounding the libraries.\r
+\r
+BROWNRIGG next explained Part 15.247, a new rule within Title 47 of the\r
+Code of Federal Regulations enacted by the FCC in 1985.  This rule\r
+challenged the industry, which has only now risen to the occasion, to\r
+build a radio that would run at no more than one watt of output power and\r
+use a fairly exotic method of modulating the radio wave called spread\r
+spectrum.  Spread spectrum in fact permits the building of networks so\r
+that numerous data communications can occur simultaneously, without\r
+interfering with each other, within the same wide radio channel.\r
+\r
+BROWNRIGG explained that the frequencies at which the radios would run\r
+are very short wave signals.  They are well above standard microwave and\r
+radar.  With a radio wave that small, one watt becomes a tremendous punch\r
+per bit and thus makes transmission at reasonable speed possible.  In\r
+order to minimize the potential for congestion, the project is\r
+undertaking to reimplement software which has been available in the\r
+networking business and is taken for granted now, for example, TCP/IP,\r
+routing algorithms, bridges, and gateways.  In addition, the project\r
+plans to take the WAIS server software in the public domain and\r
+reimplement it so that one can have a WAIS server on a Mac instead of a\r
+Unix machine.  The Memex Research Institute believes that libraries, in\r
+particular, will want to use the WAIS servers with packet radio.  This\r
+project, which has a team of about twelve people, will run through 1993\r
+and will include the 100 libraries already mentioned as well as other\r
+professionals such as those in the medical profession, engineering, and\r
+law.  Thus, the need is to create an infrastructure of radios that do not\r
+move around, which, BROWNRIGG hopes, will solve a problem not only for\r
+libraries but for individuals who, by and large today, do not have access\r
+to the Internet from their homes and offices.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Project operating frequencies *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+During a brief discussion period, which also concluded the day's\r
+proceedings, BROWNRIGG stated that the project was operating in four\r
+frequencies.  The slow speed is operating at 435 megahertz, and it would\r
+later go up to 920 megahertz.  With the high-speed frequency, the\r
+one-megabyte radios will run at 2.4 gigabits, and 1.5 will run at 5.7. \r
+At 5.7, rain can be a factor, but it would have to be tropical rain,\r
+unlike what falls in most parts of the United States.\r
+\r
+                                 ******\r
+\r
+SESSION IV.  IMAGE CAPTURE, TEXT CAPTURE, OVERVIEW OF TEXT AND\r
+             IMAGE STORAGE FORMATS\r
+\r
+William HOOTON, vice president of operations, I-NET, moderated this session.\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+KENNEY * Factors influencing development of CXP * Advantages of using\r
+digital technology versus photocopy and microfilm * A primary goal of\r
+CXP; publishing challenges * Characteristics of copies printed * Quality\r
+of samples achieved in image capture * Several factors to be considered\r
+in choosing scanning * Emphasis of CXP on timely and cost-effective\r
+production of black-and-white printed facsimiles * Results of producing\r
+microfilm from digital files * Advantages of creating microfilm * Details\r
+concerning production * Costs * Role of digital technology in library\r
+preservation *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Anne KENNEY, associate director, Department of Preservation and\r
+Conservation, Cornell University, opened her talk by observing that the\r
+Cornell Xerox Project (CXP) has been guided by the assumption that the\r
+ability to produce printed facsimiles or to replace paper with paper\r
+would be important, at least for the present generation of users and\r
+equipment.  She described three factors that influenced development of\r
+the project:  1) Because the project has emphasized the preservation of\r
+deteriorating brittle books, the quality of what was produced had to be\r
+sufficiently high to return a paper replacement to the shelf.  CXP was\r
+only interested in using:  2) a system that was cost-effective, which\r
+meant that it had to be cost-competitive with the processes currently\r
+available, principally photocopy and microfilm, and 3) new or currently\r
+available product hardware and software.\r
+\r
+KENNEY described the advantages that using digital technology offers over\r
+both photocopy and microfilm:  1) The potential exists to create a higher\r
+quality reproduction of a deteriorating original than conventional\r
+light-lens technology.  2) Because a digital image is an encoded\r
+representation, it can be reproduced again and again with no resulting\r
+loss of quality, as opposed to the situation with light-lens processes,\r
+in which there is discernible difference between a second and a\r
+subsequent generation of an image.  3) A digital image can be manipulated\r
+in a number of ways to improve image capture; for example, Xerox has\r
+developed a windowing application that enables one to capture a page\r
+containing both text and illustrations in a manner that optimizes the\r
+reproduction of both.  (With light-lens technology, one must choose which\r
+to optimize, text or the illustration; in preservation microfilming, the\r
+current practice is to shoot an illustrated page twice, once to highlight\r
+the text and the second time to provide the best capture for the\r
+illustration.)  4) A digital image can also be edited, density levels\r
+adjusted to remove underlining and stains, and to increase legibility for\r
+faint documents.  5) On-screen inspection can take place at the time of\r
+initial setup and adjustments made prior to scanning, factors that\r
+substantially reduce the number of retakes required in quality control.\r
+\r
+A primary goal of CXP has been to evaluate the paper output printed on\r
+the Xerox DocuTech, a high-speed printer that produces 600-dpi pages from\r
+scanned images at a rate of 135 pages a minute.  KENNEY recounted several\r
+publishing challenges to represent faithful and legible reproductions of\r
+the originals that the 600-dpi copy for the most part successfully\r
+captured.  For example, many of the deteriorating volumes in the project\r
+were heavily illustrated with fine line drawings or halftones or came in\r
+languages such as Japanese, in which the buildup of characters comprised\r
+of varying strokes is difficult to reproduce at lower resolutions; a\r
+surprising number of them came with annotations and mathematical\r
+formulas, which it was critical to be able to duplicate exactly.\r
+\r
+KENNEY noted that 1) the copies are being printed on paper that meets the\r
+ANSI standards for performance, 2) the DocuTech printer meets the machine\r
+and toner requirements for proper adhesion of print to page, as described\r
+by the National Archives, and thus 3) paper product is considered to be\r
+the archival equivalent of preservation photocopy.\r
+\r
+KENNEY then discussed several samples of the quality achieved in the\r
+project that had been distributed in a handout, for example, a copy of a\r
+print-on-demand version of the 1911 Reed lecture on the steam turbine,\r
+which contains halftones, line drawings, and illustrations embedded in\r
+text; the first four loose pages in the volume compared the capture\r
+capabilities of scanning to photocopy for a standard test target, the\r
+IEEE standard 167A 1987 test chart.  In all instances scanning proved\r
+superior to photocopy, though only slightly more so in one.\r
+\r
+Conceding the simplistic nature of her review of the quality of scanning\r
+to photocopy, KENNEY described it as one representation of the kinds of\r
+settings that could be used with scanning capabilities on the equipment\r
+CXP uses.  KENNEY also pointed out that CXP investigated the quality\r
+achieved with binary scanning only, and noted the great promise in gray\r
+scale and color scanning, whose advantages and disadvantages need to be\r
+examined.  She argued further that scanning resolutions and file formats\r
+can represent a complex trade-off between the time it takes to capture\r
+material, file size, fidelity to the original, and on-screen display; and\r
+printing and equipment availability.  All these factors must be taken\r
+into consideration.\r
+\r
+CXP placed primary emphasis on the production in a timely and\r
+cost-effective manner of printed facsimiles that consisted largely of\r
+black-and-white text.  With binary scanning, large files may be\r
+compressed efficiently and in a lossless manner (i.e., no data is lost in\r
+the process of compressing [and decompressing] an image--the exact\r
+bit-representation is maintained) using Group 4 CCITT (i.e., the French\r
+acronym for International Consultative Committee for Telegraph and\r
+Telephone) compression.  CXP was getting compression ratios of about\r
+forty to one.  Gray-scale compression, which primarily uses JPEG, is much\r
+less economical and can represent a lossy compression (i.e., not\r
+lossless), so that as one compresses and decompresses, the illustration\r
+is subtly changed.  While binary files produce a high-quality printed\r
+version, it appears 1) that other combinations of spatial resolution with\r
+gray and/or color hold great promise as well, and 2) that gray scale can\r
+represent a tremendous advantage for on-screen viewing.  The quality\r
+associated with binary and gray scale also depends on the equipment used. \r
+For instance, binary scanning produces a much better copy on a binary\r
+printer.\r
+\r
+Among CXP's findings concerning the production of microfilm from digital\r
+files, KENNEY reported that the digital files for the same Reed lecture\r
+were used to produce sample film using an electron beam recorder.  The\r
+resulting film was faithful to the image capture of the digital files,\r
+and while CXP felt that the text and image pages represented in the Reed\r
+lecture were superior to that of the light-lens film, the resolution\r
+readings for the 600 dpi were not as high as standard microfilming. \r
+KENNEY argued that the standards defined for light-lens technology are\r
+not totally transferable to a digital environment.  Moreover, they are\r
+based on definition of quality for a preservation copy.  Although making\r
+this case will prove to be a long, uphill struggle, CXP plans to continue\r
+to investigate the issue over the course of the next year.\r
+\r
+KENNEY concluded this portion of her talk with a discussion of the\r
+advantages of creating film:  it can serve as a primary backup and as a\r
+preservation master to the digital file; it could then become the print\r
+or production master and service copies could be paper, film, optical\r
+disks, magnetic media, or on-screen display.\r
+\r
+Finally, KENNEY presented details re production:\r
+\r
+     * Development and testing of a moderately-high resolution production\r
+     scanning workstation represented a third goal of CXP; to date, 1,000\r
+     volumes have been scanned, or about 300,000 images.\r
+\r
+     * The resulting digital files are stored and used to produce\r
+     hard-copy replacements for the originals and additional prints on\r
+     demand; although the initial costs are high, scanning technology\r
+     offers an affordable means for reformatting brittle material.\r
+\r
+     * A technician in production mode can scan 300 pages per hour when\r
+     performing single-sheet scanning, which is a necessity when working\r
+     with truly brittle paper; this figure is expected to increase\r
+     significantly with subsequent iterations of the software from Xerox;\r
+     a three-month time-and-cost study of scanning found that the average\r
+     300-page book would take about an hour and forty minutes to scan\r
+     (this figure included the time for setup, which involves keying in\r
+     primary bibliographic data, going into quality control mode to\r
+     define page size, establishing front-to-back registration, and\r
+     scanning sample pages to identify a default range of settings for\r
+     the entire book--functions not dissimilar to those performed by\r
+     filmers or those preparing a book for photocopy).\r
+\r
+     * The final step in the scanning process involved rescans, which\r
+     happily were few and far between, representing well under 1 percent\r
+     of the total pages scanned.\r
+\r
+In addition to technician time, CXP costed out equipment, amortized over\r
+four years, the cost of storing and refreshing the digital files every\r
+four years, and the cost of printing and binding, book-cloth binding, a\r
+paper reproduction.  The total amounted to a little under $65 per single\r
+300-page volume, with 30 percent overhead included--a figure competitive\r
+with the prices currently charged by photocopy vendors.\r
+\r
+Of course, with scanning, in addition to the paper facsimile, one is left\r
+with a digital file from which subsequent copies of the book can be\r
+produced for a fraction of the cost of photocopy, with readers afforded\r
+choices in the form of these copies.\r
+\r
+KENNEY concluded that digital technology offers an electronic means for a\r
+library preservation effort to pay for itself.  If a brittle-book program\r
+included the means of disseminating reprints of books that are in demand\r
+by libraries and researchers alike, the initial investment in capture\r
+could be recovered and used to preserve additional but less popular\r
+books.  She disclosed that an economic model for a self-sustaining\r
+program could be developed for CXP's report to the Commission on\r
+Preservation and Access (CPA).\r
+\r
+KENNEY stressed that the focus of CXP has been on obtaining high quality\r
+in a production environment.  The use of digital technology is viewed as\r
+an affordable alternative to other reformatting options.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ANDRE * Overview and history of NATDP * Various agricultural CD-ROM\r
+products created inhouse and by service bureaus * Pilot project on\r
+Internet transmission * Additional products in progress *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Pamela ANDRE, associate director for automation, National Agricultural\r
+Text Digitizing Program (NATDP), National Agricultural Library (NAL),\r
+presented an overview of NATDP, which has been underway at NAL the last\r
+four years, before Judith ZIDAR discussed the technical details.  ANDRE\r
+defined agricultural information as a broad range of material going from\r
+basic and applied research in the hard sciences to the one-page pamphlets\r
+that are distributed by the cooperative state extension services on such\r
+things as how to grow blueberries.\r
+\r
+NATDP began in late 1986 with a meeting of representatives from the\r
+land-grant library community to deal with the issue of electronic\r
+information.  NAL and forty-five of these libraries banded together to\r
+establish this project--to evaluate the technology for converting what\r
+were then source documents in paper form into electronic form, to provide\r
+access to that digital information, and then to distribute it. \r
+Distributing that material to the community--the university community as\r
+well as the extension service community, potentially down to the county\r
+level--constituted the group's chief concern.\r
+\r
+Since January 1988 (when the microcomputer-based scanning system was\r
+installed at NAL), NATDP has done a variety of things, concerning which\r
+ZIDAR would provide further details.  For example, the first technology\r
+considered in the project's discussion phase was digital videodisc, which\r
+indicates how long ago it was conceived.\r
+\r
+Over the four years of this project, four separate CD-ROM products on\r
+four different agricultural topics were created, two at a\r
+scanning-and-OCR station installed at NAL, and two by service bureaus. \r
+Thus, NATDP has gained comparative information in terms of those relative\r
+costs.  Each of these products contained the full ASCII text as well as\r
+page images of the material, or between 4,000 and 6,000 pages of material\r
+on these disks.  Topics included aquaculture, food, agriculture and\r
+science (i.e., international agriculture and research), acid rain, and\r
+Agent Orange, which was the final product distributed (approximately\r
+eighteen months before the Workshop).\r
+\r
+The third phase of NATDP focused on delivery mechanisms other than\r
+CD-ROM.  At the suggestion of Clifford LYNCH, who was a technical\r
+consultant to the project at this point, NATDP became involved with the\r
+Internet and initiated a project with the help of North Carolina State\r
+University, in which fourteen of the land-grant university libraries are\r
+transmitting digital images over the Internet in response to interlibrary\r
+loan requests--a topic for another meeting.  At this point, the pilot\r
+project had been completed for about a year and the final report would be\r
+available shortly after the Workshop.  In the meantime, the project's\r
+success had led to its extension.  (ANDRE noted that one of the first\r
+things done under the program title was to select a retrieval package to\r
+use with subsequent products; Windows Personal Librarian was the package\r
+of choice after a lengthy evaluation.)\r
+  \r
+Three additional products had been planned and were in progress:\r
+\r
+     1) An arrangement with the American Society of Agronomy--a\r
+     professional society that has published the Agronomy Journal since\r
+     about 1908--to scan and create bit-mapped images of its journal. \r
+     ASA granted permission first to put and then to distribute this\r
+     material in electronic form, to hold it at NAL, and to use these\r
+     electronic images as a mechanism to deliver documents or print out\r
+     material for patrons, among other uses.  Effectively, NAL has the\r
+     right to use this material in support of its program. \r
+     (Significantly, this arrangement offers a potential cooperative\r
+     model for working with other professional societies in agriculture\r
+     to try to do the same thing--put the journals of particular interest\r
+     to agriculture research into electronic form.)\r
+\r
+     2) An extension of the earlier product on aquaculture.\r
+\r
+     3) The George Washington Carver Papers--a joint project with\r
+     Tuskegee University to scan and convert from microfilm some 3,500\r
+     images of Carver's papers, letters, and drawings.\r
+\r
+It was anticipated that all of these products would appear no more than\r
+six months after the Workshop.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ZIDAR * (A separate arena for scanning) * Steps in creating a database *\r
+Image capture, with and without performing OCR * Keying in tracking data\r
+* Scanning, with electronic and manual tracking * Adjustments during\r
+scanning process * Scanning resolutions * Compression * De-skewing and\r
+filtering * Image capture from microform:  the papers and letters of\r
+George Washington Carver * Equipment used for a scanning system * \r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Judith ZIDAR, coordinator, National Agricultural Text Digitizing Program\r
+(NATDP), National Agricultural Library (NAL), illustrated the technical\r
+details of NATDP, including her primary responsibility, scanning and\r
+creating databases on a topic and putting them on CD-ROM.\r
+\r
+(ZIDAR remarked a separate arena from the CD-ROM projects, although the\r
+processing of the material is nearly identical, in which NATDP is also\r
+scanning material and loading it on a Next microcomputer, which in turn\r
+is linked to NAL's integrated library system.  Thus, searches in NAL's\r
+bibliographic database will enable people to pull up actual page images\r
+and text for any documents that have been entered.)\r
+\r
+In accordance with the session's topic, ZIDAR focused her illustrated\r
+talk on image capture, offering a primer on the three main steps in the\r
+process:  1) assemble the printed publications; 2) design the database\r
+(database design occurs in the process of preparing the material for\r
+scanning; this step entails reviewing and organizing the material,\r
+defining the contents--what will constitute a record, what kinds of\r
+fields will be captured in terms of author, title, etc.); 3) perform a\r
+certain amount of markup on the paper publications.  NAL performs this\r
+task record by record, preparing work sheets or some other sort of\r
+tracking material and designing descriptors and other enhancements to be\r
+added to the data that will not be captured from the printed publication. \r
+Part of this process also involves determining NATDP's file and directory\r
+structure:  NATDP attempts to avoid putting more than approximately 100\r
+images in a directory, because placing more than that on a CD-ROM would\r
+reduce the access speed.\r
+\r
+This up-front process takes approximately two weeks for a\r
+6,000-7,000-page database.  The next step is to capture the page images. \r
+How long this process takes is determined by the decision whether or not\r
+to perform OCR.  Not performing OCR speeds the process, whereas text\r
+capture requires greater care because of the quality of the image:  it\r
+has to be straighter and allowance must be made for text on a page, not\r
+just for the capture of photographs.\r
+\r
+NATDP keys in tracking data, that is, a standard bibliographic record\r
+including the title of the book and the title of the chapter, which will\r
+later either become the access information or will be attached to the\r
+front of a full-text record so that it is searchable.\r
+\r
+Images are scanned from a bound or unbound publication, chiefly from\r
+bound publications in the case of NATDP, however, because often they are\r
+the only copies and the publications are returned to the shelves.  NATDP\r
+usually scans one record at a time, because its database tracking system\r
+tracks the document in that way and does not require further logical\r
+separating of the images.  After performing optical character\r
+recognition, NATDP moves the images off the hard disk and maintains a\r
+volume sheet.  Though the system tracks electronically, all the\r
+processing steps are also tracked manually with a log sheet.\r
+\r
+ZIDAR next illustrated the kinds of adjustments that one can make when\r
+scanning from paper and microfilm, for example, redoing images that need\r
+special handling, setting for dithering or gray scale, and adjusting for\r
+brightness or for the whole book at one time.\r
+\r
+NATDP is scanning at 300 dots per inch, a standard scanning resolution. \r
+Though adequate for capturing text that is all of a standard size, 300\r
+dpi is unsuitable for any kind of photographic material or for very small\r
+text.  Many scanners allow for different image formats, TIFF, of course,\r
+being a de facto standard.  But if one intends to exchange images with\r
+other people, the ability to scan other image formats, even if they are\r
+less common, becomes highly desirable.\r
+\r
+CCITT Group 4 is the standard compression for normal black-and-white\r
+images, JPEG for gray scale or color.   ZIDAR recommended 1) using the\r
+standard compressions, particularly if one attempts to make material\r
+available and to allow users to download images and reuse them from\r
+CD-ROMs; and 2) maintaining the ability to output an uncompressed image,\r
+because in image exchange uncompressed images are more likely to be able\r
+to cross platforms.\r
+\r
+ZIDAR emphasized the importance of de-skewing and filtering as\r
+requirements on NATDP's upgraded system.  For instance, scanning bound\r
+books, particularly books published by the federal government whose pages\r
+are skewed, and trying to scan them straight if OCR is to be performed,\r
+is extremely time-consuming.  The same holds for filtering of\r
+poor-quality or older materials.\r
+\r
+ZIDAR described image capture from microform, using as an example three\r
+reels from a sixty-seven-reel set of the papers and letters of George\r
+Washington Carver that had been produced by Tuskegee University.  These\r
+resulted in approximately 3,500 images, which NATDP had had scanned by\r
+its service contractor, Science Applications International Corporation\r
+(SAIC).  NATDP also created bibliographic records for access.  (NATDP did\r
+not have such specialized equipment as a microfilm scanner.\r
+\r
+Unfortunately, the process of scanning from microfilm was not an\r
+unqualified success, ZIDAR reported:  because microfilm frame sizes vary,\r
+occasionally some frames were missed, which without spending much time\r
+and money could not be recaptured.\r
+\r
+OCR could not be performed from the scanned images of the frames.  The\r
+bleeding in the text simply output text, when OCR was run, that could not\r
+even be edited.  NATDP tested for negative versus positive images,\r
+landscape versus portrait orientation, and single- versus dual-page\r
+microfilm, none of which seemed to affect the quality of the image; but\r
+also on none of them could OCR be performed.\r
+\r
+In selecting the microfilm they would use, therefore, NATDP had other\r
+factors in mind.  ZIDAR noted two factors that influenced the quality of\r
+the images:  1) the inherent quality of the original and 2) the amount of\r
+size reduction on the pages.\r
+\r
+The Carver papers were selected because they are informative and visually\r
+interesting, treat a single subject, and are valuable in their own right. \r
+The images were scanned and divided into logical records by SAIC, then\r
+delivered, and loaded onto NATDP's system, where bibliographic\r
+information taken directly from the images was added.  Scanning was\r
+completed in summer 1991 and by the end of summer 1992 the disk was\r
+scheduled to be published.\r
+\r
+Problems encountered during processing included the following:  Because\r
+the microfilm scanning had to be done in a batch, adjustment for\r
+individual page variations was not possible.  The frame size varied on\r
+account of the nature of the material, and therefore some of the frames\r
+were missed while others were just partial frames.  The only way to go\r
+back and capture this material was to print out the page with the\r
+microfilm reader from the missing frame and then scan it in from the\r
+page, which was extremely time-consuming.  The quality of the images\r
+scanned from the printout of the microfilm compared unfavorably with that\r
+of the original images captured directly from the microfilm.  The\r
+inability to perform OCR also was a major disappointment.  At the time,\r
+computer output microfilm was unavailable to test.\r
+\r
+The equipment used for a scanning system was the last topic addressed by\r
+ZIDAR.  The type of equipment that one would purchase for a scanning\r
+system included:  a microcomputer, at least a 386, but preferably a 486;\r
+a large hard disk, 380 megabyte at minimum; a multi-tasking operating\r
+system that allows one to run some things in batch in the background\r
+while scanning or doing text editing, for example, Unix or OS/2 and,\r
+theoretically, Windows; a high-speed scanner and scanning software that\r
+allows one to make the various adjustments mentioned earlier; a\r
+high-resolution monitor (150 dpi ); OCR software and hardware to perform\r
+text recognition; an optical disk subsystem on which to archive all the\r
+images as the processing is done; file management and tracking software.\r
+\r
+ZIDAR opined that the software one purchases was more important than the\r
+hardware and might also cost more than the hardware, but it was likely to\r
+prove critical to the success or failure of one's system.  In addition to\r
+a stand-alone scanning workstation for image capture, then, text capture\r
+requires one or two editing stations networked to this scanning station\r
+to perform editing.  Editing the text takes two or three times as long as\r
+capturing the images.\r
+\r
+Finally, ZIDAR stressed the importance of buying an open system that allows\r
+for more than one vendor, complies with standards, and can be upgraded.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+WATERS *Yale University Library's master plan to convert microfilm to\r
+digital imagery (POB) * The place of electronic tools in the library of\r
+the future * The uses of images and an image library * Primary input from\r
+preservation microfilm * Features distinguishing POB from CXP and key\r
+hypotheses guiding POB * Use of vendor selection process to facilitate\r
+organizational work * Criteria for selecting vendor * Finalists and\r
+results of process for Yale * Key factor distinguishing vendors *\r
+Components, design principles, and some estimated costs of POB * Role of\r
+preservation materials in developing imaging market * Factors affecting\r
+quality and cost * Factors affecting the usability of complex documents\r
+in image form * \r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Donald WATERS, head of the Systems Office, Yale University Library,\r
+reported on the progress of a master plan for a project at Yale to\r
+convert microfilm to digital imagery, Project Open Book (POB).  Stating\r
+that POB was in an advanced stage of planning, WATERS detailed, in\r
+particular, the process of selecting a vendor partner and several key\r
+issues under discussion as Yale prepares to move into the project itself. \r
+He commented first on the vision that serves as the context of POB and\r
+then described its purpose and scope.\r
+\r
+WATERS sees the library of the future not necessarily as an electronic\r
+library but as a place that generates, preserves, and improves for its\r
+clients ready access to both intellectual and physical recorded\r
+knowledge.  Electronic tools must find a place in the library in the\r
+context of this vision.  Several roles for electronic tools include\r
+serving as:  indirect sources of electronic knowledge or as "finding"\r
+aids (the on-line catalogues, the article-level indices, registers for\r
+documents and archives); direct sources of recorded knowledge; full-text\r
+images; and various kinds of compound sources of recorded knowledge (the\r
+so-called compound documents of Hypertext, mixed text and image,\r
+mixed-text image format, and multimedia).\r
+\r
+POB is looking particularly at images and an image library, the uses to\r
+which images will be put (e.g., storage, printing, browsing, and then use\r
+as input for other processes), OCR as a subsequent process to image\r
+capture, or creating an image library, and also possibly generating\r
+microfilm.\r
+\r
+While input will come from a variety of sources, POB is considering\r
+especially input from preservation microfilm.  A possible outcome is that\r
+the film and paper which provide the input for the image library\r
+eventually may go off into remote storage, and that the image library may\r
+be the primary access tool.\r
+\r
+The purpose and scope of POB focus on imaging.  Though related to CXP,\r
+POB has two features which distinguish it:  1) scale--conversion of\r
+10,000 volumes into digital image form; and 2) source--conversion from\r
+microfilm.  Given these features, several key working hypotheses guide\r
+POB, including:  1) Since POB is using microfilm, it is not concerned with\r
+the image library as a preservation medium.  2) Digital imagery can improve\r
+access to recorded knowledge through printing and network distribution at\r
+a modest incremental cost of microfilm.  3) Capturing and storing documents\r
+in a digital image form is necessary to further improvements in access.\r
+(POB distinguishes between the imaging, digitizing process and OCR,\r
+which at this stage it does not plan to perform.)\r
+\r
+Currently in its first or organizational phase, POB found that it could\r
+use a vendor selection process to facilitate a good deal of the\r
+organizational work (e.g., creating a project team and advisory board,\r
+confirming the validity of the plan, establishing the cost of the project\r
+and a budget, selecting the materials to convert, and then raising the\r
+necessary funds).\r
+\r
+POB developed numerous selection criteria, including:  a firm committed\r
+to image-document management, the ability to serve as systems integrator\r
+in a large-scale project over several years, interest in developing the\r
+requisite software as a standard rather than a custom product, and a\r
+willingness to invest substantial resources in the project itself.\r
+\r
+Two vendors, DEC and Xerox, were selected as finalists in October 1991,\r
+and with the support of the Commission on Preservation and Access, each\r
+was commissioned to generate a detailed requirements analysis for the\r
+project and then to submit a formal proposal for the completion of the\r
+project, which included a budget and costs. The terms were that POB would\r
+pay the loser.  The results for Yale of involving a vendor included: \r
+broad involvement of Yale staff across the board at a relatively low\r
+cost, which may have long-term significance in carrying out the project\r
+(twenty-five to thirty university people are engaged in POB); better\r
+understanding of the factors that affect corporate response to markets\r
+for imaging products; a competitive proposal; and a more sophisticated\r
+view of the imaging markets.\r
+\r
+The most important factor that distinguished the vendors under\r
+consideration was their identification with the customer.  The size and\r
+internal complexity of the company also was an important factor.  POB was\r
+looking at large companies that had substantial resources.  In the end,\r
+the process generated for Yale two competitive proposals, with Xerox's\r
+the clear winner.  WATERS then described the components of the proposal,\r
+the design principles, and some of the costs estimated for the process.\r
+\r
+Components are essentially four:  a conversion subsystem, a\r
+network-accessible storage subsystem for 10,000 books (and POB expects\r
+200 to 600 dpi storage), browsing stations distributed on the campus\r
+network, and network access to the image printers.\r
+\r
+Among the design principles, POB wanted conversion at the highest\r
+possible resolution.  Assuming TIFF files, TIFF files with Group 4\r
+compression, TCP/IP, and ethernet network on campus, POB wanted a\r
+client-server approach with image documents distributed to the\r
+workstations and made accessible through native workstation interfaces\r
+such as Windows.  POB also insisted on a phased approach to\r
+implementation:  1) a stand-alone, single-user, low-cost entry into the\r
+business with a workstation focused on conversion and allowing POB to\r
+explore user access; 2) movement into a higher-volume conversion with\r
+network-accessible storage and multiple access stations; and 3) a\r
+high-volume conversion, full-capacity storage, and multiple browsing\r
+stations distributed throughout the campus.\r
+\r
+The costs proposed for start-up assumed the existence of the Yale network\r
+and its two DocuTech image printers.  Other start-up costs are estimated\r
+at $1 million over the three phases.  At the end of the project, the annual\r
+operating costs estimated primarily for the software and hardware proposed\r
+come to about $60,000, but these exclude costs for labor needed in the\r
+conversion process, network and printer usage, and facilities management.\r
+\r
+Finally, the selection process produced for Yale a more sophisticated\r
+view of the imaging markets:  the management of complex documents in\r
+image form is not a preservation problem, not a library problem, but a\r
+general problem in a broad, general industry.  Preservation materials are\r
+useful for developing that market because of the qualities of the\r
+material.  For example, much of it is out of copyright.  The resolution\r
+of key issues such as the quality of scanning and image browsing also\r
+will affect development of that market.\r
+\r
+The technology is readily available but changing rapidly.  In this\r
+context of rapid change, several factors affect quality and cost, to\r
+which POB intends to pay particular attention, for example, the various\r
+levels of resolution that can be achieved.  POB believes it can bring\r
+resolution up to 600 dpi, but an interpolation process from 400 to 600 is\r
+more likely.  The variation quality in microfilm will prove to be a\r
+highly important factor.  POB may reexamine the standards used to film in\r
+the first place by looking at this process as a follow-on to microfilming.\r
+\r
+Other important factors include:  the techniques available to the\r
+operator for handling material, the ways of integrating quality control\r
+into the digitizing work flow, and a work flow that includes indexing and\r
+storage.  POB's requirement was to be able to deal with quality control\r
+at the point of scanning.  Thus, thanks to Xerox, POB anticipates having\r
+a mechanism which will allow it not only to scan in batch form, but to\r
+review the material as it goes through the scanner and control quality\r
+from the outset.\r
+\r
+The standards for measuring quality and costs depend greatly on the uses\r
+of the material, including subsequent OCR, storage, printing, and\r
+browsing.  But especially at issue for POB is the facility for browsing. \r
+This facility, WATERS said, is perhaps the weakest aspect of imaging\r
+technology and the most in need of development.\r
+\r
+A variety of factors affect the usability of complex documents in image\r
+form, among them:  1) the ability of the system to handle the full range\r
+of document types, not just monographs but serials, multi-part\r
+monographs, and manuscripts; 2) the location of the database of record\r
+for bibliographic information about the image document, which POB wants\r
+to enter once and in the most useful place, the on-line catalog; 3) a\r
+document identifier for referencing the bibliographic information in one\r
+place and the images in another; 4) the technique for making the basic\r
+internal structure of the document accessible to the reader; and finally,\r
+5) the physical presentation on the CRT of those documents.  POB is ready\r
+to complete this phase now.  One last decision involves deciding which\r
+material to scan.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * TIFF files constitute de facto standard * NARA's experience\r
+with image conversion software and text conversion * RFC 1314 *\r
+Considerable flux concerning available hardware and software solutions *\r
+NAL through-put rate during scanning * Window management questions *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+In the question-and-answer period that followed WATERS's presentation,\r
+the following points emerged:\r
+\r
+     * ZIDAR's statement about using TIFF files as a standard meant de\r
+     facto standard.  This is what most people use and typically exchange\r
+     with other groups, across platforms, or even occasionally across\r
+     display software.\r
+\r
+     * HOLMES commented on the unsuccessful experience of NARA in\r
+     attempting to run image-conversion software or to exchange between\r
+     applications:  What are supposedly TIFF files go into other software\r
+     that is supposed to be able to accept TIFF but cannot recognize the\r
+     format and cannot deal with it, and thus renders the exchange\r
+     useless.  Re text conversion, he noted the different recognition\r
+     rates obtained by substituting the make and model of scanners in\r
+     NARA's recent test of an "intelligent" character-recognition product\r
+     for a new company.  In the selection of hardware and software,\r
+     HOLMES argued, software no longer constitutes the overriding factor\r
+     it did until about a year ago; rather it is perhaps important to\r
+     look at both now.\r
+\r
+     * Danny Cohen and Alan Katz of the University of Southern California\r
+     Information Sciences Institute began circulating as an Internet RFC\r
+     (RFC 1314) about a month ago a standard for a TIFF interchange\r
+     format for Internet distribution of monochrome bit-mapped images,\r
+     which LYNCH said he believed would be used as a de facto standard.\r
+\r
+     * FLEISCHHAUER's impression from hearing these reports and thinking\r
+     about AM's experience was that there is considerable flux concerning\r
+     available hardware and software solutions.  HOOTON agreed and\r
+     commented at the same time on ZIDAR's statement that the equipment\r
+     employed affects the results produced.  One cannot draw a complete\r
+     conclusion by saying it is difficult or impossible to perform OCR\r
+     from scanning microfilm, for example, with that device,  that set of\r
+     parameters, and system requirements, because numerous other people\r
+     are accomplishing just that, using other components, perhaps. \r
+     HOOTON opined that both the hardware and the software were highly\r
+     important.  Most of the problems discussed today have been solved in\r
+     numerous different ways by other people.  Though it is good to be\r
+     cognizant of various experiences, this is not to say that it will\r
+     always be thus.\r
+\r
+     * At NAL, the through-put rate of the scanning process for paper,\r
+     page by page, performing OCR, ranges from 300 to 600 pages per day;\r
+     not performing OCR is considerably faster, although how much faster\r
+     is not known.  This is for scanning from bound books, which is much\r
+     slower.\r
+\r
+     * WATERS commented on window management questions:  DEC proposed an\r
+     X-Windows solution which was problematical for two reasons.  One was\r
+     POB's requirement to be able to manipulate images on the workstation\r
+     and bring them down to the workstation itself and the other was\r
+     network usage.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+THOMA * Illustration of deficiencies in scanning and storage process *\r
+Image quality in this process * Different costs entailed by better image\r
+quality * Techniques for overcoming various de-ficiencies:  fixed\r
+thresholding, dynamic thresholding, dithering, image merge * Page edge\r
+effects *   \r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+George THOMA, chief, Communications Engineering Branch, National Library\r
+of Medicine (NLM), illustrated several of the deficiencies discussed by\r
+the previous speakers.  He introduced the topic of special problems by\r
+noting the advantages of electronic imaging.  For example, it is regenerable\r
+because it is a coded file, and real-time quality control is possible with\r
+electronic capture, whereas in photographic capture it is not.\r
+\r
+One of the difficulties discussed in the scanning and storage process was\r
+image quality which, without belaboring the obvious, means different\r
+things for maps, medical X-rays, or broadcast television.  In the case of\r
+documents, THOMA said, image quality boils down to legibility of the\r
+textual parts, and fidelity in the case of gray or color photo print-type\r
+material.  Legibility boils down to scan density, the standard in most\r
+cases being 300 dpi.  Increasing the resolution with scanners that\r
+perform 600 or 1200 dpi, however, comes at a cost.\r
+\r
+Better image quality entails at least four different kinds of costs:  1)\r
+equipment costs, because the CCD (i.e., charge-couple device) with\r
+greater number of elements costs more;  2) time costs that translate to\r
+the actual capture costs, because manual labor is involved (the time is\r
+also dependent on the fact that more data has to be moved around in the\r
+machine in the scanning or network devices that perform the scanning as\r
+well as the storage);  3) media costs, because at high resolutions larger\r
+files have to be stored; and 4) transmission costs, because there is just\r
+more data to be transmitted.\r
+\r
+But while resolution takes care of the issue of legibility in image\r
+quality, other deficiencies have to do with contrast and elements on the\r
+page scanned or the image that needed to be removed or clarified.  Thus,\r
+THOMA proceeded to illustrate various deficiencies, how they are\r
+manifested, and several techniques to overcome them.\r
+\r
+Fixed thresholding was the first technique described, suitable for\r
+black-and-white text, when the contrast does not vary over the page.  One\r
+can have many different threshold levels in scanning devices.  Thus,\r
+THOMA offered an example of extremely poor contrast, which resulted from\r
+the fact that the stock was a heavy red.  This is the sort of image that\r
+when microfilmed fails to provide any legibility whatsoever.  Fixed\r
+thresholding is the way to change the black-to-red contrast to the\r
+desired black-to-white contrast.\r
+\r
+Other examples included material that had been browned or yellowed by\r
+age.  This was also a case of contrast deficiency, and correction was\r
+done by fixed thresholding.  A final example boils down to the same\r
+thing, slight variability, but it is not significant.  Fixed thresholding\r
+solves this problem as well.  The microfilm equivalent is certainly legible,\r
+but it comes with dark areas.  Though THOMA did not have a slide of the\r
+microfilm in this case, he did show the reproduced electronic image.\r
+\r
+When one has variable contrast over a page or the lighting over the page\r
+area varies, especially in the case where a bound volume has light\r
+shining on it, the image must be processed by a dynamic thresholding\r
+scheme.  One scheme, dynamic averaging, allows the threshold level not to\r
+be fixed but to be recomputed for every pixel from the neighboring\r
+characteristics.  The neighbors of a pixel determine where the threshold\r
+should be set for that pixel.\r
+\r
+THOMA showed an example of a page that had been made deficient by a\r
+variety of techniques, including a burn mark, coffee stains, and a yellow\r
+marker.  Application of a fixed-thresholding scheme, THOMA argued, might\r
+take care of several deficiencies on the page but not all of them. \r
+Performing the calculation for a dynamic threshold setting, however,\r
+removes most of the deficiencies so that at least the text is legible.\r
+\r
+Another problem is representing a gray level with black-and-white pixels\r
+by a process known as dithering or electronic screening.  But dithering\r
+does not provide good image quality for pure black-and-white textual\r
+material.  THOMA illustrated this point with examples. Although its\r
+suitability for photoprint is the reason for electronic screening or\r
+dithering, it cannot be used for every compound image.  In the document\r
+that was distributed by CXP, THOMA noticed that the dithered image of the\r
+IEEE test chart evinced some deterioration in the text.  He presented an\r
+extreme example of deterioration in the text in which compounded\r
+documents had to be set right by other techniques.  The technique\r
+illustrated by the present example was an image merge in which the page\r
+is scanned twice and the settings go from fixed threshold to the\r
+dithering matrix; the resulting images are merged to give the best\r
+results with each technique.\r
+\r
+THOMA illustrated how dithering is also used in nonphotographic or\r
+nonprint materials with an example of a grayish page from a medical text,\r
+which was reproduced to show all of the gray that appeared in the\r
+original.  Dithering provided a reproduction of all the gray in the\r
+original of another example from the same text.\r
+\r
+THOMA finally illustrated the problem of bordering, or page-edge,\r
+effects.  Books and bound volumes that are placed on a photocopy machine\r
+or a scanner produce page-edge effects that are undesirable for two\r
+reasons:  1) the aesthetics of the image; after all, if the image is to\r
+be preserved, one does not necessarily want to keep all of its\r
+deficiencies; 2) compression (with the bordering problem THOMA\r
+illustrated, the compression ratio deteriorated tremendously).  One way\r
+to eliminate this more serious problem is to have the operator at the\r
+point of scanning window the part of the image that is desirable and\r
+automatically turn all of the pixels out of that picture to white. \r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+FLEISCHHAUER * AM's experience with scanning bound materials * Dithering\r
+*\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Carl FLEISCHHAUER, coordinator, American Memory, Library of Congress,\r
+reported AM's experience with scanning bound materials, which he likened\r
+to the problems involved in using photocopying machines.  Very few\r
+devices in the industry offer book-edge scanning, let alone book cradles. \r
+The problem may be unsolvable, FLEISCHHAUER said, because a large enough\r
+market does not exist for a preservation-quality scanner.  AM is using a\r
+Kurzweil scanner, which is a book-edge scanner now sold by Xerox.\r
+\r
+Devoting the remainder of his brief presentation to dithering,\r
+FLEISCHHAUER related AM's experience with a contractor who was using\r
+unsophisticated equipment and software to reduce moire patterns from\r
+printed halftones.  AM took the same image and used the dithering\r
+algorithm that forms part of the same Kurzweil Xerox scanner; it\r
+disguised moire patterns much more effectively.\r
+\r
+FLEISCHHAUER also observed that dithering produces a binary file which is\r
+useful for numerous purposes, for example, printing it on a laser printer\r
+without having to "re-halftone" it.  But it tends to defeat efficient\r
+compression, because the very thing that dithers to reduce moire patterns\r
+also tends to work against compression schemes.  AM thought the\r
+difference in image quality was worth it.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Relative use as a criterion for POB's selection of books to\r
+be converted into digital form *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+During the discussion period, WATERS noted that one of the criteria for\r
+selecting books among the 10,000 to be converted into digital image form\r
+would be how much relative use they would receive--a subject still\r
+requiring evaluation.  The challenge will be to understand whether\r
+coherent bodies of material will increase usage or whether POB should\r
+seek material that is being used, scan that, and make it more accessible. \r
+POB might decide to digitize materials that are already heavily used, in\r
+order to make them more accessible and decrease wear on them.  Another\r
+approach would be to provide a large body of intellectually coherent\r
+material that may be used more in digital form than it is currently used\r
+in microfilm.  POB would seek material that was out of copyright.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+BARONAS * Origin and scope of AIIM * Types of documents produced in\r
+AIIM's standards program * Domain of AIIM's standardization work * AIIM's\r
+structure * TC 171 and MS23 * Electronic image management standards *\r
+Categories of EIM standardization where AIIM standards are being\r
+developed *  \r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Jean BARONAS, senior manager, Department of Standards and Technology,\r
+Association for Information and Image Management (AIIM), described the\r
+not-for-profit association and the national and international programs\r
+for standardization in which AIIM is active.\r
+\r
+Accredited for twenty-five years as the nation's standards development\r
+organization for document image management, AIIM began life in a library\r
+community developing microfilm standards.  Today the association\r
+maintains both its library and business-image management standardization\r
+activities--and has moved into electronic image-management\r
+standardization (EIM).\r
+\r
+BARONAS defined the program's scope.  AIIM deals with:  1) the\r
+terminology of standards and of the technology it uses; 2) methods of\r
+measurement for the systems, as well as quality; 3) methodologies for\r
+users to evaluate and measure quality; 4) the features of apparatus used\r
+to manage and edit images; and 5) the procedures used to manage images.\r
+\r
+BARONAS noted that three types of documents are produced in the AIIM\r
+standards program:  the first two, accredited by the American National\r
+Standards Institute (ANSI), are standards and standard recommended\r
+practices.  Recommended practices differ from standards in that they\r
+contain more tutorial information.  A technical report is not an ANSI\r
+standard.  Because AIIM's policies and procedures for developing\r
+standards are approved by ANSI, its standards are labeled ANSI/AIIM,\r
+followed by the number and title of the standard.\r
+\r
+BARONAS then illustrated the domain of AIIM's standardization work.  For\r
+example, AIIM is the administrator of the U.S. Technical Advisory Group\r
+(TAG) to the International Standards Organization's (ISO) technical\r
+committee, TC l7l Micrographics and Optical Memories for Document and\r
+Image Recording, Storage, and Use.  AIIM officially works through ANSI in\r
+the international standardization process.\r
+\r
+BARONAS described AIIM's structure, including its board of directors, its\r
+standards board of twelve individuals active in the image-management\r
+industry, its strategic planning and legal admissibility task forces, and\r
+its National Standards Council, which is comprised of the members of a\r
+number of organizations who vote on every AIIM standard before it is\r
+published.  BARONAS pointed out that AIIM's liaisons deal with numerous\r
+other standards developers, including the optical disk community, office\r
+and publishing systems, image-codes-and-character set committees, and the\r
+National Information Standards Organization (NISO).\r
+\r
+BARONAS illustrated the procedures of TC l7l, which covers all aspects of\r
+image management.  When AIIM's national program has conceptualized a new\r
+project, it is usually submitted to the international level, so that the\r
+member countries of TC l7l can simultaneously work on the development of\r
+the standard or the technical report.  BARONAS also illustrated a classic\r
+microfilm standard, MS23, which deals with numerous imaging concepts that\r
+apply to electronic imaging.  Originally developed in the l970s, revised\r
+in the l980s, and revised again in l991, this standard is scheduled for\r
+another revision.  MS23 is an active standard whereby users may propose\r
+new density ranges and new methods of evaluating film images in the\r
+standard's revision.\r
+\r
+BARONAS detailed several electronic image-management standards, for\r
+instance, ANSI/AIIM MS44, a quality-control guideline for scanning 8.5"\r
+by 11" black-and-white office documents.  This standard is used with the\r
+IEEE fax image--a continuous tone photographic image with gray scales,\r
+text, and several continuous tone pictures--and AIIM test target number\r
+2, a representative document used in office document management.\r
+\r
+BARONAS next outlined the four categories of EIM standardization in which\r
+AIIM standards are being developed:  transfer and retrieval, evaluation,\r
+optical disc and document scanning applications, and design and\r
+conversion of documents.  She detailed several of the main projects of\r
+each:  1) in the category of image transfer and retrieval, a bi-level\r
+image transfer format, ANSI/AIIM MS53, which is a proposed standard that\r
+describes a file header for image transfer between unlike systems when\r
+the images are compressed using G3 and G4 compression; 2) the category of\r
+image evaluation, which includes the AIIM-proposed TR26 tutorial on image\r
+resolution (this technical report will treat the differences and\r
+similarities between classical or photographic and electronic imaging);\r
+3) design and conversion, which includes a proposed technical report\r
+called "Forms Design Optimization for EIM" (this report considers how\r
+general-purpose business forms can be best designed so that scanning is\r
+optimized; reprographic characteristics such as type, rules, background,\r
+tint, and color will likewise be treated in the technical report); 4)\r
+disk and document scanning applications includes a project a) on planning\r
+platters and disk management, b) on generating an application profile for\r
+EIM when images are stored and distributed on CD-ROM, and c) on\r
+evaluating SCSI2, and how a common command set can be generated for SCSI2\r
+so that document scanners are more easily integrated.  (ANSI/AIIM MS53\r
+will also apply to compressed images.)\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+BATTIN * The implications of standards for preservation * A major\r
+obstacle to successful cooperation * A hindrance to access in the digital\r
+environment * Standards a double-edged sword for those concerned with the\r
+preservation of the human record * Near-term prognosis for reliable\r
+archival standards * Preservation concerns for electronic media * Need\r
+for reconceptualizing our preservation principles * Standards in the real\r
+world and the politics of reproduction * Need to redefine the concept of\r
+archival and to begin to think in terms of life cycles * Cooperation and\r
+the La Guardia Eight * Concerns generated by discussions on the problems\r
+of preserving text and image * General principles to be adopted in a\r
+world without standards *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Patricia BATTIN, president, the Commission on Preservation and Access\r
+(CPA), addressed the implications of standards for preservation.  She\r
+listed several areas where the library profession and the analog world of\r
+the printed book had made enormous contributions over the past hundred\r
+years--for example, in bibliographic formats, binding standards, and, most\r
+important, in determining what constitutes longevity or archival quality.\r
+\r
+Although standards have lightened the preservation burden through the\r
+development of national and international collaborative programs,\r
+nevertheless, a pervasive mistrust of other people's standards remains a\r
+major obstacle to successful cooperation, BATTIN said.\r
+\r
+The zeal to achieve perfection, regardless of the cost, has hindered\r
+rather than facilitated access in some instances, and in the digital\r
+environment, where no real standards exist, has brought an ironically\r
+just reward.\r
+\r
+BATTIN argued that standards are a double-edged sword for those concerned\r
+with the preservation of the human record, that is, the provision of\r
+access to recorded knowledge in a multitude of media as far into the\r
+future as possible.  Standards are essential to facilitate\r
+interconnectivity and access, but, BATTIN said, as LYNCH pointed out\r
+yesterday, if set too soon they can hinder creativity, expansion of\r
+capability, and the broadening of access.  The characteristics of\r
+standards for digital imagery differ radically from those for analog\r
+imagery.  And the nature of digital technology implies continuing\r
+volatility and change.  To reiterate, precipitous standard-setting can\r
+inhibit creativity, but delayed standard-setting results in chaos.\r
+\r
+Since in BATTIN'S opinion the near-term prognosis for reliable archival\r
+standards, as defined by librarians in the analog world, is poor, two\r
+alternatives remain:  standing pat with the old technology, or\r
+reconceptualizing.\r
+\r
+Preservation concerns for electronic media fall into two general domains. \r
+One is the continuing assurance of access to knowledge originally\r
+generated, stored, disseminated, and used in electronic form.  This\r
+domain contains several subdivisions, including 1) the closed,\r
+proprietary systems discussed the previous day, bundled information such\r
+as electronic journals and government agency records, and electronically\r
+produced or captured raw data; and 2) the application of digital\r
+technologies to the reformatting of materials originally published on a\r
+deteriorating analog medium such as acid paper or videotape.\r
+\r
+The preservation of electronic media requires a reconceptualizing of our\r
+preservation principles during a volatile, standardless transition which\r
+may last far longer than any of us envision today.  BATTIN urged the\r
+necessity of shifting focus from assessing, measuring, and setting\r
+standards for the permanence of the medium to the concept of managing\r
+continuing access to information stored on a variety of media and\r
+requiring a variety of ever-changing hardware and software for access--a\r
+fundamental shift for the library profession.\r
+\r
+BATTIN offered a primer on how to move forward with reasonable confidence\r
+in a world without standards.  Her comments fell roughly into two sections:\r
+1) standards in the real world and 2) the politics of reproduction.\r
+\r
+In regard to real-world standards, BATTIN argued the need to redefine the\r
+concept of archive and to begin to think in terms of life cycles.  In\r
+the past, the naive assumption that paper would last forever produced a\r
+cavalier attitude toward life cycles.  The transient nature of the\r
+electronic media has compelled people to recognize and accept upfront the\r
+concept of life cycles in place of permanency.\r
+\r
+Digital standards have to be developed and set in a cooperative context\r
+to ensure efficient exchange of information.  Moreover, during this\r
+transition period, greater flexibility concerning how concepts such as\r
+backup copies and archival copies in the CXP are defined is necessary,\r
+or the opportunity to move forward will be lost.\r
+\r
+In terms of cooperation, particularly in the university setting, BATTIN\r
+also argued the need to avoid going off in a hundred different\r
+directions.  The CPA has catalyzed a small group of universities called\r
+the La Guardia Eight--because La Guardia Airport is where meetings take\r
+place--Harvard, Yale, Cornell, Princeton, Penn State, Tennessee,\r
+Stanford, and USC, to develop a digital preservation consortium to look\r
+at all these issues and develop de facto standards as we move along,\r
+instead of waiting for something that is officially blessed.  Continuing\r
+to apply analog values and definitions of standards to the digital\r
+environment, BATTIN said, will effectively lead to forfeiture of the\r
+benefits of digital technology to research and scholarship.\r
+\r
+Under the second rubric, the politics of reproduction, BATTIN reiterated\r
+an oft-made argument concerning the electronic library, namely, that it\r
+is more difficult to transform than to create, and nowhere is that belief\r
+expressed more dramatically than in the conversion of brittle books to\r
+new media.  Preserving information published in electronic media involves\r
+making sure the information remains accessible and that digital\r
+information is not lost through reproduction.  In the analog world of\r
+photocopies and microfilm, the issue of fidelity to the original becomes\r
+paramount, as do issues of "Whose fidelity?" and "Whose original?"\r
+\r
+BATTIN elaborated these arguments with a few examples from a recent study\r
+conducted by the CPA on the problems of preserving text and image. \r
+Discussions with scholars, librarians, and curators in a variety of\r
+disciplines dependent on text and image generated a variety of concerns,\r
+for example:  1) Copy what is, not what the technology is capable of. \r
+This is very important for the history of ideas.  Scholars wish to know\r
+what the author saw and worked from.  And make available at the\r
+workstation the opportunity to erase all the defects and enhance the\r
+presentation.  2) The fidelity of reproduction--what is good enough, what\r
+can we afford, and the difference it makes--issues of subjective versus\r
+objective resolution.  3) The differences between primary and secondary\r
+users.  Restricting the definition of primary user to the one in whose\r
+discipline the material has been published runs one headlong into the\r
+reality that these printed books have had a host of other users from a\r
+host of other disciplines, who not only were looking for very different\r
+things, but who also shared values very different from those of the\r
+primary user.  4) The relationship of the standard of reproduction to new\r
+capabilities of scholarship--the browsing standard versus an archival\r
+standard.  How good must the archival standard be?  Can a distinction be\r
+drawn between potential users in setting standards for reproduction? \r
+Archival storage, use copies, browsing copies--ought an attempt to set\r
+standards even be made?  5) Finally, costs.  How much are we prepared to\r
+pay to capture absolute fidelity?  What are the trade-offs between vastly\r
+enhanced access, degrees of fidelity, and costs?\r
+\r
+These standards, BATTIN concluded, serve to complicate further the\r
+reproduction process, and add to the long list of technical standards\r
+that are necessary to ensure widespread access.  Ways to articulate and\r
+analyze the costs that are attached to the different levels of standards\r
+must be found.\r
+\r
+Given the chaos concerning standards, which promises to linger for the\r
+foreseeable future, BATTIN urged adoption of the following general\r
+principles:\r
+\r
+     * Strive to understand the changing information requirements of\r
+     scholarly disciplines as more and more technology is integrated into\r
+     the process of research and scholarly communication in order to meet\r
+     future scholarly needs, not to build for the past.  Capture\r
+     deteriorating information at the highest affordable resolution, even\r
+     though the dissemination and display technologies will lag.\r
+\r
+     * Develop cooperative mechanisms to foster agreement on protocols\r
+     for document structure and other interchange mechanisms necessary\r
+     for widespread dissemination and use before official standards are\r
+     set.\r
+\r
+     * Accept that, in a transition period, de facto standards will have\r
+     to be developed.\r
+\r
+     * Capture information in a way that keeps all options open and\r
+     provides for total convertibility:  OCR, scanning of microfilm,\r
+     producing microfilm from scanned documents, etc.\r
+\r
+     * Work closely with the generators of information and the builders\r
+     of networks and databases to ensure that continuing accessibility is\r
+     a primary concern from the beginning.\r
+\r
+     * Piggyback on standards under development for the broad market, and\r
+     avoid library-specific standards; work with the vendors, in order to\r
+     take advantage of that which is being standardized for the rest of\r
+     the world.\r
+\r
+     * Concentrate efforts on managing permanence in the digital world,\r
+     rather than perfecting the longevity of a particular medium.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Additional comments on TIFF *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+During the brief discussion period that followed BATTIN's presentation,\r
+BARONAS explained that TIFF was not developed in collaboration with or\r
+under the auspices of AIIM.  TIFF is a company product, not a standard,\r
+is owned by two corporations, and is always changing.  BARONAS also\r
+observed that ANSI/AIIM MS53, a bi-level image file transfer format that\r
+allows unlike systems to exchange images, is compatible with TIFF as well\r
+as with DEC's architecture and IBM's MODCA/IOCA.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+HOOTON * Several questions to be considered in discussing text conversion\r
+*\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+HOOTON introduced the final topic, text conversion, by noting that it is\r
+becoming an increasingly important part of the imaging business.  Many\r
+people now realize that it enhances their system to be able to have more\r
+and more character data as part of their imaging system.  Re the issue of\r
+OCR versus rekeying, HOOTON posed several questions:  How does one get\r
+text into computer-readable form?  Does one use automated processes? \r
+Does one attempt to eliminate the use of operators where possible? \r
+Standards for accuracy, he said, are extremely important:  it makes a\r
+major difference in cost and time whether one sets as a standard 98.5\r
+percent acceptance or 99.5 percent.  He mentioned outsourcing as a\r
+possibility for converting text.  Finally, what one does with the image\r
+to prepare it for the recognition process is also important, he said,\r
+because such preparation changes how recognition is viewed, as well as\r
+facilitates recognition itself.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+LESK * Roles of participants in CORE * Data flow * The scanning process *\r
+The image interface * Results of experiments involving the use of\r
+electronic resources and traditional paper copies * Testing the issue of\r
+serendipity * Conclusions *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Michael LESK, executive director, Computer Science Research, Bell\r
+Communications Research, Inc. (Bellcore), discussed the Chemical Online\r
+Retrieval Experiment (CORE), a cooperative project involving Cornell\r
+University, OCLC, Bellcore, and the American Chemical Society (ACS).\r
+\r
+LESK spoke on 1) how the scanning was performed, including the unusual\r
+feature of page segmentation, and 2) the use made of the text and the\r
+image in experiments.\r
+\r
+Working with the chemistry journals (because ACS has been saving its\r
+typesetting tapes since the mid-1970s and thus has a significant back-run\r
+of the most important chemistry journals in the United States), CORE is\r
+attempting to create an automated chemical library.  Approximately a\r
+quarter of the pages by square inch are made up of images of\r
+quasi-pictorial material; dealing with the graphic components of the\r
+pages is extremely important.  LESK described the roles of participants\r
+in CORE:  1) ACS provides copyright permission, journals on paper,\r
+journals on microfilm, and some of the definitions of the files; 2) at\r
+Bellcore, LESK chiefly performs the data preparation, while Dennis Egan\r
+performs experiments on the users of chemical abstracts, and supplies the\r
+indexing and numerous magnetic tapes;  3) Cornell provides the site of the\r
+experiment; 4) OCLC develops retrieval software and other user interfaces.\r
+Various manufacturers and publishers have furnished other help.\r
+\r
+Concerning data flow, Bellcore receives microfilm and paper from ACS; the\r
+microfilm is scanned by outside vendors, while the paper is scanned\r
+inhouse on an Improvision scanner, twenty pages per minute at 300 dpi,\r
+which provides sufficient quality for all practical uses.  LESK would\r
+prefer to have more gray level, because one of the ACS journals prints on\r
+some colored pages, which creates a problem.\r
+\r
+Bellcore performs all this scanning, creates a page-image file, and also\r
+selects from the pages the graphics, to mix with the text file (which is\r
+discussed later in the Workshop).  The user is always searching the ASCII\r
+file, but she or he may see a display based on the ASCII or a display\r
+based on the images.\r
+\r
+LESK illustrated how the program performs page analysis, and the image\r
+interface.  (The user types several words, is presented with a list--\r
+usually of the titles of articles contained in an issue--that derives\r
+from the ASCII, clicks on an icon and receives an image that mirrors an\r
+ACS page.)  LESK also illustrated an alternative interface, based on text\r
+on the ASCII, the so-called SuperBook interface from Bellcore.\r
+\r
+LESK next presented the results of an experiment conducted by Dennis Egan\r
+and involving thirty-six students at Cornell, one third of them\r
+undergraduate chemistry majors, one third senior undergraduate chemistry\r
+majors, and one third graduate chemistry students.  A third of them\r
+received the paper journals, the traditional paper copies and chemical\r
+abstracts on paper.  A third received image displays of the pictures of\r
+the pages, and a third received the text display with pop-up graphics.\r
+\r
+The students were given several questions made up by some chemistry\r
+professors.  The questions fell into five classes, ranging from very easy\r
+to very difficult, and included questions designed to simulate browsing\r
+as well as a traditional information retrieval-type task.\r
+\r
+LESK furnished the following results.  In the straightforward question\r
+search--the question being, what is the phosphorus oxygen bond distance\r
+and hydroxy phosphate?--the students were told that they could take\r
+fifteen minutes and, then, if they wished, give up.  The students with\r
+paper took more than fifteen minutes on average, and yet most of them\r
+gave up.  The students with either electronic format, text or image,\r
+received good scores in reasonable time, hardly ever had to give up, and\r
+usually found the right answer.\r
+\r
+In the browsing study, the students were given a list of eight topics,\r
+told to imagine that an issue of the Journal of the American Chemical\r
+Society had just appeared on their desks, and were also told to flip\r
+through it and to find topics mentioned in the issue.  The average scores\r
+were about the same.  (The students were told to answer yes or no about\r
+whether or not particular topics appeared.)  The errors, however, were\r
+quite different.  The students with paper rarely said that something\r
+appeared when it had not.  But they often failed to find something\r
+actually mentioned in the issue.  The computer people found numerous\r
+things, but they also frequently said that a topic was mentioned when it\r
+was not.  (The reason, of course, was that they were performing word\r
+searches.  They were finding that words were mentioned and they were\r
+concluding that they had accomplished their task.)\r
+\r
+This question also contained a trick to test the issue of serendipity. \r
+The students were given another list of eight topics and instructed,\r
+without taking a second look at the journal, to recall how many of this\r
+new list of eight topics were in this particular issue.  This was an\r
+attempt to see if they performed better at remembering what they were not\r
+looking for.  They all performed about the same, paper or electronics,\r
+about 62 percent accurate.  In short, LESK said, people were not very\r
+good when it came to serendipity, but they were no worse at it with\r
+computers than they were with paper.\r
+\r
+(LESK gave a parenthetical illustration of the learning curve of students\r
+who used SuperBook.)\r
+\r
+The students using the electronic systems started off worse than the ones\r
+using print, but by the third of the three sessions in the series had\r
+caught up to print.  As one might expect, electronics provide a much\r
+better means of finding what one wants to read; reading speeds, once the\r
+object of the search has been found, are about the same.\r
+\r
+Almost none of the students could perform the hard task--the analogous\r
+transformation.  (It would require the expertise of organic chemists to\r
+complete.)  But an interesting result was that the students using the text\r
+search performed terribly, while those using the image system did best.\r
+That the text search system is driven by text offers the explanation.\r
+Everything is focused on the text; to see the pictures, one must press\r
+on an icon.  Many students found the right article containing the answer\r
+to the question, but they did not click on the icon to bring up the right\r
+figure and see it.  They did not know that they had found the right place,\r
+and thus got it wrong.\r
+\r
+The short answer demonstrated by this experiment was that in the event\r
+one does not know what to read, one needs the electronic systems; the\r
+electronic systems hold no advantage at the moment if one knows what to\r
+read, but neither do they impose a penalty.\r
+\r
+LESK concluded by commenting that, on one hand, the image system was easy\r
+to use.  On the other hand, the text display system, which represented\r
+twenty man-years of work in programming and polishing, was not winning,\r
+because the text was not being read, just searched.  The much easier\r
+system is highly competitive as well as remarkably effective for the\r
+actual chemists.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ERWAY * Most challenging aspect of working on AM * Assumptions guiding\r
+AM's approach * Testing different types of service bureaus * AM's\r
+requirement for 99.95 percent accuracy * Requirements for text-coding *\r
+Additional factors influencing AM's approach to coding * Results of AM's\r
+experience with rekeying * Other problems in dealing with service bureaus\r
+* Quality control the most time-consuming aspect of contracting out\r
+conversion * Long-term outlook uncertain *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+To Ricky ERWAY, associate coordinator, American Memory, Library of\r
+Congress, the constant variety of conversion projects taking place\r
+simultaneously represented perhaps the most challenging aspect of working\r
+on AM.  Thus, the challenge was not to find a solution for text\r
+conversion but a tool kit of solutions to apply to LC's varied\r
+collections that need to be converted.  ERWAY limited her remarks to the\r
+process of converting text to machine-readable form, and the variety of\r
+LC's text collections, for example, bound volumes, microfilm, and\r
+handwritten manuscripts.\r
+\r
+Two assumptions have guided AM's approach, ERWAY said:  1) A desire not\r
+to perform the conversion inhouse.  Because of the variety of formats and\r
+types of texts, to capitalize the equipment and have the talents and\r
+skills to operate them at LC would be extremely expensive.  Further, the\r
+natural inclination to upgrade to newer and better equipment each year\r
+made it reasonable for AM to focus on what it did best and seek external\r
+conversion services.  Using service bureaus also allowed AM to have\r
+several types of operations take place at the same time.  2) AM was not a\r
+technology project, but an effort to improve access to library\r
+collections.  Hence, whether text was converted using OCR or rekeying\r
+mattered little to AM.  What mattered were cost and accuracy of results.\r
+\r
+AM considered different types of service bureaus and selected three to\r
+perform several small tests in order to acquire a sense of the field. \r
+The sample collections with which they worked included handwritten\r
+correspondence, typewritten manuscripts from the 1940s, and\r
+eighteenth-century printed broadsides on microfilm.  On none of these\r
+samples was OCR performed; they were all rekeyed.  AM had several special\r
+requirements for the three service bureaus it had engaged.  For instance,\r
+any errors in the original text were to be retained.  Working from bound\r
+volumes or anything that could not be sheet-fed also constituted a factor\r
+eliminating companies that would have performed OCR.\r
+\r
+AM requires 99.95 percent accuracy, which, though it sounds high, often\r
+means one or two errors per page.  The initial batch of test samples\r
+contained several handwritten materials for which AM did not require\r
+text-coding.  The results, ERWAY reported, were in all cases fairly\r
+comparable:  for the most part, all three service bureaus achieved 99.95\r
+percent accuracy.  AM was satisfied with the work but surprised at the cost.\r
+\r
+As AM began converting whole collections, it retained the requirement for\r
+99.95 percent accuracy and added requirements for text-coding.  AM needed\r
+to begin performing work more than three years ago before LC requirements\r
+for SGML applications had been established.  Since AM's goal was simply\r
+to retain any of the intellectual content represented by the formatting\r
+of the document (which would be lost if one performed a straight ASCII\r
+conversion), AM used "SGML-like" codes.  These codes resembled SGML tags\r
+but were used without the benefit of document-type definitions.  AM found\r
+that many service bureaus were not yet SGML-proficient.\r
+\r
+Additional factors influencing the approach AM took with respect to\r
+coding included:  1) the inability of any known microcomputer-based\r
+user-retrieval software to take advantage of SGML coding; and 2) the\r
+multiple inconsistencies in format of the older documents, which\r
+confirmed AM in its desire not to attempt to force the different formats\r
+to conform to a single document-type definition (DTD) and thus create the\r
+need for a separate DTD for each document. \r
+\r
+The five text collections that AM has converted or is in the process of\r
+converting include a collection of eighteenth-century broadsides, a\r
+collection of pamphlets, two typescript document collections, and a\r
+collection of 150 books.\r
+\r
+ERWAY next reviewed the results of AM's experience with rekeying, noting\r
+again that because the bulk of AM's materials are historical, the quality\r
+of the text often does not lend itself to OCR.  While non-English\r
+speakers are less likely to guess or elaborate or correct typos in the\r
+original text, they are also less able to infer what we would; they also\r
+are nearly incapable of converting handwritten text.  Another\r
+disadvantage of working with overseas keyers is that they are much less\r
+likely to telephone with questions, especially on the coding, with the\r
+result that they develop their own rules as they encounter new\r
+situations.\r
+\r
+Government contracting procedures and time frames posed a major challenge\r
+to performing the conversion.  Many service bureaus are not accustomed to\r
+retaining the image, even if they perform OCR.  Thus, questions of image\r
+format and storage media were somewhat novel to many of them.  ERWAY also\r
+remarked other problems in dealing with service bureaus, for example,\r
+their inability to perform text conversion from the kind of microfilm\r
+that LC uses for preservation purposes.\r
+\r
+But quality control, in ERWAY's experience, was the most time-consuming\r
+aspect of contracting out conversion.  AM has been attempting to perform\r
+a 10-percent quality review, looking at either every tenth document or\r
+every tenth page to make certain that the service bureaus are maintaining\r
+99.95 percent accuracy.  But even if they are complying with the\r
+requirement for accuracy, finding errors produces a desire to correct\r
+them and, in turn, to clean up the whole collection, which defeats the\r
+purpose to some extent.  Even a double entry requires a\r
+character-by-character comparison to the original to meet the accuracy\r
+requirement.  LC is not accustomed to publish imperfect texts, which\r
+makes attempting to deal with the industry standard an emotionally\r
+fraught issue for AM.  As was mentioned in the previous day's discussion,\r
+going from 99.95 to 99.99 percent accuracy usually doubles costs and\r
+means a third keying or another complete run-through of the text.\r
+\r
+Although AM has learned much from its experiences with various collections\r
+and various service bureaus, ERWAY concluded pessimistically that no\r
+breakthrough has been achieved.   Incremental improvements have occurred\r
+in some of the OCR technology, some of the processes, and some of the\r
+standards acceptances, which, though they may lead to somewhat lower costs,\r
+do not offer much encouragement to many people who are anxiously awaiting\r
+the day that the entire contents of LC are available on-line.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ZIDAR * Several answers to why one attempts to perform full-text\r
+conversion * Per page cost of performing OCR * Typical problems\r
+encountered during editing * Editing poor copy OCR vs. rekeying *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Judith ZIDAR, coordinator, National Agricultural Text Digitizing Program\r
+(NATDP), National Agricultural Library (NAL), offered several answers to\r
+the question of why one attempts to perform full-text conversion:  1)\r
+Text in an image can be read by a human but not by a computer, so of\r
+course it is not searchable and there is not much one can do with it.  2)\r
+Some material simply requires word-level access.  For instance, the legal\r
+profession insists on full-text access to its material; with taxonomic or\r
+geographic material, which entails numerous names, one virtually requires\r
+word-level access.  3) Full text permits rapid browsing and searching,\r
+something that cannot be achieved in an image with today's technology. \r
+4) Text stored as ASCII and delivered in ASCII is standardized and highly\r
+portable.  5) People just want full-text searching, even those who do not\r
+know how to do it.  NAL, for the most part, is performing OCR at an\r
+actual cost per average-size page of approximately $7.  NAL scans the\r
+page to create the electronic image and passes it through the OCR device.\r
+\r
+ZIDAR next rehearsed several typical problems encountered during editing. \r
+Praising the celerity of her student workers, ZIDAR observed that editing\r
+requires approximately five to ten minutes per page, assuming that there\r
+are no large tables to audit.  Confusion among the three characters I, 1, \r
+and l, constitutes perhaps the most common problem encountered.  Zeroes\r
+and  O's also are  frequently confused.  Double M's create a particular\r
+problem, even on clean pages.  They are so wide in most fonts that they\r
+touch, and the system simply cannot tell where one letter ends and the\r
+other begins.  Complex page formats occasionally fail to columnate\r
+properly, which entails rescanning as though one were working with a\r
+single column, entering the ASCII, and decolumnating for better\r
+searching.  With proportionally spaced text, OCR can have difficulty\r
+discerning what is a space and what are merely spaces between letters, as\r
+opposed to spaces between words, and therefore will merge text or break\r
+up words where it should not.\r
+\r
+ZIDAR said that it can often take longer to edit a poor-copy OCR than to\r
+key it from scratch.  NAL has also experimented with partial editing of\r
+text, whereby project workers go into and clean up the format, removing\r
+stray characters but not running a spell-check.  NAL corrects typos in\r
+the title and authors' names, which provides a foothold for searching and\r
+browsing.  Even extremely poor-quality OCR (e.g., 60-percent accuracy)\r
+can still be searched, because numerous words are correct, while the\r
+important words are probably repeated often enough that they are likely\r
+to be found correct somewhere.  Librarians, however, cannot tolerate this\r
+situation, though end users seem more willing to use this text for\r
+searching, provided that NAL indicates that it is unedited.  ZIDAR\r
+concluded that rekeying of text may be the best route to take, in spite\r
+of numerous problems with quality control and cost.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Modifying an image before performing OCR * NAL's costs per\r
+page *AM's costs per page and experience with Federal Prison Industries *\r
+Elements comprising NATDP's costs per page * OCR and structured markup *\r
+Distinction between the structure of a document and its representation\r
+when put on the screen or printed *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+HOOTON prefaced the lengthy discussion that followed with several\r
+comments about modifying an image before one reaches the point of\r
+performing OCR.  For example, in regard to an application containing a\r
+significant amount of redundant data, such as form-type data, numerous\r
+companies today are working on various kinds of form renewal, prior to\r
+going through a recognition process, by using dropout colors.  Thus,\r
+acquiring access to form design or using electronic means are worth\r
+considering.  HOOTON also noted that conversion usually makes or breaks\r
+one's imaging system.  It is extremely important, extremely costly in\r
+terms of either capital investment or service, and determines the quality\r
+of the remainder of one's system, because it determines the character of\r
+the raw material used by the system.\r
+\r
+Concerning the four projects undertaken by NAL, two inside and two\r
+performed by outside contractors, ZIDAR revealed that an in-house service\r
+bureau executed the first at a cost between $8 and $10 per page for\r
+everything, including building of the database.  The project undertaken\r
+by the Consultative Group on International Agricultural Research (CGIAR)\r
+cost approximately $10 per page for the conversion, plus some expenses\r
+for the software and building of the database.  The Acid Rain Project--a\r
+two-disk set produced by the University of Vermont, consisting of\r
+Canadian publications on acid rain--cost $6.70 per page for everything,\r
+including keying of the text, which was double keyed, scanning of the\r
+images, and building of the database.  The in-house project offered\r
+considerable ease of convenience and greater control of the process.  On\r
+the other hand, the service bureaus know their job and perform it\r
+expeditiously, because they have more people.\r
+\r
+As a useful comparison, ERWAY revealed AM's costs as follows:  $0.75\r
+cents to $0.85 cents per thousand characters, with an average page\r
+containing 2,700 characters.  Requirements for coding and imaging\r
+increase the costs.  Thus, conversion of the text, including the coding,\r
+costs approximately $3 per page.  (This figure does not include the\r
+imaging and database-building included in the NAL costs.)  AM also\r
+enjoyed a happy experience with Federal Prison Industries, which\r
+precluded the necessity of going through the request-for-proposal process\r
+to award a contract, because it is another government agency.  The\r
+prisoners performed AM's rekeying just as well as other service bureaus\r
+and proved handy as well.  AM shipped them the books, which they would\r
+photocopy on a book-edge scanner.  They would perform the markup on\r
+photocopies, return the books as soon as they were done with them,\r
+perform the keying, and return the material to AM on WORM disks.\r
+\r
+ZIDAR detailed the elements that constitute the previously noted cost of\r
+approximately $7 per page.  Most significant is the editing, correction\r
+of errors, and spell-checkings, which though they may sound easy to\r
+perform require, in fact, a great deal of time.  Reformatting text also\r
+takes a while, but a significant amount of NAL's expenses are for equipment,\r
+which was extremely expensive when purchased because it was one of the few\r
+systems on the market.  The costs of equipment are being amortized over\r
+five years but are still quite high, nearly $2,000 per month.\r
+\r
+HOCKEY raised a general question concerning OCR and the amount of editing\r
+required (substantial in her experience) to generate the kind of\r
+structured markup necessary for manipulating the text on the computer or\r
+loading it into any retrieval system.  She wondered if the speakers could\r
+extend the previous question about the cost-benefit of adding or exerting\r
+structured markup.  ERWAY noted that several OCR systems retain italics,\r
+bolding, and other spatial formatting.  While the material may not be in\r
+the format desired, these systems possess the ability to remove the\r
+original materials quickly from the hands of the people performing the\r
+conversion, as well as to retain that information so that users can work\r
+with it.  HOCKEY rejoined that the current thinking on markup is that one\r
+should not say that something is italic or bold so much as why it is that\r
+way.  To be sure, one needs to know that something was italicized, but\r
+how can one get from one to the other?  One can map from the structure to\r
+the typographic representation.\r
+\r
+FLEISCHHAUER suggested that, given the 100 million items the Library\r
+holds, it may not be possible for LC to do more than report that a thing\r
+was in italics as opposed to why it was italics, although that may be\r
+desirable in some contexts.  Promising to talk a bit during the afternoon\r
+session about several experiments OCLC performed on automatic recognition\r
+of document elements, and which they hoped to extend, WEIBEL said that in\r
+fact one can recognize the major elements of a document with a fairly\r
+high degree of reliability, at least as good as OCR.  STEVENS drew a\r
+useful distinction between standard, generalized markup (i.e., defining\r
+for a document-type definition the structure of the document), and what\r
+he termed a style sheet, which had to do with italics, bolding, and other\r
+forms of emphasis.  Thus, two different components are at work, one being\r
+the structure of the document itself (its logic), and the other being its\r
+representation when it is put on the screen or printed.\r
+\r
+                                 ******\r
+\r
+SESSION V.  APPROACHES TO PREPARING ELECTRONIC TEXTS\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+HOCKEY * Text in ASCII and the representation of electronic text versus\r
+an image * The need to look at ways of using markup to assist retrieval *\r
+The need for an encoding format that will be reusable and multifunctional\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Susan HOCKEY, director, Center for Electronic Texts in the Humanities\r
+(CETH), Rutgers and Princeton Universities, announced that one talk\r
+(WEIBEL's) was moved into this session from the morning and that David\r
+Packard was unable to attend.  The session would attempt to focus more on\r
+what one can do with a text in ASCII and the representation of electronic\r
+text rather than just an image, what one can do with a computer that\r
+cannot be done with a book or an image.  It would be argued that one can\r
+do much more than just read a text, and from that starting point one can\r
+use markup and methods of preparing the text to take full advantage of\r
+the capability of the computer.  That would lead to a discussion of what\r
+the European Community calls REUSABILITY, what may better be termed\r
+DURABILITY, that is, how to prepare or make a text that will last a long\r
+time and that can be used for as many applications as possible, which\r
+would lead to issues of improving intellectual access.\r
+\r
+HOCKEY urged the need to look at ways of using markup to facilitate retrieval,\r
+not just for referencing or to help locate an item that is retrieved, but also to put markup tags in\r
+a text to help retrieve the thing sought either with linguistic tagging or\r
+interpretation.  HOCKEY also argued that little advancement had occurred in\r
+the software tools currently available for retrieving and searching text.\r
+She pressed the desideratum of going beyond Boolean searches and performing\r
+more sophisticated searching, which the insertion of more markup in the text\r
+would facilitate.  Thinking about electronic texts as opposed to images means\r
+considering material that will never appear in print form, or print will not\r
+be its primary form, that is, material which only appears in electronic form.\r
+HOCKEY alluded to the history and the need for markup and tagging and\r
+electronic text, which was developed through the use of computers in the\r
+humanities; as MICHELSON had observed, Father Busa had started in 1949\r
+to prepare the first-ever text on the computer.\r
+\r
+HOCKEY remarked several large projects, particularly in Europe, for the\r
+compilation of dictionaries, language studies, and language analysis, in\r
+which people have built up archives of text and have begun to recognize\r
+the need for an encoding format that will be reusable and multifunctional,\r
+that can be used not just to print the text, which may be assumed to be a\r
+byproduct of what one wants to do, but to structure it inside the computer\r
+so that it can be searched, built into a Hypertext system, etc.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+WEIBEL * OCLC's approach to preparing electronic text:  retroconversion,\r
+keying of texts, more automated ways of developing data * Project ADAPT\r
+and the CORE Project * Intelligent character recognition does not exist *\r
+Advantages of SGML * Data should be free of procedural markup;\r
+descriptive markup strongly advocated * OCLC's interface illustrated *\r
+Storage requirements and costs for putting a lot of information on line *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Stuart WEIBEL, senior research scientist, Online Computer Library Center,\r
+Inc. (OCLC), described OCLC's approach to preparing electronic text.  He\r
+argued that the electronic world into which we are moving must\r
+accommodate not only the future but the past as well, and to some degree\r
+even the present.  Thus, starting out at one end with retroconversion and\r
+keying of texts, one would like to move toward much more automated ways\r
+of developing data.\r
+\r
+For example, Project ADAPT had to do with automatically converting\r
+document images into a structured document database with OCR text as\r
+indexing and also a little bit of automatic formatting and tagging of\r
+that text.  The CORE project hosted by Cornell University, Bellcore,\r
+OCLC, the American Chemical Society, and Chemical Abstracts, constitutes\r
+WEIBEL's principal concern at the moment.  This project is an example of\r
+converting text for which one already has a machine-readable version into\r
+a format more suitable for electronic delivery and database searching. \r
+(Since Michael LESK had previously described CORE, WEIBEL would say\r
+little concerning it.)  Borrowing a chemical phrase, de novo synthesis,\r
+WEIBEL cited the Online Journal of Current Clinical Trials as an example\r
+of de novo electronic publishing, that is, a form in which the primary\r
+form of the information is electronic.\r
+\r
+Project ADAPT, then, which OCLC completed a couple of years ago and in\r
+fact is about to resume, is a model in which one takes page images either\r
+in paper or microfilm and converts them automatically to a searchable\r
+electronic database, either on-line or local.  The operating assumption\r
+is that accepting some blemishes in the data, especially for\r
+retroconversion of materials, will make it possible to accomplish more. \r
+Not enough money is available to support perfect conversion.\r
+\r
+WEIBEL related several steps taken to perform image preprocessing\r
+(processing on the image before performing optical character\r
+recognition), as well as image postprocessing.  He denied the existence\r
+of intelligent character recognition and asserted that what is wanted is\r
+page recognition, which is a long way off.  OCLC has experimented with\r
+merging of multiple optical character recognition systems that will\r
+reduce errors from an unacceptable rate of 5 characters out of every\r
+l,000 to an unacceptable rate of 2 characters out of every l,000, but it\r
+is not good enough.  It will never be perfect.\r
+\r
+Concerning the CORE Project, WEIBEL observed that Bellcore is taking the\r
+topography files, extracting the page images, and converting those\r
+topography files to SGML markup.  LESK hands that data off to OCLC, which\r
+builds that data into a Newton database, the same system that underlies\r
+the on-line system in virtually all of the reference products at OCLC. \r
+The long-term goal is to make the systems interoperable so that not just\r
+Bellcore's system and OCLC's system can access this data, but other\r
+systems can as well, and the key to that is the Z39.50 common command\r
+language and the full-text extension.  Z39.50 is fine for MARC records,\r
+but is not enough to do it for full text (that is, make full texts\r
+interoperable).\r
+\r
+WEIBEL next outlined the critical role of SGML for a variety of purposes,\r
+for example, as noted by HOCKEY, in the world of extremely large\r
+databases, using highly structured data to perform field searches. \r
+WEIBEL argued that by building the structure of the data in (i.e., the\r
+structure of the data originally on a printed page), it becomes easy to\r
+look at a journal article even if one cannot read the characters and know\r
+where the title or author is, or what the sections of that document would be.\r
+OCLC wants to make that structure explicit in the database, because it will\r
+be important for retrieval purposes.\r
+\r
+The second big advantage of SGML is that it gives one the ability to\r
+build structure into the database that can be used for display purposes\r
+without contaminating the data with instructions about how to format\r
+things.  The distinction lies between procedural markup, which tells one\r
+where to put dots on the page, and descriptive markup, which describes\r
+the elements of a document.\r
+\r
+WEIBEL believes that there should be no procedural markup in the data at\r
+all, that the data should be completely unsullied by information about\r
+italics or boldness.  That should be left up to the display device,\r
+whether that display device is a page printer or a screen display device. \r
+By keeping one's database free of that kind of contamination, one can\r
+make decisions down the road, for example, reorganize the data in ways\r
+that are not cramped by built-in notions of what should be italic and\r
+what should be bold.  WEIBEL strongly advocated descriptive markup.  As\r
+an example, he illustrated the index structure in the CORE data.  With\r
+subsequent illustrated examples of markup, WEIBEL acknowledged the common\r
+complaint that SGML is hard to read in its native form, although markup\r
+decreases considerably once one gets into the body.  Without the markup,\r
+however, one would not have the structure in the data.  One can pass\r
+markup through a LaTeX processor and convert it relatively easily to a\r
+printed version of the document.\r
+\r
+WEIBEL next illustrated an extremely cluttered screen dump of OCLC's\r
+system, in order to show as much as possible the inherent capability on\r
+the screen.  (He noted parenthetically that he had become a supporter of\r
+X-Windows as a result of the progress of the CORE Project.)  WEIBEL also\r
+illustrated the two major parts of the interface:  l) a control box that\r
+allows one to generate lists of items, which resembles a small table of\r
+contents based on key words one wishes to search, and 2) a document\r
+viewer, which is a separate process in and of itself.  He demonstrated\r
+how to follow links through the electronic database simply by selecting\r
+the appropriate button and bringing them up.  He also noted problems that\r
+remain to be accommodated in the interface (e.g., as pointed out by LESK,\r
+what happens when users do not click on the icon for the figure).\r
+\r
+Given the constraints of time, WEIBEL omitted a large number of ancillary\r
+items in order to say a few words concerning storage requirements and\r
+what will be required to put a lot of things on line.  Since it is\r
+extremely expensive to reconvert all of this data, especially if it is\r
+just in paper form (and even if it is in electronic form in typesetting\r
+tapes), he advocated building journals electronically from the start.  In\r
+that case, if one only has text graphics and indexing (which is all that\r
+one needs with de novo electronic publishing, because there is no need to\r
+go back and look at bit-maps of pages), one can get 10,000 journals of\r
+full text, or almost 6 million pages per year.  These pages can be put in\r
+approximately 135 gigabytes of storage, which is not all that much,\r
+WEIBEL said.  For twenty years, something less than three terabytes would\r
+be required.  WEIBEL calculated the costs of storing this information as\r
+follows:  If a gigabyte costs approximately $1,000, then a terabyte costs\r
+approximately $1 million to buy in terms of hardware.  One also needs a\r
+building to put it in and a staff like OCLC to handle that information. \r
+So, to support a terabyte, multiply by five, which gives $5 million per\r
+year for a supported terabyte of data.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Tapes saved by ACS are the typography files originally\r
+supporting publication of the journal * Cost of building tagged text into\r
+the database *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+During the question-and-answer period that followed WEIBEL's\r
+presentation, these clarifications emerged.  The tapes saved by the\r
+American Chemical Society are the typography files that originally\r
+supported the publication of the journal.  Although they are not tagged\r
+in SGML, they are tagged in very fine detail.  Every single sentence is\r
+marked, all the registry numbers, all the publications issues, dates, and\r
+volumes.  No cost figures on tagging material on a per-megabyte basis\r
+were available.  Because ACS's typesetting system runs from tagged text,\r
+there is no extra cost per article.  It was unknown what it costs ACS to\r
+keyboard the tagged text rather than just keyboard the text in the\r
+cheapest process.  In other words, since one intends to publish things\r
+and will need to build tagged text into a typography system in any case,\r
+if one does that in such a way that it can drive not only typography but\r
+an electronic system (which is what ACS intends to do--move to SGML\r
+publishing), the marginal cost is zero.  The marginal cost represents the\r
+cost of building tagged text into the database, which is small.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+SPERBERG-McQUEEN * Distinction between texts and computers * Implications\r
+of recognizing that all representation is encoding * Dealing with\r
+complicated representations of text entails the need for a grammar of\r
+documents * Variety of forms of formal grammars * Text as a bit-mapped\r
+image does not represent a serious attempt to represent text in\r
+electronic form * SGML, the TEI, document-type declarations, and the\r
+reusability and longevity of data * TEI conformance explicitly allows\r
+extension or modification of the TEI tag set * Administrative background\r
+of the TEI * Several design goals for the TEI tag set * An absolutely\r
+fixed requirement of the TEI Guidelines * Challenges the TEI has\r
+attempted to face * Good texts not beyond economic feasibility * The\r
+issue of reproducibility or processability * The issue of mages as\r
+simulacra for the text redux * One's model of text determines what one's\r
+software can do with a text and has economic consequences *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Prior to speaking about SGML and markup, Michael SPERBERG-McQUEEN, editor,\r
+Text Encoding Initiative (TEI), University of Illinois-Chicago, first drew\r
+a distinction between texts and computers:  Texts are abstract cultural\r
+and linguistic objects while computers are complicated physical devices,\r
+he said.  Abstract objects cannot be placed inside physical devices; with\r
+computers one can only represent text and act upon those representations.\r
+\r
+The recognition that all representation is encoding, SPERBERG-McQUEEN\r
+argued, leads to the recognition of two things:  1) The topic description\r
+for this session is slightly misleading, because there can be no discussion\r
+of pros and cons of text-coding unless what one means is pros and cons of\r
+working with text with computers.  2) No text can be represented in a\r
+computer without some sort of encoding; images are one way of encoding text,\r
+ASCII is another, SGML yet another.  There is no encoding without some\r
+information loss, that is, there is no perfect reproduction of a text that\r
+allows one to do away with the original.  Thus, the question becomes,\r
+What is the most useful representation of text for a serious work?\r
+This depends on what kind of serious work one is talking about.\r
+\r
+The projects demonstrated the previous day all involved highly complex\r
+information and fairly complex manipulation of the textual material.\r
+In order to use that complicated information, one has to calculate it\r
+slowly or manually and store the result.  It needs to be stored, therefore,\r
+as part of one's representation of the text.  Thus, one needs to store the\r
+structure in the text.  To deal with complicated representations of text,\r
+one needs somehow to control the complexity of the representation of a text;\r
+that means one needs a way of finding out whether a document and an\r
+electronic representation of a document is legal or not; and that\r
+means one needs a grammar of documents.\r
+\r
+SPERBERG-McQUEEN discussed the variety of forms of formal grammars,\r
+implicit and explicit, as applied to text, and their capabilities.  He\r
+argued that these grammars correspond to different models of text that\r
+different developers have.  For example, one implicit model of the text\r
+is that there is no internal structure, but just one thing after another,\r
+a few characters and then perhaps a start-title command, and then a few\r
+more characters and an end-title command.  SPERBERG-McQUEEN also\r
+distinguished several kinds of text that have a sort of hierarchical\r
+structure that is not very well defined, which, typically, corresponds\r
+to grammars that are not very well defined, as well as hierarchies that\r
+are very well defined (e.g., the Thesaurus Linguae Graecae) and extremely\r
+complicated things such as SGML, which handle strictly hierarchical data\r
+very nicely.\r
+\r
+SPERBERG-McQUEEN conceded that one other model not illustrated on his two\r
+displays was the model of text as a bit-mapped image, an image of a page,\r
+and confessed to having been converted to a limited extent by the\r
+Workshop to the view that electronic images constitute a promising,\r
+probably superior alternative to microfilming.  But he was not convinced\r
+that electronic images represent a serious attempt to represent text in\r
+electronic form.  Many of their problems stem from the fact that they are\r
+not direct attempts to represent the text but attempts to represent the\r
+page, thus making them representations of representations.\r
+\r
+In this situation of increasingly complicated textual information and the\r
+need to control that complexity in a useful way (which begs the question\r
+of the need for good textual grammars), one has the introduction of SGML. \r
+With SGML, one can develop specific document-type declarations\r
+for specific text types or, as with the TEI, attempts to generate\r
+general document-type declarations that can handle all sorts of text.\r
+The TEI is an attempt to develop formats for text representation that\r
+will ensure the kind of reusability and longevity of data discussed earlier.\r
+It offers a way to stay alive in the state of permanent technological\r
+revolution.\r
+\r
+It has been a continuing challenge in the TEI to create document grammars\r
+that do some work in controlling the complexity of the textual object but\r
+also allowing one to represent the real text that one will find. \r
+Fundamental to the notion of the TEI is that TEI conformance allows one\r
+the ability to extend or modify the TEI tag set so that it fits the text\r
+that one is attempting to represent.\r
+\r
+SPERBERG-McQUEEN next outlined the administrative background of the TEI. \r
+The TEI is an international project to develop and disseminate guidelines\r
+for the encoding and interchange of machine-readable text.  It is\r
+sponsored by the Association for Computers in the Humanities, the\r
+Association for Computational Linguistics, and the Association for\r
+Literary and Linguistic Computing.  Representatives of numerous other\r
+professional societies sit on its advisory board.  The TEI has a number\r
+of affiliated projects that have provided assistance by testing drafts of\r
+the guidelines.\r
+\r
+Among the design goals for the TEI tag set, the scheme first of all must\r
+meet the needs of research, because the TEI came out of the research\r
+community, which did not feel adequately served by existing tag sets. \r
+The tag set must be extensive as well as compatible with existing and\r
+emerging standards.  In 1990, version 1.0 of the Guidelines was released\r
+(SPERBERG-McQUEEN illustrated their contents).\r
+\r
+SPERBERG-McQUEEN noted that one problem besetting electronic text has\r
+been the lack of adequate internal or external documentation for many\r
+existing electronic texts.  The TEI guidelines as currently formulated\r
+contain few fixed requirements, but one of them is this:  There must\r
+always be a document header, an in-file SGML tag that provides\r
+1) a bibliographic description of the electronic object one is talking\r
+about (that is, who included it, when, what for, and under which title);\r
+and 2) the copy text from which it was derived, if any.  If there was\r
+no copy text or if the copy text is unknown, then one states as much.\r
+Version 2.0 of the Guidelines was scheduled to be completed in fall 1992\r
+and a revised third version is to be presented to the TEI advisory board\r
+for its endorsement this coming winter.  The TEI itself exists to provide\r
+a markup language, not a marked-up text.\r
+\r
+Among the challenges the TEI has attempted to face is the need for a\r
+markup language that will work for existing projects, that is, handle the\r
+level of markup that people are using now to tag only chapter, section,\r
+and paragraph divisions and not much else.  At the same time, such a\r
+language also will be able to scale up gracefully to handle the highly\r
+detailed markup which many people foresee as the future destination of\r
+much electronic text, and which is not the future destination but the\r
+present home of numerous electronic texts in specialized areas.\r
+\r
+SPERBERG-McQUEEN dismissed the lowest-common-denominator approach as\r
+unable to support the kind of applications that draw people who have\r
+never been in the public library regularly before, and make them come\r
+back.  He advocated more interesting text and more intelligent text. \r
+Asserting that it is not beyond economic feasibility to have good texts,\r
+SPERBERG-McQUEEN noted that the TEI Guidelines listing 200-odd tags\r
+contains tags that one is expected to enter every time the relevant\r
+textual feature occurs.  It contains all the tags that people need now,\r
+and it is not expected that everyone will tag things in the same way.\r
+\r
+The question of how people will tag the text is in large part a function\r
+of their reaction to what SPERBERG-McQUEEN termed the issue of\r
+reproducibility.  What one needs to be able to reproduce are the things\r
+one wants to work with.  Perhaps a more useful concept than that of\r
+reproducibility or recoverability is that of processability, that is,\r
+what can one get from an electronic text without reading it again\r
+in the original.  He illustrated this contention with a page from\r
+Jan Comenius's bilingual Introduction to Latin.\r
+\r
+SPERBERG-McQUEEN returned at length to the issue of images as simulacra\r
+for the text, in order to reiterate his belief that in the long run more\r
+than images of pages of particular editions of the text are needed,\r
+because just as second-generation photocopies and second-generation\r
+microfilm degenerate, so second-generation representations tend to\r
+degenerate, and one tends to overstress some relatively trivial aspects\r
+of the text such as its layout on the page, which is not always\r
+significant, despite what the text critics might say, and slight other\r
+pieces of information such as the very important lexical ties between the\r
+English and Latin versions of Comenius's bilingual text, for example. \r
+Moreover, in many crucial respects it is easy to fool oneself concerning\r
+what a scanned image of the text will accomplish.  For example, in order\r
+to study the transmission of texts, information concerning the text\r
+carrier is necessary, which scanned images simply do not always handle. \r
+Further, even the high-quality materials being produced at Cornell use\r
+much of the information that one would need if studying those books as\r
+physical objects.  It is a choice that has been made.  It is an arguably\r
+justifiable choice, but one does not know what color those pen strokes in\r
+the margin are or whether there was a stain on the page, because it has\r
+been filtered out.  One does not know whether there were rips in the page\r
+because they do not show up, and on a couple of the marginal marks one\r
+loses half of the mark because the pen is very light and the scanner\r
+failed to pick it up, and so what is clearly a checkmark in the margin of\r
+the original becomes a little scoop in the margin of the facsimile. \r
+Standard problems for facsimile editions, not new to electronics, but\r
+also true of light-lens photography, and are remarked here because it is\r
+important that we not fool ourselves that even if we produce a very nice\r
+image of this page with good contrast, we are not replacing the\r
+manuscript any more than microfilm has replaced the manuscript.\r
+\r
+The TEI comes from the research community, where its first allegiance\r
+lies, but it is not just an academic exercise.  It has relevance far\r
+beyond those who spend all of their time studying text, because one's\r
+model of text determines what one's software can do with a text.  Good\r
+models lead to good software.  Bad models lead to bad software.  That has\r
+economic consequences, and it is these economic consequences that have\r
+led the European Community to help support the TEI, and that will lead,\r
+SPERBERG-McQUEEN hoped, some software vendors to realize that if they\r
+provide software with a better model of the text they can make a killing.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Implications of different DTDs and tag sets * ODA versus SGML *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+During the discussion that followed, several additional points were made. \r
+Neither AAP (i.e., Association of American Publishers) nor CALS (i.e.,\r
+Computer-aided Acquisition and Logistics Support) has a document-type\r
+definition for ancient Greek drama, although the TEI will be able to\r
+handle that.  Given this state of affairs and assuming that the\r
+technical-journal producers and the commercial vendors decide to use the\r
+other two types, then an institution like the Library of Congress, which\r
+might receive all of their publications, would have to be able to handle\r
+three different types of document definitions and tag sets and be able to\r
+distinguish among them.\r
+\r
+Office Document Architecture (ODA) has some advantages that flow from its\r
+tight focus on office documents and clear directions for implementation. \r
+Much of the ODA standard is easier to read and clearer at first reading\r
+than the SGML standard, which is extremely general.  What that means is\r
+that if one wants to use graphics in TIFF and ODA, one is stuck, because\r
+ODA defines graphics formats while TIFF does not, whereas SGML says the\r
+world is not waiting for this work group to create another graphics format.\r
+What is needed is an ability to use whatever graphics format one wants.\r
+\r
+The TEI provides a socket that allows one to connect the SGML document to\r
+the graphics.  The notation that the graphics are in is clearly a choice\r
+that one needs to make based on her or his environment, and that is one\r
+advantage.  SGML is less megalomaniacal in attempting to define formats\r
+for all kinds of information, though more megalomaniacal in attempting to\r
+cover all sorts of documents.  The other advantage is that the model of\r
+text represented by SGML is simply an order of magnitude richer and more\r
+flexible than the model of text offered by ODA.  Both offer hierarchical\r
+structures, but SGML recognizes that the hierarchical model of the text\r
+that one is looking at may not have been in the minds of the designers,\r
+whereas ODA does not.\r
+\r
+ODA is not really aiming for the kind of document that the TEI wants to\r
+encompass.  The TEI can handle the kind of material ODA has, as well as a\r
+significantly broader range of material.  ODA seems to be very much\r
+focused on office documents, which is what it started out being called--\r
+office document architecture.\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+CALALUCA * Text-encoding from a publisher's perspective *\r
+Responsibilities of a publisher * Reproduction of Migne's Latin series\r
+whole and complete with SGML tags based on perceived need and expected\r
+use * Particular decisions arising from the general decision to produce\r
+and publish PLD *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+The final speaker in this session, Eric CALALUCA, vice president,\r
+Chadwyck-Healey, Inc., spoke from the perspective of a publisher re\r
+text-encoding, rather than as one qualified to discuss methods of\r
+encoding data, and observed that the presenters sitting in the room,\r
+whether they had chosen to or not, were acting as publishers:  making\r
+choices, gathering data, gathering information, and making assessments. \r
+CALALUCA offered the hard-won conviction that in publishing very large\r
+text files (such as PLD), one cannot avoid making personal judgments of\r
+appropriateness and structure.\r
+\r
+In CALALUCA's view, encoding decisions stem from prior judgments.  Two\r
+notions have become axioms for him in the consideration of future sources\r
+for electronic publication:  1) electronic text publishing is as personal\r
+as any other kind of publishing, and questions of if and how to encode\r
+the data are simply a consequence of that prior decision;  2) all\r
+personal decisions are open to criticism, which is unavoidable.\r
+\r
+CALALUCA rehearsed his role as a publisher or, better, as an intermediary\r
+between what is viewed as a sound idea and the people who would make use\r
+of it.  Finding the specialist to advise in this process is the core of\r
+that function.  The publisher must monitor and hug the fine line between\r
+giving users what they want and suggesting what they might need.  One\r
+responsibility of a publisher is to represent the desires of scholars and\r
+research librarians as opposed to bullheadedly forcing them into areas\r
+they would not choose to enter.\r
+\r
+CALALUCA likened the questions being raised today about data structure\r
+and standards to the decisions faced by the Abbe Migne himself during\r
+production of the Patrologia series in the mid-nineteenth century. \r
+Chadwyck-Healey's decision to reproduce Migne's Latin series whole and\r
+complete with SGML tags was also based upon a perceived need and an\r
+expected use.  In the same way that Migne's work came to be far more than\r
+a simple handbook for clerics, PLD is already far more than a database\r
+for theologians.  It is a bedrock source for the study of Western\r
+civilization, CALALUCA asserted.\r
+\r
+In regard to the decision to produce and publish PLD, the editorial board\r
+offered direct judgments on the question of appropriateness of these\r
+texts for conversion, their encoding and their distribution, and\r
+concluded that the best possible project was one that avoided overt\r
+intrusions or exclusions in so important a resource.  Thus, the general\r
+decision to transmit the original collection as clearly as possible with\r
+the widest possible avenues for use led to other decisions:  1) To encode\r
+the data or not, SGML or not, TEI or not.  Again, the expected user\r
+community asserted the need for normative tagging structures of important\r
+humanities texts, and the TEI seemed the most appropriate structure for\r
+that purpose.  Research librarians, who are trained to view the larger\r
+impact of electronic text sources on 80 or 90 or 100 doctoral\r
+disciplines, loudly approved the decision to include tagging.  They see\r
+what is coming better than the specialist who is completely focused on\r
+one edition of Ambrose's De Anima, and they also understand that the\r
+potential uses exceed present expectations.  2) What will be tagged and\r
+what will not.  Once again, the board realized that one must tag the\r
+obvious.  But in no way should one attempt to identify through encoding\r
+schemes every single discrete area of a text that might someday be\r
+searched.  That was another decision.  Searching by a column number, an\r
+author, a word, a volume, permitting combination searches, and tagging\r
+notations seemed logical choices as core elements.  3) How does one make\r
+the data available?  Tieing it to a CD-ROM edition creates limitations,\r
+but a magnetic tape file that is very large, is accompanied by the\r
+encoding specifications, and that allows one to make local modifications\r
+also allows one to incorporate any changes one may desire within the\r
+bounds of private research, though exporting tag files from a CD-ROM\r
+could serve just as well.  Since no one on the board could possibly\r
+anticipate each and every way in which a scholar might choose to mine\r
+this data bank, it was decided to satisfy the basics and make some\r
+provisions for what might come.  4) Not to encode the database would rob\r
+it of the interchangeability and portability these important texts should\r
+accommodate.  For CALALUCA, the extensive options presented by full-text\r
+searching require care in text selection and strongly support encoding of\r
+data to facilitate the widest possible search strategies.  Better\r
+software can always be created, but summoning the resources, the people,\r
+and the energy to reconvert the text is another matter.\r
+\r
+PLD is being encoded, captured, and distributed, because to\r
+Chadwyck-Healey and the board it offers the widest possible array of\r
+future research applications that can be seen today.  CALALUCA concluded\r
+by urging the encoding of all important text sources in whatever way\r
+seems most appropriate and durable at the time, without blanching at the\r
+thought that one's work may require emendation in the future.  (Thus,\r
+Chadwyck-Healey produced a very large humanities text database before the\r
+final release of the TEI Guidelines.)\r
+\r
+                                 ******\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+DISCUSSION * Creating texts with markup advocated * Trends in encoding *\r
+The TEI and the issue of interchangeability of standards * A\r
+misconception concerning the TEI * Implications for an institution like\r
+LC in the event that a multiplicity of DTDs develops * Producing images\r
+as a first step towards possible conversion to full text through\r
+character recognition * The AAP tag sets as a common starting point and\r
+the need for caution *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+HOCKEY prefaced the discussion that followed with several comments in\r
+favor of creating texts with markup and on trends in encoding.  In the\r
+future, when many more texts are available for on-line searching, real\r
+problems in finding what is wanted will develop, if one is faced with\r
+millions of words of data.  It therefore becomes important to consider\r
+putting markup in texts to help searchers home in on the actual things\r
+they wish to retrieve.  Various approaches to refining retrieval methods\r
+toward this end include building on a computer version of a dictionary\r
+and letting the computer look up words in it to obtain more information\r
+about the semantic structure or semantic field of a word, its grammatical\r
+structure, and syntactic structure.\r
+\r
+HOCKEY commented on the present keen interest in the encoding world\r
+in creating:  1) machine-readable versions of dictionaries that can be\r
+initially tagged in SGML, which gives a structure to the dictionary entry;\r
+these entries can then be converted into a more rigid or otherwise\r
+different database structure inside the computer, which can be treated as\r
+a dynamic tool for searching mechanisms; 2) large bodies of text to study\r
+the language.  In order to incorporate more sophisticated mechanisms,\r
+more about how words behave needs to be known, which can be learned in\r
+part from information in dictionaries.  However, the last ten years have\r
+seen much interest in studying the structure of printed dictionaries\r
+converted into computer-readable form.  The information one derives about\r
+many words from those is only partial, one or two definitions of the\r
+common or the usual meaning of a word, and then numerous definitions of\r
+unusual usages.  If the computer is using a dictionary to help retrieve\r
+words in a text, it needs much more information about the common usages,\r
+because those are the ones that occur over and over again.  Hence the\r
+current interest in developing large bodies of text in computer-readable\r
+form in order to study the language.  Several projects are engaged in\r
+compiling, for example, 100 million words. HOCKEY described one with\r
+which she was associated briefly at Oxford University involving\r
+compilation of 100 million words of British English:  about 10 percent of\r
+that will contain detailed linguistic tagging encoded in SGML; it will\r
+have word class taggings, with words identified as nouns, verbs,\r
+adjectives, or other parts of speech.  This tagging can then be used by\r
+programs which will begin to learn a bit more about the structure of the\r
+language, and then, can go to tag more text.\r
+\r
+HOCKEY said that the more that is tagged accurately, the more one can\r
+refine the tagging process and thus the bigger body of text one can build\r
+up with linguistic tagging incorporated into it.  Hence, the more tagging\r
+or annotation there is in the text, the more one may begin to learn about\r
+language and the more it will help accomplish more intelligent OCR.  She\r
+recommended the development of software tools that will help one begin to\r
+understand more about a text, which can then be applied to scanning\r
+images of that text in that format and to using more intelligence to help\r
+one interpret or understand the text.\r
+\r
+HOCKEY posited the need to think about common methods of text-encoding\r
+for a long time to come, because building these large bodies of text is\r
+extremely expensive and will only be done once.\r
+\r
+In the more general discussion on approaches to encoding that followed,\r
+these points were made:\r
+\r
+BESSER identified the underlying problem with standards that all have to\r
+struggle with in adopting a standard, namely, the tension between a very\r
+highly defined standard that is very interchangeable but does not work\r
+for everyone because something is lacking, and a standard that is less\r
+defined, more open, more adaptable, but less interchangeable.  Contending\r
+that the way in which people use SGML is not sufficiently defined, BESSER\r
+wondered 1) if people resist the TEI because they think it is too defined\r
+in certain things they do not fit into, and 2) how progress with\r
+interchangeability can be made without frightening people away.\r
+\r
+SPERBERG-McQUEEN replied that the published drafts of the TEI had met\r
+with surprisingly little objection on the grounds that they do not allow\r
+one to handle X or Y or Z.  Particular concerns of the affiliated\r
+projects have led, in practice, to discussions of how extensions are to\r
+be made; the primary concern of any project has to be how it can be\r
+represented locally, thus making interchange secondary.  The TEI has\r
+received much criticism based on the notion that everything in it is\r
+required or even recommended, which, as it happens, is a misconception\r
+from the beginning,   because none of it is required and very little is\r
+actually actively recommended for all cases, except that one document\r
+one's source.\r
+\r
+SPERBERG-McQUEEN agreed with BESSER about this trade-off:  all the\r
+projects in a set of twenty TEI-conformant projects will not necessarily\r
+tag the material in the same way.  One result of the TEI will be that the\r
+easiest problems will be solved--those dealing with the external form of\r
+the information; but the problem that is hardest in interchange is that\r
+one is not encoding what another wants, and vice versa.  Thus, after\r
+the adoption of a common notation, the differences in the underlying\r
+conceptions of what is interesting about texts become more visible.\r
+The success of a standard like the TEI will lie in the ability of\r
+the recipient of interchanged texts to use some of what it contains\r
+and to add the information that was not encoded that one wants, in a\r
+layered way, so that texts can be gradually enriched and one does not\r
+have to put in everything all at once.  Hence, having a well-behaved\r
+markup scheme is important.\r
+\r
+STEVENS followed up on the paradoxical analogy that BESSER alluded to in\r
+the example of the MARC records, namely, the formats that are the same\r
+except that they are different.  STEVENS drew a parallel between\r
+document-type definitions and MARC records for books and serials and maps,\r
+where one has a tagging structure and there is a text-interchange. \r
+STEVENS opined that the producers of the information will set the terms\r
+for the standard (i.e., develop document-type definitions for the users\r
+of their products), creating a situation that will be problematical for\r
+an institution like the Library of Congress, which will have to deal with\r
+the DTDs in the event that a multiplicity of them develops.  Thus,\r
+numerous people are seeking a standard but cannot find the tag set that\r
+will be acceptable to them and their clients.  SPERBERG-McQUEEN agreed\r
+with this view, and said that the situation was in a way worse:  attempting\r
+to unify arbitrary DTDs resembled attempting to unify a MARC record with a\r
+bibliographic record done according to the Prussian instructions. \r
+According to STEVENS, this situation occurred very early in the process.\r
+\r
+WATERS recalled from early discussions on Project Open Book the concern\r
+of many people that merely by producing images, POB was not really\r
+enhancing intellectual access to the material.  Nevertheless, not wishing\r
+to overemphasize the opposition between imaging and full text, WATERS\r
+stated that POB views getting the images as a first step toward possibly\r
+converting to full text through character recognition, if the technology\r
+is appropriate.  WATERS also emphasized that encoding is involved even\r
+with a set of images.\r
+\r
+SPERBERG-McQUEEN agreed with WATERS that one can create an SGML document\r
+consisting wholly of images.  At first sight, organizing graphic images\r
+with an SGML document may not seem to offer great advantages, but the\r
+advantages of the scheme WATERS described would be precisely that\r
+ability to move into something that is more of a multimedia document:\r
+a combination of transcribed text and page images.  WEIBEL concurred in\r
+this judgment, offering evidence from Project ADAPT, where a page is\r
+divided into text elements and graphic elements, and in fact the text\r
+elements are organized by columns and lines.  These lines may be used as\r
+the basis for distributing documents in a network environment.  As one\r
+develops software intelligent enough to recognize what those elements\r
+are, it makes sense to apply SGML to an image initially, that may, in\r
+fact, ultimately become more and more text, either through OCR or edited\r
+OCR or even just through keying.  For WATERS, the labor of composing the\r
+document and saying this set of documents or this set of images belongs\r
+to this document constitutes a significant investment.\r
+\r
+WEIBEL also made the point that the AAP tag sets, while not excessively\r
+prescriptive, offer a common starting point; they do not define the\r
+structure of the documents, though.  They have some recommendations about\r
+DTDs one could use as examples, but they do just suggest tag sets.   For\r
+example, the CORE project attempts to use the AAP markup as much as\r
+possible, but there are clearly areas where structure must be added. \r
+That in no way contradicts the use of AAP tag sets.\r
+\r
+SPERBERG-McQUEEN noted that the TEI prepared a long working paper early\r
+on about the AAP tag set and what it lacked that the TEI thought it\r
+needed, and a fairly long critique of the naming conventions, which has\r
+led to a very different style of naming in the TEI.  He stressed the\r
+importance of the opposition between prescriptive markup, the kind that a\r
+publisher or anybody can do when producing documents de novo, and\r
+descriptive markup, in which one has to take what the text carrier\r
+provides.  In these particular tag sets it is easy to overemphasize this\r
+opposition, because the AAP tag set is extremely flexible.  Even if one\r
+just used the DTDs, they allow almost anything to appear almost anywhere.\r
+\r
+                                 ******\r
+\r
+SESSION VI.  COPYRIGHT ISSUES\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+PETERS * Several cautions concerning copyright in an electronic\r
+environment * Review of copyright law in the United States * The notion\r
+of the public good and the desirability of incentives to promote it *\r
+What copyright protects * Works not protected by copyright * The rights\r
+of copyright holders * Publishers' concerns in today's electronic\r
+environment * Compulsory licenses * The price of copyright in a digital\r
+medium and the need for cooperation * Additional clarifications *  Rough\r
+justice oftentimes the outcome in numerous copyright matters * Copyright\r
+in an electronic society * Copyright law always only sets up the\r
+boundaries; anything can be changed by contract *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+Marybeth PETERS, policy planning adviser to the Register of Copyrights,\r
+Library of Congress,   made several general comments and then opened the\r
+floor to discussion of subjects of interest to the audience.\r
+\r
+Having attended several sessions in an effort to gain a sense of what\r
+people did and where copyright would affect their lives, PETERS expressed\r
+the following cautions:\r
+\r
+     * If one takes and converts materials and puts them in new forms,\r
+     then, from a copyright point of view, one is creating something and\r
+     will receive some rights.\r
+\r
+     * However, if what one is converting already exists, a question\r
+     immediately arises about the status of the materials in question.\r
+\r
+     * Putting something in the public domain in the United States offers\r
+     some freedom from anxiety, but distributing it throughout the world\r
+     on a network is another matter, even if one has put it in the public\r
+     domain in the United States.  Re foreign laws, very frequently a\r
+     work can be in the public domain in the United States but protected\r
+     in other countries.  Thus, one must consider all of the places a\r
+     work may reach, lest one unwittingly become liable to being faced\r
+     with a suit for copyright infringement, or at least a letter\r
+     demanding discussion of what one is doing.\r
+\r
+PETERS reviewed copyright law in the United States.  The U.S.\r
+Constitution effectively states that Congress has the power to enact\r
+copyright laws for two purposes:  1) to encourage the creation and\r
+dissemination of intellectual works for the good of society as a whole;\r
+and, significantly, 2) to give creators and those who package and\r
+disseminate materials the economic rewards that are due them.\r
+\r
+Congress strives to strike a balance, which at times can become an\r
+emotional issue.  The United States has never accepted the notion of the\r
+natural right of an author so much as it has accepted the notion of the\r
+public good and the desirability of incentives to promote it.  This state\r
+of affairs, however, has created strains on the international level and\r
+is the reason for several of the differences in the laws that we have. \r
+Today the United States protects almost every kind of work that can be\r
+called an expression of an author.  The standard for gaining copyright\r
+protection is simply originality.  This is a low standard and means that\r
+a work is not copied from something else, as well as shows a certain\r
+minimal amount of authorship.  One can also acquire copyright protection\r
+for making a new version of preexisting material, provided it manifests\r
+some spark of creativity.\r
+\r
+However, copyright does not protect ideas, methods, systems--only the way\r
+that one expresses those things.  Nor does copyright protect anything\r
+that is mechanical, anything that does not involve choice, or criteria\r
+concerning whether or not one should do a thing.  For example, the\r
+results of a process called declicking, in which one mechanically removes\r
+impure sounds from old recordings, are not copyrightable.  On the other\r
+hand, the choice to record a song digitally and to increase the sound of\r
+violins or to bring up the tympani constitutes the results of conversion\r
+that are copyrightable.  Moreover, if a work is protected by copyright in\r
+the United States, one generally needs the permission of the copyright\r
+owner to convert it.  Normally, who will own the new--that is, converted-\r
+-material is a matter of contract.  In the absence of a contract, the\r
+person who creates the new material is the author and owner.  But people\r
+do not generally think about the copyright implications until after the\r
+fact.  PETERS stressed the need when dealing with copyrighted works to\r
+think about copyright in advance.  One's bargaining power is much greater\r
+up front than it is down the road.\r
+\r
+PETERS next discussed works not protected by copyright, for example, any\r
+work done by a federal employee as part of his or her official duties is\r
+in the public domain in the United States.  The issue is not wholly free\r
+of doubt concerning whether or not the work is in the public domain\r
+outside the United States.  Other materials in the public domain include: \r
+any works published more than seventy-five years ago, and any work\r
+published in the United States more than twenty-eight years ago, whose\r
+copyright was not renewed.  In talking about the new technology and\r
+putting material in a digital form to send all over the world, PETERS\r
+cautioned, one must keep in mind that while the rights may not be an\r
+issue in the United States, they may be in different parts of the world,\r
+where most countries previously employed a copyright term of the life of\r
+the author plus fifty years.\r
+\r
+PETERS next reviewed the economics of copyright holding.  Simply,\r
+economic rights are the rights to control the reproduction of a work in\r
+any form.  They belong to the author, or in the case of a work made for\r
+hire, the employer.  The second right, which is critical to conversion,\r
+is the right to change a work.  The right to make new versions is perhaps\r
+one of the most significant rights of authors, particularly in an\r
+electronic world.  The third right is the right to publish the work and\r
+the right to disseminate it, something that everyone who deals in an\r
+electronic medium needs to know.  The basic rule is if a copy is sold,\r
+all rights of distribution are extinguished with the sale of that copy. \r
+The key is that it must be sold.  A number of companies overcome this\r
+obstacle by leasing or renting their product.  These companies argue that\r
+if the material is rented or leased and not sold, they control the uses\r
+of a work.  The fourth right, and one very important in a digital world,\r
+is a right of public performance, which means the right to show the work\r
+sequentially.  For example, copyright owners control the showing of a\r
+CD-ROM product in a public place such as a public library.  The reverse\r
+side of public performance is something called the right of public\r
+display.  Moral rights also exist, which at the federal level apply only\r
+to very limited visual works of art, but in theory may apply under\r
+contract and other principles.  Moral rights may include the right of an\r
+author to have his or her name on a work, the right of attribution, and\r
+the right to object to distortion or mutilation--the right of integrity.\r
+\r
+The way copyright law is worded gives much latitude to activities such as\r
+preservation; to use of material for scholarly and research purposes when\r
+the user does not make multiple copies; and to the generation of\r
+facsimile copies of unpublished works by libraries for themselves and\r
+other libraries.  But the law does not allow anyone to become the\r
+distributor of the product for the entire world.  In today's electronic\r
+environment, publishers are extremely concerned that the entire world is\r
+networked and can obtain the information desired from a single copy in a\r
+single library.  Hence, if there is to be only one sale, which publishers\r
+may choose to live with, they will obtain their money in other ways, for\r
+example, from access and use.  Hence, the development of site licenses\r
+and other kinds of agreements to cover what publishers believe they\r
+should be compensated for.  Any solution that the United States takes\r
+today has to consider the international arena.\r
+\r
+Noting that the United States is a member of the Berne Convention and\r
+subscribes to its provisions, PETERS described the permissions process. \r
+She also defined compulsory licenses.  A compulsory license, of which the\r
+United States has had a few, builds into the law the right to use a work\r
+subject to certain terms and conditions.  In the international arena,\r
+however, the ability to use compulsory licenses is extremely limited. \r
+Thus, clearinghouses and other collectives comprise one option that has\r
+succeeded in providing for use of a work.  Often overlooked when one\r
+begins to use copyrighted material and put products together is how\r
+expensive the permissions process and managing it is.  According to\r
+PETERS, the price of copyright in a digital medium, whatever solution is\r
+worked out, will include managing and assembling the database.  She\r
+strongly recommended that publishers and librarians or people with\r
+various backgrounds cooperate to work out administratively feasible\r
+systems, in order to produce better results.\r
+\r
+In the lengthy question-and-answer period that followed PETERS's\r
+presentation, the following points emerged:\r
+\r
+     * The Copyright Office maintains that anything mechanical and\r
+     totally exhaustive probably is not protected.  In the event that\r
+     what an individual did in developing potentially copyrightable\r
+     material is not understood, the Copyright Office will ask about the\r
+     creative choices the applicant chose to make or not to make.  As a\r
+     practical matter, if one believes she or he has made enough of those\r
+     choices, that person has a right to assert a copyright and someone\r
+     else must assert that the work is not copyrightable.  The more\r
+     mechanical, the more automatic, a thing is, the less likely it is to\r
+     be copyrightable.\r
+\r
+     * Nearly all photographs are deemed to be copyrightable, but no one\r
+     worries about them much, because everyone is free to take the same\r
+     image.  Thus, a photographic copyright represents what is called a\r
+     "thin" copyright.  The photograph itself must be duplicated, in\r
+     order for copyright to be violated.\r
+\r
+     * The Copyright Office takes the position that X-rays are not\r
+     copyrightable because they are mechanical.  It  can be argued\r
+     whether or not image enhancement in scanning can be protected.  One\r
+     must exercise care with material created with public funds and\r
+     generally in the public domain.  An article written by a federal\r
+     employee, if written as part of official duties, is not\r
+     copyrightable.  However, control over a scientific article written\r
+     by a National Institutes of Health grantee (i.e., someone who\r
+     receives money from the U.S. government), depends on NIH policy.  If\r
+     the government agency has no policy (and that policy can be\r
+     contained in its regulations, the contract, or the grant), the\r
+     author retains copyright.  If a provision of the contract, grant, or\r
+     regulation states that there will be no copyright, then it does not\r
+     exist.  When a work is created, copyright automatically comes into\r
+     existence unless something exists that says it does not.\r
+\r
+     * An enhanced electronic copy of a print copy of an older reference\r
+     work in the public domain that does not contain copyrightable new\r
+     material is a purely mechanical rendition of the original work, and\r
+     is not copyrightable.\r
+\r
+     * Usually, when a work enters the public domain, nothing can remove\r
+     it.  For example, Congress recently passed into law the concept of\r
+     automatic renewal, which means that copyright on any work published\r
+     between l964 and l978 does not have to be renewed in order to\r
+     receive a seventy-five-year term.  But any work not renewed before\r
+     1964 is in the public domain.\r
+\r
+     * Concerning whether or not the United States keeps track of when\r
+     authors die, nothing was ever done, nor is anything being done at\r
+     the moment by the Copyright Office.\r
+\r
+     * Software that drives a mechanical process is itself copyrightable. \r
+     If one changes platforms, the software itself has a copyright.  The\r
+     World Intellectual Property Organization will hold a symposium 28\r
+     March through 2 April l993, at Harvard University, on digital\r
+     technology, and will study this entire issue.  If one purchases a\r
+     computer software package, such as MacPaint, and creates something\r
+     new, one receives protection only for that which has been added.\r
+\r
+PETERS added that often in copyright matters, rough justice is the\r
+outcome, for example, in collective licensing, ASCAP (i.e., American\r
+Society of Composers, Authors, and Publishers), and BMI (i.e., Broadcast\r
+Music, Inc.), where it may seem that the big guys receive more than their\r
+due.  Of course, people ought not to copy a creative product without\r
+paying for it; there should be some compensation.  But the truth of the\r
+world, and it is not a great truth, is that the big guy gets played on\r
+the radio more frequently than the little guy, who has to do much more\r
+until he becomes a big guy.  That is true of every author, every\r
+composer, everyone, and, unfortunately, is part of life.\r
+\r
+Copyright always originates with the author, except in cases of works\r
+made for hire.  (Most software falls into this category.)  When an author\r
+sends his article to a journal, he has not relinquished copyright, though\r
+he retains the right to relinquish it.  The author receives absolutely\r
+everything.  The less prominent the author, the more leverage the\r
+publisher will have in contract negotiations.  In order to transfer the\r
+rights, the author must sign an agreement giving them away.\r
+\r
+In an electronic society, it is important to be able to license a writer\r
+and work out deals.  With regard to use of a work, it usually is much\r
+easier when a publisher holds the rights.  In an electronic era, a real\r
+problem arises when one is digitizing and making information available. \r
+PETERS referred again to electronic licensing clearinghouses.  Copyright\r
+ought to remain with the author, but as one moves forward globally in the\r
+electronic arena, a middleman who can handle the various rights becomes\r
+increasingly necessary.\r
+\r
+The notion of copyright law is that it resides with the individual, but\r
+in an on-line environment, where a work can be adapted and tinkered with\r
+by many individuals, there is concern.  If changes are authorized and\r
+there is no agreement to the contrary, the person who changes a work owns\r
+the changes.  To put it another way, the person who acquires permission\r
+to change a work technically will become the author and the owner, unless\r
+some agreement to the contrary has been made.  It is typical for the\r
+original publisher to try to control all of the versions and all of the\r
+uses.  Copyright law always only sets up the boundaries.  Anything can be\r
+changed by contract.\r
+\r
+                                 ******\r
+\r
+SESSION VII.  CONCLUSION\r
+\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+GENERAL DISCUSSION * Two questions for discussion * Different emphases in\r
+the Workshop * Bringing the text and image partisans together *\r
+Desiderata in planning the long-term development of something * Questions\r
+surrounding the issue of electronic deposit * Discussion of electronic\r
+deposit as an allusion to the issue of standards * Need for a directory\r
+of preservation projects in digital form and for access to their\r
+digitized files * CETH's catalogue of machine-readable texts in the\r
+humanities * What constitutes a publication in the electronic world? *\r
+Need for LC to deal with the concept of on-line publishing * LC's Network\r
+Development Office  exploring the limits of MARC as a standard in terms\r
+of handling electronic information * Magnitude of the problem and the\r
+need for distributed responsibility in order to maintain and store\r
+electronic information * Workshop participants to be viewed as a starting\r
+point * Development of a network version of AM urged * A step toward AM's\r
+construction of some sort of apparatus for network access * A delicate\r
+and agonizing policy question for LC * Re the issue of electronic\r
+deposit, LC urged to initiate a catalytic process in terms of distributed\r
+responsibility * Suggestions for cooperative ventures * Commercial\r
+publishers' fears * Strategic questions for getting the image and text\r
+people to think through long-term cooperation * Clarification of the\r
+driving force behind both the Perseus and the Cornell Xerox projects *\r
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+\r
+In his role as moderator of the concluding session, GIFFORD raised two\r
+questions he believed would benefit from discussion:  1) Are there enough\r
+commonalities among those of us that have been here for two days so that\r
+we can see courses of action that should be taken in the future?  And, if\r
+so, what are they and who might take them?  2) Partly derivative from\r
+that, but obviously very dangerous to LC as host, do you see a role for\r
+the Library of Congress in all this?  Of course, the Library of Congress\r
+holds a rather special status in a number of these matters, because it is\r
+not perceived as a player with an economic stake in them, but are there\r
+roles that LC can play that can help advance us toward where we are heading?\r
+\r
+Describing himself as an uninformed observer of the technicalities of the\r
+last two days, GIFFORD detected three different emphases in the Workshop: \r
+1) people who are very deeply committed to text; 2) people who are almost\r
+passionate about images; and 3) a few people who are very committed to\r
+what happens to the networks.  In other words, the new networking\r
+dimension, the accessibility of the processability, the portability of\r
+all this across the networks.  How do we pull those three together?\r
+\r
+Adding a question that reflected HOCKEY's comment that this was the\r
+fourth workshop she had attended in the previous thirty days, FLEISCHHAUER\r
+wondered to what extent this meeting had reinvented the wheel, or if it\r
+had contributed anything in the way of bringing together a different group\r
+of people from those who normally appear on the workshop circuit.\r
+\r
+HOCKEY confessed to being struck at this meeting and the one the\r
+Electronic Pierce Consortium organized the previous week that this was a\r
+coming together of people working on texts and not images.  Attempting to\r
+bring the two together is something we ought to be thinking about for the\r
+future:  How one can think about working with image material to begin\r
+with, but structuring it and digitizing it in such a way that at a later\r
+stage it can be interpreted into text, and find a common way of building\r
+text and images together so that they can be used jointly in the future,\r
+with the network support to begin there because that is how people will\r
+want to access it.\r
+\r
+In planning the long-term development of something, which is what is\r
+being done in electronic text, HOCKEY stressed the importance not only\r
+of discussing the technical aspects of how one does it but particularly\r
+of thinking about what the people who use the stuff will want to do.\r
+But conversely, there are numerous things that people start to do with\r
+electronic text or material that nobody ever thought of in the beginning.\r
+\r
+LESK, in response to the question concerning the role of the Library of\r
+Congress, remarked the often suggested desideratum of having electronic\r
+deposit:  Since everything is now computer-typeset, an entire decade of\r
+material that was machine-readable exists, but the publishers frequently\r
+did not save it; has LC taken any action to have its copyright deposit\r
+operation start collecting these machine-readable versions?  In the\r
+absence of PETERS, GIFFORD replied that the question was being\r
+actively considered but that that was only one dimension of the problem.\r
+Another dimension is the whole question of the integrity of the original\r
+electronic document.  It becomes highly important in science to prove\r
+authorship.  How will that be done?\r
+\r
+ERWAY explained that, under the old policy, to make a claim for a\r
+copyright for works that were published in electronic form, including\r
+software, one had to submit a paper copy of the first and last twenty\r
+pages of code--something that represented the work but did not include\r
+the entire work itself and had little value to anyone.  As a temporary\r
+measure, LC has claimed the right to demand electronic versions of\r
+electronic publications.  This measure entails a proactive role for the\r
+Library to say that it wants a particular electronic version.  Publishers\r
+then have perhaps a year to submit it.  But the real problem for LC is\r
+what to do with all this material in all these different formats.  Will\r
+the Library mount it?  How will it give people access to it?  How does LC\r
+keep track of the appropriate computers, software, and media?  The situation\r
+is so hard to control, ERWAY said, that it makes sense for each publishing\r
+house to maintain its own archive.  But LC cannot enforce that either.\r
+\r
+GIFFORD acknowledged LESK's suggestion that establishing a priority\r
+offered the solution, albeit a fairly complicated one.  But who maintains\r
+that register?, he asked.  GRABER noted that LC does attempt to collect a\r
+Macintosh version and the IBM-compatible version of software.  It does\r
+not collect other versions.  But while true for software, BYRUM observed,\r
+this reply does not speak to materials, that is, all the materials that\r
+were published that were on somebody's microcomputer or driver tapes\r
+at a publishing office across the country.  LC does well to acquire\r
+specific machine-readable products selectively that were intended to be\r
+machine-readable.  Materials that were in machine-readable form at one time,\r
+BYRUM said, would be beyond LC's capability at the moment, insofar as\r
+attempting to acquire, organize, and preserve them are concerned--and\r
+preservation would be the most important consideration.  In this\r
+connection, GIFFORD reiterated the need to work out some sense of\r
+distributive responsibility for a number of these issues, which\r
+inevitably will require significant cooperation and discussion.\r
+Nobody can do it all.\r
+\r
+LESK suggested that some publishers may look with favor on LC beginning\r
+to serve as a depository of tapes in an electronic manuscript standard. \r
+Publishers may view this as a service that they did not have to perform\r
+and they might send in tapes.  However, SPERBERG-McQUEEN countered,\r
+although publishers have had equivalent services available to them for a\r
+long time, the electronic text archive has never turned away or been\r
+flooded with tapes and is forever sending feedback to the depositor. \r
+Some publishers do send in tapes.\r
+\r
+ANDRE viewed this discussion as an allusion to the issue of standards. \r
+She recommended that the AAP standard and the TEI, which has already been\r
+somewhat harmonized internationally and which also shares several\r
+compatibilities with the AAP, be harmonized to ensure sufficient\r
+compatibility in the software.  She drew the line at saying LC ought to\r
+be the locus or forum for such harmonization.\r
+\r
+Taking the group in a slightly different direction, but one where at\r
+least in the near term LC might play a helpful role, LYNCH remarked the\r
+plans of a number of projects to carry out preservation by creating\r
+digital images that will end up in on-line or near-line storage at some\r
+institution.   Presumably, LC will link this material somehow to its\r
+on-line catalog in most cases.  Thus, it is in a digital form.  LYNCH had\r
+the impression that many of these institutions would be willing to make\r
+those files accessible to other people outside the institution, provided\r
+that there is no copyright problem.  This desideratum will require\r
+propagating the knowledge that those digitized files exist, so that they\r
+can end up in other on-line catalogs.  Although uncertain about the\r
+mechanism for achieving this result, LYNCH said that it warranted\r
+scrutiny because it seemed to be connected to some of the basic issues of\r
+cataloging and distribution of records.  It would be  foolish, given the\r
+amount of work that all of us have to do and our meager resources, to\r
+discover multiple institutions digitizing the same work.  Re microforms,\r
+LYNCH said, we are in pretty good shape.\r
+\r
+BATTIN called this a big problem and noted that the Cornell people (who\r
+had already departed) were working on it.  At issue from the beginning\r
+was to learn how to catalog that information into RLIN and then into\r
+OCLC, so that it would be accessible.  That issue remains to be resolved. \r
+LYNCH rejoined that putting it into OCLC or RLIN was helpful insofar as\r
+somebody who is thinking of performing preservation activity on that work\r
+could learn about it.  It is not necessarily helpful for institutions to\r
+make that available.  BATTIN opined that the idea was that it not only be\r
+for preservation purposes but for the convenience of people looking for\r
+this material.  She endorsed LYNCH's dictum that duplication of this\r
+effort was to be avoided by every means.\r
+\r
+HOCKEY informed the Workshop about one major current activity of CETH,\r
+namely a catalogue of machine-readable texts in the humanities.  Held on\r
+RLIN at present, the catalogue has been concentrated on ASCII as opposed\r
+to digitized images of text.  She is exploring ways to improve the\r
+catalogue and make it more widely available, and welcomed suggestions\r
+about these concerns.  CETH owns the records, which are not just\r
+restricted to RLIN, and can distribute them however it wishes.\r
+\r
+Taking up LESK's earlier question, BATTIN inquired whether LC, since it\r
+is accepting electronic files and designing a mechanism for dealing with\r
+that rather than putting books on shelves, would become responsible for\r
+the National Copyright Depository of Electronic Materials.  Of course\r
+that could not be accomplished overnight, but it would be something LC\r
+could plan for.  GIFFORD acknowledged that much thought was being devoted\r
+to that set of problems and returned the discussion to the issue raised\r
+by LYNCH--whether or not putting the kind of records that both BATTIN and\r
+HOCKEY have been talking about in RLIN is not a satisfactory solution. \r
+It seemed to him that RLIN answered LYNCH's original point concerning\r
+some kind of directory for these kinds of materials.  In a situation\r
+where somebody is attempting to decide whether or not to scan this or\r
+film that or to learn whether or not someone has already done so, LYNCH\r
+suggested, RLIN is helpful, but it is not helpful in the case of a local,\r
+on-line catalogue.  Further, one would like to have her or his system be\r
+aware that that exists in digital form, so that one can present it to a\r
+patron, even though one did not digitize it, if it is out of copyright. \r
+The only way to make those linkages would be to perform a tremendous\r
+amount of real-time look-up, which would be awkward at best, or\r
+periodically to yank the whole file from RLIN and match it against one's\r
+own stuff, which is a nuisance.\r
+\r
+But where, ERWAY inquired, does one stop including things that are\r
+available with Internet, for instance, in one's local catalogue?\r
+It almost seems that that is LC's means to acquire access to them.\r
+That represents LC's new form of library loan.  Perhaps LC's new on-line\r
+catalogue is an amalgamation of all these catalogues on line.  LYNCH\r
+conceded that perhaps that was true in the very long term, but was not\r
+applicable to scanning in the short term.  In his view, the totals cited\r
+by Yale, 10,000 books over perhaps a four-year period, and 1,000-1,500\r
+books from Cornell, were not big numbers, while searching all over\r
+creation for relatively rare occurrences will prove to be less efficient. \r
+As GIFFORD wondered if this would not be a separable file on RLIN and\r
+could be requested from them, BATTIN interjected that it was easily\r
+accessible to an institution.  SEVERTSON pointed out that that file, cum\r
+enhancements, was available with reference information on CD-ROM, which\r
+makes it a little more available.\r
+\r
+In HOCKEY's view, the real question facing the Workshop is what to put in\r
+this catalogue, because that raises the question of what constitutes a\r
+publication in the electronic world.  (WEIBEL interjected that Eric Joule\r
+in OCLC's Office of Research is also wrestling with this particular\r
+problem, while GIFFORD thought it sounded fairly generic.)  HOCKEY\r
+contended that a majority of texts in the humanities are in the hands\r
+of either a small number of large research institutions or individuals\r
+and are not generally available for anyone else to access at all.\r
+She wondered if these texts ought to be catalogued.\r
+\r
+After argument proceeded back and forth for several minutes over why\r
+cataloguing might be a necessary service, LEBRON suggested that this\r
+issue involved the responsibility of a publisher.  The fact that someone\r
+has created something electronically and keeps it under his or her\r
+control does not constitute publication.  Publication implies\r
+dissemination.  While it would be important for a scholar to let other\r
+people know that this creation exists, in many respects this is no\r
+different from an unpublished manuscript.  That is what is being accessed\r
+in there, except that now one is not looking at it in the hard-copy but\r
+in the electronic environment.\r
+\r
+LEBRON expressed puzzlement at the variety of ways electronic publishing\r
+has been viewed.  Much of what has been discussed throughout these two\r
+days has concerned CD-ROM publishing, whereas in the on-line environment\r
+that she confronts, the constraints and challenges are very different. \r
+Sooner or later LC will have to deal with the concept of on-line\r
+publishing.  Taking up the comment ERWAY made earlier about storing\r
+copies, LEBRON gave her own journal as an example.  How would she deposit\r
+OJCCT for copyright?, she asked, because the journal will exist in the\r
+mainframe at OCLC and people will be able to access it.  Here the\r
+situation is different, ownership versus access, and is something that\r
+arises with publication in the on-line environment, faster than is\r
+sometimes realized.  Lacking clear answers to all of these questions\r
+herself, LEBRON did not anticipate that LC would be able to take a role\r
+in helping to define some of them for quite a while.\r
+\r
+GREENFIELD observed that LC's Network Development Office is attempting,\r
+among other things, to explore the limits of MARC as a standard in terms\r
+of handling electronic information.  GREENFIELD also noted that Rebecca\r
+GUENTHER from that office gave a paper to the American Society for\r
+Information Science (ASIS) summarizing several of the discussion papers\r
+that were coming out of the Network Development Office.  GREENFIELD said\r
+he understood that that office had a list-server soliciting just the kind\r
+of feedback received today concerning the difficulties of identifying and\r
+cataloguing electronic information.  GREENFIELD hoped that everybody\r
+would be aware of that and somehow contribute to that conversation.\r
+\r
+Noting two of LC's roles, first, to act as a repository of record for\r
+material that is copyrighted in this country, and second, to make\r
+materials it holds available in some limited form to a clientele that\r
+goes beyond Congress, BESSER suggested that it was incumbent on LC to\r
+extend those responsibilities to all the things being published in\r
+electronic form.  This would mean eventually accepting electronic\r
+formats.  LC could require that at some point they be in a certain\r
+limited set of formats, and then develop mechanisms for allowing people\r
+to access those in the same way that other things are accessed.  This\r
+does not imply that they are on the network and available to everyone. \r
+LC does that with most of its bibliographic records, BESSER said, which\r
+end up migrating to the utility (e.g., OCLC) or somewhere else.  But just\r
+as most of LC's books are available in some form through interlibrary\r
+loan or some other mechanism, so in the same way electronic formats ought\r
+to be available to others in some format, though with some copyright\r
+considerations.  BESSER was not suggesting that these mechanisms be\r
+established tomorrow, only that they seemed to fall within LC's purview,\r
+and that there should be long-range plans to establish them.\r
+\r
+Acknowledging that those from LC in the room agreed with BESSER\r
+concerning the need to confront difficult questions, GIFFORD underscored\r
+the magnitude of the problem of what to keep and what to select.  GIFFORD\r
+noted that LC currently receives some 31,000 items per day, not counting\r
+electronic materials, and argued for much more distributed responsibility\r
+in order to maintain and store electronic information.\r
+\r
+BESSER responded that the assembled group could be viewed as a starting\r
+point, whose initial operating premise could be helping to move in this\r
+direction and defining how LC could do so, for example, in areas of\r
+standardization or distribution of responsibility.\r
+\r
+FLEISCHHAUER added that AM was fully engaged, wrestling with some of the\r
+questions that pertain to the conversion of older historical materials,\r
+which would be one thing that the Library of Congress might do.  Several\r
+points mentioned by BESSER and several others on this question have a\r
+much greater impact on those who are concerned with cataloguing and the\r
+networking of bibliographic information, as well as preservation itself.\r
+\r
+Speaking directly to AM, which he considered was a largely uncopyrighted\r
+database, LYNCH urged development of a network version of AM, or\r
+consideration of making the data in it available to people interested in\r
+doing network multimedia.  On account of the current great shortage of\r
+digital data that is both appealing and unencumbered by complex rights\r
+problems, this course of action could have a significant effect on making\r
+network multimedia a reality.\r
+\r
+In this connection, FLEISCHHAUER reported on a fragmentary prototype in\r
+LC's Office of Information Technology Services that attempts to associate\r
+digital images of photographs with cataloguing information in ways that\r
+work within a local area network--a step, so to say, toward AM's\r
+construction of some sort of apparatus for access.  Further, AM has\r
+attempted to use standard data forms in order to help make that\r
+distinction between the access tools and the underlying data, and thus\r
+believes that the database is networkable.\r
+\r
+A delicate and agonizing policy question for LC, however, which comes\r
+back to resources and unfortunately has an impact on this, is to find\r
+some appropriate, honorable, and legal cost-recovery possibilities.  A\r
+certain skittishness concerning cost-recovery has made people unsure\r
+exactly what to do.  AM would be highly receptive to discussing further\r
+LYNCH's offer to test or demonstrate its database in a network\r
+environment, FLEISCHHAUER said.\r
+\r
+Returning the discussion to what she viewed as the vital issue of\r
+electronic deposit, BATTIN recommended that LC initiate a catalytic\r
+process in terms of distributed responsibility, that is, bring together\r
+the distributed organizations and set up a study group to look at all\r
+these issues and see where we as a nation should move.  The broader\r
+issues of how we deal with the management of electronic information will\r
+not disappear, but only grow worse.\r
+\r
+LESK took up this theme and suggested that LC attempt to persuade one\r
+major library in each state to deal with its state equivalent publisher,\r
+which might produce a cooperative project that would be equitably\r
+distributed around the country, and one in which LC would be dealing with\r
+a minimal number of publishers and minimal copyright problems.\r
+\r
+GRABER remarked the recent development in the scientific community of a\r
+willingness to use SGML and either deposit or interchange on a fairly\r
+standardized format.  He wondered if a similar movement was taking place\r
+in the humanities.  Although the National Library of Medicine found only\r
+a few publishers to cooperate in a like venture two or three years ago, a\r
+new effort might generate a much larger number willing to cooperate.\r
+\r
+KIMBALL recounted his unit's (Machine-Readable Collections Reading Room)\r
+troubles with the commercial publishers of electronic media in acquiring\r
+materials for LC's collections, in particular the publishers' fear that\r
+they would not be able to cover their costs and would lose control of\r
+their products, that LC would give them away or sell them and make\r
+profits from them.  He doubted that the publishing industry was prepared\r
+to move into this area at the moment, given its resistance to allowing LC\r
+to use its machine-readable materials as the Library would like.\r
+\r
+The copyright law now addresses compact disk as a medium, and LC can\r
+request one copy of that, or two copies if it is the only version, and\r
+can request copies of software, but that fails to address magazines or\r
+books or anything like that which is in machine-readable form.\r
+\r
+GIFFORD acknowledged the thorny nature of this issue, which he illustrated\r
+with the example of the cumbersome process involved in putting a copy of a\r
+scientific database on a LAN in LC's science reading room.  He also\r
+acknowledged that LC needs help and could enlist the energies and talents\r
+of Workshop participants in thinking through a number of these problems.\r
+\r
+GIFFORD returned the discussion to getting the image and text people to\r
+think through together where they want to go in the long term.  MYLONAS\r
+conceded that her experience at the Pierce Symposium the previous week at\r
+Georgetown University and this week at LC had forced her to reevaluate\r
+her perspective on the usefulness of text as images.  MYLONAS framed the\r
+issues in a series of questions:  How do we acquire machine-readable\r
+text?  Do we take pictures of it and perform OCR on it later?  Is it\r
+important to obtain very high-quality images and text, etc.? \r
+FLEISCHHAUER agreed with MYLONAS's framing of strategic questions, adding\r
+that a large institution such as LC probably has to do all of those\r
+things at different times.  Thus, the trick is to exercise judgment.  The\r
+Workshop had added to his and AM's considerations in making those\r
+judgments.  Concerning future meetings or discussions, MYLONAS suggested\r
+that screening priorities would be helpful.\r
+\r
+WEIBEL opined that the diversity reflected in this group was a sign both\r
+of the health and of the immaturity of the field, and more time would\r
+have to pass before we convince one another concerning standards.\r
+\r
+An exchange between MYLONAS and BATTIN clarified the point that the\r
+driving force behind both the Perseus and the Cornell Xerox projects was\r
+the preservation of knowledge for the future, not simply for particular\r
+research use.  In the case of Perseus, MYLONAS said, the assumption was\r
+that the texts would not be entered again into electronically readable\r
+form.  SPERBERG-McQUEEN added that a scanned image would not serve as an\r
+archival copy for purposes of preservation in the case of, say, the Bill\r
+of Rights, in the sense that the scanned images are effectively the\r
+archival copies for the Cornell mathematics books.\r
+\r
+\r
+               ***   ***   ***   ******   ***   ***   ***\r
+\r
+\r
+                          Appendix I:  PROGRAM\r
+\r
+\r
+\r
+                                WORKSHOP\r
+                                   ON\r
+                               ELECTRONIC\r
+                                  TEXTS\r
+\r
+\r
+\r
+                             9-10 June 1992\r
+\r
+                           Library of Congress\r
+                            Washington, D.C.\r
+\r
+\r
+\r
+    Supported by a Grant from the David and Lucile Packard Foundation\r
+\r
+\r
+Tuesday, 9 June 1992\r
+\r
+NATIONAL DEMONSTRATION LAB, ATRIUM, LIBRARY MADISON\r
+\r
+8:30 AM   Coffee and Danish, registration\r
+\r
+9:00 AM   Welcome\r
+\r
+          Prosser Gifford, Director for Scholarly Programs, and Carl\r
+             Fleischhauer, Coordinator, American Memory, Library of\r
+             Congress\r
+\r
+9:l5 AM   Session I.  Content in a New Form:  Who Will Use It and What\r
+          Will They Do?\r
+\r
+          Broad description of the range of electronic information. \r
+          Characterization of who uses it and how it is or may be used. \r
+          In addition to a look at scholarly uses, this session will\r
+          include a presentation on use by students (K-12 and college)\r
+          and the general public.\r
+\r
+          Moderator:  James Daly\r
+          Avra Michelson, Archival Research and Evaluation Staff,\r
+             National Archives and Records Administration (Overview)\r
+          Susan H. Veccia, Team Leader, American Memory, User Evaluation,\r
+             and\r
+          Joanne Freeman, Associate Coordinator, American Memory, Library\r
+             of Congress (Beyond the scholar)\r
+\r
+10:30-\r
+11:00 AM  Break\r
+\r
+11:00 AM  Session II.  Show and Tell.\r
+\r
+          Each presentation to consist of a fifteen-minute\r
+          statement/show; group discussion will follow lunch.\r
+\r
+          Moderator:  Jacqueline Hess, Director, National Demonstration\r
+             Lab\r
+\r
+            1.  A classics project, stressing texts and text retrieval\r
+                more than multimedia:  Perseus Project, Harvard\r
+                University\r
+                Elli Mylonas, Managing Editor\r
+\r
+            2.  Other humanities projects employing the emerging norms of\r
+                the Text Encoding Initiative (TEI):  Chadwyck-Healey's\r
+                The English Poetry Full Text Database and/or Patrologia\r
+                Latina Database\r
+                Eric M. Calaluca, Vice President, Chadwyck-Healey, Inc.\r
+\r
+            3.  American Memory\r
+                Carl Fleischhauer, Coordinator, and\r
+                Ricky Erway, Associate Coordinator, Library of Congress\r
+\r
+            4.  Founding Fathers example from Packard Humanities\r
+                Institute:  The Papers of George Washington, University\r
+                of Virginia\r
+                Dorothy Twohig, Managing Editor, and/or\r
+                David Woodley Packard\r
+\r
+            5.  An electronic medical journal offering graphics and\r
+                full-text searchability:  The Online Journal of Current\r
+                Clinical Trials, American Association for the Advancement\r
+                of Science\r
+                Maria L. Lebron, Managing Editor\r
+\r
+            6.  A project that offers facsimile images of pages but omits\r
+                searchable text:  Cornell math books\r
+                Lynne K. Personius, Assistant Director, Cornell\r
+                   Information Technologies for Scholarly Information\r
+                   Sources, Cornell University\r
+\r
+12:30 PM  Lunch  (Dining Room A, Library Madison 620.  Exhibits\r
+          available.)\r
+\r
+1:30 PM   Session II.  Show and Tell (Cont'd.).\r
+\r
+3:00-\r
+3:30 PM   Break\r
+\r
+3:30-\r
+5:30 PM   Session III.  Distribution, Networks, and Networking:  Options\r
+          for Dissemination.\r
+\r
+          Published disks:  University presses and public-sector\r
+             publishers, private-sector publishers\r
+          Computer networks\r
+\r
+          Moderator:  Robert G. Zich, Special Assistant to the Associate\r
+             Librarian for Special Projects, Library of Congress\r
+          Clifford A. Lynch, Director, Library Automation, University of\r
+             California\r
+          Howard Besser, School of Library and Information Science,\r
+             University of Pittsburgh\r
+          Ronald L. Larsen, Associate Director of Libraries for\r
+             Information Technology, University of Maryland at College\r
+             Park\r
+          Edwin B. Brownrigg, Executive Director, Memex Research\r
+             Institute\r
+\r
+6:30 PM   Reception  (Montpelier Room, Library Madison 619.)\r
+\r
+                                 ******\r
+\r
+Wednesday, 10 June 1992\r
+\r
+DINING ROOM A, LIBRARY MADISON 620\r
+\r
+8:30 AM   Coffee and Danish\r
+\r
+9:00 AM   Session IV.  Image Capture, Text Capture, Overview of Text and\r
+          Image Storage Formats.\r
+\r
+          Moderator:  William L. Hooton, Vice President of Operations,\r
+             I-NET\r
+\r
+          A) Principal Methods for Image Capture of Text:\r
+             Direct scanning\r
+             Use of microform\r
+\r
+          Anne R. Kenney, Assistant Director, Department of Preservation\r
+             and Conservation, Cornell University\r
+          Pamela Q.J. Andre, Associate Director, Automation, and\r
+          Judith A. Zidar, Coordinator, National Agricultural Text\r
+             Digitizing Program (NATDP), National Agricultural Library\r
+             (NAL)\r
+          Donald J. Waters, Head, Systems Office, Yale University Library\r
+\r
+          B) Special Problems:\r
+             Bound volumes\r
+             Conservation\r
+             Reproducing printed halftones\r
+\r
+          Carl Fleischhauer, Coordinator, American Memory, Library of\r
+             Congress\r
+          George Thoma, Chief, Communications Engineering Branch,\r
+             National Library of Medicine (NLM)\r
+\r
+10:30-\r
+11:00 AM  Break\r
+\r
+11:00 AM  Session IV.  Image Capture, Text Capture, Overview of Text and\r
+          Image Storage Formats (Cont'd.).\r
+\r
+          C) Image Standards and Implications for Preservation\r
+\r
+          Jean Baronas, Senior Manager, Department of Standards and\r
+             Technology, Association for Information and Image Management\r
+             (AIIM)\r
+          Patricia Battin, President, The Commission on Preservation and\r
+             Access (CPA)\r
+\r
+          D) Text Conversion:\r
+             OCR vs. rekeying\r
+             Standards of accuracy and use of imperfect texts\r
+             Service bureaus\r
+\r
+          Stuart Weibel, Senior Research Specialist, Online Computer\r
+             Library Center, Inc. (OCLC)\r
+          Michael Lesk, Executive Director, Computer Science Research,\r
+             Bellcore\r
+          Ricky Erway, Associate Coordinator, American Memory, Library of\r
+             Congress\r
+          Pamela Q.J. Andre, Associate Director, Automation, and\r
+          Judith A. Zidar, Coordinator, National Agricultural Text\r
+             Digitizing Program (NATDP), National Agricultural Library\r
+             (NAL)\r
+\r
+12:30-\r
+1:30 PM   Lunch\r
+\r
+1:30 PM   Session V.  Approaches to Preparing Electronic Texts.\r
+\r
+          Discussion of approaches to structuring text for the computer;\r
+          pros and cons of text coding, description of methods in\r
+          practice, and comparison of text-coding methods.\r
+\r
+          Moderator:  Susan Hockey, Director, Center for Electronic Texts\r
+             in the Humanities (CETH), Rutgers and Princeton Universities\r
+          David Woodley Packard\r
+          C.M. Sperberg-McQueen, Editor, Text Encoding Initiative (TEI),\r
+             University of Illinois-Chicago\r
+          Eric M. Calaluca, Vice President, Chadwyck-Healey, Inc.\r
+\r
+3:30-\r
+4:00 PM   Break\r
+\r
+4:00 PM   Session VI.  Copyright Issues.\r
+\r
+          Marybeth Peters, Policy Planning Adviser to the Register of\r
+             Copyrights, Library of Congress\r
+\r
+5:00 PM   Session VII. Conclusion.\r
+\r
+          General discussion.\r
+          What topics were omitted or given short shrift that anyone\r
+             would like to talk about now?\r
+          Is there a "group" here?  What should the group do next, if\r
+             anything?  What should the Library of Congress do next, if\r
+             anything?\r
+          Moderator:  Prosser Gifford, Director for Scholarly Programs,\r
+             Library of Congress\r
+\r
+6:00 PM   Adjourn\r
+\r
+\r
+               ***   ***   ***   ******   ***   ***   ***\r
+\r
+\r
+                         Appendix II:  ABSTRACTS\r
+\r
+\r
+SESSION I\r
+\r
+Avra MICHELSON           Forecasting the Use of Electronic Texts by\r
+                         Social Sciences and Humanities Scholars\r
+\r
+This presentation explores the ways in which electronic texts are likely\r
+to be used by the non-scientific scholarly community.  Many of the\r
+remarks are drawn from a report the speaker coauthored with Jeff\r
+Rothenberg, a computer scientist at The RAND Corporation.\r
+\r
+The speaker assesses 1) current scholarly use of information technology\r
+and 2) the key trends in information technology most relevant to the\r
+research process, in order to predict how social sciences and humanities\r
+scholars are apt to use electronic texts.  In introducing the topic,\r
+current use of electronic texts is explored broadly within the context of\r
+scholarly communication.  From the perspective of scholarly\r
+communication, the work of humanities and social sciences scholars\r
+involves five processes:  1) identification of sources, 2) communication\r
+with colleagues, 3) interpretation and analysis of data, 4) dissemination\r
+of research findings, and 5) curriculum development and instruction.  The\r
+extent to which computation currently permeates aspects of scholarly\r
+communication represents a viable indicator of the prospects for\r
+electronic texts.\r
+\r
+The discussion of current practice is balanced by an analysis of key\r
+trends in the scholarly use of information technology.  These include the\r
+trends toward end-user computing and connectivity, which provide a\r
+framework for forecasting the use of electronic texts through this\r
+millennium.  The presentation concludes with a summary of the ways in\r
+which the nonscientific scholarly community can be expected to use\r
+electronic texts, and the implications of that use for information\r
+providers.\r
+\r
+Susan VECCIA and Joanne FREEMAN    Electronic Archives for the Public: \r
+                                   Use of American Memory in Public and\r
+                                   School Libraries\r
+\r
+This joint discussion focuses on nonscholarly applications of electronic\r
+library materials, specifically addressing use of the Library of Congress\r
+American Memory (AM) program in a small number of public and school\r
+libraries throughout the United States.  AM consists of selected Library\r
+of Congress primary archival materials, stored on optical media\r
+(CD-ROM/videodisc), and presented with little or no editing.  Many\r
+collections are accompanied by electronic introductions and user's guides\r
+offering background information and historical context.  Collections\r
+represent a variety of formats including photographs, graphic arts,\r
+motion pictures, recorded sound, music, broadsides and manuscripts,\r
+books, and pamphlets.\r
+\r
+In 1991, the Library of Congress began a nationwide evaluation of AM in\r
+different types of institutions.  Test sites include public libraries,\r
+elementary and secondary school libraries, college and university\r
+libraries, state libraries, and special libraries.  Susan VECCIA and\r
+Joanne FREEMAN will discuss their observations on the use of AM by the\r
+nonscholarly community, using evidence gleaned from this ongoing\r
+evaluation effort.\r
+\r
+VECCIA will comment on the overall goals of the evaluation project, and\r
+the types of public and school libraries included in this study.  Her\r
+comments on nonscholarly use of AM will focus on the public library as a\r
+cultural and community institution, often bridging the gap between formal\r
+and informal education.  FREEMAN will discuss the use of AM in school\r
+libraries.  Use by students and teachers has revealed some broad\r
+questions about the use of electronic resources, as well as definite\r
+benefits gained by the "nonscholar."  Topics will include the problem of\r
+grasping content and context in an electronic environment, the stumbling\r
+blocks created by "new" technologies, and the unique skills and interests\r
+awakened through use of electronic resources.\r
+\r
+SESSION II\r
+\r
+Elli MYLONAS             The Perseus Project:  Interactive Sources and\r
+                         Studies in Classical Greece\r
+\r
+The Perseus Project (5) has just released Perseus 1.0, the first publicly\r
+available version of its hypertextual database of multimedia materials on\r
+classical Greece.  Perseus is designed to be used by a wide audience,\r
+comprised of readers at the student and scholar levels.  As such, it must\r
+be able to locate information using different strategies, and it must\r
+contain enough detail to serve the different needs of its users.  In\r
+addition, it must be delivered so that it is affordable to its target\r
+audience.  [These problems and the solutions we chose are described in\r
+Mylonas, "An Interface to Classical Greek Civilization," JASIS 43:2,\r
+March 1992.]\r
+\r
+In order to achieve its objective, the project staff decided to make a\r
+conscious separation between selecting and converting textual, database,\r
+and image data on the one hand, and putting it into a delivery system on\r
+the other.  That way, it is possible to create the electronic data\r
+without thinking about the restrictions of the delivery system.  We have\r
+made a great effort to choose system-independent formats for our data,\r
+and to put as much thought and work as possible into structuring it so\r
+that the translation from paper to electronic form will enhance the value\r
+of the data. [A discussion of these solutions as of two years ago is in\r
+Elli Mylonas, Gregory Crane, Kenneth Morrell, and D. Neel Smith, "The\r
+Perseus Project:  Data in the Electronic Age," in Accessing Antiquity: \r
+The Computerization of Classical Databases, J. Solomon and T. Worthen\r
+(eds.),  University of Arizona Press, in press.]\r
+\r
+Much of the work on Perseus is focused on collecting and converting the\r
+data on which the project is based.  At the same time, it is necessary to\r
+provide means of access to the information, in order to make it usable,\r
+and them to investigate how it is used.  As we learn more about what\r
+students and scholars from different backgrounds do with Perseus, we can\r
+adjust our data collection, and also modify the system to accommodate\r
+them.  In creating a delivery system for general use, we have tried to\r
+avoid favoring any one type of use by allowing multiple forms of access\r
+to and navigation through the system.\r
+\r
+The way text is handled exemplifies some of these principles.  All text\r
+in Perseus is tagged using SGML, following the guidelines of the Text\r
+Encoding Initiative (TEI).  This markup is used to index the text, and\r
+process it so that it can be imported into HyperCard.  No SGML markup\r
+remains in the text that reaches the user, because currently it would be\r
+too expensive to create a system that acts on SGML in real time. \r
+However, the regularity provided by SGML is essential for verifying the\r
+content of the texts, and greatly speeds all the processing performed on\r
+them.  The fact that the texts exist in SGML ensures that they will be\r
+relatively easy to port to different hardware and software, and so will\r
+outlast the current delivery platform.  Finally, the SGML markup\r
+incorporates existing canonical reference systems (chapter, verse, line,\r
+etc.); indexing and navigation are based on these features.  This ensures\r
+that the same canonical reference will always resolve to the same point\r
+within a text, and that all versions of our texts, regardless of delivery\r
+platform (even paper printouts) will function the same way.\r
+\r
+In order to provide tools for users, the text is processed by a\r
+morphological analyzer, and the results are stored in a database. \r
+Together with the index, the Greek-English Lexicon, and the index of all\r
+the English words in the definitions of the lexicon, the morphological\r
+analyses comprise a set of linguistic tools that allow users of all\r
+levels to work with the textual information, and to accomplish different\r
+tasks.  For example, students who read no Greek may explore a concept as\r
+it appears in Greek texts by using the English-Greek index, and then\r
+looking up works in the texts and translations, or scholars may do\r
+detailed morphological studies of word use by using the morphological\r
+analyses of the texts.  Because these tools were not designed for any one\r
+use, the same tools and the same data can be used by both students and\r
+scholars.\r
+\r
+NOTES:\r
+     (5)  Perseus is based at Harvard University, with collaborators at\r
+     several other universities.  The project has been funded primarily\r
+     by the Annenberg/CPB Project, as well as by Harvard University,\r
+     Apple Computer, and others.  It is published by Yale University\r
+     Press.  Perseus runs on Macintosh computers, under the HyperCard\r
+     program.\r
+\r
+Eric CALALUCA\r
+\r
+Chadwyck-Healey embarked last year on two distinct yet related full-text\r
+humanities database projects.\r
+\r
+The English Poetry Full-Text Database and the Patrologia Latina Database\r
+represent new approaches to linguistic research resources.  The size and\r
+complexity of the projects present problems for electronic publishers,\r
+but surmountable ones if they remain abreast of the latest possibilities\r
+in data capture and retrieval software techniques.\r
+\r
+The issues which required address prior to the commencement of the\r
+projects were legion:\r
+\r
+     1.   Editorial selection (or exclusion) of materials in each\r
+          database\r
+\r
+     2.   Deciding whether or not to incorporate a normative encoding\r
+          structure into the databases?\r
+               A.  If one is selected, should it be SGML?\r
+               B.  If SGML, then the TEI?\r
+     \r
+     3.   Deliver as CD-ROM, magnetic tape, or both?\r
+\r
+     4.   Can one produce retrieval software advanced enough for the\r
+          postdoctoral linguist, yet accessible enough for unattended\r
+          general use?  Should one try?\r
+\r
+     5.   Re fair and liberal networking policies, what are the risks to\r
+          an electronic publisher?\r
+\r
+     6.   How does the emergence of national and international education\r
+          networks affect the use and viability of research projects\r
+          requiring high investment?  Do the new European Community\r
+          directives concerning database protection necessitate two\r
+          distinct publishing projects, one for North America and one for\r
+          overseas?\r
+\r
+From new notions of "scholarly fair use" to the future of optical media,\r
+virtually every issue related to electronic publishing was aired.  The\r
+result is two projects which have been constructed to provide the quality\r
+research resources with the fewest encumbrances to use by teachers and\r
+private scholars.\r
+\r
+Dorothy TWOHIG\r
+\r
+In spring 1988 the editors of the papers of George Washington, John\r
+Adams, Thomas Jefferson, James Madison, and Benjamin Franklin were\r
+approached by classics scholar David Packard on behalf of the Packard\r
+Humanities Foundation with a proposal to produce a CD-ROM edition of the\r
+complete papers of each of the Founding Fathers.  This electronic edition\r
+will supplement the published volumes, making the documents widely\r
+available to students and researchers at reasonable cost.  We estimate\r
+that our CD-ROM edition of Washington's Papers will be substantially\r
+completed within the next two years and ready for publication.  Within\r
+the next ten years or so, similar CD-ROM editions of the Franklin, Adams,\r
+Jefferson, and Madison papers also will be available.  At the Library of\r
+Congress's session on technology, I would like to discuss not only the\r
+experience of the Washington Papers in producing the CD-ROM edition, but\r
+the impact technology has had on these major editorial projects. \r
+Already, we are editing our volumes with an eye to the material that will\r
+be readily available in the CD-ROM edition.  The completed electronic\r
+edition will provide immense possibilities for the searching of documents\r
+for information in a way never possible before.  The kind of technical\r
+innovations that are currently available and on the drawing board will\r
+soon revolutionize historical research and the production of historical\r
+documents.  Unfortunately, much of this new technology is not being used\r
+in the planning stages of historical projects, simply because many\r
+historians are aware only in the vaguest way of its existence.  At least\r
+two major new historical editing projects are considering microfilm\r
+editions, simply because they are not aware of the possibilities of\r
+electronic alternatives and the advantages of the new technology in terms\r
+of flexibility and research potential compared to microfilm.  In fact,\r
+too many of us in history and literature are still at the stage of\r
+struggling with our PCs.  There are many historical editorial projects in\r
+progress presently, and an equal number of literary projects.  While the\r
+two fields have somewhat different approaches to textual editing, there\r
+are ways in which electronic technology can be of service to both.\r
+\r
+Since few of the editors involved in the Founding Fathers CD-ROM editions\r
+are technical experts in any sense, I hope to point out in my discussion\r
+of our experience how many of these electronic innovations can be used\r
+successfully by scholars who are novices in the world of new technology. \r
+One of the major concerns of the sponsors of the multitude of new\r
+scholarly editions is the limited audience reached by the published\r
+volumes.  Most of these editions are being published in small quantities\r
+and the publishers' price for them puts them out of the reach not only of\r
+individual scholars but of most public libraries and all but the largest\r
+educational institutions.  However, little attention is being given to\r
+ways in which technology can bypass conventional publication to make\r
+historical and literary documents more widely available.\r
+\r
+What attracted us most to the CD-ROM edition of The Papers of George\r
+Washington was the fact that David Packard's aim was to make a complete\r
+edition of all of the 135,000 documents we have collected available in an\r
+inexpensive format that would be placed in public libraries, small\r
+colleges, and even high schools.  This would provide an audience far\r
+beyond our present 1,000-copy, $45 published edition.  Since the CD-ROM\r
+edition will carry none of the explanatory annotation that appears in the\r
+published volumes, we also feel that the use of the CD-ROM will lead many\r
+researchers to seek out the published volumes.\r
+\r
+In addition to ignorance of new technical advances, I have found that too\r
+many editors--and historians and literary scholars--are resistant and\r
+even hostile to suggestions that electronic technology may enhance their\r
+work.  I intend to discuss some of the arguments traditionalists are\r
+advancing to resist technology, ranging from distrust of the speed with\r
+which it changes (we are already wondering what is out there that is\r
+better than CD-ROM) to suspicion of the technical language used to\r
+describe electronic developments.\r
+\r
+Maria LEBRON\r
+\r
+The Online Journal of Current Clinical Trials, a joint venture of the\r
+American Association for the Advancement of Science (AAAS) and the Online\r
+Computer Library Center, Inc. (OCLC), is the first peer-reviewed journal\r
+to provide full text, tabular material, and line illustrations on line. \r
+This presentation will discuss the genesis and start-up period of the\r
+journal.  Topics of discussion will include historical overview,\r
+day-to-day management of the editorial peer review, and manuscript\r
+tagging and publication.  A demonstration of the journal and its features\r
+will accompany the presentation.\r
+\r
+Lynne PERSONIUS\r
+\r
+Cornell University Library, Cornell Information Technologies, and Xerox\r
+Corporation, with the support of the Commission on Preservation and\r
+Access, and Sun Microsystems, Inc., have been collaborating in a project\r
+to test a prototype system for recording brittle books as digital images\r
+and producing, on demand, high-quality archival paper replacements.  The\r
+project goes beyond that, however, to investigate some of the issues\r
+surrounding scanning, storing, retrieving, and providing access to\r
+digital images in a network environment.\r
+\r
+The Joint Study in Digital Preservation began in January 1990.  Xerox\r
+provided the College Library Access and Storage System (CLASS) software,\r
+a prototype 600-dots-per-inch (dpi) scanner, and the hardware necessary\r
+to support network printing on the DocuTech printer housed in Cornell's\r
+Computing and Communications Center (CCC).\r
+\r
+The Cornell staff using the hardware and software became an integral part\r
+of the development and testing process for enhancements to the CLASS\r
+software system.  The collaborative nature of this relationship is\r
+resulting in a system that is specifically tailored to the preservation\r
+application.\r
+\r
+A digital library of 1,000 volumes (or approximately 300,000 images) has\r
+been created and is stored on an optical jukebox that resides in CCC. \r
+The library includes a collection of select mathematics monographs that\r
+provides mathematics faculty with an opportunity to use the electronic\r
+library.  The remaining volumes were chosen for the library to test the\r
+various capabilities of the scanning system.\r
+\r
+One project objective is to provide users of the Cornell library and the\r
+library staff with the ability to request facsimiles of digitized images\r
+or to retrieve the actual electronic image for browsing.  A prototype\r
+viewing workstation has been created by Xerox, with input into the design\r
+by a committee of Cornell librarians and computer professionals.  This\r
+will allow us to experiment with patron access to the images that make up\r
+the digital library.  The viewing station provides search, retrieval, and\r
+(ultimately) printing functions with enhancements to facilitate\r
+navigation through multiple documents.\r
+\r
+Cornell currently is working to extend access to the digital library to\r
+readers using workstations from their offices.  This year is devoted to\r
+the development of a network resident image conversion and delivery\r
+server, and client software that will support readers who use Apple\r
+Macintosh computers, IBM windows platforms, and Sun workstations. \r
+Equipment for this development was provided by Sun Microsystems with\r
+support from the Commission on Preservation and Access.\r
+\r
+During the show-and-tell session of the Workshop on Electronic Texts, a\r
+prototype view station will be demonstrated.  In addition, a display of\r
+original library books that have been digitized will be available for\r
+review with associated printed copies for comparison.  The fifteen-minute\r
+overview of the project will include a slide presentation that\r
+constitutes a "tour" of the preservation digitizing process.\r
+\r
+The final network-connected version of the viewing station will provide\r
+library users with another mechanism for accessing the digital library,\r
+and will also provide the capability of viewing images directly.  This\r
+will not require special software, although a powerful computer with good\r
+graphics will be needed.\r
+\r
+The Joint Study in Digital Preservation has generated a great deal of\r
+interest in the library community.  Unfortunately, or perhaps\r
+fortunately, this project serves to raise a vast number of other issues\r
+surrounding the use of digital technology for the preservation and use of\r
+deteriorating library materials, which subsequent projects will need to\r
+examine.  Much work remains.\r
+\r
+SESSION III\r
+\r
+Howard BESSER                      Networking Multimedia Databases\r
+\r
+What do we have to consider in building and distributing databases of\r
+visual materials in a multi-user environment?  This presentation examines\r
+a variety of concerns that need to be addressed before a multimedia\r
+database can be set up in a networked environment.\r
+\r
+In the past it has not been feasible to implement databases of visual\r
+materials in shared-user environments because of technological barriers. \r
+Each of the two basic models for multi-user multimedia databases has\r
+posed its own problem.  The analog multimedia storage model (represented\r
+by Project Athena's parallel analog and digital networks) has required an\r
+incredibly complex (and expensive) infrastructure.  The economies of\r
+scale that make multi-user setups cheaper per user served do not operate\r
+in an environment that requires a computer workstation, videodisc player,\r
+and two display devices for each user.\r
+\r
+The digital multimedia storage model has required vast amounts of storage\r
+space (as much as one gigabyte per thirty still images).  In the past the\r
+cost of such a large amount of storage space made this model a\r
+prohibitive choice as well.  But plunging storage costs are finally\r
+making this second alternative viable.\r
+\r
+If storage no longer poses such an impediment, what do we need to\r
+consider in building digitally stored multi-user databases of visual\r
+materials?  This presentation will examine the networking and\r
+telecommunication constraints that must be overcome before such databases\r
+can become commonplace and useful to a large number of people.\r
+\r
+The key problem is the vast size of multimedia documents, and how this\r
+affects not only storage but telecommunications transmission time. \r
+Anything slower than T-1 speed is impractical for files of 1 megabyte or\r
+larger (which is likely to be small for a multimedia document).  For\r
+instance, even on a 56 Kb line it would take three minutes to transfer a\r
+1-megabyte file.  And these figures assume ideal circumstances, and do\r
+not take into consideration other users contending for network bandwidth,\r
+disk access time, or the time needed for remote display.  Current common\r
+telephone transmission rates would be completely impractical; few users\r
+would be willing to wait the hour necessary to transmit a single image at\r
+2400 baud.\r
+\r
+This necessitates compression, which itself raises a number of other\r
+issues.  In order to decrease file sizes significantly, we must employ\r
+lossy compression algorithms.  But how much quality can we afford to\r
+lose?  To date there has been only one significant study done of\r
+image-quality needs for a particular user group, and this study did not\r
+look at loss resulting from compression.  Only after identifying\r
+image-quality needs can we begin to address storage and network bandwidth\r
+needs.\r
+\r
+Experience with X-Windows-based applications (such as Imagequery, the\r
+University of California at Berkeley image database) demonstrates the\r
+utility of a client-server topology, but also points to the limitation of\r
+current software for a distributed environment.  For example,\r
+applications like Imagequery can incorporate compression, but current X\r
+implementations do not permit decompression at the end user's\r
+workstation.  Such decompression at the host computer alleviates storage\r
+capacity problems while doing nothing to address problems of\r
+telecommunications bandwidth.\r
+\r
+We need to examine the effects on network through-put of moving\r
+multimedia documents around on a network.  We need to examine various\r
+topologies that will help us avoid bottlenecks around servers and\r
+gateways.  Experience with applications such as these raise still broader\r
+questions. How closely is the multimedia document tied to the software\r
+for viewing it?  Can it be accessed and viewed from other applications? \r
+Experience with the MARC format (and more recently with the Z39.50\r
+protocols) shows how useful it can be to store documents in a form in\r
+which they can be accessed by a variety of application software.\r
+\r
+Finally, from an intellectual-access standpoint, we need to address the\r
+issue of providing access to these multimedia documents in\r
+interdisciplinary environments.  We need to examine terminology and\r
+indexing strategies that will allow us to provide access to this material\r
+in a cross-disciplinary way.\r
+\r
+Ronald LARSEN            Directions in High-Performance Networking for\r
+                         Libraries\r
+\r
+The pace at which computing technology has advanced over the past forty\r
+years shows no sign of abating.  Roughly speaking, each five-year period\r
+has yielded an order-of-magnitude improvement in price and performance of\r
+computing equipment.  No fundamental hurdles are likely to prevent this\r
+pace from continuing for at least the next decade.  It is only in the\r
+past five years, though, that computing has become ubiquitous in\r
+libraries, affecting all staff and patrons, directly or indirectly.\r
+\r
+During these same five years, communications rates on the Internet, the\r
+principal academic computing network, have grown from 56 kbps to 1.5\r
+Mbps, and the NSFNet backbone is now running 45 Mbps.  Over the next five\r
+years, communication rates on the backbone are expected to exceed 1 Gbps. \r
+Growth in both the population of network users and the volume of network\r
+traffic  has continued to grow geometrically, at rates approaching 15\r
+percent per month.  This flood of capacity and use, likened by some to\r
+"drinking from a firehose,"  creates immense opportunities and challenges\r
+for libraries.  Libraries must anticipate the future implications of this\r
+technology, participate in its development, and deploy it to ensure\r
+access to the world's information resources.\r
+\r
+The infrastructure for the information age is being put in place. \r
+Libraries face strategic decisions about their role in the development,\r
+deployment, and use of this infrastructure.  The emerging infrastructure\r
+is much more than computers and communication lines.  It is more than the\r
+ability to compute at a remote site, send electronic mail to a peer\r
+across the country, or move a file from one library to another.  The next\r
+five years will witness substantial development of the information\r
+infrastructure of the network.\r
+\r
+In order to provide appropriate leadership, library professionals must\r
+have a fundamental understanding of and appreciation for computer\r
+networking, from local area networks to the National Research and\r
+Education Network (NREN).  This presentation addresses these\r
+fundamentals, and how they relate to libraries today and in the near\r
+future.\r
+\r
+Edwin BROWNRIGG               Electronic Library Visions and Realities\r
+\r
+The electronic library has been a vision desired by many--and rejected by\r
+some--since Vannevar Bush coined the term memex to describe an automated,\r
+intelligent, personal information system.  Variations on this vision have\r
+included Ted Nelson's Xanadau, Alan Kay's Dynabook, and Lancaster's\r
+"paperless library," with the most recent incarnation being the\r
+"Knowledge Navigator" described by John Scully of Apple.  But the reality\r
+of library service has been less visionary and the leap to the electronic\r
+library has eluded universities, publishers, and information technology\r
+files.\r
+\r
+The Memex Research Institute (MemRI), an independent, nonprofit research\r
+and development organization, has created an Electronic Library Program\r
+of shared research and development in order to make the collective vision\r
+more concrete.  The program is working toward the creation of large,\r
+indexed publicly available electronic image collections of published\r
+documents in academic, special, and public libraries.  This strategic\r
+plan is the result of the first stage of the program, which has been an\r
+investigation of the information technologies available to support such\r
+an effort, the economic parameters of electronic service compared to\r
+traditional library operations, and the business and political factors\r
+affecting the shift from print distribution to electronic networked\r
+access.\r
+\r
+The strategic plan envisions a combination of publicly searchable access\r
+databases, image (and text) document collections stored on network "file\r
+servers," local and remote network access, and an intellectual property\r
+management-control system.  This combination of technology and\r
+information content is defined in this plan as an E-library or E-library\r
+collection.  Some participating sponsors are already developing projects\r
+based on MemRI's recommended directions.\r
+\r
+The E-library strategy projected in this plan is a visionary one that can\r
+enable major changes and improvements in academic, public, and special\r
+library service.  This vision is, though, one that can be realized with\r
+today's technology.  At the same time, it will challenge the political\r
+and social structure within which libraries operate:  in academic\r
+libraries, the traditional emphasis on local collections, extending to\r
+accreditation issues; in public libraries, the potential of electronic\r
+branch and central libraries fully available to the public; and for\r
+special libraries, new opportunities for shared collections and networks.\r
+\r
+The environment in which this strategic plan has been developed is, at\r
+the moment, dominated by a sense of library limits.  The continued\r
+expansion and rapid growth of local academic library collections is now\r
+clearly at an end.  Corporate libraries, and even law libraries, are\r
+faced with operating within a difficult economic climate, as well as with\r
+very active competition from commercial information sources.  For\r
+example, public libraries may be seen as a desirable but not critical\r
+municipal service in a time when the budgets of safety and health\r
+agencies are being cut back.\r
+\r
+Further, libraries in general have a very high labor-to-cost ratio in\r
+their budgets, and labor costs are still increasing, notwithstanding\r
+automation investments.  It is difficult for libraries to obtain capital,\r
+startup, or seed funding for innovative activities, and those\r
+technology-intensive initiatives that offer the potential of decreased\r
+labor costs can provoke the opposition of library staff.\r
+\r
+However, libraries have achieved some considerable successes in the past\r
+two decades by improving both their service and their credibility within\r
+their organizations--and these positive changes have been accomplished\r
+mostly with judicious use of information technologies.  The advances in\r
+computing and information technology have been well-chronicled:  the\r
+continuing precipitous drop in computing costs, the growth of the\r
+Internet and private networks, and the explosive increase in publicly\r
+available information databases.\r
+\r
+For example, OCLC has become one of the largest computer network\r
+organizations in the world by creating a cooperative cataloging network\r
+of more than 6,000 libraries worldwide.  On-line public access catalogs\r
+now serve millions of users on more than 50,000 dedicated terminals in\r
+the United States alone.  The University of California MELVYL on-line\r
+catalog system has now expanded into an index database reference service\r
+and supports more than six million searches a year.  And, libraries have\r
+become the largest group of customers of CD-ROM publishing technology;\r
+more than 30,000 optical media publications such as those offered by\r
+InfoTrac and Silver Platter are subscribed to by U.S. libraries.\r
+\r
+This march of technology continues and in the next decade will result in\r
+further innovations that are extremely difficult to predict.  What is\r
+clear is that libraries can now go beyond automation of their order files\r
+and catalogs to automation of their collections themselves--and it is\r
+possible to circumvent the fiscal limitations that appear to obtain\r
+today.\r
+\r
+This Electronic Library Strategic Plan recommends a paradigm shift in\r
+library service, and demonstrates the steps necessary to provide improved\r
+library services with limited capacities and operating investments.\r
+\r
+SESSION IV-A\r
+\r
+Anne KENNEY\r
+\r
+The Cornell/Xerox Joint Study in Digital Preservation resulted in the\r
+recording of 1,000 brittle books as 600-dpi digital images and the\r
+production, on demand, of high-quality and archivally sound paper\r
+replacements.  The project, which was supported by the Commission on\r
+Preservation and Access, also investigated some of the issues surrounding\r
+scanning, storing, retrieving, and providing access to digital images in\r
+a network environment.\r
+\r
+Anne Kenney will focus on some of the issues surrounding direct scanning\r
+as identified in the Cornell Xerox Project.  Among those to be discussed\r
+are:  image versus text capture; indexing and access; image-capture\r
+capabilities; a comparison to photocopy and microfilm; production and\r
+cost analysis; storage formats, protocols, and standards; and the use of\r
+this scanning technology for preservation purposes.\r
+\r
+The 600-dpi digital images produced in the Cornell Xerox Project proved\r
+highly acceptable for creating paper replacements of deteriorating\r
+originals.  The 1,000 scanned volumes provided an array of image-capture\r
+challenges that are common to nineteenth-century printing techniques and\r
+embrittled material, and that defy the use of text-conversion processes. \r
+These challenges include diminished contrast between text and background,\r
+fragile and deteriorated pages, uneven printing, elaborate type faces,\r
+faint and bold text adjacency, handwritten text and annotations, nonRoman\r
+languages, and a proliferation of illustrated material embedded in text. \r
+The latter category included high-frequency and low-frequency halftones,\r
+continuous tone photographs, intricate mathematical drawings, maps,\r
+etchings, reverse-polarity drawings, and engravings.\r
+\r
+The Xerox prototype scanning system provided a number of important\r
+features for capturing this diverse material.  Technicians used multiple\r
+threshold settings, filters, line art and halftone definitions,\r
+autosegmentation, windowing, and software-editing programs to optimize\r
+image capture.  At the same time, this project focused on production. \r
+The goal was to make scanning as affordable and acceptable as\r
+photocopying and microfilming for preservation reformatting.  A\r
+time-and-cost study conducted during the last three months of this\r
+project confirmed the economic viability of digital scanning, and these\r
+findings will be discussed here.\r
+\r
+From the outset, the Cornell Xerox Project was predicated on the use of\r
+nonproprietary standards and the use of common protocols when standards\r
+did not exist.  Digital files were created as TIFF images which were\r
+compressed prior to storage using Group 4 CCITT compression.  The Xerox\r
+software is MS DOS based and utilizes off-the shelf programs such as\r
+Microsoft Windows and Wang Image Wizard.  The digital library is designed\r
+to be hardware-independent and to provide interchangeability with other\r
+institutions through network connections.  Access to the digital files\r
+themselves is two-tiered:  Bibliographic records for the computer files\r
+are created in RLIN and Cornell's local system and access into the actual\r
+digital images comprising a book is provided through a document control\r
+structure and a networked image file-server, both of which will be\r
+described.\r
+\r
+The presentation will conclude with a discussion of some of the issues\r
+surrounding the use of this technology as a preservation tool (storage,\r
+refreshing, backup).\r
+\r
+Pamela ANDRE and Judith ZIDAR\r
+\r
+The National Agricultural Library (NAL) has had extensive experience with\r
+raster scanning of printed materials.  Since 1987, the Library has\r
+participated in the National Agricultural Text Digitizing Project (NATDP)\r
+a cooperative effort between NAL and forty-five land grant university\r
+libraries.  An overview of the project will be presented, giving its\r
+history and NAL's strategy for the future.\r
+\r
+An in-depth discussion of NATDP will follow, including a description of\r
+the scanning process, from the gathering of the printed materials to the\r
+archiving of the electronic pages.  The type of equipment required for a\r
+stand-alone scanning workstation and the importance of file management\r
+software will be discussed.  Issues concerning the images themselves will\r
+be addressed briefly, such as image format; black and white versus color;\r
+gray scale versus dithering; and resolution.\r
+\r
+Also described will be a study currently in progress by NAL to evaluate\r
+the usefulness of converting microfilm to electronic images in order to\r
+improve access.  With the cooperation of Tuskegee University, NAL has\r
+selected three reels of microfilm from a collection of sixty-seven reels\r
+containing the papers, letters, and drawings of George Washington Carver. \r
+The three reels were converted into 3,500 electronic images using a\r
+specialized microfilm scanner.  The selection, filming, and indexing of\r
+this material will be discussed.\r
+\r
+Donald WATERS\r
+\r
+Project Open Book, the Yale University Library's effort to convert 10,\r
+000 books from microfilm to digital imagery, is currently in an advanced\r
+state of planning and organization.  The Yale Library has selected a\r
+major vendor to serve as a partner in the project and as systems\r
+integrator.  In its proposal, the successful vendor helped isolate areas\r
+of risk and uncertainty as well as key issues to be addressed during the\r
+life of the project.  The Yale Library is now poised to decide what\r
+material it will convert to digital image form and to seek funding,\r
+initially for the first phase and then for the entire project.\r
+\r
+The proposal that Yale accepted for the implementation of Project Open\r
+Book will provide at the end of three phases a conversion subsystem,\r
+browsing stations distributed on the campus network within the Yale\r
+Library, a subsystem for storing 10,000 books at 200 and 600 dots per\r
+inch, and network access to the image printers.  Pricing for the system\r
+implementation assumes the existence of Yale's campus ethernet network\r
+and its high-speed image printers, and includes other requisite hardware\r
+and software, as well as system integration services.  Proposed operating\r
+costs include hardware and software maintenance, but do not include\r
+estimates for the facilities management of the storage devices and image\r
+servers.\r
+\r
+Yale selected its vendor partner in a formal process, partly funded by\r
+the Commission for Preservation and Access.  Following a request for\r
+proposal, the Yale Library selected two vendors as finalists to work with\r
+Yale staff to generate a detailed analysis of requirements for Project\r
+Open Book.  Each vendor used the results of the requirements analysis to\r
+generate and submit a formal proposal for the entire project.  This\r
+competitive process not only enabled the Yale Library to select its\r
+primary vendor partner but also revealed much about the state of the\r
+imaging industry, about the varying, corporate commitments to the markets\r
+for imaging technology, and about the varying organizational dynamics\r
+through which major companies are responding to and seeking to develop\r
+these markets.\r
+\r
+Project Open Book is focused specifically on the conversion of images\r
+from microfilm to digital form.  The technology for scanning microfilm is\r
+readily available but is changing rapidly.  In its project requirements,\r
+the Yale Library emphasized features of the technology that affect the\r
+technical quality of digital image production and the costs of creating\r
+and storing the image library:  What levels of digital resolution can be\r
+achieved by scanning microfilm?  How does variation in the quality of\r
+microfilm, particularly in film produced to preservation standards,\r
+affect the quality of the digital images?  What technologies can an\r
+operator effectively and economically apply when scanning film to\r
+separate two-up images and to control for and correct image\r
+imperfections?  How can quality control best be integrated into\r
+digitizing work flow that includes document indexing and storage?\r
+\r
+The actual and expected uses of digital images--storage, browsing,\r
+printing, and OCR--help determine the standards for measuring their\r
+quality.  Browsing is especially important, but the facilities available\r
+for readers to browse image documents is perhaps the weakest aspect of\r
+imaging technology and most in need of development.  As it defined its\r
+requirements, the Yale Library concentrated on some fundamental aspects\r
+of usability for image documents:  Does the system have sufficient\r
+flexibility to handle the full range of document types, including\r
+monographs, multi-part and multivolume sets, and serials, as well as\r
+manuscript collections?  What conventions are necessary to identify a\r
+document uniquely for storage and retrieval?  Where is the database of\r
+record for storing bibliographic information about the image document? \r
+How are basic internal structures of documents, such as pagination, made\r
+accessible to the reader?  How are the image documents physically\r
+presented on the screen to the reader?\r
+\r
+The Yale Library designed Project Open Book on the assumption that\r
+microfilm is more than adequate as a medium for preserving the content of\r
+deteriorated library materials.  As planning in the project has advanced,\r
+it is increasingly clear that the challenge of digital image technology\r
+and the key to the success of efforts like Project Open Book is to\r
+provide a means of both preserving and improving access to those\r
+deteriorated materials.\r
+\r
+SESSION IV-B\r
+\r
+George THOMA\r
+\r
+In the use of electronic imaging for document preservation, there are\r
+several issues to consider, such as:  ensuring adequate image quality,\r
+maintaining substantial conversion rates (through-put), providing unique\r
+identification for automated access and retrieval, and accommodating\r
+bound volumes and fragile material.\r
+\r
+To maintain high image quality, image processing functions are required\r
+to correct the deficiencies in the scanned image.  Some commercially\r
+available systems include these functions, while some do not.  The\r
+scanned raw image must be processed to correct contrast deficiencies--\r
+both poor overall contrast resulting from light print and/or dark\r
+background, and variable contrast resulting from stains and\r
+bleed-through.  Furthermore, the scan density must be adequate to allow\r
+legibility of print and sufficient fidelity in the pseudo-halftoned gray\r
+material.  Borders or page-edge effects must be removed for both\r
+compactibility and aesthetics.  Page skew must be corrected for aesthetic\r
+reasons and to enable accurate character recognition if desired. \r
+Compound images consisting of both two-toned text and gray-scale\r
+illustrations must be processed appropriately to retain the quality of\r
+each.\r
+\r
+SESSION IV-C\r
+\r
+Jean BARONAS\r
+\r
+Standards publications being developed by scientists, engineers, and\r
+business managers in Association for Information and Image Management\r
+(AIIM) standards committees can be applied to electronic image management\r
+(EIM) processes including:  document (image) transfer, retrieval and\r
+evaluation; optical disk and document scanning; and document design and\r
+conversion.  When combined with EIM system planning and operations,\r
+standards can assist in generating image databases that are\r
+interchangeable among a variety of systems.  The applications of\r
+different approaches for image-tagging, indexing, compression, and\r
+transfer often cause uncertainty concerning EIM system compatibility,\r
+calibration, performance, and upward compatibility, until standard\r
+implementation parameters are established.  The AIIM standards that are\r
+being developed for these applications can be used to decrease the\r
+uncertainty, successfully integrate imaging processes, and promote "open\r
+systems."  AIIM is an accredited American National Standards Institute\r
+(ANSI) standards developer with more than twenty committees comprised of\r
+300 volunteers representing users, vendors, and manufacturers.  The\r
+standards publications that are developed in these committees have\r
+national acceptance and provide the basis for international harmonization\r
+in the development of new International Organization for Standardization\r
+(ISO) standards.\r
+\r
+This presentation describes the development of AIIM's EIM standards and a\r
+new effort at AIIM, a database on standards projects in a wide framework\r
+of imaging industries including capture, recording, processing,\r
+duplication, distribution, display, evaluation, and preservation.  The\r
+AIIM Imagery Database will cover imaging standards being developed by\r
+many organizations in many different countries.  It will contain\r
+standards publications' dates, origins, related national and\r
+international projects, status, key words, and abstracts.  The ANSI Image\r
+Technology Standards Board requested that such a database be established,\r
+as did the ISO/International Electrotechnical Commission Joint Task Force\r
+on Imagery.  AIIM will take on the leadership role for the database and\r
+coordinate its development with several standards developers.\r
+\r
+Patricia BATTIN\r
+\r
+     Characteristics of standards for digital imagery:\r
+\r
+          * Nature of digital technology implies continuing volatility.\r
+\r
+          * Precipitous standard-setting not possible and probably not\r
+          desirable.\r
+\r
+          * Standards are a complex issue involving the medium, the\r
+          hardware, the software, and the technical capacity for\r
+          reproductive fidelity and clarity.\r
+\r
+          * The prognosis for reliable archival standards (as defined by\r
+          librarians) in the foreseeable future is poor.\r
+\r
+     Significant potential and attractiveness of digital technology as a\r
+     preservation medium and access mechanism.\r
+\r
+     Productive use of digital imagery for preservation requires a\r
+     reconceptualizing of preservation principles in a volatile,\r
+     standardless world.\r
+\r
+     Concept of managing continuing access in the digital environment\r
+     rather than focusing on the permanence of the medium and long-term\r
+     archival standards developed for the analog world.\r
+\r
+     Transition period:  How long and what to do?\r
+\r
+          *  Redefine "archival."\r
+\r
+          *  Remove the burden of "archival copy" from paper artifacts.\r
+\r
+          *  Use digital technology for storage, develop management\r
+          strategies for refreshing medium, hardware and software.\r
+\r
+          *  Create acid-free paper copies for transition period backup\r
+          until we develop reliable procedures for ensuring continuing\r
+          access to digital files.\r
+\r
+SESSION IV-D\r
+\r
+Stuart WEIBEL            The Role of SGML Markup in the CORE Project (6)\r
+\r
+The emergence of high-speed telecommunications networks as a basic\r
+feature of the scholarly workplace is driving the demand for electronic\r
+document delivery.  Three distinct categories of electronic\r
+publishing/republishing are necessary to support access demands in this\r
+emerging environment:\r
+\r
+     1.)  Conversion of paper or microfilm archives to electronic format\r
+     2.)  Conversion of electronic files to formats tailored to\r
+          electronic retrieval and display\r
+     3.)  Primary electronic publishing (materials for which the\r
+          electronic version is the primary format)\r
+\r
+OCLC has experimental or product development activities in each of these\r
+areas.  Among the challenges that lie ahead is the integration of these\r
+three types of information stores in coherent distributed systems.\r
+\r
+The CORE (Chemistry Online Retrieval Experiment) Project is a model for\r
+the conversion of large text and graphics collections for which\r
+electronic typesetting files are available (category 2).  The American\r
+Chemical Society has made available computer typography files dating from\r
+1980 for its twenty journals.  This collection of some 250 journal-years\r
+is being converted to an electronic format that will be accessible\r
+through several end-user applications.\r
+\r
+The use of Standard Generalized Markup Language (SGML) offers the means\r
+to capture the structural richness of the original articles in a way that\r
+will support a variety of retrieval, navigation, and display options\r
+necessary to navigate effectively in very large text databases.\r
+\r
+An SGML document consists of text that is marked up with descriptive tags\r
+that specify the function of a given element within the document.  As a\r
+formal language construct, an SGML document can be parsed against a\r
+document-type definition (DTD) that unambiguously defines what elements\r
+are allowed and where in the document they can (or must) occur.  This\r
+formalized map of article structure allows the user interface design to\r
+be uncoupled from the underlying database system, an important step\r
+toward interoperability.  Demonstration of this separability is a part of\r
+the CORE project, wherein user interface designs born of very different\r
+philosophies will access the same database.\r
+\r
+NOTES:\r
+     (6)  The CORE project is a collaboration among Cornell University's\r
+     Mann Library, Bell Communications Research (Bellcore), the American\r
+     Chemical Society (ACS), the Chemical Abstracts Service (CAS), and\r
+     OCLC.\r
+\r
+Michael LESK                  The CORE Electronic Chemistry Library\r
+\r
+A major on-line file of chemical journal literature complete with\r
+graphics is being developed to test the usability of fully electronic\r
+access to documents, as a joint project of Cornell University, the\r
+American Chemical Society, the Chemical Abstracts Service, OCLC, and\r
+Bellcore (with additional support from Sun Microsystems, Springer-Verlag,\r
+DigitaI Equipment Corporation, Sony Corporation of America, and Apple\r
+Computers).  Our file contains the American Chemical Society's on-line\r
+journals, supplemented with the graphics from the paper publication.  The\r
+indexing of the articles from Chemical Abstracts Documents is available\r
+in both image and text format, and several different interfaces can be\r
+used.  Our goals are (1) to assess the effectiveness and acceptability of\r
+electronic access to primary journals as compared with paper, and (2) to\r
+identify the most desirable functions of the user interface to an\r
+electronic system of journals, including in particular a comparison of\r
+page-image display with ASCII display interfaces.  Early experiments with\r
+chemistry students on a variety of tasks suggest that searching tasks are\r
+completed much faster with any electronic system than with paper, but\r
+that for reading all versions of the articles are roughly equivalent.\r
+\r
+Pamela ANDRE and Judith ZIDAR\r
+\r
+Text conversion is far more expensive and time-consuming than image\r
+capture alone.  NAL's experience with optical character recognition (OCR)\r
+will be related and compared with the experience of having text rekeyed. \r
+What factors affect OCR accuracy?  How accurate does full text have to be\r
+in order to be useful?  How do different users react to imperfect text? \r
+These are questions that will be explored.  For many, a service bureau\r
+may be a better solution than performing the work inhouse; this will also\r
+be discussed.\r
+\r
+SESSION VI\r
+\r
+Marybeth PETERS\r
+\r
+Copyright law protects creative works.  Protection granted by the law to\r
+authors and disseminators of works includes the right to do or authorize\r
+the following:  reproduce the work, prepare derivative works, distribute\r
+the work to the public, and publicly perform or display the work.  In\r
+addition, copyright owners of sound recordings and computer programs have\r
+the right to control rental of their works.  These rights are not\r
+unlimited; there are a number of exceptions and limitations.\r
+\r
+An electronic environment places strains on the copyright system. \r
+Copyright owners want to control uses of their work and be paid for any\r
+use; the public wants quick and easy access at little or no cost.  The\r
+marketplace is working in this area.  Contracts, guidelines on electronic\r
+use, and collective licensing are in use and being refined.\r
+\r
+Issues concerning the ability to change works without detection are more\r
+difficult to deal with.  Questions concerning the integrity of the work\r
+and the status of the changed version under the copyright law are to be\r
+addressed.  These are public policy issues which require informed\r
+dialogue.\r
+\r
+\r
+               ***   ***   ***   ******   ***   ***   ***\r
+\r
+\r
+                Appendix III:  DIRECTORY OF PARTICIPANTS\r
+                         \r
+\r
+PRESENTERS:\r
+\r
+     Pamela Q.J. Andre\r
+     Associate Director, Automation\r
+     National Agricultural Library\r
+     10301 Baltimore Boulevard\r
+     Beltsville, MD 20705-2351\r
+     Phone:  (301) 504-6813\r
+     Fax:  (301) 504-7473\r
+     E-mail:  INTERNET:  PANDRE@ASRR.ARSUSDA.GOV\r
+\r
+     Jean Baronas, Senior Manager\r
+     Department of Standards and Technology\r
+     Association for Information and Image Management (AIIM)\r
+     1100 Wayne Avenue, Suite 1100\r
+     Silver Spring, MD 20910\r
+     Phone:  (301) 587-8202\r
+     Fax:  (301) 587-2711\r
+     \r
+     Patricia Battin, President\r
+     The Commission on Preservation and Access\r
+     1400 16th Street, N.W.\r
+     Suite 740\r
+     Washington, DC 20036-2217\r
+     Phone:  (202) 939-3400\r
+     Fax:  (202) 939-3407\r
+     E-mail:  CPA@GWUVM.BITNET\r
+\r
+     Howard Besser\r
+     Centre Canadien d'Architecture\r
+     (Canadian Center for Architecture)\r
+     1920, rue Baile\r
+     Montreal, Quebec H3H 2S6\r
+     CANADA\r
+     Phone:  (514) 939-7001\r
+     Fax:  (514) 939-7020\r
+     E-mail:  howard@lis.pitt.edu\r
+\r
+     Edwin B. Brownrigg, Executive Director\r
+     Memex Research Institute\r
+     422 Bonita Avenue\r
+     Roseville, CA 95678\r
+     Phone:  (916) 784-2298\r
+     Fax:  (916) 786-7559\r
+     E-mail:  BITNET:  MEMEX@CALSTATE.2\r
+\r
+     Eric M. Calaluca, Vice President\r
+     Chadwyck-Healey, Inc.\r
+     1101 King Street\r
+     Alexandria, VA 223l4\r
+     Phone:  (800) 752-05l5\r
+     Fax:  (703) 683-7589\r
+\r
+     James Daly\r
+     4015 Deepwood Road\r
+     Baltimore, MD 21218-1404\r
+     Phone:  (410) 235-0763\r
+\r
+     Ricky Erway, Associate Coordinator\r
+     American Memory\r
+     Library of Congress\r
+     Phone:  (202) 707-6233\r
+     Fax:  (202) 707-3764\r
+\r
+     Carl Fleischhauer, Coordinator\r
+     American Memory\r
+     Library of Congress\r
+     Phone:  (202) 707-6233\r
+     Fax:  (202) 707-3764\r
+\r
+     Joanne Freeman\r
+     2000 Jefferson Park Avenue, No. 7\r
+     Charlottesville, VA  22903\r
+     \r
+     Prosser Gifford\r
+     Director for Scholarly Programs\r
+     Library of Congress\r
+     Phone:  (202) 707-1517\r
+     Fax:  (202) 707-9898\r
+     E-mail:  pgif@seq1.loc.gov\r
+\r
+     Jacqueline Hess, Director\r
+     National Demonstration Laboratory\r
+       for Interactive Information Technologies\r
+     Library of Congress\r
+     Phone:  (202) 707-4157\r
+     Fax:  (202) 707-2829\r
+     \r
+     Susan Hockey, Director\r
+     Center for Electronic Texts in the Humanities (CETH)\r
+     Alexander Library\r
+     Rutgers University\r
+     169 College Avenue\r
+     New Brunswick, NJ 08903\r
+     Phone:  (908) 932-1384\r
+     Fax:  (908) 932-1386\r
+     E-mail:  hockey@zodiac.rutgers.edu\r
+\r
+     William L. Hooton, Vice President\r
+     Business & Technical Development\r
+       Imaging & Information Systems Group\r
+     I-NET\r
+     6430 Rockledge Drive, Suite 400\r
+     Bethesda, MD 208l7\r
+     Phone:  (301) 564-6750\r
+     Fax:  (513) 564-6867\r
+\r
+     Anne R. Kenney, Associate Director\r
+     Department of Preservation and Conservation\r
+     701 Olin Library\r
+     Cornell University\r
+     Ithaca, NY 14853\r
+     Phone:  (607) 255-6875\r
+     Fax:  (607) 255-9346\r
+     E-mail:  LYDY@CORNELLA.BITNET\r
+\r
+     Ronald L. Larsen\r
+     Associate Director for Information Technology\r
+     University of Maryland at College Park\r
+     Room B0224, McKeldin Library\r
+     College Park, MD 20742-7011\r
+     Phone:  (301) 405-9194\r
+     Fax:  (301) 314-9865\r
+     E-mail:  rlarsen@libr.umd.edu\r
+\r
+     Maria L. Lebron, Managing Editor\r
+     The Online Journal of Current Clinical Trials\r
+     l333 H Street, N.W.\r
+     Washington, DC 20005\r
+     Phone:  (202) 326-6735\r
+     Fax:  (202) 842-2868\r
+     E-mail:  PUBSAAAS@GWUVM.BITNET\r
+\r
+     Michael Lesk, Executive Director\r
+     Computer Science Research\r
+     Bell Communications Research, Inc.\r
+     Rm 2A-385\r
+     445 South Street\r
+     Morristown, NJ 07960-l9l0     \r
+     Phone:  (201) 829-4070\r
+     Fax:  (201) 829-5981\r
+     E-mail:  lesk@bellcore.com (Internet) or bellcore!lesk (uucp)\r
+\r
+     Clifford A. Lynch\r
+     Director, Library Automation\r
+     University of California,\r
+        Office of the President\r
+     300 Lakeside Drive, 8th Floor\r
+     Oakland, CA 94612-3350\r
+     Phone:  (510) 987-0522\r
+     Fax:  (510) 839-3573\r
+     E-mail:  calur@uccmvsa\r
+\r
+     Avra Michelson\r
+     National Archives and Records Administration\r
+     NSZ Rm. 14N\r
+     7th & Pennsylvania, N.W.\r
+     Washington, D.C. 20408\r
+     Phone:  (202) 501-5544\r
+     Fax:  (202) 501-5533\r
+     E-mail:  tmi@cu.nih.gov\r
+     \r
+     Elli Mylonas, Managing Editor\r
+     Perseus Project\r
+     Department of the Classics\r
+     Harvard University\r
+     319 Boylston Hall\r
+     Cambridge, MA 02138\r
+     Phone:  (617) 495-9025, (617) 495-0456 (direct)\r
+     Fax:  (617) 496-8886\r
+     E-mail:  Elli@IKAROS.Harvard.EDU or elli@wjh12.harvard.edu\r
+\r
+     David Woodley Packard\r
+     Packard Humanities Institute\r
+     300 Second Street, Suite 201\r
+     Los Altos, CA 94002\r
+     Phone:  (415) 948-0150 (PHI)\r
+     Fax:  (415) 948-5793\r
+\r
+     Lynne K. Personius, Assistant Director\r
+     Cornell Information Technologies for\r
+      Scholarly Information Sources\r
+     502 Olin Library\r
+     Cornell University\r
+     Ithaca, NY 14853\r
+     Phone:  (607) 255-3393\r
+     Fax:  (607) 255-9346\r
+     E-mail:  JRN@CORNELLC.BITNET\r
+\r
+     Marybeth Peters\r
+     Policy Planning Adviser to the\r
+       Register of Copyrights\r
+     Library of Congress\r
+     Office LM 403\r
+     Phone:  (202) 707-8350\r
+     Fax:  (202) 707-8366\r
+\r
+     C. Michael Sperberg-McQueen\r
+     Editor, Text Encoding Initiative\r
+     Computer Center (M/C 135)\r
+     University of Illinois at Chicago\r
+     Box 6998\r
+     Chicago, IL 60680\r
+     Phone:  (312) 413-0317\r
+     Fax:  (312) 996-6834\r
+     E-mail:  u35395@uicvm..cc.uic.edu or u35395@uicvm.bitnet\r
+\r
+     George R. Thoma, Chief\r
+     Communications Engineering Branch\r
+     National Library of Medicine\r
+     8600 Rockville Pike\r
+     Bethesda, MD 20894\r
+     Phone:  (301) 496-4496\r
+     Fax:  (301) 402-0341\r
+     E-mail:  thoma@lhc.nlm.nih.gov\r
+\r
+     Dorothy Twohig, Editor\r
+     The Papers of George Washington\r
+     504 Alderman Library\r
+     University of Virginia\r
+     Charlottesville, VA 22903-2498\r
+     Phone:  (804) 924-0523\r
+     Fax:  (804) 924-4337\r
+\r
+     Susan H. Veccia, Team leader\r
+     American Memory, User Evaluation\r
+     Library of Congress\r
+     American Memory Evaluation Project\r
+     Phone:  (202) 707-9104\r
+     Fax:  (202) 707-3764\r
+     E-mail:  svec@seq1.loc.gov\r
+\r
+     Donald J. Waters, Head\r
+     Systems Office\r
+     Yale University Library\r
+     New Haven, CT 06520\r
+     Phone:  (203) 432-4889\r
+     Fax:  (203) 432-7231\r
+     E-mail:  DWATERS@YALEVM.BITNET or DWATERS@YALEVM.YCC.YALE.EDU\r
+\r
+     Stuart Weibel, Senior Research Scientist\r
+     OCLC\r
+     6565 Frantz Road\r
+     Dublin, OH 43017\r
+     Phone:  (614) 764-608l\r
+     Fax:  (614) 764-2344\r
+     E-mail:  INTERNET:  Stu@rsch.oclc.org\r
+\r
+     Robert G. Zich\r
+     Special Assistant to the Associate Librarian\r
+       for Special Projects\r
+     Library of Congress\r
+     Phone:  (202) 707-6233\r
+     Fax:  (202) 707-3764\r
+     E-mail:  rzic@seq1.loc.gov\r
+\r
+     Judith A. Zidar, Coordinator\r
+     National Agricultural Text Digitizing Program\r
+     Information Systems Division\r
+     National Agricultural Library\r
+     10301 Baltimore Boulevard\r
+     Beltsville, MD 20705-2351\r
+     Phone:  (301) 504-6813 or 504-5853\r
+     Fax:  (301) 504-7473\r
+     E-mail:  INTERNET:  JZIDAR@ASRR.ARSUSDA.GOV\r
+\r
+\r
+OBSERVERS:\r
+\r
+     Helen Aguera, Program Officer\r
+     Division of Research\r
+     Room 318\r
+     National Endowment for the Humanities\r
+     1100 Pennsylvania Avenue, N.W.\r
+     Washington, D.C. 20506\r
+     Phone:  (202) 786-0358\r
+     Fax:  (202) 786-0243\r
+\r
+     M. Ellyn Blanton, Deputy Director\r
+     National Demonstration Laboratory\r
+       for Interactive Information Technologies\r
+     Library of Congress\r
+     Phone:  (202) 707-4157\r
+     Fax:  (202) 707-2829\r
+\r
+     Charles M. Dollar\r
+     National Archives and Records Administration\r
+     NSZ Rm. 14N\r
+     7th & Pennsylvania, N.W.\r
+     Washington, DC 20408\r
+     Phone:  (202) 501-5532\r
+     Fax:  (202) 501-5512\r
+\r
+     Jeffrey Field, Deputy to the Director\r
+     Division of Preservation and Access\r
+     Room 802\r
+     National Endowment for the Humanities\r
+     1100 Pennsylvania Avenue, N.W.\r
+     Washington, DC 20506\r
+     Phone:  (202) 786-0570\r
+     Fax:  (202) 786-0243\r
+\r
+     Lorrin Garson\r
+     American Chemical Society\r
+     Research and Development Department\r
+     1155 16th Street, N.W.\r
+     Washington, D.C. 20036\r
+     Phone:  (202) 872-4541\r
+     Fax:  E-mail:  INTERNET:  LRG96@ACS.ORG\r
+\r
+     William M. Holmes, Jr.\r
+     National Archives and Records Administration\r
+     NSZ Rm. 14N\r
+     7th & Pennsylvania, N.W.\r
+     Washington, DC 20408\r
+     Phone:  (202) 501-5540\r
+     Fax:  (202) 501-5512\r
+     E-mail:  WHOLMES@AMERICAN.EDU\r
+\r
+     Sperling Martin\r
+     Information Resource Management\r
+     20030 Doolittle Street\r
+     Gaithersburg, MD 20879\r
+     Phone:  (301) 924-1803\r
+\r
+     Michael Neuman, Director\r
+     The Center for Text and Technology\r
+     Academic Computing Center\r
+     238 Reiss Science Building\r
+     Georgetown University\r
+     Washington, DC 20057\r
+     Phone:  (202) 687-6096\r
+     Fax:  (202) 687-6003\r
+     E-mail:  neuman@guvax.bitnet, neuman@guvax.georgetown.edu\r
+\r
+     Barbara Paulson, Program Officer\r
+     Division of Preservation and Access\r
+     Room 802\r
+     National Endowment for the Humanities\r
+     1100 Pennsylvania Avenue, N.W.\r
+     Washington, DC 20506\r
+     Phone:  (202) 786-0577\r
+     Fax:  (202) 786-0243\r
+     \r
+     Allen H. Renear\r
+     Senior Academic Planning Analyst\r
+     Brown University Computing and Information Services\r
+     115 Waterman Street\r
+     Campus Box 1885\r
+     Providence, R.I. 02912\r
+     Phone:  (401) 863-7312\r
+     Fax:  (401) 863-7329\r
+     E-mail:  BITNET:  Allen@BROWNVM or           \r
+     INTERNET:  Allen@brownvm.brown.edu\r
+\r
+     Susan M. Severtson, President\r
+     Chadwyck-Healey, Inc.\r
+     1101 King Street\r
+     Alexandria, VA 223l4\r
+     Phone:  (800) 752-05l5\r
+     Fax:  (703) 683-7589     \r
+\r
+     Frank Withrow\r
+     U.S. Department of Education\r
+     555 New Jersey Avenue, N.W.\r
+     Washington, DC 20208-5644\r
+     Phone:  (202) 219-2200\r
+     Fax:  (202) 219-2106\r
+\r
+\r
+(LC STAFF)\r
+     \r
+     Linda L. Arret\r
+     Machine-Readable Collections Reading Room LJ 132\r
+     (202) 707-1490\r
+\r
+     John D. Byrum, Jr.\r
+     Descriptive Cataloging Division LM 540\r
+     (202) 707-5194\r
+\r
+     Mary Jane Cavallo\r
+     Science and Technology Division LA 5210\r
+     (202) 707-1219\r
+\r
+     Susan Thea David\r
+     Congressional Research Service LM 226\r
+     (202) 707-7169\r
+\r
+     Robert Dierker\r
+     Senior Adviser for Multimedia Activities LM 608\r
+     (202) 707-6151\r
+\r
+     William W. Ellis\r
+     Associate Librarian for Science and Technology LM 611\r
+     (202) 707-6928\r
+\r
+     Ronald Gephart\r
+     Manuscript Division LM 102\r
+     (202) 707-5097\r
+\r
+     James Graber\r
+     Information Technology Services LM G51\r
+     (202) 707-9628\r
+\r
+     Rich Greenfield\r
+     American Memory LM 603\r
+     (202) 707-6233\r
+\r
+     Rebecca Guenther\r
+     Network Development LM 639\r
+     (202) 707-5092\r
+\r
+     Kenneth E. Harris\r
+     Preservation LM G21\r
+     (202) 707-5213\r
+\r
+     Staley Hitchcock\r
+     Manuscript Division LM 102\r
+     (202) 707-5383\r
+\r
+     Bohdan Kantor\r
+     Office of Special Projects LM 612\r
+     (202) 707-0180\r
+\r
+     John W. Kimball, Jr\r
+     Machine-Readable Collections Reading Room LJ 132\r
+     (202) 707-6560\r
+\r
+     Basil Manns\r
+     Information Technology Services LM G51\r
+     (202) 707-8345\r
+\r
+     Sally Hart McCallum\r
+     Network Development LM 639\r
+     (202) 707-6237\r
+\r
+     Dana J. Pratt\r
+     Publishing Office LM 602\r
+     (202) 707-6027\r
+\r
+     Jane Riefenhauser\r
+     American Memory LM 603\r
+     (202) 707-6233\r
+\r
+     William Z. Schenck\r
+     Collections Development LM 650\r
+     (202) 707-7706\r
+\r
+     Chandru J. Shahani\r
+     Preservation Research and Testing Office (R&T) LM G38\r
+     (202) 707-5607\r
+\r
+     William J. Sittig\r
+     Collections Development LM 650\r
+     (202) 707-7050\r
+\r
+     Paul Smith\r
+     Manuscript Division LM 102\r
+     (202) 707-5097\r
+\r
+     James L. Stevens\r
+     Information Technology Services LM G51\r
+     (202) 707-9688\r
+\r
+     Karen Stuart\r
+     Manuscript Division LM 130\r
+     (202) 707-5389\r
+\r
+     Tamara Swora\r
+     Preservation Microfilming Office LM G05\r
+     (202) 707-6293\r
+\r
+     Sarah Thomas\r
+     Collections Cataloging LM 642\r
+     (202) 707-5333\r
+\r
+\r
+                                   END\r
+      *************************************************************\r
+\r
+Note:  This file has been edited for use on computer networks.  This\r
+editing required the removal of diacritics, underlining, and fonts such\r
+as italics and bold.  \r
+\r
+kde 11/92\r
+\r
+[A few of the italics (when used for emphasis) were replaced by CAPS mh]\r
+\r
+*End of The Project Gutenberg Etext of LOC WORKSHOP ON ELECTRONIC ETEXTS\r
+\r
diff --git a/snappy/snappy-1.0.5/testdata/mapreduce-osdi-1.pdf b/snappy/snappy-1.0.5/testdata/mapreduce-osdi-1.pdf
new file mode 100644 (file)
index 0000000..b98308a
Binary files /dev/null and b/snappy/snappy-1.0.5/testdata/mapreduce-osdi-1.pdf differ
diff --git a/snappy/snappy-1.0.5/testdata/plrabn12.txt b/snappy/snappy-1.0.5/testdata/plrabn12.txt
new file mode 100644 (file)
index 0000000..34088b8
--- /dev/null
@@ -0,0 +1,10699 @@
+\r
+This is the February 1992 Project Gutenberg release of: \r
\r
+Paradise Lost by John Milton \r
\r
+The oldest etext known to Project Gutenberg (ca. 1964-1965) \r
+(If you know of any older ones, please let us know.) \r
\r
\r
+Introduction  (one page) \r
\r
+This etext was originally created in 1964-1965 according to Dr. \r
+Joseph Raben of Queens College, NY, to whom it is attributed by \r
+Project Gutenberg.  We had heard of this etext for years but it \r
+was not until 1991 that we actually managed to track it down to \r
+a specific location, and then it took months to convince people \r
+to let us have a copy, then more months for them actually to do \r
+the copying and get it to us.  Then another month to convert to \r
+something we could massage with our favorite 486 in DOS.  After \r
+that is was only a matter of days to get it into this shape you \r
+will see below.  The original was, of course, in CAPS only, and \r
+so were all the other etexts of the 60's and early 70's.  Don't \r
+let anyone fool you into thinking any etext with both upper and \r
+lower case is an original; all those original Project Gutenberg \r
+etexts were also in upper case and were translated or rewritten \r
+many times to get them into their current condition.  They have \r
+been worked on by many people throughout the world. \r
\r
+In the course of our searches for Professor Raben and his etext \r
+we were never able to determine where copies were or which of a \r
+variety of editions he may have used as a source.  We did get a \r
+little information here and there, but even after we received a \r
+copy of the etext we were unwilling to release it without first \r
+determining that it was in fact Public Domain and finding Raben \r
+to verify this and get his permission.  Interested enough, in a \r
+totally unrelated action to our searches for him, the professor \r
+subscribed to the Project Gutenberg listserver and we happened, \r
+by accident, to notice his name. (We don't really look at every \r
+subscription request as the computers usually handle them.) The \r
+etext was then properly identified, copyright analyzed, and the \r
+current edition prepared. \r
\r
+To give you an estimation of the difference in the original and \r
+what we have today:  the original was probably entered on cards \r
+commonly known at the time as "IBM cards" (Do Not Fold, Spindle \r
+or Mutilate) and probably took in excess of 100,000 of them.  A \r
+single card could hold 80 characters (hence 80 characters is an \r
+accepted standard for so many computer margins), and the entire \r
+original edition we received in all caps was over 800,000 chars \r
+in length, including line enumeration, symbols for caps and the \r
+punctuation marks, etc., since they were not available keyboard \r
+characters at the time (probably the keyboards operated at baud \r
+rates of around 113, meaning the typists had to type slowly for \r
+the keyboard to keep up). \r
\r
+This is the second version of Paradise Lost released by Project \r
+Gutenberg.  The first was released as our October, 1991 etext. \r
\r
\r
\r
\r
\r
+Paradise Lost \r
\r
\r
\r
\r
+Book I \r
\r
\r
+Of Man's first disobedience, and the fruit \r
+Of that forbidden tree whose mortal taste \r
+Brought death into the World, and all our woe, \r
+With loss of Eden, till one greater Man \r
+Restore us, and regain the blissful seat, \r
+Sing, Heavenly Muse, that, on the secret top \r
+Of Oreb, or of Sinai, didst inspire \r
+That shepherd who first taught the chosen seed \r
+In the beginning how the heavens and earth \r
+Rose out of Chaos: or, if Sion hill \r
+Delight thee more, and Siloa's brook that flowed \r
+Fast by the oracle of God, I thence \r
+Invoke thy aid to my adventurous song, \r
+That with no middle flight intends to soar \r
+Above th' Aonian mount, while it pursues \r
+Things unattempted yet in prose or rhyme. \r
+And chiefly thou, O Spirit, that dost prefer \r
+Before all temples th' upright heart and pure, \r
+Instruct me, for thou know'st; thou from the first \r
+Wast present, and, with mighty wings outspread, \r
+Dove-like sat'st brooding on the vast Abyss, \r
+And mad'st it pregnant: what in me is dark \r
+Illumine, what is low raise and support; \r
+That, to the height of this great argument, \r
+I may assert Eternal Providence, \r
+And justify the ways of God to men. \r
+  Say first--for Heaven hides nothing from thy view, \r
+Nor the deep tract of Hell--say first what cause \r
+Moved our grand parents, in that happy state, \r
+Favoured of Heaven so highly, to fall off \r
+From their Creator, and transgress his will \r
+For one restraint, lords of the World besides. \r
+Who first seduced them to that foul revolt? \r
+  Th' infernal Serpent; he it was whose guile, \r
+Stirred up with envy and revenge, deceived \r
+The mother of mankind, what time his pride \r
+Had cast him out from Heaven, with all his host \r
+Of rebel Angels, by whose aid, aspiring \r
+To set himself in glory above his peers, \r
+He trusted to have equalled the Most High, \r
+If he opposed, and with ambitious aim \r
+Against the throne and monarchy of God, \r
+Raised impious war in Heaven and battle proud, \r
+With vain attempt. Him the Almighty Power \r
+Hurled headlong flaming from th' ethereal sky, \r
+With hideous ruin and combustion, down \r
+To bottomless perdition, there to dwell \r
+In adamantine chains and penal fire, \r
+Who durst defy th' Omnipotent to arms. \r
+  Nine times the space that measures day and night \r
+To mortal men, he, with his horrid crew, \r
+Lay vanquished, rolling in the fiery gulf, \r
+Confounded, though immortal. But his doom \r
+Reserved him to more wrath; for now the thought \r
+Both of lost happiness and lasting pain \r
+Torments him: round he throws his baleful eyes, \r
+That witnessed huge affliction and dismay, \r
+Mixed with obdurate pride and steadfast hate. \r
+At once, as far as Angels ken, he views \r
+The dismal situation waste and wild. \r
+A dungeon horrible, on all sides round, \r
+As one great furnace flamed; yet from those flames \r
+No light; but rather darkness visible \r
+Served only to discover sights of woe, \r
+Regions of sorrow, doleful shades, where peace \r
+And rest can never dwell, hope never comes \r
+That comes to all, but torture without end \r
+Still urges, and a fiery deluge, fed \r
+With ever-burning sulphur unconsumed. \r
+Such place Eternal Justice has prepared \r
+For those rebellious; here their prison ordained \r
+In utter darkness, and their portion set, \r
+As far removed from God and light of Heaven \r
+As from the centre thrice to th' utmost pole. \r
+Oh how unlike the place from whence they fell! \r
+There the companions of his fall, o'erwhelmed \r
+With floods and whirlwinds of tempestuous fire, \r
+He soon discerns; and, weltering by his side, \r
+One next himself in power, and next in crime, \r
+Long after known in Palestine, and named \r
+Beelzebub. To whom th' Arch-Enemy, \r
+And thence in Heaven called Satan, with bold words \r
+Breaking the horrid silence, thus began:-- \r
+  "If thou beest he--but O how fallen! how changed \r
+From him who, in the happy realms of light \r
+Clothed with transcendent brightness, didst outshine \r
+Myriads, though bright!--if he whom mutual league, \r
+United thoughts and counsels, equal hope \r
+And hazard in the glorious enterprise \r
+Joined with me once, now misery hath joined \r
+In equal ruin; into what pit thou seest \r
+From what height fallen: so much the stronger proved \r
+He with his thunder; and till then who knew \r
+The force of those dire arms? Yet not for those, \r
+Nor what the potent Victor in his rage \r
+Can else inflict, do I repent, or change, \r
+Though changed in outward lustre, that fixed mind, \r
+And high disdain from sense of injured merit, \r
+That with the Mightiest raised me to contend, \r
+And to the fierce contentions brought along \r
+Innumerable force of Spirits armed, \r
+That durst dislike his reign, and, me preferring, \r
+His utmost power with adverse power opposed \r
+In dubious battle on the plains of Heaven, \r
+And shook his throne. What though the field be lost? \r
+All is not lost--the unconquerable will, \r
+And study of revenge, immortal hate, \r
+And courage never to submit or yield: \r
+And what is else not to be overcome? \r
+That glory never shall his wrath or might \r
+Extort from me. To bow and sue for grace \r
+With suppliant knee, and deify his power \r
+Who, from the terror of this arm, so late \r
+Doubted his empire--that were low indeed; \r
+That were an ignominy and shame beneath \r
+This downfall; since, by fate, the strength of Gods, \r
+And this empyreal sybstance, cannot fail; \r
+Since, through experience of this great event, \r
+In arms not worse, in foresight much advanced, \r
+We may with more successful hope resolve \r
+To wage by force or guile eternal war, \r
+Irreconcilable to our grand Foe, \r
+Who now triumphs, and in th' excess of joy \r
+Sole reigning holds the tyranny of Heaven." \r
+  So spake th' apostate Angel, though in pain, \r
+Vaunting aloud, but racked with deep despair; \r
+And him thus answered soon his bold compeer:-- \r
+  "O Prince, O Chief of many throned Powers \r
+That led th' embattled Seraphim to war \r
+Under thy conduct, and, in dreadful deeds \r
+Fearless, endangered Heaven's perpetual King, \r
+And put to proof his high supremacy, \r
+Whether upheld by strength, or chance, or fate, \r
+Too well I see and rue the dire event \r
+That, with sad overthrow and foul defeat, \r
+Hath lost us Heaven, and all this mighty host \r
+In horrible destruction laid thus low, \r
+As far as Gods and heavenly Essences \r
+Can perish: for the mind and spirit remains \r
+Invincible, and vigour soon returns, \r
+Though all our glory extinct, and happy state \r
+Here swallowed up in endless misery. \r
+But what if he our Conqueror (whom I now \r
+Of force believe almighty, since no less \r
+Than such could have o'erpowered such force as ours) \r
+Have left us this our spirit and strength entire, \r
+Strongly to suffer and support our pains, \r
+That we may so suffice his vengeful ire, \r
+Or do him mightier service as his thralls \r
+By right of war, whate'er his business be, \r
+Here in the heart of Hell to work in fire, \r
+Or do his errands in the gloomy Deep? \r
+What can it the avail though yet we feel \r
+Strength undiminished, or eternal being \r
+To undergo eternal punishment?" \r
+  Whereto with speedy words th' Arch-Fiend replied:-- \r
+"Fallen Cherub, to be weak is miserable, \r
+Doing or suffering: but of this be sure-- \r
+To do aught good never will be our task, \r
+But ever to do ill our sole delight, \r
+As being the contrary to his high will \r
+Whom we resist. If then his providence \r
+Out of our evil seek to bring forth good, \r
+Our labour must be to pervert that end, \r
+And out of good still to find means of evil; \r
+Which ofttimes may succeed so as perhaps \r
+Shall grieve him, if I fail not, and disturb \r
+His inmost counsels from their destined aim. \r
+But see! the angry Victor hath recalled \r
+His ministers of vengeance and pursuit \r
+Back to the gates of Heaven: the sulphurous hail, \r
+Shot after us in storm, o'erblown hath laid \r
+The fiery surge that from the precipice \r
+Of Heaven received us falling; and the thunder, \r
+Winged with red lightning and impetuous rage, \r
+Perhaps hath spent his shafts, and ceases now \r
+To bellow through the vast and boundless Deep. \r
+Let us not slip th' occasion, whether scorn \r
+Or satiate fury yield it from our Foe. \r
+Seest thou yon dreary plain, forlorn and wild, \r
+The seat of desolation, void of light, \r
+Save what the glimmering of these livid flames \r
+Casts pale and dreadful? Thither let us tend \r
+From off the tossing of these fiery waves; \r
+There rest, if any rest can harbour there; \r
+And, re-assembling our afflicted powers, \r
+Consult how we may henceforth most offend \r
+Our enemy, our own loss how repair, \r
+How overcome this dire calamity, \r
+What reinforcement we may gain from hope, \r
+If not, what resolution from despair." \r
+  Thus Satan, talking to his nearest mate, \r
+With head uplift above the wave, and eyes \r
+That sparkling blazed; his other parts besides \r
+Prone on the flood, extended long and large, \r
+Lay floating many a rood, in bulk as huge \r
+As whom the fables name of monstrous size, \r
+Titanian or Earth-born, that warred on Jove, \r
+Briareos or Typhon, whom the den \r
+By ancient Tarsus held, or that sea-beast \r
+Leviathan, which God of all his works \r
+Created hugest that swim th' ocean-stream. \r
+Him, haply slumbering on the Norway foam, \r
+The pilot of some small night-foundered skiff, \r
+Deeming some island, oft, as seamen tell, \r
+With fixed anchor in his scaly rind, \r
+Moors by his side under the lee, while night \r
+Invests the sea, and wished morn delays. \r
+So stretched out huge in length the Arch-fiend lay, \r
+Chained on the burning lake; nor ever thence \r
+Had risen, or heaved his head, but that the will \r
+And high permission of all-ruling Heaven \r
+Left him at large to his own dark designs, \r
+That with reiterated crimes he might \r
+Heap on himself damnation, while he sought \r
+Evil to others, and enraged might see \r
+How all his malice served but to bring forth \r
+Infinite goodness, grace, and mercy, shewn \r
+On Man by him seduced, but on himself \r
+Treble confusion, wrath, and vengeance poured. \r
+  Forthwith upright he rears from off the pool \r
+His mighty stature; on each hand the flames \r
+Driven backward slope their pointing spires, and,rolled \r
+In billows, leave i' th' midst a horrid vale. \r
+Then with expanded wings he steers his flight \r
+Aloft, incumbent on the dusky air, \r
+That felt unusual weight; till on dry land \r
+He lights--if it were land that ever burned \r
+With solid, as the lake with liquid fire, \r
+And such appeared in hue as when the force \r
+Of subterranean wind transprots a hill \r
+Torn from Pelorus, or the shattered side \r
+Of thundering Etna, whose combustible \r
+And fuelled entrails, thence conceiving fire, \r
+Sublimed with mineral fury, aid the winds, \r
+And leave a singed bottom all involved \r
+With stench and smoke. Such resting found the sole \r
+Of unblest feet. Him followed his next mate; \r
+Both glorying to have scaped the Stygian flood \r
+As gods, and by their own recovered strength, \r
+Not by the sufferance of supernal Power. \r
+  "Is this the region, this the soil, the clime," \r
+Said then the lost Archangel, "this the seat \r
+That we must change for Heaven?--this mournful gloom \r
+For that celestial light? Be it so, since he \r
+Who now is sovereign can dispose and bid \r
+What shall be right: farthest from him is best \r
+Whom reason hath equalled, force hath made supreme \r
+Above his equals. Farewell, happy fields, \r
+Where joy for ever dwells! Hail, horrors! hail, \r
+Infernal world! and thou, profoundest Hell, \r
+Receive thy new possessor--one who brings \r
+A mind not to be changed by place or time. \r
+The mind is its own place, and in itself \r
+Can make a Heaven of Hell, a Hell of Heaven. \r
+What matter where, if I be still the same, \r
+And what I should be, all but less than he \r
+Whom thunder hath made greater? Here at least \r
+We shall be free; th' Almighty hath not built \r
+Here for his envy, will not drive us hence: \r
+Here we may reigh secure; and, in my choice, \r
+To reign is worth ambition, though in Hell: \r
+Better to reign in Hell than serve in Heaven. \r
+But wherefore let we then our faithful friends, \r
+Th' associates and co-partners of our loss, \r
+Lie thus astonished on th' oblivious pool, \r
+And call them not to share with us their part \r
+In this unhappy mansion, or once more \r
+With rallied arms to try what may be yet \r
+Regained in Heaven, or what more lost in Hell?" \r
+  So Satan spake; and him Beelzebub \r
+Thus answered:--"Leader of those armies bright \r
+Which, but th' Omnipotent, none could have foiled! \r
+If once they hear that voice, their liveliest pledge \r
+Of hope in fears and dangers--heard so oft \r
+In worst extremes, and on the perilous edge \r
+Of battle, when it raged, in all assaults \r
+Their surest signal--they will soon resume \r
+New courage and revive, though now they lie \r
+Grovelling and prostrate on yon lake of fire, \r
+As we erewhile, astounded and amazed; \r
+No wonder, fallen such a pernicious height!" \r
+  He scare had ceased when the superior Fiend \r
+Was moving toward the shore; his ponderous shield, \r
+Ethereal temper, massy, large, and round, \r
+Behind him cast. The broad circumference \r
+Hung on his shoulders like the moon, whose orb \r
+Through optic glass the Tuscan artist views \r
+At evening, from the top of Fesole, \r
+Or in Valdarno, to descry new lands, \r
+Rivers, or mountains, in her spotty globe. \r
+His spear--to equal which the tallest pine \r
+Hewn on Norwegian hills, to be the mast \r
+Of some great ammiral, were but a wand-- \r
+He walked with, to support uneasy steps \r
+Over the burning marl, not like those steps \r
+On Heaven's azure; and the torrid clime \r
+Smote on him sore besides, vaulted with fire. \r
+Nathless he so endured, till on the beach \r
+Of that inflamed sea he stood, and called \r
+His legions--Angel Forms, who lay entranced \r
+Thick as autumnal leaves that strow the brooks \r
+In Vallombrosa, where th' Etrurian shades \r
+High over-arched embower; or scattered sedge \r
+Afloat, when with fierce winds Orion armed \r
+Hath vexed the Red-Sea coast, whose waves o'erthrew \r
+Busiris and his Memphian chivalry, \r
+While with perfidious hatred they pursued \r
+The sojourners of Goshen, who beheld \r
+From the safe shore their floating carcases \r
+And broken chariot-wheels. So thick bestrown, \r
+Abject and lost, lay these, covering the flood, \r
+Under amazement of their hideous change. \r
+He called so loud that all the hollow deep \r
+Of Hell resounded:--"Princes, Potentates, \r
+Warriors, the Flower of Heaven--once yours; now lost, \r
+If such astonishment as this can seize \r
+Eternal Spirits! Or have ye chosen this place \r
+After the toil of battle to repose \r
+Your wearied virtue, for the ease you find \r
+To slumber here, as in the vales of Heaven? \r
+Or in this abject posture have ye sworn \r
+To adore the Conqueror, who now beholds \r
+Cherub and Seraph rolling in the flood \r
+With scattered arms and ensigns, till anon \r
+His swift pursuers from Heaven-gates discern \r
+Th' advantage, and, descending, tread us down \r
+Thus drooping, or with linked thunderbolts \r
+Transfix us to the bottom of this gulf? \r
+Awake, arise, or be for ever fallen!" \r
+  They heard, and were abashed, and up they sprung \r
+Upon the wing, as when men wont to watch \r
+On duty, sleeping found by whom they dread, \r
+Rouse and bestir themselves ere well awake. \r
+Nor did they not perceive the evil plight \r
+In which they were, or the fierce pains not feel; \r
+Yet to their General's voice they soon obeyed \r
+Innumerable. As when the potent rod \r
+Of Amram's son, in Egypt's evil day, \r
+Waved round the coast, up-called a pitchy cloud \r
+Of locusts, warping on the eastern wind, \r
+That o'er the realm of impious Pharaoh hung \r
+Like Night, and darkened all the land of Nile; \r
+So numberless were those bad Angels seen \r
+Hovering on wing under the cope of Hell, \r
+'Twixt upper, nether, and surrounding fires; \r
+Till, as a signal given, th' uplifted spear \r
+Of their great Sultan waving to direct \r
+Their course, in even balance down they light \r
+On the firm brimstone, and fill all the plain: \r
+A multitude like which the populous North \r
+Poured never from her frozen loins to pass \r
+Rhene or the Danaw, when her barbarous sons \r
+Came like a deluge on the South, and spread \r
+Beneath Gibraltar to the Libyan sands. \r
+Forthwith, form every squadron and each band, \r
+The heads and leaders thither haste where stood \r
+Their great Commander--godlike Shapes, and Forms \r
+Excelling human; princely Dignities; \r
+And Powers that erst in Heaven sat on thrones, \r
+Though on their names in Heavenly records now \r
+Be no memorial, blotted out and rased \r
+By their rebellion from the Books of Life. \r
+Nor had they yet among the sons of Eve \r
+Got them new names, till, wandering o'er the earth, \r
+Through God's high sufferance for the trial of man, \r
+By falsities and lies the greatest part \r
+Of mankind they corrupted to forsake \r
+God their Creator, and th' invisible \r
+Glory of him that made them to transform \r
+Oft to the image of a brute, adorned \r
+With gay religions full of pomp and gold, \r
+And devils to adore for deities: \r
+Then were they known to men by various names, \r
+And various idols through the heathen world. \r
+  Say, Muse, their names then known, who first, who last, \r
+Roused from the slumber on that fiery couch, \r
+At their great Emperor's call, as next in worth \r
+Came singly where he stood on the bare strand, \r
+While the promiscuous crowd stood yet aloof? \r
+  The chief were those who, from the pit of Hell \r
+Roaming to seek their prey on Earth, durst fix \r
+Their seats, long after, next the seat of God, \r
+Their altars by his altar, gods adored \r
+Among the nations round, and durst abide \r
+Jehovah thundering out of Sion, throned \r
+Between the Cherubim; yea, often placed \r
+Within his sanctuary itself their shrines, \r
+Abominations; and with cursed things \r
+His holy rites and solemn feasts profaned, \r
+And with their darkness durst affront his light. \r
+First, Moloch, horrid king, besmeared with blood \r
+Of human sacrifice, and parents' tears; \r
+Though, for the noise of drums and timbrels loud, \r
+Their children's cries unheard that passed through fire \r
+To his grim idol. Him the Ammonite \r
+Worshiped in Rabba and her watery plain, \r
+In Argob and in Basan, to the stream \r
+Of utmost Arnon. Nor content with such \r
+Audacious neighbourhood, the wisest heart \r
+Of Solomon he led by fraoud to build \r
+His temple right against the temple of God \r
+On that opprobrious hill, and made his grove \r
+The pleasant valley of Hinnom, Tophet thence \r
+And black Gehenna called, the type of Hell. \r
+Next Chemos, th' obscene dread of Moab's sons, \r
+From Aroar to Nebo and the wild \r
+Of southmost Abarim; in Hesebon \r
+And Horonaim, Seon's real, beyond \r
+The flowery dale of Sibma clad with vines, \r
+And Eleale to th' Asphaltic Pool: \r
+Peor his other name, when he enticed \r
+Israel in Sittim, on their march from Nile, \r
+To do him wanton rites, which cost them woe. \r
+Yet thence his lustful orgies he enlarged \r
+Even to that hill of scandal, by the grove \r
+Of Moloch homicide, lust hard by hate, \r
+Till good Josiah drove them thence to Hell. \r
+With these came they who, from the bordering flood \r
+Of old Euphrates to the brook that parts \r
+Egypt from Syrian ground, had general names \r
+Of Baalim and Ashtaroth--those male, \r
+These feminine. For Spirits, when they please, \r
+Can either sex assume, or both; so soft \r
+And uncompounded is their essence pure, \r
+Not tried or manacled with joint or limb, \r
+Nor founded on the brittle strength of bones, \r
+Like cumbrous flesh; but, in what shape they choose, \r
+Dilated or condensed, bright or obscure, \r
+Can execute their airy purposes, \r
+And works of love or enmity fulfil. \r
+For those the race of Israel oft forsook \r
+Their Living Strength, and unfrequented left \r
+His righteous altar, bowing lowly down \r
+To bestial gods; for which their heads as low \r
+Bowed down in battle, sunk before the spear \r
+Of despicable foes. With these in troop \r
+Came Astoreth, whom the Phoenicians called \r
+Astarte, queen of heaven, with crescent horns; \r
+To whose bright image nigntly by the moon \r
+Sidonian virgins paid their vows and songs; \r
+In Sion also not unsung, where stood \r
+Her temple on th' offensive mountain, built \r
+By that uxorious king whose heart, though large, \r
+Beguiled by fair idolatresses, fell \r
+To idols foul. Thammuz came next behind, \r
+Whose annual wound in Lebanon allured \r
+The Syrian damsels to lament his fate \r
+In amorous ditties all a summer's day, \r
+While smooth Adonis from his native rock \r
+Ran purple to the sea, supposed with blood \r
+Of Thammuz yearly wounded: the love-tale \r
+Infected Sion's daughters with like heat, \r
+Whose wanton passions in the sacred proch \r
+Ezekiel saw, when, by the vision led, \r
+His eye surveyed the dark idolatries \r
+Of alienated Judah. Next came one \r
+Who mourned in earnest, when the captive ark \r
+Maimed his brute image, head and hands lopt off, \r
+In his own temple, on the grunsel-edge, \r
+Where he fell flat and shamed his worshippers: \r
+Dagon his name, sea-monster,upward man \r
+And downward fish; yet had his temple high \r
+Reared in Azotus, dreaded through the coast \r
+Of Palestine, in Gath and Ascalon, \r
+And Accaron and Gaza's frontier bounds. \r
+Him followed Rimmon, whose delightful seat \r
+Was fair Damascus, on the fertile banks \r
+Of Abbana and Pharphar, lucid streams. \r
+He also against the house of God was bold: \r
+A leper once he lost, and gained a king-- \r
+Ahaz, his sottish conqueror, whom he drew \r
+God's altar to disparage and displace \r
+For one of Syrian mode, whereon to burn \r
+His odious offerings, and adore the gods \r
+Whom he had vanquished. After these appeared \r
+A crew who, under names of old renown-- \r
+Osiris, Isis, Orus, and their train-- \r
+With monstrous shapes and sorceries abused \r
+Fanatic Egypt and her priests to seek \r
+Their wandering gods disguised in brutish forms \r
+Rather than human. Nor did Israel scape \r
+Th' infection, when their borrowed gold composed \r
+The calf in Oreb; and the rebel king \r
+Doubled that sin in Bethel and in Dan, \r
+Likening his Maker to the grazed ox-- \r
+Jehovah, who, in one night, when he passed \r
+From Egypt marching, equalled with one stroke \r
+Both her first-born and all her bleating gods. \r
+Belial came last; than whom a Spirit more lewd \r
+Fell not from Heaven, or more gross to love \r
+Vice for itself. To him no temple stood \r
+Or altar smoked; yet who more oft than he \r
+In temples and at altars, when the priest \r
+Turns atheist, as did Eli's sons, who filled \r
+With lust and violence the house of God? \r
+In courts and palaces he also reigns, \r
+And in luxurious cities, where the noise \r
+Of riot ascends above their loftiest towers, \r
+And injury and outrage; and, when night \r
+Darkens the streets, then wander forth the sons \r
+Of Belial, flown with insolence and wine. \r
+Witness the streets of Sodom, and that night \r
+In Gibeah, when the hospitable door \r
+Exposed a matron, to avoid worse rape. \r
+  These were the prime in order and in might: \r
+The rest were long to tell; though far renowned \r
+Th' Ionian gods--of Javan's issue held \r
+Gods, yet confessed later than Heaven and Earth, \r
+Their boasted parents;--Titan, Heaven's first-born, \r
+With his enormous brood, and birthright seized \r
+By younger Saturn: he from mightier Jove, \r
+His own and Rhea's son, like measure found; \r
+So Jove usurping reigned. These, first in Crete \r
+And Ida known, thence on the snowy top \r
+Of cold Olympus ruled the middle air, \r
+Their highest heaven; or on the Delphian cliff, \r
+Or in Dodona, and through all the bounds \r
+Of Doric land; or who with Saturn old \r
+Fled over Adria to th' Hesperian fields, \r
+And o'er the Celtic roamed the utmost Isles. \r
+  All these and more came flocking; but with looks \r
+Downcast and damp; yet such wherein appeared \r
+Obscure some glimpse of joy to have found their Chief \r
+Not in despair, to have found themselves not lost \r
+In loss itself; which on his countenance cast \r
+Like doubtful hue. But he, his wonted pride \r
+Soon recollecting, with high words, that bore \r
+Semblance of worth, not substance, gently raised \r
+Their fainting courage, and dispelled their fears. \r
+Then straight commands that, at the warlike sound \r
+Of trumpets loud and clarions, be upreared \r
+His mighty standard. That proud honour claimed \r
+Azazel as his right, a Cherub tall: \r
+Who forthwith from the glittering staff unfurled \r
+Th' imperial ensign; which, full high advanced, \r
+Shone like a meteor streaming to the wind, \r
+With gems and golden lustre rich emblazed, \r
+Seraphic arms and trophies; all the while \r
+Sonorous metal blowing martial sounds: \r
+At which the universal host up-sent \r
+A shout that tore Hell's concave, and beyond \r
+Frighted the reign of Chaos and old Night. \r
+All in a moment through the gloom were seen \r
+Ten thousand banners rise into the air, \r
+With orient colours waving: with them rose \r
+A forest huge of spears; and thronging helms \r
+Appeared, and serried shields in thick array \r
+Of depth immeasurable. Anon they move \r
+In perfect phalanx to the Dorian mood \r
+Of flutes and soft recorders--such as raised \r
+To height of noblest temper heroes old \r
+Arming to battle, and instead of rage \r
+Deliberate valour breathed, firm, and unmoved \r
+With dread of death to flight or foul retreat; \r
+Nor wanting power to mitigate and swage \r
+With solemn touches troubled thoughts, and chase \r
+Anguish and doubt and fear and sorrow and pain \r
+From mortal or immortal minds. Thus they, \r
+Breathing united force with fixed thought, \r
+Moved on in silence to soft pipes that charmed \r
+Their painful steps o'er the burnt soil. And now \r
+Advanced in view they stand--a horrid front \r
+Of dreadful length and dazzling arms, in guise \r
+Of warriors old, with ordered spear and shield, \r
+Awaiting what command their mighty Chief \r
+Had to impose. He through the armed files \r
+Darts his experienced eye, and soon traverse \r
+The whole battalion views--their order due, \r
+Their visages and stature as of gods; \r
+Their number last he sums. And now his heart \r
+Distends with pride, and, hardening in his strength, \r
+Glories: for never, since created Man, \r
+Met such embodied force as, named with these, \r
+Could merit more than that small infantry \r
+Warred on by cranes--though all the giant brood \r
+Of Phlegra with th' heroic race were joined \r
+That fought at Thebes and Ilium, on each side \r
+Mixed with auxiliar gods; and what resounds \r
+In fable or romance of Uther's son, \r
+Begirt with British and Armoric knights; \r
+And all who since, baptized or infidel, \r
+Jousted in Aspramont, or Montalban, \r
+Damasco, or Marocco, or Trebisond, \r
+Or whom Biserta sent from Afric shore \r
+When Charlemain with all his peerage fell \r
+By Fontarabbia. Thus far these beyond \r
+Compare of mortal prowess, yet observed \r
+Their dread Commander. He, above the rest \r
+In shape and gesture proudly eminent, \r
+Stood like a tower. His form had yet not lost \r
+All her original brightness, nor appeared \r
+Less than Archangel ruined, and th' excess \r
+Of glory obscured: as when the sun new-risen \r
+Looks through the horizontal misty air \r
+Shorn of his beams, or, from behind the moon, \r
+In dim eclipse, disastrous twilight sheds \r
+On half the nations, and with fear of change \r
+Perplexes monarchs. Darkened so, yet shone \r
+Above them all th' Archangel: but his face \r
+Deep scars of thunder had intrenched, and care \r
+Sat on his faded cheek, but under brows \r
+Of dauntless courage, and considerate pride \r
+Waiting revenge. Cruel his eye, but cast \r
+Signs of remorse and passion, to behold \r
+The fellows of his crime, the followers rather \r
+(Far other once beheld in bliss), condemned \r
+For ever now to have their lot in pain-- \r
+Millions of Spirits for his fault amerced \r
+Of Heaven, and from eteranl splendours flung \r
+For his revolt--yet faithful how they stood, \r
+Their glory withered; as, when heaven's fire \r
+Hath scathed the forest oaks or mountain pines, \r
+With singed top their stately growth, though bare, \r
+Stands on the blasted heath. He now prepared \r
+To speak; whereat their doubled ranks they bend \r
+From wing to wing, and half enclose him round \r
+With all his peers: attention held them mute. \r
+Thrice he assayed, and thrice, in spite of scorn, \r
+Tears, such as Angels weep, burst forth: at last \r
+Words interwove with sighs found out their way:-- \r
+  "O myriads of immortal Spirits! O Powers \r
+Matchless, but with th' Almighth!--and that strife \r
+Was not inglorious, though th' event was dire, \r
+As this place testifies, and this dire change, \r
+Hateful to utter. But what power of mind, \r
+Forseeing or presaging, from the depth \r
+Of knowledge past or present, could have feared \r
+How such united force of gods, how such \r
+As stood like these, could ever know repulse? \r
+For who can yet believe, though after loss, \r
+That all these puissant legions, whose exile \r
+Hath emptied Heaven, shall fail to re-ascend, \r
+Self-raised, and repossess their native seat? \r
+For me, be witness all the host of Heaven, \r
+If counsels different, or danger shunned \r
+By me, have lost our hopes. But he who reigns \r
+Monarch in Heaven till then as one secure \r
+Sat on his throne, upheld by old repute, \r
+Consent or custom, and his regal state \r
+Put forth at full, but still his strength concealed-- \r
+Which tempted our attempt, and wrought our fall. \r
+Henceforth his might we know, and know our own, \r
+So as not either to provoke, or dread \r
+New war provoked: our better part remains \r
+To work in close design, by fraud or guile, \r
+What force effected not; that he no less \r
+At length from us may find, who overcomes \r
+By force hath overcome but half his foe. \r
+Space may produce new Worlds; whereof so rife \r
+There went a fame in Heaven that he ere long \r
+Intended to create, and therein plant \r
+A generation whom his choice regard \r
+Should favour equal to the Sons of Heaven. \r
+Thither, if but to pry, shall be perhaps \r
+Our first eruption--thither, or elsewhere; \r
+For this infernal pit shall never hold \r
+Celestial Spirits in bondage, nor th' Abyss \r
+Long under darkness cover. But these thoughts \r
+Full counsel must mature. Peace is despaired; \r
+For who can think submission? War, then, war \r
+Open or understood, must be resolved." \r
+  He spake; and, to confirm his words, outflew \r
+Millions of flaming swords, drawn from the thighs \r
+Of mighty Cherubim; the sudden blaze \r
+Far round illumined Hell. Highly they raged \r
+Against the Highest, and fierce with grasped arms \r
+Clashed on their sounding shields the din of war, \r
+Hurling defiance toward the vault of Heaven. \r
+  There stood a hill not far, whose grisly top \r
+Belched fire and rolling smoke; the rest entire \r
+Shone with a glossy scurf--undoubted sign \r
+That in his womb was hid metallic ore, \r
+The work of sulphur. Thither, winged with speed, \r
+A numerous brigade hastened: as when bands \r
+Of pioneers, with spade and pickaxe armed, \r
+Forerun the royal camp, to trench a field, \r
+Or cast a rampart. Mammon led them on-- \r
+Mammon, the least erected Spirit that fell \r
+From Heaven; for even in Heaven his looks and thoughts \r
+Were always downward bent, admiring more \r
+The riches of heaven's pavement, trodden gold, \r
+Than aught divine or holy else enjoyed \r
+In vision beatific. By him first \r
+Men also, and by his suggestion taught, \r
+Ransacked the centre, and with impious hands \r
+Rifled the bowels of their mother Earth \r
+For treasures better hid. Soon had his crew \r
+Opened into the hill a spacious wound, \r
+And digged out ribs of gold. Let none admire \r
+That riches grow in Hell; that soil may best \r
+Deserve the precious bane. And here let those \r
+Who boast in mortal things, and wondering tell \r
+Of Babel, and the works of Memphian kings, \r
+Learn how their greatest monuments of fame \r
+And strength, and art, are easily outdone \r
+By Spirits reprobate, and in an hour \r
+What in an age they, with incessant toil \r
+And hands innumerable, scarce perform. \r
+Nigh on the plain, in many cells prepared, \r
+That underneath had veins of liquid fire \r
+Sluiced from the lake, a second multitude \r
+With wondrous art founded the massy ore, \r
+Severing each kind, and scummed the bullion-dross. \r
+A third as soon had formed within the ground \r
+A various mould, and from the boiling cells \r
+By strange conveyance filled each hollow nook; \r
+As in an organ, from one blast of wind, \r
+To many a row of pipes the sound-board breathes. \r
+Anon out of the earth a fabric huge \r
+Rose like an exhalation, with the sound \r
+Of dulcet symphonies and voices sweet-- \r
+Built like a temple, where pilasters round \r
+Were set, and Doric pillars overlaid \r
+With golden architrave; nor did there want \r
+Cornice or frieze, with bossy sculptures graven; \r
+The roof was fretted gold. Not Babylon \r
+Nor great Alcairo such magnificence \r
+Equalled in all their glories, to enshrine \r
+Belus or Serapis their gods, or seat \r
+Their kings, when Egypt with Assyria strove \r
+In wealth and luxury. Th' ascending pile \r
+Stood fixed her stately height, and straight the doors, \r
+Opening their brazen folds, discover, wide \r
+Within, her ample spaces o'er the smooth \r
+And level pavement: from the arched roof, \r
+Pendent by subtle magic, many a row \r
+Of starry lamps and blazing cressets, fed \r
+With naptha and asphaltus, yielded light \r
+As from a sky. The hasty multitude \r
+Admiring entered; and the work some praise, \r
+And some the architect. His hand was known \r
+In Heaven by many a towered structure high, \r
+Where sceptred Angels held their residence, \r
+And sat as Princes, whom the supreme King \r
+Exalted to such power, and gave to rule, \r
+Each in his Hierarchy, the Orders bright. \r
+Nor was his name unheard or unadored \r
+In ancient Greece; and in Ausonian land \r
+Men called him Mulciber; and how he fell \r
+From Heaven they fabled, thrown by angry Jove \r
+Sheer o'er the crystal battlements: from morn \r
+To noon he fell, from noon to dewy eve, \r
+A summer's day, and with the setting sun \r
+Dropt from the zenith, like a falling star, \r
+On Lemnos, th' Aegaean isle. Thus they relate, \r
+Erring; for he with this rebellious rout \r
+Fell long before; nor aught aviled him now \r
+To have built in Heaven high towers; nor did he scape \r
+By all his engines, but was headlong sent, \r
+With his industrious crew, to build in Hell. \r
+  Meanwhile the winged Heralds, by command \r
+Of sovereign power, with awful ceremony \r
+And trumpet's sound, throughout the host proclaim \r
+A solemn council forthwith to be held \r
+At Pandemonium, the high capital \r
+Of Satan and his peers. Their summons called \r
+From every band and squared regiment \r
+By place or choice the worthiest: they anon \r
+With hundreds and with thousands trooping came \r
+Attended. All access was thronged; the gates \r
+And porches wide, but chief the spacious hall \r
+(Though like a covered field, where champions bold \r
+Wont ride in armed, and at the Soldan's chair \r
+Defied the best of Paynim chivalry \r
+To mortal combat, or career with lance), \r
+Thick swarmed, both on the ground and in the air, \r
+Brushed with the hiss of rustling wings. As bees \r
+In spring-time, when the Sun with Taurus rides. \r
+Pour forth their populous youth about the hive \r
+In clusters; they among fresh dews and flowers \r
+Fly to and fro, or on the smoothed plank, \r
+The suburb of their straw-built citadel, \r
+New rubbed with balm, expatiate, and confer \r
+Their state-affairs: so thick the airy crowd \r
+Swarmed and were straitened; till, the signal given, \r
+Behold a wonder! They but now who seemed \r
+In bigness to surpass Earth's giant sons, \r
+Now less than smallest dwarfs, in narrow room \r
+Throng numberless--like that pygmean race \r
+Beyond the Indian mount; or faery elves, \r
+Whose midnight revels, by a forest-side \r
+Or fountain, some belated peasant sees, \r
+Or dreams he sees, while overhead the Moon \r
+Sits arbitress, and nearer to the Earth \r
+Wheels her pale course: they, on their mirth and dance \r
+Intent, with jocund music charm his ear; \r
+At once with joy and fear his heart rebounds. \r
+Thus incorporeal Spirits to smallest forms \r
+Reduced their shapes immense, and were at large, \r
+Though without number still, amidst the hall \r
+Of that infernal court. But far within, \r
+And in their own dimensions like themselves, \r
+The great Seraphic Lords and Cherubim \r
+In close recess and secret conclave sat, \r
+A thousand demi-gods on golden seats, \r
+Frequent and full. After short silence then, \r
+And summons read, the great consult began. \r
\r
\r
\r
+Book II                                                          \r
\r
+  \r
+High on a throne of royal state, which far \r
+Outshone the wealth or Ormus and of Ind, \r
+Or where the gorgeous East with richest hand \r
+Showers on her kings barbaric pearl and gold, \r
+Satan exalted sat, by merit raised \r
+To that bad eminence; and, from despair \r
+Thus high uplifted beyond hope, aspires \r
+Beyond thus high, insatiate to pursue \r
+Vain war with Heaven; and, by success untaught, \r
+His proud imaginations thus displayed:-- \r
+  "Powers and Dominions, Deities of Heaven!-- \r
+For, since no deep within her gulf can hold \r
+Immortal vigour, though oppressed and fallen, \r
+I give not Heaven for lost: from this descent \r
+Celestial Virtues rising will appear \r
+More glorious and more dread than from no fall, \r
+And trust themselves to fear no second fate!-- \r
+Me though just right, and the fixed laws of Heaven, \r
+Did first create your leader--next, free choice \r
+With what besides in council or in fight \r
+Hath been achieved of merit--yet this loss, \r
+Thus far at least recovered, hath much more \r
+Established in a safe, unenvied throne, \r
+Yielded with full consent. The happier state \r
+In Heaven, which follows dignity, might draw \r
+Envy from each inferior; but who here \r
+Will envy whom the highest place exposes \r
+Foremost to stand against the Thunderer's aim \r
+Your bulwark, and condemns to greatest share \r
+Of endless pain? Where there is, then, no good \r
+For which to strive, no strife can grow up there \r
+From faction: for none sure will claim in Hell \r
+Precedence; none whose portion is so small \r
+Of present pain that with ambitious mind \r
+Will covet more! With this advantage, then, \r
+To union, and firm faith, and firm accord, \r
+More than can be in Heaven, we now return \r
+To claim our just inheritance of old, \r
+Surer to prosper than prosperity \r
+Could have assured us; and by what best way, \r
+Whether of open war or covert guile, \r
+We now debate. Who can advise may speak." \r
+  He ceased; and next him Moloch, sceptred king, \r
+Stood up--the strongest and the fiercest Spirit \r
+That fought in Heaven, now fiercer by despair. \r
+His trust was with th' Eternal to be deemed \r
+Equal in strength, and rather than be less \r
+Cared not to be at all; with that care lost \r
+Went all his fear: of God, or Hell, or worse, \r
+He recked not, and these words thereafter spake:-- \r
+  "My sentence is for open war. Of wiles, \r
+More unexpert, I boast not: them let those \r
+Contrive who need, or when they need; not now. \r
+For, while they sit contriving, shall the rest-- \r
+Millions that stand in arms, and longing wait \r
+The signal to ascend--sit lingering here, \r
+Heaven's fugitives, and for their dwelling-place \r
+Accept this dark opprobrious den of shame, \r
+The prison of his ryranny who reigns \r
+By our delay? No! let us rather choose, \r
+Armed with Hell-flames and fury, all at once \r
+O'er Heaven's high towers to force resistless way, \r
+Turning our tortures into horrid arms \r
+Against the Torturer; when, to meet the noise \r
+Of his almighty engine, he shall hear \r
+Infernal thunder, and, for lightning, see \r
+Black fire and horror shot with equal rage \r
+Among his Angels, and his throne itself \r
+Mixed with Tartarean sulphur and strange fire, \r
+His own invented torments. But perhaps \r
+The way seems difficult, and steep to scale \r
+With upright wing against a higher foe! \r
+Let such bethink them, if the sleepy drench \r
+Of that forgetful lake benumb not still, \r
+That in our porper motion we ascend \r
+Up to our native seat; descent and fall \r
+To us is adverse. Who but felt of late, \r
+When the fierce foe hung on our broken rear \r
+Insulting, and pursued us through the Deep, \r
+With what compulsion and laborious flight \r
+We sunk thus low? Th' ascent is easy, then; \r
+Th' event is feared! Should we again provoke \r
+Our stronger, some worse way his wrath may find \r
+To our destruction, if there be in Hell \r
+Fear to be worse destroyed! What can be worse \r
+Than to dwell here, driven out from bliss, condemned \r
+In this abhorred deep to utter woe! \r
+Where pain of unextinguishable fire \r
+Must exercise us without hope of end \r
+The vassals of his anger, when the scourge \r
+Inexorably, and the torturing hour, \r
+Calls us to penance? More destroyed than thus, \r
+We should be quite abolished, and expire. \r
+What fear we then? what doubt we to incense \r
+His utmost ire? which, to the height enraged, \r
+Will either quite consume us, and reduce \r
+To nothing this essential--happier far \r
+Than miserable to have eternal being!-- \r
+Or, if our substance be indeed divine, \r
+And cannot cease to be, we are at worst \r
+On this side nothing; and by proof we feel \r
+Our power sufficient to disturb his Heaven, \r
+And with perpetual inroads to alarm, \r
+Though inaccessible, his fatal throne: \r
+Which, if not victory, is yet revenge." \r
+  He ended frowning, and his look denounced \r
+Desperate revenge, and battle dangerous \r
+To less than gods. On th' other side up rose \r
+Belial, in act more graceful and humane. \r
+A fairer person lost not Heaven; he seemed \r
+For dignity composed, and high exploit. \r
+But all was false and hollow; though his tongue \r
+Dropped manna, and could make the worse appear \r
+The better reason, to perplex and dash \r
+Maturest counsels: for his thoughts were low-- \r
+ To vice industrious, but to nobler deeds \r
+Timorous and slothful. Yet he pleased the ear, \r
+And with persuasive accent thus began:-- \r
+  "I should be much for open war, O Peers, \r
+As not behind in hate, if what was urged \r
+Main reason to persuade immediate war \r
+Did not dissuade me most, and seem to cast \r
+Ominous conjecture on the whole success; \r
+When he who most excels in fact of arms, \r
+In what he counsels and in what excels \r
+Mistrustful, grounds his courage on despair \r
+And utter dissolution, as the scope \r
+Of all his aim, after some dire revenge. \r
+First, what revenge? The towers of Heaven are filled \r
+With armed watch, that render all access \r
+Impregnable: oft on the bodering Deep \r
+Encamp their legions, or with obscure wing \r
+Scout far and wide into the realm of Night, \r
+Scorning surprise. Or, could we break our way \r
+By force, and at our heels all Hell should rise \r
+With blackest insurrection to confound \r
+Heaven's purest light, yet our great Enemy, \r
+All incorruptible, would on his throne \r
+Sit unpolluted, and th' ethereal mould, \r
+Incapable of stain, would soon expel \r
+Her mischief, and purge off the baser fire, \r
+Victorious. Thus repulsed, our final hope \r
+Is flat despair: we must exasperate \r
+Th' Almighty Victor to spend all his rage; \r
+And that must end us; that must be our cure-- \r
+To be no more. Sad cure! for who would lose, \r
+Though full of pain, this intellectual being, \r
+Those thoughts that wander through eternity, \r
+To perish rather, swallowed up and lost \r
+In the wide womb of uncreated Night, \r
+Devoid of sense and motion? And who knows, \r
+Let this be good, whether our angry Foe \r
+Can give it, or will ever? How he can \r
+Is doubtful; that he never will is sure. \r
+Will he, so wise, let loose at once his ire, \r
+Belike through impotence or unaware, \r
+To give his enemies their wish, and end \r
+Them in his anger whom his anger saves \r
+To punish endless? 'Wherefore cease we, then?' \r
+Say they who counsel war; 'we are decreed, \r
+Reserved, and destined to eternal woe; \r
+Whatever doing, what can we suffer more, \r
+What can we suffer worse?' Is this, then, worst-- \r
+Thus sitting, thus consulting, thus in arms? \r
+What when we fled amain, pursued and struck \r
+With Heaven's afflicting thunder, and besought \r
+The Deep to shelter us? This Hell then seemed \r
+A refuge from those wounds. Or when we lay \r
+Chained on the burning lake? That sure was worse. \r
+What if the breath that kindled those grim fires, \r
+Awaked, should blow them into sevenfold rage, \r
+And plunge us in the flames; or from above \r
+Should intermitted vengeance arm again \r
+His red right hand to plague us? What if all \r
+Her stores were opened, and this firmament \r
+Of Hell should spout her cataracts of fire, \r
+Impendent horrors, threatening hideous fall \r
+One day upon our heads; while we perhaps, \r
+Designing or exhorting glorious war, \r
+Caught in a fiery tempest, shall be hurled, \r
+Each on his rock transfixed, the sport and prey \r
+Or racking whirlwinds, or for ever sunk \r
+Under yon boiling ocean, wrapt in chains, \r
+There to converse with everlasting groans, \r
+Unrespited, unpitied, unreprieved, \r
+Ages of hopeless end? This would be worse. \r
+War, therefore, open or concealed, alike \r
+My voice dissuades; for what can force or guile \r
+With him, or who deceive his mind, whose eye \r
+Views all things at one view? He from Heaven's height \r
+All these our motions vain sees and derides, \r
+Not more almighty to resist our might \r
+Than wise to frustrate all our plots and wiles. \r
+Shall we, then, live thus vile--the race of Heaven \r
+Thus trampled, thus expelled, to suffer here \r
+Chains and these torments? Better these than worse, \r
+By my advice; since fate inevitable \r
+Subdues us, and omnipotent decree, \r
+The Victor's will. To suffer, as to do, \r
+Our strength is equal; nor the law unjust \r
+That so ordains. This was at first resolved, \r
+If we were wise, against so great a foe \r
+Contending, and so doubtful what might fall. \r
+I laugh when those who at the spear are bold \r
+And venturous, if that fail them, shrink, and fear \r
+What yet they know must follow--to endure \r
+Exile, or igominy, or bonds, or pain, \r
+The sentence of their Conqueror. This is now \r
+Our doom; which if we can sustain and bear, \r
+Our Supreme Foe in time may much remit \r
+His anger, and perhaps, thus far removed, \r
+Not mind us not offending, satisfied \r
+With what is punished; whence these raging fires \r
+Will slacken, if his breath stir not their flames. \r
+Our purer essence then will overcome \r
+Their noxious vapour; or, inured, not feel; \r
+Or, changed at length, and to the place conformed \r
+In temper and in nature, will receive \r
+Familiar the fierce heat; and, void of pain, \r
+This horror will grow mild, this darkness light; \r
+Besides what hope the never-ending flight \r
+Of future days may bring, what chance, what change \r
+Worth waiting--since our present lot appears \r
+For happy though but ill, for ill not worst, \r
+If we procure not to ourselves more woe." \r
+  Thus Belial, with words clothed in reason's garb, \r
+Counselled ignoble ease and peaceful sloth, \r
+Not peace; and after him thus Mammon spake:-- \r
+  "Either to disenthrone the King of Heaven \r
+We war, if war be best, or to regain \r
+Our own right lost. Him to unthrone we then \r
+May hope, when everlasting Fate shall yield \r
+To fickle Chance, and Chaos judge the strife. \r
+The former, vain to hope, argues as vain \r
+The latter; for what place can be for us \r
+Within Heaven's bound, unless Heaven's Lord supreme \r
+We overpower? Suppose he should relent \r
+And publish grace to all, on promise made \r
+Of new subjection; with what eyes could we \r
+Stand in his presence humble, and receive \r
+Strict laws imposed, to celebrate his throne \r
+With warbled hyms, and to his Godhead sing \r
+Forced hallelujahs, while he lordly sits \r
+Our envied sovereign, and his altar breathes \r
+Ambrosial odours and ambrosial flowers, \r
+Our servile offerings? This must be our task \r
+In Heaven, this our delight. How wearisome \r
+Eternity so spent in worship paid \r
+To whom we hate! Let us not then pursue, \r
+By force impossible, by leave obtained \r
+Unacceptable, though in Heaven, our state \r
+Of splendid vassalage; but rather seek \r
+Our own good from ourselves, and from our own \r
+Live to ourselves, though in this vast recess, \r
+Free and to none accountable, preferring \r
+Hard liberty before the easy yoke \r
+Of servile pomp. Our greatness will appear \r
+Then most conspicuous when great things of small, \r
+Useful of hurtful, prosperous of adverse, \r
+We can create, and in what place soe'er \r
+Thrive under evil, and work ease out of pain \r
+Through labour and endurance. This deep world \r
+Of darkness do we dread? How oft amidst \r
+Thick clouds and dark doth Heaven's all-ruling Sire \r
+Choose to reside, his glory unobscured, \r
+And with the majesty of darkness round \r
+Covers his throne, from whence deep thunders roar. \r
+Mustering their rage, and Heaven resembles Hell! \r
+As he our darkness, cannot we his light \r
+Imitate when we please? This desert soil \r
+Wants not her hidden lustre, gems and gold; \r
+Nor want we skill or art from whence to raise \r
+Magnificence; and what can Heaven show more? \r
+Our torments also may, in length of time, \r
+Become our elements, these piercing fires \r
+As soft as now severe, our temper changed \r
+Into their temper; which must needs remove \r
+The sensible of pain. All things invite \r
+To peaceful counsels, and the settled state \r
+Of order, how in safety best we may \r
+Compose our present evils, with regard \r
+Of what we are and where, dismissing quite \r
+All thoughts of war. Ye have what I advise." \r
+  He scarce had finished, when such murmur filled \r
+Th' assembly as when hollow rocks retain \r
+The sound of blustering winds, which all night long \r
+Had roused the sea, now with hoarse cadence lull \r
+Seafaring men o'erwatched, whose bark by chance \r
+Or pinnace, anchors in a craggy bay \r
+After the tempest. Such applause was heard \r
+As Mammon ended, and his sentence pleased, \r
+Advising peace: for such another field \r
+They dreaded worse than Hell; so much the fear \r
+Of thunder and the sword of Michael \r
+Wrought still within them; and no less desire \r
+To found this nether empire, which might rise, \r
+By policy and long process of time, \r
+In emulation opposite to Heaven. \r
+Which when Beelzebub perceived--than whom, \r
+Satan except, none higher sat--with grave \r
+Aspect he rose, and in his rising seemed \r
+A pillar of state. Deep on his front engraven \r
+Deliberation sat, and public care; \r
+And princely counsel in his face yet shone, \r
+Majestic, though in ruin. Sage he stood \r
+With Atlantean shoulders, fit to bear \r
+The weight of mightiest monarchies; his look \r
+Drew audience and attention still as night \r
+Or summer's noontide air, while thus he spake:-- \r
+  "Thrones and Imperial Powers, Offspring of Heaven, \r
+Ethereal Virtues! or these titles now \r
+Must we renounce, and, changing style, be called \r
+Princes of Hell? for so the popular vote \r
+Inclines--here to continue, and build up here \r
+A growing empire; doubtless! while we dream, \r
+And know not that the King of Heaven hath doomed \r
+This place our dungeon, not our safe retreat \r
+Beyond his potent arm, to live exempt \r
+From Heaven's high jurisdiction, in new league \r
+Banded against his throne, but to remain \r
+In strictest bondage, though thus far removed, \r
+Under th' inevitable curb, reserved \r
+His captive multitude. For he, to be sure, \r
+In height or depth, still first and last will reign \r
+Sole king, and of his kingdom lose no part \r
+By our revolt, but over Hell extend \r
+His empire, and with iron sceptre rule \r
+Us here, as with his golden those in Heaven. \r
+What sit we then projecting peace and war? \r
+War hath determined us and foiled with loss \r
+Irreparable; terms of peace yet none \r
+Vouchsafed or sought; for what peace will be given \r
+To us enslaved, but custody severe, \r
+And stripes and arbitrary punishment \r
+Inflicted? and what peace can we return, \r
+But, to our power, hostility and hate, \r
+Untamed reluctance, and revenge, though slow, \r
+Yet ever plotting how the Conqueror least \r
+May reap his conquest, and may least rejoice \r
+In doing what we most in suffering feel? \r
+Nor will occasion want, nor shall we need \r
+With dangerous expedition to invade \r
+Heaven, whose high walls fear no assault or siege, \r
+Or ambush from the Deep. What if we find \r
+Some easier enterprise? There is a place \r
+(If ancient and prophetic fame in Heaven \r
+Err not)--another World, the happy seat \r
+Of some new race, called Man, about this time \r
+To be created like to us, though less \r
+In power and excellence, but favoured more \r
+Of him who rules above; so was his will \r
+Pronounced among the Gods, and by an oath \r
+That shook Heaven's whole circumference confirmed. \r
+Thither let us bend all our thoughts, to learn \r
+What creatures there inhabit, of what mould \r
+Or substance, how endued, and what their power \r
+And where their weakness: how attempted best, \r
+By force of subtlety. Though Heaven be shut, \r
+And Heaven's high Arbitrator sit secure \r
+In his own strength, this place may lie exposed, \r
+The utmost border of his kingdom, left \r
+To their defence who hold it: here, perhaps, \r
+Some advantageous act may be achieved \r
+By sudden onset--either with Hell-fire \r
+To waste his whole creation, or possess \r
+All as our own, and drive, as we were driven, \r
+The puny habitants; or, if not drive, \r
+Seduce them to our party, that their God \r
+May prove their foe, and with repenting hand \r
+Abolish his own works. This would surpass \r
+Common revenge, and interrupt his joy \r
+In our confusion, and our joy upraise \r
+In his disturbance; when his darling sons, \r
+Hurled headlong to partake with us, shall curse \r
+Their frail original, and faded bliss-- \r
+Faded so soon! Advise if this be worth \r
+Attempting, or to sit in darkness here \r
+Hatching vain empires." Thus beelzebub \r
+Pleaded his devilish counsel--first devised \r
+By Satan, and in part proposed: for whence, \r
+But from the author of all ill, could spring \r
+So deep a malice, to confound the race \r
+Of mankind in one root, and Earth with Hell \r
+To mingle and involve, done all to spite \r
+The great Creator? But their spite still serves \r
+His glory to augment. The bold design \r
+Pleased highly those infernal States, and joy \r
+Sparkled in all their eyes: with full assent \r
+They vote: whereat his speech he thus renews:-- \r
+"Well have ye judged, well ended long debate, \r
+Synod of Gods, and, like to what ye are, \r
+Great things resolved, which from the lowest deep \r
+Will once more lift us up, in spite of fate, \r
+Nearer our ancient seat--perhaps in view \r
+Of those bright confines, whence, with neighbouring arms, \r
+And opportune excursion, we may chance \r
+Re-enter Heaven; or else in some mild zone \r
+Dwell, not unvisited of Heaven's fair light, \r
+Secure, and at the brightening orient beam \r
+Purge off this gloom: the soft delicious air, \r
+To heal the scar of these corrosive fires, \r
+Shall breathe her balm. But, first, whom shall we send \r
+In search of this new World? whom shall we find \r
+Sufficient? who shall tempt with wandering feet \r
+The dark, unbottomed, infinite Abyss, \r
+And through the palpable obscure find out \r
+His uncouth way, or spread his airy flight, \r
+Upborne with indefatigable wings \r
+Over the vast abrupt, ere he arrive \r
+The happy Isle? What strength, what art, can then \r
+Suffice, or what evasion bear him safe, \r
+Through the strict senteries and stations thick \r
+Of Angels watching round? Here he had need \r
+All circumspection: and we now no less \r
+Choice in our suffrage; for on whom we send \r
+The weight of all, and our last hope, relies." \r
+  This said, he sat; and expectation held \r
+His look suspense, awaiting who appeared \r
+To second, or oppose, or undertake \r
+The perilous attempt. But all sat mute, \r
+Pondering the danger with deep thoughts; and each \r
+In other's countenance read his own dismay, \r
+Astonished. None among the choice and prime \r
+Of those Heaven-warring champions could be found \r
+So hardy as to proffer or accept, \r
+Alone, the dreadful voyage; till, at last, \r
+Satan, whom now transcendent glory raised \r
+Above his fellows, with monarchal pride \r
+Conscious of highest worth, unmoved thus spake:-- \r
+  "O Progeny of Heaven! Empyreal Thrones! \r
+With reason hath deep silence and demur \r
+Seized us, though undismayed. Long is the way \r
+And hard, that out of Hell leads up to light. \r
+Our prison strong, this huge convex of fire, \r
+Outrageous to devour, immures us round \r
+Ninefold; and gates of burning adamant, \r
+Barred over us, prohibit all egress. \r
+These passed, if any pass, the void profound \r
+Of unessential Night receives him next, \r
+Wide-gaping, and with utter loss of being \r
+Threatens him, plunged in that abortive gulf. \r
+If thence he scape, into whatever world, \r
+Or unknown region, what remains him less \r
+Than unknown dangers, and as hard escape? \r
+But I should ill become this throne, O Peers, \r
+And this imperial sovereignty, adorned \r
+With splendour, armed with power, if aught proposed \r
+And judged of public moment in the shape \r
+Of difficulty or danger, could deter \r
+Me from attempting. Wherefore do I assume \r
+These royalties, and not refuse to reign, \r
+Refusing to accept as great a share \r
+Of hazard as of honour, due alike \r
+To him who reigns, and so much to him due \r
+Of hazard more as he above the rest \r
+High honoured sits? Go, therefore, mighty Powers, \r
+Terror of Heaven, though fallen; intend at home, \r
+While here shall be our home, what best may ease \r
+The present misery, and render Hell \r
+More tolerable; if there be cure or charm \r
+To respite, or deceive, or slack the pain \r
+Of this ill mansion: intermit no watch \r
+Against a wakeful foe, while I abroad \r
+Through all the coasts of dark destruction seek \r
+Deliverance for us all. This enterprise \r
+None shall partake with me." Thus saying, rose \r
+The Monarch, and prevented all reply; \r
+Prudent lest, from his resolution raised, \r
+Others among the chief might offer now, \r
+Certain to be refused, what erst they feared, \r
+And, so refused, might in opinion stand \r
+His rivals, winning cheap the high repute \r
+Which he through hazard huge must earn. But they \r
+Dreaded not more th' adventure than his voice \r
+Forbidding; and at once with him they rose. \r
+Their rising all at once was as the sound \r
+Of thunder heard remote. Towards him they bend \r
+With awful reverence prone, and as a God \r
+Extol him equal to the Highest in Heaven. \r
+Nor failed they to express how much they praised \r
+That for the general safety he despised \r
+His own: for neither do the Spirits damned \r
+Lose all their virtue; lest bad men should boast \r
+Their specious deeds on earth, which glory excites, \r
+Or close ambition varnished o'er with zeal. \r
+  Thus they their doubtful consultations dark \r
+Ended, rejoicing in their matchless Chief: \r
+As, when from mountain-tops the dusky clouds \r
+Ascending, while the north wind sleeps, o'erspread \r
+Heaven's cheerful face, the louring element \r
+Scowls o'er the darkened landscape snow or shower, \r
+If chance the radiant sun, with farewell sweet, \r
+Extend his evening beam, the fields revive, \r
+The birds their notes renew, and bleating herds \r
+Attest their joy, that hill and valley rings. \r
+O shame to men! Devil with devil damned \r
+Firm concord holds; men only disagree \r
+Of creatures rational, though under hope \r
+Of heavenly grace, and, God proclaiming peace, \r
+Yet live in hatred, enmity, and strife \r
+Among themselves, and levy cruel wars \r
+Wasting the earth, each other to destroy: \r
+As if (which might induce us to accord) \r
+Man had not hellish foes enow besides, \r
+That day and night for his destruction wait! \r
+  The Stygian council thus dissolved; and forth \r
+In order came the grand infernal Peers: \r
+Midst came their mighty Paramount, and seemed \r
+Alone th' antagonist of Heaven, nor less \r
+Than Hell's dread Emperor, with pomp supreme, \r
+And god-like imitated state: him round \r
+A globe of fiery Seraphim enclosed \r
+With bright emblazonry, and horrent arms. \r
+Then of their session ended they bid cry \r
+With trumpet's regal sound the great result: \r
+Toward the four winds four speedy Cherubim \r
+Put to their mouths the sounding alchemy, \r
+By herald's voice explained; the hollow Abyss \r
+Heard far adn wide, and all the host of Hell \r
+With deafening shout returned them loud acclaim. \r
+Thence more at ease their minds, and somewhat raised \r
+By false presumptuous hope, the ranged Powers \r
+Disband; and, wandering, each his several way \r
+Pursues, as inclination or sad choice \r
+Leads him perplexed, where he may likeliest find \r
+Truce to his restless thoughts, and entertain \r
+The irksome hours, till his great Chief return. \r
+Part on the plain, or in the air sublime, \r
+Upon the wing or in swift race contend, \r
+As at th' Olympian games or Pythian fields; \r
+Part curb their fiery steeds, or shun the goal \r
+With rapid wheels, or fronted brigades form: \r
+As when, to warn proud cities, war appears \r
+Waged in the troubled sky, and armies rush \r
+To battle in the clouds; before each van \r
+Prick forth the airy knights, and couch their spears, \r
+Till thickest legions close; with feats of arms \r
+From either end of heaven the welkin burns. \r
+Others, with vast Typhoean rage, more fell, \r
+Rend up both rocks and hills, and ride the air \r
+In whirlwind; Hell scarce holds the wild uproar:-- \r
+As when Alcides, from Oechalia crowned \r
+With conquest, felt th' envenomed robe, and tore \r
+Through pain up by the roots Thessalian pines, \r
+And Lichas from the top of Oeta threw \r
+Into th' Euboic sea. Others, more mild, \r
+Retreated in a silent valley, sing \r
+With notes angelical to many a harp \r
+Their own heroic deeds, and hapless fall \r
+By doom of battle, and complain that Fate \r
+Free Virtue should enthrall to Force or Chance. \r
+Their song was partial; but the harmony \r
+(What could it less when Spirits immortal sing?) \r
+Suspended Hell, and took with ravishment \r
+The thronging audience. In discourse more sweet \r
+(For Eloquence the Soul, Song charms the Sense) \r
+Others apart sat on a hill retired, \r
+In thoughts more elevate, and reasoned high \r
+Of Providence, Foreknowledge, Will, and Fate-- \r
+Fixed fate, free will, foreknowledge absolute, \r
+And found no end, in wandering mazes lost. \r
+Of good and evil much they argued then, \r
+Of happiness and final misery, \r
+Passion and apathy, and glory and shame: \r
+Vain wisdom all, and false philosophy!-- \r
+Yet, with a pleasing sorcery, could charm \r
+Pain for a while or anguish, and excite \r
+Fallacious hope, or arm th' obdured breast \r
+With stubborn patience as with triple steel. \r
+Another part, in squadrons and gross bands, \r
+On bold adventure to discover wide \r
+That dismal world, if any clime perhaps \r
+Might yield them easier habitation, bend \r
+Four ways their flying march, along the banks \r
+Of four infernal rivers, that disgorge \r
+Into the burning lake their baleful streams-- \r
+Abhorred Styx, the flood of deadly hate; \r
+Sad Acheron of sorrow, black and deep; \r
+Cocytus, named of lamentation loud \r
+Heard on the rueful stream; fierce Phlegeton, \r
+Whose waves of torrent fire inflame with rage. \r
+Far off from these, a slow and silent stream, \r
+Lethe, the river of oblivion, rolls \r
+Her watery labyrinth, whereof who drinks \r
+Forthwith his former state and being forgets-- \r
+Forgets both joy and grief, pleasure and pain. \r
+Beyond this flood a frozen continent \r
+Lies dark and wild, beat with perpetual storms \r
+Of whirlwind and dire hail, which on firm land \r
+Thaws not, but gathers heap, and ruin seems \r
+Of ancient pile; all else deep snow and ice, \r
+A gulf profound as that Serbonian bog \r
+Betwixt Damiata and Mount Casius old, \r
+Where armies whole have sunk: the parching air \r
+Burns frore, and cold performs th' effect of fire. \r
+Thither, by harpy-footed Furies haled, \r
+At certain revolutions all the damned \r
+Are brought; and feel by turns the bitter change \r
+Of fierce extremes, extremes by change more fierce, \r
+From beds of raging fire to starve in ice \r
+Their soft ethereal warmth, and there to pine \r
+Immovable, infixed, and frozen round \r
+Periods of time,--thence hurried back to fire. \r
+They ferry over this Lethean sound \r
+Both to and fro, their sorrow to augment, \r
+And wish and struggle, as they pass, to reach \r
+The tempting stream, with one small drop to lose \r
+In sweet forgetfulness all pain and woe, \r
+All in one moment, and so near the brink; \r
+But Fate withstands, and, to oppose th' attempt, \r
+Medusa with Gorgonian terror guards \r
+The ford, and of itself the water flies \r
+All taste of living wight, as once it fled \r
+The lip of Tantalus. Thus roving on \r
+In confused march forlorn, th' adventurous bands, \r
+With shuddering horror pale, and eyes aghast, \r
+Viewed first their lamentable lot, and found \r
+No rest. Through many a dark and dreary vale \r
+They passed, and many a region dolorous, \r
+O'er many a frozen, many a fiery alp, \r
+Rocks, caves, lakes, fens, bogs, dens, and shades of death-- \r
+A universe of death, which God by curse \r
+Created evil, for evil only good; \r
+Where all life dies, death lives, and Nature breeds, \r
+Perverse, all monstrous, all prodigious things, \r
+Obominable, inutterable, and worse \r
+Than fables yet have feigned or fear conceived, \r
+Gorgons, and Hydras, and Chimeras dire. \r
+  Meanwhile the Adversary of God and Man, \r
+Satan, with thoughts inflamed of highest design, \r
+Puts on swift wings, and toward the gates of Hell \r
+Explores his solitary flight: sometimes \r
+He scours the right hand coast, sometimes the left; \r
+Now shaves with level wing the deep, then soars \r
+Up to the fiery concave towering high. \r
+As when far off at sea a fleet descried \r
+Hangs in the clouds, by equinoctial winds \r
+Close sailing from Bengala, or the isles \r
+Of Ternate and Tidore, whence merchants bring \r
+Their spicy drugs; they on the trading flood, \r
+Through the wide Ethiopian to the Cape, \r
+Ply stemming nightly toward the pole: so seemed \r
+Far off the flying Fiend. At last appear \r
+Hell-bounds, high reaching to the horrid roof, \r
+And thrice threefold the gates; three folds were brass, \r
+Three iron, three of adamantine rock, \r
+Impenetrable, impaled with circling fire, \r
+Yet unconsumed. Before the gates there sat \r
+On either side a formidable Shape. \r
+The one seemed woman to the waist, and fair, \r
+But ended foul in many a scaly fold, \r
+Voluminous and vast--a serpent armed \r
+With mortal sting. About her middle round \r
+A cry of Hell-hounds never-ceasing barked \r
+With wide Cerberean mouths full loud, and rung \r
+A hideous peal; yet, when they list, would creep, \r
+If aught disturbed their noise, into her womb, \r
+And kennel there; yet there still barked and howled \r
+Within unseen. Far less abhorred than these \r
+Vexed Scylla, bathing in the sea that parts \r
+Calabria from the hoarse Trinacrian shore; \r
+Nor uglier follow the night-hag, when, called \r
+In secret, riding through the air she comes, \r
+Lured with the smell of infant blood, to dance \r
+With Lapland witches, while the labouring moon \r
+Eclipses at their charms. The other Shape-- \r
+If shape it might be called that shape had none \r
+Distinguishable in member, joint, or limb; \r
+Or substance might be called that shadow seemed, \r
+For each seemed either--black it stood as Night, \r
+Fierce as ten Furies, terrible as Hell, \r
+And shook a dreadful dart: what seemed his head \r
+The likeness of a kingly crown had on. \r
+Satan was now at hand, and from his seat \r
+The monster moving onward came as fast \r
+With horrid strides; Hell trembled as he strode. \r
+Th' undaunted Fiend what this might be admired-- \r
+Admired, not feared (God and his Son except, \r
+Created thing naught valued he nor shunned), \r
+And with disdainful look thus first began:-- \r
+  "Whence and what art thou, execrable Shape, \r
+That dar'st, though grim and terrible, advance \r
+Thy miscreated front athwart my way \r
+To yonder gates? Through them I mean to pass, \r
+That be assured, without leave asked of thee. \r
+Retire; or taste thy folly, and learn by proof, \r
+Hell-born, not to contend with Spirits of Heaven." \r
+  To whom the Goblin, full of wrath, replied:-- \r
+"Art thou that traitor Angel? art thou he, \r
+Who first broke peace in Heaven and faith, till then \r
+Unbroken, and in proud rebellious arms \r
+Drew after him the third part of Heaven's sons, \r
+Conjured against the Highest--for which both thou \r
+And they, outcast from God, are here condemned \r
+To waste eternal days in woe and pain? \r
+And reckon'st thou thyself with Spirits of Heaven \r
+Hell-doomed, and breath'st defiance here and scorn, \r
+Where I reign king, and, to enrage thee more, \r
+Thy king and lord? Back to thy punishment, \r
+False fugitive; and to thy speed add wings, \r
+Lest with a whip of scorpions I pursue \r
+Thy lingering, or with one stroke of this dart \r
+Strange horror seize thee, and pangs unfelt before." \r
+  So spake the grisly Terror, and in shape, \r
+So speaking and so threatening, grew tenfold, \r
+More dreadful and deform. On th' other side, \r
+Incensed with indignation, Satan stood \r
+Unterrified, and like a comet burned, \r
+That fires the length of Ophiuchus huge \r
+In th' arctic sky, and from his horrid hair \r
+Shakes pestilence and war. Each at the head \r
+Levelled his deadly aim; their fatal hands \r
+No second stroke intend; and such a frown \r
+Each cast at th' other as when two black clouds, \r
+With heaven's artillery fraught, came rattling on \r
+Over the Caspian,--then stand front to front \r
+Hovering a space, till winds the signal blow \r
+To join their dark encounter in mid-air. \r
+So frowned the mighty combatants that Hell \r
+Grew darker at their frown; so matched they stood; \r
+For never but once more was wither like \r
+To meet so great a foe. And now great deeds \r
+Had been achieved, whereof all Hell had rung, \r
+Had not the snaky Sorceress, that sat \r
+Fast by Hell-gate and kept the fatal key, \r
+Risen, and with hideous outcry rushed between. \r
+  "O father, what intends thy hand," she cried, \r
+"Against thy only son? What fury, O son, \r
+Possesses thee to bend that mortal dart \r
+Against thy father's head? And know'st for whom? \r
+For him who sits above, and laughs the while \r
+At thee, ordained his drudge to execute \r
+Whate'er his wrath, which he calls justice, bids-- \r
+His wrath, which one day will destroy ye both!" \r
+  She spake, and at her words the hellish Pest \r
+Forbore: then these to her Satan returned:-- \r
+  "So strange thy outcry, and thy words so strange \r
+Thou interposest, that my sudden hand, \r
+Prevented, spares to tell thee yet by deeds \r
+What it intends, till first I know of thee \r
+What thing thou art, thus double-formed, and why, \r
+In this infernal vale first met, thou call'st \r
+Me father, and that phantasm call'st my son. \r
+I know thee not, nor ever saw till now \r
+Sight more detestable than him and thee." \r
+  T' whom thus the Portress of Hell-gate replied:-- \r
+"Hast thou forgot me, then; and do I seem \r
+Now in thine eye so foul?--once deemed so fair \r
+In Heaven, when at th' assembly, and in sight \r
+Of all the Seraphim with thee combined \r
+In bold conspiracy against Heaven's King, \r
+All on a sudden miserable pain \r
+Surprised thee, dim thine eyes and dizzy swum \r
+In darkness, while thy head flames thick and fast \r
+Threw forth, till on the left side opening wide, \r
+Likest to thee in shape and countenance bright, \r
+Then shining heavenly fair, a goddess armed, \r
+Out of thy head I sprung. Amazement seized \r
+All th' host of Heaven; back they recoiled afraid \r
+At first, and called me Sin, and for a sign \r
+Portentous held me; but, familiar grown, \r
+I pleased, and with attractive graces won \r
+The most averse--thee chiefly, who, full oft \r
+Thyself in me thy perfect image viewing, \r
+Becam'st enamoured; and such joy thou took'st \r
+With me in secret that my womb conceived \r
+A growing burden. Meanwhile war arose, \r
+And fields were fought in Heaven: wherein remained \r
+(For what could else?) to our Almighty Foe \r
+Clear victory; to our part loss and rout \r
+Through all the Empyrean. Down they fell, \r
+Driven headlong from the pitch of Heaven, down \r
+Into this Deep; and in the general fall \r
+I also: at which time this powerful key \r
+Into my hands was given, with charge to keep \r
+These gates for ever shut, which none can pass \r
+Without my opening. Pensive here I sat \r
+Alone; but long I sat not, till my womb, \r
+Pregnant by thee, and now excessive grown, \r
+Prodigious motion felt and rueful throes. \r
+At last this odious offspring whom thou seest, \r
+Thine own begotten, breaking violent way, \r
+Tore through my entrails, that, with fear and pain \r
+Distorted, all my nether shape thus grew \r
+Transformed: but he my inbred enemy \r
+Forth issued, brandishing his fatal dart, \r
+Made to destroy. I fled, and cried out Death! \r
+Hell trembled at the hideous name, and sighed \r
+From all her caves, and back resounded Death! \r
+I fled; but he pursued (though more, it seems, \r
+Inflamed with lust than rage), and, swifter far, \r
+Me overtook, his mother, all dismayed, \r
+And, in embraces forcible and foul \r
+Engendering with me, of that rape begot \r
+These yelling monsters, that with ceaseless cry \r
+Surround me, as thou saw'st--hourly conceived \r
+And hourly born, with sorrow infinite \r
+To me; for, when they list, into the womb \r
+That bred them they return, and howl, and gnaw \r
+My bowels, their repast; then, bursting forth \r
+Afresh, with conscious terrors vex me round, \r
+That rest or intermission none I find. \r
+Before mine eyes in opposition sits \r
+Grim Death, my son and foe, who set them on, \r
+And me, his parent, would full soon devour \r
+For want of other prey, but that he knows \r
+His end with mine involved, and knows that I \r
+Should prove a bitter morsel, and his bane, \r
+Whenever that shall be: so Fate pronounced. \r
+But thou, O father, I forewarn thee, shun \r
+His deadly arrow; neither vainly hope \r
+To be invulnerable in those bright arms, \r
+Through tempered heavenly; for that mortal dint, \r
+Save he who reigns above, none can resist." \r
+  She finished; and the subtle Fiend his lore \r
+Soon learned, now milder, and thus answered smooth:-- \r
+  "Dear daughter--since thou claim'st me for thy sire, \r
+And my fair son here show'st me, the dear pledge \r
+Of dalliance had with thee in Heaven, and joys \r
+Then sweet, now sad to mention, through dire change \r
+Befallen us unforeseen, unthought-of--know, \r
+I come no enemy, but to set free \r
+From out this dark and dismal house of pain \r
+Both him and thee, and all the heavenly host \r
+Of Spirits that, in our just pretences armed, \r
+Fell with us from on high. From them I go \r
+This uncouth errand sole, and one for all \r
+Myself expose, with lonely steps to tread \r
+Th' unfounded Deep, and through the void immense \r
+To search, with wandering quest, a place foretold \r
+Should be--and, by concurring signs, ere now \r
+Created vast and round--a place of bliss \r
+In the purlieus of Heaven; and therein placed \r
+A race of upstart creatures, to supply \r
+Perhaps our vacant room, though more removed, \r
+Lest Heaven, surcharged with potent multitude, \r
+Might hap to move new broils. Be this, or aught \r
+Than this more secret, now designed, I haste \r
+To know; and, this once known, shall soon return, \r
+And bring ye to the place where thou and Death \r
+Shall dwell at ease, and up and down unseen \r
+Wing silently the buxom air, embalmed \r
+With odours. There ye shall be fed and filled \r
+Immeasurably; all things shall be your prey." \r
+  He ceased; for both seemed highly pleased, and Death \r
+Grinned horrible a ghastly smile, to hear \r
+His famine should be filled, and blessed his maw \r
+Destined to that good hour. No less rejoiced \r
+His mother bad, and thus bespake her sire:-- \r
+  "The key of this infernal Pit, by due \r
+And by command of Heaven's all-powerful King, \r
+I keep, by him forbidden to unlock \r
+These adamantine gates; against all force \r
+Death ready stands to interpose his dart, \r
+Fearless to be o'ermatched by living might. \r
+But what owe I to his commands above, \r
+Who hates me, and hath hither thrust me down \r
+Into this gloom of Tartarus profound, \r
+To sit in hateful office here confined, \r
+Inhabitant of Heaven and heavenly born-- \r
+Here in perpetual agony and pain, \r
+With terrors and with clamours compassed round \r
+Of mine own brood, that on my bowels feed? \r
+Thou art my father, thou my author, thou \r
+My being gav'st me; whom should I obey \r
+But thee? whom follow? Thou wilt bring me soon \r
+To that new world of light and bliss, among \r
+The gods who live at ease, where I shall reign \r
+At thy right hand voluptuous, as beseems \r
+Thy daughter and thy darling, without end." \r
+  Thus saying, from her side the fatal key, \r
+Sad instrument of all our woe, she took; \r
+And, towards the gate rolling her bestial train, \r
+Forthwith the huge portcullis high up-drew, \r
+Which, but herself, not all the Stygian Powers \r
+Could once have moved; then in the key-hole turns \r
+Th' intricate wards, and every bolt and bar \r
+Of massy iron or solid rock with ease \r
+Unfastens. On a sudden open fly, \r
+With impetuous recoil and jarring sound, \r
+Th' infernal doors, and on their hinges grate \r
+Harsh thunder, that the lowest bottom shook \r
+Of Erebus. She opened; but to shut \r
+Excelled her power: the gates wide open stood, \r
+That with extended wings a bannered host, \r
+Under spread ensigns marching, mibht pass through \r
+With horse and chariots ranked in loose array; \r
+So wide they stood, and like a furnace-mouth \r
+Cast forth redounding smoke and ruddy flame. \r
+Before their eyes in sudden view appear \r
+The secrets of the hoary Deep--a dark \r
+Illimitable ocean, without bound, \r
+Without dimension; where length, breadth, and height, \r
+And time, and place, are lost; where eldest Night \r
+And Chaos, ancestors of Nature, hold \r
+Eternal anarchy, amidst the noise \r
+Of endless wars, and by confusion stand. \r
+For Hot, Cold, Moist, and Dry, four champions fierce, \r
+Strive here for mastery, and to battle bring \r
+Their embryon atoms: they around the flag \r
+Of each his faction, in their several clans, \r
+Light-armed or heavy, sharp, smooth, swift, or slow, \r
+Swarm populous, unnumbered as the sands \r
+Of Barca or Cyrene's torrid soil, \r
+Levied to side with warring winds, and poise \r
+Their lighter wings. To whom these most adhere \r
+He rules a moment: Chaos umpire sits, \r
+And by decision more embroils the fray \r
+By which he reigns: next him, high arbiter, \r
+Chance governs all. Into this wild Abyss, \r
+The womb of Nature, and perhaps her grave, \r
+Of neither sea, nor shore, nor air, nor fire, \r
+But all these in their pregnant causes mixed \r
+Confusedly, and which thus must ever fight, \r
+Unless th' Almighty Maker them ordain \r
+His dark materials to create more worlds-- \r
+Into this wild Abyss the wary Fiend \r
+Stood on the brink of Hell and looked a while, \r
+Pondering his voyage; for no narrow frith \r
+He had to cross. Nor was his ear less pealed \r
+With noises loud and ruinous (to compare \r
+Great things with small) than when Bellona storms \r
+With all her battering engines, bent to rase \r
+Some capital city; or less than if this frame \r
+Of Heaven were falling, and these elements \r
+In mutiny had from her axle torn \r
+The steadfast Earth. At last his sail-broad vans \r
+He spread for flight, and, in the surging smoke \r
+Uplifted, spurns the ground; thence many a league, \r
+As in a cloudy chair, ascending rides \r
+Audacious; but, that seat soon failing, meets \r
+A vast vacuity. All unawares, \r
+Fluttering his pennons vain, plumb-down he drops \r
+Ten thousand fathom deep, and to this hour \r
+Down had been falling, had not, by ill chance, \r
+The strong rebuff of some tumultuous cloud, \r
+Instinct with fire and nitre, hurried him \r
+As many miles aloft. That fury stayed-- \r
+Quenched in a boggy Syrtis, neither sea, \r
+Nor good dry land--nigh foundered, on he fares, \r
+Treading the crude consistence, half on foot, \r
+Half flying; behoves him now both oar and sail. \r
+As when a gryphon through the wilderness \r
+With winged course, o'er hill or moory dale, \r
+Pursues the Arimaspian, who by stealth \r
+Had from his wakeful custody purloined \r
+The guarded gold; so eagerly the Fiend \r
+O'er bog or steep, through strait, rough, dense, or rare, \r
+With head, hands, wings, or feet, pursues his way, \r
+And swims, or sinks, or wades, or creeps, or flies. \r
+At length a universal hubbub wild \r
+Of stunning sounds, and voices all confused, \r
+Borne through the hollow dark, assaults his ear \r
+With loudest vehemence. Thither he plies \r
+Undaunted, to meet there whatever Power \r
+Or Spirit of the nethermost Abyss \r
+Might in that noise reside, of whom to ask \r
+Which way the nearest coast of darkness lies \r
+Bordering on light; when straight behold the throne \r
+Of Chaos, and his dark pavilion spread \r
+Wide on the wasteful Deep! With him enthroned \r
+Sat sable-vested Night, eldest of things, \r
+The consort of his reign; and by them stood \r
+Orcus and Ades, and the dreaded name \r
+Of Demogorgon; Rumour next, and Chance, \r
+And Tumult, and Confusion, all embroiled, \r
+And Discord with a thousand various mouths. \r
+  T' whom Satan, turning boldly, thus:--"Ye Powers \r
+And Spirtis of this nethermost Abyss, \r
+Chaos and ancient Night, I come no spy \r
+With purpose to explore or to disturb \r
+The secrets of your realm; but, by constraint \r
+Wandering this darksome desert, as my way \r
+Lies through your spacious empire up to light, \r
+Alone and without guide, half lost, I seek, \r
+What readiest path leads where your gloomy bounds \r
+Confine with Heaven; or, if some other place, \r
+From your dominion won, th' Ethereal King \r
+Possesses lately, thither to arrive \r
+I travel this profound. Direct my course: \r
+Directed, no mean recompense it brings \r
+To your behoof, if I that region lost, \r
+All usurpation thence expelled, reduce \r
+To her original darkness and your sway \r
+(Which is my present journey), and once more \r
+Erect the standard there of ancient Night. \r
+Yours be th' advantage all, mine the revenge!" \r
+  Thus Satan; and him thus the Anarch old, \r
+With faltering speech and visage incomposed, \r
+Answered:  "I know thee, stranger, who thou art--  *** \r
+That mighty leading Angel, who of late \r
+Made head against Heaven's King, though overthrown. \r
+I saw and heard; for such a numerous host \r
+Fled not in silence through the frighted Deep, \r
+With ruin upon ruin, rout on rout, \r
+Confusion worse confounded; and Heaven-gates \r
+Poured out by millions her victorious bands, \r
+Pursuing. I upon my frontiers here \r
+Keep residence; if all I can will serve \r
+That little which is left so to defend, \r
+Encroached on still through our intestine broils \r
+Weakening the sceptre of old Night: first, Hell, \r
+Your dungeon, stretching far and wide beneath; \r
+Now lately Heaven and Earth, another world \r
+Hung o'er my realm, linked in a golden chain \r
+To that side Heaven from whence your legions fell! \r
+If that way be your walk, you have not far; \r
+So much the nearer danger. Go, and speed; \r
+Havoc, and spoil, and ruin, are my gain." \r
+  He ceased; and Satan stayed not to reply, \r
+But, glad that now his sea should find a shore, \r
+With fresh alacrity and force renewed \r
+Springs upward, like a pyramid of fire, \r
+Into the wild expanse, and through the shock \r
+Of fighting elements, on all sides round \r
+Environed, wins his way; harder beset \r
+And more endangered than when Argo passed \r
+Through Bosporus betwixt the justling rocks, \r
+Or when Ulysses on the larboard shunned \r
+Charybdis, and by th' other whirlpool steered. \r
+So he with difficulty and labour hard \r
+Moved on, with difficulty and labour he; \r
+But, he once passed, soon after, when Man fell, \r
+Strange alteration! Sin and Death amain, \r
+Following his track (such was the will of Heaven) \r
+Paved after him a broad and beaten way \r
+Over the dark Abyss, whose boiling gulf \r
+Tamely endured a bridge of wondrous length, \r
+From Hell continued, reaching th' utmost orb \r
+Of this frail World; by which the Spirits perverse \r
+With easy intercourse pass to and fro \r
+To tempt or punish mortals, except whom \r
+God and good Angels guard by special grace. \r
+  But now at last the sacred influence \r
+Of light appears, and from the walls of Heaven \r
+Shoots far into the bosom of dim Night \r
+A glimmering dawn. Here Nature first begins \r
+Her farthest verge, and Chaos to retire, \r
+As from her outmost works, a broken foe, \r
+With tumult less and with less hostile din; \r
+That Satan with less toil, and now with ease, \r
+Wafts on the calmer wave by dubious light, \r
+And, like a weather-beaten vessel, holds \r
+Gladly the port, though shrouds and tackle torn; \r
+Or in the emptier waste, resembling air, \r
+Weighs his spread wings, at leisure to behold \r
+Far off th' empyreal Heaven, extended wide \r
+In circuit, undetermined square or round, \r
+With opal towers and battlements adorned \r
+Of living sapphire, once his native seat; \r
+And, fast by, hanging in a golden chain, \r
+This pendent World, in bigness as a star \r
+Of smallest magnitude close by the moon. \r
+Thither, full fraught with mischievous revenge, \r
+Accursed, and in a cursed hour, he hies. \r
\r
\r
\r
+Book III                                                         \r
\r
\r
+Hail, holy Light, offspring of Heaven firstborn, \r
+Or of the Eternal coeternal beam \r
+May I express thee unblam'd?  since God is light, \r
+And never but in unapproached light \r
+Dwelt from eternity, dwelt then in thee \r
+Bright effluence of bright essence increate. \r
+Or hear"st thou rather pure ethereal stream, \r
+Whose fountain who shall tell?  before the sun, \r
+Before the Heavens thou wert, and at the voice \r
+Of God, as with a mantle, didst invest  *** \r
+The rising world of waters dark and deep, \r
+Won from the void and formless infinite. \r
+Thee I re-visit now with bolder wing, \r
+Escap'd the Stygian pool, though long detain'd \r
+In that obscure sojourn, while in my flight \r
+Through utter and through middle darkness borne, \r
+With other notes than to the Orphean lyre \r
+I sung of Chaos and eternal Night; \r
+Taught by the heavenly Muse to venture down \r
+The dark descent, and up to re-ascend, \r
+Though hard and rare:  Thee I revisit safe, \r
+And feel thy sovran vital lamp; but thou \r
+Revisit'st not these eyes, that roll in vain \r
+To find thy piercing ray, and find no dawn; \r
+So  thick a drop serene hath quench'd their orbs, \r
+Or dim suffusion veil'd.  Yet not the more \r
+Cease I to wander, where the Muses haunt, \r
+Clear spring, or shady grove, or sunny hill, \r
+Smit with the love of sacred song; but chief \r
+Thee, Sion, and the flowery brooks beneath, \r
+That wash thy hallow'd feet, and warbling flow, \r
+Nightly I visit:  nor sometimes forget \r
+So were I equall'd with them in renown, \r
+Thy sovran command, that Man should find grace; \r
+Blind Thamyris, and blind Maeonides, \r
+And Tiresias, and Phineus, prophets old: \r
+Then feed on thoughts, that voluntary move \r
+Harmonious numbers; as the wakeful bird \r
+Sings darkling, and in shadiest covert hid \r
+Tunes her nocturnal note.  Thus with the year \r
+Seasons return; but not to me returns \r
+Day, or the sweet approach of even or morn, \r
+Or sight of vernal bloom, or summer's rose, \r
+Or flocks, or herds, or human face divine; \r
+But cloud instead, and ever-during dark \r
+Surrounds me, from the cheerful ways of men \r
+Cut off, and for the book of knowledge fair \r
+Presented with a universal blank \r
+Of nature's works to me expung'd and ras'd, \r
+And wisdom at one entrance quite shut out. \r
+So much the rather thou, celestial Light, \r
+Shine inward, and the mind through all her powers \r
+Irradiate; there plant eyes, all mist from thence \r
+Purge and disperse, that I may see and tell \r
+Of things invisible to mortal sight. \r
+Now had the Almighty Father from above, \r
+From the pure empyrean where he sits \r
+High thron'd above all highth, bent down his eye \r
+His own works and their works at once to view: \r
+About him all the Sanctities of Heaven \r
+Stood thick as stars, and from his sight receiv'd \r
+Beatitude past utterance; on his right \r
+The radiant image of his glory sat, \r
+His only son; on earth he first beheld \r
+Our two first parents, yet the only two \r
+Of mankind in the happy garden plac'd \r
+Reaping immortal fruits of joy and love, \r
+Uninterrupted joy, unrivall'd love, \r
+In blissful solitude; he then survey'd \r
+Hell and the gulf between, and Satan there  \r
+Coasting the wall of Heaven on this side Night \r
+In the dun air sublime, and ready now \r
+To stoop with wearied wings, and willing feet, \r
+On the bare outside of this world, that seem'd \r
+Firm land imbosom'd, without firmament, \r
+Uncertain which, in ocean or in air. \r
+Him God beholding from his prospect high, \r
+Wherein past, present, future, he beholds, \r
+Thus to his only Son foreseeing spake. \r
+Only begotten Son, seest thou what rage \r
+Transports our Adversary?  whom no bounds \r
+Prescrib'd no bars of Hell, nor all the chains \r
+Heap'd on him there, nor yet the main abyss \r
+Wide interrupt, can hold; so bent he seems \r
+On desperate revenge, that shall redound \r
+Upon his own rebellious head.  And now, \r
+Through all restraint broke loose, he wings his way \r
+Not far off Heaven, in the precincts of light, \r
+Directly towards the new created world, \r
+And man there plac'd, with purpose to assay \r
+If him by force he can destroy, or, worse, \r
+By some false guile pervert; and shall pervert; \r
+For man will hearken to his glozing lies, \r
+And easily transgress the sole command, \r
+Sole pledge of his obedience:  So will fall \r
+He and his faithless progeny:  Whose fault? \r
+Whose but his own?  ingrate, he had of me \r
+All he could have; I made him just and right, \r
+Sufficient to have stood, though free to fall. \r
+Such I created all the ethereal Powers \r
+And Spirits, both them who stood, and them who fail'd; \r
+Freely they stood who stood, and fell who fell. \r
+Not free, what proof could they have given sincere \r
+Of true allegiance, constant faith or love, \r
+Where only what they needs must do appear'd, \r
+Not what they would?  what praise could they receive? \r
+What pleasure I from such obedience paid, \r
+When will and reason (reason also is choice) \r
+Useless and vain, of freedom both despoil'd, \r
+Made passive both, had serv'd necessity, \r
+Not me?  they therefore, as to right belong$ 'd, \r
+So were created, nor can justly accuse \r
+Their Maker, or their making, or their fate, \r
+As if predestination over-rul'd \r
+Their will dispos'd by absolute decree \r
+Or high foreknowledge they themselves decreed \r
+Their own revolt, not I; if I foreknew, \r
+Foreknowledge had no influence on their fault, \r
+Which had no less proved certain unforeknown. \r
+So without least impulse or shadow of fate, \r
+Or aught by me immutably foreseen, \r
+They trespass, authors to themselves in all \r
+Both what they judge, and what they choose; for so \r
+I form'd them free: and free they must remain, \r
+Till they enthrall themselves; I else must change \r
+Their nature, and revoke the high decree \r
+Unchangeable, eternal, which ordain'd \r
+$THeir freedom: they themselves ordain'd their fall. \r
+The first sort by their own suggestion fell, \r
+Self-tempted, self-deprav'd:  Man falls, deceiv'd \r
+By the other first:  Man therefore shall find grace, \r
+The other none:  In mercy and justice both, \r
+Through Heaven and Earth, so shall my glory excel; \r
+But Mercy, first and last, shall brightest shine. \r
+Thus while God spake, ambrosial fragrance fill'd \r
+All Heaven, and in the blessed Spirits elect \r
+Sense of new joy ineffable diffus'd. \r
+Beyond compare the Son of God was seen \r
+Most glorious; in him all his Father shone \r
+Substantially express'd; and in his face \r
+Divine compassion visibly appear'd, \r
+Love without end, and without measure grace, \r
+Which uttering, thus he to his Father spake. \r
+O Father, gracious was that word which clos'd \r
+Thy sovran command, that Man should find grace; \r
+, that Man should find grace; \r
+For which both Heaven and earth shall high extol \r
+Thy praises, with the innumerable sound \r
+Of hymns and sacred songs, wherewith thy throne \r
+Encompass'd shall resound thee ever blest. \r
+For should Man finally be lost, should Man, \r
+Thy creature late so lov'd, thy youngest son, \r
+Fall circumvented thus by fraud, though join'd \r
+With his own folly?  that be from thee far, \r
+That far be from thee, Father, who art judge \r
+Of all things made, and judgest only right. \r
+Or shall the Adversary thus obtain \r
+His end, and frustrate thine?  shall he fulfill \r
+His malice, and thy goodness bring to nought, \r
+Or proud return, though to his heavier doom, \r
+Yet with revenge accomplish'd, and to Hell \r
+Draw after him the whole race of mankind, \r
+By him corrupted?  or wilt thou thyself \r
+Abolish thy creation, and unmake \r
+For him, what for thy glory thou hast made? \r
+So should thy goodness and thy greatness both \r
+Be question'd and blasphem'd without defence. \r
+To whom the great Creator thus replied. \r
+O son, in whom my soul hath chief delight, \r
+Son of my bosom, Son who art alone. \r
+My word, my wisdom, and effectual might,  \r
+All hast thou spoken as my thoughts are, all \r
+As my eternal purpose hath decreed; \r
+Man shall not quite be lost, but sav'd who will; \r
+Yet not of will in him, but grace in me \r
+Freely vouchsaf'd; once more I will renew \r
+His lapsed powers, though forfeit; and enthrall'd \r
+By sin to foul exorbitant desires; \r
+Upheld by me, yet once more he shall stand \r
+On even ground against his mortal foe; \r
+By me upheld, that he may know how frail \r
+His fallen condition is, and to me owe \r
+All his deliverance, and to none but me. \r
+Some I have chosen of peculiar grace, \r
+Elect above the rest; so is my will: \r
+The rest shall hear me call, and oft be warn'd \r
+Their sinful state, and to appease betimes \r
+The incensed Deity, while offer'd grace \r
+Invites; for I will clear their senses dark, \r
+What may suffice, and soften stony hearts \r
+To pray, repent, and bring obedience due. \r
+To prayer, repentance, and obedience due, \r
+Though but endeavour'd with sincere intent, \r
+Mine ear shall not be slow, mine eye not shut. \r
+And I will place within them as a guide, \r
+My umpire Conscience; whom if they will hear, \r
+Light after light, well us'd, they shall attain, \r
+And to the end, persisting, safe arrive. \r
+This my long sufferance, and my day of grace, \r
+They who neglect and scorn, shall never taste; \r
+But hard be harden'd, blind be blinded more, \r
+That they may stumble on, and deeper fall; \r
+And none but such from mercy I exclude. \r
+But yet all is not done; Man disobeying, \r
+Disloyal, breaks his fealty, and sins \r
+Against the high supremacy of Heaven, \r
+Affecting God-head, and, so losing all, \r
+To expiate his treason hath nought left, \r
+But to destruction sacred and devote, \r
+He, with his whole posterity, must die, \r
+Die he or justice must; unless for him \r
+Some other able, and as willing, pay \r
+The rigid satisfaction, death for death. \r
+Say, heavenly Powers, where shall we find such love? \r
+Which of you will be mortal, to redeem \r
+Man's mortal crime, and just the unjust to save? \r
+Dwells in all Heaven charity so dear? \r
+And silence was in Heaven: $ on Man's behalf \r
+He ask'd, but all the heavenly quire stood mute, \r
+Patron or intercessour none appear'd, \r
+Much less that durst upon his own head draw \r
+The deadly forfeiture, and ransom set. \r
+And now without redemption all mankind \r
+Must have been lost, adjudg'd to Death and Hell \r
+By doom severe, had not the Son of God, \r
+In whom the fulness dwells of love divine, \r
+His dearest mediation thus renew'd. \r
+Father, thy word is past, Man shall find grace; \r
+And shall grace not find means, that finds her way, \r
+The speediest of thy winged messengers, \r
+To visit all thy creatures, and to all \r
+Comes unprevented, unimplor'd, unsought? \r
+Happy for Man, so coming; he her aid \r
+Can never seek, once dead in sins, and lost; \r
+Atonement for himself, or offering meet, \r
+Indebted and undone, hath none to bring; \r
+Behold me then:  me for him, life for life \r
+I offer: on me let thine anger fall; \r
+Account me Man; I for his sake will leave \r
+ Thy bosom, and this glory next to thee \r
+ Freely put off, and for him lastly die \r
+ Well pleased; on me let Death wreak all his rage. \r
+ Under his gloomy power I shall not long \r
+ Lie vanquished. Thou hast given me to possess \r
+ Life in myself for ever; by thee I live; \r
+ Though now to Death I yield, and am his due, \r
+ All that of me can die, yet, that debt paid, \r
+ $ thou wilt not leave me in the loathsome grave \r
+ His prey, nor suffer my unspotted soul \r
+ For ever with corruption there to dwell; \r
+ But I shall rise victorious, and subdue \r
+ My vanquisher, spoiled of his vaunted spoil. \r
+ Death his death's wound shall then receive, and stoop \r
+ Inglorious, of his mortal sting disarmed; \r
+ I through the ample air in triumph high \r
+ Shall lead Hell captive maugre Hell, and show \r
+The powers of darkness bound. Thou, at the sight \r
+ Pleased, out of Heaven shalt look down and smile, \r
+ While, by thee raised, I ruin all my foes; \r
+ Death last, and with his carcase glut the grave; \r
+ Then, with the multitude of my redeemed, \r
+ Shall enter Heaven, long absent, and return, \r
+ Father, to see thy face, wherein no cloud \r
+ Of anger shall remain, but peace assured \r
+ And reconcilement: wrath shall be no more \r
+ Thenceforth, but in thy presence joy entire. \r
+ His words here ended; but his meek aspect \r
+ Silent yet spake, and breathed immortal love \r
+ To mortal men, above which only shone \r
+ Filial obedience: as a sacrifice \r
+ Glad to be offered, he attends the will \r
+ Of his great Father. Admiration seized \r
+ All Heaven, what this might mean, and whither tend, \r
+ Wondering; but soon th' Almighty thus replied. \r
+ O thou in Heaven and Earth the only peace \r
+ Found out for mankind under wrath, O thou \r
+ My sole complacence! Well thou know'st how dear \r
+ To me are all my works; nor Man the least, \r
+ Though last created, that for him I spare \r
+ Thee from my bosom and right hand, to save, \r
+ By losing thee a while, the whole race lost.                    \r
\r
+     00021053  \r
+ Thou, therefore, whom thou only canst redeem, \r
+ Their nature also to thy nature join; \r
+ And be thyself Man among men on Earth, \r
+ Made flesh, when time shall be, of virgin seed, \r
+ By wondrous birth; be thou in Adam's room \r
+The head of all mankind, though Adam's son. \r
+As in him perish all men, so in thee, \r
+As from a second root, shall be restored \r
+As many as are restored, without thee none. \r
+His crime makes guilty all his sons; thy merit, \r
+Imputed, shall absolve them who renounce \r
+Their own both righteous and unrighteous deeds, \r
+And live in thee transplanted, and from thee \r
+Receive new life.  So Man, as is most just, \r
+Shall satisfy for Man, be judged and die, \r
+And dying rise, and rising with him raise \r
+His brethren, ransomed with his own dear life. \r
+So heavenly love shall outdo hellish hate, \r
+Giving to death, and dying to redeem, \r
+So dearly to redeem what hellish hate \r
+So easily destroyed, and still destroys \r
+In those who, when they may, accept not grace. \r
+Nor shalt thou, by descending to assume \r
+Man's nature, lessen or degrade thine own. \r
+Because thou hast, though throned in highest bliss \r
+Equal to God, and equally enjoying \r
+God-like fruition, quitted all, to save \r
+A world from utter loss, and hast been found \r
+By merit more than birthright Son of God, \r
+Found worthiest to be so by being good, \r
+Far more than great or high; because in thee \r
+Love hath abounded more than glory abounds; \r
+Therefore thy humiliation shall exalt \r
+With thee thy manhood also to this throne: \r
+Here shalt thou sit incarnate, here shalt reign \r
+Both God and Man, Son both of God and Man, \r
+Anointed universal King; all power \r
+I give thee; reign for ever, and assume \r
+Thy merits; under thee, as head supreme, \r
+Thrones, Princedoms, Powers, Dominions, I reduce: \r
+All knees to thee shall bow, of them that bide \r
+In Heaven, or Earth, or under Earth in Hell. \r
+When thou, attended gloriously from Heaven, \r
+Shalt in the sky appear, and from thee send \r
+The summoning Arch-Angels to proclaim \r
+Thy dread tribunal; forthwith from all winds, \r
+The living, and forthwith the cited dead \r
+Of all past ages, to the general doom \r
+Shall hasten; such a peal shall rouse their sleep. \r
+Then, all thy saints assembled, thou shalt judge \r
+Bad Men and Angels; they, arraigned, shall sink \r
+Beneath thy sentence; Hell, her numbers full, \r
+Thenceforth shall be for ever shut.  Mean while \r
+The world shall burn, and from her ashes spring \r
+New Heaven and Earth, wherein the just shall dwell, \r
+And, after all their tribulations long, \r
+See golden days, fruitful of golden deeds, \r
+With joy and peace triumphing, and fair truth. \r
+Then thou thy regal scepter shalt lay by, \r
+For regal scepter then no more shall need, \r
+God shall be all in all.  But, all ye Gods, \r
+Adore him, who to compass all this dies; \r
+Adore the Son, and honour him as me. \r
+No sooner had the Almighty ceased, but all \r
+The multitude of Angels, with a shout \r
+Loud as from numbers without number, sweet \r
+As from blest voices, uttering joy, Heaven rung \r
+With jubilee, and loud Hosannas filled \r
+The eternal regions:  Lowly reverent \r
+Towards either throne they bow, and to the ground \r
+With solemn adoration down they cast \r
+Their crowns inwove with amarant and gold; \r
+Immortal amarant, a flower which once \r
+In Paradise, fast by the tree of life, \r
+Began to bloom; but soon for man's offence \r
+To Heaven removed, where first it grew, there grows, \r
+And flowers aloft shading the fount of life, \r
+And where the river of bliss through midst of Heaven \r
+Rolls o'er Elysian flowers her amber stream; \r
+With these that never fade the Spirits elect \r
+Bind their resplendent locks inwreathed with beams; \r
+Now in loose garlands thick thrown off, the bright \r
+Pavement, that like a sea of jasper shone, \r
+Impurpled with celestial roses smiled. \r
+Then, crowned again, their golden harps they took, \r
+Harps ever tuned, that glittering by their side \r
+Like quivers hung, and with preamble sweet \r
+Of charming symphony they introduce \r
+Their sacred song, and waken raptures high; \r
+No voice exempt, no voice but well could join \r
+Melodious part, such concord is in Heaven. \r
+Thee, Father, first they sung Omnipotent, \r
+Immutable, Immortal, Infinite, \r
+Eternal King; the Author of all being, \r
+Fonntain of light, thyself invisible \r
+Amidst the glorious brightness where thou sit'st \r
+Throned inaccessible, but when thou shadest \r
+The full blaze of thy beams, and, through a cloud \r
+Drawn round about thee like a radiant shrine, \r
+Dark with excessive bright thy skirts appear, \r
+Yet dazzle Heaven, that brightest Seraphim \r
+Approach not, but with both wings veil their eyes. \r
+Thee next they sang of all creation first, \r
+Begotten Son, Divine Similitude, \r
+In whose conspicuous countenance, without cloud \r
+Made visible, the Almighty Father shines, \r
+Whom else no creature can behold; on thee \r
+Impressed the effulgence of his glory abides, \r
+Transfused on thee his ample Spirit rests. \r
+He Heaven of Heavens and all the Powers therein \r
+By thee created; and by thee threw down \r
+The aspiring Dominations:  Thou that day \r
+Thy Father's dreadful thunder didst not spare, \r
+Nor stop thy flaming chariot-wheels, that shook \r
+Heaven's everlasting frame, while o'er the necks \r
+Thou drovest of warring Angels disarrayed. \r
+Back from pursuit thy Powers with loud acclaim \r
+Thee only extolled, Son of thy Father's might, \r
+To execute fierce vengeance on his foes, \r
+Not so on Man:  Him through their malice fallen, \r
+Father of mercy and grace, thou didst not doom \r
+So strictly, but much more to pity incline: \r
+No sooner did thy dear and only Son \r
+Perceive thee purposed not to doom frail Man \r
+So strictly, but much more to pity inclined, \r
+He to appease thy wrath, and end the strife \r
+Of mercy and justice in thy face discerned, \r
+Regardless of the bliss wherein he sat \r
+Second to thee, offered himself to die \r
+For Man's offence.  O unexampled love, \r
+Love no where to be found less than Divine! \r
+Hail, Son of God, Saviour of Men!  Thy name \r
+Shall be the copious matter of my song \r
+Henceforth, and never shall my heart thy praise \r
+Forget, nor from thy Father's praise disjoin. \r
+Thus they in Heaven, above the starry sphere, \r
+Their happy hours in joy and hymning spent. \r
+Mean while upon the firm opacous globe \r
+Of this round world, whose first convex divides \r
+The luminous inferiour orbs, enclosed \r
+From Chaos, and the inroad of Darkness old, \r
+Satan alighted walks:  A globe far off \r
+It seemed, now seems a boundless continent \r
+Dark, waste, and wild, under the frown of Night \r
+Starless exposed, and ever-threatening storms \r
+Of Chaos blustering round, inclement sky; \r
+Save on that side which from the wall of Heaven, \r
+Though distant far, some small reflection gains \r
+Of glimmering air less vexed with tempest loud: \r
+Here walked the Fiend at large in spacious field. \r
+As when a vultur on Imaus bred, \r
+Whose snowy ridge the roving Tartar bounds, \r
+Dislodging from a region scarce of prey \r
+To gorge the flesh of lambs or yeanling kids, \r
+On hills where flocks are fed, flies toward the springs \r
+Of Ganges or Hydaspes, Indian streams; \r
+But in his way lights on the barren plains \r
+Of Sericana, where Chineses drive \r
+With sails and wind their cany waggons light: \r
+So, on this windy sea of land, the Fiend \r
+Walked up and down alone, bent on his prey; \r
+Alone, for other creature in this place, \r
+Living or lifeless, to be found was none; \r
+None yet, but store hereafter from the earth \r
+Up hither like aereal vapours flew \r
+Of all things transitory and vain, when sin \r
+With vanity had filled the works of men: \r
+Both all things vain, and all who in vain things \r
+Built their fond hopes of glory or lasting fame, \r
+Or happiness in this or the other life; \r
+All who have their reward on earth, the fruits \r
+Of painful superstition and blind zeal, \r
+Nought seeking but the praise of men, here find \r
+Fit retribution, empty as their deeds; \r
+All the unaccomplished works of Nature's hand, \r
+Abortive, monstrous, or unkindly mixed, \r
+Dissolved on earth, fleet hither, and in vain, \r
+Till final dissolution, wander here; \r
+Not in the neighbouring moon as some have dreamed; \r
+Those argent fields more likely habitants, \r
+Translated Saints, or middle Spirits hold \r
+Betwixt the angelical and human kind. \r
+Hither of ill-joined sons and daughters born \r
+First from the ancient world those giants came \r
+With many a vain exploit, though then renowned: \r
+The builders next of Babel on the plain \r
+Of Sennaar, and still with vain design, \r
+New Babels, had they wherewithal, would build: \r
+Others came single; he, who, to be deemed \r
+A God, leaped fondly into Aetna flames, \r
+Empedocles; and he, who, to enjoy \r
+Plato's Elysium, leaped into the sea, \r
+Cleombrotus; and many more too long, \r
+Embryos, and idiots, eremites, and friars \r
+White, black, and gray, with all their trumpery. \r
+Here pilgrims roam, that strayed so far to seek \r
+In Golgotha him dead, who lives in Heaven; \r
+And they, who to be sure of Paradise, \r
+Dying, put on the weeds of Dominick, \r
+Or in Franciscan think to pass disguised; \r
+They pass the planets seven, and pass the fixed, \r
+And that crystalling sphere whose balance weighs \r
+The trepidation talked, and that first moved; \r
+And now Saint Peter at Heaven's wicket seems \r
+To wait them with his keys, and now at foot \r
+Of Heaven's ascent they lift their feet, when lo \r
+A violent cross wind from either coast \r
+Blows them transverse, ten thousand leagues awry \r
+Into the devious air:  Then might ye see \r
+Cowls, hoods, and habits, with their wearers, tost \r
+And fluttered into rags; then reliques, beads, \r
+Indulgences, dispenses, pardons, bulls, \r
+The sport of winds:  All these, upwhirled aloft, \r
+Fly o'er the backside of the world far off \r
+Into a Limbo large and broad, since called \r
+The Paradise of Fools, to few unknown \r
+Long after; now unpeopled, and untrod. \r
+All this dark globe the Fiend found as he passed, \r
+And long he wandered, till at last a gleam \r
+Of dawning light turned thither-ward in haste \r
+His travelled steps: far distant he descries \r
+Ascending by degrees magnificent \r
+Up to the wall of Heaven a structure high; \r
+At top whereof, but far more rich, appeared \r
+The work as of a kingly palace-gate, \r
+With frontispiece of diamond and gold \r
+Embellished; thick with sparkling orient gems \r
+The portal shone, inimitable on earth \r
+By model, or by shading pencil, drawn. \r
+These stairs were such as whereon Jacob saw \r
+Angels ascending and descending, bands \r
+Of guardians bright, when he from Esau fled \r
+To Padan-Aram, in the field of Luz \r
+Dreaming by night under the open sky \r
+And waking cried,  This is the gate of Heaven. \r
+Each stair mysteriously was meant, nor stood \r
+There always, but drawn up to Heaven sometimes \r
+Viewless; and underneath a bright sea flowed \r
+Of jasper, or of liquid pearl, whereon \r
+Who after came from earth, failing arrived \r
+Wafted by Angels, or flew o'er the lake \r
+Rapt in a chariot drawn by fiery steeds. \r
+The stairs were then let down, whether to dare \r
+The Fiend by easy ascent, or aggravate \r
+His sad exclusion from the doors of bliss: \r
+Direct against which opened from beneath, \r
+Just o'er the blissful seat of Paradise, \r
+A passage down to the Earth, a passage wide, \r
+Wider by far than that of after-times \r
+Over mount Sion, and, though that were large, \r
+Over the Promised Land to God so dear; \r
+By which, to visit oft those happy tribes, \r
+On high behests his angels to and fro \r
+Passed frequent, and his eye with choice regard \r
+From Paneas, the fount of Jordan's flood, \r
+To Beersaba, where the Holy Land \r
+Borders on Egypt and the Arabian shore; \r
+So wide the opening seemed, where bounds were set \r
+To darkness, such as bound the ocean wave. \r
+Satan from hence, now on the lower stair, \r
+That scaled by steps of gold to Heaven-gate, \r
+Looks down with wonder at the sudden view \r
+Of all this world at once.  As when a scout, \r
+Through dark?;nd desart ways with?oeril gone \r
+All?might,?;t?kast by break of cheerful dawn \r
+Obtains the brow of some high-climbing hill, \r
+Which to his eye discovers unaware \r
+The goodly prospect of some foreign land \r
+First seen, or some renowned metropolis \r
+With glistering spires and pinnacles adorned, \r
+Which now the rising sun gilds with his beams: \r
+Such wonder seised, though after Heaven seen, \r
+The Spirit malign, but much more envy seised, \r
+At sight of all this world beheld so fair. \r
+Round he surveys (and well might, where he stood \r
+So high above the circling canopy \r
+Of night's extended shade,) from eastern point \r
+Of Libra to the fleecy star that bears \r
+Andromeda far off Atlantick seas \r
+Beyond the horizon; then from pole to pole \r
+He views in breadth, and without longer pause \r
+Down right into the world's first region throws \r
+His flight precipitant, and winds with ease \r
+Through the pure marble air his oblique way \r
+Amongst innumerable stars, that shone \r
+Stars distant, but nigh hand seemed other worlds; \r
+Or other worlds they seemed, or happy isles, \r
+Like those Hesperian gardens famed of old, \r
+Fortunate fields, and groves, and flowery vales, \r
+Thrice happy isles; but who dwelt happy there \r
+He staid not to inquire:  Above them all \r
+The golden sun, in splendour likest Heaven, \r
+Allured his eye; thither his course he bends \r
+Through the calm firmament, (but up or down, \r
+By center, or eccentrick, hard to tell, \r
+Or longitude,) where the great luminary \r
+Aloof the vulgar constellations thick, \r
+That from his lordly eye keep distance due, \r
+Dispenses light from far; they, as they move \r
+Their starry dance in numbers that compute \r
+Days, months, and years, towards his all-cheering lamp \r
+Turn swift their various motions, or are turned \r
+By his magnetick beam, that gently warms \r
+The universe, and to each inward part \r
+With gentle penetration, though unseen, \r
+Shoots invisible virtue even to the deep; \r
+So wonderously was set his station bright. \r
+There lands the Fiend, a spot like which perhaps \r
+Astronomer in the sun's lucent orb \r
+Through his glazed optick tube yet never saw. \r
+The place he found beyond expression bright, \r
+Compared with aught on earth, metal or stone; \r
+Not all parts like, but all alike informed \r
+With radiant light, as glowing iron with fire; \r
+If metal, part seemed gold, part silver clear; \r
+If stone, carbuncle most or chrysolite, \r
+Ruby or topaz, to the twelve that shone \r
+In Aaron's breast-plate, and a stone besides \r
+Imagined rather oft than elsewhere seen, \r
+That stone, or like to that which here below \r
+Philosophers in vain so long have sought, \r
+In vain, though by their powerful art they bind \r
+Volatile Hermes, and call up unbound \r
+In various shapes old Proteus from the sea, \r
+Drained through a limbeck to his native form. \r
+What wonder then if fields and regions here \r
+Breathe forth Elixir pure, and rivers run \r
+Potable gold, when with one virtuous touch \r
+The arch-chemick sun, so far from us remote, \r
+Produces, with terrestrial humour mixed, \r
+Here in the dark so many precious things \r
+Of colour glorious, and effect so rare? \r
+Here matter new to gaze the Devil met \r
+Undazzled; far and wide his eye commands; \r
+For sight no obstacle found here, nor shade, \r
+But all sun-shine, as when his beams at noon \r
+Culminate from the equator, as they now \r
+Shot upward still direct, whence no way round \r
+Shadow from body opaque can fall; and the air, \r
+No where so clear, sharpened his visual ray \r
+To objects distant far, whereby he soon \r
+Saw within ken a glorious Angel stand, \r
+The same whom John saw also in the sun: \r
+His back was turned, but not his brightness hid; \r
+Of beaming sunny rays a golden tiar \r
+Circled his head, nor less his locks behind \r
+Illustrious on his shoulders fledge with wings \r
+Lay waving round; on some great charge employed \r
+He seemed, or fixed in cogitation deep. \r
+Glad was the Spirit impure, as now in hope \r
+To find who might direct his wandering flight \r
+To Paradise, the happy seat of Man, \r
+His journey's end and our beginning woe. \r
+But first he casts to change his proper shape, \r
+Which else might work him danger or delay: \r
+And now a stripling Cherub he appears, \r
+Not of the prime, yet such as in his face \r
+Youth smiled celestial, and to every limb \r
+Suitable grace diffused, so well he feigned: \r
+Under a coronet his flowing hair \r
+In curls on either cheek played; wings he wore \r
+Of many a coloured plume, sprinkled with gold; \r
+His habit fit for speed succinct, and held \r
+Before his decent steps a silver wand. \r
+He drew not nigh unheard; the Angel bright, \r
+Ere he drew nigh, his radiant visage turned, \r
+Admonished by his ear, and straight was known \r
+The Arch-Angel Uriel, one of the seven \r
+Who in God's presence, nearest to his throne, \r
+Stand ready at command, and are his eyes \r
+That run through all the Heavens, or down to the Earth \r
+Bear his swift errands over moist and dry, \r
+O'er sea and land: him Satan thus accosts. \r
+Uriel, for thou of those seven Spirits that stand \r
+In sight of God's high throne, gloriously bright, \r
+The first art wont his great authentick will \r
+Interpreter through highest Heaven to bring, \r
+Where all his sons thy embassy attend; \r
+And here art likeliest by supreme decree \r
+Like honour to obtain, and as his eye \r
+To visit oft this new creation round; \r
+Unspeakable desire to see, and know \r
+All these his wonderous works, but chiefly Man, \r
+His chief delight and favour, him for whom \r
+All these his works so wonderous he ordained, \r
+Hath brought me from the quires of Cherubim \r
+Alone thus wandering.  Brightest Seraph, tell \r
+In which of all these shining orbs hath Man \r
+His fixed seat, or fixed seat hath none, \r
+But all these shining orbs his choice to dwell; \r
+That I may find him, and with secret gaze \r
+Or open admiration him behold, \r
+On whom the great Creator hath bestowed \r
+Worlds, and on whom hath all these graces poured; \r
+That both in him and all things, as is meet, \r
+The universal Maker we may praise; \r
+Who justly hath driven out his rebel foes \r
+To deepest Hell, and, to repair that loss, \r
+Created this new happy race of Men \r
+To serve him better:  Wise are all his ways. \r
+So spake the false dissembler unperceived; \r
+For neither Man nor Angel can discern \r
+Hypocrisy, the only evil that walks \r
+Invisible, except to God alone, \r
+By his permissive will, through Heaven and Earth: \r
+And oft, though wisdom wake, suspicion sleeps \r
+At wisdom's gate, and to simplicity \r
+Resigns her charge, while goodness thinks no ill \r
+Where no ill seems:  Which now for once beguiled \r
+Uriel, though regent of the sun, and held \r
+The sharpest-sighted Spirit of all in Heaven; \r
+Who to the fraudulent impostor foul, \r
+In his uprightness, answer thus returned. \r
+Fair Angel, thy desire, which tends to know \r
+The works of God, thereby to glorify \r
+The great Work-master, leads to no excess \r
+That reaches blame, but rather merits praise \r
+The more it seems excess, that led thee hither \r
+From thy empyreal mansion thus alone, \r
+To witness with thine eyes what some perhaps, \r
+Contented with report, hear only in Heaven: \r
+For wonderful indeed are all his works, \r
+Pleasant to know, and worthiest to be all \r
+Had in remembrance always with delight; \r
+But what created mind can comprehend \r
+Their number, or the wisdom infinite \r
+That brought them forth, but hid their causes deep? \r
+I saw when at his word the formless mass, \r
+This world's material mould, came to a heap: \r
+Confusion heard his voice, and wild uproar \r
+Stood ruled, stood vast infinitude confined; \r
+Till at his second bidding Darkness fled, \r
+Light shone, and order from disorder sprung: \r
+Swift to their several quarters hasted then \r
+The cumbrous elements, earth, flood, air, fire; \r
+And this ethereal quintessence of Heaven \r
+Flew upward, spirited with various forms, \r
+That rolled orbicular, and turned to stars \r
+Numberless, as thou seest, and how they move; \r
+Each had his place appointed, each his course; \r
+The rest in circuit walls this universe. \r
+Look downward on that globe, whose hither side \r
+With light from hence, though but reflected, shines; \r
+That place is Earth, the seat of Man; that light \r
+His day, which else, as the other hemisphere, \r
+Night would invade; but there the neighbouring moon \r
+So call that opposite fair star) her aid \r
+Timely interposes, and her monthly round \r
+Still ending, still renewing, through mid Heaven, \r
+With borrowed light her countenance triform \r
+Hence fills and empties to enlighten the Earth, \r
+And in her pale dominion checks the night. \r
+That spot, to which I point, is Paradise, \r
+Adam's abode; those lofty shades, his bower. \r
+Thy way thou canst not miss, me mine requires. \r
+Thus said, he turned; and Satan, bowing low, \r
+As to superiour Spirits is wont in Heaven, \r
+Where honour due and reverence none neglects, \r
+Took leave, and toward the coast of earth beneath, \r
+Down from the ecliptick, sped with hoped success, \r
+Throws his steep flight in many an aery wheel; \r
+Nor staid, till on Niphates' top he lights. \r
\r
\r
\r
+Book IV                                                          \r
\r
\r
+O, for that warning voice, which he, who saw \r
+The Apocalypse, heard cry in Heaven aloud, \r
+Then when the Dragon, put to second rout, \r
+Came furious down to be revenged on men, \r
+Woe to the inhabitants on earth! that now, \r
+While time was, our first parents had been warned \r
+The coming of their secret foe, and 'scaped, \r
+Haply so 'scaped his mortal snare:  For now \r
+Satan, now first inflamed with rage, came down, \r
+The tempter ere the accuser of mankind, \r
+To wreak on innocent frail Man his loss \r
+Of that first battle, and his flight to Hell: \r
+Yet, not rejoicing in his speed, though bold \r
+Far off and fearless, nor with cause to boast, \r
+Begins his dire attempt; which nigh the birth \r
+Now rolling boils in his tumultuous breast, \r
+And like a devilish engine back recoils \r
+Upon himself; horrour and doubt distract \r
+His troubled thoughts, and from the bottom stir \r
+The Hell within him; for within him Hell \r
+He brings, and round about him, nor from Hell \r
+One step, no more than from himself, can fly \r
+By change of place:  Now conscience wakes despair, \r
+That slumbered; wakes the bitter memory \r
+Of what he was, what is, and what must be \r
+Worse; of worse deeds worse sufferings must ensue. \r
+Sometimes towards Eden, which now in his view \r
+Lay pleasant, his grieved look he fixes sad; \r
+Sometimes towards Heaven, and the full-blazing sun, \r
+Which now sat high in his meridian tower: \r
+Then, much revolving, thus in sighs began. \r
+O thou, that, with surpassing glory crowned, \r
+Lookest from thy sole dominion like the God \r
+Of this new world; at whose sight all the stars \r
+Hide their diminished heads; to thee I call, \r
+But with no friendly voice, and add thy name, \r
+Of Sun! to tell thee how I hate thy beams, \r
+That bring to my remembrance from what state \r
+I fell, how glorious once above thy sphere; \r
+Till pride and worse ambition threw me down \r
+Warring in Heaven against Heaven's matchless King: \r
+Ah, wherefore! he deserved no such return \r
+From me, whom he created what I was \r
+In that bright eminence, and with his good \r
+Upbraided none; nor was his service hard. \r
+What could be less than to afford him praise, \r
+The easiest recompence, and pay him thanks, \r
+How due! yet all his good proved ill in me, \r
+And wrought but malice; lifted up so high \r
+I sdeined subjection, and thought one step higher \r
+Would set me highest, and in a moment quit \r
+The debt immense of endless gratitude, \r
+So burdensome still paying, still to owe, \r
+Forgetful what from him I still received, \r
+And understood not that a grateful mind \r
+By owing owes not, but still pays, at once \r
+Indebted and discharged; what burden then \r
+O, had his powerful destiny ordained \r
+Me some inferiour Angel, I had stood \r
+Then happy; no unbounded hope had raised \r
+Ambition!  Yet why not some other Power \r
+As great might have aspired, and me, though mean, \r
+Drawn to his part; but other Powers as great \r
+Fell not, but stand unshaken, from within \r
+Or from without, to all temptations armed. \r
+Hadst thou the same free will and power to stand? \r
+Thou hadst: whom hast thou then or what to accuse, \r
+But Heaven's free love dealt equally to all? \r
+Be then his love accursed, since love or hate, \r
+To me alike, it deals eternal woe. \r
+Nay, cursed be thou; since against his thy will \r
+Chose freely what it now so justly rues. \r
+Me miserable! which way shall I fly \r
+Infinite wrath, and infinite despair? \r
+Which way I fly is Hell; myself am Hell; \r
+And, in the lowest deep, a lower deep \r
+Still threatening to devour me opens wide, \r
+To which the Hell I suffer seems a Heaven. \r
+O, then, at last relent:  Is there no place \r
+Left for repentance, none for pardon left? \r
+None left but by submission; and that word \r
+Disdain forbids me, and my dread of shame \r
+Among the Spirits beneath, whom I seduced \r
+With other promises and other vaunts \r
+Than to submit, boasting I could subdue \r
+The Omnipotent.  Ay me! they little know \r
+How dearly I abide that boast so vain, \r
+Under what torments inwardly I groan, \r
+While they adore me on the throne of Hell. \r
+With diadem and scepter high advanced, \r
+The lower still I fall, only supreme \r
+In misery:  Such joy ambition finds. \r
+But say I could repent, and could obtain, \r
+By act of grace, my former state; how soon \r
+Would highth recall high thoughts, how soon unsay \r
+What feigned submission swore?  Ease would recant \r
+Vows made in pain, as violent and void. \r
+For never can true reconcilement grow, \r
+Where wounds of deadly hate have pierced so deep: \r
+Which would but lead me to a worse relapse \r
+And heavier fall:  so should I purchase dear \r
+Short intermission bought with double smart. \r
+This knows my Punisher; therefore as far \r
+From granting he, as I from begging, peace; \r
+All hope excluded thus, behold, in stead \r
+Mankind created, and for him this world. \r
+So farewell, hope; and with hope farewell, fear; \r
+Farewell, remorse! all good to me is lost; \r
+Evil, be thou my good; by thee at least \r
+Divided empire with Heaven's King I hold, \r
+By thee, and more than half perhaps will reign; \r
+As Man ere long, and this new world, shall know. \r
+Thus while he spake, each passion dimmed his face \r
+Thrice changed with pale, ire, envy, and despair; \r
+Which marred his borrowed visage, and betrayed \r
+Him counterfeit, if any eye beheld. \r
+For heavenly minds from such distempers foul \r
+Are ever clear.  Whereof he soon aware, \r
+Each perturbation smoothed with outward calm, \r
+Artificer of fraud; and was the first \r
+That practised falsehood under saintly show, \r
+Deep malice to conceal, couched with revenge: \r
+Yet not enough had practised to deceive \r
+Uriel once warned; whose eye pursued him down \r
+ The way he went, and on the Assyrian mount \r
+ Saw him disfigured, more than could befall \r
+ Spirit of happy sort; his gestures fierce \r
+ He marked and mad demeanour, then alone, \r
+ As he supposed, all unobserved, unseen. \r
+ So on he fares, and to the border comes \r
+ Of Eden, where delicious Paradise, \r
+ Now nearer, crowns with her enclosure green, \r
+ As with a rural mound, the champaign head \r
+ Of a steep wilderness, whose hairy sides \r
+Access denied; and overhead upgrew \r
+ Insuperable height of loftiest shade, \r
+ Cedar, and pine, and fir, and branching palm, \r
+ A sylvan scene, and, as the ranks ascend, \r
+ Shade above shade, a woody theatre \r
+ Of stateliest view. Yet higher than their tops \r
+ The verdurous wall of Paradise upsprung;                        \r
\r
+    00081429  \r
+Which to our general sire gave prospect large \r
+Into his nether empire neighbouring round. \r
+And higher than that wall a circling row \r
+Of goodliest trees, loaden with fairest fruit, \r
+Blossoms and fruits at once of golden hue, \r
+Appeared, with gay enamelled colours mixed: \r
+On which the sun more glad impressed his beams \r
+Than in fair evening cloud, or humid bow, \r
+When God hath showered the earth; so lovely seemed \r
+That landskip:  And of pure now purer air \r
+Meets his approach, and to the heart inspires \r
+Vernal delight and joy, able to drive \r
+All sadness but despair:  Now gentle gales, \r
+Fanning their odoriferous wings, dispense \r
+Native perfumes, and whisper whence they stole \r
+Those balmy spoils.  As when to them who fail \r
+Beyond the Cape of Hope, and now are past \r
+Mozambick, off at sea north-east winds blow \r
+Sabean odours from the spicy shore \r
+Of Araby the blest; with such delay \r
+Well pleased they slack their course, and many a league \r
+Cheered with the grateful smell old Ocean smiles: \r
+So entertained those odorous sweets the Fiend, \r
+Who came their bane; though with them better pleased \r
+Than Asmodeus with the fishy fume \r
+That drove him, though enamoured, from the spouse \r
+Of Tobit's son, and with a vengeance sent \r
+From Media post to Egypt, there fast bound. \r
+Now to the ascent of that steep savage hill \r
+Satan had journeyed on, pensive and slow; \r
+But further way found none, so thick entwined, \r
+As one continued brake, the undergrowth \r
+Of shrubs and tangling bushes had perplexed \r
+All path of man or beast that passed that way. \r
+One gate there only was, and that looked east \r
+On the other side: which when the arch-felon saw, \r
+Due entrance he disdained; and, in contempt, \r
+At one flight bound high over-leaped all bound \r
+Of hill or highest wall, and sheer within \r
+Lights on his feet.  As when a prowling wolf, \r
+Whom hunger drives to seek new haunt for prey, \r
+Watching where shepherds pen their flocks at eve \r
+In hurdled cotes amid the field secure, \r
+Leaps o'er the fence with ease into the fold: \r
+Or as a thief, bent to unhoard the cash \r
+Of some rich burgher, whose substantial doors, \r
+Cross-barred and bolted fast, fear no assault, \r
+In at the window climbs, or o'er the tiles: \r
+So clomb this first grand thief into God's fold; \r
+So since into his church lewd hirelings climb. \r
+Thence up he flew, and on the tree of life, \r
+The middle tree and highest there that grew, \r
+Sat like a cormorant; yet not true life \r
+Thereby regained, but sat devising death \r
+To them who lived; nor on the virtue thought \r
+Of that life-giving plant, but only used \r
+For prospect, what well used had been the pledge \r
+Of immortality.  So little knows \r
+Any, but God alone, to value right \r
+The good before him, but perverts best things \r
+To worst abuse, or to their meanest use. \r
+Beneath him with new wonder now he views, \r
+To all delight of human sense exposed, \r
+In narrow room, Nature's whole wealth, yea more, \r
+A Heaven on Earth:  For blissful Paradise \r
+Of God the garden was, by him in the east \r
+Of Eden planted; Eden stretched her line \r
+From Auran eastward to the royal towers \r
+Of great Seleucia, built by Grecian kings, \r
+Of where the sons of Eden long before \r
+Dwelt in Telassar:  In this pleasant soil \r
+His far more pleasant garden God ordained; \r
+Out of the fertile ground he caused to grow \r
+All trees of noblest kind for sight, smell, taste; \r
+And all amid them stood the tree of life, \r
+High eminent, blooming ambrosial fruit \r
+Of vegetable gold; and next to life, \r
+Our death, the tree of knowledge, grew fast by, \r
+Knowledge of good bought dear by knowing ill. \r
+Southward through Eden went a river large, \r
+Nor changed his course, but through the shaggy hill \r
+Passed underneath ingulfed; for God had thrown \r
+That mountain as his garden-mould high raised \r
+Upon the rapid current, which, through veins \r
+Of porous earth with kindly thirst up-drawn, \r
+Rose a fresh fountain, and with many a rill \r
+Watered the garden; thence united fell \r
+Down the steep glade, and met the nether flood, \r
+Which from his darksome passage now appears, \r
+And now, divided into four main streams, \r
+Runs diverse, wandering many a famous realm \r
+And country, whereof here needs no account; \r
+But rather to tell how, if Art could tell, \r
+How from that sapphire fount the crisped brooks, \r
+Rolling on orient pearl and sands of gold, \r
+With mazy errour under pendant shades \r
+Ran nectar, visiting each plant, and fed \r
+Flowers worthy of Paradise, which not nice Art \r
+In beds and curious knots, but Nature boon \r
+Poured forth profuse on hill, and dale, and plain, \r
+Both where the morning sun first warmly smote \r
+The open field, and where the unpierced shade \r
+Imbrowned the noontide bowers:  Thus was this place \r
+A happy rural seat of various view; \r
+Groves whose rich trees wept odorous gums and balm, \r
+Others whose fruit, burnished with golden rind, \r
+Hung amiable, Hesperian fables true, \r
+If true, here only, and of delicious taste: \r
+Betwixt them lawns, or level downs, and flocks \r
+Grazing the tender herb, were interposed, \r
+Or palmy hillock; or the flowery lap \r
+Of some irriguous valley spread her store, \r
+Flowers of all hue, and without thorn the rose: \r
+Another side, umbrageous grots and caves \r
+Of cool recess, o'er which the mantling vine \r
+Lays forth her purple grape, and gently creeps \r
+Luxuriant; mean while murmuring waters fall \r
+Down the slope hills, dispersed, or in a lake, \r
+That to the fringed bank with myrtle crowned \r
+Her crystal mirrour holds, unite their streams. \r
+The birds their quire apply; airs, vernal airs, \r
+Breathing the smell of field and grove, attune \r
+The trembling leaves, while universal Pan, \r
+Knit with the Graces and the Hours in dance, \r
+Led on the eternal Spring.  Not that fair field \r
+Of Enna, where Proserpine gathering flowers, \r
+Herself a fairer flower by gloomy Dis \r
+Was gathered, which cost Ceres all that pain \r
+To seek her through the world; nor that sweet grove \r
+Of Daphne by Orontes, and the inspired \r
+Castalian spring, might with this Paradise \r
+Of Eden strive; nor that Nyseian isle \r
+Girt with the river Triton, where old Cham, \r
+Whom Gentiles Ammon call and Libyan Jove, \r
+Hid Amalthea, and her florid son \r
+Young Bacchus, from his stepdame Rhea's eye; \r
+Nor where Abassin kings their issue guard, \r
+Mount Amara, though this by some supposed \r
+True Paradise under the Ethiop line \r
+By Nilus' head, enclosed with shining rock, \r
+A whole day's journey high, but wide remote \r
+From this Assyrian garden, where the Fiend \r
+Saw, undelighted, all delight, all kind \r
+Of living creatures, new to sight, and strange \r
+Two of far nobler shape, erect and tall, \r
+Godlike erect, with native honour clad \r
+In naked majesty seemed lords of all: \r
+And worthy seemed; for in their looks divine \r
+The image of their glorious Maker shone, \r
+Truth, wisdom, sanctitude severe and pure, \r
+(Severe, but in true filial freedom placed,) \r
+Whence true authority in men; though both \r
+Not equal, as their sex not equal seemed; \r
+For contemplation he and valour formed; \r
+For softness she and sweet attractive grace; \r
+He for God only, she for God in him: \r
+His fair large front and eye sublime declared \r
+Absolute rule; and hyacinthine locks \r
+Round from his parted forelock manly hung \r
+Clustering, but not beneath his shoulders broad: \r
+She, as a veil, down to the slender waist \r
+Her unadorned golden tresses wore \r
+Dishevelled, but in wanton ringlets waved \r
+As the vine curls her tendrils, which implied \r
+Subjection, but required with gentle sway, \r
+And by her yielded, by him best received, \r
+Yielded with coy submission, modest pride, \r
+And sweet, reluctant, amorous delay. \r
+Nor those mysterious parts were then concealed; \r
+Then was not guilty shame, dishonest shame \r
+Of nature's works, honour dishonourable, \r
+Sin-bred, how have ye troubled all mankind \r
+With shows instead, mere shows of seeming pure, \r
+And banished from man's life his happiest life, \r
+Simplicity and spotless innocence! \r
+So passed they naked on, nor shunned the sight \r
+Of God or Angel; for they thought no ill: \r
+So hand in hand they passed, the loveliest pair, \r
+That ever since in love's embraces met; \r
+Adam the goodliest man of men since born \r
+His sons, the fairest of her daughters Eve. \r
+Under a tuft of shade that on a green \r
+Stood whispering soft, by a fresh fountain side \r
+They sat them down; and, after no more toil \r
+Of their sweet gardening labour than sufficed \r
+To recommend cool Zephyr, and made ease \r
+More easy, wholesome thirst and appetite \r
+More grateful, to their supper-fruits they fell, \r
+Nectarine fruits which the compliant boughs \r
+Yielded them, side-long as they sat recline \r
+On the soft downy bank damasked with flowers: \r
+The savoury pulp they chew, and in the rind, \r
+Still as they thirsted, scoop the brimming stream; \r
+Nor gentle purpose, nor endearing smiles \r
+Wanted, nor youthful dalliance, as beseems \r
+Fair couple, linked in happy nuptial league, \r
+Alone as they.  About them frisking played \r
+All beasts of the earth, since wild, and of all chase \r
+In wood or wilderness, forest or den; \r
+Sporting the lion ramped, and in his paw \r
+Dandled the kid; bears, tigers, ounces, pards, \r
+Gambolled before them; the unwieldy elephant, \r
+To make them mirth, used all his might, and wreathed \r
+His?kithetmroboscis; close the serpent sly, \r
+Insinuating, wove with Gordian twine \r
+His braided train, and of his fatal guile \r
+Gave proof unheeded; others on the grass \r
+Couched, and now filled with pasture gazing sat, \r
+Or bedward ruminating; for the sun, \r
+Declined, was hasting now with prone career \r
+To the ocean isles, and in the ascending scale \r
+Of Heaven the stars that usher evening rose: \r
+When Satan still in gaze, as first he stood, \r
+Scarce thus at length failed speech recovered sad. \r
+O Hell! what do mine eyes with grief behold! \r
+Into our room of bliss thus high advanced \r
+Creatures of other mould, earth-born perhaps, \r
+Not Spirits, yet to heavenly Spirits bright \r
+Little inferiour; whom my thoughts pursue \r
+With wonder, and could love, so lively shines \r
+In them divine resemblance, and such grace \r
+The hand that formed them on their shape hath poured. \r
+Ah! gentle pair, ye little think how nigh \r
+Your change approaches, when all these delights \r
+Will vanish, and deliver ye to woe; \r
+More woe, the more your taste is now of joy; \r
+Happy, but for so happy ill secured \r
+Long to continue, and this high seat your Heaven \r
+Ill fenced for Heaven to keep out such a foe \r
+As now is entered; yet no purposed foe \r
+To you, whom I could pity thus forlorn, \r
+Though I unpitied:  League with you I seek, \r
+And mutual amity, so strait, so close, \r
+That I with you must dwell, or you with me \r
+Henceforth; my dwelling haply may not please, \r
+Like this fair Paradise, your sense; yet such \r
+Accept your Maker's work; he gave it me, \r
+Which I as freely give:  Hell shall unfold, \r
+To entertain you two, her widest gates, \r
+And send forth all her kings; there will be room, \r
+Not like these narrow limits, to receive \r
+Your numerous offspring; if no better place, \r
+Thank him who puts me loth to this revenge \r
+On you who wrong me not for him who wronged. \r
+And should I at your harmless innocence \r
+Melt, as I do, yet publick reason just, \r
+Honour and empire with revenge enlarged, \r
+By conquering this new world, compels me now \r
+To do what else, though damned, I should abhor. \r
+So spake the Fiend, and with necessity, \r
+The tyrant's plea, excused his devilish deeds. \r
+Then from his lofty stand on that high tree \r
+Down he alights among the sportful herd \r
+Of those four-footed kinds, himself now one, \r
+Now other, as their shape served best his end \r
+Nearer to view his prey, and, unespied, \r
+To mark what of their state he more might learn, \r
+By word or action marked. About them round \r
+A lion now he stalks with fiery glare; \r
+Then as a tiger, who by chance hath spied \r
+In some purlieu two gentle fawns at play, \r
+Straight couches close, then, rising, changes oft \r
+His couchant watch, as one who chose his ground, \r
+Whence rushing, he might surest seize them both, \r
+Griped in each paw: when, Adam first of men \r
+To first of women Eve thus moving speech, \r
+Turned him, all ear to hear new utterance flow. \r
+Sole partner, and sole part, of all these joys, \r
+Dearer thyself than all; needs must the Power \r
+That made us, and for us this ample world, \r
+Be infinitely good, and of his good \r
+As liberal and free as infinite; \r
+That raised us from the dust, and placed us here \r
+In all this happiness, who at his hand \r
+Have nothing merited, nor can perform \r
+Aught whereof he hath need; he who requires \r
+From us no other service than to keep \r
+This one, this easy charge, of all the trees \r
+In Paradise that bear delicious fruit \r
+So various, not to taste that only tree \r
+Of knowledge, planted by the tree of life; \r
+So near grows death to life, whate'er death is, \r
+Some dreadful thing no doubt; for well thou knowest \r
+God hath pronounced it death to taste that tree, \r
+The only sign of our obedience left, \r
+Among so many signs of power and rule \r
+Conferred upon us, and dominion given \r
+Over all other creatures that possess \r
+Earth, air, and sea.  Then let us not think hard \r
+One easy prohibition, who enjoy \r
+Free leave so large to all things else, and choice \r
+Unlimited of manifold delights: \r
+But let us ever praise him, and extol \r
+His bounty, following our delightful task, \r
+To prune these growing plants, and tend these flowers, \r
+Which were it toilsome, yet with thee were sweet. \r
+To whom thus Eve replied.  O thou for whom \r
+And from whom I was formed, flesh of thy flesh, \r
+And without whom am to no end, my guide \r
+And head! what thou hast said is just and right. \r
+For we to him indeed all praises owe, \r
+And daily thanks; I chiefly, who enjoy \r
+So far the happier lot, enjoying thee \r
+Pre-eminent by so much odds, while thou \r
+Like consort to thyself canst no where find. \r
+That day I oft remember, when from sleep \r
+I first awaked, and found myself reposed \r
+Under a shade on flowers, much wondering where \r
+And what I was, whence thither brought, and how. \r
+Not distant far from thence a murmuring sound \r
+Of waters issued from a cave, and spread \r
+Into a liquid plain, then stood unmoved \r
+Pure as the expanse of Heaven; I thither went \r
+With unexperienced thought, and laid me down \r
+On the green bank, to look into the clear \r
+Smooth lake, that to me seemed another sky. \r
+As I bent down to look, just opposite \r
+A shape within the watery gleam appeared, \r
+Bending to look on me:  I started back, \r
+It started back; but pleased I soon returned, \r
+Pleased it returned as soon with answering looks \r
+Of sympathy and love:  There I had fixed \r
+Mine eyes till now, and pined with vain desire, \r
+Had not a voice thus warned me;  'What thou seest, \r
+'What there thou seest, fair Creature, is thyself; \r
+'With thee it came and goes: but follow me, \r
+'And I will bring thee where no shadow stays \r
+'Thy coming, and thy soft embraces, he \r
+'Whose image thou art; him thou shalt enjoy \r
+'Inseparably thine, to him shalt bear \r
+'Multitudes like thyself, and thence be called \r
+'Mother of human race.'  What could I do, \r
+But follow straight, invisibly thus led? \r
+Till I espied thee, fair indeed and tall, \r
+Under a platane; yet methought less fair, \r
+Less winning soft, less amiably mild, \r
+Than that smooth watery image:  Back I turned; \r
+Thou following cryedst aloud, 'Return, fair Eve; \r
+'Whom flyest thou?  whom thou flyest, of him thou art, \r
+'His flesh, his bone; to give thee being I lent \r
+'Out of my side to thee, nearest my heart, \r
+'Substantial life, to have thee by my side \r
+'Henceforth an individual solace dear; \r
+'Part of my soul I seek thee, and thee claim \r
+'My other half:'  With that thy gentle hand \r
+Seised mine:  I yielded;and from that time see \r
+How beauty is excelled by manly grace, \r
+And wisdom, which alone is truly fair. \r
+So spake our general mother, and with eyes \r
+Of conjugal attraction unreproved, \r
+And meek surrender, half-embracing leaned \r
+On our first father; half her swelling breast \r
+Naked met his, under the flowing gold \r
+Of her loose tresses hid: he in delight \r
+Both of her beauty, and submissive charms, \r
+Smiled with superiour love, as Jupiter \r
+On Juno smiles, when he impregns the clouds \r
+That shed Mayflowers; and pressed her matron lip \r
+With kisses pure:  Aside the Devil turned \r
+For envy; yet with jealous leer malign \r
+Eyed them askance, and to himself thus plained. \r
+Sight hateful, sight tormenting! thus these two, \r
+Imparadised in one another's arms, \r
+The happier Eden, shall enjoy their fill \r
+Of bliss on bliss; while I to Hell am thrust, \r
+Where neither joy nor love, but fierce desire, \r
+Among our other torments not the least, \r
+Still unfulfilled with pain of longing pines. \r
+Yet let me not forget what I have gained \r
+From their own mouths:  All is not theirs, it seems; \r
+One fatal tree there stands, of knowledge called, \r
+Forbidden them to taste:  Knowledge forbidden \r
+Suspicious, reasonless.  Why should their Lord \r
+Envy them that?  Can it be sin to know? \r
+Can it be death?  And do they only stand \r
+By ignorance?  Is that their happy state, \r
+The proof of their obedience and their faith? \r
+O fair foundation laid whereon to build \r
+Their ruin! hence I will excite their minds \r
+With more desire to know, and to reject \r
+Envious commands, invented with design \r
+To keep them low, whom knowledge might exalt \r
+Equal with Gods: aspiring to be such, \r
+They taste and die:  What likelier can ensue \r
+But first with narrow search I must walk round \r
+This garden, and no corner leave unspied; \r
+A chance but chance may lead where I may meet \r
+Some wandering Spirit of Heaven by fountain side, \r
+Or in thick shade retired, from him to draw \r
+What further would be learned.  Live while ye may, \r
+Yet happy pair; enjoy, till I return, \r
+Short pleasures, for long woes are to succeed! \r
+So saying, his proud step he scornful turned, \r
+But with sly circumspection, and began \r
+Through wood, through waste, o'er hill, o'er dale, his roam \r
+Mean while in utmost longitude, where Heaven \r
+With earth and ocean meets, the setting sun \r
+Slowly descended, and with right aspect \r
+Against the eastern gate of Paradise \r
+Levelled his evening rays:  It was a rock \r
+Of alabaster, piled up to the clouds, \r
+Conspicuous far, winding with one ascent \r
+Accessible from earth, one entrance high; \r
+The rest was craggy cliff, that overhung \r
+Still as it rose, impossible to climb. \r
+Betwixt these rocky pillars Gabriel sat, \r
+Chief of the angelick guards, awaiting night; \r
+About him exercised heroick games \r
+The unarmed youth of Heaven, but nigh at hand \r
+Celestial armoury, shields, helms, and spears, \r
+Hung high with diamond flaming, and with gold. \r
+Thither came Uriel, gliding through the even \r
+On a sun-beam, swift as a shooting star \r
+In autumn thwarts the night, when vapours fired \r
+Impress the air, and shows the mariner \r
+From what point of his compass to beware \r
+Impetuous winds:  He thus began in haste. \r
+Gabriel, to thee thy course by lot hath given \r
+Charge and strict watch, that to this happy place \r
+No evil thing approach or enter in. \r
+This day at highth of noon came to my sphere \r
+A Spirit, zealous, as he seemed, to know \r
+More of the Almighty's works, and chiefly Man, \r
+God's latest image:  I described his way \r
+Bent all on speed, and marked his aery gait; \r
+But in the mount that lies from Eden north, \r
+Where he first lighted, soon discerned his looks \r
+Alien from Heaven, with passions foul obscured: \r
+Mine eye pursued him still, but under shade \r
+Lost sight of him:  One of the banished crew, \r
+I fear, hath ventured from the deep, to raise \r
+New troubles; him thy care must be to find. \r
+To whom the winged warriour thus returned. \r
+Uriel, no wonder if thy perfect sight, \r
+Amid the sun's bright circle where thou sitst, \r
+See far and wide:  In at this gate none pass \r
+The vigilance here placed, but such as come \r
+Well known from Heaven; and since meridian hour \r
+No creature thence:  If Spirit of other sort, \r
+So minded, have o'er-leaped these earthly bounds \r
+On purpose, hard thou knowest it to exclude \r
+Spiritual substance with corporeal bar. \r
+But if within the circuit of these walks, \r
+In whatsoever shape he lurk, of whom \r
+Thou tellest, by morrow dawning I shall know. \r
+So promised he; and Uriel to his charge \r
+Returned on that bright beam, whose point now raised \r
+Bore him slope downward to the sun now fallen \r
+Beneath the Azores; whether the prime orb, \r
+Incredible how swift, had thither rolled \r
+Diurnal, or this less volubil earth, \r
+By shorter flight to the east, had left him there \r
+Arraying with reflected purple and gold \r
+The clouds that on his western throne attend. \r
+Now came still Evening on, and Twilight gray \r
+Had in her sober livery all things clad; \r
+Silence accompanied; for beast and bird, \r
+They to their grassy couch, these to their nests \r
+Were slunk, all but the wakeful nightingale; \r
+She all night long her amorous descant sung; \r
+Silence was pleased:  Now glowed the firmament \r
+With living sapphires:  Hesperus, that led \r
+The starry host, rode brightest, till the moon, \r
+Rising in clouded majesty, at length \r
+Apparent queen unveiled her peerless light, \r
+And o'er the dark her silver mantle threw. \r
+When Adam thus to Eve.  Fair Consort, the hour \r
+Of night, and all things now retired to rest, \r
+Mind us of like repose; since God hath set \r
+Labour and rest, as day and night, to men \r
+Successive; and the timely dew of sleep, \r
+Now falling with soft slumbrous weight, inclines \r
+Our eye-lids:  Other creatures all day long \r
+Rove idle, unemployed, and less need rest; \r
+Man hath his daily work of body or mind \r
+Appointed, which declares his dignity, \r
+And the regard of Heaven on all his ways; \r
+While other animals unactive range, \r
+And of their doings God takes no account. \r
+To-morrow, ere fresh morning streak the east \r
+With first approach of light, we must be risen, \r
+And at our pleasant labour, to reform \r
+Yon flowery arbours, yonder alleys green, \r
+Our walk at noon, with branches overgrown, \r
+That mock our scant manuring, and require \r
+More hands than ours to lop their wanton growth: \r
+Those blossoms also, and those dropping gums, \r
+That lie bestrown, unsightly and unsmooth, \r
+Ask riddance, if we mean to tread with ease; \r
+Mean while, as Nature wills, night bids us rest. \r
+To whom thus Eve, with perfect beauty adorned \r
+My Author and Disposer, what thou bidst \r
+Unargued I obey:  So God ordains; \r
+God is thy law, thou mine:  To know no more \r
+Is woman's happiest knowledge, and her praise. \r
+With thee conversing I forget all time; \r
+All seasons, and their change, all please alike. \r
+Sweet is the breath of Morn, her rising sweet, \r
+With charm of earliest birds:  pleasant the sun, \r
+When first on this delightful land he spreads \r
+His orient beams, on herb, tree, fruit, and flower, \r
+Glistering with dew; fragrant the fertile earth \r
+After soft showers; and sweet the coming on \r
+Of grateful Evening mild; then silent Night, \r
+With this her solemn bird, and this fair moon, \r
+And these the gems of Heaven, her starry train: \r
+But neither breath of Morn, when she ascends \r
+With charm of earliest birds; nor rising sun \r
+On this delightful land; nor herb, fruit, flower, \r
+Glistering with dew; nor fragrance after showers; \r
+Nor grateful Evening mild; nor silent Night, \r
+With this her solemn bird, nor walk by moon, \r
+Or glittering star-light, without thee is sweet. \r
+But wherefore all night long shine these? for whom \r
+This glorious sight, when sleep hath shut all eyes? \r
+To whom our general ancestor replied. \r
+Daughter of God and Man, accomplished Eve, \r
+These have their course to finish round the earth, \r
+By morrow evening, and from land to land \r
+In order, though to nations yet unborn, \r
+Ministring light prepared, they set and rise; \r
+Lest total Darkness should by night regain \r
+Her old possession, and extinguish life \r
+In Nature and all things; which these soft fires \r
+Not only enlighten, but with kindly heat \r
+Of various influence foment and warm, \r
+Temper or nourish, or in part shed down \r
+Their stellar virtue on all kinds that grow \r
+On earth, made hereby apter to receive \r
+Perfection from the sun's more potent ray. \r
+These then, though unbeheld in deep of night, \r
+Shine not in vain; nor think, though men were none, \r
+That Heaven would want spectators, God want praise: \r
+Millions of spiritual creatures walk the earth \r
+Unseen, both when we wake, and when we sleep: \r
+All these with ceaseless praise his works behold \r
+Both day and night:  How often from the steep \r
+Of echoing hill or thicket have we heard \r
+Celestial voices to the midnight air, \r
+Sole, or responsive each to others note, \r
+Singing their great Creator? oft in bands \r
+While they keep watch, or nightly rounding walk, \r
+With heavenly touch of instrumental sounds \r
+In full harmonick number joined, their songs \r
+Divide the night, and lift our thoughts to Heaven. \r
+Thus talking, hand in hand alone they passed \r
+On to their blissful bower: it was a place \r
+Chosen by the sovran Planter, when he framed \r
+All things to Man's delightful use; the roof \r
+Of thickest covert was inwoven shade \r
+Laurel and myrtle, and what higher grew \r
+Of firm and fragrant leaf; on either side \r
+Acanthus, and each odorous bushy shrub, \r
+Fenced up the verdant wall; each beauteous flower, \r
+Iris all hues, roses, and jessamin, \r
+Reared high their flourished heads between, and wrought \r
+Mosaick; underfoot the violet, \r
+Crocus, and hyacinth, with rich inlay \r
+Broidered the ground, more coloured than with stone \r
+Of costliest emblem:  Other creature here, \r
+Bird, beast, insect, or worm, durst enter none, \r
+Such was their awe of Man.  In shadier bower \r
+More sacred and sequestered, though but feigned, \r
+Pan or Sylvanus never slept, nor Nymph \r
+Nor Faunus haunted.  Here, in close recess, \r
+With flowers, garlands, and sweet-smelling herbs, \r
+Espoused Eve decked first her nuptial bed; \r
+And heavenly quires the hymenaean sung, \r
+What day the genial Angel to our sire \r
+Brought her in naked beauty more adorned, \r
+More lovely, than Pandora, whom the Gods \r
+Endowed with all their gifts, and O! too like \r
+In sad event, when to the unwiser son \r
+Of Japhet brought by Hermes, she ensnared \r
+Mankind with her fair looks, to be avenged \r
+On him who had stole Jove's authentick fire. \r
+Thus, at their shady lodge arrived, both stood, \r
+Both turned, and under open sky adored \r
+The God that made both sky, air, earth, and heaven, \r
+Which they beheld, the moon's resplendent globe, \r
+And starry pole:  Thou also madest the night, \r
+Maker Omnipotent, and thou the day, \r
+Which we, in our appointed work employed, \r
+Have finished, happy in our mutual help \r
+And mutual love, the crown of all our bliss \r
+Ordained by thee; and this delicious place \r
+For us too large, where thy abundance wants \r
+Partakers, and uncropt falls to the ground. \r
+But thou hast promised from us two a race \r
+To fill the earth, who shall with us extol \r
+Thy goodness infinite, both when we wake, \r
+And when we seek, as now, thy gift of sleep. \r
+This said unanimous, and other rites \r
+Observing none, but adoration pure \r
+Which God likes best, into their inmost bower \r
+Handed they went; and, eased the putting off \r
+These troublesome disguises which we wear, \r
+Straight side by side were laid; nor turned, I ween, \r
+Adam from his fair spouse, nor Eve the rites \r
+Mysterious of connubial love refused: \r
+Whatever hypocrites austerely talk \r
+Of purity, and place, and innocence, \r
+Defaming as impure what God declares \r
+Pure, and commands to some, leaves free to all. \r
+Our Maker bids encrease; who bids abstain \r
+But our Destroyer, foe to God and Man? \r
+Hail, wedded Love, mysterious law, true source \r
+Of human offspring, sole propriety \r
+In Paradise of all things common else! \r
+By thee adulterous Lust was driven from men \r
+Among the bestial herds to range; by thee \r
+Founded in reason, loyal, just, and pure, \r
+Relations dear, and all the charities \r
+Of father, son, and brother, first were known. \r
+Far be it, that I should write thee sin or blame, \r
+Or think thee unbefitting holiest place, \r
+Perpetual fountain of domestick sweets, \r
+Whose bed is undefiled and chaste pronounced, \r
+Present, or past, as saints and patriarchs used. \r
+Here Love his golden shafts employs, here lights \r
+His constant lamp, and waves his purple wings, \r
+Reigns here and revels; not in the bought smile \r
+Of harlots, loveless, joyless, unendeared, \r
+Casual fruition; nor in court-amours, \r
+Mixed dance, or wanton mask, or midnight ball, \r
+Or serenate, which the starved lover sings \r
+To his proud fair, best quitted with disdain. \r
+These, lulled by nightingales, embracing slept, \r
+And on their naked limbs the flowery roof \r
+Showered roses, which the morn repaired.  Sleep on, \r
+Blest pair; and O!yet happiest, if ye seek \r
+No happier state, and know to know no more. \r
+Now had night measured with her shadowy cone \r
+Half way up hill this vast sublunar vault, \r
+And from their ivory port the Cherubim, \r
+Forth issuing at the accustomed hour, stood armed \r
+To their night watches in warlike parade; \r
+When Gabriel to his next in power thus spake. \r
+Uzziel, half these draw off, and coast the south \r
+With strictest watch; these other wheel the north; \r
+Our circuit meets full west.  As flame they part, \r
+Half wheeling to the shield, half to the spear. \r
+From these, two strong and subtle Spirits he called \r
+That near him stood, and gave them thus in charge. \r
+Ithuriel and Zephon, with winged speed \r
+Search through this garden, leave unsearched no nook; \r
+But chiefly where those two fair creatures lodge, \r
+Now laid perhaps asleep, secure of harm. \r
+This evening from the sun's decline arrived, \r
+Who tells of some infernal Spirit seen \r
+Hitherward bent (who could have thought?) escaped \r
+The bars of Hell, on errand bad no doubt: \r
+Such, where ye find, seise fast, and hither bring. \r
+So saying, on he led his radiant files, \r
+Dazzling the moon; these to the bower direct \r
+In search of whom they sought:  Him there they found \r
+Squat like a toad, close at the ear of Eve, \r
+Assaying by his devilish art to reach \r
+The organs of her fancy, and with them forge \r
+Illusions, as he list, phantasms and dreams; \r
+Or if, inspiring venom, he might taint \r
+The animal spirits, that from pure blood arise \r
+Like gentle breaths from rivers pure, thence raise \r
+At least distempered, discontented thoughts, \r
+Vain hopes, vain aims, inordinate desires, \r
+Blown up with high conceits ingendering pride. \r
+Him thus intent Ithuriel with his spear \r
+Touched lightly; for no falshood can endure \r
+Touch of celestial temper, but returns \r
+Of force to its own likeness:  Up he starts \r
+Discovered and surprised.  As when a spark \r
+Lights on a heap of nitrous powder, laid \r
+Fit for the tun some magazine to store \r
+Against a rumoured war, the smutty grain, \r
+With sudden blaze diffused, inflames the air; \r
+So started up in his own shape the Fiend. \r
+Back stept those two fair Angels, half amazed \r
+So sudden to behold the grisly king; \r
+Yet thus, unmoved with fear, accost him soon. \r
+Which of those rebel Spirits adjudged to Hell \r
+Comest thou, escaped thy prison? and, transformed, \r
+Why sat'st thou like an enemy in wait, \r
+Here watching at the head of these that sleep? \r
+Know ye not then said Satan, filled with scorn, \r
+Know ye not me? ye knew me once no mate \r
+For you, there sitting where ye durst not soar: \r
+Not to know me argues yourselves unknown, \r
+The lowest of your throng; or, if ye know, \r
+Why ask ye, and superfluous begin \r
+Your message, like to end as much in vain? \r
+To whom thus Zephon, answering scorn with scorn. \r
+Think not, revolted Spirit, thy shape the same, \r
+Or undiminished brightness to be known, \r
+As when thou stoodest in Heaven upright and pure; \r
+That glory then, when thou no more wast good, \r
+Departed from thee; and thou resemblest now \r
+Thy sin and place of doom obscure and foul. \r
+But come, for thou, be sure, shalt give account \r
+To him who sent us, whose charge is to keep \r
+This place inviolable, and these from harm. \r
+So spake the Cherub; and his grave rebuke, \r
+Severe in youthful beauty, added grace \r
+Invincible:  Abashed the Devil stood, \r
+And felt how awful goodness is, and saw \r
+Virtue in her shape how lovely; saw, and pined \r
+His loss; but chiefly to find here observed \r
+His lustre visibly impaired; yet seemed \r
+Undaunted.  If I must contend, said he, \r
+Best with the best, the sender, not the sent, \r
+Or all at once; more glory will be won, \r
+Or less be lost.  Thy fear, said Zephon bold, \r
+Will save us trial what the least can do \r
+Single against thee wicked, and thence weak. \r
+The Fiend replied not, overcome with rage; \r
+But, like a proud steed reined, went haughty on, \r
+Champing his iron curb:  To strive or fly \r
+He held it vain; awe from above had quelled \r
+His heart, not else dismayed.  Now drew they nigh \r
+The western point, where those half-rounding guards \r
+Just met, and closing stood in squadron joined, \r
+A waiting next command.  To whom their Chief, \r
+Gabriel, from the front thus called aloud. \r
+O friends!  I hear the tread of nimble feet \r
+Hasting this way, and now by glimpse discern \r
+Ithuriel and Zephon through the shade; \r
+And with them comes a third of regal port, \r
+But faded splendour wan; who by his gait \r
+And fierce demeanour seems the Prince of Hell, \r
+Not likely to part hence without contest; \r
+Stand firm, for in his look defiance lours. \r
+He scarce had ended, when those two approached, \r
+And brief related whom they brought, where found, \r
+How busied, in what form and posture couched. \r
+To whom with stern regard thus Gabriel spake. \r
+Why hast thou, Satan, broke the bounds prescribed \r
+To thy transgressions, and disturbed the charge \r
+Of others, who approve not to transgress \r
+By thy example, but have power and right \r
+To question thy bold entrance on this place; \r
+Employed, it seems, to violate sleep, and those \r
+Whose dwelling God hath planted here in bliss! \r
+To whom thus Satan with contemptuous brow. \r
+Gabriel? thou hadst in Heaven the esteem of wise, \r
+And such I held thee; but this question asked \r
+Puts me in doubt.  Lives there who loves his pain! \r
+Who would not, finding way, break loose from Hell, \r
+Though thither doomed!  Thou wouldst thyself, no doubt \r
+And boldly venture to whatever place \r
+Farthest from pain, where thou mightst hope to change \r
+Torment with ease, and soonest recompense \r
+Dole with delight, which in this place I sought; \r
+To thee no reason, who knowest only good, \r
+But evil hast not tried: and wilt object \r
+His will who bounds us!  Let him surer bar \r
+His iron gates, if he intends our stay \r
+In that dark durance:  Thus much what was asked. \r
+The rest is true, they found me where they say; \r
+But that implies not violence or harm. \r
+Thus he in scorn.  The warlike Angel moved, \r
+Disdainfully half smiling, thus replied. \r
+O loss of one in Heaven to judge of wise \r
+Since Satan fell, whom folly overthrew, \r
+And now returns him from his prison 'scaped, \r
+Gravely in doubt whether to hold them wise \r
+Or not, who ask what boldness brought him hither \r
+Unlicensed from his bounds in Hell prescribed; \r
+So wise he judges it to fly from pain \r
+However, and to 'scape his punishment! \r
+So judge thou still, presumptuous! till the wrath, \r
+Which thou incurrest by flying, meet thy flight \r
+Sevenfold, and scourge that wisdom back to Hell, \r
+Which taught thee yet no better, that no pain \r
+Can equal anger infinite provoked. \r
+But wherefore thou alone? wherefore with thee \r
+Came not all hell broke loose? or thou than they \r
+Less hardy to endure?  Courageous Chief! \r
+The first in flight from pain! hadst thou alleged \r
+To thy deserted host this cause of flight, \r
+Thou surely hadst not come sole fugitive. \r
+To which the Fiend thus answered, frowning stern. \r
+Not that I less endure, or shrink from pain, \r
+Insulting Angel! well thou knowest I stood \r
+Thy fiercest, when in battle to thy aid \r
+The blasting vollied thunder made all speed, \r
+And seconded thy else not dreaded spear. \r
+But still thy words at random, as before, \r
+Argue thy inexperience what behoves \r
+From hard assays and ill successes past \r
+A faithful leader, not to hazard all \r
+Through ways of danger by himself untried: \r
+I, therefore, I alone first undertook \r
+To wing the desolate abyss, and spy \r
+This new created world, whereof in Hell \r
+Fame is not silent, here in hope to find \r
+Better abode, and my afflicted Powers \r
+To settle here on earth, or in mid air; \r
+Though for possession put to try once more \r
+What thou and thy gay legions dare against; \r
+Whose easier business were to serve their Lord \r
+High up in Heaven, with songs to hymn his throne, \r
+And practised distances to cringe, not fight, \r
+To whom the warriour Angel soon replied. \r
+To say and straight unsay, pretending first \r
+Wise to fly pain, professing next the spy, \r
+Argues no leader but a liear traced, \r
+Satan, and couldst thou faithful add?  O name, \r
+O sacred name of faithfulness profaned! \r
+Faithful to whom? to thy rebellious crew? \r
+Army of Fiends, fit body to fit head. \r
+Was this your discipline and faith engaged, \r
+Your military obedience, to dissolve \r
+Allegiance to the acknowledged Power supreme? \r
+And thou, sly hypocrite, who now wouldst seem \r
+Patron of liberty, who more than thou \r
+Once fawned, and cringed, and servily adored \r
+Heaven's awful Monarch? wherefore, but in hope \r
+To dispossess him, and thyself to reign? \r
+But mark what I arreed thee now, Avant; \r
+Fly neither whence thou fledst!  If from this hour \r
+Within these hallowed limits thou appear, \r
+Back to the infernal pit I drag thee chained, \r
+And seal thee so, as henceforth not to scorn \r
+The facile gates of Hell too slightly barred. \r
+So threatened he; but Satan to no threats \r
+Gave heed, but waxing more in rage replied. \r
+Then when I am thy captive talk of chains, \r
+Proud limitary Cherub! but ere then \r
+Far heavier load thyself expect to feel \r
+From my prevailing arm, though Heaven's King \r
+Ride on thy wings, and thou with thy compeers, \r
+Us'd to the yoke, drawest his triumphant wheels \r
+In progress through the road of Heaven star-paved. \r
+While thus he spake, the angelick squadron bright \r
+Turned fiery red, sharpening in mooned horns \r
+Their phalanx, and began to hem him round \r
+With ported spears, as thick as when a field \r
+Of Ceres ripe for harvest waving bends \r
+Her bearded grove of ears, which way the wind \r
+Sways them; the careful plowman doubting stands, \r
+Left on the threshing floor his hopeless sheaves \r
+Prove chaff.  On the other side, Satan, alarmed, \r
+Collecting all his might, dilated stood, \r
+Like Teneriff or Atlas, unremoved: \r
+His stature reached the sky, and on his crest \r
+Sat Horrour plumed; nor wanted in his grasp \r
+What seemed both spear and shield:  Now dreadful deeds \r
+Might have ensued, nor only Paradise \r
+In this commotion, but the starry cope \r
+Of Heaven perhaps, or all the elements \r
+At least had gone to wrack, disturbed and torn \r
+With violence of this conflict, had not soon \r
+The Eternal, to prevent such horrid fray, \r
+Hung forth in Heaven his golden scales, yet seen \r
+Betwixt Astrea and the Scorpion sign, \r
+Wherein all things created first he weighed, \r
+The pendulous round earth with balanced air \r
+In counterpoise, now ponders all events, \r
+Battles and realms:  In these he put two weights, \r
+The sequel each of parting and of fight: \r
+The latter quick up flew, and kicked the beam, \r
+Which Gabriel spying, thus bespake the Fiend. \r
+Satan, I know thy strength, and thou knowest mine; \r
+Neither our own, but given:  What folly then \r
+To boast what arms can do? since thine no more \r
+Than Heaven permits, nor mine, though doubled now \r
+To trample thee as mire:  For proof look up, \r
+And read thy lot in yon celestial sign; \r
+Where thou art weighed, and shown how light, how weak, \r
+If thou resist.  The Fiend looked up, and knew \r
+His mounted scale aloft:  Nor more;but fled \r
+Murmuring, and with him fled the shades of night. \r
\r
\r
\r
+Book V                                                           \r
\r
\r
+Now Morn, her rosy steps in the eastern clime \r
+Advancing, sowed the earth with orient pearl, \r
+When Adam waked, so customed; for his sleep \r
+Was aery-light, from pure digestion bred, \r
+And temperate vapours bland, which the only sound \r
+Of leaves and fuming rills, Aurora's fan, \r
+Lightly dispersed, and the shrill matin song \r
+Of birds on every bough; so much the more \r
+His wonder was to find unwakened Eve \r
+With tresses discomposed, and glowing cheek, \r
+As through unquiet rest:  He, on his side \r
+Leaning half raised, with looks of cordial love \r
+Hung over her enamoured, and beheld \r
+Beauty, which, whether waking or asleep, \r
+Shot forth peculiar graces; then with voice \r
+Mild, as when Zephyrus on Flora breathes, \r
+Her hand soft touching, whispered thus.  Awake, \r
+My fairest, my espoused, my latest found, \r
+Heaven's last best gift, my ever new delight! \r
+Awake:  The morning shines, and the fresh field \r
+Calls us; we lose the prime, to mark how spring \r
+Our tender plants, how blows the citron grove, \r
+What drops the myrrh, and what the balmy reed, \r
+How nature paints her colours, how the bee \r
+Sits on the bloom extracting liquid sweet. \r
+Such whispering waked her, but with startled eye \r
+On Adam, whom embracing, thus she spake. \r
+O sole in whom my thoughts find all repose, \r
+My glory, my perfection! glad I see \r
+Thy face, and morn returned; for I this night \r
+(Such night till this I never passed) have dreamed, \r
+If dreamed, not, as I oft am wont, of thee, \r
+Works of day past, or morrow's next design, \r
+But of offence and trouble, which my mind \r
+Knew never till this irksome night:  Methought, \r
+Close at mine ear one called me forth to walk \r
+With gentle voice;  I thought it thine: It said, \r
+'Why sleepest thou, Eve? now is the pleasant time, \r
+'The cool, the silent, save where silence yields \r
+'To the night-warbling bird, that now awake \r
+'Tunes sweetest his love-laboured song; now reigns \r
+'Full-orbed the moon, and with more pleasing light \r
+'Shadowy sets off the face of things; in vain, \r
+'If none regard; Heaven wakes with all his eyes, \r
+'Whom to behold but thee, Nature's desire? \r
+'In whose sight all things joy, with ravishment \r
+'Attracted by thy beauty still to gaze.' \r
+I rose as at thy call, but found thee not; \r
+To find thee I directed then my walk; \r
+And on, methought, alone I passed through ways \r
+That brought me on a sudden to the tree \r
+Of interdicted knowledge: fair it seemed, \r
+Much fairer to my fancy than by day: \r
+And, as I wondering looked, beside it stood \r
+One shaped and winged like one of those from Heaven \r
+By us oft seen; his dewy locks distilled \r
+Ambrosia; on that tree he also gazed; \r
+And 'O fair plant,' said he, 'with fruit surcharged, \r
+'Deigns none to ease thy load, and taste thy sweet, \r
+'Nor God, nor Man?  Is knowledge so despised? \r
+'Or envy, or what reserve forbids to taste? \r
+'Forbid who will, none shall from me withhold \r
+'Longer thy offered good; why else set here? \r
+This said, he paused not, but with venturous arm \r
+He plucked, he tasted; me damp horrour chilled \r
+At such bold words vouched with a deed so bold: \r
+But he thus, overjoyed; 'O fruit divine, \r
+'Sweet of thyself, but much more sweet thus cropt, \r
+'Forbidden here, it seems, as only fit \r
+'For Gods, yet able to make Gods of Men: \r
+'And why not Gods of Men; since good, the more \r
+'Communicated, more abundant grows, \r
+'The author not impaired, but honoured more? \r
+'Here, happy creature, fair angelick Eve! \r
+'Partake thou also; happy though thou art, \r
+'Happier thou mayest be, worthier canst not be: \r
+'Taste this, and be henceforth among the Gods \r
+'Thyself a Goddess, not to earth confined, \r
+'But sometimes in the air, as we, sometimes \r
+'Ascend to Heaven, by merit thine, and see \r
+'What life the Gods live there, and such live thou!' \r
+So saying, he drew nigh, and to me held, \r
+Even to my mouth of that same fruit held part \r
+Which he had plucked; the pleasant savoury smell \r
+So quickened appetite, that I, methought, \r
+Could not but taste.  Forthwith up to the clouds \r
+With him I flew, and underneath beheld \r
+The earth outstretched immense, a prospect wide \r
+And various:  Wondering at my flight and change \r
+To this high exaltation; suddenly \r
+My guide was gone, and I, methought, sunk down, \r
+And fell asleep; but O, how glad I waked \r
+To find this but a dream!  Thus Eve her night \r
+Related, and thus Adam answered sad. \r
+Best image of myself, and dearer half, \r
+The trouble of thy thoughts this night in sleep \r
+Affects me equally; nor can I like \r
+This uncouth dream, of evil sprung, I fear; \r
+Yet evil whence? in thee can harbour none, \r
+Created pure.  But know that in the soul \r
+Are many lesser faculties, that serve \r
+Reason as chief; among these Fancy next \r
+Her office holds; of all external things \r
+Which the five watchful senses represent, \r
+She forms imaginations, aery shapes, \r
+Which Reason, joining or disjoining, frames \r
+All what we affirm or what deny, and call \r
+Our knowledge or opinion; then retires \r
+Into her private cell, when nature rests. \r
+Oft in her absence mimick Fancy wakes \r
+To imitate her; but, misjoining shapes, \r
+Wild work produces oft, and most in dreams; \r
+Ill matching words and deeds long past or late. \r
+Some such resemblances, methinks, I find \r
+Of our last evening's talk, in this thy dream, \r
+But with addition strange; yet be not sad. \r
+Evil into the mind of God or Man \r
+May come and go, so unreproved, and leave \r
+No spot or blame behind:  Which gives me hope \r
+That what in sleep thou didst abhor to dream, \r
+Waking thou never will consent to do. \r
+Be not disheartened then, nor cloud those looks, \r
+That wont to be more cheerful and serene, \r
+Than when fair morning first smiles on the world; \r
+And let us to our fresh employments rise \r
+Among the groves, the fountains, and the flowers \r
+That open now their choisest bosomed smells, \r
+Reserved from night, and kept for thee in store. \r
+So cheered he his fair spouse, and she was cheered; \r
+But silently a gentle tear let fall \r
+From either eye, and wiped them with her hair; \r
+Two other precious drops that ready stood, \r
+Each in their crystal sluice, he ere they fell \r
+Kissed, as the gracious signs of sweet remorse \r
+And pious awe, that feared to have offended. \r
+So all was cleared, and to the field they haste. \r
+But first, from under shady arborous roof \r
+Soon as they forth were come to open sight \r
+Of day-spring, and the sun, who, scarce up-risen, \r
+With wheels yet hovering o'er the ocean-brim, \r
+Shot parallel to the earth his dewy ray, \r
+Discovering in wide landskip all the east \r
+Of Paradise and Eden's happy plains, \r
+Lowly they bowed adoring, and began \r
+Their orisons, each morning duly paid \r
+In various style; for neither various style \r
+Nor holy rapture wanted they to praise \r
+Their Maker, in fit strains pronounced, or sung \r
+Unmeditated; such prompt eloquence \r
+Flowed from their lips, in prose or numerous verse, \r
+More tuneable than needed lute or harp \r
+To add more sweetness; and they thus began. \r
+These are thy glorious works, Parent of good, \r
+Almighty!  Thine this universal frame, \r
+Thus wonderous fair;  Thyself how wonderous then! \r
+Unspeakable, who sitst above these heavens \r
+To us invisible, or dimly seen \r
+In these thy lowest works; yet these declare \r
+Thy goodness beyond thought, and power divine. \r
+Speak, ye who best can tell, ye sons of light, \r
+Angels; for ye behold him, and with songs \r
+And choral symphonies, day without night, \r
+Circle his throne rejoicing; ye in Heaven \r
+On Earth join all ye Creatures to extol \r
+Him first, him last, him midst, and without end. \r
+Fairest of stars, last in the train of night, \r
+If better thou belong not to the dawn, \r
+Sure pledge of day, that crownest the smiling morn \r
+With thy bright circlet, praise him in thy sphere, \r
+While day arises, that sweet hour of prime. \r
+Thou Sun, of this great world both eye and soul, \r
+Acknowledge him thy greater; sound his praise \r
+In thy eternal course, both when thou climbest, \r
+And when high noon hast gained, and when thou fallest. \r
+Moon, that now meetest the orient sun, now flyest, \r
+With the fixed Stars, fixed in their orb that flies; \r
+And ye five other wandering Fires, that move \r
+In mystick dance not without song, resound \r
+His praise, who out of darkness called up light. \r
+Air, and ye Elements, the eldest birth \r
+Of Nature's womb, that in quaternion run \r
+Perpetual circle, multiform; and mix \r
+And nourish all things; let your ceaseless change \r
+Vary to our great Maker still new praise. \r
+Ye Mists and Exhalations, that now rise \r
+From hill or steaming lake, dusky or gray, \r
+Till the sun paint your fleecy skirts with gold, \r
+In honour to the world's great Author rise; \r
+Whether to deck with clouds the uncoloured sky, \r
+Or wet the thirsty earth with falling showers, \r
+Rising or falling still advance his praise. \r
+His praise, ye Winds, that from four quarters blow, \r
+Breathe soft or loud; and, wave your tops, ye Pines, \r
+With every plant, in sign of worship wave. \r
+Fountains, and ye that warble, as ye flow, \r
+Melodious murmurs, warbling tune his praise. \r
+Join voices, all ye living Souls:  Ye Birds, \r
+That singing up to Heaven-gate ascend, \r
+Bear on your wings and in your notes his praise. \r
+Ye that in waters glide, and ye that walk \r
+The earth, and stately tread, or lowly creep; \r
+Witness if I be silent, morn or even, \r
+To hill, or valley, fountain, or fresh shade, \r
+Made vocal by my song, and taught his praise. \r
+Hail, universal Lord, be bounteous still \r
+To give us only good; and if the night \r
+Have gathered aught of evil, or concealed, \r
+Disperse it, as now light dispels the dark! \r
+So prayed they innocent, and to their thoughts \r
+Firm peace recovered soon, and wonted calm. \r
+On to their morning's rural work they haste, \r
+Among sweet dews and flowers; where any row \r
+Of fruit-trees over-woody reached too far \r
+Their pampered boughs, and needed hands to check \r
+Fruitless embraces: or they led the vine \r
+To wed her elm; she, spoused, about him twines \r
+Her marriageable arms, and with him brings \r
+Her dower, the adopted clusters, to adorn \r
+His barren leaves.  Them thus employed beheld \r
+With pity Heaven's high King, and to him called \r
+Raphael, the sociable Spirit, that deigned \r
+To travel with Tobias, and secured \r
+His marriage with the seventimes-wedded maid. \r
+Raphael, said he, thou hearest what stir on Earth \r
+Satan, from Hell 'scaped through the darksome gulf, \r
+Hath raised in Paradise; and how disturbed \r
+This night the human pair; how he designs \r
+In them at once to ruin all mankind. \r
+Go therefore, half this day as friend with friend \r
+Converse with Adam, in what bower or shade \r
+Thou findest him from the heat of noon retired, \r
+To respite his day-labour with repast, \r
+Or with repose; and such discourse bring on, \r
+As may advise him of his happy state, \r
+Happiness in his power left free to will, \r
+Left to his own free will, his will though free, \r
+Yet mutable; whence warn him to beware \r
+He swerve not, too secure:  Tell him withal \r
+His danger, and from whom; what enemy, \r
+Late fallen himself from Heaven, is plotting now \r
+The fall of others from like state of bliss; \r
+By violence? no, for that shall be withstood; \r
+But by deceit and lies:  This let him know, \r
+Lest, wilfully transgressing, he pretend \r
+Surprisal, unadmonished, unforewarned. \r
+So spake the Eternal Father, and fulfilled \r
+All justice:  Nor delayed the winged Saint \r
+After his charge received; but from among \r
+Thousand celestial Ardours, where he stood \r
+Veiled with his gorgeous wings, up springing light, \r
+Flew through the midst of Heaven; the angelick quires, \r
+On each hand parting, to his speed gave way \r
+Through all the empyreal road; till, at the gate \r
+Of Heaven arrived, the gate self-opened wide \r
+On golden hinges turning, as by work \r
+Divine the sovran Architect had framed. \r
+From hence no cloud, or, to obstruct his sight, \r
+Star interposed, however small he sees, \r
+Not unconformed to other shining globes, \r
+Earth, and the garden of God, with cedars crowned \r
+Above all hills.  As when by night the glass \r
+Of Galileo, less assured, observes \r
+Imagined lands and regions in the moon: \r
+Or pilot, from amidst the Cyclades \r
+Delos or Samos first appearing, kens \r
+A cloudy spot.  Down thither prone in flight \r
+He speeds, and through the vast ethereal sky \r
+Sails between worlds and worlds, with steady wing \r
+Now on the polar winds, then with quick fan \r
+Winnows the buxom air; till, within soar \r
+Of towering eagles, to all the fowls he seems \r
+A phoenix, gazed by all as that sole bird, \r
+When, to enshrine his reliques in the Sun's \r
+Bright temple, to Egyptian Thebes he flies. \r
+At once on the eastern cliff of Paradise \r
+He lights, and to his proper shape returns \r
+A Seraph winged:  Six wings he wore, to shade \r
+His lineaments divine; the pair that clad \r
+Each shoulder broad, came mantling o'er his breast \r
+With regal ornament; the middle pair \r
+Girt like a starry zone his waist, and round \r
+Skirted his loins and thighs with downy gold \r
+And colours dipt in Heaven; the third his feet \r
+Shadowed from either heel with feathered mail, \r
+Sky-tinctured grain.  Like Maia's son he stood, \r
+And shook his plumes, that heavenly fragrance filled \r
+The circuit wide.  Straight knew him all the bands \r
+Of Angels under watch; and to his state, \r
+And to his message high, in honour rise; \r
+For on some message high they guessed him bound. \r
+Their glittering tents he passed, and now is come \r
+Into the blissful field, through groves of myrrh, \r
+And flowering odours, cassia, nard, and balm; \r
+A wilderness of sweets; for Nature here \r
+Wantoned as in her prime, and played at will \r
+Her virgin fancies pouring forth more sweet, \r
+Wild above rule or art, enormous bliss. \r
+Him through the spicy forest onward come \r
+Adam discerned, as in the door he sat \r
+Of his cool bower, while now the mounted sun \r
+Shot down direct his fervid rays to warm \r
+Earth's inmost womb, more warmth than Adam needs: \r
+And Eve within, due at her hour prepared \r
+For dinner savoury fruits, of taste to please \r
+True appetite, and not disrelish thirst \r
+Of nectarous draughts between, from milky stream, \r
+Berry or grape:  To whom thus Adam called. \r
+Haste hither, Eve, and worth thy sight behold \r
+Eastward among those trees, what glorious shape \r
+Comes this way moving; seems another morn \r
+Risen on mid-noon; some great behest from Heaven \r
+To us perhaps he brings, and will vouchsafe \r
+This day to be our guest.  But go with speed, \r
+And, what thy stores contain, bring forth, and pour \r
+Abundance, fit to honour and receive \r
+Our heavenly stranger:  Well we may afford \r
+Our givers their own gifts, and large bestow \r
+From large bestowed, where Nature multiplies \r
+Her fertile growth, and by disburthening grows \r
+More fruitful, which instructs us not to spare. \r
+To whom thus Eve.  Adam, earth's hallowed mould, \r
+Of God inspired! small store will serve, where store, \r
+All seasons, ripe for use hangs on the stalk; \r
+Save what by frugal storing firmness gains \r
+To nourish, and superfluous moist consumes: \r
+But I will haste, and from each bough and brake, \r
+Each plant and juciest gourd, will pluck such choice \r
+To entertain our Angel-guest, as he \r
+Beholding shall confess, that here on Earth \r
+God hath dispensed his bounties as in Heaven. \r
+So saying, with dispatchful looks in haste \r
+She turns, on hospitable thoughts intent \r
+What choice to choose for delicacy best, \r
+What order, so contrived as not to mix \r
+Tastes, not well joined, inelegant, but bring \r
+Taste after taste upheld with kindliest change; \r
+Bestirs her then, and from each tender stalk \r
+Whatever Earth, all-bearing mother, yields \r
+In India East or West, or middle shore \r
+In Pontus or the Punick coast, or where \r
+Alcinous reigned, fruit of all kinds, in coat \r
+Rough, or smooth rind, or bearded husk, or shell, \r
+She gathers, tribute large, and on the board \r
+Heaps with unsparing hand; for drink the grape \r
+She crushes, inoffensive must, and meaths \r
+From many a berry, and from sweet kernels pressed \r
+She tempers dulcet creams; nor these to hold \r
+Wants her fit vessels pure; then strows the ground \r
+With rose and odours from the shrub unfumed. \r
+Mean while our primitive great sire, to meet \r
+His God-like guest, walks forth, without more train \r
+Accompanied than with his own complete \r
+Perfections; in himself was all his state, \r
+More solemn than the tedious pomp that waits \r
+On princes, when their rich retinue long \r
+Of horses led, and grooms besmeared with gold, \r
+Dazzles the croud, and sets them all agape. \r
+Nearer his presence Adam, though not awed, \r
+Yet with submiss approach and reverence meek, \r
+As to a superiour nature bowing low, \r
+Thus said.  Native of Heaven, for other place \r
+None can than Heaven such glorious shape contain; \r
+Since, by descending from the thrones above, \r
+Those happy places thou hast deigned a while \r
+To want, and honour these, vouchsafe with us \r
+Two only, who yet by sovran gift possess \r
+This spacious ground, in yonder shady bower \r
+To rest; and what the garden choicest bears \r
+To sit and taste, till this meridian heat \r
+Be over, and the sun more cool decline. \r
+Whom thus the angelick Virtue answered mild. \r
+Adam, I therefore came; nor art thou such \r
+Created, or such place hast here to dwell, \r
+As may not oft invite, though Spirits of Heaven, \r
+To visit thee; lead on then where thy bower \r
+O'ershades; for these mid-hours, till evening rise, \r
+I have at will.  So to the sylvan lodge \r
+They came, that like Pomona's arbour smiled, \r
+With flowerets decked, and fragrant smells; but Eve, \r
+Undecked save with herself, more lovely fair \r
+Than Wood-Nymph, or the fairest Goddess feigned \r
+Of three that in mount Ida naked strove, \r
+Stood to entertain her guest from Heaven; no veil \r
+She needed, virtue-proof; no thought infirm \r
+Altered her cheek.  On whom the Angel Hail \r
+Bestowed, the holy salutation used \r
+Long after to blest Mary, second Eve. \r
+Hail, Mother of Mankind, whose fruitful womb \r
+Shall fill the world more numerous with thy sons, \r
+Than with these various fruits the trees of God \r
+Have heaped this table!--Raised of grassy turf \r
+Their table was, and mossy seats had round, \r
+And on her ample square from side to side \r
+All autumn piled, though spring and autumn here \r
+Danced hand in hand.  A while discourse they hold; \r
+No fear lest dinner cool; when thus began \r
+Our author.  Heavenly stranger, please to taste \r
+These bounties, which our Nourisher, from whom \r
+All perfect good, unmeasured out, descends, \r
+To us for food and for delight hath caused \r
+The earth to yield; unsavoury food perhaps \r
+To spiritual natures; only this I know, \r
+That one celestial Father gives to all. \r
+To whom the Angel.  Therefore what he gives \r
+(Whose praise be ever sung) to Man in part \r
+Spiritual, may of purest Spirits be found \r
+No ingrateful food:  And food alike those pure \r
+Intelligential substances require, \r
+As doth your rational; and both contain \r
+Within them every lower faculty \r
+Of sense, whereby they hear, see, smell, touch, taste, \r
+Tasting concoct, digest, assimilate, \r
+And corporeal to incorporeal turn. \r
+For know, whatever was created, needs \r
+To be sustained and fed:  Of elements \r
+The grosser feeds the purer, earth the sea, \r
+Earth and the sea feed air, the air those fires \r
+Ethereal, and as lowest first the moon; \r
+Whence in her visage round those spots, unpurged \r
+Vapours not yet into her substance turned. \r
+Nor doth the moon no nourishment exhale \r
+From her moist continent to higher orbs. \r
+The sun that light imparts to all, receives \r
+From all his alimental recompence \r
+In humid exhalations, and at even \r
+Sups with the ocean.  Though in Heaven the trees \r
+Of life ambrosial fruitage bear, and vines \r
+Yield nectar; though from off the boughs each morn \r
+We brush mellifluous dews, and find the ground \r
+Covered with pearly grain:  Yet God hath here \r
+Varied his bounty so with new delights, \r
+As may compare with Heaven; and to taste \r
+Think not I shall be nice.  So down they sat, \r
+And to their viands fell; nor seemingly \r
+The Angel, nor in mist, the common gloss \r
+Of Theologians; but with keen dispatch \r
+Of real hunger, and concoctive heat \r
+To transubstantiate:  What redounds, transpires \r
+Through Spirits with ease; nor wonder;if by fire \r
+Of sooty coal the empirick alchemist \r
+Can turn, or holds it possible to turn, \r
+Metals of drossiest ore to perfect gold, \r
+As from the mine.  Mean while at table Eve \r
+Ministered naked, and their flowing cups \r
+With pleasant liquours crowned:  O innocence \r
+Deserving Paradise! if ever, then, \r
+Then had the sons of God excuse to have been \r
+Enamoured at that sight; but in those hearts \r
+Love unlibidinous reigned, nor jealousy \r
+Was understood, the injured lover's hell. \r
+Thus when with meats and drinks they had sufficed, \r
+Not burdened nature, sudden mind arose \r
+In Adam, not to let the occasion pass \r
+Given him by this great conference to know \r
+Of things above his world, and of their being \r
+Who dwell in Heaven, whose excellence he saw \r
+Transcend his own so far; whose radiant forms, \r
+Divine effulgence, whose high power, so far \r
+Exceeded human; and his wary speech \r
+Thus to the empyreal minister he framed. \r
+Inhabitant with God, now know I well \r
+Thy favour, in this honour done to Man; \r
+Under whose lowly roof thou hast vouchsafed \r
+To enter, and these earthly fruits to taste, \r
+Food not of Angels, yet accepted so, \r
+As that more willingly thou couldst not seem \r
+At Heaven's high feasts to have fed: yet what compare \r
+To whom the winged Hierarch replied. \r
+O Adam, One Almighty is, from whom \r
+All things proceed, and up to him return, \r
+If not depraved from good, created all \r
+Such to perfection, one first matter all, \r
+Endued with various forms, various degrees \r
+Of substance, and, in things that live, of life; \r
+But more refined, more spiritous, and pure, \r
+As nearer to him placed, or nearer tending \r
+Each in their several active spheres assigned, \r
+Till body up to spirit work, in bounds \r
+Proportioned to each kind.  So from the root \r
+Springs lighter the green stalk, from thence the leaves \r
+More aery, last the bright consummate flower \r
+Spirits odorous breathes: flowers and their fruit, \r
+Man's nourishment, by gradual scale sublimed, \r
+To vital spirits aspire, to animal, \r
+To intellectual; give both life and sense, \r
+Fancy and understanding; whence the soul \r
+Reason receives, and reason is her being, \r
+Discursive, or intuitive; discourse \r
+Is oftest yours, the latter most is ours, \r
+Differing but in degree, of kind the same. \r
+Wonder not then, what God for you saw good \r
+If I refuse not, but convert, as you \r
+To proper substance.  Time may come, when Men \r
+With Angels may participate, and find \r
+No inconvenient diet, nor too light fare; \r
+And from these corporal nutriments perhaps \r
+Your bodies may at last turn all to spirit, \r
+Improved by tract of time, and, winged, ascend \r
+Ethereal, as we; or may, at choice, \r
+Here or in heavenly Paradises dwell; \r
+If ye be found obedient, and retain \r
+Unalterably firm his love entire, \r
+Whose progeny you are.  Mean while enjoy \r
+Your fill what happiness this happy state \r
+Can comprehend, incapable of more. \r
+To whom the patriarch of mankind replied. \r
+O favourable Spirit, propitious guest, \r
+Well hast thou taught the way that might direct \r
+Our knowledge, and the scale of nature set \r
+From center to circumference; whereon, \r
+In contemplation of created things, \r
+By steps we may ascend to God.  But say, \r
+What meant that caution joined, If ye be found \r
+Obedient?  Can we want obedience then \r
+To him, or possibly his love desert, \r
+Who formed us from the dust and placed us here \r
+Full to the utmost measure of what bliss \r
+Human desires can seek or apprehend? \r
+To whom the Angel.  Son of Heaven and Earth, \r
+Attend!  That thou art happy, owe to God; \r
+That thou continuest such, owe to thyself, \r
+That is, to thy obedience; therein stand. \r
+This was that caution given thee; be advised. \r
+God made thee perfect, not immutable; \r
+And good he made thee, but to persevere \r
+He left it in thy power; ordained thy will \r
+By nature free, not over-ruled by fate \r
+Inextricable, or strict necessity: \r
+Our voluntary service he requires, \r
+Not our necessitated; such with him \r
+Finds no acceptance, nor can find; for how \r
+Can hearts, not free, be tried whether they serve \r
+Willing or no, who will but what they must \r
+By destiny, and can no other choose? \r
+Myself, and all the angelick host, that stand \r
+In sight of God, enthroned, our happy state \r
+Hold, as you yours, while our obedience holds; \r
+On other surety none:  Freely we serve, \r
+Because we freely love, as in our will \r
+To love or not; in this we stand or fall: \r
+And some are fallen, to disobedience fallen, \r
+And so from Heaven to deepest Hell; O fall \r
+From what high state of bliss, into what woe! \r
+To whom our great progenitor.  Thy words \r
+Attentive, and with more delighted ear, \r
+Divine instructer, I have heard, than when \r
+Cherubick songs by night from neighbouring hills \r
+Aereal musick send:  Nor knew I not \r
+To be both will and deed created free; \r
+Yet that we never shall forget to love \r
+Our Maker, and obey him whose command \r
+Single is yet so just, my constant thoughts \r
+Assured me, and still assure:  Though what thou tellest \r
+Hath passed in Heaven, some doubt within me move, \r
+But more desire to hear, if thou consent, \r
+The full relation, which must needs be strange, \r
+Worthy of sacred silence to be heard; \r
+And we have yet large day, for scarce the sun \r
+Hath finished half his journey, and scarce begins \r
+His other half in the great zone of Heaven. \r
+Thus Adam made request; and Raphael, \r
+After short pause assenting, thus began. \r
+High matter thou enjoinest me, O prime of men, \r
+Sad task and hard:  For how shall I relate \r
+To human sense the invisible exploits \r
+Of warring Spirits? how, without remorse, \r
+The ruin of so many glorious once \r
+And perfect while they stood? how last unfold \r
+The secrets of another world, perhaps \r
+Not lawful to reveal? yet for thy good \r
+This is dispensed; and what surmounts the reach \r
+Of human sense, I shall delineate so, \r
+By likening spiritual to corporal forms, \r
+As may express them best; though what if Earth \r
+Be but a shadow of Heaven, and things therein \r
+Each to other like, more than on earth is thought? \r
+As yet this world was not, and Chaos wild \r
+Reigned where these Heavens now roll, where Earth now rests \r
+Upon her center poised; when on a day \r
+(For time, though in eternity, applied \r
+To motion, measures all things durable \r
+By present, past, and future,) on such day \r
+As Heaven's great year brings forth, the empyreal host \r
+Of Angels by imperial summons called, \r
+Innumerable before the Almighty's throne \r
+Forthwith, from all the ends of Heaven, appeared \r
+Under their Hierarchs in orders bright: \r
+Ten thousand thousand ensigns high advanced, \r
+Standards and gonfalons 'twixt van and rear \r
+Stream in the air, and for distinction serve \r
+Of hierarchies, of orders, and degrees; \r
+Or in their glittering tissues bear imblazed \r
+Holy memorials, acts of zeal and love \r
+Recorded eminent.  Thus when in orbs \r
+Of circuit inexpressible they stood, \r
+Orb within orb, the Father Infinite, \r
+By whom in bliss imbosomed sat the Son, \r
+Amidst as from a flaming mount, whose top \r
+Brightness had made invisible, thus spake. \r
+Hear, all ye Angels, progeny of light, \r
+Thrones, Dominations, Princedoms, Virtues, Powers; \r
+Hear my decree, which unrevoked shall stand. \r
+This day I have begot whom I declare \r
+My only Son, and on this holy hill \r
+Him have anointed, whom ye now behold \r
+At my right hand; your head I him appoint; \r
+And by myself have sworn, to him shall bow \r
+All knees in Heaven, and shall confess him Lord: \r
+Under his great vice-gerent reign abide \r
+United, as one individual soul, \r
+For ever happy:  Him who disobeys, \r
+Me disobeys, breaks union, and that day, \r
+Cast out from God and blessed vision, falls \r
+Into utter darkness, deep ingulfed, his place \r
+Ordained without redemption, without end. \r
+So spake the Omnipotent, and with his words \r
+All seemed well pleased; all seemed, but were not all. \r
+That day, as other solemn days, they spent \r
+In song and dance about the sacred hill; \r
+Mystical dance, which yonder starry sphere \r
+Of planets, and of fixed, in all her wheels \r
+Resembles nearest, mazes intricate, \r
+Eccentrick, intervolved, yet regular \r
+Then most, when most irregular they seem; \r
+And in their motions harmony divine \r
+So smooths her charming tones, that God's own ear \r
+Listens delighted.  Evening now approached, \r
+(For we have also our evening and our morn, \r
+We ours for change delectable, not need;) \r
+Forthwith from dance to sweet repast they turn \r
+Desirous; all in circles as they stood, \r
+Tables are set, and on a sudden piled \r
+With Angels food, and rubied nectar flows \r
+In pearl, in diamond, and massy gold, \r
+Fruit of delicious vines, the growth of Heaven. \r
+On flowers reposed, and with fresh flowerets crowned, \r
+They eat, they drink, and in communion sweet \r
+Quaff immortality and joy, secure \r
+Of surfeit, where full measure only bounds \r
+Excess, before the all-bounteous King, who showered \r
+With copious hand, rejoicing in their joy. \r
+Now when ambrosial night with clouds exhaled \r
+From that high mount of God, whence light and shade \r
+Spring both, the face of brightest Heaven had changed \r
+To grateful twilight, (for night comes not there \r
+In darker veil,) and roseat dews disposed \r
+All but the unsleeping eyes of God to rest; \r
+Wide over all the plain, and wider far \r
+Than all this globous earth in plain outspread, \r
+(Such are the courts of God) the angelick throng, \r
+Dispersed in bands and files, their camp extend \r
+By living streams among the trees of life, \r
+Pavilions numberless, and sudden reared, \r
+Celestial tabernacles, where they slept \r
+Fanned with cool winds; save those, who, in their course, \r
+Melodious hymns about the sovran throne \r
+Alternate all night long: but not so waked \r
+Satan; so call him now, his former name \r
+Is heard no more in Heaven; he of the first, \r
+If not the first Arch-Angel, great in power, \r
+In favour and pre-eminence, yet fraught \r
+With envy against the Son of God, that day \r
+Honoured by his great Father, and proclaimed \r
+Messiah King anointed, could not bear \r
+Through pride that sight, and thought himself impaired. \r
+Deep malice thence conceiving and disdain, \r
+Soon as midnight brought on the dusky hour \r
+Friendliest to sleep and silence, he resolved \r
+With all his legions to dislodge, and leave \r
+Unworshipt, unobeyed, the throne supreme, \r
+Contemptuous; and his next subordinate \r
+Awakening, thus to him in secret spake. \r
+Sleepest thou, Companion dear?  What sleep can close \r
+Thy eye-lids? and rememberest what decree \r
+Of yesterday, so late hath passed the lips \r
+Of Heaven's Almighty.  Thou to me thy thoughts \r
+Wast wont, I mine to thee was wont to impart; \r
+Both waking we were one; how then can now \r
+Thy sleep dissent?  New laws thou seest imposed; \r
+New laws from him who reigns, new minds may raise \r
+In us who serve, new counsels to debate \r
+What doubtful may ensue:  More in this place \r
+To utter is not safe.  Assemble thou \r
+Of all those myriads which we lead the chief; \r
+Tell them, that by command, ere yet dim night \r
+Her shadowy cloud withdraws, I am to haste, \r
+And all who under me their banners wave, \r
+Homeward, with flying march, where we possess \r
+The quarters of the north; there to prepare \r
+Fit entertainment to receive our King, \r
+The great Messiah, and his new commands, \r
+Who speedily through all the hierarchies \r
+Intends to pass triumphant, and give laws. \r
+So spake the false Arch-Angel, and infused \r
+Bad influence into the unwary breast \r
+Of his associate:  He together calls, \r
+Or several one by one, the regent Powers, \r
+Under him Regent; tells, as he was taught, \r
+That the Most High commanding, now ere night, \r
+Now ere dim night had disincumbered Heaven, \r
+The great hierarchal standard was to move; \r
+Tells the suggested cause, and casts between \r
+Ambiguous words and jealousies, to sound \r
+Or taint integrity:  But all obeyed \r
+The wonted signal, and superiour voice \r
+Of their great Potentate; for great indeed \r
+His name, and high was his degree in Heaven; \r
+His countenance, as the morning-star that guides \r
+The starry flock, allured them, and with lies \r
+Drew after him the third part of Heaven's host. \r
+Mean while the Eternal eye, whose sight discerns \r
+Abstrusest thoughts, from forth his holy mount, \r
+And from within the golden lamps that burn \r
+Nightly before him, saw without their light \r
+Rebellion rising; saw in whom, how spread \r
+Among the sons of morn, what multitudes \r
+Were banded to oppose his high decree; \r
+And, smiling, to his only Son thus said. \r
+Son, thou in whom my glory I behold \r
+In full resplendence, Heir of all my might, \r
+Nearly it now concerns us to be sure \r
+Of our Omnipotence, and with what arms \r
+We mean to hold what anciently we claim \r
+Of deity or empire:  Such a foe \r
+Is rising, who intends to erect his throne \r
+Equal to ours, throughout the spacious north; \r
+Nor so content, hath in his thought to try \r
+In battle, what our power is, or our right. \r
+Let us advise, and to this hazard draw \r
+With speed what force is left, and all employ \r
+In our defence; lest unawares we lose \r
+This our high place, our sanctuary, our hill. \r
+To whom the Son with calm aspect and clear, \r
+Lightning divine, ineffable, serene, \r
+Made answer.  Mighty Father, thou thy foes \r
+Justly hast in derision, and, secure, \r
+Laughest at their vain designs and tumults vain, \r
+Matter to me of glory, whom their hate \r
+Illustrates, when they see all regal power \r
+Given me to quell their pride, and in event \r
+Know whether I be dextrous to subdue \r
+Thy rebels, or be found the worst in Heaven. \r
+So spake the Son; but Satan, with his Powers, \r
+Far was advanced on winged speed; an host \r
+Innumerable as the stars of night, \r
+Or stars of morning, dew-drops, which the sun \r
+Impearls on every leaf and every flower. \r
+Regions they passed, the mighty regencies \r
+Of Seraphim, and Potentates, and Thrones, \r
+In their triple degrees; regions to which \r
+All thy dominion, Adam, is no more \r
+Than what this garden is to all the earth, \r
+And all the sea, from one entire globose \r
+Stretched into longitude; which having passed, \r
+At length into the limits of the north \r
+They came; and Satan to his royal seat \r
+High on a hill, far blazing, as a mount \r
+Raised on a mount, with pyramids and towers \r
+From diamond quarries hewn, and rocks of gold; \r
+The palace of great Lucifer, (so call \r
+That structure in the dialect of men \r
+Interpreted,) which not long after, he \r
+Affecting all equality with God, \r
+In imitation of that mount whereon \r
+Messiah was declared in sight of Heaven, \r
+The Mountain of the Congregation called; \r
+For thither he assembled all his train, \r
+Pretending so commanded to consult \r
+About the great reception of their King, \r
+Thither to come, and with calumnious art \r
+Of counterfeited truth thus held their ears. \r
+Thrones, Dominations, Princedoms, Virtues, Powers; \r
+If these magnifick titles yet remain \r
+Not merely titular, since by decree \r
+Another now hath to himself engrossed \r
+All power, and us eclipsed under the name \r
+Of King anointed, for whom all this haste \r
+Of midnight-march, and hurried meeting here, \r
+This only to consult how we may best, \r
+With what may be devised of honours new, \r
+Receive him coming to receive from us \r
+Knee-tribute yet unpaid, prostration vile! \r
+Too much to one! but double how endured, \r
+To one, and to his image now proclaimed? \r
+But what if better counsels might erect \r
+Our minds, and teach us to cast off this yoke? \r
+Will ye submit your necks, and choose to bend \r
+The supple knee?  Ye will not, if I trust \r
+To know ye right, or if ye know yourselves \r
+Natives and sons of Heaven possessed before \r
+By none; and if not equal all, yet free, \r
+Equally free; for orders and degrees \r
+Jar not with liberty, but well consist. \r
+Who can in reason then, or right, assume \r
+Monarchy over such as live by right \r
+His equals, if in power and splendour less, \r
+In freedom equal? or can introduce \r
+Law and edict on us, who without law \r
+Err not? much less for this to be our Lord, \r
+And look for adoration, to the abuse \r
+Of those imperial titles, which assert \r
+Our being ordained to govern, not to serve. \r
+Thus far his bold discourse without controul \r
+Had audience; when among the Seraphim \r
+Abdiel, than whom none with more zeal adored \r
+The Deity, and divine commands obeyed, \r
+Stood up, and in a flame of zeal severe \r
+The current of his fury thus opposed. \r
+O argument blasphemous, false, and proud! \r
+Words which no ear ever to hear in Heaven \r
+Expected, least of all from thee,  Ingrate, \r
+In place thyself so high above thy peers. \r
+Canst thou with impious obloquy condemn \r
+The just decree of God, pronounced and sworn, \r
+That to his only Son, by right endued \r
+With regal scepter, every soul in Heaven \r
+Shall bend the knee, and in that honour due \r
+Confess him rightful King? unjust, thou sayest, \r
+Flatly unjust, to bind with laws the free, \r
+And equal over equals to let reign, \r
+One over all with unsucceeded power. \r
+Shalt thou give law to God? shalt thou dispute \r
+With him the points of liberty, who made \r
+Thee what thou art, and formed the Powers of Heaven \r
+Such as he pleased, and circumscribed their being? \r
+Yet, by experience taught, we know how good, \r
+And of our good and of our dignity \r
+How provident he is; how far from thought \r
+To make us less, bent rather to exalt \r
+Our happy state, under one head more near \r
+United.  But to grant it thee unjust, \r
+That equal over equals monarch reign: \r
+Thyself, though great and glorious, dost thou count, \r
+Or all angelick nature joined in one, \r
+Equal to him begotten Son? by whom, \r
+As by his Word, the Mighty Father made \r
+All things, even thee; and all the Spirits of Heaven \r
+By him created in their bright degrees, \r
+Crowned them with glory, and to their glory named \r
+Thrones, Dominations, Princedoms, Virtues, Powers, \r
+Essential Powers; nor by his reign obscured, \r
+But more illustrious made; since he the head \r
+One of our number thus reduced becomes; \r
+His laws our laws; all honour to him done \r
+Returns our own.  Cease then this impious rage, \r
+And tempt not these; but hasten to appease \r
+The incensed Father, and the incensed Son, \r
+While pardon may be found in time besought. \r
+So spake the fervent Angel; but his zeal \r
+None seconded, as out of season judged, \r
+Or singular and rash:  Whereat rejoiced \r
+The Apostate, and, more haughty, thus replied. \r
+That we were formed then sayest thou? and the work \r
+Of secondary hands, by task transferred \r
+From Father to his Son? strange point and new! \r
+Doctrine which we would know whence learned: who saw \r
+When this creation was? rememberest thou \r
+Thy making, while the Maker gave thee being? \r
+We know no time when we were not as now; \r
+Know none before us, self-begot, self-raised \r
+By our own quickening power, when fatal course \r
+Had circled his full orb, the birth mature \r
+Of this our native Heaven, ethereal sons. \r
+Our puissance is our own; our own right hand \r
+Shall teach us highest deeds, by proof to try \r
+Who is our equal:  Then thou shalt behold \r
+Whether by supplication we intend \r
+Address, and to begirt the almighty throne \r
+Beseeching or besieging.  This report, \r
+These tidings carry to the anointed King; \r
+And fly, ere evil intercept thy flight. \r
+He said; and, as the sound of waters deep, \r
+Hoarse murmur echoed to his words applause \r
+Through the infinite host; nor less for that \r
+The flaming Seraph fearless, though alone \r
+Encompassed round with foes, thus answered bold. \r
+O alienate from God, O Spirit accursed, \r
+Forsaken of all good!  I see thy fall \r
+Determined, and thy hapless crew involved \r
+In this perfidious fraud, contagion spread \r
+Both of thy crime and punishment:  Henceforth \r
+No more be troubled how to quit the yoke \r
+Of God's Messiah; those indulgent laws \r
+Will not be now vouchsafed; other decrees \r
+Against thee are gone forth without recall; \r
+That golden scepter, which thou didst reject, \r
+Is now an iron rod to bruise and break \r
+Thy disobedience.  Well thou didst advise; \r
+Yet not for thy advice or threats I fly \r
+These wicked tents devoted, lest the wrath \r
+Impendent, raging into sudden flame, \r
+Distinguish not:  For soon expect to feel \r
+His thunder on thy head, devouring fire. \r
+Then who created thee lamenting learn, \r
+When who can uncreate thee thou shalt know. \r
+So spake the Seraph Abdiel, faithful found \r
+Among the faithless, faithful only he; \r
+Among innumerable false, unmoved, \r
+Unshaken, unseduced, unterrified, \r
+His loyalty he kept, his love, his zeal; \r
+Nor number, nor example, with him wrought \r
+To swerve from truth, or change his constant mind, \r
+Though single.  From amidst them forth he passed, \r
+Long way through hostile scorn, which he sustained \r
+Superiour, nor of violence feared aught; \r
+And, with retorted scorn, his back he turned \r
+On those proud towers to swift destruction doomed. \r
\r
\r
\r
+Book VI                                                          \r
\r
\r
+All night the dreadless Angel, unpursued, \r
+Through Heaven's wide champain held his way; till Morn, \r
+Waked by the circling Hours, with rosy hand \r
+Unbarred the gates of light.  There is a cave \r
+Within the mount of God, fast by his throne, \r
+Where light and darkness in perpetual round \r
+Lodge and dislodge by turns, which makes through Heaven \r
+Grateful vicissitude, like day and night; \r
+Light issues forth, and at the other door \r
+Obsequious darkness enters, till her hour \r
+To veil the Heaven, though darkness there might well \r
+Seem twilight here:  And now went forth the Morn \r
+Such as in highest Heaven arrayed in gold \r
+Empyreal; from before her vanished Night, \r
+Shot through with orient beams; when all the plain \r
+Covered with thick embattled squadrons bright, \r
+Chariots, and flaming arms, and fiery steeds, \r
+Reflecting blaze on blaze, first met his view: \r
+War he perceived, war in procinct; and found \r
+Already known what he for news had thought \r
+To have reported:  Gladly then he mixed \r
+Among those friendly Powers, who him received \r
+With joy and acclamations loud, that one, \r
+That of so many myriads fallen, yet one \r
+Returned not lost.  On to the sacred hill \r
+They led him high applauded, and present \r
+Before the seat supreme; from whence a voice, \r
+From midst a golden cloud, thus mild was heard. \r
+Servant of God. Well done; well hast thou fought \r
+The better fight, who single hast maintained \r
+Against revolted multitudes the cause \r
+Of truth, in word mightier than they in arms; \r
+And for the testimony of truth hast borne \r
+Universal reproach, far worse to bear \r
+Than violence; for this was all thy care \r
+To stand approved in sight of God, though worlds \r
+Judged thee perverse:  The easier conquest now \r
+Remains thee, aided by this host of friends, \r
+Back on thy foes more glorious to return, \r
+Than scorned thou didst depart; and to subdue \r
+By force, who reason for their law refuse, \r
+Right reason for their law, and for their King \r
+Messiah, who by right of merit reigns. \r
+Go, Michael, of celestial armies prince, \r
+And thou, in military prowess next, \r
+Gabriel, lead forth to battle these my sons \r
+Invincible; lead forth my armed Saints, \r
+By thousands and by millions, ranged for fight, \r
+Equal in number to that Godless crew \r
+Rebellious:  Them with fire and hostile arms \r
+Fearless assault; and, to the brow of Heaven \r
+Pursuing, drive them out from God and bliss, \r
+Into their place of punishment, the gulf \r
+Of Tartarus, which ready opens wide \r
+His fiery Chaos to receive their fall. \r
+So spake the Sovran Voice, and clouds began \r
+To darken all the hill, and smoke to roll \r
+In dusky wreaths, reluctant flames, the sign \r
+Of wrath awaked; nor with less dread the loud \r
+Ethereal trumpet from on high 'gan blow: \r
+At which command the Powers militant, \r
+That stood for Heaven, in mighty quadrate joined \r
+Of union irresistible, moved on \r
+In silence their bright legions, to the sound \r
+Of instrumental harmony, that breathed \r
+Heroick ardour to adventurous deeds \r
+Under their God-like leaders, in the cause \r
+Of God and his Messiah.  On they move \r
+Indissolubly firm; nor obvious hill, \r
+Nor straitening vale, nor wood, nor stream, divides \r
+Their perfect ranks; for high above the ground \r
+Their march was, and the passive air upbore \r
+Their nimble tread; as when the total kind \r
+Of birds, in orderly array on wing, \r
+Came summoned over Eden to receive \r
+Their names of thee; so over many a tract \r
+Of Heaven they marched, and many a province wide, \r
+Tenfold the length of this terrene:  At last, \r
+Far in the horizon to the north appeared \r
+From skirt to skirt a fiery region, stretched \r
+In battailous aspect, and nearer view \r
+Bristled with upright beams innumerable \r
+Of rigid spears, and helmets thronged, and shields \r
+Various, with boastful argument portrayed, \r
+The banded Powers of Satan hasting on \r
+With furious expedition; for they weened \r
+That self-same day, by fight or by surprise, \r
+To win the mount of God, and on his throne \r
+To set the Envier of his state, the proud \r
+Aspirer; but their thoughts proved fond and vain \r
+In the mid way:  Though strange to us it seemed \r
+At first, that Angel should with Angel war, \r
+And in fierce hosting meet, who wont to meet \r
+So oft in festivals of joy and love \r
+Unanimous, as sons of one great Sire, \r
+Hymning the Eternal Father:  But the shout \r
+Of battle now began, and rushing sound \r
+Of onset ended soon each milder thought. \r
+High in the midst, exalted as a God, \r
+The Apostate in his sun-bright chariot sat, \r
+Idol of majesty divine, enclosed \r
+With flaming Cherubim, and golden shields; \r
+Then lighted from his gorgeous throne, for now \r
+"twixt host and host but narrow space was left, \r
+A dreadful interval, and front to front \r
+Presented stood in terrible array \r
+Of hideous length:  Before the cloudy van, \r
+On the rough edge of battle ere it joined, \r
+Satan, with vast and haughty strides advanced, \r
+Came towering, armed in adamant and gold; \r
+Abdiel that sight endured not, where he stood \r
+Among the mightiest, bent on highest deeds, \r
+And thus his own undaunted heart explores. \r
+O Heaven! that such resemblance of the Highest \r
+Should yet remain, where faith and realty \r
+Remain not:  Wherefore should not strength and might \r
+There fail where virtue fails, or weakest prove \r
+Where boldest, though to fight unconquerable? \r
+His puissance, trusting in the Almighty's aid, \r
+I mean to try, whose reason I have tried \r
+Unsound and false; nor is it aught but just, \r
+That he, who in debate of truth hath won, \r
+Should win in arms, in both disputes alike \r
+Victor; though brutish that contest and foul, \r
+When reason hath to deal with force, yet so \r
+Most reason is that reason overcome. \r
+So pondering, and from his armed peers \r
+Forth stepping opposite, half-way he met \r
+His daring foe, at this prevention more \r
+Incensed, and thus securely him defied. \r
+Proud, art thou met? thy hope was to have reached \r
+The highth of thy aspiring unopposed, \r
+The throne of God unguarded, and his side \r
+Abandoned, at the terrour of thy power \r
+Or potent tongue:  Fool!not to think how vain \r
+Against the Omnipotent to rise in arms; \r
+Who out of smallest things could, without end, \r
+Have raised incessant armies to defeat \r
+Thy folly; or with solitary hand \r
+Reaching beyond all limit, at one blow, \r
+Unaided, could have finished thee, and whelmed \r
+Thy legions under darkness:  But thou seest \r
+All are not of thy train; there be, who faith \r
+Prefer, and piety to God, though then \r
+To thee not visible, when I alone \r
+Seemed in thy world erroneous to dissent \r
+From all:  My sect thou seest;now learn too late \r
+How few sometimes may know, when thousands err. \r
+Whom the grand foe, with scornful eye askance, \r
+Thus answered.  Ill for thee, but in wished hour \r
+Of my revenge, first sought for, thou returnest \r
+From flight, seditious Angel! to receive \r
+Thy merited reward, the first assay \r
+Of this right hand provoked, since first that tongue, \r
+Inspired with contradiction, durst oppose \r
+A third part of the Gods, in synod met \r
+Their deities to assert; who, while they feel \r
+Vigour divine within them, can allow \r
+Omnipotence to none.  But well thou comest \r
+Before thy fellows, ambitious to win \r
+From me some plume, that thy success may show \r
+Destruction to the rest:  This pause between, \r
+(Unanswered lest thou boast) to let thee know, \r
+At first I thought that Liberty and Heaven \r
+To heavenly souls had been all one; but now \r
+I see that most through sloth had rather serve, \r
+Ministring Spirits, trained up in feast and song! \r
+Such hast thou armed, the minstrelsy of Heaven, \r
+Servility with freedom to contend, \r
+As both their deeds compared this day shall prove. \r
+To whom in brief thus Abdiel stern replied. \r
+Apostate! still thou errest, nor end wilt find \r
+Of erring, from the path of truth remote: \r
+Unjustly thou depravest it with the name \r
+Of servitude, to serve whom God ordains, \r
+Or Nature:  God and Nature bid the same, \r
+When he who rules is worthiest, and excels \r
+Them whom he governs.  This is servitude, \r
+To serve the unwise, or him who hath rebelled \r
+Against his worthier, as thine now serve thee, \r
+Thyself not free, but to thyself enthralled; \r
+Yet lewdly darest our ministring upbraid. \r
+Reign thou in Hell, thy kingdom; let me serve \r
+In Heaven God ever blest, and his divine \r
+Behests obey, worthiest to be obeyed; \r
+Yet chains in Hell, not realms, expect:  Mean while \r
+From me returned, as erst thou saidst, from flight, \r
+This greeting on thy impious crest receive. \r
+So saying, a noble stroke he lifted high, \r
+Which hung not, but so swift with tempest fell \r
+On the proud crest of Satan, that no sight, \r
+Nor motion of swift thought, less could his shield, \r
+Such ruin intercept:  Ten paces huge \r
+He back recoiled; the tenth on bended knee \r
+His massy spear upstaid; as if on earth \r
+Winds under ground, or waters forcing way, \r
+Sidelong had pushed a mountain from his seat, \r
+Half sunk with all his pines.  Amazement seised \r
+The rebel Thrones, but greater rage, to see \r
+Thus foiled their mightiest; ours joy filled, and shout, \r
+Presage of victory, and fierce desire \r
+Of battle:  Whereat Michael bid sound \r
+The Arch-Angel trumpet; through the vast of Heaven \r
+It sounded, and the faithful armies rung \r
+Hosanna to the Highest:  Nor stood at gaze \r
+The adverse legions, nor less hideous joined \r
+The horrid shock.  Now storming fury rose, \r
+And clamour such as heard in Heaven till now \r
+Was never; arms on armour clashing brayed \r
+Horrible discord, and the madding wheels \r
+Of brazen chariots raged; dire was the noise \r
+Of conflict; over head the dismal hiss \r
+Of fiery darts in flaming vollies flew, \r
+And flying vaulted either host with fire. \r
+So under fiery cope together rushed \r
+Both battles main, with ruinous assault \r
+And inextinguishable rage.  All Heaven \r
+Resounded; and had Earth been then, all Earth \r
+Had to her center shook.  What wonder? when \r
+Millions of fierce encountering Angels fought \r
+On either side, the least of whom could wield \r
+These elements, and arm him with the force \r
+Of all their regions:  How much more of power \r
+Army against army numberless to raise \r
+Dreadful combustion warring, and disturb, \r
+Though not destroy, their happy native seat; \r
+Had not the Eternal King Omnipotent, \r
+From his strong hold of Heaven, high over-ruled \r
+And limited their might; though numbered such \r
+As each divided legion might have seemed \r
+A numerous host; in strength each armed hand \r
+A legion; led in fight, yet leader seemed \r
+Each warriour single as in chief, expert \r
+When to advance, or stand, or turn the sway \r
+Of battle, open when, and when to close \r
+The ridges of grim war:  No thought of flight, \r
+None of retreat, no unbecoming deed \r
+That argued fear; each on himself relied, \r
+As only in his arm the moment lay \r
+Of victory:  Deeds of eternal fame \r
+Were done, but infinite; for wide was spread \r
+That war and various; sometimes on firm ground \r
+A standing fight, then, soaring on main wing, \r
+Tormented all the air; all air seemed then \r
+Conflicting fire.  Long time in even scale \r
+The battle hung; till Satan, who that day \r
+Prodigious power had shown, and met in arms \r
+No equal, ranging through the dire attack \r
+Of fighting Seraphim confused, at length \r
+Saw where the sword of Michael smote, and felled \r
+Squadrons at once; with huge two-handed sway \r
+Brandished aloft, the horrid edge came down \r
+Wide-wasting; such destruction to withstand \r
+He hasted, and opposed the rocky orb \r
+Of tenfold adamant, his ample shield, \r
+A vast circumference.  At his approach \r
+The great Arch-Angel from his warlike toil \r
+Surceased, and glad, as hoping here to end \r
+Intestine war in Heaven, the arch-foe subdued \r
+Or captive dragged in chains, with hostile frown \r
+And visage all inflamed first thus began. \r
+Author of evil, unknown till thy revolt, \r
+Unnamed in Heaven, now plenteous as thou seest \r
+These acts of hateful strife, hateful to all, \r
+Though heaviest by just measure on thyself, \r
+And thy  adherents:  How hast thou disturbed \r
+Heaven's blessed peace, and into nature brought \r
+Misery, uncreated till the crime \r
+Of thy rebellion! how hast thou instilled \r
+Thy malice into thousands, once upright \r
+And faithful, now proved false!  But think not here \r
+To trouble holy rest; Heaven casts thee out \r
+From all her confines.  Heaven, the seat of bliss, \r
+Brooks not the works of violence and war. \r
+Hence then, and evil go with thee along, \r
+Thy offspring, to the place of evil, Hell; \r
+Thou and thy wicked crew! there mingle broils, \r
+Ere this avenging sword begin thy doom, \r
+Or some more sudden vengeance, winged from God, \r
+Precipitate thee with augmented pain. \r
+So spake the Prince of Angels; to whom thus \r
+The Adversary.  Nor think thou with wind \r
+Of aery threats to awe whom yet with deeds \r
+Thou canst not.  Hast thou turned the least of these \r
+To flight, or if to fall, but that they rise \r
+Unvanquished, easier to transact with me \r
+That thou shouldst hope, imperious, and with threats \r
+To chase me hence? err not, that so shall end \r
+The strife which thou callest evil, but we style \r
+The strife of glory; which we mean to win, \r
+Or turn this Heaven itself into the Hell \r
+Thou fablest; here however to dwell free, \r
+If not to reign:  Mean while thy utmost force, \r
+And join him named Almighty to thy aid, \r
+I fly not, but have sought thee far and nigh. \r
+They ended parle, and both addressed for fight \r
+Unspeakable; for who, though with the tongue \r
+Of Angels, can relate, or to what things \r
+Liken on earth conspicuous, that may lift \r
+Human imagination to such highth \r
+Of Godlike power? for likest Gods they seemed, \r
+Stood they or moved, in stature, motion, arms, \r
+Fit to decide the empire of great Heaven. \r
+Now waved their fiery swords, and in the air \r
+Made horrid circles; two broad suns their shields \r
+Blazed opposite, while Expectation stood \r
+In horrour:  From each hand with speed retired, \r
+Where erst was thickest fight, the angelick throng, \r
+And left large field, unsafe within the wind \r
+Of such commotion; such as, to set forth \r
+Great things by small, if, nature's concord broke, \r
+Among the constellations war were sprung, \r
+Two planets, rushing from aspect malign \r
+Of fiercest opposition, in mid sky \r
+Should combat, and their jarring spheres confound. \r
+Together both with next to almighty arm \r
+Up-lifted imminent, one stroke they aimed \r
+That might determine, and not need repeat, \r
+As not of power at once; nor odds appeared \r
+In might or swift prevention:  But the sword \r
+Of Michael from the armoury of God \r
+Was given him tempered so, that neither keen \r
+Nor solid might resist that edge: it met \r
+The sword of Satan, with steep force to smite \r
+Descending, and in half cut sheer; nor staid, \r
+But with swift wheel reverse, deep entering, shared \r
+All his right side:  Then Satan first knew pain, \r
+And writhed him to and fro convolved; so sore \r
+The griding sword with discontinuous wound \r
+Passed through him:  But the ethereal substance closed, \r
+Not long divisible; and from the gash \r
+A stream of necturous humour issuing flowed \r
+Sanguine, such as celestial Spirits may bleed, \r
+And all his armour stained, ere while so bright. \r
+Forthwith on all sides to his aid was run \r
+By Angels many and strong, who interposed \r
+Defence, while others bore him on their shields \r
+Back to his chariot, where it stood retired \r
+From off the files of war:  There they him laid \r
+Gnashing for anguish, and despite, and shame, \r
+To find himself not matchless, and his pride \r
+Humbled by such rebuke, so far beneath \r
+His confidence to equal God in power. \r
+Yet soon he healed; for Spirits that live throughout \r
+Vital in every part, not as frail man \r
+In entrails, heart of head, liver or reins, \r
+Cannot but by annihilating die; \r
+Nor in their liquid texture mortal wound \r
+Receive, no more than can the fluid air: \r
+All heart they live, all head, all eye, all ear, \r
+All intellect, all sense; and, as they please, \r
+They limb themselves, and colour, shape, or size \r
+Assume, as?kikes them best, condense or rare. \r
+Mean while in other parts like deeds deserved \r
+Memorial, where the might of Gabriel fought, \r
+And with fierce ensigns pierced the deep array \r
+Of Moloch, furious king; who him defied, \r
+And at his chariot-wheels to drag him bound \r
+Threatened, nor from the Holy One of Heaven \r
+Refrained his tongue blasphemous; but anon \r
+Down cloven to the waist, with shattered arms \r
+And uncouth pain fled bellowing.  On each wing \r
+Uriel, and Raphael, his vaunting foe, \r
+Though huge, and in a rock of diamond armed, \r
+Vanquished Adramelech, and Asmadai, \r
+Two potent Thrones, that to be less than Gods \r
+Disdained, but meaner thoughts learned in their flight, \r
+Mangled with ghastly wounds through plate and mail. \r
+Nor stood unmindful Abdiel to annoy \r
+The atheist crew, but with redoubled blow \r
+Ariel, and Arioch, and the violence \r
+Of Ramiel scorched and blasted, overthrew. \r
+I might relate of thousands, and their names \r
+Eternize here on earth; but those elect \r
+Angels, contented with their fame in Heaven, \r
+Seek not the praise of men:  The other sort, \r
+In might though wonderous and in acts of war, \r
+Nor of renown less eager, yet by doom \r
+Cancelled from Heaven and sacred memory, \r
+Nameless in dark oblivion let them dwell. \r
+For strength from truth divided, and from just, \r
+Illaudable, nought merits but dispraise \r
+And ignominy; yet to glory aspires \r
+Vain-glorious, and through infamy seeks fame: \r
+Therefore eternal silence be their doom. \r
+And now, their mightiest quelled, the battle swerved, \r
+With many an inroad gored; deformed rout \r
+Entered, and foul disorder; all the ground \r
+With shivered armour strown, and on a heap \r
+Chariot and charioteer lay overturned, \r
+And fiery-foaming steeds; what stood, recoiled \r
+O'er-wearied, through the faint Satanick host \r
+Defensive scarce, or with pale fear surprised, \r
+Then first with fear surprised, and sense of pain, \r
+Fled ignominious, to such evil brought \r
+By sin of disobedience; till that hour \r
+Not liable to fear, or flight, or pain. \r
+Far otherwise the inviolable Saints, \r
+In cubick phalanx firm, advanced entire, \r
+Invulnerable, impenetrably armed; \r
+Such high advantages their innocence \r
+Gave them above their foes; not to have sinned, \r
+Not to have disobeyed; in fight they stood \r
+Unwearied, unobnoxious to be pained \r
+By wound, though from their place by violence moved, \r
+Now Night her course began, and, over Heaven \r
+Inducing darkness, grateful truce imposed, \r
+And silence on the odious din of war: \r
+Under her cloudy covert both retired, \r
+Victor and vanquished:  On the foughten field \r
+Michael and his Angels prevalent \r
+Encamping, placed in guard their watches round, \r
+Cherubick waving fires:  On the other part, \r
+Satan with his rebellious disappeared, \r
+Far in the dark dislodged; and, void of rest, \r
+His potentates to council called by night; \r
+And in the midst thus undismayed began. \r
+O now in danger tried, now known in arms \r
+Not to be overpowered, Companions dear, \r
+Found worthy not of liberty alone, \r
+Too mean pretence! but what we more affect, \r
+Honour, dominion, glory, and renown; \r
+Who have sustained one day in doubtful fight, \r
+(And if one day, why not eternal days?) \r
+What Heaven's Lord had powerfullest to send \r
+Against us from about his throne, and judged \r
+Sufficient to subdue us to his will, \r
+But proves not so:  Then fallible, it seems, \r
+Of future we may deem him, though till now \r
+Omniscient thought.  True is, less firmly armed, \r
+Some disadvantage we endured and pain, \r
+Till now not known, but, known, as soon contemned; \r
+Since now we find this our empyreal form \r
+Incapable of mortal injury, \r
+Imperishable, and, though pierced with wound, \r
+Soon closing, and by native vigour healed. \r
+Of evil then so small as easy think \r
+The remedy; perhaps more valid arms, \r
+Weapons more violent, when next we meet, \r
+May serve to better us, and worse our foes, \r
+Or equal what between us made the odds, \r
+In nature none:  If other hidden cause \r
+Left them superiour, while we can preserve \r
+Unhurt our minds, and understanding sound, \r
+Due search and consultation will disclose. \r
+He sat; and in the assembly next upstood \r
+Nisroch, of Principalities the prime; \r
+As one he stood escaped from cruel fight, \r
+Sore toiled, his riven arms to havock hewn, \r
+And cloudy in aspect thus answering spake. \r
+Deliverer from new Lords, leader to free \r
+Enjoyment of our right as Gods; yet hard \r
+For Gods, and too unequal work we find, \r
+Against unequal arms to fight in pain, \r
+Against unpained, impassive; from which evil \r
+Ruin must needs ensue; for what avails \r
+Valour or strength, though matchless, quelled with pain \r
+Which all subdues, and makes remiss the hands \r
+Of mightiest?  Sense of pleasure we may well \r
+Spare out of life perhaps, and not repine, \r
+But live content, which is the calmest life: \r
+But pain is perfect misery, the worst \r
+Of evils, and, excessive, overturns \r
+All patience.  He, who therefore can invent \r
+With what more forcible we may offend \r
+Our yet unwounded enemies, or arm \r
+Ourselves with like defence, to me deserves \r
+No less than for deliverance what we owe. \r
+Whereto with look composed Satan replied. \r
+Not uninvented that, which thou aright \r
+Believest so main to our success, I bring. \r
+Which of us who beholds the bright surface \r
+Of this ethereous mould whereon we stand, \r
+This continent of spacious Heaven, adorned \r
+With plant, fruit, flower ambrosial, gems, and gold; \r
+Whose eye so superficially surveys \r
+These things, as not to mind from whence they grow \r
+Deep under ground, materials dark and crude, \r
+Of spiritous and fiery spume, till touched \r
+With Heaven's ray, and tempered, they shoot forth \r
+So beauteous, opening to the ambient light? \r
+These in their dark nativity the deep \r
+Shall yield us, pregnant with infernal flame; \r
+Which, into hollow engines, long and round, \r
+Thick rammed, at the other bore with touch of fire \r
+Dilated and infuriate, shall send forth \r
+From far, with thundering noise, among our foes \r
+Such implements of mischief, as shall dash \r
+To pieces, and o'erwhelm whatever stands \r
+Adverse, that they shall fear we have disarmed \r
+The Thunderer of his only dreaded bolt. \r
+Nor long shall be our labour; yet ere dawn, \r
+Effect shall end our wish.  Mean while revive; \r
+Abandon fear; to strength and counsel joined \r
+Think nothing hard, much less to be despaired. \r
+He ended, and his words their drooping cheer \r
+Enlightened, and their languished hope revived. \r
+The invention all admired, and each, how he \r
+To be the inventer missed; so easy it seemed \r
+Once found, which yet unfound most would have thought \r
+Impossible:  Yet, haply, of thy race \r
+In future days, if malice should abound, \r
+Some one intent on mischief, or inspired \r
+With devilish machination, might devise \r
+Like instrument to plague the sons of men \r
+For sin, on war and mutual slaughter bent. \r
+Forthwith from council to the work they flew; \r
+None arguing stood; innumerable hands \r
+Were ready; in a moment up they turned \r
+Wide the celestial soil, and saw beneath \r
+The originals of nature in their crude \r
+Conception; sulphurous and nitrous foam \r
+They found, they mingled, and, with subtle art, \r
+Concocted and adusted they reduced \r
+To blackest grain, and into store conveyed: \r
+Part hidden veins digged up (nor hath this earth \r
+Entrails unlike) of mineral and stone, \r
+Whereof to found their engines and their balls \r
+Of missive ruin; part incentive reed \r
+Provide, pernicious with one touch to fire. \r
+So all ere day-spring, under conscious night, \r
+Secret they finished, and in order set, \r
+With silent circumspection, unespied. \r
+Now when fair morn orient in Heaven appeared, \r
+Up rose the victor-Angels, and to arms \r
+The matin trumpet sung:  In arms they stood \r
+Of golden panoply, refulgent host, \r
+Soon banded; others from the dawning hills \r
+Look round, and scouts each coast light-armed scour, \r
+Each quarter to descry the distant foe, \r
+Where lodged, or whither fled, or if for fight, \r
+In motion or in halt:  Him soon they met \r
+Under spread ensigns moving nigh, in slow \r
+But firm battalion; back with speediest sail \r
+Zophiel, of Cherubim the swiftest wing, \r
+Came flying, and in mid air aloud thus cried. \r
+Arm, Warriours, arm for fight; the foe at hand, \r
+Whom fled we thought, will save us long pursuit \r
+This day; fear not his flight;so thick a cloud \r
+He comes, and settled in his face I see \r
+Sad resolution, and secure:  Let each \r
+His adamantine coat gird well, and each \r
+Fit well his helm, gripe fast his orbed shield, \r
+Borne even or high; for this day will pour down, \r
+If I conjecture aught, no drizzling shower, \r
+But rattling storm of arrows barbed with fire. \r
+So warned he them, aware themselves, and soon \r
+In order, quit of all impediment; \r
+Instant without disturb they took alarm, \r
+And onward moved embattled:  When behold! \r
+Not distant far with heavy pace the foe \r
+Approaching gross and huge, in hollow cube \r
+Training his devilish enginery, impaled \r
+On every side with shadowing squadrons deep, \r
+To hide the fraud.  At interview both stood \r
+A while; but suddenly at head appeared \r
+Satan, and thus was heard commanding loud. \r
+Vanguard, to right and left the front unfold; \r
+That all may see who hate us, how we seek \r
+Peace and composure, and with open breast \r
+Stand ready to receive them, if they like \r
+Our overture; and turn not back perverse: \r
+But that I doubt; however witness, Heaven! \r
+Heaven, witness thou anon! while we discharge \r
+Freely our part: ye, who appointed stand \r
+Do as you have in charge, and briefly touch \r
+What we propound, and loud that all may hear! \r
+So scoffing in ambiguous words, he scarce \r
+Had ended; when to right and left the front \r
+Divided, and to either flank retired: \r
+Which to our eyes discovered, new and strange, \r
+A triple mounted row of pillars laid \r
+On wheels (for like to pillars most they seemed, \r
+Or hollowed bodies made of oak or fir, \r
+With branches lopt, in wood or mountain felled,) \r
+Brass, iron, stony mould, had not their mouths \r
+With hideous orifice gaped on us wide, \r
+Portending hollow truce:  At each behind \r
+A Seraph stood, and in his hand a reed \r
+Stood waving tipt with fire; while we, suspense, \r
+Collected stood within our thoughts amused, \r
+Not long; for sudden all at once their reeds \r
+Put forth, and to a narrow vent applied \r
+With nicest touch.  Immediate in a flame, \r
+But soon obscured with smoke, all Heaven appeared, \r
+From those deep-throated engines belched, whose roar \r
+Embowelled with outrageous noise the air, \r
+And all her entrails tore, disgorging foul \r
+Their devilish glut, chained thunderbolts and hail \r
+Of iron globes; which, on the victor host \r
+Levelled, with such impetuous fury smote, \r
+That, whom they hit, none on their feet might stand, \r
+Though standing else as rocks, but down they fell \r
+By thousands, Angel on Arch-Angel rolled; \r
+The sooner for their arms; unarmed, they might \r
+Have easily, as Spirits, evaded swift \r
+By quick contraction or remove; but now \r
+Foul dissipation followed, and forced rout; \r
+Nor served it to relax their serried files. \r
+What should they do? if on they rushed, repulse \r
+Repeated, and indecent overthrow \r
+Doubled, would render them yet more despised, \r
+And to their foes a laughter; for in view \r
+Stood ranked of Seraphim another row, \r
+In posture to displode their second tire \r
+Of thunder:  Back defeated to return \r
+They worse abhorred.  Satan beheld their plight, \r
+And to his mates thus in derision called. \r
+O Friends! why come not on these victors proud \r
+Ere while they fierce were coming; and when we, \r
+To entertain them fair with open front \r
+And breast, (what could we more?) propounded terms \r
+Of composition, straight they changed their minds, \r
+Flew off, and into strange vagaries fell, \r
+As they would dance; yet for a dance they seemed \r
+Somewhat extravagant and wild; perhaps \r
+For joy of offered peace:  But I suppose, \r
+If our proposals once again were heard, \r
+We should compel them to a quick result. \r
+To whom thus Belial, in like gamesome mood. \r
+Leader! the terms we sent were terms of weight, \r
+Of hard contents, and full of force urged home; \r
+Such as we might perceive amused them all, \r
+And stumbled many:  Who receives them right, \r
+Had need from head to foot well understand; \r
+Not understood, this gift they have besides, \r
+They show us when our foes walk not upright. \r
+So they among themselves in pleasant vein \r
+Stood scoffing, hightened in their thoughts beyond \r
+All doubt of victory:  Eternal Might \r
+To match with their inventions they presumed \r
+So easy, and of his thunder made a scorn, \r
+And all his host derided, while they stood \r
+A while in trouble:  But they stood not long; \r
+Rage prompted them at length, and found them arms \r
+Against such hellish mischief fit to oppose. \r
+Forthwith (behold the excellence, the power, \r
+Which God hath in his mighty Angels placed!) \r
+Their arms away they threw, and to the hills \r
+(For Earth hath this variety from Heaven \r
+Of pleasure situate in hill and dale,) \r
+Light as the lightning glimpse they ran, they flew; \r
+From their foundations loosening to and fro, \r
+They plucked the seated hills, with all their load, \r
+Rocks, waters, woods, and by the shaggy tops \r
+Up-lifting bore them in their hands:  Amaze, \r
+Be sure, and terrour, seized the rebel host, \r
+When coming towards them so dread they saw \r
+The bottom of the mountains upward turned; \r
+Till on those cursed engines' triple-row \r
+They saw them whelmed, and all their confidence \r
+Under the weight of mountains buried deep; \r
+Themselves invaded next, and on their heads \r
+Main promontories flung, which in the air \r
+Came shadowing, and oppressed whole legions armed; \r
+Their armour helped their harm, crushed in and bruised \r
+Into their substance pent, which wrought them pain \r
+Implacable, and many a dolorous groan; \r
+Long struggling underneath, ere they could wind \r
+Out of such prison, though Spirits of purest light, \r
+Purest at first, now gross by sinning grown. \r
+The rest, in imitation, to like arms \r
+Betook them, and the neighbouring hills uptore: \r
+So hills amid the air encountered hills, \r
+Hurled to and fro with jaculation dire; \r
+That under ground they fought in dismal shade; \r
+Infernal noise! war seemed a civil game \r
+To this uproar; horrid confusion heaped \r
+Upon confusion rose:  And now all Heaven \r
+Had gone to wrack, with ruin overspread; \r
+Had not the Almighty Father, where he sits \r
+Shrined in his sanctuary of Heaven secure, \r
+Consulting on the sum of things, foreseen \r
+This tumult, and permitted all, advised: \r
+That his great purpose he might so fulfil, \r
+To honour his anointed Son avenged \r
+Upon his enemies, and to declare \r
+All power on him transferred:  Whence to his Son, \r
+The Assessour of his throne, he thus began. \r
+Effulgence of my glory, Son beloved, \r
+Son, in whose face invisible is beheld \r
+Visibly, what by Deity I am; \r
+And in whose hand what by decree I do, \r
+Second Omnipotence! two days are past, \r
+Two days, as we compute the days of Heaven, \r
+Since Michael and his Powers went forth to tame \r
+These disobedient:  Sore hath been their fight, \r
+As likeliest was, when two such foes met armed; \r
+For to themselves I left them; and thou knowest, \r
+Equal in their creation they were formed, \r
+Save what sin hath impaired; which yet hath wrought \r
+Insensibly, for I suspend their doom; \r
+Whence in perpetual fight they needs must last \r
+Endless, and no solution will be found: \r
+War wearied hath performed what war can do, \r
+And to disordered rage let loose the reins \r
+With mountains, as with weapons, armed; which makes \r
+Wild work in Heaven, and dangerous to the main. \r
+Two days are therefore past, the third is thine; \r
+For thee I have ordained it; and thus far \r
+Have suffered, that the glory may be thine \r
+Of ending this great war, since none but Thou \r
+Can end it.  Into thee such virtue and grace \r
+Immense I have transfused, that all may know \r
+In Heaven and Hell thy power above compare; \r
+And, this perverse commotion governed thus, \r
+To manifest thee worthiest to be Heir \r
+Of all things; to be Heir, and to be King \r
+By sacred unction, thy deserved right. \r
+Go then, Thou Mightiest, in thy Father's might; \r
+Ascend my chariot, guide the rapid wheels \r
+That shake Heaven's basis, bring forth all my war, \r
+My bow and thunder, my almighty arms \r
+Gird on, and sword upon thy puissant thigh; \r
+Pursue these sons of darkness, drive them out \r
+From all Heaven's bounds into the utter deep: \r
+There let them learn, as likes them, to despise \r
+God, and Messiah his anointed King. \r
+He said, and on his Son with rays direct \r
+Shone full; he all his Father full expressed \r
+Ineffably into his face received; \r
+And thus the Filial Godhead answering spake. \r
+O Father, O Supreme of heavenly Thrones, \r
+First, Highest, Holiest, Best; thou always seek'st \r
+To glorify thy Son, I always thee, \r
+As is most just:  This I my glory account, \r
+My exaltation, and my whole delight, \r
+That thou, in me well pleased, declarest thy will \r
+Fulfilled, which to fulfil is all my bliss. \r
+Scepter and power, thy giving, I assume, \r
+And gladlier shall resign, when in the end \r
+Thou shalt be all in all, and I in thee \r
+For ever; and in me all whom thou lovest: \r
+But whom thou hatest, I hate, and can put on \r
+Thy terrours, as I put thy mildness on, \r
+Image of thee in all things; and shall soon, \r
+Armed with thy might, rid Heaven of these rebelled; \r
+To their prepared ill mansion driven down, \r
+To chains of darkness, and the undying worm; \r
+That from thy just obedience could revolt, \r
+Whom to obey is happiness entire. \r
+Then shall thy Saints unmixed, and from the impure \r
+Far separate, circling thy holy mount, \r
+Unfeigned Halleluiahs to thee sing, \r
+Hymns of high praise, and I among them Chief. \r
+So said, he, o'er his scepter bowing, rose \r
+From the right hand of Glory where he sat; \r
+And the third sacred morn began to shine, \r
+Dawning through Heaven.  Forth rushed with whirlwind sound \r
+The chariot of Paternal Deity, \r
+Flashing thick flames, wheel within wheel undrawn, \r
+Itself instinct with Spirit, but convoyed \r
+By four Cherubick shapes; four faces each \r
+Had wonderous; as with stars, their bodies all \r
+And wings were set with eyes; with eyes the wheels \r
+Of beryl, and careering fires between; \r
+Over their heads a crystal firmament, \r
+Whereon a sapphire throne, inlaid with pure \r
+Amber, and colours of the showery arch. \r
+He, in celestial panoply all armed \r
+Of radiant Urim, work divinely wrought, \r
+Ascended; at his right hand Victory \r
+Sat eagle-winged; beside him hung his bow \r
+And quiver with three-bolted thunder stored; \r
+And from about him fierce effusion rolled \r
+Of smoke, and bickering flame, and sparkles dire: \r
+Attended with ten thousand thousand Saints, \r
+He onward came; far off his coming shone; \r
+And twenty thousand (I their number heard) \r
+Chariots of God, half on each hand, were seen; \r
+He on the wings of Cherub rode sublime \r
+On the crystalline sky, in sapphire throned, \r
+Illustrious far and wide; but by his own \r
+First seen:  Them unexpected joy surprised, \r
+When the great ensign of Messiah blazed \r
+Aloft by Angels borne, his sign in Heaven; \r
+Under whose conduct Michael soon reduced \r
+His army, circumfused on either wing, \r
+Under their Head imbodied all in one. \r
+Before him Power Divine his way prepared; \r
+At his command the uprooted hills retired \r
+Each to his place; they heard his voice, and went \r
+Obsequious; Heaven his wonted face renewed, \r
+And with fresh flowerets hill and valley smiled. \r
+This saw his hapless foes, but stood obdured, \r
+And to rebellious fight rallied their Powers, \r
+Insensate, hope conceiving from despair. \r
+In heavenly Spirits could such perverseness dwell? \r
+But to convince the proud what signs avail, \r
+Or wonders move the obdurate to relent? \r
+They, hardened more by what might most reclaim, \r
+Grieving to see his glory, at the sight \r
+Took envy; and, aspiring to his highth, \r
+Stood re-embattled fierce, by force or fraud \r
+Weening to prosper, and at length prevail \r
+Against God and Messiah, or to fall \r
+In universal ruin last; and now \r
+To final battle drew, disdaining flight, \r
+Or faint retreat; when the great Son of God \r
+To all his host on either hand thus spake. \r
+Stand still in bright array, ye Saints; here stand, \r
+Ye Angels armed; this day from battle rest: \r
+Faithful hath been your warfare, and of God \r
+Accepted, fearless in his righteous cause; \r
+And as ye have received, so have ye done, \r
+Invincibly:  But of this cursed crew \r
+The punishment to other hand belongs; \r
+Vengeance is his, or whose he sole appoints: \r
+Number to this day's work is not ordained, \r
+Nor multitude; stand only, and behold \r
+God's indignation on these godless poured \r
+By me; not you, but me, they have despised, \r
+Yet envied; against me is all their rage, \r
+Because the Father, to whom in Heaven s'preme \r
+Kingdom, and power, and glory appertains, \r
+Hath honoured me, according to his will. \r
+Therefore to me their doom he hath assigned; \r
+That they may have their wish, to try with me \r
+In battle which the stronger proves; they all, \r
+Or I alone against them; since by strength \r
+They measure all, of other excellence \r
+Not emulous, nor care who them excels; \r
+Nor other strife with them do I vouchsafe. \r
+So spake the Son, and into terrour changed \r
+His countenance too severe to be beheld, \r
+And full of wrath bent on his enemies. \r
+At once the Four spread out their starry wings \r
+With dreadful shade contiguous, and the orbs \r
+Of his fierce chariot rolled, as with the sound \r
+Of torrent floods, or of a numerous host. \r
+He on his impious foes right onward drove, \r
+Gloomy as night; under his burning wheels \r
+The stedfast empyrean shook throughout, \r
+All but the throne itself of God.  Full soon \r
+Among them he arrived; in his right hand \r
+Grasping ten thousand thunders, which he sent \r
+Before him, such as in their souls infixed \r
+Plagues:  They, astonished, all resistance lost, \r
+All courage; down their idle weapons dropt: \r
+O'er shields, and helms, and helmed heads he rode \r
+Of Thrones and mighty Seraphim prostrate, \r
+That wished the mountains now might be again \r
+Thrown on them, as a shelter from his ire. \r
+Nor less on either side tempestuous fell \r
+His arrows, from the fourfold-visaged Four \r
+Distinct with eyes, and from the living wheels \r
+Distinct alike with multitude of eyes; \r
+One Spirit in them ruled; and every eye \r
+Glared lightning, and shot forth pernicious fire \r
+Among the accursed, that withered all their strength, \r
+And of their wonted vigour left them drained, \r
+Exhausted, spiritless, afflicted, fallen. \r
+Yet half his strength he put not forth, but checked \r
+His thunder in mid volley; for he meant \r
+Not to destroy, but root them out of Heaven: \r
+The overthrown he raised, and as a herd \r
+Of goats or timorous flock together thronged \r
+Drove them before him thunder-struck, pursued \r
+With terrours, and with furies, to the bounds \r
+And crystal wall of Heaven; which, opening wide, \r
+Rolled inward, and a spacious gap disclosed \r
+Into the wasteful deep:  The monstrous sight \r
+Struck them with horrour backward, but far worse \r
+Urged them behind:  Headlong themselves they threw \r
+Down from the verge of Heaven; eternal wrath \r
+Burnt after them to the bottomless pit. \r
+Hell heard the unsufferable noise, Hell saw \r
+Heaven ruining from Heaven, and would have fled \r
+Affrighted; but strict Fate had cast too deep \r
+Her dark foundations, and too fast had bound. \r
+Nine days they fell:  Confounded Chaos roared, \r
+And felt tenfold confusion in their fall \r
+Through his wild anarchy, so huge a rout \r
+Incumbered him with ruin:  Hell at last \r
+Yawning received them whole, and on them closed; \r
+Hell, their fit habitation, fraught with fire \r
+Unquenchable, the house of woe and pain. \r
+Disburdened Heaven rejoiced, and soon repaired \r
+Her mural breach, returning whence it rolled. \r
+Sole victor, from the expulsion of his foes, \r
+Messiah his triumphal chariot turned: \r
+To meet him all his Saints, who silent stood \r
+Eye-witnesses of his almighty acts, \r
+With jubilee advanced; and, as they went, \r
+Shaded with branching palm, each Order bright, \r
+Sung triumph, and him sung victorious King, \r
+Son, Heir, and Lord, to him dominion given, \r
+Worthiest to reign:  He, celebrated, rode \r
+Triumphant through mid Heaven, into the courts \r
+And temple of his Mighty Father throned \r
+On high; who into glory him received, \r
+Where now he sits at the right hand of bliss. \r
+Thus, measuring things in Heaven by things on Earth, \r
+At thy request, and that thou mayest beware \r
+By what is past, to thee I have revealed \r
+What might have else to human race been hid; \r
+The discord which befel, and war in Heaven \r
+Among the angelick Powers, and the deep fall \r
+Of those too high aspiring, who rebelled \r
+With Satan; he who envies now thy state, \r
+Who now is plotting how he may seduce \r
+Thee also from obedience, that, with him \r
+Bereaved of happiness, thou mayest partake \r
+His punishment, eternal misery; \r
+Which would be all his solace and revenge, \r
+As a despite done against the Most High, \r
+Thee once to gain companion of his woe. \r
+But listen not to his temptations, warn \r
+Thy weaker; let it profit thee to have heard, \r
+By terrible example, the reward \r
+Of disobedience; firm they might have stood, \r
+Yet fell; remember, and fear to transgress. \r
\r
\r
\r
+Book VII                                                         \r
\r
\r
+Descend from Heaven, Urania, by that name \r
+If rightly thou art called, whose voice divine \r
+Following, above the Olympian hill I soar, \r
+Above the flight of Pegasean wing! \r
+The meaning, not the name, I call: for thou \r
+Nor of the Muses nine, nor on the top \r
+Of old Olympus dwellest; but, heavenly-born, \r
+Before the hills appeared, or fountain flowed, \r
+Thou with eternal Wisdom didst converse, \r
+Wisdom thy sister, and with her didst play \r
+In presence of the Almighty Father, pleased \r
+With thy celestial song.  Up led by thee \r
+Into the Heaven of Heavens I have presumed, \r
+An earthly guest, and drawn empyreal air, \r
+Thy tempering: with like safety guided down \r
+Return me to my native element: \r
+Lest from this flying steed unreined, (as once \r
+Bellerophon, though from a lower clime,) \r
+Dismounted, on the Aleian field I fall, \r
+Erroneous there to wander, and forlorn. \r
+Half yet remains unsung, but narrower bound \r
+Within the visible diurnal sphere; \r
+Standing on earth, not rapt above the pole, \r
+More safe I sing with mortal voice, unchanged \r
+To hoarse or mute, though fallen on evil days, \r
+On evil days though fallen, and evil tongues; \r
+In darkness, and with dangers compassed round, \r
+And solitude; yet not alone, while thou \r
+Visitest my slumbers nightly, or when morn \r
+Purples the east: still govern thou my song, \r
+Urania, and fit audience find, though few. \r
+But drive far off the barbarous dissonance \r
+Of Bacchus and his revellers, the race \r
+Of that wild rout that tore the Thracian bard \r
+In Rhodope, where woods and rocks had ears \r
+To rapture, till the savage clamour drowned \r
+Both harp and voice; nor could the Muse defend \r
+Her son.  So fail not thou, who thee implores: \r
+For thou art heavenly, she an empty dream. \r
+Say, Goddess, what ensued when Raphael, \r
+The affable Arch-Angel, had forewarned \r
+Adam, by dire example, to beware \r
+Apostasy, by what befel in Heaven \r
+To those apostates; lest the like befall \r
+In Paradise to Adam or his race, \r
+Charged not to touch the interdicted tree, \r
+If they transgress, and slight that sole command, \r
+So easily obeyed amid the choice \r
+Of all tastes else to please their appetite, \r
+Though wandering.  He, with his consorted Eve, \r
+The story heard attentive, and was filled \r
+With admiration and deep muse, to hear \r
+Of things so high and strange; things, to their thought \r
+So unimaginable, as hate in Heaven, \r
+And war so near the peace of God in bliss, \r
+With such confusion: but the evil, soon \r
+Driven back, redounded as a flood on those \r
+From whom it sprung; impossible to mix \r
+With blessedness.  Whence Adam soon repealed \r
+The doubts that in his heart arose: and now \r
+Led on, yet sinless, with desire to know \r
+What nearer might concern him, how this world \r
+Of Heaven and Earth conspicuous first began; \r
+When, and whereof created; for what cause; \r
+What within Eden, or without, was done \r
+Before his memory; as one whose drouth \r
+Yet scarce allayed still eyes the current stream, \r
+Whose liquid murmur heard new thirst excites, \r
+Proceeded thus to ask his heavenly guest. \r
+Great things, and full of wonder in our ears, \r
+Far differing from this world, thou hast revealed, \r
+Divine interpreter! by favour sent \r
+Down from the empyrean, to forewarn \r
+Us timely of what might else have been our loss, \r
+Unknown, which human knowledge could not reach; \r
+For which to the infinitely Good we owe \r
+Immortal thanks, and his admonishment \r
+Receive, with solemn purpose to observe \r
+Immutably his sovran will, the end \r
+Of what we are.  But since thou hast vouchsafed \r
+Gently, for our instruction, to impart \r
+Things above earthly thought, which yet concerned \r
+Our knowing, as to highest wisdom seemed, \r
+Deign to descend now lower, and relate \r
+What may no less perhaps avail us known, \r
+How first began this Heaven which we behold \r
+Distant so high, with moving fires adorned \r
+Innumerable; and this which yields or fills \r
+All space, the ambient air wide interfused \r
+Embracing round this floried Earth; what cause \r
+Moved the Creator, in his holy rest \r
+Through all eternity, so late to build \r
+In Chaos; and the work begun, how soon \r
+Absolved; if unforbid thou mayest unfold \r
+What we, not to explore the secrets ask \r
+Of his eternal empire, but the more \r
+To magnify his works, the more we know. \r
+And the great light of day yet wants to run \r
+Much of his race though steep; suspense in Heaven, \r
+Held by thy voice, thy potent voice, he hears, \r
+And longer will delay to hear thee tell \r
+His generation, and the rising birth \r
+Of Nature from the unapparent Deep: \r
+Or if the star of evening and the moon \r
+Haste to thy audience, Night with her will bring, \r
+Silence; and Sleep, listening to thee, will watch; \r
+Or we can bid his absence, till thy song \r
+End, and dismiss thee ere the morning shine. \r
+Thus Adam his illustrious guest besought: \r
+And thus the Godlike Angel answered mild. \r
+This also thy request, with caution asked, \r
+Obtain; though to recount almighty works \r
+What words or tongue of Seraph can suffice, \r
+Or heart of man suffice to comprehend? \r
+Yet what thou canst attain, which best may serve \r
+To glorify the Maker, and infer \r
+Thee also happier, shall not be withheld \r
+Thy hearing; such commission from above \r
+I have received, to answer thy desire \r
+Of knowledge within bounds; beyond, abstain \r
+To ask; nor let thine own inventions hope \r
+Things not revealed, which the invisible King, \r
+Only Omniscient, hath suppressed in night; \r
+To none communicable in Earth or Heaven: \r
+Enough is left besides to search and know. \r
+But knowledge is as food, and needs no less \r
+Her temperance over appetite, to know \r
+In measure what the mind may well contain; \r
+Oppresses else with surfeit, and soon turns \r
+Wisdom to folly, as nourishment to wind. \r
+Know then, that, after Lucifer from Heaven \r
+(So call him, brighter once amidst the host \r
+Of Angels, than that star the stars among,) \r
+Fell with his flaming legions through the deep \r
+Into his place, and the great Son returned \r
+Victorious with his Saints, the Omnipotent \r
+Eternal Father from his throne beheld \r
+Their multitude, and to his Son thus spake. \r
+At least our envious Foe hath failed, who thought \r
+All like himself rebellious, by whose aid \r
+This inaccessible high strength, the seat \r
+Of Deity supreme, us dispossessed, \r
+He trusted to have seised, and into fraud \r
+Drew many, whom their place knows here no more: \r
+Yet far the greater part have kept, I see, \r
+Their station; Heaven, yet populous, retains \r
+Number sufficient to possess her realms \r
+Though wide, and this high temple to frequent \r
+With ministeries due, and solemn rites: \r
+But, lest his heart exalt him in the harm \r
+Already done, to have dispeopled Heaven, \r
+My damage fondly deemed, I can repair \r
+That detriment, if such it be to lose \r
+Self-lost; and in a moment will create \r
+Another world, out of one man a race \r
+Of men innumerable, there to dwell, \r
+Not here; till, by degrees of merit raised, \r
+They open to themselves at length the way \r
+Up hither, under long obedience tried; \r
+And Earth be changed to Heaven, and Heaven to Earth, \r
+One kingdom, joy and union without end. \r
+Mean while inhabit lax, ye Powers of Heaven; \r
+And thou my Word, begotten Son, by thee \r
+This I perform; speak thou, and be it done! \r
+My overshadowing Spirit and Might with thee \r
+I send along; ride forth, and bid the Deep \r
+Within appointed bounds be Heaven and Earth; \r
+Boundless the Deep, because I Am who fill \r
+Infinitude, nor vacuous the space. \r
+Though I, uncircumscribed myself, retire, \r
+And put not forth my goodness, which is free \r
+To act or not, Necessity and Chance \r
+Approach not me, and what I will is Fate. \r
+So spake the Almighty, and to what he spake \r
+His Word, the Filial Godhead, gave effect. \r
+Immediate are the acts of God, more swift \r
+Than time or motion, but to human ears \r
+Cannot without process of speech be told, \r
+So told as earthly notion can receive. \r
+Great triumph and rejoicing was in Heaven, \r
+When such was heard declared the Almighty's will; \r
+Glory they sung to the Most High, good will \r
+To future men, and in their dwellings peace; \r
+Glory to Him, whose just avenging ire \r
+Had driven out the ungodly from his sight \r
+And the habitations of the just; to Him \r
+Glory and praise, whose wisdom had ordained \r
+Good out of evil to create; instead \r
+Of Spirits malign, a better race to bring \r
+Into their vacant room, and thence diffuse \r
+His good to worlds and ages infinite. \r
+So sang the Hierarchies:  Mean while the Son \r
+On his great expedition now appeared, \r
+Girt with Omnipotence, with radiance crowned \r
+Of Majesty Divine; sapience and love \r
+Immense, and all his Father in him shone. \r
+About his chariot numberless were poured \r
+Cherub, and Seraph, Potentates, and Thrones, \r
+And Virtues, winged Spirits, and chariots winged \r
+From the armoury of God; where stand of old \r
+Myriads, between two brazen mountains lodged \r
+Against a solemn day, harnessed at hand, \r
+Celestial equipage; and now came forth \r
+Spontaneous, for within them Spirit lived, \r
+Attendant on their Lord:  Heaven opened wide \r
+Her ever-during gates, harmonious sound \r
+On golden hinges moving, to let forth \r
+The King of Glory, in his powerful Word \r
+And Spirit, coming to create new worlds. \r
+On heavenly ground they stood; and from the shore \r
+They viewed the vast immeasurable abyss \r
+Outrageous as a sea, dark, wasteful, wild, \r
+Up from the bottom turned by furious winds \r
+And surging waves, as mountains, to assault \r
+Heaven's highth, and with the center mix the pole. \r
+Silence, ye troubled Waves, and thou Deep, peace, \r
+Said then the Omnifick Word; your discord end! \r
+Nor staid; but, on the wings of Cherubim \r
+Uplifted, in paternal glory rode \r
+Far into Chaos, and the world unborn; \r
+For Chaos heard his voice:  Him all his train \r
+Followed in bright procession, to behold \r
+Creation, and the wonders of his might. \r
+Then staid the fervid wheels, and in his hand \r
+He took the golden compasses, prepared \r
+In God's eternal store, to circumscribe \r
+This universe, and all created things: \r
+One foot he centered, and the other turned \r
+Round through the vast profundity obscure; \r
+And said, Thus far extend, thus far thy bounds, \r
+This be thy just circumference, O World! \r
+Thus God the Heaven created, thus the Earth, \r
+Matter unformed and void:  Darkness profound \r
+Covered the abyss: but on the watery calm \r
+His brooding wings the Spirit of God outspread, \r
+And vital virtue infused, and vital warmth \r
+Throughout the fluid mass; but downward purged \r
+The black tartareous cold infernal dregs, \r
+Adverse to life: then founded, then conglobed \r
+Like things to like; the rest to several place \r
+Disparted, and between spun out the air; \r
+And Earth self-balanced on her center hung. \r
+Let there be light, said God; and forthwith Light \r
+Ethereal, first of things, quintessence pure, \r
+Sprung from the deep; and from her native east \r
+To journey through the aery gloom began, \r
+Sphered in a radiant cloud, for yet the sun \r
+Was not; she in a cloudy tabernacle \r
+Sojourned the while.  God saw the light was good; \r
+And light from darkness by the hemisphere \r
+Divided: light the Day, and darkness Night, \r
+He named.  Thus was the first day even and morn: \r
+Nor past uncelebrated, nor unsung \r
+By the celestial quires, when orient light \r
+Exhaling first from darkness they beheld; \r
+Birth-day of Heaven and Earth; with joy and shout \r
+The hollow universal orb they filled, \r
+And touched their golden harps, and hymning praised \r
+God and his works; Creator him they sung, \r
+Both when first evening was, and when first morn. \r
+Again, God said,  Let there be firmament \r
+Amid the waters, and let it divide \r
+The waters from the waters; and God made \r
+The firmament, expanse of liquid, pure, \r
+Transparent, elemental air, diffused \r
+In circuit to the uttermost convex \r
+Of this great round; partition firm and sure, \r
+The waters underneath from those above \r
+Dividing: for as earth, so he the world \r
+Built on circumfluous waters calm, in wide \r
+Crystalline ocean, and the loud misrule \r
+Of Chaos far removed; lest fierce extremes \r
+Contiguous might distemper the whole frame: \r
+And Heaven he named the Firmament:  So even \r
+And morning chorus sung the second day. \r
+The Earth was formed, but in the womb as yet \r
+Of waters, embryon immature involved, \r
+Appeared not: over all the face of Earth \r
+Main ocean flowed, not idle; but, with warm \r
+Prolifick humour softening all her globe, \r
+Fermented the great mother to conceive, \r
+Satiate with genial moisture; when God said, \r
+Be gathered now ye waters under Heaven \r
+Into one place, and let dry land appear. \r
+Immediately the mountains huge appear \r
+Emergent, and their broad bare backs upheave \r
+Into the clouds; their tops ascend the sky: \r
+So high as heaved the tumid hills, so low \r
+Down sunk a hollow bottom broad and deep, \r
+Capacious bed of waters:  Thither they \r
+Hasted with glad precipitance, uprolled, \r
+As drops on dust conglobing from the dry: \r
+Part rise in crystal wall, or ridge direct, \r
+For haste; such flight the great command impressed \r
+On the swift floods:  As armies at the call \r
+Of trumpet (for of armies thou hast heard) \r
+Troop to their standard; so the watery throng, \r
+Wave rolling after wave, where way they found, \r
+If steep, with torrent rapture, if through plain, \r
+Soft-ebbing; nor withstood them rock or hill; \r
+But they, or under ground, or circuit wide \r
+With serpent errour wandering, found their way, \r
+And on the washy oose deep channels wore; \r
+Easy, ere God had bid the ground be dry, \r
+All but within those banks, where rivers now \r
+Stream, and perpetual draw their humid train. \r
+The dry land, Earth; and the great receptacle \r
+Of congregated waters, he called Seas: \r
+And saw that it was good; and said, Let the Earth \r
+Put forth the verdant grass, herb yielding seed, \r
+And fruit-tree yielding fruit after her kind, \r
+Whose seed is in herself upon the Earth. \r
+He scarce had said, when the bare Earth, till then \r
+Desart and bare, unsightly, unadorned, \r
+Brought forth the tender grass, whose verdure clad \r
+Her universal face with pleasant green; \r
+Then herbs of every leaf, that sudden flowered \r
+Opening their various colours, and made gay \r
+Her bosom, smelling sweet: and, these scarce blown, \r
+Forth flourished thick the clustering vine, forth crept \r
+The swelling gourd, up stood the corny reed \r
+Embattled in her field, and the humble shrub, \r
+And bush with frizzled hair implicit:  Last \r
+Rose, as in dance, the stately trees, and spread \r
+Their branches hung with copious fruit, or gemmed \r
+Their blossoms:  With high woods the hills were crowned; \r
+With tufts the valleys, and each fountain side; \r
+With borders long the rivers: that Earth now \r
+Seemed like to Heaven, a seat where Gods might dwell, \r
+Or wander with delight, and love to haunt \r
+Her sacred shades: though God had yet not rained \r
+Upon the Earth, and man to till the ground \r
+None was; but from the Earth a dewy mist \r
+Went up, and watered all the ground, and each \r
+Plant of the field; which, ere it was in the Earth, \r
+God made, and every herb, before it grew \r
+On the green stem:  God saw that it was good: \r
+So even and morn recorded the third day. \r
+Again the Almighty spake, Let there be lights \r
+High in the expanse of Heaven, to divide \r
+The day from night; and let them be for signs, \r
+For seasons, and for days, and circling years; \r
+And let them be for lights, as I ordain \r
+Their office in the firmament of Heaven, \r
+To give light on the Earth; and it was so. \r
+And God made two great lights, great for their use \r
+To Man, the greater to have rule by day, \r
+The less by night, altern; and made the stars, \r
+And set them in the firmament of Heaven \r
+To illuminate the Earth, and rule the day \r
+In their vicissitude, and rule the night, \r
+And light from darkness to divide.  God saw, \r
+Surveying his great work, that it was good: \r
+For of celestial bodies first the sun \r
+A mighty sphere he framed, unlightsome first, \r
+Though of ethereal mould: then formed the moon \r
+Globose, and every magnitude of stars, \r
+And sowed with stars the Heaven, thick as a field: \r
+Of light by far the greater part he took, \r
+Transplanted from her cloudy shrine, and placed \r
+In the sun's orb, made porous to receive \r
+And drink the liquid light; firm to retain \r
+Her gathered beams, great palace now of light. \r
+Hither, as to their fountain, other stars \r
+Repairing, in their golden urns draw light, \r
+And hence the morning-planet gilds her horns; \r
+By tincture or reflection they augment \r
+Their small peculiar, though from human sight \r
+So far remote, with diminution seen, \r
+First in his east the glorious lamp was seen, \r
+Regent of day, and all the horizon round \r
+Invested with bright rays, jocund to run \r
+His longitude through Heaven's high road; the gray \r
+Dawn, and the Pleiades, before him danced, \r
+Shedding sweet influence:  Less bright the moon, \r
+But opposite in levelled west was set, \r
+His mirrour, with full face borrowing her light \r
+From him; for other light she needed none \r
+In that aspect, and still that distance keeps \r
+Till night; then in the east her turn she shines, \r
+Revolved on Heaven's great axle, and her reign \r
+With thousand lesser lights dividual holds, \r
+With thousand thousand stars, that then appeared \r
+Spangling the hemisphere:  Then first adorned \r
+With their bright luminaries that set and rose, \r
+Glad evening and glad morn crowned the fourth day. \r
+And God said, Let the waters generate \r
+Reptile with spawn abundant, living soul: \r
+And let fowl fly above the Earth, with wings \r
+Displayed on the open firmament of Heaven. \r
+And God created the great whales, and each \r
+Soul living, each that crept, which plenteously \r
+The waters generated by their kinds; \r
+And every bird of wing after his kind; \r
+And saw that it was good, and blessed them, saying. \r
+Be fruitful, multiply, and in the seas, \r
+And lakes, and running streams, the waters fill; \r
+And let the fowl be multiplied, on the Earth. \r
+Forthwith the sounds and seas, each creek and bay, \r
+With fry innumerable swarm, and shoals \r
+Of fish that with their fins, and shining scales, \r
+Glide under the green wave, in sculls that oft \r
+Bank the mid sea: part single, or with mate, \r
+Graze the sea-weed their pasture, and through groves \r
+Of coral stray; or, sporting with quick glance, \r
+Show to the sun their waved coats dropt with gold; \r
+Or, in their pearly shells at ease, attend \r
+Moist nutriment; or under rocks their food \r
+In jointed armour watch: on smooth the seal \r
+And bended dolphins play: part huge of bulk \r
+Wallowing unwieldy, enormous in their gait, \r
+Tempest the ocean: there leviathan, \r
+Hugest of living creatures, on the deep \r
+Stretched like a promontory sleeps or swims, \r
+And seems a moving land; and at his gills \r
+Draws in, and at his trunk spouts out, a sea. \r
+Mean while the tepid caves, and fens, and shores, \r
+Their brood as numerous hatch, from the egg that soon \r
+Bursting with kindly rupture forth disclosed \r
+Their callow young; but feathered soon and fledge \r
+They summed their pens; and, soaring the air sublime, \r
+With clang despised the ground, under a cloud \r
+In prospect; there the eagle and the stork \r
+On cliffs and cedar tops their eyries build: \r
+Part loosely wing the region, part more wise \r
+In common, ranged in figure, wedge their way, \r
+Intelligent of seasons, and set forth \r
+Their aery caravan, high over seas \r
+Flying, and over lands, with mutual wing \r
+Easing their flight; so steers the prudent crane \r
+Her annual voyage, borne on winds; the air \r
+Floats as they pass, fanned with unnumbered plumes: \r
+From branch to branch the smaller birds with song \r
+Solaced the woods, and spread their painted wings \r
+Till even; nor then the solemn nightingale \r
+Ceased warbling, but all night tun'd her soft lays: \r
+Others, on silver lakes and rivers, bathed \r
+Their downy breast; the swan with arched neck, \r
+Between her white wings mantling proudly, rows \r
+Her state with oary feet; yet oft they quit \r
+The dank, and, rising on stiff pennons, tower \r
+The mid aereal sky:  Others on ground \r
+Walked firm; the crested cock whose clarion sounds \r
+The silent hours, and the other whose gay train \r
+Adorns him, coloured with the florid hue \r
+Of rainbows and starry eyes.  The waters thus \r
+With fish replenished, and the air with fowl, \r
+Evening and morn solemnized the fifth day. \r
+The sixth, and of creation last, arose \r
+With evening harps and matin; when God said, \r
+Let the Earth bring forth soul living in her kind, \r
+Cattle, and creeping things, and beast of the Earth, \r
+Each in their kind.  The Earth obeyed, and straight \r
+Opening her fertile womb teemed at a birth \r
+Innumerous living creatures, perfect forms, \r
+Limbed and full grown:  Out of the ground up rose, \r
+As from his lair, the wild beast where he wons \r
+In forest wild, in thicket, brake, or den; \r
+Among the trees in pairs they rose, they walked: \r
+The cattle in the fields and meadows green: \r
+Those rare and solitary, these in flocks \r
+Pasturing at once, and in broad herds upsprung. \r
+The grassy clods now calved; now half appeared \r
+The tawny lion, pawing to get free \r
+His hinder parts, then springs as broke from bonds, \r
+And rampant shakes his brinded mane; the ounce, \r
+The libbard, and the tiger, as the mole \r
+Rising, the crumbled earth above them threw \r
+In hillocks:  The swift stag from under ground \r
+Bore up his branching head:  Scarce from his mould \r
+Behemoth biggest born of earth upheaved \r
+His vastness:  Fleeced the flocks and bleating rose, \r
+As plants:  Ambiguous between sea and land \r
+The river-horse, and scaly crocodile. \r
+At once came forth whatever creeps the ground, \r
+Insect or worm: those waved their limber fans \r
+For wings, and smallest lineaments exact \r
+In all the liveries decked of summer's pride \r
+With spots of gold and purple, azure and green: \r
+These, as a line, their long dimension drew, \r
+Streaking the ground with sinuous trace; not all \r
+Minims of nature; some of serpent-kind, \r
+Wonderous in length and corpulence, involved \r
+Their snaky folds, and added wings.  First crept \r
+The parsimonious emmet, provident \r
+Of future; in small room large heart enclosed; \r
+Pattern of just equality perhaps \r
+Hereafter, joined in her popular tribes \r
+Of commonalty:  Swarming next appeared \r
+The female bee, that feeds her husband drone \r
+Deliciously, and builds her waxen cells \r
+With honey stored:  The rest are numberless, \r
+And thou their natures knowest, and gavest them names, \r
+Needless to thee repeated; nor unknown \r
+The serpent, subtlest beast of all the field, \r
+Of huge extent sometimes, with brazen eyes \r
+And hairy mane terrifick, though to thee \r
+Not noxious, but obedient at thy call. \r
+Now Heaven in all her glory shone, and rolled \r
+Her motions, as the great first Mover's hand \r
+First wheeled their course:  Earth in her rich attire \r
+Consummate lovely smiled; air, water, earth, \r
+By fowl, fish, beast, was flown, was swum, was walked, \r
+Frequent; and of the sixth day yet remained: \r
+There wanted yet the master-work, the end \r
+Of all yet done; a creature, who, not prone \r
+And brute as other creatures, but endued \r
+With sanctity of reason, might erect \r
+His stature, and upright with front serene \r
+Govern the rest, self-knowing; and from thence \r
+Magnanimous to correspond with Heaven, \r
+But grateful to acknowledge whence his good \r
+Descends, thither with heart, and voice, and eyes \r
+Directed in devotion, to adore \r
+And worship God Supreme, who made him chief \r
+Of all his works:  therefore the Omnipotent \r
+Eternal Father (for where is not he \r
+Present?) thus to his Son audibly spake. \r
+Let us make now Man in our image, Man \r
+In our similitude, and let them rule \r
+Over the fish and fowl of sea and air, \r
+Beast of the field, and over all the Earth, \r
+And every creeping thing that creeps the ground. \r
+This said, he formed thee, Adam, thee, O Man, \r
+Dust of the ground, and in thy nostrils breathed \r
+The breath of life; in his own image he \r
+Created thee, in the image of God \r
+Express; and thou becamest a living soul. \r
+Male he created thee; but thy consort \r
+Female, for race; then blessed mankind, and said, \r
+Be fruitful, multiply, and fill the Earth; \r
+Subdue it, and throughout dominion hold \r
+Over fish of the sea, and fowl of the air, \r
+And every living thing that moves on the Earth. \r
+Wherever thus created, for no place \r
+Is yet distinct by name, thence, as thou knowest, \r
+He brought thee into this delicious grove, \r
+This garden, planted with the trees of God, \r
+Delectable both to behold and taste; \r
+And freely all their pleasant fruit for food \r
+Gave thee; all sorts are here that all the Earth yields, \r
+Variety without end; but of the tree, \r
+Which, tasted, works knowledge of good and evil, \r
+Thou mayest not; in the day thou eatest, thou diest; \r
+Death is the penalty imposed; beware, \r
+And govern well thy appetite; lest Sin \r
+Surprise thee, and her black attendant Death. \r
+Here finished he, and all that he had made \r
+Viewed, and behold all was entirely good; \r
+So even and morn accomplished the sixth day: \r
+Yet not till the Creator from his work \r
+Desisting, though unwearied, up returned, \r
+Up to the Heaven of Heavens, his high abode; \r
+Thence to behold this new created world, \r
+The addition of his empire, how it showed \r
+In prospect from his throne, how good, how fair, \r
+Answering his great idea.  Up he rode \r
+Followed with acclamation, and the sound \r
+Symphonious of ten thousand harps, that tuned \r
+Angelick harmonies:  The earth, the air \r
+Resounded, (thou rememberest, for thou heardst,) \r
+The heavens and all the constellations rung, \r
+The planets in their station listening stood, \r
+While the bright pomp ascended jubilant. \r
+Open, ye everlasting gates! they sung, \r
+Open, ye Heavens! your living doors;let in \r
+The great Creator from his work returned \r
+Magnificent, his six days work, a World; \r
+Open, and henceforth oft; for God will deign \r
+To visit oft the dwellings of just men, \r
+Delighted; and with frequent intercourse \r
+Thither will send his winged messengers \r
+On errands of supernal grace.  So sung \r
+The glorious train ascending:  He through Heaven, \r
+That opened wide her blazing portals, led \r
+To God's eternal house direct the way; \r
+A broad and ample road, whose dust is gold \r
+And pavement stars, as stars to thee appear, \r
+Seen in the galaxy, that milky way, \r
+Which nightly, as a circling zone, thou seest \r
+Powdered with stars.  And now on Earth the seventh \r
+Evening arose in Eden, for the sun \r
+Was set, and twilight from the east came on, \r
+Forerunning night; when at the holy mount \r
+Of Heaven's high-seated top, the imperial throne \r
+Of Godhead, fixed for ever firm and sure, \r
+The Filial Power arrived, and sat him down \r
+With his great Father; for he also went \r
+Invisible, yet staid, (such privilege \r
+Hath Omnipresence) and the work ordained, \r
+Author and End of all things; and, from work \r
+Now resting, blessed and hallowed the seventh day, \r
+As resting on that day from all his work, \r
+But not in silence holy kept: the harp \r
+Had work and rested not; the solemn pipe, \r
+And dulcimer, all organs of sweet stop, \r
+All sounds on fret by string or golden wire, \r
+Tempered soft tunings, intermixed with voice \r
+Choral or unison: of incense clouds, \r
+Fuming from golden censers, hid the mount. \r
+Creation and the six days acts they sung: \r
+Great are thy works, Jehovah! infinite \r
+Thy power! what thought can measure thee, or tongue \r
+Relate thee!  Greater now in thy return \r
+Than from the giant Angels:  Thee that day \r
+Thy thunders magnified; but to create \r
+Is greater than created to destroy. \r
+Who can impair thee, Mighty King, or bound \r
+Thy empire!  Easily the proud attempt \r
+Of Spirits apostate, and their counsels vain, \r
+Thou hast repelled; while impiously they thought \r
+Thee to diminish, and from thee withdraw \r
+The number of thy worshippers.  Who seeks \r
+To lessen thee, against his purpose serves \r
+To manifest the more thy might: his evil \r
+Thou usest, and from thence createst more good. \r
+Witness this new-made world, another Heaven \r
+From Heaven-gate not far, founded in view \r
+On the clear hyaline, the glassy sea; \r
+Of amplitude almost immense, with stars \r
+Numerous, and every star perhaps a world \r
+Of destined habitation; but thou knowest \r
+Their seasons: among these the seat of Men, \r
+Earth, with her nether ocean circumfused, \r
+Their pleasant dwelling-place.  Thrice happy Men, \r
+And sons of Men, whom God hath thus advanced! \r
+Created in his image, there to dwell \r
+And worship him; and in reward to rule \r
+Over his works, on earth, in sea, or air, \r
+And multiply a race of worshippers \r
+Holy and just:  Thrice happy, if they know \r
+Their happiness, and persevere upright! \r
+So sung they, and the empyrean rung \r
+With halleluiahs:  Thus was sabbath kept. \r
+And thy request think now fulfilled, that asked \r
+How first this world and face of things began, \r
+And what before thy memory was done \r
+From the beginning; that posterity, \r
+Informed by thee, might know:  If else thou seekest \r
+Aught, not surpassing human measure, say. \r
\r
\r
\r
+Book VIII                                                        \r
\r
\r
+The Angel ended, and in Adam's ear \r
+So charming left his voice, that he a while \r
+Thought him still speaking, still stood fixed to hear; \r
+Then, as new waked, thus gratefully replied. \r
+What thanks sufficient, or what recompence \r
+Equal, have I to render thee, divine \r
+Historian, who thus largely hast allayed \r
+The thirst I had of knowledge, and vouchsafed \r
+This friendly condescension to relate \r
+Things, else by me unsearchable; now heard \r
+With wonder, but delight, and, as is due, \r
+With glory attributed to the high \r
+Creator!  Something yet of doubt remains, \r
+Which only thy solution can resolve. \r
+When I behold this goodly frame, this world, \r
+Of Heaven and Earth consisting; and compute \r
+Their magnitudes; this Earth, a spot, a grain, \r
+An atom, with the firmament compared \r
+And all her numbered stars, that seem to roll \r
+Spaces incomprehensible, (for such \r
+Their distance argues, and their swift return \r
+Diurnal,) merely to officiate light \r
+Round this opacous Earth, this punctual spot, \r
+One day and night; in all her vast survey \r
+Useless besides; reasoning I oft admire, \r
+How Nature wise and frugal could commit \r
+Such disproportions, with superfluous hand \r
+So many nobler bodies to create, \r
+Greater so manifold, to this one use, \r
+For aught appears, and on their orbs impose \r
+Such restless revolution day by day \r
+Repeated; while the sedentary Earth, \r
+That better might with far less compass move, \r
+Served by more noble than herself, attains \r
+Her end without least motion, and receives, \r
+As tribute, such a sumless journey brought \r
+Of incorporeal speed, her warmth and light; \r
+Speed, to describe whose swiftness number fails. \r
+So spake our sire, and by his countenance seemed \r
+Entering on studious thoughts abstruse; which Eve \r
+Perceiving, where she sat retired in sight, \r
+With lowliness majestick from her seat, \r
+And grace that won who saw to wish her stay, \r
+Rose, and went forth among her fruits and flowers, \r
+To visit how they prospered, bud and bloom, \r
+Her nursery; they at her coming sprung, \r
+And, touched by her fair tendance, gladlier grew. \r
+Yet went she not, as not with such discourse \r
+Delighted, or not capable her ear \r
+Of what was high: such pleasure she reserved, \r
+Adam relating, she sole auditress; \r
+Her husband the relater she preferred \r
+Before the Angel, and of him to ask \r
+Chose rather; he, she knew, would intermix \r
+Grateful digressions, and solve high dispute \r
+With conjugal caresses: from his lip \r
+Not words alone pleased her.  O! when meet now \r
+Such pairs, in love and mutual honour joined? \r
+With Goddess-like demeanour forth she went, \r
+Not unattended; for on her, as Queen, \r
+A pomp of winning Graces waited still, \r
+And from about her shot darts of desire \r
+Into all eyes, to wish her still in sight. \r
+And Raphael now, to Adam's doubt proposed, \r
+Benevolent and facile thus replied. \r
+To ask or search, I blame thee not; for Heaven \r
+Is as the book of God before thee set, \r
+Wherein to read his wonderous works, and learn \r
+His seasons, hours, or days, or months, or years: \r
+This to attain, whether Heaven move or Earth, \r
+Imports not, if thou reckon right; the rest \r
+From Man or Angel the great Architect \r
+Did wisely to conceal, and not divulge \r
+His secrets to be scanned by them who ought \r
+Rather admire; or, if they list to try \r
+Conjecture, he his fabrick of the Heavens \r
+Hath left to their disputes, perhaps to move \r
+His laughter at their quaint opinions wide \r
+Hereafter; when they come to model Heaven \r
+And calculate the stars, how they will wield \r
+The mighty frame; how build, unbuild, contrive \r
+To save appearances; how gird the sphere \r
+With centrick and eccentrick scribbled o'er, \r
+Cycle and epicycle, orb in orb: \r
+Already by thy reasoning this I guess, \r
+Who art to lead thy offspring, and supposest \r
+That bodies bright and greater should not serve \r
+The less not bright, nor Heaven such journeys run, \r
+Earth sitting still, when she alone receives \r
+The benefit:  Consider first, that great \r
+Or bright infers not excellence: the Earth \r
+Though, in comparison of Heaven, so small, \r
+Nor glistering, may of solid good contain \r
+More plenty than the sun that barren shines; \r
+Whose virtue on itself works no effect, \r
+But in the fruitful Earth; there first received, \r
+His beams, unactive else, their vigour find. \r
+Yet not to Earth are those bright luminaries \r
+Officious; but to thee, Earth's habitant. \r
+And for the Heaven's wide circuit, let it speak \r
+The Maker's high magnificence, who built \r
+So spacious, and his line stretched out so far; \r
+That Man may know he dwells not in his own; \r
+An edifice too large for him to fill, \r
+Lodged in a small partition; and the rest \r
+Ordained for uses to his Lord best known. \r
+The swiftness of those circles attribute, \r
+Though numberless, to his Omnipotence, \r
+That to corporeal substances could add \r
+Speed almost spiritual:  Me thou thinkest not slow, \r
+Who since the morning-hour set out from Heaven \r
+Where God resides, and ere mid-day arrived \r
+In Eden; distance inexpressible \r
+By numbers that have name.  But this I urge, \r
+Admitting motion in the Heavens, to show \r
+Invalid that which thee to doubt it moved; \r
+Not that I so affirm, though so it seem \r
+To thee who hast thy dwelling here on Earth. \r
+God, to remove his ways from human sense, \r
+Placed Heaven from Earth so far, that earthly sight, \r
+If it presume, might err in things too high, \r
+And no advantage gain.  What if the sun \r
+Be center to the world; and other stars, \r
+By his attractive virtue and their own \r
+Incited, dance about him various rounds? \r
+Their wandering course now high, now low, then hid, \r
+Progressive, retrograde, or standing still, \r
+In six thou seest; and what if seventh to these \r
+The planet earth, so stedfast though she seem, \r
+Insensibly three different motions move? \r
+Which else to several spheres thou must ascribe, \r
+Moved contrary with thwart obliquities; \r
+Or save the sun his labour, and that swift \r
+Nocturnal and diurnal rhomb supposed, \r
+Invisible else above all stars, the wheel \r
+Of day and night; which needs not thy belief, \r
+If earth, industrious of herself, fetch day \r
+Travelling east, and with her part averse \r
+From the sun's beam meet night, her other part \r
+Still luminous by his ray.  What if that light, \r
+Sent from her through the wide transpicuous air, \r
+To the terrestrial moon be as a star, \r
+Enlightening her by day, as she by night \r
+This earth? reciprocal, if land be there, \r
+Fields and inhabitants:  Her spots thou seest \r
+As clouds, and clouds may rain, and rain produce \r
+Fruits in her softened soil for some to eat \r
+Allotted there; and other suns perhaps, \r
+With their attendant moons, thou wilt descry, \r
+Communicating male and female light; \r
+Which two great sexes animate the world, \r
+Stored in each orb perhaps with some that live. \r
+For such vast room in Nature unpossessed \r
+By living soul, desart and desolate, \r
+Only to shine, yet scarce to contribute \r
+Each orb a glimpse of light, conveyed so far \r
+Down to this habitable, which returns \r
+Light back to them, is obvious to dispute. \r
+But whether thus these things, or whether not; \r
+But whether the sun, predominant in Heaven, \r
+Rise on the earth; or earth rise on the sun; \r
+He from the east his flaming road begin; \r
+Or she from west her silent course advance, \r
+With inoffensive pace that spinning sleeps \r
+On her soft axle, while she paces even, \r
+And bears thee soft with the smooth hair along; \r
+Sollicit not thy thoughts with matters hid; \r
+Leave them to God above; him serve, and fear! \r
+Of other creatures, as him pleases best, \r
+Wherever placed, let him dispose; joy thou \r
+In what he gives to thee, this Paradise \r
+And thy fair Eve; Heaven is for thee too high \r
+To know what passes there; be lowly wise: \r
+Think only what concerns thee, and thy being; \r
+Dream not of other worlds, what creatures there \r
+Live, in what state, condition, or degree; \r
+Contented that thus far hath been revealed \r
+Not of Earth only, but of highest Heaven. \r
+To whom thus Adam, cleared of doubt, replied. \r
+How fully hast thou satisfied me, pure \r
+Intelligence of Heaven, Angel serene! \r
+And, freed from intricacies, taught to live \r
+The easiest way; nor with perplexing thoughts \r
+To interrupt the sweet of life, from which \r
+God hath bid dwell far off all anxious cares, \r
+And not molest us; unless we ourselves \r
+Seek them with wandering thoughts, and notions vain. \r
+But apt the mind or fancy is to rove \r
+Unchecked, and of her roving is no end; \r
+Till warned, or by experience taught, she learn, \r
+That, not to know at large of things remote \r
+From use, obscure and subtle; but, to know \r
+That which before us lies in daily life, \r
+Is the prime wisdom:  What is more, is fume, \r
+Or emptiness, or fond impertinence: \r
+And renders us, in things that most concern, \r
+Unpractised, unprepared, and still to seek. \r
+Therefore from this high pitch let us descend \r
+A lower flight, and speak of things at hand \r
+Useful; whence, haply, mention may arise \r
+Of something not unseasonable to ask, \r
+By sufferance, and thy wonted favour, deigned. \r
+Thee I have heard relating what was done \r
+Ere my remembrance: now, hear me relate \r
+My story, which perhaps thou hast not heard; \r
+And day is not yet spent; till then thou seest \r
+How subtly to detain thee I devise; \r
+Inviting thee to hear while I relate; \r
+Fond! were it not in hope of thy reply: \r
+For, while I sit with thee, I seem in Heaven; \r
+And sweeter thy discourse is to my ear \r
+Than fruits of palm-tree pleasantest to thirst \r
+And hunger both, from labour, at the hour \r
+Of sweet repast; they satiate, and soon fill, \r
+Though pleasant; but thy words, with grace divine \r
+Imbued, bring to their sweetness no satiety. \r
+To whom thus Raphael answered heavenly meek. \r
+Nor are thy lips ungraceful, Sire of men, \r
+Nor tongue ineloquent; for God on thee \r
+Abundantly his gifts hath also poured \r
+Inward and outward both, his image fair: \r
+Speaking, or mute, all comeliness and grace \r
+Attends thee; and each word, each motion, forms; \r
+Nor less think we in Heaven of thee on Earth \r
+Than of our fellow-servant, and inquire \r
+Gladly into the ways of God with Man: \r
+For God, we see, hath honoured thee, and set \r
+On Man his equal love:  Say therefore on; \r
+For I that day was absent, as befel, \r
+Bound on a voyage uncouth and obscure, \r
+Far on excursion toward the gates of Hell; \r
+Squared in full legion (such command we had) \r
+To see that none thence issued forth a spy, \r
+Or enemy, while God was in his work; \r
+Lest he, incensed at such eruption bold, \r
+Destruction with creation might have mixed. \r
+Not that they durst without his leave attempt; \r
+But us he sends upon his high behests \r
+For state, as Sovran King; and to inure \r
+Our prompt obedience.  Fast we found, fast shut, \r
+The dismal gates, and barricadoed strong; \r
+But long ere our approaching heard within \r
+Noise, other than the sound of dance or song, \r
+Torment, and loud lament, and furious rage. \r
+Glad we returned up to the coasts of light \r
+Ere sabbath-evening: so we had in charge. \r
+But thy relation now; for I attend, \r
+Pleased with thy words no less than thou with mine. \r
+So spake the Godlike Power, and thus our Sire. \r
+For Man to tell how human life began \r
+Is hard; for who himself beginning knew \r
+Desire with thee still longer to converse \r
+Induced me.  As new waked from soundest sleep, \r
+Soft on the flowery herb I found me laid, \r
+In balmy sweat; which with his beams the sun \r
+Soon dried, and on the reeking moisture fed. \r
+Straight toward Heaven my wondering eyes I turned, \r
+And gazed a while the ample sky; till, raised \r
+By quick instinctive motion, up I sprung, \r
+As thitherward endeavouring, and upright \r
+Stood on my feet: about me round I saw \r
+Hill, dale, and shady woods, and sunny plains, \r
+And liquid lapse of murmuring streams; by these, \r
+Creatures that lived and moved, and walked, or flew; \r
+Birds on the branches warbling; all things smiled; \r
+With fragrance and with joy my heart o'erflowed. \r
+Myself I then perused, and limb by limb \r
+Surveyed, and sometimes went, and sometimes ran \r
+With supple joints, as lively vigour led: \r
+But who I was, or where, or from what cause, \r
+Knew not; to speak I tried, and forthwith spake; \r
+My tongue obeyed, and readily could name \r
+Whate'er I saw.  Thou Sun, said I, fair light, \r
+And thou enlightened Earth, so fresh and gay, \r
+Ye Hills, and Dales, ye Rivers, Woods, and Plains, \r
+And ye that live and move, fair Creatures, tell, \r
+Tell, if ye saw, how I came thus, how here?-- \r
+Not of myself;--by some great Maker then, \r
+In goodness and in power pre-eminent: \r
+Tell me, how may I know him, how adore, \r
+From whom I have that thus I move and live, \r
+And feel that I am happier than I know.-- \r
+While thus I called, and strayed I knew not whither, \r
+From where I first drew air, and first beheld \r
+This happy light; when, answer none returned, \r
+On a green shady bank, profuse of flowers, \r
+Pensive I sat me down:  There gentle sleep \r
+First found me, and with soft oppression seised \r
+My droused sense, untroubled, though I thought \r
+I then was passing to my former state \r
+Insensible, and forthwith to dissolve: \r
+When suddenly stood at my head a dream, \r
+Whose inward apparition gently moved \r
+My fancy to believe I yet had being, \r
+And lived:  One came, methought, of shape divine, \r
+And said, 'Thy mansion wants thee, Adam; rise, \r
+'First Man, of men innumerable ordained \r
+'First Father! called by thee, I come thy guide \r
+'To the garden of bliss, thy seat prepared.' \r
+So saying, by the hand he took me raised, \r
+And over fields and waters, as in air \r
+Smooth-sliding without step, last led me up \r
+A woody mountain; whose high top was plain, \r
+A circuit wide, enclosed, with goodliest trees \r
+Planted, with walks, and bowers; that what I saw \r
+Of Earth before scarce pleasant seemed.  Each tree, \r
+Loaden with fairest fruit that hung to the eye \r
+Tempting, stirred in me sudden appetite \r
+To pluck and eat; whereat I waked, and found \r
+Before mine eyes all real, as the dream \r
+Had lively shadowed:  Here had new begun \r
+My wandering, had not he, who was my guide \r
+Up hither, from among the trees appeared, \r
+Presence Divine.  Rejoicing, but with awe, \r
+In adoration at his feet I fell \r
+Submiss:  He reared me, and 'Whom thou soughtest I am,' \r
+Said mildly, 'Author of all this thou seest \r
+'Above, or round about thee, or beneath. \r
+'This Paradise I give thee, count it thine \r
+'To till and keep, and of the fruit to eat: \r
+'Of every tree that in the garden grows \r
+'Eat freely with glad heart; fear here no dearth: \r
+'But of the tree whose operation brings \r
+'Knowledge of good and ill, which I have set \r
+'The pledge of thy obedience and thy faith, \r
+'Amid the garden by the tree of life, \r
+'Remember what I warn thee, shun to taste, \r
+'And shun the bitter consequence: for know, \r
+'The day thou eatest thereof, my sole command \r
+'Transgressed, inevitably thou shalt die, \r
+'From that day mortal; and this happy state \r
+'Shalt lose, expelled from hence into a world \r
+'Of woe and sorrow.'  Sternly he pronounced \r
+The rigid interdiction, which resounds \r
+Yet dreadful in mine ear, though in my choice \r
+Not to incur; but soon his clear aspect \r
+Returned, and gracious purpose thus renewed. \r
+'Not only these fair bounds, but all the Earth \r
+'To thee and to thy race I give; as lords \r
+'Possess it, and all things that therein live, \r
+'Or live in sea, or air; beast, fish, and fowl. \r
+'In sign whereof, each bird and beast behold \r
+'After their kinds; I bring them to receive \r
+'From thee their names, and pay thee fealty \r
+'With low subjection; understand the same \r
+'Of fish within their watery residence, \r
+'Not hither summoned, since they cannot change \r
+'Their element, to draw the thinner air.' \r
+As thus he spake, each bird and beast behold \r
+Approaching two and two; these cowering low \r
+With blandishment; each bird stooped on his wing. \r
+I named them, as they passed, and understood \r
+Their nature, with such knowledge God endued \r
+My sudden apprehension:  But in these \r
+I found not what methought I wanted still; \r
+And to the heavenly Vision thus presumed. \r
+O, by what name, for thou above all these, \r
+Above mankind, or aught than mankind higher, \r
+Surpassest far my naming; how may I \r
+Adore thee, Author of this universe, \r
+And all this good to man? for whose well being \r
+So amply, and with hands so liberal, \r
+Thou hast provided all things:  But with me \r
+I see not who partakes.  In solitude \r
+What happiness, who can enjoy alone, \r
+Or, all enjoying, what contentment find? \r
+Thus I presumptuous; and the Vision bright, \r
+As with a smile more brightened, thus replied. \r
+What callest thou solitude?  Is not the Earth \r
+With various living creatures, and the air \r
+Replenished, and all these at thy command \r
+To come and play before thee?  Knowest thou not \r
+Their language and their ways?  They also know, \r
+And reason not contemptibly:  With these \r
+Find pastime, and bear rule; thy realm is large. \r
+So spake the Universal Lord, and seemed \r
+So ordering:  I, with leave of speech implored, \r
+And humble deprecation, thus replied. \r
+Let not my words offend thee, Heavenly Power; \r
+My Maker, be propitious while I speak. \r
+Hast thou not made me here thy substitute, \r
+And these inferiour far beneath me set? \r
+Among unequals what society \r
+Can sort, what harmony, or true delight? \r
+Which must be mutual, in proportion due \r
+Given and received; but, in disparity \r
+The one intense, the other still remiss, \r
+Cannot well suit with either, but soon prove \r
+Tedious alike:  Of fellowship I speak \r
+Such as I seek, fit to participate \r
+All rational delight: wherein the brute \r
+Cannot be human consort:  They rejoice \r
+Each with their kind, lion with lioness; \r
+So fitly them in pairs thou hast combined: \r
+Much less can bird with beast, or fish with fowl \r
+So well converse, nor with the ox the ape; \r
+Worse then can man with beast, and least of all. \r
+Whereto the Almighty answered, not displeased. \r
+A nice and subtle happiness, I see, \r
+Thou to thyself proposest, in the choice \r
+Of thy associates, Adam! and wilt taste \r
+No pleasure, though in pleasure, solitary. \r
+What thinkest thou then of me, and this my state? \r
+Seem I to thee sufficiently possessed \r
+Of happiness, or not? who am alone \r
+From all eternity; for none I know \r
+Second to me or like, equal much less. \r
+How have I then with whom to hold converse, \r
+Save with the creatures which I made, and those \r
+To me inferiour, infinite descents \r
+Beneath what other creatures are to thee? \r
+He ceased; I lowly answered.  To attain \r
+The highth and depth of thy eternal ways \r
+All human thoughts come short, Supreme of things! \r
+Thou in thyself art perfect, and in thee \r
+Is no deficience found:  Not so is Man, \r
+But in degree; the cause of his desire \r
+By conversation with his like to help \r
+Or solace his defects.  No need that thou \r
+Shouldst propagate, already Infinite; \r
+And through all numbers absolute, though One: \r
+But Man by number is to manifest \r
+His single imperfection, and beget \r
+Like of his like, his image multiplied, \r
+In unity defective; which requires \r
+Collateral love, and dearest amity. \r
+Thou in thy secresy although alone, \r
+Best with thyself accompanied, seekest not \r
+Social communication; yet, so pleased, \r
+Canst raise thy creature to what highth thou wilt \r
+Of union or communion, deified: \r
+I, by conversing, cannot these erect \r
+From prone; nor in their ways complacence find. \r
+Thus I emboldened spake, and freedom used \r
+Permissive, and acceptance found; which gained \r
+This answer from the gracious Voice Divine. \r
+Thus far to try thee, Adam, I was pleased; \r
+And find thee knowing, not of beasts alone, \r
+Which thou hast rightly named, but of thyself; \r
+Expressing well the spirit within thee free, \r
+My image, not imparted to the brute; \r
+Whose fellowship therefore unmeet for thee \r
+Good reason was thou freely shouldst dislike; \r
+And be so minded still:  I, ere thou spakest, \r
+Knew it not good for Man to be alone; \r
+And no such company as then thou sawest \r
+Intended thee; for trial only brought, \r
+To see how thou couldest judge of fit and meet: \r
+What next I bring shall please thee, be assured, \r
+Thy likeness, thy fit help, thy other self, \r
+Thy wish exactly to thy heart's desire. \r
+He ended, or I heard no more; for now \r
+My earthly by his heavenly overpowered, \r
+Which it had long stood under, strained to the highth \r
+In that celestial colloquy sublime, \r
+As with an object that excels the sense \r
+Dazzled and spent, sunk down; and sought repair \r
+Of sleep, which instantly fell on me, called \r
+By Nature as in aid, and closed mine eyes. \r
+Mine eyes he closed, but open left the cell \r
+Of fancy, my internal sight; by which, \r
+Abstract as in a trance, methought I saw, \r
+Though sleeping, where I lay, and saw the shape \r
+Still glorious before whom awake I stood: \r
+Who stooping opened my left side, and took \r
+From thence a rib, with cordial spirits warm, \r
+And life-blood streaming fresh; wide was the wound, \r
+But suddenly with flesh filled up and healed: \r
+The rib he formed and fashioned with his hands; \r
+Under his forming hands a creature grew, \r
+Man-like, but different sex; so lovely fair, \r
+That what seemed fair in all the world, seemed now \r
+Mean, or in her summed up, in her contained \r
+And in her looks; which from that time infused \r
+Sweetness into my heart, unfelt before, \r
+And into all things from her air inspired \r
+The spirit of love and amorous delight. \r
+She disappeared, and left me dark; I waked \r
+To find her, or for ever to deplore \r
+Her loss, and other pleasures all abjure: \r
+When out of hope, behold her, not far off, \r
+Such as I saw her in my dream, adorned \r
+With what all Earth or Heaven could bestow \r
+To make her amiable:  On she came, \r
+Led by her heavenly Maker, though unseen, \r
+And guided by his voice; nor uninformed \r
+Of nuptial sanctity, and marriage rites: \r
+Grace was in all her steps, Heaven in her eye, \r
+In every gesture dignity and love. \r
+I, overjoyed, could not forbear aloud. \r
+This turn hath made amends; thou hast fulfilled \r
+Thy words, Creator bounteous and benign, \r
+Giver of all things fair! but fairest this \r
+Of all thy gifts! nor enviest.  I now see \r
+Bone of my bone, flesh of my flesh, myself \r
+Before me:  Woman is her name;of Man \r
+Extracted: for this cause he shall forego \r
+Father and mother, and to his wife adhere; \r
+And they shall be one flesh, one heart, one soul. \r
+She heard me thus; and though divinely brought, \r
+Yet innocence, and virgin modesty, \r
+Her virtue, and the conscience of her worth, \r
+That would be wooed, and not unsought be won, \r
+Not obvious, not obtrusive, but, retired, \r
+The more desirable; or, to say all, \r
+Nature herself, though pure of sinful thought, \r
+Wrought in her so, that, seeing me, she turned: \r
+I followed her; she what was honour knew, \r
+And with obsequious majesty approved \r
+My pleaded reason.  To the nuptial bower \r
+I led her blushing like the morn: All Heaven, \r
+And happy constellations, on that hour \r
+Shed their selectest influence; the Earth \r
+Gave sign of gratulation, and each hill; \r
+Joyous the birds; fresh gales and gentle airs \r
+Whispered it to the woods, and from their wings \r
+Flung rose, flung odours from the spicy shrub, \r
+Disporting, till the amorous bird of night \r
+Sung spousal, and bid haste the evening-star \r
+On his hill top, to light the bridal lamp. \r
+Thus have I told thee all my state, and brought \r
+My story to the sum of earthly bliss, \r
+Which I enjoy; and must confess to find \r
+In all things else delight indeed, but such \r
+As, used or not, works in the mind no change, \r
+Nor vehement desire; these delicacies \r
+I mean of taste, sight, smell, herbs, fruits, and flowers, \r
+Walks, and the melody of birds: but here \r
+Far otherwise, transported I behold, \r
+Transported touch; here passion first I felt, \r
+Commotion strange! in all enjoyments else \r
+Superiour and unmoved; here only weak \r
+Against the charm of Beauty's powerful glance. \r
+Or Nature failed in me, and left some part \r
+Not proof enough such object to sustain; \r
+Or, from my side subducting, took perhaps \r
+More than enough; at least on her bestowed \r
+Too much of ornament, in outward show \r
+Elaborate, of inward less exact. \r
+For well I understand in the prime end \r
+Of Nature her the inferiour, in the mind \r
+And inward faculties, which most excel; \r
+In outward also her resembling less \r
+His image who made both, and less expressing \r
+The character of that dominion given \r
+O'er other creatures:  Yet when I approach \r
+Her loveliness, so absolute she seems \r
+And in herself complete, so well to know \r
+Her own, that what she wills to do or say, \r
+Seems wisest, virtuousest, discreetest, best: \r
+All higher knowledge in her presence falls \r
+Degraded;  Wisdom in discourse with her \r
+Loses discountenanced, and like Folly shows; \r
+Authority and Reason on her wait, \r
+As one intended first, not after made \r
+Occasionally; and, to consummate all, \r
+Greatness of mind and Nobleness their seat \r
+Build in her loveliest, and create an awe \r
+About her, as a guard angelick placed. \r
+To whom the Angel with contracted brow. \r
+Accuse not Nature, she hath done her part; \r
+Do thou but thine; and be not diffident \r
+Of Wisdom; she deserts thee not, if thou \r
+Dismiss not her, when most thou needest her nigh, \r
+By attributing overmuch to things \r
+Less excellent, as thou thyself perceivest. \r
+For, what admirest thou, what transports thee so, \r
+An outside? fair, no doubt, and worthy well \r
+Thy cherishing, thy honouring, and thy love; \r
+Not thy subjection:  Weigh with her thyself; \r
+Then value:  Oft-times nothing profits more \r
+Than self-esteem, grounded on just and right \r
+Well managed; of that skill the more thou knowest, \r
+The more she will acknowledge thee her head, \r
+And to realities yield all her shows: \r
+Made so adorn for thy delight the more, \r
+So awful, that with honour thou mayest love \r
+Thy mate, who sees when thou art seen least wise. \r
+But if the sense of touch, whereby mankind \r
+Is propagated, seem such dear delight \r
+Beyond all other; think the same vouchsafed \r
+To cattle and each beast; which would not be \r
+To them made common and divulged, if aught \r
+Therein enjoyed were worthy to subdue \r
+The soul of man, or passion in him move. \r
+What higher in her society thou findest \r
+Attractive, human, rational, love still; \r
+In loving thou dost well, in passion not, \r
+Wherein true love consists not:  Love refines \r
+The thoughts, and heart enlarges; hath his seat \r
+In reason, and is judicious; is the scale \r
+By which to heavenly love thou mayest ascend, \r
+Not sunk in carnal pleasure; for which cause, \r
+Among the beasts no mate for thee was found. \r
+To whom thus, half abashed, Adam replied. \r
+Neither her outside formed so fair, nor aught \r
+In procreation common to all kinds, \r
+(Though higher of the genial bed by far, \r
+And with mysterious reverence I deem,) \r
+So much delights me, as those graceful acts, \r
+Those thousand decencies, that daily flow \r
+From all her words and actions mixed with love \r
+And sweet compliance, which declare unfeigned \r
+Union of mind, or in us both one soul; \r
+Harmony to behold in wedded pair \r
+More grateful than harmonious sound to the ear. \r
+Yet these subject not; I to thee disclose \r
+What inward thence I feel, not therefore foiled, \r
+Who meet with various objects, from the sense \r
+Variously representing; yet, still free, \r
+Approve the best, and follow what I approve. \r
+To love, thou blamest me not; for Love, thou sayest, \r
+Leads up to Heaven, is both the way and guide; \r
+Bear with me then, if lawful what I ask: \r
+Love not the heavenly Spirits, and how their love \r
+Express they? by looks only? or do they mix \r
+Irradiance, virtual or immediate touch? \r
+To whom the Angel, with a smile that glowed \r
+Celestial rosy red, Love's proper hue, \r
+Answered.  Let it suffice thee that thou knowest \r
+Us happy, and without love no happiness. \r
+Whatever pure thou in the body enjoyest, \r
+(And pure thou wert created) we enjoy \r
+In eminence; and obstacle find none \r
+Of membrane, joint, or limb, exclusive bars; \r
+Easier than air with air, if Spirits embrace, \r
+Total they mix, union of pure with pure \r
+Desiring, nor restrained conveyance need, \r
+As flesh to mix with flesh, or soul with soul. \r
+But I can now no more; the parting sun \r
+Beyond the Earth's green Cape and verdant Isles \r
+Hesperian sets, my signal to depart. \r
+Be strong, live happy, and love!  But, first of all, \r
+Him, whom to love is to obey, and keep \r
+His great command; take heed lest passion sway \r
+Thy judgement to do aught, which else free will \r
+Would not admit: thine, and of all thy sons, \r
+The weal or woe in thee is placed; beware! \r
+I in thy persevering shall rejoice, \r
+And all the Blest:  Stand fast;to stand or fall \r
+Free in thine own arbitrement it lies. \r
+Perfect within, no outward aid require; \r
+And all temptation to transgress repel. \r
+So saying, he arose; whom Adam thus \r
+Followed with benediction.  Since to part, \r
+Go, heavenly guest, ethereal Messenger, \r
+Sent from whose sovran goodness I adore! \r
+Gentle to me and affable hath been \r
+Thy condescension, and shall be honoured ever \r
+With grateful memory:  Thou to mankind \r
+Be good and friendly still, and oft return! \r
+So parted they; the Angel up to Heaven \r
+From the thick shade, and Adam to his bower. \r
\r
\r
\r
+Book IX                                                          \r
\r
\r
+No more of talk where God or Angel guest \r
+With Man, as with his friend, familiar us'd, \r
+To sit indulgent, and with him partake \r
+Rural repast; permitting him the while \r
+Venial discourse unblam'd. I now must change \r
+Those notes to tragick; foul distrust, and breach \r
+Disloyal on the part of Man, revolt, \r
+And disobedience: on the part of Heaven \r
+Now alienated, distance and distaste, \r
+Anger and just rebuke, and judgement given, \r
+That brought into this world a world of woe, \r
+Sin and her shadow Death, and Misery \r
+Death's harbinger: Sad talk!yet argument \r
+Not less but more heroick than the wrath \r
+Of stern Achilles on his foe pursued \r
+Thrice fugitive about Troy wall; or rage \r
+Of Turnus for Lavinia disespous'd; \r
+Or Neptune's ire, or Juno's, that so long \r
+Perplexed the Greek, and Cytherea's son:                         \r
\r
+   00482129  \r
+If answerable style I can obtain \r
+Of my celestial patroness, who deigns \r
+Her nightly visitation unimplor'd, \r
+And dictates to me slumbering; or inspires \r
+Easy my unpremeditated verse: \r
+Since first this subject for heroick song \r
+Pleas'd me long choosing, and beginning late; \r
+Not sedulous by nature to indite \r
+Wars, hitherto the only argument \r
+Heroick deem'd chief mastery to dissect \r
+With long and tedious havock fabled knights \r
+In battles feign'd; the better fortitude \r
+Of patience and heroick martyrdom \r
+Unsung; or to describe races and games, \r
+Or tilting furniture, imblazon'd shields, \r
+Impresses quaint, caparisons and steeds, \r
+Bases and tinsel trappings, gorgeous knights \r
+At joust and tournament; then marshall'd feast \r
+Serv'd up in hall with sewers and seneshals; \r
+The skill of artifice or office mean, \r
+Not that which justly gives heroick name \r
+To person, or to poem.  Me, of these \r
+Nor skill'd nor studious, higher argument \r
+Remains; sufficient of itself to raise \r
+That name, unless an age too late, or cold \r
+Climate, or years, damp my intended wing \r
+Depress'd; and much they may, if all be mine, \r
+Not hers, who brings it nightly to my ear. \r
+The sun was sunk, and after him the star \r
+Of Hesperus, whose office is to bring \r
+Twilight upon the earth, short arbiter \r
+"twixt day and night, and now from end to end \r
+Night's hemisphere had veil'd the horizon round: \r
+When satan, who late fled before the threats \r
+Of Gabriel out of Eden, now improv'd \r
+In meditated fraud and malice, bent \r
+On Man's destruction, maugre what might hap \r
+Of heavier on himself, fearless returned \r
+From compassing the earth; cautious of day, \r
+Since Uriel, regent of the sun, descried \r
+His entrance, and foreworned the Cherubim \r
+That kept their watch; thence full of anguish driven, \r
+The space of seven continued nights he rode \r
+With darkness; thrice the equinoctial line \r
+He circled; four times crossed the car of night \r
+From pole to pole, traversing each colure; \r
+On the eighth returned; and, on the coast averse \r
+From entrance or Cherubick watch, by stealth \r
+Found unsuspected way.  There was a place, \r
+Now not, though sin, not time, first wrought the change, \r
+Where Tigris, at the foot of Paradise, \r
+Into a gulf shot under ground, till part \r
+Rose up a fountain by the tree of life: \r
+In with the river sunk, and with it rose \r
+Satan, involved in rising mist; then sought \r
+Where to lie hid; sea he had searched, and land, \r
+From Eden over Pontus and the pool \r
+Maeotis, up beyond the river Ob; \r
+Downward as far antarctick; and in length, \r
+West from Orontes to the ocean barred \r
+At Darien ; thence to the land where flows \r
+Ganges and Indus: Thus the orb he roamed \r
+With narrow search; and with inspection deep \r
+Considered every creature, which of all \r
+Most opportune might serve his wiles; and found \r
+The Serpent subtlest beast of all the field. \r
+Him after long debate, irresolute \r
+Of thoughts revolved, his final sentence chose \r
+Fit vessel, fittest imp of fraud, in whom \r
+To enter, and his dark suggestions hide \r
+From sharpest sight: for, in the wily snake \r
+Whatever sleights, none would suspicious mark, \r
+As from his wit and native subtlety \r
+Proceeding; which, in other beasts observed, \r
+Doubt might beget of diabolick power \r
+Active within, beyond the sense of brute. \r
+Thus he resolved, but first from inward grief \r
+His bursting passion into plaints thus poured. \r
+More justly, seat worthier of Gods, as built \r
+With second thoughts, reforming what was old! \r
+O Earth, how like to Heaven, if not preferred \r
+For what God, after better, worse would build? \r
+Terrestrial Heaven, danced round by other Heavens \r
+That shine, yet bear their bright officious lamps, \r
+Light above light, for thee alone, as seems, \r
+In thee concentring all their precious beams \r
+Of sacred influence!  As God in Heaven \r
+Is center, yet extends to all; so thou, \r
+Centring, receivest from all those orbs: in thee, \r
+Not in themselves, all their known virtue appears \r
+Productive in herb, plant, and nobler birth \r
+Of creatures animate with gradual life \r
+Of growth, sense, reason, all summed up in Man. \r
+With what delight could I have walked thee round, \r
+If I could joy in aught, sweet interchange \r
+Of hill, and valley, rivers, woods, and plains, \r
+Now land, now sea and shores with forest crowned, \r
+Rocks, dens, and caves!  But I in none of these \r
+Find place or refuge; and the more I see \r
+Pleasures about me, so much more I feel \r
+Torment within me, as from the hateful siege \r
+Of contraries: all good to me becomes \r
+Bane, and in Heaven much worse would be my state. \r
+But neither here seek I, no nor in Heaven \r
+To dwell, unless by mastering Heaven's Supreme; \r
+Nor hope to be myself less miserable \r
+By what I seek, but others to make such \r
+As I, though thereby worse to me redound: \r
+For only in destroying I find ease \r
+To my relentless thoughts; and, him destroyed, \r
+Or won to what may work his utter loss, \r
+For whom all this was made, all this will soon \r
+Follow, as to him linked in weal or woe; \r
+In woe then; that destruction wide may range: \r
+To me shall be the glory sole among \r
+The infernal Powers, in one day to have marred \r
+What he, Almighty styled, six nights and days \r
+Continued making; and who knows how long \r
+Before had been contriving? though perhaps \r
+Not longer than since I, in one night, freed \r
+From servitude inglorious well nigh half \r
+The angelick name, and thinner left the throng \r
+Of his adorers: He, to be avenged, \r
+And to repair his numbers thus impaired, \r
+Whether such virtue spent of old now failed \r
+More Angels to create, if they at least \r
+Are his created, or, to spite us more, \r
+Determined to advance into our room \r
+A creature formed of earth, and him endow, \r
+Exalted from so base original, \r
+With heavenly spoils, our spoils: What he decreed, \r
+He effected; Man he made, and for him built \r
+Magnificent this world, and earth his seat, \r
+Him lord pronounced; and, O indignity! \r
+Subjected to his service angel-wings, \r
+And flaming ministers to watch and tend \r
+Their earthly charge: Of these the vigilance \r
+I dread; and, to elude, thus wrapt in mist \r
+Of midnight vapour glide obscure, and pry \r
+In every bush and brake, where hap may find \r
+The serpent sleeping; in whose mazy folds \r
+To hide me, and the dark intent I bring. \r
+O foul descent! that I, who erst contended \r
+With Gods to sit the highest, am now constrained \r
+Into a beast; and, mixed with bestial slime, \r
+This essence to incarnate and imbrute, \r
+That to the highth of Deity aspired! \r
+But what will not ambition and revenge \r
+Descend to?  Who aspires, must down as low \r
+As high he soared; obnoxious, first or last, \r
+To basest things.  Revenge, at first though sweet, \r
+Bitter ere long, back on itself recoils: \r
+Let it; I reck not, so it light well aimed, \r
+Since higher I fall short, on him who next \r
+Provokes my envy, this new favourite \r
+Of Heaven, this man of clay, son of despite, \r
+Whom, us the more to spite, his Maker raised \r
+From dust: Spite then with spite is best repaid. \r
+So saying, through each thicket dank or dry, \r
+Like a black mist low-creeping, he held on \r
+His midnight-search, where soonest he might find \r
+The serpent; him fast-sleeping soon he found \r
+In labyrinth of many a round self-rolled, \r
+His head the midst, well stored with subtile wiles: \r
+Not yet in horrid shade or dismal den, \r
+Nor nocent yet; but, on the grassy herb, \r
+Fearless unfeared he slept: in at his mouth \r
+The Devil entered; and his brutal sense, \r
+In heart or head, possessing, soon inspired \r
+With act intelligential; but his sleep \r
+Disturbed not, waiting close the approach of morn. \r
+Now, when as sacred light began to dawn \r
+In Eden on the humid flowers, that breathed \r
+Their morning incense, when all things, that breathe, \r
+From the Earth's great altar send up silent praise \r
+To the Creator, and his nostrils fill \r
+With grateful smell, forth came the human pair, \r
+And joined their vocal worship to the quire \r
+Of creatures wanting voice; that done, partake \r
+The season prime for sweetest scents and airs: \r
+Then commune, how that day they best may ply \r
+Their growing work: for much their work out-grew \r
+The hands' dispatch of two gardening so wide, \r
+And Eve first to her husband thus began. \r
+Adam, well may we labour still to dress \r
+This garden, still to tend plant, herb, and flower, \r
+Our pleasant task enjoined; but, till more hands \r
+Aid us, the work under our labour grows, \r
+Luxurious by restraint; what we by day \r
+Lop overgrown, or prune, or prop, or bind, \r
+One night or two with wanton growth derides \r
+Tending to wild.  Thou therefore now advise, \r
+Or bear what to my mind first thoughts present: \r
+Let us divide our labours; thou, where choice \r
+Leads thee, or where most needs, whether to wind \r
+The woodbine round this arbour, or direct \r
+The clasping ivy where to climb; while I, \r
+In yonder spring of roses intermixed \r
+With myrtle, find what to redress till noon: \r
+For, while so near each other thus all day \r
+Our task we choose, what wonder if so near \r
+Looks intervene and smiles, or object new \r
+Casual discourse draw on; which intermits \r
+Our day's work, brought to little, though begun \r
+Early, and the hour of supper comes unearned? \r
+To whom mild answer Adam thus returned. \r
+Sole Eve, associate sole, to me beyond \r
+Compare above all living creatures dear! \r
+Well hast thou motioned, well thy thoughts employed, \r
+How we might best fulfil the work which here \r
+God hath assigned us; nor of me shalt pass \r
+Unpraised: for nothing lovelier can be found \r
+In woman, than to study houshold good, \r
+And good works in her husband to promote. \r
+Yet not so strictly hath our Lord imposed \r
+Labour, as to debar us when we need \r
+Refreshment, whether food, or talk between, \r
+Food of the mind, or this sweet intercourse \r
+Of looks and smiles; for smiles from reason flow, \r
+To brute denied, and are of love the food; \r
+Love, not the lowest end of human life. \r
+For not to irksome toil, but to delight, \r
+He made us, and delight to reason joined. \r
+These paths and bowers doubt not but our joint hands \r
+Will keep from wilderness with ease, as wide \r
+As we need walk, till younger hands ere long \r
+Assist us; But, if much converse perhaps \r
+Thee satiate, to short absence I could yield: \r
+For solitude sometimes is best society, \r
+And short retirement urges sweet return. \r
+But other doubt possesses me, lest harm \r
+Befall thee severed from me; for thou knowest \r
+What hath been warned us, what malicious foe \r
+Envying our happiness, and of his own \r
+Despairing, seeks to work us woe and shame \r
+By sly assault; and somewhere nigh at hand \r
+Watches, no doubt, with greedy hope to find \r
+His wish and best advantage, us asunder; \r
+Hopeless to circumvent us joined, where each \r
+To other speedy aid might lend at need: \r
+Whether his first design be to withdraw \r
+Our fealty from God, or to disturb \r
+Conjugal love, than which perhaps no bliss \r
+Enjoyed by us excites his envy more; \r
+Or this, or worse, leave not the faithful side \r
+That gave thee being, still shades thee, and protects. \r
+The wife, where danger or dishonour lurks, \r
+Safest and seemliest by her husband stays, \r
+Who guards her, or with her the worst endures. \r
+To whom the virgin majesty of Eve, \r
+As one who loves, and some unkindness meets, \r
+With sweet austere composure thus replied. \r
+Offspring of Heaven and Earth, and all Earth's Lord! \r
+That such an enemy we have, who seeks \r
+Our ruin, both by thee informed I learn, \r
+And from the parting Angel over-heard, \r
+As in a shady nook I stood behind, \r
+Just then returned at shut of evening flowers. \r
+But, that thou shouldst my firmness therefore doubt \r
+To God or thee, because we have a foe \r
+May tempt it, I expected not to hear. \r
+His violence thou fearest not, being such \r
+As we, not capable of death or pain, \r
+Can either not receive, or can repel. \r
+His fraud is then thy fear; which plain infers \r
+Thy equal fear, that my firm faith and love \r
+Can by his fraud be shaken or seduced; \r
+Thoughts, which how found they harbour in thy breast, \r
+Adam, mis-thought of her to thee so dear? \r
+To whom with healing words Adam replied. \r
+Daughter of God and Man, immortal Eve! \r
+For such thou art; from sin and blame entire: \r
+Not diffident of thee do I dissuade \r
+Thy absence from my sight, but to avoid \r
+The attempt itself, intended by our foe. \r
+For he who tempts, though in vain, at least asperses \r
+The tempted with dishonour foul; supposed \r
+Not incorruptible of faith, not proof \r
+Against temptation: Thou thyself with scorn \r
+And anger wouldst resent the offered wrong, \r
+Though ineffectual found: misdeem not then, \r
+If such affront I labour to avert \r
+From thee alone, which on us both at once \r
+The enemy, though bold, will hardly dare; \r
+Or daring, first on me the assault shall light. \r
+Nor thou his malice and false guile contemn; \r
+Subtle he needs must be, who could seduce \r
+Angels; nor think superfluous other's aid. \r
+I, from the influence of thy looks, receive \r
+Access in every virtue; in thy sight \r
+More wise, more watchful, stronger, if need were \r
+Of outward strength; while shame, thou looking on, \r
+Shame to be overcome or over-reached, \r
+Would utmost vigour raise, and raised unite. \r
+Why shouldst not thou like sense within thee feel \r
+When I am present, and thy trial choose \r
+With me, best witness of thy virtue tried? \r
+So spake domestick Adam in his care \r
+And matrimonial love; but Eve, who thought \r
+Less attributed to her faith sincere, \r
+Thus her reply with accent sweet renewed. \r
+If this be our condition, thus to dwell \r
+In narrow circuit straitened by a foe, \r
+Subtle or violent, we not endued \r
+Single with like defence, wherever met; \r
+How are we happy, still in fear of harm? \r
+But harm precedes not sin: only our foe, \r
+Tempting, affronts us with his foul esteem \r
+Of our integrity: his foul esteem \r
+Sticks no dishonour on our front, but turns \r
+Foul on himself; then wherefore shunned or feared \r
+By us? who rather double honour gain \r
+From his surmise proved false; find peace within, \r
+Favour from Heaven, our witness, from the event. \r
+And what is faith, love, virtue, unassayed \r
+Alone, without exteriour help sustained? \r
+Let us not then suspect our happy state \r
+Left so imperfect by the Maker wise, \r
+As not secure to single or combined. \r
+Frail is our happiness, if this be so, \r
+And Eden were no Eden, thus exposed. \r
+To whom thus Adam fervently replied. \r
+O Woman, best are all things as the will \r
+Of God ordained them: His creating hand \r
+Nothing imperfect or deficient left \r
+Of all that he created, much less Man, \r
+Or aught that might his happy state secure, \r
+Secure from outward force; within himself \r
+The danger lies, yet lies within his power: \r
+Against his will he can receive no harm. \r
+But God left free the will; for what obeys \r
+Reason, is free; and Reason he made right, \r
+But bid her well be ware, and still erect; \r
+Lest, by some fair-appearing good surprised, \r
+She dictate false; and mis-inform the will \r
+To do what God expressly hath forbid. \r
+Not then mistrust, but tender love, enjoins, \r
+That I should mind thee oft; and mind thou me. \r
+Firm we subsist, yet possible to swerve; \r
+Since Reason not impossibly may meet \r
+Some specious object by the foe suborned, \r
+And fall into deception unaware, \r
+Not keeping strictest watch, as she was warned. \r
+Seek not temptation then, which to avoid \r
+Were better, and most likely if from me \r
+Thou sever not: Trial will come unsought. \r
+Wouldst thou approve thy constancy, approve \r
+First thy obedience; the other who can know, \r
+Not seeing thee attempted, who attest? \r
+But, if thou think, trial unsought may find \r
+Us both securer than thus warned thou seemest, \r
+Go; for thy stay, not free, absents thee more; \r
+Go in thy native innocence, rely \r
+On what thou hast of virtue; summon all! \r
+For God towards thee hath done his part, do thine. \r
+So spake the patriarch of mankind; but Eve \r
+Persisted; yet submiss, though last, replied. \r
+With thy permission then, and thus forewarned \r
+Chiefly by what thy own last reasoning words \r
+Touched only; that our trial, when least sought, \r
+May find us both perhaps far less prepared, \r
+The willinger I go, nor much expect \r
+A foe so proud will first the weaker seek; \r
+So bent, the more shall shame him his repulse. \r
+Thus saying, from her husband's hand her hand \r
+Soft she withdrew; and, like a Wood-Nymph light, \r
+Oread or Dryad, or of Delia's train, \r
+Betook her to the groves; but Delia's self \r
+In gait surpassed, and Goddess-like deport, \r
+Though not as she with bow and quiver armed, \r
+But with such gardening tools as Art yet rude, \r
+Guiltless of fire, had formed, or Angels brought. \r
+To Pales, or Pomona, thus adorned, \r
+Likest she seemed, Pomona when she fled \r
+Vertumnus, or to Ceres in her prime, \r
+Yet virgin of Proserpina from Jove. \r
+Her long with ardent look his eye pursued \r
+Delighted, but desiring more her stay. \r
+Oft he to her his charge of quick return \r
+Repeated; she to him as oft engaged \r
+To be returned by noon amid the bower, \r
+And all things in best order to invite \r
+Noontide repast, or afternoon's repose. \r
+O much deceived, much failing, hapless Eve, \r
+Of thy presumed return! event perverse! \r
+Thou never from that hour in Paradise \r
+Foundst either sweet repast, or sound repose; \r
+Such ambush, hid among sweet flowers and shades, \r
+Waited with hellish rancour imminent \r
+To intercept thy way, or send thee back \r
+Despoiled of innocence, of faith, of bliss! \r
+For now, and since first break of dawn, the Fiend, \r
+Mere serpent in appearance, forth was come; \r
+And on his quest, where likeliest he might find \r
+The only two of mankind, but in them \r
+The whole included race, his purposed prey. \r
+In bower and field he sought, where any tuft \r
+Of grove or garden-plot more pleasant lay, \r
+Their tendance, or plantation for delight; \r
+By fountain or by shady rivulet \r
+He sought them both, but wished his hap might find \r
+Eve separate; he wished, but not with hope \r
+Of what so seldom chanced; when to his wish, \r
+Beyond his hope, Eve separate he spies, \r
+Veiled in a cloud of fragrance, where she stood, \r
+Half spied, so thick the roses blushing round \r
+About her glowed, oft stooping to support \r
+Each flower of slender stalk, whose head, though gay \r
+Carnation, purple, azure, or specked with gold, \r
+Hung drooping unsustained; them she upstays \r
+Gently with myrtle band, mindless the while \r
+Herself, though fairest unsupported flower, \r
+From her best prop so far, and storm so nigh. \r
+Nearer he drew, and many a walk traversed \r
+Of stateliest covert, cedar, pine, or palm; \r
+Then voluble and bold, now hid, now seen, \r
+Among thick-woven arborets, and flowers \r
+Imbordered on each bank, the hand of Eve: \r
+Spot more delicious than those gardens feigned \r
+Or of revived Adonis, or renowned \r
+Alcinous, host of old Laertes' son; \r
+Or that, not mystick, where the sapient king \r
+Held dalliance with his fair Egyptian spouse. \r
+Much he the place admired, the person more. \r
+As one who long in populous city pent, \r
+Where houses thick and sewers annoy the air, \r
+Forth issuing on a summer's morn, to breathe \r
+Among the pleasant villages and farms \r
+Adjoined, from each thing met conceives delight; \r
+The smell of grain, or tedded grass, or kine, \r
+Or dairy, each rural sight, each rural sound; \r
+If chance, with nymph-like step, fair virgin pass, \r
+What pleasing seemed, for her now pleases more; \r
+She most, and in her look sums all delight: \r
+Such pleasure took the Serpent to behold \r
+This flowery plat, the sweet recess of Eve \r
+Thus early, thus alone: Her heavenly form \r
+Angelick, but more soft, and feminine, \r
+Her graceful innocence, her every air \r
+Of gesture, or least action, overawed \r
+His malice, and with rapine sweet bereaved \r
+His fierceness of the fierce intent it brought: \r
+That space the Evil-one abstracted stood \r
+From his own evil, and for the time remained \r
+Stupidly good; of enmity disarmed, \r
+Of guile, of hate, of envy, of revenge: \r
+But the hot Hell that always in him burns, \r
+Though in mid Heaven, soon ended his delight, \r
+And tortures him now more, the more he sees \r
+Of pleasure, not for him ordained: then soon \r
+Fierce hate he recollects, and all his thoughts \r
+Of mischief, gratulating, thus excites. \r
+Thoughts, whither have ye led me! with what sweet \r
+Compulsion thus transported, to forget \r
+What hither brought us! hate, not love;nor hope \r
+Of Paradise for Hell, hope here to taste \r
+Of pleasure; but all pleasure to destroy, \r
+Save what is in destroying; other joy \r
+To me is lost.  Then, let me not let pass \r
+Occasion which now smiles; behold alone \r
+The woman, opportune to all attempts, \r
+Her husband, for I view far round, not nigh, \r
+Whose higher intellectual more I shun, \r
+And strength, of courage haughty, and of limb \r
+Heroick built, though of terrestrial mould; \r
+Foe not informidable! exempt from wound, \r
+I not; so much hath Hell debased, and pain \r
+Enfeebled me, to what I was in Heaven. \r
+She fair, divinely fair, fit love for Gods! \r
+Not terrible, though terrour be in love \r
+And beauty, not approached by stronger hate, \r
+Hate stronger, under show of love well feigned; \r
+The way which to her ruin now I tend. \r
+So spake the enemy of mankind, enclosed \r
+In serpent, inmate bad! and toward Eve \r
+Addressed his way: not with indented wave, \r
+Prone on the ground, as since; but on his rear, \r
+Circular base of rising folds, that towered \r
+Fold above fold, a surging maze! his head \r
+Crested aloft, and carbuncle his eyes; \r
+With burnished neck of verdant gold, erect \r
+Amidst his circling spires, that on the grass \r
+Floated redundant: pleasing was his shape \r
+And lovely; never since of serpent-kind \r
+Lovelier, not those that in Illyria changed, \r
+Hermione and Cadmus, or the god \r
+In Epidaurus; nor to which transformed \r
+Ammonian Jove, or Capitoline, was seen; \r
+He with Olympias; this with her who bore \r
+Scipio, the highth of Rome.  With tract oblique \r
+At first, as one who sought access, but feared \r
+To interrupt, side-long he works his way. \r
+As when a ship, by skilful steersmen wrought \r
+Nigh river's mouth or foreland, where the wind \r
+Veers oft, as oft so steers, and shifts her sail: \r
+So varied he, and of his tortuous train \r
+Curled many a wanton wreath in sight of Eve, \r
+To lure her eye; she, busied, heard the sound \r
+Of rusling leaves, but minded not, as used \r
+To such disport before her through the field, \r
+From every beast; more duteous at her call, \r
+Than at Circean call the herd disguised. \r
+He, bolder now, uncalled before her stood, \r
+But as in gaze admiring: oft he bowed \r
+His turret crest, and sleek enamelled neck, \r
+Fawning; and licked the ground whereon she trod. \r
+His gentle dumb expression turned at length \r
+The eye of Eve to mark his play; he, glad \r
+Of her attention gained, with serpent-tongue \r
+Organick, or impulse of vocal air, \r
+His fraudulent temptation thus began. \r
+Wonder not, sovran Mistress, if perhaps \r
+Thou canst, who art sole wonder! much less arm \r
+Thy looks, the Heaven of mildness, with disdain, \r
+Displeased that I approach thee thus, and gaze \r
+Insatiate; I thus single;nor have feared \r
+Thy awful brow, more awful thus retired. \r
+Fairest resemblance of thy Maker fair, \r
+Thee all things living gaze on, all things thine \r
+By gift, and thy celestial beauty adore \r
+With ravishment beheld! there best beheld, \r
+Where universally admired; but here \r
+In this enclosure wild, these beasts among, \r
+Beholders rude, and shallow to discern \r
+Half what in thee is fair, one man except, \r
+Who sees thee? and what is one? who should be seen \r
+A Goddess among Gods, adored and served \r
+By Angels numberless, thy daily train. \r
+So glozed the Tempter, and his proem tuned: \r
+Into the heart of Eve his words made way, \r
+Though at the voice much marvelling; at length, \r
+Not unamazed, she thus in answer spake. \r
+What may this mean? language of man pronounced \r
+By tongue of brute, and human sense expressed? \r
+The first, at least, of these I thought denied \r
+To beasts; whom God, on their creation-day, \r
+Created mute to all articulate sound: \r
+The latter I demur; for in their looks \r
+Much reason, and in their actions, oft appears. \r
+Thee, Serpent, subtlest beast of all the field \r
+I knew, but not with human voice endued; \r
+Redouble then this miracle, and say, \r
+How camest thou speakable of mute, and how \r
+To me so friendly grown above the rest \r
+Of brutal kind, that daily are in sight? \r
+Say, for such wonder claims attention due. \r
+To whom the guileful Tempter thus replied. \r
+Empress of this fair world, resplendent Eve! \r
+Easy to me it is to tell thee all \r
+What thou commandest; and right thou shouldst be obeyed: \r
+I was at first as other beasts that graze \r
+The trodden herb, of abject thoughts and low, \r
+As was my food; nor aught but food discerned \r
+Or sex, and apprehended nothing high: \r
+Till, on a day roving the field, I chanced \r
+A goodly tree far distant to behold \r
+Loaden with fruit of fairest colours mixed, \r
+Ruddy and gold: I nearer drew to gaze; \r
+When from the boughs a savoury odour blown, \r
+Grateful to appetite, more pleased my sense \r
+Than smell of sweetest fennel, or the teats \r
+Of ewe or goat dropping with milk at even, \r
+Unsucked of lamb or kid, that tend their play. \r
+To satisfy the sharp desire I had \r
+Of tasting those fair apples, I resolved \r
+Not to defer; hunger and thirst at once, \r
+Powerful persuaders, quickened at the scent \r
+Of that alluring fruit, urged me so keen. \r
+About the mossy trunk I wound me soon; \r
+For, high from ground, the branches would require \r
+Thy utmost reach or Adam's: Round the tree \r
+All other beasts that saw, with like desire \r
+Longing and envying stood, but could not reach. \r
+Amid the tree now got, where plenty hung \r
+Tempting so nigh, to pluck and eat my fill \r
+I spared not; for, such pleasure till that hour, \r
+At feed or fountain, never had I found. \r
+Sated at length, ere long I might perceive \r
+Strange alteration in me, to degree \r
+Of reason in my inward powers; and speech \r
+Wanted not long; though to this shape retained. \r
+Thenceforth to speculations high or deep \r
+I turned my thoughts, and with capacious mind \r
+Considered all things visible in Heaven, \r
+Or Earth, or Middle; all things fair and good: \r
+But all that fair and good in thy divine \r
+Semblance, and in thy beauty's heavenly ray, \r
+United I beheld; no fair to thine \r
+Equivalent or second! which compelled \r
+Me thus, though importune perhaps, to come \r
+And gaze, and worship thee of right declared \r
+Sovran of creatures, universal Dame! \r
+So talked the spirited sly Snake; and Eve, \r
+Yet more amazed, unwary thus replied. \r
+Serpent, thy overpraising leaves in doubt \r
+The virtue of that fruit, in thee first proved: \r
+But say, where grows the tree? from hence how far? \r
+For many are the trees of God that grow \r
+In Paradise, and various, yet unknown \r
+To us; in such abundance lies our choice, \r
+As leaves a greater store of fruit untouched, \r
+Still hanging incorruptible, till men \r
+Grow up to their provision, and more hands \r
+Help to disburden Nature of her birth. \r
+To whom the wily Adder, blithe and glad. \r
+Empress, the way is ready, and not long; \r
+Beyond a row of myrtles, on a flat, \r
+Fast by a fountain, one small thicket past \r
+Of blowing myrrh and balm: if thou accept \r
+My conduct, I can bring thee thither soon \r
+Lead then, said Eve.  He, leading, swiftly rolled \r
+In tangles, and made intricate seem straight, \r
+To mischief swift.  Hope elevates, and joy \r
+Brightens his crest; as when a wandering fire, \r
+Compact of unctuous vapour, which the night \r
+Condenses, and the cold environs round, \r
+Kindled through agitation to a flame, \r
+Which oft, they say, some evil Spirit attends, \r
+Hovering and blazing with delusive light, \r
+Misleads the amazed night-wanderer from his way \r
+To bogs and mires, and oft through pond or pool; \r
+There swallowed up and lost, from succour far. \r
+So glistered the dire Snake, and into fraud \r
+Led Eve, our credulous mother, to the tree \r
+Of prohibition, root of all our woe; \r
+Which when she saw, thus to her guide she spake. \r
+Serpent, we might have spared our coming hither, \r
+Fruitless to me, though fruit be here to excess, \r
+The credit of whose virtue rest with thee; \r
+Wonderous indeed, if cause of such effects. \r
+But of this tree we may not taste nor touch; \r
+God so commanded, and left that command \r
+Sole daughter of his voice; the rest, we live \r
+Law to ourselves; our reason is our law. \r
+To whom the Tempter guilefully replied. \r
+Indeed! hath God then said that of the fruit \r
+Of all these garden-trees ye shall not eat, \r
+Yet Lords declared of all in earth or air$? \r
+To whom thus Eve, yet sinless.  Of the fruit \r
+Of each tree in the garden we may eat; \r
+But of the fruit of this fair tree amidst \r
+The garden, God hath said, Ye shall not eat \r
+Thereof, nor shall ye touch it, lest ye die. \r
+She scarce had said, though brief, when now more bold \r
+The Tempter, but with show of zeal and love \r
+To Man, and indignation at his wrong, \r
+New part puts on; and, as to passion moved, \r
+Fluctuates disturbed, yet comely and in act \r
+Raised, as of some great matter to begin. \r
+As when of old some orator renowned, \r
+In Athens or free Rome, where eloquence \r
+Flourished, since mute! to some great cause addressed, \r
+Stood in himself collected; while each part, \r
+Motion, each act, won audience ere the tongue; \r
+Sometimes in highth began, as no delay \r
+Of preface brooking, through his zeal of right: \r
+So standing, moving, or to highth up grown, \r
+The Tempter, all impassioned, thus began. \r
+O sacred, wise, and wisdom-giving Plant, \r
+Mother of science! now I feel thy power \r
+Within me clear; not only to discern \r
+Things in their causes, but to trace the ways \r
+Of highest agents, deemed however wise. \r
+Queen of this universe! do not believe \r
+Those rigid threats of death: ye shall not die: \r
+How should you? by the fruit? it gives you life \r
+To knowledge; by the threatener? look on me, \r
+Me, who have touched and tasted; yet both live, \r
+And life more perfect have attained than Fate \r
+Meant me, by venturing higher than my lot. \r
+Shall that be shut to Man, which to the Beast \r
+Is open? or will God incense his ire \r
+For such a petty trespass? and not praise \r
+Rather your dauntless virtue, whom the pain \r
+Of death denounced, whatever thing death be, \r
+Deterred not from achieving what might lead \r
+To happier life, knowledge of good and evil; \r
+Of good, how just? of evil, if what is evil \r
+Be real, why not known, since easier shunned? \r
+God therefore cannot hurt ye, and be just; \r
+Not just, not God; not feared then, nor obeyed: \r
+Your fear itself of death removes the fear. \r
+Why then was this forbid?  Why, but to awe; \r
+Why, but to keep ye low and ignorant, \r
+His worshippers?  He knows that in the day \r
+Ye eat thereof, your eyes that seem so clear, \r
+Yet are but dim, shall perfectly be then \r
+Opened and cleared, and ye shall be as Gods, \r
+Knowing both good and evil, as they know. \r
+That ye shall be as Gods, since I as Man, \r
+Internal Man, is but proportion meet; \r
+I, of brute, human; ye, of human, Gods. \r
+So ye shall die perhaps, by putting off \r
+Human, to put on Gods; death to be wished, \r
+Though threatened, which no worse than this can bring. \r
+And what are Gods, that Man may not become \r
+As they, participating God-like food? \r
+The Gods are first, and that advantage use \r
+On our belief, that all from them proceeds: \r
+I question it; for this fair earth I see, \r
+Warmed by the sun, producing every kind; \r
+Them, nothing: if they all things, who enclosed \r
+Knowledge of good and evil in this tree, \r
+That whoso eats thereof, forthwith attains \r
+Wisdom without their leave? and wherein lies \r
+The offence, that Man should thus attain to know? \r
+What can your knowledge hurt him, or this tree \r
+Impart against his will, if all be his? \r
+Or is it envy? and can envy dwell \r
+In heavenly breasts?  These, these, and many more \r
+Causes import your need of this fair fruit. \r
+Goddess humane, reach then, and freely taste! \r
+He ended; and his words, replete with guile, \r
+Into her heart too easy entrance won: \r
+Fixed on the fruit she gazed, which to behold \r
+Might tempt alone; and in her ears the sound \r
+Yet rung of his persuasive words, impregned \r
+With reason, to her seeming, and with truth: \r
+Mean while the hour of noon drew on, and waked \r
+An eager appetite, raised by the smell \r
+So savoury of that fruit, which with desire, \r
+Inclinable now grown to touch or taste, \r
+Solicited her longing eye; yet first \r
+Pausing a while, thus to herself she mused. \r
+Great are thy virtues, doubtless, best of fruits, \r
+Though kept from man, and worthy to be admired; \r
+Whose taste, too long forborn, at first assay \r
+Gave elocution to the mute, and taught \r
+The tongue not made for speech to speak thy praise: \r
+Thy praise he also, who forbids thy use, \r
+Conceals not from us, naming thee the tree \r
+Of knowledge, knowledge both of good and evil; \r
+Forbids us then to taste! but his forbidding \r
+Commends thee more, while it infers the good \r
+By thee communicated, and our want: \r
+For good unknown sure is not had; or, had \r
+And yet unknown, is as not had at all. \r
+In plain then, what forbids he but to know, \r
+Forbids us good, forbids us to be wise? \r
+Such prohibitions bind not.  But, if death \r
+Bind us with after-bands, what profits then \r
+Our inward freedom?  In the day we eat \r
+Of this fair fruit, our doom is, we shall die! \r
+How dies the Serpent? he hath eaten and lives, \r
+And knows, and speaks, and reasons, and discerns, \r
+Irrational till then.  For us alone \r
+Was death invented? or to us denied \r
+This intellectual food, for beasts reserved? \r
+For beasts it seems: yet that one beast which first \r
+Hath tasted envies not, but brings with joy \r
+The good befallen him, author unsuspect, \r
+Friendly to man, far from deceit or guile. \r
+What fear I then? rather, what know to fear \r
+Under this ignorance of good and evil, \r
+Of God or death, of law or penalty? \r
+Here grows the cure of all, this fruit divine, \r
+Fair to the eye, inviting to the taste, \r
+Of virtue to make wise:  What hinders then \r
+To reach, and feed at once both body and mind? \r
+So saying, her rash hand in evil hour \r
+Forth reaching to the fruit, she plucked, she eat! \r
+Earth felt the wound; and Nature from her seat, \r
+Sighing through all her works, gave signs of woe, \r
+That all was lost.  Back to the thicket slunk \r
+The guilty Serpent; and well might;for Eve, \r
+Intent now wholly on her taste, nought else \r
+Regarded; such delight till then, as seemed, \r
+In fruit she never tasted, whether true \r
+Or fancied so, through expectation high \r
+Of knowledge; not was Godhead from her thought. \r
+Greedily she ingorged without restraint, \r
+And knew not eating death:  Satiate at length, \r
+And hightened as with wine, jocund and boon, \r
+Thus to herself she pleasingly began. \r
+O sovran, virtuous, precious of all trees \r
+In Paradise! of operation blest \r
+To sapience, hitherto obscured, infamed. \r
+And thy fair fruit let hang, as to no end \r
+Created; but henceforth my early care, \r
+Not without song, each morning, and due praise, \r
+Shall tend thee, and the fertile burden ease \r
+Of thy full branches offered free to all; \r
+Till, dieted by thee, I grow mature \r
+In knowledge, as the Gods, who all things know; \r
+Though others envy what they cannot give: \r
+For, had the gift been theirs, it had not here \r
+Thus grown.  Experience, next, to thee I owe, \r
+Best guide; not following thee, I had remained \r
+In ignorance; thou openest wisdom's way, \r
+And givest access, though secret she retire. \r
+And I perhaps am secret: Heaven is high, \r
+High, and remote to see from thence distinct \r
+Each thing on Earth; and other care perhaps \r
+May have diverted from continual watch \r
+Our great Forbidder, safe with all his spies \r
+About him.  But to Adam in what sort \r
+Shall I appear? shall I to him make known \r
+As yet my change, and give him to partake \r
+Full happiness with me, or rather not, \r
+But keeps the odds of knowledge in my power \r
+Without copartner? so to add what wants \r
+In female sex, the more to draw his love, \r
+And render me more equal; and perhaps, \r
+A thing not undesirable, sometime \r
+Superiour; for, inferiour, who is free \r
+This may be well:  But what if God have seen, \r
+And death ensue? then I shall be no more! \r
+And Adam, wedded to another Eve, \r
+Shall live with her enjoying, I extinct; \r
+A death to think!  Confirmed then I resolve, \r
+Adam shall share with me in bliss or woe: \r
+So dear I love him, that with him all deaths \r
+I could endure, without him live no life. \r
+So saying, from the tree her step she turned; \r
+But first low reverence done, as to the Power \r
+That dwelt within, whose presence had infused \r
+Into the plant sciential sap, derived \r
+From nectar, drink of Gods.  Adam the while, \r
+Waiting desirous her return, had wove \r
+Of choicest flowers a garland, to adorn \r
+Her tresses, and her rural labours crown; \r
+As reapers oft are wont their harvest-queen. \r
+Great joy he promised to his thoughts, and new \r
+Solace in her return, so long delayed: \r
+Yet oft his heart, divine of something ill, \r
+Misgave him; he the faltering measure felt; \r
+And forth to meet her went, the way she took \r
+That morn when first they parted: by the tree \r
+Of knowledge he must pass; there he her met, \r
+Scarce from the tree returning; in her hand \r
+A bough of fairest fruit, that downy smiled, \r
+New gathered, and ambrosial smell diffused. \r
+To him she hasted; in her face excuse \r
+Came prologue, and apology too prompt; \r
+Which, with bland words at will, she thus addressed. \r
+Hast thou not wondered, Adam, at my stay? \r
+Thee I have missed, and thought it long, deprived \r
+Thy presence; agony of love till now \r
+Not felt, nor shall be twice; for never more \r
+Mean I to try, what rash untried I sought, \r
+The pain of absence from thy sight.  But strange \r
+Hath been the cause, and wonderful to hear: \r
+This tree is not, as we are told, a tree \r
+Of danger tasted, nor to evil unknown \r
+Opening the way, but of divine effect \r
+To open eyes, and make them Gods who taste; \r
+And hath been tasted such:  The serpent wise, \r
+Or not restrained as we, or not obeying, \r
+Hath eaten of the fruit; and is become, \r
+Not dead, as we are threatened, but thenceforth \r
+Endued with human voice and human sense, \r
+Reasoning to admiration; and with me \r
+Persuasively hath so prevailed, that I \r
+Have also tasted, and have also found \r
+The effects to correspond; opener mine eyes, \r
+Dim erst, dilated spirits, ampler heart, \r
+And growing up to Godhead; which for thee \r
+Chiefly I sought, without thee can despise. \r
+For bliss, as thou hast part, to me is bliss; \r
+Tedious, unshared with thee, and odious soon. \r
+Thou therefore also taste, that equal lot \r
+May join us, equal joy, as equal love; \r
+Lest, thou not tasting, different degree \r
+Disjoin us, and I then too late renounce \r
+Deity for thee, when Fate will not permit. \r
+Thus Eve with countenance blithe her story told; \r
+But in her cheek distemper flushing glowed. \r
+On the other side Adam, soon as he heard \r
+The fatal trespass done by Eve, amazed, \r
+Astonied stood and blank, while horrour chill \r
+Ran through his veins, and all his joints relaxed; \r
+From his slack hand the garland wreathed for Eve \r
+Down dropt, and all the faded roses shed: \r
+Speechless he stood and pale, till thus at length \r
+First to himself he inward silence broke. \r
+O fairest of Creation, last and best \r
+Of all God's works, Creature in whom excelled \r
+Whatever can to sight or thought be formed, \r
+Holy, divine, good, amiable, or sweet! \r
+How art thou lost! how on a sudden lost, \r
+Defaced, deflowered, and now to death devote! \r
+Rather, how hast thou yielded to transgress \r
+The strict forbiddance, how to violate \r
+The sacred fruit forbidden!  Some cursed fraud \r
+Of enemy hath beguiled thee, yet unknown, \r
+And me with thee hath ruined; for with thee \r
+Certain my resolution is to die: \r
+How can I live without thee! how forego \r
+Thy sweet converse, and love so dearly joined, \r
+To live again in these wild woods forlorn! \r
+Should God create another Eve, and I \r
+Another rib afford, yet loss of thee \r
+Would never from my heart: no, no!I feel \r
+The link of Nature draw me: flesh of flesh, \r
+Bone of my bone thou art, and from thy state \r
+Mine never shall be parted, bliss or woe. \r
+So having said, as one from sad dismay \r
+Recomforted, and after thoughts disturbed \r
+Submitting to what seemed remediless, \r
+Thus in calm mood his words to Eve he turned. \r
+Bold deed thou hast presumed, adventurous Eve, \r
+And peril great provoked, who thus hast dared, \r
+Had it been only coveting to eye \r
+That sacred fruit, sacred to abstinence, \r
+Much more to taste it under ban to touch. \r
+But past who can recall, or done undo? \r
+Not God Omnipotent, nor Fate; yet so \r
+Perhaps thou shalt not die, perhaps the fact \r
+Is not so heinous now, foretasted fruit, \r
+Profaned first by the serpent, by him first \r
+Made common, and unhallowed, ere our taste; \r
+Nor yet on him found deadly; yet he lives; \r
+Lives, as thou saidst, and gains to live, as Man, \r
+Higher degree of life; inducement strong \r
+To us, as likely tasting to attain \r
+Proportional ascent; which cannot be \r
+But to be Gods, or Angels, demi-Gods. \r
+Nor can I think that God, Creator wise, \r
+Though threatening, will in earnest so destroy \r
+Us his prime creatures, dignified so high, \r
+Set over all his works; which in our fall, \r
+For us created, needs with us must fail, \r
+Dependant made; so God shall uncreate, \r
+Be frustrate, do, undo, and labour lose; \r
+Not well conceived of God, who, though his power \r
+Creation could repeat, yet would be loth \r
+Us to abolish, lest the Adversary \r
+Triumph, and say; "Fickle their state whom God \r
+"Most favours; who can please him long? Me first \r
+"He ruined, now Mankind; whom will he next?" \r
+Matter of scorn, not to be given the Foe. \r
+However I with thee have fixed my lot, \r
+Certain to undergo like doom:  If death \r
+Consort with thee, death is to me as life; \r
+So forcible within my heart I feel \r
+The bond of Nature draw me to my own; \r
+My own in thee, for what thou art is mine; \r
+Our state cannot be severed; we are one, \r
+One flesh; to lose thee were to lose myself. \r
+So Adam; and thus Eve to him replied. \r
+O glorious trial of exceeding love, \r
+Illustrious evidence, example high! \r
+Engaging me to emulate; but, short \r
+Of thy perfection, how shall I attain, \r
+Adam, from whose dear side I boast me sprung, \r
+And gladly of our union hear thee speak, \r
+One heart, one soul in both; whereof good proof \r
+This day affords, declaring thee resolved, \r
+Rather than death, or aught than death more dread, \r
+Shall separate us, linked in love so dear, \r
+To undergo with me one guilt, one crime, \r
+If any be, of tasting this fair fruit; \r
+Whose virtue for of good still good proceeds, \r
+Direct, or by occasion, hath presented \r
+This happy trial of thy love, which else \r
+So eminently never had been known? \r
+Were it I thought death menaced would ensue \r
+This my attempt, I would sustain alone \r
+The worst, and not persuade thee, rather die \r
+Deserted, than oblige thee with a fact \r
+Pernicious to thy peace; chiefly assured \r
+Remarkably so late of thy so true, \r
+So faithful, love unequalled: but I feel \r
+Far otherwise the event; not death, but life \r
+Augmented, opened eyes, new hopes, new joys, \r
+Taste so divine, that what of sweet before \r
+Hath touched my sense, flat seems to this, and harsh. \r
+On my experience, Adam, freely taste, \r
+And fear of death deliver to the winds. \r
+So saying, she embraced him, and for joy \r
+Tenderly wept; much won, that he his love \r
+Had so ennobled, as of choice to incur \r
+Divine displeasure for her sake, or death. \r
+In recompence for such compliance bad \r
+Such recompence best merits from the bough \r
+She gave him of that fair enticing fruit \r
+With liberal hand: he scrupled not to eat, \r
+Against his better knowledge; not deceived, \r
+But fondly overcome with female charm. \r
+Earth trembled from her entrails, as again \r
+In pangs; and Nature gave a second groan; \r
+Sky loured; and, muttering thunder, some sad drops \r
+Wept at completing of the mortal sin \r
+Original: while Adam took no thought, \r
+Eating his fill; nor Eve to iterate \r
+Her former trespass feared, the more to sooth \r
+Him with her loved society; that now, \r
+As with new wine intoxicated both, \r
+They swim in mirth, and fancy that they feel \r
+Divinity within them breeding wings, \r
+Wherewith to scorn the earth:  But that false fruit \r
+Far other operation first displayed, \r
+Carnal desire inflaming; he on Eve \r
+Began to cast lascivious eyes; she him \r
+As wantonly repaid; in lust they burn: \r
+Till Adam thus 'gan Eve to dalliance move. \r
+Eve, now I see thou art exact of taste, \r
+And elegant, of sapience no small part; \r
+Since to each meaning savour we apply, \r
+And palate call judicious; I the praise \r
+Yield thee, so well this day thou hast purveyed. \r
+Much pleasure we have lost, while we abstained \r
+From this delightful fruit, nor known till now \r
+True relish, tasting; if such pleasure be \r
+In things to us forbidden, it might be wished, \r
+For this one tree had been forbidden ten. \r
+But come, so well refreshed, now let us play, \r
+As meet is, after such delicious fare; \r
+For never did thy beauty, since the day \r
+I saw thee first and wedded thee, adorned \r
+With all perfections, so inflame my sense \r
+With ardour to enjoy thee, fairer now \r
+Than ever; bounty of this virtuous tree! \r
+So said he, and forbore not glance or toy \r
+Of amorous intent; well understood \r
+Of Eve, whose eye darted contagious fire. \r
+Her hand he seised; and to a shady bank, \r
+Thick over-head with verdant roof imbowered, \r
+He led her nothing loth; flowers were the couch, \r
+Pansies, and violets, and asphodel, \r
+And hyacinth;  Earth's freshest softest lap. \r
+There they their fill of love and love's disport \r
+Took largely, of their mutual guilt the seal, \r
+The solace of their sin; till dewy sleep \r
+Oppressed them, wearied with their amorous play, \r
+Soon as the force of that fallacious fruit, \r
+That with exhilarating vapour bland \r
+About their spirits had played, and inmost powers \r
+Made err, was now exhaled; and grosser sleep, \r
+Bred of unkindly fumes, with conscious dreams \r
+Incumbered, now had left them; up they rose \r
+As from unrest; and, each the other viewing, \r
+Soon found their eyes how opened, and their minds \r
+How darkened; innocence, that as a veil \r
+Had shadowed them from knowing ill, was gone; \r
+Just confidence, and native righteousness, \r
+And honour, from about them, naked left \r
+To guilty Shame; he covered, but his robe \r
+Uncovered more.  So rose the Danite strong, \r
+Herculean Samson, from the harlot-lap \r
+Of Philistean Dalilah, and waked \r
+Shorn of his strength.  They destitute and bare \r
+Of all their virtue:  Silent, and in face \r
+Confounded, long they sat, as strucken mute: \r
+Till Adam, though not less than Eve abashed, \r
+At length gave utterance to these words constrained. \r
+O Eve, in evil hour thou didst give ear \r
+To that false worm, of whomsoever taught \r
+To counterfeit Man's voice; true in our fall, \r
+False in our promised rising; since our eyes \r
+Opened we find indeed, and find we know \r
+Both good and evil; good lost, and evil got; \r
+Bad fruit of knowledge, if this be to know; \r
+Which leaves us naked thus, of honour void, \r
+Of innocence, of faith, of purity, \r
+Our wonted ornaments now soiled and stained, \r
+And in our faces evident the signs \r
+Of foul concupiscence; whence evil store; \r
+Even shame, the last of evils; of the first \r
+Be sure then.--How shall I behold the face \r
+Henceforth of God or Angel, erst with joy \r
+And rapture so oft beheld?  Those heavenly shapes \r
+Will dazzle now this earthly with their blaze \r
+Insufferably bright.  O! might I here \r
+In solitude live savage; in some glade \r
+Obscured, where highest woods, impenetrable \r
+To star or sun-light, spread their umbrage broad \r
+And brown as evening:  Cover me, ye Pines! \r
+Ye Cedars, with innumerable boughs \r
+Hide me, where I may never see them more!-- \r
+But let us now, as in bad plight, devise \r
+What best may for the present serve to hide \r
+The parts of each from other, that seem most \r
+To shame obnoxious, and unseemliest seen; \r
+Some tree, whose broad smooth leaves together sewed, \r
+And girded on our loins, may cover round \r
+Those middle parts; that this new comer, Shame, \r
+There sit not, and reproach us as unclean. \r
+So counselled he, and both together went \r
+Into the thickest wood; there soon they chose \r
+The fig-tree; not that kind for fruit renowned, \r
+But such as at this day, to Indians known, \r
+In Malabar or Decan spreads her arms \r
+Branching so broad and long, that in the ground \r
+The bended twigs take root, and daughters grow \r
+About the mother tree, a pillared shade \r
+High over-arched, and echoing walks between: \r
+There oft the Indian herdsman, shunning heat, \r
+Shelters in cool, and tends his pasturing herds \r
+At loop-holes cut through thickest shade:  Those leaves \r
+They gathered, broad as Amazonian targe; \r
+And, with what skill they had, together sewed, \r
+To gird their waist; vain covering, if to hide \r
+Their guilt and dreaded shame!  O, how unlike \r
+To that first naked glory!  Such of late \r
+Columbus found the American, so girt \r
+With feathered cincture; naked else, and wild \r
+Among the trees on isles and woody shores. \r
+Thus fenced, and, as they thought, their shame in part \r
+Covered, but not at rest or ease of mind, \r
+They sat them down to weep; nor only tears \r
+Rained at their eyes, but high winds worse within \r
+Began to rise, high passions, anger, hate, \r
+Mistrust, suspicion, discord; and shook sore \r
+Their inward state of mind, calm region once \r
+And full of peace, now tost and turbulent: \r
+For Understanding ruled not, and the Will \r
+Heard not her lore; both in subjection now \r
+To sensual Appetite, who from beneath \r
+Usurping over sovran Reason claimed \r
+Superiour sway: From thus distempered breast, \r
+Adam, estranged in look and altered style, \r
+Speech intermitted thus to Eve renewed. \r
+Would thou hadst hearkened to my words, and staid \r
+With me, as I besought thee, when that strange \r
+Desire of wandering, this unhappy morn, \r
+I know not whence possessed thee; we had then \r
+Remained still happy; not, as now, despoiled \r
+Of all our good; shamed, naked, miserable! \r
+Let none henceforth seek needless cause to approve \r
+The faith they owe; when earnestly they seek \r
+Such proof, conclude, they then begin to fail. \r
+To whom, soon moved with touch of blame, thus Eve. \r
+What words have passed thy lips, Adam severe! \r
+Imputest thou that to my default, or will \r
+Of wandering, as thou callest it, which who knows \r
+But might as ill have happened thou being by, \r
+Or to thyself perhaps?  Hadst thou been there, \r
+Or here the attempt, thou couldst not have discerned \r
+Fraud in the Serpent, speaking as he spake; \r
+No ground of enmity between us known, \r
+Why he should mean me ill, or seek to harm. \r
+Was I to have never parted from thy side? \r
+As good have grown there still a lifeless rib. \r
+Being as I am, why didst not thou, the head, \r
+Command me absolutely not to go, \r
+Going into such danger, as thou saidst? \r
+Too facile then, thou didst not much gainsay; \r
+Nay, didst permit, approve, and fair dismiss. \r
+Hadst thou been firm and fixed in thy dissent, \r
+Neither had I transgressed, nor thou with me. \r
+To whom, then first incensed, Adam replied. \r
+Is this the love, is this the recompence \r
+Of mine to thee, ingrateful Eve! expressed \r
+Immutable, when thou wert lost, not I; \r
+Who might have lived, and joyed immortal bliss, \r
+Yet willingly chose rather death with thee? \r
+And am I now upbraided as the cause \r
+Of thy transgressing?  Not enough severe, \r
+It seems, in thy restraint:  What could I more \r
+I warned thee, I admonished thee, foretold \r
+The danger, and the lurking enemy \r
+That lay in wait; beyond this, had been force; \r
+And force upon free will hath here no place. \r
+But confidence then bore thee on; secure \r
+Either to meet no danger, or to find \r
+Matter of glorious trial; and perhaps \r
+I also erred, in overmuch admiring \r
+What seemed in thee so perfect, that I thought \r
+No evil durst attempt thee; but I rue \r
+The errour now, which is become my crime, \r
+And thou the accuser.  Thus it shall befall \r
+Him, who, to worth in women overtrusting, \r
+Lets her will rule: restraint she will not brook; \r
+And, left to herself, if evil thence ensue, \r
+She first his weak indulgence will accuse. \r
+Thus they in mutual accusation spent \r
+The fruitless hours, but neither self-condemning; \r
+And of their vain contest appeared no end. \r
\r
\r
\r
+Book X                                                           \r
\r
\r
+Mean while the heinous and despiteful act \r
+Of Satan, done in Paradise; and how \r
+He, in the serpent, had perverted Eve, \r
+Her husband she, to taste the fatal fruit, \r
+Was known in Heaven; for what can 'scape the eye \r
+Of God all-seeing, or deceive his heart \r
+Omniscient? who, in all things wise and just, \r
+Hindered not Satan to attempt the mind \r
+Of Man, with strength entire and free will armed, \r
+Complete to have discovered and repulsed \r
+Whatever wiles of foe or seeming friend. \r
+For still they knew, and ought to have still remembered, \r
+The high injunction, not to taste that fruit, \r
+Whoever tempted; which they not obeying, \r
+(Incurred what could they less?) the penalty; \r
+And, manifold in sin, deserved to fall. \r
+Up into Heaven from Paradise in haste \r
+The angelick guards ascended, mute, and sad, \r
+For Man; for of his state by this they knew, \r
+Much wondering how the subtle Fiend had stolen \r
+Entrance unseen.  Soon as the unwelcome news \r
+From Earth arrived at Heaven-gate, displeased \r
+All were who heard; dim sadness did not spare \r
+That time celestial visages, yet, mixed \r
+With pity, violated not their bliss. \r
+About the new-arrived, in multitudes \r
+The ethereal people ran, to hear and know \r
+How all befel:  They towards the throne supreme, \r
+Accountable, made haste, to make appear, \r
+With righteous plea, their utmost vigilance \r
+And easily approved; when the Most High \r
+Eternal Father, from his secret cloud, \r
+Amidst in thunder uttered thus his voice. \r
+Assembled Angels, and ye Powers returned \r
+From unsuccessful charge; be not dismayed, \r
+Nor troubled at these tidings from the earth, \r
+Which your sincerest care could not prevent; \r
+Foretold so lately what would come to pass, \r
+When first this tempter crossed the gulf from Hell. \r
+I told ye then he should prevail, and speed \r
+On his bad errand; Man should be seduced, \r
+And flattered out of all, believing lies \r
+Against his Maker; no decree of mine \r
+Concurring to necessitate his fall, \r
+Or touch with lightest moment of impulse \r
+His free will, to her own inclining left \r
+In even scale.  But fallen he is; and now \r
+What rests, but that the mortal sentence pass \r
+On his transgression,--death denounced that day? \r
+Which he presumes already vain and void, \r
+Because not yet inflicted, as he feared, \r
+By some immediate stroke; but soon shall find \r
+Forbearance no acquittance, ere day end. \r
+Justice shall not return as bounty scorned. \r
+But whom send I to judge them? whom but thee, \r
+Vicegerent Son?  To thee I have transferred \r
+All judgement, whether in Heaven, or Earth, or Hell. \r
+Easy it may be seen that I intend \r
+Mercy colleague with justice, sending thee \r
+Man's friend, his Mediator, his designed \r
+Both ransom and Redeemer voluntary, \r
+And destined Man himself to judge Man fallen. \r
+So spake the Father; and, unfolding bright \r
+Toward the right hand his glory, on the Son \r
+Blazed forth unclouded Deity: He full \r
+Resplendent all his Father manifest \r
+Expressed, and thus divinely answered mild. \r
+Father Eternal, thine is to decree; \r
+Mine, both in Heaven and Earth, to do thy will \r
+Supreme; that thou in me, thy Son beloved, \r
+Mayest ever rest well pleased.  I go to judge \r
+On earth these thy transgressours; but thou knowest, \r
+Whoever judged, the worst on me must light, \r
+When time shall be; for so I undertook \r
+Before thee; and, not repenting, this obtain \r
+Of right, that I may mitigate their doom \r
+On me derived; yet I shall temper so \r
+Justice with mercy, as may illustrate most \r
+Them fully satisfied, and thee appease. \r
+Attendance none shall need, nor train, where none \r
+Are to behold the judgement, but the judged, \r
+Those two; the third best absent is condemned, \r
+Convict by flight, and rebel to all law: \r
+Conviction to the serpent none belongs. \r
+Thus saying, from his radiant seat he rose \r
+Of high collateral glory: Him Thrones, and Powers, \r
+Princedoms, and Dominations ministrant, \r
+Accompanied to Heaven-gate; from whence \r
+Eden, and all the coast, in prospect lay. \r
+Down he descended straight; the speed of Gods \r
+Time counts not, though with swiftest minutes winged. \r
+Now was the sun in western cadence low \r
+From noon, and gentle airs, due at their hour, \r
+To fan the earth now waked, and usher in \r
+The evening cool; when he, from wrath more cool, \r
+Came the mild Judge, and Intercessour both, \r
+To sentence Man:  The voice of God they heard \r
+Now walking in the garden, by soft winds \r
+Brought to their ears, while day declined; they heard, \r
+And from his presence hid themselves among \r
+The thickest trees, both man and wife; till God, \r
+Approaching, thus to Adam called aloud. \r
+Where art thou, Adam, wont with joy to meet \r
+My coming seen far off?  I miss thee here, \r
+Not pleased, thus entertained with solitude, \r
+Where obvious duty ere while appeared unsought: \r
+Or come I less conspicuous, or what change \r
+Absents thee, or what chance detains?--Come forth! \r
+He came; and with him Eve, more loth, though first \r
+To offend; discountenanced both, and discomposed; \r
+Love was not in their looks, either to God, \r
+Or to each other; but apparent guilt, \r
+And shame, and perturbation, and despair, \r
+Anger, and obstinacy, and hate, and guile. \r
+Whence Adam, faltering long, thus answered brief. \r
+I heard thee in the garden, and of thy voice \r
+Afraid, being naked, hid myself.  To whom \r
+The gracious Judge without revile replied. \r
+My voice thou oft hast heard, and hast not feared, \r
+But still rejoiced; how is it now become \r
+So dreadful to thee?  That thou art naked, who \r
+Hath told thee?  Hast thou eaten of the tree, \r
+Whereof I gave thee charge thou shouldst not eat? \r
+To whom thus Adam sore beset replied. \r
+O Heaven! in evil strait this day I stand \r
+Before my Judge; either to undergo \r
+Myself the total crime, or to accuse \r
+My other self, the partner of my life; \r
+Whose failing, while her faith to me remains, \r
+I should conceal, and not expose to blame \r
+By my complaint: but strict necessity \r
+Subdues me, and calamitous constraint; \r
+Lest on my head both sin and punishment, \r
+However insupportable, be all \r
+Devolved; though should I hold my peace, yet thou \r
+Wouldst easily detect what I conceal.-- \r
+This Woman, whom thou madest to be my help, \r
+And gavest me as thy perfect gift, so good, \r
+So fit, so acceptable, so divine, \r
+That from her hand I could suspect no ill, \r
+And what she did, whatever in itself, \r
+Her doing seemed to justify the deed; \r
+She gave me of the tree, and I did eat. \r
+To whom the Sovran Presence thus replied. \r
+Was she thy God, that her thou didst obey \r
+Before his voice? or was she made thy guide, \r
+Superiour, or but equal, that to her \r
+Thou didst resign thy manhood, and the place \r
+Wherein God set thee above her made of thee, \r
+And for thee, whose perfection far excelled \r
+Hers in all real dignity?  Adorned \r
+She was indeed, and lovely, to attract \r
+Thy love, not thy subjection; and her gifts \r
+Were such, as under government well seemed; \r
+Unseemly to bear rule; which was thy part \r
+And person, hadst thou known thyself aright. \r
+So having said, he thus to Eve in few. \r
+Say, Woman, what is this which thou hast done? \r
+To whom sad Eve, with shame nigh overwhelmed, \r
+Confessing soon, yet not before her Judge \r
+Bold or loquacious, thus abashed replied. \r
+The Serpent me beguiled, and I did eat. \r
+Which when the Lord God heard, without delay \r
+To judgement he proceeded on the accused \r
+Serpent, though brute; unable to transfer \r
+The guilt on him, who made him instrument \r
+Of mischief, and polluted from the end \r
+Of his creation; justly then accursed, \r
+As vitiated in nature:  More to know \r
+Concerned not Man, (since he no further knew) \r
+Nor altered his offence; yet God at last \r
+To Satan first in sin his doom applied, \r
+Though in mysterious terms, judged as then best: \r
+And on the Serpent thus his curse let fall. \r
+Because thou hast done this, thou art accursed \r
+Above all cattle, each beast of the field; \r
+Upon thy belly groveling thou shalt go, \r
+And dust shalt eat all the days of thy life. \r
+Between thee and the woman I will put \r
+Enmity, and between thine and her seed; \r
+Her seed shall bruise thy head, thou bruise his heel. \r
+So spake this oracle, then verified \r
+When Jesus, Son of Mary, second Eve, \r
+Saw Satan fall, like lightning, down from Heaven, \r
+Prince of the air; then, rising from his grave \r
+Spoiled Principalities and Powers, triumphed \r
+In open show; and, with ascension bright, \r
+Captivity led captive through the air, \r
+The realm itself of Satan, long usurped; \r
+Whom he shall tread at last under our feet; \r
+Even he, who now foretold his fatal bruise; \r
+And to the Woman thus his sentence turned. \r
+Thy sorrow I will greatly multiply \r
+By thy conception; children thou shalt bring \r
+In sorrow forth; and to thy husband's will \r
+Thine shall submit; he over thee shall rule. \r
+On Adam last thus judgement he pronounced. \r
+Because thou hast hearkened to the voice of thy wife, \r
+And eaten of the tree, concerning which \r
+I charged thee, saying, Thou shalt not eat thereof: \r
+Cursed is the ground for thy sake; thou in sorrow \r
+Shalt eat thereof, all the days of thy life; \r
+Thorns also and thistles it shall bring thee forth \r
+Unbid; and thou shalt eat the herb of the field; \r
+In the sweat of thy face shalt thou eat bread, \r
+Till thou return unto the ground; for thou \r
+Out of the ground wast taken, know thy birth, \r
+For dust thou art, and shalt to dust return. \r
+So judged he Man, both Judge and Saviour sent; \r
+And the instant stroke of death, denounced that day, \r
+Removed far off; then, pitying how they stood \r
+Before him naked to the air, that now \r
+Must suffer change, disdained not to begin \r
+Thenceforth the form of servant to assume; \r
+As when he washed his servants feet; so now, \r
+As father of his family, he clad \r
+Their nakedness with skins of beasts, or slain, \r
+Or as the snake with youthful coat repaid; \r
+And thought not much to clothe his enemies; \r
+Nor he their outward only with the skins \r
+Of beasts, but inward nakedness, much more. \r
+Opprobrious, with his robe of righteousness, \r
+Arraying, covered from his Father's sight. \r
+To him with swift ascent he up returned, \r
+Into his blissful bosom reassumed \r
+In glory, as of old; to him appeased \r
+All, though all-knowing, what had passed with Man \r
+Recounted, mixing intercession sweet. \r
+Mean while, ere thus was sinned and judged on Earth, \r
+Within the gates of Hell sat Sin and Death, \r
+In counterview within the gates, that now \r
+Stood open wide, belching outrageous flame \r
+Far into Chaos, since the Fiend passed through, \r
+Sin opening; who thus now to Death began. \r
+O Son, why sit we here each other viewing \r
+Idly, while Satan, our great author, thrives \r
+In other worlds, and happier seat provides \r
+For us, his offspring dear?  It cannot be \r
+But that success attends him; if mishap, \r
+Ere this he had returned, with fury driven \r
+By his avengers; since no place like this \r
+Can fit his punishment, or their revenge. \r
+Methinks I feel new strength within me rise, \r
+Wings growing, and dominion given me large \r
+Beyond this deep; whatever draws me on, \r
+Or sympathy, or some connatural force, \r
+Powerful at greatest distance to unite, \r
+With secret amity, things of like kind, \r
+By secretest conveyance.  Thou, my shade \r
+Inseparable, must with me along; \r
+For Death from Sin no power can separate. \r
+But, lest the difficulty of passing back \r
+Stay his return perhaps over this gulf \r
+Impassable, impervious; let us try \r
+Adventurous work, yet to thy power and mine \r
+Not unagreeable, to found a path \r
+Over this main from Hell to that new world, \r
+Where Satan now prevails; a monument \r
+Of merit high to all the infernal host, \r
+Easing their passage hence, for intercourse, \r
+Or transmigration, as their lot shall lead. \r
+Nor can I miss the way, so strongly drawn \r
+By this new-felt attraction and instinct. \r
+Whom thus the meager Shadow answered soon. \r
+Go, whither Fate, and inclination strong, \r
+Leads thee; I shall not lag behind, nor err \r
+The way, thou leading; such a scent I draw \r
+Of carnage, prey innumerable, and taste \r
+The savour of death from all things there that live: \r
+Nor shall I to the work thou enterprisest \r
+Be wanting, but afford thee equal aid. \r
+So saying, with delight he snuffed the smell \r
+Of mortal change on earth.  As when a flock \r
+Of ravenous fowl, though many a league remote, \r
+Against the day of battle, to a field, \r
+Where armies lie encamped, come flying, lured \r
+With scent of living carcasses designed \r
+For death, the following day, in bloody fight: \r
+So scented the grim Feature, and upturned \r
+His nostril wide into the murky air; \r
+Sagacious of his quarry from so far. \r
+Then both from out Hell-gates, into the waste \r
+Wide anarchy of Chaos, damp and dark, \r
+Flew diverse; and with power (their power was great) \r
+Hovering upon the waters, what they met \r
+Solid or slimy, as in raging sea \r
+Tost up and down, together crouded drove, \r
+From each side shoaling towards the mouth of Hell; \r
+As when two polar winds, blowing adverse \r
+Upon the Cronian sea, together drive \r
+Mountains of ice, that stop the imagined way \r
+Beyond Petsora eastward, to the rich \r
+Cathaian coast.  The aggregated soil \r
+Death with his mace petrifick, cold and dry, \r
+As with a trident, smote; and fixed as firm \r
+As Delos, floating once; the rest his look \r
+Bound with Gorgonian rigour not to move; \r
+And with Asphaltick slime, broad as the gate, \r
+Deep to the roots of Hell the gathered beach \r
+They fastened, and the mole immense wrought on \r
+Over the foaming deep high-arched, a bridge \r
+Of length prodigious, joining to the wall \r
+Immoveable of this now fenceless world, \r
+Forfeit to Death; from hence a passage broad, \r
+Smooth, easy, inoffensive, down to Hell. \r
+So, if great things to small may be compared, \r
+Xerxes, the liberty of Greece to yoke, \r
+From Susa, his Memnonian palace high, \r
+Came to the sea: and, over Hellespont \r
+Bridging his way, Europe with Asia joined, \r
+And scourged with many a stroke the indignant waves. \r
+Now had they brought the work by wonderous art \r
+Pontifical, a ridge of pendant rock, \r
+Over the vexed abyss, following the track \r
+Of Satan to the self-same place where he \r
+First lighted from his wing, and landed safe \r
+From out of Chaos, to the outside bare \r
+Of this round world:  With pins of adamant \r
+And chains they made all fast, too fast they made \r
+And durable!  And now in little space \r
+The confines met of empyrean Heaven, \r
+And of this World; and, on the left hand, Hell \r
+With long reach interposed; three several ways \r
+In sight, to each of these three places led. \r
+And now their way to Earth they had descried, \r
+To Paradise first tending; when, behold! \r
+Satan, in likeness of an Angel bright, \r
+Betwixt the Centaur and the Scorpion steering \r
+His zenith, while the sun in Aries rose: \r
+Disguised he came; but those his children dear \r
+Their parent soon discerned, though in disguise. \r
+He, after Eve seduced, unminded slunk \r
+Into the wood fast by; and, changing shape, \r
+To observe the sequel, saw his guileful act \r
+By Eve, though all unweeting, seconded \r
+Upon her husband; saw their shame that sought \r
+Vain covertures; but when he saw descend \r
+The Son of God to judge them, terrified \r
+He fled; not hoping to escape, but shun \r
+The present; fearing, guilty, what his wrath \r
+Might suddenly inflict; that past, returned \r
+By night, and listening where the hapless pair \r
+Sat in their sad discourse, and various plaint, \r
+Thence gathered his own doom; which understood \r
+Not instant, but of future time, with joy \r
+And tidings fraught, to Hell he now returned; \r
+And at the brink of Chaos, near the foot \r
+Of this new wonderous pontifice, unhoped \r
+Met, who to meet him came, his offspring dear. \r
+Great joy was at their meeting, and at sight \r
+Of that stupendious bridge his joy encreased. \r
+Long he admiring stood, till Sin, his fair \r
+Enchanting daughter, thus the silence broke. \r
+O Parent, these are thy magnifick deeds, \r
+Thy trophies! which thou viewest as not thine own; \r
+Thou art their author, and prime architect: \r
+For I no sooner in my heart divined, \r
+My heart, which by a secret harmony \r
+Still moves with thine, joined in connexion sweet, \r
+That thou on earth hadst prospered, which thy looks \r
+Now also evidence, but straight I felt, \r
+Though distant from thee worlds between, yet felt, \r
+That I must after thee, with this thy son; \r
+Such fatal consequence unites us three! \r
+Hell could no longer hold us in our bounds, \r
+Nor this unvoyageable gulf obscure \r
+Detain from following thy illustrious track. \r
+Thou hast achieved our liberty, confined \r
+Within Hell-gates till now; thou us impowered \r
+To fortify thus far, and overlay, \r
+With this portentous bridge, the dark abyss. \r
+Thine now is all this world; thy virtue hath won \r
+What thy hands builded not; thy wisdom gained \r
+With odds what war hath lost, and fully avenged \r
+Our foil in Heaven; here thou shalt monarch reign, \r
+There didst not; there let him still victor sway, \r
+As battle hath adjudged; from this new world \r
+Retiring, by his own doom alienated; \r
+And henceforth monarchy with thee divide \r
+Of all things, parted by the empyreal bounds, \r
+His quadrature, from thy orbicular world; \r
+Or try thee now more dangerous to his throne. \r
+Whom thus the Prince of darkness answered glad. \r
+Fair Daughter, and thou Son and Grandchild both; \r
+High proof ye now have given to be the race \r
+Of Satan (for I glory in the name, \r
+Antagonist of Heaven's Almighty King,) \r
+Amply have merited of me, of all \r
+The infernal empire, that so near Heaven's door \r
+Triumphal with triumphal act have met, \r
+Mine, with this glorious work; and made one realm, \r
+Hell and this world, one realm, one continent \r
+Of easy thorough-fare.  Therefore, while I \r
+Descend through darkness, on your road with ease, \r
+To my associate Powers, them to acquaint \r
+With these successes, and with them rejoice; \r
+You two this way, among these numerous orbs, \r
+All yours, right down to Paradise descend; \r
+There dwell, and reign in bliss; thence on the earth \r
+Dominion exercise and in the air, \r
+Chiefly on Man, sole lord of all declared; \r
+Him first make sure your thrall, and lastly kill. \r
+My substitutes I send ye, and create \r
+Plenipotent on earth, of matchless might \r
+Issuing from me: on your joint vigour now \r
+My hold of this new kingdom all depends, \r
+Through Sin to Death exposed by my exploit. \r
+If your joint power prevail, the affairs of Hell \r
+No detriment need fear; go, and be strong! \r
+So saying he dismissed them; they with speed \r
+Their course through thickest constellations held, \r
+Spreading their bane; the blasted stars looked wan, \r
+And planets, planet-struck, real eclipse \r
+Then suffered.  The other way Satan went down \r
+The causey to Hell-gate:  On either side \r
+Disparted Chaos overbuilt exclaimed, \r
+And with rebounding surge the bars assailed, \r
+That scorned his indignation:  Through the gate, \r
+Wide open and unguarded, Satan passed, \r
+And all about found desolate; for those, \r
+Appointed to sit there, had left their charge, \r
+Flown to the upper world; the rest were all \r
+Far to the inland retired, about the walls \r
+Of Pandemonium; city and proud seat \r
+Of Lucifer, so by allusion called \r
+Of that bright star to Satan paragoned; \r
+There kept their watch the legions, while the Grand \r
+In council sat, solicitous what chance \r
+Might intercept their emperour sent; so he \r
+Departing gave command, and they observed. \r
+As when the Tartar from his Russian foe, \r
+By Astracan, over the snowy plains, \r
+Retires; or Bactrin Sophi, from the horns \r
+Of Turkish crescent, leaves all waste beyond \r
+The realm of Aladule, in his retreat \r
+To Tauris or Casbeen:  So these, the late \r
+Heaven-banished host, left desart utmost Hell \r
+Many a dark league, reduced in careful watch \r
+Round their metropolis; and now expecting \r
+Each hour their great adventurer, from the search \r
+Of foreign worlds:  He through the midst unmarked, \r
+In show plebeian Angel militant \r
+Of lowest order, passed; and from the door \r
+Of that Plutonian hall, invisible \r
+Ascended his high throne; which, under state \r
+Of richest texture spread, at the upper end \r
+Was placed in regal lustre.  Down a while \r
+He sat, and round about him saw unseen: \r
+At last, as from a cloud, his fulgent head \r
+And shape star-bright appeared, or brighter; clad \r
+With what permissive glory since his fall \r
+Was left him, or false glitter:  All amazed \r
+At that so sudden blaze the Stygian throng \r
+Bent their aspect, and whom they wished beheld, \r
+Their mighty Chief returned: loud was the acclaim: \r
+Forth rushed in haste the great consulting peers, \r
+Raised from their dark Divan, and with like joy \r
+Congratulant approached him; who with hand \r
+Silence, and with these words attention, won. \r
+Thrones, Dominations, Princedoms, Virtues, Powers; \r
+For in possession such, not only of right, \r
+I call ye, and declare ye now; returned \r
+Successful beyond hope, to lead ye forth \r
+Triumphant out of this infernal pit \r
+Abominable, accursed, the house of woe, \r
+And dungeon of our tyrant:  Now possess, \r
+As Lords, a spacious world, to our native Heaven \r
+Little inferiour, by my adventure hard \r
+With peril great achieved.  Long were to tell \r
+What I have done; what suffered;with what pain \r
+Voyaged th' unreal, vast, unbounded deep \r
+Of horrible confusion; over which \r
+By Sin and Death a broad way now is paved, \r
+To expedite your glorious march; but I \r
+Toiled out my uncouth passage, forced to ride \r
+The untractable abyss, plunged in the womb \r
+Of unoriginal Night and Chaos wild; \r
+That, jealous of their secrets, fiercely opposed \r
+My journey strange, with clamorous uproar \r
+Protesting Fate supreme; thence how I found \r
+The new created world, which fame in Heaven \r
+Long had foretold, a fabrick wonderful \r
+Of absolute perfection! therein Man \r
+Placed in a Paradise, by our exile \r
+Made happy:  Him by fraud I have seduced \r
+From his Creator; and, the more to encrease \r
+Your wonder, with an apple; he, thereat \r
+Offended, worth your laughter! hath given up \r
+Both his beloved Man, and all his world, \r
+To Sin and Death a prey, and so to us, \r
+Without our hazard, labour, or alarm; \r
+To range in, and to dwell, and over Man \r
+To rule, as over all he should have ruled. \r
+True is, me also he hath judged, or rather \r
+Me not, but the brute serpent in whose shape \r
+Man I deceived: that which to me belongs, \r
+Is enmity which he will put between \r
+Me and mankind; I am to bruise his heel; \r
+His seed, when is not set, shall bruise my head: \r
+A world who would not purchase with a bruise, \r
+Or much more grievous pain?--Ye have the account \r
+Of my performance:  What remains, ye Gods, \r
+But up, and enter now into full bliss? \r
+So having said, a while he stood, expecting \r
+Their universal shout, and high applause, \r
+To fill his ear; when, contrary, he hears \r
+On all sides, from innumerable tongues, \r
+A dismal universal hiss, the sound \r
+Of publick scorn; he wondered, but not long \r
+Had leisure, wondering at himself now more, \r
+His visage drawn he felt to sharp and spare; \r
+His arms clung to his ribs; his legs entwining \r
+Each other, till supplanted down he fell \r
+A monstrous serpent on his belly prone, \r
+Reluctant, but in vain; a greater power \r
+Now ruled him, punished in the shape he sinned, \r
+According to his doom: he would have spoke, \r
+But hiss for hiss returned with forked tongue \r
+To forked tongue; for now were all transformed \r
+Alike, to serpents all, as accessories \r
+To his bold riot:  Dreadful was the din \r
+Of hissing through the hall, thick swarming now \r
+With complicated monsters head and tail, \r
+Scorpion, and Asp, and Amphisbaena dire, \r
+Cerastes horned, Hydrus, and Elops drear, \r
+And Dipsas; (not so thick swarmed once the soil \r
+Bedropt with blood of Gorgon, or the isle \r
+Ophiusa,) but still greatest he the midst, \r
+Now Dragon grown, larger than whom the sun \r
+Ingendered in the Pythian vale or slime, \r
+Huge Python, and his power no less he seemed \r
+Above the rest still to retain; they all \r
+Him followed, issuing forth to the open field, \r
+Where all yet left of that revolted rout, \r
+Heaven-fallen, in station stood or just array; \r
+Sublime with expectation when to see \r
+In triumph issuing forth their glorious Chief; \r
+They saw, but other sight instead! a croud \r
+Of ugly serpents; horrour on them fell, \r
+And horrid sympathy; for, what they saw, \r
+They felt themselves, now changing; down their arms, \r
+Down fell both spear and shield; down they as fast; \r
+And the dire hiss renewed, and the dire form \r
+Catched, by contagion; like in punishment, \r
+As in their crime.  Thus was the applause they meant, \r
+Turned to exploding hiss, triumph to shame \r
+Cast on themselves from their own mouths.  There stood \r
+A grove hard by, sprung up with this their change, \r
+His will who reigns above, to aggravate \r
+Their penance, laden with fair fruit, like that \r
+Which grew in Paradise, the bait of Eve \r
+Used by the Tempter: on that prospect strange \r
+Their earnest eyes they fixed, imagining \r
+For one forbidden tree a multitude \r
+Now risen, to work them further woe or shame; \r
+Yet, parched with scalding thirst and hunger fierce, \r
+Though to delude them sent, could not abstain; \r
+But on they rolled in heaps, and, up the trees \r
+Climbing, sat thicker than the snaky locks \r
+That curled Megaera: greedily they plucked \r
+The fruitage fair to sight, like that which grew \r
+Near that bituminous lake where Sodom flamed; \r
+This more delusive, not the touch, but taste \r
+Deceived; they, fondly thinking to allay \r
+Their appetite with gust, instead of fruit \r
+Chewed bitter ashes, which the offended taste \r
+With spattering noise rejected: oft they assayed, \r
+Hunger and thirst constraining; drugged as oft, \r
+With hatefullest disrelish writhed their jaws, \r
+With soot and cinders filled; so oft they fell \r
+Into the same illusion, not as Man \r
+Whom they triumphed once lapsed.  Thus were they plagued \r
+And worn with famine, long and ceaseless hiss, \r
+Till their lost shape, permitted, they resumed; \r
+Yearly enjoined, some say, to undergo, \r
+This annual humbling certain numbered days, \r
+To dash their pride, and joy, for Man seduced. \r
+However, some tradition they dispersed \r
+Among the Heathen, of their purchase got, \r
+And fabled how the Serpent, whom they called \r
+Ophion, with Eurynome, the wide-- \r
+Encroaching Eve perhaps, had first the rule \r
+Of high Olympus; thence by Saturn driven \r
+And Ops, ere yet Dictaean Jove was born. \r
+Mean while in Paradise the hellish pair \r
+Too soon arrived; Sin, there in power before, \r
+Once actual; now in body, and to dwell \r
+Habitual habitant; behind her Death, \r
+Close following pace for pace, not mounted yet \r
+On his pale horse: to whom Sin thus began. \r
+Second of Satan sprung, all-conquering Death! \r
+What thinkest thou of our empire now, though earned \r
+With travel difficult, not better far \r
+Than still at Hell's dark threshold to have sat watch, \r
+Unnamed, undreaded, and thyself half starved? \r
+Whom thus the Sin-born monster answered soon. \r
+To me, who with eternal famine pine, \r
+Alike is Hell, or Paradise, or Heaven; \r
+There best, where most with ravine I may meet; \r
+Which here, though plenteous, all too little seems \r
+To stuff this maw, this vast unhide-bound corps. \r
+To whom the incestuous mother thus replied. \r
+Thou therefore on these herbs, and fruits, and flowers, \r
+Feed first; on each beast next, and fish, and fowl; \r
+No homely morsels! and, whatever thing \r
+The sithe of Time mows down, devour unspared; \r
+Till I, in Man residing, through the race, \r
+His thoughts, his looks, words, actions, all infect; \r
+And season him thy last and sweetest prey. \r
+This said, they both betook them several ways, \r
+Both to destroy, or unimmortal make \r
+All kinds, and for destruction to mature \r
+Sooner or later; which the Almighty seeing, \r
+From his transcendent seat the Saints among, \r
+To those bright Orders uttered thus his voice. \r
+See, with what heat these dogs of Hell advance \r
+To waste and havock yonder world, which I \r
+So fair and good created; and had still \r
+Kept in that state, had not the folly of Man \r
+Let in these wasteful furies, who impute \r
+Folly to me; so doth the Prince of Hell \r
+And his adherents, that with so much ease \r
+I suffer them to enter and possess \r
+A place so heavenly; and, conniving, seem \r
+To gratify my scornful enemies, \r
+That laugh, as if, transported with some fit \r
+Of passion, I to them had quitted all, \r
+At random yielded up to their misrule; \r
+And know not that I called, and drew them thither, \r
+My Hell-hounds, to lick up the draff and filth \r
+Which Man's polluting sin with taint hath shed \r
+On what was pure; til, crammed and gorged, nigh burst \r
+With sucked and glutted offal, at one sling \r
+Of thy victorious arm, well-pleasing Son, \r
+Both Sin, and Death, and yawning Grave, at last, \r
+Through Chaos hurled, obstruct the mouth of Hell \r
+For ever, and seal up his ravenous jaws. \r
+Then Heaven and Earth renewed shall be made pure \r
+To sanctity, that shall receive no stain: \r
+Till then, the curse pronounced on both precedes. \r
+He ended, and the heavenly audience loud \r
+Sung Halleluiah, as the sound of seas, \r
+Through multitude that sung:  Just are thy ways, \r
+Righteous are thy decrees on all thy works; \r
+Who can extenuate thee?  Next, to the Son, \r
+Destined Restorer of mankind, by whom \r
+New Heaven and Earth shall to the ages rise, \r
+Or down from Heaven descend.--Such was their song; \r
+While the Creator, calling forth by name \r
+His mighty Angels, gave them several charge, \r
+As sorted best with present things.  The sun \r
+Had first his precept so to move, so shine, \r
+As might affect the earth with cold and heat \r
+Scarce tolerable; and from the north to call \r
+Decrepit winter; from the south to bring \r
+Solstitial summer's heat.  To the blanc moon \r
+Her office they prescribed; to the other five \r
+Their planetary motions, and aspects, \r
+In sextile, square, and trine, and opposite, \r
+Of noxious efficacy, and when to join \r
+In synod unbenign; and taught the fixed \r
+Their influence malignant when to shower, \r
+Which of them rising with the sun, or falling, \r
+Should prove tempestuous:  To the winds they set \r
+Their corners, when with bluster to confound \r
+Sea, air, and shore; the thunder when to roll \r
+With terrour through the dark aereal hall. \r
+Some say, he bid his Angels turn ascanse \r
+The poles of earth, twice ten degrees and more, \r
+From the sun's axle; they with labour pushed \r
+Oblique the centrick globe:  Some say, the sun \r
+Was bid turn reins from the equinoctial road \r
+Like distant breadth to Taurus with the seven \r
+Atlantick Sisters, and the Spartan Twins, \r
+Up to the Tropick Crab: thence down amain \r
+By Leo, and the Virgin, and the Scales, \r
+As deep as Capricorn; to bring in change \r
+Of seasons to each clime; else had the spring \r
+Perpetual smiled on earth with vernant flowers, \r
+Equal in days and nights, except to those \r
+Beyond the polar circles; to them day \r
+Had unbenighted shone, while the low sun, \r
+To recompense his distance, in their sight \r
+Had rounded still the horizon, and not known \r
+Or east or west; which had forbid the snow \r
+From cold Estotiland, and south as far \r
+Beneath Magellan.  At that tasted fruit \r
+The sun, as from Thyestean banquet, turned \r
+His course intended; else, how had the world \r
+Inhabited, though sinless, more than now, \r
+Avoided pinching cold and scorching heat? \r
+These changes in the Heavens, though slow, produced \r
+Like change on sea and land; sideral blast, \r
+Vapour, and mist, and exhalation hot, \r
+Corrupt and pestilent:  Now from the north \r
+Of Norumbega, and the Samoed shore, \r
+Bursting their brazen dungeon, armed with ice, \r
+And snow, and hail, and stormy gust and flaw, \r
+Boreas, and Caecias, and Argestes loud, \r
+And Thrascias, rend the woods, and seas upturn; \r
+With adverse blast upturns them from the south \r
+Notus, and Afer black with thunderous clouds \r
+From Serraliona; thwart of these, as fierce, \r
+Forth rush the Levant and the Ponent winds, \r
+Eurus and Zephyr, with their lateral noise, \r
+Sirocco and Libecchio.  Thus began \r
+Outrage from lifeless things; but Discord first, \r
+Daughter of Sin, among the irrational \r
+Death introduced, through fierce antipathy: \r
+Beast now with beast 'gan war, and fowl with fowl, \r
+And fish with fish; to graze the herb all leaving, \r
+Devoured each other; nor stood much in awe \r
+Of Man, but fled him; or, with countenance grim, \r
+Glared on him passing.  These were from without \r
+The growing miseries, which Adam saw \r
+Already in part, though hid in gloomiest shade, \r
+To sorrow abandoned, but worse felt within; \r
+And, in a troubled sea of passion tost, \r
+Thus to disburden sought with sad complaint. \r
+O miserable of happy!  Is this the end \r
+Of this new glorious world, and me so late \r
+The glory of that glory, who now become \r
+Accursed, of blessed? hide me from the face \r
+Of God, whom to behold was then my highth \r
+Of happiness!--Yet well, if here would end \r
+The misery; I deserved it, and would bear \r
+My own deservings; but this will not serve: \r
+All that I eat or drink, or shall beget, \r
+Is propagated curse.  O voice, once heard \r
+Delightfully, Encrease and multiply; \r
+Now death to hear! for what can I encrease, \r
+Or multiply, but curses on my head? \r
+Who of all ages to succeed, but, feeling \r
+The evil on him brought by me, will curse \r
+My head?  Ill fare our ancestor impure, \r
+For this we may thank Adam! but his thanks \r
+Shall be the execration: so, besides \r
+Mine own that bide upon me, all from me \r
+Shall with a fierce reflux on me rebound; \r
+On me, as on their natural center, light \r
+Heavy, though in their place.  O fleeting joys \r
+Of Paradise, dear bought with lasting woes! \r
+Did I request thee, Maker, from my clay \r
+To mould me Man? did I solicit thee \r
+From darkness to promote me, or here place \r
+In this delicious garden?  As my will \r
+Concurred not to my being, it were but right \r
+And equal to reduce me to my dust; \r
+Desirous to resign and render back \r
+All I received; unable to perform \r
+Thy terms too hard, by which I was to hold \r
+The good I sought not.  To the loss of that, \r
+Sufficient penalty, why hast thou added \r
+The sense of endless woes?  Inexplicable \r
+Why am I mocked with death, and lengthened out \r
+To deathless pain?  How gladly would I meet \r
+Mortality my sentence, and be earth \r
+Insensible!  How glad would lay me down \r
+As in my mother's lap!  There I should rest, \r
+And sleep secure; his dreadful voice no more \r
+Would thunder in my ears; no fear of worse \r
+To me, and to my offspring, would torment me \r
+With cruel expectation.  Yet one doubt \r
+Pursues me still, lest all I cannot die; \r
+Lest that pure breath of life, the spirit of Man \r
+Which God inspired, cannot together perish \r
+With this corporeal clod; then, in the grave, \r
+Or in some other dismal place, who knows \r
+But I shall die a living death?  O thought \r
+Horrid, if true!  Yet why? It was but breath \r
+Of life that sinned; what dies but what had life \r
+And sin?  The body properly had neither, \r
+All of me then shall die: let this appease \r
+The doubt, since human reach no further knows. \r
+For though the Lord of all be infinite, \r
+Is his wrath also?  Be it, Man is not so, \r
+But mortal doomed.  How can he exercise \r
+Wrath without end on Man, whom death must end? \r
+Can he make deathless death?  That were to make \r
+Strange contradiction, which to God himself \r
+Impossible is held; as argument \r
+Of weakness, not of power.  Will he draw out, \r
+For anger's sake, finite to infinite, \r
+In punished Man, to satisfy his rigour, \r
+Satisfied never?  That were to extend \r
+His sentence beyond dust and Nature's law; \r
+By which all causes else, according still \r
+To the reception of their matter, act; \r
+Not to the extent of their own sphere.  But say \r
+That death be not one stroke, as I supposed, \r
+Bereaving sense, but endless misery \r
+From this day onward; which I feel begun \r
+Both in me, and without me; and so last \r
+To perpetuity;--Ay me!that fear \r
+Comes thundering back with dreadful revolution \r
+On my defenceless head; both Death and I \r
+Am found eternal, and incorporate both; \r
+Nor I on my part single; in me all \r
+Posterity stands cursed:  Fair patrimony \r
+That I must leave ye, Sons!  O, were I able \r
+To waste it all myself, and leave ye none! \r
+So disinherited, how would you bless \r
+Me, now your curse!  Ah, why should all mankind, \r
+For one man's fault, thus guiltless be condemned, \r
+It guiltless?  But from me what can proceed, \r
+But all corrupt; both mind and will depraved \r
+Not to do only, but to will the same \r
+With me?  How can they then acquitted stand \r
+In sight of God?  Him, after all disputes, \r
+Forced I absolve: all my evasions vain, \r
+And reasonings, though through mazes, lead me still \r
+But to my own conviction: first and last \r
+On me, me only, as the source and spring \r
+Of all corruption, all the blame lights due; \r
+So might the wrath!  Fond wish!couldst thou support \r
+That burden, heavier than the earth to bear; \r
+Than all the world much heavier, though divided \r
+With that bad Woman?  Thus, what thou desirest, \r
+And what thou fearest, alike destroys all hope \r
+Of refuge, and concludes thee miserable \r
+Beyond all past example and future; \r
+To Satan only like both crime and doom. \r
+O Conscience! into what abyss of fears \r
+And horrours hast thou driven me; out of which \r
+I find no way, from deep to deeper plunged! \r
+Thus Adam to himself lamented loud, \r
+Through the still night; not now, as ere Man fell, \r
+Wholesome, and cool, and mild, but with black air \r
+Accompanied; with damps, and dreadful gloom; \r
+Which to his evil conscience represented \r
+All things with double terrour:  On the ground \r
+Outstretched he lay, on the cold ground; and oft \r
+Cursed his creation;  Death as oft accused \r
+Of tardy execution, since denounced \r
+The day of his offence.  Why comes not Death, \r
+Said he, with one thrice-acceptable stroke \r
+To end me?  Shall Truth fail to keep her word, \r
+Justice Divine not hasten to be just? \r
+But Death comes not at call; Justice Divine \r
+Mends not her slowest pace for prayers or cries, \r
+O woods, O fountains, hillocks, dales, and bowers! \r
+With other echo late I taught your shades \r
+To answer, and resound far other song.-- \r
+Whom thus afflicted when sad Eve beheld, \r
+Desolate where she sat, approaching nigh, \r
+Soft words to his fierce passion she assayed: \r
+But her with stern regard he thus repelled. \r
+Out of my sight, thou Serpent!  That name best \r
+Befits thee with him leagued, thyself as false \r
+And hateful; nothing wants, but that thy shape, \r
+Like his, and colour serpentine, may show \r
+Thy inward fraud; to warn all creatures from thee \r
+Henceforth; lest that too heavenly form, pretended \r
+To hellish falshood, snare them!  But for thee \r
+I had persisted happy; had not thy pride \r
+And wandering vanity, when least was safe, \r
+Rejected my forewarning, and disdained \r
+Not to be trusted; longing to be seen, \r
+Though by the Devil himself; him overweening \r
+To over-reach; but, with the serpent meeting, \r
+Fooled and beguiled; by him thou, I by thee \r
+To trust thee from my side; imagined wise, \r
+Constant, mature, proof against all assaults; \r
+And understood not all was but a show, \r
+Rather than solid virtue; all but a rib \r
+Crooked by nature, bent, as now appears, \r
+More to the part sinister, from me drawn; \r
+Well if thrown out, as supernumerary \r
+To my just number found.  O! why did God, \r
+Creator wise, that peopled highest Heaven \r
+With Spirits masculine, create at last \r
+This novelty on earth, this fair defect \r
+Of nature, and not fill the world at once \r
+With Men, as Angels, without feminine; \r
+Or find some other way to generate \r
+Mankind?  This mischief had not been befallen, \r
+And more that shall befall; innumerable \r
+Disturbances on earth through female snares, \r
+And strait conjunction with this sex: for either \r
+He never shall find out fit mate, but such \r
+As some misfortune brings him, or mistake; \r
+Or whom he wishes most shall seldom gain \r
+Through her perverseness, but shall see her gained \r
+By a far worse; or, if she love, withheld \r
+By parents; or his happiest choice too late \r
+Shall meet, already linked and wedlock-bound \r
+To a fell adversary, his hate or shame: \r
+Which infinite calamity shall cause \r
+To human life, and houshold peace confound. \r
+He added not, and from her turned; but Eve, \r
+Not so repulsed, with tears that ceased not flowing \r
+And tresses all disordered, at his feet \r
+Fell humble; and, embracing them, besought \r
+His peace, and thus proceeded in her plaint. \r
+Forsake me not thus, Adam! witness Heaven \r
+What love sincere, and reverence in my heart \r
+I bear thee, and unweeting have offended, \r
+Unhappily deceived!  Thy suppliant \r
+I beg, and clasp thy knees; bereave me not, \r
+Whereon I live, thy gentle looks, thy aid, \r
+Thy counsel, in this uttermost distress, \r
+My only strength and stay:  Forlorn of thee, \r
+Whither shall I betake me, where subsist? \r
+While yet we live, scarce one short hour perhaps, \r
+Between us two let there be peace; both joining, \r
+As joined in injuries, one enmity \r
+Against a foe by doom express assigned us, \r
+That cruel Serpent:  On me exercise not \r
+Thy hatred for this misery befallen; \r
+On me already lost, me than thyself \r
+More miserable!  Both have sinned;but thou \r
+Against God only; I against God and thee; \r
+And to the place of judgement will return, \r
+There with my cries importune Heaven; that all \r
+The sentence, from thy head removed, may light \r
+On me, sole cause to thee of all this woe; \r
+Me, me only, just object of his ire! \r
+She ended weeping; and her lowly plight, \r
+Immoveable, till peace obtained from fault \r
+Acknowledged and deplored, in Adam wrought \r
+Commiseration:  Soon his heart relented \r
+Towards her, his life so late, and sole delight, \r
+Now at his feet submissive in distress; \r
+Creature so fair his reconcilement seeking, \r
+His counsel, whom she had displeased, his aid: \r
+As one disarmed, his anger all he lost, \r
+And thus with peaceful words upraised her soon. \r
+Unwary, and too desirous, as before, \r
+So now of what thou knowest not, who desirest \r
+The punishment all on thyself; alas! \r
+Bear thine own first, ill able to sustain \r
+His full wrath, whose thou feelest as yet least part, \r
+And my displeasure bearest so ill.  If prayers \r
+Could alter high decrees, I to that place \r
+Would speed before thee, and be louder heard, \r
+That on my head all might be visited; \r
+Thy frailty and infirmer sex forgiven, \r
+To me committed, and by me exposed. \r
+But rise;--let us no more contend, nor blame \r
+Each other, blamed enough elsewhere; but strive \r
+In offices of love, how we may lighten \r
+Each other's burden, in our share of woe; \r
+Since this day's death denounced, if aught I see, \r
+Will prove no sudden, but a slow-paced evil; \r
+A long day's dying, to augment our pain; \r
+And to our seed (O hapless seed!) derived. \r
+To whom thus Eve, recovering heart, replied. \r
+Adam, by sad experiment I know \r
+How little weight my words with thee can find, \r
+Found so erroneous; thence by just event \r
+Found so unfortunate:  Nevertheless, \r
+Restored by thee, vile as I am, to place \r
+Of new acceptance, hopeful to regain \r
+Thy love, the sole contentment of my heart \r
+Living or dying, from thee I will not hide \r
+What thoughts in my unquiet breast are risen, \r
+Tending to some relief of our extremes, \r
+Or end; though sharp and sad, yet tolerable, \r
+As in our evils, and of easier choice. \r
+If care of our descent perplex us most, \r
+Which must be born to certain woe, devoured \r
+By Death at last; and miserable it is \r
+To be to others cause of misery, \r
+Our own begotten, and of our loins to bring \r
+Into this cursed world a woeful race, \r
+That after wretched life must be at last \r
+Food for so foul a monster; in thy power \r
+It lies, yet ere conception to prevent \r
+The race unblest, to being yet unbegot. \r
+Childless thou art, childless remain: so Death \r
+Shall be deceived his glut, and with us two \r
+Be forced to satisfy his ravenous maw. \r
+But if thou judge it hard and difficult, \r
+Conversing, looking, loving, to abstain \r
+From love's due rights, nuptial embraces sweet; \r
+And with desire to languish without hope, \r
+Before the present object languishing \r
+With like desire; which would be misery \r
+And torment less than none of what we dread; \r
+Then, both ourselves and seed at once to free \r
+From what we fear for both, let us make short, -- \r
+Let us seek Death; -- or, he not found, supply \r
+With our own hands his office on ourselves: \r
+Why stand we longer shivering under fears, \r
+That show no end but death, and have the power, \r
+Of many ways to die the shortest choosing, \r
+Destruction with destruction to destroy? -- \r
+She ended here, or vehement despair \r
+Broke off the rest: so much of death her thoughts \r
+Had entertained, as dyed her cheeks with pale. \r
+But Adam, with such counsel nothing swayed, \r
+To better hopes his more attentive mind \r
+Labouring had raised; and thus to Eve replied. \r
+Eve, thy contempt of life and pleasure seems \r
+To argue in thee something more sublime \r
+And excellent, than what thy mind contemns; \r
+But self-destruction therefore sought, refutes \r
+That excellence thought in thee; and implies, \r
+Not thy contempt, but anguish and regret \r
+For loss of life and pleasure overloved. \r
+Or if thou covet death, as utmost end \r
+Of misery, so thinking to evade \r
+The penalty pronounced; doubt not but God \r
+Hath wiselier armed his vengeful ire, than so \r
+To be forestalled; much more I fear lest death, \r
+So snatched, will not exempt us from the pain \r
+We are by doom to pay; rather, such acts \r
+Of contumacy will provoke the Highest \r
+To make death in us live:  Then let us seek \r
+Some safer resolution, which methinks \r
+I have in view, calling to mind with heed \r
+Part of our sentence, that thy seed shall bruise \r
+The Serpent's head; piteous amends! unless \r
+Be meant, whom I conjecture, our grand foe, \r
+Satan; who, in the serpent, hath contrived \r
+Against us this deceit:  To crush his head \r
+Would be revenge indeed! which will be lost \r
+By death brought on ourselves, or childless days \r
+Resolved, as thou proposest; so our foe \r
+Shal 'scape his punishment ordained, and we \r
+Instead shall double ours upon our heads. \r
+No more be mentioned then of violence \r
+Against ourselves; and wilful barrenness, \r
+That cuts us off from hope; and savours only \r
+Rancour and pride, impatience and despite, \r
+Reluctance against God and his just yoke \r
+Laid on our necks.  Remember with what mild \r
+And gracious temper he both heard, and judged, \r
+Without wrath or reviling; we expected \r
+Immediate dissolution, which we thought \r
+Was meant by death that day; when lo!to thee \r
+Pains only in child-bearing were foretold, \r
+And bringing forth; soon recompensed with joy, \r
+Fruit of thy womb:  On me the curse aslope \r
+Glanced on the ground; with labour I must earn \r
+My bread; what harm? Idleness had been worse; \r
+My labour will sustain me; and, lest cold \r
+Or heat should injure us, his timely care \r
+Hath, unbesought, provided; and his hands \r
+Clothed us unworthy, pitying while he judged; \r
+How much more, if we pray him, will his ear \r
+Be open, and his heart to pity incline, \r
+And teach us further by what means to shun \r
+The inclement seasons, rain, ice, hail, and snow! \r
+Which now the sky, with various face, begins \r
+To show us in this mountain; while the winds \r
+Blow moist and keen, shattering the graceful locks \r
+Of these fair spreading trees; which bids us seek \r
+Some better shroud, some better warmth to cherish \r
+Our limbs benummed, ere this diurnal star \r
+Leave cold the night, how we his gathered beams \r
+Reflected may with matter sere foment; \r
+Or, by collision of two bodies, grind \r
+The air attrite to fire; as late the clouds \r
+Justling, or pushed with winds, rude in their shock, \r
+Tine the slant lightning; whose thwart flame, driven down \r
+Kindles the gummy bark of fir or pine; \r
+And sends a comfortable heat from far, \r
+Which might supply the sun:  Such fire to use, \r
+And what may else be remedy or cure \r
+To evils which our own misdeeds have wrought, \r
+He will instruct us praying, and of grace \r
+Beseeching him; so as we need not fear \r
+To pass commodiously this life, sustained \r
+By him with many comforts, till we end \r
+In dust, our final rest and native home. \r
+What better can we do, than, to the place \r
+Repairing where he judged us, prostrate fall \r
+Before him reverent; and there confess \r
+Humbly our faults, and pardon beg; with tears \r
+Watering the ground, and with our sighs the air \r
+Frequenting, sent from hearts contrite, in sign \r
+Of sorrow unfeigned, and humiliation meek \r
\r
\r
\r
+Book XI                                                          \r
\r
\r
+Undoubtedly he will relent, and turn \r
+From his displeasure; in whose look serene, \r
+When angry most he seemed and most severe, \r
+What else but favour, grace, and mercy, shone? \r
+So spake our father penitent; nor Eve \r
+Felt less remorse: they, forthwith to the place \r
+Repairing where he judged them, prostrate fell \r
+Before him reverent; and both confessed \r
+Humbly their faults, and pardon begged; with tears \r
+Watering the ground, and with their sighs the air \r
+Frequenting, sent from hearts contrite, in sign \r
+Of sorrow unfeigned, and humiliation meek. \r
+Thus they, in lowliest plight, repentant stood \r
+Praying; for from the mercy-seat above \r
+Prevenient grace descending had removed \r
+The stony from their hearts, and made new flesh \r
+Regenerate grow instead; that sighs now breathed \r
+Unutterable; which the Spirit of prayer \r
+Inspired, and winged for Heaven with speedier flight \r
+Than loudest oratory:  Yet their port \r
+Not of mean suitors; nor important less \r
+Seemed their petition, than when the ancient pair \r
+In fables old, less ancient yet than these, \r
+Deucalion and chaste Pyrrha, to restore \r
+The race of mankind drowned, before the shrine \r
+Of Themis stood devout.  To Heaven their prayers \r
+Flew up, nor missed the way, by envious winds \r
+Blown vagabond or frustrate: in they passed \r
+Dimensionless through heavenly doors; then clad \r
+With incense, where the golden altar fumed, \r
+By their great intercessour, came in sight \r
+Before the Father's throne: them the glad Son \r
+Presenting, thus to intercede began. \r
+See$ Father, what first-fruits on earth are sprung \r
+From thy implanted grace in Man; these sighs \r
+And prayers, which in this golden censer mixed \r
+With incense, I thy priest before thee bring; \r
+Fruits of more pleasing savour, from thy seed \r
+Sown with contrition in his heart, than those \r
+Which, his own hand manuring, all the trees \r
+Of Paradise could have produced, ere fallen \r
+From innocence.  Now therefore, bend thine ear \r
+To supplication; hear his sighs, though mute; \r
+Unskilful with what words to pray, let me \r
+Interpret for him; me, his advocate \r
+And propitiation; all his works on me, \r
+Good, or not good, ingraft; my merit those \r
+Shall perfect, and for these my death shall pay. \r
+Accept me; and, in me, from these receive \r
+The smell of peace toward mankind: let him live \r
+Before thee reconciled, at least his days \r
+Numbered, though sad; till death, his doom, (which I \r
+To mitigate thus plead, not to reverse,) \r
+To better life shall yield him: where with me \r
+All my redeemed may dwell in joy and bliss; \r
+Made one with me, as I with thee am one. \r
+To whom the Father, without cloud, serene. \r
+All thy request for Man, accepted Son, \r
+Obtain; all thy request was my decree: \r
+But, longer in that Paradise to dwell, \r
+The law I gave to Nature him forbids: \r
+Those pure immortal elements, that know, \r
+No gross, no unharmonious mixture foul, \r
+Eject him, tainted now; and purge him off, \r
+As a distemper, gross, to air as gross, \r
+And mortal food; as may dispose him best \r
+For dissolution wrought by sin, that first \r
+Distempered all things, and of incorrupt \r
+Corrupted.  I, at first, with two fair gifts \r
+Created him endowed; with happiness, \r
+And immortality: that fondly lost, \r
+This other served but to eternize woe; \r
+Till I provided death: so death becomes \r
+His final remedy; and, after life, \r
+Tried in sharp tribulation, and refined \r
+By faith and faithful works, to second life, \r
+Waked in the renovation of the just, \r
+Resigns him up with Heaven and Earth renewed. \r
+But let us call to synod all the Blest, \r
+Through Heaven's wide bounds: from them I will not hide \r
+My judgements; how with mankind I proceed, \r
+As how with peccant Angels late they saw, \r
+And in their state, though firm, stood more confirmed. \r
+He ended, and the Son gave signal high \r
+To the bright minister that watched; he blew \r
+His trumpet, heard in Oreb since perhaps \r
+When God descended, and perhaps once more \r
+To sound at general doom.  The angelick blast \r
+Filled all the regions: from their blisful bowers \r
+Of amarantine shade, fountain or spring, \r
+By the waters of life, where'er they sat \r
+In fellowships of joy, the sons of light \r
+Hasted, resorting to the summons high; \r
+And took their seats; till from his throne supreme \r
+The Almighty thus pronounced his sovran will. \r
+O Sons, like one of us Man is become \r
+To know both good and evil, since his taste \r
+Of that defended fruit; but let him boast \r
+His knowledge of good lost, and evil got; \r
+Happier! had it sufficed him to have known \r
+Good by itself, and evil not at all. \r
+He sorrows now, repents, and prays contrite, \r
+My motions in him; longer than they move, \r
+His heart I know, how variable and vain, \r
+Self-left.  Lest therefore his now bolder hand \r
+Reach also of the tree of life, and eat, \r
+And live for ever, dream at least to live \r
+For ever, to remove him I decree, \r
+And send him from the garden forth to till \r
+The ground whence he was taken, fitter soil. \r
+Michael, this my behest have thou in charge; \r
+Take to thee from among the Cherubim \r
+Thy choice of flaming warriours, lest the Fiend, \r
+Or in behalf of Man, or to invade \r
+Vacant possession, some new trouble raise: \r
+Haste thee, and from the Paradise of God \r
+Without remorse drive out the sinful pair; \r
+From hallowed ground the unholy; and denounce \r
+To them, and to their progeny, from thence \r
+Perpetual banishment.  Yet, lest they faint \r
+At the sad sentence rigorously urged, \r
+(For I behold them softened, and with tears \r
+Bewailing their excess,) all terrour hide. \r
+If patiently thy bidding they obey, \r
+Dismiss them not disconsolate; reveal \r
+To Adam what shall come in future days, \r
+As I shall thee enlighten; intermix \r
+My covenant in the Woman's seed renewed; \r
+So send them forth, though sorrowing, yet in peace: \r
+And on the east side of the garden place, \r
+Where entrance up from Eden easiest climbs, \r
+Cherubick watch; and of a sword the flame \r
+Wide-waving; all approach far off to fright, \r
+And guard all passage to the tree of life: \r
+Lest Paradise a receptacle prove \r
+To Spirits foul, and all my trees their prey; \r
+With whose stolen fruit Man once more to delude. \r
+He ceased; and the arch-angelick Power prepared \r
+For swift descent; with him the cohort bright \r
+Of watchful Cherubim: four faces each \r
+Had, like a double Janus; all their shape \r
+Spangled with eyes more numerous than those \r
+Of Argus, and more wakeful than to drouse, \r
+Charmed with Arcadian pipe, the pastoral reed \r
+Of Hermes, or his opiate rod.  Mean while, \r
+To re-salute the world with sacred light, \r
+Leucothea waked; and with fresh dews imbalmed \r
+The earth; when Adam and first matron Eve \r
+Had ended now their orisons, and found \r
+Strength added from above; new hope to spring \r
+Out of despair; joy, but with fear yet linked; \r
+Which thus to Eve his welcome words renewed. \r
+Eve, easily my faith admit, that all \r
+The good which we enjoy from Heaven descends; \r
+But, that from us aught should ascend to Heaven \r
+So prevalent as to concern the mind \r
+Of God high-blest, or to incline his will, \r
+Hard to belief may seem; yet this will prayer \r
+Or one short sigh of human breath, upborne \r
+Even to the seat of God.  For since I sought \r
+By prayer the offended Deity to appease; \r
+Kneeled, and before him humbled all my heart; \r
+Methought I saw him placable and mild, \r
+Bending his ear; persuasion in me grew \r
+That I was heard with favour; peace returned \r
+Home to my breast, and to my memory \r
+His promise, that thy seed shall bruise our foe; \r
+Which, then not minded in dismay, yet now \r
+Assures me that the bitterness of death \r
+Is past, and we shall live.  Whence hail to thee, \r
+Eve rightly called, mother of all mankind, \r
+Mother of all things living, since by thee \r
+Man is to live; and all things live for Man. \r
+To whom thus Eve with sad demeanour meek. \r
+Ill-worthy I such title should belong \r
+To me transgressour; who, for thee ordained \r
+A help, became thy snare; to me reproach \r
+Rather belongs, distrust, and all dispraise: \r
+But infinite in pardon was my Judge, \r
+That I, who first brought death on all, am graced \r
+The source of life; next favourable thou, \r
+Who highly thus to entitle me vouchsaf'st, \r
+Far other name deserving.  But the field \r
+To labour calls us, now with sweat imposed, \r
+Though after sleepless night; for see!the morn, \r
+All unconcerned with our unrest, begins \r
+Her rosy progress smiling: let us forth; \r
+I never from thy side henceforth to stray, \r
+Where'er our day's work lies, though now enjoined \r
+Laborious, till day droop; while here we dwell, \r
+What can be toilsome in these pleasant walks? \r
+Here let us live, though in fallen state, content. \r
+So spake, so wished much humbled Eve; but Fate \r
+Subscribed not:  Nature first gave signs, impressed \r
+On bird, beast, air; air suddenly eclipsed, \r
+After short blush of morn; nigh in her sight \r
+The bird of Jove, stooped from his aery tour, \r
+Two birds of gayest plume before him drove; \r
+Down from a hill the beast that reigns in woods, \r
+First hunter then, pursued a gentle brace, \r
+Goodliest of all the forest, hart and hind; \r
+Direct to the eastern gate was bent their flight. \r
+Adam observed, and with his eye the chase \r
+Pursuing, not unmoved, to Eve thus spake. \r
+O Eve, some further change awaits us nigh, \r
+Which Heaven, by these mute signs in Nature, shows \r
+Forerunners of his purpose; or to warn \r
+Us, haply too secure, of our discharge \r
+From penalty, because from death released \r
+Some days: how long, and what till then our life, \r
+Who knows? or more than this, that we are dust, \r
+And thither must return, and be no more? \r
+Why else this double object in our sight \r
+Of flight pursued in the air, and o'er the ground, \r
+One way the self-same hour? why in the east \r
+Darkness ere day's mid-course, and morning-light \r
+More orient in yon western cloud, that draws \r
+O'er the blue firmament a radiant white, \r
+And slow descends with something heavenly fraught? \r
+He erred not; for by this the heavenly bands \r
+Down from a sky of jasper lighted now \r
+In Paradise, and on a hill made halt; \r
+A glorious apparition, had not doubt \r
+And carnal fear that day dimmed Adam's eye. \r
+Not that more glorious, when the Angels met \r
+Jacob in Mahanaim, where he saw \r
+The field pavilioned with his guardians bright; \r
+Nor that, which on the flaming mount appeared \r
+In Dothan, covered with a camp of fire, \r
+Against the Syrian king, who to surprise \r
+One man, assassin-like, had levied war, \r
+War unproclaimed.  The princely Hierarch \r
+In their bright stand there left his Powers, to seise \r
+Possession of the garden; he alone, \r
+To find where Adam sheltered, took his way, \r
+Not unperceived of Adam; who to Eve, \r
+While the great visitant approached, thus spake. \r
+Eve$ now expect great tidings, which perhaps \r
+Of us will soon determine, or impose \r
+New laws to be observed; for I descry, \r
+From yonder blazing cloud that veils the hill, \r
+One of the heavenly host; and, by his gait, \r
+None of the meanest; some great Potentate \r
+Or of the Thrones above; such majesty \r
+Invests him coming! yet not terrible, \r
+That I should fear; nor sociably mild, \r
+As Raphael, that I should much confide; \r
+But solemn and sublime; whom not to offend, \r
+With reverence I must meet, and thou retire. \r
+He ended: and the Arch-Angel soon drew nigh, \r
+Not in his shape celestial, but as man \r
+Clad to meet man; over his lucid arms \r
+A military vest of purple flowed, \r
+Livelier than Meliboean, or the grain \r
+Of Sarra, worn by kings and heroes old \r
+In time of truce; Iris had dipt the woof; \r
+His starry helm unbuckled showed him prime \r
+In manhood where youth ended; by his side, \r
+As in a glistering zodiack, hung the sword, \r
+Satan's dire dread; and in his hand the spear. \r
+Adam bowed low; he, kingly, from his state \r
+Inclined not, but his coming thus declared. \r
+Adam, Heaven's high behest no preface needs: \r
+Sufficient that thy prayers are heard; and Death, \r
+Then due by sentence when thou didst transgress, \r
+Defeated of his seisure many days \r
+Given thee of grace; wherein thou mayest repent, \r
+And one bad act with many deeds well done \r
+Mayest cover:  Well may then thy Lord, appeased, \r
+Redeem thee quite from Death's rapacious claim; \r
+But longer in this Paradise to dwell \r
+Permits not: to remove thee I am come, \r
+And send thee from the garden forth to till \r
+The ground whence thou wast taken, fitter soil. \r
+He added not; for Adam at the news \r
+Heart-struck with chilling gripe of sorrow stood, \r
+That all his senses bound; Eve, who unseen \r
+Yet all had heard, with audible lament \r
+Discovered soon the place of her retire. \r
+O unexpected stroke, worse than of Death! \r
+Must I thus leave thee$ Paradise? thus leave \r
+Thee, native soil! these happy walks and shades, \r
+Fit haunt of Gods? where I had hope to spend, \r
+Quiet though sad, the respite of that day \r
+That must be mortal to us both.  O flowers, \r
+That never will in other climate grow, \r
+My early visitation, and my last \r
+ ;t even, which I bred up with tender hand \r
+From the first opening bud, and gave ye names! \r
+Who now shall rear ye to the sun, or rank \r
+Your tribes, and water from the ambrosial fount? \r
+Thee lastly, nuptial bower! by me adorned \r
+With what to sight or smell was sweet! from thee \r
+How shall I part, and whither wander down \r
+Into a lower world; to this obscure \r
+And wild? how shall we breathe in other air \r
+Less pure, accustomed to immortal fruits? \r
+Whom thus the Angel interrupted mild. \r
+Lament not, Eve, but patiently resign \r
+What justly thou hast lost, nor set thy heart, \r
+Thus over-fond, on that which is not thine: \r
+Thy going is not lonely; with thee goes \r
+Thy husband; whom to follow thou art bound; \r
+Where he abides, think there thy native soil. \r
+Adam, by this from the cold sudden damp \r
+Recovering, and his scattered spirits returned, \r
+To Michael thus his humble words addressed. \r
+Celestial, whether among the Thrones, or named \r
+Of them the highest; for such of shape may seem \r
+Prince above princes! gently hast thou told \r
+Thy message, which might else in telling wound, \r
+And in performing end us; what besides \r
+Of sorrow, and dejection, and despair, \r
+Our frailty can sustain, thy tidings bring, \r
+Departure from this happy place, our sweet \r
+Recess, and only consolation left \r
+Familiar to our eyes! all places else \r
+Inhospitable appear, and desolate; \r
+Nor knowing us, nor known:  And, if by prayer \r
+Incessant I could hope to change the will \r
+Of Him who all things can, I would not cease \r
+To weary him with my assiduous cries: \r
+But prayer against his absolute decree \r
+No more avails than breath against the wind, \r
+Blown stifling back on him that breathes it forth: \r
+Therefore to his great bidding I submit. \r
+This most afflicts me, that, departing hence, \r
+As from his face I shall be hid, deprived \r
+His blessed countenance:  Here I could frequent \r
+With worship place by place where he vouchsafed \r
+Presence Divine; and to my sons relate, \r
+'On this mount he appeared; under this tree \r
+'Stood visible; among these pines his voice \r
+'I heard; here with him at this fountain talked: \r
+So many grateful altars I would rear \r
+Of grassy turf, and pile up every stone \r
+Of lustre from the brook, in memory, \r
+Or monument to ages; and theron \r
+Offer sweet-smelling gums, and fruits, and flowers: \r
+In yonder nether world where shall I seek \r
+His bright appearances, or foot-step trace? \r
+For though I fled him angry, yet recalled \r
+To life prolonged and promised race, I now \r
+Gladly behold though but his utmost skirts \r
+Of glory; and far off his steps adore. \r
+To whom thus Michael with regard benign. \r
+Adam, thou knowest Heaven his, and all the Earth; \r
+Not this rock only; his Omnipresence fills \r
+Land, sea, and air, and every kind that lives, \r
+Fomented by his virtual power and warmed: \r
+All the earth he gave thee to possess and rule, \r
+No despicable gift; surmise not then \r
+His presence to these narrow bounds confined \r
+Of Paradise, or Eden: this had been \r
+Perhaps thy capital seat, from whence had spread \r
+All generations; and had hither come \r
+From all the ends of the earth, to celebrate \r
+And reverence thee, their great progenitor. \r
+But this pre-eminence thou hast lost, brought down \r
+To dwell on even ground now with thy sons: \r
+Yet doubt not but in valley, and in plain, \r
+God is, as here; and will be found alike \r
+Present; and of his presence many a sign \r
+Still following thee, still compassing thee round \r
+With goodness and paternal love, his face \r
+Express, and of his steps the track divine. \r
+Which that thou mayest believe, and be confirmed \r
+Ere thou from hence depart; know, I am sent \r
+To show thee what shall come in future days \r
+To thee, and to thy offspring: good with bad \r
+Expect to hear; supernal grace contending \r
+With sinfulness of men; thereby to learn \r
+True patience, and to temper joy with fear \r
+And pious sorrow; equally inured \r
+By moderation either state to bear, \r
+Prosperous or adverse: so shalt thou lead \r
+Safest thy life, and best prepared endure \r
+Thy mortal passage when it comes.--Ascend \r
+This hill; let Eve (for I have drenched her eyes) \r
+Here sleep below; while thou to foresight wakest; \r
+As once thou sleptst, while she to life was formed. \r
+To whom thus Adam gratefully replied. \r
+Ascend, I follow thee, safe Guide, the path \r
+Thou leadest me; and to the hand of Heaven submit, \r
+However chastening; to the evil turn \r
+My obvious breast; arming to overcome \r
+By suffering, and earn rest from labour won, \r
+If so I may attain. -- So both ascend \r
+In the visions of God.  It was a hill, \r
+Of Paradise the highest; from whose top \r
+The hemisphere of earth, in clearest ken, \r
+Stretched out to the amplest reach of prospect lay. \r
+Not higher that hill, nor wider looking round, \r
+Whereon, for different cause, the Tempter set \r
+Our second Adam, in the wilderness; \r
+To show him all Earth's kingdoms, and their glory. \r
+His eye might there command wherever stood \r
+City of old or modern fame, the seat \r
+Of mightiest empire, from the destined walls \r
+Of Cambalu, seat of Cathaian Can, \r
+And Samarchand by Oxus, Temir's throne, \r
+To Paquin of Sinaean kings; and thence \r
+To Agra and Lahor of great Mogul, \r
+Down to the golden Chersonese; or where \r
+The Persian in Ecbatan sat, or since \r
+In Hispahan; or where the Russian Ksar \r
+In Mosco; or the Sultan in Bizance, \r
+Turchestan-born; nor could his eye not ken \r
+The empire of Negus to his utmost port \r
+Ercoco, and the less maritim kings \r
+Mombaza, and Quiloa, and Melind, \r
+And Sofala, thought Ophir, to the realm \r
+Of Congo, and Angola farthest south; \r
+Or thence from Niger flood to Atlas mount \r
+The kingdoms of Almansor, Fez and Sus, \r
+Morocco, and Algiers, and Tremisen; \r
+On Europe thence, and where Rome was to sway \r
+The world: in spirit perhaps he also saw \r
+Rich Mexico, the seat of Montezume, \r
+And Cusco in Peru, the richer seat \r
+Of Atabalipa; and yet unspoiled \r
+Guiana, whose great city Geryon's sons \r
+Call El Dorado.  But to nobler sights \r
+Michael from Adam's eyes the film removed, \r
+Which that false fruit that promised clearer sight \r
+Had bred; then purged with euphrasy and rue \r
+The visual nerve, for he had much to see; \r
+And from the well of life three drops instilled. \r
+So deep the power of these ingredients pierced, \r
+Even to the inmost seat of mental sight, \r
+That Adam, now enforced to close his eyes, \r
+Sunk down, and all his spirits became entranced; \r
+But him the gentle Angel by the hand \r
+Soon raised, and his attention thus recalled. \r
+Adam, now ope thine eyes; and first behold \r
+The effects, which thy original crime hath wrought \r
+In some to spring from thee; who never touched \r
+The excepted tree; nor with the snake conspired; \r
+Nor sinned thy sin; yet from that sin derive \r
+Corruption, to bring forth more violent deeds. \r
+His eyes he opened, and beheld a field, \r
+Part arable and tilth, whereon were sheaves \r
+New reaped; the other part sheep-walks and folds; \r
+I' the midst an altar as the land-mark stood, \r
+Rustick, of grassy sord; thither anon \r
+A sweaty reaper from his tillage brought \r
+First fruits, the green ear, and the yellow sheaf, \r
+Unculled, as came to hand; a shepherd next, \r
+More meek, came with the firstlings of his flock, \r
+Choicest and best; then, sacrificing, laid \r
+The inwards and their fat, with incense strowed, \r
+On the cleft wood, and all due rights performed: \r
+His offering soon propitious fire from Heaven \r
+Consumed with nimble glance, and grateful steam; \r
+The other's not, for his was not sincere; \r
+Whereat he inly raged, and, as they talked, \r
+Smote him into the midriff with a stone \r
+That beat out life; he fell;and, deadly pale, \r
+Groaned out his soul with gushing blood effused. \r
+Much at that sight was Adam in his heart \r
+Dismayed, and thus in haste to the Angel cried. \r
+O Teacher, some great mischief hath befallen \r
+To that meek man, who well had sacrificed; \r
+Is piety thus and pure devotion paid? \r
+To whom Michael thus, he also moved, replied. \r
+These two are brethren, Adam, and to come \r
+Out of thy loins; the unjust the just hath slain, \r
+For envy that his brother's offering found \r
+From Heaven acceptance; but the bloody fact \r
+Will be avenged; and the other's faith, approved, \r
+Lose no reward; though here thou see him die, \r
+Rolling in dust and gore.  To which our sire. \r
+Alas! both for the deed, and for the cause! \r
+But have I now seen Death?  Is this the way \r
+I must return to native dust?  O sight \r
+Of terrour, foul and ugly to behold, \r
+Horrid to think, how horrible to feel! \r
+To whom thus Michael.  Death thou hast seen \r
+In his first shape on Man; but many shapes \r
+Of Death, and many are the ways that lead \r
+To his grim cave, all dismal; yet to sense \r
+More terrible at the entrance, than within. \r
+Some, as thou sawest, by violent stroke shall die; \r
+By fire, flood, famine, by intemperance more \r
+In meats and drinks, which on the earth shall bring \r
+Diseases dire, of which a monstrous crew \r
+Before thee shall appear; that thou mayest know \r
+What misery the inabstinence of Eve \r
+Shall bring on Men.  Immediately a place \r
+Before his eyes appeared, sad, noisome, dark; \r
+A lazar-house it seemed; wherein were laid \r
+Numbers of all diseased; all maladies \r
+Of ghastly spasm, or racking torture, qualms \r
+Of heart-sick agony, all feverous kinds, \r
+Convulsions, epilepsies, fierce catarrhs, \r
+Intestine stone and ulcer, colick-pangs, \r
+Demoniack phrenzy, moaping melancholy, \r
+And moon-struck madness, pining atrophy, \r
+Marasmus, and wide-wasting pestilence, \r
+Dropsies, and asthmas, and joint-racking rheums. \r
+Dire was the tossing, deep the groans; Despair \r
+Tended the sick busiest from couch to couch; \r
+And over them triumphant Death his dart \r
+Shook, but delayed to strike, though oft invoked \r
+With vows, as their chief good, and final hope. \r
+Sight so deform what heart of rock could long \r
+Dry-eyed behold?  Adam could not, but wept, \r
+Though not of woman born; compassion quelled \r
+His best of man, and gave him up to tears \r
+A space, till firmer thoughts restrained excess; \r
+And, scarce recovering words, his plaint renewed. \r
+O miserable mankind, to what fall \r
+Degraded, to what wretched state reserved! \r
+Better end here unborn.  Why is life given \r
+To be thus wrested from us? rather, why \r
+Obtruded on us thus? who, if we knew \r
+What we receive, would either no accept \r
+Life offered, or soon beg to lay it down; \r
+Glad to be so dismissed in peace.  Can thus \r
+The image of God in Man, created once \r
+So goodly and erect, though faulty since, \r
+To such unsightly sufferings be debased \r
+Under inhuman pains?  Why should not Man, \r
+Retaining still divine similitude \r
+In part, from such deformities be free, \r
+And, for his Maker's image sake, exempt? \r
+Their Maker's image, answered Michael, then \r
+Forsook them, when themselves they vilified \r
+To serve ungoverned Appetite; and took \r
+His image whom they served, a brutish vice, \r
+Inductive mainly to the sin of Eve. \r
+Therefore so abject is their punishment, \r
+Disfiguring not God's likeness, but their own; \r
+Or if his likeness, by themselves defaced; \r
+While they pervert pure Nature's healthful rules \r
+To loathsome sickness; worthily, since they \r
+God's image did not reverence in themselves. \r
+I yield it just, said Adam, and submit. \r
+But is there yet no other way, besides \r
+These painful passages, how we may come \r
+To death, and mix with our connatural dust? \r
+There is, said Michael, if thou well observe \r
+The rule of Not too much; by temperance taught, \r
+In what thou eatest and drinkest; seeking from thence \r
+Due nourishment, not gluttonous delight, \r
+Till many years over thy head return: \r
+So mayest thou live; till, like ripe fruit, thou drop \r
+Into thy mother's lap; or be with ease \r
+Gathered, nor harshly plucked; for death mature: \r
+This is Old Age; but then, thou must outlive \r
+Thy youth, thy strength, thy beauty; which will change \r
+To withered, weak, and gray; thy senses then, \r
+Obtuse, all taste of pleasure must forego, \r
+To what thou hast; and, for the air of youth, \r
+Hopeful and cheerful, in thy blood will reign \r
+A melancholy damp of cold and dry \r
+To weigh thy spirits down, and last consume \r
+The balm of life.  To whom our ancestor. \r
+Henceforth I fly not death, nor would prolong \r
+Life much; bent rather, how I may be quit, \r
+Fairest and easiest, of this cumbrous charge; \r
+Which I must keep till my appointed day \r
+Of rendering up, and patiently attend \r
+My dissolution.  Michael replied. \r
+Nor love thy life, nor hate; but what thou livest \r
+Live well; how long, or short, permit to Heaven: \r
+And now prepare thee for another sight. \r
+He looked, and saw a spacious plain, whereon \r
+Were tents of various hue; by some, were herds \r
+Of cattle grazing; others, whence the sound \r
+Of instruments, that made melodious chime, \r
+Was heard, of harp and organ; and, who moved \r
+Their stops and chords, was seen; his volant touch, \r
+Instinct through all proportions, low and high, \r
+Fled and pursued transverse the resonant fugue. \r
+In other part stood one who, at the forge \r
+Labouring, two massy clods of iron and brass \r
+Had melted, (whether found where casual fire \r
+Had wasted woods on mountain or in vale, \r
+Down to the veins of earth; thence gliding hot \r
+To some cave's mouth; or whether washed by stream \r
+From underground;) the liquid ore he drained \r
+Into fit moulds prepared; from which he formed \r
+First his own tools; then, what might else be wrought \r
+Fusil or graven in metal.  After these, \r
+But on the hither side, a different sort \r
+From the high neighbouring hills, which was their seat, \r
+Down to the plain descended; by their guise \r
+Just men they seemed, and all their study bent \r
+To worship God aright, and know his works \r
+Not hid; nor those things last, which might preserve \r
+Freedom and peace to Men; they on the plain \r
+Long had not walked, when from the tents, behold! \r
+A bevy of fair women, richly gay \r
+In gems and wanton dress; to the harp they sung \r
+Soft amorous ditties, and in dance came on: \r
+The men, though grave, eyed them; and let their eyes \r
+Rove without rein; till, in the amorous net \r
+Fast caught, they liked; and each his liking chose; \r
+And now of love they treat, till the evening-star, \r
+Love's harbinger, appeared; then, all in heat \r
+They light the nuptial torch, and bid invoke \r
+Hymen, then first to marriage rites invoked: \r
+With feast and musick all the tents resound. \r
+Such happy interview, and fair event \r
+Of love and youth not lost, songs, garlands, flowers, \r
+And charming symphonies, attached the heart \r
+Of Adam, soon inclined to admit delight, \r
+The bent of nature; which he thus expressed. \r
+True opener of mine eyes, prime Angel blest; \r
+Much better seems this vision, and more hope \r
+Of peaceful days portends, than those two past; \r
+Those were of hate and death, or pain much worse; \r
+Here Nature seems fulfilled in all her ends. \r
+To whom thus Michael.  Judge not what is best \r
+By pleasure, though to nature seeming meet; \r
+Created, as thou art, to nobler end \r
+Holy and pure, conformity divine. \r
+Those tents thou sawest so pleasant, were the tents \r
+Of wickedness, wherein shall dwell his race \r
+Who slew his brother; studious they appear \r
+Of arts that polish life, inventers rare; \r
+Unmindful of their Maker, though his Spirit \r
+Taught them; but they his gifts acknowledged none. \r
+Yet they a beauteous offspring shall beget; \r
+For that fair female troop thou sawest, that seemed \r
+Of Goddesses, so blithe, so smooth, so gay, \r
+Yet empty of all good wherein consists \r
+Woman's domestick honour and chief praise; \r
+Bred only and completed to the taste \r
+Of lustful appetence, to sing, to dance, \r
+To dress, and troll the tongue, and roll the eye: \r
+To these that sober race of men, whose lives \r
+Religious titled them the sons of God, \r
+Shall yield up all their virtue, all their fame \r
+Ignobly, to the trains and to the smiles \r
+Of these fair atheists; and now swim in joy, \r
+Erelong to swim at large; and laugh, for which \r
+The world erelong a world of tears must weep. \r
+To whom thus Adam, of short joy bereft. \r
+O pity and shame, that they, who to live well \r
+Entered so fair, should turn aside to tread \r
+Paths indirect, or in the mid way faint! \r
+But still I see the tenour of Man's woe \r
+Holds on the same, from Woman to begin. \r
+From Man's effeminate slackness it begins, \r
+Said the Angel, who should better hold his place \r
+By wisdom, and superiour gifts received. \r
+But now prepare thee for another scene. \r
+He looked, and saw wide territory spread \r
+Before him, towns, and rural works between; \r
+Cities of men with lofty gates and towers, \r
+Concourse in arms, fierce faces threatening war, \r
+Giants of mighty bone and bold emprise; \r
+Part wield their arms, part curb the foaming steed, \r
+Single or in array of battle ranged \r
+Both horse and foot, nor idly mustering stood; \r
+One way a band select from forage drives \r
+A herd of beeves, fair oxen and fair kine, \r
+From a fat meadow ground; or fleecy flock, \r
+Ewes and their bleating lambs over the plain, \r
+Their booty; scarce with life the shepherds fly, \r
+But call in aid, which makes a bloody fray; \r
+With cruel tournament the squadrons join; \r
+Where cattle pastured late, now scattered lies \r
+With carcasses and arms the ensanguined field, \r
+Deserted:  Others to a city strong \r
+Lay siege, encamped; by battery, scale, and mine, \r
+Assaulting; others from the wall defend \r
+With dart and javelin, stones, and sulphurous fire; \r
+On each hand slaughter, and gigantick deeds. \r
+In other part the sceptered heralds call \r
+To council, in the city-gates; anon \r
+Gray-headed men and grave, with warriours mixed, \r
+Assemble, and harangues are heard; but soon, \r
+In factious opposition; till at last, \r
+Of middle age one rising, eminent \r
+In wise deport, spake much of right and wrong, \r
+Of justice, or religion, truth, and peace, \r
+And judgement from above: him old and young \r
+Exploded, and had seized with violent hands, \r
+Had not a cloud descending snatched him thence \r
+Unseen amid the throng: so violence \r
+Proceeded, and oppression, and sword-law, \r
+Through all the plain, and refuge none was found. \r
+Adam was all in tears, and to his guide \r
+Lamenting turned full sad; O!what are these, \r
+Death's ministers, not men? who thus deal death \r
+Inhumanly to men, and multiply \r
+Ten thousandfold the sin of him who slew \r
+His brother: for of whom such massacre \r
+Make they, but of their brethren; men of men \r
+But who was that just man, whom had not Heaven \r
+Rescued, had in his righteousness been lost? \r
+To whom thus Michael.  These are the product \r
+Of those ill-mated marriages thou sawest; \r
+Where good with bad were matched, who of themselves \r
+Abhor to join; and, by imprudence mixed, \r
+Produce prodigious births of body or mind. \r
+Such were these giants, men of high renown; \r
+For in those days might only shall be admired, \r
+And valour and heroick virtue called; \r
+To overcome in battle, and subdue \r
+Nations, and bring home spoils with infinite \r
+Man-slaughter, shall be held the highest pitch \r
+Of human glory; and for glory done \r
+Of triumph, to be styled great conquerours \r
+Patrons of mankind, Gods, and sons of Gods; \r
+Destroyers rightlier called, and plagues of men. \r
+Thus fame shall be achieved, renown on earth; \r
+And what most merits fame, in silence hid. \r
+But he, the seventh from thee, whom thou beheldst \r
+The only righteous in a world preverse, \r
+And therefore hated, therefore so beset \r
+With foes, for daring single to be just, \r
+And utter odious truth, that God would come \r
+To judge them with his Saints; him the Most High \r
+Rapt in a balmy cloud with winged steeds \r
+Did, as thou sawest, receive, to walk with God \r
+High in salvation and the climes of bliss, \r
+Exempt from death; to show thee what reward \r
+Awaits the good; the rest what punishment; \r
+Which now direct thine eyes and soon behold. \r
+He looked, and saw the face of things quite changed; \r
+The brazen throat of war had ceased to roar; \r
+All now was turned to jollity and game, \r
+To luxury and riot, feast and dance; \r
+Marrying or prostituting, as befel, \r
+Rape or adultery, where passing fair \r
+Allured them; thence from cups to civil broils. \r
+At length a reverend sire among them came, \r
+And of their doings great dislike declared, \r
+And testified against their ways; he oft \r
+Frequented their assemblies, whereso met, \r
+Triumphs or festivals; and to them preached \r
+Conversion and repentance, as to souls \r
+In prison, under judgements imminent: \r
+But all in vain: which when he saw, he ceased \r
+Contending, and removed his tents far off; \r
+Then, from the mountain hewing timber tall, \r
+Began to build a vessel of huge bulk; \r
+Measured by cubit, length, and breadth, and highth; \r
+Smeared round with pitch; and in the side a door \r
+Contrived; and of provisions laid in large, \r
+For man and beast: when lo, a wonder strange! \r
+Of every beast, and bird, and insect small, \r
+Came sevens, and pairs; and entered in as taught \r
+Their order: last the sire and his three sons, \r
+With their four wives; and God made fast the door. \r
+Mean while the south-wind rose, and, with black wings \r
+Wide-hovering, all the clouds together drove \r
+From under Heaven; the hills to their supply \r
+Vapour, and exhalation dusk and moist, \r
+Sent up amain; and now the thickened sky \r
+Like a dark cieling stood; down rushed the rain \r
+Impetuous; and continued, till the earth \r
+No more was seen: the floating vessel swum \r
+Uplifted, and secure with beaked prow \r
+Rode tilting o'er the waves; all dwellings else \r
+Flood overwhelmed, and them with all their pomp \r
+Deep under water rolled; sea covered sea, \r
+Sea without shore; and in their palaces, \r
+Where luxury late reigned, sea-monsters whelped \r
+And stabled; of mankind, so numerous late, \r
+All left, in one small bottom swum imbarked. \r
+How didst thou grieve then, Adam, to behold \r
+The end of all thy offspring, end so sad, \r
+Depopulation!  Thee another flood, \r
+Of tears and sorrow a flood, thee also drowned, \r
+And sunk thee as thy sons; till, gently reared \r
+By the Angel, on thy feet thou stoodest at last, \r
+Though comfortless; as when a father mourns \r
+His children, all in view destroyed at once; \r
+And scarce to the Angel utter'dst thus thy plaint. \r
+O visions ill foreseen!  Better had I \r
+Lived ignorant of future! so had borne \r
+My part of evil only, each day's lot \r
+Enough to bear; those now, that were dispensed \r
+The burden of many ages, on me light \r
+At once, by my foreknowledge gaining birth \r
+Abortive, to torment me ere their being, \r
+With thought that they must be.  Let no man seek \r
+Henceforth to be foretold, what shall befall \r
+Him or his children; evil he may be sure, \r
+Which neither his foreknowing can prevent; \r
+And he the future evil shall no less \r
+In apprehension than in substance feel, \r
+Grievous to bear: but that care now is past, \r
+Man is not whom to warn: those few escaped \r
+Famine and anguish will at last consume, \r
+Wandering that watery desart:  I had hope, \r
+When violence was ceased, and war on earth, \r
+All would have then gone well; peace would have crowned \r
+With length of happy days the race of Man; \r
+But I was far deceived; for now I see \r
+Peace to corrupt no less than war to waste. \r
+How comes it thus? unfold, celestial Guide, \r
+And whether here the race of Man will end. \r
+To whom thus Michael.  Those, whom last thou sawest \r
+In triumph and luxurious wealth, are they \r
+First seen in acts of prowess eminent \r
+And great exploits, but of true virtue void; \r
+Who, having spilt much blood, and done much wast \r
+Subduing nations, and achieved thereby \r
+Fame in the world, high titles, and rich prey; \r
+Shall change their course to pleasure, ease, and sloth, \r
+Surfeit, and lust; till wantonness and pride \r
+Raise out of friendship hostile deeds in peace. \r
+The conquered also, and enslaved by war, \r
+Shall, with their freedom lost, all virtue lose \r
+And fear of God; from whom their piety feigned \r
+In sharp contest of battle found no aid \r
+Against invaders; therefore, cooled in zeal, \r
+Thenceforth shall practice how to live secure, \r
+Worldly or dissolute, on what their lords \r
+Shall leave them to enjoy; for the earth shall bear \r
+More than enough, that temperance may be tried: \r
+So all shall turn degenerate, all depraved; \r
+Justice and temperance, truth and faith, forgot; \r
+One man except, the only son of light \r
+In a dark age, against example good, \r
+Against allurement, custom, and a world \r
+Offended: fearless of reproach and scorn, \r
+The grand-child, with twelve sons encreased, departs \r
+From Canaan, to a land hereafter called \r
+Egypt, divided by the river Nile; \r
+See where it flows, disgorging at seven mouths \r
+Into the sea:  To sojourn in that land \r
+He comes, invited by a younger son \r
+In time of dearth; a son, whose worthy deeds \r
+Raise him to be the second in that realm \r
+Of Pharaoh:  There he dies, and leaves his race \r
+Growing into a nation, and now grown \r
+Suspected to a sequent king, who seeks \r
+To stop their overgrowth, as inmate guests \r
+Or violence, he of their wicked ways \r
+Shall them admonish; and before them set \r
+The paths of righteousness, how much more safe \r
+And full of peace; denouncing wrath to come \r
+On their impenitence; and shall return \r
+Of them derided, but of God observed \r
+The one just man alive; by his command \r
+Shall build a wonderous ark, as thou beheldst, \r
+To save himself, and houshold, from amidst \r
+A world devote to universal wrack. \r
+No sooner he, with them of man and beast \r
+Select for life, shall in the ark be lodged, \r
+And sheltered round; but all the cataracts \r
+Of Heaven set open on the Earth shall pour \r
+Rain, day and night; all fountains of the deep, \r
+Broke up, shall heave the ocean to usurp \r
+Beyond all bounds; till inundation rise \r
+Above the highest hills:  Then shall this mount \r
+Of Paradise by might of waves be moved \r
+Out of his place, pushed by the horned flood, \r
+With all his verdure spoiled, and trees adrift, \r
+Down the great river to the opening gulf, \r
+And there take root an island salt and bare, \r
+The haunt of seals, and orcs, and sea-mews' clang: \r
+To teach thee that God attributes to place \r
+No sanctity, if none be thither brought \r
+By men who there frequent, or therein dwell. \r
+And now, what further shall ensue, behold. \r
+He looked, and saw the ark hull on the flood, \r
+Which now abated; for the clouds were fled, \r
+Driven by a keen north-wind, that, blowing dry, \r
+Wrinkled the face of deluge, as decayed; \r
+And the clear sun on his wide watery glass \r
+Gazed hot, and of the fresh wave largely drew, \r
+As after thirst; which made their flowing shrink \r
+From standing lake to tripping ebb, that stole \r
+With soft foot towards the deep; who now had stopt \r
+His sluces, as the Heaven his windows shut. \r
+The ark no more now floats, but seems on ground, \r
+Fast on the top of some high mountain fixed. \r
+And now the tops of hills, as rocks, appear; \r
+With clamour thence the rapid currents drive, \r
+Towards the retreating sea, their furious tide. \r
+Forthwith from out the ark a raven flies, \r
+And after him, the surer messenger, \r
+A dove sent forth once and again to spy \r
+Green tree or ground, whereon his foot may light: \r
+The second time returning, in his bill \r
+An olive-leaf he brings, pacifick sign: \r
+Anon dry ground appears, and from his ark \r
+The ancient sire descends, with all his train; \r
+Then with uplifted hands, and eyes devout, \r
+Grateful to Heaven, over his head beholds \r
+A dewy cloud, and in the cloud a bow \r
+Conspicuous with three lifted colours gay, \r
+Betokening peace from God, and covenant new. \r
+Whereat the heart of Adam, erst so sad, \r
+Greatly rejoiced; and thus his joy broke forth. \r
+O thou, who future things canst represent \r
+As present, heavenly Instructer!  I revive \r
+At this last sight; assured that Man shall live, \r
+With all the creatures, and their seed preserve. \r
+Far less I now lament for one whole world \r
+Of wicked sons destroyed, than I rejoice \r
+For one man found so perfect, and so just, \r
+That God vouchsafes to raise another world \r
+From him, and all his anger to forget. \r
+But say, what mean those coloured streaks in Heaven \r
+Distended, as the brow of God appeased? \r
+Or serve they, as a flowery verge, to bind \r
+The fluid skirts of that same watery cloud, \r
+Lest it again dissolve, and shower the earth? \r
+To whom the Arch-Angel.  Dextrously thou aimest; \r
+So willingly doth God remit his ire, \r
+Though late repenting him of Man depraved; \r
+Grieved at his heart, when looking down he saw \r
+The whole earth filled with violence, and all flesh \r
+Corrupting each their way; yet, those removed, \r
+Such grace shall one just man find in his sight, \r
+That he relents, not to blot out mankind; \r
+And makes a covenant never to destroy \r
+The earth again by flood; nor let the sea \r
+Surpass his bounds; nor rain to drown the world, \r
+With man therein or beast; but, when he brings \r
+Over the earth a cloud, will therein set \r
+His triple-coloured bow, whereon to look, \r
+And call to mind his covenant: Day and night, \r
+Seed-time and harvest, heat and hoary frost, \r
+Shall hold their course; till fire purge all things new, \r
+Both Heaven and Earth, wherein the just shall dwell. \r
\r
\r
\r
+Book XII                                                         \r
\r
\r
+As one who in his journey bates at noon, \r
+Though bent on speed; so here the Arch-Angel paused \r
+Betwixt the world destroyed and world restored, \r
+If Adam aught perhaps might interpose; \r
+Then, with transition sweet, new speech resumes. \r
+Thus thou hast seen one world begin, and end; \r
+And Man, as from a second stock, proceed. \r
+Much thou hast yet to see; but I perceive \r
+Thy mortal sight to fail; objects divine \r
+Must needs impair and weary human sense: \r
+Henceforth what is to come I will relate; \r
+Thou therefore give due audience, and attend. \r
+This second source of Men, while yet but few, \r
+And while the dread of judgement past remains \r
+Fresh in their minds, fearing the Deity, \r
+With some regard to what is just and right \r
+Shall lead their lives, and multiply apace; \r
+Labouring the soil, and reaping plenteous crop, \r
+Corn, wine, and oil; and, from the herd or flock, \r
+Oft sacrificing bullock, lamb, or kid, \r
+With large wine-offerings poured, and sacred feast, \r
+Shall spend their days in joy unblamed; and dwell \r
+Long time in peace, by families and tribes, \r
+Under paternal rule: till one shall rise \r
+Of proud ambitious heart; who, not content \r
+With fair equality, fraternal state, \r
+Will arrogate dominion undeserved \r
+Over his brethren, and quite dispossess \r
+Concord and law of nature from the earth; \r
+Hunting (and men not beasts shall be his game) \r
+With war, and hostile snare, such as refuse \r
+Subjection to his empire tyrannous: \r
+A mighty hunter thence he shall be styled \r
+Before the Lord; as in despite of Heaven, \r
+Or from Heaven, claiming second sovranty; \r
+And from rebellion shall derive his name, \r
+Though of rebellion others he accuse. \r
+He with a crew, whom like ambition joins \r
+With him or under him to tyrannize, \r
+Marching from Eden towards the west, shall find \r
+The plain, wherein a black bituminous gurge \r
+Boils out from under ground, the mouth of Hell: \r
+Of brick, and of that stuff, they cast to build \r
+A city and tower, whose top may reach to Heaven; \r
+And get themselves a name; lest, far dispersed \r
+In foreign lands, their memory be lost; \r
+Regardless whether good or evil fame. \r
+But God, who oft descends to visit men \r
+Unseen, and through their habitations walks \r
+To mark their doings, them beholding soon, \r
+Comes down to see their city, ere the tower \r
+Obstruct Heaven-towers, and in derision sets \r
+Upon their tongues a various spirit, to rase \r
+Quite out their native language; and, instead, \r
+To sow a jangling noise of words unknown: \r
+Forthwith a hideous gabble rises loud, \r
+Among the builders; each to other calls \r
+Not understood; till hoarse, and all in rage, \r
+As mocked they storm: great laughter was in Heaven, \r
+And looking down, to see the hubbub strange, \r
+And hear the din:  Thus was the building left \r
+Ridiculous, and the work Confusion named. \r
+Whereto thus Adam, fatherly displeased. \r
+O execrable son! so to aspire \r
+Above his brethren; to himself assuming \r
+Authority usurped, from God not given: \r
+He gave us only over beast, fish, fowl, \r
+Dominion absolute; that right we hold \r
+By his donation; but man over men \r
+He made not lord; such title to himself \r
+Reserving, human left from human free. \r
+But this usurper his encroachment proud \r
+Stays not on Man; to God his tower intends \r
+Siege and defiance:  Wretched man!what food \r
+Will he convey up thither, to sustain \r
+Himself and his rash army; where thin air \r
+Above the clouds will pine his entrails gross, \r
+And famish him of breath, if not of bread? \r
+To whom thus Michael.  Justly thou abhorrest \r
+That son, who on the quiet state of men \r
+Such trouble brought, affecting to subdue \r
+Rational liberty; yet know withal, \r
+Since thy original lapse, true liberty \r
+Is lost, which always with right reason dwells \r
+Twinned, and from her hath no dividual being: \r
+Reason in man obscured, or not obeyed, \r
+Immediately inordinate desires, \r
+And upstart passions, catch the government \r
+From reason; and to servitude reduce \r
+Man, till then free.  Therefore, since he permits \r
+Within himself unworthy powers to reign \r
+Over free reason, God, in judgement just, \r
+Subjects him from without to violent lords; \r
+Who oft as undeservedly enthrall \r
+His outward freedom:  Tyranny must be; \r
+Though to the tyrant thereby no excuse. \r
+Yet sometimes nations will decline so low \r
+From virtue, which is reason, that no wrong, \r
+But justice, and some fatal curse annexed, \r
+Deprives them of their outward liberty; \r
+Their inward lost:  Witness the irreverent son \r
+Of him who built the ark; who, for the shame \r
+Done to his father, heard this heavy curse, \r
+Servant of servants, on his vicious race. \r
+Thus will this latter, as the former world, \r
+Still tend from bad to worse; till God at last, \r
+Wearied with their iniquities, withdraw \r
+His presence from among them, and avert \r
+His holy eyes; resolving from thenceforth \r
+To leave them to their own polluted ways; \r
+And one peculiar nation to select \r
+From all the rest, of whom to be invoked, \r
+A nation from one faithful man to spring: \r
+Him on this side Euphrates yet residing, \r
+Bred up in idol-worship:  O, that men \r
+(Canst thou believe?) should be so stupid grown, \r
+While yet the patriarch lived, who 'scaped the flood, \r
+As to forsake the living God, and fall \r
+To worship their own work in wood and stone \r
+For Gods!  Yet him God the Most High vouchsafes \r
+To call by vision, from his father's house, \r
+His kindred, and false Gods, into a land \r
+Which he will show him; and from him will raise \r
+A mighty nation; and upon him shower \r
+His benediction so, that in his seed \r
+All nations shall be blest: he straight obeys; \r
+Not knowing to what land, yet firm believes: \r
+I see him, but thou canst not, with what faith \r
+He leaves his Gods, his friends, and native soil, \r
+Ur of Chaldaea, passing now the ford \r
+To Haran; after him a cumbrous train \r
+Of herds and flocks, and numerous servitude; \r
+Not wandering poor, but trusting all his wealth \r
+With God, who called him, in a land unknown. \r
+Canaan he now attains; I see his tents \r
+Pitched about Sechem, and the neighbouring plain \r
+Of Moreh; there by promise he receives \r
+Gift to his progeny of all that land, \r
+From Hameth northward to the Desart south; \r
+(Things by their names I call, though yet unnamed;) \r
+From Hermon east to the great western Sea; \r
+Mount Hermon, yonder sea; each place behold \r
+In prospect, as I point them; on the shore \r
+Mount Carmel; here, the double-founted stream, \r
+Jordan, true limit eastward; but his sons \r
+Shall dwell to Senir, that long ridge of hills. \r
+This ponder, that all nations of the earth \r
+Shall in his seed be blessed:  By that seed \r
+Is meant thy great Deliverer, who shall bruise \r
+The Serpent's head; whereof to thee anon \r
+Plainlier shall be revealed.  This patriarch blest, \r
+Whom faithful Abraham due time shall call, \r
+A son, and of his son a grand-child, leaves; \r
+Like him in faith, in wisdom, and renown: \r
+The grandchild, with twelve sons increased, departs \r
+From Canaan to a land hereafter called \r
+Egypt, divided by the river Nile \r
+See where it flows, disgorging at seven mouths \r
+Into the sea. To sojourn in that land \r
+He comes, invited by a younger son \r
+In time of dearth, a son whose worthy deeds \r
+Raise him to be the second in that realm \r
+Of Pharaoh. There he dies, and leaves his race \r
+Growing into a nation, and now grown \r
+Suspected to a sequent king, who seeks \r
+To stop their overgrowth, as inmate guests \r
+Too numerous; whence of guests he makes them slaves \r
+Inhospitably, and kills their infant males: \r
+Till by two brethren (these two brethren call \r
+Moses and Aaron) sent from God to claim \r
+His people from enthralment, they return, \r
+With glory and spoil, back to their promised land. \r
+But first, the lawless tyrant, who denies \r
+To know their God, or message to regard, \r
+Must be compelled by signs and judgements dire; \r
+To blood unshed the rivers must be turned; \r
+Frogs, lice, and flies, must all his palace fill \r
+With loathed intrusion, and fill all the land; \r
+His cattle must of rot and murren die; \r
+Botches and blains must all his flesh emboss, \r
+And all his people; thunder mixed with hail, \r
+Hail mixed with fire, must rend the Egyptians sky, \r
+And wheel on the earth, devouring where it rolls; \r
+What it devours not, herb, or fruit, or grain, \r
+A darksome cloud of locusts swarming down \r
+Must eat, and on the ground leave nothing green; \r
+Darkness must overshadow all his bounds, \r
+Palpable darkness, and blot out three days; \r
+Last, with one midnight stroke, all the first-born \r
+Of Egypt must lie dead.  Thus with ten wounds \r
+The river-dragon tamed at length submits \r
+To let his sojourners depart, and oft \r
+Humbles his stubborn heart; but still, as ice \r
+More hardened after thaw; till, in his rage \r
+Pursuing whom he late dismissed, the sea \r
+Swallows him with his host; but them lets pass, \r
+As on dry land, between two crystal walls; \r
+Awed by the rod of Moses so to stand \r
+Divided, till his rescued gain their shore: \r
+Such wondrous power God to his saint will lend, \r
+Though present in his Angel; who shall go \r
+Before them in a cloud, and pillar of fire; \r
+By day a cloud, by night a pillar of fire; \r
+To guide them in their journey, and remove \r
+Behind them, while the obdurate king pursues: \r
+All night he will pursue; but his approach \r
+Darkness defends between till morning watch; \r
+Then through the fiery pillar, and the cloud, \r
+God looking forth will trouble all his host, \r
+And craze their chariot-wheels: when by command \r
+Moses once more his potent rod extends \r
+Over the sea; the sea his rod obeys; \r
+On their embattled ranks the waves return, \r
+And overwhelm their war:  The race elect \r
+Safe toward Canaan from the shore advance \r
+Through the wild Desart, not the readiest way; \r
+Lest, entering on the Canaanite alarmed, \r
+War terrify them inexpert, and fear \r
+Return them back to Egypt, choosing rather \r
+Inglorious life with servitude; for life \r
+To noble and ignoble is more sweet \r
+Untrained in arms, where rashness leads not on. \r
+This also shall they gain by their delay \r
+In the wide wilderness; there they shall found \r
+Their government, and their great senate choose \r
+Through the twelve tribes, to rule by laws ordained: \r
+God from the mount of Sinai, whose gray top \r
+Shall tremble, he descending, will himself \r
+In thunder, lightning, and loud trumpets' sound, \r
+Ordain them laws; part, such as appertain \r
+To civil justice; part, religious rites \r
+Of sacrifice; informing them, by types \r
+And shadows, of that destined Seed to bruise \r
+The Serpent, by what means he shall achieve \r
+Mankind's deliverance.  But the voice of God \r
+To mortal ear is dreadful:  They beseech \r
+That Moses might report to them his will, \r
+And terrour cease; he grants what they besought, \r
+Instructed that to God is no access \r
+Without Mediator, whose high office now \r
+Moses in figure bears; to introduce \r
+One greater, of whose day he shall foretel, \r
+And all the Prophets in their age the times \r
+Of great Messiah shall sing.  Thus, laws and rites \r
+Established, such delight hath God in Men \r
+Obedient to his will, that he vouchsafes \r
+Among them to set up his tabernacle; \r
+The Holy One with mortal Men to dwell: \r
+By his prescript a sanctuary is framed \r
+Of cedar, overlaid with gold; therein \r
+An ark, and in the ark his testimony, \r
+The records of his covenant; over these \r
+A mercy-seat of gold, between the wings \r
+Of two bright Cherubim; before him burn \r
+Seven lamps as in a zodiack representing \r
+The heavenly fires; over the tent a cloud \r
+Shall rest by day, a fiery gleam by night; \r
+Save when they journey, and at length they come, \r
+Conducted by his Angel, to the land \r
+Promised to Abraham and his seed:--The rest \r
+Were long to tell; how many battles fought \r
+How many kings destroyed; and kingdoms won; \r
+Or how the sun shall in mid Heaven stand still \r
+A day entire, and night's due course adjourn, \r
+Man's voice commanding, 'Sun, in Gibeon stand, \r
+'And thou moon in the vale of Aialon, \r
+'Till Israel overcome! so call the third \r
+From Abraham, son of Isaac; and from him \r
+His whole descent, who thus shall Canaan win. \r
+Here Adam interposed.  O sent from Heaven, \r
+Enlightener of my darkness, gracious things \r
+Thou hast revealed; those chiefly, which concern \r
+Just Abraham and his seed: now first I find \r
+Mine eyes true-opening, and my heart much eased; \r
+Erewhile perplexed with thoughts, what would become \r
+Of me and all mankind:  But now I see \r
+His day, in whom all nations shall be blest; \r
+Favour unmerited by me, who sought \r
+Forbidden knowledge by forbidden means. \r
+This yet I apprehend not, why to those \r
+Among whom God will deign to dwell on earth \r
+So many and so various laws are given; \r
+So many laws argue so many sins \r
+Among them; how can God with such reside? \r
+To whom thus Michael.  Doubt not but that sin \r
+Will reign among them, as of thee begot; \r
+And therefore was law given them, to evince \r
+Their natural pravity, by stirring up \r
+Sin against law to fight: that when they see \r
+Law can discover sin, but not remove, \r
+Save by those shadowy expiations weak, \r
+The blood of bulls and goats, they may conclude \r
+Some blood more precious must be paid for Man; \r
+Just for unjust; that, in such righteousness \r
+To them by faith imputed, they may find \r
+Justification towards God, and peace \r
+Of conscience; which the law by ceremonies \r
+Cannot appease; nor Man the mortal part \r
+Perform; and, not performing, cannot live. \r
+So law appears imperfect; and but given \r
+With purpose to resign them, in full time, \r
+Up to a better covenant; disciplined \r
+From shadowy types to truth; from flesh to spirit; \r
+From imposition of strict laws to free \r
+Acceptance of large grace; from servile fear \r
+To filial; works of law to works of faith. \r
+And therefore shall not Moses, though of God \r
+Highly beloved, being but the minister \r
+Of law, his people into Canaan lead; \r
+But Joshua, whom the Gentiles Jesus call, \r
+His name and office bearing, who shall quell \r
+The adversary-Serpent, and bring back \r
+Through the world's wilderness long-wandered Man \r
+Safe to eternal Paradise of rest. \r
+Mean while they, in their earthly Canaan placed, \r
+Long time shall dwell and prosper, but when sins \r
+National interrupt their publick peace, \r
+Provoking God to raise them enemies; \r
+From whom as oft he saves them penitent \r
+By Judges first, then under Kings; of whom \r
+The second, both for piety renowned \r
+And puissant deeds, a promise shall receive \r
+Irrevocable, that his regal throne \r
+For ever shall endure; the like shall sing \r
+All Prophecy, that of the royal stock \r
+Of David (so I name this king) shall rise \r
+A Son, the Woman's seed to thee foretold, \r
+Foretold to Abraham, as in whom shall trust \r
+All nations; and to kings foretold, of kings \r
+The last; for of his reign shall be no end. \r
+But first, a long succession must ensue; \r
+And his next son, for wealth and wisdom famed, \r
+The clouded ark of God, till then in tents \r
+Wandering, shall in a glorious temple enshrine. \r
+Such follow him, as shall be registered \r
+Part good, part bad; of bad the longer scroll; \r
+Whose foul idolatries, and other faults \r
+Heaped to the popular sum, will so incense \r
+God, as to leave them, and expose their land, \r
+Their city, his temple, and his holy ark, \r
+With all his sacred things, a scorn and prey \r
+To that proud city, whose high walls thou sawest \r
+Left in confusion; Babylon thence called. \r
+There in captivity he lets them dwell \r
+The space of seventy years; then brings them back, \r
+Remembering mercy, and his covenant sworn \r
+To David, stablished as the days of Heaven. \r
+Returned from Babylon by leave of kings \r
+Their lords, whom God disposed, the house of God \r
+They first re-edify; and for a while \r
+In mean estate live moderate; till, grown \r
+In wealth and multitude, factious they grow; \r
+But first among the priests dissention springs, \r
+Men who attend the altar, and should most \r
+Endeavour peace: their strife pollution brings \r
+Upon the temple itself: at last they seise \r
+The scepter, and regard not David's sons; \r
+Then lose it to a stranger, that the true \r
+Anointed King Messiah might be born \r
+Barred of his right; yet at his birth a star, \r
+Unseen before in Heaven, proclaims him come; \r
+And guides the eastern sages, who inquire \r
+His place, to offer incense, myrrh, and gold: \r
+His place of birth a solemn Angel tells \r
+To simple shepherds, keeping watch by night; \r
+They gladly thither haste, and by a quire \r
+Of squadroned Angels hear his carol sung. \r
+A virgin is his mother, but his sire \r
+The power of the Most High:  He shall ascend \r
+The throne hereditary, and bound his reign \r
+With Earth's wide bounds, his glory with the Heavens. \r
+He ceased, discerning Adam with such joy \r
+Surcharged, as had like grief been dewed in tears, \r
+Without the vent of words; which these he breathed. \r
+O prophet of glad tidings, finisher \r
+Of utmost hope! now clear I understand \r
+What oft my steadiest thoughts have searched in vain; \r
+Why our great Expectation should be called \r
+The seed of Woman:  Virgin Mother, hail, \r
+High in the love of Heaven; yet from my loins \r
+Thou shalt proceed, and from thy womb the Son \r
+Of God Most High: so God with Man unites! \r
+Needs must the Serpent now his capital bruise \r
+Expect with mortal pain:  Say where and when \r
+Their fight, what stroke shall bruise the victor's heel. \r
+To whom thus Michael.  Dream not of their fight, \r
+As of a duel, or the local wounds \r
+Of head or heel:  Not therefore joins the Son \r
+Manhood to Godhead, with more strength to foil \r
+Thy enemy; nor so is overcome \r
+Satan, whose fall from Heaven, a deadlier bruise, \r
+Disabled, not to give thee thy death's wound: \r
+Which he, who comes thy Saviour, shall recure, \r
+Not by destroying Satan, but his works \r
+In thee, and in thy seed:  Nor can this be, \r
+But by fulfilling that which thou didst want, \r
+Obedience to the law of God, imposed \r
+On penalty of death, and suffering death; \r
+The penalty to thy transgression due, \r
+And due to theirs which out of thine will grow: \r
+So only can high Justice rest appaid. \r
+The law of God exact he shall fulfil \r
+Both by obedience and by love, though love \r
+Alone fulfil the law; thy punishment \r
+He shall endure, by coming in the flesh \r
+To a reproachful life, and cursed death; \r
+Proclaiming life to all who shall believe \r
+In his redemption; and that his obedience, \r
+Imputed, becomes theirs by faith; his merits \r
+To save them, not their own, though legal, works. \r
+For this he shall live hated, be blasphemed, \r
+Seised on by force, judged, and to death condemned \r
+A shameful and accursed, nailed to the cross \r
+By his own nation; slain for bringing life: \r
+But to the cross he nails thy enemies, \r
+The law that is against thee, and the sins \r
+Of all mankind, with him there crucified, \r
+Never to hurt them more who rightly trust \r
+In this his satisfaction; so he dies, \r
+But soon revives; Death over him no power \r
+Shall long usurp; ere the third dawning light \r
+Return, the stars of morn shall see him rise \r
+Out of his grave, fresh as the dawning light, \r
+Thy ransom paid, which Man from death redeems, \r
+His death for Man, as many as offered life \r
+Neglect not, and the benefit embrace \r
+By faith not void of works:  This God-like act \r
+Annuls thy doom, the death thou shouldest have died, \r
+In sin for ever lost from life; this act \r
+Shall bruise the head of Satan, crush his strength, \r
+Defeating Sin and Death, his two main arms; \r
+And fix far deeper in his head their stings \r
+Than temporal death shall bruise the victor's heel, \r
+Or theirs whom he redeems; a death, like sleep, \r
+A gentle wafting to immortal life. \r
+Nor after resurrection shall he stay \r
+Longer on earth, than certain times to appear \r
+To his disciples, men who in his life \r
+Still followed him; to them shall leave in charge \r
+To teach all nations what of him they learned \r
+And his salvation; them who shall believe \r
+Baptizing in the profluent stream, the sign \r
+Of washing them from guilt of sin to life \r
+Pure, and in mind prepared, if so befall, \r
+For death, like that which the Redeemer died. \r
+All nations they shall teach; for, from that day, \r
+Not only to the sons of Abraham's loins \r
+Salvation shall be preached, but to the sons \r
+Of Abraham's faith wherever through the world; \r
+So in his seed all nations shall be blest. \r
+Then to the Heaven of Heavens he shall ascend \r
+With victory, triumphing through the air \r
+Over his foes and thine; there shall surprise \r
+The Serpent, prince of air, and drag in chains \r
+Through all his realm, and there confounded leave; \r
+Then enter into glory, and resume \r
+His seat at God's right hand, exalted high \r
+Above all names in Heaven; and thence shall come, \r
+When this world's dissolution shall be ripe, \r
+With glory and power to judge both quick and dead; \r
+To judge the unfaithful dead, but to reward \r
+His faithful, and receive them into bliss, \r
+Whether in Heaven or Earth; for then the Earth \r
+Shall all be Paradise, far happier place \r
+Than this of Eden, and far happier days. \r
+So spake the Arch-Angel Michael; then paused, \r
+As at the world's great period; and our sire, \r
+Replete with joy and wonder, thus replied. \r
+O Goodness infinite, Goodness immense! \r
+That all this good of evil shall produce, \r
+And evil turn to good; more wonderful \r
+Than that which by creation first brought forth \r
+Light out of darkness!  Full of doubt I stand, \r
+Whether I should repent me now of sin \r
+By me done, and occasioned; or rejoice \r
+Much more, that much more good thereof shall spring; \r
+To God more glory, more good-will to Men \r
+From God, and over wrath grace shall abound. \r
+But say, if our Deliverer up to Heaven \r
+Must re-ascend, what will betide the few \r
+His faithful, left among the unfaithful herd, \r
+The enemies of truth?  Who then shall guide \r
+His people, who defend?  Will they not deal \r
+Worse with his followers than with him they dealt? \r
+Be sure they will, said the Angel; but from Heaven \r
+He to his own a Comforter will send, \r
+The promise of the Father, who shall dwell \r
+His Spirit within them; and the law of faith, \r
+Working through love, upon their hearts shall write, \r
+To guide them in all truth; and also arm \r
+With spiritual armour, able to resist \r
+Satan's assaults, and quench his fiery darts; \r
+What man can do against them, not afraid, \r
+Though to the death; against such cruelties \r
+With inward consolations recompensed, \r
+And oft supported so as shall amaze \r
+Their proudest persecutors:  For the Spirit, \r
+Poured first on his Apostles, whom he sends \r
+To evangelize the nations, then on all \r
+Baptized, shall them with wonderous gifts endue \r
+To speak all tongues, and do all miracles, \r
+As did their Lord before them.  Thus they win \r
+Great numbers of each nation to receive \r
+With joy the tidings brought from Heaven:  At length \r
+Their ministry performed, and race well run, \r
+Their doctrine and their story written left, \r
+They die; but in their room, as they forewarn, \r
+Wolves shall succeed for teachers, grievous wolves, \r
+Who all the sacred mysteries of Heaven \r
+To their own vile advantages shall turn \r
+Of lucre and ambition; and the truth \r
+With superstitions and traditions taint, \r
+Left only in those written records pure, \r
+Though not but by the Spirit understood. \r
+Then shall they seek to avail themselves of names, \r
+Places, and titles, and with these to join \r
+Secular power; though feigning still to act \r
+By spiritual, to themselves appropriating \r
+The Spirit of God, promised alike and given \r
+To all believers; and, from that pretence, \r
+Spiritual laws by carnal power shall force \r
+On every conscience; laws which none shall find \r
+Left them inrolled, or what the Spirit within \r
+Shall on the heart engrave.  What will they then \r
+But force the Spirit of Grace itself, and bind \r
+His consort Liberty? what, but unbuild \r
+His living temples, built by faith to stand, \r
+Their own faith, not another's? for, on earth, \r
+Who against faith and conscience can be heard \r
+Infallible? yet many will presume: \r
+Whence heavy persecution shall arise \r
+On all, who in the worship persevere \r
+Of spirit and truth; the rest, far greater part, \r
+Will deem in outward rites and specious forms \r
+Religion satisfied; Truth shall retire \r
+Bestuck with slanderous darts, and works of faith \r
+Rarely be found:  So shall the world go on, \r
+To good malignant, to bad men benign; \r
+Under her own weight groaning; till the day \r
+Appear of respiration to the just, \r
+And vengeance to the wicked, at return \r
+Of him so lately promised to thy aid, \r
+The Woman's Seed; obscurely then foretold, \r
+Now ampler known thy Saviour and thy Lord; \r
+Last, in the clouds, from Heaven to be revealed \r
+In glory of the Father, to dissolve \r
+Satan with his perverted world; then raise \r
+From the conflagrant mass, purged and refined, \r
+New Heavens, new Earth, ages of endless date, \r
+Founded in righteousness, and peace, and love; \r
+To bring forth fruits, joy and eternal bliss. \r
+He ended; and thus Adam last replied. \r
+How soon hath thy prediction, Seer blest, \r
+Measured this transient world, the race of time, \r
+Till time stand fixed!  Beyond is all abyss, \r
+Eternity, whose end no eye can reach. \r
+Greatly-instructed I shall hence depart; \r
+Greatly in peace of thought; and have my fill \r
+Of knowledge, what this vessel can contain; \r
+Beyond which was my folly to aspire. \r
+Henceforth I learn, that to obey is best, \r
+And love with fear the only God; to walk \r
+As in his presence; ever to observe \r
+His providence; and on him sole depend, \r
+Merciful over all his works, with good \r
+Still overcoming evil, and by small \r
+Accomplishing great things, by things deemed weak \r
+Subverting worldly strong, and worldly wise \r
+By simply meek: that suffering for truth's sake \r
+Is fortitude to highest victory, \r
+And, to the faithful, death the gate of life; \r
+Taught this by his example, whom I now \r
+Acknowledge my Redeemer ever blest. \r
+To whom thus also the Angel last replied. \r
+This having learned, thou hast attained the sum \r
+Of wisdom; hope no higher, though all the stars \r
+Thou knewest by name, and all the ethereal powers, \r
+All secrets of the deep, all Nature's works, \r
+Or works of God in Heaven, air, earth, or sea, \r
+And all the riches of this world enjoyedst, \r
+And all the rule, one empire; only add \r
+Deeds to thy knowledge answerable; add faith, \r
+Add virtue, patience, temperance; add love, \r
+By name to come called charity, the soul \r
+Of all the rest: then wilt thou not be loth \r
+To leave this Paradise, but shalt possess \r
+A Paradise within thee, happier far.-- \r
+Let us descend now therefore from this top \r
+Of speculation; for the hour precise \r
+Exacts our parting hence; and see!the guards, \r
+By me encamped on yonder hill, expect \r
+Their motion; at whose front a flaming sword, \r
+In signal of remove, waves fiercely round: \r
+We may no longer stay: go, waken Eve; \r
+Her also I with gentle dreams have calmed \r
+Portending good, and all her spirits composed \r
+To meek submission: thou, at season fit, \r
+Let her with thee partake what thou hast heard; \r
+Chiefly what may concern her faith to know, \r
+The great deliverance by her seed to come \r
+(For by the Woman's seed) on all mankind: \r
+That ye may live, which will be many days, \r
+Both in one faith unanimous, though sad, \r
+With cause, for evils past; yet much more cheered \r
+With meditation on the happy end. \r
+He ended, and they both descend the hill; \r
+Descended, Adam to the bower, where Eve \r
+Lay sleeping, ran before; but found her waked; \r
+And thus with words not sad she him received. \r
+Whence thou returnest, and whither wentest, I know; \r
+For God is also in sleep; and dreams advise, \r
+Which he hath sent propitious, some great good \r
+Presaging, since with sorrow and heart's distress \r
+Wearied I fell asleep:  But now lead on; \r
+In me is no delay; with thee to go, \r
+Is to stay here; without thee here to stay, \r
+Is to go hence unwilling; thou to me \r
+Art all things under $Heaven, all places thou, \r
+Who for my wilful crime art banished hence. \r
+This further consolation yet secure \r
+I carry hence; though all by me is lost, \r
+Such favour I unworthy am vouchsafed, \r
+By me the Promised Seed shall all restore. \r
+So spake our mother Eve; and Adam heard \r
+Well pleased, but answered not:  For now, too nigh \r
+The Arch-Angel stood; and, from the other hill \r
+To their fixed station, all in bright array \r
+The Cherubim descended; on the ground \r
+Gliding meteorous, as evening-mist \r
+Risen from a river o'er the marish glides, \r
+And gathers ground fast at the labourer's heel \r
+Homeward returning.  High in front advanced, \r
+The brandished sword of God before them blazed, \r
+Fierce as a comet; which with torrid heat, \r
+And vapour as the Libyan air adust, \r
+Began to parch that temperate clime; whereat \r
+In either hand the hastening Angel caught \r
+Our lingering parents, and to the eastern gate \r
+Led them direct, and down the cliff as fast \r
+To the subjected plain; then disappeared. \r
+They, looking back, all the eastern side beheld \r
+Of Paradise, so late their happy seat, \r
+Waved over by that flaming brand; the gate \r
+With dreadful faces thronged, and fiery arms: \r
+Some natural tears they dropt, but wiped them soon; \r
+The world was all before them, where to choose \r
+Their place of rest, and Providence their guide: \r
+They, hand in hand, with wandering steps and slow, \r
+Through Eden took their solitary way. \r
\r
+[The End]\1a\1a\r
diff --git a/snappy/snappy-1.0.5/testdata/ptt5 b/snappy/snappy-1.0.5/testdata/ptt5
new file mode 100644 (file)
index 0000000..bdd7f36
Binary files /dev/null and b/snappy/snappy-1.0.5/testdata/ptt5 differ
diff --git a/snappy/snappy-1.0.5/testdata/sum b/snappy/snappy-1.0.5/testdata/sum
new file mode 100644 (file)
index 0000000..758fd81
Binary files /dev/null and b/snappy/snappy-1.0.5/testdata/sum differ
diff --git a/snappy/snappy-1.0.5/testdata/urls.10K b/snappy/snappy-1.0.5/testdata/urls.10K
new file mode 100644 (file)
index 0000000..eaf0633
--- /dev/null
@@ -0,0 +1,10000 @@
+http://ftp.sektornet.dk/tucows/herdwin0904.html
+http://209.143.244.16/directory/us/nd/fargo/insurance/automotive.html
+http://bellona.itworld.com:8080/cwi/reprint/0,1926,NAV63-128-1357-1367_STO46538,00.html
+http://www.legis.state.ia.us/usr/ns-home/docs/GA/76GA/Session.2/SJournal/01600/01644.html
+http://www.centc251.org/forums/aca-1/dispatch.cgi/isowg4/showFolder/100001/1211898
+http://www.burstnet.com/ads/ad7826a-map.cgi/271412263
+http://topcu.tucows.com/winme/adnload/137036_30095.html
+http://topcu.tucows.com/winme/adnload/145034_49120.html
+http://link.fastpartner.com/do/session/600342/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/bitconomy.php
+http://www.retrobytes.org/classiccmp/9911/msg01245.html
+http://www.localbusiness.com/Story/Print/0,1197,DFW_196102,00.html
+http://bbs.kh.edu.tw/treasure/childhood/M.962620586.A/M.966031025.A/M.966031098.A.html
+http://www.hig.se/(accessed,clientname,return)/~jackson/roxen/testform.html
+http://www.ipclub.ru:8102/cgi-bin/linkmaker/linklist-view.cgi?owner=elvis&Sector=434
+http://www.dulux.co.uk/UKRETAIL:229853034:DFinity.1QJiP4jMofi7bof
+http://www.dominionpost.com/cgi-bin/redirect.exe/85288
+http://br.egroups.com/message/anedotas/3988
+http://www.ing.iac.es/~cfg/group_notes/texinfo/spec/file$_must$_exist_$28appendfile$29.html
+http://hurweb01.hurriyetim.com.tr/hur/turk/99/06/22/yasam/14yas.htm
+http://www3.plala.or.jp/shinchi/niltuki/mai0416.htm
+http://www3.plala.or.jp/shinchi/niltuki/mai0420.htm
+http://213.36.119.69/do/session/152968/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www3.travelprice.com/voyages/recherche.phtml
+http://www.meristation.es/Trucos/s/starcraft_brood.htm
+http://www.meristation.es/Trucos/trainer/train_star_war.htm
+http://www.askme.com/cat/ShowCategory_3104_an_9.htm
+http://mozilla.org/newlayout/testcases/css/sec542cm.htm
+http://ampec.ampec.it/ted/box04/page36.htm
+http://ampec.ampec.it/ted/box04/page39.htm
+http://ampec.ampec.it/ted/box04/page42.htm
+http://ampec.ampec.it/ted/box04/page58.htm
+http://ampec.ampec.it/ted/box04/page62.htm
+http://www.businesswire.com/webbox/bw.080300/202160192.htm
+http://www.businesswire.com/webbox/bw.062700/201790580.htm
+http://www.businesswire.com/webbox/bw.040300/200940796.htm
+http://retailer.gocollect.com/do/session/1912606/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/top_ten.asp?pagenum=1
+http://retailer.gocollect.com/do/session/1912606/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/clubhouse/suggestions.asp
+http://genforum.genealogy.com/cgi-bin/print.cgi?ivy::116.html
+http://www.spiral.at/Katalog/Artikel/6150331/
+http://www.spiral.at/Katalog/Artikel/6150390/
+http://www.spiral.at/Katalog/Artikel/6150411/
+http://bbs.msquare.or.kr/list.bbs/writer/Soohah/8.html
+http://www.eskimo.com/~wesn/waflyfishers/msg03537.html
+http://denniscares.mp2.homes.com/content/glossary.html?Letter=A
+http://library.bangor.ac.uk/search/aChandler,+Peter,+1936-/achandler+peter+1936/-5,-1,0,B/bibandlinks&F=achandler+raymond+1888+1959&5,,6
+http://www.kimkihong.pe.kr/
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/199/1998/6/0/1323673/
+http://musictz.com/user/fernman.html
+http://tucows.concepts.nl/winnt/adnload/1381_28803.html
+http://www.mirror.kiev.ua:8083/paper/2000/03/1251/text/03-06-6.htm
+http://ring.crl.go.jp/pub/linux/debian/debian-jp/dists/stable/non-free/binary-arm/x11/?N=D
+http://news.novgorod.ru/news/2000/4/23/2/9
+http://www.egroups.com/dir/World/Deutsch/Gesellschaft/Bildung/Schule?st=167
+http://www.egroups.com/group/abitur98
+http://genforum.genealogy.com/cgi-genforum/forums/casey.cgi?1477
+http://www.tvstore.com/browse/TV/BOXERSHO/s.UtRroVXF
+http://www.tvstore.com/browse/TV/COLLECTI/s.UtRroVXF
+http://www.tvstore.com/browse/TV/EARRINGS/s.UtRroVXF
+http://polygraph.ircache.net:8181/text/m90/http_-2ewp.aliant.com/attivita.htm
+http://rosebay.1000pages.com/ceclgt12.htm
+http://www02.u-page.so-net.ne.jp/sb3/mizo/home/sub1/link2/?M=A
+http://community.webshots.com/photo/5827455/5827535oqdRLPNiek
+http://troy.lib.sfu.ca/search/dbiology+periodicals/dbiology+periodicals/19,-1,0,B/frameset&F=dbiology+religious+aspects&1,1
+http://213.36.119.69/do/session/152973/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/special/alitalia.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/programs/simple/linux/math/computers/tunes.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/programs/simple/linux/math/lit/hasard.html
+http://www.elop.de/l0-1011-xx-3006-top.html
+http://britanica.com/bcom/eb/article/idxref/0/0,5716,364643,00.html
+http://britanica.com/bcom/eb/article/7/0,5716,28557+1+28108,00.html
+http://www.geocrawler.com/archives/3/3174/2000/5/50/3724502/
+http://www.geocrawler.com/archives/3/3174/2000/5/50/3699557/
+http://www.geocrawler.com/archives/3/3174/2000/5/50/3689003/
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-stable/net/slirp/files/
+http://www.duluxvalentine.com/FRANCE:219793321:DFinity.1QJiP4jmPgUaedp
+http://mundo.ole.es/ocio/articulo/html/oci4270.htm
+http://www.maasvlakte-cam.nl/webcams/43/etna__italy/1999/08/29/01:28:02.html
+http://www.chinabyte.com/staticpages/builder/builder_course_next/HIPR/builder_course_next_219_HIPR.html
+http://www.prospects2.csu.ac.uk/servlet/postgrad.TcAssess?pgid=9634
+http://ftp.sunet.se/pub/lang/perl/CPAN/authors/id/SPP/?N=D
+http://www.egroups.com/message/WDT/7751
+http://pub8.ezboard.com/fapricotyarn.unsubscribeUnregisteredToTopic?topicID=4.topic
+http://support.tandy.com/support_audio/doc9/9679.htm
+http://megalink.tucows.com/winme/preview/74862.html
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/199/1996/2/0/2460450/
+http://www.monaco.gouv.mc/dataweb/gouvmc.nsf/(NewsActu)/d28eaee29b3287d4c1256905004e1ef1!OpenDocument&ExpandSection=10.3,10.4,7,9,4,6
+http://www.fao.org/montes/foda/wforcong/PUBLI/V2/T8S/1-3.HTM
+http://library.cuhk.edu.hk/search*chi/a蔡淙霖,+1965-/a%7B215572%7D%7B214758%7D%7B215f60%7D+1965/-5,-1,0,B/browse
+http://www.nrk.no/finnmark/x31_12_97/nyh6.htm
+http://www.dailyrush.dk/stories/129/comments/pages/1
+http://home.wanadoo.nl/pieter.heres/nedbaskteam/nbt/Web%20Album%20nbt%20spelers/page3.htm
+http://members.tripod.co.jp/masa_selfish/?M=A
+http://bsd.sinica.edu.tw/cgi-bin/cvsweb.cgi/ports/misc/lile/patches/Attic/?sortby=date
+http://www.chaos.dk/sexriddle/z/l/x/y/m/
+http://www.chaos.dk/sexriddle/z/l/x/y/p/
+http://users.sexyboards.com/amandaslut/messages/17.html
+http://pub11.ezboard.com/fusscroatiastartrekanimators.showAddTopicScreenFromWeb
+http://retailer.gocollect.com/do/session/1912610/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/help/site_tour/index.asp
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-current/misc/boxes/pkg-comment
+http://www.ce-europe2.philips.com/do/session/80299/vsid/1034/tid/1034/cid/28533/mid/1020/rid/1021/chid/1024/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkZHbjbHrolLmbkKmefLifmLpkZHljlKmoaLl0/url/http://www.eu.microsoft.com/windows/ie_intl/es/
+http://www.peopledaily.co.jp/199904/26/newfiles/col_990426001084_tyxw.html
+http://www.peopledaily.co.jp/199904/26/newfiles/col_990426001087_tyxw.html
+http://iraustralia.com/listco/hk/swire/profile.htm
+http://jefferson.village.virginia.edu/wax/slow/english/3pix/BRight2/1/1a5a15a1.html
+http://infoserv2.ita.doc.gov/efm/efm.nsf/Sources!OpenView&Start=35.16&Count=30&Expand=37
+http://www.affiliate.hpstore.hp.co.uk/do/session/380772/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/entry1.asp
+http://www.trax.nilex.co.uk/trax.cgi/A1S/B1U/B1R/A3S/A4R/C2U/
+http://www.trax.nilex.co.uk/trax.cgi/A1S/B1U/B1R/A3S/A4R/C2S/
+http://www.quia.com/email.cgi?7106&fc
+http://www.mirror.edu.cn/res/sunsite/pub/academic/agriculture/sustainable_agriculture/news+mail-archives/6/
+http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/Beholder/CVSROOT/config?only_with_tag=MAIN
+http://collection.nlc-bnc.ca/100/201/300/info_tabac/html/1998/bull21/poumon.html
+http://www.erotism.com/sweetlostcherry/g3.htm
+http://adex3.flycast.com/server/socket/127.0.0.1:2800/click/SharewareMusicMachine/MusicSoftware1/96457
+http://members.tripod.com/~tonarcos/paginas/Nancy1.html
+http://www.gbnf.com/genealog2/stout/html/d0024/I2144.HTM
+http://ftp.du.se/disk4/FreeBSD/branches/4.0-stable/ports/deskutils/cbb/
+http://www.hri.org/docs//statedep/95-09-13.std.html
+http://ftp.univie.ac.at/packages/tex/macros/latex//contrib/supported/eurofont/adobeuro/readme.txt
+http://forum.rai.it/aca-finestre/dispatch.cgi/FORUM/showNextUnseen/fol/100001/1513138
+http://tucows.ipv.pt/winnt/adnload/1891_28712.html
+http://www.tucsonweekly.com/tw/02-09-95/danehy.htm
+http://message/artefactphil/87?expand=1
+http://www.kiarchive.ru:8091/pub/FreeBSD/FreeBSD-current/src/gnu/Makefile/
+http://retailer.gocollect.com/do/session/1912644/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/index.asp
+http://retailer.gocollect.com/do/session/1912644/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/about.asp
+http://park.org:8888/Cdrom/TheNot/Mail/NotPark/msg00070.html
+http://citeseer.nj.nec.com/cachedpage/67611/1
+http://citeseer.nj.nec.com/cidcontext/1053642
+http://www.3w-buecher.de/GiacamanGeorge/GiacamanGeorge0745312381.htm
+http://au.yahoo.com/Regional/U_S__States/Colorado/Cities/Littleton/Real_Estate/Agencies/
+http://www.power2lead.com/Global/English.nsf/pgWWLocations!OpenPage&ExpandSection=21,28,29,32,22
+http://hem.fyristorg.com/bfo/gagarin/WWW.SAMIRADIO.ORG/svenska/sport-sv.html
+http://www.chaos.dk/sexriddle/e/n/q/v/m/
+http://www.hig.se/(formoutput,remove_cookie,sort,sql,sqlquery)/~jackson/roxen/
+http://129.142.8.149/ds/it/isodocs/122400/12240011/12240000117900/
+http://129.142.8.149/ds/it/isodocs/122400/12240011/12240000116400/
+http://129.142.8.149/ds/it/isodocs/122400/12240011/12240000116200/
+http://129.142.8.149/ds/it/isodocs/122400/12240011/12240000113100/
+http://129.142.8.149/ds/it/isodocs/122400/12240011/12240000110800/
+http://koi.www.citycat.ru/funny/fido/2000_10/07.html
+http://koi.www.citycat.ru/funny/fido/2000_10/09.html
+http://www.hig.se/(countdown,debug,header,if,return)/~jackson/roxen/
+http://www.findtravel.to/search_engine_directory/north_america_usa_canada/united_states/michigan/_travel_guides/
+http://mediate.magicbutton.net/do/session/625534/vsid/3255/tid/3255/cid/87978/mid/2008/rid/2157/chid/2581/url/http://www1.getmapping.com/competition/index.cfm
+http://mediate.magicbutton.net/do/session/625534/vsid/3255/tid/3255/cid/87978/mid/2008/rid/2157/chid/2581/url/http://www1.getmapping.com/aboutus/partners2.cfm
+http://www.petropages.com/products/p9827.htm
+http://www.egroups.com/login.cgi?login_target=%2Fmessage%2Fspynews%2F54
+http://health.sx.zj.cn/Treatment/SuperGuide/2000-3-8/4716.htm
+http://www.nease.net/~qin/chardware.htm
+http://www.argos.asso.fr/bourges/pratiq/emploi/texte/anpesud.htm
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-current/www/p5-Apache-Session/?S=A
+http://www.eveclub.com/cgi-bin/eveclub.front/972959425847/Catalog/1000046
+http://retailer.gocollect.com/do/session/1912628/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/top_ten.asp?pagenum=1
+http://yp.gates96.com/1/10/21/73.html
+http://yp.gates96.com/1/10/21/95.html
+http://yp.gates96.com/1/10/22/21.html
+http://yp.gates96.com/1/10/22/31.html
+http://yp.gates96.com/1/10/22/52.html
+http://yp.gates96.com/1/10/22/76.html
+http://yp.gates96.com/1/10/22/79.html
+http://yp.gates96.com/1/10/23/57.html
+http://yp.gates96.com/1/10/23/73.html
+http://yp.gates96.com/1/10/25/20.html
+http://yp.gates96.com/1/10/25/46.html
+http://yp.gates96.com/1/10/25/87.html
+http://yp.gates96.com/1/10/26/76.html
+http://yp.gates96.com/1/10/26/84.html
+http://yp.gates96.com/1/10/27/67.html
+http://yp.gates96.com/1/10/28/70.html
+http://yp.gates96.com/1/10/28/91.html
+http://live.excite.com/lifestyle/politics_and_society/countries/asia/uzbekistan/guides_and_reference/
+http://biblioteca.upv.es/bib/doc/doc_fisbd/367/114176//C/1825519/0////25/S/MLTPAI
+http://mai.flora.org/forum/5322
+http://mai.flora.org/forum/5318
+http://www.brickshelf.com/scans/0000/0715/0715-03.html
+http://www.brickshelf.com/scans/0000/0715/0715-12.html
+http://www.brickshelf.com/scans/0000/0715/0715-21.html
+http://www.msb.malmo.se/search*swe/dManikyr/dmanikyr/-5,-1,0,B/frameset&F=dmani&1,1
+http://message/cinematik/2441?expand=1
+http://message/cinematik/2447?expand=1
+http://www.jamba.de/KNet/_KNet-Rco8j1-WDd-137sh/showInfo-special1.de/node.0/cde7f1uou
+http://www.jamba.de/KNet/_KNet-Rco8j1-WDd-137ss/showInfo-hilfe.de/node.0/cde7f1uou
+http://acmepet.petsmart.com/canine/breeds/labrador/bboard/messages/5245.html
+http://acmepet.petsmart.com/canine/breeds/labrador/bboard/messages/5226.html
+http://config.tucows.com/winnt/adnload/67680_29009.html
+http://config.tucows.com/winnt/adnload/55386_29005.html
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/kdeutils/knotes/Attic/renamedlg.cpp?r1=1.7&only_with_tag=MAIN
+http://www.imagestation.com/member/?name=Twiggy5&c=1
+http://cometweb01.comet.co.uk/do!tid=20&rtid=3&vsid=700&session=131981&mid=1000&rid=1060&cid=37030&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHljbLqleHqjiLlel5jblKqlmLkeq5j1
+http://community.webshots.com/photo/1921549/2334169DWEIWPyCoH
+http://www.fogdog.com/cedroID/ssd3040183158605/nav/stores/skateboarding/
+http://www.fogdog.com/cedroID/ssd3040183158605/content/fan/subway_series/
+http://www.fogdog.com/cedroID/ssd3040183158605/boutique/ashworth/
+http://www.fogdog.com/cedroID/ssd3040183158605/customer_service/our_partners.html
+http://www.jacksonhewitt.com/ctg/cgi-bin/JacksonHewitt/media_center/AAAksrACwAAACCOAAl
+http://www.jacksonhewitt.com/ctg/cgi-bin/JacksonHewitt/talktous/AAAksrACwAAACCOAAl
+http://arabia.com/jordan/article/print/1,5130,3048|Life,00.html
+http://198.3.99.101/reference/politics_and_govt/humor/games/
+http://www.pocketbible.co.kr/old/Leviticus/Leviticus24/Leviticus24-14.htm
+http://www.ozon.ru/detail.cfm/ent=5&id=12&txt=1
+http://www.ozon.ru/detail.cfm/ent=2&id=2141
+http://www.chaos.dk/sexriddle/m/t/i/t/j/
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/5VhIq3rCy0eiHAzs1LOyTswNBIR33Wxc8NtFBCnYVNlrV5p9laRchaQrPWdU7-F739tsfX-p5-IA-j1rTm1YLCRAwn1FAriW9Ps21GP6CvyIL7YFYjLtOcez03i6Q9Xw3LRDtJY2CIzGQuZp-sH_-s_D66j9
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/lKhIoWbn-weE729M1n0JT8Ina4qOfm_FI2ROg8RdrrVu5kq_AK_urPMHafLCMwWCiOLuc8OIIHCFnJaCfz2LSrURBHFjDJP1fBO0X58Y28opSv0qVXWAKYtub7NbCIIWMbE_ldcypBmh
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/PbhIoduIKw3faQWbBTWSK5aq7Y-nGqcvK3flLaTRo02t7k7GMY8rPlupJIheD8869wCXUAer4VimzyYa25qUx7ef2l2VdMR9i_p-pJ5gg2S6ZcP-G6RuPfdDS3TEsJNXGVsOTs1rA605
+http://www.linux.com/networking/network/development/web_server/performance/?printable=yes
+http://www.linux.com/networking/network/development/web_server/performance/IBM/
+http://sunsite.icm.edu.pl/Linux/Documentation/HOWTO/mini/IP-Subnetworking-3.html
+http://dreamcity.gaiax.com/www/dreamcity/m/s/musou/frame.html
+http://guardian.co.uk/Widgets/Read_It_Later/TR/1,4694,4043922,00.html
+http://www.gpul.org/ftp/os/infinite/?M=A
+http://www.gpul.org/ftp/os/infinite/infinite_OS.txt
+http://retailer.gocollect.com/do/session/1912666/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/exclusives/exclusives.asp
+http://yp.gates96.com/13/77/10/66.html
+http://yp.gates96.com/13/77/10/91.html
+http://yp.gates96.com/13/77/11/82.html
+http://yp.gates96.com/13/77/12/17.html
+http://yp.gates96.com/13/77/13/68.html
+http://yp.gates96.com/13/77/13/80.html
+http://yp.gates96.com/13/77/16/3.html
+http://yp.gates96.com/13/77/16/17.html
+http://yp.gates96.com/13/77/16/49.html
+http://yp.gates96.com/13/77/17/8.html
+http://yp.gates96.com/13/77/18/4.html
+http://yp.gates96.com/13/77/18/61.html
+http://yp.gates96.com/13/77/18/71.html
+http://yp.gates96.com/13/77/19/3.html
+http://yp.gates96.com/13/77/19/24.html
+http://yp.gates96.com/13/77/19/48.html
+http://yp.gates96.com/13/77/19/98.html
+http://yp.gates96.com/13/77/19/99.html
+http://scsinternet.tucows.com/winnt/mail95.html
+http://tolm.terrashare.com/45.htm
+http://news.dreamwiz.com/news/08/20001030/kukmin/200010301903081903261.html
+http://www.tccomputers.com/cgi-bin/bp/1463655603/services/info/tci.htm
+http://www.tccomputers.com/cgi-bin/bp/1463655603/services/csc/csc.htm
+http://www.2pl.com/b/pl/to/1/01/04/v2/1010400016-6-2r.htm
+http://www.2pl.com/b/pl/to/1/01/04/v2/1010400016-3-2r.htm
+http://www.2pl.com/b/pl/to/1/01/04/v2/1010400016-18-2r.htm
+http://www.2pl.com/b/pl/to/1/01/04/v2/1010400016-1r.htm
+http://www.123bestphonerates.com/q/001p/vn/vR85aEOIaY.htm
+http://www.thisislancashire.co.uk/lancashire/archive/1997/07/17/SPORTST5VQ.html
+http://www.thisislancashire.co.uk/lancashire/archive/1997/07/17/SPORTST7VQ.html
+http://www.thisislancashire.co.uk/lancashire/archive/1997/07/17/SPORTST11VQ.html
+http://www.elsur.cl/archivo/marzo2000/13marzo2000/elsur/deportes/ind3.php3
+http://home.no.net/fristart/kvasir816/
+http://www.fun7.de/party/cafe_europa/_vti_cnf/?D=A
+http://www.users.yun.co.jp/cgi-bin/moriq/pigeon/pigeon.cgi/%C5%E7%BA%AC%B8%A9.%C2%E7%B8%B6%B7%B4%C2%E7%C5%EC%C4%AE?c=e
+http://polygraph.ircache.net:8181/http_-2www.whowhere.com/http_-2www.expired.com/html/service.html
+http://home.t-online.de/home/mtc.hannover/head1655833.htm
+http://moneycentral.msn.com/investor/invsub/insider/Details.asp?Pval=1&Symbol=MKSI
+http://www.sohu.com/Regional/hunan/City_County/Yiyang/Firms/Food_Beverage/
+http://www.kulturkreis-rhein-lahn.de/lauer/fax.htm
+http://ustlib.ust.hk/search*chi/aporter+bill+1943/aporter+bill+1943/7,-1,0,B/browse
+http://www.brio.de/BRIO.catalog/39fe2f3708fb3c8e2740d472aa7806d5/UserTemplate/2
+http://www.brio.de/BRIO.catalog/39fe2f3708fb3c8e2740d472aa7806d5/UserTemplate/6
+http://rcsl.auto.inha.ac.kr/~treeman/Documents/HOWTO/Keyboard-and-Console-HOWTO-19.html
+http://www.etoys.com/cat/toy/category/construction/brio_builder_system/1
+http://www.kxmd.com/now/story/0,1597,194790-295,00.shtml
+http://www.ferien-immobilien.de/DominikanischeRep/verkauf/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/Gemeinsam/Gemeinsam/versicherungen/gebaeude/IIM-Teil/Startseite/froben.htm
+http://hiv.medscape.com/LWW/SMD/1999/v21.n03/smd2103.01.html
+http://www.egroups.com/message/dk-jaws/530
+http://no.egroups.com/message/daemon-news-announce/12
+http://ring.toyama-ix.net/archives/text/elisp/jaist/yamaoka/apel/00_THIS_DIRECTORY_WILL_NOT_BE_UPDATED_UNTIL_2000-10-26
+http://pub12.ezboard.com/ftibesataxg1637tibes.subscribeUnregisteredToTopic?topicID=7.topic
+http://ustlib.ust.hk/search*chi/ali+huan+1827+1891/ali+huan+1827+1891/-5,-1,0,E/frameset&F=ali+huan&4,,0
+http://ustlib.ust.hk/search*chi/ali+huan+1827+1891/ali+huan+1827+1891/-5,-1,0,E/frameset&F=ali+huang+1895&1,,0
+http://www.digitalcity.com/cincinnati/sports/log.dci?league=NCF&team=NNF
+http://ftp.nacamar.de/pub/debian/dists/potato/main/disks-m68k/2.2.16-2000-07-14/mac/images-1.44/?D=A
+http://www.academyfloral.com/state/arboo/flowers/thanksabunchbouquet2.html
+http://dante.bdp.it/cgi-bin/poseidon_v2.0/reflect/poseidon/disc/peacelink-scuola/2015003604/view/8
+http://ring.omp.ad.jp/pub/NetBSD/NetBSD-current/pkgsrc/lang/smalltalk/files/?S=A
+http://ring.omp.ad.jp/pub/NetBSD/NetBSD-current/pkgsrc/lang/smalltalk/files/patch-sum
+http://carriage.de/Schoner/Sammlungen/literature/collections/literature/modelle/
+http://www.buybuddy.com/sleuth/27/1/11001/1692/
+http://193.120.14.241/pub/languages/perl/CPAN/src/5.0/devel/
+http://lastminutetravel.bedandbreakfast.com/bbc/p208900.asp
+http://chat.sportsline.com/u/wire/stories/0,1169,2957692_59,00.html
+http://acad.uis.edu/sas/qc/q-index.htm
+http://acad.uis.edu/sas/qc/s-index.htm
+http://library.cuhk.edu.hk/search*chi/aPan,+Zhuonan./apan+zhuonan/-5,1,1,B/frameset&F=apan+zhichang+1956&1,1,
+http://www.linux.com/networking/network/install/tools/updates/new/
+http://www.linux.com/networking/network/install/tools/updates/Standards/
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=13,31,5,11,26
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=23,31,5,11,26
+http://www.mfa.no/fin/norsk/publ/stprp/006005-991562/index-hov017-b-n-a.html
+http://ftp.sunet.se/pub/lang/perl/CPAN/authors/id/DBEAZLEY/?N=D
+http://fi.egroups.com/messages/infoespo/6?expand=1
+http://ibc.cn.net/2000/0718/it-1message.html
+http://www.shaggysguide.com/conhtml/adnload/51647_1809.html
+http://www.shaggysguide.com/conhtml/adnload/51657_5567.html
+http://www.shaggysguide.com/conhtml/adnload/74370_17872.html
+http://www.shaggysguide.com/conhtml/adnload/78469_19520.html
+http://www.shaggysguide.com/conhtml/adnload/78940_19788.html
+http://www.backflip.com/members/jhferrara/5171381/page=1/sort=1/linkspp=10
+http://www.amcity.com/philadelphia/stories/1998/08/24/newscolumn3.html?t=printable
+http://www.rge.com/pub/tex/biblio/bibtex/ms-dos/demel/?N=D
+http://www.v2music.com/Scripts/WebObjects-ISAPI.dll/V2_New_Publisher.woa/67841000005885200000309700000064451/Giveaways.wo/257820000054451/2.0.0.6.0/3/Webobjects1
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/www-gds.desy.de:8080/zeitpl/zpl.htm
+http://click-to.tell-a-friend.boardhost.com/tell-a-friend-confirm.cgi?chudtvlogic&msg=1596
+http://retailer.gocollect.com/do/session/1912639/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/clubhouse/suggestions.asp
+http://www.jpc-music.com/5590216.htm
+http://huntingfishing.tripod.com/sturgeonmain.htm
+http://polygraph.ircache.net:8181/wwwboard/prodev/seminar/fast/http_-2www.centennialcc.org/bps.html
+http://www.chaos.dk/sexriddle/s/t/c/x/l/
+http://www.chaos.dk/sexriddle/s/t/c/x/z/
+http://es.egroups.com/messages/plato-meno/1285
+http://tonggu-gch.ed.seoul.kr/home/2grade/2-10/981001/hang.htm
+http://sjsulib1.sjsu.edu:81/search/dreligion/-5,-1,0,E/exact&dreligion+libraries&1,3
+http://www.generation-formation.fr/chiffrec.htm---o21zAo0UPwo0Ol9A074fo6Td4ezyr6feZJPAPfVbNyqHSezTHkekydMfeZJPdspt6dsSAtdsNhJdspt6dsrvrdjlhkfbd.htm
+http://www.generation-formation.fr/dicoguid/diclogin.htm---o21zAo0UPwo0Ol9A074fo6Td4ezyr6feZJPAPfVbNyqureds5cezwhlezMpDeH7vGebI1yoKkfMd4vmMAxaAooKkfMd4u5xdfb7rmdfbT.htm
+http://www.hollywoodonline.com/asplocal/mgvideoad.asp?rushhour-video-holdon-mov
+http://www.ifg.uni-kiel.de/doc-clients/kdelibs-doc/html/kdeui/full-list-KRestrictedLine.html
+http://www.3w-sciencefiction.de/ShapiroLarry/ShapiroLarry0760306729.htm
+http://202.96.140.98/js/wenge/
+http://www.great-cyber-mall.com/SelectCompany.asp?CityID=230&CatID=19
+http://www.great-cyber-mall.com/SelectCompany.asp?CityID=230&CatID=34
+http://www.amazon.com.hk/exec/obidos/tg/stores/browse/-/books/13361/
+http://www.hole.kommune.no/hole/journweb.nsf/weboffjournal!OpenView&Start=99&Count=50&Collapse=116
+http://www.pbase.com/image/35702/small
+http://www.infoscape.com.cn:8171/nf/0010/21/nfzy2104.htm
+http://dell.excite.com/photo/topic/weather/national/19
+http://www.linux.com/networking/network/network/firewall/microsoft/government/
+http://www.gasex.com/gay.photo/gay.penis.pics.html
+http://hausarbeiten.de/cgi-bin/superDBinters.pl/archiv/geschichte/gesch-stedinger.shtml
+http://polygraph.ircache.net:8181/http_-2www.microsoft.com/frontpage/http_-2www.exploreuw.com/cards/ssoenews.html
+http://www.fogdog.com/cedroID/ssd3040183137325/cgi-bin/MyFogdog
+http://www.fogdog.com/cedroID/ssd3040183137325/cgi-bin/CedroCommerce?func=EditBasket
+http://www.fogdog.com/cedroID/ssd3040183137325/nav/stores/cycling/
+http://www.fogdog.com/cedroID/ssd3040183137325/nav/stores/snowboarding/
+http://tucows.wanadoo.nl/win2k/organ2k_license.html
+http://tucows.wanadoo.nl/win2k/preview/59164.html
+http://windows.tucows.com/preview/001-009-005-005C.html
+http://anekdotwall.boom.ru/car/html/75.htm
+http://tucows.concepts.nl/win2k/clipb2k_size.html
+http://tucows.concepts.nl/win2k/adnload/37291_29917.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=cricrila&l=pt
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=cricrilava&l=pt
+http://www.trax.nilex.co.uk/trax.cgi/A1C/1AR/A2S/A3S/A3D/D1S/
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/12_ngqyjt_ngqyjt.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/12_rtnucb_tyciyrg.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/12_kiektgt_fpwif.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/12_rjdbc_rjdbc.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/12_xsygo_xsygo.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/12_bovqcy_mkaqta.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/12_lgbrnl_psnjjt.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/12_lgbrnl_ybvfp.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/12_vermn_xmxmm.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/12_keojvu_faoex.html
+http://info-china.hypermart.net/enterprise/company/messages/25.html
+http://ring.yamanashi.ac.jp/pub/linux/debian/debian-jp/dists/potato/non-US/contrib/binary-m68k/Release
+http://www.amigos.com/cgi-bin/w3com/pws/ffe/R7RIRASjZ5ATyRjNyXQBbwzK4LLK-rhgzZEBqJsLaR1cdnaeB7LT1xORWRg6aQmLxO7QWLEpsdjuf2ZqAnUO1IKpfrRctaIMYIzMNy1DSb7dp8_5z39WdF7oxbKUAByA
+http://indigotrem1.chemie.uni-mainz.de/~manng001/Filme/S/SexLuegenundVideo.html
+http://se.egroups.com/message/hur/387
+http://www.ilmessaggero.it/hermes/19990111/07_MARCHE/MARCHE_REGIONE/DUE.htm
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/lit/quizz/misc/colorart/lit/pushkin.html
+http://www.amzn.com/exec/obidos/ts/artist-glance/201040/ref=pm_dp_ln_m_6/
+http://tucows.netpower.no/winme/adnload/138674_29970.html
+http://www.chaos.dk/sexriddle/z/d/q/p/c/
+http://www.chaos.dk/sexriddle/z/d/q/p/u/
+http://sv.pachinkovillage.co.jp/catalog/DinoVaderB/3.html
+http://ww2.comune.fe.it/cgi-win/hiweb.exe/a2/B1,a,1f,6,6,3a,3a,,5,,1f,5,
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=deflazioneranno&l=it
+http://polygraph.ircache.net:8181/company/html/http_-2www.io.com/~kinnaman/pchealth/f-agents.html
+http://polygraph.ircache.net:8181/company/html/http_-2www.io.com/~kinnaman/pchealth/f-leisureworld.html
+http://ftp.univie.ac.at/packages/perl/modules/by-module/Tie/ILYAZ/cperl-mode/rms-emacs-20.2-patch-narrow-buffer+dirfiles
+http://www.expressindia.com/ie/daily/19991126/ige26097p.html
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/ELINKEINO-+JA+YRITYSTOIMINTA/yritt%E4jyys/lukio/oppimateriaali/itseopiskelu/
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=36,23,11,33,18
+http://www.trib.com/scjournal/ARC/1996/MAR/3_24_96/marines.html
+http://www.slac.stanford.edu/BFROOT/www/Computing/Programming/QA/QaBetaTools/6.7.5a/SunOS5/?S=D
+http://pokemonplant.tripod.com/150yellow.html
+http://ftp.debian.org/dists/potato/contrib/binary-all/devel/?N=D
+http://sunsite.org.uk/packages/tcl/Collections/ftp.neosoft.com/sorted/packages-8.0/print/frink/1.2p35/
+http://library.bangor.ac.uk/search/m304.6+LIN/m304.6+lin/-5,-1,0,B/frameset&F=m304.6+jos&1,1
+http://members.tripod.lycos.nl/janninksweg145/huis.htm
+http://www.uib.no/People/mihtr/PS01/PS01_219.htm
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus141561/eus174865/eus327367/eus327602/eus329879/
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus141561/eus174865/eus327367/eus327602/eus327608/
+http://sound-dist.secured.co.uk/cgi-bin/psShop.cgi/add|39P02|972959512|Communications|user|0|1,0,0,1
+http://www.bluefreds.f9.co.uk/vote2.html
+http://www.hri.org/docs//statedep/1999/99-05-07.std.html
+http://polygraph.ircache.net:8181/http_-2www.hblinfo.com/f_snowbuddies.html
+http://mediate.magicbutton.net/do/session/625565/vsid/3342/tid/3342/cid/88020/mid/2008/rid/2313/chid/2648/url/http://www1.getmapping.com/products.cfm
+http://cometweb01.comet.co.uk/do!tid=20&rtid=2&vsid=692&session=131975&mid=1000&rid=1060&cid=37051&chid=1702&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplG5ubLZDXLZolLl3l5jbqLlci5XqVLkXsLkao4tloHbmlLoq5
+http://digilander.iol.it/net4free/spedia.htm
+http://totalsports.aol.com/stats/bbo/mlb/20000425/col.at.mon.prvw.html
+http://210.178.135.1/netbbs/Bbs.cgi/nhic32042/qry/pno/0/zka/B2-kB2Zk/qqatt/^
+http://cikkek.lezlisoft.com/kikelet/spiritualitas/spirit3v9.shtml
+http://www.wingateinns.com/ctg/cgi-bin/Wingate/aarp/AAAksrACwAAACCPAAl
+http://sunsite.berkeley.edu/PhiloBiblon/BITAGAP/BIB/BIB1848.html
+http://sunsite.uakom.sk/tucows/adnload/69390_28371.html
+http://sunsite.uakom.sk/tucows/preview/77630.html
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=(22,0+9,0-~0,3
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=(22,0+9,0-~9,6
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=(22,0+9,0-~21,0
+http://sirac.inrialpes.fr/Infos/Personnes/Christophe.Rippert/ressources/jdk1.2.2/docs/api/java/security/
+http://polygraph.ircache.net:8181/getting_started/http_-2www.microsoft.com/powered/radio/email_pal/email_pal.htm
+http://mirror.nucba.ac.jp/mirror/FreeBSD/branches/2.2-stable/ports/net/tund/?M=A
+http://mirror.nucba.ac.jp/mirror/FreeBSD/branches/2.2-stable/ports/net/tund/?D=A
+http://library.bangor.ac.uk/search/tNursing+times+clinical+monographs+&%2359%3B+no.+51/tnursing+times+clinical+monographs+no+++51/-17,-1,0,B/browse
+http://library.bangor.ac.uk/search/tNursing+times+clinical+monographs+&%2359%3B+no.+51/tnursing+times+clinical+monographs+no+++51/-5,-1,0,B/frameset&F=tnursing+times+complementary+therapy&1,1
+http://ftp.chg.ru/pub/FreeBSD/doc/en_US.ISO_8859-1/articles/programming-tools/
+http://polygraph.ircache.net:8181/getting_started/http_-2www.microsoft.com/powered/bomb/bomb.htm
+http://linux.tucows.inwind.it/conhtml/adnload/8523_5414.html
+http://www.magicvillage.de/magicvillage/KonferenzPlaza/fbs/%2328835852?NextInThread
+http://www.shopworks.com/samplers/index.cfm/action/cart/userid/0009CECE-2EE1-19FE-9038010B0A0ADCF2
+http://dailynews.sina.com/newsCenter/taiwan/udn/2000/1021/2051701_b5.html
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/kdeutils/khexedit/pics/Attic/?hideattic=1&sortby=date
+http://moviestore.zap2it.com/browse/MOVIES/BOWL/s.zchC6lsi
+http://moviestore.zap2it.com/browse/MOVIES/MUSIC/s.zchC6lsi
+http://ww2.comune.fe.it/cgi-win/hiweb.exe/a2/d13/b12,c,1f,18,18,,13,,1f,13,17,,1f,17,
+http://ww2.comune.fe.it/cgi-win/hiweb.exe/a2/d14/b12,c,1f,18,18,,13,,1f,13,17,,1f,17,
+http://209.50.251.176/~bb/
+http://tucows.energy.it/winnt/adnload/59163_30035.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=circundara&l=pt
+http://vishvesha.tripod.com/4/068d.htm
+http://www.hot.ee/timbsy/kass_files/pildikogu.html
+http://www3.newstimes.com/archive99/jan2599/rga.htm
+http://pub11.ezboard.com/fmarjoriesdmboardpostyourdmpedigreeshere.showMessage?topicID=21.topic
+http://www.geocities.com/Heartland/Plains/4825/bennyn.html
+http://citeseer.nj.nec.com/site/115145
+http://www.techsupplies.com/sleuth/17/1/40406/254200/
+http://ccmnet.xj.cei.gov.cn/10/b10/b1007/99-05-02/a5-02.asp
+http://206.251.18.85/FEATURES/home_improvement/1999/10/01/fall_lawncare3.html
+http://www.dulux.co.uk/UKRETAIL:1355333640:DFinity.1QJiP4jmPgimjKlA
+http://cometweb01.comet.co.uk/do!tid=20&rtid=2&vsid=700&session=131985&mid=1000&rid=1060&cid=37030&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplG5ubLZDXLZolLl3l5jbqLlci5XqVLkXsLkao4tloHbmlLoq5
+http://cometweb01.comet.co.uk/do!tid=20&rtid=1&vsid=700&session=131985&mid=1000&rid=1060&cid=37030&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplGGolLarZLq4fLpmiLXv-KmooLckYLoznGmpq0qsc0mojLbkYLozvGotc0ZdoLckYLozvGsmv0qmc0jXfLkVZLdocLkYoLzcj1XfkLVZXLqkXLjbzKcob5qroLkVrLoizKlZd5fjYHfklKkZlLjjbLoZbLpl51ubZLDXZLollK3ljLbqlKjXfLkkaHotl4obmLloqL
+http://www.berliner-morgenpost.de/bm/inhalt/990928/berlin/story14.html
+http://gb.toget.com.tw/article/printer_tool/19990825_3210_p1.html
+http://sbtr42.sbsusa.com/ncsamples/base1.htm
+http://halflife02.opasia.dk/cs3stats/players/_AMNeSIA_.html
+http://mediate.magicbutton.net/do/session/625570/vsid/3342/tid/3342/cid/88020/mid/2008/rid/2313/chid/2648/url/http://www1.getmapping.com/basket.cfm
+http://mediate.magicbutton.net/do/session/625570/vsid/3342/tid/3342/cid/88020/mid/2008/rid/2313/chid/2648/url/http://www1.getmapping.com/viewer.cfm
+http://www.citythek.de/erfurt/rheinhyp/fsinhalt.htm
+http://my.egroups.com/group/mall-komputer
+http://www-bd.cricket.org/link_to_database/ARCHIVE/1997-98/PAK_IN_RSA/PAK_IN_RSA_JAN-APR1998_PAK-SQUAD.html
+http://www-bd.cricket.org/link_to_database/GROUNDS/RSA/ST-GEORGE_PARK_PT-ELIZ/
+http://www-bd.cricket.org/link_to_database/ARCHIVE/1997-98/PAK_IN_RSA/PAK_RSA_T3_06-10MAR1998_ET_MR.html
+http://www.bemi-immobilien.de/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Gemeinsam/versicherungen/unfall/Gemeinsam/erreichenPartner/Gemeinsam/MarketingStrategie/Gemeinsam/versicherungen/gebaeude/Gemeinsam/Top-Darlehens-Konditionen/anforderungsformular.htm
+http://www.online.kokusai.co.jp/Qa/V0043459/wrd/G800/qa/
+http://iland.tucows.com/win2k/adnload/59229_29990.html
+http://iland.tucows.com/win2k/preview/144411.html
+http://iland.tucows.com/win2k/adnload/38173_29963.html
+http://www.arm.com/sitearchitek/armtech.ns4/8ab0ea422fba51238025691f00399e13/9cb09cb360a967848025691f004e28b2!OpenDocument&ExpandSection=6,13,12,-1
+http://ftp.uni-mannheim.de/languages/perl/CPAN/modules/by-authors/id/JMURPHY/?N=D
+http://proam.golfonline.com/tours/2000/hooters/silversprings/scores2.html
+http://ftp.du.se/pub/FreeBSD/branches/4.0-stable/src/games/grdc/
+http://ftp.du.se/pub/FreeBSD/branches/4.0-stable/src/games/pom/
+http://ftp.du.se/pub/FreeBSD/branches/4.0-stable/src/games/Makefile
+http://www.artex.firenze.it/_qualitart/articoli/zoom/03651.htm
+http://www.chaos.dk/sexriddle/m/k/v/b/p/
+http://www.chaos.dk/sexriddle/m/k/v/b/s/
+http://www.chaos.dk/sexriddle/t/j/d/n/n/
+http://www.daysinn.com/ctg/cgi-bin/DaysInn/media_center/AAAksrACwAAACCQAAM
+http://tukela.heha.net/ys/ll/boyuan.htm
+http://tukela.heha.net/ys/ll/jinciming.htm
+http://genforum.genealogy.com/ai/messages/4299.html
+http://genforum.genealogy.com/ai/messages/4221.html
+http://genforum.genealogy.com/ai/messages/4225.html
+http://www.linkclub.or.jp/~sticky/index1/diary/1999/199906.html
+http://ww.egroups.com/subscribe/lexingtonkystrapon
+http://chita.fi.upm.es/docs/info/en_US/a_doc_lib/motif/motifsg/About.htm
+http://chita.fi.upm.es/docs/info/en_US/a_doc_lib/motif/motifsg/motifsg41.htm
+http://chita.fi.upm.es/docs/info/en_US/a_doc_lib/motif/motifsg/motifsg43.htm
+http://hakuba-net.gr.jp/guide/rest/spa_each/spa_2.html
+http://yp.gates96.com/6/16/40/22.html
+http://yp.gates96.com/6/16/40/44.html
+http://yp.gates96.com/6/16/40/50.html
+http://yp.gates96.com/6/16/40/69.html
+http://yp.gates96.com/6/16/40/83.html
+http://yp.gates96.com/6/16/41/49.html
+http://yp.gates96.com/6/16/41/50.html
+http://yp.gates96.com/6/16/41/67.html
+http://yp.gates96.com/6/16/42/15.html
+http://yp.gates96.com/6/16/42/51.html
+http://yp.gates96.com/6/16/42/56.html
+http://yp.gates96.com/6/16/43/8.html
+http://yp.gates96.com/6/16/43/69.html
+http://yp.gates96.com/6/16/43/71.html
+http://yp.gates96.com/6/16/44/11.html
+http://yp.gates96.com/6/16/44/51.html
+http://yp.gates96.com/6/16/45/20.html
+http://yp.gates96.com/6/16/45/43.html
+http://yp.gates96.com/6/16/46/12.html
+http://yp.gates96.com/6/16/46/25.html
+http://yp.gates96.com/6/16/46/64.html
+http://yp.gates96.com/6/16/47/42.html
+http://yp.gates96.com/6/16/47/80.html
+http://yp.gates96.com/6/16/48/54.html
+http://yp.gates96.com/6/16/48/85.html
+http://yp.gates96.com/6/16/49/51.html
+http://yp.gates96.com/6/16/49/62.html
+http://assgay.com/main.html?fuck.cock.gaysex
+http://ring.yamanashi.ac.jp/pub/linux/linuxppc/contrib/software/System_Environment/Libraries/?S=A
+http://computalynx.tucows.com/winme/adnload/138681_29976.html
+http://computalynx.tucows.com/winme/adnload/138706_29992.html
+http://computalynx.tucows.com/winme/adnload/138690_29990.html
+http://computalynx.tucows.com/winme/adnload/138694_29981.html
+http://iceberg.adhomeworld.com/cgi-win/redirect.exe/851857198
+http://link.fastpartner.com/do/session/600337/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/mondosoft.php
+http://link.fastpartner.com/do/session/600337/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/nordicliving.php
+http://link.fastpartner.com/do/session/600337/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/create/learn.htm
+http://www.linux.com/networking/network/applications/hardware/device/development/
+http://www.linux.com/networking/network/applications/hardware/device/Corel/
+http://www.linux.com/networking/network/applications/hardware/device/?kw_offset=50
+http://ftp.gigabell.net/debian/dists/unstable/main/binary-m68k/sound/?M=A
+http://no.egroups.com/message/slfxpzur/36
+http://no.egroups.com/message/slfxpzur/38
+http://nuance.dhs.org/lbo-talk/0004/2286.html
+http://www.jamba.de/KNet/_KNet-XEk8j1-ADd-136sq/showInfo-datenschutz.de/node.0/cde7f1uou
+http://yp.gates96.com/2/37/60/0.html
+http://yp.gates96.com/2/37/60/13.html
+http://yp.gates96.com/2/37/61/24.html
+http://yp.gates96.com/2/37/61/66.html
+http://yp.gates96.com/2/37/62/5.html
+http://yp.gates96.com/2/37/62/31.html
+http://yp.gates96.com/2/37/63/31.html
+http://yp.gates96.com/2/37/63/43.html
+http://yp.gates96.com/2/37/63/48.html
+http://yp.gates96.com/2/37/63/60.html
+http://yp.gates96.com/2/37/63/88.html
+http://yp.gates96.com/2/37/64/62.html
+http://yp.gates96.com/2/37/64/74.html
+http://yp.gates96.com/2/37/65/0.html
+http://yp.gates96.com/2/37/66/20.html
+http://yp.gates96.com/2/37/67/41.html
+http://yp.gates96.com/2/37/68/2.html
+http://yp.gates96.com/2/37/68/50.html
+http://yp.gates96.com/2/37/69/15.html
+http://yp.gates96.com/2/37/69/41.html
+http://yp.gates96.com/2/37/69/47.html
+http://yp.gates96.com/2/37/69/60.html
+http://yp.gates96.com/2/37/69/75.html
+http://yp.gates96.com/2/37/69/76.html
+http://gettosdownloads.subportal.com/sn/Palm_Pilot/Games/12428.html
+http://news.novgorod.ru/read/65/2000/10/27/10/49
+http://www.schwan.de/links-biografie.html
+http://www.fogdog.com/cedroID/ssd3040183124617/cgi-bin/MyFogdog
+http://www.nrk.no/finnmark/x27_6_97/nyh9.htm
+http://www.aelita.net/products/news/services/sitemap/~archive/Download_redirect/company/Copyright.htm
+http://www.staroriental.net/nav/soeg_c/ihf,aol,n15,149,TVB香港小姐2000.html
+http://members.xoom.com/agent187/politics.htm
+http://sunsite.org.uk/public/packages/perl/collections/cis.ufl/comp.lang.perl.announce/1998-03/724
+http://www.thestateofcolorado.com/gcecommercialsales.html
+http://ftp.du.se/pub/redhat/rawhide/sparc/RedHat/RPMS/?M=A
+http://www.linux.com/networking/network/community/trade_show/magazine/open_source/
+http://www.linux.com/networking/network/community/trade_show/magazine/Slashdot/
+http://www.linux.com/networking/network/community/trade_show/magazine/investors/
+http://scifi.emerchandise.com/browse/TV/PIN/b.TV/s.KkOtzPMn
+http://scifi.emerchandise.com/browse/DILBERT/_/b.TV/s.KkOtzPMn
+http://scifi.emerchandise.com/browse/DR.KATZ/_/b.TV/s.KkOtzPMn
+http://scifi.emerchandise.com/browse/FRIENDS/_/b.TV/s.KkOtzPMn
+http://scifi.emerchandise.com/browse/FUTURAMA/_/b.TV/s.KkOtzPMn
+http://scifi.emerchandise.com/browse/LOIS-CLARK/_/b.TV/s.KkOtzPMn
+http://scifi.emerchandise.com/browse/SPEEDRACER/_/b.TV/s.KkOtzPMn
+http://scifi.emerchandise.com/browse/THUNDERCATS/_/b.TV/s.KkOtzPMn
+http://scifi.emerchandise.com/browse/WCW/_/b.TV/s.KkOtzPMn
+http://www.railion.de/home/db_reise_touristik/region/bremen/db_rt_firmenreisedienst_reisezentrum_hb.shtml
+http://pegasus.infor.kanazawa-it.ac.jp/~hara/bsd4.1-release/D/N_GETFLAG_NET.html
+http://yp.gates96.com/5/54/20/19.html
+http://yp.gates96.com/5/54/21/5.html
+http://yp.gates96.com/5/54/21/42.html
+http://yp.gates96.com/5/54/21/60.html
+http://yp.gates96.com/5/54/21/69.html
+http://yp.gates96.com/5/54/21/81.html
+http://yp.gates96.com/5/54/21/96.html
+http://yp.gates96.com/5/54/22/6.html
+http://yp.gates96.com/5/54/22/29.html
+http://yp.gates96.com/5/54/22/33.html
+http://yp.gates96.com/5/54/22/64.html
+http://yp.gates96.com/5/54/22/83.html
+http://yp.gates96.com/5/54/22/94.html
+http://yp.gates96.com/5/54/22/98.html
+http://yp.gates96.com/5/54/23/17.html
+http://yp.gates96.com/5/54/23/41.html
+http://yp.gates96.com/5/54/24/2.html
+http://yp.gates96.com/5/54/24/5.html
+http://yp.gates96.com/5/54/24/9.html
+http://yp.gates96.com/5/54/24/90.html
+http://yp.gates96.com/5/54/25/89.html
+http://yp.gates96.com/5/54/26/41.html
+http://yp.gates96.com/5/54/27/83.html
+http://yp.gates96.com/6/59/21/52.html
+http://yp.gates96.com/6/59/22/63.html
+http://yp.gates96.com/6/59/23/37.html
+http://yp.gates96.com/6/59/23/95.html
+http://yp.gates96.com/6/59/24/3.html
+http://yp.gates96.com/6/59/24/9.html
+http://yp.gates96.com/6/59/25/26.html
+http://yp.gates96.com/6/59/25/55.html
+http://yp.gates96.com/6/59/25/84.html
+http://yp.gates96.com/6/59/25/94.html
+http://yp.gates96.com/6/59/26/53.html
+http://yp.gates96.com/6/59/26/73.html
+http://yp.gates96.com/6/59/27/15.html
+http://yp.gates96.com/6/59/27/29.html
+http://yp.gates96.com/6/59/27/49.html
+http://yp.gates96.com/6/59/27/97.html
+http://yp.gates96.com/6/59/28/31.html
+http://yp.gates96.com/6/59/28/32.html
+http://yp.gates96.com/6/59/28/39.html
+http://yp.gates96.com/6/59/28/98.html
+http://yp.gates96.com/6/59/29/22.html
+http://yp.gates96.com/6/59/29/83.html
+http://www.gbnf.com/genealogy/royal92/html/d0016/I1249.HTM
+http://www.gbnf.com/genealogy/royal92/html/d0018/I734.HTM
+http://hifichoice.co.uk/archive/perl/193_printreview.htm
+http://hifichoice.co.uk/archive/perl/313_printreview.htm
+http://www.highwired.net/Paper/UniversalNav/Redirect/0,5314,2623-7802,00.html
+http://www.mrlinux.notrix.de/
+http://www.ucalgary.ca/UofC/faculties/medicine/CHS/nhrdb/area/anat/fr.htm
+http://home.pchome.com.tw/tv/pili0614/xing-sh/capric/capric47.htm
+http://home.pchome.com.tw/tv/pili0614/xing-sh/capric/capric21.htm
+http://home.pchome.com.tw/tv/pili0614/xing-sh/capric/caf26.htm
+http://user.chollian.net/~pleiad7s/josun/3-37.htm
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=233&discrim=81,3,15
+http://mediate.magicbutton.net/do/session/625571/vsid/3342/tid/3342/cid/88020/mid/2008/rid/2313/chid/2648/url/http://www1.getmapping.com/aboutus/index.cfm
+http://www.telecombrokers.com/q/001p/atn8/2aS9DLAZRXc.htm
+http://www.telecomrefunds.com/q/001p/atn8/4SeFiiXvs2A.htm
+http://soho.nascom.nasa.gov/solarsoft/soho/lasco/lasco/data_anal/data/9701/?M=A
+http://members.xoom.com/mindnare
+http://people.freenet.de/TheChamp/nachhilfe.htm
+http://people.freenet.de/TheChamp/cheats.htm
+http://www.zinezone.com/movies/1,4003,1040-23080,00.html
+http://kulichki-win.rambler.ru/moshkow/TURIZM/kutsajo6.txt_with-icons.html
+http://www.linux.com/networking/network/release/availability/hardware/?printable=yes
+http://www.linux.com/networking/network/release/availability/hardware/applications/
+http://www.shopworks.com/flmp/index.cfm/action/cart/userid/000D1850-2F00-19FE-9038010B0A0ADCF2
+http://shrike.depaul.edu/~afranz/multimedia/?S=A
+http://totalsports.net/news/20001014/bbo/mlb/sea/001014.0024.html
+http://totalsports.net/news/20001009/bbo/mlb/sea/001009.0039.html
+http://totalsports.net/news/20001006/bbo/mlb/sea/001006.0354.html
+http://cometweb01.comet.co.uk/do!session=131986&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkkHbqpLZXmLbkZHljlKaltLkilLXalKfkaLbukKeqjLi1
+http://html.tucows.ciaoweb.it/adnload/berglincondlbind.html
+http://www.tiscover.com/1Root/Interessante_Region/127151/sportfreizeit/m_sportfreizeit.wm_sport_freibad..1.html
+http://f24.parsimony.net/forum54080/messages/97.htm
+http://f24.parsimony.net/forum54080/messages/68.htm
+http://www.amulation.com/md-l-archive/199702/msg00210.html
+http://netpower.tucows.com/winnt/adnload/2821_29573.html
+http://kutschen.de/Schoner/Info-d/literature/collections/collections/Geschichte/
+http://webtools.myschoolonline.com/page/0,1871,0-353-38-44534,00.html
+http://www.linux.com/networking/network/help/hardware/open_source/GNOME/
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=12,25,26,17,24
+http://retailer.gocollect.com/do/session/1912664/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/exclusives/exclusives.asp
+http://retailer.gocollect.com/do/session/1912665/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/news/index.asp
+http://ring.nihon-u.ac.jp/pub/doc/jpnic/members/WORLDNET/members.txt
+http://www.123webagent.com/q/001p/atn8/zImXxARDSm.htm
+http://www.tu-chemnitz.de/~jflo/DOSDemos/cost_b.txt
+http://yp.gates96.com/5/54/27/97.html
+http://yp.gates96.com/5/54/28/23.html
+http://yp.gates96.com/5/54/29/33.html
+http://yp.gates96.com/5/54/29/64.html
+http://rex.skyline.net/html/Medical_Equipment.html?224,software,equipment,agriculture,science
+http://adex3.flycast.com/server/socket/127.0.0.1:2800/click/OnlineCitiesSM/OnlineCitiesInteractiveCityGuides/bd434602591
+http://www.dispatch.co.za/1998/05/29/business/BA.HTM
+http://www.dispatch.co.za/1998/05/29/business/JSE.HTM
+http://retailer.gocollect.com/do/session/1912663/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/help/site_tour/index.asp
+http://retailer.gocollect.com/do/session/1912663/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/about.asp
+http://retailer.gocollect.com/do/session/1912663/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/contact.asp
+http://www.hblb.org.uk/hblbweb.nsf/$Pages/NewsArchive1!OpenDocument&ExpandSection=8,9,3,6,1,11,13
+http://retailer.gocollect.com/do/session/1912620/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/gifts/gift_floor.asp
+http://genforum.genealogy.com/ga/messages/4583.html
+http://genforum.genealogy.com/ga/messages/4582.html
+http://genforum.genealogy.com/ga/messages/4570.html
+http://genforum.genealogy.com/ga/messages/4561.html
+http://genforum.genealogy.com/ga/messages/5575.html
+http://ftp.gnu.org/software/sather/ICSI_Sather/whoswho.html
+http://dk.egroups.com/group/GHSBasketball
+http://dk.egroups.com/group/lovebasket
+http://biblioteca.upv.es/bib/doc/doc_fisbd/10/131276//V/1820145/0////25/S/MLTPAID
+http://www.qth.net/archive/packfr/200009/20000921.html
+http://213.36.119.69/do/session/152975/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/preparer/sante.htm
+http://ftp.lip6.fr/pub8/FreeBSD/FreeBSD-current/ports/emulators/mtools/
+http://ftp.lip6.fr/pub8/FreeBSD/FreeBSD-current/ports/emulators/sim6811/
+http://fyi.cnn.com/ASIANOW/asiaweek/97/0328/aa7.html
+http://pub21.ezboard.com/fbeauxbatonfrm32.showMessage?topicID=6.topic
+http://www.tente.de/us/produkte/produkteigenschaften/aa000001609.htm
+http://www.tente.de/us/produkte/produkteigenschaften/aa000001630.htm
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-stable/net/rboot/?N=D
+http://www.geocities.co.jp/Technopolis-Mars/3952/link.html
+http://saleonall.com/cat/software/reference/5112/969434/advanced-search.html
+http://www.jazzbude.de/EddieLockjawDavis/B000026F24.htm
+http://www6.freeweb.ne.jp/art/iftaka/art/
+http://www.canit.se/(ftp,irc,k15,www)/support/kontakt.html
+http://www.mirror.edu.cn/res/sunsite/pub/academic/chemistry/iupac/Download/publications/pac/special/0199/
+http://cinemabilia.de/details/katnr/234764/
+http://polygraph.ircache.net:8181/services/design/http_-2www.infolane.com/dallas.htm
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-stable/games/crafty-open-medium/pkg-comment
+http://uk.dir.yahoo.com/Education/Primary_and_Secondary/Schools/Middle_Schools/By_Region/U_S__States/Virginia/Complete_List/
+http://yp.gates96.com/6/2/10/13.html
+http://yp.gates96.com/6/2/10/41.html
+http://yp.gates96.com/6/2/10/83.html
+http://yp.gates96.com/6/2/11/51.html
+http://yp.gates96.com/6/2/11/89.html
+http://yp.gates96.com/6/2/12/22.html
+http://yp.gates96.com/6/2/12/58.html
+http://yp.gates96.com/6/2/12/62.html
+http://yp.gates96.com/6/2/12/79.html
+http://yp.gates96.com/6/2/13/19.html
+http://yp.gates96.com/6/2/13/51.html
+http://yp.gates96.com/6/2/13/64.html
+http://yp.gates96.com/6/2/14/75.html
+http://yp.gates96.com/6/2/15/91.html
+http://yp.gates96.com/6/2/16/83.html
+http://yp.gates96.com/6/2/18/15.html
+http://yp.gates96.com/6/2/18/54.html
+http://yp.gates96.com/6/2/19/35.html
+http://yp.gates96.com/6/2/19/68.html
+http://yp.gates96.com/6/2/19/75.html
+http://yp.gates96.com/6/2/19/82.html
+http://yp.gates96.com/6/2/19/87.html
+http://www.chaos.dk/sexriddle/z/w/c/b/v/
+http://itcareers.careercast.com/texis/it/itjs/+bwwBmeg5986wwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewhTwdGpdGwBna5dhBiwGnawppcoqwBodD5amnVncdpMnDBaiw5roDtBdDamwBwaoDqc1moDtamn5otDanLpnGonDqnawDwcO5o5aMFqhTfR20Dzme8hwwwpBmeMWD86etmwww5rmeHdwwwBrmeZpwww/jobpage.html
+http://itcareers.careercast.com/texis/it/itjs/+3wwBmeV6D86euhwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewhTwdGpdGwBna5dhBiwGnawppcoqwBodD5amnVncdpMnDBaiw5roDtBdDamwBwaoDqc1moDtamn5otDanLpnGonDqnawDwcO5o5aMFqhTfR20Dzme8hwwwpBmeMWD86etmwww5rmeidwwwBrmeZpwww/jobpage.html
+http://itcareers.careercast.com/texis/it/itjs/+iwwBmeiWD86zwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewhTwdGpdGwBna5dhBiwGnawppcoqwBodD5amnVncdpMnDBaiw5roDtBdDamwBwaoDqc1moDtamn5otDanLpnGonDqnawDwcO5o5aMFqhTfR20Dzme8hwwwpBmeMWD86etmwww5rme3dwwwBrmeZpwww/jobpage.html
+http://sanming.ebigchina.com/
+http://www.bestinfo.net.cn/bsti_kjxn/gn/guoneifagui/17hebei3.htm
+http://www.detroitfreepress.com/photos/umgallery/g8/g8.1.htm
+http://www.detroitfreepress.com/photos/umgallery/g8/g8.3.htm
+http://xgll.soyou.edu.cn/item/2000-04-07/43733.html43733.html
+http://se.egroups.com/message/bunyan/903
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/KIRJASTO-+JA+TIETOPALVELUT/p%E4ij%E4t-h%E4meen+koulutuskonserni/tietokannat/kirjastot/viitetietokannat/
+http://channel.nytimes.com/2000/05/19/technology/
+http://www.ycwb.com.cn/gb/2000/04/15/jrzk/jrms/5.html
+http://no.egroups.com/message/healthdigest/97
+http://no.egroups.com/message/healthdigest/119
+http://www.securitiestimes.com.cn/199909/10/ssgs_19990910007_xw.html
+http://javatest.a-net.nl/servlet/pedit.Main/http://www.dohistory.org/interests/i_teaching.html
+http://www.buybuddy.com/sleuth/27/1/11009/518452/
+http://www.buybuddy.com/sleuth/27/1/11001/518452/
+http://www.buybuddy.com/sleuth/27/1/11004/518452/
+http://ring.omp.ad.jp/archives/text/CTAN/fonts/metrics/tools/?D=A
+http://www.jamba.de/KNet/_KNet-CIq8j1-hEd-138qo/showInfo-special1.de/node.0/cde7f1uou
+http://cafe4.daum.net/Cafe-bin/Bbs.cgi/sdfamilypds/qry/zka/B2-kBI7p/qqatt/^
+http://www.insurequotes.com/oh3/1AB2.html
+http://www.egroups.com/login.cgi?login_target=%2Fmessage%2FWHKPNews%2F190
+http://www.linux.com/networking/network/performance/reliability/linux/?printable=yes
+http://preview.egroups.com/message/tattoos88/32
+http://ring.shibaura-it.ac.jp/archives/NetBSD/packages/1.5/cobalt/math/
+http://ring.shibaura-it.ac.jp/archives/NetBSD/packages/1.5/cobalt/sysutils/
+http://in.us.biz.yahoo.com/z/a/p/prgx/prgx_f0149933.html
+http://www.backflip.org/members/robeeena/6484057
+http://www.accesslasvegas.com/shared/health/adam/ency/article/003481res.html
+http://library.cuhk.edu.hk/search*chi/dAir+--+Pollution+--+China+--+Hong+Kong./dair+pollution+china+hong+kong/-17,1,1,B/frameset&F=dair+pilots+united+states+biography&7,,7
+http://innopac.lib.tsinghua.edu.cn:2082/search*chi/cTM-62+C288/ctm-62+c288/-5,-1,,B/browse
+http://www.nd.edu/~rarebook/coins/bnl-mg/BNL-index-B/BNL-index-BU/BNL-index-bursley.html
+http://home.kimo.com.tw/lcl566/布告欄.htm
+http://www.northampton.ac.uk/cgi-bin/liberation/betsie/betsie.pl/1005/www.northampton.ac.uk/stu/commdev/chap.htm
+http://www.peopledaily.co.jp/199905/11/newfiles/col_990511001040_zyxw.html
+http://missuniverse.studiostore.com/browse/PAGEANTS/CAP/s.pJicQfVY
+http://ftp.up.pt/Linux/Linus/kernel/v2.1/patch-html/patch-2.2.0-pre6/linux_drivers_misc_parport_procfs.c.html
+http://ftp.up.pt/Linux/Linus/kernel/v2.1/patch-html/patch-2.2.0-pre6/linux_drivers_sound_es1370.c.html
+http://ftp.up.pt/Linux/Linus/kernel/v2.1/patch-html/patch-2.2.0-pre6/linux_include_asm-arm_arch-vnc_system.h.html
+http://ftp.up.pt/Linux/Linus/kernel/v2.1/patch-html/patch-2.2.0-pre6/linux_include_asm-arm_dec21285.h.html
+http://www.gbnf.com/genealog2/dezarn/html/d0004/I1071.HTM
+http://dogbert.wu-wien.ac.at/UniverCD/cc/td/doc/product/access/acs_mod/cis4000/4000/c4000him/22693/
+http://www.uralweb.ru:8081/stats/who
+http://www.rrz.uni-hamburg.de/biologie/b_online/kegg/kegg/db/ligand/cpdhtm/C04881.html
+http://www.la.digitalcity.com/fortwaynein/health/conditions.dci?condition=badbreath
+http://ibelong.digitalcity.com/uticaarea/guygirlmidwest/main.dci?page=guyssept2000
+http://moviestore.zap2it.com/browse/MOVIES/JACKET/s.jNIqMaLO
+http://www.doc.ic.ac.uk/~ace97/whoknows/whoknows.cgi?topic=applescript
+http://www.doc.ic.ac.uk/~ace97/whoknows/whoknows.cgi?topic=prolog
+http://www.doc.ic.ac.uk/~ace97/whoknows/whoknows.cgi?topic=samba
+http://209.52.189.2/discussions.cfm/3031/1757-1776
+http://209.52.189.2/discussions.cfm/3031/757-776
+http://209.52.189.2/discussions.cfm/3031/57-76
+http://itcareers.careercast.com/texis/it/itjs/+DwwBmeOWD86OwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewVtqDhdGMwBodDanDtoDnnGaoDBntGwBodDaMwDwtnMnDBanDBnGpGo5na5nGVnG5anLpnGonDqnaDnBidGAa5O5BnMawppcoqwBodDaMFqhTfR20DzmeitwwwpBme2WD86e1xwww5rmenDwwwBrmeZpwww/morelike.html
+http://volunteersolutions.org/austin/volunteer/opp/one_100634_printer_detailed.html
+http://www.changeyourhome.net/PropertiesToLet/WithamLet/LOO606/pages/DCP_0421_JPG.htm
+http://www.users.qwest.net/~eagletac/
+http://www.motorradversand.de/cgi-bin/bekleidung/integralhelm/NG94G933/beurteilung.htm
+http://stol.list.ru/catalog/25440.html
+http://stol.list.ru/catalog/25301.html
+http://www.eveclub.com/cgi-bin/eveclub.front/972959436300/Club/start/1000000
+http://www.gohamptonroads.com/sportsticker/events/06-12/0447.CWS.FSUTEXCURRENT.html
+http://genforum.genealogy.com/merriman/messages/228.html
+http://genforum.genealogy.com/merriman/messages/223.html
+http://genforum.genealogy.com/merriman/messages/163.html
+http://genforum.genealogy.com/merriman/messages/495.html
+http://genforum.genealogy.com/merriman/messages/232.html
+http://genforum.genealogy.com/merriman/messages/351.html
+http://genforum.genealogy.com/merriman/messages/324.html
+http://genforum.genealogy.com/merriman/messages/510.html
+http://genforum.genealogy.com/merriman/messages/57.html
+http://genforum.genealogy.com/merriman/messages/12.html
+http://genforum.genealogy.com/merriman/messages/263.html
+http://genforum.genealogy.com/merriman/messages/15.html
+http://retailer.gocollect.com/do/session/1912656/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/clubhouse/suggestions.asp
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus53832/eus53833/eus328722/eus129553/eus129564/
+http://cma.arabia.com:8008/jordan/article/print/arabic/0,5195,3750,00.html
+http://webhome.ai-lab.fh-furtwangen.de/for_local_use_only/CD-TMFUMV/daten/mathema/01121m/?N=D
+http://store1.europe.yahoo.com/brink2/2000000141305.html
+http://www.contractorresource.com/Vermont/Westford/Architects.shtml
+http://www.bemi-immobilien.de/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Gemeinsam/3d-service/Top-Darlehens-Konditionen/Startseite/Gemeinsam/versicherungen/gebaeude/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Top-Darlehens-Konditionen/anforderungsformular.htm
+http://free.polbox.pl/p/pphromar/OFERTA.htm
+http://www.burstnet.com/ads/ad5788a-map.cgi/tr00010005_12
+http://www.private-immobilien-boerse.de/ungarn/verkauf/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/Gemeinsam/Immolink/3d-service/IIM-Teil/Startseite/froben.htm
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/KIRJASTO-+JA+TIETOPALVELUT/ammattikorkeakoulukirjastot/lahti/toisen+asteen+koulutus/ammattikorkeakoulut/
+http://www.geomag.com/pirates/html/4books.html
+http://www.lithoquoter.com/Scripts/WebObjects.exe/Printers.woa/559420000049560000009753100000548302/main.wo/7016200000448302/0/-/prime
+http://www.adventurecentre.com/Framesets/intrside/csh.htm
+http://mitglied.tripod.de/vox0/negrostodos/de_sexo_dobles.html
+http://www.sasinstitute.com/offices/asiapacific/taiwan/whatsnew/art1999/art091601.html
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/gdb/sim/ppc/Attic/ppc-opcode-complex?only_with_tag=HEAD
+http://www.yorosiku.net:8080/-_-http://www.suntory.co.jp/eco/what.html
+http://www.yorosiku.net:8080/-_-http://www.suntory.co.jp/culture/birds/welcome.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/linux/music/misc/unitest/lit/pushkin.html
+http://sunsite.uakom.sk/tucows/adnload/69291_28346.html
+http://members.tripod.com/yamabito2/gardening_000416_0502_n22.htm
+http://www.affiliate.hpstore.hp.co.uk/do/session/380775/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/REGISTRATION/entry.asp
+http://www.onsemi.com.cn/pub/prod/0,1193,products1_Disty_order=MC100H642FNR2,00.html
+http://perso.wanadoo.fr/michel.brunel/Infographie/content/contacts.htm
+http://mindit.netmind.com/proxy/http://www.film.com/RGI/FC.(/watch/broadband.jhtml).def...RGI//reviews/features/mow/blairwitch2.jhtml
+http://www.doc.ic.ac.uk/lab/labsrc_area/firstyear/submissions/1997-98/jmc1/labs/Ex09/gv197/?N=D
+http://www-d0.fnal.gov/d0dist/dist/releases/test/l3fmuo_unpack/rcp/?N=D
+http://students.lsu.edu/students/main.nsf/c81d2bf8cb0b80ff862566fb00105ab2/44dc495cc7534894862566fe00127751!OpenDocument&ExpandSection=7,10,4,9
+http://www.zdnet.com/gamespot/filters/printerfriendly/0,10855,2531809-95,00.html
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/asiasanahaku/el%25C3%2583%25C2%25A4kelaitokset/vakuutuslaitokset/rahoitus/el%E4kerahastot/
+http://coe.ier.hit-u.ac.jp/BibEc/data/Papers/fthteavfo2-96.html
+http://polygraph.ircache.net:8181/http_-2ESPN.SportsZone.com/nfl/mall/http_-2www.excite.com/http_-2www.exploreuw.com/cards/
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=cosido&l=pt
+http://fazmali.bigsmart.com/mall/allinone/comparison_chart_new.html
+http://sunsite.ualberta.ca/pub/Mirror/gnu/etc/ORDERS
+http://www.bumppo.net/lists/realbasic-dr/1998/12/msg00347.html
+http://www.bumppo.net/lists/realbasic-dr/1998/12/msg00363.html
+http://www.bumppo.net/lists/realbasic-dr/1998/12/msg00482.html
+http://www.bumppo.net/lists/realbasic-dr/1998/12/msg00483.html
+http://www.bumppo.net/lists/realbasic-dr/1998/12/msg00499.html
+http://www.bumppo.net/lists/realbasic-dr/1998/12/msg00508.html
+http://www.bumppo.net/lists/realbasic-dr/1998/12/msg00518.html
+http://it.sports.yahoo.com/000911/90/of8m.html
+http://ftp.support.compaq.com/public/dunix/v3.2g/TruCluster_V1.0/?M=A
+http://ftp.support.compaq.com/public/dunix/v3.2g/TruCluster_V1.0/ReleaseNotes.pdf
+http://www.quzhou.gov.cn/flfg.nsf/0a043ae26eb50247002564640039f21d/e3cb86464a9f805a002564ac0039422d!OpenDocument&ExpandSection=5,1,9
+http://www.quzhou.gov.cn/flfg.nsf/0a043ae26eb50247002564640039f21d/e3cb86464a9f805a002564ac0039422d!OpenDocument&ExpandSection=6,1,9
+http://polygraph.ircache.net:8181/Keyboards/http_-2www.sky.net/~robertf/http_-2domino.findyn.com/fdi.nsf/http_-2home.netscape.com/
+http://www.nv.cc.va.us/home/jakim
+http://itcareers.careercast.com/texis/it/itjs/+nwwBmJe0B-deVmwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewXhmoBGnaqdGpdGwBodDaDnBidGAoDta5O5BnM5amo5BGox1BnmanDtoDnnGaMw55wqr15nBB5a51ppdGBamnVncdpaBn5BaMFqhTfR20DzmeQtwwwpBme-WD86eyxwww5rmesdwwwBrmeZpwww/morelike.html
+http://itcareers.careercast.com/texis/it/itjs/+MwwBme7WD86JwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewXhmoBGnaqdGpdGwBodDaDnBidGAoDta5O5BnM5amo5BGox1BnmanDtoDnnGaMw55wqr15nBB5a51ppdGBamnVncdpaBn5BaMFqhTfR20DzmeQtwwwpBme-WD86eyxwww5rme4dwwwBrmeZpwww/jobpage.html
+http://my.dreamwiz.com/hideyu/couple/couplemain.htm
+http://www.noras.bizland.com/top_pages/top_gen_1.htm
+http://www.nomade.fr/catm6/entreprises_economi/electricite_electro/electricite/composants_fournitu/index5.shtml
+http://www.staroriental.net/nav/soeg_c/ihf,aeb,s0,363,黎明.html
+http://online.excite.de/lifestyle/katalog/27990
+http://www.linux.com/networking/network/performance/install/news/Linux/
+http://www.linux.com/networking/network/performance/install/news/kernel/
+http://tw.yahoo.com/Regional/Countries_and_Regions/China/Provinces__Regions_and_Municipalities/Shandong/Cities_and_Towns/He_Zhe/Government/
+http://kernel2.adver.com.tw/Counter/log/kernel2.adver.com.tw/ReadAdverData/2000-10-29/12/972792271154.txt
+http://independent-sun-01.whoc.theplanet.co.uk/news/Sport/Football/Bradford/ipswich221000.shtml
+http://www.emis.de/journals/EJDE/Monographs/Volumes/Monographs/1996/05-Hetzer/Hetzer-tex
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/linux-2.3-4/linux/arch/arm/def-configs/assabet?only_with_tag=LINUX-2_4_0-test1
+http://www.nrk.no/finnmark/x22_8_96/arkivet/
+http://pelit.saunalahti.fi/.9/telenation/valveworld/games/Half-Life/?S=A
+http://pelit.saunalahti.fi/.9/telenation/valveworld/games/Half-Life/_Dedicated.txt
+http://pelit.saunalahti.fi/.9/telenation/valveworld/games/Half-Life/_Mods.txt
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-stable/games/bugsx/?N=D
+http://ring.yamanashi.ac.jp/archives/NetBSD/packages/1.4.1/sparc/databases/
+http://citeseer.nj.nec.com/cidcontext/260967
+http://members.tripod.co.jp/jojo6251/sasamineHP.htm
+http://www.segodnya.ru/w3s.nsf/Archive/2000_96_life_vrez_noname2.html
+http://www.citybrasil.com.br/rs/ivora/cidadefala.htm
+http://web62.com/engl/fashion/pompoes/nav.htm
+http://www.jufo.com/netcenter/house/item/bglz/477_lmt.html
+http://gatekeeper.dec.com/pub/BSD/FreeBSD/FreeBSD-current/src/gnu/libexec/uucp/uupick/
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/lelandsystems.stanford.edu/announce/pubsw/
+http://www.schleuse.de/maschine/World/Deutsch/Kultur/Literatur/Autoren_und_Autorinnen/D/Dominik,_Hans/
+http://www.elsur.cl/archivo/mayo2000/8mayo2000/elsur/espectaculos/ind2.php3
+http://www.jpc-neuheiten.de/2881737.htm
+http://www.digitaldrucke.de/(aktuell,arbeitsvermittlung,computer,creaccess,gaestebuch,hilfe,hilfeallgemein,individualverkehr,kultur,onlineservice,schnellübersicht,sense,veranstaltungen,verkehr,von)/_fort/html/themen/computer/soft/links/softquad.htm
+http://bbs.syu.ac.kr/NetBBS/Bbs.dll/groupbbs031/rcm/zka/B2-kB23m/qqo/004A/qqatt/^
+http://www.city-map.de/city/print/nl/Niedersachsen/Osterholz/actueel_&_nieuw/onroerendgoed_&_woningen/k012700681.html
+http://members.tripod.com/sultana_2/thiskindalife.htm
+http://members.tripod.com/sultana_2/thisthing.htm
+http://members.tripod.com/sultana_2/believeinthis.html
+http://tulips.ntu.edu.tw/search*chi/m586.47+4412/m586.47+4412/-5,-1,0,B/frameset&F=m586.48+0146&1,1
+http://btp1da.phy.uni-bayreuth.de/ftp/pub/FreeBSD/ports/www/linbot/?S=A
+http://pub6.ezboard.com/fbiblediscussionandsharingparableorversesharing.subscribeUnregisteredToTopic?topicID=113.topic
+http://www.cs.rit.edu/usr/local/pub/atk/course_descr/481.dir/?M=A
+http://neptune.guestworld.com/gear/gateway.cfm?action=manage&owner=Nickdays
+http://retailer.gocollect.com/do/session/1912673/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/shipping_policy.asp
+http://tucows.minorisa.es/adnload/001-006-009-001.html
+http://www.cwi.nl/~jack/spunk/texts/pubs/sekhmet/8/sp001225.txt
+http://homepage.yesky.com/33554432/36700160/103524.htm
+http://cvs.php.net/viewcvs.cgi/php3/functions/gd.c?annotate=1.65&sortby=log
+http://www.genexchange.com/deathreg.cfm?state=nc&county=pasquotank
+http://www.genexchange.com/schoolreg.cfm?state=nc&county=pasquotank
+http://www.tagnet.org/uva/Eventos/Emergencia99/Fotos/FotosOccidente01.htm
+http://itcareers.careercast.com/texis/it/itjs/+CwwBmue0B-dswwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew6nmoBGnaqdGpdGwBodDa5oBnaoDqc1mnanLqnca15naGn31oGnma5Aocc5awqqd1DBoDtamn5oGwxcnaMFqhTfR20Dzme9twwwpBme+6D865www5rmesDwwwBrmeRdwww/jobpage.html
+http://retailer.gocollect.com/do/session/1912638/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/clubhouse/suggestions.asp
+http://kulichki-win.rambler.ru/inkwell/bio/zitinsk.htm
+http://www.thestateofcolorado.com/e1tatpiercing.html
+http://www.pc-schulmusik.purespace.de/seminar/START.HTM
+http://www.feeler.nl/rubrieken/index.xml/818004059
+http://ftp.dartmouth.edu/~mcb/faculty/fiering.html
+http://ustlib.ust.hk/search*chi/cHD30.28+.C56+1995/chd+++30.28+c56+1995/-17,-1,0,E/2browse
+http://herndon1.sdrdc.com/cgi-bin/com_detail/C00325258/
+http://www.linux.com/networking/network/industry/press_release/linuxworld/Linux/
+http://mindit.netmind.com/proxy/http://www.abc.net.au/children/bananas/dreamtime/page1.htm
+http://www.allkorea.co.jp/cgi-bin/allkorea.front/972959860700/Catalog/1000188
+http://207.87.5.36/pc/news/saa7108/
+http://musicalproducts.asiaep.com/muspro5a.htm
+http://www.trax.nilex.co.uk/trax.cgi/A1S/A1U/1AL/A1S/A2S/C1L/
+http://www.cjga.com/JamMoviesCanadianO/obsessed.html
+http://www.symantec.se/region/jp/support/mac/utiliti/num352/num352up.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=catapultaras&l=pt
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=catapultai&l=pt
+http://no.egroups.com/group/Chenzhou-families
+http://www.teenplatinum.com/barelylegal/anal-sexass/young-adultbest-friends/hardaction/slutsnude/red-toenail-polishfoot-fetish/toenail-polish.html
+http://beatles.sonicnet.com/allmusic/ai_links.jhtml?ai_id=1000
+http://www.luecos.de/wow/art/fu_satir_30142.html
+http://nw1.newsweek.com/nw-srv/inetguide/iguide_4505343.html
+http://www.si.uniovi.es/mirror/squid/mail-archive/squid-users/200002/0637.html
+http://sunsite.compapp.dcu.ie/pub/perl/modules/by-category/08_User_Interfaces/Tk/NI-S/Tk402.004.readme
+http://www.amzn.com/exec/obidos/tg/feature/-/44435/
+http://www.amzn.com/exec/obidos/tg/feature/-/2869/
+http://www.hanter21.co.kr/NetBBS/Bbs.dll/dhliter02/lst/qqeq/1/zka/B2-kBINo/qqo/PRMY
+http://www.linux.com/networking/network/help/email/web/security/
+http://www.linux.com/networking/network/help/email/web/Slackware/
+http://www.linux.com/networking/network/help/email/web/e-commerce/
+http://www.linux.com/networking/network/help/email/web/release/
+http://debian.tod.net/debian/dists/stable/contrib/binary-all/web/?S=A
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-current/devel/fastcrc/pkg-descr
+http://www.trax.nilex.co.uk/trax.cgi/A1C/A2S/B1S/B3S/B1S/C1U/
+http://www.trax.nilex.co.uk/trax.cgi/A1C/A2S/B1S/B3S/B1S/C1D/
+http://rex.skyline.net/html/Metalurgy.html?266,supplies,hobbies,painting,arts
+http://infoseek.wunderground.com/geo/BigtempBannerPromo/US/CO/Cortez.html
+http://www.kaernten.at/1Root/Kontinent/6/Staat/7/Bundesland/17/Ort/820/Pension/304806/Homepage/h_homepage...1.html
+http://dellnet.excite.de/nachrichten/katalog/6663
+http://www.users.skynet.be/eloymarc/infomobil2/sobeen13.htm
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/hXRIA9gT9KNJakAdbkyW2SaEFRyXAJCa2tpUDiYF1BHxbpYG0_go-roWL4XPWFopknXRvCQG4gmCQLNceomD4GJpJ4hvR4eYeQbgN2CFeSPhxakPczINPvttFOQK3IDjjmYz66jR
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/_cRIZWRepq55uG8fC8ijlWOJrkBzrY7AXdlxz7fhosBeDRNPqhpYFY3uMBgWodvLAPXL2sPRQ7GqKF66xzHYxHZISDRz4dfZjEKnEShXdRFhDxBcOPx4ufr7uXHA0sNvRvMq6Z1j
+http://polygraph.ircache.net:8181/health/http_-2cyril.com/http_-2www.americanexpress.com/corp/consumerinfo/privacy/privacystatement.shtml
+http://polygraph.ircache.net:8181/health/http_-2cyril.com/arch.html
+http://www.villager.com/ctg/cgi-bin/Villager/home/AAAksrACwAAACCOAAI
+http://www.medoc-ias.u-psud.fr:81/synoptic/gif/950829/?D=A
+http://members.tripod.lycos.nl/unlimited_pagez/pld2.html
+http://www.thisislancashire.co.uk/lancashire/archive/1996/01/25/FEATURES0VQ.html
+http://members.tripod.com/rebelstrange/buxoms.html
+http://fi.egroups.com/message/TEZKo/3
+http://www.yamato.jp.ibm.com/servers/eserver/xseries/about/availa.html
+http://polygraph.ircache.net:8181/NetworkInfo/http_-2www.thepetsupply.com/3d/web.html
+http://polygraph.ircache.net:8181/NetworkInfo/http_-2www.thepetsupply.com/3d/http_-2www.sccsi.com/welcome.html
+http://www.luf.org/wiki/edit/GIG/GenericCodingTerm
+http://208.178.109.85/msgshow.cfm/msgboard=822531545582878&msg=50215618980084&page=1&idDispSub=-1
+http://mercury.spaceports.com/~xenical/diet-food.html
+http://de.news.yahoo.com/991202/3/echc.html
+http://web.tiscalinet.it/ipsiang/uviafede/tertulli.html
+http://www.brio.de/BRIO.catalog/39fdb8820423a4d82740d472aa780733/Customer/Register
+http://rainforest.parentsplace.com/dialog/thread.pl/bradley2/16/2.html?dir=prevResponse
+http://www.centc251.org/forums/aca-1/dispatch.cgi/isowg4/folderFrame/100012/0/def/1208103
+http://www.bemi-immobilien.de/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Gemeinsam/versicherungen/gebaeude/Gemeinsam/Inserieren/Gemeinsam/MarketingStrategie/Gemeinsam/erreichenPartner/Gemeinsam/versicherungen/unfall/Top-Darlehens-Konditionen/anforderungsformular.htm
+http://www.planetit.com/techcenters/docs/internet_&_intranet/news/PIT20000630S0024/threads?comment_status=on
+http://ftp.eq.uc.pt/software/unix/Linux/redhat/redhat-6.2/doc/HOWTOS/localization/Hellenic-HOWTO-html/Hellenic-HOWTO-8.html
+http://help.sap.com/saphelp_45b/helpdata/de/20/7be8341545ab06e10000009b38f83b/applet.htm
+http://www.imagestation.com/member/?name=RonnyClas6&c=1
+http://www.egroups.com/messages/cmass-syd-talk/1170
+http://bellsouth-cl.tucows.com/winnt/xwinservernt_size.html
+http://ftp.surfnet.nl/os/FreeBSD/cdrom/development/FreeBSD-CVS/ports/mail/youbin/patches/home.html
+http://chat.bigchurch.com/cgi-bin/w3com/pws/bc/PDhIf1s64yA1us4SS1FzmCsroIgpwrmcmdaKEhvT295b5JjMxs9ttaP_gpBzDbn5VR9hkgTaiz3efTGjRK64ORbhJMs0Q8ONiYshBhnFHdkQjl3uSSwZim5B5Layd_SDwYDTVgHM659c
+http://www.starshop.co.uk/Masson-Andre/Masson-Andre-Soleil-3200802.html
+http://www.21hk.com/book/wx1/wx/zpj/h/huanzhulouzhu/shushan/4/
+http://www.dietrich-computer.de/creativegrafik.htm
+http://forum.kf.kommorg.no/forum/agenda21/dispatch.cgi/disk_1/showFolder/100005/9206559
+http://mindit.netmind.com/proxy/http://abc.net.au/rn/schedule/wed.htm
+http://www.fogdog.com/cedroID/ssd3040183156802/nav/stores/adventure_travel/
+http://www.fogdog.com/cedroID/ssd3040183156802/nav/stores/tennis/
+http://link.fastpartner.com/do/session/600349/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/nordicliving.php
+http://members2.clubphoto.com/luisf216501/TAMARINDO/icons.phtml
+http://www.affiliate.hpstore.hp.co.uk/do/session/380795/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/SMARTTIPS/brocdesign.asp
+http://www.hblb.org.uk/hblbweb.nsf/$Pages/NewsArchive1!OpenDocument&ExpandSection=3,7,14,5,13,4,12
+http://www.chaos.dk/sexriddle/d/l/t/i/a/
+http://www.crutchfield.com/S-s7BJxKzNmKr/shop/
+http://www.crutchfield.com/cgi-bin/S-s7BJxKzNmKr/email.asp?sid=S-s7BJxKzNmKr
+http://tucows.interbaun.com/winme/adnload/137104_47064.html
+http://iland.tucows.com/win2k/adnload/73990_29810.html
+http://ftp.uk.debian.org/debian/dists/woody/contrib/binary-alpha/text/?M=A
+http://sound-dist.secured.co.uk/cgi-bin/psShop.cgi/add|10P02|972959526|Warm===and===Dry|user|0|1,0,0,1
+http://pub14.ezboard.com/fjavagateforum69255multibasicboard
+http://www.xrefer.com/entry/317621
+http://library.cuhk.edu.hk/search*chi/aChen,+Jih-peng./achen+jih+peng/-5,-1,0,B/frameset&F=achen+jie+qi&1,1
+http://library.cuhk.edu.hk/search*chi/aChen,+Jih-peng./achen+jih+peng/-5,-1,0,B/exact&F=achen+jih+hsin&1,2
+http://yp.gates96.com/5/50/60/53.html
+http://yp.gates96.com/5/50/60/98.html
+http://yp.gates96.com/5/50/61/14.html
+http://yp.gates96.com/5/50/61/60.html
+http://yp.gates96.com/5/50/62/0.html
+http://yp.gates96.com/5/50/63/12.html
+http://yp.gates96.com/5/50/63/14.html
+http://yp.gates96.com/5/50/63/51.html
+http://yp.gates96.com/5/50/63/52.html
+http://yp.gates96.com/5/50/64/2.html
+http://yp.gates96.com/5/50/64/31.html
+http://yp.gates96.com/5/50/65/36.html
+http://yp.gates96.com/5/50/65/44.html
+http://yp.gates96.com/5/50/65/58.html
+http://yp.gates96.com/5/50/65/78.html
+http://yp.gates96.com/5/50/66/33.html
+http://yp.gates96.com/5/50/66/38.html
+http://yp.gates96.com/5/50/67/3.html
+http://yp.gates96.com/5/50/67/83.html
+http://yp.gates96.com/5/50/68/40.html
+http://yp.gates96.com/5/50/69/2.html
+http://yp.gates96.com/5/50/69/36.html
+http://yp.gates96.com/5/50/69/49.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=cochichastes&l=pt
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=cochicharam&l=pt
+http://www.affiliate.hpstore.hp.co.uk/do/session/380791/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp.com/cposupport/fr/?CTRYcod=FR
+http://www.affiliate.hpstore.hp.co.uk/do/session/380791/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/FR/REGISTRATION/entry.asp
+http://pub22.ezboard.com/fworldofmugenfrm2.showMessage?topicID=131.topic&index=1
+http://pub23.ezboard.com/fmugenshowdownfrm8.showMessage?topicID=36.topic&index=1
+http://www.questlink.com/QL/CDA/Research/ProductBrief/1,1768,0_11203_135680_85724,00.html
+http://www.jamba.de/KNet/_KNet-KBq8j1-gEd-138pd/showInfo-special1.de/node.0/cde7f1uou
+http://www.leg.wa.gov/pub/rcw%20-%20text/title_41/chapter_050/rcw_41_50_650.txt
+http://www.tiscover.ch/1Root/Kontinent/6/Staat/30/Bundesland/31/Ort/234/Ferienpaket/20120/Homepage/buchen...1.html
+http://family.go.com/Categories/Features/family_2000_02/kidv/kidv0200resourceiii/
+http://www.online.kokusai.co.jp/Service/V0043469/wrd/G200/service/service.html
+http://www.linux.com/networking/network/help/hardware/website/ISP/
+http://store1.europe.yahoo.com/I/freemans_1592_58696403
+http://202.99.23.195/BIG5/channel5/745/20000427/51173.html
+http://www-usa10.cricket.org/link_to_database/GROUNDS/WI/ALBION/ALBION_SPORTS_COMPLEX_00772/
+http://www16.freeweb.ne.jp/computer/taka34/
+http://books.hyperlink.co.uk/bookinfo/Caught_in_a_Tornado/Ross/James_R./155553192X
+http://ftp.uni-stuttgart.de/pub/security/unix/SSLapps/doc/?S=A
+http://www.moviestarpages.com/rebecca_romijn-stamos/picture05.htm
+http://html.tucows.ciaoweb.it/adnload/001-009-008-022.html
+http://html.tucows.ciaoweb.it/adnload/001-009-008-019.html
+http://www.brio.de/BRIO.catalog/39fe2f4306cb75f4273fd472aa780708/UserTemplate/2
+http://www.hole.kommune.no/hole/journweb.nsf/weboffjournal!OpenView&Start=92&Count=50&Expand=170
+http://polygraph.ircache.net:8181/docs/Win95/MSdialer/http_-2www.fastcounter.com/http_-2home.netscape.com/home/http_-2www.bildhome.com/plantationhomes/bale1500.htm
+http://polygraph.ircache.net:8181/docs/Win95/MSdialer/http_-2www.fastcounter.com/http_-2home.netscape.com/home/http_-2www.bildhome.com/plantationhomes/bale8000.htm
+http://writer.heha.net/poetics/90_poetics.htm
+http://yp.gates96.com/5/55/20/98.html
+http://yp.gates96.com/5/55/21/17.html
+http://yp.gates96.com/5/55/21/75.html
+http://yp.gates96.com/5/55/22/2.html
+http://yp.gates96.com/5/55/22/22.html
+http://yp.gates96.com/5/55/22/92.html
+http://yp.gates96.com/5/55/23/11.html
+http://yp.gates96.com/5/55/23/46.html
+http://yp.gates96.com/5/55/23/66.html
+http://yp.gates96.com/5/55/23/90.html
+http://yp.gates96.com/5/55/24/2.html
+http://yp.gates96.com/5/55/24/83.html
+http://yp.gates96.com/5/55/24/85.html
+http://yp.gates96.com/5/55/25/62.html
+http://yp.gates96.com/5/55/26/38.html
+http://yp.gates96.com/5/55/26/48.html
+http://yp.gates96.com/5/55/28/5.html
+http://yp.gates96.com/5/55/28/77.html
+http://yp.gates96.com/5/55/29/14.html
+http://yp.gates96.com/6/50/40/47.html
+http://yp.gates96.com/6/50/40/60.html
+http://yp.gates96.com/6/50/40/62.html
+http://yp.gates96.com/6/50/41/81.html
+http://yp.gates96.com/6/50/41/83.html
+http://yp.gates96.com/6/50/42/58.html
+http://yp.gates96.com/6/50/42/90.html
+http://yp.gates96.com/6/50/42/93.html
+http://yp.gates96.com/6/50/43/29.html
+http://yp.gates96.com/6/50/43/79.html
+http://yp.gates96.com/6/50/43/85.html
+http://yp.gates96.com/6/50/44/40.html
+http://yp.gates96.com/6/50/44/76.html
+http://yp.gates96.com/6/50/44/81.html
+http://yp.gates96.com/6/50/45/15.html
+http://yp.gates96.com/6/50/45/52.html
+http://yp.gates96.com/6/50/46/15.html
+http://yp.gates96.com/6/50/46/19.html
+http://yp.gates96.com/6/50/46/92.html
+http://yp.gates96.com/6/50/47/2.html
+http://yp.gates96.com/6/50/47/7.html
+http://yp.gates96.com/6/50/47/33.html
+http://yp.gates96.com/6/50/49/29.html
+http://yp.gates96.com/6/50/49/36.html
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/wRtIx3JBCL5wVzA1pIKradbm9z4Oo2BbPRx_FVh-j4UyLzjojbipsV0nsuM2iF9RxJ1jG2C4LUy3YP5pJl7qDqPdnqV765l2x5hJ0fIUUJuWLaccxO0svbclJ4-alyBQj6Y5dO8YdURyhf9q05q8mJ25FlvF62sm
+http://213.36.119.69/do/session/152980/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www3.travelprice.com/voyages/recherche.phtml
+http://yp.gates96.com/6/2/20/11.html
+http://yp.gates96.com/6/2/21/12.html
+http://yp.gates96.com/6/2/21/51.html
+http://yp.gates96.com/6/2/21/56.html
+http://yp.gates96.com/6/2/22/8.html
+http://yp.gates96.com/6/2/22/38.html
+http://yp.gates96.com/6/2/22/65.html
+http://yp.gates96.com/6/2/23/14.html
+http://yp.gates96.com/6/2/23/50.html
+http://yp.gates96.com/6/2/23/57.html
+http://yp.gates96.com/6/2/23/75.html
+http://yp.gates96.com/6/2/24/15.html
+http://yp.gates96.com/6/2/24/31.html
+http://yp.gates96.com/6/2/24/43.html
+http://yp.gates96.com/6/2/24/70.html
+http://yp.gates96.com/6/2/24/87.html
+http://yp.gates96.com/6/2/25/22.html
+http://yp.gates96.com/6/2/25/53.html
+http://yp.gates96.com/6/2/25/90.html
+http://yp.gates96.com/6/2/26/25.html
+http://yp.gates96.com/6/2/26/26.html
+http://yp.gates96.com/6/2/26/45.html
+http://yp.gates96.com/6/2/26/76.html
+http://yp.gates96.com/6/2/27/34.html
+http://yp.gates96.com/6/2/28/1.html
+http://yp.gates96.com/6/2/28/25.html
+http://yp.gates96.com/6/2/29/2.html
+http://yp.gates96.com/6/2/29/31.html
+http://yp.gates96.com/6/2/29/57.html
+http://yp.gates96.com/6/2/29/74.html
+http://archive.bitcon.no/tucows//winme/preview/136862.html
+http://archive.bitcon.no/tucows//winme/preview/138371.html
+http://archive.bitcon.no/tucows//winme/preview/137011.html
+http://archive.bitcon.no/tucows//winme/preview/137897.html
+http://archive.bitcon.no/tucows//winme/preview/138157.html
+http://www.ngmag.com/books/reference/0792275667.html
+http://socrates.berkeley.edu:4231/pth.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/music/midi/lit/quizz/lit/multiple.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/music/midi/lit/quizz/lit/god.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/music/midi/lit/quizz/misc/colorart/
+http://retailer.gocollect.com/do/session/1912687/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/postcards/index.asp
+http://www.affiliate.hpstore.hp.co.uk/do/session/380807/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/creative/entry.asp
+http://home.swipnet.se/~w-29806/Tab/Guitar/Svenska/h/Jakob%20Hellman/VACKERT_.TXT
+http://jupiter.u-3mrs.fr/~msc41www/releves/16860204.HTM
+http://citeseer.nj.nec.com/cidcontext/1003669
+http://citeseer.nj.nec.com/cidcontext/1003675
+http://citeseer.nj.nec.com/cidcontext/1003676
+http://www.escribe.com/religion/nondualitysalon/m10801.html
+http://www.escribe.com/religion/nondualitysalon/m10824.html
+http://www.tvstore.com/browse/TV/PATCH/s.bCooTxTe
+http://digilander.iol.it/lorciao/computer.htm
+http://yosemite.epa.gov/r9/sfund/overview.nsf/ef81e03b0f6bcdb28825650f005dc4c1/1d8f2e36da9dc1de8825660b007ee696?OpenDocument&ExpandSection=-1,-8,-4
+http://cn.egroups.com/post/ukr_liga?act=reply&messageNum=40
+http://www.lithoquoter.com/Scripts/WebObjects.exe/Printers.woa/048720000079262000002260000000798302/Session_Expired_Page.wo/6144200000698302/0/-/prime
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=coadjuvaram&l=pt
+http://www.craft-supplies.co.uk/cgi-bin/psProdDet.cgi/LW132|972959517|Liming_&_Patinating|user|0|0,0,1,1
+http://www.angelfire.com/va/boogiescamp
+http://www.kyotei.or.jp/JLC/VS/19/991209/0212.htm
+http://www.affiliate.hpstore.hp.co.uk/do/session/380800/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/assistance/entry.asp
+http://www.city-map.nl/city/map/en/Niedersachsen/Landkreis_Cuxhaven/customers/Dr.rer.nat._Büro_für_Erdwiss.Untersuchungen_Udo_Lade/contact.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=consternais&l=pt
+http://muenchen.bda.de/freizeitparks/gastbuch/gaestebuch003.html
+http://www.linux.com/networking/network/industry/growth/editing/SAP/
+http://www.linux.com/networking/network/industry/growth/editing/mobile/
+http://lists.omnipotent.net/qmail/199909/msg00892.html
+http://lists.omnipotent.net/qmail/199909/msg00952.html
+http://lists.omnipotent.net/qmail/199909/msg00964.html
+http://ftp.cc.chuo-u.ac.jp/home/pub/lang/perl/CPAN/ports/msdos/old/?N=D
+http://www3.buch-per-sms.de/faq.jsp$ID=To7697mC5277111659640048At0.5320036065114109
+http://www3.buch-per-sms.de/wir_ueber_uns.jsp$ID=To7697mC5277111659640048At0.5337056452821441
+http://tradersdirectory.com/channel/jobs/insurance/insurance_policy_clerk/b.2166.g.2360.html
+http://www.mapion.co.jp/custom/nikkei/admi/13/13119/takashimadaira/7chome/27/
+http://www.dispatch.co.za/1998/02/19/easterncape/MARCHANC.HTM
+http://www.techsupplies.com/sleuth/33/1/10703/523434/
+http://fi.egroups.com/message/911dispatchers/171
+http://polygraph.ircache.net:8181/services/define/toast/congress2000/http_-2www.sportfish.net/fish.htm
+http://polygraph.ircache.net:8181/services/define/toast/congress2000/MS.htm
+http://polygraph.ircache.net:8181/services/define/toast/congress2000/http_-2leader.linkexchange.com/1/X171400/clicklogo
+http://polygraph.ircache.net:8181/services/define/toast/congress2000/cfiref.htm
+http://www.digitaldrucke.de/(aktuell,arbeitsvermittlung,computer,daham,hilfe,individualverkehr,kultur,literatur,veranstaltungen,verkehr)/_fort/html/themen/aktuell/events/events.htm#regional
+http://dellnet.excite.de/computer/katalog/7054
+http://read.cnread.net/cnread1/ztxs/b/baitian/lmss/006.htm
+http://www-d0.fnal.gov/d0dist/dist/releases/psim01.02.00/l2utils/GNUmakefile
+http://www.allgemeine-immobilien-boerse.de/Frankreich/Verkauf/Private-IB/Startseite/Gemeinsam/erreichenPartner/Gemeinsam/Inserieren/Allgemeine-IB/
+http://wish.themes.tucows.com/adnload/14495.html
+http://wish.themes.tucows.com/preview/14494.html
+http://wish.themes.tucows.com/preview/78220.html
+http://www.uwm.edu/IMT/Computing/sasdoc8/sashtml/af/z0230835.htm
+http://www.bdnet.com/Taiga/H/Fulu/fiche_serie.htm
+http://se.egroups.com/message/clippingts/14?source=1
+http://adelaida.net/music/texts/trex_s1.html
+http://archive.bitcon.no/pub/cica/handheld/desktop/
+http://www.jacksonhewitt.com/ctg/cgi-bin/JacksonHewitt/disclaimers/AAAksrACwAAACCMAAC
+http://ftp.cc.chuo-u.ac.jp/home/pub/TeX/CTAN/language/ethiopia/ethtex/lj_fonts/?N=D
+http://sirac.inrialpes.fr/Infos/Personnes/Christophe.Rippert/ressources/jdk1.3/docs/guide/jdbc/spec/jdbc-spec.frame16.html
+http://www.linux.com/networking/network/release/press_release/competition/web/
+http://www.linux.com/networking/network/release/press_release/competition/internet/
+http://www.linux.com/networking/network/release/press_release/competition/HTTP/
+http://hughes.tucows.com/win2k/share2k_size.html
+http://icq.planetout.com/popcornq/movienews/98/10/23/money/careers
+http://go3.163.com/_NTES/~cntop07/files/k20808/zengby-k201/zengby-k201-09.html
+http://uunetnl.pda.tucows.com/palm/pqa_news_license.html
+http://uunetnl.pda.tucows.com/palm/preview/54359.html
+http://uunetnl.pda.tucows.com/palm/preview/58637.html
+http://uunetnl.pda.tucows.com/palm/adnload/72726_21807.html
+http://uunetnl.pda.tucows.com/palm/adnload/62079_21796.html
+http://uunetnl.pda.tucows.com/palm/preview/33674.html
+http://uunetnl.pda.tucows.com/palm/preview/33501.html
+http://uunetnl.pda.tucows.com/palm/adnload/52518_21780.html
+http://ftp.dei.uc.pt/pub/net/ip/trace/traffic/?N=D
+http://dreamgallery.simplenet.com/lobby/yrestless/sets/26/yrz19.htm
+http://sanqin.net/wenyuan/gudian/fengshen/a/fengshen24.html
+http://windows.tucows.com/preview/001-010-005-007C.html
+http://windows.tucows.com/preview/001-010-005-004C.html
+http://proshikanet.tucows.com/win2k/preview/37883.html
+http://www5.cplaza.ne.jp/auth/kingdom/bbs/rescue/no70/182.html
+http://www5.cplaza.ne.jp/auth/kingdom/bbs/rescue/no70/84.html
+http://www5.cplaza.ne.jp/auth/kingdom/bbs/rescue/no70/82.html
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=7,19,34,20,29
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=36,19,34,20,29
+http://www.ne.jp/asahi/kume-kume/kume/photogellery/zoo/nihon_saru/html/nihon_saru04.html
+http://www.ne.jp/asahi/kume-kume/kume/photogellery/zoo/nihon_saru/html/nihon_saru05.html
+http://www.iabusnet.org:90/forums/aca-1/dispatch.exe/survey/showNextUnseen/fol/100001/2443194
+http://www.chaos.dk/sexriddle/t/r/p/c/p/
+http://www.ld.com/cbd/archive/1999/09(September)/13-Sep-1999/16sol007.htm
+http://www.ld.com/cbd/archive/1999/09(September)/13-Sep-1999/16sol024.htm
+http://www.ld.com/cbd/archive/1999/09(September)/13-Sep-1999/16sol025.htm
+http://www.ld.com/cbd/archive/1999/09(September)/13-Sep-1999/16sol030.htm
+http://debian.linux.org.tw/debian/dists/Debian2.1r4/non-free/binary-alpha/oldlibs/?N=D
+http://www.tamil.net/list/2000-04/nav00304.html
+http://www.2pl.com/b/se/to/1/01/05/v2/1010500263-7.htm
+http://www.2pl.com/b/se/to/1/01/05/v2/1010500263-8.htm
+http://www.mirror.ac.uk/sites/ftp.microsoft.com/deskapps/powerpt/KB/Q129/5/
+http://www.gbnf.com/genealogy/royal92/html/d0028/I307.HTM
+http://www-linux.gsi.de/linux-doc/libqt2/examples/qfd/?M=A
+http://www.arm.com/sitearchitek/support.ns4/html/sdt_debug!OpenDocument&ExpandSection=24,6,37,7
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/kdeutils/kab/kab_kab1importer.h?sortby=log&only_with_tag=KDE_2_0_RELEASE
+http://www.allgemeine-immobilien-boerse.de/nordrhein-Westfalen/bielefeld/Verkauf/Allgemeine-IB/Gemeinsam/versicherungen/gebaeude/Private-IB/Gemeinsam/erreichenPartner/email3d.htm
+http://www.allgemeine-immobilien-boerse.de/nordrhein-Westfalen/bielefeld/Verkauf/Allgemeine-IB/Gemeinsam/versicherungen/gebaeude/Private-IB/3d-service/info.htm
+http://satlink.tucows.com/winme/htmleditme_rating.html
+http://satlink.tucows.com/winme/adnload/137630_29066.html
+http://satlink.tucows.com/winme/adnload/137653_29087.html
+http://yp.gates96.com/5/55/40/63.html
+http://yp.gates96.com/5/55/40/93.html
+http://yp.gates96.com/5/55/41/8.html
+http://yp.gates96.com/5/55/41/27.html
+http://yp.gates96.com/5/55/41/93.html
+http://yp.gates96.com/5/55/42/1.html
+http://yp.gates96.com/5/55/42/65.html
+http://yp.gates96.com/5/55/43/15.html
+http://yp.gates96.com/5/55/43/26.html
+http://yp.gates96.com/5/55/43/94.html
+http://yp.gates96.com/5/55/44/70.html
+http://yp.gates96.com/5/55/44/83.html
+http://yp.gates96.com/5/55/45/17.html
+http://yp.gates96.com/5/55/46/3.html
+http://yp.gates96.com/5/55/46/39.html
+http://yp.gates96.com/5/55/46/43.html
+http://yp.gates96.com/5/55/47/18.html
+http://yp.gates96.com/5/55/48/23.html
+http://yp.gates96.com/5/55/48/40.html
+http://yp.gates96.com/5/55/48/72.html
+http://yp.gates96.com/5/55/48/93.html
+http://yp.gates96.com/5/55/49/7.html
+http://yp.gates96.com/5/55/49/8.html
+http://yp.gates96.com/5/55/49/20.html
+http://yp.gates96.com/5/55/49/37.html
+http://yp.gates96.com/5/55/49/49.html
+http://yp.gates96.com/5/55/49/60.html
+http://yp.gates96.com/5/55/49/69.html
+http://www.ramtron.com/pages/visiters.htm
+http://genforum.genealogy.com/cgi-genforum/forums/oh/wayne.cgi?56
+http://freebsd.ntu.edu.tw/perl/modules/by-module/DB_File/STAS/?N=D
+http://sunsite.org.uk/public/usenet/news-faqs/alt.answers/us-visa-faq/?D=A
+http://circumstance.co.kr/www.globalvillage.com/support/software.html
+http://mediate.magicbutton.net/do/session/625589/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-top50.html
+http://itcareers.careercast.com/texis/it/itjs/+9wwBmev6D86wwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewGPndhBiwGna5O5BnManDtoDnnGamnVncdpoDtaBn5Baw1BdMwBodDaGn31oGnma5Aocc5anLpnGonDqnaGnwcaMFqhTfR20DzmeTtwwwpBm3eP0-dmwww5rmehDwwwBrmeZpwww/morelike.html
+http://library.bangor.ac.uk/search/dProtestant+churches+--+New+York+(State)+--+History+--+19th+century/dprotestant+churches+new+york+state+history+++19th+century/-17,-1,0,B/frameset&F=dprotestant+churches+england+history+++16th+century&2,,3
+http://augustachronicle.com/stories/021299/fea_223-4914.000.shtml
+http://dreamcity.gaiax.com/www/dreamcity/k/n/kint/menu.html
+http://commerce.was-inc.com/cgi-bin/abtwsam.dll/LbkWebCommerceMallCategories-BBC709D6_97E3_3D628A3FC67830F4FB7BD0E0AC833504
+http://www.mirror.kiev.ua:8082/paper/2000/07/1251/text/07-09-1.htm
+http://www.burstnet.com/ads/ad7826a-map.cgi/1025131450
+http://link.fastpartner.com/do/session/600341/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/se/
+http://topcu.tucows.com/winme/adnload/137966_29370.html
+http://topcu.tucows.com/winme/adnload/137990_29378.html
+http://itcareers.careercast.com/texis/it/itjs/+9wwBmeS+D86swwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew6hwAwMwoaBnqrDoqwcaqdD51cBoDta5wcn5aqdD51cBwDB5aBnqrDdcdton5apGd5pnqBoVnaq15BdMnG5apGdm1qBaBnwMaMFqtwAwMwoDzmehxwwwpBmeV+D86eqxwww5rmedDwwwBrmeZpwww/jobpage.html
+http://itcareers.careercast.com/texis/it/itjs/+DwwBmeoWD86eDqwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew6hwAwMwoaBnqrDoqwcaqdD51cBoDta5wcn5aqdD51cBwDB5aBnqrDdcdton5apGd5pnqBoVnaq15BdMnG5apGdm1qBaBnwMaMFqtwAwMwoDzmehxwwwpBmeV+D86eqxwww5rmeqDwwwBrmeZpwww/morelike.html
+http://itcareers.careercast.com/texis/it/itjs/+QwwBme4+D86qxwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew6hwAwMwoaBnqrDoqwcaqdD51cBoDta5wcn5aqdD51cBwDB5aBnqrDdcdton5apGd5pnqBoVnaq15BdMnG5apGdm1qBaBnwMaMFqtwAwMwoDzmehxwwwpBmeV+D86eqxwww5rm+mwwBrmeZpwww/jobpage.html
+http://wwwbackup.trinler.net/anleitungen/manual/mod/mod_dll.html
+http://wwwbackup.trinler.net/anleitungen/manual/mod/mod_log_agent.html
+http://as400bks.rochester.ibm.com/pubs/html/as400/v4r5/ic2962/info/RZAIENETDOTDATA.HTM
+http://www.gov.ie/educ/000928.htm
+http://www.gov.ie/educ/speech/000928.htm
+http://pub3.ezboard.com/utaela.showPublicProfile?language=EN
+http://genforum.genealogy.com/cody/messages/700.html
+http://genforum.genealogy.com/cody/messages/525.html
+http://genforum.genealogy.com/cody/messages/494.html
+http://genforum.genealogy.com/cody/messages/447.html
+http://ftp.surfnet.nl/os/FreeBSD/cdrom/development/FreeBSD-CVS/ports/editors/psgml-emacs/files/home.html
+http://www.mic.hr/PGBURZA:135556
+http://pub8.ezboard.com/fthecompanionswebboardfrm19
+http://pub8.ezboard.com/fthecompanionswebboardarchive
+http://gallery2.simplenet.com/lobby/main/videocaps/ghoffman/precious/ghsp36.htm
+http://www.symantec.ru/avcenter/venc/data/unashamed.html
+http://www.symantec.ru/avcenter/cgi-bin/virauto.cgi?vid=7000
+http://www.symantec.ru/avcenter/cgi-bin/virauto.cgi?vid=1685
+http://www.symantec.ru/avcenter/cgi-bin/virauto.cgi?vid=5358
+http://rex.skyline.net/navigate.cgi?reading,retail,hobbies,painting,arts
+http://rex.skyline.net/navigate.cgi?forsale,retail,hobbies,painting,arts
+http://pds.nchu.edu.tw/cpatch/ftp/cuteftp/?S=A
+http://www.tel.de/s/M/MCFIT.htm
+http://zeus.uni-trier.de/~ley/db/indices/a-tree/s/Stevenson:Allan.html
+http://www.alsapresse.com/jdj/00/07/14/SA/article_16.html
+http://link.fastpartner.com/do/session/600359/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/jobpilot.php
+http://link.fastpartner.com/do/session/600359/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/index.php
+http://news.dreamwiz.com/news_lg/04/20001025/joins/200010251653041653193.html
+http://news.dreamwiz.com/news_lg/04/20001025/joins/200010250820040820583.html
+http://windows.tucows.com/winnt/adnload/71593_30161.html
+http://213.36.119.69/do/session/152979/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/reserver/encheres/
+http://213.36.119.69/do/session/152979/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/IT_IT/
+http://www.centc251.org/forums/aca-1/dispatch.cgi/isowg4/showNextUnseen/fol/100012/1220541
+http://bigpanda.net/46/alphabetical.html
+http://bigpanda.net/46/io.html
+http://fi.egroups.com/message/puzzles/547
+http://theaceshow.com/drawinglinda.html
+http://theaceshow.com/drawingsketch.html
+http://ftp.jp.debian.org/debian/dists/woody/main/binary-all/news/?D=A
+http://www.trax.nilex.co.uk/trax.cgi/A1S/A2L/1AS/B3U/B4L/C2S/
+http://www.trax.nilex.co.uk/trax.cgi/A1S/A2L/1AS/B3U/B4L/C4D/
+http://in.egroups.com/message/islaam/3
+http://in.egroups.com/message/islaam/29
+http://ustlib.ust.hk/search*chi/a%7B233e68%7D%7B215976%7D%7B213e2e%7D/a%7B233e68%7D%7B215976%7D%7B213e2e%7D/-5,-1,0,B/browse
+http://yp.gates96.com/13/8/20/68.html
+http://yp.gates96.com/13/8/21/25.html
+http://yp.gates96.com/13/8/21/32.html
+http://yp.gates96.com/13/8/21/49.html
+http://yp.gates96.com/13/8/21/63.html
+http://yp.gates96.com/13/8/21/88.html
+http://yp.gates96.com/13/8/22/2.html
+http://yp.gates96.com/13/8/22/10.html
+http://yp.gates96.com/13/8/22/67.html
+http://yp.gates96.com/13/8/22/79.html
+http://yp.gates96.com/13/8/23/19.html
+http://yp.gates96.com/13/8/23/31.html
+http://yp.gates96.com/13/8/25/64.html
+http://yp.gates96.com/13/8/25/68.html
+http://yp.gates96.com/13/8/25/73.html
+http://yp.gates96.com/13/8/26/6.html
+http://yp.gates96.com/13/8/26/11.html
+http://yp.gates96.com/13/8/26/12.html
+http://yp.gates96.com/13/8/26/39.html
+http://yp.gates96.com/13/8/26/54.html
+http://yp.gates96.com/13/8/26/55.html
+http://yp.gates96.com/13/8/26/82.html
+http://yp.gates96.com/13/8/27/89.html
+http://yp.gates96.com/13/8/28/22.html
+http://yp.gates96.com/13/8/28/61.html
+http://yp.gates96.com/13/8/29/13.html
+http://yp.gates96.com/13/8/29/33.html
+http://yp.gates96.com/13/8/29/83.html
+http://www.private-immobilien-boerse.de/baden-wuertemberg/ostalb-kreis/Verkauf/Versteigerungen-IB/Startseite/Gemeinsam/erreichenPartner/IIM-Teil/Startseite/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/indexbeginn.htm
+http://www2.so-net.ne.jp/mc/columns/nakama/1112/
+http://ring.shibaura-it.ac.jp/archives/pack/x68/personal/tokei/00_index.txt
+http://yp.gates96.com/5/32/0/0.html
+http://yp.gates96.com/5/32/0/99.html
+http://yp.gates96.com/5/32/1/92.html
+http://yp.gates96.com/5/32/1/93.html
+http://yp.gates96.com/5/32/3/68.html
+http://yp.gates96.com/5/32/4/21.html
+http://yp.gates96.com/5/32/4/72.html
+http://yp.gates96.com/5/32/5/87.html
+http://yp.gates96.com/5/32/6/64.html
+http://yp.gates96.com/5/32/7/25.html
+http://yp.gates96.com/5/32/7/32.html
+http://yp.gates96.com/5/32/7/44.html
+http://yp.gates96.com/5/32/7/68.html
+http://yp.gates96.com/5/32/7/78.html
+http://yp.gates96.com/5/32/8/40.html
+http://yp.gates96.com/5/32/8/59.html
+http://yp.gates96.com/5/32/8/90.html
+http://yp.gates96.com/5/32/8/95.html
+http://yp.gates96.com/5/32/9/3.html
+http://yp.gates96.com/5/32/9/54.html
+http://yp.gates96.com/5/32/9/62.html
+http://yp.gates96.com/5/32/9/77.html
+http://tucows.soneraplaza.nl/winme/preview/138260.html
+http://www.cnnews.com/maya/finance/cjsy/gncj/item/2000_07/206341.shtml
+http://212.31.0.37/hur/turk/98/09/23/dunya/02dun.htm
+http://212.31.0.37/hur/turk/98/09/12/dunya/01dun.htm
+http://ftp.cwi.nl/ftp/mdr/LOCKED/
+http://ftp.cwi.nl/ftp/mdr/PICH/
+http://www.ncte.org/lists/ncte-talk/jan2000/msg02008.html
+http://www.russ.ru/forums/prav-dir/conf2/695_r.htm
+http://www.doc.ic.ac.uk/lab/labsrc_area/firstyear/submissions/1997-98/jmc1/labs/Ex05/mjp97/?D=A
+http://www.affiliate.hpstore.hp.co.uk/do/session/380786/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/search.asp
+http://www.flapjack.de/main/2ndHP/jangl43637.htm
+http://195.166.55.201/vfg-uk/HTML/P145232.HTM
+http://www.greenleaves.com/bookcat/gb_0689826788.html
+http://webraft.its.unimelb.edu.au/730452/students/sgm/pub/
+http://ring.omp.ad.jp/pub/NetBSD/packages/pkgsrc/print/teTeX-share/files/
+http://ww.egroups.com/subscribe/wtcjk_purnawirawan
+http://167.8.29.14/life/travel/ski/skinj.htm
+http://www.nrk.no/finnmark/x26_5_97/fastesid/abonn.htm
+http://www.brio.de/BRIO.catalog/39fe2f41050aa9b82741d472aa7806dd/UserTemplate/6
+http://207.25.71.143/golf/news/2000/04/18/heintz/
+http://weekends.worldres.com/script/gen_review.asp?hotel_id=4291&n=1231
+http://www.netitor.com/photos/schools/bc/sport/m-footbl/auto_pdf/weekly-release-082800.pdf
+http://www.3w-sciencefiction.de/SmytheRH/SmytheRH0785808744.htm
+http://www.zdnet.com/gamespot/stories/screens/0,10865,2617426-32,00.html
+http://ftp.lip6.fr/pub2/sgml-tools/website/HOWTO/Root-RAID-HOWTO/t1450.html
+http://webusers.siba.fi/doc/texmf/latex/ms/?M=A
+http://www.trax.nilex.co.uk/trax.cgi/A1S/1AL/A3L/A1U/A3S/1AS/
+http://www.trax.nilex.co.uk/trax.cgi/A1S/1AL/A3L/A1U/A3S/D1U/
+http://www.trax.nilex.co.uk/trax.cgi/A1S/1AL/A3L/A1U/A3S/D3S/
+http://thaigate.rd.nacsis.ac.jp/ftp/thaisoft/nectec/linux.tle/6.01/Mandrake/?S=D
+http://www-ind5.cricket.org/link_to_database/ARCHIVE/2000-01/AUS_LOCAL/GRADE/NSW/SCA/WOMEN/SCA-WOMEN_2000-01_FIXTURES.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=abbratend&l=de
+http://www.webvillage.org/mBEDJPsite/html/downloadplugins.html
+http://www.gov.karelia.ru:8081/gov/Karelia/658/8.html
+http://www.private-immobilien-boerse.de/bayern/ingolstadt/Verkauf/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/Gemeinsam/Inserieren/Gemeinsam/erreichenPartner/Ferien-IB/Startseite/
+http://pillsonline.00go.com/lowfatdiet/lifetime_fitness.htm
+http://tecfa2.unige.ch/guides/java/examples/JavaClassLibExamples/io/FileReader/Main.class
+http://www.burstnet.com/ads/ad7826a-map.cgi/1933336291
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/asiasanahaku/Hong%2520Kong/aasia/talous/pika-+ja+perustilastoja/
+http://home.tiscalinet.be/oaseidstad/vonk/optop2000.html
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=19,36,22,32,23
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=29,36,22,32,23
+http://cn.egroups.com/messages/virtualaccess/194
+http://jerken.grida.no/nor/soeno97/ozone/frames/pressure.htm
+http://online.excite.de/erotik/katalog/6213
+http://online.excite.de/erotik/katalog/6187
+http://online.excite.de/erotik/katalog/6221
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=28,7,35,25,13
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=31,7,35,25,13
+http://genforum.genealogy.com/cgi-genforum/forums/loughlin.cgi?11
+http://freesoftware.missouri.edu/pub/CPAN/authors/id/J/JS/JSWARTZ/?D=A
+http://link.fastpartner.com/do/session/600360/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/fastpartner.php
+http://www.jobvillage.com/channel/jobs/sciences/life_sciences/soil_plant_scientist/b.1041.g.251.html
+http://ftp.debian.org/dists/Debian2.2r0/non-free/binary-sparc/mail/?D=A
+http://generalstore.everdream.com/kore/catalog/Office_Supplies/General_Office_Supplies/Tape_Flags/Arrow/GRP-US6663/product.html
+http://www.hig.se/(date,if,set,tablify,user)/~jackson/roxen/
+http://www.hig.se/(date,if,language,set,tablify)/~jackson/roxen/
+http://www.cyber-pages.com/0prog/classifieds_display.cgi?oakland=WEMP=0
+http://202.84.17.6/csnews/articles/141_18691.htm
+http://202.84.17.6/csnews/articles/142_18526.htm
+http://ftp.dti.ad.jp/pub/FreeBSD/FreeBSD-current/www/es/releases/1.1.5/
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=9&discrim=247,207,129
+http://ftp.up.pt/Linux/debian/dists/unstable/main/disks-i386/?M=A
+http://www.unterhaltungs-cd.de/HillJonny/B000025087.htm
+http://filebox.vt.edu/users/aneal/excess/_fpclass/
+http://www.jamba.de/KNet/_KNet-JOt8j1-OEd-139q0/showInfo-presse.de/node.0/cde7f1uou
+http://www.tercera.cl/diario/1997/12/05/win.html
+http://yp.gates96.com/14/88/20/8.html
+http://yp.gates96.com/14/88/20/13.html
+http://yp.gates96.com/14/88/22/30.html
+http://yp.gates96.com/14/88/25/28.html
+http://yp.gates96.com/14/88/25/65.html
+http://yp.gates96.com/14/88/26/3.html
+http://bsdweb.pasta.cs.uit.no/bsdweb.cgi/~checkout~/pkgsrc/math/grace/pkg/
+http://ftp.tokyonet.ad.jp/pub/Linux/debian-jp/dists/unstable-jp/contrib/binary-m68k/math/?S=A
+http://my.dreamwiz.com/piramos/lan.htm
+http://pub8.ezboard.com/fselfreliantlivingfrm16.showMessage?topicID=11.topic
+http://pub8.ezboard.com/fselfreliantlivingfrm16.showMessage?topicID=4.topic
+http://www.affiliate.hpstore.hp.co.uk/do/session/380798/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/SMARTTIPS/vacationcards.asp
+http://systemlogic.neoseeker.com/Companies/productportfolios/NEC_Interchannel/?sortby=sections
+http://www.houses-apartment-rentals.com/Virginia/city_search_criteria.asp?state=VA&City=DALHART
+http://www.wcbcourses.com/wcb2/schools/MERCED/merced/dhauser/2/forums/forum2/messages/17.html
+http://www.wcbcourses.com/wcb2/schools/MERCED/merced/dhauser/2/forums/forum2/messages/10.html
+http://beautifulsavers.subportal.com/sn/Shell_and_Desktop/Quick_Shutdown_Tools/2702.html
+http://polygraph.ircache.net:8181/getting_started/http_-2www.lucent.com/micro/K56flex/http_-2home.netscape.com/comprod/mirror/http_-2www.wtcsf.org/mall/http_-2www.cdnow.com/http_-2www.microsoft.com/msoffice/publicaffairs.html
+http://polygraph.ircache.net:8181/getting_started/http_-2www.lucent.com/micro/K56flex/http_-2home.netscape.com/comprod/mirror/http_-2www.wtcsf.org/mall/http_-2www.cdnow.com/http_-2www.microsoft.com/msoffice/videobroadcast/
+http://www.yagoo.co.kr/stats/pitching.asp?Mlbmanid=JESPEN7599
+http://www.4hotfantasy.com/acommon/guests/python4.html
+http://boerseninfos.ksk-tut.de/dynamic/ak/adhoc/news/519000-20000316-150811.html
+http://boerseninfos.ksk-tut.de/dynamic/ak/adhoc/news/519000-19991025-082814.html
+http://cn.yahoo.com/Regional/Countries_and_Regions/China/Provinces__Regions_and_Municipalities/Zhejiang/Cities_and_Towns/Li_Hsua/Business/Companies/Books/
+http://www.affiliate.hpstore.hp.co.uk/do/session/380810/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/FR/REGISTRATION/entry.asp
+http://kuyper.calvin.edu/fathers2/NPNF1-01/npnf1-01-12.htm
+http://library.bangor.ac.uk/search/dModernism+(Literature)/dmodernism+literature/-5,-1,0,E/2browse
+http://aleph.tau.ac.il:4500/ALEPH/ENG/ATA/AAS/AAS/SHORT/410519/1/
+http://pub1.ezboard.com/fflashboard1flashjunkiestalk.showAddReplyScreenFromWeb?topicID=190.topic&index=2
+http://www.inforiese.de/db_cargo/typ_b_files/db_cargo_cargo_ansprechpartner.shtml
+http://www.gbnf.com/genealogy/dehart/html/d0005/I985.HTM
+http://btclickfam.excite.co.uk/directory/categories/670199
+http://www.worldmedicus.com/servlet/Controller/$7008040516620000.sj_viewc/
+http://www.worldmedicus.com/servlet/Controller/$7008040528250000.sj/
+http://207.25.71.143/features/galleries/then_and_now/belinsky/belinsky01_lg_01.html
+http://wiem.onet.pl/wiem/002c66.html
+http://www.peopledaily.com.cn/GB/paper40/544/58242.html
+http://www.uihealthcare.com////PatientsVisitors/MedMuseum/CenturyOfCaring/UniversityHospitals/05Quarantine.html
+http://se.egroups.com/login.cgi?login_target=%2Fmessages%2Fwotccglist%2F333
+http://se.egroups.com/message/wotccglist/334
+http://se.egroups.com/message/wotccglist/350
+http://se.egroups.com/message/wotccglist/358
+http://www.msn.expedia.co.uk/wg/North_America/United_States/P30131.asp
+http://www.uol.com.br/cinemaonline/starwars
+http://www.perotech.ch/d/securedb/html/listtopic.php?7396
+http://moviestore.zap2it.com/browse/X-FILES/POSTCARD/s.goFzN1Lb
+http://zeus.uni-trier.de/~ley/db/indices/a-tree/m/Morgoev:Vladimir_K=.html
+http://www.3w-buecher.de/GilliesRobertJ/GilliesRobertJ0122839803.htm
+http://www.buybuddy.com/sleuth/27/1/11002/6637/
+http://ftp.uk.debian.org/debian/dists/unstable/contrib/binary-powerpc/oldlibs/?D=A
+http://no.egroups.com/login.cgi?login_target=%2Fgroup%2Fwww.members.xoom.com%2FLibertyFlame
+http://www.aelita.net/products/support/sitemap/Reg/QuoteRegister/news/company/Copyright.htm
+http://www.aelita.net/products/support/sitemap/Reg/QuoteRegister/news/services/default.htm
+http://www.amateurplatinum.com/spankingfantasy/fertiletrophy-wife/hot-hardcore-fuckinglongest/red-toenail-polishfeet-fucking-/vietnamesewomen/chinesechi/womenpetite.html
+http://www.amateurplatinum.com/spankingfantasy/fertiletrophy-wife/hot-hardcore-fuckinglongest/red-toenail-polishfeet-fucking-/vietnamesewomen/fuckinghard/actionsmacking.html
+http://genforum.genealogy.com/cgi-bin/print.cgi?fikes::26.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/programs/unlambda/lit/quizz/music/midi/
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/programs/unlambda/lit/quizz/computers/callcc.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/programs/unlambda/lit/quizz/misc/colorart/
+http://www.musiciansfriend.com/ex/ds/live/001030182726064208037002434823
+http://www.musiciansfriend.com/ex/ds/home/funzone/001030182726064208037002434823?doc=doc,postcard.html
+http://www.musiciansfriend.com/ex/ds/home/platinum/001030182726064208037002434823?g,home.platinum.html
+http://www.musiciansfriend.com/ex/ds/home/articles/001030182726064208037002434823?dbase=gw,gwmain.html
+http://www.musiciansfriend.com/ex/ds/home/articles/001030182726064208037002434823?dbase=info,privacy.html
+http://preview.egroups.com/dir/Business/Training_and_Schools/Management_Training/Consultants?st=4
+http://hammer.prohosting.com/~nieting/html1216/lmtf015.htm
+http://planetfreebies.subportal.com/sn/Information_Management/Misc__Information_Databases/12835.html
+http://dada.linuxberg.com/kdehtml/adnload/61589_33448.html
+http://www.wlu.ca/~wwwregi/95-96/cal/ucourses/GM/GM151.html
+http://walkabout.tucows.com/win2k/adnload/61015_28629.html
+http://www.1001e.net/02/qbt/09.htm
+http://se.egroups.com/post/webfaaa?act=reply&messageNum=3
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/keats.admin.virginia.edu/asbestos/home.html
+http://www.hotelboulevard.com/fr/riviera/standard/htmlf752567459c6d803842381c50e94fd9f/sessionLang/ANG/gettingstarted.html
+http://ring.omp.ad.jp/pub/NetBSD/packages/pkgsrc/print/transfig/?N=D
+http://citeseer.nj.nec.com/cidcontext/2339336
+http://www.uk.multimap.com/p/browse.cgi?pc=LS287DR
+http://topcu.linux.tucows.com/x11html/adnload/46019_3809.html
+http://www.mon.de/nr/stuemges
+http://www.tamil.net/list/1998-10/msg00212.html
+http://retailer.gocollect.com/do/session/1912682/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/terms_and_conditions.asp
+http://pl.php.net/manual/nl/function.pfpro-version.php
+http://members.tripod.co.jp/millenium/top.html
+http://community.webshots.com/photo/4331085/4331572GooaFzYUAJ
+http://community.webshots.com/photo/4331085/4331589oKrBmsJbga
+http://community.webshots.com/photo/4331085/4331620zgfyMLoSjs
+http://www.utdallas.edu/~chansen/text/qabbala9.html
+http://www.jobvillage.com/channel/jobs/installation_repair/safety_equipment/fire_alarm/b.2283.g.3516.html
+http://www.geocities.com/Area51/Chamber/8750/DoesKitEverTalkAboutTheSubjectOnHand.html
+http://www.geocities.com/Area51/Chamber/8750/TheMotherofAllMissleBoats.html
+http://www.geocities.com/Area51/Chamber/8750/Tomahawk2.html
+http://www.thecitizennews.com/main/archive-000628/thecitizennews/citizen.html
+http://links2go.publiweb.com/expert/topic/Mp3_Hardware
+http://webhelp.promovacances.net/S02/BL/BEGYP/SAI00512024/cal.htm?d=1013
+http://205.161.150.96/cgi-bin/c2k/title_talent.html&id=143786&title_star=DOMINICK
+http://dennou-q.geo.kyushu-u.ac.jp/library/Linux/debian-jp/dists/stable/non-free-jp/binary-all/net/?S=A
+http://wow-online.vhm.de/Wirtschaft/Unternehmen/Versicherungen/Versicherungsgesellschaften/Signal_Versicherung.html
+http://www.linux.com/networking/network/firewall/web/communications/?kw_offset=50
+http://www.leg.wa.gov/pub/rcw%20-%20text/title_28b/chapter_056/rcw_28b_56_090.txt
+http://pub12.ezboard.com/flalaland96545listeningbooth.showMessage?topicID=74.topic
+http://www.fogdog.com/cedroID/ssd3040183156032/crs/pw__/wld/fogdog_sports/lee_sport/fan_memorabilia/apparel/new_york_yanke_2000_ameri_leagu_champ_tee_shi.html
+http://www.fogdog.com/cedroID/ssd3040183156032/nav/stores/adventure_travel/
+http://www.hoovers.com/travel/cityguide/detailed/0,3368,46_119158,00.html
+http://user.chollian.net/~mlsc/
+http://www.158china.com/data/stock/fundowner/default.asp?stck_cd=0548
+http://www.affiliate.hpstore.hp.co.uk/do/session/380803/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/SMARTTIPS/createbroch.asp
+http://rcsl.auto.inha.ac.kr/~treeman/Documents/HOWTO/Consultants-HOWTO-3.html
+http://www.diogenes.ch/4DACTION/web_rd_aut_prview/a_id=7056427&area=&ID=483330
+http://polygraph.ircache.net:8181/http_-2www.horizonfinance.com/http_-2www.netscape.com/download/http_-2www.microsoft.com/ie/http_-2207.91.150.20/links.html
+http://www.multicosm.com/facade/www.adobe.com/support/techguides/printpublishing/scanning/psscanning01b.html
+http://yp.gates96.com/0/50/10/62.html
+http://yp.gates96.com/0/50/10/95.html
+http://yp.gates96.com/0/50/11/1.html
+http://yp.gates96.com/0/50/11/18.html
+http://yp.gates96.com/0/50/11/49.html
+http://yp.gates96.com/0/50/12/55.html
+http://yp.gates96.com/0/50/13/48.html
+http://yp.gates96.com/0/50/13/96.html
+http://yp.gates96.com/0/50/14/15.html
+http://yp.gates96.com/0/50/14/73.html
+http://yp.gates96.com/0/50/15/50.html
+http://yp.gates96.com/0/50/15/80.html
+http://yp.gates96.com/0/50/16/1.html
+http://yp.gates96.com/0/50/16/8.html
+http://yp.gates96.com/0/50/17/50.html
+http://yp.gates96.com/0/50/17/71.html
+http://yp.gates96.com/0/50/18/25.html
+http://yp.gates96.com/0/50/18/73.html
+http://yp.gates96.com/0/50/18/82.html
+http://yp.gates96.com/0/50/18/84.html
+http://yp.gates96.com/0/50/18/90.html
+http://cisne.sim.ucm.es/search*spi/dBallets+--+Gran+BretaÃ\83±a+--+Discos+compactos/dballets+gran+bretan~aa+discos+compactos/-29,-1,0,B/browse
+http://opac.lib.ntnu.edu.tw/search*chi/++ftlist/bp20005025/-17,-1,0,B/browse
+http://www.trax.nilex.co.uk/trax.cgi/A1S/1AL/A3L/A4R/B1D/A3S/
+http://php.nic.fi/manual/html/function.cpdf-open.html
+http://php.nic.fi/manual/html/function.cpdf-fill.html
+http://php.nic.fi/manual/html/function.cpdf-setrgbcolor-fill.html
+http://www.classiccmp.org/mail-archive/classiccmp/1998-04/1426.html
+http://text.csn.ul.ie/~danny/tabs/p/proclaimers/?N=D
+http://mirror.nucba.ac.jp/mirror/FreeBSD/branches/3.0-stable/ports/japanese/zangband/?N=D
+http://augustachronicle.com/stories/100197/spo_fishing.html
+http://www.symatrixinc.com/website/website.nsf/0/3e40df86fb357cd5882568720079613f!OpenDocument&ExpandSection=10,8,9,5
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/linux/music/quizz/pics.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/linux/music/quizz/lit/ldvelh.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/linux/music/quizz/misc/unitest/
+http://mirror.nucba.ac.jp/mirror/FreeBSD/branches/3.0-stable/ports/japanese/ptex-pkfonts360/?N=D
+http://www.2pl.com/b/ru/fi/1/24/06/b1/1240601249-11023.htm
+http://galaxy.einet.net/galaxy/Community/United-States/States/Minnesota/Cities-and-Regions/Winona/Education/K--12/Middle/Public.html
+http://www.hotelboulevard.com/fr/paris/standard/htmlc866e5cecf73322551f00b0108eb84bc/sessionLang/ANG/prov/browse/cp/75001/resultatSearch.html
+http://btp1da.phy.uni-bayreuth.de/ftp/pub/FreeBSD/ports/japanese/dvipsk-vflib/pkg-descr
+http://32548news.subportal.com/sn/Utilities/Misc__Encryption_Utilities/
+http://www.hongen.com/proedu/hext/zxks/dxyw/html/dxy62804.htm
+http://www.users.globalnet.co.uk/~roy/InternetTree/WC01/WC01_226.htm
+http://www2.msstate.edu/~eaddy/famtread/html/nti07339.htm
+http://www.trackinfo.com/trakdocs/hound/ca/RESULTS/ARCHIVE/1996/0996/GRCA19S.HTM
+http://www.idg.net/crd_essential_110984.html
+http://www.zdnet.de//news/artikel/2000/09/06015-wc.html
+http://www.secinfo.com/d114Cu.52.htm
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus141561/eus174865/eus327367/eus327527/eus331435/
+http://enjoy100.com.cn/200005/23/
+http://link.fastpartner.com/do/session/600348/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/mediatransfer.php
+http://www.chaos.dk/sexriddle/t/z/p/b/b/
+http://www.brio.de/BRIO.catalog/39fe2f4106ca8ce0273fd472aa7806ff/UserTemplate/6
+http://link.fastpartner.com/do/session/600352/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/robinhus.php
+http://link.fastpartner.com/do/session/600352/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/create/index.php
+http://www.underground-online.com/companyfinder/filters/products/0,9996,1793-101,00.html
+http://mediate.magicbutton.net/do/session/625588/vsid/3342/tid/3342/cid/88020/mid/2008/rid/2313/chid/2648/url/http://www1.getmapping.com/viewer.cfm
+http://aol.digitalcity.com/houston/recreation/event.dci?eid=6452
+http://www.linux.com.hk/mirror/ldp/LDP/LG/issue10/lg_bytes10.html
+http://www.linux.com.hk/mirror/ldp/LDP/LG/issue10/issue10.txt
+http://www.beauty.net.cn/main/japanese/mie.htm
+http://www.allgemeine-immobilien-boerse.de/kanada/verkauf/Gemeinsam/Inserieren/Allgemeine-IB/Ferien-IB/Startseite/Private-IB/Startseite/Default.htm
+http://www.kodak.co.uk/US/en/corp/store/catalog/Product.jhtml?PRODID=2113&CATID=2234
+http://opac.lib.ntnu.edu.tw/search*chi/f373+017/f373+017/-5,-1,,B/browse
+http://ftp.du.se/disk3/mandrake/7.1/Mandrake/mdkinst/etc/pcmcia/?M=A
+http://www.teenplatinum.com/barelylegal/anal-sexass/taismall/almond-skinned/{gaylink}
+http://194.128.65.4/pa/cm199697/cmhansrd/vo970318/debtext/70318-11.htm
+http://netlondon.hotelbook.com/live/photos/19368
+http://www.centc251.org/forums/aca-1/dispatch.cgi/hsi/folderFrame/100205/0/author/1243894
+http://www.teacherformation.org/html/od/facilitators.cfm/task1,login/discussion_id,2/xid,5474/yid,3022999
+http://polygraph.ircache.net:8181/environment_energy/heritage/http_-2www.apache.org/
+http://plat.debian.or.jp/debian/dists/unstable/main/binary-alpha/math/?D=A
+http://home.hiwaay.net/~bjacobs/genealogy/laster/html/d0054/g0000038.html
+http://www.northampton.ac.uk/cgi-bin/liberation/betsie/betsie.pl/1005/www.northampton.ac.uk/cgi-bin/liberation/betsie/betsie.pl/1037/www.northampton.ac.uk/lrs/Information/refword.html
+http://ustlib.ust.hk/search*chi/cPL1275+.F426+1991/cpl+1275+f426+1991/-5,1,1,E/frameset&F=cpl+1273+y36+1982&1,1,
+http://stormix.com/en/resources/packages/tex/devel/debmake
+http://stormix.com/en/resources/packages/tex/devel/doc++
+http://stormix.com/en/resources/packages/tex/devel/ftnchek
+http://stormix.com/en/resources/packages/tex/devel/libnet0-dev
+http://stormix.com/en/resources/packages/tex/devel/libobgtk-dev
+http://stormix.com/en/resources/packages/tex/devel/netatalk-dev
+http://stormix.com/en/resources/packages/tex/devel/pact-base
+http://stormix.com/en/resources/packages/tex/devel/scalapack1-mpich
+http://members.tripod.co.jp/sugisaka/?M=A
+http://www.szinfo.com/book/wai/no/fa/h/hongyuhei/011.htm
+http://www.szinfo.com/book/wai/no/fa/h/hongyuhei/054.htm
+http://www.centc251.org/forums/aca-1/dispatch.cgi/hsi/listUnseen/fol/100205/20,0/1230074
+http://www.crutchfield.com/cgi-bin/S-p5rPnwuC0SA/Auto.asp
+http://www.abb.co.uk/global/seapr/SEAPR035.NSF/viewUNID/f79b6db19a951ce0c125697300319a41!OpenDocument&ExpandSection=6,4,8,5
+http://freebsd.ntu.edu.tw/perl/authors/id/A/AO/AOCINAR/?S=A
+http://www.gaymencam.com/elke.html
+http://www.linux.com/networking/network/industry/new/web_server/website/
+http://www.tccomputers.com/cgi-bin/bp/1899758621/products/removeabledrives/removeabledrives.htm
+http://www.tccomputers.com/cgi-bin/bp/1899758621/store/showcart.html
+http://www.highwired.net/Guidance/Section/0,1860,1779-27626,00.html
+http://gd.cnread.net/cnread1/net/zpj/r/repinsky/005.htm
+http://www.amateurplatinum.com/tubal-ligationmilk/pregnanttubal-ligation/off-the-ragnipples/jizz-dribbling-cumshotscumming/{amateurlink}
+http://home.dqt.com.cn/~why/wenzhang/ckpajq/.htm
+http://ftp.fi.debian.org/debian/dists/woody/non-free/binary-all/doc/?D=A
+http://www.linux.com/networking/network/website/hardware/howto/Linuxcare/
+http://www.linux.com/networking/network/website/hardware/howto/sales/
+http://shn.webmd.com/printing/asset/adam_imagepage_8626
+http://www.geocities.co.jp/Outdoors/2127/bangai_makuyama.html
+http://www2.to/souhey
+http://www.hotelboulevard.com/fr/paris/standard/html73b90b9d262d517e98c9d779b3b09b7a/sessionLang/ANG/prov/browse/cp/75017/resultatSearch.html
+http://perso.wanadoo.fr/olivier.leieber/page22.html
+http://www.computer-networking.de/studenten/dv_labor/onlinebuecher/apache/sections.html
+http://saejong.pufs.ac.kr/~cilim/homepage/link.html
+http://cafe3.daum.net/Cafe-bin/Bbs.cgi/hopepds/qry/zka/B2-kCYFp/qqatt/^
+http://www3.newstimes.com/archive99/jun1899/lch.htm
+http://www.7thlevel.com/python/cwot/demo/
+http://www.paidmania.com/getpaid/signup/100/4632
+http://yp.gates96.com/12/14/0/31.html
+http://yp.gates96.com/12/14/0/43.html
+http://yp.gates96.com/12/14/0/60.html
+http://yp.gates96.com/12/14/1/18.html
+http://yp.gates96.com/12/14/1/44.html
+http://yp.gates96.com/12/14/1/64.html
+http://yp.gates96.com/12/14/1/82.html
+http://yp.gates96.com/12/14/2/84.html
+http://yp.gates96.com/12/14/3/61.html
+http://yp.gates96.com/12/14/4/65.html
+http://yp.gates96.com/12/14/5/24.html
+http://yp.gates96.com/12/14/5/49.html
+http://yp.gates96.com/12/14/5/60.html
+http://yp.gates96.com/12/14/5/62.html
+http://yp.gates96.com/12/14/6/20.html
+http://yp.gates96.com/12/14/6/51.html
+http://yp.gates96.com/12/14/7/28.html
+http://yp.gates96.com/12/14/7/85.html
+http://yp.gates96.com/12/14/7/93.html
+http://planet.gaiax.com/home/kito/main
+http://www.svt.se/falun/packat/program/603/images/1rep/?D=A
+http://volunteersolutions.org/swt/volunteer/opp/one_151124_printer_detailed.html
+http://fyi.cnn.com/ASIANOW/asiaweek/97/1003/nat1.html
+http://www.farhi.org/ps09/ps09_233.htm
+http://yp.gates96.com/6/8/30/27.html
+http://biz.yahoo.com/apf/000929/tire_death_7.html
+http://www.studentadvantage.gamers.com/game/135583
+http://www.studentadvantage.gamers.com/game/45759
+http://yp.gates96.com/6/8/30/44.html
+http://yp.gates96.com/6/8/30/50.html
+http://yp.gates96.com/6/8/30/72.html
+http://yp.gates96.com/6/8/30/86.html
+http://yp.gates96.com/6/8/30/89.html
+http://yp.gates96.com/6/8/31/78.html
+http://yp.gates96.com/6/8/31/88.html
+http://yp.gates96.com/6/8/32/3.html
+http://yp.gates96.com/6/8/32/24.html
+http://yp.gates96.com/6/8/32/34.html
+http://yp.gates96.com/6/8/33/14.html
+http://yp.gates96.com/6/8/33/42.html
+http://yp.gates96.com/6/8/33/75.html
+http://yp.gates96.com/6/8/34/32.html
+http://yp.gates96.com/6/8/34/97.html
+http://yp.gates96.com/6/8/35/53.html
+http://yp.gates96.com/6/8/35/98.html
+http://yp.gates96.com/6/8/36/74.html
+http://yp.gates96.com/6/8/36/99.html
+http://yp.gates96.com/6/8/38/92.html
+http://yp.gates96.com/6/8/38/97.html
+http://yp.gates96.com/6/8/39/45.html
+http://yp.gates96.com/6/8/39/69.html
+http://tour.stanford.edu/tour/29.0/gMlPb
+http://idl.tucows.com/winme/adnload/138396_30343.html
+http://idl.tucows.com/winme/adnload/138395_29743.html
+http://web.singnet.com.sg/~tay7012i/family.htm
+http://www.chaos.dk/sexriddle/p/f/g/j/o/
+http://lcweb2.loc.gov/ll/llnt/070/?S=A
+http://lcweb2.loc.gov/ll/llnt/070/0100/
+http://www.crosswinds.net/~lucifern/
+http://pub14.ezboard.com/fblazinofdablazinestdabattledome.subscribeUnregisteredToTopic?topicID=190.topic
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/computers/lit/quizz/programs/unlambda/misc/peanuts.html
+http://members.se.tripod.de/svdata/inglis/sida2.htm
+http://www.fogdog.com/cedroID/ssd3040183217284/crs/hp/nav/stores/golf/
+http://198.103.152.100/search*frc/tOperations+guide+to+ZIM/toperations+guide+to+zim/-17,-1,0,E/2browse
+http://herndon1.sdrdc.com/cgi-bin/com_detail/C00186353
+http://www.j2ee.com/products/javamail/javadocs/javax/mail/Flags.html
+http://www.j2ee.com/products/javamail/javadocs/javax/mail/Header.html
+http://www.intellicast.com/Sail/World/UnitedStates/FourCorners/Arizona/LakeMeadCanyon/LocalWinds/d1_18/
+http://genforum.genealogy.com/cgi-bin/print.cgi?guill::871.html
+http://in.egroups.com/message/ucc-medicine/9
+http://in.egroups.com/message/ucc-medicine/14
+http://www-uk3.cricket.org/link_to_database/PLAYERS/WOMEN/AUS/WILSON_B_02011221/index.NSW-WOMEN.html
+http://ftp.du.se/disk4/FreeBSD/FreeBSD-current/www/ja/releases/?M=A
+http://www.citythek.de/koeln/eduscho/fsinhalt.htm
+http://198.103.152.100/search*frc/cCA1+MPY30+97C31/cca1+mpy30+97c31/-5,-1,,E/browse
+http://ftp.nsysu.edu.tw/Linux/RedHat/doc/en/HOWTOS/localization/Serbian/?N=D
+http://mk158.tripod.co.jp/old/praga1/do/bio.html
+http://oneplace.adbureau.net/accipiter/adclick/site=ONEPLACE/area=INDEX/POSITION=FOOTER/AAMSZ=468x60/ACC_RANDOM=449975866078
+http://members.tripod.co.jp/Primrose/honeydcolumn3.html
+http://911codes.com/games/platform/n64/sect/div/cont/list_cheat/spray/y/id/0000009564/gid/0000003291/_cheats/_walkthroughs/_codes/_pc/_n64/_psx/_gameboy/_playstation/
+http://iqseek.shop.goto.com/compperiph/monfol/mon/search/detail.jhtml?MANUF=ViewSonic&MODEL=E790
+http://iqseek.shop.goto.com/compperiph/monfol/mon/search/detail.jhtml?MANUF=ViewSonic&MODEL=GA655
+http://plat.debian.or.jp/debian/dists/stable/main/binary-powerpc/shells/?M=A
+http://retailer.gocollect.com/do/session/1912686/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/shipping_policy.asp
+http://vvv.geocities.co.jp/Playtown-Yoyo/5287/
+http://vvv.geocities.co.jp/Playtown-Yoyo/5714/
+http://vvv.geocities.co.jp/Playtown-Yoyo/5750/
+http://genforum.genealogy.com/cgi-genforum/forums/charpia.cgi?3
+http://www.amateurplatinum.com/tubal-ligationmilk/plus-sizecoushin-for-the-pushin/best-friendsjail-bait/vietnamese/ac/dclubrication/bisexualelbow-grease.html
+http://library.bangor.ac.uk/search/tContemporary+psychology+series/tcontemporary+psychology+series/-17,-1,0,B/2exact&F=tcontemporary+problems+in+geography&1,4
+http://www-d0.fnal.gov/cgi-bin/cvsweb.cgi/calreco/VERSION?only_with_tag=p05-br
+http://www.158china.com/news/2000/08/21/52747.htm
+http://www.ln.cei.gov.cn/dh/hgjj/wscf/hx/hx031009.txt
+http://www.ln.cei.gov.cn/dh/hgjj/wscf/hx/hx031106.txt
+http://www.ln.cei.gov.cn/dh/hgjj/wscf/hx/hx031208.txt
+http://www.ln.cei.gov.cn/dh/hgjj/wscf/hx/hx031507.txt
+http://www.ln.cei.gov.cn/dh/hgjj/wscf/hx/hx032406.txt
+http://www.ln.cei.gov.cn/dh/hgjj/wscf/hx/hx032902.txt
+http://www.ln.cei.gov.cn/dh/hgjj/wscf/hx/hx041501.txt
+http://www.ln.cei.gov.cn/dh/hgjj/wscf/hx/hx041611.txt
+http://www.ln.cei.gov.cn/dh/hgjj/wscf/hx/hx1.txt
+http://wuarchive.wustl.edu/edu/math/software/multi-platform/SLATEC/G/G2/G2H/G2H2/sbols/
+http://www.loststars.net/story4/ab200-2.html
+http://www.indian-express.com/ie/daily/19981219/35350564.html
+http://www.indian-express.com/ie/daily/19981219/35351234.html
+http://www.homestead.com/jennyb/pets.html
+http://www.allgemeine-immobilien-boerse.de/kanada/verkauf/Gemeinsam/Inserieren/Allgemeine-IB/Versteigerungen-IB/Startseite/Gemeinsam/suche.htm
+http://www.sankei.co.jp/databox/paper/9808/06/paper/today/sports/soccer/06soc002.htm
+http://rex.skyline.net/navigate.cgi?history,collectibles,recreation,sculpture,arts
+http://tjohoo.se/sport/snowboard/2.php3
+http://www.du-et.net/prof/n/nkaworu.html
+http://www.iwon.com/home/movies/movies_summary_page/0,13160,383543,00.html
+http://www.iwon.com/home/movies/movies_summary_page/0,13160,481885,00.html
+http://www.iwon.com/home/movies/movies_summary_page/0,13160,372508,00.html
+http://pub13.ezboard.com/fvisualbasicexplorergettingstarted.emailToFriend?topicID=861.topic
+http://www.fogdog.com/cedroID/ssd3040183158417/customer_service/
+http://www.fogdog.com/cedroID/ssd3040183158417/cgi-bin/CedroCommerce?func=EditBasket
+http://www.fogdog.com/cedroID/ssd3040183158417/nav/products/cycling/1y/software/
+http://www.niwl.se/wais/new/28/28189.htm
+http://retailer.gocollect.com/do/session/1912674/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/clubhouse/suggestions.asp
+http://www.trax.nilex.co.uk/trax.cgi/A1C/A2R/A2U/B3R/A1U/Resign/
+http://www.sofitware.com/books/sci05/0471969664.html
+http://www.genome.wustl.edu:8021/gsc1/est/zebrafish_reports/old_rank_reports/zebrafish.rank.990322
+http://www.genome.wustl.edu:8021/gsc1/est/zebrafish_reports/old_rank_reports/zebrafish.rank.991004
+http://www.farhi.org/ps01/ps01_015.htm
+http://www-usa10.cricket.org/link_to_database/ARCHIVE/WORLD_CUPS/WC99/STATS/BY_TEAM/SL/WC99_BOWL_BEST_INNS_SR_SL.html
+http://www.online.kokusai.co.jp/Stock_corner/V0043480/wrd/G500/stock_corner/stock_corner.html
+http://www.online.kokusai.co.jp/Mmf_corner/V0043480/mmf_corner/mmf_corner/url
+http://mediate.magicbutton.net/do/session/625604/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-cust.html
+http://www.malaysia.net/lists/sangkancil/1999-05/frm00449.html
+http://www.bigstar.com/contest/index.cfm/4ae093fg371d8ddg3?fa=contest
+http://www.bigstar.com/tv/index.cfm/4ae093fg371d8ddg3
+http://linux.tucows.dia.dk/gnomehtml/adnload/49933_5879.html
+http://dc.web.aol.com/roanoke/health/directories.dci?type=professionals
+http://dc.web.aol.com/roanoke/health/categories.dci?category=fitnessdiet
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/linux/drivers/isdn/icn/Makefile?only_with_tag=davem-cvs-merge
+http://dennou-h.gfd-dennou.org/arch/cc-env.old/db/?M=A
+http://www.envy.nu/wildcats/gare.html
+http://www.envy.nu/wildcats/horst.html
+http://www.linux.com/networking/network/release/performance/updates/Netscape/
+http://ftpsearch.belnet.be/pub/os/linux/Linux-sunsite.unc/distributions/ultra/Users-Guide/?S=A
+http://www.chaos.dk/sexriddle/n/f/p/g/a/
+http://pub24.ezboard.com/fphilosophersstonefrm7.showAddTopicScreenFromWeb
+http://pub24.ezboard.com/fphilosophersstonefrm7.showMessage?topicID=10.topic
+http://www.yorosiku.net:8080/-_-http://www2.biglobe.ne.jp/~animenet/jan222/note/bbs2.html
+http://www.web-chart.com/Detail.htm?s=2568&c=229
+http://www.brio.de/BRIO.catalog/39fe2f5009021d362740d472aa780645/UserTemplate/8
+http://www.service911.com/egghead/step/0,2743,10+55+157+24348+17295_2,00.html
+http://home.pchome.com.tw/computer/judy7777/fast-7.htm
+http://big5.peopledaily.com.cn/zdxw/11/20000126/200001261111.html
+http://www.nhic.or.kr/netbbs/Bbs.cgi/nhic31792/lst/qqo/012D
+http://sunsite.org.uk/public/usenet/news-faqs/alt.answers/paranormal/faq
+http://newsone.net/nnr/listl/alt.bbs.elebbs/1
+http://ourworld.compuserve.com/homepages/hallg/mg_vor.htm
+http://www.world001.com/forum/yue/1573.html
+http://www.greenleaves.com/bookcat/gb_1567112730.html
+http://quotidiano.monrif.net/chan/motori:1119539:/2000/10/30:
+http://quotidiano.monrif.net/chan/motori:926303:/2000/10/30:
+http://quotidiano.monrif.net/chan/motori:944719:/2000/10/30:
+http://home.online.tj.cn/~madgoe/subtitle/nt/nt363.htm
+http://home.online.tj.cn/~madgoe/subtitle/nt/nt352.htm
+http://home.online.tj.cn/~madgoe/subtitle/nt/nt343.htm
+http://home.online.tj.cn/~madgoe/subtitle/nt/nt327.htm
+http://home.online.tj.cn/~madgoe/subtitle/nt/nt320.htm
+http://www.collectingnation.com/cgi-bin/bn/request_email.mod?EHANDLE=Vincze
+http://www.beanienation.com/cgi-bin/bn/view_feedback.mod?HANDLE=ving
+http://www.collectingnation.com/cgi-bin/bn/request_email.mod?EHANDLE=Vinrye
+http://www.collectingnation.com/cgi-bin/bn/request_email.mod?EHANDLE=Vinzy
+http://www.beanienation.com/cgi-bin/bn/view_feedback.mod?HANDLE=violinist
+http://www.beanienation.com/cgi-bin/bn/view_feedback.mod?HANDLE=Violin
+http://www.collectingnation.com/cgi-bin/bn/request_email.mod?EHANDLE=vione
+http://www.beanienation.com/cgi-bin/bn/view_feedback.mod?HANDLE=viper0669
+http://www.missouri.edu/HyperNews/get/writery/poetry/1.html?embed=-1
+http://www.missouri.edu/HyperNews/get/writery/poetry/6.html?outline=1&embed=1
+http://www.missouri.edu/HyperNews/get/writery/poetry/9.html?outline=-1&embed=1
+http://www.missouri.edu/HyperNews/get/writery/poetry/20.html?outline=3&embed=1
+http://www.missouri.edu/HyperNews/get/writery/poetry/21.html?outline=-1&embed=1
+http://www.missouri.edu/HyperNews/get/writery/poetry/23.html?outline=1&embed=1
+http://www.missouri.edu/HyperNews/get/writery/poetry/38.html?outline=1&embed=1
+http://fi.egroups.com/messages/Avon3DayBoston/5
+http://www.online.kokusai.co.jp/Demo/V0043481/wrd/G400/demo/
+http://www.jamba.de/KNet/_KNet-TQt8j1-PEd-139qr/showInfo-werbung.de/node.0/cde7f1uou
+http://computalynx.tucows.com/winnt/adnload/73435_29524.html
+http://www.intellicast.com/Golf/World/UnitedStates/Northwest/Oregon/OregonDunes/THUNDERcast/d2_06/
+http://202.105.55.146/h0/news/200009/20/jty7.htm
+http://pda.tucows.edisontel.com/newton/newtsfiction_size.html
+http://pda.tucows.edisontel.com/newton/adnload/33238_19961.html
+http://hem.fyristorg.com/lottaleman/LLfar/1_2942.htm
+http://www.norrblom.com/..\hund\1996\s2665496.htm
+http://www.ferien-immobilien.de/niedersachsen/weserbergland/Verkauf/Gemeinsam/MarketingStrategie/Allgemeine-IB/Gemeinsam/Super-Zins-Konditionen/Private-IB/Startseite/Default.htm
+http://nathanael.upi.jussieu.fr/tele6.nsf/autres+centres+de+formations!OpenPage&ExpandSection=14,18,11,9,15,8
+http://dennou-h.gfd-dennou.org/arch/cc-env.old/xtop/TEBIKI.top.rs590
+http://www.amzn.com/exec/obidos/search-handle-url/index=vhs&field-director=Jim%20Stenstrum/
+http://www.amzn.com/exec/obidos/tg/browse/-/169237/
+http://www.flora.org/flora.oclug/old-6088
+http://www.msn.expedia.co.uk/wg/Images/P24601.htm
+http://www.asahi-net.or.jp/~ei2h-kdu/photos/rail/sanin/amarube3.html
+http://au.yahoo.com/Business_and_Economy/Shopping_and_Services/Health/Providers/By_Region/U_S__States/Montana/Complete_List/
+http://www.staroriental.net/nav/soeg/ihf,aai,n2,118,Electric+Wave+Girl+1998.html
+http://www.hig.se/(accessed,formoutput,referrer,smallcaps,sqlquery)/~jackson/roxen/
+http://carefinder.digitalcity.com/fargond/sports/team.dci?league=NF2&team=VAC
+http://carefinder.digitalcity.com/fargond/sports/team.dci?league=NF2&team=GAA
+http://carefinder.digitalcity.com/fargond/sports/team.dci?league=NF2&team=AAB
+http://carefinder.digitalcity.com/fargond/sports/team.dci?league=NF2&team=AAF
+http://newnova.tucows.com/preview/60922.html
+http://www-d0.fnal.gov/d0dist/dist/releases/test/l3fsmtcluster/rcp/?S=A
+http://www.cs.rit.edu/~ats/inferno/man/html/proto8.htm
+http://dandini.cranfield.ac.uk/vl=-39835473/cl=140/nw=1/rpsv/cw/web/nw1/browse.htm
+http://homepage.mac.com/nanameneko/job/architecture-oriented/OHP/Why/why_05.html
+http://ftp.sunet.se/pub/FreeBSD/FreeBSD-current/ports/games/CaribbeanStud/?M=A
+http://ftp.sunet.se/pub/FreeBSD/FreeBSD-current/ports/games/CaribbeanStud/distinfo
+http://ads3.zdnet.com/c/g=r734&c=a53975&idx=2000.10.30.21.30.24/www.zdnet.com/downloads/stories/info/0,,000FDG,.html
+http://yp.gates96.com/6/57/80/89.html
+http://yp.gates96.com/6/57/81/42.html
+http://yp.gates96.com/6/57/81/66.html
+http://yp.gates96.com/6/57/82/16.html
+http://yp.gates96.com/6/57/82/61.html
+http://yp.gates96.com/6/57/83/37.html
+http://yp.gates96.com/6/57/83/54.html
+http://yp.gates96.com/6/57/84/14.html
+http://yp.gates96.com/6/57/85/7.html
+http://yp.gates96.com/6/57/85/24.html
+http://yp.gates96.com/6/57/85/35.html
+http://yp.gates96.com/6/57/85/64.html
+http://yp.gates96.com/6/57/86/80.html
+http://yp.gates96.com/6/57/86/96.html
+http://yp.gates96.com/6/57/87/15.html
+http://yp.gates96.com/6/57/89/2.html
+http://yp.gates96.com/6/57/89/95.html
+http://www.oncology.com/v2_MainFrame/1,1614,_12|00332|00_21|002|00_04|0039|00_38|00188,00.html
+http://library.bangor.ac.uk/search/aEllis,+Gail/aellis+gail/-5,-1,0,B/exact&F=aellis+griffith+1844+1913&1,9
+http://www.rezel.enst.fr/ftp/linux/distributions/debian/CD-2/debian/dists/unstable/contrib/source/mail/?S=A
+http://itcareers.careercast.com/texis/it/itjs/+SwwBmeYKD86e8hwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewhPndhBiwGna5O5BnManDtoDnnGamn5otDamnVncdpaGnwcaBoMnaoDhdGMwBodDaDnBidGAanLpnGonDqnaMFqhTfR20Dzme4twwwpBmex_D86ejxwww5rme6dwwwBrmeZpwww/morelike.html
+http://esatnet.tucows.com/winnt/adnload/31316_29136.html
+http://home.c2i.net/w-225961/steinare/brosjyre.htm
+http://aleph.tau.ac.il:4500/ALEPH/ENG/ATA/AAS/AAS/FIND-ACC/0860271
+http://www.chaos.dk/sexriddle/v/c/w/d/r/
+http://www9.hmv.co.uk:5555/do/session/1347760/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d135_sd0_pt0.html
+http://tagesanzeiger.ch/archiv/99november/991122/79295.HTM
+http://www.pacifictech.com.cn/pcsoftware/sj/jq/00803.htm
+http://www.pacifictech.com.cn/pcsoftware/sj/jq/00430b.htm
+http://www.pacifictech.com.cn/pcsoftware/zl/syjq/dmtgj/old/tuxing/3d/20000131.html
+http://www.building.com/communities/texis/db/go/+DexVFdeKmYnwrmwxerJOwrmwx3exmww/profile.html
+http://my.egroups.com/message/mathies/43?source=1
+http://www.brio.de/BRIO.catalog/39fe2f5706df064c273fd472aa78067c/UserTemplate/6
+http://www.brio.de/BRIO.catalog/39fe2f5706df064c273fd472aa78067c/UserTemplate/9
+http://www.egroups.com/messages/GollyBeenz/44
+http://www.buybuddy.com/sleuth/15/1/1020507/495848/
+http://www.brio.de/BRIO.catalog/39fe2f41010c308a2742d472aa7806a7/UserTemplate/5
+http://www.ferien-immobilien.de/hessen/bad-hersfeld/Verkauf/IIM-Teil/Startseite/Private-IB/Allgemeine-IB/Gemeinsam/versicherungen/gebaeude/deckungsumfang.htm
+http://www.ferien-immobilien.de/hessen/bad-hersfeld/Verkauf/IIM-Teil/Startseite/Private-IB/Allgemeine-IB/Gemeinsam/impressum.htm
+http://beetle.marion.ohio-state.edu/Bratt2000/D0029/I10769.html
+http://members.tripod.lycos.co.kr/RAINBOR/?D=A
+http://www.eos.ncsu.edu/eos/info/bae/bae324_info/
+http://www.chez.com/mousis/vg/aqui/pages/0006.htm
+http://search.chollian.net/cgi-bin/filter.cgi?cid=2052&p=1
+http://channel.nytimes.com/1998/03/15/technology/cybertimes/eurobytes/
+http://www4.nas.edu/ohr.nsf/All+Documents/Major+Units?OpenDocument&ExpandSection=13,4,2,7,11
+http://uk.dir.yahoo.com/Regional/Countries/Mexico/States/Baja_California/Cities/Ensenada/Travel_and_Transportation/Accommodation/Caravan_Parks_and_Campgrounds/
+http://ring.toyama-ix.net/archives/mac/info-mac/inet/_Mail/_Eudora/
+http://sport.voila.fr/it/calcio/euro2000/teams/por/squad/nunogomes.html
+http://idefix-41.cs.kuleuven.ac.be/~henk/DPS/
+http://library.bangor.ac.uk/search/dLaw+--+Study+and+teaching+--+Great+Britain/dlaw+study+and+teaching+great+britain/-5,-1,0,B/buttonframe&F=dlaw+study+and+teaching+great+britain&7,,7
+http://www.eveclub.com/cgi-bin/eveclub.front/972959440822/Catalog/1000002
+http://www.eveclub.com/cgi-bin/eveclub.front/972959440822/Catalog/1000062
+http://ring.shibaura-it.ac.jp/archives/FreeBSD-PC98/dists/4.0-RELEASE/XF86336/PC98-Servers/?N=D
+http://www.uq.edu.au/site-index/index.phtml?site_tree_data=1,91,95,203,338,344,2,6,182,148
+http://www.uq.edu.au/site-index/index.phtml?site_tree_data=1,91,95,203,338,344,2,6,182,163
+http://www.xmission.com/(apocalypse,art,caffiene,geek,misc,music,music,caffiene,art,toys,dots,edge,misc,shopping,ftp,places,privacy,geek,cuseeme,apocalypse,people,stuffiuse,people,places,shopping,stuffiuse,toys)/~bill/links.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=confinarias&l=pt
+http://www.xmission.com/(apocalypse,art,caffiene,cuseeme,geek,misc,music,music,caffiene,art,toys,dots,edge,misc,shopping,ftp,places,privacy,geek,cuseeme,apocalypse,people,stuffiuse,places,privacy,stuffiuse,toys)/~bill/links.html
+http://www.gigclub.co.jp/tanigawa/tanigawa/980915/menu.html
+http://www.3w-sciencefiction.de/SmithWilliamK/SmithWilliamK0126528756.htm
+http://w3c1.inria.fr/Mobile/posdep/Presentations/Mogid/sld014.htm
+http://members.tripod.co.jp/view_i/p.html
+http://202.99.23.245/zdxw/11/20000317/200003171117.html
+http://www.jpc-music.com/7334085.htm
+http://library.bangor.ac.uk/search/aLibrary+Association/alibrary+association/-5,-1,0,B/buttonframe&F=alibrary+association&2,,64
+http://www.sf.digitalcity.com/puntagordafl/sports/team.dci?league=FSL&team=CHA
+http://www.sf.digitalcity.com/puntagordafl/sports/team.dci?league=FSL&team=LAK
+http://brain.brent.gov.uk/__802564ff0045d739.nsf/vWebAllPagesByLocsSrvd!OpenView&Start=33&Count=60&Collapse=45
+http://www.nypost.com/news/933.htm
+http://www.nypost.com/business/979.htm
+http://www.nypost.com/living/951.htm
+http://www.computer-networking.de/studenten/cn_intern/bauer/jobst/k07-graphik-gui/controls/swing/
+http://194.55.30.33/albanian/tema_gjermane/67823.html
+http://194.55.30.33/albanian/tema_gjermane/65962.html
+http://yp.gates96.com/14/85/10/12.html
+http://yp.gates96.com/14/85/11/98.html
+http://yp.gates96.com/14/85/12/24.html
+http://yp.gates96.com/14/85/13/57.html
+http://yp.gates96.com/14/85/14/92.html
+http://yp.gates96.com/14/85/16/37.html
+http://yp.gates96.com/14/85/16/51.html
+http://yp.gates96.com/14/85/16/78.html
+http://yp.gates96.com/14/85/17/38.html
+http://yp.gates96.com/14/85/17/48.html
+http://yp.gates96.com/14/85/17/91.html
+http://yp.gates96.com/14/85/19/35.html
+http://yp.gates96.com/14/85/19/88.html
+http://genforum.genealogy.com/cgi-genforum/forums/deppen.cgi?3
+http://www.ferien-immobilien.de/nordrhein-Westfalen/Muehlheim-ruhr/Verkauf/Private-IB/Startseite/Gemeinsam/Inserieren/Versteigerungen-IB/Startseite/Ferien-IB/Startseite/
+http://www.redrocksports.com/sports/webSession/shopper/RR972959668-31057/store/dept-5/department/dept-5/item/51800
+http://www.redrocksports.com/sports/webSession/shopper/RR972959668-31057/store/dept-5/department/dept-5/item/53510
+http://www.redrocksports.com/sports/webSession/shopper/RR972959668-31057/store/dept-5/department/dept-5/item/52600
+http://www.redrocksports.com/sports/webSession/shopper/RR972959668-31057/store/dept-5/department/dept-5/item/50510
+http://www.redrocksports.com/sports/webSession/shopper/RR972959668-31057/store/dept-5/department/dept-5/item/50400
+http://polygraph.ircache.net:8181/http_-2www.horizonfinance.com/http_-2www.netscape.com/download/http_-2www.microsoft.com/ie/http_-2207.91.150.20/http_-2www.updowntowner.org/julyjamm/headliners.html
+http://www.ccurrents.com/magazine/national/1702/nets31702.html
+http://adept.subportal.com/sn/Themes/Vehicle_Themes/5090.html
+http://www.fogdog.com/cedroID/ssd3040183211390/nav/products/outlet/1a/fishing/
+http://www.linux.com/networking/network/communications/article/unix/sales/
+http://fyi.cnn.com/content/US/9902/25/germans.death.penalty.ap/
+http://fyi.cnn.com/US/9902/09/monk.execute.ap.02/
+http://fyi.cnn.com/WORLD/asiapcf/9902/06/PM-Philippines-DeathPena.ap/
+http://pub11.ezboard.com/ucivik.showPublicProfile
+http://playboy.software.net/PKIN005896/prod.htm
+http://www.linux.com/networking/network/help/free/performance/install/
+http://www.linux.com/networking/network/help/free/performance/X/
+http://se.egroups.com/message/ghost_tales/1490
+http://niteowl.userfriendly.net/linux/RPM/rawhide/1.0/i386/usr_src_linux-2.4.0_include_Tree.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=coexistissem&l=pt
+http://promed.univ-rennes1.fr/cerf/ico_an/IDRE/21_HADM.HTM
+http://promed.univ-rennes1.fr/cerf/ico_an/IDRE/25_HADM.HTM
+http://promed.univ-rennes1.fr/cerf/ico_an/IDRE/86_HADM.HTM
+http://promed.univ-rennes1.fr/cerf/ico_an/IDRE/88_HADM.HTM
+http://promed.univ-rennes1.fr/cerf/ico_an/IDRE/90_HADM.HTM
+http://promed.univ-rennes1.fr/cerf/ico_an/IDRE/HADM6.HTM
+http://www.estrelladigital.es/000814/articulos/economia/correos.htm
+http://itcareers.careercast.com/texis/it/itjs/+awwBme4CD86LxwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewPPnBwpcnaqdGpdGwBnaoDhdGMwBodDahoDma5BdGnaq15BdMnGa5nGVoqnaqdDBwqBamo5BGox1BodDaMwDwtnMnDBaMFqrIRE7P0IDzme_xwwwpBmHe0B-deaqwww5rmsmwwBrme7Dwww/morelike.html
+http://yp.gates96.com/3/79/50/30.html
+http://yp.gates96.com/3/79/50/54.html
+http://yp.gates96.com/3/79/51/1.html
+http://yp.gates96.com/3/79/51/11.html
+http://yp.gates96.com/3/79/51/80.html
+http://yp.gates96.com/3/79/52/27.html
+http://yp.gates96.com/3/79/52/81.html
+http://yp.gates96.com/3/79/53/81.html
+http://yp.gates96.com/3/79/54/0.html
+http://yp.gates96.com/3/79/54/31.html
+http://yp.gates96.com/3/79/55/74.html
+http://yp.gates96.com/3/79/55/78.html
+http://yp.gates96.com/3/79/56/72.html
+http://yp.gates96.com/3/79/57/0.html
+http://yp.gates96.com/3/79/58/27.html
+http://yp.gates96.com/3/79/58/31.html
+http://yp.gates96.com/3/79/58/48.html
+http://yp.gates96.com/3/79/58/76.html
+http://yp.gates96.com/3/79/58/99.html
+http://yp.gates96.com/3/79/59/27.html
+http://yp.gates96.com/3/79/59/32.html
+http://yp.gates96.com/3/79/59/49.html
+http://yp.gates96.com/3/79/59/81.html
+http://yp.gates96.com/3/79/59/83.html
+http://startribune.atevo.com/misc/print_article/0,3869,4504302,00.html
+http://browse.carnaby.com/home/showcase/6/381/2078/A0638120780000EA01.html
+http://www.checkout.com/music/earmail/form/1,7650,325272-1761567,00.html
+http://ring.shibaura-it.ac.jp/archives/doc/jpnic/minutes/committee/200007/shiryou-4-1.txt
+http://www.secinfo.com/d1ZMQs.51h.htm
+http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/AtlantisPBEM/CVSROOT/modules?only_with_tag=MAIN
+http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/AtlantisPBEM/CVSROOT/modules?only_with_tag=HEAD
+http://ftp.bitcon.no/tucows/adnload/4961_28325.html
+http://yp.gates96.com/3/37/0/21.html
+http://yp.gates96.com/3/37/0/29.html
+http://yp.gates96.com/3/37/0/80.html
+http://yp.gates96.com/3/37/0/87.html
+http://yp.gates96.com/3/37/1/9.html
+http://yp.gates96.com/3/37/2/83.html
+http://yp.gates96.com/3/37/2/92.html
+http://yp.gates96.com/3/37/3/26.html
+http://yp.gates96.com/3/37/4/9.html
+http://yp.gates96.com/3/37/4/29.html
+http://yp.gates96.com/3/37/5/31.html
+http://yp.gates96.com/3/37/5/49.html
+http://yp.gates96.com/3/37/5/51.html
+http://yp.gates96.com/3/37/5/63.html
+http://yp.gates96.com/3/37/5/95.html
+http://yp.gates96.com/3/37/6/0.html
+http://yp.gates96.com/3/37/6/4.html
+http://yp.gates96.com/3/37/7/22.html
+http://yp.gates96.com/3/37/8/10.html
+http://yp.gates96.com/3/37/8/50.html
+http://yp.gates96.com/3/37/8/92.html
+http://yp.gates96.com/3/37/9/46.html
+http://ftp.digex.net/debian/dists/woody/contrib/binary-sh/libs/?N=D
+http://students.lsu.edu/students/main.nsf/c81d2bf8cb0b80ff862566fb00105ab2/7f3436ae9cb1268886256773006f9288!OpenDocument&ExpandSection=4,15,12,16
+http://in.egroups.com/group/bbw-uk
+http://home.swipnet.se/~w-20817/
+http://shop.puretec.de/kunden/19867293/detailansicht_Aku1025B.html
+http://www.rezeptkoch.de/Rezepte/Heimisches_/Gemuse/Sommerliche_Gemusegerichte/sommerliche_gemusegerichte_2.html
+http://www.rezeptkoch.de/Rezepte/Heimisches_/Gemuse/Kohl/kohl_4.html
+http://www.rezeptkoch.de/Rezepte/Heimisches_/Gemuse/Kohl/kohl_11.html
+http://www.chinainvest.com.cn/C/Showdetail/20359.html
+http://tucows.sp-plus.nl/winme/preview/141310.html
+http://www.al-hujjat.grid9.net/gnomehtml/ent_enhance_rating.html
+http://www.warmbloods.net/breeding/_vti_bin/shtml.dll/disc123_post.htm?1260
+http://ftp.sunet.se/pub/FreeBSD/FreeBSD-current/ports/net/ruby-snmp/Makefile
+http://basil.cs.uwp.edu/Documentation/java/jdk/docs/guide/sound/prog_guide/chapter3.fm.html
+http://tucows.1web.it/winme/preview/75525.html
+http://uk-wire.ukinvest.com/articles/200009180701200586R.html
+http://www.ozon.ru/detail.cfm/ent=33&id=953&add2navigator=1&txt=1
+http://cometweb01.comet.co.uk/do!session=131984&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkkHbqpLZXmLbkZHljlKaltLkilLXalKfkaLbukKeqjLi1
+http://community.webshots.com/photo/3922869/3923445TSuTSQIWpD
+http://www.eveclub.com/cgi-bin/eveclub.front/972959447434/Catalog/1000040
+http://www.tvstore.com/browse/TV/NIGHTSHI/s.nXZNPRgQ
+http://www.tvstore.com/browse/TV/COMIC/s.nXZNPRgQ
+http://www.xmwb.sh.cn/xmwb/19981016/GB/13389^8101623.htm
+http://helios.nlib.ee/search*est/tThe+threshold+series/tthreshold+series/-5,-1,0,B/frameset&F=tthrillers&1,1
+http://www4.nas.edu/ohr.nsf/All+Documents/Major+Units?OpenDocument&ExpandSection=23,9,7,18
+http://ftp.bitcon.no/pub/windowsce/epoc/desktop5.htm
+http://ftp.lip6.fr/pub2/sgml-tools/website/HOWTO/Multicast-HOWTO/t1595.html
+http://ftp.rge.com/pub/X/XFree86/3.3.3.1/untarred/xc/programs/Xserver/
+http://ftp.rge.com/pub/X/XFree86/3.3.3.1/untarred/xc/programs/xwud/
+http://syix.tucows.com/win2k/adnload/73370_29328.html
+http://yp.gates96.com/0/54/80/40.html
+http://yp.gates96.com/0/54/80/56.html
+http://yp.gates96.com/0/54/80/61.html
+http://yp.gates96.com/0/54/80/79.html
+http://yp.gates96.com/0/54/81/11.html
+http://yp.gates96.com/0/54/81/25.html
+http://yp.gates96.com/0/54/81/58.html
+http://yp.gates96.com/0/54/82/48.html
+http://yp.gates96.com/0/54/82/75.html
+http://yp.gates96.com/0/54/83/0.html
+http://yp.gates96.com/0/54/84/12.html
+http://yp.gates96.com/0/54/84/67.html
+http://yp.gates96.com/0/54/85/47.html
+http://yp.gates96.com/0/54/85/59.html
+http://yp.gates96.com/0/54/86/52.html
+http://yp.gates96.com/0/54/86/55.html
+http://yp.gates96.com/0/54/86/79.html
+http://yp.gates96.com/0/54/86/87.html
+http://yp.gates96.com/0/54/87/12.html
+http://yp.gates96.com/0/54/87/81.html
+http://yp.gates96.com/0/54/88/97.html
+http://yp.gates96.com/0/54/89/90.html
+http://www.yorosiku.net:8080/-_-http://liinwww.ira.uka.de/bibliography/Distributed/SIGCOMM.94.html
+http://news.pchome.com.tw/ftv/health/20000915/
+http://www.emis.de/journals/EJDE/Volumes/Volumes/Monographs/1998/05/?N=D
+http://travelocity-dest.excite.com/DestGuides/0,1840,TRAVELOCITY|5706|3|1|159040|photo_id|4022,00.html
+http://travelocity-dest.excite.com/DestGuides/0,1840,TRAVELOCITY|5706|3|1|159040|photo_id|4020,00.html
+http://lhcbsoft.web.cern.ch/LHCbSoft/simmuon/v1/mgr/CVS/Root
+http://tucows.soneraplaza.nl/winme/adnload/137454_28942.html
+http://www.borland.nl/techpubs/jbuilder/jbuilder3/ui/wclass.html
+http://fi.egroups.com/links/dssf
+http://www.homestead.com/jcv2000/MBoard.html
+http://careershop.resumeshotgun.com/directory/italy/sardegna/o.10.p.4408.html
+http://www.hantsnet.co.uk/istcclr/cch32751.html
+http://www.hantsnet.co.uk/istcclr/cch16729.html
+http://www.hantsnet.co.uk/istcclr/cch03788.html
+http://www.hantsnet.co.uk/istcclr/cch05491.html
+http://www.hantsnet.co.uk/istcclr/cchr0418.html
+http://www.hantsnet.co.uk/istcclr/cchh2289.html
+http://www.hantsnet.co.uk/istcclr/cchh2074.html
+http://www.hantsnet.co.uk/istcclr/cch30426.html
+http://www.hantsnet.co.uk/istcclr/cch11726.html
+http://www.hantsnet.co.uk/istcclr/cch03858.html
+http://www.hantsnet.co.uk/istcclr/cche0920.html
+http://www.hantsnet.co.uk/istcclr/cch34768.html
+http://www.hantsnet.co.uk/istcclr/cchc2067.html
+http://www.hantsnet.co.uk/istcclr/cche1085.html
+http://www.v2music.com/Scripts/WebObjects-ISAPI.dll/V2_New_Publisher.woa/53771000000443000000339400000065451/v2tvindex.wo/614720000055451/1.14/3/Webobjects1
+http://www.sternonline.de/magazin/fotogalerie/hinz/index5.html
+http://www.envy.nu/Sing.html
+http://employment.subportal.com/sn/Themes/
+http://www.diogenes.ch/4DACTION/web_rd_aut_prview/a_id=7002120&area=&ID=483332
+http://wlink.tucows.com/winme/adnload/137847_29260.html
+http://tucows.computalynx.net/winnt/adnload/71633_28766.html
+http://ftp.up.pt/Linux/debian/dists/stable/main/disks-m68k/?M=A
+http://lcweb2.loc.gov/ll/llnt/009/0000/
+http://www.magma.ca/~denisd/africa/day02.html
+http://www.magma.ca/~denisd/africa/day16.html
+http://content.health.msn.com/message_board_author/802072
+http://ep.com/js/about/c0/189455
+http://ep.com/js/about/c0/154005
+http://www.realbig.com/miata/miata/1999-12/2340.html
+http://www.multimap.com/wi/33738.htm
+http://www.multimap.com/wi/148724.htm
+http://www.bemi-immobilien.de/Landhaus-Bordeaux/Gemeinsam/3d-service/Gemeinsam/versicherungen/lebensversicherung/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Gemeinsam/versicherungen/lebensversicherung/Gemeinsam/MarketingStrategie/Strategie.htm
+http://link.fastpartner.com/do/session/600347/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/create/learn.htm
+http://pub16.ezboard.com/fisnforumsfrm16.subscribeUnregisteredToTopic?topicID=731.topic
+http://freesoftware.subportal.com/sn/Business/Application_Add-ins/726.html
+http://people.freebsd.org/~knu/cgi-bin/cvsweb.cgi/ports/deskutils/genius/files/?sortby=date
+http://www.madein.nnov.ru/stat/index.phtml?cid=418&t=3
+http://citeseer.nj.nec.com/correct/294145
+http://www.phillips.semiconductors.com/pip/PCF5001H
+http://www.tvstore.com/browse/TV/BANK/s.Vaphccqs
+http://www.tvstore.com/browse/TV/SCRIPT/s.Vaphccqs
+http://www.tvstore.com/aboutus/s.Vaphccqs
+http://www.fogdog.com/cedroID/ssd3040183205929/nav/products/featured_brands/3b/arm_warmers/
+http://orders.mkn.co.uk/bear/steiff/classic/order/now.en$NOK?what-e=1
+http://www.crutchfield.com/S-jtpRS1P7vRY/help/
+http://www06.u-page.so-net.ne.jp/tb3/y-miyu/azure/kodatour.htm
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-stable/japanese/escpf/distinfo
+http://no.egroups.com/subscribe/Theater_plays
+http://www.equipe.fr/Football/FootballFicheJoueur8954_0.html
+http://www.equipe.fr/Football/FootballFicheJoueur6039_0.html
+http://www.pmdc.org.uk/dogsdb/p00/P00133.HTM
+http://ip.tosp.co.jp/i.asp?i=nononatti3
+http://tucows.wlink.com.np/adnload/144221_48889.html
+http://store.yahoo.co.jp/I/naturum_1590_147867488
+http://providenet.office.tucows.com/adnload/77414_41755.html
+http://providenet.office.tucows.com/adnload/73011_41097.html
+http://www.goldersgreen.londonengland.co.uk/medicalequipmentrentalandleasing.htm
+http://www.online.kokusai.co.jp/Mmf_corner/V0043462/mmf_corner/mmf_corner/url
+http://www.qth.net/archive/packrats/200008/20000804.html
+http://www.expage.com/buffykat11nelly
+http://dk.egroups.com/login.cgi?login_target=%2Fmessages%2Fbbs_people
+http://dk.egroups.com/message/bbs_people/23
+http://www.linux.com/networking/network/technology/free/development/learning/
+http://www.chaos.dk/sexriddle/r/x/z/t/l/
+http://www.opensecrets.org/lobbyists/98profiles/5918.htm
+http://www.cbs.sportsline.com/u/football/nfl/kids/players/3418.htm
+http://www.cbs.sportsline.com/u/football/nfl/kids/players/3868.htm
+http://www.cbs.sportsline.com/u/football/nfl/kids/players/133268.htm
+http://www.hig.se/(apre,clientname,countdown,language,set_cookie)/~jackson/roxen/
+http://www.platogmbh.de/plato/home.nsf/c81870434660ba41c125652a0029a47a/fb7566ed772f8580c12566f00036ac59!OpenDocument&ExpandSection=4,8,11,12
+http://www.fogdog.com/cedroID/ssd3040183211315/nav/products/featured_brands/2m/kick_sprint_boards/
+http://www.iabusnet.org:90/forums/aca-1/dispatch.exe/survey/folderFrame/100001/0/alpha/2458960
+http://www.jamba.de/KNet/_KNet-ONt8j1-NEd-139p9/showInfo-jobs.de/node.0/cde7f1uou
+http://www.jamba.de/KNet/_KNet-ONt8j1-NEd-139pf/browse.de/node.0/cdzqggtyb
+http://iland.tucows.com/win2k/adnload/38318_29882.html
+http://builder.hw.net/frmRestDir/0,1112,'1~21~325~1~S~020060~04880',00.html
+http://builder.hw.net/frmRestDir/0,1112,'1~21~325~1~S~020060~35840',00.html
+http://builder.hw.net/frmRestDir/0,1112,'1~21~325~1~S~020060~90237',00.html
+http://sunsite.org.uk/public/usenet/news.answers/alt.answers/self-impr-faq/part1
+http://ftp.bitcon.no/pub/simtelnet/win95/fileutl/?S=A
+http://totalsports.aol.com/stats/bbo/mlb/20000517/bal.at.ana.game.html
+http://au.yahoo.com/Regional/U_S__States/Virginia/Counties_and_Regions/Henrico_County/Business_and_Shopping/Shopping_and_Services/Travel/
+http://ftp.up.pt/Linux/debian/dists/unstable/main/binary-all/math/
+http://students.lsu.edu/students/main.nsf/c81d2bf8cb0b80ff862566fb00105ab2/7f3436ae9cb1268886256773006f9288!OpenDocument&ExpandSection=10,17,13,14
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-stable/japanese/vfghostscript/Makefile
+http://polygraph.ircache.net:8181/yp/User_Contribs/http_-2home.netscape.com/comprod/mirror/
+http://www.emis.de/journals/EJDE/Volumes/Monographs/Volumes/1998/26/?S=A
+http://www.smartshop.com/cgi-bin/main.cgi?c=314&a=contactus
+http://213.36.119.69/do/session/152986/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/BE_NL/
+http://www.outdoorwire.com/lists/dirt/200009/msg01273.html
+http://chicagocow.com/top/1,1419,M-Metromix-Home-Carryout!InputReview-9757--0,00.html
+http://www.lithoquoter.com/Scripts/WebObjects.exe/Printers.woa/659920000022582000008720100000129302/main.wo/9193100000029302/4/-/prime
+http://groups.haas.berkeley.edu/hcs/Docs/SASv8/sasdoc/sashtml/proc/z0292493.htm
+http://groups.haas.berkeley.edu/hcs/Docs/SASv8/sasdoc/sashtml/proc/z0292495.htm
+http://groups.haas.berkeley.edu/hcs/Docs/SASv8/sasdoc/sashtml/proc/z0292496.htm
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/jlhIVflnBPgWmpC4eFAjXlk3QXcFhcK-b9D_cbZyHLtTP5aigpMrgot7TKiIhNzg8y23_mmQAn7GVTQsvALIGIvJI8RFNXRZDuyGCzJ8JFs6ysbZfjgM3ik0nyIt5yhT_ujQhRI-42lzAOeb666j
+http://www.nissan.co.jp/RENAULT-DEALERS/PASSPORT/view.cgi/admission/972959588--
+http://www.intellicast.com/Golf/World/UnitedStates/MidAtlantic/Virginia/RoyalNewKentGC/LocalWinds/d1_12/
+http://gbchinese.yahoo.com/headlines/001028/sports/ycwb/ycba28c003txttyxw00102800.html
+http://gbchinese.yahoo.com/headlines/001028/sports/ycwb/ycba28c004txttyxw00102800.html
+http://mx.php.net/manual/hu/language.references.unset.php
+http://www.cbtravelguide.com/north_america/united_states/info_2.htm?sortby=city
+http://www.intellicast.com/Sail/World/UnitedStates/Northwest/Idaho/Targhee/LocalWinds/d1_03/
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-current/devel/libgii/distinfo
+http://biblioteca.upv.es/bib/doc/doc_fisbd/816/149599//C/1826373/0////25/S/MLTPAI
+http://willsmith.sonicnet.com/events/jay_z/index_sonicnet.jhtml
+http://tucows.soneraplaza.nl/winme/tucowsme_license.html
+http://people.freebsd.org/~knu/cgi-bin/cvsweb.cgi/src/usr.sbin/fdcontrol/Makefile?only_with_tag=MAIN
+http://www.kurit.com/ip/a5iu/dungeon/showsw1.html
+http://www.mapion.co.jp/custom/AOL/admi/13/13118/minamisenju/3chome/index-30.html
+http://yp.gates96.com/3/2/10/4.html
+http://yp.gates96.com/3/2/10/19.html
+http://yp.gates96.com/3/2/10/48.html
+http://yp.gates96.com/3/2/10/52.html
+http://yp.gates96.com/3/2/10/82.html
+http://yp.gates96.com/3/2/11/10.html
+http://yp.gates96.com/3/2/11/13.html
+http://yp.gates96.com/3/2/13/31.html
+http://yp.gates96.com/3/2/13/41.html
+http://yp.gates96.com/3/2/13/43.html
+http://yp.gates96.com/3/2/14/3.html
+http://yp.gates96.com/3/2/14/19.html
+http://yp.gates96.com/3/2/15/54.html
+http://yp.gates96.com/3/2/15/72.html
+http://yp.gates96.com/3/2/16/84.html
+http://yp.gates96.com/3/2/17/22.html
+http://yp.gates96.com/3/2/17/61.html
+http://yp.gates96.com/3/2/18/1.html
+http://yp.gates96.com/3/2/18/41.html
+http://yp.gates96.com/3/2/18/58.html
+http://yp.gates96.com/3/2/19/56.html
+http://yp.gates96.com/3/2/19/79.html
+http://www.stas.net/lonlywtrsoul/minesweeper/ms.html
+http://ksu.freeyellow.com/
+http://www.genome.wustl.edu:8021/gsc10/est/yt/yt69/
+http://www.genome.wustl.edu:8021/gsc10/est/yt/yt82/
+http://www.winsite.com/info/pc/win95/miscutil/cutty10.exe/downltop.html
+http://habenix.uni-muenster.de/Rektorat/Forschungsberichte-1997-1998/fo05bbe03.htm
+http://www.jobvillage.com/channel/jobs/installation_repair/bicycle/g.3370.html
+http://www.mordkommission.de/ratgeber/praxis/service/broschueren/40504/
+http://www.aelita.net/products/news/solutions/sitemap/company/library/default.htm
+http://www.beanienation.com/cgi-bin/bn/view_feedback.mod?HANDLE=acejet
+http://cgi1.washingtonpost.com/wp-dyn/metro/va/alexandria/
+http://www.linux.com/networking/network/applications/interface/linux/distro/
+http://www2.brent.gov.uk/bv1nsf.nsf/031d5c68638196618025664000760871/963fe55ca97ccaa5802568f900503269!OpenDocument&Start=57.3&Count=60&Expand=69
+http://www2.brent.gov.uk/bv1nsf.nsf/031d5c68638196618025664000760871/963fe55ca97ccaa5802568f900503269!OpenDocument&Start=57.3&Count=60&Expand=72
+http://www2.brent.gov.uk/bv1nsf.nsf/031d5c68638196618025664000760871/963fe55ca97ccaa5802568f900503269!OpenDocument&Start=57.3&Count=60&Expand=87
+http://genforum.genealogy.com/cgi-genforum/forums/youngs.cgi?26
+http://www.tvstore.com/browse/TV/CAP/s.IRspZRIy
+http://210.178.135.1/netbbs/Bbs.cgi/nhic30592/qry/zka/B2-kB2-p/pno/0/qqo/012A/qqatt/^
+http://home.sol.no/~leskjerv/aner/12063.htm
+http://pub6.ezboard.com/fwatckkeepersgeneralwatchkeeperdiscussion?page=5
+http://www.centc251.org/forums/aca-1/dispatch.cgi/hsi/folderFrame/100217/0/def/1210456
+http://ftp.sunet.se/pub/FreeBSD/ports/ports-stable/games/xosmulti/?S=A
+http://opac.lib.rpi.edu/search/ddata+processing+english+language+style/7,-1,0,B/browse
+http://yp.gates96.com/7/40/0/5.html
+http://yp.gates96.com/7/40/0/33.html
+http://yp.gates96.com/7/40/1/27.html
+http://yp.gates96.com/7/40/3/25.html
+http://yp.gates96.com/7/40/3/36.html
+http://yp.gates96.com/7/40/4/67.html
+http://yp.gates96.com/7/40/4/77.html
+http://yp.gates96.com/7/40/6/28.html
+http://yp.gates96.com/7/40/6/49.html
+http://yp.gates96.com/7/40/6/89.html
+http://yp.gates96.com/7/40/7/21.html
+http://yp.gates96.com/7/40/9/24.html
+http://indonesian.wunderground.com/geo/GizmoTempBigPromo/global/stations/07434.html
+http://www.teenplatinum.com/barelylegal/anal-sexass/legsred-toenail-polish/swallowspit/submissiondiscipline/maledomspanking/hardcorebondage.html
+http://cgi.cnnsi.com/basketball/college/women/scoreboards/aeast/2000/10/18/
+http://cgi.cnnsi.com/basketball/college/women/scoreboards/aeast/2000/10/16/
+http://bellona.itworld.com:8080/cwi/Printer_Friendly_Version/frame/0,1212,NAV63-128-1357-1367_STO48482-,00.html
+http://cdrwww.who.int/fsf/ehec.pdf
+http://tw.yahoo.com/Regional/Countries_and_Regions/China/Provinces__Regions_and_Municipalities/Jiangxi/Cities_and_Towns/Nanchang/Real_Estate/
+http://tw.yahoo.com/Regional/Countries_and_Regions/China/Provinces__Regions_and_Municipalities/Jiangxi/Cities_and_Towns/Nanchang/Society_and_Culture/
+http://www.camden-industrial.com/supply/webSession/shopper/CI972959657-31048/store/dept-8
+http://www.msb.malmo.se/search*swe/mQdfm/mqdfm/-5,-1,0,E/2browse
+http://tagesanzeiger.ch/archiv/96september/960903/213235.htm
+http://yp.gates96.com/3/7/20/3.html
+http://yp.gates96.com/3/7/20/28.html
+http://yp.gates96.com/3/7/20/42.html
+http://yp.gates96.com/3/7/21/5.html
+http://yp.gates96.com/3/7/21/61.html
+http://yp.gates96.com/3/7/22/18.html
+http://yp.gates96.com/3/7/22/20.html
+http://yp.gates96.com/3/7/22/24.html
+http://yp.gates96.com/3/7/23/33.html
+http://yp.gates96.com/3/7/23/49.html
+http://yp.gates96.com/3/7/23/57.html
+http://yp.gates96.com/3/7/24/22.html
+http://yp.gates96.com/3/7/24/23.html
+http://yp.gates96.com/3/7/24/27.html
+http://yp.gates96.com/3/7/24/36.html
+http://yp.gates96.com/3/7/24/45.html
+http://yp.gates96.com/3/7/25/98.html
+http://yp.gates96.com/3/7/26/56.html
+http://yp.gates96.com/3/7/26/77.html
+http://yp.gates96.com/3/7/26/94.html
+http://yp.gates96.com/3/7/27/10.html
+http://yp.gates96.com/3/7/27/17.html
+http://yp.gates96.com/3/7/27/61.html
+http://yp.gates96.com/3/7/27/73.html
+http://yp.gates96.com/3/7/27/81.html
+http://yp.gates96.com/3/7/27/82.html
+http://yp.gates96.com/3/7/27/87.html
+http://yp.gates96.com/3/7/28/48.html
+http://yp.gates96.com/3/7/29/1.html
+http://yp.gates96.com/3/7/29/8.html
+http://yp.gates96.com/3/7/29/32.html
+http://www.crit.org/http://www-mel.nrlmry.navy.mil/%ff:words:(MEL-is-a-sponsored-distributed-environmental-data-access-system-which-allows-users-to-search-for-browse-and-retrieve-environmental-data-from-distributed-sources)
+http://www.crit.org/http://crit.org/pub/radiks.net/jwoods/%ff:words:jwoods-radiks-net-(A-More-Graceful-Transition)-An-expanded-definition
+http://shn.webmd.com/roundtable_reply/802056
+http://shn.webmd.com/roundtable_author/802056
+http://bbs.bianca.com/mforums/e/expounder/posts/2000_Jan_09/3067/3073.html
+http://www.spaindustry.com/ita/geosearch/navarra/navarra/ESLAVA.html
+http://www.backflip.org/members/rj2nagle/4643211
+http://www.backflip.org/members/rj2nagle/7211888
+http://www.backflip.org/members/rj2nagle/5066953
+http://www.backflip.org/members/rj2nagle/5346740
+http://www.backflip.org/members/rj2nagle/5382951
+http://www.linux.com/networking/network/performance/help/va_linux_systems/server/
+http://www.secinfo.com/d178s.ad.htm
+http://www.secinfo.com/d178s.9d.htm
+http://www.secinfo.com/d178s.8b.htm
+http://www.secinfo.com/d178s.8y.htm
+http://iceberg.adhomeworld.com/cgi-win/redirect.exe/1153874888
+http://tmxy.363.net/refer-e.htm
+http://www.narodnaobroda.sk/20000210/10_007.html
+http://retailer.gocollect.com/do/session/1912712/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/index.asp
+http://retailer.gocollect.com/do/session/1912712/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/halloween/halloween.asp
+http://www.larevista.elmundo.es/documentos/secciones/ciencia.html
+http://ftpsearch.belnet.be/mirrors/ftp.isc.org/pub/usenet/control/brightnet/?M=A
+http://www.5a8.com/book/zt/zpj/k/kelisidi/wanshenjie/006.htm
+http://www.5a8.com/book/zt/zpj/k/kelisidi/wanshenjie/019.htm
+http://www.northwoods.bigsmart.com/mall/cat_automotive.cfm?drop_menu=yes
+http://www.leg.wa.gov/pub/rcw%20-%20text/title_41/chapter_004/rcw_41_04_220.txt
+http://www.leg.wa.gov/pub/rcw%20-%20text/title_41/chapter_004/rcw_41_04_364.txt
+http://www.leg.wa.gov/pub/rcw%20-%20text/title_41/chapter_004/rcw_41_04_400.txt
+http://www.leg.wa.gov/pub/rcw%20-%20text/title_41/chapter_004/rcw_41_04_630.txt
+http://bsd.tucows.mol.com/x11html/adnload/69206_8129.html
+http://ldp.teihal.gr/LDP/LG/issue22/notes-mode.html
+http://ldp.teihal.gr/LDP/LG/issue22/haters.html
+http://members.nbci.com/design_res/software_ftp.htm
+http://www.nativeamerican-jewelry.com/necklace53.htm
+http://members.theglobe.com/pamile/Pamela0004.html
+http://webtools.familyeducation.com/whatworks/item/front/0,2551,22-9696-7350-1099-49655,00.html
+http://wwws.br-online.de/geld/boerse/970909/072001.html
+http://212.31.0.37/fix98/75yil/1938.htm
+http://212.31.0.37/fix98/75yil/1950.htm
+http://212.31.0.37/fix98/75yil/26ekl.htm
+http://212.31.0.37/fix98/75yil/28ekl.htm
+http://212.31.0.37/fix98/75yil/38ekl.htm
+http://212.31.0.37/fix98/75yil/67ekl.htm
+http://212.31.0.37/fix98/75yil/92ekl.htm
+http://212.31.0.37/fix98/75yil/15ekl.htm
+http://www.insurequotes.com/wa2/71J2.html
+http://cn.egroups.com/message/csreye/112
+http://ring.crl.go.jp/archives/lang/perl/CPAN/authors/id/J/JA/JARIAALTO/?D=A
+http://ds.dial.pipex.com/town/drive/kch36/select/s31/ch027.html
+http://ds.dial.pipex.com/town/drive/kch36/select/s31/ch056.html
+http://ds.dial.pipex.com/town/drive/kch36/select/s31/ch043.html
+http://202.99.23.245/huadong/199905/25/no_4.html
+http://www.linux.com/networking/network/industry/training/services/business/
+http://www.writtenbyme.com/articles/849308468.shtml
+http://members.tripod.com/TroupeLynx/index_m.htm
+http://polygraph.ircache.net:8181/http_-2www.horizonfinance.com/https_-2www.truste.org/validate/http_-2www.ziplink.net/~ralphb/newsroom/http_-2www.travelsc.com/industry/home.html
+http://ftp.bitcon.no/pub/tucows/preview/1095.html
+http://ftp.bitcon.no/pub/tucows/preview/870.html
+http://ftp.bitcon.no/pub/tucows/preview/144675.html
+http://ftp.bitcon.no/pub/tucows/preview/144869.html
+http://ftp.bitcon.no/pub/tucows/preview/31162.html
+http://ftp.bitcon.no/pub/tucows/preview/7724.html
+http://ftp.bitcon.no/pub/tucows/preview/2691.html
+http://ftp.bitcon.no/pub/tucows/preview/72841.html
+http://ftp.bitcon.no/pub/tucows/preview/72185.html
+http://www.jacksonhewitt.com/ctg/cgi-bin/JacksonHewitt/company_profile/AAAksrACwAAABtvAAX
+http://search.excaliburfilms.com/moviepgs/goodbadanddirty.htm?currency=NOK&stock=8377V1
+http://search.excaliburfilms.com/moviepgs/goodbadanddirty.htm?currency=FRF&stock=8377V1
+http://genforum.genealogy.com/cgi-bin/print.cgi?torian::44.html
+http://retailer.gocollect.com/do/session/1912702/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/exclusives/newintros.asp
+http://www.retrobytes.org/classiccmp/9911/msg00941.html
+http://ftp.support.compaq.com/public/dunix/v3.2d-1/dce/?S=A
+http://www.collectingnation.com/cgi-bin/bn/request_email.mod?EHANDLE=CoyoteChief
+http://www.collectingnation.com/cgi-bin/bn/request_email.mod?EHANDLE=cpatch
+http://www.beanienation.com/cgi-bin/bn/view_feedback.mod?HANDLE=cpegasus
+http://www.quzhou.gov.cn/flfg.nsf/0a043ae26eb50247002564640039f21d/483ed12afec2b31d002564ac0039427a!OpenDocument&ExpandSection=7,6,5
+http://www.luecos.de/wow/art/mu_newsc_12080.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/quizz/misc/lit/programs/simple/pages_new.html
+http://library.cuhk.edu.hk/search*chi/aChen,+Hui-fen./achen+hui+fen/31,-1,0,E/frameset&F=achen+hung&4,,0
+http://www.vedomosti.spb.ru/2000/arts/spbved-82-art-2.html
+http://www.vedomosti.spb.ru/2000/arts/spbved-82-art-21.html
+http://www.vedomosti.spb.ru/2000/arts/spbved-82-art-45.html
+http://caller-times.com/1999/june/26/today/national/2447.html
+http://cafe5.daum.net/Cafe-bin/Bbs.cgi/vision20pds/lst/qqeq/1/zka/B2-kB2Np
+http://www.crutchfield.com/S-q8jdM6hvouc/sales.html
+http://www.crutchfield.com/S-q8jdM6hvouc/cgi-bin/Catalog.asp?sid=S-q8jdM6hvouc
+http://www.crutchfield.com/S-q8jdM6hvouc/copyright.html
+http://deliveryc.aftonbladet.se/puls/stockholmsguiden/presentation/0,1714,2000023149,00.html
+http://deliveryc.aftonbladet.se/puls/stockholmsguiden/presentation/0,1714,2000023162,00.html
+http://deliveryc.aftonbladet.se/puls/stockholmsguiden/presentation/0,1714,2000023220,00.html
+http://www.tnonline.com/archives/news/2000weeklies/09.20/pocono/pocono/police.html
+http://retailer.gocollect.com/do/session/1912688/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/sports/index.asp
+http://ftp.fas.org/irp/world/iraq/hadi/
+http://rusf.ru/kb/stories/kogda_chapaev_ne_utonul/text.htm
+http://ring.yamanashi.ac.jp/pub/FreeBSD-PC98/dists/4.1-RELEASE/packages/chinese/?M=A
+http://www3.buch-per-sms.de/anmeldung0.jsp$ID=To7737mC4935289641883087At0.9095524774481786
+http://www3.buch-per-sms.de/impressum.jsp$ID=To7737mC4935289641883087At0.9104482951702283
+http://ftp.uni-bremen.de/pub/linux/dist/suse/6.4/i386.de/suse/contents/
+http://ftp.uni-bremen.de/pub/linux/dist/suse/6.4/i386.de/suse/pay3/
+http://ftp.uni-bremen.de/pub/linux/dist/suse/6.4/i386.de/suse/xdev2/
+http://www.mlbworldseries.com/u/baseball/mlb/players/moreplayer_7649.htm
+http://www.rismedia.com/consumer/27/5192/
+http://www.rismedia.com/consumer/27/18760/
+http://library.cuhk.edu.hk/search*chi/aZhang,+Wei-Yuan./azhang+wei+yuan/-5,-1,0,B/browse
+http://itcareers.careercast.com/texis/it/itjs/+XwwBmeSFy86xwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew8awn5otDanDtoDnnGaxdo5na5BwBnazdxanLpnGonDqnamnVncdpaBnwMahoGMiwGna31wcohoqwBodDaMFqpl0bP0RRe2PftgQE2yDzmesxwwwpBmeAFy86Kwww5rmepdwwwBrmeZpwww/morelike.html
+http://itcareers.careercast.com/texis/it/itjs/+zwwBmerEy86e+xwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew8awn5otDanDtoDnnGaxdo5na5BwBnazdxanLpnGonDqnamnVncdpaBnwMahoGMiwGna31wcohoqwBodDaMFqpl0bP0RRe2PftgQE2yDzmesxwwwpBmeAFy86Kwww5rmeADwwwBrmeZpwww/jobpage.html
+http://itcareers.careercast.com/texis/it/itjs/++wwBmex8286xwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew8awn5otDanDtoDnnGaxdo5na5BwBnazdxanLpnGonDqnamnVncdpaBnwMahoGMiwGna31wcohoqwBodDaMFqpl0bP0RRe2PftgQE2yDzmesxwwwpBmeAFy86Kwww5rm6mwwBrmeZpwww/jobpage.html
+http://archive.soccerage.com/s/de/09/b2445.html
+http://archive.soccerage.com/s/de/09/b2408.html
+http://archive.soccerage.com/s/de/09/b2272.html
+http://archive.soccerage.com/s/de/09/b2256.html
+http://archive.soccerage.com/s/de/09/b2249.html
+http://archive.soccerage.com/s/de/09/b2245.html
+http://archive.soccerage.com/s/de/09/b2246.html
+http://archive.soccerage.com/s/de/09/b2237.html
+http://archive.soccerage.com/s/de/09/b2207.html
+http://genforum.genealogy.com/cgi-genforum/forums/wickham.cgi?296
+http://ftpsearch.belnet.be/packages/CPAN/authors/id/N/NE/NEDKONZ/?S=A
+http://www.cheatscape.com/amiga/a/game53cindex_1.htm
+http://www.best.com/~radko/lounge/messages/3572.html
+http://www.best.com/~radko/lounge/messages/3542.html
+http://www.best.com/~radko/lounge/messages/3563.html
+http://www.best.com/~radko/lounge/messages/3502.html
+http://www.best.com/~radko/lounge/messages/3431.html
+http://user.tninet.se/~lrg243i/leo2.htm
+http://www.pocketbible.co.kr/new/hebrews/hebrews07/hebrews7-5.htm
+http://www.pocketbible.co.kr/new/hebrews/hebrews07/hebrews7-10.htm
+http://members.tripod.co.jp/sugart/?D=A
+http://www.linux.com/networking/network/industry/growth/new/server/
+http://kdecvs.stud.fh-heilbronn.de/cvsweb/kdegames/kspaceduel/sprites/?hideattic=0&sortby=log
+http://karate.list.ru/catalog/10621.html
+http://www.digitaldrucke.de/(aktuell,arbeitsvermittlung,computer,hilfe,individualverkehr,kultur,mix,nuernberg,sense,software,verkehr)/_fort/html/themen/aktuell/verkehr.htm
+http://www.digitaldrucke.de/(aktuell,arbeitsvermittlung,computer,hilfe,individualverkehr,kultur,mix,nuernberg,sense,software,verkehr)/_fort/html/themen/aktuell/fahrzeug/fahrzeug.htm
+http://www.digitaldrucke.de/(aktuell,arbeitsvermittlung,computer,creaccess,hilfe,individualverkehr,kultur,mix,nuernberg,schnellübersicht,sense,software,verkehr,von)/_fort/html/themen/hilfe/getall.htm
+http://polygraph.ircache.net:8181/http_-2www.infolane.com/http_-2www.neosoft.com/~nitemoon/technical/http_-2www2.davidweekleyhomes.com/advancedproj.html
+http://wow-online.vhm.de/Regional/Sri_Lanka/Nachrichten.html
+http://www.bell.bellnet.com/suchen/sport/rodeo.html
+http://netway.pda.tucows.com/palm/adnload/67796_21902.html
+http://netway.pda.tucows.com/palm/preview/48544.html
+http://netway.pda.tucows.com/palm/adnload/139037_47478.html
+http://netway.pda.tucows.com/palm/adnload/73256_21914.html
+http://netway.pda.tucows.com/palm/adnload/71930_21910.html
+http://netway.pda.tucows.com/palm/adnload/136499_47294.html
+http://netway.pda.tucows.com/palm/adnload/77938_21926.html
+http://wap.jamba.de/KNet/_KNet-g_v8j1-4Fd-13aaq/browse.de/node.0/cde7f2elw
+http://www.oreilly.com/medical/autism/news/research.html
+http://www.geocities.co.jp/HeartLand-Namiki/5523/kopen.html
+http://br-online.de/wissenschaft/wimfs/tm/tm9611/tt9611ol.htm
+http://retailer.gocollect.com/do/session/1912709/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/exclusives/preorder.asp
+http://rac.co.kr/www.avm.de/
+http://rac.co.kr/www.aztech.com.sg/
+http://rac.co.kr/www.simple.com.au/drivers.htm
+http://www.egroups.com/messages/Wrestlings2ndComing/263
+http://mediate.magicbutton.net/do/session/625584/vsid/3342/tid/3342/cid/88020/mid/2008/rid/2313/chid/2648/url/http://www1.getmapping.com/index.cfm
+http://ben.aspads.net/ex/c/643/874990125
+http://www.hri.org/docs//statedep/1998/98-05-26.std.html
+http://member1.shangdu.net/home2/longing/byzs/036.htm
+http://web.tiscalinet.it/informacitta/n2Maggio2000/n2Maggio2000/Pagine/P16.htm
+http://www.eveclub.com/cgi-bin/eveclub.front/972959455723/Catalog/11000155
+http://www.eveclub.com/cgi-bin/eveclub.front/972959455723/Basket/View/1000038
+http://student.monterey.edu/sz/troxellphillipju/campus/
+http://readers.thevines.com/leaf/AA0000401329/45///&act=24-1-11&bref=1601
+http://caller-times.com/1999/september/30/today/business/750.html
+http://www.online.kokusai.co.jp/Mmf_corner/V0043482/mmf_corner/mmf_corner/url
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=27,33,21,19,32
+http://jupiter.u-3mrs.fr/~msc41www/GRATXT/PD6483.HTM
+http://webtools.familyeducation.com/whatworks/item/front/0,2551,1-9696-7765-539-51377,00.html
+http://parallel.fh-bielefeld.de/ti/vorlesung/sp/jdk_doc/java/text/class-use/FieldPosition.html
+http://cinemabilia.de/details/katnr/239509/
+http://ftp.sunet.se/pub/FreeBSD/FreeBSD-current/ports/games/xgolgo/pkg-comment
+http://yp.gates96.com/13/2/50/12.html
+http://yp.gates96.com/13/2/50/68.html
+http://yp.gates96.com/13/2/52/56.html
+http://yp.gates96.com/13/2/53/71.html
+http://yp.gates96.com/13/2/54/13.html
+http://yp.gates96.com/13/2/54/21.html
+http://yp.gates96.com/13/2/54/43.html
+http://yp.gates96.com/13/2/54/52.html
+http://yp.gates96.com/13/2/54/94.html
+http://yp.gates96.com/13/2/55/25.html
+http://yp.gates96.com/13/2/55/57.html
+http://yp.gates96.com/13/2/56/95.html
+http://yp.gates96.com/13/2/57/24.html
+http://yp.gates96.com/13/2/57/34.html
+http://yp.gates96.com/13/2/57/35.html
+http://yp.gates96.com/13/2/57/64.html
+http://yp.gates96.com/13/2/58/92.html
+http://yp.gates96.com/13/2/59/2.html
+http://yp.gates96.com/13/2/59/31.html
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/RLhI7rcI1D4JxQFT7-3mEP5SJK8AVzq_FCHTmPD4oB4tzM54LVISOGr6gaW80TieiLj3vEEhfqMBuYuDKIQXk3pROAhdckz6dDnbPsi72aC9ZSsK2o3j3J8YlLpw-uOtcBIEsA4ZZATUNj1D6atp66I4
+http://www.dulux.co.uk/UKRETAIL:1938649915:DFinity.1QJiP4jRabmkmb
+http://www.dulux.co.uk/UKRETAIL:1938649915:DFinity.1QJiP4jMomdoclfieh
+http://www.egroups.com/messages/raite-dvd/1442
+http://www3.newstimes.com/archive2000/jun28/bzd.htm
+http://yp.gates96.com/2/75/20/35.html
+http://yp.gates96.com/2/75/20/42.html
+http://yp.gates96.com/2/75/20/48.html
+http://yp.gates96.com/2/75/21/28.html
+http://yp.gates96.com/2/75/21/88.html
+http://yp.gates96.com/2/75/21/91.html
+http://yp.gates96.com/2/75/21/93.html
+http://yp.gates96.com/2/75/21/96.html
+http://yp.gates96.com/2/75/22/23.html
+http://yp.gates96.com/2/75/23/50.html
+http://yp.gates96.com/2/75/24/13.html
+http://yp.gates96.com/2/75/24/47.html
+http://yp.gates96.com/2/75/24/90.html
+http://yp.gates96.com/2/75/25/33.html
+http://yp.gates96.com/2/75/25/46.html
+http://yp.gates96.com/2/75/25/84.html
+http://yp.gates96.com/2/75/26/37.html
+http://yp.gates96.com/2/75/26/40.html
+http://yp.gates96.com/2/75/27/30.html
+http://yp.gates96.com/2/75/27/66.html
+http://yp.gates96.com/2/75/27/81.html
+http://yp.gates96.com/2/75/28/34.html
+http://yp.gates96.com/2/75/28/55.html
+http://yp.gates96.com/2/75/29/12.html
+http://yp.gates96.com/2/75/29/19.html
+http://yp.gates96.com/2/75/29/45.html
+http://yp.gates96.com/2/75/29/56.html
+http://yp.gates96.com/2/75/29/86.html
+http://yp.gates96.com/2/75/29/99.html
+http://cn.egroups.com/message/agribusiness1/31
+http://biblio.cesga.es:81/search*gag/jLugo+(Provincia).+Mapas+topogrÃ\83Â\83Ã\82¡ficos.+[1890%3F]/jlugo+provincia+mapas+topograficos+1890/31,-1,0,B/browse
+http://bbs.lineone.net/news/uknews/msg01030.html
+http://bbs.lineone.net/news/uknews/msg01047.html
+http://bbs.lineone.net/news/uknews/msg01026.html
+http://bbs.lineone.net/news/uknews/msg00976.html
+http://bbs.lineone.net/news/uknews/msg00960.html
+http://bbs.lineone.net/news/uknews/msg00952.html
+http://idl.tucows.com/winnt/adnload/1380_28802.html
+http://retailer.gocollect.com/do/session/1912681/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/christmas/holiday_shoppe.asp
+http://www1.zdnet.co.uk/software/fstore/A/9/000BA9.html
+http://polygraph.ircache.net:8181/home/http_-2www.tauchbali.com/SERV.HTM
+http://channel.nytimes.com/1998/05/01/technology/cybertimes/artsatlarge/
+http://ftp.sunet.se/pub/FreeBSD/ports/ports/japanese/linux-netscape47-communicator/?D=A
+http://www9.hmv.co.uk:5555/do/session/1347757/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/hiddenframe.html
+http://www9.hmv.co.uk:5555/do/session/1347757/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/logoframe.html
+http://www-usa9.cricket.org/link_to_database/ARCHIVE/1999-2000/WI_IN_NZ/ARTICLES/
+http://www-usa9.cricket.org/link_to_database/ARCHIVE/1999-2000/WI_IN_NZ/SCORECARDS/
+http://a228.g.akamai.net/7/228/289/55d96730f1ea56/news.indiainfo.com/2000/08/13/floods.html
+http://caller-times.com/1999/august/08/today/texas_me/4241.html
+http://ftp.uni-bremen.de/pub/doc/news.answers/movies/winona-ryder-faq/part3
+http://www.globalsources.com/gsol/owa/website.gold/GP3/8801728414/HOME.HTM
+http://eds.kse.or.kr/jaemoo/jipyo_e/k_grp/E01683.htm
+http://eds.kse.or.kr/jaemoo/jipyo_e/i_grp/E01116.htm
+http://eds.kse.or.kr/jaemoo/jipyo_e/i_grp/E01126.htm
+http://eds.kse.or.kr/jaemoo/jipyo_e/d_grp/E00366.htm
+http://eds.kse.or.kr/jaemoo/jipyo_e/h_grp/E00929.htm
+http://www.jobvillage.com/channel/jobs/cleaning/pruner/g.1276.html
+http://www.affiliate.hpstore.hp.co.uk/do/session/380817/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/assistance/entry.asp
+http://gamingplace.zeelandnet.nl/poker_rating.html
+http://no.egroups.com/message/DVD-Info/111
+http://www.relax.ch/static/it/lazurigo/mercatodellavoro/oben.html
+http://internet.exit.de/mees-online/left_geld.html
+http://www.redrocksports.com/sports/webSession/shopper/RR972959658-31049/store/dept-5/department/dept-5/item/footwear
+http://www.redrocksports.com/sports/webSession/shopper/RR972959658-31049/store/dept-5/department/dept-5/item/52550
+http://www11.cplaza.ne.jp/babyweb/bbs/bdnmp01/no16/61N.html
+http://www.daimi.au.dk/dIntProg/java/jdk1.2.2/docs/api/javax/swing/plaf/basic/BasicScrollBarUI.ArrowButtonListener.html
+http://www.daimi.au.dk/dIntProg/java/jdk1.2.2/docs/api/javax/swing/plaf/basic/BasicScrollBarUI.ModelListener.html
+http://www.angelfire.com/nc/Percosolation/POSDerisions.html
+http://yp.gates96.com/3/4/40/80.html
+http://yp.gates96.com/3/4/41/23.html
+http://yp.gates96.com/3/4/41/24.html
+http://yp.gates96.com/3/4/41/37.html
+http://yp.gates96.com/3/4/41/90.html
+http://yp.gates96.com/3/4/42/26.html
+http://yp.gates96.com/3/4/42/71.html
+http://yp.gates96.com/3/4/42/90.html
+http://yp.gates96.com/3/4/44/44.html
+http://yp.gates96.com/3/4/45/52.html
+http://yp.gates96.com/3/4/45/75.html
+http://yp.gates96.com/3/4/45/77.html
+http://yp.gates96.com/3/4/46/0.html
+http://yp.gates96.com/3/4/46/85.html
+http://yp.gates96.com/3/4/47/19.html
+http://yp.gates96.com/3/4/47/20.html
+http://yp.gates96.com/3/4/47/23.html
+http://yp.gates96.com/3/4/47/72.html
+http://yp.gates96.com/3/4/48/4.html
+http://yp.gates96.com/3/4/48/16.html
+http://yp.gates96.com/3/4/48/45.html
+http://yp.gates96.com/3/4/48/51.html
+http://yp.gates96.com/3/4/49/16.html
+http://ftpsearch.belnet.be/pub/mirror/sunsite.cnlab-switch.ch/mirror/harvest/contrib/Example-Customizations/?S=A
+http://pub9.ezboard.com/fgaprforeignrelationdepartment.showAddTopicScreenFromWeb
+http://pub9.ezboard.com/fgaprforeignrelationdepartment.showMessage?topicID=4.topic
+http://www.asstr.org/nifty/gay/authoritarian/adonis-brotherhood/adonis-brotherhood-3
+http://www.brio.de/BRIO.catalog/39fe2f4c06d41844273fd472aa7806a9/UserTemplate/8
+http://itcareers.careercast.com/texis/it/itjs/+HwwBmeH_D86aqwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew6nxqdDdMoqax15oDn55a5BwhhawDwcO5o5aqd5Ban5BoMwBoDtaGo5Aa5nGVoqnaADdicnmtnaBddc5aMFqhTfR20DzmenxwwwpBmeWWD86exhwww5rmeWcwwwBrmeZpwww/jobpage.html
+http://polygraph.ircache.net:8181/http_-2www.whowhere.com/http_-2www.updowntowner.org/julyjamm/frmain.htm
+http://213.36.119.69/do/session/152987/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/reserver/spectacles/
+http://www.jobvillage.com/channel/jobs/health_care/physician/anesthesiologist/b.9467.g.1575.html
+http://www.private-immobilien-boerse.de/friesland/verkauf/IIM-Teil/Startseite/Gemeinsam/Super-Zins-Konditionen/Gemeinsam/Inserieren/Gemeinsam/MarketingStrategie/inhalt.htm
+http://se.egroups.com/message/yemdiscussion/38
+http://se.egroups.com/message/yemdiscussion/45
+http://home.bip.net/kerstin.hjelm/Stamtavla%20Z-kullen.html
+http://mediate.magicbutton.net/do/session/625616/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-abou.html
+http://members.tripod.lycos.co.kr/KWEN3607/?S=A
+http://cpan.clix.pt/authors/id/B/BP/BPOWERS/String-StringLib-1.02.readme
+http://www.gbnf.com/genealogy/bookout/html/d0001/I3283.HTM
+http://m4.findmail.com/group/Opera2Developers
+http://m4.findmail.com/group/acctworks
+http://retailer.gocollect.com/do/session/1912690/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/top_ten.asp?pagenum=1
+http://retailer.gocollect.com/do/session/1912690/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/postcards/index.asp
+http://platsbanken.amv.se/kap/text/47/001023,170030,140912,11,1276051947.shtml
+http://www.gamespot.com/features/dunesg/dune6a.html
+http://tucows.iquest.net/winme/preview/138053.html
+http://tucows.iquest.net/winme/preview/137529.html
+http://tucows.iquest.net/winme/preview/138641.html
+http://archive.soccerage.com/s/pt/09/03721.html
+http://archive.soccerage.com/s/pt/09/07102.html
+http://www10.nytimes.com/library/national/science/health/021500hth-women-diabetes.html
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/www.phy.bnl.gov/e949/e949_update.txt
+http://www.mapion.co.jp/custom/AOL/admi/13/13105/otsuka/3chome/index-7.html
+http://go18.163.com/_NTES/~starseeker/gin/saga/gin01/gin0100.htm
+http://village.infoweb.ne.jp/~fvgg8450/t91.html
+http://clickahouse.mp2.homes.com/content/articles/locks.html
+http://findmail.com/messages/studentdoctor/354
+http://ldp.mirror.nettuno.it/Linux/LDP/LDP/lkmpg/node3.html
+http://ldp.mirror.nettuno.it/Linux/LDP/LDP/lkmpg/node13.html
+http://fi.egroups.com/group/sandycove
+http://www.fogdog.com/cedroID/ssd3040183219992/boutique/nike/
+http://www.fogdog.com/cedroID/ssd3040183219992/boutique/harbinger/
+http://www.fogdog.com/cedroID/ssd3040183219992/customer_service/employment.html
+http://www.genoma.de/shop/736a8b4b4c331e80f780899842a4b0b4/99/b
+http://sjsulib1.sjsu.edu:81/search/tbraille+transcription+project+of+santa+clara+county+inc/-5,-1,1,B/frameset&tbook+reviews+in+the+humanities&1,1,
+http://students.washington.edu/emgall/eng481/final/
+http://www.vc-graz.ac.at/ilct/ffe_349_99.htm
+http://www.vc-graz.ac.at/ilct/ffe_372_00.htm
+http://www.vc-graz.ac.at/ilct/ffe_375_00.htm
+http://www.escribe.com/computing/virtcom/m452.html
+http://members.tripod.com/~TreasureIsland/welcom/e.htm
+http://augustachronicle.com/stories/022699/obi_038-5494.001.shtml
+http://augustachronicle.com/stories/022699/obi_038-5477.001.shtml
+http://ring.edogawa-u.ac.jp/archives/X/opengroup/R6.5.1/xc/lib/Imakefile
+http://www.elop.de/d0-1015-2044-3001-top.html
+http://www.ibiblio.org/pub/languages/java/blackdown.org/JDK-1.1.7/i386/glibc/v1a/?S=D
+http://www.linux.com/networking/network/enterprise/integration/management/Linux/
+http://www.mapion.co.jp/custom/AOL/admi/13/13221/matsuyama/2chome/index-7.html
+http://www.mapion.co.jp/custom/AOL/admi/13/13221/matsuyama/2chome/index-12.html
+http://ftp.sunet.se/pub/FreeBSD/ports/ports/japanese/tcl76/Makefile
+http://ftp.lip6.fr/pub2/sgml-tools/website/HOWTO/Consultants-HOWTO/t19977.html
+http://www.irishnews.com/archive2000/06072000/sportuk1.html
+http://allmacintosh.ii.net/adnload/71893.html
+http://allmacintosh.ii.net/adnload/70339.html
+http://www.museumshops.co.uk/Bonnefoit-Alain/Bonnefoit-Alain-Die-Schoene-mit-dem-Pelz-3000062.html
+http://www.timesoc.com/editions/orange/20001030/t000103758.html
+http://www.musiciansfriend.com/ex/ds/bv/001030182803064208037039434033
+http://www.beneteau-owners.com/library.nsf/Library+By+System!OpenView&Start=41.4&Count=45&Expand=49
+http://www.musiciansfriend.com/ex/search/guitar/001030182759064208037059215342?FIND=BABX&q=c
+http://www.musiciansfriend.com/ex/search/guitar/001030182759064208037059215342?FIND=ASAX&q=c
+http://www.iabusnet.org:90/forums/aca-1/dispatch.exe/survey/showNextUnseen/fol/100001/2467632
+http://tucows.wish.net/winme/adnload/137243_28721.html
+http://yp.gates96.com/3/71/10/71.html
+http://yp.gates96.com/3/71/11/12.html
+http://yp.gates96.com/3/71/11/27.html
+http://yp.gates96.com/3/71/11/34.html
+http://yp.gates96.com/3/71/11/40.html
+http://yp.gates96.com/3/71/11/62.html
+http://yp.gates96.com/3/71/11/78.html
+http://yp.gates96.com/3/71/12/70.html
+http://yp.gates96.com/3/71/13/34.html
+http://yp.gates96.com/3/71/13/38.html
+http://yp.gates96.com/3/71/13/82.html
+http://yp.gates96.com/3/71/14/94.html
+http://yp.gates96.com/3/71/15/0.html
+http://yp.gates96.com/3/71/15/88.html
+http://yp.gates96.com/3/71/17/28.html
+http://yp.gates96.com/3/71/17/85.html
+http://yp.gates96.com/3/71/18/37.html
+http://yp.gates96.com/3/71/18/69.html
+http://yp.gates96.com/3/71/19/55.html
+http://www.kodak.ca/US/en/corp/jobs/samplingMechanicalProds.shtml
+http://ring.crl.go.jp/archives/lang/perl/CPAN/authors/id/G/GR/GRICHTER/HTML-Embperl-1.3b4.readme
+http://www7.freeweb.ne.jp/photo/lystra/a/n_aikawa.html
+http://www.imagesofengland.org.uk/31/73/317339.htm
+http://webraft.its.unimelb.edu.au/110080/students/ojb/pub/?D=A
+http://pub.chinaccm.com/13/news/200010/31/155751.asp
+http://pub.chinaccm.com/13/news/200010/21/162140.asp
+http://go18.163.com/_NTES/~chen0580/y25.htm
+http://pub17.ezboard.com/fcometalkfreetalk.showMessage?topicID=15.topic
+http://pub17.ezboard.com/fcometalkfreetalk.showMessage?topicID=6.topic
+http://mediate.magicbutton.net/do/session/625593/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-tips.html
+http://213.36.119.69/do/session/152982/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/wap/lancement.html
+http://wap.jamba.de/KNet/_KNet-Drs8j1-yEd-1395x/showInfo-presse.de/node.0/cde7f1uou
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=choramingar&l=pt
+http://www.amcity.com/philadelphia/stories/1998/11/09/story5.html?t=email_story
+http://www.mic.hr/PGMARKET:553666
+http://cn.egroups.com/messages/KristinChenoweth/2280
+http://quest7.proteome.com/databases/YPD/PombePD/SPAC343.03.html
+http://www.engines.org.uk/white/fld19/
+http://www.engines.org.uk/white/fld27/
+http://se.egroups.com/subscribe/plusgothswap
+http://www.headlight.com/invoice_process/1,1074,adpa-4049-2423-69-718,00.html
+http://www.findarticles.com/cf_0/m4PRN/1999_Nov_3/57153314/p1/article.jhtml
+http://www.iabusnet.org:90/forums/aca-1/dispatch.exe/survey/folderFrame/100001/0/alpha/2480022
+http://archive.soccerage.com/s/it/06/10903.html
+http://innopac.lib.tsinghua.edu.cn/search*chi/dProduction+engineering/dproduction+engineering/-5,-1,0,B/browse
+http://www.consource.com/communities/profile_categories/1759/1510
+http://column.daum.net/Column-bin/Bbs.cgi/thinkaboutrbs/new/zka/B2-kB2Np
+http://wwws.br-online.de/geld/boerse/960301/0730.html
+http://www.2pl.com/asp/tools/fili1.asp?sp=ro&fi=pppp0003zi
+http://www.proviser.co.uk/regional/towns/alford/property_prices/compare_current_prices/terraced.html
+http://cometweb01.comet.co.uk/do!session=131998&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplG3XqLbdlLov4LfpmLiXvL-Zd5jbkLYozKvot0cZd5ockLYozKvsm0utt0cZX5qkXLjbzKMfaLblpLbom0bos0bom04M4Lbom0miXLvboLp1
+http://cometweb01.comet.co.uk/do!session=131998&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplG3XqLbdlLov4LfpmLiXvL-Zd5jbkLYozKvot0cZd5ockLYozKvsm0uqo0cZX5qkXLjbzKG3pLibo0miX5mqlLmpbKomb0osb0oml1odXLkfpLbopL
+http://www.geocities.co.jp/Milano/8578/profile.html
+http://ftp.dti.ad.jp/pub/XFree86/3.3.3/binaries/NetBSD-1.2/Servers/?N=D
+http://ftp.dti.ad.jp/pub/XFree86/3.3.3/binaries/NetBSD-1.2/Servers/?D=A
+http://www.best.com/~radko/lounge/messages/3742.html
+http://www.best.com/~radko/lounge/messages/3711.html
+http://www.best.com/~radko/lounge/messages/3619.html
+http://www.linux.com/networking/network/help/email/business/RuleSpace/
+http://www.financialexpress.com/fe/daily/20000918/fco17026.html
+http://209.67.27.70/comics/dilbert/scott/dawn/pg19.html
+http://209.67.27.70/comics/dilbert/scott/dawn/pg22.html
+http://flamingo.promote.ru/href.pl?fct_051
+http://pda.saa.net/palm/adnload/34404_22152.html
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/q6tIzhLNlKeaaMXYVAPJiOq7V33Ul08VcQoPAomjWMQzOxA0cR6_kRLx42D4nA_uumPVc2DRZtv6CVpWQCyNUgVZQ2P9F7bqqvcf_5WqCdUM7UIRKBdjb9lTbrCrrl5_jZ6cQsstJDqry3XrFI0toILqSCSm66j2
+http://www.home.ch/~spaw9012/ps11/ps11_003.htm
+http://help.sap.com/saphelp_45b/helpdata/de/1c/e464b20437d1118b3f0060b03ca329/frameset.htm
+http://abc.ru/cgi-bin/get_firminfo.pl?firm=comsys
+http://www.pressa.spb.ru/newspapers/nevrem/arts/nevrem-1749-art-28.html
+http://www.pressa.spb.ru/newspapers/nevrem/arts/nevrem-1749-art-32.html
+http://admin.afiliando.com/do/session/189435/vsid/1507/tid/1507/cid/23455/mid/1025/rid/1168/chid/1205/parser/yes/imref/eqqLmwlGltt5tkpHrYjLXofLklkKZljLkju5lZa5l0/url/http://www.submarino.com.mx/pesquisa/jutherC.asp?id_categoria=57&id_tipo=C
+http://admin.afiliando.com/do/session/189435/vsid/1507/tid/1507/cid/23455/mid/1025/rid/1168/chid/1205/parser/yes/imref/eqqLmwlGltt5tkpHrYjLXofLklkKZljLkju5lZa5l0/url/http://www.submarino.com.mx/extra/talk_to_sub.asp
+http://cometweb01.comet.co.uk/do!session=131998&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplG3XqLbdlLov4LfpmLiXvL-Zd5jbkLYozKvot0cZd5ockLYozKvsn0mvm0cZX5qkXLjbzKGelLkbpL
+http://yp.gates96.com/3/39/30/1.html
+http://yp.gates96.com/3/39/30/53.html
+http://yp.gates96.com/3/39/31/22.html
+http://yp.gates96.com/3/39/32/0.html
+http://yp.gates96.com/3/39/32/39.html
+http://yp.gates96.com/3/39/32/41.html
+http://yp.gates96.com/3/39/32/45.html
+http://yp.gates96.com/3/39/32/97.html
+http://yp.gates96.com/3/39/34/39.html
+http://yp.gates96.com/3/39/34/50.html
+http://yp.gates96.com/3/39/34/68.html
+http://yp.gates96.com/3/39/34/72.html
+http://yp.gates96.com/3/39/35/14.html
+http://yp.gates96.com/3/39/35/84.html
+http://yp.gates96.com/3/39/36/3.html
+http://yp.gates96.com/3/39/36/19.html
+http://yp.gates96.com/3/39/36/20.html
+http://yp.gates96.com/3/39/36/84.html
+http://yp.gates96.com/3/39/36/88.html
+http://yp.gates96.com/3/39/37/37.html
+http://yp.gates96.com/3/39/38/60.html
+http://yp.gates96.com/3/39/38/63.html
+http://yp.gates96.com/3/39/39/52.html
+http://yp.gates96.com/3/39/39/56.html
+http://yp.gates96.com/3/39/39/58.html
+http://yp.gates96.com/3/39/39/63.html
+http://yp.gates96.com/13/9/80/14.html
+http://yp.gates96.com/13/9/80/92.html
+http://yp.gates96.com/13/9/81/23.html
+http://yp.gates96.com/13/9/81/47.html
+http://yp.gates96.com/13/9/82/45.html
+http://yp.gates96.com/13/9/82/59.html
+http://yp.gates96.com/13/9/82/65.html
+http://yp.gates96.com/13/9/82/71.html
+http://yp.gates96.com/13/9/82/77.html
+http://yp.gates96.com/13/9/83/86.html
+http://yp.gates96.com/13/9/83/88.html
+http://yp.gates96.com/13/9/84/4.html
+http://yp.gates96.com/13/9/84/28.html
+http://yp.gates96.com/13/9/84/77.html
+http://yp.gates96.com/13/9/85/34.html
+http://yp.gates96.com/13/9/85/59.html
+http://yp.gates96.com/13/9/86/22.html
+http://yp.gates96.com/13/9/86/28.html
+http://yp.gates96.com/13/9/86/30.html
+http://yp.gates96.com/13/9/86/37.html
+http://yp.gates96.com/13/9/86/85.html
+http://yp.gates96.com/13/9/87/1.html
+http://yp.gates96.com/13/9/87/2.html
+http://yp.gates96.com/13/9/88/58.html
+http://yp.gates96.com/13/9/89/17.html
+http://yp.gates96.com/13/9/89/49.html
+http://yp.gates96.com/13/9/89/51.html
+http://yp.gates96.com/13/9/89/64.html
+http://yp.gates96.com/13/9/89/69.html
+http://yp.gates96.com/13/9/89/79.html
+http://www.diogenes.ch/4DACTION/web_rd_aut_frlist_az/ID=483337&chr=D
+http://ngi.tucows.com/win2k/adnload/37473_28857.html
+http://www4.nas.edu/ohr.nsf/All+Documents/Major+Units?OpenDocument&ExpandSection=1,4,21,7,17
+http://www4.nas.edu/ohr.nsf/All+Documents/Major+Units?OpenDocument&ExpandSection=2,4,21,7,17
+http://www4.nas.edu/ohr.nsf/All+Documents/Major+Units?OpenDocument&ExpandSection=15,4,21,7,17
+http://www4.nas.edu/ohr.nsf/All+Documents/Major+Units?OpenDocument&ExpandSection=16,4,21,7,17
+http://www.susi.de/cgi-bin/order/segelzentrum-kagerer/c134-5021905270003,de
+http://www.egroups.com/messages/iraq-l/9973
+http://www2.kbank.no/Web/nlpublish.nsf/Published/ord_og_uttrykk!OpenDocument&ExpandSection=29,24,30,11
+http://www.etoys.com/prod/book/51604361
+http://link.fastpartner.com/do/session/600358/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/itjobbank.php
+http://link.fastpartner.com/do/session/600358/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/shopnett.php
+http://mirror.nucba.ac.jp/mirror/FreeBSD/branches/2.2-stable/ports/devel/mips64orion-rtems-objc/?S=A
+http://www-uk5.cricket.org/link_to_database/NATIONAL/ENG/FC_TEAMS/SOMERSET/STATS/CAREER/SOMERSET_CAREER_J.html
+http://www.linux.com/networking/network/performance/install/distro/industry/
+http://www.linux.com/networking/network/performance/install/distro/tools/
+http://www.linux.com/networking/network/performance/install/distro/enterprise/
+http://mx.php.net/manual/de/language.basic-syntax.php
+http://mx.php.net/manual/fr/language.basic-syntax.php
+http://moviestore.zap2it.com/browse/MOVIES/SCRIPT/s.UxBwM3db
+http://www.armouries.org.uk/bjarni/introduction.htm
+http://mirror.cc.utsunomiya-u.ac.jp/mirror/CPAN/authors/id/C/CT/CTWETEN/?D=A
+http://atlanta.webmd.com/related_results/1/25/article/1738.50204
+http://www.ccnet.com/tzimmer/?M=A
+http://go2.163.com/~xinhua/
+http://www.ualberta.ca/FTP/OpenBSD/src/regress/lib/libc/_setjmp/CVS/Root
+http://www.dqt.com.cn/wymb/military/jinyong/金庸全集.htm
+http://www.hole.kommune.no/hole/journweb.nsf/7e180336094ef23a412568cd004a5093/2fd09f96f20814cac12568e300443d50!Navigate&To=Next
+http://classifieds.alberta.com/js/mi/c16000/b16000/n15/858640.html
+http://classifieds.alberta.com/js/mi/c16000/b16000/n15/861013.html
+http://homepages.go.com/homepages/b/n/g/bngholo/
+http://www.aelita.net/products/news/library/support/Reg/Subscribe/library/default.htm
+http://www.chaos.dk/sexriddle/j/a/b/s/e/
+http://www.chaos.dk/sexriddle/j/a/b/s/t/
+http://213.36.119.69/do/session/152985/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/contact/info-publicite.html
+http://www.indian-express.com/fe/daily/19990807/corporate.html
+http://web.cln.com/archives/atlanta/newsstand/atl100795/1316.htm
+http://web.cln.com/archives/atlanta/newsstand/atl100795/1317.htm
+http://plaza.gaiax.com/www/plaza/k/n/kenta/friends.html
+http://polygraph.ircache.net:8181/docs/eudora/http_-2www.kentuckylake.com/rates/http_-2www.hubbell-wiring.com/NEMA/admin/additional.html
+http://gd.cnread.net/cnread1/wxxs/d/dongfangying/pljc/015.htm
+http://www.bemi-immobilien.de/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Startseite/Gemeinsam/versicherungen/gebaeude/Gemeinsam/versicherungen/unfall/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Gemeinsam/versicherungen/lebensversicherung/Gemeinsam/versicherungen/gebaeude/anforderungsformular.htm
+http://www.linux.com/networking/network/help/free/red_hat/competition/
+http://www.linux.com/networking/network/help/free/red_hat/development/
+http://www.linux.com/networking/network/help/free/red_hat/SuSE/
+http://search.chollian.net/d/%b1%e2%be%f7,%c8%b8%bb%e7/%b0%e1%c8%a5/%c5%e4%c5%bb%bf%fe%b5%f9%bc%ad%ba%f1%bd%ba/16.html
+http://no.egroups.com/message/plowshares/840
+http://www.pressa.spb.ru/newspapers/nevrem/arts/nevrem-1872-art-13.html
+http://www.bemi-immobilien.de/Startseite/www.allgemeine-immobilien-boerse.de/allgemeine-ib/landkreiszwickau/Verkauf/29109700708107kirchbergvillamü/Gemeinsam/erreichenPartner/Startseite/Gemeinsam/versicherungen/lebensversicherung/Top-Darlehens-Konditionen/Gemeinsam/versicherungen/unfall/anforderungsformular.htm
+http://www.affiliate.hpstore.hp.co.uk/do/session/380819/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.france.hp.com/main/respect/
+http://www-rn.informatik.uni-bremen.de/home/ftp/pub/linux/redhat/updates/6.2EE/i586/
+http://archive.soccerage.com/s/es/09/12718.html
+http://www.intel.es/kr/hangul/pressroom/archive/releases/dp990218.htm
+http://www.intel.es/kr/hangul/pressroom/archive/releases/dp990105.htm
+http://sunsite.informatik.rwth-aachen.de/cgi-bin/ftp/ftpshow/pub/Linux/sunsite.unc.edu/distributions/caldera/eServer/updates/2.3/021/RPMS/
+http://library.bangor.ac.uk/search/aMatis,+James+H/amatis+james+h/-5,-1,0,B/browse
+http://polygraph.ircache.net:8181/http_-2www.microsoft.com/frontpage/html/http_-2www.sharkyextreme.com/hardware/hercules_tnt/
+http://ring.nihon-u.ac.jp/archives/pack/win95/net/fee/?N=D
+http://dbc.copystar.com.tw/bcbchat/199804/msg03730.htm
+http://dbc.copystar.com.tw/bcbchat/199804/msg03761.htm
+http://dbc.copystar.com.tw/bcbchat/199804/msg03787.htm
+http://www.private-immobilien-boerse.de/nordrhein-Westfalen/grevenbroich/Verkauf/Gemeinsam/Super-Zins-Konditionen/Exklusiv-IB/Startseite/IIM-Teil/Startseite/Gemeinsam/IIMMitglieder.htm
+http://www.private-immobilien-boerse.de/nordrhein-Westfalen/grevenbroich/Verkauf/Gemeinsam/Super-Zins-Konditionen/Exklusiv-IB/Startseite/IIM-Teil/Startseite/Gemeinsam/vertriebspartner.htm
+http://pd.shiseido.co.jp/s9604tub/html_00/win00051.htm
+http://solaris.license.virginia.edu/os_product_patches/patches/5.7/107094-04/SUNWdtbas/pkgmap
+http://www.eveclub.com/cgi-bin/eveclub.front/972959470432/Catalog/11000034
+http://www.sportinggreen.com/news/20001007/fbo/fbc/aar/001007.0607.html
+http://www-x500-1.uni-giessen.de:8890/Lcn%3dBelloch%20Belloch%5c,%20Juana%20Maria,ou%3dFacultad%20de%20Medicina%20y%20Odontologia,o%3dUniversidad%20de%20Valencia,c%3dES
+http://retailer.gocollect.com/do/session/1912723/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/exclusives/limited_editions.asp
+http://www.jufo.com/netcenter/chemistry/item/000904/16888.htm
+http://ww2.comune.fe.it/cgi-win/hiweb.exe/a2/d29/b14,8,1f,1d,1d,,19,,1f,19,
+http://www.2pl.com/b/ru/to/1/24/16/v2/1241600107-8.htm
+http://ring.htcn.ne.jp/pub/text/CTAN/fonts/metrics/polish/plpsfont/?D=A
+http://config.tucows.com/winme/adnload/26398_28890.html
+http://ocean.ntou.edu.tw/search*chi/aRadojcic,+Riko,+jt.+auth./aradojcic+riko/-5,-1,0,B/frameset&F=aradomsky+nellie+a&1,1
+http://www.intellicast.com/Sail/World/UnitedStates/Northwest/Montana/Beaverhead/LocalWinds/d1_09/
+http://www.bild.de/service/archiv/2000/mar/31/sport/coulthard/coulthard.html
+http://ustlib.ust.hk/search*chi/a%7B215a36%7D%7B213246%7D%7B215e42%7D+1926/a{215a36}{213246}{215e42}+1926/-5,-1,0,B/frameset&F=a{215a36}{213230}{214e70}&1,1
+http://mediate.magicbutton.net/do/session/625620/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-top50.html
+http://mediate.magicbutton.net/do/session/625620/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-corp.html
+http://www.amateurplatinum.com/mouthlicking/eunuchhershey-highway/bad-girlsubmission/petitebeauties/actionno-boundaries/fellatiogoing-down-on/give-headcock-suckers.html
+http://www.brd.net/brd-cgi/brd_dkameras/filmscanner_fotodrucker/FZ00F0EF/beurteilung/ci=972751646.htm
+http://www.niwl.se/WAIS/31607/31607073.htm
+http://www.magicvillage.de/Login/magicvillage/magiclife/Lucullus/%2328706045/Reply
+http://polygraph.ircache.net:8181/consumer/rel_meet_main.html
+http://sunsite.informatik.rwth-aachen.de/cgi-bin/ftp/ftpshow/pub/Linux/sunsite.unc.edu/distributions/debian/dists/potato/non-free/binary-i386/x11/
+http://www.great-cyber-mall.com/SelectCompany.asp?CityID=67&CatID=5
+http://www.great-cyber-mall.com/SelectCompany.asp?CityID=67&CatID=50
+http://rainforest.parentsplace.com/dialog/get/bradley2/39/1/1.html?embed=2
+http://www.users.yun.co.jp/cgi-bin/moriq/pigeon/pigeon.cgi/DataSet.after_post?c=e
+http://www.chaos.dk/sexriddle/n/f/p/x/x/
+http://www.amcity.com/dayton/stories/2000/03/20/smallb1.html?t=email_story
+http://www.linux.com/networking/network/industry/web_server/windows_nt/Red_Hat/
+http://www.du-et.net/cgi/mail.cgi?NickName=naiki
+http://gameboyz.com/g/demos_p1_c41_lV_w2.html
+http://intelinfo.subportal.com/sn/Games/Strategy_Games/9289.html
+http://home.kimo.com.tw/maso-kid/index2.html
+http://citeseer.nj.nec.com/nrelated/1377121/289677
+http://citeseer.nj.nec.com/nrelated/0/289677
+http://ccar.ust.hk/~dataop/rs_ocean_cd/WVS/wvsplus/wvs003m/bat/q/h/lf/
+http://home.baoding.cn.net/~tjhlove/dzrwy/l11.htm
+http://home.baoding.cn.net/~tjhlove/dzrwy/l23.htm
+http://208.178.109.85/msgshow.cfm/msgboard=129014524422386&msg=3558983275052&page=1&idDispSub=-1
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=4,9,33,27,35
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=29,9,33,27,35
+http://config.tucows.com/win2k/adnload/76944_30007.html
+http://www1.zdnet.com/zdnn/stories/news/0,4586,1021147,00.html
+http://www.fogdog.com/cedroID/ssd3040183236187/nav/stores/snowboarding/
+http://www.fogdog.com/cedroID/ssd3040183236187/nav/stores/institutional/
+http://debian.linux.org.tw/debian/dists/sid/main/disks-powerpc/current/source/?M=A
+http://satftp.soest.hawaii.edu/dlr/slides/ql21176.html
+http://www.linux.com/networking/network/industry/new/help/internet/
+http://www.linux.com/networking/network/industry/new/help/growth/
+http://flint.freethemes.com/skins/winamp/preview/46994.html
+http://flint.freethemes.com/skins/winamp/preview/24628.html
+http://flint.freethemes.com/skins/winamp/preview/25113.html
+http://flint.freethemes.com/skins/winamp/preview/24645.html
+http://flint.freethemes.com/skins/winamp/preview/25319.html
+http://flint.freethemes.com/skins/winamp/preview/25017.html
+http://flint.freethemes.com/skins/winamp/preview/26154.html
+http://flint.freethemes.com/skins/winamp/preview/24669.html
+http://flint.freethemes.com/skins/winamp/preview/24674.html
+http://flint.freethemes.com/skins/winamp/preview/69522.html
+http://flint.freethemes.com/skins/winamp/preview/58805.html
+http://flint.freethemes.com/skins/winamp/preview/71909.html
+http://flint.freethemes.com/skins/winamp/preview/24389.html
+http://flint.freethemes.com/skins/winamp/preview/25052.html
+http://flint.freethemes.com/skins/winamp/preview/77185.html
+http://flint.freethemes.com/skins/winamp/preview/56733.html
+http://flint.freethemes.com/skins/winamp/preview/24736.html
+http://flint.freethemes.com/skins/winamp/preview/24408.html
+http://flint.freethemes.com/skins/winamp/preview/24744.html
+http://flint.freethemes.com/skins/winamp/preview/24424.html
+http://flint.freethemes.com/skins/winamp/preview/25075.html
+http://flint.freethemes.com/skins/winamp/preview/71807.html
+http://nomade.fr/cat/informatique_tele/informatique/progiciels_logiciel/utilitaires/communication
+http://pub9.ezboard.com/umetalman5566.showPublicProfile?language=EN
+http://archiv.leo.org/pub/comp/usenet/comp.binaries.atari.st/texinfo31/texif31b.zoo/
+http://www.maas.ccr.it/cgi-win/hiweb.exe/a18/d13/b261,4,d,,be,d,
+http://citeseer.nj.nec.com/cidcontext/608466
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/asiasanahaku/strategia/kansainv%E4listyminen/ulkomaankauppa/kansainv%E4linen+kauppa/
+http://cms.letsmusic.com/directory/search/albuminfo/1,1125,af0127818000000,00.asp
+http://www.musiciansfriend.com/ex/ds/other/001030182805064208037054818832
+http://www.musiciansfriend.com/ex/search/other/001030182805064208037054818832?FIND=IBAX&q=c
+http://www.mapion.co.jp/custom/tv/admi/13/13106/kuramae/3chome/19/
+http://dblab.comeng.chungnam.ac.kr/~dolphin//db/journals/ac/ac11.html
+http://archive.soccerage.com/s/de/09/c4816.html
+http://archive.soccerage.com/s/de/09/c4698.html
+http://archive.soccerage.com/s/de/09/c4664.html
+http://archive.soccerage.com/s/de/09/c4463.html
+http://archive.soccerage.com/s/de/09/c4423.html
+http://archive.soccerage.com/s/de/09/c4422.html
+http://workingfamilies.digitalcity.com/tampabay/penpals/browse.dci?cat=teens&sort=f
+http://www.bemi-immobilien.de/Startseite/www.allgemeine-immobilien-boerse.de/allgemeine-ib/landkreiszwickau/Verkauf/29109700708107kirchbergvillamü/Gemeinsam/Inserieren/Startseite/Gemeinsam/immolink/Top-Darlehens-Konditionen/Gemeinsam/versicherungen/unfall/anforderungsformular.htm
+http://www.samba.org/cgi-bin/cvsweb/gnokii/xgnokii/docs/help/en_US/windows/main/?sortby=log
+http://www.accesslasvegas.com/shared/health/adam/ency/article/002669sym.html
+http://www.egroups.com/message/gaywrestle/33
+http://lfs.cyf-kr.edu.pl:8888/3Lcn%3dDirectory%20Manager,%20o%3dSPRITEL,%20c%3dES
+http://www.acfas.ca/congres/congres66/S10.htm
+http://hansard.www.act.gov.au/2000/week02/423.htm
+http://207.25.71.142/cycling/2000/tour_de_france/stages/4/
+http://207.25.71.142/cycling/2000/tour_de_france/news/2000/07/20/pantani_reflects
+http://207.25.71.142/cycling/2000/tour_de_france/news/2000/07/19/driver_charged/
+http://207.25.71.142/POLL/results/1142011.html
+http://www2.kbank.no/Web/nlpublish.nsf/Published/ord_og_uttrykk!OpenDocument&ExpandSection=6,14,27,22
+http://www2.kbank.no/Web/nlpublish.nsf/Published/ord_og_uttrykk!OpenDocument&ExpandSection=29,14,27,22
+http://www.affiliate.hpstore.hp.co.uk/do/session/380816/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.france.hp.com/
+http://www.affiliate.hpstore.hp.co.uk/do/session/380816/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/products/entry.asp
+http://ads.carltononline.com/accipiter/adclick/site=purejamba/area=jamba.home_page/AAMSZ=POPUP/ACC_RANDOM=972959547609
+http://retailer.gocollect.com/do/session/1912714/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/contact.asp
+http://208.178.101.41/news/1998/12/10newsd.html
+http://208.178.101.41/news/1998/03/05news.html
+http://208.178.101.41/news/1998/03/03news.html
+http://208.178.101.41/news/1998/01/09news.html
+http://hff.shunde.net/mobile/radio2000.163.net/radio2000.163.html
+http://hff.shunde.net/mobile/www.tohome.net/www.tohome.html
+http://www.egroups.com/login.cgi?login_target=%2Fmessages%2FShayrs%2F31
+http://moviestore.zap2it.com/browse/MOVIES/BANK/s.bsk4qCBs
+http://moviestore.zap2it.com/browse/MOVIES/STATION/s.bsk4qCBs
+http://moviestore.zap2it.com/browse/MOVIES/VIDEO/s.bsk4qCBs
+http://ftp.fi.debian.org/debian/dists/unstable/contrib/source/x11/?N=D
+http://link.fastpartner.com/do/session/600364/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/company/jobs.htm
+http://pub16.ezboard.com/uprieni.showPublicProfile
+http://ftp.du.se/disk4/FreeBSD/branches/4.0-stable/ports/x11-servers/XFree86-4-FontServer/
+http://ftp.du.se/disk4/FreeBSD/branches/4.0-stable/ports/x11-servers/XttXF98srv-NKVNEC/
+http://www.generation-formation.fr/services/adrutils/GUIDES/CCI.HTM---o21zAo0UaWo0Ol9A074fo65iyfmKlze8SUeecTAseLvI5ehw7se7NeCfeZJPAPfVbNyqgBecVktePbBxehwwlezc9fAb0vyApuRtAhGqGdisSLdspt6dsSAtdsNhJdspt6dsrvrdjlhkfbu.htm
+http://www.generation-formation.fr/services/adrutils/GUIDES/DRIRE.HTM---o21zAo0UaWo0Ol9A074fo65iyfmKlze8SUeecTAseLvI5ehw7se7NeCfeZJPAPfVbNyqgBecVktePbBxehwwlezc9fAb0vyApuRudNnJpo1XCjdRsR3djaPfdNjfcdRsR3djakUApvGdhcmdfbv.htm
+http://198.103.152.100/search*frc/aMayer,+Anita/amayer+anita/-5,-1,0,B/frameset&F=amaybank+j+e&1,1
+http://198.103.152.100/search*frc/aMayer,+Anita/amayer+anita/-5,-1,0,B/2exact&F=amaycunich+ann&1,3
+http://kobenhavn.icepage.se/hilfe/XFree86/3.9.18/DECtga2.html
+http://itcareers.careercast.com/texis/it/itjs/+YwwBmeJf5C6wwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewyhw1Bdmn5AanLnq1BoVnawmMoDo5BGwBoVnazdxamnpwGBMnDBaGnpdGB5a5BdGnaqddGmoDwBnanMwoca5Aocc5aMFqoEuRZy0IQDzmeJqwwwpBmeBFZ86mwww5rmehpwwwBrmeZpwww/morelike.html
+http://itcareers.careercast.com/texis/it/itjs/+cwwBmetKD86eMmwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewyhw1Bdmn5AanLnq1BoVnawmMoDo5BGwBoVnazdxamnpwGBMnDBaGnpdGB5a5BdGnaqddGmoDwBnanMwoca5Aocc5aMFqoEuRZy0IQDzmeJqwwwpBmeBFZ86mwww5rmeODwwwBrmeZpwww/morelike.html
+http://bbs.syu.ac.kr/NetBBS/Bbs.dll/scbbs008/rcm/zka/B2-kB27p/qqo/005A/qqatt/^
+http://musicmabey.subportal.com/sn/Themes/Misc__Themes/
+http://www.intel.it/eBusiness/pdf/prod/ia64/SAS_IA-64_Paper.pdf
+http://elflife.bigpanda.net/2866/io.html
+http://www.excelsior.com.mx/9609/960911/nac11.html
+http://www.allgemeine-immobilien-boerse.de/ungarn/verkauf/Private-IB/Ferien-IB/Startseite/Allgemeine-IB/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/indexbeginn.htm
+http://www.allgemeine-immobilien-boerse.de/ungarn/verkauf/Private-IB/Ferien-IB/Startseite/Allgemeine-IB/Gemeinsam/geschaeftsbedingungen.htm
+http://www.wingateinns.com/ctg/cgi-bin/Wingate/look_over/AAAksrACwAAACCPAAT
+http://my.netian.com/~rakyun/?N=D
+http://www.bemi-immobilien.de/Landhaus-Bordeaux/Gemeinsam/versicherungen/gebaeude/Gemeinsam/immolink/Top-Darlehens-Konditionen/Gemeinsam/Inserieren/Gemeinsam/suche.htm
+http://www.mirror.kiev.ua:8083/paper/2000/04/1251/text/04-07-5.htm
+http://ring.toyama-u.ac.jp/archives/NetBSD/packages/1.4.2/sun3/?N=D
+http://ring.toyama-u.ac.jp/archives/NetBSD/packages/1.4.2/sun3/lang/
+http://www.vstore.com/vstorecomputers/8store/
+http://indiadirectory.indiatimes.com/webdirectory/1514pg1.htm
+http://indiadirectory.indiatimes.com/webdirectory/1513pg1.htm
+http://www.online.kokusai.co.jp/Map/V0002508/wrd/G400/demo/
+http://www.gamespot.com.au/features/everquest_gg/creatures1.html
+http://www.jxi.gov.cn/yw-ty001.nsf/view!OpenView&Start=38.11&Count=30&Expand=40
+http://www.jxi.gov.cn/yw-ty001.nsf/view!OpenView&Start=38.11&Count=30&Expand=42
+http://yp.gates96.com/6/0/40/22.html
+http://yp.gates96.com/6/0/40/85.html
+http://yp.gates96.com/6/0/41/26.html
+http://yp.gates96.com/6/0/41/94.html
+http://yp.gates96.com/6/0/42/50.html
+http://yp.gates96.com/6/0/43/30.html
+http://yp.gates96.com/6/0/43/76.html
+http://yp.gates96.com/6/0/44/43.html
+http://yp.gates96.com/6/0/44/61.html
+http://yp.gates96.com/6/0/44/99.html
+http://yp.gates96.com/6/0/45/37.html
+http://yp.gates96.com/6/0/45/84.html
+http://yp.gates96.com/6/0/47/33.html
+http://yp.gates96.com/6/0/47/43.html
+http://yp.gates96.com/6/0/47/54.html
+http://yp.gates96.com/6/0/48/30.html
+http://yp.gates96.com/6/0/48/47.html
+http://yp.gates96.com/6/0/49/5.html
+http://hammer.prohosting.com/~kobeweb/cgi-bin/nagaya/nagaya.cgi?room=036&action=mente
+http://www.petropages.com/kproduct/k4267p.htm
+http://webraft.its.unimelb.edu.au/536029/students/plam/pub/?M=A
+http://www.ld.com/cbd/archive/1999/09(September)/13-Sep-1999/Fawd001.htm
+http://www.caijing.yesky.com/33554432/36700160/122010.htm
+http://yp.gates96.com/14/85/0/7.html
+http://yp.gates96.com/14/85/2/86.html
+http://yp.gates96.com/14/85/3/90.html
+http://yp.gates96.com/14/85/6/37.html
+http://yp.gates96.com/14/85/8/82.html
+http://yp.gates96.com/14/85/8/88.html
+http://cn.egroups.com/messages/Toledo_Storm/228
+http://mediate.magicbutton.net/do/session/625598/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-cart.html
+http://rainforest.parentsplace.com/dialog/thread.pl/bradley2/10/2.html?dir=prevResponse
+http://tvstore.zap2it.com/browse/TV/JACKET/s.CmMildAx
+http://tvstore.zap2it.com/browse/TV/CLOCK/s.CmMildAx
+http://findmail.com/post/studentdoctor?act=forward&messageNum=2315
+http://www.chaos.dk/sexriddle/d/j/l/a/y/
+http://gandalf.neark.org/pub/distributions/OpenBSD/src/gnu/egcs/libstdc++/testsuite/libstdc++.tests/?D=A
+http://gd.cnread.net/cnread1/net/zpj/s/shenfang/004.htm
+http://www.imagesignworks.com/vinylmasksforacidetching/index.nhtml
+http://209.249.170.32/stores/dir/bycat/Holiday_and_Seasonal/Christmas.shtml
+http://www.allkorea.co.jp/cgi-bin/allkorea.front/972959867726/Catalog/1000107
+http://www.allkorea.co.jp/cgi-bin/allkorea.front/972959867726/Catalog/1000108
+http://www.linux.com/networking/network/applications/interface/microsoft/IBM/
+http://www.linux.com/networking/network/applications/interface/microsoft/Corel/
+http://www.linux.com/networking/network/applications/interface/microsoft/?kw_offset=50
+http://www.tiefbau-suhl.de/Leistung/Stuetzmauern/stuetzmauern2.htm
+http://providenet.tucows.com/win2k/adnload/38394_29124.html
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/index.opentext.net/weather/detail.cgi?us-dc
+http://iceberg.adhomeworld.com/cgi-win/redirect.exe/2133549064
+http://www.dc.digitalcity.com/charlestonwvarea/announce/main.dci?page=letusknow
+http://members.tripod.co.jp/yoshihiro_2/yotete.html
+http://www.bemi-immobilien.de/Startseite/www.allgemeine-immobilien-boerse.de/allgemeine-ib/landkreiszwickau/Verkauf/29109700708107kirchbergvillamü/Gemeinsam/immolink/Startseite/Gemeinsam/versicherungen/lebensversicherung/Gemeinsam/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/
+http://ftp.debian.org/dists/Debian2.2r0/non-free/binary-arm/web/?N=D
+http://www.complete-skier.co.uk/resorts/survey/submit.asp?ResortID=1755
+http://members.tripod.com/~BHS_CC/boys_times_1997.html
+http://fi.egroups.com/post/mens-health?act=forward&messageNum=11
+http://nomade.fr/cat/famille_sante/sante/medecine_pratique/medecine_generale/
+http://home.att.net/~mlbvault/mac8.htm
+http://mirror.nucba.ac.jp/mirror/Perl/authors/id/ROSCH/String-ShellQuote-1.00.readme
+http://www.nrk.no/finnmark/x12_9_96/nyh6.htm
+http://ftp.debian.org/dists/Debian2.2r0/non-free/binary-m68k/editors/?N=D
+http://134.84.160.1/infoserv/lists/nih-image/archives/nih-image-9702/0141.html
+http://www.philly.digitalcity.com/saintjosephmo/penpals/browse.dci?cat=seniors&sort=m
+http://www.idg.net/crd_percent_19960.html
+http://204.202.130.51/playerfile/profile/mark_karcher.html
+http://www.redrocksports.com/sports/webSession/shopper/RR972959692-31077/store/dept-5/department/dept-5/item/52800
+http://www.redrocksports.com/sports/webSession/shopper/RR972959692-31077/store/dept-5/department/dept-5/item/52900
+http://www.online.kokusai.co.jp/Service/V0043510/wrd/G200/service/service.html
+http://www.service911.com/mvu/step/0,2632,1+13+139+23899+17191_4,00.html
+http://216.34.146.180/141000afp/14worl21.htm
+http://www.chaos.dk/sexriddle/t/p/v/r/i/
+http://www.chaos.dk/sexriddle/t/p/v/r/x/
+http://www.ualberta.ca/FTP/Mirror/debian/dists/potato-proposed-updates/eruby_0.0.9-1potato1_arm.changes
+http://www.hbdaily.com.cn/scznb/20000622/BIG5/scznb^1104^16^Zn16014.htm
+http://www.linux.com/networking/network/administrator/internet/ftp/install/
+http://bsdweb.pasta.cs.uit.no/bsdweb.cgi/xsrc/xc/lib/Xt/PassivGrab.c?sortby=author
+http://bsdweb.pasta.cs.uit.no/bsdweb.cgi/xsrc/xc/lib/Xt/ConstrainP.h?sortby=author
+http://www.jamba.de/KNet/_KNet-EAA8j1-vFd-13b95/browse.de/node.0/cdel3j591
+http://vvv.geocities.co.jp/SiliconValley-SanJose/5688/sn-3.html
+http://vvv.geocities.co.jp/SiliconValley-SanJose/5688/n.html
+http://www.amel.net/english/computer/games/b/X0006_Backstab__.html
+http://www.amel.net/english/computer/games/b/X0059_Bumper_Ships_1.1.html
+http://retailer.gocollect.com/do/session/1912693/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/sports/index.asp
+http://www.hig.se/(apre,formoutput,modified,set,set_cookie)/~jackson/roxen/
+http://yp.gates96.com/3/73/80/18.html
+http://yp.gates96.com/3/73/81/27.html
+http://yp.gates96.com/3/73/81/48.html
+http://yp.gates96.com/3/73/81/58.html
+http://yp.gates96.com/3/73/82/38.html
+http://yp.gates96.com/3/73/83/30.html
+http://yp.gates96.com/3/73/83/43.html
+http://yp.gates96.com/3/73/83/49.html
+http://yp.gates96.com/3/73/83/52.html
+http://yp.gates96.com/3/73/84/33.html
+http://yp.gates96.com/3/73/84/75.html
+http://yp.gates96.com/3/73/85/2.html
+http://yp.gates96.com/3/73/85/44.html
+http://yp.gates96.com/3/73/85/70.html
+http://yp.gates96.com/3/73/86/37.html
+http://yp.gates96.com/3/73/86/59.html
+http://yp.gates96.com/3/73/87/97.html
+http://yp.gates96.com/3/73/87/99.html
+http://yp.gates96.com/3/73/88/58.html
+http://yp.gates96.com/3/73/88/63.html
+http://yp.gates96.com/3/73/88/97.html
+http://yp.gates96.com/3/73/89/31.html
+http://yp.gates96.com/3/73/89/40.html
+http://deseretbook.com/products/4108132/stock-38.html
+http://workingfamilies.digitalcity.com/madison/search/
+http://debian.linux.org.tw/debian/dists/Debian2.2r0/main/disks-sparc/current/?D=A
+http://debian.linux.org.tw/debian/dists/Debian2.2r0/main/disks-sparc/current/base-contents.txt
+http://www.wizardsoftheweb.com/news/183.shtml
+http://mathematics.fiz-karlsruhe.de/stn/whyonline/why_0367.html
+http://www.nrk.no/finnmark/x27_11_98/nyh3.htm
+http://rex.skyline.net/navigate.cgi?computers,agriculture,nature,agriculture,computers
+http://www.secinfo.com/d1ZG7r.78.htm
+http://www.secinfo.com/d1ZG7r.74.htm
+http://www.freesoftware.com.cn/python.org.cn/doc/essays/ppt/hp-training/tsld051.htm
+http://www.nrk.no/finnmark/x28_5_96/nyh1.htm
+http://www.areteoutdoors.com/channel/snow/downhilling/b.354.g.2944.html
+http://www.areteoutdoors.com/channel/snow/downhilling/b.357.g.2944.html
+http://www.mywebmd.net/roundtable_message/662348
+http://lovers-lane.porncity.net/216/
+http://myhome.thrunet.com/~estefe/seng/sen18.htm
+http://myhome.thrunet.com/~estefe/seng/sen42.htm
+http://myhome.thrunet.com/~estefe/seng/sen52.htm
+http://myhome.thrunet.com/~estefe/seng/sen73.htm
+http://no.egroups.com/login.cgi?login_target=%2Fmessages%2Fenglish-zone
+http://www.uzp.gov.pl/biulety/1998/100/100_1327.html
+http://www.uzp.gov.pl/biulety/1998/100/100_1341.html
+http://www.uzp.gov.pl/biulety/1998/100/100_1372.html
+http://www.uzp.gov.pl/biulety/1998/100/100_1377.html
+http://www.uzp.gov.pl/biulety/1998/100/100_1428.html
+http://www.hotelboulevard.com/fr/riviera/standard/html40f8403856d2fa84c9080a860b7608ba/sessionLang/ANG/prov/browse/lstLieu[0]/Saint-Tropez/resultatSearch.html
+http://polygraph.ircache.net:8181/http_-2www.microsoft.com/frontpage/speeches/Pages/funds/portfolio.html
+http://www9.hmv.co.uk:5555/do/session/1347778/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d40_sd0_pt0.html
+http://edc.uni-augsburg.de/doc/susehilf/pak/paket_doinst_insure.html
+http://www.schlagerplatten.de/NewmanJimmyC/B000009PXU.htm
+http://cn.egroups.com/message/pro92/604
+http://wwws.br-online.de/geld/boerse/980107/190001.html
+http://faqs.bilkent.edu.tr/faqs/sgi/faq/performer/section-3.html
+http://faqs.bilkent.edu.tr/faqs/sgi/faq/performer/section-46.html
+http://faqs.bilkent.edu.tr/faqs/sgi/faq/performer/section-105.html
+http://faqs.bilkent.edu.tr/faqs/sgi/faq/performer/section-111.html
+http://newsone.net/nnr/prep/maus.soziales.recht
+http://www.mapion.co.jp/custom/tv/admi/14/14131/yako/3chome/1/
+http://info.verwaltung.uni-freiburg.de/doc/packages/qt/html/qpicture-members.html
+http://www.allkorea.co.jp/cgi-bin/allkorea.front/972959870915/ContentView/1000091/1/1200207
+http://tour.stanford.edu/cgi/locate2.prl/135.5/jltA
+http://mapquest.digitalcity.com/daytonarea/salaries/main.dci?page=admin
+http://linuxberg.zeelandnet.nl/x11html/adnload/9146_6809.html
+http://medwebplus.com/subject/Alternative%20and%20Complementary%20Medicine/Population/Lists%20of%20Internet%20Resources?^ftc=240&^cc=ftc
+http://ftp.du.se/disk0/slackware/slackware-current/contrib/ham/login/package_descriptions
+http://yp.gates96.com/12/56/70/0.html
+http://yp.gates96.com/12/56/70/14.html
+http://yp.gates96.com/12/56/70/62.html
+http://yp.gates96.com/12/56/71/19.html
+http://yp.gates96.com/12/56/71/38.html
+http://yp.gates96.com/12/56/71/46.html
+http://yp.gates96.com/12/56/72/49.html
+http://yp.gates96.com/12/56/72/78.html
+http://yp.gates96.com/12/56/72/91.html
+http://yp.gates96.com/12/56/73/18.html
+http://yp.gates96.com/12/56/73/52.html
+http://yp.gates96.com/12/56/74/15.html
+http://yp.gates96.com/12/56/74/54.html
+http://yp.gates96.com/12/56/74/79.html
+http://yp.gates96.com/12/56/75/28.html
+http://yp.gates96.com/12/56/75/68.html
+http://yp.gates96.com/12/56/75/71.html
+http://yp.gates96.com/12/56/75/76.html
+http://yp.gates96.com/12/56/75/88.html
+http://yp.gates96.com/12/56/75/94.html
+http://yp.gates96.com/12/56/76/27.html
+http://yp.gates96.com/12/56/76/57.html
+http://yp.gates96.com/12/56/76/73.html
+http://yp.gates96.com/12/56/77/60.html
+http://yp.gates96.com/12/56/78/3.html
+http://yp.gates96.com/12/56/78/45.html
+http://yp.gates96.com/12/56/78/64.html
+http://yp.gates96.com/12/56/78/86.html
+http://yp.gates96.com/12/56/78/91.html
+http://yp.gates96.com/12/56/78/95.html
+http://yp.gates96.com/12/56/79/39.html
+http://yp.gates96.com/12/56/79/75.html
+http://www.alldata.com/TSB/19/831915CS.html
+http://polygraph.ircache.net:8181/iisadmin/libraries/http_-2www.travelsc.com/welcome_v3/form1.html
+http://majordomo.cgu.edu/cgi-bin/lwgate/NEMAI/archives/nemai.archive.0003/Date/article-9.html
+http://home.tiscalinet.be/fysinet/studententips/tipsVanStudentenNicolas/sld007.htm
+http://www4.netease.com/~abac/writting/zpnr/xw.htm
+http://64.209.212.162/learnlots/step/0,2891,47+75+26299+10981_5,00.html
+http://www.adcentral.com/cgi-bin/w3com/pws/adsites/KLhIZjY9X9xD5moK2JGI9yyxCV4tsONpzxjYyzP1Uq5ZFTlQAg3Wd-d9dlZbdFK8g3p8_O5GT8q_tKPHmrHXekF-PEpGmxPO69EhQYYR0fwhi_k2GqJa7eAy8n4PQUv0fLw2IIBwNP_qQkQpWEvx666v
+http://www.nrc.nl/W2/Nieuws/1998/08/01/
+http://online.excite.de/unterhaltung/katalog/38320
+http://202.167.121.158/ebooks/jetro/tra1-1-1.html
+http://ftp.uni-paderborn.de/aminet/aminet/demo/tp94/Blur.readme
+http://www.symatrixinc.com/website/website.nsf/0/3e40df86fb357cd5882568720079613f!OpenDocument&ExpandSection=11,14,12,26
+http://www.intellicast.com/Ski/World/UnitedStates/Northeast/NewYork/WingedFootGCWest/WindChill/d1_12/
+http://yp.gates96.com/10/17/80/25.html
+http://yp.gates96.com/10/17/80/66.html
+http://yp.gates96.com/10/17/80/92.html
+http://yp.gates96.com/10/17/82/56.html
+http://yp.gates96.com/10/17/82/80.html
+http://yp.gates96.com/10/17/83/48.html
+http://yp.gates96.com/10/17/83/71.html
+http://yp.gates96.com/10/17/83/85.html
+http://yp.gates96.com/10/17/84/9.html
+http://yp.gates96.com/10/17/84/20.html
+http://yp.gates96.com/10/17/84/56.html
+http://yp.gates96.com/10/17/84/63.html
+http://yp.gates96.com/10/17/85/88.html
+http://yp.gates96.com/10/17/86/4.html
+http://yp.gates96.com/10/17/86/43.html
+http://yp.gates96.com/10/17/86/45.html
+http://yp.gates96.com/10/17/86/89.html
+http://yp.gates96.com/10/17/86/97.html
+http://yp.gates96.com/10/17/87/2.html
+http://yp.gates96.com/10/17/87/46.html
+http://yp.gates96.com/10/17/88/0.html
+http://yp.gates96.com/10/17/89/21.html
+http://yp.gates96.com/10/17/89/83.html
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/www.w3.org/International/O-URL-and-ident
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=(9,6)+21,0+3,0
+http://polygraph.ircache.net:8181/http_-2www.hystuff.com/nrc.htm
+http://jproxy.uol.es/jproxy/http://www.ocregister.com/beaches/capistrano
+http://www1.zdnet.com/companyfinder/filters/products/0,9996,38071-58,00.html
+http://www.ftp.uni-erlangen.de/pub/mirrors/_other/afterstep.foo.net/AfterStep/binaries/?M=A
+http://www.genome.wustl.edu:8021/gsc10/mouse/up/?D=A
+http://www.genome.wustl.edu:8021/gsc10/mouse/up/up24/
+http://rotten-tomatoes.com/movies/browse/1074473/reviews.php?view=reviews.source
+http://www.virtual-impact-mktg.com/fx110001.htm
+http://genforum.genealogy.com/hagen/messages/164.html
+http://genforum.genealogy.com/hagen/messages/111.html
+http://genforum.genealogy.com/hagen/messages/7.html
+http://genforum.genealogy.com/hagen/messages/271.html
+http://genforum.genealogy.com/hagen/messages/40.html
+http://nt.mortgage101.com/partner-scripts/1024.asp?p=cashsolutions
+http://nt.mortgage101.com/partner-scripts/1026.asp?p=cashsolutions
+http://library.cuhk.edu.hk/search*chi/t龍情三地+%26%2359%3B+[3]/t%7B21632b%7D%7B213e5b%7D%7B213024%7D%7B213779%7D++++3/-5,-1,0,B/browse
+http://ftp.net.uni-c.dk/pub/linux/redhat/redhat-6.2/sparc/misc/src/anaconda/isys/?S=A
+http://ftp.net.uni-c.dk/pub/linux/redhat/redhat-6.2/sparc/misc/src/anaconda/isys/modutils/
+http://cobrand.altrec.com/shop/detail/8273/30
+http://pegasus.infor.kanazawa-it.ac.jp/~hatlab/kaga/docs/jdk1.3-beta_api/jdk1.3/docs/api/java/lang/class-use/ClassFormatError.html
+http://bci.tucows.com/winnt/adnload/58788_28761.html
+http://www.buybuddy.com/sleuth/33/1/1020503/300/
+http://203.116.23.91/computer/pages2/it120800e.html
+http://203.116.23.91/special/newspapers/2000/pages4/computer030700.html
+http://203.116.23.91/computer/pages1/software131197.html
+http://dic.empas.com/show.tsp/?q=anarchically&f=B
+http://noodle.tigris.org/source/browse/subversion/subversion/libsvn_vcdiff/tests/target0.txt
+http://www.dbservicestore.de/home/db_reise_touristik/angebote/db_rt_gat_muenster.shtml
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=2&discrim=16,237,275
+http://www.narodnaobroda.sk/20000926/06_006.html
+http://mandijin.chinamarket.com.cn/C/Showdetail_company/22591.html
+http://202.167.121.158/ebooks/jetro/t6.html
+http://a228.g.akamai.net/7/228/289/dd50406be5fc91/news.indiainfo.com/2000/08/17/world-index.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=disaminerei&l=it
+http://polygraph.ircache.net:8181/http_-2www.eastnebr.net/html/conversions.htm
+http://www.secinfo.com/d2wVq.7ar.htm
+http://www.secinfo.com/d2wVq.7B5.htm
+http://www.secinfo.com/d2wVq.6cd.htm
+http://www.secinfo.com/d2wVq.59x.htm
+http://www.jamba.de/KNet/_KNet-xdz8j1-mFd-13b2b/browse.de/node.0/cenv0b09a
+http://213.36.119.69/do/session/152991/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/jeux/jeux_himalaya.html
+http://www.dailyexcelsior.com/99sep30/edit.htm
+http://www.dailyexcelsior.com/99sep30/sports.htm
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/misc/misc/music/lit/quizz/computers/netwars.html
+http://cometweb01.comet.co.uk/do!session=132020&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkjHfZoLlplLcqkKZljLlfb5lal5tkiLlXaLl0
+http://www.affiliate.hpstore.hp.co.uk/do/session/380832/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/search.asp
+http://208.216.182.15/exec/obidos/ASIN/0516206443/qid=972959559/sr=1-22/
+http://fi.egroups.com/messages/alau/2350
+http://ads.puntopartenza.com/cgi-bin/redirect.cgi/31033631
+http://pds.nchu.edu.tw/cpatch/ftp/ftpctrl/?N=D
+http://www.brio.de/BRIO.catalog/39fe2f5606def942273fd472aa7806e2/UserTemplate/5
+http://ep.com/js/mi/c7246/b0/832275.html
+http://ep.com/js/mi/c7246/b0/837505.html
+http://ep.com/js/mi/c7246/b0/764046.html
+http://www.fogdog.com/cedroID/ssd3040183223072/nav/products/nhl/pittsburgh_penguins/fan/gender/autographed_pucks/
+http://netway.pda.tucows.com/palm/preview/33567.html
+http://netway.pda.tucows.com/palm/preview/34007.html
+http://cometweb01.comet.co.uk/do!session=132006&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkjHfZoLlplLcqkKZljLlfb5lal5tkiLlXaLl0
+http://www.udn.com.tw/ARCHIVE/2000/08/04/DOMESTIC/YUNLIN/587058.htm
+http://www.linux.com/networking/network/support/web/news/services/
+http://www.linux.com/networking/network/support/web/news/website/
+http://www.linux.com/networking/network/support/web/news/business/
+http://ads.carltononline.com/accipiter/adclick/site=purejamba/area=jamba.home_page/AAMSZ=IAB_FULL_BANNER//ACC_RANDOM=972959548213
+http://www-x500-1.uni-giessen.de:8890/Lcn%3dConsuelo%20Alvarez,ou%3dDpto.%20Fisiologia%20y%20Biologia%20Animal,o%3dUniversidad%20de%20Sevilla,c%3dES
+http://www.chaos.dk/sexriddle/b/q/v/y/n/
+http://www.cs.kuleuven.ac.be/~java/docs/tutorial/uiswing/converting/example-1dot1/ListDemo.html
+http://golfonline.comfluent.net/cgi.pan$player&lpga82&Debbie_Raso&lpga?golfstats
+http://acetoys.com/cgi-bin/exec/modify_cart_button=1&cart_id=1999923.7130.303&page=/tystore/htmlfiles/eden/dw.html
+http://www.bigchurch.com/cgi-bin/w3com/pws/bc/y1hIyNzn0Bl2XX5GzG9wVnUEhWD8GTd-XbpDm6aNI4ZMGTnV_YsP2OjB0RrwLpDbJub1pKlzEMrInSQi9hRM-Rz4WNq8C1vKJ9STiU9leUD_a3PBVh-7OMZDzJtyEBAXTehiRqme6jBR
+http://www.bigchurch.com/cgi-bin/w3com/pws/bc/mChIR_iy1798J8x9InaTkzOfisuwH2hv2KUj0e64IQ9CeS327muTnTo70bT5YC4YznUddEOY5WdX70keIPRlsQibJtG6uzZtaaPmL58O5zJ0z_2PkJNxmBS5dj5-gWoeBgE0zaSvCbi66Grq
+http://wap.jamba.de/KNet/_KNet-8qB8j1-FFd-13blo/browse.de/node.0/cde7f2elw
+http://collection.nlc-bnc.ca/100/201/300/info_tabac/html/1997/bull7/fdacarol.html
+http://pub17.ezboard.com/fzhaostempleofenlightenmentzhaosforum.showMessage?topicID=116.topic
+http://www.home.ch/~spaw4360/HOWTO_fr/Ethernet-HOWTO-5.html
+http://www.chaos.dk/sexriddle/s/g/n/y/j/
+http://polygraph.ircache.net:8181/http_-2www.horizonfinance.com/https_-2www.truste.org/validate/page3.html
+http://marketbiz.subportal.com/sn/Themes/Sports_Themes/288.html
+http://www.chinaccm.com/04/news/200004/20/120305.asp
+http://www.american.webtourist.net/travel/northamerica/usa/lagunabeach/bwlagunareefinn.htm
+http://elib.zib.de/pub/visual/avs/mirror/imperial/new/?S=A
+http://www.burstnet.com/ads/ad7826a-map.cgi/969206790
+http://yp.gates96.com/14/82/10/81.html
+http://yp.gates96.com/14/82/12/82.html
+http://yp.gates96.com/14/82/13/55.html
+http://yp.gates96.com/14/82/14/27.html
+http://yp.gates96.com/14/82/14/31.html
+http://yp.gates96.com/14/82/15/52.html
+http://yp.gates96.com/14/82/17/16.html
+http://yp.gates96.com/14/82/17/93.html
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/P2hI5ODQEZ1-vIl-agOzeOeNg4wShDlZrsCbdT5YZ3TrprEU4rb4NnnDXiGmf5cX3dh8ltMer04TMDd3q-cE5Mne85eH57ltxsi4ZQfER6vkktoaaYlS9JFTzylmCJZ2_PAT9uu2oWvIjgMzt9toyeuV
+http://www.mirror.ac.uk/sites/ftp.microsoft.com/deskapps/powerpt/KB/Q226/7/
+http://mirror.nucba.ac.jp/mirror/Perl/authors/id/MIKEKING/?M=A
+http://lists.insecure.org/linux-kernel/2000/Jun/4357.html
+http://www.nlc-bnc.ca/indexmus-bin/resultsum/m=0/e=0/h=25/p=1/f=AU/t=Siroir,+Maryse+Angrignon
+http://genforum.genealogy.com/cgi-bin/print.cgi?leavy::19.html
+http://www.egroups.com/message/malaysiakini/219
+http://wuarchive.wustl.edu/graphics/mirrors/ftp.povray.org/.3/netlib/ode/rksuite/?S=A
+http://www.earthsystems.org/list/greenyes/jan2000/1999-2/0858.html
+http://pp3.shef.ac.uk:4040/search=browse/dn=countryName%3DGB%40organizationName%3DUniversity+of+Sheffield%40organizationalUnitName%3DAutomatic+Control+and+Systems+Engineering%40commonName%3DI+D+Durkacz
+http://cobrand.altrec.com/shop/detail/6133/15/sizing
+http://cobrand.altrec.com/shop/detail/5624/17/write
+http://members.theglobe.com/inwardpath/history.htm
+http://findmail.com/post/studentdoctor?act=reply&messageNum=5168
+http://www.service911.com/everythingtele/step/0,2675,3+26057+24201+16394_0,00.html
+http://www.linux.com/networking/network/free/release/development/mysql/
+http://www.nbip.com.cn/books/xdwx/Hongyan/hongyan14.html
+http://ftp.jp.debian.org/debian-non-US/dists/sid/non-US/non-free/binary-hurd-i386/?N=D
+http://homepage.swissonline.ch/chico_logo/www.Link008
+http://homepage.swissonline.ch/chico_logo/www.Link009
+http://citeseer.nj.nec.com/cidcontext/3719857
+http://itcareers.careercast.com/texis/it/itjs/+CwwBme3AT+6e-xwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewXnmoBGnamwBwxw5naBnqrDdcdtOaOnwGaMdDBramwOaqmwBwamn5otDamnVncdpoDtanDtoDnnGoDtaMFqhTfR20DzmebmwwwpBme3AT+6ekxwww5rmeXdwwwBrmeZpwww/jobpage.html
+http://www.amazon.com.hk/exec/obidos/tg/stores/detail/-/pro-tools/B0000224UB/customer-reviews/ref=th_hp_rs_2_6/
+http://www.ard-buffet.de/buffet/teledoktor/1998/02/16/
+http://pub19.ezboard.com/fmissionimplausiblewhatpeoplearesaying.emailToFriend?topicID=41.topic
+http://no.egroups.com/message/NikonCoolPix/211
+http://www.gasex.com/free.gay.sex/gay.men.dick.dicks.html
+http://www.centc251.org/forums/aca-1/dispatch.cgi/hsi/showFolder/100001/1255931
+http://www.uni-duesseldorf.de/ftp/ftp/pf/s/yagirc-0.65.6/?N=D
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/uIhI1DhpdvAdxVFONIJuaNcvtSTejSMmZIBgOwsZamHFS4JpS3i6VWNOSb8LsLcmqmG0gp2hs1YjuScHwXmociV5L_3_fCYngafHC4CIYDuKoI-rOZldw1RU5K3jOfh5d3PxatRmmHqB662F
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/elax176954/eus53832/eus155852/eus53907/eus62316/
+http://www.magictraders.com/cgi-bin/ubb/ubbmisc.cgi?action=getbio&UserName=Ammo187
+http://fi.egroups.com/login.cgi?login_target=%2Fgroup%2Fweirdchicks
+http://www.accesslasvegas.com/shared/health/adam/ency/article/000589.images.html
+http://pp3.shef.ac.uk:4040/search=browse/dn=countryName%3DGB%40organizationName%3DAberdeen+University%40organizationalUnitName%3DGeneral+Practice%40commonName%3DMorrison+S
+http://worldres.lycos.com/script/gen_amen.asp?hotel_id=2252&n=2089
+http://tulips.ntu.edu.tw/search*chi/dSymbolism+in+fairy+tales/dsymbolism+in+fairy+tales/-5,-1,0,B/browse
+http://ftp.du.se/disk4/FreeBSD/branches/4.0-stable/ports/x11-clocks/pclock/
+http://ftp.du.se/disk4/FreeBSD/branches/4.0-stable/ports/x11-clocks/xtimer/
+http://polygraph.ircache.net:8181/cgi-win/lincoln/$cgi4wpro.exe/http_-2www.k56.com/http_-2www.webexplorer.net/c/SHLFFREZ.HTM
+http://www.ecs.soton.ac.uk/~seg7/private/contact.html
+http://wiem.onet.pl/wiem/00de68-s.html
+http://lcweb2.loc.gov/ll/llnt/008/?M=A
+http://www.alladvantage.com/pressroom.asp?refid=CBI-463
+http://herndon1.sdrdc.com/cgi-bin/ind_detail/FERRELL|PORTER|FORT+WORTH|TX|76107|SINGLE+SERVER+COMMUNICATIONS/
+http://herndon1.sdrdc.com/cgi-bin/ind_detail/HARRIS|WILLIAM|FAIRFAX|VA|22031|HARRIS+AND+ASSOCIATES/
+http://herndon1.sdrdc.com/cgi-bin/ind_detail/HUTCHER|LARRY|NEW+YORK|NY|10023|DAVIDOFF+AND+MALITO/
+http://herndon1.sdrdc.com/cgi-bin/ind_detail/ISIKOFF|NATHAN+R|WASHINGTON|DC|20007|CAREY-WINSTON+CO/
+http://www.linux.com/networking/network/communications/security/wireless/protocol/
+http://www.linux.com/networking/network/communications/security/wireless/technology/
+http://retailer.gocollect.com/do/session/1912719/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/about.asp
+http://retailer.gocollect.com/do/session/1912719/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/exclusives/limited_editions.asp
+http://retailer.gocollect.com/do/session/1912719/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/clubhouse/suggestions.asp
+http://www9.hmv.co.uk:5555/do/session/1347779/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/hiddenframe.html
+http://pub9.ezboard.com/fwestlifedublinmessageboardwestlifemessageboard.showMessage?topicID=8.topic
+http://no.egroups.com/subscribe/hardzero
+http://link.fastpartner.com/do/session/600378/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/index.php
+http://link.fastpartner.com/do/session/600378/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/gosafe.php
+http://link.fastpartner.com/do/session/600378/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/bitconomy.php
+http://www.hello.co.jp/~daichi2/
+http://bbs.nsysu.edu.tw/txtVersion/treasure/ChiaYi/M.937783175.A/M.959916136.M.html
+http://chat.hani.co.kr/NetBBS/Bbs.dll/chosun21/lst/qqeq/1/zka/B2-kB2Bp/qqo/PRMY
+http://www.gartenfachmarkt.de/haus/schleifen/so.htm
+http://links2go.publiweb.com/topic/US_Department_of_Agriculture
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=14,15,6,36,22
+http://www.linux.com/networking/network/new/hardware/open_source/operating_system/
+http://www.linux.com/networking/network/new/hardware/open_source/availability/
+http://tokyo.cool.ne.jp/pure0101/Oblivion_dust.html
+http://www.digitaldrucke.de/(aktuell,computer,gaestebuch,hilfe,hilfeallgemein,individualverkehr,kultur,onlineservice,peripherie,sense,veranstaltungen,verkehr)/_fort/html/themen/computer/hard/links/mitsu.htm
+http://www.gbnf.com/genealogy/jenkins/html/d0097/I4129.HTM
+http://www.geocities.co.jp/Outdoors-River/1625/hakuba0502.htm
+http://ftp.fi.debian.org/OpenBSD/src/regress/share/man/
+http://www3.buch-per-sms.de/angemeldet.jsp$ID=To7767mC050667397857644736At0.8818825373175998
+http://www2.kbank.no/Web/nlpublish.nsf/Published/ord_og_uttrykk!OpenDocument&ExpandSection=15,25,16,27
+http://debian.tod.net/debian/dists/sid/main/binary-sparc/electronics/?D=A
+http://hs1.takeoff.ne.jp/~hatuse/
+http://polygraph.ircache.net:8181/Keyboards/http_-2www.sky.net/~robertf/handson/engine.html
+http://www.gbnf.com/genealogy/jenkins/html/d0005/I3818.HTM
+http://sepwww.stanford.edu/oldreports/sep67/old_src/jon/extend/junk.listing
+http://www.kol.net/~calldj/cyberstar/map/dw25a.htm
+http://citeseer.nj.nec.com/cidcontext/1297195
+http://citeseer.nj.nec.com/cidcontext/1297207
+http://books.hyperlink.co.uk/xt2/Peace_Verses_War/Cole/Derek/0722329539
+http://www.spousehouse.com/
+http://futures.homeway.com.cn/lbi-html/news/special/zhzt/jdht/twparty/zhengfu94652.shtml
+http://www.yorosiku.net:8080/-_-http://www.zdnet.co.jp/zdii/interviews/interviews.html
+http://library.cwu.edu/search/aIdaho+State+University/aidaho+state+university/-5,-1,0,E/frameset&F=aidaho+state+university&2,,0
+http://pelit.saunalahti.fi/.1/tucows/preview/68721.html
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=34,20,30,36,32
+http://pike-community.org/(base=/forums/show.html,forum=7,show=146,t=972959487953431)/forums/show.html
+http://pike-community.org/(base=/forums/show.html,forum=7,show=185,t=972959487953431)/forums/show.html
+http://pike-community.org/(base=/forums/show.html,explode=763,forum=7,t=972959487953431)/forums/show.html
+http://pike-community.org/(base=/forums/show.html,forum=7,show=870,t=972959487953431)/forums/show.html
+http://pike-community.org/(base=/forums/show.html,forum=7,show=890,t=972959487953431)/forums/show.html
+http://ww2.comune.fe.it/cgi-win/hiweb.exe/a2/d3/b34,8,1,,1f,1,65,,1f,65,
+http://www.telematik.informatik.uni-karlsruhe.de/osf/sw/v4.0x/lp2/bst320/kit/
+http://cafe3.daum.net/Cafe-bin/Bbs.cgi/harukypds/rnw/zka/B2-kB2Zq
+http://www.digitaldrucke.de/(computer,hilfe)/_fort/html/themen/computer/hard/links/escom.htm
+http://www2.ipc.pku.edu.cn/scop/pdb.cgi?sid=d6stdb_
+http://www2.ipc.pku.edu.cn/scop/pdb.cgi?sid=d4stdc_
+http://www.shopworks.com/index.cfm/action/specials/userid/00029735-2E1C-19FE-AF65010C0A0A8CF2
+http://www.shopworks.com/index.cfm/action/search/userid/00029735-2E1C-19FE-AF65010C0A0A8CF2
+http://www.helpnow.net.cn/helpnow/hardware/bbs/cpu/?D=A
+http://books.hyperlink.co.uk/xt1/Light_My_Fire/Manzarek/Ray/0099280655
+http://bsd.sinica.edu.tw/cgi-bin/cvsweb.cgi/src/crypto/heimdal/appl/ftp/ftp/?sortby=author
+http://tucows.interbaun.com/winme/adnload/5147_28523.html
+http://tucows.interbaun.com/winme/adnload/137019_28530.html
+http://moviestore.zap2it.com/browse/MOVIES/COLLECTI/s.NedNjpDf
+http://moviestore.zap2it.com/browse/MOVIES/STRAW/s.NedNjpDf
+http://www.online.kokusai.co.jp/Words/V0043505/wrd/G700/words/kana_main.html
+http://www.mirror.edu.cn/res/sunsite/pub/X11/contrib/window_managers/gwm/patches/gwm_patch_1.8a_001
+http://www.musicblvd.com/cgi-bin/tw/270242907922133_20_hip
+http://www.cowo.de/archiv/1991/21/9121c045.html
+http://www.russ.ru:8080/netcult/nevod/19990827-pr.html
+http://usol.linux.tucows.com/x11html/preview/26680.html
+http://usol.linux.tucows.com/x11html/preview/10385.html
+http://yp.gates96.com/7/22/20/54.html
+http://yp.gates96.com/7/22/20/67.html
+http://yp.gates96.com/7/22/20/71.html
+http://yp.gates96.com/7/22/22/26.html
+http://yp.gates96.com/7/22/22/55.html
+http://yp.gates96.com/7/22/22/74.html
+http://yp.gates96.com/7/22/22/94.html
+http://yp.gates96.com/7/22/23/38.html
+http://yp.gates96.com/7/22/23/59.html
+http://yp.gates96.com/7/22/24/43.html
+http://yp.gates96.com/7/22/24/60.html
+http://yp.gates96.com/7/22/24/64.html
+http://yp.gates96.com/7/22/24/66.html
+http://yp.gates96.com/7/22/24/72.html
+http://yp.gates96.com/7/22/24/85.html
+http://yp.gates96.com/7/22/26/11.html
+http://yp.gates96.com/7/22/26/69.html
+http://yp.gates96.com/7/22/27/3.html
+http://yp.gates96.com/7/22/27/11.html
+http://yp.gates96.com/7/22/27/22.html
+http://yp.gates96.com/7/22/27/48.html
+http://yp.gates96.com/7/22/27/69.html
+http://yp.gates96.com/7/22/28/13.html
+http://yp.gates96.com/7/22/28/30.html
+http://yp.gates96.com/7/22/29/39.html
+http://yp.gates96.com/7/22/29/58.html
+http://www.allgemeine-immobilien-boerse.de/frankfurt/verkauf/Gemeinsam/Super-Zins-Konditionen/Private-IB/Startseite/IIM-Teil/Startseite/Gemeinsam/Super-Zins-Konditionen/anforderungsformular.htm
+http://cobrand.altrec.com/shop/detail/8470/9/description
+http://oa-nett.no/0/73/90/2.html
+http://www.nordi.no/~steinsk/
+http://www02.geocities.co.jp/Stylish/6692/
+http://no.egroups.com/login.cgi?login_target=%2Fmessages%2Fsan-diego-tango
+http://no.egroups.com/message/san-diego-tango/390
+http://www.jamba.de/KNet/_KNet-m_C8j1-PFd-13bt7/showInfo-special1.de/node.0/cenv0b09a
+http://www.bemi-immobilien.de/Ferien-IB/Startseite/Gemeinsam/immolink/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Startseite/Gemeinsam/versicherungen/gebaeude/Startseite/froben.htm
+http://it.egroups.com/post/pimnews-homeworker?act=reply&messageNum=661
+http://members.es.tripod.de/remoto/t2/p3b.htm
+http://no.egroups.com/post/Translat2000?act=reply&messageNum=530
+http://www.opengroup.com/pabooks/081/0816631352.shtml
+http://www6.freeweb.ne.jp/feminine/ki18/portrait10/p21.htm
+http://genforum.genealogy.com/cgi-genforum/forums/cantrell.cgi?2117
+http://www9.hmv.co.uk:5555/do/session/1347769/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d30_sd0_pt0.html
+http://polygraph.ircache.net:8181/docs/Win95/MSdialer/http_-2www.fastcounter.com/http_-2www.perrypip.com/http_-2www.scruz.net/~dvb/cam.html
+http://polygraph.ircache.net:8181/docs/Win95/MSdialer/http_-2www.fastcounter.com/http_-2www.perrypip.com/~logan/
+http://polygraph.ircache.net:8181/docs/Win95/MSdialer/http_-2www.fastcounter.com/http_-2www.perrypip.com/http_-2hits.omino.com/
+http://javatest.a-net.nl/servlet/pedit.Main/http://epidem13.plantsci.cam.ac.uk/~js/glossary/course-glossary.html
+http://www.hellefors.se/ulf/akno/alla/p0349c5e1e.html
+http://home.no.net/islamnor/had.sira.html
+http://www.gutenberg2000.de/immerman/muenchim/muen1171.htm
+http://www.gutenberg2000.de/immerman/muenchim/muen3091.htm
+http://www.gutenberg2000.de/immerman/muenchim/muen7011.htm
+http://www.sikhnet.com/sikhnet/music.nsf/by%20Shabad!OpenView&Start=30&Count=20&Expand=2
+http://www.proteome.com/databases/PombePD/reports/SPCC613.01.html
+http://www.midwestvanlines.com/oh/indexC.html
+http://ring.tains.tohoku.ac.jp/pub/linux/debian/debian-jp/dists/stable/contrib/binary-arm/electronics/?S=A
+http://members.tripod.com/~infolog/Genhouses/Chap12.htm
+http://www.4positiveimages.com/4positiveimages/1998693855/UserTemplate/2
+http://www.greenleaves.com/bookcat/gb_096855900X.html
+http://www-rn.informatik.uni-bremen.de/home/X11R6/xc/doc/hardcopy/test/?M=A
+http://rex.skyline.net/html/Shipping_of_Goods.html?48,airplanes,transportation,collectibles,transportation
+http://rex.skyline.net/html/Automobile_Classified_Listings.html?59,airplanes,transportation,collectibles,transportation
+http://www.admin.co.martin.fl.us/GOVT/depts/cas/corresp/2000/cas00l.133.html
+http://www.admin.co.martin.fl.us/GOVT/depts/cas/corresp/2000/cas00l.126.html
+http://www.affiliate.hpstore.hp.co.uk/do/session/380834/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hpstore.hewlett-packard.fr/gp
+http://link.fastpartner.com/do/session/600367/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/no/
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/www-library.lbl.gov/photo/gallery/
+http://dogbert.wu-wien.ac.at/UniverCD/cc/td/doc/product/core/cis12012/bfrcfig/4334acps/?M=A
+http://ftp.uni-stuttgart.de/pub/tex/nonfree/support/latexdraw/doc/ltdmanual.html.g/node10.html
+http://se.egroups.com/message/911dispatchers/718
+http://ftp.eecs.umich.edu/.1/people/jfr/Pinata_Book/?D=A
+http://community.bigchalk.com/servlet/schools_ProcServ/DBPAGE=cge&GID=66001000660906746080215398&PG=66001000660906746080492039
+http://www2.kbank.no/Web/nlpublish.nsf/Published/ord_og_uttrykk!OpenDocument&ExpandSection=16,27,29,4
+http://www2.kbank.no/Web/nlpublish.nsf/Published/ord_og_uttrykk!OpenDocument&ExpandSection=22,27,29,4
+http://pds.nchu.edu.tw/cpatch/ftp/dap/cdap_4002.txt
+http://pds.nchu.edu.tw/cpatch/ftp/dap/source/
+http://kuyper.calvin.edu/fathers2/ANF-03/anf03-22.htm
+http://kuyper.calvin.edu/fathers2/ANF-03/anf03-27.htm
+http://blisty.internet.cz/1250/9908/19990813a.html
+http://ring.shibaura-it.ac.jp/archives/doc/jpnic/minutes/committee/200008/shiryou-2-8-2.txt
+http://194.128.65.4/pa/cm199697/cmhansrd/vo970306/text/70306w14.htm
+http://www.mortgagemag.com/guide/c096/c096573.htm
+http://link.fastpartner.com/do/session/600369/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/mondosoft.php
+http://link.fastpartner.com/do/session/600369/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/gosafe.php
+http://cometweb01.comet.co.uk/do!session=132008&vsid=692&tid=20&cid=37051&mid=1000&rid=1060&chid=1702&url=eqqLmwlGltt5tkjHfZoLlplLcqkKZljLlfb5lal5tkiLlXaLl0
+http://www.vh.org///////Patients/IHB/FamilyPractice/AFP/November1994/HormoneReplacement.html
+http://ftp.sunet.se/pub/unix/OpenBSD/distfiles/md5/74892a6ae002937d011d3e1102269b7f/?M=A
+http://www.pcdads.com/pressroom/archive/releases/cn112999.htm
+http://www.pcdads.com/pressroom/archive/releases/Fe90199a.htm
+http://www.pcdads.com/pressroom/archive/releases/Cn042199.htm
+http://www.cheap-cds.com/surf/order/017172
+http://www.hani.co.kr/ECONOMY/data/9909/day09/print/p00909060.html
+http://www.bemi-immobilien.de/Startseite/www.allgemeine-immobilien-boerse.de/allgemeine-ib/landkreiszwickau/Verkauf/29109700708107kirchbergvillamü/Gemeinsam/MarketingStrategie/Startseite/Gemeinsam/Inserieren/Gemeinsam/Gemeinsam/versicherungen/unfall/anforderungsformular.htm
+http://www.sj-rmall.com/Mall/Catalog/Product/ASP/product-id/57419/store-id/1000400121.html
+http://www.travelodge.com/ctg/cgi-bin/Travelodge/home/AAAksrACwAAABvTAAd
+http://ctc.org.cn/ctc2/news/internet/develop/news0322-6.htm
+http://www.schlagertempel.de/FallbachTrio/B000025MBP.htm
+http://www.fogdog.com/cedroID/ssd3040183238127/nav/products/nike/1b/all/10.html
+http://www.fogdog.com/cedroID/ssd3040183238127/customer_service/security_policy.html
+http://in.egroups.com/login.cgi?login_target=%2Fgroup%2Fradiotutorium
+http://yp.gates96.com/7/87/70/43.html
+http://yp.gates96.com/7/87/70/61.html
+http://yp.gates96.com/7/87/71/85.html
+http://yp.gates96.com/7/87/72/75.html
+http://yp.gates96.com/7/87/73/1.html
+http://yp.gates96.com/7/87/73/5.html
+http://yp.gates96.com/7/87/73/60.html
+http://yp.gates96.com/7/87/74/34.html
+http://yp.gates96.com/7/87/75/9.html
+http://yp.gates96.com/7/87/75/50.html
+http://yp.gates96.com/7/87/75/92.html
+http://yp.gates96.com/7/87/76/2.html
+http://yp.gates96.com/7/87/76/59.html
+http://yp.gates96.com/7/87/76/92.html
+http://yp.gates96.com/7/87/78/30.html
+http://yp.gates96.com/7/87/78/32.html
+http://yp.gates96.com/7/87/78/75.html
+http://yp.gates96.com/7/87/78/85.html
+http://yp.gates96.com/7/87/78/93.html
+http://yp.gates96.com/7/87/79/30.html
+http://yp.gates96.com/7/87/79/50.html
+http://yp.gates96.com/7/87/79/71.html
+http://yp.gates96.com/7/87/79/85.html
+http://interhotel.com/luxembourg/es/hoteles/45691.html
+http://interhotel.com/luxembourg/es/hoteles/73094.html
+http://bart.kullen.rwth-aachen.de/~quake3/Html_log/471_chat.html
+http://search.yam.com.tw/en/search/rec/travel/domest/resorts/miaolir/
+http://www.narodnaobroda.sk/19991009/23_006.html
+http://news.china.com/zh_cn/social/1007/20001027/7624.html
+http://www.fila.com.br/
+http://www.jobvillage.com/channel/jobs/health_care/female_health/b.3122.g.2360.html
+http://online.excite.de/bildung/katalog/35461
+http://deportes.ole.com/ocio/articulo/articulo.cfm?ID=OCI8055
+http://yp.gates96.com/3/36/90/2.html
+http://yp.gates96.com/3/36/90/37.html
+http://yp.gates96.com/3/36/90/55.html
+http://yp.gates96.com/3/36/90/79.html
+http://yp.gates96.com/3/36/91/7.html
+http://yp.gates96.com/3/36/92/59.html
+http://yp.gates96.com/3/36/92/95.html
+http://yp.gates96.com/3/36/93/76.html
+http://yp.gates96.com/3/36/93/88.html
+http://yp.gates96.com/3/36/94/41.html
+http://yp.gates96.com/3/36/94/64.html
+http://yp.gates96.com/3/36/95/16.html
+http://yp.gates96.com/3/36/95/33.html
+http://yp.gates96.com/3/36/95/39.html
+http://yp.gates96.com/3/36/96/36.html
+http://yp.gates96.com/3/36/96/53.html
+http://yp.gates96.com/3/36/99/30.html
+http://yp.gates96.com/3/36/99/73.html
+http://download.sourceforge.net/mirrors/turbolinux/turbolinux-cn/pub/turbolinux/updates/TLC3.0.2/?S=D
+http://www.jobvillage.com/channel/jobs/administrative/mrd/courier/b.4728.g.3366.html
+http://www.jobvillage.com/channel/jobs/administrative/mrd/shipping_clerk/b.4713.g.3366.html
+http://quote.fool.com/simple.asp?symbols=NS
+http://itcareers.careercast.com/texis/it/itjs/+NwwBmeIXD86dxwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewXhmoBGnaqdGpdGwBodDaqdMp1BnGadpnGwBodD5aMw55wqr15nBB5aqdGpdGwBnahoDwDqowcaMwocaBn5BoDtapGdxcnMaMFqhTfR20DzmetmwwwpBme_9D86eYmwww5rme1DwwwBrmeZpwww/jobpage.html
+http://www.shopworks.com/index.cfm/action/info/userid/00066256-1160-19FE-A703010D0A0A8CF2
+http://isbn.nu/0716723212/fatbrain
+http://isbn.nu/0716723212/amazon.ceo.html
+http://ftp.nacamar.de/pub/NetBSD/NetBSD-current/pkgsrc/www/p5-URI/?N=D
+http://213.36.119.69/do/session/152993/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/preparer/sante.htm
+http://213.36.119.69/do/session/152993/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/jeux/jeux_himalaya.html
+http://213.36.119.69/do/session/152993/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/DE_DE/
+http://www.linux.com/networking/network/support/open_source/investors/consulting/
+http://www.linux.com/networking/network/support/open_source/investors/research/
+http://sunsite.uakom.sk/doc/FAQ/alt-sex/fetish-fashion/?S=A
+http://sunsite.uakom.sk/doc/FAQ/alt-sex/fetish-fashion/?D=A
+http://phnet.tucows.com/winme/preview/75994.html
+http://www.fivedoves.com/letters/june99/trish67.htm
+http://www.teacherformation.org/html/od/facilitators.cfm/task1,about/discussion_id,2/xid,8571/yid,4064381
+http://pub24.ezboard.com/fnightmagicfrm1.showMessage?topicID=3.topic
+http://infoserv2.ita.doc.gov/efm/efm.nsf/Sources!OpenView&Start=53.28&Count=30&Expand=54
+http://www.linux.com/networking/network/communications/management/windows_nt/website/
+http://www.linux.com/networking/network/communications/management/windows_nt/?kw_offset=50
+http://www.epinions.com/cmd-review-593A-C9BAC2B-3987B6DC-prod1
+http://www.bande-dessinee.org/bd/bd02.nsf/InterDescenaristes!OpenView&Start=1&Count=50&Collapse=51
+http://www.business-partner.ch/static/fr/pourlesfirmes/lesgrandesentreprises/whateveryouwant/solutionsspecifiquesalabranche/transport/main.html
+http://ads.carltononline.com/accipiter/adclick/site=purejamba/area=JAMBA.HOME_PAGE/AAMSZ=KSJAMBA//ACC_RANDOM=972959547161
+http://expert.cc.purdue.edu/~yoko/simpsons/front.html
+http://dailynews.sina.com.cn/society/2000-06-14/97332.html
+http://ftp.dti.ad.jp/pub/Linux/debian-jp/dists/potato/main/binary-all/editors/?M=A
+http://www.babyheirlooms.com/catalog/htmlos.cat/041124.1.5608817466
+http://www9.hmv.co.uk:5555/do/session/1347791/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d100_sd0_pt0.html
+http://www.jobvillage.com/channel/jobs/health_care/pharmaceutical/pharmacist/b.3231.g.1267.html
+http://yp.gates96.com/11/24/80/12.html
+http://yp.gates96.com/11/24/80/18.html
+http://yp.gates96.com/11/24/80/84.html
+http://yp.gates96.com/11/24/80/90.html
+http://yp.gates96.com/11/24/81/6.html
+http://yp.gates96.com/11/24/81/9.html
+http://yp.gates96.com/11/24/81/54.html
+http://yp.gates96.com/11/24/81/74.html
+http://yp.gates96.com/11/24/81/98.html
+http://yp.gates96.com/11/24/82/17.html
+http://yp.gates96.com/11/24/82/96.html
+http://yp.gates96.com/11/24/83/54.html
+http://yp.gates96.com/11/24/83/58.html
+http://yp.gates96.com/11/24/84/44.html
+http://yp.gates96.com/11/24/84/52.html
+http://yp.gates96.com/11/24/84/63.html
+http://yp.gates96.com/11/24/85/35.html
+http://yp.gates96.com/11/24/85/77.html
+http://yp.gates96.com/11/24/85/78.html
+http://yp.gates96.com/11/24/87/15.html
+http://yp.gates96.com/11/24/87/77.html
+http://yp.gates96.com/11/24/88/0.html
+http://yp.gates96.com/11/24/88/63.html
+http://yp.gates96.com/11/24/89/93.html
+http://www.iabusnet.org:90/forums/aca-1/dispatch.exe/survey/listUnseen/fol/100001/20,0/2498053
+http://www.zeenzone.com/movies/1,4003,1040-21565,00.html
+http://www.zeenzone.com/movies/1,4003,1040-99354,00.html
+http://www.zeenzone.com/movies/1,4003,1040-109493,00.html
+http://forum.rai.it/aca-finestre/dispatch.cgi/FORUM/folderFrame/100001/0/author/627181
+http://moshkow.rsl.ru/alt/MORUA/letters.txt
+http://members.tripod.co.jp/muttley2000/?M=A
+http://www.shopworks.com/index.cfm/action/specials/userid/000A8C31-2EFD-19FE-9038010B0A0ADCF2
+http://www.bookhome.net/xiandangdai/other1/chunjiang/006.html
+http://www.bookhome.net/xiandangdai/other1/chunjiang/013.html
+http://www.dailyrush.dk/clans/145
+http://www.berlinonline.de/wissen/berliner_kurier/archiv/2000/0429/auto/0210/
+http://www.berlinonline.de/wissen/berliner_kurier/archiv/2000/0429/brandenburg/0011/
+http://www.berlinonline.de/wissen/berliner_kurier/archiv/2000/0429/lokales/0077/
+http://www.berlinonline.de/wissen/berliner_kurier/archiv/2000/0429/lokales/0009/
+http://www.berlinonline.de/wissen/berliner_kurier/archiv/2000/0429/lokales/0111/
+http://www.berlinonline.de/wissen/berliner_kurier/archiv/2000/0429/lokales/0117/
+http://www.berlinonline.de/wissen/berliner_kurier/archiv/2000/0429/lokales/0014/
+http://www.berlinonline.de/wissen/berliner_kurier/archiv/2000/0429/sport/0018/
+http://www.berlinonline.de/wissen/berliner_kurier/archiv/2000/0429/sport/0158/
+http://www.berlinonline.de/wissen/berliner_kurier/archiv/2000/0429/tv/0209/
+http://www.multicosm.com/facade/www.contigo.com/
+http://www.boston.digitalcity.com/cincinnati/health/conditions.dci?condition=sids
+http://www.onlineathens.com/1998/041498/0414.a2zbriefs.html
+http://ist.linux.tucows.com/conhtml/adnload/52224_1782.html
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/-2hIv4VApV7948YHO6tPdd62dgSdHSwg0xTrLhYidK4__IjhefvQTQrwpTMkkPdR5C5XRGbdA57_pJIxtMRvHJmrtjKdnzn_di6Er9p9vwIk1rLYwssqdvQbgeNAvSgd2M1a7O5NWleCth4ETxMfqPQS
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/VwhIXbmwUfG9PK362Tf07_xy8BQY7YBwNspFlCmPD_syQhuUcYEAU2eNoW3Liccn5fOj3JHbx2nCG9Tkl-PZwI9bR0uW5_3bO8O3kRwFm2Sp0E8MBNqJ9FvuLKt4pS_X3qzA8sbHcygn7lFrBe9ZZqi565Rs
+http://www.crutchfield.com/cgi-bin/S-5ILchLS19Z9/auto.asp
+http://www.quzhou.gov.cn/flfg.nsf/0a043ae26eb50247002564640039f21d/7cdda9dbc7e2b2bb002564ac00393b48!OpenDocument&ExpandSection=1,7,6
+http://opac.lib.ntnu.edu.tw/search*chi/m92+R627/m92+r627/-5,-1,0,B/buttonframe&F=m92+r449m&1,1
+http://www03.u-page.so-net.ne.jp/fc4/kazumasa/tdl/side2/side2.html
+http://launchbase.com/Home/Personal_Organization/communication/information/Bank_Rates_&_Info.htm
+http://launchbase.com/Home/Personal_Organization/communication/entertainment/Sports.htm
+http://launchbase.com/Home/Personal_Organization/communication/shopping/Flowers.htm
+http://launchbase.com/Home/Personal_Organization/communication/shopping/Pro-Audio.htm
+http://www.nissan.co.jp/RENAULT-DEALERS/PASSPORT/view.cgi/admission/972959587--
+http://channel.nytimes.com/1998/10/15/technology/
+http://www.la.gunma-u.ac.jp/S97/thtml/m/kiso/41808.html
+http://www1.ocn.ne.jp/~yaiba/_private/kobanasi/tyouhen/haraguroido/noroi.htm
+http://www.duluxvalentine.com/FRANCE:1161209847:DFinity.1QJiP4jmPgipihoa
+http://fi.egroups.com/messages/mediamalle-letter/6
+http://personal.wol.com.cn/lxz20a/gp13.htm
+http://eclat.gaiax.com/www/eclat/y/k/yoko_mama/main.html
+http://eclat.gaiax.com/www/eclat/y/k/yoko_mama/bbs.html
+http://findmail.com/login.cgi?login_target=%2Fgroup%2Fohsama-iroiro
+http://www.fogdog.com/cedroID/ssd3040183248487/crs/po__/wld/fogdog_sports/superfeet/outdoor/footwear/green_hi-profile.html
+http://www.fogdog.com/cedroID/ssd3040183248487/nav/stores/baseball/
+http://www.fogdog.com/cedroID/ssd3040183248487/nav/stores/winter_sports/
+http://www.consource.com/members/signup/signup_temp_user.html?tAccountID=561
+http://213.36.119.69/do/session/152994/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/reserver/voit.htm
+http://213.36.119.69/do/session/152994/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/BE_NL/
+http://webcvs.kde.org/cgi-bin/cvsweb.cgi/kdevelop/Attic/configure.in?r1=1.62&sortby=rev
+http://webcvs.kde.org/cgi-bin/cvsweb.cgi/kdevelop/Attic/configure.in?annotate=1.53&sortby=rev
+http://webcvs.kde.org/cgi-bin/cvsweb.cgi/kdevelop/Attic/configure.in?r1=1.46&sortby=rev
+http://www.aelita.net/products/solutions/sitemap/Reg/QuoteRegister/solutions/products/default.htm
+http://sunsite.org.uk/public/public/packages/pine/docs/?S=A
+http://sunsite.org.uk/public/public/packages/pine/docs/QandA.txt
+http://www.sfc.keio.ac.jp/~s98008na/miniproject/0.html
+http://www.allkorea.co.jp/cgi-bin/allkorea.front/972959867760/Catalog/1000023
+http://www.msn.expedia.co.uk/wg/Africa/Mauritius/P39048.asp
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/asiasanahaku/rakennesuunnittelu/talonrakennus/rakennukset/ohjeet/
+http://www.ericsson.cl/education/centers/dtmexic.shtml
+http://ftp.gigabell.net/debian/dists/Debian2.2r0/main/binary-powerpc/web/?S=A
+http://dirs.educationamerica.net/Colorado/Localities/C/Colorado_Springs/News_and_Media/Television/
+http://polygraph.ircache.net:8181/services/define/jeff/http_-2web01.hq.cyberserv.com/ryanhomes/http_-2www.travelsc.com/cgi-bin/news/NewsList.cfm?ID=1
+http://salinas2000.com/index.cfm/r/960/a/95.htm
+http://213.36.119.69/do/session/152988/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www3.travelprice.com/voyages/recherche.phtml
+http://213.36.119.69/do/session/152988/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/connaitre/questions-reponses.htm
+http://ftp.cpan.org/src/5.0/sperl-2000-08-05/?D=A
+http://virtualpubliclibrary.com/hallofanima/moresports/JOELOUIS.ORG//hallofanima/music/
+http://x500.rz.uni-karlsruhe.de:8000/Lcn%3dMonika%20Vogel,%20ou%3dPersonalabteilung,%20ou%3dUniversitaetsleitung%20und%20-verwaltung,%20o%3dUniversitaet%20Konstanz,%20c%3dDE
+http://bsd.sinica.edu.tw/cgi-bin/cvsweb.cgi/ports/korean/pine/files/patch-ai?only_with_tag=RELEASE_2_2_2
+http://ftp.ring.gr.jp/archives/XFree86/4.0.1/binaries/Linux-ix86-glibc21/RELNOTES
+http://homepage1.nifty.com/SAKURAISANS/itoshi.html
+http://www.expage.com/savetucker
+http://ring.edogawa-u.ac.jp/archives/pack/os2/prog/rexx/?N=D
+http://www.saarreisen.de/rueckel-reisen/fluege-buchen/barbados/reise-ibiza.htm
+http://debian.linux.org.tw/debian/dists/sid/contrib/binary-powerpc/interpreters/?S=A
+http://ricoh.co.jp/rtoss/School/other/other/lotus_syo/pg7.html
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus52213/eus52841/eus236353/eus591199/eus937052/
+http://www.mapion.co.jp/custom/AOL/admi/23/23101/higashiyamatori/4chome/index-17.html
+http://stocks.tradingcharts.com/stocks/charts/swti-bb/w/javachart
+http://ftp.univ-lyon1.fr/gnu/Manuals/diffutils-2.7/html_chapter/diff_15.html
+http://www.elfoco.com/EL_Foco/CDA/PrintPage/1,2171,2_53_28444,00.html
+http://www.debian.org.cn/Bugs/db/61/61000.html
+http://www.debian.org.cn/Bugs/db/66/66591.html
+http://www.debian.org.cn/Bugs/db/57/57112.html
+http://www.gxrb.com.cn/26/tbzl.htm
+http://opac.lib.rpi.edu/search/dyosemite+national+park+water+resources+development+research+california/-5,-1,0,E/2browse
+http://ring.omp.ad.jp/pub/NetBSD/NetBSD-current/src/usr.sbin/dhcp/client/scripts/openbsd
+http://attach1.egroups.com/attach/1087162/28/gs-108=71=1087162/10-1-10-160/application=octet-stream/IntOrganist.htm
+http://www.brainerddispatch.com/stories/071299/obi_0712990015.shtml
+http://webusers.siba.fi/doc/HOWTO/en-html/Multi-Disk-HOWTO-27.html
+http://www.pressa.spb.ru/newspapers/nevrem/arts/nevrem-1667-art-30.html
+http://www4.ocn.ne.jp/~l-tommy/C1024.html
+http://pub13.ezboard.com/fsequelossavannasoftwaredevelopment.showMessage?topicID=74.topic
+http://pub13.ezboard.com/fsequelossavannasoftwaredevelopment.showMessage?topicID=109.topic
+http://www.z-plus.de/freizeit/kino/galerie/unhold/kritikdpa.html
+http://www.tiscover.com/1Root/Kontinent/6/Staat/7/Bundesland/16/Ort/515/Privatvermieter/326225/Homepage/m_homepage...2.html
+http://wap.jamba.de/KNet/_KNet-NKE8j1-2Gd-13c6l/showInfo-wir.de/node.0/cde7f1uou
+http://www.refdag.nl/kl/990706kl02.html
+http://www.ferien-immobilien.de/nordrhein-Westfalen/soest/Verkauf/Versteigerungen-IB/Startseite/Gemeinsam/versicherungen/gebaeude/Versteigerungen-IB/Startseite/Gemeinsam/Super-Zins-Konditionen/anforderungsformular.htm
+http://caller-times.com/1999/september/18/today/local_sp/78.html
+http://link.fastpartner.com/do/session/600350/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/mondosoft.php
+http://providenet.tukids.tucows.com/mac/9-12/adnload/11899_25711.html
+http://providenet.tukids.tucows.com/mac/9-12/adnload/51475_24795.html
+http://fivestar.subportal.com/sn/Network_and_Internet/Dial-up_Networking_Dialers/11735.html
+http://www.kenley.londonengland.co.uk/newspaperandmagazinepublishers.htm
+http://builder.hw.net/frmRestDir/0,1112,'1~21~325~1~C~013800~07790',00.html
+http://builder.hw.net/frmRestDir/0,1112,'1~21~325~1~C~013800~54357',00.html
+http://ftp1.support.compaq.com/public/vms/vax/v6.0/sls/2.6/?M=A
+http://cpan.clix.pt/authors/id/I/IL/ILYAM/Mail-CheckUser-0.15.readme
+http://www.maasvlakte-cam.nl/webcams/23/stavanger__norway/2000/10/12/?D=A
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/music/midi/computers/quizz/lit/arnheim.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/music/midi/computers/quizz/misc/colorart/
+http://www.taftp.com/A555D3/WebDir.nsf/MBC!OpenView&Start=89.2&Count=30&Expand=106
+http://jundavid.subportal.com/sn/Shell_and_Desktop/Animal_Cursors/11879.html
+http://www.netitor.com/photos/schools/ucla/sports/m-wpolo/98-99action/?M=A
+http://cpan.nitco.com/modules/by-module/Devel/MSCHWERN/Class-DBI-0.03.readme
+http://cpan.nitco.com/modules/by-module/Devel/MSCHWERN/Text-Metaphone-0.02.readme
+http://www.digitaldrucke.de/(aktuell,computer,gaestebuch,kino,literatur,nuernberg,rundfunk,sense,veranstaltungen,zeitschriften)/_fort/html/themen/kultur/literat/links/bin.htm
+http://194.128.65.4/pa/cm199899/cmhansrd/vo990727/text/90727w01.htm
+http://194.128.65.4/pa/cm199899/cmhansrd/vo990727/text/90727w15.htm
+http://213.36.119.69/do/session/152989/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/jeux/jeux_himalaya.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/misc/quizz/lit/misc/cv.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/misc/quizz/lit/misc/lit/larme.html
+http://www.hblb.org.uk/hblbweb.nsf/$Pages/NewsArchive1!OpenDocument&ExpandSection=6,7,3,5,1,8,11
+http://www.identer.co.kr/삶의여유/데이트정보/데이트정보/
+http://allmacintosh.arrakis.es/adnload/54801.html
+http://link.fastpartner.com/do/session/600380/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/brleksaker.php
+http://link.fastpartner.com/do/session/600380/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/local/redirect.php
+http://icm.html.tucows.com/adnload/001-009-003-014.html
+http://www.rakuten.co.jp/coffee/forum/forum-w.cgi?p=131&url=coffee
+http://jxi.gov.cn/yw-cj001.nsf/6770fc9e7685796c482568c70008a30a!OpenView&Start=69&Count=30&Expand=70
+http://jxi.gov.cn/yw-cj001.nsf/6770fc9e7685796c482568c70008a30a!OpenView&Start=69&Count=30&Expand=72
+http://freehomepage.taconet.com.tw/This/is/taconet/top_hosts//tsyang/test9g.htm
+http://www11.cplaza.ne.jp/babyweb/bbs/bdnm01/no33/130N.html
+http://library.cuhk.edu.hk/search*chi/a憪���/a{213972}{213230}/-5,-1,0,B/frameset&F=a{213972}{213233}{215b34}&1,1
+http://library.cuhk.edu.hk/search*chi/a憪���/a{213972}{213230}/-5,-1,0,B/frameset&F=a{213972}{21323e}{213165}+1947&1,1
+http://library.cuhk.edu.hk/search*chi/a撱嗅ˊ,+904-975./a{213d32}{213877}++904++975/-5,-1,0,B/frameset&F=a{213d32}{213a67}{213779}{213455}+china+{215f7a}{213579}{213966}{21363e}{21435a}+{214241}{213c37}&1,1
+http://www.online.kokusai.co.jp/Service/V0043539/wrd/G200/service/service.html
+http://quote.morningstar.com/Quote.html?ticker=GASFX
+http://uoi.linux.tucows.com/x11html/adnload/9826_7194.html
+http://dk.egroups.com/post/batoco?act=forward&messageNum=2017
+http://www.chaos.dk/sexriddle/b/h/l/o/h/
+http://www.picktips.com/category-1031-1174_1171_1170-4_3_2
+http://www.schmunzelecke.de/pic18.htm
+http://sun1.rrzn-user.uni-hannover.de/zzzzgart/matlab/help/techdoc/umg/chhand20.html
+http://sun1.rrzn-user.uni-hannover.de/zzzzgart/matlab/help/techdoc/umg/chhand25.html
+http://sun1.rrzn-user.uni-hannover.de/zzzzgart/matlab/help/techdoc/umg/chhand30.html
+http://sun1.rrzn-user.uni-hannover.de/zzzzgart/matlab/help/techdoc/umg/chimag16.html
+http://sun1.rrzn-user.uni-hannover.de/zzzzgart/matlab/help/techdoc/umg/chimag26.html
+http://sun1.rrzn-user.uni-hannover.de/zzzzgart/matlab/help/techdoc/umg/chlight3.html
+http://sun1.rrzn-user.uni-hannover.de/zzzzgart/matlab/help/techdoc/umg/chspec34.html
+http://sun1.rrzn-user.uni-hannover.de/zzzzgart/matlab/help/techdoc/umg/chspec35.html
+http://sun1.rrzn-user.uni-hannover.de/zzzzgart/matlab/help/techdoc/umg/chview15.html
+http://sun1.rrzn-user.uni-hannover.de/zzzzgart/matlab/help/techdoc/umg/chvolvi5.html
+http://www.t-onlien.de/dtag/mail/kontaktseite/1,3606,160,00.html
+http://yumemi.ne.jp/bbs/hiroba/ky/view/h/hiroba3/8_wdsmcn_wdsmcn.html
+http://yumemi.ne.jp/bbs/hiroba/ky/view/h/hiroba3/8_mrlinl_tcincn.html
+http://yumemi.ne.jp/bbs/hiroba/ky/view/h/hiroba3/8_caouny_hixlcy.html
+http://students.lsu.edu/students/main.nsf/c81d2bf8cb0b80ff862566fb00105ab2/7f3436ae9cb1268886256773006f9288!OpenDocument&ExpandSection=20,9,13,16
+http://www.crn.com/sections/BreakingNews/breakingnews.asp?ArticleID=5760
+http://dennou-h.ees.hokudai.ac.jp/library/Linux/debian-jp/dists/hamm/main-jp/binary-all/tex/?M=A
+http://www.cmyk21.com/photo1-3.htm
+http://www.cs.ruu.nl/mirror/CPAN/modules/by-category/14_Security_and_Encryption/User/ILYAZ/images/?N=D
+http://www.egroups.com/login.cgi?login_target=%2Fmessage%2FFloodsystems%2F45
+http://www.mirnet.org/ccsi/nisorgs/ukraine/kyiv/renaisnc.htm
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=231&discrim=2,125,10
+http://ring.omp.ad.jp/archives/lang/perl/CPAN/authors/id/BRADAPP/PodParser-1.17.readme
+http://www.amzn.com.ref.digital-price.com/redir/amzn.com/prods/0553373730
+http://library.cwu.edu/search/dGermany+--+Politics+and+government+--+1918-1933/dgermany+politics+and+government+1918+1933/-5,-1,0,B/marc&F=dgermany+politics+and+government+1918+1933+bibliography&1,1,
+http://www.multicosm.com/facade/www.unisys.com/partners/default.asp?cn=su
+http://enjoy100.com.cn/200006/08/sssh/sssh_ssjp.html
+http://enjoy100.com.cn/200006/08/yskj/b_s_big3_f.jpg.html
+http://www.hoops.ne.jp/~zuikaku/photo2000/0811/rie11.html
+http://pub23.ezboard.com/fiolaniy2kmessageboardfrm1.showMessage?topicID=66.topic
+http://ring.htcn.ne.jp/archives/lang/perl/CPAN/modules/by-module/CGI/ULPFR/Wais-2.301.readme
+http://www3.newstimes.com/archive99/mar1199/spg.htm
+http://ftp1.support.compaq.com/public/vms/axp/v6.2-1h2/dsnlink/2.2/dsnlinkd022.CVRLET_TXT
+http://ftp.nacamar.de/pub/redhat/cpan/6.2/CPAN-archive/doc/manual/html/pod/perldsc.html
+http://ftp.nacamar.de/pub/redhat/cpan/6.2/CPAN-archive/doc/manual/html/pod/perlfaq5.html
+http://info.cs.unitn.it/sdb/de/html/keylist.SOFTWARE.html
+http://www.online.kokusai.co.jp/Mmf_corner/V0043545/mmf_corner/mmf_corner/url
+http://www.office.com/global/0,2724,66-15915,FF.html
+http://polygraph.ircache.net:8181/home/ISO9001.htm
+http://www.allgemeine-immobilien-boerse.de/niedersachsen/emsland/Verkauf/Versteigerungen-IB/Startseite/Allgemeine-IB/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/Gemeinsam/hilfe.htm
+http://launchbase.com/Health/Home_Health/communication/information/Science.htm
+http://library.cwu.edu/search/aLockyer,+Norman,+Sir,+1836-1920/alockyer+norman+sir+1836+1920/-17,-1,0,B/frameset&F=alockwood+victoria+s+1953&1,1
+http://bbs.kcm.co.kr/NetBBS/Bbs.dll/chbod05/lst/qqa/r/qqo/004D/zka/B2-kCYFl
+http://www.egroups.com/post/bhagavad_gita?act=forward&messageNum=101
+http://carriage.de/Schoner/Literatur/info-e/Geschichte/modelle/
+http://carriage.de/Schoner/Literatur/info-e/Geschichte/history/
+http://carriage.de/Schoner/Literatur/info-e/Geschichte/literature/
+http://wwwftp.ciril.fr/pub/linux/kernel///people/andrea/kernels
+http://www.inctechnology.com/guide/item/0,7462,AGD6_GDE79,00.html
+http://live.sportsline.com/u/basketball/college/teams/injuries/VATECH.htm
+http://www-1.cisco.com/univercd/cc/td/doc/product/lan/28201900/1928v67x/28icg67x/28icpref.pdf
+http://www.hitlist.com/music/presult/003948.php3
+http://ip.tosp.co.jp/Eki/TosiE000.asp?I=Jerryfish
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=(20,0)-16,0-9,2
+http://www.bigchurch.com/cgi-bin/w3com/pws/bc/RLhIotYxW-B0bt7seq4d876RzKIuJDYbydJP1qooxhzSKDVca77BUHQv6tsO2JdNpkx837SBl7FHRIEy00rmcLBk9Y1kQEmni0_YSk5mrym8WALtovIPQU_vlEtiMcNswNyh9z6CjU-2oS2uurrk666t
+http://www.secinfo.com/d2wVq.7hv.htm
+http://www.secinfo.com/d2wVq.6yd.htm
+http://www.secinfo.com/d2wVq.6Y5.htm
+http://www.secinfo.com/d2wVq.5gf.htm
+http://www.secinfo.com/d2wVq.5hp.htm
+http://www.secinfo.com/d2wVq.5y4.htm
+http://ring.htcn.ne.jp/pub/text/CTAN/graphics/psfig/unsupported/macdemo/macfigs/?N=D
+http://ring.htcn.ne.jp/pub/text/CTAN/graphics/psfig/unsupported/macdemo/macfigs/?M=A
+http://books.hyperlink.co.uk/xt2/Drakelow_Unearthed/Stokes/Paul/0904015408
+http://www.homestead.com/rebeccah/files/
+http://sunsite.compapp.dcu.ie/pub/linux/redhat/redhat-6.1/alpha/usr/share/locale/ga_IE/LC_TIME
+http://www.gbnf.com/genealogy/rockwel4/html/d0037/I2684.HTM
+http://www.yorosiku.net:8080/-_-http://www.dd.iij4u.or.jp/~oni9/skebe/aindex18.html
+http://www.yorosiku.net:8080/-_-http://www.dd.iij4u.or.jp/~oni9/skebe/aindex12.html
+http://www.yorosiku.net:8080/-_-http://www.dd.iij4u.or.jp/~oni9/skebe/atg05.html
+http://shn.webmd.net/content/article/1700.50808
+http://home.clara.net/cornell/woodcraft/spring2000/contents.htm
+http://dic.empas.com/show.tsp/EDACITY
+http://www.sanxia.net/beauty/Eriimai/417.htm
+http://www.judds-resort.com/judds/Lake-Winni-pike-lodge/97menu/fallphoto/playground/boat/photo/12.html
+http://www.judds-resort.com/judds/Lake-Winni-pike-lodge/97menu/fallphoto/playground/boat/fallphoto/2.html
+http://imageserver2.tibetart.com:8087/fif=fpxbuddhistreverse/56.fpx&init=0.0,0.0,1.0,1.0&rect=0.0,0.25,0.5,0.75&wid=1443&hei=400&lng=en_US&enablePastMaxZoom=OFF&page=image.html&obj=uv,1.0&cmd=W
+http://www.jamba.nl/KNet/_KNet-krE8j1-KC4-pv5y/showInfo-hilfe.nl/node.0/ce6u2jadf
+http://www.babyheirlooms.com/catalog/htmlos.cat/011639.1.3372173854
+http://community.webshots.com/photo/441160/441363
+http://www.kaos.dk/sexriddle/x/n/d/x/b/
+http://isbn.nu/088730866X/chapters
+http://login.hq.cricinfo.org/link_to_database/ARCHIVE/1992-93/AUS_LOCAL/MMC/WA_NSW_MMC_11OCT1992.html
+http://login.hq.cricinfo.org/link_to_database/ARCHIVE/1991-92/AUS_LOCAL/FAI/WA_TAS_FAI_11OCT1991.html
+http://login.hq.cricinfo.org/link_to_database/ARCHIVE/1991-92/AUS_LOCAL/FAI/WA_QLD_FAI-SEMI_19OCT1991.html
+http://login.hq.cricinfo.org/link_to_database/ARCHIVE/1980S/1987-88/AUS_LOCAL/MDC/WA_SOA_MDC_06MAR1988.html
+http://login.hq.cricinfo.org/link_to_database/ARCHIVE/1980S/1981-82/AUS_LOCAL/MDC/QLD_WA_MDC_08NOV1981.html
+http://www.chaos.dk/sexriddle/x/k/l/y/h/
+http://tucows.teihal.gr/winnt/preview/6004.html
+http://tucows.teihal.gr/winnt/preview/5986.html
+http://tucows.teihal.gr/winnt/preview/71328.html
+http://tucows.teihal.gr/winnt/preview/2757.html
+http://www.medoc-ias.u-psud.fr:81/synoptic/gif/950724/?N=D
+http://www4.nas.edu/ohr.nsf/All+Documents/Major+Units?OpenDocument&ExpandSection=18,7,21,20,4
+http://members.xoom.fr/logart/Anciens/Liste25/Selection_Navlist25.html
+http://polygraph.ircache.net:8181/http_-2www.arthritis.org/http_-2pathfinder.com/si/swimsuit/swim97/terms2.html
+http://polygraph.ircache.net:8181/http_-2www.arthritis.org/http_-2pathfinder.com/si/swimsuit/swim97/products2.html
+http://debian.linux.org.tw/debian/dists/Debian2.2r0/main/disks-m68k/current/doc/
+http://findmail.com/dir/Arts/Writing/Fan_Fiction?st=1943
+http://www.telecombroker.com/q/001p/tgcb/4izQYz7mc.htm
+http://www.free-phone.com/q/001p/tgcb/ItMd2D3jdEM.htm
+http://www.123bestlongdistance.com/q/001p/tgcb/msN54jfl4mE.htm
+http://www.netitor.com/photos/schools/nw/sport/w-baskbl/97action/?S=A
+http://excite.de/katalog/katalog/33823
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/programs/simple/music/midi/lit/misc/unitest/programs/
+http://yp.gates96.com/14/43/40/9.html
+http://yp.gates96.com/14/43/40/43.html
+http://yp.gates96.com/14/43/40/82.html
+http://yp.gates96.com/14/43/40/85.html
+http://yp.gates96.com/14/43/41/6.html
+http://yp.gates96.com/14/43/41/18.html
+http://yp.gates96.com/14/43/41/44.html
+http://yp.gates96.com/14/43/41/96.html
+http://yp.gates96.com/14/43/42/12.html
+http://yp.gates96.com/14/43/46/38.html
+http://yp.gates96.com/14/43/46/66.html
+http://yp.gates96.com/14/43/46/68.html
+http://yp.gates96.com/14/43/47/4.html
+http://yp.gates96.com/14/43/47/37.html
+http://yp.gates96.com/14/43/47/64.html
+http://yp.gates96.com/14/43/47/68.html
+http://yp.gates96.com/14/43/47/70.html
+http://yp.gates96.com/14/43/48/68.html
+http://yp.gates96.com/14/43/48/69.html
+http://yp.gates96.com/14/43/49/7.html
+http://yp.gates96.com/14/43/49/36.html
+http://yp.gates96.com/14/43/49/37.html
+http://yp.gates96.com/14/43/49/52.html
+http://sound-dist.secured.co.uk/cgi-bin/psProdDet.cgi/5P005|972959562|Accessories|user|0|1,0,0,1
+http://school.educities.org/card/judy180.html
+http://207.138.41.133/message/the-voice1/123
+http://207.138.41.133/message/the-voice1/124
+http://www-d0.fnal.gov/d0dist/dist/releases/p05.00.00/muo_analyze/?S=A
+http://sjsulib1.sjsu.edu:81/search/cernest+haberkern+director/-5,-1,0,B/frameset&cgeorge+miller+director&1,1
+http://ring.nii.ac.jp/pub/pack/x68/net/00_index.txt
+http://pub24.ezboard.com/fdoyoustillneedtoventfrm43.showMessage?topicID=19.topic
+http://pub24.ezboard.com/fdoyoustillneedtoventfrm43.showMessage?topicID=15.topic
+http://ukinvest.ukwire.com/articles/200007200700261473O.html
+http://www.brd.net/brd-cgi/brd_multimedia/lautsprecher/LZ7460LK/ci=972822952.htm
+http://my.netian.com/~haeng14/tatler_july6.htm
+http://genforum.genealogy.com/cgi-genforum/forums/anderton.cgi?122
+http://www.excelsior.com.mx/0001/000125/for03.html
+http://www.jobvillage.com/channel/jobs/sciences/b.9070.g.1675.html
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/www/contact.html?annotate=1.19&sortby=author
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/www/contact.html?r1=1.12&sortby=author
+http://www.doc.ic.ac.uk/lab/labsrc_area/firstyear/submissions/1998-99/jmc1/labs/Ex06/skw98/?N=D
+http://www.jamba.de/KNet/_KNet-fNw8j1-6Fd-13acp/browse.de/node.0/cde7f1uou
+http://www.jamba.de/KNet/_KNet-fNw8j1-6Fd-13act/browse.de/node.0/cdel3j591
+http://www.nedstat.nl/cgi-bin/viewstat?name=mrbertmat
+http://no.egroups.com/message/acessibilidade/1092
+http://no.egroups.com/message/acessibilidade/1099
+http://sound-dist.secured.co.uk/cgi-bin/psShop.cgi/add|38P08A|972959552|Communications|user|0|1,0,0,1
+http://213.36.119.69/do/session/152990/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/reserver/spectacles/
+http://213.36.119.69/do/session/152990/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/CA_EN/
+http://wiki2.parsimony.net/wiki2954/
+http://www.f2.parsimony.net/forum2954/messages/214.htm
+http://www.f2.parsimony.net/forum2954/messages/181.htm
+http://www.f2.parsimony.net/forum2954/messages/292.htm
+http://www.f2.parsimony.net/forum2954/messages/115.htm
+http://www.f2.parsimony.net/forum2954/messages/290.htm
+http://www.f2.parsimony.net/forum2954/messages/54.htm
+http://home.pchome.com.tw/cool/162203/wunew15.htm
+http://hem.fyristorg.com/lottaleman/LLfar/1_6721.htm
+http://www.babyheirlooms.com/catalog/htmlos.cat/011628.1.4596216338
+http://www.affiliate.hpstore.hp.co.uk/do/session/380833/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/search.asp
+http://www.outdoorwire.com/content/lists/dirt/200007/msg00127.html?{LoadingFrameset}
+http://adept.subportal.com/sn/Programming/ActiveX/11674.html
+http://www.staroriental.net/nav/soeg/ihf,aog,s0,10,Lam+Hei-Lui.html
+http://www-d0.fnal.gov/d0dist/dist/releases/p05.00.01/man/?N=D
+http://members.tripod.com/bluti/PSX/V/VACUUM.HTM
+http://connexus.tucows.com/winme/adnload/138384_29728.html
+http://wwwtios.cs.utwente.nl/archive/wilyfans/msg00265.html
+http://custom.clubnet.zeelandnet.nl/eckhardt/myself.htm
+http://ftp.tokyonet.ad.jp/pub/Linux/debian/dists/potato/contrib/binary-arm/otherosfs/?D=A
+http://www.amcity.com/charlotte/stories/1997/07/07/daily4.html?t=email_story
+http://www.generation-formation.fr/chiffrec.htm---o21zAo0UbDo0Ol9A074fo6Td4ezyr6feZJPAPfVbNyqHSezTHkekydMfeZJPdspt6dsSAtdsNhJdspt6dsrvrdjlhkfbi.htm
+http://tv.thevines.com/leaf/AA0000369140/2
+http://kuyper.calvin.edu/fathers2/NPNF2-02/Npnf2-02-06.htm
+http://www.intellicast.com/Ski/World/UnitedStates/Southeast/Florida/FortWaltonBeach/TEMPcast/d0_12/
+http://stevebarnes.studiostore.com/aboutus/b.EMERCH/s.P01EBK2I
+http://student.monterey.edu/Students_N-R/richterheidil/private/
+http://ds.dial.pipex.com/town/drive/kch36/select/s30/ch052.html
+http://ds.dial.pipex.com/town/drive/kch36/select/s30/ch027.html
+http://ds.dial.pipex.com/town/drive/kch36/select/s30/ch077.html
+http://ds.dial.pipex.com/town/drive/kch36/select/s30/ch092.html
+http://soneraplaza.tucows.com/winme/adnload/137026_28536.html
+http://www.egroups.com/post/realtyindia
+http://www.kita.or.kr/untpdc/incubator/zwe/tphar/ZIMB0037.htm
+http://citeseer.nj.nec.com/nrelated/126165/187254
+http://citeseer.nj.nec.com/cachedpage/187254/1
+http://citeseer.nj.nec.com/cidcontext/2417551
+http://yp.gates96.com/13/6/1/36.html
+http://yp.gates96.com/13/6/1/61.html
+http://yp.gates96.com/13/6/1/83.html
+http://yp.gates96.com/13/6/1/91.html
+http://yp.gates96.com/13/6/3/39.html
+http://yp.gates96.com/13/6/3/45.html
+http://yp.gates96.com/13/6/3/65.html
+http://yp.gates96.com/13/6/4/46.html
+http://yp.gates96.com/13/6/4/57.html
+http://yp.gates96.com/13/6/5/44.html
+http://yp.gates96.com/13/6/6/21.html
+http://yp.gates96.com/13/6/6/42.html
+http://yp.gates96.com/13/6/7/0.html
+http://yp.gates96.com/13/6/7/30.html
+http://yp.gates96.com/13/6/7/69.html
+http://yp.gates96.com/13/6/7/82.html
+http://yp.gates96.com/13/6/8/5.html
+http://yp.gates96.com/13/6/8/98.html
+http://yp.gates96.com/13/6/9/45.html
+http://home.wanadoo.nl/hockeyclub.nieuwegein/Teams/Dames/Dames_IV/body_dames_iv.html
+http://pub3.ezboard.com/fthe4thdimensiongeneralinsanity.subscribeUnregisteredToTopic?topicID=38.topic
+http://pub3.ezboard.com/fthe4thdimensiongeneralinsanity.unsubscribeUnregisteredToTopic?topicID=38.topic
+http://moviestore.zap2it.com/help_shipping/s.hXCLyc56
+http://www.geocities.co.jp/Outdoors/2363/typoon1.html
+http://ua.php.net/manual/it/function.pg-numrows.php
+http://kidneyfailure.shn.net/roundtable_reply/727640
+http://itcareers.careercast.com/texis/it/itjs/+HwwBmje0B-deZqwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewyPxGwproqamn5otDnGaoDm15BGowcamn5otDapGdm1qBamnVncdpa5dhBiwGna5BGwBnton5ah1DqBodDanD51GnaMFqnFZI0DzmzwwwpBmje0B-deZqwww5rmeZpwwwBrmeZpwww/morelike.html
+http://itcareers.careercast.com/texis/it/itjs/+lwwBmex6D86egqwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewyPxGwproqamn5otDnGaoDm15BGowcamn5otDapGdm1qBamnVncdpa5dhBiwGna5BGwBnton5ah1DqBodDanD51GnaMFqnFZI0DzmzwwwpBmje0B-deZqwww5rmeacwwwBrmeZpwww/morelike.html
+http://pub23.ezboard.com/fhardoverclockfrm1.showAddReplyScreenFromWeb?topicID=43.topic&index=3
+http://www.adquest3d.com/content.cfm?BRD=1578&PAG=63
+http://pelit.saunalahti.fi/.1/tucows/adnload/51_28438.html
+http://pelit.saunalahti.fi/.1/tucows/preview/70307.html
+http://www.maillist.com.tw/maillist/publicboard_newform.pl?maillist_id=softuse
+http://dennou-t.ms.u-tokyo.ac.jp/arch/cc-env/Linux/debian-jp/dists/woody/non-free-jp/binary-alpha/news/?M=A
+http://ustlib.ust.hk/search*chi/amarcot+bruce+g/amarcot+bruce+g/-5,-1,0,B/frameset&F=amarcotty+michael+1931&1,1
+http://wine.cc.chuo-u.ac.jp/home/pub/TeX/CTAN/support/rtf2tex/?M=A
+http://netchief.tucows.com/winme/preview/75911.html
+http://yp.gates96.com/4/57/60/83.html
+http://yp.gates96.com/4/57/60/99.html
+http://yp.gates96.com/4/57/62/17.html
+http://yp.gates96.com/4/57/62/88.html
+http://yp.gates96.com/4/57/63/9.html
+http://yp.gates96.com/4/57/63/39.html
+http://yp.gates96.com/4/57/63/64.html
+http://yp.gates96.com/4/57/64/33.html
+http://yp.gates96.com/4/57/65/41.html
+http://yp.gates96.com/4/57/65/70.html
+http://yp.gates96.com/4/57/66/18.html
+http://yp.gates96.com/4/57/66/56.html
+http://yp.gates96.com/4/57/66/61.html
+http://yp.gates96.com/4/57/66/94.html
+http://yp.gates96.com/4/57/67/0.html
+http://yp.gates96.com/4/57/67/63.html
+http://yp.gates96.com/4/57/67/85.html
+http://yp.gates96.com/4/57/69/1.html
+http://yp.gates96.com/4/57/69/56.html
+http://citeseer.nj.nec.com/cs?q=dbnum%3D1,DID%3D9262,qtype%3Dsamesite:
+http://citeseer.nj.nec.com/cidcontext/163444
+http://www.amazon.com.au/exec/obidos/change-style/tg/stores/detail/-/books/0873995562/e-mail-friend/
+http://www.sdinfonet.com.cn/411/24/411249999.htm
+http://pub14.ezboard.com/fallpodsgotoroswellsayhello.threadControl?topicID=17.topic
+http://in.egroups.com/message/sexualidades-noticias/14
+http://in.egroups.com/message/sexualidades-noticias/37
+http://library.cuhk.edu.hk/search*chi/dChinese+literature+--+20th+century+--+Periodicals/dchinese+literature+++20th+century+periodicals/-5,-1,0,B/frameset&F=dchinese+literature+++20th+century+periodicals&26,,188
+http://www.3w-zeitschriften.de/EyreLinda/EyreLinda1582380570.htm
+http://cometweb01.comet.co.uk/do!session=132027&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkjHfZoLlplLcqkKZljLlfb5lal5tkiLlXaLl0
+http://retailer.gocollect.com/do/session/1912774/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/contact.asp
+http://providenet.games.tucows.com/adnload/71993_40744.html
+http://www.geocities.co.jp/playtown-Toys/6366/bbsp.html
+http://www.hnby.com.cn/docroot/jzrb/200001/19/km01/19031711.htm
+http://213.36.119.69/do/session/152997/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/IT_IT/
+http://www.jamba.de/KNet/_KNet-p7t8j1-FEd-139gj/showInfo-datenschutz.de/node.0/cde7f1uou
+http://www.jamba.de/KNet/_KNet-p7t8j1-FEd-139gn/browse.de/node.0/cdzqggtyb
+http://www.paidmania.com/getpaid/signup/42/2518
+http://www.pressa.spb.ru/newspapers/nevrem/arts/nevrem-1679-art-13.html
+http://jproxy.uol.es/jproxy/http://jama.ama-assn.org/issues/current/related/joc00479.html
+http://www.mirror.kiev.ua:8082/paper/2000/11/1251/text/11-08-2.htm
+http://my.netian.com/~eco71/wzmain.html
+http://www.craft-supplies.co.uk/cgi-bin/psProdDet.cgi/HT206|972959540|Deluxe_Dividers|user|0|0,0,1,1
+http://www.trax.nilex.co.uk/trax.cgi/A1S/1AR/A3R/B3D/A4R/A4S/
+http://www.linux.com/networking/network/network/development/project/growth/
+http://www.linux.com/networking/network/development/project/growth/sales/
+http://www.icopyright.com/1.1653.134616
+http://retailer.gocollect.com/do/session/1912718/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/about.asp
+http://www.dw-tv.de/indonesia/sari_pers/19793.html
+http://freethemes.netc.pt/skins/icq/preview/44470.html
+http://freethemes.netc.pt/skins/icq/adnload/26145.html
+http://freethemes.netc.pt/skins/icq/preview/52524.html
+http://freethemes.netc.pt/skins/icq/adnload/52040.html
+http://students.lsu.edu/students/main.nsf/c81d2bf8cb0b80ff862566fb00105ab2/7f3436ae9cb1268886256773006f9288!OpenDocument&ExpandSection=7,18,9,16
+http://golfonline.comfluent.net/cgi.pan$player&pga93&John_Morse&pga?golfstats
+http://wai.camera.it/_presidenti/003.htm
+http://www.pcmagazine.de/produkte/artikel/komp/200003/mainboards01_00-wc.html
+http://www.pcmagazine.de/produkte/artikel/komp/199908/asus_00-wc.html
+http://se.sslug.dk/emailarkiv/locale/2000_09/msg00053.html
+http://se.sslug.dk/emailarkiv/locale/2000_09/msg00057.html
+http://se.sslug.dk/emailarkiv/locale/2000_09/msg00115.html
+http://www.brio.de/BRIO.catalog/39fe2f7406fad828273fd472aa7806ff/UserTemplate/8
+http://link.fastpartner.com/do/session/600389/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/jobpilot.php
+http://www.shopworks.com/grizzlygulch/index.cfm/action/search/userid/000B40E3-1177-19FE-A703010D0A0A8CF2
+http://www.shopworks.com/grizzlygulch/index.cfm/action/product/prodid/0001AF94-3FC3-19E7-A703010D0A0A8CF2/userid/000B40E3-1177-19FE-A703010D0A0A8CF2
+http://spiritwolf52.subportal.com/sn/Web_Authoring/Misc__Programming_Tools/2670.html
+http://www.chaos.dk/sexriddle/o/g/j/h/t/
+http://link.fastpartner.com/do/session/600394/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/learn/
+http://opac.lib.rpi.edu/search/dpolitical+corruption+united+states/-5,-1,0,B/frameset&dpolitical+corruption+united+states&7,,22
+http://cnnsi.com/baseball/mlb/news/2000/01/28/
+http://amrr.com/agents/contact.html?Agents_id=3707
+http://www.dulux.co.uk/UKRETAIL:1489107816:DFinity.1QJiP4jMomdkbEc
+http://www.geocities.com/SiliconValley/Screen/9059/
+http://www.nrk.no/finnmark/x17_4_96/nyh4.htm
+http://in.egroups.com/message/islaam/288
+http://www.incestpornstories.com/knocked-upepisiotomy/fertileoff-the-rag/one-night-standlubrication/japaneseslanted-eyes/{storieslink}
+http://kuyper.calvin.edu/fathers2/ANF-04/anf04-30.htm
+http://wuarchive.wustl.edu/systems/unix/NetBSD/NetBSD-release/src/sys/arch/sun3/stand/bootxx/
+http://polygraph.ircache.net:8181/services/define/noframes/http_-2www.microsoft.com/ie/download/http_-2www.microsoft.com/infoserv/about.html
+http://pub23.ezboard.com/fferion80369frm4.showMessage?topicID=192.topic
+http://pub23.ezboard.com/fferion80369frm4.showMessage?topicID=182.topic
+http://www.cs.ruu.nl/mirror/CPAN/authors/id/N/NO/?S=A
+http://yp.gates96.com/1/40/30/16.html
+http://yp.gates96.com/1/40/30/72.html
+http://yp.gates96.com/1/40/30/99.html
+http://yp.gates96.com/1/40/31/25.html
+http://yp.gates96.com/1/40/31/42.html
+http://yp.gates96.com/1/40/31/54.html
+http://yp.gates96.com/1/40/31/61.html
+http://yp.gates96.com/1/40/31/95.html
+http://yp.gates96.com/1/40/32/39.html
+http://yp.gates96.com/1/40/32/88.html
+http://yp.gates96.com/1/40/32/92.html
+http://yp.gates96.com/1/40/33/33.html
+http://yp.gates96.com/1/40/34/24.html
+http://yp.gates96.com/1/40/34/51.html
+http://yp.gates96.com/1/40/34/62.html
+http://yp.gates96.com/1/40/34/72.html
+http://yp.gates96.com/1/40/35/38.html
+http://yp.gates96.com/1/40/36/80.html
+http://yp.gates96.com/1/40/36/98.html
+http://yp.gates96.com/1/40/37/35.html
+http://yp.gates96.com/1/40/37/89.html
+http://yp.gates96.com/1/40/38/13.html
+http://yp.gates96.com/1/40/38/67.html
+http://yp.gates96.com/1/40/39/8.html
+http://yp.gates96.com/1/40/39/11.html
+http://yp.gates96.com/1/40/39/42.html
+http://netway.pda.tucows.com/palm/preview/33466.html
+http://netway.pda.tucows.com/palm/preview/70276.html
+http://netway.pda.tucows.com/palm/adnload/76963_22012.html
+http://netway.pda.tucows.com/palm/preview/33676.html
+http://www.private-immobilien-boerse.de/berlin-immobilien/verkauf/Private-IB/Startseite/Gemeinsam/versicherungen/gebaeude/Gemeinsam/Immolink/Gemeinsam/Super-Zins-Konditionen/anforderungsformular.htm
+http://www.ne.jp/asahi/matinami/gallery/mati/hokkaido/hakodate/ph_l011.html
+http://www.findarticles.com/cf_0/m0EKF/14_46/61415465/p1/article.jhtml
+http://www.trax.nilex.co.uk/trax.cgi/A1C/A2S/B1S/B1L/B4S/A1S/
+http://students.lsu.edu/students/main.nsf/c81d2bf8cb0b80ff862566fb00105ab2/7f3436ae9cb1268886256773006f9288!OpenDocument&ExpandSection=1,21,16,5
+http://students.lsu.edu/students/main.nsf/c81d2bf8cb0b80ff862566fb00105ab2/7f3436ae9cb1268886256773006f9288!OpenDocument&ExpandSection=18,21,16,5
+http://ddb.libnet.kulib.kyoto-u.ac.jp/exhibit/fl3/image/fl3lhf/fl3lh0344.html
+http://www.trnonline.com/archives/2000archives/04072000/sports/26732.shtml
+http://www.linux.com/networking/network/new/press_release/management/editor/
+http://www.linux.com/networking/network/new/press_release/management/experiences/
+http://jundavid.subportal.com/sn/Business/Misc__Phone_Tools/index3.html
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=27,9,23,14,19
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/music/misc/thoughts/lit/music/midi/mirroring.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/music/misc/thoughts/lit/music/midi/legendes/
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/music/misc/thoughts/lit/music/midi/lit/laurent.txt
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/music/misc/thoughts/lit/music/midi/misc/colorart/
+http://www.lz.gs.cninfo.net/news/shenghuo/messages/361.html
+http://www.egroups.com/messages/skarmflyg/683
+http://www.egroups.com/message/skarmflyg/675
+http://www.egroups.com/message/skarmflyg/681
+http://www.genoma.de/shop/0d79e8c12cc42ea8242eafc8a0c5586a/99/b
+http://travelocity-dest.excite.com/Vacations/Reviews/Cruise/Submit/1,2586,0_228__,00.html
+http://www02.geocities.co.jp/HeartLand-Sakura/1068/history.html
+http://www.streetprices.com/Electronics/Computer_Software_PC/Programming/MAKE+DIGITAL/sortproductbyhighprice/SP275945.html
+http://www.streetprices.com/Electronics/Computer_Software_PC/Programming/MAKE+DIGITAL/sortproductbyhighprice/SP246217.html
+http://www.emerchandise.com/help_privacy/b.TV%20SATNIGHTLIVE/s.BOkfj8Vk
+http://ftp.ccu.edu.tw/pub/documents/faq/mail/setup/?S=A
+http://iceberg.adhomeworld.com/cgi-win/redirect.exe/304063772
+http://pdacentral.zeelandnet.nl/rim/email_license.htm
+http://pdacentral.zeelandnet.nl/rim/adnload/139471_47673.html
+http://www.loisirs.ch/tfhglx/17/ltxeld.html
+http://au.yahoo.com/Business_and_Economy/Shopping_and_Services/Health/Providers/By_Region/U_S__States/Mississippi/Cities/
+http://sound-dist.secured.co.uk/cgi-bin/psProdDet.cgi/15P02A|972959527|Helmet|user|0|1,0,0,0
+http://news.dreamwiz.com/news_lg/04/20001030/yonhap/200010301014041007292.html
+http://news.dreamwiz.com/news_lg/04/20001028/yonhap/
+http://pds.nchu.edu.tw/cpatch/ftp/ftpnav/?D=A
+http://members.tripod.lycos.co.kr/BONGBAE/?N=D
+http://www9.hmv.co.uk:5555/do/session/1347758/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d50_sd0_pt0.html
+http://itcareers.careercast.com/texis/it/itjs/+xwwBmeHWD86YwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewDhmoBGnaqdGpdGwBodDarGo5awDwcO5Baiw5roDtBdDaGn31n5BaGn31oGnmamnVncdpar1MwDaGn5d1Gqn5aMFqhTfR20DzmehrwwwpBmefWD86mwww5rmeddwwwBrmeZpwww/morelike.html
+http://www.3w-buecher.de/GibbonsRob/GibbonsRob1572152214.htm
+http://sennka.hoops.livedoor.com/%91%90%8a%a0%93%fa%98a%81%f4.htm
+http://www.uni-duesseldorf.de/ftp/ftp/pf/s/netscape-v451/?S=A
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/0nhIQeA1Kelaujy0pUaBOo2AAoNruJ7MPpvxwl5qu-YeCeEn6SDc5vURHb5rk8dZP84c_4bSWkIDaPe8dCV5mfxj4LA69UDbXc_J2Z-eZg7dURZLZinceqCXYFUYC4pqT29R1BQKpdPvHP0APgIYRhQG
+http://208.178.109.85/msgshow.cfm/msgboard=4779506785434&msg=80064825094809&page=1&idDispSub=-1
+http://interbox.tucows.com/preview/61367.html
+http://www.crutchfield.com/cgi-bin/S-CI62JsDkHYX/viewcart.asp
+http://www.hig.se/(aconf,formoutput,if,modified,set_cookie)/~jackson/roxen/
+http://www.trax.nilex.co.uk/trax.cgi/A1C/1AS/B1D/A3L/A1S/1AR/
+http://www.trax.nilex.co.uk/trax.cgi/A1C/1AS/B1D/A3L/A1S/C1R/
+http://www.trax.nilex.co.uk/trax.cgi/A1C/1AS/B1D/A3L/A1S/B4L/
+http://www.haikou.hi.cn/pandect/nj/n96ei3.htm
+http://se.egroups.com/message/dailydreamers/36
+http://sunsite.org.uk/Mirrors/ftp.cdrom.com/pub/linux/slackware/contrib/contrib-sources/gcc-2.7.2.3/
+http://hp-partner.whowhere.lycos.com/hp/excite/Online_Communities/Angelfire/wi/index9.html
+http://www.cse.unsw.edu.au/archives/linux/redhat/beta/?M=A
+http://www.webcrawler.com/entertainment/music/artists_and_genres/folk_and_acoustic/artists_s/simon_and_garfunkel/garfunkel_art/interviews/
+http://www.russ.ru:8081/journal/media/98-05-21/telen0.htm
+http://www.chaos.dk/sexriddle/x/r/k/o/w/
+http://www.jt.com.br/noticias/98/06/22/sd2.htm
+http://retailer.gocollect.com/do/session/1912734/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/gifts/gift_floor.asp
+http://www.ualberta.ca/CNS/RESEARCH/Software/SAS/gis/z0782606.htm
+http://www.sentientnet.com/univercd/cc/td/doc/product/rtrmgmt/bluelist/cwblue21/cwbwsug/features.htm
+http://pub5.ezboard.com/fthekojiroestrogenbrigadeconsolegaming.threadControl?topicID=16.topic
+http://www.zjrs.zei.gov.cn/economy/text/policy/LHB/LHBA0909.TXT
+http://seascape.tucows.com/winnt/adnload/2060_29646.html
+http://seascape.tucows.com/winnt/adnload/2063_29648.html
+http://seascape.tucows.com/winnt/adnload/2066_29651.html
+http://ben.aspads.net/ex/c/641/517693268
+http://yp.gates96.com/7/63/80/20.html
+http://yp.gates96.com/7/63/80/22.html
+http://yp.gates96.com/7/63/80/80.html
+http://yp.gates96.com/7/63/80/87.html
+http://yp.gates96.com/7/63/81/50.html
+http://yp.gates96.com/7/63/81/77.html
+http://yp.gates96.com/7/63/81/79.html
+http://yp.gates96.com/7/63/81/91.html
+http://yp.gates96.com/7/63/82/36.html
+http://yp.gates96.com/7/63/82/73.html
+http://yp.gates96.com/7/63/84/6.html
+http://yp.gates96.com/7/63/84/91.html
+http://yp.gates96.com/7/63/85/30.html
+http://yp.gates96.com/7/63/85/57.html
+http://yp.gates96.com/7/63/85/98.html
+http://yp.gates96.com/7/63/89/13.html
+http://yp.gates96.com/7/63/89/20.html
+http://yp.gates96.com/7/63/89/32.html
+http://yp.gates96.com/7/63/89/65.html
+http://www.rarf.riken.go.jp/archives/tex-archive/macros/latex//contrib/supported/linguex/?M=A
+http://members.tripod.com/shelly34/shellyphotos/page12.html
+http://ftp.nsysu.edu.tw/Unix/Perl/modules/by-category/23_Miscellaneous_Modules/Bundle/PlRPC-0.2003.readme
+http://www.affiliate.hpstore.hp.co.uk/do/session/380827/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/SMARTTIPS/vacationcards.asp
+http://www.marktplatz-hs.de/cgi-bin/ChioEditionShop.s/39fe2ee3005fd9642740d47540f806e1/IconBar
+http://home.sprynet.com/~keithco/london.htm
+http://earth.collectingnation.com/cgi-bin/bn/post.mod/aupn?B=cna&R=48
+http://earth.collectingnation.com/cgi-bin/bn/post.mod/aupn?B=cna&R=38
+http://www.realize.com/am747b81.htm,qt=e784fe2f=2a38a234-e-1adebfb-80000000-0-0-3--
+http://www.opengroup.com/dfbooks/009/0091856140.shtml
+http://www.egroups.org/message/fotografya/216
+http://www.cn.informatik.fh-furtwangen.de/studenten/dv_labor/onlinebuecher/php/function.yaz-errno.html
+http://www.cn.informatik.fh-furtwangen.de/studenten/dv_labor/onlinebuecher/php/function.yaz-hits.html
+http://www.cn.informatik.fh-furtwangen.de/studenten/dv_labor/onlinebuecher/php/function.yaz-wait.html
+http://www.catholicstore.com/search/index.cfm/FuseAction/detailSearch/SKU/17311/category/Bo/subCategory/G/subject/1
+http://www.cc.ntut.edu.tw/~584ce040/anne-1.htm
+http://www.intervoz.com.ar/2000/09/23/sociedad_n11.htm
+http://pub22.ezboard.com/frecipegoldminesharearecipe.showAddReplyScreenFromWeb?topicID=4.topic
+http://opencity.kulichki.ru/moshkow/PROZA/LIPSKEROV/okno.txt
+http://www.tccomputers.com/cgi-bin/bp/1021890426/products/modems/modems.htm
+http://www.tccomputers.com/cgi-bin/bp/1021890426/services/sitemap.htm
+http://library.bangor.ac.uk/search/dCrystallography+--+Periodicals/dcrystallography+periodicals/-5,-1,0,B/frameset&F=dcrystallography+mathematical&8,,9
+http://music.excite.ca/artist/-264813
+http://www.gameboyz.com/g/review_465_p4_n3.html
+http://library.cwu.edu/search/aCarande,+Robert/acarande+robert/-5,-1,0,B/2exact&F=acarande+robert&1,2
+http://www.townstuff.com/search.cfm?directory=1040&town=285
+http://bsd.sinica.edu.tw/cgi-bin/cvsweb.cgi/ports/graphics/png/files/patch-aa?only_with_tag=RELEASE_2_2_7
+http://www.amcity.com/columbus/stories/1997/07/07/focus6.html?t=email_story
+http://retailer.gocollect.com/do/session/1912716/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/checkout/shopping_cart.asp
+http://ds.dial.pipex.com/town/drive/kch36/select/s12/ch034.html
+http://ds.dial.pipex.com/town/drive/kch36/select/s12/ch118.html
+http://www.dbring.de/160/16005-09.html
+http://198.103.152.100/search*frc/lHQ+769+E3614/lhq++769+e3614/7,-1,0,B/frameset&F=lhq++777.4+d47&1,1
+http://yp.gates96.com/7/27/70/14.html
+http://yp.gates96.com/7/27/70/27.html
+http://yp.gates96.com/7/27/70/35.html
+http://yp.gates96.com/7/27/70/37.html
+http://yp.gates96.com/7/27/70/62.html
+http://yp.gates96.com/7/27/71/38.html
+http://yp.gates96.com/7/27/71/80.html
+http://yp.gates96.com/7/27/72/62.html
+http://yp.gates96.com/7/27/72/80.html
+http://yp.gates96.com/7/27/73/10.html
+http://yp.gates96.com/7/27/73/61.html
+http://yp.gates96.com/7/27/73/78.html
+http://yp.gates96.com/7/27/74/7.html
+http://yp.gates96.com/7/27/74/16.html
+http://yp.gates96.com/7/27/75/62.html
+http://yp.gates96.com/7/27/76/90.html
+http://yp.gates96.com/7/27/77/7.html
+http://yp.gates96.com/7/27/77/92.html
+http://yp.gates96.com/7/27/78/21.html
+http://yp.gates96.com/7/27/79/21.html
+http://yp.gates96.com/7/27/79/57.html
+http://yp.gates96.com/7/27/79/96.html
+http://moviestore.zap2it.com/help/b.STARWARSSAGA%20STARWARS-ROJ/s.nrF6V2sr
+http://www2.kbank.no/Web/nlpublish.nsf/Published/ord_og_uttrykk!OpenDocument&ExpandSection=8,27,13,5
+http://newspaper.swww.com.cn/1999/cdwb/199912/26/html/1003.html
+http://newspaper.swww.com.cn/1999/cdwb/199912/26/html/1008.html
+http://iworld.freethemes.com/adnload/77752.html
+http://iworld.freethemes.com/adnload/15251.html
+http://iworld.freethemes.com/adnload/54697.html
+http://iworld.freethemes.com/adnload/15232.html
+http://www.fogdog.com/cedroID/ssd3040183238457/nav/products/ice_hockey/1d/gear_accessories/
+http://www.ftp.uni-erlangen.de/pub/Linux/DEBIAN/dists/Debian2.2r0/main/binary-m68k/doc/
+http://www.ftp.uni-erlangen.de/pub/Linux/DEBIAN/dists/Debian2.2r0/main/binary-m68k/sound/
+http://library.cwu.edu/search/aThimbleby,+Harold/athimbleby+harold/-5,-1,0,B/exact&F=athilde+jean&1,2
+http://www5.pconline.com.cn/pcedu/soft/doc/001024/2.htm
+http://member.nifty.ne.jp/kaito-mist/nifty5.htm
+http://www.cc.yamaguchi-u.ac.jp/~archive/doc/jdk1.2.2/docs/api/java/awt/image/BandedSampleModel.html
+http://www.sandiego.digitalcity.com/honolulu/arts/occurrence.dci?ecid=75
+http://ubahn.exit.de/ffm/pic/pp/?S=A
+http://www.visiobroker.com/opcvm/details/4/43591.html
+http://www.visiobroker.com/opcvm/details/9/9765.html
+http://ring.toyama-ix.net/archives/linux/debian/debian-jp/dists/woody-towns/?M=A
+http://www.asahi-net.or.jp/~ZI3H-KWRZ/lawylegalaid.html
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/195/1999/7/0/
+http://www.buybuddy.com/sleuth/27/1/1060103/490578/
+http://java.javasoft.com/products/jdk/1.2/ja/docs/ja/api/java/awt/image/BandedSampleModel.html
+http://mitglied.tripod.de/~HTTC/mannschaften/3LigaGr1_0001.htm
+http://opac.lib.rpi.edu/search/anightingale+peggy+1942/-5,-1,0,B/browse
+http://ftp.unina.it/pub/Amiga/NetBSD/NetBSD-current/pkgsrc/editors/ssam/files/
+http://kikakusvr3.city.yokohama.jp/y/j/e25/ktt/ktt.html
+http://members.spree.com/entertainment/juskickit/http//members.spree.com/sports/comicus1
+http://www.butuanon.tsx.org/
+http://archive.soccerage.com/s/de/07/05375.html
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/151/1995/10/0/859255/
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/151/1995/10/50
+http://polygraph.ircache.net:8181/http_-2www.soniajekums.com/docs/Http_-2ua.battle-zone.com/html/html/on_line.html
+http://www.affiliate.hpstore.hp.co.uk/do/session/380855/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-creativeworld.com/creativeworld.asp?lang=f
+http://mirror.cc.utsunomiya-u.ac.jp/mirror/CPAN/authors/id/T/TO/TOSTI/vstadaf-0.01.readme
+http://www.xmission.com/~dkenison/cgi/lwgate.cgi/KLR650/archives/v02.n1633/Subject/article-16.html
+http://www.realize.com/p25581.htm,qt=e784fe2f=2a38a234-7-da710e-0-0-0-1--
+http://www.realize.com/am947681.htm,qt=e784fe2f=2a38a234-7-da6e1d-80000000-0-0-3--
+http://www.realize.com/am2c3a81.htm,qt=e784fe2f=2a38a234-7-da6e1d-80000000-0-0-3--
+http://www.realize.com/amd15381.htm,qt=e784fe2f=2a38a234-7-da6e1d-1-84-0-3--
+http://link.fastpartner.com/do/session/600403/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/speednames.php
+http://home.freeuk.net/lyne/work.htm
+http://www.gotocity.com/local/2/us/AZ/p/85643/people/
+http://www.service911.com/egghead/step/0,2743,6+33+121+25440+18092_4,00.html
+http://www.jamba.de/KNet/_KNet-irv8j1-WEd-139z7/showInfo-werbung.de/node.0/cenv0b09a
+http://ustlib.ust.hk/search*chi/dbeijing+mandarin+dialects+china+slang/dbeijing+mandarin+dialects+china+slang/-5,1,1,B/frameset&F=dbeijing+mayors+china+fiction&1,1,
+http://www.linux.org.tw/~chester/xlib/GC/convenience-functions/XSetGraphicsExposures.html
+http://www.linux.org.tw/~chester/xlib/graphics/font-metrics/XUnloadFont.html
+http://www.chaos.dk/sexriddle/c/f/j/u/c/
+http://www.chaos.dk/sexriddle/c/f/j/u/q/
+http://www.bornloser.com/comics/committed/archive/committed-20001027.html
+http://tulips.ntu.edu.tw/search*chi/dDeath+lc/ddeath+lc/-17,-1,0,E/frameset&F=ddeath+in+adolescence+abstracts&1,,0
+http://hem.fyristorg.com/lottaleman/LLfar/1_6955.htm
+http://preview.egroups.com/post/scoresheet-talk?act=reply&messageNum=7013
+http://209.52.189.2/profile.cfm/TimmyJ
+http://archive.soccerage.com/s/pt/37/04816.html
+http://pub16.ezboard.com/fleftbehindmessageboardfellowshiphall.showMessage?topicID=456.topic&index=16
+http://www.2pl.com/asp/tools/fili1.asp?sp=se&fi=pppp0005s8
+http://link.fastpartner.com/do/session/600382/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/company/jobs.htm
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/kdenetwork/kppp/Rules/Poland/?only_with_tag=MAIN
+http://genforum.genealogy.com/cgi-genforum/forums/flippin.cgi?30
+http://pub.chinaccm.com/23/news/200010/28/114339.asp
+http://pub.chinaccm.com/23/news/200010/27/134259.asp
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=21,9,14,35,15
+http://gamesearcher.com/games/pc/returnofphantom-cheatsfaqs.html
+http://ua.php.net/manual/es/function.pg-errormessage.php
+http://findmail.com/group/prairydog
+http://www.loria.fr/projets/dilib/DILIB_ROOT/SYSTEMS/Linux/Dilib/Data/NLM/MedLine/
+http://www.daysinn.com/ctg/cgi-bin/DaysInn/programs/AAAksrACwAAACEaAAQ
+http://www.leo.org/leoclick/35dd60550f1ba90ed5bb7952eebae0d3+L+1__
+http://members.fortunecity.com/abbalink/songs/lyrics/wg.htm
+http://chat.sportsline.com/u/football/nfl/xword/answers/091500.htm
+http://210.173.172.13/entertainments/sports/sydney/kanrenkiji/0924/0925m096-500.html
+http://210.173.172.13/entertainments/sports/sydney/kanrenkiji/0924/0925m094-500.html
+http://www.private-immobilien-boerse.de/nordrhein-Westfalen/Muehlheim-ruhr/Verkauf/3d-service/Gemeinsam/Inserieren/3d-service/Gemeinsam/versicherungen/gebaeude/deckungsumfang.htm
+http://www.private-immobilien-boerse.de/nordrhein-Westfalen/Muehlheim-ruhr/Verkauf/3d-service/Gemeinsam/Inserieren/3d-service/Gemeinsam/IIMMitglieder.htm
+http://www.realize.com/amcf7781.htm,qt=e784fe2f=2a38a234-4-7cf2ef-80000000-0-0-3--
+http://family.go.com/Categories/Features/family_1998_12/penn/penn128urban/
+http://www.loria.fr/projets/dilib/DILIB_ROOT/ApplicationsTest/Dilib/newBD/Prog/?N=D
+http://www.loisirs.ch/xfeoav/7/kqbmsh.html
+http://tucows.tu-graz.ac.at/herdwin0807.html
+http://www-d0.fnal.gov/cgi-bin/cvsweb.cgi/gtr_htf/dat/?sortby=log
+http://www.buybuddy.com/sleuth/17/1/2006/32619/
+http://www.aelita.net/products/Reg/QuoteRegister/products/library/products/company/Privacy.htm
+http://www.refdag.nl/bui/990803bui08.html
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=3,0+9,6-14,0+0,2
+http://www.aelita.net/products/services/support/sitemap/news/solutions/default.htm
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=26,5,30,16,12
+http://www.ericsson.cl/gsmpro/contact.shtml
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/maheuitu/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/mangoo333/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/maomizhijia/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/masaki_hamada/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/maxiaofei/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/maz0503/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/menghuanboy/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/michealshen/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/mike717/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/mikeshang_2/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/mingyueyaze/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/mm3/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/mnbv89/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/morsia/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/move/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/mslug/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/msshi/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/muwei/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/my1799/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/mychat2000/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/myesky/
+http://members.tripodasia.com.cn/maolin_photo/maolin_suzuki/maolin_suzuki/mzlzq/
+http://www.ring.gr.jp/pub/linux/Vine/VineSeed/alpha/mnt/source/sbin/loader
+http://www.nrk.no/finnmark/x8_5_96/nyh7.htm
+http://202.99.23.245/rmrb/200001/27/no_txb_6.html
+http://www-d0.fnal.gov/d0dist/dist/releases/test/smt_hit/test/?N=D
+http://www-d0.fnal.gov/d0dist/dist/releases/test/smt_hit/test/LIBRARIES
+http://jupiter.u-3mrs.fr/~msc41www/releves/13440405.HTM
+http://ftp.univie.ac.at/packages/perl/modules/by-category/15_World_Wide_Web_HTML_HTTP_CGI/CGI/ANDK/Apache-correct_headers.readme.html
+http://www.linux.com/networking/network/networking/free/windows_nt/distro/
+http://www.linux.com/networking/network/networking/free/windows_nt/tip/
+http://australia-holiday-guide.com/Englisch/Queensland_1/QLD_Furher_North_1/qld_further_north_1.html
+http://australia-holiday-guide.com/Englisch/Queensland_1/QLD_Great_Barrier_Reef_1/qld_great_barrier_reef_1.html
+http://ftp.uni-paderborn.de/aminet/aminet/demo/aga/Ayrton.readme
+http://ftp.uni-paderborn.de/aminet/aminet/demo/aga/Deadline_1.readme
+http://ftp.uni-paderborn.de/aminet/aminet/demo/aga/DiamondPPC.readme
+http://ftp.uni-paderborn.de/aminet/aminet/demo/aga/Gravity2_inv.readme
+http://ftp.uni-paderborn.de/aminet/aminet/demo/aga/HJB-BCFix.readme
+http://ftp.uni-paderborn.de/aminet/aminet/demo/aga/ImpPos.readme
+http://ftp.uni-paderborn.de/aminet/aminet/demo/aga/Nat-AutF.readme
+http://ftp.uni-paderborn.de/aminet/aminet/demo/aga/PSB-Desperado2.readme
+http://ftp.uni-paderborn.de/aminet/aminet/demo/aga/PSB-PUK_final.readme
+http://genforum.genealogy.com/cgi-genforum/forums/kilroy.cgi?34
+http://genforum.genealogy.com/cgi-bin/print.cgi?kilroy::34.html
+http://content.health.msn.com/ef/message/803324/content.health.msn.com%2fmessage_board_message%2f803324/803324
+http://de.excite.de/gesundheit/katalog/6107
+http://de.excite.de/gesundheit/katalog/4909
+http://de.excite.de/gesundheit/katalog/5941
+http://de.excite.de/gesundheit/katalog/4924
+http://de.excite.de/gesundheit/katalog/5898
+http://de.excite.de/gesundheit/katalog/4949
+http://de.excite.de/gesundheit/katalog/5987
+http://de.excite.de/gesundheit/katalog/5855
+http://de.excite.de/gesundheit/katalog/39862
+http://de.excite.de/gesundheit/katalog/5852
+http://de.excite.de/gesundheit/katalog/5645
+http://de.excite.de/gesundheit/katalog/6078
+http://de.excite.de/gesundheit/katalog/5834
+http://yp.gates96.com/11/26/80/31.html
+http://yp.gates96.com/11/26/80/47.html
+http://yp.gates96.com/11/26/80/91.html
+http://yp.gates96.com/11/26/81/61.html
+http://yp.gates96.com/11/26/81/86.html
+http://yp.gates96.com/11/26/82/37.html
+http://yp.gates96.com/11/26/82/49.html
+http://yp.gates96.com/11/26/83/38.html
+http://yp.gates96.com/11/26/83/52.html
+http://yp.gates96.com/11/26/83/58.html
+http://yp.gates96.com/11/26/83/84.html
+http://yp.gates96.com/11/26/84/0.html
+http://yp.gates96.com/11/26/84/59.html
+http://yp.gates96.com/11/26/84/75.html
+http://yp.gates96.com/11/26/84/99.html
+http://yp.gates96.com/11/26/85/37.html
+http://yp.gates96.com/11/26/85/63.html
+http://yp.gates96.com/11/26/85/78.html
+http://yp.gates96.com/11/26/86/36.html
+http://yp.gates96.com/11/26/86/40.html
+http://yp.gates96.com/11/26/87/66.html
+http://yp.gates96.com/11/26/87/87.html
+http://yp.gates96.com/11/26/89/7.html
+http://yp.gates96.com/11/26/89/21.html
+http://yp.gates96.com/11/26/89/38.html
+http://providenet.tukids.tucows.com/mac/9-12/macspell912_license.html
+http://providenet.tukids.tucows.com/mac/9-12/adnload/25805_25780.html
+http://www04.u-page.so-net.ne.jp/zb3/eiji-m/dog6.htm
+http://school.educities.org/card/jou0731.html
+http://school.educities.org/card/ke234.html
+http://school.educities.org/card/aaaaaqqqqqqq.html
+http://school.educities.org/card/cso.html
+http://school.educities.org/card/g40203.html
+http://school.educities.org/card/h123915388.html
+http://school.educities.org/card/k1084211.html
+http://www.cigar-pipe.de/SP/dhuc3112.htm
+http://www.newquestcity.com/cities/MA///news/3675.htm
+http://caowei_814.home.chinaren.com//wenxue/wenxue-mood/love147.htm
+http://www.amulation.com/md-l-archive/199805/msg00065.html
+http://in.egroups.com/messages/conventions/51?viscount=-30
+http://yp.gates96.com/11/63/20/4.html
+http://yp.gates96.com/11/63/20/21.html
+http://yp.gates96.com/11/63/20/51.html
+http://yp.gates96.com/11/63/21/29.html
+http://yp.gates96.com/11/63/21/41.html
+http://yp.gates96.com/11/63/21/74.html
+http://yp.gates96.com/11/63/22/4.html
+http://yp.gates96.com/11/63/22/29.html
+http://yp.gates96.com/11/63/22/80.html
+http://yp.gates96.com/11/63/22/86.html
+http://yp.gates96.com/11/63/23/7.html
+http://yp.gates96.com/11/63/23/24.html
+http://yp.gates96.com/11/63/23/39.html
+http://yp.gates96.com/11/63/24/1.html
+http://yp.gates96.com/11/63/25/35.html
+http://yp.gates96.com/11/63/25/78.html
+http://yp.gates96.com/11/63/25/83.html
+http://yp.gates96.com/11/63/26/37.html
+http://yp.gates96.com/11/63/27/3.html
+http://yp.gates96.com/11/63/27/9.html
+http://yp.gates96.com/11/63/27/14.html
+http://yp.gates96.com/11/63/28/16.html
+http://yp.gates96.com/11/63/28/26.html
+http://yp.gates96.com/11/63/28/54.html
+http://yp.gates96.com/11/63/28/55.html
+http://yp.gates96.com/11/63/29/13.html
+http://yp.gates96.com/11/63/29/64.html
+http://yp.gates96.com/11/63/29/69.html
+http://spaceports.tucows.com/winnt/httpservernt_license.html
+http://www.affiliate.hpstore.hp.co.uk/do/session/380848/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/FR/REGISTRATION/entry.asp
+http://incrediblegolfsavings.subportal.com/sn/Games/Simulation_Games/11310.html
+http://incrediblegolfsavings.subportal.com/sn/Games/Simulation_Games/12064.html
+http://www.linux.com/networking/linux/industry/gnu/operating_system/Corel/
+http://www.linux.com/networking/linux/industry/gnu/operating_system/Updates/
+http://www.fogdog.com/cedroID/ssd3040183307418/womens/
+http://www.fogdog.com/cedroID/ssd3040183307418/nav/products/featured_brands/1o/casual_sunglasses/
+http://www.fogdog.com/cedroID/ssd3040183307418/nav/products/featured_brands/1o/hockey_skates/
+http://www.fogdog.com/cedroID/ssd3040183307418/nav/products/featured_brands/1o/sweatshirts_fleece/
+http://www.fogdog.com/cedroID/ssd3040183307418/crs/nvCZ/wld/fogdog_sports/nike/football/equipment/500r_series_football.html
+http://www.seoul.co.kr/dmaeil/199908/0820j015.htm
+http://www-trn.bards.ru/Lobanovskiy/part13.htm
+http://www-trn.bards.ru/Vahnuk/part27.htm
+http://www-trn.bards.ru/Vetrova_Svetlana/part9.htm
+http://www-trn.bards.ru/Tretiyakov/part22.htm
+http://www-trn.bards.ru/Okoudjava/part202.htm
+http://www-trn.bards.ru/Panyushkin/part100.htm
+http://www-trn.bards.ru/Gorodnicky/part287.htm
+http://yumemi.ne.jp/bbs/ky/view/f/forum9/1_jpbshj_vvvzil.html
+http://yumemi.ne.jp/bbs/ky/view/f/forum9/1_xxosis_czhmrb.html
+http://yumemi.ne.jp/bbs/ky/view/f/forum9/1_yikriy_qjvins.html
+http://www.peopledaily.co.jp/shch/199907/28/newfiles/D103.html
+http://legalminds.lp.findlaw.com/list/newlawbooks-l/frm00336.html
+http://tucows.sp-plus.nl/winme/phoneme.html
+http://ustlib.ust.hk/search*chi/dalcoholic+beverages+china/dalcoholic+beverages+china/7,-1,0,E/2browse
+http://ustlib.ust.hk/search*chi/dalcoholic+beverages+china/dalcoholic+beverages+china/-5,-1,0,E/frameset&F=dalcoholic+beverages+great+britain&1,,0
+http://www.canit.se/(k10,k13,k16,k6)/support/faq/faq.html
+http://aecjobbank.com/texis/script/jobbank/+Owwrmwxeri2wBV6evNVpwwwF6eWYqkwwwn6eXmcOwwwn6ekmyjwwwn6eULpOwwqn6eUCBZwwwn6e22QuwwwefPY9GepmwwmeiP46eczdwwmeOTB6eXhzwwwnmBVve89AHwwxeY44Ie-pxwww+vejWRhwwxealYTeXjzwwwhvep9q9wwwxveoA6kwwqe0PYieqFzwwwv6eFRFrwwwt6eSGxDwwwetNY1e8drwwqeT53Amwww0h7mwww1tzmwwweb-3qmwwww/jobdirectory.html
+http://www9.hmv.co.uk:5555/do/session/1347780/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/newmenu.html
+http://www9.hmv.co.uk:5555/do/session/1347780/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d30_sd0_pt0.html
+http://www9.hmv.co.uk:5555/do/session/1347780/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d70_sd0_pt0.html
+http://www9.hmv.co.uk:5555/do/session/1347780/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d90_sd0_pt0.html
+http://www9.hmv.co.uk:5555/do/session/1347780/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d120_sd0_pt0.html
+http://www.hbdaily.com.cn/hbrb/20000622/BIG5/hbrb^18323^12^0622h016.htm
+http://excite.de/immobilien/katalog/6877
+http://excite.de/immobilien/katalog/7012
+http://www.globalmart.com/housewares/appliances/household/irons/blackanddecker/S680.htm
+http://mediate.magicbutton.net/do/session/625631/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-artc.html
+http://ddb.libnet.kulib.kyoto-u.ac.jp/exhibit/mt3/image/mt3shf/mt3sh0192.html
+http://us.parsimony.net/forum26166/messages/410.htm
+http://linux.tnc.edu.tw/CPAN/authors/id/A/AZ/AZEMGI/?M=A
+http://linux.tnc.edu.tw/CPAN/authors/id/A/AZ/AZEMGI/CHECKSUMS
+http://launchbase.com/Shopping/Visual_Arts/communication/entertainment/Pictures_&_Images.htm
+http://launchbase.com/Shopping/Visual_Arts/communication/shopping/Gifts.htm
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/programs/simple/music/midi/lit/lit/quizz/quizz1.html
+http://home02.wxs.nl/~nash0002/amber-94.htm
+http://www.redrocksports.com/sports/webSession/shopper/RR972959711-31098/store/dept-5/department/dept-5/item/52400
+http://www.redrocksports.com/sports/webSession/shopper/RR972959711-31098/store/dept-5/department/dept-5/item/52550
+http://www.redrocksports.com/sports/webSession/shopper/RR972959711-31098/store/dept-5/department/dept-5/item/50900
+http://gnu.archive.sunet.se/software/sather/ICSI_Sather/Documentation/Compiler/CompilerBrowser/shortflat-FLIST{_}.html
+http://mailman.real-time.com/rte-crossfire/1992/Dec/mail1.html
+http://de.nedstat.net/viewstat.asp?name=larsen
+http://ftp.ring.gr.jp/archives/pc/gnu-win32/latest/man/?S=A
+http://src.openresources.com/debian/src/graphics/HTML/D/S_ISSOCK.html
+http://www.perotech.ch/d/securedb/html/listtopic.php?4277
+http://web.health.aol.thriveonline.oxygen.com/medical/library/article/003558res.html
+http://cn.egroups.com/message/Website_Warez/346
+http://adex3.flycast.com/server/socket/127.0.0.1:2800/click/OnlineCitiesSM/OnlineCitiesInteractiveCityGuides/bd510213891
+http://ring.nii.ac.jp/pub/pack/x68/personal/calendar/
+http://www.zeal.com/Government/U_S__Government/State___Local_Governments/South_Carolina/Politics/Elections/State_wide/
+http://ftp.unina.it/pub/TeX/macros/latex209/contrib/manual/?S=A
+http://www.perotech.ch/d/securedb/html/listtopic.php?5376
+http://polygraph.ircache.net:8181/lci/https_-2ssl.galaxy-net.net/jazzee/http_-2www.microsoft.com/truetype/fontpack/win.htm
+http://python.konbib.nl/dutchess.ned/83/00/info-1592.html
+http://www.excite.com/lifestyle/cultures_and_groups/world_cultures/regions/north_america/ethnic_communities/african_american/history/military_history/
+http://www.bluemonutain.com/engy/david/CHI1-educk.html
+http://www.bluemonutain.com/engy/susie/CHI1-edaddog.html
+http://cn.egroups.com/messages/childhoodepilepsy/3349
+http://cn.egroups.com/messages/childhoodepilepsy/648
+http://cn.egroups.com/messages/childhoodepilepsy/1189
+http://polygraph.ircache.net:8181/services/design/http_-2www.swnebr.net/~cambridg/http_-2www.bikininet.com/climate.htm
+http://www.annuairefrancais.com/54/France/I/INTERNET/Fournisseurs-d'acces/Fournisseurs-d
+http://polygraph.ircache.net:8181/http_-2www.monarchcom.net/http_-2www.netscape.com/comprod/mirror/http_-2bible.gospelcom.net/http_-2www.rehablinks.com/ptlinks.htm
+http://findmail.com/message/studentdoctor/4312?source=1
+http://mediate.magicbutton.net/do/session/625624/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-cart.html
+http://ring.htcn.ne.jp/archives/lang/perl/CPAN/authors/id/P/PG/?M=A
+http://www.buybuddy.com/sleuth/33/1/10601/526343/
+http://www1.zdnet.com/products/stories/reviews/0,4161,2470142,00.html
+http://www1.zdnet.com/companyfinder/filters/products/0,9996,2256-82,00.html
+http://webcvs.kde.org/cgi-bin/cvsweb.cgi/kdeutils/ark/doc/en/Attic/index-2.html?only_with_tag=MAIN
+http://tv.thevines.com/leaf/AA0000364048/45///&act=24-1-11&bref=1601
+http://link.fastpartner.com/do/session/600384/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/local/redirect.php
+http://www.excite.com/lifestyle/politics_and_society/community_and_cultures/world_cultures/diaspora/jewish/judaism/congregations/humanistic_judaism/
+http://biblio.cesga.es:81/search*gag/aXove,+XosÃ\83Â\83Ã\82©/axove+xose/7,-1,0,B/frameset&F=axuntanza&1,,3
+http://biblio.cesga.es:81/search*gag/aXove,+XosÃ\83Â\83Ã\82©/axove+xose/7,-1,0,B/frameset&F=axuntanza&3,,3
+http://db.zaq.ne.jp/asp/bbs/jttk_baasc506_1/article/36
+http://db.zaq.ne.jp/asp/bbs/jttk_baasc506_1/article/37
+http://db.zaq.ne.jp/asp/bbs/jttk_baasc506_1/article/35
+http://db.zaq.ne.jp/asp/bbs/jttk_baasc506_1/article/21
+http://www.tiroler-adler.com/1Root/Kontinent/6/Staat/7/Bundesland/16/Ort/691/Homepage/f_homepage...1.html
+http://yp.gates96.com/4/52/90/87.html
+http://yp.gates96.com/4/52/90/95.html
+http://yp.gates96.com/4/52/91/4.html
+http://yp.gates96.com/4/52/91/39.html
+http://yp.gates96.com/4/52/91/42.html
+http://yp.gates96.com/4/52/92/33.html
+http://yp.gates96.com/4/52/92/93.html
+http://yp.gates96.com/4/52/93/6.html
+http://yp.gates96.com/4/52/93/98.html
+http://yp.gates96.com/4/52/94/8.html
+http://yp.gates96.com/4/52/94/14.html
+http://yp.gates96.com/4/52/95/92.html
+http://yp.gates96.com/4/52/96/16.html
+http://yp.gates96.com/4/52/96/32.html
+http://yp.gates96.com/4/52/96/72.html
+http://yp.gates96.com/4/52/96/90.html
+http://yp.gates96.com/4/52/97/1.html
+http://yp.gates96.com/4/52/97/53.html
+http://yp.gates96.com/4/52/98/34.html
+http://yp.gates96.com/4/52/98/84.html
+http://yp.gates96.com/4/52/98/97.html
+http://yp.gates96.com/4/52/99/55.html
+http://yp.gates96.com/4/52/99/68.html
+http://yp.gates96.com/14/40/10/3.html
+http://yp.gates96.com/14/40/10/86.html
+http://yp.gates96.com/14/40/11/53.html
+http://yp.gates96.com/14/40/12/74.html
+http://yp.gates96.com/14/40/13/11.html
+http://yp.gates96.com/14/40/13/34.html
+http://yp.gates96.com/14/40/13/45.html
+http://yp.gates96.com/14/40/13/79.html
+http://yp.gates96.com/14/40/14/3.html
+http://yp.gates96.com/14/40/14/6.html
+http://yp.gates96.com/14/40/14/25.html
+http://yp.gates96.com/14/40/14/84.html
+http://yp.gates96.com/14/40/14/88.html
+http://yp.gates96.com/14/40/15/39.html
+http://yp.gates96.com/14/40/15/40.html
+http://yp.gates96.com/14/40/16/64.html
+http://yp.gates96.com/14/40/16/92.html
+http://yp.gates96.com/14/40/17/69.html
+http://yp.gates96.com/14/40/18/42.html
+http://yp.gates96.com/14/40/18/82.html
+http://yp.gates96.com/14/40/19/36.html
+http://www.4positiveimages.com/4positiveimages/727410225/IconBar
+http://www.teacherformation.org/html/od/facilitators.cfm/task1,login/discussion_id,2/xid,6559/yid,6157439
+http://www.secinfo.com/dSU5m.74.htm
+http://www.secinfo.com/dSU5m.7v.htm
+http://www.secinfo.com/dSU5m.6y.htm
+http://www.secinfo.com/dSU5m.5c.htm
+http://linux.softhouse.com.cn/linux/knowledge/tech/qs/linux5.htm
+http://linux.softhouse.com.cn/linux/knowledge/tech/qs/linux10.htm
+http://freesoftware.subportal.com/sn/Programming/Visual_Basic_Components_H-P/993.html
+http://dk.egroups.com/message/NGHILUAN/2881
+http://dk.egroups.com/message/NGHILUAN/2889
+http://www.cga.state.ct.us/ps98/cbs/H/hj-0084.htm
+http://apple.excite.com/entertainment/music/artists_and_genres/jazz/new_world_jazz/afro_cuban/
+http://www.euronet.nl/users/hiroshi/ksweb/interest.htm
+http://library.bangor.ac.uk/search/aMollica,+Anthony/amollica+anthony/-5,-1,0,B/browse
+http://www.fogdog.com/cedroID/ssd3040183308040/nav/products/featured_brands/14t/all/
+http://www.brio.de/BRIO.catalog/39fe2f8d0912d4962740d472aa780701/UserTemplate/9
+http://www.hig.se/(accessed,autoformat,referrer,sqloutput,tablify)/~jackson/roxen/
+http://www.newstimescybermall.com/Mall/Catalog/Product/ASP/product-id/206059/store-id/1000010991.html
+http://www6.163.com/news/p-item/0,1587,economy_1916,00.html
+http://ftp.uni-stuttgart.de/pub/systems/sgi/graphics/lib/?D=A
+http://preview.egroups.com/message/abdou3/152
+http://ch.php.net/manual/it/function.pg-loimport.php
+http://yp.gates96.com/1/94/30/39.html
+http://yp.gates96.com/1/94/30/78.html
+http://yp.gates96.com/1/94/31/11.html
+http://yp.gates96.com/1/94/31/72.html
+http://yp.gates96.com/1/94/31/85.html
+http://yp.gates96.com/1/94/32/25.html
+http://yp.gates96.com/1/94/32/45.html
+http://yp.gates96.com/1/94/32/74.html
+http://yp.gates96.com/1/94/33/20.html
+http://yp.gates96.com/1/94/33/68.html
+http://yp.gates96.com/1/94/34/92.html
+http://yp.gates96.com/1/94/35/1.html
+http://yp.gates96.com/1/94/35/50.html
+http://yp.gates96.com/1/94/35/60.html
+http://yp.gates96.com/1/94/37/0.html
+http://yp.gates96.com/1/94/37/46.html
+http://yp.gates96.com/1/94/37/47.html
+http://yp.gates96.com/1/94/37/61.html
+http://yp.gates96.com/1/94/38/19.html
+http://yp.gates96.com/1/94/39/49.html
+http://yp.gates96.com/1/94/39/57.html
+http://www.gartenfachmarkt.de/beratung_garten/duengen_und_kompostieren/anlage_und_vorarbeiten/fertig.htm
+http://support.dell.com/docs/storage/4955r/en/Hw/setup.htm
+http://www.hig.se/(clientname,header,sort,sqlquery,sqltable)/~jackson/roxen/
+http://www.mic.hr/PGBURZA:423870
+http://www.mic.hr/PGNEWS:423870
+http://members.tripod.com/Tess_Tom/my_photoalbum/page12.html
+http://legalminds.lp.findlaw.com/list/courtinterp-spanish/nav05815.html
+http://www.fogdog.com/cedroID/ssd3040183239698/crs/pn__/wld/fogdog_sports/pearl_izumi/road_cycling/apparel/classic_vest.html
+http://www.fogdog.com/cedroID/ssd3040183239698/nav/stores/wakeboarding/
+http://troy.lib.sfu.ca/search/slogos/slogos/-5,-1,0,E/frameset&F=slogistics+and+transportation+review&1,,0
+http://themes.tucows.dia.dk/skins/icq/preview/54718.html
+http://php.nic.fi/manual/html/function.shm_open.html
+http://ftp.fi.debian.org/debian/dists/woody/non-free/binary-m68k/misc/?S=A
+http://www.csupomona.edu/reference/java/jdk1.2/docs/api/org/omg/CORBA/class-use/CompletionStatus.html
+http://www.trax.nilex.co.uk/trax.cgi/A1C/B1U/A1D/C1R/A1D/B1R/
+http://www.uni-duesseldorf.de/ftp/ftp/software/opt/cpio-2.4.2/?M=A
+http://ep.com/js/about/c9079/b0/250918.html
+http://polygraph.ircache.net:8181/busi/html/http_-2www.dirtsports.com/index.html-ssi
+http://www.chabadlibrary.org/ecatalog/EC06/EC06232.HTM
+http://chat.hani.co.kr/NetBBS/Bbs.dll/brief/lst/qqa/f/qqo/PRMY/zka/B23qB2Bm
+http://209.207.239.212/bkindex/c1047/f1128.html
+http://tv.thevines.com/leaf/AA0000364429/4/1
+http://tv.thevines.com/leaf/AA0000364429/4//&order_by=WORST
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=12,17,20,5,16
+http://yp.gates96.com/4/4/40/22.html
+http://yp.gates96.com/4/4/40/29.html
+http://yp.gates96.com/4/4/41/11.html
+http://yp.gates96.com/4/4/42/0.html
+http://yp.gates96.com/4/4/42/27.html
+http://yp.gates96.com/4/4/42/89.html
+http://yp.gates96.com/4/4/42/99.html
+http://yp.gates96.com/4/4/43/40.html
+http://yp.gates96.com/4/4/43/69.html
+http://yp.gates96.com/4/4/43/85.html
+http://yp.gates96.com/4/4/44/27.html
+http://yp.gates96.com/4/4/44/28.html
+http://yp.gates96.com/4/4/44/36.html
+http://yp.gates96.com/4/4/44/86.html
+http://yp.gates96.com/4/4/45/76.html
+http://yp.gates96.com/4/4/45/82.html
+http://yp.gates96.com/4/4/45/86.html
+http://yp.gates96.com/4/4/46/61.html
+http://yp.gates96.com/4/4/47/1.html
+http://yp.gates96.com/4/4/47/41.html
+http://yp.gates96.com/4/4/47/42.html
+http://yp.gates96.com/4/4/48/66.html
+http://people.freebsd.org/~knu/cgi-bin/cvsweb.cgi/ports/misc/geekcode/pkg-descr?only_with_tag=RELEASE_3_4_0
+http://perso.wanadoo.fr/genealogie.aubert.jm/geweb/ff100.htm
+http://www.securitiestimes.com.cn/199904/29/data/newfiles/0060080.htm
+http://autos.yahoo.co.jp/ucar/m1015/k10152012199906/g21/a101520120210248821003520208199906.html
+http://dg.galaxy.com/galaxy/Community/United-States/States/Connecticut/Cities-and-Regions/Guilford/Education/K--12/Middle.html
+http://carriage.de/Schoner/info-e/literature/collections/models/
+http://www.amcity.com/orlando/stories/1998/06/29/weekinbiz.html?t=email_story
+http://www.icopyright.com/1.1655.94549
+http://biblio.cesga.es:81/search*gag/dMicrosoft+Visual+BASIC+(Archivo+de+ordenador)/dmicrosoft+visual+basic+archivo+de+ordenador/-5,1,1,B/frameset&F=dmicrosoft+project+archivo+de+ordenador&1,1,
+http://www.jamba.de/KNet/_KNet-AzI8j1-tGd-13d56/browse.de/node.0/cde7f1uou
+http://www.jamba.de/KNet/_KNet-AzI8j1-tGd-13d5e/browse.de/node.0/cde7f1uou
+http://www.ioppublishing.com/PEL/help/article/ja30010l2/refs/?topic=refs
+http://members.tripod.lycos.co.kr/uuujsh/?N=D
+http://www.wlu.ca/~wwwregi/95-96/cal/ucourses/CP/CP417.html
+http://books.hyperlink.co.uk/bookinfo/Essential_Papers_on_Messianic_Movements_and_Personalities_in_Jewish_History/0814779433
+http://generalstore.everdream.com/kore/catalog/Office_Supplies/Furniture_&_Accessories/File_Cabinets/Vertical/GRP-US747/product.html
+http://satlink.tucows.com/winnt/adnload/54136_29678.html
+http://dc.web.aol.com/myrtlebeacharea/penpals/browse.dci?cat=twenties&sort=m
+http://itcareers.careercast.com/texis/it/itjs/+nwwBme4WD86e4rwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewDthDo5O5apGdtGwMaBGnDBdDaqd1DBGon5aoDqc1moDtax15oDn55amnVncdpoDta5dc1BodD5adppdGB1DoBon5aqdMpnBoBoVnaMFqtuNfIjIDzmYqwwpBme68D86eihwww5rmerdwwwBrmeZpwww/jobpage.html
+http://ring.yamanashi.ac.jp/pub/linux/debian/debian-jp/dists/hamm-jp/hamm/disks-i386/current/base14-3.bin.2.0.11.2-i386
+http://www.ibm.co.jp/pc/thinkpad/pt110/look110.html
+http://retailer.gocollect.com/do/session/1912720/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/postcards/index.asp
+http://www-rn.informatik.uni-bremen.de/home/X11R6/xc/doc/hardcopy/XProtocol/?N=D
+http://cafe3.daum.net/Cafe-bin/bbsList?bbsgrp=SIXTEEN&bbscode=SIXTEENbbs
+http://allmacintosh.arrakis.es/adnload/12140.html
+http://allmacintosh.arrakis.es/adnload/2476.html
+http://www.msb.malmo.se/search*swe/dSkÃ\83¶nlitteratur/dskz~cnlitteratur/-5,-1,0,B/2exact&F=dskz~cnliteratur&1,2
+http://tucows.syix.com/winme/preview/137803.html
+http://pages.prodigy.net/patotoole/musicman/page6.htm
+http://yp.gates96.com/14/43/0/39.html
+http://yp.gates96.com/14/43/0/78.html
+http://yp.gates96.com/14/43/0/79.html
+http://yp.gates96.com/14/43/0/99.html
+http://yp.gates96.com/14/43/1/3.html
+http://yp.gates96.com/14/43/1/57.html
+http://yp.gates96.com/14/43/1/86.html
+http://yp.gates96.com/14/43/2/74.html
+http://yp.gates96.com/14/43/2/80.html
+http://yp.gates96.com/14/43/3/2.html
+http://yp.gates96.com/14/43/3/97.html
+http://yp.gates96.com/14/43/3/99.html
+http://yp.gates96.com/14/43/4/37.html
+http://yp.gates96.com/14/43/4/51.html
+http://yp.gates96.com/14/43/4/72.html
+http://yp.gates96.com/14/43/6/4.html
+http://yp.gates96.com/14/43/7/20.html
+http://yp.gates96.com/14/43/7/39.html
+http://yp.gates96.com/14/43/7/45.html
+http://yp.gates96.com/14/43/9/41.html
+http://yp.gates96.com/14/43/9/58.html
+http://yp.gates96.com/14/43/9/60.html
+http://ftp.support.compaq.com/public/dunix/v3.2g/ASE_V1.3/ReleaseNotes.htm
+http://seniorfriendfinder.com/cgi-bin/w3com/pws/ffsenior/mchI1k9vDw6DGJ19bljzJPwhHhJYxAcnAIKgudPEJtzjiTWMWT4U-YMr4m-AccPn7sEIqMzfFTZnQEQBZNx-lh8DEr_c1F3DXpcc4PzhALzHJ76GytRWNCSauwtfVocYmy_RKsP-H9T-UhQgoc9_uexBhD4a
+http://seniorfriendfinder.com/cgi-bin/w3com/pws/ffsenior/IqtI3V1hdRxfYW_4AHOzeXZkuTzyKfveVl4qdYM_2WFldvLDKFgK8SvYa0mSlrWDVodDERGv2jvb2dEN1-mRmY3TBKURFCsqneanb8BNMBeBfqmSnBYuou5RMCmHxXCedHy3TQnL51n3TYbg5exYBWl9FJTcQEIJt2wyyrfB66jP
+http://seniorfriendfinder.com/cgi-bin/w3com/pws/ffsenior/Hk1ILVbQbFwze5TrhlBima0MylJ0gTqcnVeTbMTcn7Gy5GkelYKhUQ7m8P8_K3IkOWfIWbpGOJEuHqJLX5jY_7ygFevbtkNXPvb1yztdy9qzCTsCJvS5uaHN3cZd0LtuoMX3lX7d_-L_PrwRXSfTE3TNvWl-RHiY4Xmxk1fXhD_uwwjDvC7DDsxz66j6
+http://seniorfriendfinder.com/cgi-bin/w3com/pws/ffsenior/T41IiB449vZ7nrOl2Z_klJHCHQZhigz52e9YVMztVI-K01klBYQrw4VmiKN8JDs9xaeMSWopQs1euSbr6BAiyuqpbSFiiVWObVmWHv031jtdQ1y93wnHhx8PkbrA4hkNhjTPs2mUhBF9wIAJSPCYLkf6W7mCB8ObikqLTuIwBfRtSgMK4Hz9e7Bp
+http://seniorfriendfinder.com/cgi-bin/w3com/pws/ffsenior/CI1IlJNaoNrBcwJYSEcjLyxBnpQHK3wpRPeCR_0u07GznNXQ3Ug57ciOqlfXKlYM1HbRfcvrF5s214yaEHiIizneyWrbSEW_xal49NjQDbWj6R2nEZvDQdDMQEMoTuQlSetyUwMidLBmJJ5v5w9m066en6Yxuzt3RkGIyoHKaVmXgVIYD2Fc40eA
+http://www.secinfo.com/dSm4r.997.htm
+http://www.secinfo.com/dSm4r.68c.htm
+http://www.secinfo.com/dSm4r.69c.htm
+http://mirror.cc.utsunomiya-u.ac.jp/mirror/CPAN/modules/by-module/MD5/GAAS/HTML-Parser-3.04.readme
+http://polygraph.ircache.net:8181/Game+Controllers/http_-2www.real-e-video.com/price-abuse.html
+http://ecomonly.shop.goto.com/z/netadp/search/matches.jhtml?MANUF=Linksys
+http://ecomonly.shop.goto.com/z/netadp/search/matches.jhtml?MANUF=Madge
+http://freesoftware.subportal.com/sn/Web_Authoring/Misc__Programming_Tools/3100.html
+http://www.sam.hi-ho.ne.jp/m-saka/stepwgn/himeji/6scene/
+http://ftp.unina.it/pub/Unix/linux/SuSE/ftp.suse.com/projects/3d/kernel/?N=D
+http://www.ld.com/cbd/archive/1999/08(August)/10-Aug-1999/61awd001.htm
+http://www.ld.com/cbd/archive/1999/08(August)/10-Aug-1999/61awd004.htm
+http://statweb.byu.edu/sasdoc/sashtml/stat/chap2/sect5.htm
+http://www.diogenes.de/4DACTION/web_rd_aut_show_authorlist/ID=483367&chr=F
+http://web1.localbusiness.com/Story/Email/1,1198,RDU_461041,00.html
+http://www.clientwire.com/A55697/tmr.nsf/vwApprovedResumesbyDate!OpenView&Start=55&Count=50&Collapse=48
+http://cpan.nitco.com/modules/by-module/Mail/JWIED/SNMP-Monitor-0.1011.readme
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=237&discrim=178,16,10
+http://www6.compaq.com/products/quickspecs/10135_na/10135_na.PDF
+http://www.suk2.com/user/777/20001012.html
+http://www.jamba.de/KNet/_KNet-vAy8j1-iFd-13az6/browse.de/node.0/cde7f2elw
+http://www.imagesofengland.org.uk/41/69/416915.htm
+http://ocean.ntou.edu.tw/search*chi/aLaplante,+Phillip+A./alaplante+phillip+a/7,-1,0,B/frameset&F=alappe+frances+moore&1,,2
+http://ocean.ntou.edu.tw/search*chi/aLaplante,+Phillip+A./alaplante+phillip+a/7,-1,0,B/frameset&F=alappe+frances+moore&2,,2
+http://wap.jamba.de/KNet/_KNet-6Fz8j1-oFd-13b3x/admLogin.de/node.0/cde7f1uou
+http://yp.gates96.com/14/49/20/26.html
+http://yp.gates96.com/14/49/20/37.html
+http://yp.gates96.com/14/49/20/39.html
+http://yp.gates96.com/14/49/20/86.html
+http://yp.gates96.com/14/49/20/94.html
+http://yp.gates96.com/14/49/20/97.html
+http://yp.gates96.com/14/49/21/19.html
+http://yp.gates96.com/14/49/21/43.html
+http://yp.gates96.com/14/49/21/68.html
+http://yp.gates96.com/14/49/21/78.html
+http://yp.gates96.com/14/49/24/6.html
+http://yp.gates96.com/14/49/24/62.html
+http://yp.gates96.com/14/49/24/77.html
+http://yp.gates96.com/14/49/24/83.html
+http://yp.gates96.com/14/49/25/30.html
+http://yp.gates96.com/14/49/25/41.html
+http://yp.gates96.com/14/49/26/17.html
+http://yp.gates96.com/14/49/26/53.html
+http://yp.gates96.com/14/49/27/21.html
+http://yp.gates96.com/14/49/27/27.html
+http://yp.gates96.com/14/49/27/45.html
+http://yp.gates96.com/14/49/27/65.html
+http://yp.gates96.com/14/49/28/71.html
+http://www.boston.digitalcity.com/orangecounty/entertainment/article.dci?aid=1293&start=10
+http://tucows.allnet.it/winme/adnload/143-006-005-021.html
+http://tucows.allnet.it/winme/adnload/143-006-005-030.html
+http://www.trax.nilex.co.uk/trax.cgi/A1C/B1U/A1D/C1R/A2D/A1U/
+http://www.crosswinds.net/~klinnia/DragonsDomain/Nest/nest.htm
+http://mirrors.valueclick.com/backup.pause/modules/by-category/99_Not_In_Modulelist/Memoize/?S=A
+http://www.tgw.com/EJr.5ajd/customer/category/product.html?SUBCATEGORY_ID=557
+http://www.sohu.com/business_economy/Company/Computer_Internet/Network_System/Network/
+http://china-water.51.net/oicq/oicq_down.htm
+http://ftp.lip6.fr/pub/FreeBSD/development/FreeBSD-CVS/ports/math/plplot/patches/Attic/patch-ac,v
+http://library.cuhk.edu.hk/search*chi/cHC427.92.C59/chc++427.92+c59/-5,-1,,E/browse
+http://yp.gates96.com/4/8/60/2.html
+http://yp.gates96.com/4/8/60/19.html
+http://yp.gates96.com/4/8/62/9.html
+http://yp.gates96.com/4/8/62/23.html
+http://yp.gates96.com/4/8/62/59.html
+http://yp.gates96.com/4/8/63/26.html
+http://yp.gates96.com/4/8/63/41.html
+http://yp.gates96.com/4/8/64/48.html
+http://yp.gates96.com/4/8/65/0.html
+http://yp.gates96.com/4/8/65/42.html
+http://yp.gates96.com/4/8/66/13.html
+http://yp.gates96.com/4/8/66/88.html
+http://yp.gates96.com/4/8/67/23.html
+http://yp.gates96.com/4/8/67/51.html
+http://yp.gates96.com/4/8/68/11.html
+http://yp.gates96.com/4/8/68/16.html
+http://yp.gates96.com/4/8/68/78.html
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/CehIaxpSN7cGOeOUjXx_FtrylkakPWisW0DYq0MYmHwGxLBo7shB2XGSeXyvbnsBzHMJTZtmYOUK-XaaAW0Yh88wTY-Mms-hxw67Xaw8WMk3-vUJ4sXm4U7yIGdiN9XoPOqfnODrkqXYztjU6Var
+http://www.brd.net/brd-cgi/brd_netzwerk?mailto&router&BZ85G0IL
+http://power.luneng.com/power/library/jxgcs/jxgc99/jxgc9912/991204.htm
+http://www.egroups.com/messages/Creative_Teaching/72?viscount=-30
+http://www.egroups.com/message/Creative_Teaching/85
+http://ftp.eecs.umich.edu/.1/people/elta/cusm-Javajae-elta/?D=A
+http://polygraph.ircache.net:8181/cagliari/WHOWOULD.HTM
+http://www.tiscover.ch/1Root/Kontinent/6/Staat/30/Bundesland/33/Ort/1564/Homepage/h_homepage...2.html
+http://t-online.de/computer/haupt/intcoh87.htm
+http://prodigy-sports.excite.com/ncaab/news/025uwire1
+http://wwwold.ifi.uni-klu.ac.at/Manuals/jdk1.1b3/docs/guide/awt/designspec/graphics/imagescale.html
+http://www.taconet.com.tw/a6983/
+http://www.mapion.co.jp/custom/AOL/admi/13/13107/higashimukojima/3chome/index-3.html
+http://www.mapion.co.jp/custom/AOL/admi/13/13107/higashimukojima/3chome/index-13.html
+http://caller-times.com/autoconv/kickoff98/kickoff30.html
+http://www.incestpornstories.com/bisexualbisexual/big-bonedmen/beautiesslanted-eyes/plus-sizeoverweight/{teenlink}
+http://qcardsccg.safeshopper.com/8/359.htm?923
+http://qcardsccg.safeshopper.com/8/429.htm?923
+http://qcardsccg.safeshopper.com/8/433.htm?923
+http://lib1.nippon-foundation.or.jp/1997/0486/contents/011.htm
+http://commerce.was-inc.com/cgi-bin/abtwsam.dll/LbkWebCommerceOrderStatusOverview-BBC709F1_97EF_F357031944376B6D965FDC23BED4C6F4
+http://in.egroups.com/subscribe/muovimallit
+http://multichat.de/fp/talk/cb-funk/4.htm
+http://multichat.de/fp/talk/cb-funk/5.htm
+http://www.jamba.de/KNet/_KNet-zfB8j1-EFd-13bkr/browse.de/node.0/cde7f2elw
+http://www.jamba.de/KNet/_KNet-zfB8j1-EFd-13bl7/showInfo-jobs.de/node.0/cenv0b09a
+http://152.80.49.210/PUBLIC/WXMAP/GLOBAL/AVN/2000103000/avn.prp.00-36.swasia.htm
+http://retailer.gocollect.com/do/session/1912741/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/help/site_tour/index.asp
+http://retailer.gocollect.com/do/session/1912741/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/top_ten.asp?pagenum=2
+http://www.fogdog.com/cedroID/ssd3040183248168/nav/products/winter_sports/1b/shell_jackets/
+http://www.fogdog.com/cedroID/ssd3040183248168/nav/products/featured_brands/3c/all/
+http://kutschen.de/Schoner/literature/Sammlungen/modelle/collections/
+http://el-mundo.es/1999/06/04/television/04N0121.html
+http://bitwise.tucows.com/win2k/htmlval2k_license.html
+http://bbs.ee.ntu.edu.tw/boards/Saturn/3/7/12/5.html
+http://ustlib.ust.hk/search*chi/deconomic+conditions+cameroon+to+1960/deconomic+conditions+cameroon+to+1960/-5,-1,0,B/browse
+http://excite.de/kunst/katalog/865
+http://www2.hindustantimes.com/ht/nonfram/280498/detFRO07.htm
+http://yp.gates96.com/11/69/0/60.html
+http://yp.gates96.com/11/69/1/60.html
+http://yp.gates96.com/11/69/1/72.html
+http://yp.gates96.com/11/69/2/80.html
+http://yp.gates96.com/11/69/3/7.html
+http://yp.gates96.com/11/69/3/54.html
+http://yp.gates96.com/11/69/3/66.html
+http://yp.gates96.com/11/69/3/90.html
+http://yp.gates96.com/11/69/3/91.html
+http://yp.gates96.com/11/69/4/13.html
+http://yp.gates96.com/11/69/4/18.html
+http://yp.gates96.com/11/69/4/26.html
+http://yp.gates96.com/11/69/4/70.html
+http://yp.gates96.com/11/69/5/45.html
+http://yp.gates96.com/11/69/5/77.html
+http://yp.gates96.com/11/69/6/10.html
+http://yp.gates96.com/11/69/6/80.html
+http://yp.gates96.com/11/69/7/43.html
+http://yp.gates96.com/11/69/7/76.html
+http://yp.gates96.com/11/69/8/17.html
+http://yp.gates96.com/11/69/8/33.html
+http://yp.gates96.com/11/69/8/98.html
+http://yp.gates96.com/11/69/9/3.html
+http://yp.gates96.com/11/69/9/41.html
+http://yp.gates96.com/11/69/9/92.html
+http://store.peoplestour.com/kore/catalog/Music/R&B/G_by_artist/104757/product.html
+http://free.prohosting.com/~seikyo/speak2.htm
+http://pub.chinaccm.com/12/news/200009/16/160724.asp
+http://pub.chinaccm.com/12/news/200008/11/155448.asp
+http://www.fogdog.com/cedroID/ssd3040183305379/nav/products/featured_brands/12r/spa_products/
+http://itcareers.careercast.com/texis/it/itjs/+EwwBmev6D86ebtwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewGtmoBGnaqdGpdGwBodDacnwmaADdicnmtnaMwDwtnMnDBanDtoDnnGaMw55wqr15nBB5aqwpB1GnaoDhdGMwBodDaBnqrDdcdton5aMFqhTfR20DzmewrwwwpBmGeP0-dmwww5rmeNDwwwBrmeZpwww/jobpage.html
+http://www.outdoorwire.com/content/lists/dirt/200004/msg00354.html?{LoadingFrameset}
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=5&discrim=186,22,8
+http://www.teleparc.com/sports/funski/02/03.htm
+http://cn.egroups.com/post/safrica_bridge?act=reply&messageNum=43
+http://www.dfae.diplomatie.gouv.fr/culture/france/cinema/documentaires/recherche/francais/ethique.html
+http://ring.toyama-ix.net/archives/mac/info-mac/_Communication/ctb/?D=A
+http://www.eveclub.com/cgi-bin/eveclub.front/972959528284/Catalog/11000155
+http://www.eveclub.com/cgi-bin/eveclub.front/972959528284/Catalog/2000019
+http://cometweb01.comet.co.uk/do!session=132005&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplG5ubLZDXLZolLl3l5jbqLljX5fkkKaotHlob5mloLq1
+http://cometweb01.comet.co.uk/do!session=132005&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplG3XqLbdlLov4LfpmLiXvL-Zd5jbkLYozKvot0cZd5ockLYozKvsm0uts0cZX5qkXLjbzKKbiLbsfLpflLkp5
+http://www.ualberta.ca/CNS/RESEARCH/Software/SAS/cms/zfor-hex.htm
+http://www.ualberta.ca/CNS/RESEARCH/Software/SAS/os390/zlibname.htm
+http://genforum.genealogy.com/cgi-bin/print.cgi?hanrahan::175.html
+http://library.bangor.ac.uk/search/dAIDS+(Disease)+--+Risk+factors+--+Psychological+aspects+--+Periodicals/daids+disease+risk+factors+psychological+aspects+periodicals/-5,1,1,B/frameset&F=daids+disease+research&1,1,
+http://www.rismedia.com/consumer/27/12194/
+http://www.hole.kommune.no/hole/journweb.nsf/weboffjournal!OpenView&Start=39&Count=50&Expand=38
+http://www.etoys.com/prod/toy/53097261
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/J6tI5danl1CaEvxOmyBVl8pzyaGqhs1RWIGq0aJ2_fwvzv4y9T7bHlxQKPzsrhMRN5HEI_Y9ZKrSvboCZvKhdwPPYK2klPp0EqNMO7Mb8fDTcz6xykQv8YQCQ2dy_iLZjbXwrknXqcH32HVSXAq7iUr4yIVG66IK
+http://www.amcity.com/jacksonville/stories/1999/11/22/daily16.html?t=printable
+http://moviestore.zap2it.com/browse/MOVIES/BOXERSHO/s.F0FWmEHm
+http://moviestore.zap2it.com/browse/MOVIES/SHIRT/s.F0FWmEHm
+http://moviestore.zap2it.com/browse/MOVIES/TIE/s.F0FWmEHm
+http://moviestore.zap2it.com/browse/MOVIES/WATCH/s.F0FWmEHm
+http://yp.gates96.com/11/25/30/0.html
+http://yp.gates96.com/11/25/30/47.html
+http://yp.gates96.com/11/25/31/87.html
+http://yp.gates96.com/11/25/32/3.html
+http://yp.gates96.com/11/25/32/61.html
+http://yp.gates96.com/11/25/32/97.html
+http://yp.gates96.com/11/25/33/6.html
+http://yp.gates96.com/11/25/33/81.html
+http://yp.gates96.com/11/25/33/83.html
+http://yp.gates96.com/11/25/34/10.html
+http://yp.gates96.com/11/25/34/35.html
+http://yp.gates96.com/11/25/34/88.html
+http://yp.gates96.com/11/25/34/90.html
+http://yp.gates96.com/11/25/35/95.html
+http://yp.gates96.com/11/25/36/19.html
+http://yp.gates96.com/11/25/36/98.html
+http://yp.gates96.com/11/25/37/61.html
+http://yp.gates96.com/11/25/37/74.html
+http://yp.gates96.com/11/25/38/2.html
+http://yp.gates96.com/11/25/38/62.html
+http://yp.gates96.com/11/25/39/1.html
+http://yp.gates96.com/11/25/39/25.html
+http://yp.gates96.com/11/25/39/85.html
+http://yp.gates96.com/11/25/39/95.html
+http://www.linux.com/networking/network/industry/server/community/Red_Hat/
+http://www.linux.com/networking/network/industry/server/community/Slashdot/
+http://www.linux.com/networking/network/industry/server/community/growth/
+http://mirror.cc.utsunomiya-u.ac.jp/mirror/CPAN/modules/by-category/16_Server_and_Daemon_Utilities/Server/DRUOSO/Server-FastPL-1.0.0.readme
+http://ftp.nacamar.de/pub/NetBSD/NetBSD-current/pkgsrc/parallel/clusterit/pkg/DESCR
+http://dk.egroups.com/login.cgi?login_target=%2Fgroup%2FGravesrus
+http://www.maxfunds.com/MF1000.nsf/FUNDanalysisPrint/FGOAX
+http://www.gbnf.com/genealog2/brothers/html/d0065/I12666.HTM
+http://office.net/benelux/nld/downloadcatalog/dldpowerpoint.asp
+http://yam.com/en/rand/ent/music/minfo/
+http://kernel2.adver.com.tw/Counter/log/kernel2.adver.com.tw/Collect_DB_Advers2/2000-09-28/23/?N=D
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=22,11,35
+http://dk.egroups.com/messages/lafz/6
+http://www.online.kokusai.co.jp/Words/V0043555/wrd/G700/words/kana_main.html
+http://adelaida.net/music/texts/pink75.html
+http://support.tandy.com/support_audio/doc40/40914.htm
+http://www.nutritionblvd.com/426162.html
+http://www.nutritionblvd.com/426121.html
+http://www.nutritionblvd.com/426117.html
+http://www.fogdog.com/cedroID/ssd3040183301450/boutique/aaron_chang/
+http://www.fogdog.com/cedroID/ssd3040183301450/boutique/moving_comfort/
+http://www.fogdog.com/cedroID/ssd3040183301450/fly/
+http://in.egroups.com/login.cgi?login_target=%2Fmessage%2Finfogiappone%2F81
+http://in.egroups.com/post/infogiappone?act=reply&messageNum=81
+http://cn.egroups.com/message/1800list/5416
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/www.slac.stanford.edu/grp/arb/tn/arbvol1/ARDB011.pdf
+http://crrstv.tucows.com/winnt/adnload/135146_46908.html
+http://syix.tucows.com/win2k/adnload/61785_28334.html
+http://ftp.ccu.edu.tw/pub/language/tcl/sorted/packages-7.6/sound/xmpeg_0.5/
+http://www.eos.ncsu.edu/linux/LDP/LDP/khg/HyperNews/get/fs/fs/3.html
+http://polygraph.ircache.net:8181/http_-2www.tvguide.com/sports/football/http_-2home.netscape.com/http_-2www.premaonline.com/http_-2www.ionet.net/~burndragon/form1.html
+http://se.egroups.com/group/MyLuminaGoezBoom
+http://www.diogenes.ch/4DACTION/web_rd_aut_show_author/a_id=7056553&tmpl=AUT_00&ID=483371
+http://www3.newstimes.com/archive97/apr0497/tvg.htm
+http://dic.empas.com/show.tsp/?q=edger&f=B
+http://www.brio.de/BRIO.catalog/39fe2f570905fb6a2740d472aa7806aa/UserTemplate/2
+http://itcareers.careercast.com/texis/it/itjs/+uwwBme7WD86eYtwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewGtmoBGnaqdGpdGwBodDaoDhdGMwBodDa5nq1GoBOanDtoDnnGaiw5roDtBdDanDBnGpGo5naGn31oGnmawGqroBnqB1Gna5O5BnM5aMFqhTfR20DzmehrwwwpBmeZWD86Nwww5rmekdwwwBrmeZpwww/jobpage.html
+http://itcareers.careercast.com/texis/it/itjs/+pwwBmet5986twwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewGtmoBGnaqdGpdGwBodDaoDhdGMwBodDa5nq1GoBOanDtoDnnGaiw5roDtBdDanDBnGpGo5naGn31oGnmawGqroBnqB1Gna5O5BnM5aMFqhTfR20DzmehrwwwpBmeZWD86Nwww5rmekdwwwBrmeZpwww/morelike.html
+http://biblioteca.upv.es/bib/doc/doc_fisbd/180/132317//C/1825784/0////25/S/MLTPAI
+http://www.stanford.edu/~sevls/files/?M=D
+http://library.bangor.ac.uk/search/dSystem+analysis+--+Periodicals/dsystem+analysis+periodicals/-17,-1,0,B/browse
+http://mirror.ox.ac.uk/Mirrors/ftp.redhat.com/roughcuts/m68k/misc/src/install/pci-probing/CVS/
+http://yp.gates96.com/0/13/10/17.html
+http://yp.gates96.com/0/13/11/26.html
+http://yp.gates96.com/0/13/12/20.html
+http://yp.gates96.com/0/13/12/24.html
+http://yp.gates96.com/0/13/12/49.html
+http://yp.gates96.com/0/13/13/22.html
+http://yp.gates96.com/0/13/13/80.html
+http://yp.gates96.com/0/13/15/8.html
+http://yp.gates96.com/0/13/16/4.html
+http://yp.gates96.com/0/13/16/18.html
+http://yp.gates96.com/0/13/16/64.html
+http://yp.gates96.com/0/13/17/15.html
+http://yp.gates96.com/0/13/18/11.html
+http://yp.gates96.com/0/13/18/18.html
+http://yp.gates96.com/0/13/19/5.html
+http://yp.gates96.com/0/13/19/22.html
+http://yp.gates96.com/0/13/19/60.html
+http://library.cuhk.edu.hk/search*chi/aYen-shou,+Shih,+904-975./ayen+shou+shih++904++975/-5,-1,0,E/2browse
+http://china.sydney2000.com/StaticNews/2000-07-29/News372a86.htm
+http://www.fujian-window.com/Fujian_w/news/mzrb1/20000724/3_1.html
+http://www.fujian-window.com/Fujian_w/news/mzrb1/20000724/3_2.html
+http://legalminds.lp.findlaw.com/list/law-lib/nav07807.html
+http://ftp.fi.debian.org/debian/dists/woody/contrib/binary-sparc/tex/?N=D
+http://community.webshots.com/photo/3635718/3636284GcTotmmONR
+http://www.power2lead.com/Global/English.nsf/pgWWLocations!OpenPage&ExpandSection=23,24,25,17,10
+http://spaindustry.com/por/exp/911.html
+http://niagara.tucows.com/winme/preview/10464.html
+http://niagara.tucows.com/winme/adnload/138750_30032.html
+http://niagara.tucows.com/winme/adnload/138743_30025.html
+http://niagara.tucows.com/winme/adnload/138740_30023.html
+http://retailer.gocollect.com/do/session/1912780/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/advanced_search.asp
+http://preview.egroups.com/messages/UKMatrix
+http://fi.egroups.com/login.cgi?login_target=%2Fmessage%2Fhecates_news%2F21
+http://pub.chinaccm.com/02/news/200005/31/133146.asp
+http://pub.chinaccm.com/02/news/200005/31/133212.asp
+http://localhost/test,
+http://kuyper.calvin.edu/fathers2/ANF-02/anf02-25.htm
+http://kuyper.calvin.edu/fathers2/ANF-02/anf02-56.htm
+http://totalsports.aol.com/stats/bbo/mlb/mlb/990910.cle.AT.cws.box.html
+http://totalsports.aol.com/stats/bbo/mlb/mlb/990915.nym.AT.col.box.html
+http://totalsports.aol.com/stats/bbo/mlb/mlb/990919.cws.AT.tor.box.html
+http://totalsports.aol.com/stats/bbo/mlb/mlb/990926.hou.AT.mil.box.html
+http://totalsports.aol.com/stats/bbo/mlb/mlb/991003.nyy.AT.tam.box.html
+http://totalsports.aol.com/stats/bbo/mlb/mlb/991006.bos.AT.cle.box.html
+http://totalsports.aol.com/stats/bbo/mlb/mlb/ALscores.html
+http://totalsports.aol.com/stats/bbo/mlb/mlb/CAT.ROS.pit.html
+http://totalsports.aol.com/stats/bbo/mlb/mlb/NYY.CLE.pit.html
+http://totalsports.aol.com/stats/bbo/mlb/mlb/mlb.ARI.recap.html
+http://totalsports.aol.com/stats/bbo/mlb/mlb/mlb.atl.vs.hou.stat.html
+http://www.jpc-music.com/2241771.htm
+http://sunsite.org.uk/packages/TeX/uk-tex/macros/latex/contrib/supported/europs/?M=A
+http://mitglied.tripod.de/blueblood/forum.html
+http://kuyper.calvin.edu/fathers2/NPNF1-06/npnf1-06-92.htm
+http://garbage.sonicnet.com/classical/features/Thomas,_Tilson/060500/index04.jhtml
+http://dk.egroups.com/post/danish?act=forward&messageNum=6
+http://www.bornloser.com/comics/peanuts/f_profiles/html/f4b1.html
+http://www.online.kokusai.co.jp/Home/V0043517/wrd/G100/
+http://www.affiliate.hpstore.hp.co.uk/do/session/380823/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.france.hp.com/Main/acheterhp/
+http://www.bemi-immobilien.de/Landhaus-Bordeaux/Gemeinsam/versicherungen/lebensversicherung/Gemeinsam/Startseite/Top-Darlehens-Konditionen/Gemeinsam/erreichenPartner/email3d.htm
+http://sunsite.org.uk/public/pub/Mirrors/ftp.hpc.uh.edu/pub/?D=A
+http://genforum.genealogy.com/cgi-bin/print.cgi?tillery::418.html
+http://ring.omp.ad.jp/archives/lang/perl/CPAN/authors/id/MSCHWARTZ/?M=A
+http://montxsuz.all-hotels.com/usa/massachusetts/plymouth_e1.htm
+http://montxsuz.all-hotels.com/usa/massachusetts/brewster_e1.htm
+http://montxsuz.all-hotels.com/usa/massachusetts/edgartown_e1.htm
+http://montxsuz.all-hotels.com/usa/massachusetts/north_dartmouth_e1.htm
+http://montxsuz.all-hotels.com/usa/massachusetts/washington_e1.htm
+http://romeo.univ-savoie.fr/winnt/adnload/51179_28892.html
+http://www.dispatch.co.za/1998/12/02/sport/FALDO.HTM
+http://www.dispatch.co.za/1998/12/02/sport/RACE2.HTM
+http://store1.europe.yahoo.com/brink2/2000074707407.html
+http://www34.yahoo.co.jp/horse/1999/tokyo/0530/result_08.html
+http://members.tripod.co.jp/suiha_izumi/gallery-taikoubou-.htm
+http://linuxberg.vol.at/gnomehtml/adnload/020-008-002-004_6145.html
+http://books.hyperlink.com/bookdetails/Nuclear_Power_Plants_Worldwide/0810388804
+http://www.hudecek.de/gen/gen57.htm
+http://www.hudecek.de/gen/gen61.htm
+http://unofficial.capital.edu/students/kralph/
+http://web6.peopledaily.com.cn/gjjrb/200004/home.htm
+http://www.gov.hk/hkma/eng/public/sccr/toc.htm
+http://www4.50megs.com/johnphil29/86week3injury.htm
+http://www4.50megs.com/johnphil29/86week3loupitlog.htm
+http://naver22.juniornaver.co.kr/Entertainment_and_Arts/Performing_Arts/Theater/Musical/
+http://198.103.152.100/search*frc/dInfrastructure+(Economics)+--+Canada/dinfrastructure+economics+canada/-5,-1,0,B/frameset&F=dinfrastructure+economics&3,,0
+http://198.103.152.100/search*frc/dInfrastructure+(Economics)+--+Canada/dinfrastructure+economics+canada/-5,-1,0,B/frameset&F=dinfrastructure+economics&5,,0
+http://www.playgirl.dk/oncampus/feature/collegemovies/06.html
+http://www.linux.com/networking/support/red_hat/internet/consumer/growth/
+http://www.linux.com/networking/support/red_hat/internet/consumer/mainstream/
+http://no.egroups.com/message/tengu-l/224
+http://no.egroups.com/message/tengu-l/229
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/linux-2.3-4/linux/Documentation/filesystems/romfs.txt?only_with_tag=LINUX-2_3_24
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/linux-2.3-4/linux/Documentation/filesystems/romfs.txt?only_with_tag=LINUX-2_3_22
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/linux-2.3-4/linux/Documentation/filesystems/romfs.txt?only_with_tag=LINUX-2_3_16
+http://sunsite.informatik.rwth-aachen.de/LinuxArchives/slackware/slackware/source/a/e2fsprog/?M=A
+http://bbs.syu.ac.kr/NetBBS/Bbs.dll/ipspds018/lst/qqa/f/qqo/008A/zka/B2-kB2-p
+http://stulchik.list.ru/catalog/13346.html
+http://katalog.wp.pl/www/Biznes_i_Ekonomia/Firmy_Podzial_wg_Branz/Elektrotechnika_i_Energetyka/index25.html
+http://www.fogdog.com/cedroID/ssd3040183313356/nav/stores/tennis/
+http://www.fogdog.com/cedroID/ssd3040183313356/customer_service/shop_by_catalog.html
+http://193.207.57.3/cgi-win/hiweb.exe/a2/d13/b4,4,1f,4,4,,
+http://ring.omp.ad.jp/archives/lang/perl/CPAN/modules/by-authors/id/JPRIT/Envy-2.45.readme
+http://193.207.57.3/cgi-win/hiweb.exe/a2/d1342/b4,4,1f,e,e,,
+http://library.wuhee.edu.cn/dzsy/military/china/army/002.htm
+http://library.wuhee.edu.cn/dzsy/military/china/army/006.htm
+http://library.wuhee.edu.cn/dzsy/military/china/army/059.htm
+http://library.wuhee.edu.cn/dzsy/military/china/army/095.htm
+http://polygraph.ircache.net:8181/http_-2www.geocities.com/TimesSquare/Maze/2075/http_-2www.yahoo.com/Science/Engineering/Mechanical_Engineering/corporate.htm
+http://198.103.152.100/search*frc/aGundavaram,+Shishir/agundavaram+shishir/-17,-1,0,B/frameset&F=aguirdham+maureen&1,1
+http://findmail.com/message/geewhiz/21
+http://sound-dist.secured.co.uk/cgi-bin/psProdDet.cgi/19P02|972959597|Luggage|user|0|1,0,0,1
+http://sound-dist.secured.co.uk/cgi-bin/psShop.cgi/add|19P03|972959597|Luggage|user|0|1,0,0,1
+http://nme.com/AST/Discussion_Groups/CDA/Message_Search/1,1105,37_92-0-0-7,00.html
+http://namviet.subportal.com/sn/Programming/Visual_Basic_Components_H-P/5638.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4963.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4810.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4735.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/3294.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/3329.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4689.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4646.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4582.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4587.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4154.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4607.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4600.html
+http://www2.so-net.ne.jp/cinet/board/log/200001/messages/4571.html
+http://www.gotocity.com/local/2/us/KS/g/67455/shopping/
+http://www.mapion.co.jp/custom/AOL/admi/13/13115/ogikubo/1chome/index-1.html
+http://www.mapion.co.jp/custom/AOL/admi/13/13115/ogikubo/1chome/index-21.html
+http://neuro-www.mgh.harvard.edu/forum_2/ChronicPainF/Capornottocapthatisthe.html
+http://www.yagoo.co.kr/stats/pitching.asp?Mlbmanid=MIGDEL7299
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=50&discrim=165,233,7
+http://www.mirror.edu.cn/res/sunsite/pub/academic/literature/book-reviews/1994/8-August/?N=D
+http://www.ferien-immobilien.de/ungarn/verkauf/Versteigerungen-IB/Startseite/Allgemeine-IB/Gemeinsam/versicherungen/gebaeude/Gemeinsam/vertriebspartner.htm
+http://www.ferien-immobilien.de/ungarn/verkauf/Versteigerungen-IB/Startseite/Allgemeine-IB/Gemeinsam/versicherungen/gebaeude/Gemeinsam/feedback.html
+http://www.bjd.com.cn/BJWB/20000401/GB/BJWB^10199^1^01W136.htm
+http://pluto.beseen.com/boardroom/u/49766/
+http://amadeus.siba.fi/doc/bitchx/documentation/color.txt
+http://www.ealingcommon.londonengland.co.uk/pensions.htm
+http://pub8.ezboard.com/fthecriticalpoetsmessageboartheartofcritiquing.showMessage?topicID=11.topic&index=13
+http://pub8.ezboard.com/fthecriticalpoetsmessageboareverythingelse.showMessage?topicID=223.topic&index=10
+http://www.endocrine.ru/Meln_09_10_00/_vti_bin/shtml.exe/meln_post.htm?79
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=9,0+9,3-12,0+18,0
+http://www.jobvillage.com/channel/jobs/media_communication/b.9255.g.1733.html
+http://www.teenplatinum.com/barelylegal/no-boundarieshardcore/flashingbarely-legal/sweatingendurance/cuntamateur/chinesepetite/bootygay-bar/lubricationfellatio.html
+http://www.babyheirlooms.com/catalog/htmlos.cat/001222.1.5246799112
+http://src.openresources.com/debian/src/utils/HTML/R/change_cur_jutil.html
+http://genforum.genealogy.com/caudill/messages/389.html
+http://www.allkorea.co.jp/cgi-bin/allkorea.front/972959928076/Catalog/1000003
+http://www.allkorea.co.jp/cgi-bin/allkorea.front/972959928076/ContentView/1000188/1/1201981
+http://www.marketingtool.com/contribute/webfirm/b.435.r.2416.html
+http://dell.excite.co.jp/member_encounters/mailing_list/ml_for_women
+http://www.angeredsgymn.se/doc/sdb/en/html/keylist.SIGNSET.html
+http://map.ipc.co.jp/asp/onmap/r/new/g-27/f-525628/
+http://www.jpc-music.com/2549026.htm
+http://www.egroups.com/message/nandscarolina/324?source=1
+http://www.jpc-music.com/2226499.htm
+http://www.jpc-music.com/2226480.htm
+http://tucows.bigskysoft.com/winnt/miscaudiont_rating.html
+http://tucows.bigskysoft.com/winnt/adnload/69355_28370.html
+http://www.hole.kommune.no/hole/journweb.nsf/weboffjournal!OpenView&Start=115.23&Count=50&Expand=130
+http://personal.atl.bellsouth.net/mia/a/j/ajcubas/
+http://yp.gates96.com/7/49/21/96.html
+http://yp.gates96.com/7/49/22/39.html
+http://yp.gates96.com/7/49/22/60.html
+http://yp.gates96.com/7/49/22/70.html
+http://yp.gates96.com/7/49/22/75.html
+http://yp.gates96.com/7/49/23/8.html
+http://yp.gates96.com/7/49/23/30.html
+http://yp.gates96.com/7/49/23/43.html
+http://yp.gates96.com/7/49/24/7.html
+http://yp.gates96.com/7/49/24/8.html
+http://yp.gates96.com/7/49/24/27.html
+http://yp.gates96.com/7/49/24/49.html
+http://yp.gates96.com/7/49/25/92.html
+http://yp.gates96.com/7/49/26/56.html
+http://yp.gates96.com/7/49/26/77.html
+http://yp.gates96.com/7/49/28/23.html
+http://yp.gates96.com/7/49/28/34.html
+http://yp.gates96.com/7/49/29/56.html
+http://yp.gates96.com/7/49/29/60.html
+http://sound-dist.secured.co.uk/cgi-bin/psShop.cgi/add|38P08B|972959501|Communications|user|0|1,0,0,1
+http://193.207.57.3/cgi-win/hiweb.exe/a2/d170/b9,4,1f,1c,1c,,
+http://wuarchive.wustl.edu/systems/linux/replay/debian/dists/unstable/non-US/binary-hurd-i386/?M=D
+http://www.private-immobilien-boerse.de/friesland/verkauf/Ferien-IB/Startseite/Gemeinsam/MarketingStrategie/Allgemeine-IB/Startseite/Exklusiv-IB/Startseite/
+http://citeseer.nj.nec.com/update/269184
+http://citeseer.nj.nec.com/cidcontext/3266491
+http://citeseer.nj.nec.com/cidcontext/3266502
+http://genforum.genealogy.com/cgi-genforum/forums/hinkle.cgi?786
+http://eagle.synet.edu.cn/mirror/www.wisc.edu/grad/catalog/cals/biometry.html
+http://cisne.sim.ucm.es/search*spi/cCDR7(035)TRA/ccdr7(035)tra/-5,-1,0,B/frameset&F=ccdr7(058)may&1,1
+http://www.wfg-rhein-lahn.de/goldenes-fass/schrott2.htm
+http://www.jamba.nl/KNet/_KNet-6Aw8j1-pC4-ptt0/browse.nl/node.0/cdn40t70v
+http://www.dcc.ufmg.br/Entnet/estrem/tsld018.htm
+http://sites.uol.com.br/knaumann/DorstnerDrahtwerke.html
+http://64.209.212.162/learnlots/step/0,2891,9+47+95+23413+12412_0,00.html
+http://www.on-semiconductor.com/pub/prod/0,1824,productsm_ProductSummary_BasePartNumber=LM337A,00.html
+http://jxi.gov.cn/yw-gn001.nsf/view!OpenView&Start=39.19&Count=30&Expand=53
+http://systemlogic.neoseeker.com/Games/Products/PC/dropship/dropship_reviews.html
+http://link.fastpartner.com/do/session/600373/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/smartguy.php
+http://www.bsv.ch/ch/d/sr/0_211_222_1/a10.html
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/contact.netscape.com/contact
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/entertainment.netscape.com/entertainment/
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/games.netscape.com/computing/games/features/
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/home.netscape.com/finance/taxes/
+http://link.fastpartner.com/do/session/600379/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/brleksaker.php
+http://itcareers.careercast.com/texis/it/itjs/+TwwBmeOWD86eDhwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewPXwotoBwcaqconDBahoDwDqnaqddGmoDwBdGaqdMpwDon5aBnwMax1mtnBoDtaMwoDBnDwDqnapGdqn55n5aGn51MnaMFqryfHfREIDzmUwwwpBme+9D86Exww5rme7dwwwBrmeZpwww/jobpage.html
+http://fi.egroups.com/message/handebol_aaagm/5?source=1
+http://www.crutchfield.com/cgi-bin/S-SHC3792E7De/viewcart.asp
+http://www.links2go.org/more/www.asle.umn.edu/
+http://yp.gates96.com/7/69/10/58.html
+http://yp.gates96.com/7/69/10/64.html
+http://yp.gates96.com/7/69/10/76.html
+http://yp.gates96.com/7/69/10/91.html
+http://yp.gates96.com/7/69/11/31.html
+http://yp.gates96.com/7/69/11/67.html
+http://yp.gates96.com/7/69/11/70.html
+http://yp.gates96.com/7/69/11/88.html
+http://yp.gates96.com/7/69/11/96.html
+http://yp.gates96.com/7/69/12/25.html
+http://yp.gates96.com/7/69/12/29.html
+http://yp.gates96.com/7/69/12/61.html
+http://yp.gates96.com/7/69/12/65.html
+http://yp.gates96.com/7/69/12/73.html
+http://yp.gates96.com/7/69/13/30.html
+http://yp.gates96.com/7/69/13/36.html
+http://yp.gates96.com/7/69/14/8.html
+http://yp.gates96.com/7/69/14/32.html
+http://yp.gates96.com/7/69/14/54.html
+http://yp.gates96.com/7/69/14/62.html
+http://yp.gates96.com/7/69/14/83.html
+http://yp.gates96.com/7/69/15/34.html
+http://yp.gates96.com/7/69/15/87.html
+http://yp.gates96.com/7/69/16/18.html
+http://yp.gates96.com/7/69/17/5.html
+http://yp.gates96.com/7/69/17/22.html
+http://yp.gates96.com/7/69/17/44.html
+http://yp.gates96.com/7/69/17/86.html
+http://yp.gates96.com/7/69/17/88.html
+http://yp.gates96.com/7/69/18/16.html
+http://yp.gates96.com/7/69/18/83.html
+http://yp.gates96.com/7/69/18/88.html
+http://yp.gates96.com/7/69/19/0.html
+http://yp.gates96.com/7/69/19/1.html
+http://yp.gates96.com/7/69/19/97.html
+http://213.36.119.69/do/session/152995/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/jeux/jeux_himalaya.html
+http://www.egroups.com/post/sikhstudent?act=forward&messageNum=77
+http://ca.yahoo.com/Regional/U_S__States/Wisconsin/Metropolitan_Areas/Milwaukee_Metro/Business_and_Shopping/Shopping_and_Services/Food_and_Drink/Beverages/
+http://www.aelita.net/products/services/library/~archive/Download_redirect/company/news/default.htm
+http://mindex.tucows.com/winme/preview/430.html
+http://coda.nctu.edu.tw/vendors/DBMaker/DBMaker/driver/PHP/?S=A
+http://www.streetprices.com/Electronics/Computer_Hardware_PC/Switches/Monitor/MAKE+BELKIN+COMPONENTS/sortproductbydesc/SP151043.html
+http://wynnsystems.com/y9I_5aVd/careerlink.html
+http://www.volny.cz/alik/akordy/zizen.htm
+http://www.houses-apartment-listings.com/Michigan/city_search_criteria.asp?state=MI&City=CHAMPION
+http://pub9.ezboard.com/fpyro1394pyro1394.showAddReplyScreenFromWeb?topicID=345.topic
+http://www.maastrek.de/maas/01851471b455eff5cd01/1/0/1
+http://beta.mkn.co.uk/wine/order/champ2?what-mnw9=1
+http://beta.mkn.co.uk/wine/order/champ2?what-mnw14=1
+http://sunsite.org.uk/public/pub/packages/andrew/auis-6.3/overhead/
+http://www.ferien-immobilien.de/Spanien/Verkauf/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/Gemeinsam/Exklusiv-IB/Startseite/Gemeinsam/geschaeftsbedingungen.htm
+http://www.trax.nilex.co.uk/trax.cgi/A1S/A2S/A3S/1AL/A2D/A1S/
+http://www.trax.nilex.co.uk/trax.cgi/A1S/A2S/A3S/1AL/A2D/C2S/
+http://tv.thevines.com/leaf/AA0000369148/3/1
+http://tv.thevines.com/leaf/AA0000369148/37/0/&favorite[join]=yes
+http://www.centc251.org/forums/aca-1/dispatch.cgi/isowg4/showFolder/100001/1304571
+http://freebsd.ntu.edu.tw/perl/modules/by-module/FileCache/ILYAZ/?D=A
+http://www.highwired.net/Sport/Player/0,2291,2037-46698,00.html
+http://www.nl.sco.com/unixware/adminguide/qs-11-32.html
+http://www.online.kokusai.co.jp/Service/V0043502/wrd/G200/service/service.html
+http://www.realize.com/ambe7581.htm,qt=e784fe2f=2a38a234-14-26557ed-80000000-0-0-3--
+http://www.realize.com/am9a7d81.htm,qt=e784fe2f=2a38a234-14-26557ed-80000000-0-0-3--
+http://www.geocities.co.jp/Colosseum/7952/dragon3.html
+http://uk.dir.clubs.yahoo.com/Entertainment___Arts/Magic/~other/~White_Pages/2.html
+http://yp.gates96.com/13/9/60/95.html
+http://yp.gates96.com/13/9/60/97.html
+http://yp.gates96.com/13/9/61/12.html
+http://yp.gates96.com/13/9/61/42.html
+http://yp.gates96.com/13/9/61/52.html
+http://yp.gates96.com/13/9/62/13.html
+http://yp.gates96.com/13/9/62/19.html
+http://yp.gates96.com/13/9/62/32.html
+http://yp.gates96.com/13/9/62/44.html
+http://yp.gates96.com/13/9/62/75.html
+http://yp.gates96.com/13/9/63/71.html
+http://yp.gates96.com/13/9/63/89.html
+http://yp.gates96.com/13/9/64/16.html
+http://yp.gates96.com/13/9/64/64.html
+http://yp.gates96.com/13/9/64/83.html
+http://yp.gates96.com/13/9/65/15.html
+http://yp.gates96.com/13/9/65/39.html
+http://yp.gates96.com/13/9/65/81.html
+http://yp.gates96.com/13/9/66/19.html
+http://yp.gates96.com/13/9/66/51.html
+http://yp.gates96.com/13/9/67/72.html
+http://yp.gates96.com/13/9/67/75.html
+http://yp.gates96.com/13/9/67/93.html
+http://yp.gates96.com/13/9/67/94.html
+http://yp.gates96.com/13/9/68/9.html
+http://yp.gates96.com/13/9/68/14.html
+http://yp.gates96.com/13/9/68/23.html
+http://yp.gates96.com/13/9/68/39.html
+http://yp.gates96.com/13/9/68/68.html
+http://yp.gates96.com/13/9/69/22.html
+http://yp.gates96.com/13/9/69/62.html
+http://shop.intouch.de/cgi-bin/Eternit-Shop/1678827467/IconBar
+http://www.jango.com/home_and_garden/outdoor_and_garden/gardening/outdoor_furniture/miscellaneous/?num=1&prod=7
+http://ring.omp.ad.jp/archives/lang/perl/CPAN/authors/id/SHERWOOD/CHECKSUMS
+http://www.acad.polyu.edu.hk/spkg/sas8/sasdoc/hrddoc/indfiles/57263.htm
+http://ftp.te.fcu.edu.tw/cpatch/system/mbm/source/?D=A
+http://web1.localbusiness.com/Story/0,1118,SAN_11751,00.html
+http://www.amulation.com/md-l-archive/199902/msg00357.html
+http://ads3.zdnet.com/c/g=r1517&c=a53585&camp=c13878&idx=2000.10.30.21.32.11/www.sega.com/seganet
+http://pub.chinaccm.com/23/news/200009/30/111206.asp
+http://www.online.kokusai.co.jp/Service/V0043534/wrd/G200/service/service.html
+http://www.buybuddy.com/sleuth/27/1/1060204/2992/
+http://www.friend4life.com/foreign-affair/infopage/info12655.htm
+http://www.friend4life.com/women/info7867.htm
+http://www.friend4life.com/women/info11637.htm
+http://www.chabadlibrary.org/ecatalog/EC07/EC07328.HTM
+http://tulips.ntu.edu.tw/search*chi/cJC311+S275+1992/cjc++311+s275+1992/7,-1,0,E/2browse
+http://stationradio.subportal.com/sn/Network_and_Internet/Misc__Networking_Tools/866.html
+http://www.canlii.org/ca/regu/sor88-278/sec2.html
+http://www.rottentomato.com/movies/titles/traffic/click.php?review=1
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=4,26,16,35,15
+http://www.staroriental.net/nav/soeg/ihf,aai,n2,169,Electric+Wave+Girl+1998.html
+http://www.staroriental.net/nav/soeg/ihf,aai,n2,176,Electric+Wave+Girl+1998.html
+http://www.teenplatinum.com/barelylegal/bellyovary/parkingjail-bait/oral-sexoral-sex/big-bonedmen/sex/main.html
+http://troy.lib.sfu.ca/search/snewsinc/snewsinc/-5,1,1,B/frameset&F=snewsbrief&1,,2
+http://biblio.cesga.es:81/search*gag/dL&oacute%3Bpez+de+Medina,+Juan/dlopez+de+medina+juan/-5,-1,0,B/frameset&F=dlopez+de+ayala+pedro+critica+e+interpretacion&1,,2
+http://proxy.rmcnet.fr/udsp68/commissions.htm
+http://proxy.rmcnet.fr/udsp68/csp_colmar.htm
+http://yp.gates96.com/4/0/70/88.html
+http://yp.gates96.com/4/0/71/51.html
+http://yp.gates96.com/4/0/71/57.html
+http://yp.gates96.com/4/0/71/84.html
+http://yp.gates96.com/4/0/71/85.html
+http://yp.gates96.com/4/0/72/84.html
+http://yp.gates96.com/4/0/72/94.html
+http://yp.gates96.com/4/0/73/15.html
+http://yp.gates96.com/4/0/73/92.html
+http://yp.gates96.com/4/0/74/96.html
+http://yp.gates96.com/4/0/75/23.html
+http://yp.gates96.com/4/0/75/94.html
+http://yp.gates96.com/4/0/76/41.html
+http://yp.gates96.com/4/0/76/82.html
+http://yp.gates96.com/4/0/77/64.html
+http://yp.gates96.com/4/0/78/93.html
+http://yp.gates96.com/4/0/79/72.html
+http://yp.gates96.com/4/0/79/82.html
+http://fi.egroups.com/message/morehealth/13?source=1
+http://cn.egroups.com/message/Multicultural/489
+http://cn.egroups.com/message/Multicultural/495
+http://cn.egroups.com/message/Multicultural/497
+http://yp.gates96.com/4/1/60/54.html
+http://yp.gates96.com/4/1/60/69.html
+http://yp.gates96.com/4/1/61/83.html
+http://yp.gates96.com/4/1/62/68.html
+http://yp.gates96.com/4/1/63/13.html
+http://yp.gates96.com/4/1/63/42.html
+http://yp.gates96.com/4/1/63/61.html
+http://yp.gates96.com/4/1/63/73.html
+http://yp.gates96.com/4/1/64/15.html
+http://yp.gates96.com/4/1/64/49.html
+http://yp.gates96.com/4/1/64/54.html
+http://yp.gates96.com/4/1/65/19.html
+http://yp.gates96.com/4/1/65/26.html
+http://yp.gates96.com/4/1/65/69.html
+http://yp.gates96.com/4/1/65/98.html
+http://yp.gates96.com/4/1/66/57.html
+http://yp.gates96.com/4/1/66/62.html
+http://yp.gates96.com/4/1/66/79.html
+http://yp.gates96.com/4/1/66/86.html
+http://yp.gates96.com/4/1/66/88.html
+http://yp.gates96.com/4/1/67/6.html
+http://yp.gates96.com/4/1/67/49.html
+http://yp.gates96.com/4/1/67/76.html
+http://yp.gates96.com/4/1/67/78.html
+http://yp.gates96.com/4/1/68/57.html
+http://yp.gates96.com/4/1/69/10.html
+http://yp.gates96.com/4/1/69/47.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=blich&l=de
+http://www.secinfo.com/d17xw.53m.htm
+http://www.cs.unm.edu/sheppard-bin/igmdesc.cgi/n=shep/I1475
+http://home.pchome.com.tw/computer/54915491/data/data2.htm
+http://forum.rai.it/aca-finestre/dispatch.cgi/FORUM/folderFrame/100001/0/author/3910318
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=215&discrim=164,80,165
+http://library.bangor.ac.uk/search/cHN582+.R45+1991/chn++582+r45+1991/-5,-1,0,B/bibandlinks&F=chn++573+h313&1,1
+http://mai.flora.org/forum/new-2110
+http://www.tucows.telia.no/winnt/adnload/68747_30295.html
+http://www.tucows.telia.no/winnt/adnload/135780_47081.html
+http://www.annotate.net/html/Annotate_Directory/Top/Regional/North_America/United_States/Louisiana/Localities/C/Coushatta
+http://wine.cc.chuo-u.ac.jp/home/pub/TeX/CTAN/support/mctex/?D=A
+http://pub21.ezboard.com/ujaletheadmin.showPublicProfile?language=EN
+http://ftp.lip6.fr/pub11/NetBSD/NetBSD-current/src/usr.sbin/quot/Makefile
+http://www.hrdc.gc.ca/socpol/cfs/bulletins/jan97/man_f.shtml
+http://www.loveme.com/infopage/info23899.htm
+http://polygraph.ircache.net:8181/http_-2www.fsa.org/MutareMap.asp
+http://www.sdrt.com.cn/tiyuzhichuang/wangqiu/mingxingdangan/4/gelafu.htm
+http://home.netvigator.com/~raympoon/digital7.htm
+http://www.bemi-immobilien.de/Startseite/www.allgemeine-immobilien-boerse.de/allgemeine-ib/landkreiszwickau/Verkauf/29109700708107kirchbergvillamü/Gemeinsam/3d-service/Top-Darlehens-Konditionen/Startseite/Gemeinsam/immolink/Startseite/froben.htm
+http://www.hum.auc.dk/~magnus/MHonArc/NTSEC/frm00999.html
+http://www.hum.auc.dk/~magnus/MHonArc/NTSEC/frm09255.html
+http://www.affiliate.hpstore.hp.co.uk/do/session/380849/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/entry.asp
+http://genforum.genealogy.com/cgi-genforum/forums/skeen.cgi?265
+http://wiem.onet.pl/wiem/00f59f.html
+http://www2.ipc.pku.edu.cn/scop/data/scop.1.007.033.001.002.000.html
+http://splitrock.themes.tucows.com/cursors/adnload/15789.html
+http://splitrock.themes.tucows.com/cursors/adnload/15884.html
+http://www.cpami.gov.tw/ymsnp/animal/insect/34654text.htm
+http://lateline.muzi.net/ll/fanti/89027.shtml
+http://www.hig.se/(accessed,comment,date,header,quote)/~jackson/roxen/
+http://ftpsearch.belnet.be/ftp/packages/Linux-RedHat/up2date/rhl-6.0/alpha/README
+http://ftpsearch.belnet.be/ftp/packages/Linux-RedHat/up2date/rhl-6.0/alpha/etc/
+http://ftpsearch.belnet.be/ftp/packages/Linux-RedHat/up2date/rhl-6.0/alpha/lib/
+http://polygraph.ircache.net:8181/services/define/http_-2www.microsoft.com/http_-2www.microsoft.com/ntserver/http_-2www.netscape.com/comprod/mirror/http_-2gateway.olympcfunding.com/products.html
+http://polygraph.ircache.net:8181/services/define/http_-2www.microsoft.com/http_-2www.microsoft.com/ntserver/http_-2www.netscape.com/comprod/mirror/http_-2gateway.olympcfunding.com/products/
+http://f7.parsimony.net/forum9177/messages/638.htm
+http://f7.parsimony.net/forum9177/messages/594.htm
+http://japan.medscape.com/medscape/HIV/journal/1998/v04.n03/expert1098/expert1098.html
+http://golfonline.comfluent.net/cgi.pan$advsts&Dicky_Pride&102&lwfth&pga?golfstats
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=93&discrim=5,200,183
+http://girls.4gee.com/japan/azumi_kawashima/big_page/0023.htm
+http://www.jobvillage.com/channel/jobs/travel/travel_guide/b.4899.g.37.html
+http://www.chaos.dk/sexriddle/b/o/q/p/
+http://www.osiris.978.org/~brianr/mirrors/olga/cowpie/m/mellencamp_john/?N=D
+http://www.jpc-music.com/1695294.htm
+http://sunsite.org.uk/packages/TeX/uk-tex/macros/latex/contrib/supported/t-angles/?D=A
+http://www.shopworks.com/index.cfm/action/info/userid/000B34B5-2F17-19FE-9038010B0A0ADCF2
+http://www.bemi-immobilien.de/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Top-Darlehens-Konditionen/Gemeinsam/Startseite/Gemeinsam/Gemeinsam/versicherungen/gebaeude/Gemeinsam/Inserieren/onlineInserieren.htm
+http://www.idgnet.com/crd_playstation_254384.html
+http://www.3wbooks.de/BauerGunter/BauerGunter3406402798.htm
+http://library.cwu.edu/search/dSports+--+Washington+(State)+--+Periodicals/dsports+washington+state+periodicals/-5,-1,0,B/request&F=dsports+university+of+michigan&1,,2
+http://www.aelita.net/products/library/sitemap/Reg/Subscribe/sitemap/Reg/QuoteRegister/Default.htm
+http://topcu.tucows.com/winme/preview/76604.html
+http://tonet.com.cn/zhuanyejihua/kaoshijihua/ligonglei/dianzizhuanyezhuanke.htm
+http://tonet.com.cn/zhuanyejihua/kaoshijihua/falv2001.htm
+http://tonet.com.cn/zhuanyejihua/kaoshijihua/caijinglei/gongshangqiyeguanlibenke.htm
+http://ftp.univ-lyon1.fr/faq/by-name/cats-faq/breeds/american-curl
+http://www.videos-erotism.com/xhuge/1/hardMid3.html
+http://www.zope.org/Wikis/DevSite/Projects/CoreSessionTracking/WikiWikiWeb/map
+http://www.v2music.com/Scripts/WebObjects-ISAPI.dll/V2_New_Publisher.woa/74461000003304200000112720000087451/Labels.wo/603110000077451/2.0.0.5.0/3/Webobjects1
+http://books.hyperlink.co.uk/bookinfo/Willa_Cathers_Transforming_Vision/Brienzo/Gary_W./0945636660
+http://ftp.darenet.dk/tucows/winme/adnload/137112_28604.html
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/TEKNIIKKA/korkeakoulukirjastot/yliopisto-+ja+korkeakoulukirjastot/insin%F6%F6rit/kirjastot/
+http://www.pokers.com/asp/sp-asp/_/SZ--2/PD--10017288/posters.htm
+http://itcareers.careercast.com/texis/it/itjs/+RwwBmelXD86elmwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewhXwotoBwcaMnmowamoGnqBdGaDntdBowBodD5aqconDBaMwGAnBoDtapd5oBodDaMwDwtnainxawqqd1DBaMFqryfHfREIDzmbwwwpBmezWD86Wwww5rme9cwwwBrmeZpwww/jobpage.html
+http://berlin-charlottenburg.de/deutsch/politik/ma/062.htm
+http://www.ericsson.cl/cables/protection/index.shtml
+http://209.207.239.212/bkindex/c1007/f1401.html
+http://209.207.239.212/bkindex/c1007/f1418.html
+http://www.neoseeker.com/forums/index.php?function=edit_message&messageid=1037
+http://www.neoseeker.com/forums/index.php?function=edit_message&messageid=1199
+http://www.geocities.co.jp/SweetHome-Green/3692/PROFILE.HTML
+http://www.geocities.co.jp/SweetHome-Green/3692/MELINDEX.HTML
+http://myhome.naver.com/bora1234/photo.html
+http://www.magicvillage.de/magicvillage/computercenter/Grafik%20%26%20Layout/Software/Macintosh/Hotline/PowerBooks/
+http://student.monterey.edu/nr/panditharatnesha/world/
+http://in.egroups.com/message/Michelles__Miracles/657
+http://www.babyheirlooms.com/catalog/htmlos.cat/001248.1.5492769465
+http://republika.pl/raduczulu/counter.html
+http://adex3.flycast.com/server/socket/127.0.0.1:2800/click/OnlineCitiesSM/OnlineCitiesInteractiveCityGuides/bd378258019
+http://www.8848.net/fjnews/200007/0728/2000072811393979.htm
+http://www.chaos.dk/sexriddle/m/n/x/t/
+http://www.maastrek.de/maas/01eea86f59dac641c053/1/0/4
+http://yp.gates96.com/14/79/82/8.html
+http://yp.gates96.com/14/79/82/95.html
+http://yp.gates96.com/14/79/82/98.html
+http://yp.gates96.com/14/79/83/10.html
+http://yp.gates96.com/14/79/83/16.html
+http://yp.gates96.com/14/79/83/48.html
+http://yp.gates96.com/14/79/84/4.html
+http://yp.gates96.com/14/79/84/96.html
+http://yp.gates96.com/14/79/85/34.html
+http://yp.gates96.com/14/79/85/96.html
+http://yp.gates96.com/14/79/86/9.html
+http://yp.gates96.com/14/79/86/11.html
+http://yp.gates96.com/14/79/86/28.html
+http://yp.gates96.com/14/79/86/32.html
+http://yp.gates96.com/14/79/86/86.html
+http://yp.gates96.com/14/79/86/96.html
+http://yp.gates96.com/14/79/87/96.html
+http://yp.gates96.com/14/79/88/38.html
+http://yp.gates96.com/14/79/88/74.html
+http://yp.gates96.com/14/79/88/95.html
+http://yp.gates96.com/14/79/89/57.html
+http://autos.yahoo.co.jp/ucar/m1010/k10102006199904/g24/a101020060240158710008510205199904_4.html
+http://www02.geocities.co.jp/HeartLand-Keyaki/7483/
+http://online.excite.de/wirtschaft/katalog/32476
+http://www9.hmv.co.uk:5555/do/session/1347777/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/Top_Navigation_Bar/top_navbar.html
+http://www9.hmv.co.uk:5555/do/session/1347777/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d90_sd0_pt0.html
+http://infoserv2.ita.doc.gov/efm/efm.nsf/Sources!OpenView&Start=5&Count=30&Collapse=54
+http://users.ai-lab.fh-furtwangen.de/for_local_use_only/CD-TMFUMV/daten/beisp/05321/?D=A
+http://www.babyheirlooms.com/catalog/htmlos.cat/011629.1.0871727476
+http://www.fogdog.com/cedroID/ssd3040183241146/cgi-bin/MyFogdog
+http://www.3w-geschichte.de/OReillyJamesT/OReillyJamesT0471287237.htm
+http://www.annotate.net/html/Annotate_Directory/Top/Arts/Movies/Titles/W/World_According_to_Garp,The/
+http://dandini.cranfield.ac.uk/vl=-39536559/cl=151/nw=1/rpsv/cw/web/nw1/bargen.htm
+http://cgi.superonline.com/cgi-bin/sworld43/thread.pl/forums/sworld43/oss2000/45.html?dir=nextResponse
+http://cgi.superonline.com/cgi-bin/sworld43/get/forums/sworld43/oss2000/45.html?admin
+http://dogbert.bizit.net/debian/dists/unstable/non-US/non-free/binary-sparc/?M=A
+http://ftp.eecs.umich.edu/debian/dists/potato/main/binary-i386/misc/?D=A
+http://fi.egroups.com/message/girlscouting/3383
+http://dk.egroups.com/group/scaleauto
+http://members.tripod.lycos.co.kr/SM4/paper.htm
+http://www.jamba.nl/KNet/_KNet-BqE8j1-JC4-pv4w/browse.nl/node.0/cde7f2elw
+http://yp.gates96.com/4/6/10/47.html
+http://yp.gates96.com/4/6/10/52.html
+http://yp.gates96.com/4/6/10/96.html
+http://yp.gates96.com/4/6/11/25.html
+http://yp.gates96.com/4/6/11/61.html
+http://yp.gates96.com/4/6/11/67.html
+http://yp.gates96.com/4/6/11/93.html
+http://yp.gates96.com/4/6/12/11.html
+http://yp.gates96.com/4/6/12/28.html
+http://yp.gates96.com/4/6/12/66.html
+http://yp.gates96.com/4/6/12/81.html
+http://yp.gates96.com/4/6/12/93.html
+http://yp.gates96.com/4/6/13/86.html
+http://yp.gates96.com/4/6/13/94.html
+http://yp.gates96.com/4/6/14/17.html
+http://yp.gates96.com/4/6/14/76.html
+http://yp.gates96.com/4/6/15/61.html
+http://yp.gates96.com/4/6/16/47.html
+http://yp.gates96.com/4/6/16/71.html
+http://yp.gates96.com/4/6/17/62.html
+http://yp.gates96.com/4/6/18/1.html
+http://yp.gates96.com/4/6/18/24.html
+http://yp.gates96.com/4/6/18/28.html
+http://158.169.50.70/eur-lex/it/lif/dat/1994/it_294D1217_09.html
+http://158.169.50.70/eur-lex/it/lif/dat/1995/it_295D0928_02.html
+http://158.169.50.70/eur-lex/it/lif/dat/1997/it_297D0904_03.html
+http://www.irishnews.com/k_archive/181299/local4.html
+http://www.irishnews.com/k_archive/181299/local14.html
+http://www.irishnews.com/k_archive/181299/local16.html
+http://uk.dir.yahoo.com/Regional/U_S__States/North_Carolina/Cities/Charlotte/Business_and_Shopping/Business_to_Business/Manufacturing/Casting__Moulding__and_Machining/
+http://www.uwec.edu/Academic/English/Projects/VonHaden/
+http://www.playease.com/et/beauty/img/jijinglian/jjl054.htm
+http://www.digitaldrucke.de/(aktuell,für,marktplatz,metamorphose,raum,sense)/_fort/html/themen/kultur/digital/digital.htm
+http://pub6.ezboard.com/fzfreesubmissiondirectoryplacestosubmitforfree.showMessage?topicID=35.topic
+http://pub6.ezboard.com/fzfreesubmissiondirectoryplacestosubmitforfree.showMessage?topicID=12.topic
+http://www.emerchandise.com/browse/DISNEY/TOY/b.FAVORITES%20COMICS%20CARTOONS%20DISNEY/s.CgJlPxcV
+http://www.centc251.org/forums/aca-1/dispatch.cgi/hsi/showNextUnseen/fol/100001/1302769
+http://911codes.com/games/platform/gameboy/sect/div/cont/list_cheat/spray/y/id/0000010187/gid/0000003974/_cheats/_walkthroughs/_codes/_pc/_n64/_psx/_gameboy/_playstation/
+http://library.bangor.ac.uk/search/dPolice+regulations+--+Great+Britain/dpolice+regulations+great+britain/7,-1,0,E/frameset&F=dpolice+social+work+great+britain+congresses&1,1
+http://www02.u-page.so-net.ne.jp/ta2/grosh/Training/Training9.html
+http://ring.shibaura-it.ac.jp/archives/linux/RedHat/redhat/code/i18n/trans/?D=A
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=15,35,22,28,26
+http://ftp.nacamar.de/pub/NetBSD/NetBSD-current/pkgsrc/graphics/ruby-gl/?S=A
+http://www.academyfloral.com/state/aliro/flowers/birthdaybouquet1.html
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/KIRJASTO-+JA+TIETOPALVELUT/ammattikorkeakoulukirjastot/ammattikorkeakoulut/p%E4ij%E4t-h%E4meen+koulutuskonserni/kirjastot/
+http://www.jpc-music.com/1409509.htm
+http://chat.sportsline.com/u/ce/feature/0,1518,2565545_56,00.html
+http://chat.sportsline.com/u/ce/feature/0,1518,1675610_56,00.html
+http://www.affiliate.hpstore.hp.co.uk/do/session/380831/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hpstore.hewlett-packard.fr/gp
+http://209.207.239.212/bkindex/c1016/f1419.html
+http://209.207.239.212/bkindex/c1016/f1424.html
+http://www.sports.aol.fr/Jo/Perec_2.html
+http://www.citybrazil.com.br/go/smiguelaraguaia/transporte.htm
+http://www.fileamerica.com/states/texas/local/cameron/ptax.html
+http://www.angelfire.com/nv/bellea
+http://school.educities.org/card/a4711862.html
+http://school.educities.org/card/a60902.html
+http://school.educities.org/card/amy60630.html
+http://school.educities.org/card/aney1.html
+http://school.educities.org/card/christinelee.html
+http://school.educities.org/card/grace3721.html
+http://school.educities.org/card/jj1245j.html
+http://school.educities.org/card/jyik.html
+http://school.educities.org/card/k3813813.html
+http://school.educities.org/card/k78780606.html
+http://school.educities.org/card/kitty1snoopy.html
+http://school.educities.org/card/landy1.html
+http://school.educities.org/card/m0522.html
+http://school.educities.org/card/mark747.html
+http://school.educities.org/card/okdh.html
+http://school.educities.org/card/poppybaby.html
+http://school.educities.org/card/ry21.html
+http://www.secinfo.com/dvtBm.7a.htm
+http://www.craft-supplies.co.uk/cgi-bin/psProdDet.cgi/HT206|972959537|Deluxe_Dividers|user|0|0,0,1,1
+http://in.egroups.com/post/book-readers?act=forward&messageNum=3829
+http://www.nacion.co.cr/ln_ee/2000/enero/31/mundo10.html
+http://www.bigstar.com/news/sb/index.cfm/4ae0978g371d907g1?fa=today
+http://www.bigstar.com/cs/index.cfm/4ae0978g371d907g1?fa=privacy
+http://v2.bdnet.com/I/Cailleaux/I/Cannabissimo/fiche_serie.htm
+http://ftp.darenet.dk/tucows/winnt/adnload/12475_29978.html
+http://ftp.darenet.dk/tucows/winnt/adnload/1879_29966.html
+http://www.canit.se/(h1,k15,mail,unix,www)/support/
+http://byron17.home.chinaren.com/lit/novle/maio.htm
+http://www.emerchandise.com/browse/PAGEANTS/MUG/b.FAVORITES%20PAGEANTS/s.Q8q0znEj
+http://stulchik.list.ru/catalog/10310.html
+http://stulchik.list.ru/catalog/10967.2.html
+http://dada.tucows.com/adnload/70717_30131.html
+http://forum.rai.it/aca-finestre/dispatch.cgi/FORUM/folderFrame/100001/0/alpha/7677890
+http://webraft.its.unimelb.edu.au/196024/students/cabong/pub/?M=A
+http://www.crutchfield.com/S-fFFHlZKyKNq/shop/
+http://www.earthsystems.org/gopher/seacnet/announce97-08-03-14/1994/aug94/94-08-25-18:%20Violence%20in%20Indian%20Country%20Over%20Waste
+http://www.brio.de/BRIO.catalog/39fdb65f08c44c28273fd472aa7806e3/UserTemplate/10
+http://www.qsl.net/hj3ufa
+http://www-jl.jl.cninfo.net/jlweb/book/wxtd/gu_long/chuliuxiang/bat/009.htm
+http://www.intel.fr/support/netport/pro/21402.htm
+http://shopping.lycos.co.kr/cgi-bin/LCWB.cgi/957423999/957522544/Catalog/1375/001
+http://www01.u-page.so-net.ne.jp/qc4/sam-ft/gallerycraftspace.html
+http://rpmfind.net/linux/RPM/mandrake/usr_src_linux-2.2.16_pcmcia-cs-3.1.14_doc_Tree.html
+http://www.chrisgraef.de/chg/webdesigner_medien.html
+http://www.opengroup.com/trbooks/186/1864501634.shtml
+http://moviestore.zap2it.com/shopcart/s.1GUFVsoF
+http://moviestore.zap2it.com/browse/MOVIES/ACTIONFI/s.1GUFVsoF
+http://moviestore.zap2it.com/browse/MOVIES/PUPPET/s.1GUFVsoF
+http://ocean.ntou.edu.tw/search*chi/m387.224+M178t/m387.224+m178+t/-5,-1,0,E/buttonframe&F=m387.224+m178+m&1,,0
+http://www.egroups.com/message/BalletBuds/25
+http://link.fastpartner.com/do/session/600375/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/create/learn.htm
+http://www.vedomosti.spb.ru/2000/arts/spbved-2180-art-27.html
+http://www.vedomosti.spb.ru/2000/arts/spbved-2180-art-42.html
+http://www.vedomosti.spb.ru/2000/arts/spbved-2180-art-45.html
+http://www.vedomosti.spb.ru/2000/arts/spbved-2180-art-46.html
+http://www2.ipc.pku.edu.cn/scop/rsgen.cgi?pd=3nla
+http://www.allkorea.co.jp/cgi-bin/allkorea.front/972959900763/Catalog/1000006
+http://www.allkorea.co.jp/cgi-bin/allkorea.front/972959900763/Catalog/1000031
+http://fi.egroups.com/message/gailporter/199
+http://fi.egroups.com/message/gailporter/222
+http://www.egroups.com/messages/X-Air_Ultralight_Aircraft/359
+http://dia.tucows.com/winme/adnload/136838_28375.html
+http://dia.tucows.com/winme/adnload/136846_28383.html
+http://www.letsmusic.co.kr/directory/weblink/weblink_list/1,1011,100000000186810,00.html
+http://www.smcworld.com/smcworld/bp/large/0744_2_1611_2_1611b.html
+http://news.pchome.com.tw/ettoday/entertainment/20001028/index-20001028155543020439.html
+http://www2.stas.net/lostlane/J.html
+http://allmacintosh.arrakis.es/utilsmac_rating.html
+http://novel.hichinese.net/zt/zpj/k/kelisidi/kill/008.htm
+http://194.174.50.23/cgi-bin/FisRun/InsertExhibitorIntoNotebook/1/interpack99/d/2891
+http://www.loisirs.ch/jifmuf/14/roedrz.html
+http://www.linux.com/networking/server/business/operating_system/learning/consumer/
+http://dandini.cranfield.ac.uk/vl=-39685335/cl=158/nw=1/rpsv/cw/www/faqs.htm
+http://blisty.internet.cz/1250/9901/19990108a.html
+http://www.staroriental.net/nav/soeg/ihf,aai,n2,247,Electric+Wave+Girl+1998.html
+http://www.multimania.com/excave/vicking.html
+http://students.lsu.edu/students/main.nsf/Pages/CSISAJ1!OpenDocument&ExpandSection=5,14,21,12
+http://www.secinfo.com/dWXc8.bz.htm
+http://www.secinfo.com/dWXc8.9d.htm
+http://bbs.ee.ntu.edu.tw/boards/RomanceNovel/11/2/9/2/
+http://ftp.nacamar.de/pub/NetBSD/packages/1.4/amiga/emulators/?M=A
+http://no.egroups.com/subscribe/windows98
+http://ftp.dei.uc.pt/pub/netscape/communicator/english/4.76/unix/unsupported/linux20_libc5/?D=A
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/www.gsb.stanford.edu/sloan/sloan_fellows.html
+http://apple.excite.com/entertainment/music/artists_and_genres/alternative_rock/grunge/stone_temple_pilots/merchandise/
+http://home.sprynet.com/~tales/asw2.html
+http://fi.egroups.com/post/audiovision?act=reply&messageNum=145
+http://www.zema.ru/post/forum/komi_respublika/usinsk/messages/712
+http://opac.lib.rpi.edu/search/ddesert+ecology/-5,-1,0,B/browse
+http://www.arm.com/sitearchitek/support.ns4/html/sdt_debug!OpenDocument&ExpandSection=6,32,7,5
+http://www.linux.com/networking/network/technology/security/community/open_source/
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=9,33,15,36,22
+http://isbn.nu/0505523892/borders
+http://www.informika.ru/text/database/geom/Draw/ris/ris34_1.htm
+http://caselaw.lp.findlaw.com/casecode/uscodes/42/chapters/77/subchapters/iii/parts/h/sections/section_6374_notes.html
+http://www.cyd.com.cn/zqb/19991104/GB/9672^Q805.htm
+http://providenet.tukids.tucows.com/win95nt/9-12/adnload/132963_46167.html
+http://www.chaos.dk/sexriddle/e/o/g/k/i/
+http://www2.brent.gov.uk/planning.nsf/013459d30f2ad00680256623005fcc0a/8af30b42469a1215802568720046524a!OpenDocument&ExpandSection=16,13,11,9,15
+http://jje.subportal.com/sn/Multimedia_and_Graphics/MPEG_Audio_Players_and_Editors/9126.html
+http://www.ropnet.ru/HyperNews/edit-response.pl/case/2856.html
+http://www.eveclub.com/cgi-bin/eveclub.front/972959508447/Catalog/1000045
+http://itcareers.careercast.com/texis/it/itjs/+rwwBmeO9D86MwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewDXnnqrDoqwcaiGoBnapd5oBodDaxw5nmamdq1MnDBwBodDawppcoqwBodD5a15naM15BapGdm1qBodDawxcnaMFqtPfRRZNDzme8xwwwpBme7WD86eLrwww5rm-mwwBrmeZpwww/jobpage.html
+http://www.iucr.ac.uk/iucr-top/journalsonline/iucr-top/cif/software/hiccup/prods/?M=A
+http://lists.omnipotent.net/mysql/199707/msg00381.html
+http://www.yescall.co.kr/kyungheein/
+http://minyos.its.rmit.edu.au/~s9763278/sparks/sparks.html
+http://www.movieguide.com/pressroom/events/nbcpresstour/festival_nbcpresstour9.html
+http://www.gamers.net/game/190940/reviews
+http://www.staroriental.net/nav/soeg/ihf,aai,n2,198,Electric+Wave+Girl+1998.html
+http://marysz.freeservers.com/cgi-bin/c/736/64/dXNlcmJhbm5lcg==/gn/6616/
+http://subversion.tigris.org/source/browse/subversion/subversion/libsvn_delta/delta.h?annotate=1.34&sortby=rev
+http://subversion.tigris.org/source/browse/subversion/subversion/libsvn_delta/delta.h?annotate=1.28&sortby=rev
+http://sunsite.org.uk/public/public/packages/WWW/spinner/?D=A
+http://sunsite.org.uk/public/public/packages/WWW/spinner/untared/
+http://www.realbig.com/miata/miata/1998-01/1635.html
+http://cky.8k.com/cgi-bin/framed/1359/info/jess.html
+http://cky.8k.com/cgi-bin/framed/1359/info/bran.html
+http://www.loisirs.ch/jifmuf/10/bhcqud.html
+http://naver22.jrnaver.co.kr/Entertainment_and_Arts/Design_Arts/Architecture/Organizations/
+http://www.zing.com/member/?name=birchpole&c=1
+http://student.monterey.edu/nr/porrasjohnny/campus/
+http://ftp.lip6.fr/pub/FreeBSD/development/FreeBSD-CVS/ports/misc/peq/files/patch-ab,v
+http://www.multimania.com/lesoir2/news/sept99/quake4.htm
+http://www.multimania.com/lesoir2/news/sept99/2309-12.txt
+http://www.multimania.com/lesoir2/news/sept99/0609-06.txt
+http://www.multimania.com/lesoir2/news/sept99/1309-13.txt
+http://homepage1.nifty.com/shiraishi/school/school2.htm
+http://ring.htcn.ne.jp/pub/NetBSD/NetBSD-current/pkgsrc/mbone/sdr/pkg/PLIST
+http://www.chaos.dk/sexriddle/m/c/z/b/
+http://www.chaos.dk/sexriddle/m/c/z/p/
+http://map.ipc.co.jp/asp/onmap/r/new/g-26/f-523824/
+http://www.nissan.co.jp/RENAULT-DEALERS/PASSPORT/view.cgi/admission/972959650--
+http://novel.hichinese.net/xd/gt/zpj/l/liangfengyi/jingrong/010.htm
+http://www.tvstore.com/browse/TV/MAGNET/s.l03qOWiP
+http://www.tvstore.com/browse/TV/KEYCHAIN/s.l03qOWiP
+http://www.gbnf.com/genealog2/burt/html/d0002/I1199.HTM
+http://www.gbnf.com/genealog2/burt/html/d0006/I1187.HTM
+http://www.gbnf.com/genealog2/burt/html/d0004/I1521.HTM
+http://src.openresources.com/debian/src/graphics/HTML/R/HVcreate.html
+http://yomama.tgm.ac.at/doc/susehilf/gnu/vip/Changing.html
+http://www.science.uva.nl/pub/NetBSD/NetBSD-current/pkgsrc/sysutils/gmc/pkg/
+http://news.fm365.com/zonghe/20001009/156610.htm
+http://homepage1.nifty.com/tojo/shin13.htm
+http://www.sf.digitalcity.com/naplesfl/personals/browse.dci?cat=wsw&sort=t
+http://plat.debian.or.jp/debian/dists/woody/non-free/binary-hppa/otherosfs/?M=A
+http://people.freebsd.org/~knu/cgi-bin/cvsweb.cgi/ports/databases/gdbm/distinfo?only_with_tag=RELEASE_4_1_0
+http://bbs.csie.ntu.edu.tw/txt/Emprisenovel/ebooks/mystery/alisanderla/wsyz/013.txt
+http://www.legis.state.ia.us/GA/78GA/Legislation/SCR/00000/SCR00018/?M=D
+http://www.mapion.co.jp/custom/AOL/admi/23/23104/kaminagoya/2chome/index-2.html
+http://ciscom.cnet.com/hardware/member/entry/0,10285,0-1069-419-1544825,00.html
+http://wow-online.vhm.de/Regional/Grossbritannien/Kunst.html
+http://www.cs.rit.edu/~hpb/Man/_Man_Openwin_html/html2/sigaction.2.html
+http://in.egroups.com/message/talksigncreate/287
+http://rainforest.parentsplace.com/dialog/thread.pl/newclubfoot8/19.html?dir=nextThread
+http://ftp.jp.debian.org/debian-non-US/dists/potato/non-US/main/binary-arm/?N=D
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=baumelte&l=de
+http://www.chaos.dk/sexriddle/i/f/p/k/h/
+http://unionsoft.narod.ru/3d/anatomy/pages/head1.htm
+http://src.openresources.com/debian/src/electronics/acs_021.orig/acs-021.orig/
+http://www.mapion.co.jp/custom/AOL/admi/23/23111/takagicho/2chome/index-45.html
+http://dennou-q.geo.kyushu-u.ac.jp/library/Linux/debian-jp/dists/unstable/contrib-jp/binary-m68k/tex/?N=D
+http://rapidus.tucows.com/winnt/adnload/54123_28460.html
+http://193.207.119.193/MV/gazzette_ufficiali/303-99/8.htm
+http://www.emerchandise.com/help_security/b.TV%20FRASIER/s.LoO0xS99
+http://gpul.org/ftp/os/linux/cd-images/other/ISO/suse/?M=A
+http://opac.lib.rpi.edu/search/arush+sean+c/-17,-1,0,E/frameset&arush+homer+f&1,,0
+http://genforum.genealogy.com/cgi-genforum/forums/griffin.cgi?3823
+http://www.leo.org/leoclick/dce2b1c893db6a8193428ecad9ecd878+L+1__
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=55&discrim=178,230,174
+http://www.msb.malmo.se/search*swe/aKling,+Rolf/akling+rolf/7,-1,0,B/browse
+http://retailer.gocollect.com/do/session/1912785/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/checkout/shopping_cart.asp
+http://st3.yahoo.co.jp/nihondo/k4932828003023.html
+http://webtools.familyeducation.com/whatworks/review/front/0,2562,1-10641-2316_-7233-3,00.html
+http://www.bretagne-online.com/telegram/htdocs/archive/1997/19970618/sommaire/stpoldeleon.htm
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=234&discrim=235,230,183
+http://www.yagoo.co.kr/stats/batting.asp?Mlbmanid=HAMPAT7709
+http://www.linux.com/networking/network/new/website/suse/SAP/
+http://www.linux.com/networking/network/new/website/suse/security/
+http://javatest.a-net.nl/servlet/pedit.Main/http://www.cdc.gov/ncidod/dpd/parasiticpathways/drinkingwater.htm
+http://www.across.or.jp/shizuoka/nbbs.cgi/seibu:n52/post
+http://www.across.or.jp/shizuoka/nbbs.cgi/seibu:n52/450
+http://www.across.or.jp/shizuoka/nbbs.cgi/seibu:n52/607
+http://dangerous.co.kr/www.sony.co.jp/ProductsPark/Consumer/Peripheral/MDData/page6.html
+http://www2.sega.co.jp/bbs/article/s/sports/47/xvwixh/jlvcgk.html
+http://troy.lib.sfu.ca/search/alondon+mathematical+society/alondon+mathematical+society/-5,-1,0,B/frameset&F=alondon+m+c+s&2,,3
+http://pub14.ezboard.com/fbrlproductionsfrm10.showAddTopicScreenFromWeb
+http://rex.skyline.net/html/Computers_-_Monitors.html?16,computers,radio,electronics,communication
+http://rex.skyline.net/html/Software_-_Developers.html?20,computers,radio,electronics,communication
+http://ftp.cwi.nl/static/publications/reports/abs/MAS-R9815.html
+http://www.jt.com.br/noticias/98/09/28/sd2.htm
+http://www.kentuckyconnect.com/heraldleader/news/080899/sportsdocs/08chuck.htm
+http://pix.egroups.com/post/ipe?act=forward&messageNum=5302
+http://tulips.ntu.edu.tw/search*chi/cHT392+Un3/cht++392+un3/-5,-1,,B/browse
+http://magazines.sina.com/gourmet/contents/199912/199912-006_3_gb.html
+http://collection.nlc-bnc.ca/100/201/300/january/2000/00-06-05/sanctuary.html
+http://collection.nlc-bnc.ca/100/201/300/january/2000/00-06-05/blue1.html
+http://www.vorlesungen.uni-osnabrueck.de/informatik/pt/code/DiagramPalettes/Components.dpalette2/Image45
+http://www.vorlesungen.uni-osnabrueck.de/informatik/pt/code/DiagramPalettes/Components.dpalette2/Image5
+http://playsite.top263.net/software/hh-13.htm
+http://www.dispatch.co.za/1998/12/21/sport/MISS.HTM
+http://www.allhealth.com/parentsplace/send/0,3288,14-844-1-fertility-INFERTILITY,00.html
+http://www.tucows.telia.no/win2k/preview/37705.html
+http://www.peopledaily.co.jp/9803/09/current/newfiles/j1020.html
+http://shopping.lycos.co.kr/cgi-bin/LCWB.cgi/957424007/957522556/Catalog/1320/001
+http://shopping.lycos.co.kr/cgi-bin/LCWB.cgi/957424007/957522556/Catalog/1321/001
+http://shopping.lycos.co.kr/cgi-bin/LCWB.cgi/957424007/957522556/Catalog/1328/001
+http://shopping.lycos.co.kr/cgi-bin/LCWB.cgi/957424007/957522556/Catalog/1350/001
+http://shopping.lycos.co.kr/cgi-bin/LCWB.cgi/957424007/957522556/Catalog/1359/001
+http://shopping.lycos.co.kr/cgi-bin/LCWB.cgi/957424007/957522556/ProductView/26897
+http://www.uftree.com/UFT/WebPages/Don_MacFarlane/FEB99/d1/i0001285.htm
+http://wap.jamba.de/KNet/_KNet-n4B8j1-DFd-13bgt/showInfo-jambabanner.de/node.0/cde7f1uou
+http://launchbase.com/Shopping/Visual_Arts/entertainment/information/Politics.htm
+http://launchbase.com/Shopping/Visual_Arts/entertainment/shopping/Electronics.htm
+http://www.aoyun.sina.com.cn/news/sports/table/2000-09-15/1/4622.shtml
+http://www.eggerwirt.at/1Root/Kontinent/6/Staat/7/Bundesland/21/Ort/129509/Homepage/m_homepage...1.html
+http://198.103.152.100/search*frc/dSociologie+rurale+--+Ontario/dsociologie+rurale+ontario/-5,-1,0,B/frameset&F=dsociologie+religieuse+islam&1,,0
+http://msn.excite.co.jp/travel/the_country/kinki/wakayama/hot_spring_of_accommodations/inn_tourist_home_in_wakayama?summary=false
+http://search.ibm.co.jp/as400/year2000/v3r2.html
+http://www.allgemeine-immobilien-boerse.de/nordrhein-Westfalen/Muehlheim-ruhr/Verkauf/Allgemeine-IB/Startseite/3d-service/Private-IB/Startseite/Gemeinsam/Super-Zins-Konditionen/anforderungsformular.htm
+http://spaceports.tucows.com/winnt/adnload/78908_28797.html
+http://www.trax.nilex.co.uk/trax.cgi/A1S/A2R/A3R/B1S/A1D/A1S/
+http://www.babyheirlooms.com/catalog/htmlos.cat/041130.1.3206884924
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/music/misc/thoughts/lit/misc/colorart/misc/freespeech.html
+http://www.cs.rit.edu/~hpb/Lectures/2000/JRMS_590/all-2.7.html
+http://www.cs.rit.edu/~hpb/Lectures/2000/JRMS_590/all-4.11.html
+http://www.refdag.nl/kl/990615klfo01.html
+http://pub20.ezboard.com/ftheimperiumknightsfrm11.showMessage?topicID=9.topic
+http://retailer.gocollect.com/do/session/1912767/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/advanced_search.asp
+http://www.thestateofcolorado.com/saudealersnew.html
+http://awelymor.weblogs.co.uk/sdb/en/html/ftp://ftp.suse.com/pub/suse/i386/6.2/suse/n1/
+http://www.mirror.kiev.ua:8083/paper/2000/21/1251/text/21-13-3.htm
+http://www.recipezaar.com/browse/0110FC1070110A301109901109E00F06D
+http://www.linux.com/networking/network/vpn/server/Unix/
+http://www.gasex.com/main.html?m4m.gallery.twinks
+http://www.xtdnet.nl/listarch/linux-router/1998-05-01/nav00046.html
+http://www.fogdog.com/cedroID/ssd3040183325831/cgi-bin/CedroCommerce?func=EditBasket
+http://www.totalmarketing.com/an/basket.pl/cancel/xwxm6773.94076
+http://ciaoweb.tucows.com/winnt/adnload/56695_29112.html
+http://www.brio.de/BRIO.catalog/39fe2f6006e4fc48273fd472aa7806e0/UserTemplate/1
+http://retailer.gocollect.com/do/session/1912715/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/top_ten.asp?pagenum=2
+http://retailer.gocollect.com/do/session/1912715/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/dealer_lookup.asp
+http://www.streetprices.com/Electronics/Computer_Hardware_PC/Motherboards/ATX/Slot1/Via_Pro133/sortproductbymake/sortcategorybylowprice/
+http://www.streetprices.com/Electronics/Computer_Hardware_PC/Projectors/MAKE+CTX/sortdetailbystock/sortproductbyhighprice/sortcategorybycount/SP318392.html
+http://www.multimania.com/egypt95/img0017.htm
+http://dic.empas.com/show.tsp/?q=fourteenthly&f=B
+http://linux2.ipc.pku.edu.cn/scop/pdb.cgi?sid=d1repc2
+http://www.schlagertempel.de/RobertPayer/B00000B8D2.htm
+http://www.cricinfo.com/link_to_database/INTERACTIVE/MAGAZINE/1996-97/SL_IN_NZ/SL_IN_NZ_FEEDBACK_1.html
+http://mediate.magicbutton.net/do/session/625637/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-top50.html
+http://www.clickm.dk/Clickmusic_Web_Guide/Bands_and_Artists/B/Better_Than_Ezra/
+http://www.clickm.dk/Clickmusic_Web_Guide/Bands_and_Artists/B/Breeders,_The/
+http://www.maastrek.de/maas/71eb3baf4c78ed98ef94/1/0/4
+http://www.trnonline.com/archives/1999archives/07221999/obits/24620.shtml
+http://www.recipezaar.com/browse/0110FC1070110A100F06D0110A00110A3
+http://www.areaguide.net/addlisting.asp?book=box&CatID=516
+http://webraft.its.unimelb.edu.au/196023/students/lucym/
+http://sunsite.org.uk/public/0-Most-Packages/quake/utils/frontends/qshel15b.txt
+http://pub14.ezboard.com/flfiaglarafabianisagoddess.emailToFriend?topicID=858.topic
+http://www.realize.com/am4d0481.htm,qt=e784fe2f=2a38a234-4-7cf2ef-1-1-0-3--
+http://www.realize.com/am7bcd81.htm,qt=e784fe2f=2a38a234-4-7cf2ef-1-10-0-3--
+http://mailman.real-time.com/rte-crossfire/1993/Dec/msg00022.html
+http://mailman.real-time.com/rte-crossfire/1993/Dec/msg00000.html
+http://mailman.real-time.com/rte-crossfire/1993/Dec/msg00009.html
+http://www.eallinfo.com/A55782/sameeron.nsf/homeFood!OpenPage&ExpandSection=8,4,3,6
+http://www.ami.dk/udgivelser/emne/36.html
+http://www-x500-1.uni-giessen.de:8890/Lcn%3dKai%20Cheong%20HO,ou%3dEstates%20Management%20Office,o%3dHong%20Kong%20University%20of%20Science%20and%20Technology,c%3dHK
+http://ftp.telepac.pt/pub/cpan/modules/by-module/DBD/DMOW/?D=A
+http://members.se.tripod.de/aah/jochumsen/per02614.htm
+http://www.academyfloral.com/state/cacat/flowers/funeralofferingshare.html
+http://www.hotelboulevard.com/fr/paris/standard/htmlb877e62937802c0678f4638130be1ef0/sessionLang/ANG/prov/browse/cp/75013/resultatSearch.html
+http://www.alsapresse.com/jdj/00/03/24/AK/article_4.html
+http://www.mairie-montreuil93.fr/ville_pratique/environ/democrat/printemps/_vti_cnf/interstice.htm
+http://variety.studiostore.com/help/b.FAVORITES%20COMICS%20CARTOONS%20POWERPUFF/s.UAREyMtL
+http://ftp.sektornet.dk/tucows/winme/adnload/137341_28799.html
+http://www.eveclub.com/cgi-bin/eveclub.front/972959532302/Catalog/1000046
+http://www.eveclub.com/cgi-bin/eveclub.front/972959532302/ClubBoard/list/1000022
+http://findmail.com/post/geewhiz?act=reply&messageNum=2039
+http://orders.mkn.co.uk/toy/rattles/order/now.en$NOK?what-bells=1
+http://www.buybuddy.com.au/sleuth/26/1/502/10134/
+http://spokesmanreview.sportshuddle.com/sports/baseball/playbetter/ask-expert/vincent3.asp
+http://ant.i.hosei.ac.jp/Ant.WWW/PCD0420/HTMLE/29.html
+http://ant.i.hosei.ac.jp/Ant.WWW/PCD0420/HTMLE/34.html
+http://builder.hw.net/frmRestDir/0,1112,'1~21~325~1~S~074800~90270',00.html
+http://builder.hw.net/frmRestDir/0,1112,'1~21~325~1~S~074800~09890',00.html
+http://dennou-h.ees.hokudai.ac.jp/library/Linux/debian-jp/dists/hamm-jp/non-free/binary-i386/games/?M=A
+http://www.peopledaily.com.cn/GB/paper68/1469/236625.html
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/koffice/kformula/BracketElement.cc?hideattic=1&sortby=rev
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/koffice/kformula/FractionElement.cc?hideattic=1&sortby=rev
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/koffice/kformula/MIMETYPE-Format?hideattic=1&sortby=rev
+http://linuxberg.ii.net/conhtml/preview/7963.html
+http://213.36.119.69/do/session/152992/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/reserver/hotels.html
+http://213.36.119.69/do/session/152992/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.spycamera.com/webcam/
+http://ftp.netc.pt/pub/idgames/levels/doom/d-f/deathme.txt
+http://ftp.netc.pt/pub/idgames/levels/doom/d-f/dork.txt
+http://ustlib.ust.hk/search*chi/dsea+stories/dsea+stories/-5,-1,0,B/browse
+http://members.fortunecity.com/skinweaver/nf/nfpin01.htm
+http://se.egroups.com/group/French_
+http://www.gencat.es/cgi-bin/bc/drawer.cgi/LD/0074/L00465?101
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/projects/ogl-sample/main/gfx/lib/glut/glut_shapes.c?sortby=author
+http://www.teacherformation.org/html/od/facilitators.cfm/task1,about/discussion_id,2/xid,9456/yid,7276398
+http://genforum.genealogy.com/cgi-genforum/forums/getchell.cgi?230
+http://www9.hmv.co.uk:5555/do/session/1347795/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d100_sd0_pt0.html
+http://www.brd.net/brd-cgi/brd_multimedia/bildbearbeitung/WZ01K0DJ/beurteilung/ci=972850465.htm
+http://retailer.gocollect.com/do/session/1912745/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/affiliate_network.asp
+http://www.fao.org/icatalog/orders/basket.asp?prev2=yes&aries_id=1310
+http://www.realestate-mls.com/list.cgi/VACANT_LAND|WATERFRONT|Edenville!Midland!MI
+http://www.geocities.co.jp/SilkRoad-Desert/1661/profile/profile.html
+http://hp-partner.whowhere.lycos.com/hp/chick/com/nj/
+http://hp-partner.whowhere.lycos.com/hp/chick/com/next/
+http://hp-partner.whowhere.lycos.com/hp/chick/com/nightflight/
+http://www.emerchandise.com/browse/FRIENDS/TSHIRT/20/10/b.TV%20FRIENDS/s.kGIgjr5i
+http://dk.egroups.com/group/anarchymcgill
+http://bbs.gznet.edu.cn/cgi-bin/getannounce//groups/GROUP_3/WinNT_Win2k/smthbbs/Dir002
+http://de.excite.de/computer/katalog/12947
+http://www.bizline.co.kr/library/data/002/001/007/008/020/002/000017.html
+http://www.bizline.co.kr/library/data/002/001/007/008/020/002/000046.html
+http://saleonall.com/cat/OPTOMA/6492/video/projectors/145336/oneprod.html
+http://sun1.rrzn-user.uni-hannover.de/jgaertner/matlab/help/techdoc/newfeat/ch213.html
+http://sun1.rrzn-user.uni-hannover.de/jgaertner/matlab/help/techdoc/newfeat/newfeat.html
+http://excite.de/wirtschaft/katalog/37737
+http://www.digitaldrucke.de/(aktuell,kino,kultur,werbung)/_fort/html/themen/aktuell/events/events.htm
+http://www.digitaldrucke.de/(aktuell,kino,kultur,kunst)/suche/uebersicht.html
+http://www.online.kokusai.co.jp/Stock_corner/V0043566/wrd/G500/stock_corner/stock_corner.html
+http://yp.gates96.com/4/37/0/92.html
+http://yp.gates96.com/4/37/1/3.html
+http://yp.gates96.com/4/37/1/38.html
+http://yp.gates96.com/4/37/1/58.html
+http://yp.gates96.com/4/37/2/21.html
+http://yp.gates96.com/4/37/3/56.html
+http://yp.gates96.com/4/37/3/68.html
+http://yp.gates96.com/4/37/3/79.html
+http://yp.gates96.com/4/37/4/1.html
+http://yp.gates96.com/4/37/4/48.html
+http://yp.gates96.com/4/37/4/99.html
+http://yp.gates96.com/4/37/5/27.html
+http://yp.gates96.com/4/37/6/1.html
+http://yp.gates96.com/4/37/6/7.html
+http://yp.gates96.com/4/37/6/80.html
+http://yp.gates96.com/4/37/7/0.html
+http://yp.gates96.com/4/37/7/5.html
+http://yp.gates96.com/4/37/7/9.html
+http://yp.gates96.com/4/37/7/12.html
+http://yp.gates96.com/4/37/7/49.html
+http://yp.gates96.com/4/37/7/97.html
+http://yp.gates96.com/4/37/8/15.html
+http://yp.gates96.com/4/37/8/32.html
+http://yp.gates96.com/4/37/8/62.html
+http://yp.gates96.com/4/37/8/76.html
+http://yp.gates96.com/4/37/8/96.html
+http://yp.gates96.com/4/37/9/12.html
+http://yp.gates96.com/4/37/9/14.html
+http://yp.gates96.com/4/37/9/23.html
+http://yp.gates96.com/4/37/9/78.html
+http://yp.gates96.com/4/37/9/80.html
+http://cgi.cnn.com/US/9601/state_union_poll/state_union_speech/pm/
+http://freethemes.netc.pt/cursors/adnload/16904.html
+http://freethemes.netc.pt/cursors/preview/16926.html
+http://freethemes.netc.pt/cursors/adnload/16953.html
+http://library.bangor.ac.uk/search/dTelevision+broadcasting+of+news+--+Wales/dtelevision+broadcasting+of+news+wales/-17,-1,0,B/frameset&F=dtelevision+broadcasting+moral+and+ethical+aspects&1,1
+http://home.baoding.cn.net/~snowcxm/photoshop/newpage6tp.htm
+http://home.baoding.cn.net/~snowcxm/photoshop/newpage6xq2.htm
+http://dennou-q.geo.kyushu-u.ac.jp/library/Linux/debian-jp/dists/woody/non-free-jp/binary-sparc/otherosfs/?D=A
+http://www.tucows.ch/winnt/toolnt_size.html
+http://www.sdinfonet.com.cn/379/26/379269983.htm
+http://www.sdinfonet.com.cn/379/26/379269980.htm
+http://www.egroups.com/message/wdf/3368
+http://de.excite.de/bildung/katalog/35821
+http://kidneyfailure.shn.net/content/article/1677.57596
+http://kidneyfailure.shn.net/content/article/1677.57625
+http://kidneyfailure.shn.net/content/article/1677.57517
+http://kidneyfailure.shn.net/content/article/1677.57456
+http://kidneyfailure.shn.net/content/article/1677.57562
+http://dia.tucows.com/winme/adnload/138490_29803.html
+http://www.nhic.or.kr/netbbs/Bbs.cgi/nhic31062/lst/qqo/004A
+http://www.nhic.or.kr/netbbs/Bbs.cgi/nhic31062/qry/zka/B2-kB23p/pno/0/qqatt/^
+http://www.nhic.or.kr/netbbs/Bbs.cgi/nhic31062/qry/zka/B2-kB2-n/pno/0/qqatt/^
+http://www.nhic.or.kr/netbbs/Bbs.cgi/nhic31062/qry/zka/B2-kB2-o/pno/0/qqatt/^
+http://dk.egroups.com/message/tw2002/3626
+http://dk.egroups.com/message/tw2002/3644
+http://www.spiral.at/Katalog/Artikel/8908435/
+http://www.spiral.at/Katalog/Artikel/8908842/
+http://168.160.224.62/insurance/200006/10/114941.asp
+http://168.160.224.62/insurance/200006/10/114219.asp
+http://tucows.soneraplaza.nl/termnt_license.html
+http://pub13.ezboard.com/ubelegruin.showPublicProfile?language=EN
+http://troy.lib.sfu.ca/search/tbiometrics/tbiometrics/-5,-1,0,B/exact&F=tbiometrical+genetics+the+study+of+continuous+variation&1,2/limit
+http://futures.homeway.com.cn/lbi-html/news/content/20001013/172026.shtml
+http://jproxy.uol.es/jproxy/http://www.channel6000.com/sh/sports/columnist/stories/columnists-20001030-154321.html
+http://www.linux.com/networking/network/free/release/community/development/
+http://pub17.ezboard.com/fskysurfingskysurfersubb.showAddReplyScreenFromWeb?topicID=4.topic
+http://ring.tains.tohoku.ac.jp/pub/linux/debian/debian-jp/dists/woody/contrib-jp/binary-m68k/oldlibs/?D=A
+http://10000downloads.subportal.com/sn/Network_and_Internet/Misc__Communications_Tools/12507.html
+http://www.hbdaily.com.cn/ctdsb/19991101/GB/ctdsb^1042^06^Ct06b08.htm
+http://cytobase.cnusc.fr:8101/textes/PURDmail/1998-12/nav00129.html
+http://www.brio.de/BRIO.catalog/39fe2f73050d53aa2741d472aa7806d2/UserTemplate/9
+http://www.anekdot.ru:8084/an/an0007/t000731.html
+http://statweb.byu.edu/sasdoc/sashtml/gref/z0265802.htm
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/linux/drivers/char/ftape/Makefile?only_with_tag=davem-cvs-merge
+http://www.intellicast.com/Golf/World/UnitedStates/Southeast/NorthCarolina/Hawksnest/WINDcast/d1_00/bannerAd.shtml
+http://dailynews.sina.com.hk/sinaNews/wiser/hkStock/2000/0720/1418727.html
+http://ftp.dti.ad.jp/pub/lang/CPAN/authors/id/A/AG/AGUL/?S=A
+http://link.fastpartner.com/do/session/600392/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/jobpilot.php
+http://link.fastpartner.com/do/session/600392/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/smartguy.php
+http://citeseer.nj.nec.com/cidcontext/1024594
+http://www.burstnet.com/ads/ad4820b-map.cgi/1395444997
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/kdeutils/kpm/proc.h?r1=1.6&only_with_tag=HEAD
+http://www.uftree.com/UFT/WebPages/JenHawkins/ALL/d0/i0001501.htm
+http://www.uftree.com/UFT/WebPages/JenHawkins/ALL/d0/i0000641.htm
+http://www.uftree.com/UFT/WebPages/JenHawkins/ALL/d1/i0000932.htm
+http://www.uftree.com/UFT/WebPages/JenHawkins/ALL/d1/i0000762.htm
+http://www.uftree.com/UFT/WebPages/JenHawkins/ALL/d1/i0000997.htm
+http://www.uftree.com/UFT/WebPages/JenHawkins/ALL/d1/i0001325.htm
+http://www.uftree.com/UFT/WebPages/JenHawkins/ALL/nindex.htm
+http://www.primenet.com/~g-lady/Farewell/_borders/
+http://imasy.or.jp/~iwao/hokkaido/kushiro.html
+http://citeseer.nj.nec.com/nrelated/0/208436
+http://www.zeal.com/Arts___Entertainment/Literature/Authors/Lovecraft__H_P_/Books/Cthulhu_Campus_Crusade_for_Cthulhu/
+http://ftp1.se.debian.org/debian/dists/woody/contrib/binary-mipsel/mail/?M=A
+http://ftp1.se.debian.org/debian/dists/woody/contrib/binary-mipsel/mail/?S=A
+http://webtools.familyeducation.com/whatworks/item/front/0,2551,1-10698-1981-,00.html
+http://www.affiliate.hpstore.hp.co.uk/do/session/380859/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/REGISTRATION/entry.asp
+http://www.collectingnation.com/cgi-bin/bn/view_feedback.mod/pn?HANDLE=pokeweed
+http://www.egroups.com/messages/Future-History-L/213
+http://www.egroups.com/message/Future-History-L/192
+http://www.burstnet.com/ads/cb7826a-map.cgi/1384588733
+http://www.cs.com.cn/csnews/articles/142_23823.htm
+http://search.yam.com.tw/en/new/edu/hs/voca/tpc_vs/
+http://ftp.univie.ac.at/packages/tex/macros/latex2e/contrib/supported/vmargin/?D=A
+http://citeseer.nj.nec.com/cidcontext/3145269
+http://yp.gates96.com/11/72/80/34.html
+http://yp.gates96.com/11/72/80/36.html
+http://yp.gates96.com/11/72/80/76.html
+http://yp.gates96.com/11/72/81/26.html
+http://yp.gates96.com/11/72/81/67.html
+http://yp.gates96.com/11/72/83/68.html
+http://yp.gates96.com/11/72/84/29.html
+http://yp.gates96.com/11/72/84/39.html
+http://yp.gates96.com/11/72/85/56.html
+http://yp.gates96.com/11/72/85/63.html
+http://yp.gates96.com/11/72/85/96.html
+http://yp.gates96.com/11/72/86/3.html
+http://yp.gates96.com/11/72/86/28.html
+http://yp.gates96.com/11/72/86/59.html
+http://yp.gates96.com/11/72/86/63.html
+http://yp.gates96.com/11/72/88/43.html
+http://yp.gates96.com/11/72/89/8.html
+http://yp.gates96.com/11/72/89/13.html
+http://yp.gates96.com/11/72/89/20.html
+http://cometweb01.comet.co.uk/do!session=132039&vsid=700&tid=20&cid=37030&mid=1000&rid=1060&chid=1713&url=eqqLmwlGltt5tkkHbqpLZXmLbkZHljlKaltLkilLXalKfkaLbukKeqjLi1
+http://iworld.freethemes.com/savers/adnload/77213.html
+http://iworld.freethemes.com/savers/adnload/35420.html
+http://www.questlink.com/QL/CDA/Research/ProductBrief/1,1768,0_11201_353170_43264,00.html
+http://www.questlink.com/QL/CDA/Research/ProductBrief/1,1768,0_11201_353170_43305,00.html
+http://www2.eunet.lv/library/iso/HISTORY/RUSSIA/Mirrors
+http://nathanael.upi.jussieu.fr/tele6.nsf/autres+centres+de+formations!OpenPage&ExpandSection=10,3,5,16,14,6
+http://nathanael.upi.jussieu.fr/tele6.nsf/autres+centres+de+formations!OpenPage&ExpandSection=17,3,5,16,14,6
+http://opac.lib.rpi.edu/search/dnatural+history+united+states+historiography+dictionaries/-17,-1,0,B/browse
+http://opac.lib.rpi.edu/search/dnatural+history+united+states+historiography+dictionaries/7,-1,0,B/browse
+http://www.sportinggreen.com/news/20001014/fbo/fbc/abb/001014.0391.html
+http://yp.gates96.com/0/14/10/63.html
+http://yp.gates96.com/0/14/10/80.html
+http://yp.gates96.com/0/14/11/32.html
+http://yp.gates96.com/0/14/11/37.html
+http://yp.gates96.com/0/14/11/80.html
+http://yp.gates96.com/0/14/13/21.html
+http://yp.gates96.com/0/14/13/23.html
+http://yp.gates96.com/0/14/13/38.html
+http://yp.gates96.com/0/14/13/49.html
+http://yp.gates96.com/0/14/13/90.html
+http://yp.gates96.com/0/14/14/53.html
+http://yp.gates96.com/0/14/14/63.html
+http://yp.gates96.com/0/14/14/77.html
+http://yp.gates96.com/0/14/15/12.html
+http://yp.gates96.com/0/14/15/88.html
+http://yp.gates96.com/0/14/15/96.html
+http://yp.gates96.com/0/14/16/27.html
+http://yp.gates96.com/0/14/16/62.html
+http://yp.gates96.com/0/14/16/67.html
+http://yp.gates96.com/0/14/16/86.html
+http://yp.gates96.com/0/14/16/92.html
+http://yp.gates96.com/0/14/17/15.html
+http://yp.gates96.com/0/14/17/22.html
+http://yp.gates96.com/0/14/17/44.html
+http://yp.gates96.com/0/14/18/27.html
+http://yp.gates96.com/0/14/18/29.html
+http://yp.gates96.com/0/14/18/83.html
+http://yp.gates96.com/0/14/19/35.html
+http://yp.gates96.com/0/14/19/58.html
+http://www.123bestphonerates.com/q/001p/vn/ZWUdEJwdxM.htm
+http://www.trax.nilex.co.uk/trax.cgi/A1C/B1U/A2S/B3L/A4S/B1L/
+http://www.trax.nilex.co.uk/trax.cgi/A1C/B1U/A2S/B3L/A4S/C2D/
+http://southwind.themes.tucows.com/skins/icq/preview/68532.html
+http://southwind.themes.tucows.com/skins/icq/adnload/77797.html
+http://southwind.themes.tucows.com/skins/icq/preview/55623.html
+http://southwind.themes.tucows.com/skins/icq/adnload/51324.html
+http://southwind.themes.tucows.com/skins/icq/adnload/26609.html
+http://southwind.themes.tucows.com/skins/icq/adnload/48629.html
+http://southwind.themes.tucows.com/skins/icq/adnload/48628.html
+http://www.webcom.com.mx/cronica/1999/mar/09/neg01.html
+http://jproxy.uol.es/jproxy/http://mars.jpl.nasa.gov/msp98/news/mpl000207.html
+http://jproxy.uol.es/jproxy/http://mars.jpl.nasa.gov/msp98/news/news61.html
+http://jproxy.uol.es/jproxy/http://mars.jpl.nasa.gov/msp98/ds2/fact.html
+http://jproxy.uol.es/jproxy/http://mars.jpl.nasa.gov/mgs/sci/mola/98lander.html
+http://jproxy.uol.es/jproxy/http://mars.jpl.nasa.gov/msp98/news/status990123.html
+http://ustlib.ust.hk/search*chi/dmarriage/dmarriage/-5,-1,0,B/exact&F=dmarriage+china&1,4/limit
+http://mediate.magicbutton.net/do/session/625641/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-artc.html
+http://www.scifi.com/cgi-bin/rbox/articles.pl?1&6&1721&20
+http://www.areteoutdoors.com/contribute/earth/b.97.r.54.g.1706.html
+http://members.tripod.lycos.co.kr/ifoo6981/?M=A
+http://link.fastpartner.com/do/session/600395/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/bol.php
+http://link.fastpartner.com/do/session/600395/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/mediatransfer.php
+http://link.fastpartner.com/do/session/600395/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/smartguy.php
+http://www.safrex.com/catalog/elite08/elite084c.html
+http://www.911codes.com/games/platform/psx/sect/div/cont/list_cheat/spray/y/id/0000005511/gid/0000003893/_cheats/_walkthroughs/_codes/_pc/_n64/_psx/_gameboy/_playstation/
+http://yp.gates96.com/7/44/10/4.html
+http://yp.gates96.com/7/44/10/15.html
+http://yp.gates96.com/7/44/10/30.html
+http://yp.gates96.com/7/44/10/32.html
+http://yp.gates96.com/7/44/10/36.html
+http://yp.gates96.com/7/44/11/1.html
+http://yp.gates96.com/7/44/11/41.html
+http://yp.gates96.com/7/44/11/44.html
+http://yp.gates96.com/7/44/12/29.html
+http://yp.gates96.com/7/44/12/76.html
+http://yp.gates96.com/7/44/12/81.html
+http://yp.gates96.com/7/44/13/56.html
+http://yp.gates96.com/7/44/14/19.html
+http://yp.gates96.com/7/44/15/14.html
+http://yp.gates96.com/7/44/15/52.html
+http://yp.gates96.com/7/44/15/62.html
+http://yp.gates96.com/7/44/15/72.html
+http://yp.gates96.com/7/44/15/78.html
+http://yp.gates96.com/7/44/15/81.html
+http://yp.gates96.com/7/44/15/82.html
+http://yp.gates96.com/7/44/16/78.html
+http://yp.gates96.com/7/44/16/93.html
+http://yp.gates96.com/7/44/17/51.html
+http://yp.gates96.com/7/44/17/75.html
+http://yp.gates96.com/7/44/18/43.html
+http://yp.gates96.com/7/44/18/92.html
+http://yp.gates96.com/7/44/19/26.html
+http://www3.newstimes.com/archive2000/oct17/bze.htm
+http://member.aol.co%20m/askmo/
+http://home.excite.co.uk/directory/categories/528195
+http://www.scifi.com/bboard/browse.cgi/1/5/545/11566?pnum=1
+http://member.shangdu.net/home1/havdone/game/gonglue/ljcq.htm
+http://member.shangdu.net/home1/havdone/game/gonglue/lishou.htm
+http://archiv.leo.org/cgi-bin/leo-md5.pl/pub/comp/usenet/comp.sources.misc/dostrace/
+http://yp.gates96.com/8/70/91/12.html
+http://yp.gates96.com/8/70/91/20.html
+http://yp.gates96.com/8/70/91/45.html
+http://yp.gates96.com/8/70/92/29.html
+http://yp.gates96.com/8/70/92/40.html
+http://yp.gates96.com/8/70/92/74.html
+http://yp.gates96.com/8/70/93/9.html
+http://yp.gates96.com/8/70/93/11.html
+http://yp.gates96.com/8/70/94/10.html
+http://yp.gates96.com/8/70/94/90.html
+http://yp.gates96.com/8/70/95/4.html
+http://yp.gates96.com/8/70/95/13.html
+http://yp.gates96.com/8/70/95/58.html
+http://yp.gates96.com/8/70/95/74.html
+http://yp.gates96.com/8/70/95/80.html
+http://yp.gates96.com/8/70/96/34.html
+http://yp.gates96.com/8/70/96/65.html
+http://yp.gates96.com/8/70/97/0.html
+http://yp.gates96.com/8/70/97/16.html
+http://yp.gates96.com/8/70/97/75.html
+http://yp.gates96.com/8/70/98/27.html
+http://yp.gates96.com/8/70/98/60.html
+http://www.icopyright.com/1.1638.306154
+http://www.zeal.com/category/be_zealous.jhtml?cid=828
+http://lib1.nippon-foundation.or.jp/1996/0621/contents/004.htm
+http://www.haikou.hainan.gov.cn/pandect/nj/n96jada.htm
+http://www.chaos.dk/sexriddle/s/e/x/p/b/m/s/
+http://www.symantec.ca/region/uk/resources/mobile/nav.html
+http://retailer.gocollect.com/do/session/1912798/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/products/product_lines.asp
+http://polygraph.ircache.net:8181/services/define/http_-2www.microsoft.com/ie/Tabitha/http_-2www.adultlinks.net/gallery.shtml
+http://f22.parsimony.net/forum42460/messages/1.htm
+http://www.greenleaves.com/bookcat/gb_0722530986.html
+http://www.classiccmp.org/mail-archive/classiccmp/1998-06/0638.html
+http://www1.onelist.com/dir/Society/Paranormal/UFOs/Biblical_Perspectives
+http://home.hiwaay.net/~bjacobs/genealogy/laster/html/d0055/g0000045.html
+http://link.fastpartner.com/do/session/600374/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/netmaling.php
+http://big5.peopledaily.com.cn/haiwai/200003/03/newfiles/A104.html
+http://ustlib.ust.hk/search*chi/achang+chieh+mei/achang+chieh+mei/-5,-1,0,B/frameset&F=achang+chieh+fu&1,,2
+http://teleline.terra.es/personal/mgsair/chtml/ejemplos/marcos1.html
+http://myhome.naver.com/toktok01/bbs.php3?p_work=admin&p_page=1
+http://netway.pda.tucows.com/palm/adnload/34443_22051.html
+http://netway.pda.tucows.com/palm/adnload/34930_22057.html
+http://netway.pda.tucows.com/palm/adnload/34435_22044.html
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/kmusic/brahms/qtWaveTrack.h?sortby=rev&only_with_tag=HEAD
+http://sinr.net/book/content/39/8411.html
+http://www.egroups.com/post/gvocsa?act=reply&messageNum=145
+http://www.diogenes.ch/4DACTION/web_rd_aut_prview/a_id=7056669&area=&ID=483352
+http://www.brio.de/BRIO.catalog/39fe2f7d06fe4a08273fd472aa7806a9/UserTemplate/1
+http://www3.newstimes.com/archive2000/sep01/rgd.htm
+http://community.webshots.com/photo/5886633/5886821zAagKCgZhs
+http://community.webshots.com/photo/5886633/5917061PxBHHqElgV
+http://www.dnai.com/~mbaum/anita/html/eng/art/images/image38.html
+http://www.houses-apartment-listings.com/Michigan/city_search_criteria.asp?state=MI&City=CLINTON
+http://www.brio.de/BRIO.catalog/39fdb87c09896af6273fd472aa78076c/UserTemplate/10
+http://www.expressindia.com/ie/daily/19990129/02950495p.html
+http://www.linux.com/networking/web/unix/internet/project/security/
+http://www.linux.com/networking/web/unix/internet/project/Red_Hat/
+http://www.linux.com/networking/web/unix/internet/project/freshmeat/
+http://www.linux.com/networking/web/unix/internet/project/?kw_offset=50
+http://ring.yamanashi.ac.jp/pub/linux/debian/debian/dists/Debian2.2r0/non-free/binary-i386/science/?N=D
+http://ftp.task.gda.pl/pub/games/idgames/utils/level_edit/acaddoom.txt
+http://www.affiliate.hpstore.hp.co.uk/do/session/380864/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/FR/REGISTRATION/entry.asp
+http://fi.egroups.com/post/allianc?act=reply&messageNum=2305
+http://polygraph.ircache.net:8181/services/design/company/http_-2burn.ucsd.edu/~abcf
+http://polygraph.ircache.net:8181/services/design/company/miami.htm
+http://www.utexas.edu/ftp/admin/AI_ATTIC/ATW/Mosaic.instruct/?D=A
+http://ftp.du.se/disk3/redhat/updates/powertools/current/alpha/
+http://www.multicosm.com/facade/demo.multicosm.com/facade/www.informationweek.com/mediakit/00/default.html
+http://www.multicosm.com/facade/demo.multicosm.com/facade/www.informationweek.com/mediakit/00/about_overview.html
+http://www7.tok2.com/home/maki67/menu.htm
+http://www.mapion.co.jp/custom/AOL/admi/23/23103/tsujicho/2chome/index-24.html
+http://sunsite.org.uk/public/computing/networks/internet/ietf/printmib/printmib-attendees-97apr.txt
+http://ftp.univie.ac.at/packages/tex/macros/latex2e/contrib/supported/nomencl/?N=D
+http://spaceports.tucows.com/winme/adnload/137993_30287.html
+http://habenix.uni-muenster.de/Rektorat/Forschungsberichte-1997-1998/fo05acd01.htm
+http://www.power2lead.com/Global/English.nsf/pgWWLocations!OpenPage&ExpandSection=2,25,7,32,18
+http://www.teacherformation.org/html/od/facilitators.cfm/task1,help/discussion_id,2/xid,6155/yid,3651726
+http://itcareers.careercast.com/texis/it/itjs/+IwwBmeS9D867xwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew7hmwGAnBoDtapGdtGwMamnVncdpa51ppdGBaqconDBaqdMM1DoqwBodDaoDVn5BMnDBapGdm1qBaMwDwtnaqGnwBoVnaMFqhgfHNEDzm7wwwpBmeg9D86exqwww5rmeqDwwwBrmeZpwww/morelike.html
+http://itcareers.careercast.com/texis/it/itjs/+XwwBmie0B-deaqwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew7hmwGAnBoDtapGdtGwMamnVncdpa51ppdGBaqconDBaqdMM1DoqwBodDaoDVn5BMnDBapGdm1qBaMwDwtnaqGnwBoVnaMFqhgfHNEDzm7wwwpBmeg9D86exqwww5rm-mwwBrmeZpwww/morelike.html
+http://members.iinet.net.au/~scott3/legacy/matt.html
+http://cn.egroups.com/post/bastardimage?act=forward&messageNum=11
+http://ftp.nodomainname.net/pub/mirrors/.2/gnu/tasks/?N=D
+http://ftp.nodomainname.net/pub/mirrors/.2/gnu/tasks/standards.text
+http://10000downloads.subportal.com/sn/Utilities/Misc__Utilities/11320.html
+http://mindit.netmind.com/proxy/http://www.altera.com/html/tools/swupdates.html
+http://www.next.com.hk/mag/419/news/an06.htm
+http://www.areteoutdoors.com/channel/air/b.283.g.3871.html
+http://troop485.tripod.com/documents/johnwayne.htm
+http://troop485.tripod.com/documents/bp-churchhill.htm
+http://sound-dist.secured.co.uk/cgi-bin/psProdDet.cgi/22P03|972959558|Security|user|0|1,0,0,1
+http://www9.hmv.co.uk:5555/do/session/1347794/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d120_sd0_pt0.html
+http://ftp.du.se/debian/dists/Debian2.2r0/main/disks-m68k/2.2.16-2000-07-14/mac/images-1.44/?S=A
+http://opac.lib.ntnu.edu.tw/search*chi/++ftlist/bp20043193/-5,-1,0,B/buttonframe&F=bp20043190&1,1
+http://www.parlament.ch/internet98/Poly/Suchen_amtl_Bulletin/ce98/ete/275.HTM
+http://in.egroups.com/messages/svpvril/5195?viscount=-30
+http://in.egroups.com/messages/svpvril/?expand=1
+http://retailer.gocollect.com/do/session/1912744/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/checkout/shopping_cart.asp
+http://retailer.gocollect.com/do/session/1912744/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/clubhouse/suggestions.asp
+http://www18.freeweb.ne.jp/sports/imamako/
+http://www.cs.ucc.ie/javadocs/jdk1.2.2/docs/api/java/awt/geom/class-use/QuadCurve2D.Double.html
+http://click-to.tell-a-friend.boardhost.com/tell-a-friend-confirm.cgi?stigmaonline&msg=172
+http://www.emerchandise.com/aboutus/b.TV%20ANGEL/s.2YYjVOgH
+http://www.leyou.com/product/ShowResult.php?LY_Category=0531&page=3
+http://cafe6.daum.net/Cafe-bin/Bbs.cgi/rest114pds/qry/zka/B2-kB23o/qqatt/^
+http://sunsite.informatik.rwth-aachen.de/LinuxArchives/sunsite.unc.edu/distributions/linux-router/dists/2.9.6/base/?N=D
+http://www-uk5.cricket.org/link_to_database/ARCHIVE/1999-2000/PAK_IN_SL/FANTASY/
+http://findmail.com/message/sangersreview/99
+http://phase.etl.go.jp/mirrors/netlib/utk/people/JackDongarra/SLIDES/osu-498/sld011.htm
+http://tucows.datasync.com/winme/preview/75261.html
+http://secure.danysoft.com/asp/dany.tienda/1266636789/Catalog
+http://www.birding.about.com/hobbies/birding/cs/placesecuador/index_2.htm
+http://www.cpami.gov.tw/ymsnp/animal/fauna/nospc385text.htm
+http://www.fh-telekom-leipzig.de/hilfe/pak_e/paket_inhalt_jade_dsl.html
+http://home.vicnet.net.au/~nunayl/feedback.html
+http://www.expage.com/nibina
+http://www.expage.com/virtuaalisiittolantallivihko
+http://www.expage.com/muittentallijenkisoja
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=9,39,33
+http://retailer.gocollect.com/do/session/1912707/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/top_ten.asp?pagenum=2
+http://www.streetprices.com/Electronics/Other/MAKE+SYMANTEC/sortdetailbystock/SP322647.html
+http://www.peopledaily.co.jp/haiwai/199810/09/no_981009003024_6.html
+http://mediate.magicbutton.net/do/session/625622/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-artc.html
+http://mediate.magicbutton.net/do/session/625622/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-top50.html
+http://www.nada.kth.se/systemgruppen/docs/javadoc/jdk-1.3/docs/api/javax/swing/plaf/basic/class-use/BasicSliderUI.ChangeHandler.html
+http://kernel2.adver.com.tw/Counter/log/kernel2.adver.com.tw/Collect_DB_Advers2/2000-09-10/08/?N=D
+http://yp.gates96.com/12/57/30/53.html
+http://yp.gates96.com/12/57/32/14.html
+http://yp.gates96.com/12/57/32/97.html
+http://yp.gates96.com/12/57/33/1.html
+http://yp.gates96.com/12/57/33/37.html
+http://yp.gates96.com/12/57/37/91.html
+http://yp.gates96.com/12/57/37/98.html
+http://yp.gates96.com/12/57/38/23.html
+http://yp.gates96.com/12/57/38/34.html
+http://yp.gates96.com/12/57/38/51.html
+http://yp.gates96.com/12/57/38/53.html
+http://yp.gates96.com/12/57/39/43.html
+http://yp.gates96.com/12/57/39/56.html
+http://yp.gates96.com/12/57/39/68.html
+http://yp.gates96.com/12/57/39/70.html
+http://www3.sympatico.ca/jacques.m.boisvert/Data_Distribution.html
+http://www.garekiya.com/female/female02-25.html
+http://www.brio.de/BRIO.catalog/39fe2f6c06f4cd8e273fd472aa780734/UserTemplate/5
+http://202.99.23.195/GB/channel1/13/20001030/291723.html
+http://db.bbc.co.uk/education/gcsebitesize/maths/shape_and_space_i_h/loci_rev.shtml
+http://commerce.was-inc.com/cgi-bin/abtwsam.dll/LbkWebCommerceStoreCategories-BBC709F9_97F3_1F2D7EFC4CA45617D914720977E88400
+http://commerce.was-inc.com/cgi-bin/abtwsam.dll/LbkWebCommerceShoppingCartPage-BBC709F9_97F3_1F2D7EFC4CA45617D914720977E88400
+http://polygraph.ircache.net:8181/http_-2www.microsoft.com/frontpage/http_-2www.hercules.com/history.htm
+http://www.jbc.org/cgi/content/short/275/36/27501
+http://brazil.mit.edu/sdb/de/html/keylist.NNTP.html
+http://ads3.zdnet.com/c/g=r771&c=a53605&idx=2000.10.30.21.30.57/www.micronpc.com/zd/max1299
+http://webtools.familyeducation.com/whatworks/item/front/0,2551,22-9696-6689-473-46499,00.html
+http://www.dispatch.co.za/2000/04/08/business/HIGHLOW.HTM
+http://generalstore.everdream.com/kore/catalog/Office_Supplies/Forms,_Record_Keeping_&_Reference/Human_Resources/Motivational/brand.html?sort=price&count=0
+http://www.laria.u-picardie.fr/docs/www.linux-france.org/article/securite/intro.html
+http://ftp.uni-stuttgart.de/pub/netscape/communicator/slovenian/4.51/windows/windows95_or_nt/
+http://cafe4.daum.net/Cafe-bin/Bbs.cgi/monjatingpds/lst/qqeq/1/zka/B2-kBnNt
+http://myhome.shinbiro.com/~funky27/novel18.htm
+http://www.apcmag.com/apcweb/reviewsdisc.nsf/aac7d56ca8fd884b852563be00610639/25858e2d9c878e294a2567060015364d!EditDocument
+http://www.private-immobilien-boerse.de/nordrhein-Westfalen/luedinghausen/Verkauf/3d-service/Gemeinsam/Immolink/Gemeinsam/erreichenPartner/Private-IB/
+http://www.eos.dk/archive/swing/msg00405.html
+http://www.jobvillage.com/channel/jobs/human_resources/benefits_analysis/b.2807.g.1757.html
+http://www.hanaga.com.cn/gbjc/tc/jq.htm
+http://www.multimap.com/wi/33747.htm
+http://www.multimap.com/wi/143959.htm
+http://home.freeuk.net/jdl/Left_Navigate.htm
+http://www.crit.org/nph-edit.cgi/http://crit.org/pub/ifi.unizh.ch/wagner/just-testing.html
+http://www.interessengemeinschaft-musik.de/catalog%20data/body_22.html
+http://aleph.tau.ac.il:4500/ALEPH/ENG/ATA/AAS/AAS/FIND-ACC/0333501
+http://www.mojahedin.org/Pages/Mojahed/Mojahed451/rp/rp09.html
+http://genforum.genealogy.com/cgi-genforum/forums/lenhart.cgi?158
+http://carriage.de/Schoner/collections/Geschichte/Sammlungen/info-e/
+http://cafe4.daum.net/Cafe-bin/Bbs.cgi/pflhs11pds/rnw/zka/B2-kB2-s
+http://ftp.lip6.fr/pub11/NetBSD/arch/hpcmips/pkgstat/20001008.0536/textproc/xerces-j-current/
+http://dk.egroups.com/message/scotdisinfo/306
+http://groups.haas.berkeley.edu/hcs/Docs/SASv8/sasdoc/sashtml/proc/z0360708.htm
+http://www.legend-net.com/news/tiyu/messages/474.html
+http://www.legend-net.com/news/tiyu/messages/466.html
+http://tv.thevines.com/leaf/AA0000373887/3/0/0/&hmode=on
+http://vorg1.subportal.com/sn/Business/Enhanced_Calculators/5511.html
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=7,28,31,24,35
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=24,5,17,30,11
+http://ftp.gwdg.de/pub/eff/Global/USA/Legislation/gtda_export.regulations
+http://www.dein-schicksal.de/Fotoanzeigen/April_2000/7/17/27/body_57.html
+http://www.fujian-window.com/Fujian_w/news/mzrb1/20000630/2_14.html
+http://www.webswap.com/shelf/2/17559/sell.html
+http://search.leg.wa.gov/wslrcw/RCW%20%2036%20%20TITLE/RCW%20%2036%20.100%20%20CHAPTER/RCW%20%2036%20.100%20.060.htm
+http://www.doc.ic.ac.uk/lab/labsrc_area/firstyear/submissions/1997-98/jmc1/labs/Ex02/icc97/?M=A
+http://school.educities.org/card/abc0609.html
+http://school.educities.org/card/huangmei.html
+http://school.educities.org/card/a126457822.html
+http://school.educities.org/card/a8911.html
+http://school.educities.org/card/aa5117.html
+http://school.educities.org/card/b3575610.html
+http://school.educities.org/card/c5625.html
+http://school.educities.org/card/h1230997.html
+http://school.educities.org/card/h224153937.html
+http://school.educities.org/card/julie9.html
+http://school.educities.org/card/lefe135.html
+http://school.educities.org/card/nl123.html
+http://school.educities.org/card/s5802.html
+http://school.educities.org/card/s58120.html
+http://school.educities.org/card/s5931.html
+http://school.educities.org/card/s6197.html
+http://school.educities.org/card/vov.html
+http://school.educities.org/card/xx5331.html
+http://darkwing.uoregon.edu/~cblanksh/GeneratedItems/?M=A
+http://ciscom.gamecenter.com/Tipcheat/PC/Item/0,128,0-202,00.html
+http://rotten-tomatoes.com/movies/browse/1010942/video.php
+http://rotten-tomatoes.com/movies/browse/1076825/reviews.php
+http://archive.soccerage.com/s/fr/09/98335.html
+http://www.ferien-immobilien.de/nordrhein-Westfalen/aachen/Verkauf/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/3d-service/Gemeinsam/erreichenPartner/Gemeinsam/impressum.htm
+http://www.ebigchina.com/tool_tellfriend.phtml?code=msg&mid=3174
+http://people.freebsd.org/~knu/cgi-bin/cvsweb.cgi/src/libexec/rpc.rwalld/Makefile?only_with_tag=RELENG_3
+http://people.freebsd.org/~knu/cgi-bin/cvsweb.cgi/src/libexec/rpc.rwalld/Makefile?only_with_tag=MAIN
+http://people.freebsd.org/~knu/cgi-bin/cvsweb.cgi/src/libexec/rpc.rwalld/Makefile?only_with_tag=RELENG_3_BP
+http://ring.jec.ad.jp/pub/linux/debian/debian/dists/unstable/contrib/binary-sh/admin/?M=A
+http://www2.eunet.lv/library/alt/URIKOVA/FORTUNE_D/Mirrors
+http://www.hermes.dk/departments/om/publica.shtml
+http://208.194.150.10/Ski/Articles/DrDewpoint/001/bannerAd.shtml
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/quanta/quanta/widgets/?sortby=log&only_with_tag=start
+http://biblio.cesga.es:81/search*gag/aSempere+Navarro,+Antonio-Vicente/asempere+navarro+antonio+vicente/-5,-1,0,E/frameset&F=asempere+y+guarinos+juan+trad&1,1
+http://www.fractal.com.ru/Component/Toshiba/74Cxx/TC74HC74DS.pdf
+http://www.staroriental.net/nav/soeg/ihf,aai,n3,7,Electric+Wave+Girl+1998.html
+http://excite.de/auto/katalog/11803
+http://gatekeeper.dec.com/pub/BSD/NetBSD/NetBSD-current/pkgsrc/sysutils/amanda-client/pkg/
+http://www.smcworld.com/smcworld/bp_e/large/0524_2301_002x2301_003x2301_004x2301_005x2301_006x2301_007_2301_005b.html
+http://www.kaos.dk/sexriddle/x/j/t/z/d/
+http://www.kaos.dk/sexriddle/x/j/t/z/e/
+http://spartanburg2.edgate.com/blgspringes/school_athletics/parent/
+http://www-personal.engin.umich.edu/~mhaanpaa/?S=D
+http://www.amcity.com/jacksonville/stories/2000/05/15/story8.html?t=email_story
+http://yp.gates96.com/7/47/40/13.html
+http://yp.gates96.com/7/47/42/7.html
+http://yp.gates96.com/7/47/43/2.html
+http://yp.gates96.com/7/47/43/22.html
+http://yp.gates96.com/7/47/43/54.html
+http://yp.gates96.com/7/47/44/0.html
+http://yp.gates96.com/7/47/45/3.html
+http://yp.gates96.com/7/47/45/30.html
+http://yp.gates96.com/7/47/45/78.html
+http://yp.gates96.com/7/47/45/89.html
+http://yp.gates96.com/7/47/46/41.html
+http://yp.gates96.com/7/47/46/71.html
+http://yp.gates96.com/7/47/48/1.html
+http://yp.gates96.com/7/47/48/68.html
+http://yp.gates96.com/7/47/48/92.html
+http://yp.gates96.com/7/47/49/6.html
+http://yp.gates96.com/7/47/49/43.html
+http://yp.gates96.com/7/47/49/86.html
+http://yp.gates96.com/7/47/49/97.html
+http://de.excite.de/bildung/katalog/24692
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=90&discrim=226,20,231
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=90&discrim=226,20,4
+http://www.affiliate.hpstore.hp.co.uk/do/session/380862/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/search.asp
+http://www1.zdnet.co.uk/news/news1/ns-1511.html
+http://bellona.itworld.com:8080/cwi/reprint/0,1926,NAV63-128-1357-1367_STO48730,00.html
+http://wwwhome.cs.utwente.nl/~zwiers/projects/docs/jdk/api/java/util/class-use/SortedMap.html
+http://cgi.cnnsi.com/football/nfl/players/Ed.McCaffrey/
+http://fi.egroups.com/messages/philmusic/12006
+http://fi.egroups.com/messages/philmusic/12123
+http://fi.egroups.com/messages/philmusic/213
+http://fi.egroups.com/messages/philmusic/1826
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=22,0+20,0-9,2-~
+http://my.egroups.com/message/gps4gis/164
+http://www.bemi-immobilien.de/Startseite/www.allgemeine-immobilien-boerse.de/allgemeine-ib/landkreiszwickau/Verkauf/29109700708107kirchbergvillamü/Gemeinsam/MarketingStrategie/Gemeinsam/Inserieren/Startseite/Startseite/Gemeinsam/versicherungen/gebaeude/anforderungsformular.htm
+http://apple.excite.com/entertainment/fine_arts/classical_music/composers/baroque_composers/albinoni_tomaso/works/
+http://www.lithoquoter.com/Scripts/WebObjects.exe/Printers.woa/609420000046582000001552000000949302/main.wo/7834100000849302/4/-/prime
+http://yp.gates96.com/11/75/40/25.html
+http://yp.gates96.com/11/75/40/38.html
+http://yp.gates96.com/11/75/40/88.html
+http://yp.gates96.com/11/75/40/91.html
+http://yp.gates96.com/11/75/42/1.html
+http://yp.gates96.com/11/75/42/74.html
+http://yp.gates96.com/11/75/42/81.html
+http://yp.gates96.com/11/75/43/45.html
+http://yp.gates96.com/11/75/43/51.html
+http://yp.gates96.com/11/75/46/25.html
+http://yp.gates96.com/11/75/46/72.html
+http://yp.gates96.com/11/75/46/89.html
+http://yp.gates96.com/11/75/46/91.html
+http://yp.gates96.com/11/75/47/5.html
+http://yp.gates96.com/11/75/48/67.html
+http://yp.gates96.com/11/75/49/89.html
+http://users.telerama.com/~mross/jenny/forsale.html
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=14&discrim=212,57
+http://ring.htcn.ne.jp/archives/NetBSD/NetBSD-1.4.2/atari/binary/security/?N=D
+http://library.bangor.ac.uk/search/dCanada+--+Agricultural+resources+--+19th+century/dcanada+agricultural+resources+++19th+century/-5,-1,0,B/exact&F=dcanaanites&1,3
+http://www.brio.de/BRIO.catalog/39fe2f6406e8eec4273fd472aa780738/UserTemplate/5
+http://kuyper.calvin.edu/fathers2/NPNF1-05/npnf1-05-04.htm
+http://kuyper.calvin.edu/fathers2/NPNF1-05/npnf1-05-08.htm
+http://kuyper.calvin.edu/fathers2/NPNF1-05/npnf1-05-20.htm
+http://polygraph.ircache.net:8181/http_-2www.sgi.net/http_-2www.itools.com/research-it/http_-2www.aardvarkclay.com/Themes/http_-2www.snapsite.com/guests/sk8ctrl/public/html/sitemap/sitemap.htm
+http://www.genexchange.com/cemlist.cfm?state=mo&county=webster
+http://newsone.net/nnr/showart/alt.current-events.haiti/911
+http://212.11.11.62/voyages_degriffes/MEXIQUE/PARIS+-+MEXICO+A%2FR/SAI00511790/
+http://bitwise.linux.tucows.com/x11html/adnload/131942_45932.html
+http://www.brio.de/BRIO.catalog/39fe2f740910301a2740d472aa7806aa/UserTemplate/1
+http://singles-ads.theshoppe.com/cgi-bin/c/736/64/dXNlcmJhbm5lcg==/gn/3585/
+http://www.chaos.dk/sexriddle/j/l/v/y/t/
+http://www.interlog.com/~prandall/relations/d0003/g0000795.html
+http://ftp.jp.debian.org/debian/dists/woody/non-free/binary-arm/oldlibs/?M=A
+http://biblioteca.upv.es/bib/doc/doc_fisbd/129/97268//V/1828099/6////25/N/MLTPAID
+http://biblioteca.upv.es/bib/doc/doc_fisbd/129/147168//V/1828099/11////25/N/MLTPAID
+http://biblioteca.upv.es/bib/doc/doc_fisbd/129/124846//V/1828099/24////25/N/MLTPAID
+http://mirrortucows.technet.it/winme/htmlbeginnerme_size.html
+http://www.bcbsal.org/Provider_Dir/pharmacy/state/Georgia/HAWKINSVILLE/index_10201.html
+http://www.incestpornstories.com/tinkerbellbeard/ac/plus-sizehealthy/petitevietnamese/slanted-eyes/cuntschoolgirls/high-schoolteenager/cherryunderage.html
+http://www.0563.net/imode2/hazu/play/outdoor/nature/nature1.htm
+http://www.launch.com/music/songpage/pvn_content/0,5259,1074221,00.html
+http://ftp.jp.debian.org/debian/dists/unstable/main/binary-alpha/tex/?S=A
+http://iceberg.adhomeworld.com/cgi-win/redirect.exe/896425026
+http://www.nrc-handelsblad.nl/W2/Lab/Baan/000726-a.html
+http://www.nrc-handelsblad.nl/W2/Lab/Baan/000718-a.html
+http://members.tripod.co.jp/muzyaki/?M=A
+http://alfa.nic.in/lsdeb/ls12/ses4/0413039930.htm
+http://excite.de/immobilien/katalog/26640
+http://excite.de/immobilien/katalog/27591
+http://excite.de/immobilien/katalog/28370
+http://excite.de/immobilien/katalog/28376
+http://excite.de/immobilien/katalog/26426
+http://excite.de/immobilien/katalog/28458
+http://www.emerchandise.com/aboutus/b.TV%20THE60S/s.qxmvd5Gr
+http://www.computerworld.com.cn/99/week/9920/9920c13.asp
+http://www.stud.ntnu.no/~oystena/oystena/cache/dvx70a.html
+http://nealet.subportal.com/sn/Shell_and_Desktop/Holiday_Screen_Savers/
+http://dk.egroups.com/message/ugm/40?source=1
+http://www1.bdaserver.de/bda/nat/pzt/formel1/gp/mon.html
+http://www17.freeweb.ne.jp/diary/t-soken/love-love.htm
+http://kernel2.adver.com.tw/Counter/log/kernel2.adver.com.tw/SaveCounter/2000-10-12/14/971332013437.txt
+http://pub3.ezboard.com/f80sxchangegeneraldiscussion.showMessage?topicID=60.topic
+http://www.northampton.ac.uk/cgi-bin/liberation/betsie/betsie.pl/0005/www.nene.ac.uk/ncr/enrol/sectn4/pdf/4-5.pdf
+http://www.xmission.com/~dkenison/cgi/lwgate.cgi/LDS-BOOKSHELF/archives/v01.n676/Date/article-15.html
+http://www.eos.dk/archive/swing/nav08574.html
+http://nathanael.upi.jussieu.fr/tele6.nsf/autres+centres+de+formations!OpenPage&ExpandSection=1,4,11,18,5,17
+http://nathanael.upi.jussieu.fr/tele6.nsf/autres+centres+de+formations!OpenPage&ExpandSection=6,4,11,18,5,17
+http://cn.egroups.com/message/highlanderswaps/3351
+http://cn.egroups.com/message/highlanderswaps/3356
+http://www.mobygames.com/user/sheet/view/havelist/so,game_title(game_id)+DESC,game_havelist_id+DESC/userHaveListId,18/userSheetId,832/offset,15/
+http://www.mobygames.com/user/sheet/view/havelist/so,game_title(game_id)+DESC,game_havelist_id+DESC/userHaveListId,18/userSheetId,832/offset,60/
+http://gettosdownloads.subportal.com/sn/Palm_Pilot/Home_and_Hobby/12385.html
+http://biblio.cesga.es:81/search*gag/aOurense+(Di%26oacute%3Bcesis).+Obispado+de+Ourense,+ed./aourense+diocesis+obispado+de+ourense+ed/-5,-1,0,B/browse
+http://www.beneteau-owners.com/beneteau.nsf/userlistbyboat!OpenView&Start=21.24&Count=45&Expand=39
+http://www.geocities.com/Yosemite/8908/
+http://www.geocities.com/Yosemite/3295/
+http://lists.insecure.org/linux-kernel/2000/Apr/4105.html
+http://www.telematik.informatik.uni-karlsruhe.de/osf/sw/v5.0x/lp2/dna500/
+http://atlas.web.cern.ch/Atlas/GROUPS/SOFTWARE/OO/dist/0.0.28/graphics/TreeBuilder/TreeMaker/CVS/?M=A
+http://www.21hk.com/book/zt/zt/zpj/c/chichuancilang/txmoxj/012.htm
+http://chat.hani.co.kr/NetBBS/Bbs.dll/brief/rcm/zka/B23lBn-t/qqatt/^
+http://www3.buch-per-sms.de/impressum.jsp$ID=To7770mC6889218603037781At0.41865389376542195
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/151/1997/7/0/904457/
+http://www.mets.com/gameinfo/990504-recap.htm
+http://www.mets.com/Video/990709-PiazzaHR_lr.asp
+http://www.people.zeelandnet.nl/cn.atlas/compatlasw1.html
+http://www.digitaldrucke.de/(aktuell,bekanntschaften,hilfe,marktplatz,nuernberg)/_fort/html/themen/markt/bekannt/bekannt.htm
+http://www.staroriental.net/nav/soeg/ihf,acf,s0,359,Gigi+Leung+Wing-Kay.html
+http://rapidus.tucows.com/winme/adnload/137435_28887.html
+http://library.bangor.ac.uk/search/aBerthoff,+Ann+E/aberthoff+ann+e/-5,-1,0,B/frameset&F=aberthier+rene&1,1
+http://www.teenplatinum.com/barelylegal/underagevirgin/abductionbondage/amateurco-ed/chijapanese/{gaylink}
+http://www.paisvirtual.com/informatica/freeware/cltorres/contra.htm
+http://library.cuhk.edu.hk/search*chi/aInstitution+of+Civil+Engineers+(Great+Britain)/ainstitution+of+civil+engineers+great+britain/-5,-1,0,B/browse
+http://www.digitaldrucke.de/(aktuell,computer,hersteller,hilfe)/_fort/html/themen/computer/hard/links/dell.htm
+http://www.angelfire.com/ar/jimbowles/weekofoct3.html
+http://www.dtic.mil/envirodod/derpreport95/vol_2/b2_1991.html
+http://www.dtic.mil/envirodod/derpreport95/vol_2/b2_2010.html
+http://kobe.cool.ne.jp/heartisland/y_top0004.html
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=146&discrim=10,97,3
+http://www.channel7000.com/partners/tv/consumer/partners-tv-consumer-20000207-231308.html
+http://www.channel7000.com/partners/tv/consumer/partners-tv-consumer-19991206-195152.html
+http://www.channel7000.com/partners/tv/consumer/partners-tv-consumer-990920-105620.html
+http://www.channel7000.com/partners/tv/consumer/partners-tv-consumer-990810-082554.html
+http://gallery2.simplenet.com/lobby/main/videocaps/lalbrght/conair/laca26.htm
+http://www.ld.com/cbd/archive/1999/09(September)/30-Sep-1999/Bawd007.htm
+http://www.ld.com/cbd/archive/1999/09(September)/30-Sep-1999/Bawd013.htm
+http://chunma.yeungnam.ac.kr/~j4390071/
+http://www.chaos.dk/sexriddle/h/y/z/m/
+http://www.maas.ccr.it/cgi-win/hiweb.exe/a18/d262/b190,8,be,29,29,,b,,be,b,
+http://pub17.ezboard.com/fanimesandrpgslinkstositesandotherforums.showMessage?topicID=2.topic
+http://www.hotelboulevard.com/fr/riviera/standard/htmled1e03872682f66e105b3c38b4506d50/sessionLang/ANG/search.html
+http://bbs.msquare.or.kr/list.bbs/course/old/DiscMath95/9.html
+http://www.rezel.enst.fr/ftp/linux/distributions/debian/CD-1/dists/unstable/main/binary-all/mail/?N=D
+http://www.ee/epbe/pangandus/9910/0.2.txt
+http://shitty.10pics.com/buttfucking/rear/
+http://www.thestateofcolorado.com/hsiwindowdoorlettering.html
+http://www.generation-formation.fr/brevesc.htm---o21zAo0UtDo0Ol9A074fo6Td4ezyr6feZJPAPfVbNyqruePl9neNHhIeOkatAhcgNA074wNV8XzAhcgNAPfVbdsNhJI.htm
+http://netscape.digitalcity.com/boston/sports/standings.dci?league=NBA&team=BOS
+http://netscape.digitalcity.com/boston/sports/attcompare.dci?league=NBA&team=BOS
+http://retailer.gocollect.com/do/session/1912752/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/clubhouse/suggestions.asp
+http://mindit.netmind.com/proxy/http://www.skepdic.com/sympathetic.html
+http://mindit.netmind.com/proxy/http://faculty.washington.edu/chudler/moon.html
+http://itcareers.careercast.com/texis/it/itjs/++wwBmeE_D86esmwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqew8Qwo5qda5dc1BodDawGnwaGn31oGnmaoDmnpBraADdicnmtnapGdm1qBaBnqrDoqwcatGd1pamnVncdpaMFqoET02fgENDzmezxwwwpBmeC_D86Qwww5rmkmwwBrmeyDwww/morelike.html
+http://retailer.gocollect.com/do/session/1912762/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/terms_and_conditions.asp
+http://retailer.gocollect.com/do/session/1912762/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/clubhouse/suggestions.asp
+http://www.writtenbyme.com/cgi-bin/rw_readarticle.cgi/141339880.shtml
+http://www.writtenbyme.com/cgi-bin/rw_readarticle.cgi/410769654.shtml
+http://www.writtenbyme.com/cgi-bin/rw_readarticle.cgi/190045923.shtml
+http://tucows.megalink.com/winme/preview/76155.html
+http://www.buybuddy.com/sleuth/17/1/2006/32184/
+http://www.affiliate.hpstore.hp.co.uk/do/session/380853/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/FR/REGISTRATION/entry.asp
+http://pchome.net:81/ch/Hw/CAMERA/canoneosd30/canoneosd30.htm
+http://pchome.net:81/ch/Hw/CAMERA/kodaknew.htm
+http://pchome.net:81/ch/Hw/MODEM/twluc562w2k.htm
+http://pchome.net:81/ch/Hw/MONITOR/mag796fd.htm
+http://pchome.net:81/ch/Hw/cool/anquanshuileng/anquanshuileng.htm
+http://pchome.net:81/ch/Hw/DISPLAY/3dbenchmarks/3dbenchmarks.htm
+http://pchome.net:81/ch/Hw/CAMERA/Microdrive.htm
+http://pchome.net:81/ch/Hw/harddisk/niyaomaishime.htm
+http://www.civila.com/guitar/desenredada/chat/logos/index.html-ssi
+http://members.xoom.it/scialpinismo/gitaappenparm/PreviewPages/PreviewPage7.htm
+http://cpan.nitco.com/modules/by-module/Mail/ASPIERS/URI-Bookmarks-0.92.readme
+http://polygraph.ircache.net:8181/services/design/http_-2www.swnebr.net/~cambridg/http_-2www.cauce.org/Malcolm/
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_aswkit_aswkit.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_nbilwv_rbpobu.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_jkawvi_messod.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_jkawvi_otdbms.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_jkawvi_hoktlo.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_uhfkhdn_ilaeh.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_xyhsj_pfepjoa.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_alkqaay_mogsts.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_ighrg_ighrg.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_cbfjod_parbe.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_dqnlq_jfspcj.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_phcro_bwlah.html
+http://www.asahi-net.or.jp/~yd7k-itu/sbbsindex/old/16_phcro_xoxchqb.html
+http://seniorfriendfinder.com/cgi-bin/w3com/pws/ffsenior/IkhI2h2UISFGhSJ4dK-jGu69npNFUTS7n0SO4q6b8rSzWq_RIDBJOsj9QRxPcb3IZgZlQ5jvjGikzJWNeK-85DucH1Ag5dhhL0czi-GMxyHC1dmfKc0hW5TzqJpnm938SIT3xNrWgjZN66P6
+http://seniorfriendfinder.com/cgi-bin/w3com/pws/ffsenior/oo1IpLu33emgRiskeudWkzY7LxFY35wz6EqyQ42lguNadi_4qnt4FhGUPOob_C5Wt99hQSEKEuRTRevsau9UYJ9lySivV-u51_OF4aSEhYXTt98QpjnIOFYPV6acMb20In922uOHMyYdC8HXvwhIP-8o8oM4wLBMdll6aW8xe922WllgXE1F5qlvFqyA
+http://msdn.microsoft.com/library/devprods/vs6/visualj/vjref/java.sql.DatabaseMetaData136.html
+http://msdn.microsoft.com/library/devprods/vs6/visualj/vjref/java.sql.DatabaseMetaData090.html
+http://romulus.ehs.uiuc.edu/cgi-bin/lwgate/RADSAFE/archives/radsafe9902/Date/article-572.html
+http://spaceports.tucows.com/winme/preview/76400.html
+http://www.telecombroker.com/q/001p/ppc3/qG4gs1ewhU.htm
+http://ftp.nodomainname.net/pub/mirrors/.2/gnu/graphics/?N=D
+http://retailer.gocollect.com/do/session/1912813/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/help/site_tour/index.asp
+http://retailer.gocollect.com/do/session/1912813/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/news/index.asp
+http://retailer.gocollect.com/do/session/1912813/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/privacy_policy.asp
+http://202.101.106.19/dir/100/10a/zzgk/bszn/111.htm
+http://www.eveclub.com/cgi-bin/eveclub.front/972959538910/Catalog/1000084
+http://www.eveclub.com/cgi-bin/eveclub.front/972959538910/Club/start/1000000
+http://www.slis.ua.edu/cgi-bin/clickthrough.cgi/CT=http_3a_2f_2fwww_2edermis_2enet_2fbilddb_2fdiagnose_2fenglisch_2fi697015_2ehtm
+http://forum.rai.it/aca-finestre/dispatch.cgi/FORUM/folderFrame/100001/0/rnumber/8467604
+http://www-personal.engin.umich.edu/~vernage/teamweb/team.building/effective.meetings/effective.meetings.facilitation.htm
+http://www4.law.cornell.edu/uscode/42/ch87subchIV.head.html
+http://yp.gates96.com/7/27/90/10.html
+http://yp.gates96.com/7/27/90/11.html
+http://yp.gates96.com/7/27/90/30.html
+http://yp.gates96.com/7/27/91/72.html
+http://yp.gates96.com/7/27/91/76.html
+http://yp.gates96.com/7/27/91/85.html
+http://yp.gates96.com/7/27/91/92.html
+http://yp.gates96.com/7/27/92/61.html
+http://yp.gates96.com/7/27/92/72.html
+http://yp.gates96.com/7/27/93/10.html
+http://yp.gates96.com/7/27/93/17.html
+http://yp.gates96.com/7/27/93/30.html
+http://yp.gates96.com/7/27/93/65.html
+http://yp.gates96.com/7/27/93/76.html
+http://yp.gates96.com/7/27/93/99.html
+http://yp.gates96.com/7/27/94/37.html
+http://yp.gates96.com/7/27/94/85.html
+http://yp.gates96.com/7/27/95/5.html
+http://yp.gates96.com/7/27/95/14.html
+http://yp.gates96.com/7/27/95/55.html
+http://yp.gates96.com/7/27/95/57.html
+http://yp.gates96.com/7/27/96/21.html
+http://yp.gates96.com/7/27/96/49.html
+http://yp.gates96.com/7/27/96/50.html
+http://yp.gates96.com/7/27/96/55.html
+http://yp.gates96.com/7/27/96/92.html
+http://yp.gates96.com/7/27/97/24.html
+http://yp.gates96.com/7/27/97/73.html
+http://yp.gates96.com/7/27/97/98.html
+http://yp.gates96.com/7/27/98/26.html
+http://yp.gates96.com/7/27/98/62.html
+http://yp.gates96.com/7/27/99/15.html
+http://yp.gates96.com/7/27/99/52.html
+http://www.nrk.no/finnmark/x2_9_98/nyh11.htm
+http://www.excelsior.com.mx/9701/970105/nac18.html
+http://www.symantec.co.kr/sabu/igear/igear_educ/stories.html
+http://www.smcworld.com/smcworld/bp/pre/0204_1_1070.html
+http://www.cpami.gov.tw/ymsnp/animal/fauna/nospc708choice.htm
+http://pub9.ezboard.com/fdawsonscreek50374helpwanted
+http://pub9.ezboard.com/fdawsonscreek50374frm17
+http://www.happychannel.it/turismo/europa/top_news/schede/scheda_991209110434.shtml
+http://www.happychannel.it/turismo/europa/top_news/schede/scheda_991111111106.shtml
+http://dirs.educationamerica.net/New_York/Localities/N/New_York_City/Manhattan/Business_and_Economy/
+http://dirs.educationamerica.net/New_York/Localities/N/New_York_City/Manhattan/Government/
+http://china-water.51.net/life/life_20.htm
+http://china-water.51.net/life/life_22.htm
+http://www.egroups.com/message/ramtalk/17801
+http://www.usahardware.com/inet/webSession/shopper/US972959720-31113/store/dept-1
+http://www.usahardware.com/inet/webSession/shopper/US972959720-31113/store/specials
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=97&discrim=2,68,201
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/quizz/legendes/misc/music/lit/hasard.html
+http://findmail.com/group/ken2061
+http://www.affiliate.hpstore.hp.co.uk/do/session/380852/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-photoworld.com/photoworld.asp?lang=f
+http://www.affiliate.hpstore.hp.co.uk/do/session/380852/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/SMARTTIPS/traveljournal.asp
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/www-med.stanford.edu/school/banner.html
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/www-med.stanford.edu/school/neurosurgery.html
+http://hotop.on.net.cn/diguo/club/disp.asp?owner=A201&ID=894
+http://hotop.on.net.cn/diguo/club/disp.asp?owner=A201&ID=846
+http://interbaun.tucows.com/winme/preview/577.html
+http://www.ferien-immobilien.de/ungarn/verkauf/Gemeinsam/Immolink/Exklusiv-IB/Startseite/3d-service/Private-IB/Startseite/Default.htm
+http://www.eos.dk/archive/swing/msg10936.html
+http://www.egroups.com/message/ICSIA-PublicForum/138
+http://www.online.kokusai.co.jp/Service/V0043601/wrd/G200/service/service.html
+http://debian.tod.net/debian/dists/unstable/main/source/libs/?N=D
+http://www.maas.ccr.it/cgi-win/hiweb.exe/a17/d79/b77,e,4d,51,51,819,819,,2,,51,2,4e,,4d,4e,
+http://www.redhat.com/mirrors/LDP/LDP/khg/HyperNews/get/fs/fs/9/?N=D
+http://ftp.oleane.net/pub/CTAN/systems/knuth/local/man1/?D=A
+http://www.jamba.de/KNet/_KNet-_UA8j1-xFd-13bat/browse.de/node.0/cde7f1uou
+http://www.jamba.de/KNet/_KNet-_UA8j1-xFd-13bbg/showInfo-jambabanner.de/node.0/cenv0b09a
+http://www.tente.de/us/produkte/artikel/af000000736.htm
+http://dwp.bigplanet.com/bloomingprairie/look/sitemap.nhtml
+http://www.kfh-mainz.de/Organisationen/Ketteler/pf/ws0001.html
+http://extreme-dm.com/tracking/reports/dj/nph-reloads.cgi?tag=agmusik
+http://www.chaos.dk/sexriddle/c/v/m/v/y/
+http://ring.jec.ad.jp/pub/linux/debian/debian/dists/woody/non-free/binary-i386/electronics/?D=A
+http://tongbang-gh.ed.taejon.kr/1998대전시/math/olym/function/m103_003/html/m103_003h01.html
+http://www.company-product.com/23063/
+http://members.tripod.lycos.co.kr/re22/CPUCOOL5195/uni2k15/?N=D
+http://209.52.189.2/print_message.cfm/stepparents/8279/173602
+http://216.33.87.17/sports/baseball/sba/sba04r.htm
+http://www.mc99.co.jp/mvp/member/new/honda/16kr3fj2/search.cgi?_file=038
+http://www.emerchandise.com/browse/EMERCH/COASTERS/s.cU6lmV05
+http://www.emerchandise.com/browse/CHARMED/s.cU6lmV05
+http://www.across.or.jp/nbbs/nbbs.cgi/talk:n18/replyto/462
+http://www.vins-siffert-scea.fr/lycee-seijo/guide/staff/yoshida.htm
+http://www.egroups.com/messages/grebel-list/2305
+http://polygraph.ircache.net:8181/services/design/http_-2www.abcjewelry.com/http_-2www.1045fm.com/http_-2www.4sitedesign.com/stp/nbm.html
+http://bsd.sinica.edu.tw/cgi-bin/cvsweb.cgi/ports/astro/wmmoonclock/pkg/Attic/DESCR?only_with_tag=RELEASE_4_0_0
+http://biblio.cesga.es:81/search*gag/tMariposas+negras.+1:08,50+min/tmariposas+negras++++1+++08+++50+min/-5,-1,0,B/frameset&F=tmariposa+y+la+hormiga&1,1
+http://polygraph.ircache.net:8181/Cameras/order/rr962.htm
+http://polygraph.ircache.net:8181/Cameras/order/dfwmap.htm
+http://support.tandy.com/support_audio/doc45/45827.htm
+http://image.tulips.tsukuba.ac.jp:70/fif=picture/ECWP/001.fpx&init=-0.23170732,0.0,1.2317073,1.0&rect=0.5,0.25,0.6829269,0.375&wid=600&hei=600&lng=ja&enablePastMaxZoom=OFF&page=uv1-en.html&obj=uv,1.0&cmd=NW
+http://pub23.ezboard.com/fcaribbeanvoiceforumsfrm3.showAddTopicScreenFromWeb
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=9,1+0,0-19,0+9,4
+http://vipnet.tucows.com/win2k/adnload/51108_28465.html
+http://vipnet.tucows.com/win2k/adnload/38782_28482.html
+http://www4.50megs.com/tstazer/edhtms/edbeats.htm
+http://www.unterhaltungs-cd.de/ObervellacherBuam/B000025KMT.htm
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=bocarderont&l=fr
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=146&discrim=10,3,211
+http://variety.studiostore.com/help_security/b.TV%20HERCULES/s.cD15jQkr
+http://variety.studiostore.com/help_shipping/b.TV%20HERCULES/s.cD15jQkr
+http://variety.studiostore.com/product/TSHER0001/b.TV%20HERCULES/s.cD15jQkr
+http://variety.studiostore.com/aboutus/b.TV%20HERCULES/s.cD15jQkr
+http://www.redrocksports.com/sports/webSession/shopper/RR972959753-31163/store/dept-5/department/dept-5/item/51530
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=135&discrim=165,71,194
+http://www.kagtech.com/SpitfrireKennels
+http://www.expage.com/page/thekatshow
+http://www.jobvillage.com/channel/jobs/cleaning/gardener/b.4255.g.3878.html
+http://www.xmwb.sh.cn/xmwb/20000704/BIG5/14016^6070408.htm
+http://www.xmwb.sh.cn/xmwb/20000704/BIG5/14016^7070414.htm
+http://dennou-t.ms.u-tokyo.ac.jp/arch/cc-env/Linux/debian-jp/dists/woody-jp/contrib/binary-all/tex/?S=A
+http://genforum.genealogy.com/ny/monroe/messages/350.html
+http://genforum.genealogy.com/ny/monroe/messages/296.html
+http://genforum.genealogy.com/ny/monroe/messages/306.html
+http://genforum.genealogy.com/ny/monroe/messages/213.html
+http://otenet.themes.tucows.com/fonts/preview/18792.html
+http://otenet.themes.tucows.com/fonts/adnload/18828.html
+http://otenet.themes.tucows.com/fonts/adnload/18876.html
+http://otenet.themes.tucows.com/fonts/preview/18877.html
+http://otenet.themes.tucows.com/fonts/adnload/18894.html
+http://otenet.themes.tucows.com/fonts/adnload/18910.html
+http://otenet.themes.tucows.com/fonts/adnload/18941.html
+http://otenet.themes.tucows.com/fonts/adnload/18949.html
+http://otenet.themes.tucows.com/fonts/adnload/25945.html
+http://ww.egroups.com/message/schoolnet_sadc/96
+http://ww.egroups.com/message/schoolnet_sadc/98
+http://www6.pasta.cs.uit.no/ietf/ietf45/proceedings/I-D/webdav-dublin-core-01.txt
+http://www-uk9.cricket.org/link_to_database/INTERACTIVE/SURVEYS/POLLS_DEC1998.html
+http://www.ucp.org/ucp_generaldsc.cfm/151/8/35/ucp_disctpc/292/263
+http://www.ucp.org/ucp_generaldsc.cfm/151/8/35/ucp_disctpc/79/79
+http://se.egroups.com/message/DBA/1700
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/138/2000/6/0/
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/138/2000/7/0/
+http://www.inf.fu-berlin.de/lehre/WS00/SWT/material/rosebeispiele/interaccess/logicalview/cat32862112022a/cat36e7162c0192/msg343269780227.htm
+http://www.private-immobilien-boerse.de/leipzig/verkauf/Gemeinsam/erreichenPartner/IIM-Teil/Startseite/Gemeinsam/versicherungen/gebaeude/Allgemeine-IB/Startseite/
+http://www.private-immobilien-boerse.de/leipzig/verkauf/Gemeinsam/erreichenPartner/IIM-Teil/Startseite/Gemeinsam/versicherungen/gebaeude/Gemeinsam/Immolink/link.htm
+http://freetravel.bedandbreakfast.com/Canada/Prince%20Edward%20Island/Little%20Sands.asp
+http://freetravel.bedandbreakfast.com/Canada/Prince%20Edward%20Island/Miscouche.asp
+http://freetravel.bedandbreakfast.com/Canada/Prince%20Edward%20Island/O'Leary.asp
+http://www.buybuddy.com/sleuth/15/1/1070306/519432/
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/KIRJASTO-+JA+TIETOPALVELUT/ammattikorkeakoulukirjastot/ammattikorkeakoulut/lahti/p%E4ij%E4t-h%E4me/
+http://www.3w-buecher.de/GravesRobert/GravesRobert0140171991.htm
+http://www.3w-buecher.de/GravesRobert/GravesRobert1559948345.htm
+http://www.3w-buecher.de/GravesRobert/GravesRobert1850897506.htm
+http://members.theglobe.com/heliox2/pokepages/ninepic.htm
+http://taiwan.vh.org//////Providers/Textbooks/MuscleInjuries/Fig2.html
+http://www.globalgarden.com/Tomato/Archives/vol.1/1147.html
+http://www.mojahedin.org/Pages/Mojahed/Mojahed442/articles/articlesftx03.html
+http://216.34.146.180/161000reu/16hlth6.htm
+http://moshkow.sstu.samara.ru/win/BESTER/Encoding_koi
+http://in.egroups.com/message/Girl-Scout-Swaps/9
+http://in.egroups.com/message/Girl-Scout-Swaps/31
+http://members.tripod.com/floydechoes/more.htm
+http://nanjingnews.jlonline.com/nanjingnews/njrb/20000222/08dushi.htm
+http://www.egroups.com/messages/archery/38?expand=1
+http://retailer.gocollect.com/do/session/1912759/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/index.asp
+http://home.dqt.com.cn/~ying_jia/wangwen/new/111.htm
+http://canoe.com/MLB97FLASF/sep30_fla_sf.html
+http://pub2.ezboard.com/fespguitarsmessageboardltdguitarandbassreviews.subscribeUnregisteredToTopic?topicID=8.topic
+http://www.catholicstore.com/search/index.cfm/FuseAction/largeImage/SKU/2558/category/Bo/subCategory/AE/subject/17
+http://www.allgemeine-immobilien-boerse.de/bayern/augsburg/Verkauf/Private-IB/Startseite/Gemeinsam/Inserieren/Private-IB/IIM-Teil/Startseite/froben.htm
+http://www.infoscape.com.cn:8171/nf/0004/18/nfga1801.htm
+http://www.infoscape.com.cn:8171/nf/0004/18/nfga1809.htm
+http://www.linux.com/networking/network/kernel/apache/applications/HTTP/
+http://www.linux.com/networking/network/kernel/apache/applications/Linuxcare/
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=exacerbate&l=en
+http://dopey.rediris.es/ftp/mirror/CPAN/modules/by-module/overload/GSAR/Archive-Tar-0.071.readme
+http://dopey.rediris.es/ftp/mirror/CPAN/modules/by-module/overload/GSAR/Tie-IxHash-1.21.readme
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=207&discrim=3,201,226
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=207&discrim=3,201,85
+http://www.gsnet.com/bdltg/es/1_136243.html?num=2
+http://www.pinoycentral.com/img/UBB.nsf/e39d540ca6a9104b4825694d006ed185/6668efca7b60518648256966000fd202?Navigate&To=Prev
+http://www.academyfloral.com/state/cabel/flowers/harmony.html
+http://trading.rakuten.co.jp/items001/4c/0d/10138895/bidlist.html
+http://www.cs.uwa.edu.au/programming/jdk1.2.2/api/javax/swing/event/class-use/TableColumnModelListener.html
+http://secure.danysoft.com/asp/dany.tienda/803039052/IconBar
+http://ftp-stud.fht-esslingen.de/pub/Mirrors/CPAN/modules/by-authors/id/L/LH/LHS/?S=A
+http://genforum.genealogy.com/ga/messages/6297.html
+http://genforum.genealogy.com/ga/messages/7843.html
+http://genforum.genealogy.com/ga/messages/7281.html
+http://www.jsinc.com/dd/destnat/sep00/fromcol10090800.asp
+http://www.secinfo.com/$/SEC/Filing.asp?T=nDA3.7c_9i4
+http://www.secinfo.com/$/SEC/Filing.asp?T=nDA3.7c_b19
+http://www.sd.digitalcity.com/maconga/penpals/browse.dci?cat=teens
+http://www.sd.digitalcity.com/maconga/penpals/browse.dci?cat=seniors&sort=f
+http://www.picktips.com/category-1031-1172_1170_1174-4_1_3
+http://www-us6.semiconductors.com/acrobat/datasheets/CR6627_1.pdf
+http://ftp.netc.pt/pub/idgames/levels/doom2/deathmatch/p-r/pimp.txt
+http://ftp.netc.pt/pub/idgames/levels/doom2/deathmatch/p-r/radiated.txt
+http://commerce.was-inc.com/cgi-bin/abtwsam.dll/LbkWebCommerceMallCategories-BBC709FC_97F7_9E91E7C8C7066684B664C77C8575B940
+http://commerce.was-inc.com/cgi-bin/abtwsam.dll/LbkWebCommerceOrderStatusOverview-BBC709FC_97F7_9E91E7C8C7066684B664C77C8575B940
+http://ads.puntopartenza.com/cgi-bin/redirect.cgi/31033638
+http://mediate.magicbutton.net/do/session/625642/vsid/4385/tid/4385/cid/88138/mid/1702/rid/2114/chid/3393/url/http://www.worldgallery.co.uk/frameset-top50.html
+http://link.fastpartner.com/do/session/600388/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/netmaling.php
+http://www.egroups.com/message/RecipeCollectors2/3785
+http://plat.debian.or.jp/debian/dists/woody/contrib/binary-alpha/admin/?S=A
+http://198.103.152.100/search*frc/aFILIPPELLI,+R.L/afilippelli+r+l/-5,-1,0,B/frameset&F=afilion+louis+jacques&1,,0
+http://de.excite.de/wetter/katalog/4206
+http://www.burstnet.com/ads/ad8386a-map.cgi/973225252.925077
+http://www.branchenfuehreronline.de/A/hauptteil_a.html
+http://www.linux.com/networking/support/red_hat/internet/test/simple/
+http://www.shopworks.com/ccfarm/index.cfm/action/search/userid/00061450-2F40-19FE-9038010B0A0ADCF2
+http://www.shopworks.com/index.cfm/userid/00061450-2F40-19FE-9038010B0A0ADCF2
+http://pelit.saunalahti.fi/.1/tucows/preview/144491.html
+http://pelit.saunalahti.fi/.1/tucows/preview/52377.html
+http://www.teacherformation.org/html/od/facilitators.cfm/xid,7238/yid,4053212
+http://tw.yahoo.com/Regional/Countries_and_Regions/China/Provinces__Regions_and_Municipalities/Tianjin/Business/Companies/Utilities/
+http://brain.brent.gov.uk/WebPages.nsf/vWebAllPagesByKey!OpenView&Start=174&Count=60&Expand=194
+http://brain.brent.gov.uk/WebPages.nsf/vWebAllPagesByKey!OpenView&Start=174&Count=60&Expand=227
+http://www.bemi-immobilien.de/Landhaus-Bordeaux/Gemeinsam/versicherungen/unfall/Gemeinsam/erreichenPartner/Startseite/Gemeinsam/MarketingStrategie/Startseite/froben.htm
+http://www.bemi-immobilien.de/Landhaus-Bordeaux/Gemeinsam/versicherungen/unfall/Gemeinsam/erreichenPartner/Startseite/Gemeinsam/MarketingStrategie/Gemeinsam/versicherungen/gebaeude/deckungsumfang.htm
+http://www.3wposter.com/hake/hkg1701.htm
+http://www.citybrazil.com.br/go/mossamedes/utilpub.htm
+http://oss.software.ibm.com/developerworks/opensource/cvs/icu4j/icu4j/src/com/ibm/demo/translit/Attic/?sortby=date
+http://www.linux.com/networking/network/management/operating_system/enterprise/research/
+http://www.angelfire.com/pq/Prophetess/Prophetess.page3.html
+http://www.3w-nostalgie.de/ZeigerMimi/ZeigerMimi007072833X.htm
+http://www.excelsior.com.mx/9801/980128/for01.html
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=11&discrim=49,235,5
+http://retailer.gocollect.com/do/session/1912802/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/contact.asp
+http://citeseer.nj.nec.com/track/64292/4220924
+http://citeseer.nj.nec.com/correct/318910
+http://citeseer.nj.nec.com/correct/249393
+http://www.chaos.dk/sexriddle/h/y/r/k/
+http://www.hig.se/(aconf,date,doc,insert,return)/~jackson/roxen/
+http://www.hig.se/(aconf,date,doc,gtext,insert)/~jackson/roxen/
+http://mediate.magicbutton.net/do/session/625608/vsid/4573/tid/4573/cid/88043/mid/2247/rid/2383/chid/3527/url/http://www.winesmart.com/expert.asp
+http://magazines.sina.com/education/renbun/93/13.html
+http://www6.freeweb.ne.jp/art/cilter/kamijo02.htm
+http://yp.gates96.com/11/25/50/28.html
+http://yp.gates96.com/11/25/50/41.html
+http://yp.gates96.com/11/25/50/65.html
+http://yp.gates96.com/11/25/50/74.html
+http://yp.gates96.com/11/25/50/91.html
+http://yp.gates96.com/11/25/50/93.html
+http://yp.gates96.com/11/25/50/94.html
+http://yp.gates96.com/11/25/51/59.html
+http://yp.gates96.com/11/25/51/93.html
+http://yp.gates96.com/11/25/52/66.html
+http://yp.gates96.com/11/25/54/46.html
+http://yp.gates96.com/11/25/54/68.html
+http://yp.gates96.com/11/25/54/83.html
+http://yp.gates96.com/11/25/54/95.html
+http://yp.gates96.com/11/25/54/98.html
+http://yp.gates96.com/11/25/55/1.html
+http://yp.gates96.com/11/25/55/6.html
+http://yp.gates96.com/11/25/55/96.html
+http://yp.gates96.com/11/25/56/83.html
+http://yp.gates96.com/11/25/56/89.html
+http://yp.gates96.com/11/25/57/30.html
+http://yp.gates96.com/11/25/57/68.html
+http://yp.gates96.com/11/25/58/56.html
+http://yp.gates96.com/11/25/58/67.html
+http://yp.gates96.com/11/25/59/7.html
+http://yp.gates96.com/11/25/59/40.html
+http://yp.gates96.com/11/25/59/58.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/misc/legendes/lit/misc/quizz/quizz2.html
+http://excite.de/kleinanzeigen/katalog/7100
+http://www.egroups.org/messages/stepup/97
+http://sunsite.org.uk/pub/packages/proftpd/misc/?S=A
+http://ring.htcn.ne.jp/archives/lang/perl/CPAN/modules/by-module/CGI/DOUGM/?M=A
+http://ring.htcn.ne.jp/archives/lang/perl/CPAN/modules/by-module/CGI/DOUGM/Apache-Scoreboard-0.10.readme
+http://ring.htcn.ne.jp/archives/lang/perl/CPAN/modules/by-module/CGI/DOUGM/B-Size-0.04.readme
+http://herndon1.sdrdc.com/cgi-bin/can_ind/S8NY00082/1/Y/
+http://in.egroups.com/message/msu-foi/20?source=1
+http://www.worldstocks.de/htm/boersen/asien/indonesien_boerse.htm
+http://members.xoom.com/pvmnieuws/movies/movies.html
+http://gb.toget.com.tw/article/screensaver/index_a_2.html
+http://www.emis.de/journals/EJDE/Volumes/Monographs/Volumes/2000/64/?N=D
+http://bsd.wj.o3.net/8/1/18/4.html
+http://www.ftp.uni-erlangen.de/pub/mirrors/_other/afterstep.foo.net/apps/asprint/?S=A
+http://citeseer.nj.nec.com/cidcontext/3597768
+http://m4.findmail.com/dir/Sports/Soccer/Academic_Study_of_Soccer/History
+http://genforum.genealogy.com/cgi-bin/print.cgi?westerman::121.html
+http://www-koi.bards.ru/Egorov/part84.htm
+http://www-koi.bards.ru/Egorov/part29.htm
+http://www-koi.bards.ru/Egorov/part127.htm
+http://www-koi.bards.ru/Egorov/part68.htm
+http://www.loisirs.ch/emjius/10/brglll.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/quizz/music/computers/legendes/lit/hellequin.html
+http://www.redrival.com/dejanss/muzika/exploited/themassacre.html
+http://kernel2.adver.com.tw/Counter/log/kernel2.adver.com.tw/SaveCounter/2000-08-31/13/967698323786.txt
+http://kernel2.adver.com.tw/Counter/log/kernel2.adver.com.tw/SaveCounter/2000-08-31/13/967699453627.txt
+http://kernel2.adver.com.tw/Counter/log/kernel2.adver.com.tw/SaveCounter/2000-08-31/13/967699813970.txt
+http://www.chaos.dk/sexriddle/c/v/w/l/o/
+http://www.chaos.dk/sexriddle/c/v/w/l/x/
+http://www.allgemeine-immobilien-boerse.de/Oesterreich/verkauf/IIM-Teil/Startseite/Allgemeine-IB/Gemeinsam/3d-service/info.htm
+http://www.marktplatz-hs.de/cgi-bin/ChioEditionShop.s/39fe2eeb0239a4a4273fd47540f806ea/IconBar
+http://www.jamba.nl/KNet/_KNet-sDD8j1-GC4-puzu/browse.nl/node.0/cde7f1uou
+http://www.icopyright.com/1.1635.66362
+http://www.ld.com/cbd/archive/1999/05(May)/07-May-1999/Vsol004.htm
+http://www.infoscape.com.cn:8171/nf/0007/05/nfgz0517.htm
+http://209.207.239.212/bkindex/c1034/f1392.html
+http://www.gbnf.com/genealogy/rockwel4/html/d0007/I1584.HTM
+http://www.gbnf.com/genealogy/rockwel4/html/d0023/I3700.HTM
+http://www.hornchurch.londonengland.co.uk/designersgraphic.htm
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/computers/lit/misc/colorart/lit/quizz/
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/computers/lit/misc/colorart/lit/misc/orders_mag.html
+http://www.multimap.com/wi/141313.htm
+http://www.multimap.com/wi/141326.htm
+http://www.thestateofcolorado.com/aconplumbing.html
+http://www.thestateofcolorado.com/aconstairs.html
+http://ftp.netc.pt/pub/idgames/levels/doom2/0-9/10level.txt
+http://members.tripod.com.br/Magoo13/musicas.htm
+http://tucows.bigskysoft.com/winme/adnload/137256_30133.html
+http://www.houses-apartment-rentals.com/Texas/city_search_criteria.asp?state=TX&City=CHICOTA
+http://se.egroups.com/message/trabalhoseguro/186
+http://www.daysinn.com/ctg/cgi-bin/DaysInn/financial_support/AAAksrACwAAABvyAAQ
+http://www.long-life.de/lt040.htm
+http://smartnet.tucows.com/winme/meditme_rating.html
+http://smartnet.tucows.com/winme/meditme_size.html
+http://www.kmoviefc-jp.com/db/prod/pd/k1000003.htm
+http://ftp.rge.com/pub/usenet/readers/mac/Mews/?S=A
+http://fi.egroups.com/messages/lasermail/298
+http://fi.egroups.com/message/lasermail/295
+http://www.voter.com/home/message/post/1,1559,24-60_2976_2473-,00.html
+http://se.egroups.com/message/rv8list/1122
+http://www.ferien-immobilien.de/Rhein-Sieg-kreis/verkauf/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/3d-service/Gemeinsam/Inserieren/Private-IB/Startseite/Default.htm
+http://library.bangor.ac.uk/search/aUnited+Kingdom+Reading+Association/aunited+kingdom+reading+association/-17,-1,0,B/exact&F=aunited+kingdom+environmental+law+association&1,2/limit
+http://webcenter.travelocity-leisure.netscape.com/DestGuides/0,1840,TRAVELOCITY|1987|5|2,00.html
+http://yokohama.cool.ne.jp/michirur/dragon/maria/m2.htm
+http://ring.omp.ad.jp/archives/NetBSD/packages/pkgsrc/graphics/Ngraph/patches/?D=A
+http://mitglied.tripod.de/argewesterwald/jr/jrfo3.htm
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=3,16,10
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=28,16,10
+http://avdistrict.edgate.com/hhs/pa_rc_gre.html
+http://pub26.ezboard.com/fdysfuctionalrealityfrm2.showAddReplyScreenFromWeb?topicID=32.topic&index=1
+http://www.geocities.co.jp/Playtown-Domino/5245/guti.html
+http://www.haikou.hi.cn/Pandect/hknj98/nj98d1.html
+http://retailer.gocollect.com/do/session/1912800/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/help/site_tour/index.asp
+http://ftp.unina.it/pub/Pcibm/pcdemos/ftp.hornet.org/graphics/images/1998/b/?M=A
+http://variety.studiostore.com/browse/ABUGSLIFE/FIGURINE/s.qjEoNLlG
+http://yp.gates96.com/11/76/10/13.html
+http://yp.gates96.com/11/76/10/18.html
+http://yp.gates96.com/11/76/11/63.html
+http://yp.gates96.com/11/76/14/45.html
+http://yp.gates96.com/11/76/14/65.html
+http://yp.gates96.com/11/76/14/77.html
+http://yp.gates96.com/11/76/15/1.html
+http://yp.gates96.com/11/76/15/68.html
+http://yp.gates96.com/11/76/15/97.html
+http://yp.gates96.com/11/76/16/2.html
+http://yp.gates96.com/11/76/16/59.html
+http://yp.gates96.com/11/76/16/64.html
+http://yp.gates96.com/11/76/16/79.html
+http://yp.gates96.com/11/76/17/10.html
+http://yp.gates96.com/11/76/17/52.html
+http://yp.gates96.com/11/76/19/9.html
+http://yp.gates96.com/11/76/19/11.html
+http://yp.gates96.com/11/76/19/17.html
+http://yp.gates96.com/11/76/19/19.html
+http://www.debian.org.cn/Bugs/db/67/67207-b.html
+http://www.bemi-immobilien.de/Exklusiv-IB/Startseite/Gemeinsam/immolink/Gemeinsam/Inserieren/Startseite/Gemeinsam/versicherungen/unfall/Gemeinsam/3d-service/info.htm
+http://www.private-immobilien-boerse.de/baden-wuertemberg/calw/Verkauf/Gemeinsam/versicherungen/gebaeude/Gemeinsam/erreichenPartner/Private-IB/IIM-Teil/Startseite/frinfo.htm
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=21,0-(14,0)+9,5
+http://www.thesite.msnbc.com/tlkbck/comment/2100652/0,7436,80913-291181,00.html
+http://202.109.72.57:8077/article/19991130/1741.htm
+http://www.mit.edu/afs/athena.mit.edu/astaff/project/eolcdev/arch/sgi_62/
+http://www.metromix.com/top/1,1419,M-Metromix-Home-reviews!PlaceDetail-13623,00.html
+http://ring.jec.ad.jp/pub/linux/debian/debian/dists/woody/non-free/binary-powerpc/news/?M=A
+http://commerce.was-inc.com/cgi-bin/abtwsam.dll/LbkWebCommerceStoreCategories-BBC70A07_97FC_42E663949129E2030ACC2E97E71CD8B3
+http://grwy.online.ha.cn/paoe/about/aoe2.htm
+http://www.2pl.com/b/ar/to/1/01/01/v1/1010178470-3.htm
+http://www.digitaldrucke.de/(aktuell,marktplatz,nuernberg,sense,werbung)/suche/uebersicht.html
+http://ustlib.ust.hk/search*chi/aswiss+radio+symphony+orchestra/aswiss+radio+symphony+orchestra/-5,-1,0,B/frameset&F=aswiss+society+for+soil+and+rock+mechanics&1,1
+http://www.ecatsbridge.com/BiB/static/sims/bbljuly99/00000101843221172F1.htm
+http://www.videogames.com/psx/sports/freestyle99/screen.html?page=19
+http://www.mojahedin.org/Pages/Mojahed/Mojahed474/sci/sci02.html
+http://www.shopworks.com/bigmountain/index.cfm/action/cart/userid/000E50D6-1185-19FE-A703010D0A0A8CF2
+http://polygraph.ircache.net:8181/http_-2www.horizonfinance.com/~xionthia/as/
+http://yp.gates96.com/14/76/30/16.html
+http://yp.gates96.com/14/76/30/81.html
+http://yp.gates96.com/14/76/31/12.html
+http://yp.gates96.com/14/76/31/37.html
+http://yp.gates96.com/14/76/31/68.html
+http://yp.gates96.com/14/76/32/11.html
+http://yp.gates96.com/14/76/32/50.html
+http://yp.gates96.com/14/76/32/68.html
+http://yp.gates96.com/14/76/33/26.html
+http://yp.gates96.com/14/76/33/53.html
+http://yp.gates96.com/14/76/35/11.html
+http://yp.gates96.com/14/76/35/26.html
+http://yp.gates96.com/14/76/35/47.html
+http://yp.gates96.com/14/76/35/74.html
+http://yp.gates96.com/14/76/36/16.html
+http://yp.gates96.com/14/76/37/23.html
+http://yp.gates96.com/14/76/37/56.html
+http://yp.gates96.com/14/76/37/82.html
+http://yp.gates96.com/14/76/38/76.html
+http://yp.gates96.com/14/76/39/20.html
+http://yp.gates96.com/14/76/39/25.html
+http://yp.gates96.com/14/76/39/28.html
+http://yp.gates96.com/14/76/39/33.html
+http://yp.gates96.com/14/76/39/61.html
+http://yp.gates96.com/14/76/39/69.html
+http://yp.gates96.com/14/76/39/91.html
+http://www-usa8.cricket.org/link_to_database/ARCHIVE/ARTICLES/JAN-JUN_1996/PRESS_REACTIONS_AUS_18MAR1996
+http://www-usa8.cricket.org/link_to_database/ARCHIVE/ARTICLES/JAN-JUN_1996/LOSS_WI_CRICKET_11MAR1996.html
+http://www-usa8.cricket.org/link_to_database/ARCHIVE/ARTICLES/JAN-JUN_1996/SPINNERS_TALES_11JAN1996
+http://hurweb01.hurriyetim.com.tr/hur/turk/98/11/19/gundem/31gun.htm
+http://library.cuhk.edu.hk/search*chi/aKuan,+Jui-hsuan./akuan+jui+hsuan/-5,-1,0,E/exact&F=akuan+jui+hsuan&1,22
+http://library.cuhk.edu.hk/search*chi/aKuan,+Jui-hsuan./akuan+jui+hsuan/-5,-1,0,E/frameset&F=akuan+jung&1,,0
+http://ring.toyama-ix.net/archives/pc/winsock-l/Windows95/Finger/fing32l.txt
+http://cometweb01.comet.co.uk/do!tid=20&rtid=1&vsid=700&session=132044&mid=1000&rid=1060&cid=37030&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplGGolLarZLq4fLpmiLXv-KmooLckYLoznGmpq0qsc0mojLbkYLozvGotc0ZdoLckYLozvGsmv0qmc0jXfLkVZLdocLkYoLzcj1XfkLVZXLqkXLjbzKcob5qroLkVrLoizKlZd5fjYHfklKkZlLjjbLoZbLpl51ubZLDXZLollK3ljLbqlKjXfLkkaHotl4obmLloqL
+http://student.monterey.edu/nr/riveradebranepom/campus/
+http://forum.rai.it/aca-finestre/dispatch.cgi/FORUM/listUnseen/fol/100001/20,0/5170254
+http://www.ibiblio.org/pub/Linux/distributions/debian/contrib/binary-all/otherosfs/?D=D
+http://www.ilmessaggero.it/hermes/19980909/01_NAZIONALE/SPETTACOLI/E.htm
+http://ayasii.virtualspace.net/html/1207/12071611_himemiya02.htm
+http://retailer.gocollect.com/do/session/1912732/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/about.asp
+http://retailer.gocollect.com/do/session/1912732/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/exclusives/newintros.asp
+http://retailer.gocollect.com/do/session/1912732/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/dealer_lookup.asp
+http://se.egroups.com/subscribe/pretty_of_five
+http://home.neo.rr.com/keeter/pics.html
+http://www.peopledaily.co.jp/haiwai/199910/12/newfiles/E108.html
+http://www.telematik.informatik.uni-karlsruhe.de/osf/sw/v4.0x/lp2/snt100/?M=A
+http://www.alyon.org/perso/1001-sciences/sciences_citoyens/agronomie/agronomie/intervenants.htm
+http://www.2pl.com/b/no/fi/3/02/24/b1/3022400016-11131.htm
+http://channel.nytimes.com/indexes/2000/07/21/sports/hockey/
+http://space.tin.it/io/fivird/REM/eng/albums/lyrics/documentfr.html
+http://www.kurit.com/girls/galleryf.cgi?mp_code=7332&service=girls
+http://store.efunctional.com/nokia.html
+http://dk.egroups.com/login.cgi?login_target=%2Fmessage%2Fbonsai-cz%2F274
+http://bbs.kcm.co.kr/NetBBS/Bbs.dll/boliviabbs/opn/zka/B2-kB2Fq/qqo/007D/qqatt/^
+http://www.loisirs.ch/cvljnq/10/yrespd.html
+http://www.primenet.com/~trakker/events/abcforum.htm
+http://www.primenet.com/~trakker/events/frame_abcforum.htm
+http://www.fogdog.com/cedroID/ssd3040183253760/nav/products/featured_brands/12r/gift_packs/
+http://www.fogdog.com/cedroID/ssd3040183253760/nav/products/featured_brands/12r/windshirts/
+http://www.oreilly.com/homepages/dtdparse/docbook/3.0/dtdent/simmod02.htm
+http://dk.egroups.com/group/SCMHCSC
+http://www.ycwb.com.cn/gb/2000/01/11/ycwb/dsxw/9.html
+http://dk.egroups.com/message/teenhealth/1620
+http://nbzhuhq1.top263.net/htm/y/y14-5.htm
+http://adserver.latimes.com/editions/orange/20001030/t000103739.html
+http://adserver.latimes.com/editions/orange/20001030/t000103751.html
+http://library.bangor.ac.uk/search/cWS+200+G4655+1999/cws++200+g4655+1999/-17,-1,0,B/frameset&F=cws++141+j74+h+1989&2,,2
+http://ftpsearch.belnet.be/pub/os/linux/SuSE-Linux/i386/6.4/disks/rescue
+http://www.rarf.riken.go.jp/archives/tex-archive/macros/latex//contrib/supported/elsevier/model-harv.pdf
+http://www.diogenes.ch/4DACTION/web_glob_showhtml/path=leser/verlag/index.html&ID=483373
+http://crn.com/Components/emailArticle.asp?ArticleID=2114
+http://link.fastpartner.com/do/session/600410/vsid/1970/tid/1970/cid/135878/mid/1060/rid/1488/chid/1970/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/speednames.php
+http://link.fastpartner.com/do/session/600410/vsid/1970/tid/1970/cid/135878/mid/1060/rid/1488/chid/1970/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/nordicliving.php
+http://ftp.gigabell.net/pub/FreeBSD/FreeBSD-stable/packages/emulators/
+http://ftp.gigabell.net/pub/FreeBSD/FreeBSD-stable/packages/print/
+http://emplois.fr.net/archive062000/2348.html
+http://variety.studiostore.com/browse/ANASTASIA/_/b.FAVORITES%20COMICS%20ANIMFEAT/s.eKoxAPfo
+http://www.geocities.co.jp/HeartLand-Gaien/3163/choko.htm
+http://members.tripod.com/~moviemaniac1/moviesR/Rocketman.html
+http://wiem.onet.pl/wiem/0006ac-sp1.html
+http://msdn.microsoft.com/library/devprods/vs6/visualj/vjref/java.net.UnknownHostException001.html
+http://www.tiscover.ch/1Root/Kontinent/6/Staat/30/Bundesland/31/Ort/1732/Homepage/m_homepage...2.html
+http://power.luneng.com/power/library/jzjs/jzjs99/jzjs9903/990311.htm
+http://citeseer.nj.nec.com/cidcontext/1976718
+http://in.egroups.com/messages/srcg/2
+http://sunsite.informatik.rwth-aachen.de/cgi-bin/ftp/ftpshow/pub/comp/Linux/debian/dists/potato/main/disks-sparc
+http://pd.shiseido.co.jp/s9701unt/html/unt00025.htm
+http://www.kame.tadaima.com/9721036/taro1.html
+http://www.kame.tadaima.com/9721036/taro8.html
+http://www.unc.edu/courses/chem41/classnotes/41s6/sld008.htm
+http://a1sexpics.com/butts/buttfucking/
+http://moundoflove.com/buttfucking/butts/asslickinganal.html
+http://www.digitaldrucke.de/(arbeitsvermittlung,hilfe,nuernberg)/_fort/html/themen/hilfe/hilfe.htm
+http://freethemes.netc.pt/preview/15221.html
+http://freethemes.netc.pt/preview/51972.html
+http://freethemes.netc.pt/preview/74442.html
+http://cn.tech.yahoo.com/000913/23/1dpl.html
+http://cn.tech.yahoo.com/000913/23/1dp2.html
+http://wap.jamba.de/KNet/_KNet-JgK8j1-FGd-13di8/browse.de/node.0/cde7f1uou
+http://imageserver2.tibetart.com:8087/fif=fpxbuddhist/43.fpx&init=0.0,0.0,1.0,1.0&rect=-0.25,0.25,0.25,0.75&wid=280&hei=400&lng=en_US&enablePastMaxZoom=OFF&page=image.html&obj=uv,1.0&cmd=S
+http://www.ozemail.com.au/~pballard/gnt_hidden123/mar12.htm
+http://www.ozemail.com.au/~pballard/gnt_hidden123/act9.htm
+http://www.ozemail.com.au/~pballard/gnt_hidden123/rom7.htm
+http://www.ozemail.com.au/~pballard/gnt_hidden123/2co13.htm
+http://www.ozemail.com.au/~pballard/gnt_hidden123/heb12.htm
+http://www.ozemail.com.au/~pballard/gnt_hidden123/jam4.htm
+http://ftp.darenet.dk/tucows/winnt/adnload/1449_29554.html
+http://www.chaos.dk/sexriddle/w/j/u/o/
+http://www.chaos.dk/sexriddle/w/j/u/v/
+http://opac.lib.rpi.edu/search/tmcgraw+hill+series+in+advanced+chemistry/-5,-1,0,B/frameset&tmcgraw+hill+series+in+advanced+chemistry&9,,42
+http://www.zcu.cz/ftp/mirrors/pgp/6.5/6.5.1/win/
+http://webpolitik.subportal.com/sn/Multimedia_and_Graphics/Misc__Graphics_Tools/12852.html
+http://ftp.lip6.fr/pub2/perl/CPAN/doc/manual/html/lib/SysV/SysV.html
+http://bbs.gznet.edu.cn/cgi-bin/getannounce//groups/GROUP_9/Telecom/friend/fbf/ewqtr
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9709/date/article-10.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9709/date/article-88.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9709/date/article-92.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9709/date/article-177.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9709/date/article-178.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9709/date/article-229.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9709/date/article-288.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9709/date/article-293.html
+http://www.usq.edu.au/unit-1997/fullspec/54081s2x.htm
+http://sound-dist.secured.co.uk/cgi-bin/psProdDet.cgi/15P04|972959617|Helmet|user|0|1,0,0,0
+http://www.buybuddy.com.au/sleuth/8/1/5010204/40843/
+http://www.maxpages.com/vote.cgi?site=pokemonyellow1&pg=Home
+http://rex.skyline.net/html/Automobiles_-_Dealers_-_Used.html?64,outdoor,transportation,collectibles,transportation
+http://www.linux.com/networking/network/communications/management/updates/Windows_NT/
+http://retailer.gocollect.com/do/session/1912735/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/top_ten.asp?pagenum=1
+http://amarilloglobenews.com/stories/031000/
+http://www.egroups.com/post/swish?act=reply&messageNum=275
+http://www.apcmag.com/apcweb/reviewsdisc.nsf/aac7d56ca8fd884b852563be00610639/af5bb64432e7f9444a2565240026bbbf!Navigate&To=PrevMain
+http://best.netease.com/guestbook/personal/zhuirinew3.html
+http://best.netease.com/cgi-bin/view/viewbasic.cgi?japanboy4
+http://www.ftp.uni-erlangen.de/cgi-bin/view/pub/mirrors/redhat/current/i386/doc/gsg/ch-basics.htm
+http://www.ftp.uni-erlangen.de/cgi-bin/view/pub/mirrors/redhat/current/i386/doc/gsg/p5202.htm
+http://splitrock.themes.tucows.com/preview/77000.html
+http://splitrock.themes.tucows.com/preview/25855.html
+http://splitrock.themes.tucows.com/preview/134493.html
+http://splitrock.themes.tucows.com/preview/14722.html
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=13,0-22,0+15,0-0,2
+http://www.icopyright.com/1.1634.64625
+http://mvweb.de/olympia/nachrichten/sportarten/ergebnisse/bdt-190900-438-dpa_153140.html
+http://www.rge.com/pub/tex/fonts/armtex/v2.0/examples/plain/
+http://www.club-internet.fr/cgi-bin/h?Antibes
+http://www.caprili.it/santantimo.htm
+http://dic.empas.com/show.tsp/?q=%C3%EB%C8%EF%20%F6%AD%FD%E9&f=B
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=98&discrim=2,38
+http://www.artex.firenze.it/_qualitart/articoli/zoom/02235.htm
+http://home.powertech.no/huftis/w3c/TR/WAI-WEBCONTENT-NO-NYN/checkpoint-list.txt
+http://mtlab.biol.tsukuba.ac.jp/WWW/PDB2/PCD0467/htmls/07.html
+http://library.cuhk.edu.hk/search*chi/aShu,+Tien-min./ashu+tien+min/-5,-1,0,B/exact&F=ashu+tsung+chiao&1,6
+http://www.trnonline.com/archives/2000archives/05242000/how_now_joe_brown/23506.shtml
+http://www.bemi-immobilien.de/Exklusiv-IB/Startseite/Gemeinsam/versicherungen/gebaeude/Gemeinsam/MarketingStrategie/Gemeinsam/erreichenPartner/Gemeinsam/versicherungen/lebensversicherung/Startseite/frinfo.htm
+http://santabarbarashops.com/Mall/Stores/StoreInfo/asp/store-id/1000007121.html
+http://www.angelfire.com/ok/americassweetheart/UNique.html
+http://ukinvest.ukwire.com/articles/199909070731000375A.html
+http://www.streetprices.com/Electronics/Consumer/Camcorders/Digital/sortproductbylowprice/SP374033.html
+http://www.streetprices.com/Electronics/Consumer/Camcorders/Digital/sortproductbylowprice/SP363722.html
+http://www.streetprices.com/Electronics/Consumer/Camcorders/Digital/sortproductbylowprice/SP288187.html
+http://www.streetprices.com/Electronics/Consumer/Camcorders/Digital/sortproductbylowprice/SP288192.html
+http://www.bemi-immobilien.de/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Gemeinsam/Gemeinsam/versicherungen/gebaeude/Startseite/Gemeinsam/Gemeinsam/immolink/Top-Darlehens-Konditionen/anforderungsformular.htm
+http://celes.subportal.com/sn/Business/Standard_Calculators/index1.html
+http://www.linux.com/networking/network/networking/it/future/firewall/
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=198&discrim=87,19,3
+http://www.hig.se/(append,define,language,quote,tablify)/~jackson/roxen/
+http://www.guba.com/114/236/12fE/index-3.phtml
+http://genforum.genealogy.com/tn/messages/7906.html
+http://207.138.41.133/message/BienestarCalifornia/16
+http://207.138.41.133/message/BienestarCalifornia/26
+http://chasnaz.freeyellow.com/email.html
+http://genforum.genealogy.com/cgi-bin/print.cgi?mcevoy::217.html
+http://www.civila.com/brasil/fov/
+http://www.emerchandise.com/associates/b.FAVORITES%20PAGEANTS/s.oAq5vp1w
+http://www.emerchandise.com/help_security/b.FAVORITES%20PAGEANTS/s.oAq5vp1w
+http://www.z-plus.de/freizeit/kino/galerie/roula/kritikwelt.html
+http://www.angelfire.com/mo2/MrMime2000/wewon.html
+http://www.gazeta.com/Iso/Regiony/Lodz/Raporty/Jedzenie/Jedz/020jed.html
+http://www.sportas.de/ddsup00.htm
+http://muc-zvs-web1.goethe.de/an/mel/wabhorst/dtourism.htm
+http://www.cardina.net/~erps
+http://www.polbox.com/p/paruwa/spec.html
+http://ww2.comune.fe.it/cgi-win/hiweb.exe/a2/d72/b31,e,1f,b,b,50,50,,3,,1f,3,9,,1f,9,
+http://www.ld.com/cbd/archive/1999/03(March)/29-Mar-1999/15awd002.htm
+http://dk.egroups.com/post/cbradio?act=reply&messageNum=823
+http://aecjobbank.com/texis/script/newjobs/+lww7mwww0xBV6e52iHwwwesPBB2eZmwwwt6erV0Vwwwh6er6Gswwwt6er6bgwwwt6etDL-www+6ethrCwwxeRT43eR4mwwwt6etrvuwwwn6KeU-wwwmcmrmwxerjmx7mwww1hzmww-eHxww/jobdirectory.html
+http://www.envy.nu/summerslip/past.html
+http://www.envy.nu/summerslip/leave.html
+http://home.pacific.net.sg/~kinnkinn/
+http://www.bluesapphires.net/ladies/lv0444.shtml
+http://www.freerepublic.com/forum/a4148bd.htm
+http://www.sdinfonet.com.cn/024/32/024329969.htm
+http://www.sdinfonet.com.cn/024/32/024329953.htm
+http://www.jpc-music.com/8754347.htm
+http://www.jpc-music.com/5183511.htm
+http://www.jamba.nl/KNet/_KNet-ytO8j1-7D4-pwef/browse.nl/node.0/cde7f38ny
+http://dk.egroups.com/message/noholdsbarred/210
+http://uoi.tucows.com/winme/preview/75912.html
+http://207.197.132.133/lobbyists/98profiles/556.htm
+http://www.jobvillage.com/channel/jobs/protective_services/private_investigator/g.4.html
+http://www.jobvillage.com/channel/jobs/protective_services/private_investigator/b.8946.g.4179.html
+http://aleph.tau.ac.il:4500/ALEPH/eng/ATA/AAS/AAS/SET-MAIL/381462/11/
+http://www-rn.informatik.uni-bremen.de/home/X11R6/xc/lib/font/Speedo/?D=A
+http://www.brio.de/BRIO.catalog/39fe2f7006f69fb6273fd472aa78073d/UserTemplate/6
+http://cardiology.medscape.com/IMNG/ClinPsychNews/1998/v26.n07/cpn2607.34.01.html
+http://www.incestpornstories.com/hot-hardcore-fuckingbanging/plus-sizewhale/slutspretty/slutsbest-friends/erectionfellatio/bisexualtinkerbell.html
+http://yp.gates96.com/7/65/10/40.html
+http://yp.gates96.com/7/65/11/15.html
+http://yp.gates96.com/7/65/11/34.html
+http://yp.gates96.com/7/65/11/69.html
+http://yp.gates96.com/7/65/11/88.html
+http://yp.gates96.com/7/65/12/95.html
+http://yp.gates96.com/7/65/13/82.html
+http://yp.gates96.com/7/65/13/91.html
+http://yp.gates96.com/7/65/13/93.html
+http://yp.gates96.com/7/65/14/2.html
+http://yp.gates96.com/7/65/14/8.html
+http://yp.gates96.com/7/65/15/31.html
+http://yp.gates96.com/7/65/15/38.html
+http://yp.gates96.com/7/65/15/51.html
+http://yp.gates96.com/7/65/15/95.html
+http://yp.gates96.com/7/65/15/96.html
+http://yp.gates96.com/7/65/16/4.html
+http://yp.gates96.com/7/65/16/20.html
+http://yp.gates96.com/7/65/16/58.html
+http://yp.gates96.com/7/65/17/22.html
+http://yp.gates96.com/7/65/17/66.html
+http://yp.gates96.com/7/65/18/37.html
+http://yp.gates96.com/7/65/18/69.html
+http://yp.gates96.com/7/65/18/97.html
+http://yp.gates96.com/7/65/19/0.html
+http://yp.gates96.com/7/65/19/12.html
+http://yp.gates96.com/7/65/19/16.html
+http://yp.gates96.com/7/65/19/28.html
+http://yp.gates96.com/7/65/19/37.html
+http://yp.gates96.com/7/65/19/44.html
+http://dyade.inrialpes.fr/aaa/public/java/jdk1.3/docs/api/javax/swing/plaf/basic/class-use/BasicSplitPaneUI.KeyboardUpLeftHandler.html
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/asiasanahaku/kalatalous/ty%F6voimapolitiikka/pienet+ja+keskisuuret+yritykset/maatilatalous/
+http://www.ferien-immobilien.de/ungarn/verkauf/Gemeinsam/MarketingStrategie/Allgemeine-IB/Private-IB/Private-IB/Startseite/Default.htm
+http://ftp.du.se/disk2/CPAN/modules/by-category/15_World_Wide_Web_HTML_HTTP_CGI/WWW/libwww-perl-5.43.readme
+http://ftp.du.se/disk2/CPAN/modules/by-category/15_World_Wide_Web_HTML_HTTP_CGI/WWW/libwww-perl-5.46.readme
+http://ftp.du.se/disk2/CPAN/modules/by-category/15_World_Wide_Web_HTML_HTTP_CGI/WWW/webchat-0.05.readme
+http://209.0.220.240/biz/541519/541-389-1493.htm
+http://www.shsu.edu/wcb/schools/SHSU/sed/rmzoubi/12/forums/forum54/wwwboard.html
+http://retailer.gocollect.com/do/session/1912768/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/news/index.asp
+http://romulus.ehs.uiuc.edu/cgi-bin/lwgate/RADSAFE/archives/radsafe9610/Date/article-33.html
+http://romulus.ehs.uiuc.edu/cgi-bin/lwgate/RADSAFE/archives/radsafe9610/Date/article-31.html
+http://www.acfas.ca/congres/congres67/S408.htm
+http://pub1.ezboard.com/fthehawkeyehotspotfrm16.showMessage?topicID=178.topic
+http://archives.marshall.edu/~mccomas/cd315-spring00-list/1549.html
+http://www.asiastockwatch.com/AsiaStockWatch_-_Cached/Articles/asw_recommend_friend_con/1,1145,617_1_1:3,00.html
+http://wiem.onet.pl/wiem/014a7e.html
+http://linux99.inrialpes.fr/linux/RPM/kondara/1.2/errata/bugfixes/i586/System_Environment_Daemons.html
+http://linux99.inrialpes.fr/linux/RPM/kondara/1.2/errata/bugfixes/i586/User_Interface_X.html
+http://cn.egroups.com/login.cgi?login_target=%2Fmessage%2FWeb_Holidays%2F35
+http://library.bangor.ac.uk/search/aEuropean+Academy+of+Allergology+and+Clinical+Immunology/aeuropean+academy+of+allergology+and+clinical+immunology/7,-1,0,B/bibandlinks&F=aeuropean+association+for+animal+production+commission+on+animal+management&1,1
+http://www4.freeweb.ne.jp/art/fujiso/gehp/pge222.html
+http://pnews.jcc.co.jp/scoop/9905/990506kk2-3ss.html
+http://ring.nii.ac.jp/archives/linux/Vine/Vine-1.1/kernel-2.2.x-kit/RPMS/
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=81&discrim=8,230,214
+http://www.emerchandise.com/browse/BUFFYTHEVAMP/KEYCHAIN/b.TV%20BUFFYTHEVAMP/s.DfgPpLQw
+http://www.emerchandise.com/browse/BUFFYTHEVAMP/MAGNET/s.DfgPpLQw
+http://www.koms.de/I-Data/Upgrades/HostCom/Cx/isp/?S=A
+http://www.back2roots.org/Aminet/Forums/Util--Wb--Amero36/
+http://www.hig.se/(autoformat,define,en,modified,referrer)/~jackson/roxen/
+http://216.35.79.131/sites/gunits/052302u.html
+http://216.35.79.131/sites/gunits/052303u.html
+http://216.35.79.131/sites/gunits/032883u.html
+http://itcareers.careercast.com/texis/it/itjs/+4wwBmecXD86ExwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewShwAwMwoacnwmamnpcdOMnDBaMwoDBnDwDqnanDtoDnnGaDnBidGAaoDqc1mna5BGdDtaADdicnmtnaGn31oGnmaMFqtwAwMwoDzmeZxwwwpBmIe0B-decrwww5rmeAdwwwBrmeZpwww/morelike.html
+http://troy.lib.sfu.ca/search/tadvocate+vanc/tadvocate+vanc/7,-1,0,B/browse
+http://210.159.30.200:8080/-_-http://www2s.biglobe.ne.jp/~proton/kokuritu/
+http://210.159.30.200:8080/-_-http://www2s.biglobe.ne.jp/~proton/mituzawa/mitusta.html
+http://config.tucows.com/win2k/monitor2k_size.html
+http://config.tucows.com/win2k/adnload/136674_47327.html
+http://www.thisisyork.com/york/news/YORK_NEWS_CAMPAIGNS_POSTOFFICE5.html
+http://yp.gates96.com/5/78/0/35.html
+http://yp.gates96.com/5/78/0/41.html
+http://yp.gates96.com/5/78/0/65.html
+http://yp.gates96.com/5/78/0/79.html
+http://yp.gates96.com/5/78/0/81.html
+http://yp.gates96.com/5/78/1/33.html
+http://yp.gates96.com/5/78/1/76.html
+http://yp.gates96.com/5/78/2/0.html
+http://yp.gates96.com/5/78/2/65.html
+http://yp.gates96.com/5/78/3/37.html
+http://yp.gates96.com/5/78/4/31.html
+http://yp.gates96.com/5/78/4/60.html
+http://yp.gates96.com/5/78/4/73.html
+http://yp.gates96.com/5/78/5/28.html
+http://yp.gates96.com/5/78/5/65.html
+http://yp.gates96.com/5/78/6/12.html
+http://yp.gates96.com/5/78/6/38.html
+http://yp.gates96.com/5/78/6/99.html
+http://yp.gates96.com/5/78/7/48.html
+http://yp.gates96.com/5/78/8/49.html
+http://yp.gates96.com/5/78/8/55.html
+http://yp.gates96.com/5/78/8/71.html
+http://yp.gates96.com/5/78/9/19.html
+http://yp.gates96.com/5/78/9/94.html
+http://link.fastpartner.com/do/session/600420/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/fastpartner.php
+http://www.highwired.net/Guidance/UniversalNav/Redirect/0,5314,15089-15089-728,00.html
+http://ring.tains.tohoku.ac.jp/archives/lang/perl/CPAN/modules/by-module/Math/ILYAZ/os2/?S=A
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/DzRIZER-v0LffJEf3raIMcG3_vXLUQncNB0JHLK7Xt_XcNu5W9Xwg3bnK7e0BWrbchX2jMSNnK6eY6UuDPq6GFLMrzB0DcydY5VgMGVRUFbdksWiDCuTI0LBo3psuJxBJjEd
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/vihIvBk0g-CdjheZ4MILAcJAB--YtsE3nzjAldQSrSojV9JzVQJV-1yVbCi9rsPamZBGc9GfXE6dq1sCz-CnrfwDCHqr_nfUtl2qUN5oWAHphPSuuQXCc2fjfBv3EI-W4XBgp-ANhxEJS0536665
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/VihIDgZ6TF6W8zfPesIFMiw-CNzcKPLyYr5OXnsaqepOa1j4Wz2V-pVOhRfX5lUkxRpYs_BkTdpvjf7zUAk3RdhEaXDfmzm4RA2CLjQ84zSbEZ_Vil1cFFmY0FFZr5oIErljk11AnTlYM6y066jO
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/dRhIQJ3pEIfD5uG_JFeaP3_7Bke37Z5pJi0A-hZ_-kxEK4Z1jl3HNb6d3hgJ7UZ34jMQGSNzhYuMNxB-oyBon62h9GWx3Xt1Zk_o4kS3s9ybikCpzetMwprVGDCC-YzllwvEWxmP66jF
+http://www.v2music.com/Scripts/WebObjects-ISAPI.dll/V2_New_Publisher.woa/24161000003783000000741030000081551/v2tvindex.wo/810000000071551/1.0.4/3/Webobjects1
+http://www.maas.ccr.it/cgi-win/hiweb.exe/a17/d3345/b77,c,4d,469,469,46e,46e,168e,168e,,51,,4d,51,
+http://findmail.com/messages/themcse/102
+http://netcon.tucows.com/winme/adnload/136907_28427.html
+http://netcon.tucows.com/winme/adnload/136906_30076.html
+http://www.jyu.fi/~heili/tietoverkot/?S=A
+http://www1.onelist.com/dir/1/16/483/32773?st=10
+http://www1.onelist.com/messages/animadores
+http://seussville.com/teachers/authors/ayre.html
+http://seussville.com/teachers/authors/corm.html
+http://www.tente.de/sw/produkte/rubriksuche/aa000001461.htm
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=57&discrim=165,57,164
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=57&discrim=165,57,207
+http://jars.developer.com//classes/jresout.cgi?resource=2897
+http://members.tripod.co.jp/spirits/?S=A
+http://homepages.go.com/homepages/i/u/g/iuguy22/
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=21,5,24
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=31,5,24
+http://troy.lib.sfu.ca/search/delectrolytes+periodicals/delectrolytes+periodicals/-5,-1,0,B/exact&F=delectrolytes+congresses&1,3
+http://www.rdg.ac.uk/ITS/Topic/Stats/StGSAS8_01/SAS8/af/z0254912.htm
+http://www.rdg.ac.uk/ITS/Topic/Stats/StGSAS8_01/SAS8/af/z0254924.htm
+http://ring.jec.ad.jp/local/mirror/FreeBSD-current/snapshots/i386/5.0-20000902-CURRENT/compat20/
+http://ring.jec.ad.jp/local/mirror/FreeBSD-current/snapshots/i386/5.0-20000902-CURRENT/dict/
+http://ring.jec.ad.jp/local/mirror/FreeBSD-current/snapshots/i386/5.0-20000902-CURRENT/manpages/
+http://www.xmission.com/~dkenison/cgi/lwgate.cgi/KLR650/archives/v02.n1682/date/article-7.html
+http://ring.toyama-ix.net/pub/linux/Vine/Vine-2.0/ppc/?S=A
+http://romulus.ehs.uiuc.edu/cgi-bin/lwgate/RADSAFE/archives/radsafe9907/Date/article-80.html
+http://www.officeqmart.com/cgi-bin/qmart.front/972959552267/Catalog/3000033
+http://www.checkout.com/member/movies/title/member_reviews_form/1,7722,882122,00.html
+http://mindit.netmind.com/proxy/http://www.siennasoft.com/english/order/orders_retail.shtml
+http://pelit.saunalahti.fi/.1/tucows/adnload/267_29529.html
+http://pelit.saunalahti.fi/.1/tucows/adnload/7574_29534.html
+http://zenha.myrice.com/2/23.htm
+http://zenha.myrice.com/2/20.htm
+http://citeseer.nj.nec.com/cachedpage/62677/1
+http://citeseer.nj.nec.com/check/248055
+http://www.3wbooks.de/BrackRuth/BrackRuth3258053200.htm
+http://preview.egroups.com/group/u_exactus
+http://preview.egroups.com/group/ticovista
+http://www.linux.com/networking/linux/support/va_linux_systems/price/sales/
+http://kulichki-mac.rambler.ru/moshkow/akm/zercalo/kosmix/03.html
+http://innopac.lib.tsinghua.edu.cn:2080/search*chi/tStructure+and+bonding+&%2359%3B+70/tstructure+and+bonding+++70/19,-1,0,B/browse
+http://www.science.uva.nl/pub/NetBSD/NetBSD-current/pkgsrc/archivers/gcpio/files/
+http://www-d0.fnal.gov/d0dist/dist/releases/pmc04.00.00/calibration_management/?S=A
+http://mvweb.de/olympia/nachrichten/sportarten/news/bdt-290900-158-dpa_173282.html
+http://www.scifi.com/bboard/browse.cgi/3/1/69/57?pnum=2
+http://www.diogenes.ch/4DACTION/web_rd_aut_prview/a_id=7056459&area=&ID=483365
+http://mirror.cc.utsunomiya-u.ac.jp/mirror/CPAN/authors/id/L/LA/LAXEN/?D=A
+http://www.affiliate.hpstore.hp.co.uk/do/session/380856/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.france.hp.com/Main/acheterhp/
+http://library.cuhk.edu.hk/search*chi/aLu,+Li,+1914-/alu+li+1914/-5,-1,0,B/frameset&F=alu+li+chun&1,1
+http://www-usa4.cricket.org/link_to_database/ARCHIVE/2000-01/IND_LOCAL/WOMEN/OTHERS/KLCA-SL/SQUADS/
+http://www.babyheirlooms.com/catalog/htmlos.cat/041141.1.4425650346
+http://193.207.57.3/cgi-win/hiweb.exe/a2/d9/b1305,4,5,,1f,5,
+http://www.icopyright.com/1.1664.228033
+http://www.trax.nilex.co.uk/trax.cgi/A1C/B1S/1AR/A2S/A1S/D1L/
+http://www.trax.nilex.co.uk/trax.cgi/A1C/B1S/1AR/A2S/A1S/A2S/
+http://www.ferien-immobilien.de/baden-wuertemberg/calw/Verkauf/Gemeinsam/Inserieren/Private-IB/Gemeinsam/Super-Zins-Konditionen/3d-service/info.htm
+http://sunsite.informatik.rwth-aachen.de/LinuxArchives/redhat/releases/guinness/i386/en/dosutils/fips15c/restorrb/
+http://213.36.119.69/do/session/153002/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/connaitre/revue-presse_titres.html
+http://pub19.ezboard.com/uvinylangel.showPublicProfile?language=EN
+http://boeing_dude.tripod.com/id125_m.htm
+http://members.fortunecity.com/greatway1/gallery-pageother-0.htm
+http://www.searchtraffic.com/wsignup.php3?owor12
+http://www.staroriental.net/nav/soeg_c/ihf,acv,s0,194,陳慧琳.html
+http://www.jpc-music.com/5864555.htm
+http://oaziz.narod.ru/kuhn/uzb/sal_f1.html
+http://preview.egroups.com/message/4aromatherapy/1112
+http://www.luecos.de/webguides/reisen/travelpictures/europe
+http://www.maas.ccr.it/cgi-win/hiweb.exe/a18/d47/b47,8,be,29,29,,38,,be,38,
+http://www.chaos.dk/sexriddle/k/u/u/a/
+http://www.chaos.dk/sexriddle/k/u/u/d/
+http://student.monterey.edu/nr/nielsenadamp/campus/
+http://excite.de/gesundheit/katalog/3727
+http://www.ozemail.com.au/~jcai/page19.html
+http://www.ozemail.com.au/~jcai/page24.html
+http://www.hantsnet.co.uk/scrmxn/c23173.html
+http://www.fogdog.com/cedroID/ssd3040183334784/content/fan/subway_series/
+http://www.fogdog.com/cedroID/ssd3040183334784/boutique/arnette/
+http://www.fogdog.com/cedroID/ssd3040183334784/boutique/hi-tec/
+http://www.fogdog.com/cedroID/ssd3040183334784/boutique/marmot/
+http://ftpsearch.belnet.be/packages/CPAN/modules/by-module/Stat/ENNO/
+http://go1.163.com/_NTES/~yejingsong/03/y18/506.htm
+http://sinr.net/book/content/343/26710.html
+http://www.ramada.com/ctg/cgi-bin/Ramada/progpack/AAAksrACwAAABtrAAV
+http://library.bangor.ac.uk/search/aBoer,+J.+H.+de+(Jan+Hendrik),+1899-/aboer+j+h+de+jan+hendrik+1899/-5,-1,0,B/buttonframe&F=aboer+dirk+jan+den&1,1
+http://library.cuhk.edu.hk/search*chi/a三省堂(千代田區,+Tokyo,+Japan)/a%7B213024%7D%7B214d49%7D%7B213840%7D+%7B213458%7D%7B213073%7D%7B214c24%7D%7B213455%7D+tokyo+japan/-5,-1,0,B/browse
+http://ibm1.cicrp.jussieu.fr/ibmc/classref/ref/ISetCanvas--Style_DSC.htm
+http://amateur-alley.porncity.net/169/
+http://www.teacherformation.org/html/od/facilitators.cfm/task1,about/discussion_id,2/xid,1989/yid,5768630
+http://www.shopworks.com/index.cfm/action/mallcat/mallcatlevel/2/parentmallcat/6/userid/000056F0-2E26-19FE-AF65010C0A0A8CF2
+http://retailer.gocollect.com/do/session/1912760/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/shipping_policy.asp
+http://news.novgorod.ru/news/2001/4/1/8/-1
+http://news.novgorod.ru/news/2001/4/3/8/-1
+http://sp201.unige.ch:49213/cxxdoc/classref/ref/ITimingTestStopwatch_DSC.htm
+http://netscape.digitalcity.com/boston/localexperts/profile.dci?screenName=PSYWU
+http://netscape.digitalcity.com/boston/localexperts/profile.dci?screenName=Mende67
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=17,2,26,33,23
+http://www.multicosm.com/facade/www.isinet.com/isilinks/isilinks.html
+http://kutschen.de/Schoner/Info-d/history/history/literature/
+http://troy.lib.sfu.ca/search/dengineering+research+periodicals/dengineering+research+periodicals/-5,-1,0,B/frameset&F=dengineering+research+grants+canada&3,,4
+http://member.nifty.ne.jp/y-shibata/pc/pch2.htm
+http://stocks.tradingcharts.com/stocks/charts/iops-bb/m
+http://www.kaos.dk/sexriddle/x/j/c/s/z/
+http://www.bioimages.org.uk/HTML/R138925.HTM
+http://pub22.ezboard.com/fawolpaintballfrm1.threadControl?topicID=82.topic
+http://www.incestpornstories.com/hot-hardcore-fuckingbanging/plus-sizewhale/body-shotstounge/fuckinghardcore/barely-legalbackseat/{gaylink}
+http://www.buybuddy.com/sleuth/27/1/1060904/5811/
+http://www.loisirs.ch/gtfmjv/9/nkrlua.html
+http://vorg1.subportal.com/sn/Utilities/File_Maintenance_and_Repair_Utilities/6387.html
+http://smartnet.tucows.com/winme/adnload/138584_30392.html
+http://ftpsearch.belnet.be/mirrors/src.doc.ic.ac.uk/usenet/usenet-by-hierarchy/comp/emacs/?D=A
+http://genforum.genealogy.com/cgi-genforum/forums/green.cgi?7578
+http://cio.cisco.com/warp/public/789/33.html
+http://www7.freeweb.ne.jp/diary/bru_dog/tk/
+http://www.chinabyte.com/staticpages/software/software_download/GRBA/software_download_23274_GRBA.html
+http://www.chinabyte.com/staticpages/software/software_download/GRBA/software_download_9599_GRBA.html
+http://www.seekon.com/L/US/IL/Abingdon
+http://freethemes.arrakis.es/skins/winamp/adnload/25359.html
+http://www.hig.se/(accessed,modified,remove_cookie,smallcaps,sqlquery)/~jackson/roxen/
+http://cn.egroups.com/message/SF-users/218
+http://cn.egroups.com/message/SF-users/235
+http://www.chaos.dk/sexriddle/r/f/y/c/
+http://www.chaos.dk/sexriddle/r/f/y/e/
+http://www.chaos.dk/sexriddle/r/f/y/g/
+http://yp.gates96.com/13/50/10/33.html
+http://yp.gates96.com/13/50/10/49.html
+http://yp.gates96.com/13/50/10/55.html
+http://yp.gates96.com/13/50/10/98.html
+http://yp.gates96.com/13/50/11/35.html
+http://yp.gates96.com/13/50/11/73.html
+http://yp.gates96.com/13/50/11/94.html
+http://yp.gates96.com/13/50/12/39.html
+http://yp.gates96.com/13/50/13/8.html
+http://yp.gates96.com/13/50/13/67.html
+http://yp.gates96.com/13/50/14/8.html
+http://yp.gates96.com/13/50/14/11.html
+http://yp.gates96.com/13/50/14/47.html
+http://yp.gates96.com/13/50/16/18.html
+http://yp.gates96.com/13/50/16/58.html
+http://yp.gates96.com/13/50/17/33.html
+http://yp.gates96.com/13/50/18/13.html
+http://yp.gates96.com/13/50/18/49.html
+http://yp.gates96.com/13/50/18/54.html
+http://yp.gates96.com/13/50/19/0.html
+http://cn.egroups.com/post/romtrade?act=reply&messageNum=3851
+http://members.fortunecity.com/toleransi/sorbonne.html
+http://ring.htcn.ne.jp/pub/lang/perl/CPAN/modules/by-module/PPM/MURRAY/?S=A
+http://sunsite.berkeley.edu/PhiloBiblon/BITAGAP/BIB/BIB5648.html
+http://sunsite.berkeley.edu/PhiloBiblon/BITAGAP/BIB/BIB7392.html
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus53940/eus53960/eus54753/eus543189/eus550516/
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus53940/eus53960/eus54753/eus543189/eus550528/
+http://shn.webmd.com/roundtable_printing/774674
+http://www.zi.unizh.ch/software/unix/statmath/sas/sasdoc/lgref/z0205140.htm
+http://www.hblb.org.uk/hblbweb.nsf/$Pages/NewsArchive1!OpenDocument&ExpandSection=16,12,3,13,5,6,9
+http://www.uni-duesseldorf.de/ftp/ftp/pf/share/fvwm-2.0.45/?S=A
+http://members.tripod.com/~PhyrePhox/mcse/70-088.htm
+http://extreme-dm.com/tracking/reports/dj/nph-ref1.cgi?tag=nimrood
+http://opac.lib.ntnu.edu.tw/search*chi/++ftlist/bp20040397/-5,-1,0,B/frameset&F=bp20040402&1,1
+http://209.0.220.240/spec/txve.htm
+http://209.0.220.240/spec/tyai.htm
+http://ftp.up.pt/Linux/Linus/net-source/www/clients/netscape/?M=A
+http://ftp.up.pt/Linux/Linus/net-source/www/clients/netscape/?D=A
+http://www.jobvillage.com/channel/jobs/health_care/nursing/licensed_practical_nurse/b.9505.g.1766.html
+http://www.zope.org/Members/stevea/CoadObjectModels/BackLinks/backlinks
+http://www.mairie-montreuil93.fr/ville_pratique/environ/energie/mve/media/?D=A
+http://member.shangdu.net/home2/chr/jishang/hongkong/inxg-6.html
+http://www.wild-dog.com/activity/touring/idx/page_18_1.html
+http://members.tripod.co.jp/susu/?M=A
+http://www.dulux.co.uk/UKRETAIL:623356687:DFinity.1QJiP4jMLco
+http://www.kordic.re.kr/~trend/Content326/agriculture04.html
+http://www.kordic.re.kr/~trend/Content326/agriculture09.html
+http://ftp.lip6.fr/pub12/OpenBSD/src/gnu/egcs/config/mh-aix43
+http://ftp.lip6.fr/pub12/OpenBSD/src/gnu/egcs/config/mh-elfalphapic
+http://ftp.lip6.fr/pub12/OpenBSD/src/gnu/egcs/config/mt-x86pic
+http://www.ecatsbridge.com/BiB/static/sims/bbljuly99/00000101758612773F1.htm
+http://pub20.ezboard.com/faustralianslotcarreviewhoracing.showMessage?topicID=2.topic&index=47
+http://ring.omp.ad.jp/archives/NetBSD/packages/pkgsrc/games/exchess/pkg/DESCR
+http://homepage.renren.com/sandybay/help.htm
+http://no.egroups.com/post/oslosynth?act=reply&messageNum=634
+http://www.brio.de/BRIO.catalog/39fe2f940703266c273fd472aa7806a8/UserTemplate/2
+http://www.50megs.com/prettysenshi/captures/ep3/SMep3.html
+http://www.thisislancashire.co.uk/lancashire/archive/1999/11/05/CHORNEWS5VQ.html
+http://au.yahoo.com/Regional/U_S__States/California/Metropolitan_Areas/San_Francisco_Bay_Area/Entertainment_and_Arts/Restaurants/Coffee_and_Tea_Houses/
+http://www.niwl.se/WAIS/30002/30002360.htm
+http://www.infoscape.com.cn:8178/gb/content/2000-08/16/content_6082.htm
+http://link.fastpartner.com/do/session/600419/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/mondosoft.php
+http://www.canit.se/(c1,f3,ftp,generellt,irc,mail)/support/
+http://citeseer.nj.nec.com/cidcontext/3787443
+http://www.affiliate.hpstore.hp.co.uk/do/session/380878/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/entry.asp
+http://www.usq.edu.au/unit-1997/fullspec/51129s3x.htm
+http://worldres.lycos.com/script/gen_mr.asp?hotel_id=6354&n=1518
+http://www.members.aon.at/~kleindlp/neue_seite_4.htm
+http://210.169.76.95/html/tai_0043/bat_1180.html
+http://oneplace.adbureau.net/accipiter/adclick/site=ONEPLACE/area=INDEX/POSITION=FOOTER/AAMSZ=468x60/ACC_RANDOM=262411779164
+http://www.service911.com/mvu/step/0,2632,6+34+90+23506+13880_4,00.html
+http://ftp.lip6.fr/pub11/NetBSD/NetBSD-current/src/usr.sbin/kvm_mkdb/Makefile
+http://www.bemi-immobilien.de/Private-IB/Startseite/Startseite/Gemeinsam/versicherungen/unfall/Gemeinsam/immolink/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Gemeinsam/versicherungen/gebaeude/anforderungsformular.htm
+http://wap.jamba.de/KNet/_KNet-BOC8j1-LFd-13bpy/showInfo-hilfe.de/node.0/cenv0b09a
+http://wap.jamba.de/KNet/_KNet-BOC8j1-LFd-13bq0/browse.de/node.0/cde7f1uou
+http://cnnews.sina.com/kwongzhou/china/2000/1026/2083022_2.html
+http://www.msb.malmo.se/search*swe/dFlygplanskonstruktion/dflygplanskonstruktion/-5,-1,0,B/frameset&F=dflygolyckor&4,,6
+http://home.hanmir.com/~100sun/joo4.htm
+http://www.szed.com/szsb/19990629/GB/default.htm
+http://www.szed.com/szsb/19990629/GB/4-NPCLASS.HTM
+http://www.szed.com/szsb/19990629/GB/7-NPCLASS.HTM
+http://www2.kbank.no/Web/nlpublish.nsf/Published/ord_og_uttrykk!OpenDocument&ExpandSection=15,24,26,25
+http://movies.exit.de/lichtsammler/images/tunnel/gross/sw_kb/?D=A
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=5,34,38
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=21,34,38
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=31,34,38
+http://fi.egroups.com/login.cgi?login_target=%2Fmessage%2Fgamp%2F1734
+http://de.excite.de/katalog/katalog/9231
+http://www-win.rusf.ru/esli/rubr/books/es0500di.htm
+http://www.jamba.de/KNet/_KNet-yjF8j1-8Gd-13cj6/browse.de/node.0/cde7f1uou
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/misc/lit/programs/misc/math/lit/athalie.html
+http://ftp.fi.debian.org/debian/dists/Debian2.2r0/contrib/binary-powerpc/interpreters/?S=A
+http://jupiter.u-3mrs.fr/~msc41www/releves/04350110.HTM
+http://ocean.ntou.edu.tw/search*chi/dDigital+modulation/ddigital+modulation/7,-1,0,E/frameset&F=ddigital+techniques+signal+processing&4,,0
+http://pub20.ezboard.com/fcharmingtailsresourcetradeyoursportscardshere.unsubscribeUnregisteredToTopic?topicID=43.topic
+http://www.kaos.dk/sexriddle/x/w/k/u/q/
+http://www.kaos.dk/sexriddle/x/w/k/u/t/
+http://216.205.158.3/smm/programs/CDG_Player/wwwboard/messages/27.html
+http://216.205.158.3/smm/programs/CDG_Player/wwwboard/messages/60.html
+http://fen.com/whatworks/review/edit/1,2560,1-9696-5539-0-45394,00.html
+http://yp.gates96.com/8/74/30/30.html
+http://yp.gates96.com/8/74/31/1.html
+http://yp.gates96.com/8/74/32/12.html
+http://yp.gates96.com/8/74/32/60.html
+http://yp.gates96.com/8/74/32/92.html
+http://yp.gates96.com/8/74/33/41.html
+http://yp.gates96.com/8/74/33/55.html
+http://yp.gates96.com/8/74/33/57.html
+http://yp.gates96.com/8/74/33/95.html
+http://yp.gates96.com/8/74/34/21.html
+http://yp.gates96.com/8/74/34/23.html
+http://yp.gates96.com/8/74/34/79.html
+http://yp.gates96.com/8/74/35/3.html
+http://yp.gates96.com/8/74/35/22.html
+http://yp.gates96.com/8/74/35/79.html
+http://yp.gates96.com/8/74/36/31.html
+http://yp.gates96.com/8/74/36/84.html
+http://yp.gates96.com/8/74/37/58.html
+http://yp.gates96.com/8/74/37/77.html
+http://yp.gates96.com/8/74/37/89.html
+http://yp.gates96.com/8/74/37/97.html
+http://yp.gates96.com/8/74/39/43.html
+http://yp.gates96.com/8/74/39/63.html
+http://yp.gates96.com/8/74/39/88.html
+http://www9.hmv.co.uk:5555/do/session/1347828/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/newmenu.html
+http://www9.hmv.co.uk:5555/do/session/1347828/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/departments/d80_sd0_pt0.html
+http://gladstone.uoregon.edu/~sme28057/arch181-202/assign2/?M=A
+http://cco.cisco.com/univercd/cc/td/doc/product/core/7206/7206ig/trble6ug.pdf
+http://210.32.1.18/goldbook/humor/mh/c/changgu/1/028.htm
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=17,28,24,31,11
+http://www.spiral.at/Katalog/Artikel/7561032/
+http://www.crutchfield.com/cgi-bin/S-Ql7dbZlSZa2/viewcart.asp
+http://www.fogdog.com/cedroID/ssd3040183327788/nav/products/winter_sports/1b/shell_pants/
+http://www.fogdog.com/cedroID/ssd3040183327788/nav/products/winter_sports/1j/oakley/
+http://www.fogdog.com/cedroID/ssd3040183327788/nav/products/winter_sports/1l/day_packs/
+http://www.thestateofcolorado.com/pglblock.html
+http://www.staroriental.net/nav/soeg/ihf,adj,s0,259,Kristy+Yeung+Gung-Yu.html
+http://pcmcia.sourceforge.org/cgi-bin/HyperNews/get/pcmcia/toshiba/38.html
+http://sunsite.org.uk/public/public/packages/Dr-Fun/df9412/?N=D
+http://nt.mortgage101.com/partner-scripts/1144.asp?p=mig&pw=600
+http://biblioteca.upv.es/bib/doc/doc_fisbd/17/87050//C/1828104/3////25/N/MLTPAI
+http://130.80.29.3/content/houston/k-12/hanc/
+http://javatest.a-net.nl/exhibits/default.htm
+http://javatest.a-net.nl/museum_info/job_opportunities.asp
+http://books.hyperlink.co.uk/booklist/Alphabet_Workbook/Cheney/Martha/1565658396
+http://kobe.cool.ne.jp/orera/guestbook.html
+http://ftp.eecs.umich.edu/pub/NetBSD/packages/1.4.1/vax/audio/
+http://ftp.eecs.umich.edu/pub/NetBSD/packages/1.4.1/vax/editors/
+http://ftp.eecs.umich.edu/pub/NetBSD/packages/1.4.1/vax/tk80/
+http://www.zdnet.de//news/artikel/1999/03/09001-wc.html
+http://neptune.guestworld.com/gear/gateway.cfm?action=private&owner=sitonga7
+http://www.de.lycos.de/dir/Reisen_und_Regionen/L%E4nder_und_St%E4dte/Deutschland/Schleswig-Holstein/St%E4dte_und_Orte/St%E4dte_und_Orte_P_bis_S/
+http://www.mirror.edu.cn/res/sunsite/pub/academic/music/album-reviews/1995/9-September/?M=A
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=213&discrim=176,11,57
+http://europa.eu.int/abc/doc/off/bull/el/9705/x085.htm
+http://europa.eu.int/abc/doc/off/bull/el/9705/x209.htm
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=15,0+17,0-3,0-9,0
+http://www.ferien-immobilien.de/baden-wuertemberg/stuttgart/Verkauf/Gemeinsam/MarketingStrategie/Ferien-IB/Startseite/Gemeinsam/Super-Zins-Konditionen/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/indexbeginn.htm
+http://www.ferien-immobilien.de/baden-wuertemberg/stuttgart/Verkauf/Gemeinsam/MarketingStrategie/Ferien-IB/Startseite/Gemeinsam/Super-Zins-Konditionen/Gemeinsam/impressum.htm
+http://www.chaos.dk/sexriddle/s/e/x/v/i/a/w/
+http://pub4.ezboard.com/fscarletstreethorroritalianstyle.showAddReplyScreenFromWeb?topicID=15.topic
+http://ftp.dti.ad.jp/pub/lang/CPAN/authors/id/P/PJ/PJF/
+http://www.highwired.net/Paper/EmailToFriend/1,2102,302-183023,00.html
+http://ftpsearch.belnet.be/mirror3/ftp.kde.org/pub/kde/Incoming/Attic/old/1.1.2/apps/ide/?D=A
+http://www.affiliate.hpstore.hp.co.uk/do/session/380877/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-creativeworld.com/creativeworld.asp?lang=f
+http://expert.cc.purdue.edu/~steinfoc/assignment3/assig3.html
+http://www.wyborcza.com/Ascii/Raporty/Filmowa/277rap.html
+http://www.redhat.com/mirrors/LDP/LDP/LG/issue50/misc/pollman/?D=A
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=148&discrim=142,11,200
+http://www.marktplatz-hs.de/cgi-bin/ChioEditionShop.s/39fe2ee602379b7e273fd47540f806e1/Catalog
+http://www.affiliate.hpstore.hp.co.uk/do/session/380836/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/SMARTTIPS/createbroch.asp
+http://joy1.alpha-g.ne.jp/tree/user/a/amuro/2_index.shtml
+http://time.188.net/movie/star/taiwan/2/pic/image36.htm
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=25,1,36,31,11
+http://bsd.sinica.edu.tw/cgi-bin/cvsweb.cgi/ports/audio/kdemultimedia11-i18n/Attic/pkg-comment?only_with_tag=RELEASE_2_2_7
+http://www.landfield.com/ftp/usenet/news.answers/bicycles-faq/?S=A
+http://wap.jamba.de/KNet/_KNet-puF8j1-aGd-13clg/browse.de/node.0/cenv0b09a
+http://www.empas.com/search/all.html?q=%C0%CC%B7%D3%B4%D9
+http://www.linux.com/networking/server/install/howto/website/developers/
+http://aecjobbank.com/texis/script/newjobs/+NwxBm6ev7I1wwwhmrmwxetiAw/jobdirectory.html
+http://www.egroups.com/message/ijtihadmk/5
+http://www.egroups.com/message/ijtihadmk/11
+http://www.realize.com/am67bd81.htm,qt=e784fe2f=2a38a234-7-da6e2d-0-0-0-3--
+http://www.realize.com/p643c81.htm,qt=e784fe2f=2a38a234-7-da6e80-0-0-0-3--
+http://moneysaver.net/netcall/?almktng
+http://www.agria.hu/bikersmeeting/archivum/talalkozo/foto/taj.cgi?15n
+http://link.fastpartner.com/do/session/600401/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/company/
+http://198.103.152.100/search*frc/aDidsbury,+Howard+F.,+1924-/adidsbury+howard+f+1924/-5,-1,0,B/frameset&F=adidier+marcel&1,,0
+http://198.103.152.100/search*frc/aDidsbury,+Howard+F.,+1924-/adidsbury+howard+f+1924/-5,-1,0,B/frameset&F=adidier+michel&1,,0
+http://www.medoc-ias.u-psud.fr:81/synoptic/gif/001020/?D=A
+http://shop.goto.com/compperiph/periph/cdrom/search/sidexside.jhtml?s=1&sort_up=LOW_PRICE
+http://excite.de/wirtschaft/katalog/1356
+http://excite.de/wirtschaft/katalog/2631
+http://www.areteoutdoors.com/channel/earth/caving/b.89.g.473.html
+http://www.areteoutdoors.com/channel/earth/caving/b.91.g.473.html
+http://bo.ole.com/actualidad/articulo/html/act13873.htm
+http://www.dulux.co.uk/UKRETAIL:446033260:DFinity.1QJiP4jMomdoclfieh
+http://www.linux.com/networking/network/release/sap/hardware/firewall/
+http://genforum.genealogy.com/cgi-genforum/forums/hendrix.cgi?430
+http://www.chaos.dk/sexriddle/s/p/w/c/
+http://198.103.152.100/search*frc/tCanada+in+the+21st+century.+II,+Resources+and+technology/tcanada+in+the+21st+century+ii+resources+and+technology/-5,-1,0,B/frameset&F=tcanada+in+the+21st+century+no+01&1,1
+http://books.hyperlink.co.uk/bookinfo/Sunk_Costs_and_Market_Structure/Sutton/John/0262193051
+http://members.tripod.com/theshavedbeaver/site2/s2laststand.html
+http://members.tripod.com/theshavedbeaver/site2/s2s1ep21.html
+http://www.ytmag.com/cgi-bin/redirect.cgi/602479760
+http://www18.freeweb.ne.jp/school/syodou/you005.htm
+http://www.fogdog.com/cedroID/ssd3040183334500/nav/products/featured_brands/2h/replica_jerseys/
+http://www.fogdog.com/cedroID/ssd3040183334500/nav/products/featured_brands/2h/replica_jerseys/4.html
+http://www.fogdog.com/cedroID/ssd3040183334500/crs/nvCZ/wld/fogdog_sports/champion/fan_memorabilia/apparel/vlade_divac_replica_jersey.html
+http://www.jobvillage.com/channel/jobs/travel/travel_guide/b.4897.g.5299.html
+http://www.bcbsal.org/Provider_Dir/pharmacy/state/Oregon/HILLSBORO/index_29061.html
+http://www.maas.ccr.it/cgi-win/hiweb.exe/a17/d2066/b77,c,4d,469,469,1b65,1b65,,51,811,4d,51,811,,
+http://www.loisirs.ch/bbewxu/2/wofyff.html
+http://mitglied.tripod.de/Jag3/jag3b.htm
+http://linuxberg.starhub.net.sg/x11html/preview/9016.html
+http://linuxberg.starhub.net.sg/x11html/preview/9062.html
+http://linuxberg.starhub.net.sg/x11html/preview/9103.html
+http://linuxberg.starhub.net.sg/x11html/preview/9820.html
+http://linuxberg.starhub.net.sg/x11html/preview/10370.html
+http://linuxberg.starhub.net.sg/x11html/preview/9965.html
+http://linuxberg.starhub.net.sg/x11html/preview/10117.html
+http://linuxberg.starhub.net.sg/x11html/preview/10129.html
+http://linuxberg.starhub.net.sg/x11html/preview/10152.html
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=150&discrim=251,11,3
+http://totalsports.aol.com/stats/bbo/int/20000624/tol.at.swb.game.html
+http://excite.de/gesundheit/katalog/41575
+http://bbs.csie.ntu.edu.tw/txt/Emprisenovel/ebooks/other/hsiao_yi/jqhy/007.txt
+http://www.memorialcup99.com/HockeyStLouisArchive/nov17_stl.html
+http://www.letsmusic.com/directory/theme/genre_each/1,1137,Z-ㄴ-124-2-2,00.asp
+http://rainforest.parentsplace.com/dialog/get/bedwetting/29/2.html?outline=-1
+http://www.volny.cz/j_medkova/p05.html
+http://www.maas.ccr.it/cgi-win/hiweb.exe/a17/d2072/b77,c,4d,51,51,815,815,818,7d9,,51,7d9,818,,
+http://collection.nlc-bnc.ca/100/200/301/ccmd-ccg/ccmd_report-e/rpt1e.pdf
+http://cn.egroups.com/post/export-import-indonesia?act=forward&messageNum=595
+http://www.secinfo.com/$/SEC/Filing.asp?T=1zBgb.6t_9yc
+http://www.realize.com/am81.htm,qt=4619dc8c=279e650e-c-16fba7d-1-0-0-0--
+http://amadeus.siba.fi/doc/php3-ldap/html/features.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.ada-fetchrow.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.array-pop.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.current.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.ftp-size.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.getmyinode.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.gmdate.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.hw-getusername.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.icap-list-alarms.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.ifx-free-char.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.imap-reopen.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.is-link.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.is-string.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.mcal-event-set-recur-monthly-wday.html
+http://amadeus.siba.fi/doc/php3-ldap/html/function.mhash-get-block-size.html
+http://wwws.br-online.de/geld/boerse/980420/110001.html
+http://family.go.com/Categories/reviews/Features/family_2000_01/dony/dony0100craftapple/
+http://family.go.com/Categories/reviews/Features/family_2000_01/dony/dony0100craftcactus/
+http://family.go.com/Categories/reviews/Features/family_2000_01/dony/dony0100petvetticks/
+http://www.maastrek.de/maas/d49da6854db9e797f212/1/0/1
+http://astro1.chungnam.ac.kr/NetBBS/Bbs.dll/astromov/lst/qqadm/1/zka/B2-kB2Bl/qqo/004D
+http://channel.cnnsi.com/basketball/college/2000/ncaa_tourney/west/news/2000/03/25/keady_ap/lg_keady_ap.html
+http://incmagazine.com/articles/details/0,3532,AGD5_ART13806_CNT56_GDE30,00.html
+http://incmagazine.com/research/details/0,3470,AGD5_CNT49_GDE30_RSC16754,00.html
+http://gatekeeper.dec.com/pub/linux/lorax/i386/misc/src/anaconda/balkan/CVS/
+http://adex3.flycast.com/server/socket/127.0.0.1:2800/click/OnlineCitiesSM/OnlineCitiesInteractiveCityGuides/bd720350329
+http://www.proviser.co.uk/regional/towns/alford/street_maps/alpha_b.html
+http://www.fogdog.com/cedroID/ssd3040183255203/
+http://www.columbia.edu/~wl158/OCD.htm
+http://www.irishnews.com/Archive2000/29052000/international.html
+http://www.irishnews.com/Archive2000/29052000/sportinter.html
+http://38scbshop.freeyellow.com/download.html
+http://news.dinf.ne.jp/news/fj/rec/animation/msg01441.html
+http://datastore.tucows.com/winnt/adnload/5372_28388.html
+http://pages.infinit.net/limal/visage/chap17.htm
+http://www.hotelboulevard.com/fr/paris/standard/htmlc258073cfbe254c1722c86e0aec5f5da/sessionLang/ANG/search.html
+http://www.icopyright.com/1.1642.213678
+http://wiem.onet.pl/wiem/012aa2.html
+http://www.secinfo.com/dRRsz.9e.htm
+http://lily.nju.edu.cn/literature/cangshu/wx/wra/ysz/16.htm
+http://home.swipnet.se/~w-15978/
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/www.stanford.edu/dept/EIS/moral_responsibility.htm
+http://smb.slac.stanford.edu/cgi-bin/nph-proxy.cgi/000/http/www.stanford.edu/dept/EIS/hardin_review.htm
+http://www.uni-duesseldorf.de/ftp/pf/share/flex-2.5.2/man/man1/?S=A
+http://mindit.netmind.com/proxy/http://www.ninds.nih.gov/health_and_medical/pubs/chronic_pain_htr.htm
+http://mindit.netmind.com/proxy/http://www.smalltime.com/notvictims/cutting.html
+http://www.peopledaily.co.jp/zdxw/7/19991231/19991231001085.html
+http://pokemonothin.8m.com/cgi-bin/c/736/64/dXNlcmJhbm5lcg==/gn/4638/
+http://www.chaos.dk/sexriddle/s/e/x/u/y/n/d/
+http://www.bestinfo.net.cn/bsti_kjhy/kyys/bjkyys/arim/technical.html
+http://www.leicos.de/webguides/fun_lifestyle/unterhaltung/43101.html
+http://209.207.239.212/bkindex/c1047/f1423.html
+http://cylis.lib.cycu.edu.tw/search*chi/tEncyclopaedia+of+mathematical+sciences+&%2359%3B+v.+65/tencyclopaedia+of+mathematical+sciences+v+++65/-17,-1,0,B/frameset&F=tencyclopaedia+of+mathematical+sciences+v+++48&1,1
+http://www.sanxia.net/beauty/Nanako/313.htm
+http://www.sanxia.net/beauty/Nanako/323.htm
+http://mirrortucows.technet.it/winme/adnload/138469_29790.html
+http://www.fogdog.com/cedroID/ssd3040183321970/nav/stores/walking/
+http://www.fogdog.com/cedroID/ssd3040183321970/customer_service/employment.html
+http://mirror.pku.edu.cn/www.berkeley.edu/ls.berkeley.edu/lscr/services/backups/UCBackup.html
+http://retailer.gocollect.com/do/session/1912804/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/postcards/index.asp
+http://www.uni-duesseldorf.de/ftp/pf/share/ddd-1.4d/man/man1/?M=A
+http://www.uni-duesseldorf.de/ftp/pf/share/ddd-1.4d/man/man1/?S=A
+http://javatest.a-net.nl/servlet/pedit.Main/http://www.zdnet.com/special/stories/wireless/0,10676,2557092-8,00.html
+http://ftp.sunet.se/pub/os/FreeBSD/development/FreeBSD-CVS/ports/archivers/makeself/
+http://www.jamba.nl/KNet/_KNet-QYL8j1-2D4-pw4k/browse.nl/node.0/cde7f1uou
+http://www.discoveromaha.com/shared/health/adam/ency/imagepage/1090.000233.html
+http://home.dqt.com.cn/cgi-bin/push/setluntan?luntan=64
+http://sjsulib1.sjsu.edu:81/search/dbusiness+periodicals/-5,-1,1,B/frameset&dbusiness+vocational+guidance&2,,3
+http://www-d0.fnal.gov/d0dist/dist/releases/psim01.01.00/cft_tuple/VERSION
+http://pub3.ezboard.com/fmcdonaldscollectorsclubauctions.subscribeUnregisteredToTopic?topicID=136.topic
+http://shopping.lycos.co.kr/cgi-bin/LCWB.cgi/957424027/957522583/Catalog/1301/001
+http://www.cs.kuleuven.ac.be/~java/docs/jdk1.3/docs/api/java/sql/class-use/DriverPropertyInfo.html
+http://www.buybuddy.com/sleuth/27/1/1060701/505427/
+http://web4.sportsline.com/u/football/nfl/players/splits/4451_split.htm
+http://mirror.cc.utsunomiya-u.ac.jp/mirror/FreeBSD/ports/alpha/packages-5-current/japanese/?M=A
+http://no.egroups.com/login.cgi?login_target=%2Fgroup%2Ftkd-full
+http://www.bemi-immobilien.de/Ferien-IB/Startseite/Gemeinsam/MarketingStrategie/Gemeinsam/immolink/Gemeinsam/3d-service/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Gemeinsam/MarketingStrategie/Strategie.htm
+http://www.bemi-immobilien.de/Ferien-IB/Startseite/Gemeinsam/MarketingStrategie/Gemeinsam/immolink/Gemeinsam/3d-service/Startseite/www.ferien-immobilien.de/ferien-ib/startseite/Gemeinsam/versicherungen/gebaeude/deckungsumfang.htm
+http://www.3wposter.com/czaja/czj2002.htm
+http://pub19.ezboard.com/fallamericanbaseballleagueplayersneeded.showMessage?topicID=6.topic
+http://ftp.uni-mannheim.de/info/OReilly/nutshell/practcpp/disk/doit/?N=D
+http://www02.geocities.co.jp/HeartLand-Kaede/4970/index2.htm
+http://www.selbstmachen.de/shops/pop/infotext/8008.htm
+http://dennou-t.ms.u-tokyo.ac.jp/arch/cc-env/Linux/debian-jp/dists/unstable/contrib-jp/binary-alpha/doc/?D=A
+http://genforum.genealogy.com/cgi-genforum/forums/flynn.cgi?1004
+http://www.iwon.com/home/movies/movies_filmography_page/0,13178,Marguerite+Hickey,00.html
+http://cometweb01.comet.co.uk/do!tid=20&rtid=2&vsid=700&session=132028&mid=1000&rid=1060&cid=37030&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplG5ubLZDXLZolLl3l5jbqLlci5XqVLkXsLkao4tloHbmlLoq5
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus65300/eus65303/eus77824/eus541028/eus168664/
+http://user.chollian.net/~iipuni/pds1/?M=A
+http://tucows.ciaoweb.it/winnt/adnload/73935_29937.html
+http://home2.keyciti.com/x2001/
+http://www.amateurplatinum.com/teenagerclique/fagbodyshots/elbow-greaseac/plus-sizemen/butt-fuckpartner/actionextreme/hitting-itendurance.html
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/linux-2.3-4/linux/Documentation/filesystems/vfs.txt?only_with_tag=LINUX-2_3_99_pre4
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/linux-2.3-4/linux/Documentation/filesystems/vfs.txt?only_with_tag=LINUX-2_3_17
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=3,0+18,0-0,0-3,0
+http://www.skaninforma.no/nord-troendelag/leksvik-h.htm
+http://194.128.65.4/pa/cm199798/cmwib/wb971115/nil.htm
+http://www.on.fuchu.or.jp/~oimatudo/englishmisomanzyu.htm
+http://map.ipc.co.jp/asp/onmap/connect/g-2/a-719/
+http://cherokee1.edgate.com/goucheres/ed_current.html
+http://www.online.kokusai.co.jp/Service/V0043594/wrd/G200/service/service.html
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=21,16,7
+http://binary.tucows.com/winnt/adnload/70807_30160.html
+http://binary.tucows.com/winnt/adnload/1422_28846.html
+http://genforum.genealogy.com/cgi-genforum/forums/theroux.cgi?69
+http://rex.skyline.net/navigate.cgi?news,ice,women,resources,living
+http://umweb2.unitedmedia.com/creators/rugrats/archive/rugrats-20001015.html
+http://retailer.gocollect.com/do/session/1912824/vsid/2089/tid/2089/cid/621609/mid/1540/rid/1520/chid/2083/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLlmo5larLZqVLafpLmiXLvlmHolaLrZqLpl4/url/http://www.gocollect.com/product_display/products/product_lines.asp
+http://retailer.gocollect.com/do/session/1912824/vsid/2089/tid/2089/cid/621609/mid/1540/rid/1520/chid/2083/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLlmo5larLZqVLafpLmiXLvlmHolaLrZqLpl4/url/http://www.gocollect.com/clubhouse/suggestions.asp
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=146&discrim=146,7,19
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=146&discrim=146,7,231
+http://login.hq.cricinfo.org/link_to_database/ARCHIVE/1996-97/OD_TOURNEYS/SINWS/SINWS-MATCHES/SL_ZIM_SINWS_ODI5_03SEP1996_DAILY_MR.html
+http://preview.egroups.com/group/God_Calling
+http://www.fogdog.com/cedroID/ssd3040183340945/nav/products/outlet/1b/sunglasses_optics/
+http://www.fogdog.com/cedroID/ssd3040183340945/nav/products/outlet/1c/dc/
+http://www.fogdog.com/cedroID/ssd3040183340945/customer_service/contact_us.html
+http://link.fastpartner.com/do/session/600424/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/itjobbank.php
+http://link.fastpartner.com/do/session/600424/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/index.php
+http://pub2.ezboard.com/fteamnexgenforumhelpnexgennexencodestudio.unsubscribeUnregisteredToTopic?topicID=29.topic
+http://www02.geocities.co.jp/SiliconValley-PaloAlto/1763/event/ni2k/ni2k.htm
+http://yp.gates96.com/7/89/60/35.html
+http://yp.gates96.com/7/89/61/4.html
+http://yp.gates96.com/7/89/61/38.html
+http://yp.gates96.com/7/89/62/80.html
+http://yp.gates96.com/7/89/63/8.html
+http://yp.gates96.com/7/89/63/16.html
+http://yp.gates96.com/7/89/65/10.html
+http://yp.gates96.com/7/89/65/42.html
+http://yp.gates96.com/7/89/65/54.html
+http://yp.gates96.com/7/89/65/88.html
+http://yp.gates96.com/7/89/65/98.html
+http://yp.gates96.com/7/89/66/26.html
+http://yp.gates96.com/7/89/66/55.html
+http://yp.gates96.com/7/89/67/28.html
+http://yp.gates96.com/7/89/68/67.html
+http://yp.gates96.com/7/89/69/63.html
+http://yp.gates96.com/7/89/69/73.html
+http://www.mediko.de/news/alt.support.eating-disord/19944.html
+http://www.mediko.de/news/alt.support.eating-disord/19975.html
+http://www13.cplaza.ne.jp/musicnavi/i-mode/id/KICS113.html
+http://home.beseen.com/community/alienpilot/AbductionTheory.html
+http://www.hausbau-finder.de/festpreis/anbieter/A11/A11_05_eg.htm
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=237&discrim=10,15,200
+http://ftp.eecs.umich.edu/pub/NetBSD/packages/1.3.3/mac68k/kde/
+http://www.leg.wa.gov/pub/rcw%20-%20text/title_49/chapter_028/rcw_49_28_065.txt
+http://fi.egroups.com/login.cgi?login_target=%2Fmessages%2Fdfbl%2F77
+http://ring.omp.ad.jp/pub/NetBSD/NetBSD-current/src/sys/arch/sgimips/dev/?D=A
+http://retailer.gocollect.com/do/session/1912781/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/postcards/index.asp
+http://providenet.tucows.com/win2k/adnload/136128_47180.html
+http://providenet.tucows.com/win2k/adnload/38527_29571.html
+http://no.egroups.com/dir/1/16/476/32069/32291/104313/293356
+http://www.playease.com/et/beauty/img/lingmuyamei/lmam043.htm
+http://202.99.23.201/gb/special/node_484.htm
+http://202.99.23.201/gb/special/node_518.htm
+http://202.99.23.201/gb/special/node_531.htm
+http://ring.jec.ad.jp/archives/NetBSD/NetBSD-current/pkgsrc/fonts/acroread-chsfont/README.html
+http://www.gaiax.com/~dengeki/lineb.html?haru_da_pump
+http://cafe2.daum.net/Cafe-bin/Bbs.cgi/naturalproductspds/qry/zka/B2-kB27p/qqatt/^
+http://cafe2.daum.net/Cafe-bin/Bbs.cgi/naturalproductspds/qry/zka/B2-kB23t/qqatt/^
+http://cafe2.daum.net/Cafe-bin/Bbs.cgi/naturalproductspds/qry/zka/B2-kB23r/qqatt/^
+http://my.egroups.com/group/uk-mac-dev
+http://www.f20.parsimony.net/forum35990/archiv.htm
+http://findmail.com/group/Costumers
+http://variety.studiostore.com/browse/PEOPLE/b.FAVORITES%20PEOPLE/s.ZaC1r6Q6
+http://www.chinawolf.com/~warson/japan/chichuan/cat/jiangzuo/020.htm
+http://www.branchen-vermittler.de/Branchen/Mecklenburg/Mecklenburg_Region_3/Neustrelitz/kopf_neustrelitz.html
+http://www.xmission.com/(art,ftp,geek,music,music,caffiene,art,toys,dots,edge,misc,shopping,ftp,places,privacy,geek,cuseeme,apocalypse,people,stuffiuse,places,privacy,stuffiuse)/~bill/links.html
+http://www.cs.helsinki.fi/linux/linux-kernel/Year-1999/1999-49/1283.html
+http://www.ecotec.co.jp/view/arc/f/free/33/umcotk/zxlqox.html
+http://www.ecotec.co.jp/view/arc/f/free/33/tgiotk/uftfwm.html
+http://www.ecotec.co.jp/view/arc/f/free/33/purotk/qxxotk.html
+http://www.ecotec.co.jp/view/arc/f/free/33/purotk/sewotk.html
+http://www.ecotec.co.jp/view/arc/f/free/33/purotk/sjkfwm.html
+http://www.ecotec.co.jp/view/arc/f/free/33/hazfwm/llhetk.html
+http://www.ecotec.co.jp/view/arc/f/free/33/bvtctk/eptrik.html
+http://www.ecotec.co.jp/view/arc/f/free/33/rvkptk/syurzz.html
+http://library.cuhk.edu.hk/search*chi/a��頦��哨蕭嚙賢��鞈�嚙踝���+1934-/a{214b33}{213021}{214451}+1934/-5,-1,0,B/frameset&F=a{214b33}{213021}{213c63}&6,,7
+http://mitglied.tripod.de/~haubentaucher/bilder.htm
+http://amc.hollywood.com/maltin/v/valleyofthekings-1954.htm
+http://amc.hollywood.com/maltin/v/vannuysblvd-1979.htm
+http://amc.hollywood.com/maltin/v/venicevenice-1992.htm
+http://amc.hollywood.com/maltin/v/vicesquad-1931.htm
+http://amc.hollywood.com/maltin/v/violette-1978.htm
+http://amc.hollywood.com/maltin/v/voiceofthewhistler-1945.htm
+http://amc.hollywood.com/maltin/v/vulturethe-1967.htm
+http://members.tripod.co.jp/hatahata/hikoki/?D=A
+http://kernel2.adver.com.tw/Counter/log/kernel2.adver.com.tw/SaveCounter/2000-10-23/07/972255822718.txt
+http://www.mapion.co.jp/custom/AOL/admi/23/23105/matsubaracho/5chome/index-43.html
+http://search.chollian.net/cgi-bin/filter.cgi?cid=1109&g=11
+http://search.chollian.net/cgi-bin/filter.cgi?cid=1109&p=5
+http://www.linux.com/networking/network/new/website/applications/business/
+http://www.fogdog.com/cedroID/ssd3040183313598/nav/products/w_golf/1s/ball_retrievers/
+http://www.fogdog.com/cedroID/ssd3040183313598/nav/products/w_golf/1t/biographical_books/
+http://rammstein.sonicnet.com/artists/news/1090.jhtml
+http://rammstein.sonicnet.com/allmusic/ai_bio.jhtml?ai_id=1090
+http://www.ycwb.com.cn/gb/2000/08/18/ycwb/gnxw/7.html
+http://www.vorlesungen.uni-osnabrueck.de/informatik/c98/code/19/?D=A
+http://kernel2.adver.com.tw/Counter/log/kernel2.adver.com.tw/SaveCounter/2000-10-23/11/972270515716.txt
+http://www.affiliate.hpstore.hp.co.uk/do/session/380869/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/entry1.asp
+http://uk.biz.yahoo.com/mutual_funds/micropal/lf/fund/008776/properf.html
+http://troy.lib.sfu.ca/search/aasociacion+argentina+de+ciencias+naturales/aasociacion+argentina+de+ciencias+naturales/-5,-1,0,E/frameset&F=aasociacion+argentina+de+ciencias+naturales&1,,0
+http://uk.dir.yahoo.com/Regional/U_S__States/Virginia/Metropolitan_Areas/Charlottesville_Metro/Travel_and_Transportation/Accommodation/Caravan_Parks_and_Camp_Sites/
+http://uk.dir.yahoo.com/Regional/U_S__States/Virginia/Metropolitan_Areas/Charlottesville_Metro/Travel_and_Transportation/Accommodation/Hotels/
+http://library.cwu.edu/search/cQA76.73.A35+T75/cqa+++76.73+a35+t75/-5,-1,0,B/marc&F=cqa+++76.73+a8+j33+1985&1,1,
+http://www.tages-anzeiger.ch/sport/nagano/0902/olymp_art4.htm
+http://finance.sina.com.cn/globe/globe/2000-03-16/23725.html
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=9,3-9,0+0,1-0,3
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=9,3-9,0+0,1-9,3
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=9,3-9,0+0,1-19,0
+http://temps-libre.promovacances.net/D02/BH/BDANE/voyagealacarte.htm
+http://sunsite.org.uk/public/computing/networks/internet/ietf/98aug/imapext-attendees-98aug.txt
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=124&discrim=221,178
+http://cpan.nettuno.it/authors/Ilya_Zakharevich/modules/FreezeThaw-0.41.readme
+http://cpan.nettuno.it/authors/Ilya_Zakharevich/modules/Math-Pari-2.001700.readme
+http://ricoh.co.jp/SHOGI/emate/tanigawa/tume0069a.html
+http://troy.lib.sfu.ca/search/dlatin+america+periodicals/dlatin+america+periodicals/-5,-1,0,B/marc&F=dlatin+america+pest+control+industry&1,1,
+http://moviestore.zap2it.com/browse/MOVIES/COLLECTI/s.w2bwHPkr
+http://moviestore.zap2it.com/browse/MOVIES/BUNDLE/s.w2bwHPkr
+http://moviestore.zap2it.com/browse/MOVIES/BOWL/s.w2bwHPkr
+http://moviestore.zap2it.com/browse/MOVIES/JEWELRY/s.w2bwHPkr
+http://moviestore.zap2it.com/browse/MOVIES/COMIC/s.w2bwHPkr
+http://www9.hmv.co.uk:5555/do/session/1347801/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/Top_Navigation_Bar/top_banner.html
+http://www3.adobe.com/type/browser/F/P_103/F_FRAK-70005000.html
+http://ftp.netc.pt/pub/idgames/levels/doom2/deathmatch/j-l/kewl.txt
+http://ftp.netc.pt/pub/idgames/levels/doom2/deathmatch/j-l/ledges-z.txt
+http://park.org:8888/Japan/CSK/hyakki/zukan/turezure/ue/c_tirizuka.html
+http://pub4.ezboard.com/fscarletstreetfilmmusic.unsubscribeUnregisteredToTopic?topicID=54.topic
+http://tucows.niagara.com/win2k/adnload/37364_29149.html
+http://wap.jamba.de/KNet/_KNet-JGG8j1-eGd-13cre/showInfo-special1.de/node.0/cde7f1uou
+http://www.personalmd.com/news/n0706062122.shtml
+http://ds.dial.pipex.com/tmc/ConfPresentations/s2000/NetworkingJ/msconfig.htm
+http://calcul.si.uji.es/Programes/SAS/proc/z0325264.htm
+http://www.kaos.dk/sexriddle/x/m/k/i/i/
+http://ring.toyama-ix.net/archives/lang/perl/CPAN/clpa/1998-08/?N=D
+http://ring.toyama-ix.net/archives/lang/perl/CPAN/clpa/1998-08/?S=A
+http://www.spiral.at/Katalog/Artikel/0879070/
+http://homepage1.nifty.com/nao~nao/pages/profile.html
+http://www.ferien-immobilien.de/friesland/verkauf/Gemeinsam/Inserieren/Allgemeine-IB/3d-service/Allgemeine-IB/Startseite/
+http://www.ferien-immobilien.de/friesland/verkauf/Gemeinsam/Inserieren/Allgemeine-IB/3d-service/Gemeinsam/erreichenPartner/email3d.htm
+http://www.thestateofcolorado.com/m1jerepair.html
+http://www.legis.state.pa.us/WU01/LI/BI/TI/1989/0/MNTENNIS.HTM
+http://www.legis.state.pa.us/WU01/LI/BI/TI/1989/0/MNTRASH.HTM
+http://www.shop4magazines.com/pg004752.htm
+http://www.shop4magazines.com/pg005070.htm
+http://www.shop4magazines.com/pg005084.htm
+http://fi.egroups.com/login.cgi?login_target=%2Fmessage%2Fsocalscan%2F5293
+http://www.incestpornstories.com/hot-hardcore-fuckingbanging/bootsfeet-/hitting-itsmacking/{hardcorelink}
+http://www.columbia.edu/~mkn12/Nominees.html
+http://www.generation-formation.fr/pdetail.htm---o21zAo06Rxo0Ol9A074fo6s0Md6jIHeNHhIeOkn2ApvFFo6s5dfexiWo2W81N3OsPeaR2VeuzlEdRsR3djaPfdNjfco41qrfP6sWd6wuCoz4ZteOgKHekLVSePl8vNhiWhAhcgNAPfVbdsNhJl.htm
+http://tiscover.at/1Root/Kontinent/6/Staat/7/Bundesland/20/Ort/212/Sonstige_Sportstaette/276591/Bericht/berw...1.html
+http://fi.egroups.com/message/meterreader/207?source=1
+http://polygraph.ircache.net:8181/services/design/http_-2www.arthritis.org/http_-2www.alameda-vcf.org/http_-2www.microsoft.com/ie/ie.htm
+http://www.fortunecity.com/lavender/deathrace/251/billy.html
+http://ftpsearch.belnet.be/packages/CPAN/modules/by-module/AppleII/?N=D
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=7,34,29,16,25
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=21,34,29,16,25
+http://www.ftp.uni-erlangen.de/pub/unix/BSD/FreeBSD/FreeBSD-current/ports/irc/tirc/
+http://retailer.gocollect.com/do/session/1912840/vsid/1696/tid/1696/cid/604361/mid/1540/rid/1420/chid/1725/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLlmo5larLZqVLafpLmiXLvlmHolaLrZqLpl4/url/http://www.gocollect.com/company_info/about.asp
+http://retailer.gocollect.com/do/session/1912840/vsid/1696/tid/1696/cid/604361/mid/1540/rid/1420/chid/1725/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLlmo5larLZqVLafpLmiXLvlmHolaLrZqLpl4/url/http://www.gocollect.com/company_info/terms_and_conditions.asp
+http://businessrecorder.com/story/S0024/S2401/S2401113.htm
+http://arabia.com/article/0,1690,Sports|20732,00.html
+http://www.worldmedicus.com/servlet/Controller/$7006041629a50000.sj_viewa/
+http://myhome.naver.com/chocobini/company.html
+http://builder.hw.net/frmMessageFront/1,1079,'1~21~0~8~1~2348~9590',00.html
+http://pub1.ezboard.com/fcrossstitchcorner504212000shepherdsbushretreat.showAddReplyScreenFromWeb?topicID=48.topic&index=5
+http://www.parisnights.de/fanfiction/archive/authors/andrews/stories/bright.htm
+http://198.103.152.100/search*frc/cCA1+MPR+NS51+98Y25/cca1+mpr+ns51+98y25/7,-1,0,E/2browse
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus51605/eus147927/eus269761/eus269920/eus918452/
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus51605/eus147927/eus269761/eus269920/eus918493/
+http://www.computing.net/cgi-bin/report.pl/windows95/wwwboard/forum/3119.html|21
+http://www.kiarchive.ru:8093/pub/misc/books/Camelot/Vasilyev/Forgotten_Road/
+http://yp.gates96.com/4/9/50/30.html
+http://yp.gates96.com/4/9/51/1.html
+http://yp.gates96.com/4/9/51/88.html
+http://yp.gates96.com/4/9/51/92.html
+http://yp.gates96.com/4/9/52/3.html
+http://yp.gates96.com/4/9/52/53.html
+http://yp.gates96.com/4/9/52/67.html
+http://yp.gates96.com/4/9/53/25.html
+http://yp.gates96.com/4/9/53/50.html
+http://yp.gates96.com/4/9/53/96.html
+http://yp.gates96.com/4/9/54/40.html
+http://yp.gates96.com/4/9/54/57.html
+http://yp.gates96.com/4/9/54/77.html
+http://yp.gates96.com/4/9/55/57.html
+http://yp.gates96.com/4/9/55/71.html
+http://yp.gates96.com/4/9/56/1.html
+http://yp.gates96.com/4/9/56/98.html
+http://yp.gates96.com/4/9/57/6.html
+http://yp.gates96.com/4/9/57/90.html
+http://yp.gates96.com/4/9/58/91.html
+http://yp.gates96.com/4/9/58/96.html
+http://yp.gates96.com/4/9/59/29.html
+http://yp.gates96.com/4/9/59/33.html
+http://yp.gates96.com/4/9/59/84.html
+http://yp.gates96.com/4/9/59/97.html
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/151/1997/5/0/900308/
+http://www2.odn.ne.jp/~cao20970/affair/oh/ha-342
+http://www2.odn.ne.jp/~cao20970/affair/oh/ha-346
+http://wap.jamba.de/KNet/_KNet-lvH8j1-nGd-13d1j/browse.de/node.0/cdzqggtyb
+http://www.danielwebster.org//hallofusa/thestampact/HENDRICKFISHER.COM//thestampact/
+http://news.cn.tom.com/maya/cnnav/01/item/2000_09/309490.shtml
+http://polygraph.ircache.net:8181/services/design/http_-2www.paducahrotary.org/pbcmap.htm
+http://polygraph.ircache.net:8181/services/design/http_-2www.paducahrotary.org/mainpage.htm
+http://www.debian.org.cn/Bugs/db/23/23547.html
+http://www.debian.org.cn/Bugs/db/54/54172.html
+http://www.adetti.iscte.pt/ADETTI/Security/HowTo/Java/jdk1.2.1/docs/guide/beans/spec/beancontext.fm7.html
+http://www.users.qwest.net/~campputz/page413.htm
+http://flybird.soyou.edu.cn/item/2000-07-31/164671.html
+http://www.cognigen.net/corporate/trainers.cgi?full-timer
+http://www.babyheirlooms.com/catalog/htmlos.cat/041143.1.1156359481
+http://ramdam.com/art/k/katerine.htm
+http://ramdam.com/art/k/krapulax.htm
+http://aleph.tau.ac.il:4501/ALEPH/eng/ATA/AAM/AAM/SET-MAIL///1249009
+http://online.linux.tucows.com/conhtml/adnload/8973_2294.html
+http://www.arrakis.es/~lady_cel/frcontenf.htm
+http://online.linux.tucows.com/conhtml/adnload/39034_1349.html
+http://online.linux.tucows.com/conhtml/adnload/51651_2248.html
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=23,0+14,0-13,0-13,0
+http://www.ferien-immobilien.de/Westerwald/verkauf/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/Gemeinsam/Inserieren/Private-IB/Gemeinsam/suche.htm
+http://www.linux.com/networking/network/it/alternative/developers/Apple/
+http://www.sanxia.net/beauty/Nanako/418.htm
+http://www-usa8.cricket.org/link_to_database/ARCHIVE/1999-2000/OTHERS+ICC/NORTHANTS_IN_WI/ARTICLES/
+http://gds.cc.va.us:8888/Mcn%3dMELISSA%20BACK,%20ou%3dSV.CC.VA.US,%20ou%3dFaculty%20%26%20Staff,%20o%3dvccs,%20c%3dUS
+http://www.allgemeine-immobilien-boerse.de/nordrhein-Westfalen/luedinghausen/Verkauf/Ferien-IB/Startseite/Gemeinsam/erreichenPartner/Versteigerungen-IB/Startseite/IIM-Teil/Startseite/froben.htm
+http://198.103.152.100/search*frc/dIndustrial+relations+--+Germany+(West)+--+History/dindustrial+relations+germany+west+history/-5,-1,0,B/frameset&F=dindustrial+relations+germany+dictionaries&1,,0
+http://secure.danysoft.com/asp/dany.tienda/892496425/Catalog
+http://yp.gates96.com/13/57/90/23.html
+http://yp.gates96.com/13/57/90/91.html
+http://yp.gates96.com/13/57/91/68.html
+http://yp.gates96.com/13/57/92/22.html
+http://yp.gates96.com/13/57/92/49.html
+http://yp.gates96.com/13/57/92/73.html
+http://yp.gates96.com/13/57/93/75.html
+http://yp.gates96.com/13/57/94/16.html
+http://yp.gates96.com/13/57/94/62.html
+http://yp.gates96.com/13/57/94/99.html
+http://yp.gates96.com/13/57/95/19.html
+http://yp.gates96.com/13/57/95/34.html
+http://yp.gates96.com/13/57/95/84.html
+http://yp.gates96.com/13/57/96/22.html
+http://yp.gates96.com/13/57/96/24.html
+http://yp.gates96.com/13/57/96/52.html
+http://yp.gates96.com/13/57/96/70.html
+http://yp.gates96.com/13/57/97/39.html
+http://yp.gates96.com/13/57/97/55.html
+http://yp.gates96.com/13/57/98/4.html
+http://yp.gates96.com/13/57/98/41.html
+http://yp.gates96.com/13/57/98/58.html
+http://yp.gates96.com/13/57/98/98.html
+http://yp.gates96.com/13/57/98/99.html
+http://yp.gates96.com/13/57/99/79.html
+http://carriage.de/Schoner/Info-d/history/literature/literature/
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/lit/computers/misc/unitest/misc/computers/programs/simple/simple.html
+http://kwic.tucows.com/partners/flyswat/get_acx.html
+http://sp201.unige.ch:49213/cxxdoc/ioc/concepts/c2g2rcsm.htm
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=0,2-0,1-21,0+9,1
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=237&discrim=10,2,183
+http://firstweb.tucows.com/win2k/adnload/58783_28760.html
+http://www.boerseninfos.de/dynamic/ak/mk/news/719350-20000830-104827.html
+http://baseball.mainichi.co.jp/life/family/syuppan/wakaru/wakaru-j/10/01/01.html
+http://helios.nlib.ee/search*est/dsÃ\83Ä©jalised+blokid/dsw~ajalised+blokid/-5,-1,0,B/exact&F=dsw~ajalised+konfliktid&1,58/limit
+http://helios.nlib.ee/search*est/dsÃ\83Ä©jalised+blokid/dsw~ajalised+blokid/-5,-1,0,B/frameset&F=dsw~ajalised+konfliktid&11,,58
+http://lexicon.linux.tucows.com/conhtml/adnload/8642_2088.html
+http://ua.php.net/manual/es/function.pg-fieldisnull.php
+http://www.babyheirlooms.com/catalog/htmlos.cat/041132.1.4352706945
+http://www.civila.com/guitar/chat/desenredada/juegos/
+http://sunsite.org.uk/public/pub/packages/info-mac/pilot/?N=D
+http://www.aelita.net/products/products/support/news/Reg/Subscribe/company/contact/default.htm
+http://cn.egroups.com/message/newsclips/295
+http://www.jornada.unam.mx/2000/sep00/000922/oriente-y.htm
+http://members.tripod.co.jp/mosokke/dubair01ghe.html
+http://202.99.23.245/zdxw/21/20000217/200002172112.html
+http://link.fastpartner.com/do/session/600412/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/speednames.php
+http://link.fastpartner.com/do/session/600412/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/nordicliving.php
+http://link.fastpartner.com/do/session/600412/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/local/redirect.php
+http://iant.subportal.com/sn/Utilities/System_Maintenance_and_Repair_Utilities/2128.html
+http://polygraph.ircache.net:8181/client/http_-2www.scubaring.com/http_-2www.aaainvestments.com/http_-2www.primenet.com/~stmmoon/stmbik.html
+http://itcareers.careercast.com/texis/it/itjs/+wwwBme89D86qxwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewGtmoBGnaqdGpdGwBodDanDtoDnnGaMw55wqr15nBB5aoDhdGMwBodDa5nq1GoBOaDnBidGAapGdBdqdc5aGn31oGnmanLpnGonDqnaMFqhTfR20DzmehrwwwpBme26D86eSqwww5rmePdwwwBrmeZpwww/morelike.html
+http://itcareers.careercast.com/texis/it/itjs/+awwBme3AT+6ezqwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewGtmoBGnaqdGpdGwBodDanDtoDnnGaMw55wqr15nBB5aoDhdGMwBodDa5nq1GoBOaDnBidGAapGdBdqdc5aGn31oGnmanLpnGonDqnaMFqhTfR20DzmehrwwwpBme26D86eSqwww5rmeEdwwwBrmeZpwww/jobpage.html
+http://itcareers.careercast.com/texis/it/itjs/+vwwBme26D86eSqwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewGtmoBGnaqdGpdGwBodDanDtoDnnGaMw55wqr15nBB5aoDhdGMwBodDa5nq1GoBOaDnBidGAapGdBdqdc5aGn31oGnmanLpnGonDqnaMFqhTfR20DzmehrwwwpBme26D86eSqwwwGzmwwww5rmeEdwwwBrmeZpwww/morelike.html
+http://www.starcities.com/usa/ca/carlsbad/
+http://www.3w-geschichten.de/PlumptreGeorge/PlumptreGeorge1857938461.htm
+http://residence.educities.edu.tw/goyen/
+http://polygraph.ircache.net:8181/http_-2www.whowhere.com/http_-2www.primenet.com/~mmfact/http_-2www.microsoft.com/ie/download/
+http://polygraph.ircache.net:8181/http_-2www.whowhere.com/http_-2www.primenet.com/~mmfact/http_-2www.infohwy.com/odframes.html
+http://www.linux.com/networking/network/management/industry/internet/services/
+http://cn.egroups.com/message/ruosulista/1176
+http://ftp.jp.debian.org/debian/dists/unstable/main/binary-i386/tex/?M=A
+http://de.excite.de/bildung/katalog/17722
+http://de.excite.de/bildung/katalog/17893
+http://de.excite.de/bildung/katalog/17879
+http://www.emerchandise.com/browse/BUFFYTHEVAMP/PIN/b.TV%20BUFFYTHEVAMP/s.Xpiu5LCZ
+http://variety.studiostore.com/browse/VARIETY/CAMERA/s.dmZspziz
+http://carriage.de/Schoner/Sammlungen/models/info-e/Info-d/
+http://www.gazeta.com/Iso/Plus/Kraj/Prezyden/Ak/700kwa.html
+http://www.linux.com/networking/network/networking/developers/operating_system/Debian/
+http://online.linux.tucows.com/conhtml/adnload/8808_32695.html
+http://149.221.91.10/news/lokales/wermelskirchen/
+http://opac.lib.rpi.edu/search/avirgin+vision+limited/7,-1,0,B/frameset&avirginia+cooperative+fisheries+research+unit&1,1
+http://www.emerchandise.com/browse/DISNEY-FAM/ACTIONFI/b.FAVORITES%20KIDSSTUFF%20DISNEY-FAM/s.erm2bF5K
+http://polit.kulichki.net/moshkow/PXESY/GORIN/
+http://polit.kulichki.net/moshkow/COPYRIGHT/stolyarov.txt
+http://www.science.uva.nl/pub/NetBSD/NetBSD-current/pkgsrc/textproc/rman/pkg/DESCR
+http://cgi.www.4tourism.com/uk/wareham65426.html
+http://cgi.www.4tourism.com/uk/wareham22477.html
+http://www.ccnet.com/affif/_themes/sumipntg/_vti_cnf/?M=A
+http://web.tin.it/regionesardegna/ital/lavpubb/bandi_contratti/schema5_1q.htm
+http://ring.htcn.ne.jp/archives/text/CTAN/macros/latex/contrib/other/apa/
+http://ftpsearch.belnet.be/packages/CPAN/modules/by-module/Callback/Callback-1.02.readme
+http://iant.subportal.com/sn/Utilities/Misc__Utilities/12800.html
+http://yp.gates96.com/2/51/0/86.html
+http://yp.gates96.com/2/51/1/72.html
+http://yp.gates96.com/2/51/2/10.html
+http://yp.gates96.com/2/51/3/7.html
+http://yp.gates96.com/2/51/3/50.html
+http://yp.gates96.com/2/51/4/90.html
+http://yp.gates96.com/2/51/5/6.html
+http://yp.gates96.com/2/51/5/42.html
+http://yp.gates96.com/2/51/5/50.html
+http://yp.gates96.com/2/51/6/49.html
+http://yp.gates96.com/2/51/8/12.html
+http://yp.gates96.com/2/51/8/50.html
+http://yp.gates96.com/2/51/9/82.html
+http://yp.gates96.com/2/51/9/94.html
+http://archive.soccerage.com/s/fr/09/37602.html
+http://archive.soccerage.com/s/fr/09/39203.html
+http://ftp.ring.gr.jp/archives/NetBSD/NetBSD-1.4.1/pmax/binary/security/
+http://www.yorosiku.net:8080/-_-http://www.us-japan.org/otr/
+http://support.dell.com/docs/storage/dlt1/ug/sp/jumpers.htm
+http://moviestore.zap2it.com/browse/MOVIES/MOUSEPAD/s.uiIfdEiW
+http://moviestore.zap2it.com/browse/MOVIES/STANDUP/s.uiIfdEiW
+http://focusin.ads.targetnet.com/ad/id=animeart&opt=cin&cv=210&uid=972942857
+http://www.emerchandise.com/browse/SATNIGHTLIVE/SWEATSHI/s.pJ2FFfba
+http://www.realize.com/p5dee81.htm,qt=e784fe2f=2a38a234-e-1ade986-0-0-0-3--
+http://support.tandy.com/support_audio/doc30/30780.htm
+http://sun1.rrzn-user.uni-hannover.de/jgaertner/matlab/help/techdoc/umg/chlabel2.html
+http://sun1.rrzn-user.uni-hannover.de/jgaertner/matlab/help/techdoc/umg/chprin12.html
+http://www.es.co.nz/~rotary.home.html
+http://www.excelsior.com.mx/9802/980217/nac18.html
+http://dante.bdp.it/cgi-bin/poseidon_v2.0/reflect/poseidon/disc/biblioteca1/1316779952/prevarticle
+http://dennou-t.ms.u-tokyo.ac.jp/arch/cc-env/Linux/debian-jp/dists/stable/non-free-jp/binary-alpha/net/?D=A
+http://guest/forestpatholog/diseases/annosus.html
+http://guest/forestpatholog/diseases/rot.html
+http://no.egroups.com/message/readbygrade3/2029
+http://www.cybercd.de/artist/Fabri,+Stafke.htm
+http://www.jamba.de/KNet/_KNet-zQG8j1-hGd-13cwi/admLogin.de/node.0/cenv0b09a
+http://www.digitaldrucke.de/(aktuell,computer,marktplatz,sense,tausch)/_fort/html/themen/computer/computer.htm
+http://ring.tains.tohoku.ac.jp/pub/linux/debian/debian-jp/dists/potato/contrib-jp/source/news/?S=A
+http://strategis.ic.gc.ca/sc_indps/recboats/frndoc/3g.html
+http://ftp.eq.uc.pt/software/unix/Linux/redhat/redhat-6.2/i386/doc/gsg/figs/rpmlite/?M=A
+http://www.judds-resort.com/judds/Lake-Winni-pike-lodge/upload/upload/photo/fallphoto/boat/12.html
+http://ftp.eecs.umich.edu/.7/NetBSD/NetBSD-current/src/usr.sbin/cnwctl/
+http://ftp.eecs.umich.edu/.7/NetBSD/NetBSD-current/src/usr.sbin/mailwrapper/
+http://ftp.eecs.umich.edu/.7/NetBSD/NetBSD-current/src/usr.sbin/traceroute6/
+http://ftp.eecs.umich.edu/.7/NetBSD/NetBSD-current/src/usr.sbin/yppoll/
+http://pelit.saunalahti.fi/.3/linuxberg/conhtml/preview/8785.html
+http://www.asahi-net.or.jp/~rz3n-snd/kitakan/kamiyosida.html
+http://www.chaos.dk/sexriddle/s/e/x/q/x/k/l/
+http://www.chaos.dk/sexriddle/s/e/x/q/x/k/y/
+http://ring.jec.ad.jp/archives/text/CTAN/dviware/umddvi/libcompat/?S=A
+http://seniorfriendfinder.com/cgi-bin/w3com/pws/ffsenior/OCtIhwK0_lecIJU9yN87J4DTFWqXdztVO8nfP1zxdwq79fkod_IhHN3-iHbCrlaXZ5ATMMc_Gb5Zt_RdtVOloKJ1Z7DGqz2vE9vOjESyOqryETO-lNa0NWtCoTJH_QGCfq7ss5VGa1MO3iLryKZ2gIVI_Lonfx_bC9m7
+http://seniorfriendfinder.com/cgi-bin/w3com/pws/ffsenior/D-tI2p4N__5TTgffRqVzdrKNYFZc3jj2Oatw29gt_YiNBPXUlYZaTA2ndP2CrwlrdiMS8YzPKxDR7Vp4ZBqD3d5o3MwYrYIxk31YsVtP3yFS2bLdZcBGLKdyNUc9yYgvGsGMXAMcEAUJPjtRqUVzDpuhHzS6V_U76I6G
+http://my.egroups.com/subscribe/enemapix
+http://yp.gates96.com/0/23/40/60.html
+http://yp.gates96.com/0/23/40/82.html
+http://yp.gates96.com/0/23/41/67.html
+http://yp.gates96.com/0/23/43/71.html
+http://yp.gates96.com/0/23/43/75.html
+http://yp.gates96.com/0/23/44/64.html
+http://yp.gates96.com/0/23/44/73.html
+http://yp.gates96.com/0/23/44/84.html
+http://yp.gates96.com/0/23/45/19.html
+http://yp.gates96.com/0/23/46/9.html
+http://yp.gates96.com/0/23/46/26.html
+http://yp.gates96.com/0/23/46/37.html
+http://yp.gates96.com/0/23/46/92.html
+http://yp.gates96.com/0/23/47/39.html
+http://yp.gates96.com/0/23/47/52.html
+http://yp.gates96.com/0/23/48/52.html
+http://yp.gates96.com/0/23/49/12.html
+http://yp.gates96.com/0/23/49/90.html
+http://retailer.gocollect.com/do/session/1912812/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/help/index.asp
+http://retailer.gocollect.com/do/session/1912812/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/sports/index.asp
+http://203.93.50.148:2222/*0110http://www.snweb.com/gb/people_daily/2000/10/20/i1020004.htm
+http://cn.egroups.com/messages/romtrade/5024
+http://members.tripod.co.jp/medo/_private/
+http://dbc.copystar.com.tw/DelphiChat/200001/msg0325.htm
+http://tucows.pi.be/winnt/diskcnt_license.html
+http://millennium.fortunecity.com/ruthven/144/5041.htm
+http://news.pchome.com.tw/ttv/finance/20000616/
+http://library.bangor.ac.uk/search/dEcology+--+Poland+--+Periodicals/decology+poland+periodicals/-17,-1,0,B/frameset&F=decology+north+america+congresses&1,1
+http://www.could.be/travel/north_america/united_states/lodge_2.htm
+http://genforum.genealogy.com/cgi-bin/print.cgi?huntington::195.html
+http://www.bemi-immobilien.de/Ferien-IB/Startseite/Gemeinsam/immolink/Gemeinsam/MarketingStrategie/Gemeinsam/erreichenPartner/Gemeinsam/3d-service/Top-Darlehens-Konditionen/anforderungsformular.htm
+http://members.tripod.co.jp/snowmen/?D=A
+http://ftp.unicamp.br/pub/FAQ/sf/alt_history/part6
+http://www.affiliate.hpstore.hp.co.uk/do/session/380884/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/REGISTRATION/entry.asp
+http://grid9.linux.tucows.com/x11html/adnload/9444_3744.html
+http://www.linux.com/networking/network/communications/tools/web/support/
+http://www.linux.com/networking/network/communications/tools/web/alternative/
+http://cometweb01.comet.co.uk/do!tid=20&rtid=1&vsid=700&session=132030&mid=1000&rid=1060&cid=37030&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplGGolLarZLq4fLpmiLXv-KmooLckYLoznGmpq0qsc0mojLbkYLozvGotc0ZdoLckYLozvGsmv0qmc0jXfLkVZLdocLkYoLzcj1XfkLVZXLqkXLjbzKcob5qroLkVrLoizKlZd5fjYHfklKkZlLjjbLoZbLpl51ubZLDXZLollK3ljLbqlKjXfLkkaHotl4obmLloqL
+http://yp.gates96.com/14/77/20/1.html
+http://yp.gates96.com/14/77/20/3.html
+http://yp.gates96.com/14/77/20/32.html
+http://yp.gates96.com/14/77/20/55.html
+http://yp.gates96.com/14/77/21/7.html
+http://yp.gates96.com/14/77/22/20.html
+http://yp.gates96.com/14/77/22/26.html
+http://yp.gates96.com/14/77/22/50.html
+http://yp.gates96.com/14/77/23/63.html
+http://yp.gates96.com/14/77/23/96.html
+http://yp.gates96.com/14/77/25/53.html
+http://yp.gates96.com/14/77/26/8.html
+http://yp.gates96.com/14/77/26/32.html
+http://yp.gates96.com/14/77/27/0.html
+http://yp.gates96.com/14/77/27/55.html
+http://yp.gates96.com/14/77/27/78.html
+http://yp.gates96.com/14/77/28/8.html
+http://yp.gates96.com/14/77/28/53.html
+http://yp.gates96.com/14/77/28/57.html
+http://yp.gates96.com/14/77/28/99.html
+http://yp.gates96.com/14/77/29/96.html
+http://mirror.nucba.ac.jp/mirror/FreeBSD/FreeBSD-stable/ports/cad/xcircuit/files/?D=A
+http://pub3.ezboard.com/BBSForum.showForumSearch?boardName=jenxforum&forumName=jenxforumfrm0
+http://genforum.genealogy.com/cgi-genforum/forums/hi.cgi?415
+http://elib.zib.de/pub/opt-net/msc/msc-90-xx/90c15/v93w20n4
+http://biblio.cesga.es:81/search*gag/aDittrich,+Stefan/adittrich+stefan/-5,-1,0,E/frameset&F=adittman+richard+h+coaut&1,,0
+http://biblio.cesga.es:81/search*gag/aDittrich,+Stefan/adittrich+stefan/-5,-1,0,E/frameset&F=adittmar+jorge&1,1
+http://biblio.cesga.es:81/search*gag/aDittrich,+Stefan/adittrich+stefan/-5,-1,0,E/exact&F=adivis+jan&1,4
+http://www.doc.ic.ac.uk/~gwsb98/bucket/Wine-20001026/etc/?D=A
+http://news.fm365.com/xinwen/guoji/20000531/72641.htm
+http://www.newquestcity.com/templates/eventout.cfm?nqc=TN0730
+http://www.rhena.de/kempinsk1.htm
+http://www.jamba.de/KNet/_KNet-tkL8j1-PGd-13dss/showInfo-wir.de/node.0/cenvd8eze
+http://www.jamba.de/KNet/_KNet-tkL8j1-PGd-13dsv/browse.de/node.0/ceo0fdeye
+http://cpan.nitco.com/modules/by-module/String/BLCKSMTH/?N=D
+http://www.digitaldrucke.de/(hilfe,nuernberg)/_fort/html/themen/computer/soft/links/intuit.htm
+http://www.jeunesdocteurs.com/fplr/56/08.html
+http://simf1.tripod.com/Rio.htm
+http://www.mirror.kiev.ua:8083/paper/1998/17/1251/people.htm
+http://web2.sportsline.com/u/baseball/mlb/2000PO_stats/tpSTLw.htm
+http://www15.freeweb.ne.jp/art/charukun/yusuke.htm
+http://map.ipc.co.jp/asp/onmap/r/new/g-24/f-905972/
+http://www.affiliate.hpstore.hp.co.uk/do/session/380882/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/REGISTRATION/entry.asp
+http://www.webcrawler.com/education/arts_and_humanities/visual_arts/art_history/c19th/arts_and_crafts/mackintosh_cr/structures/
+http://polygraph.ircache.net:8181/wwwboard/http_-2www.microsoft.com/msoffice/frontpage/http_-2www.linkstar.com/home/partners/marketlink-international-inc
+http://polygraph.ircache.net:8181/wwwboard/http_-2www.microsoft.com/msoffice/frontpage/ECA2.htm
+http://polygraph.ircache.net:8181/wwwboard/http_-2www.microsoft.com/msoffice/frontpage/http_-2www.intac.com/~dversch/catalog.html
+http://excite.de.netscape.com/kunst/katalog/24315
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/KhhIzVYqtXJlJzGPqrqzbJbUw7ERB8P7PSm9mTaj3BkJF6tLfllGlz2yKgLweoM1LPKLdHjjKv8zfb9tb2yojpTmzt6264ZE3V9vWzxY1mZnhDOG1vlwPrnwH5OCJM6C98fbjgZX66II
+http://mirror.nucba.ac.jp/mirror/Netscape/netscape6/french/6_PR2/windows/win32/?S=A
+http://www.linux.com/networking/server/install/howto/red_hat/package/
+http://www.nissan.co.jp/RENAULT-DEALERS/PASSPORT/view.cgi/proof/972959618--
+http://brain.brent.gov.uk/WebPages.nsf/vWebAllPagesByKey!OpenView&Start=97&Count=60&Expand=152
+http://i-mode.kakiko.com/deaitomo/mag/magurox/1405b.html
+http://www.ring.gr.jp/pub/NetBSD/arch/amiga/snapshot/20000115-1.4P/binary/security/
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=18,0+20,0-17,0-0,0
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/www/anoncvs.html?annotate=1.2&sortby=rev
+http://ftp.jp.debian.org/debian/dists/woody/non-free/binary-sh/hamradio/?M=A
+http://netscape.complete-skier.com/resorts/survey/submit.asp?ResortID=772
+http://nathanael.upi.jussieu.fr/tele6.nsf/autres+centres+de+formations!OpenPage&ExpandSection=9,17,2,16,5,14
+http://www.egroups.com/messages/zingiber/238
+http://www.umr.edu/~rhall/class/sap/sap8/demo.html
+http://209.207.239.212/bkindex/c1043/f1202.html
+http://se.egroups.com/message/ackmud/104
+http://school.educities.org/card/cug55.html
+http://school.educities.org/card/wgl.html
+http://school.educities.org/card/a77125.html
+http://school.educities.org/card/apple6128.html
+http://school.educities.org/card/c369852.html
+http://school.educities.org/card/cges4216.html
+http://school.educities.org/card/cges6307.html
+http://school.educities.org/card/eaa.html
+http://school.educities.org/card/f129235832.html
+http://school.educities.org/card/g1546.html
+http://school.educities.org/card/h223422022.html
+http://school.educities.org/card/lemon6112.html
+http://school.educities.org/card/st6408.html
+http://www.dulux.co.uk/UKRETAIL:1243142410:DFinity.1QJiP4jRACol
+http://www.iagora.com/pages/bbaddpost/::bb_id=148:mid=43302:thread_id=8185:parent_id=43302::lang=de
+http://www.iagora.com/pages/bbaddpost/::bb_id=148:mid=43431:thread_id=8185:parent_id=43431::lang=de
+http://www.egroups.com/message/intelligent_humor/875
+http://club.telepolis.com/klvinbc/fotosb.htm
+http://plat.debian.or.jp/debian/dists/woody/non-free/binary-mips/editors/?D=A
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=207&discrim=3,12,63
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=207&discrim=3,12,237
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=207&discrim=3,12,120
+http://www.jamba.de/KNet/_KNet-_tJ8j1-AGd-13ddq/browse.de/node.0/cdel3j591
+http://immihelpdownloads.subportal.com/sn/Utilities/System_Analysis_Utilities/2980.html
+http://dwp.bigplanet.com/crestinginc/discussion/edit.nhtml
+http://dwp.bigplanet.com/crestinginc/discussion/list.nhtml?profile=discussion
+http://194.128.65.4/pa/cm199900/cmwib/wb991127/ahead.htm
+http://61.128.218.34/book/hhsh/wu/wolongsheng/jiangxue/055.htm
+http://gd.cnread.net/cnread1/wgwx/t/tuwen/kxj/035.htm
+http://gd.cnread.net/cnread1/wgwx/t/tuwen/kxj/041.htm
+http://www.redrocksports.com/sports/webSession/shopper/RR972959743-31143/store/dept-5/department/dept-5/item/50110
+http://www.redrocksports.com/sports/webSession/shopper/RR972959743-31143/store/dept-5/department/dept-5/item/51530
+http://www.redrocksports.com/sports/webSession/shopper/RR972959743-31143/store/dept-5/department/dept-5/item/51510
+http://www.yorku.ca/org/yusa/who99/wh02.html
+http://www1.onelist.com/message/ar8200/3350
+http://www.kodak.se/US/en/corp/features/kern/jodi/index.shtml
+http://cafe3.daum.net/Cafe-bin/Bbs.cgi/semtle15pds/rnw/zka/B2-kB27k
+http://my.egroups.com/messages/dcfwriters/187?expand=1
+http://link.fastpartner.com/do/session/600414/vsid/1970/tid/1970/cid/135878/mid/1060/rid/1488/chid/1970/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/gosafe.php
+http://www.tiscover.com/1Root/Kontinent/6/Staat/7/Bundesland/20/Ort/108147/Bauernhof/315126/Homepage/f_homepage...2.html
+http://ring.omp.ad.jp/archives/NetBSD/packages/pkgsrc/net/gnut/patches/?D=A
+http://www.mtranslations.cz/40/cs/dictionary/dictionary_index.html
+http://pub10.ezboard.com/BBSSystem.handleLoginCheck?action=forgotPassword&boardName=alakazamslair
+http://tour.stanford.edu/cgi/locate3.prl/139.6/jMtlo
+http://www.shopworks.com/index.cfm/action/search/userid/00042DDE-2F63-19FE-9038010B0A0ADCF2
+http://thestar.com/back_issues/ED20001004/life/20000820LFE01_AH-BATH.html
+http://thestar.com/back_issues/ED20001004/life/20000818LFE01_LI-DEPRESS.html
+http://thestar.com/back_issues/ED20001004/life/20000806LFE01_AH-DAHLIAS.html
+http://www.hole.kommune.no/hole/journweb.nsf/7e180336094ef23a412568cd004a5093/466e7592a4c6c7ccc12568e3004402e8!Navigate&To=Prev
+http://mailthat.subportal.com/sn/Multimedia_and_Graphics/Graphics_Editors/3752.html
+http://www.gbnf.com/genealogy/rockwel4/html/d0014/I6348.HTM
+http://www.lookforforestry.com/catalog/FORSALE/FORKLIFT/JCB/930RTFL/
+http://www.espl.org/mearscol/pagendxs/stockley/d1828.htm
+http://in.egroups.com/messages/eyecandy/1290
+http://in.egroups.com/message/eyecandy/1264
+http://in.egroups.com/message/eyecandy/1271
+http://www.ferien-immobilien.de/bayern/deggendorf/Verkauf/Exklusiv-IB/Startseite/3d-service/Gemeinsam/Immolink/Gemeinsam/vertriebspartner.htm
+http://linux99.inrialpes.fr/linux/RPM/redhat/6.2/i386/Distribs.html
+http://students.lsu.edu/students/main.nsf/Pages/CSISAJ1!OpenDocument&ExpandSection=4,13,11,10
+http://www.doc.ic.ac.uk/lab/labsrc_area/firstyear/submissions/1997-98/jmc1/labs/Ex04/jwb97/?S=A
+http://www.iabusnet.org:90/forums/aca-1/dispatch.exe/survey/folderFrame/100001/0/alpha/2509069
+http://www.scifi.com/bboard/browse.cgi/1/5/545?lnum=4223
+http://www.fogdog.com/cedroID/ssd3040183304719/customer_service/
+http://www.fogdog.com/cedroID/ssd3040183304719/nav/products/winter_sports/1b/suits/
+http://www.gpul.org/ftp/lang/java/JDK/jdk1.1.6-docs/api/java.lang.Math.html
+http://www.gpul.org/ftp/lang/java/JDK/jdk1.1.6-docs/api/java.lang.IncompatibleClassChangeError.html
+http://www.staroriental.net/nav/soeg/ihf,aai,n2,418,Electric+Wave+Girl+1998.html
+http://www.parentsplace.com/expert/lactation/basics/qa/0,3459,5757,00.html
+http://www.francetrade.fr/opcvm/details/4/44200.html
+http://www.francetrade.fr/opcvm/details/4/42876.html
+http://genforum.genealogy.com/cgi-bin/print.cgi?phillippines::319.html
+http://www.affiliate.hpstore.hp.co.uk/do/session/380860/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-photoworld.com/photoworld.asp?lang=f
+http://ftp.eq.uc.pt/software/unix/Linux/docs/HOWTO/translations/italian/distributions/?M=A
+http://store1.europe.yahoo.com/brink2/2000074017704.html
+http://store1.europe.yahoo.com/brink2/2000073276003.html
+http://www.cbe21.com.cn/xueke/dili/jiaoxuezs/ziliaojn/tupianhc/i0733.htm
+http://www.networkpatternmatching.com/inventory/L/Limoges-American/Limoges-American-Tea-Rose-(Green).html
+http://www.networkpatternmatching.com/inventory/L/Limoges-American/Limoges-American-Toledo-Delight-(Sand).html
+http://ftp.debian.org/dists/sid/non-free/binary-hppa/games/?M=A
+http://www.angelfire.com/vt/kAoZzZ
+http://yp.gates96.com/14/28/60/15.html
+http://yp.gates96.com/14/28/60/17.html
+http://yp.gates96.com/14/28/60/41.html
+http://yp.gates96.com/14/28/60/75.html
+http://yp.gates96.com/14/28/60/83.html
+http://yp.gates96.com/14/28/60/87.html
+http://yp.gates96.com/14/28/61/96.html
+http://yp.gates96.com/14/28/62/12.html
+http://yp.gates96.com/14/28/62/28.html
+http://yp.gates96.com/14/28/62/45.html
+http://yp.gates96.com/14/28/62/74.html
+http://yp.gates96.com/14/28/63/24.html
+http://yp.gates96.com/14/28/63/45.html
+http://yp.gates96.com/14/28/64/33.html
+http://yp.gates96.com/14/28/65/84.html
+http://yp.gates96.com/14/28/66/28.html
+http://yp.gates96.com/14/28/66/49.html
+http://yp.gates96.com/14/28/67/15.html
+http://yp.gates96.com/14/28/67/17.html
+http://yp.gates96.com/14/28/67/92.html
+http://yp.gates96.com/14/28/67/95.html
+http://yp.gates96.com/14/28/68/10.html
+http://yp.gates96.com/14/28/69/20.html
+http://yp.gates96.com/14/28/69/64.html
+http://yp.gates96.com/14/28/69/74.html
+http://www.cs.kuleuven.ac.be/documentation/Sun/WorkShop/html_docs/c-plusplus/stdlibcr/deq_4164.htm
+http://no.egroups.com/message/Holiday-Best/571?source=1
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/G1hIPcWIQWr-i3fHpjDuaPPPdDR9n25II-MFpjX9vR_df0A3ukwPXLd19bYe7oxRH5Zr5z3G_wJnwM6gAVSOlRUN-p5MKYEBVJa1T-GaZS44Z98yjSST2LfXzEdc9Xqp8W0jRiNL6iAX
+http://msn.expedia.co.uk/wg/Asia/China/P31642.asp
+http://www.angelfire.com/fl2/gulfcoastsoftball/images/?N=D
+http://www.greenleaves.com/bookcat/gb_0879513802.html
+http://cn.egroups.com/post/Digitrends_Daily?act=reply&messageNum=210
+http://www.bookhome.net/wuxia/hzlz/li/031.html
+http://gb.toget.com.tw/intro/game_action/game_action_click/19990804_3190_dl.html
+http://www.mbnet.mb.ca/gray/cgrcc.html
+http://www.civila.com/noticias/chat/logos/juegos/esgratis/logos/index.html-ssi
+http://www.ytmag.com/cgi-bin/redirect.cgi/1197948180
+http://debian.tod.net/debian/dists/sid/contrib/binary-arm/admin/?M=A
+http://haste.co.kr/www.amaquest.com.tw/support.htm
+http://www.diogenes.ch/4DACTION/web_rd_aut_frlist_az/ID=483376&chr=A
+http://ads.neoseeker.com/remoteclick/GB972959289/
+http://urawa.cool.ne.jp/whoinside/cg/cgframe2.htm
+http://excite.de/bildung/katalog/33148
+http://plat.debian.or.jp/debian-archive/dists/Debian-2.0/hamm/binary-m68k/news/
+http://wwwpriv.uni-koblenz.de:81/~admin/Doku/HtmlTutor/tcdkc.htm
+http://platsbanken.amv.se/kap/text/62/000907,150090,120901,40,1427050362.shtml
+http://216.35.79.131/sites/gunits/022140u.html
+http://www.hotelboulevard.com/fr/paris/standard/htmle55cd396d0d1450ad1eddadf65bd6574/sessionLang/ANG/prov/browse/cp/75011/resultatSearch.html
+http://www.ftp.uni-erlangen.de/cgi-bin/view/pub/unix/Linux/MIRROR.KDE/unstable/apps/README
+http://www.ftp.uni-erlangen.de/pub/unix/Linux/MIRROR.KDE/unstable/apps/network/
+http://www.ycwb.com.cn/gb/2000/04/28/dnzk/itkx/3.html
+http://polygraph.ircache.net:8181/http_-2www.microsoft.com/guestbook/http_-2www.nmpinc.com/cfiguest.htm
+http://www.our-home.org/giulianovallemani/success.htm
+http://retailer.gocollect.com/do/session/1912838/vsid/2312/tid/2312/cid/573127/mid/1020/rid/2147/chid/2210/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLlZe5ofpLqjXLpl4/url/http://www.gocollect.com/product_display/products/product_lines.asp
+http://binary.tucows.com/win2k/adnload/60913_29719.html
+http://www.allhealth.com/kickbutt/qa/0,4801,6565_168263-1,00.html
+http://library.cuhk.edu.hk/search*chi/tChinese+history+series.+[Motion+picture]/tchinese+history+series/-5,1,1,B/frameset&F=tchinese+history+index+to+learned+articles+1902+1962&1,1,
+http://cafe4.daum.net/Cafe-bin/Bbs.cgi/culturalistpds/lst/qqeq/1/zka/B2-kB27p
+http://lib1.nippon-foundation.or.jp/1997/0012/contents/086.htm
+http://members.tripod.com/~theernest/lit/long.html
+http://de.excite.de/auto/katalog/13030
+http://www.szinfo.com/book/ke/fam/nk1/wlsf/001.htm
+http://www.backflip.com/members/cquinn/466730/sort=1/
+http://130.158.208.53/WWW/PDB2/PCD4711/htmls/49.html
+http://astronomysite.com/mapug1/15/msg15752.htm
+http://astronomysite.com/mapug1/15/msg15922.htm
+http://astronomysite.com/mapug1/15/msg15970.htm
+http://astronomysite.com/mapug1/12/msg12909.htm
+http://astronomysite.com/mapug1/9/msg9909.htm
+http://astronomysite.com/mapug1/7/msg7248.htm
+http://astronomysite.com/mapug1/7/msg7288.htm
+http://astronomysite.com/mapug1/7/msg7300.htm
+http://astronomysite.com/mapug1/7/msg7277.htm
+http://astronomysite.com/mapug1/3/msg3386.htm
+http://astronomysite.com/mapug1/0/msg898.htm
+http://astronomysite.com/mapug1/2/msg2146.htm
+http://people.freebsd.org/~knu/cgi-bin/cvsweb.cgi/ports/x11-fm/systemg/pkg/Attic/DESCR
+http://www.posterwelt.de/byers/bye2506.htm
+http://www.5a8.com/book/wg/zpj/f/fajieyefu/huimie/003.htm
+http://www.5a8.com/book/wg/zpj/f/fajieyefu/huimie/015.htm
+http://businessrecorder.com/story/S0015/S1510/top
+http://sunsite.org.uk/Mirrors/ftp.microsoft.com/bussys/winnt/winnt-public/fixes/usa/nt351/hotfixes-postsp5/sec-fix/?S=A
+http://sunsite.org.uk/Mirrors/ftp.microsoft.com/bussys/winnt/winnt-public/fixes/usa/nt351/hotfixes-postsp5/sec-fix/readme.txt
+http://www.angelfire.com/ky/dodone/HistJ.html
+http://www.cricinfo.com/link_to_database/ARCHIVE/1997-98/WI_IN_PAK/WI_IN_PAK_NOV-DEC1997_WI-SQUAD.html
+http://www.egroups.com/message/-Girlhelp-/3251
+http://www.egroups.com/message/-Girlhelp-/3268
+http://202.130.244.3/wuliwangye/help/help.htm
+http://ftp.gwdg.de/pub/EMIS/EMS/journals/SLC/divers/mirror.html
+http://ftp.gwdg.de/pub/EMIS/EMS/journals/SLC/divers/s20ghinelli.html
+http://ftp.gwdg.de/pub/EMIS/EMS/journals/SLC/divers/s25dress.html
+http://ftp.gwdg.de/pub/EMIS/EMS/journals/SLC/divers/s30wen.html
+http://ftp.gwdg.de/pub/EMIS/EMS/journals/SLC/divers/slc41email.html
+http://guardian.co.uk/Print/0,3858,3889048,00.html
+http://genforum.genealogy.com/mccallum/messages/187.html
+http://genforum.genealogy.com/mccallum/messages/192.html
+http://genforum.genealogy.com/mccallum/messages/133.html
+http://genforum.genealogy.com/mccallum/messages/95.html
+http://genforum.genealogy.com/mccallum/messages/82.html
+http://genforum.genealogy.com/mccallum/messages/30.html
+http://dekooi.tucows.com/win2k/adnload/37333_29427.html
+http://dekooi.tucows.com/win2k/adnload/37624_29418.html
+http://dekooi.tucows.com/win2k/preview/139483.html
+http://www.zurich-schweiz.ch/static/it/peraziende/grandiimprese/riskmanagement/procedere_con_metodo/gestione_del_rischio/
+http://cn.egroups.com/login.cgi?login_target=%2Fmessage%2Fcertdev%2F373
+http://www.angelfire.com/pa2/DreamAvs/
+http://www.madisonmag.com/sh/entertainment/stories/entertainment-20000713-013454.html
+http://variety.studiostore.com/browse/WHATSNEW/SHIRT/b.FAVORITES%20WHATSNEW/s.GqXR0UHu
+http://variety.studiostore.com/browse/WHATSNEW/MUG/b.FAVORITES%20WHATSNEW/s.GqXR0UHu
+http://www.ecs.soton.ac.uk/~ecc/teaching/java/ExampleCode/Chapter10/s03/
+http://ftp.nacamar.de/pub/NetBSD/packages/1.4/alpha/cross/?M=A
+http://www.he.ctc.org.cn/ctc2/news/internet/develop/news0413-7.htm
+http://www.he.ctc.org.cn/ctc2/news/internet/invest/news0523-4.htm
+http://www.he.ctc.org.cn/ctc2/news/internet/invest/news0514-1.htm
+http://www.he.ctc.org.cn/ctc2/news/internet/politics/news0518-1.htm
+http://www.linux.com/networking/network/applications/industry/trade_show/internet/
+http://www.linux.com/networking/network/applications/industry/trade_show/Motorola/
+http://www.linux.com/networking/network/applications/industry/trade_show/distro/
+http://iinet.tukids.tucows.com/mac/5-8/macmulti58_license.html
+http://www.leg.wa.gov/pub/rcw%20-%20text/title_48/chapter_098/rcw_48_98_005.txt
+http://universal.eud.com/1999/02/28/28304AA.shtml
+http://www.firstview.com/WRTWfall97/MAX_MARA/P033.html
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/SOSIAALI-+JA+TERVEYSALA/tietoverkot/suositukset/tietotekniikka/sanat/getdoc.akM?document_id=479
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/SOSIAALI-+JA+TERVEYSALA/tietoverkot/suositukset/tietotekniikka/sanat/www/
+http://ns.studenti.to.it/~s86852/applets/tetris.htm
+http://www.egroups.com/message/grebel-list/1014
+http://emedici.net/www.homesbyavi.com/canadian_site/communities/evergreen/evergreen.html
+http://ring.toyama-ix.net/pub/net/wu-ftpd/wu-ftpd/binaries/?N=D
+http://ring.nii.ac.jp/archives/text/CTAN/support/vmspell/?N=D
+http://ftpsearch.belnet.be/packages/CPAN/modules/by-authors/John_Macdonald/CHECKSUMS
+http://students.depaul.edu/~eephrem/piazza123
+http://students.depaul.edu/~eephrem/maqdoomi.html
+http://ftp.unina.it/pub/Unix/KDE/stable/2.0/distribution/deb/?D=A
+http://www.dulux.co.uk/UKRETAIL:1433075516:DFinity.1QJiP4jMofi7bof
+http://yp.gates96.com/14/20/10/26.html
+http://yp.gates96.com/14/20/10/34.html
+http://yp.gates96.com/14/20/10/63.html
+http://yp.gates96.com/14/20/11/36.html
+http://yp.gates96.com/14/20/11/73.html
+http://yp.gates96.com/14/20/12/93.html
+http://yp.gates96.com/14/20/13/42.html
+http://yp.gates96.com/14/20/13/44.html
+http://yp.gates96.com/14/20/14/9.html
+http://yp.gates96.com/14/20/15/62.html
+http://yp.gates96.com/14/20/15/77.html
+http://yp.gates96.com/14/20/16/52.html
+http://yp.gates96.com/14/20/16/70.html
+http://yp.gates96.com/14/20/16/83.html
+http://yp.gates96.com/14/20/17/91.html
+http://yp.gates96.com/14/20/17/98.html
+http://yp.gates96.com/14/20/18/8.html
+http://yp.gates96.com/14/20/18/73.html
+http://yp.gates96.com/14/20/19/38.html
+http://yp.gates96.com/14/20/19/42.html
+http://yp.gates96.com/14/20/19/56.html
+http://www.wco.com/~havok/wellington.html
+http://opac.lib.ntnu.edu.tw/search*chi/++ftlist/bbm0019678/7,-1,0,E/frameset&F=bbm0019685&1,1
+http://cdrom.zeelandnet.nl/elfsound/archief.htm
+http://businessrecorder.com/story/S0055/S5527/top
+http://www.private-immobilien-boerse.de/DominikanischeRep/verkauf/Versteigerungen-IB/Startseite/Gemeinsam/GmbH-Kauf-Verkauf-Insolvenz-konkurs/Startseite/IIM-Teil/Startseite/froben.htm
+http://ring.nii.ac.jp/archives/lang/perl/CPAN/doc/manual/html/pod/perlfunc/utime.html
+http://yp.gates96.com/14/21/10/71.html
+http://yp.gates96.com/14/21/11/15.html
+http://yp.gates96.com/14/21/12/55.html
+http://yp.gates96.com/14/21/12/58.html
+http://yp.gates96.com/14/21/13/94.html
+http://yp.gates96.com/14/21/14/7.html
+http://yp.gates96.com/14/21/14/12.html
+http://yp.gates96.com/14/21/14/32.html
+http://yp.gates96.com/14/21/14/96.html
+http://yp.gates96.com/14/21/15/3.html
+http://yp.gates96.com/14/21/15/51.html
+http://yp.gates96.com/14/21/16/32.html
+http://yp.gates96.com/14/21/16/87.html
+http://yp.gates96.com/14/21/17/19.html
+http://yp.gates96.com/14/21/17/31.html
+http://yp.gates96.com/14/21/18/15.html
+http://yp.gates96.com/14/21/18/68.html
+http://yp.gates96.com/14/21/19/56.html
+http://cafe2.daum.net/Cafe-bin/Bbs.cgi/kjbugopds/lst/qqa/f/zka/B2-kB2Rt
+http://legalminds.lp.findlaw.com/list/courtinterp-spanish/frm04580.html
+http://legalminds.lp.findlaw.com/list/courtinterp-spanish/frm04611.html
+http://genforum.genealogy.com/cgi-genforum/forums/sweden.cgi?5207
+http://variety.studiostore.com/main/b.FAVORITES%20NOSTALGI%20CLASTV%20ILOVELUCY/s.VfgR3aEr
+http://variety.studiostore.com/help/b.FAVORITES%20NOSTALGI%20CLASTV%20ILOVELUCY/s.VfgR3aEr
+http://bsd.sinica.edu.tw/cgi-bin/cvsweb.cgi/ports/x11-clocks/xalarm/patches/Attic/patch-aa?only_with_tag=RELEASE_2_2_8
+http://gd.cnread.net/cnread1/ztxs/h/henggouzhengshi/eld/013.htm
+http://gd.cnread.net/cnread1/ztxs/h/henggouzhengshi/eld/022.htm
+http://gd.cnread.net/cnread1/ztxs/h/henggouzhengshi/eld/024.htm
+http://ftp.unina.it/pub/Amiga/NetBSD/NetBSD-current/xsrc/xc/lib/xkbfile/?N=D
+http://202.99.23.245/zdxw/17/20000217/200002171734.html
+http://sunsite.org.uk/packages/netbsd/NetBSD-current/pkgsrc/net/batchftp/files/
+http://www.highwired.net/Activity/PrintArticle/0,1640,1326-186648,00.html
+http://phpbuilder.net/forum/archives/1/2000/10/1/104426?&print_mode=1
+http://www.cognos.co.uk/de/vertriebspartner/vertriebspartner_plz.html
+http://citeseer.nj.nec.com/cidcontext/3974259
+http://fi.egroups.com/message/free-classifieds/4556?source=1
+http://genforum.genealogy.com/cgi-genforum/forums/epler.cgi?2
+http://no.egroups.com/post/relations_iVillage?act=reply&messageNum=5
+http://198.103.152.100/search*frc/lHD69+P75H84/lhd+++69+p75+h84/-5,-1,0,E/frameset&F=lhd+++69+p75+k47+1984&1,1
+http://www.4positiveimages.com/4positiveimages/921456486/UserTemplate/2
+http://haha.3322.net/donghua/agui/adi/6.htm
+http://mediate.magicbutton.net/do/session/625591/vsid/4573/tid/4573/cid/88043/mid/2247/rid/2383/chid/3527/url/http://www.winesmart.com/CaseDetails.asp?idCase=66
+http://www.lettera.de/tp/deutsch/inhalt/lis/8676/1.html
+http://www.citybrazil.com.br/sc/regioes/joinville/expressoes.htm
+http://webcvs.kde.org/cgi-bin/cvsweb.cgi/www/food/worse_is_better.html?sortby=date
+http://yp.gates96.com/7/45/60/13.html
+http://yp.gates96.com/7/45/61/3.html
+http://yp.gates96.com/7/45/61/60.html
+http://yp.gates96.com/7/45/62/37.html
+http://yp.gates96.com/7/45/62/48.html
+http://yp.gates96.com/7/45/62/70.html
+http://yp.gates96.com/7/45/64/9.html
+http://yp.gates96.com/7/45/64/33.html
+http://yp.gates96.com/7/45/64/43.html
+http://yp.gates96.com/7/45/64/55.html
+http://yp.gates96.com/7/45/65/14.html
+http://yp.gates96.com/7/45/65/48.html
+http://yp.gates96.com/7/45/65/57.html
+http://yp.gates96.com/7/45/66/27.html
+http://yp.gates96.com/7/45/67/51.html
+http://yp.gates96.com/7/45/68/12.html
+http://yp.gates96.com/7/45/68/78.html
+http://yp.gates96.com/7/45/69/25.html
+http://www.msb.malmo.se/search*swe/aHarley,+Robert/aharley+robert/-5,-1,0,B/browse
+http://www.superdownloads.com.br/linkinvalido.cfm?ID=748
+http://linuz.sns.it/doc/howto/en/html/AI-Alife-HOWTO-6.html
+http://www.linux.com/networking/network/market/tools/applications/
+http://www.linux.com/networking/network/market/tools/frame_relay/
+http://www.linux.com/networking/network/market/tools/e-commerce/
+http://opac.lib.ntnu.edu.tw/search*chi/aUnited+Nations.+Dept.+of+Economic+and+Social+Affairs/aunited+nations+dept+of+economic+and+social+affairs/7,-1,0,B/frameset&F=aunited+nations+economic+and+social+commission+for+asia+and+the+pacific&6,,7
+http://www.affiliate.hpstore.hp.co.uk/do/session/380863/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/assistance/entry.asp
+http://www.affiliate.hpstore.hp.co.uk/do/session/380863/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/entry.asp
+http://www.shmoo.com/mail/ids/oct99/msg00288.html
+http://bsd.sinica.edu.tw/ftp_pub/NetBSD/packages/1.3/hp300/?M=A
+http://bsd.sinica.edu.tw/ftp_pub/NetBSD/packages/1.3/hp300/archivers/
+http://www.affiliate.hpstore.hp.co.uk/do/session/380868/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/REGISTRATION/entry.asp
+http://www.insideneworleans.com/shared/health/adam/ency/imagepage/1562.000872.html
+http://ring.omp.ad.jp/archives/NetBSD/packages/pkgsrc/devel/xxgdb/patches/patch-ac
+http://genforum.genealogy.com/casey/messages/327.html
+http://genforum.genealogy.com/casey/messages/164.html
+http://genforum.genealogy.com/casey/messages/337.html
+http://genforum.genealogy.com/casey/messages/73.html
+http://genforum.genealogy.com/casey/messages/57.html
+http://genforum.genealogy.com/casey/messages/50.html
+http://genforum.genealogy.com/casey/messages/23.html
+http://genforum.genealogy.com/casey/messages/116.html
+http://www.msb.malmo.se/search*swe/aNorman,+Karin,+1947-/anorman+karin+1947/-5,-1,0,B/frameset&F=anorman+leslie&1,1
+http://forum.rai.it/aca-finestre/dispatch.cgi/FORUM/folderFrame/100001/0/rnumber/9096335
+http://www.mindspring.com/~arachnid/?S=D
+http://www6.freeweb.ne.jp/business/n-bns/hre/
+http://news.swww.com.cn/wccdaily/review/200005/29/html/0908.htm
+http://tucows.hom.net/croomnt_rating.html
+http://www.trax.nilex.co.uk/trax.cgi/A1C/A2S/1AS/A4L/A4D/B1R/
+http://www.trax.nilex.co.uk/trax.cgi/A1C/A2S/1AS/A4L/A4D/A5L/
+http://www.5a8.com/book/kh/zg/zpj/h/heju/001.htm
+http://www.5a8.com/book/kh/zg/zpj/h/heju/002.htm
+http://www.luckyman.de/computer/hpaccess/java_cgi/java_applet/linien/applet_linien_nav1.htm
+http://www.secure-me.net/information/kb/POP
+http://in.egroups.com/message/BodybuildingContests/2804
+http://in.egroups.com/message/BodybuildingContests/2820
+http://in.egroups.com/message/BodybuildingContests/2822
+http://theconnection.vnunet.com/Analysis/Stfriend/70206
+http://www.yorosiku.net:8080/-_-http://www.nrcse.washington.edu/newsletter/newsletter.pdf
+http://www.britishairways.nl/regional/barbados/docs/spec_world_offer.shtml
+http://www.xmwb.sh.cn/xmwb/19981117/BIG5/13421^4111719.htm
+http://www.z-plus.de/TEXTE/HOMEPAGE/HILFE/HILFE_SURFTIPS201099/text5.html
+http://uzgamez.subportal.com/games/previews/0900/westwood/russian_general.html
+http://bsd.sinica.edu.tw/ftp_pub/NetBSD/packages/1.3/sun3/?D=A
+http://my.egroups.com/messages/dcfwriters/132?expand=1
+http://my.egroups.com/message/dcfwriters/147
+http://my.egroups.com/message/dcfwriters/149
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/projects/failsafe/FailSafe/failsafe/scripts/?only_with_tag=MAIN
+http://sound-dist.secured.co.uk/cgi-bin/psShop.cgi/add|8P007|972959615|Warm===and===Dry|user|0|1,0,0,1
+http://www.alsapresse.com/jdj/00/01/13/MA/photo_6.html
+http://www.highwired.net/ESchoolDrive/Frameset/0,5592,13577-52,00.html
+http://uk.sports.yahoo.com/000922/59/ak705.html
+http://universal.eud.com/1999/02/26/26204DD.shtml
+http://people.freebsd.org/~knu/cgi-bin/cvsweb.cgi/ports/audio/gkrellmvolume/pkg-descr?only_with_tag=MAIN
+http://www3.skolverket.se/kursinfo/99_00/skolform/21/alt_nav/S_52S_10S_36VAV_SVSTEK_1715.HTML
+http://www3.skolverket.se/kursinfo/99_00/skolform/21/alt_nav/S_52S_10S_36VAV_SVSTEK_1719.HTML
+http://www.wsrn.com/apps/research/history.xpl?s=CMDCD&f=HISTORY
+http://www.wsrn.com/apps/charts/?s=CMDCD&data=Z10
+http://pub3.ezboard.com/utherealcharron.showPublicProfile?language=EN
+http://ring.shibaura-it.ac.jp/archives/graphics/gimp/gtk/binary/DEBIAN/stable/?S=A
+http://209.52.189.2/discussion.cfm/autism/29762/198522
+http://www.affiliate.hpstore.hp.co.uk/do/session/380851/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/assistance/entry.asp
+http://www01.sankei.co.jp/advertising/furusato/tokuhain/9810/1018sindou.html
+http://kulichki-mac.rambler.ru/abiturient/ak.htm
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=3,0+9,1-20,0+9,0
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=3,0+9,1-20,0+18,0
+http://ballesta.inrialpes.fr/Infos/Personnes/Christophe.Rippert/ressources/tutorial/security1.2/summary/glossary.html
+http://www.affiliate.hpstore.hp.co.uk/do/session/380872/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.france.hp.com/main/respect/
+http://www11.cplaza.ne.jp/babyweb/bbs/bdnmp01/no24/99N.html
+http://www.homeway.com.cn/lbi-html/news/zhxw/gatxw/20000922/165807.shtml
+http://gd.cnread.net/cnread1/yqxs/d/dingqianrou/ssqj/009.htm
+http://library.bangor.ac.uk/search/tBiol.+philos/tbiol+philos/-17,-1,0,B/frameset&F=tbioindicators+and+environmental+management&1,1
+http://dante.bdp.it/cgi-bin/poseidon_v2.0/reflect/poseidon/disc/peacelink-scuola/70630505/view/1
+http://www.indian-express.com/ie/daily/19980626/17750374.html
+http://www.indian-express.com/ie/daily/19980626/17751044.html
+http://www.indian-express.com/ie/daily/19980626/17751334.html
+http://www.indian-express.com/ie/daily/19980626/17751494.html
+http://polygraph.ircache.net:8181/services/define/http_-2www.disney.com/links.html
+http://pub10.ezboard.com/fsavings4yousavings4you.subscribeUnregisteredToTopic?topicID=56.topic
+http://www8.freeweb.ne.jp/shopping/arthome/arthome/menu.html
+http://rainforest.parentsplace.com/dialog/get/medinfo/4/1.html?outline=3
+http://www.emerchandise.com/aboutus/b.TV%20SATNIGHTLIVE/s.afJ7iGE2
+http://ring.omp.ad.jp/archives/NetBSD/packages/pkgsrc/net/arpwatch/pkg/?S=A
+http://ring.omp.ad.jp/archives/NetBSD/packages/pkgsrc/net/arpwatch/pkg/DESCR
+http://210.178.135.1/netbbs/Bbs.cgi/nhic30872/qry/zka/B2-kBI-o/pno/0/qqo/004A/qqatt/^
+http://yp.gates96.com/8/48/0/54.html
+http://yp.gates96.com/8/48/1/98.html
+http://yp.gates96.com/8/48/2/23.html
+http://yp.gates96.com/8/48/3/13.html
+http://yp.gates96.com/8/48/3/14.html
+http://yp.gates96.com/8/48/3/23.html
+http://yp.gates96.com/8/48/3/84.html
+http://yp.gates96.com/8/48/4/5.html
+http://yp.gates96.com/8/48/4/72.html
+http://yp.gates96.com/8/48/5/4.html
+http://yp.gates96.com/8/48/5/49.html
+http://yp.gates96.com/8/48/6/38.html
+http://yp.gates96.com/8/48/6/89.html
+http://yp.gates96.com/8/48/8/10.html
+http://yp.gates96.com/8/48/8/41.html
+http://yp.gates96.com/8/48/8/87.html
+http://news.medscape.com/adis/CDI/2000/v19.n02/cdi1902.02.biel/cdi1902.02.biel-01.html
+http://www.parsonstech.com/genealogy/trees/PKINGMAN/d2438.htm
+http://www.parsonstech.com/genealogy/trees/PKINGMAN/d2502.htm
+http://www.chaos.dk/sexriddle/j/c/b/o/
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/FahI8ikSPIvk79ErK106-87Jy3U1_XgCksR4DWkUOldKaD_pciJBXOOmI2Sr4jXlDCT9Mkz59aBZhyyi3xxBeYROt0IpVObKZD4YcwBAhl9afrfb6y3nWI3SwdRE_Vp3d80RzmrDkPVZYQkJyvOgorzS
+http://opac.lib.rpi.edu/search/dchemicals+dictionaries/-5,-1,0,E/frameset&dchemicals+catalogs&3,,0
+http://opac.lib.rpi.edu/search/dchemicals+dictionaries/-5,-1,0,E/frameset&dchemicals+catalogs+periodicals&1,1
+http://opac.lib.rpi.edu/search/dchemicals+dictionaries/-5,-1,0,E/frameset&dchemicals+dictionaries&3,,0
+http://opac.lib.rpi.edu/search/dchemicals+dictionaries/-5,-1,0,E/frameset&dchemicals+economic+aspects+united+states&1,,0
+http://www.jsonline.com/news/state/oct00/lambeau31103000a.asp
+http://polygraph.ircache.net:8181/used/http_-2www.scubaring.com/http_-2www.alpinehotel.com/chinese/chine.htm
+http://www.kaos.dk/sex-riddle/k/a/k/i/p/g/g/e/
+http://haikou.hainan.gov.cn/ghgl/ghsc/hkfg3020.html
+http://variety.studiostore.com/main/VARIETY/s.Fz90iGDh
+http://library.cuhk.edu.hk/search*chi/cPN595.C6I18+1993/cpn++595+c6+i18+1993/-5,1,1,E/frameset&F=cpn++595+c6+k6+1997&1,1,
+http://library.cuhk.edu.hk/search*chi/cPN595.C6I18+1993/cpn++595+c6+i18+1993/-5,1,1,E/frameset&F=cpn++595+c6+l515&1,1,
+http://link.fastpartner.com/do/session/600425/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/learn.htm
+http://www.nanyang.com.my/20001020/articles/15-10-2000k16.htm
+http://202.99.23.245/rmrb/199912/11/newfiles/col_19991211001063_zhxw.html
+http://help.sap.com/saphelp_45b/helpdata/en/a7/2872510a6c11d28a220000e829fbbd/frameset.htm
+http://www.s10.sexshare.com/~pornking/hardcore/43.html
+http://www.gbnf.com/genealogy/Lawler99/html/d0102/I1772.HTM
+http://ring.edogawa-u.ac.jp/pub/linux/RedHat/aic/OLD/aic7xxx-5.0.x/boot_disks/5.0.11/SuSE/?D=A
+http://www.t-online.de/sport/inhalte/adispi51.htm
+http://ftp.lip6.fr/pub11/FreeBSD/development/FreeBSD-CVS/src/kerberos5/usr.sbin/k5stash/
+http://education.legend-net.com/xinwen/gaokao/zl5/zhsh/3/zhshyk.html
+http://www.contractorresource.com/Wyoming/Cody/
+http://213.36.119.69/do/session/152998/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/boutique/
+http://213.36.119.69/do/session/153000/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/reserver/hotels.html
+http://213.36.119.69/do/session/153000/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www3.travelprice.com/voyages/recherche.phtml
+http://ftp.unina.it/pub/TeX/macros/latex/contrib/supported/combine/?D=A
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=237&discrim=178,2,11
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=237&discrim=178,2,233
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=237&discrim=178,2,5
+http://www12.freeweb.ne.jp/novel/urufu24/linkz/ug1.html
+http://www12.freeweb.ne.jp/novel/urufu24/linkz/pv.html
+http://computers.kharkov.ua/win/43/
+http://www.1001e.net/nk4/022.htm
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=4&discrim=93,164,176
+http://dic.empas.com/show.tsp/?q=revisable&f=B
+http://yp.gates96.com/0/28/30/45.html
+http://yp.gates96.com/0/28/30/46.html
+http://yp.gates96.com/0/28/31/24.html
+http://yp.gates96.com/0/28/32/64.html
+http://yp.gates96.com/0/28/33/28.html
+http://yp.gates96.com/0/28/33/85.html
+http://yp.gates96.com/0/28/33/87.html
+http://yp.gates96.com/0/28/33/96.html
+http://yp.gates96.com/0/28/34/52.html
+http://yp.gates96.com/0/28/35/7.html
+http://yp.gates96.com/0/28/36/23.html
+http://yp.gates96.com/0/28/36/52.html
+http://yp.gates96.com/0/28/37/50.html
+http://yp.gates96.com/0/28/38/85.html
+http://yp.gates96.com/0/28/39/16.html
+http://www.fan590.com/JamMoviesReviewsE/earth_king.html
+http://www.sportbuecher.de/shop/3-88034-750-6.html
+http://www.msb.malmo.se/search*swe/aWhitaker,+Galvin,+Utgivare/awhitaker+galvin/-5,-1,0,B/exact&F=awhitburn+joel&1,2
+http://ftp.sunet.se/pub/security/vendor/microsoft/winnt/frn/nt40/?M=A
+http://www.intervoz.com.ar/2000/03/02/op_n04.htm
+http://www.ntut.edu.tw/~s7370840/8-19.htm
+http://www.back2roots.org/Music/Files/Wondergirl%20-%20You%26Me/
+http://www.private-immobilien-boerse.de/nordrhein-Westfalen/Muehlheim-ruhr/Verkauf/3d-service/IIM-Teil/Startseite/Gemeinsam/Inserieren/IIM-Teil/Startseite/frinfo.htm
+http://web.singnet.com.sg/~spirit5/letters/oct2000/frankm1025-3.htm
+http://web.singnet.com.sg/~spirit5/letters/oct2000/davidp1025.htm
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=decuplicavamo&l=it
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=decuplichiate&l=it
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=decuplichereste&l=it
+http://members.tripod.com/~OZEMU/cgi-bin/
+http://ring.tains.tohoku.ac.jp/archives/pack/dos/hardware/midi/?D=A
+http://kutschen.de/Schoner/info-e/info-e/collections/literature/
+http://www.jamba.de/KNet/_KNet-MJJ8j1-DGd-13dgc/showInfo-special1.de/node.0/cde7f1uou
+http://www.jamba.de/KNet/_KNet-MJJ8j1-DGd-13dgy/browse.de/node.0/cenv0b09a
+http://in.egroups.com/message/sfconsim-l/6415
+http://genforum.genealogy.com/cgi-genforum/forums/vt.cgi?4123
+http://www.linux.com/networking/network/sap/article/price/VA_Linux_Systems/
+http://www.linux.com/networking/network/sap/article/price/regulation/
+http://slacvx.slac.stanford.edu/sldmcwww/mc/MC74BB_98R16B_WIN_ALL.HTML
+http://www.xmission.com/~dkenison/cgi/lwgate.cgi/KLR650/archives/v02.n1611/date/article-15.html
+http://www.iwon.com/home/movies/movies_filmography_page/0,13178,Macon+McCalman,00.html
+http://excite.de/spiele/katalog/26997
+http://www.trax.nilex.co.uk/trax.cgi/A1C/B1S/B2R/A2U/B3S/B1R/
+http://www.power2lead.com/Global/English.nsf/pgWWLocations!OpenPage&ExpandSection=2,6,27,9,26
+http://itcareers.careercast.com/texis/it/itjs/+owwBm1eP0-dzwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewDPwdGpdGwBodDa5dhBiwGna5O5BnManDtoDnnGa5nDodGa5BwhhaidGAanLpnGonDqnaqdMp1BnGamnVncdpaMFqhTfR20Dzme8twwwpBmer+D86e9qwww5rmeZpwwwBrmeZpwww/morelike.html
+http://pub4.ezboard.com/fnationoferidinegeneral.showAddReplyScreenFromWeb?topicID=615.topic&index=2
+http://www.chaos.dk/sexriddle/m/i/s/x/
+http://kiasuplanet.subportal.com/sn/Games/Tetris_Clone_Games/5532.html
+http://kiasuplanet.subportal.com/sn/Games/Tetris_Clone_Games/11418.html
+http://kiasuplanet.subportal.com/sn/Games/Tetris_Clone_Games/676.html
+http://www.rge.com/pub/networking/ldap/umich/max500/beta/?M=A
+http://my.egroups.com/dir/Health/Fitness/Exercise_Equipment
+http://my.egroups.com/messages/prevention
+http://pub4.ezboard.com/factiveprodiscussioncommunityactivitiesquestions.showMessage?topicID=12.topic
+http://www.look4cranes.com/catalog/AUCTIONRESULT/AGGREGATE+-+CONVEYOR+%2F+FEEDER+%2F+STACKER/POWERSCREEN/
+http://www.fogdog.com/cedroID/ssd3040183344300/cgi-bin/MyFogdog
+http://www.fogdog.com/cedroID/ssd3040183344300/nav/products/featured_brands/3b/gloves_mittens/
+http://www.houses-apartment-listings.com/Washington/city_search_criteria.asp?state=WA&City=CONCONULLY
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/c23417.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x12810.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x14250.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x14507.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x15988.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x17214.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x18550.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x19113.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x1949.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x21473.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x31101.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x3585.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x44035.html
+http://www.brunel.ac.uk/~ccusjpe/linux/howto/Consultants-HOWTO/x4711.html
+http://www.online.kokusai.co.jp/Home/V0043638/wrd/G100/
+http://ftp.lip6.fr/pub5/FreeBSD/branches/-current/ports/print/ghostscript5/
+http://ftp.lip6.fr/pub5/FreeBSD/branches/-current/ports/print/texinfo/
+http://ftpsearch.belnet.be/mirrors/ftp.isc.org/pub/usenet/control/ats/?N=D
+http://garbo.uwasa.fi/pub/linux/distributions/SuSE/7.0/dosutils/exceed/USER/HOSTEX/SCHEME/?D=A
+http://forum.rai.it/aca-finestre/dispatch.cgi/FORUM/showNextUnseen/fol/100001/922702
+http://link.fastpartner.com/do/session/600391/vsid/1314/tid/1314/cid/134340/mid/1060/rid/1180/chid/1314/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/local/redirect.php
+http://www.jamba.de/KNet/_KNet-wEF8j1-bGd-13cma/showInfo-datenschutz.de/node.0/cenvptf1i
+http://www.jamba.de/KNet/_KNet-wEF8j1-bGd-13cmd/browse.de/node.0/cenv0b09a
+http://www-usa6.cricket.org/link_to_database/PLAYERS/RSA/T/THOMPSON_DS_03003252/
+http://sunsite.org.uk/public/public/packages/WWW/emacs-w3/?S=A
+http://www.excelsior.com.mx/9811/981129/buh25.html
+http://www.anixter.nl/SBJEVE/170699-2155-01.html
+http://innopac.lib.tsinghua.edu.cn:2082/search*chi/aBrooks,+Jane+B./abrooks+jane+b/-5,-1,0,B/browse
+http://tour.stanford.edu/cgi/options.prl/95.70/gMcto
+http://www.cksd.edgate.com/emeraldheightses/elections/students/the_parties/
+http://novel.hichinese.net/comment/comment.php?page=2091&action=write
+http://205.161.150.96/cgi-bin/c2k/additem.html&item=204578
+http://www.nhic.or.kr/netbbs/Bbs.cgi/nhic31282/qry/zka/B2-kB2-m/pno/0/qqo/004A/qqatt/^
+http://scripts.infoart.ru/magazine/znamia/n4-20/shpakov.htm
+http://excite.de/bildung/katalog/19909
+http://911codes.com/games/platform/n64/sect/div/cont/list_cheat/spray/y/id/0000009557/gid/0000003573/_cheats/_walkthroughs/_codes/_pc/_n64/_psx/_gameboy/_playstation/
+http://ftp.jp.debian.org/debian/dists/stable/main/source/web/?M=A
+http://www.fogdog.com/cedroID/ssd3040183335913/nav/products/featured_brands/3c/all/
+http://his.luky.org/ML/linux-users.3/msg08073.html
+http://yomiuri-1422.excite.co.jp/entertainment/animated_cartoon_comic/each_work_title/ha_line/ha
+http://yomiuri-1422.excite.co.jp/entertainment/animated_cartoon_comic/each_work_title/ha_line/hu_he/berserk
+http://library.cwu.edu/search/dWorld+War,+1914-1918+--+Diplomatic+history/dworld+war+1914+1918+diplomatic+history/-5,-1,0,B/exact&F=dworld+war+1914+1918+diplomatic+history&1,49
+http://www.utdallas.edu/dept/sci_ed/Caribbean/images/Jennifer%20Jordan/Antigua%20Mangrove/?N=D
+http://www.baustoffhandel.de/service/faqs/faq-tapezieren.htm
+http://muc-zvs-web1.goethe.de/ms/bud/film/un_f2.htm
+http://www.online.kokusai.co.jp/Map/V0043636/wrd/G1000/map/sitemap.html
+http://win.www.citycat.ru/funny/fido/2000_05/25.html
+http://nathanael.upi.jussieu.fr/tele6.nsf/autres+centres+de+formations!OpenPage&ExpandSection=9,1,7,13,15,6
+http://yp.gates96.com/11/79/50/1.html
+http://yp.gates96.com/11/79/50/92.html
+http://yp.gates96.com/11/79/52/64.html
+http://yp.gates96.com/11/79/54/79.html
+http://yp.gates96.com/11/79/54/81.html
+http://yp.gates96.com/11/79/56/28.html
+http://yp.gates96.com/11/79/56/30.html
+http://yp.gates96.com/11/79/56/46.html
+http://yp.gates96.com/11/79/56/83.html
+http://yp.gates96.com/11/79/57/10.html
+http://yp.gates96.com/11/79/57/33.html
+http://yp.gates96.com/11/79/58/1.html
+http://yp.gates96.com/11/79/58/48.html
+http://yp.gates96.com/11/79/58/82.html
+http://yp.gates96.com/11/79/59/62.html
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/ELINKEINO-+JA+YRITYSTOIMINTA/Matkailu+-+maantiede/matkailu/linja-autoliikenne/joukkoliikenne/aikataulut/
+http://cn.egroups.com/message/romtrade/3823
+http://www.idgnet.com/idgns/1999/07/16/SmallFrenchBusinessesMoveSlowlyTo.shtml
+http://www-d0.fnal.gov/d0dist/dist/releases/psim01.01.00/Exceptions/?M=A
+http://www.4positiveimages.com/4positiveimages/781560892/Catalog
+http://dellnet.excite.fr/yellow_pages/annuaire/823
+http://ftp.chg.ru/pub/math/grace/MIRRORS
+http://ftp.chg.ru/pub/math/grace/aux/
+http://legalminds.lp.findlaw.com/list/lawlibref-l/mail8.html
+http://carriage.de/Schoner/modelle/models/Info-d/Sammlungen/
+http://chunma.yeungnam.ac.kr/~j4390214/경기상승.htm
+http://members.tripod.co.jp/stpp/?M=A
+http://map.ipc.co.jp/asp/onmap/connect/f-525598/g-28/
+http://www.fortunecity.com/business/lerner/101/form.html
+http://www.sportskorea.net/BBS/Bbs/db/L019/act/new/bnum/000060/zka/6/o/6/drc/f
+http://ftp.jp.debian.org/debian/dists/Debian2.2r0/main/binary-all/hamradio/?M=A
+http://admin.afiliando.com/do/session/189476/vsid/1507/tid/1507/cid/23455/mid/1025/rid/1168/chid/1205/parser/yes/imref/eqqLmwlGltt5tkpHrYjLXofLklkKZljLkju5lZa5l0/url/http://www.submarino.com.mx/toy/home.asp
+http://www.gasex.com/gay.male.erotica/penis.gay.twink.men.html
+http://ftpsearch.belnet.be/mirrors/ftp.isc.org/pub/usenet/control/ak/?S=A
+http://gb.toget.com.tw/intro/desktop_wallpaper/desktop_wallpaper_idol/20000417_7747_dl.html
+http://yp.gates96.com/13/50/50/27.html
+http://yp.gates96.com/13/50/52/20.html
+http://yp.gates96.com/13/50/52/31.html
+http://yp.gates96.com/13/50/52/44.html
+http://yp.gates96.com/13/50/53/33.html
+http://yp.gates96.com/13/50/53/45.html
+http://yp.gates96.com/13/50/53/72.html
+http://yp.gates96.com/13/50/54/34.html
+http://yp.gates96.com/13/50/54/62.html
+http://yp.gates96.com/13/50/54/83.html
+http://yp.gates96.com/13/50/54/84.html
+http://yp.gates96.com/13/50/55/5.html
+http://yp.gates96.com/13/50/55/61.html
+http://yp.gates96.com/13/50/55/75.html
+http://yp.gates96.com/13/50/56/0.html
+http://yp.gates96.com/13/50/56/15.html
+http://yp.gates96.com/13/50/56/21.html
+http://yp.gates96.com/13/50/56/29.html
+http://yp.gates96.com/13/50/57/2.html
+http://yp.gates96.com/13/50/57/54.html
+http://yp.gates96.com/13/50/58/9.html
+http://yp.gates96.com/13/50/58/34.html
+http://yp.gates96.com/13/50/59/64.html
+http://yp.gates96.com/13/50/59/70.html
+http://yp.gates96.com/13/50/59/75.html
+http://yp.gates96.com/13/50/59/85.html
+http://www.ilmessaggero.it/hermes/19990419/07_MARCHE/40/AGRI.htm
+http://www.ilmessaggero.it/hermes/19990419/07_MARCHE/40/NERA.htm
+http://amigos.com/cgi-bin/w3com/pws/ffe/IURImAxosglBgN4t3Iz538S9DOsFp6mHl6tpYJehgGibFrnWNcTM3WIsDckFomPqZ-JB8f_Qj8Aua4sE4AFvcFyidtj2iI6k1zPchuFbLwWMCo3hr8eXPNuxbHPQdRvo8J246667
+http://amigos.com/cgi-bin/w3com/pws/ffe/F3hIBiydr9mPRNSqk-dll3MTqIZCaRN3wRH0-H7o4qF0vlfPBXUV-Vhn028iva56e-GCSyYZKBQxuCJO8Y2JF25fVTkPHzFtrNMoOVhEp2n7Y11PhN9pvFNyqgssdZW8Eay0XJsP0vuD4oCbmJVx
+http://home.digitalcity.com/boston/sportsguy/main.dci?page=curse2
+http://ftpsearch.belnet.be/mirror/ftp.funet.fi/pub/Linux/doc/logos/.cap/?S=A
+http://ftpsearch.belnet.be/mirror/ftp.funet.fi/pub/Linux/doc/logos/.cap/?D=A
+http://my.netian.com/~52tour/kyung1.html
+http://aol.weather.com/weather/radar/single_site/us_ny_allegany.html
+http://www-usa16.cricket.org/link_to_database/GROUNDS/RSA/CENTURION/
+http://polygraph.ircache.net:8181/prodev/career/http_-2www.getstats.com/http_-2www.shindex.com/in_dex/in_dex.html
+http://polygraph.ircache.net:8181/prodev/career/http_-2www.getstats.com/http_-2www.microsoft.com/msoffice
+http://www.5a8.com/book/wg/cp/p/puge/zhizhunv/005.htm
+http://tukids.raha.com/crafts/preview/52044.html
+http://tukids.raha.com/crafts/preview/52401.html
+http://buc.co.kr/www.ecs.com.tw/
+http://wap.jamba.de/KNet/_KNet-EDS8j1-KHd-13gbq/showInfo-werbung.de/node.0/cde7f1uou
+http://www.launch.com/music/songpage/1,4425,322514,00.html
+http://www.emerchandise.com/browse/BUFFYTHEVAMP/CAP/b.TV%20BUFFYTHEVAMP/s.NGdTZGLC
+http://www.emerchandise.com/browse/BUFFYTHEVAMP/STICKER/b.TV%20BUFFYTHEVAMP/s.NGdTZGLC
+http://www.emerchandise.com/help_security/b.TV%20BUFFYTHEVAMP/s.NGdTZGLC
+http://yp.gates96.com/14/70/50/9.html
+http://yp.gates96.com/14/70/50/23.html
+http://yp.gates96.com/14/70/50/24.html
+http://yp.gates96.com/14/70/50/40.html
+http://yp.gates96.com/14/70/50/47.html
+http://yp.gates96.com/14/70/50/79.html
+http://yp.gates96.com/14/70/50/89.html
+http://yp.gates96.com/14/70/51/83.html
+http://yp.gates96.com/14/70/52/98.html
+http://yp.gates96.com/14/70/53/46.html
+http://yp.gates96.com/14/70/54/4.html
+http://yp.gates96.com/14/70/54/24.html
+http://yp.gates96.com/14/70/54/97.html
+http://yp.gates96.com/14/70/55/51.html
+http://yp.gates96.com/14/70/57/51.html
+http://yp.gates96.com/14/70/58/3.html
+http://yp.gates96.com/14/70/58/84.html
+http://yp.gates96.com/14/70/59/0.html
+http://opac.lib.ntnu.edu.tw/search*chi/++ftlist/bp20046027/-5,-1,0,B/frameset&F=bp20046031&1,1
+http://www.free-phone.com/q/001p/ppc2/KtIYye9a8Pw.htm
+http://www.1stemlm.com/q/001p/ppc2/7kwUxQYfGMk.htm
+http://sports.excite.com/ten/grand_german
+http://www.omniseek.com/dir/Arts+%26+Humanities/Fine+Arts/Ceramics/Organizations/Australia/
+http://ftp1.service.digital.com/patches/public/vms/axp/v7.1-2/dec-axpvms-vms712_usb-v0100--4.pcsi-dcx_axpexe
+http://ftp1.service.digital.com/patches/public/vms/axp/v7.1-2/vms712_acrtl-v0100.README
+http://ftp1.service.digital.com/patches/public/vms/axp/v7.1-2/vms712_acrtl-v0100.html
+http://ftp1.service.digital.com/patches/public/vms/axp/v7.1-2/vms712_dqconfig-v0200.README
+http://ftp1.service.digital.com/patches/public/vms/axp/v7.1-2/vms712_ds20e-v0100.html
+http://ftp1.service.digital.com/patches/public/vms/axp/v7.1-2/vms712_shadowing-v0300.CVRLET_TXT
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=barrissait&l=fr
+http://dk.egroups.com/message/M-1911/4394
+http://www.netsh.com.cn/wwwboardm/526/messages/2116.html
+http://www.netsh.com.cn/wwwboardm/526/messages/2270.html
+http://www.netsh.com.cn/wwwboardm/526/messages/773.html
+http://www.netsh.com.cn/wwwboardm/526/messages/2058.html
+http://www.netsh.com.cn/wwwboardm/526/messages/2329.html
+http://www.netsh.com.cn/wwwboardm/526/messages/1813.html
+http://linux.softhouse.com.cn/linux/knowledge/tech/HOWTO/Java-CGI-HOWTO-7.html
+http://news.novgorod.ru/news/2000/9/22/2/12
+http://news.novgorod.ru/news/2000/9/24/2/12
+http://homepage1.nifty.com/sigenyan/nikki9.htm
+http://perso.club-internet.fr/guige/ncpc78.htm
+http://www.vr-homes.com/usa/California/Cities/Victorville/Travel/Maps_Images/
+http://www.incestpornstories.com/cum-sex-pics/underagecoed/spankingsweating/hardendurance.html
+http://www.freeforums.com/forums/Hardball/000008-000007.asp
+http://www.freeforums.com/forums/Hardball/000005-000001.asp
+http://www.freeforums.com/forums/Hardball/000004-000001.asp
+http://rex.skyline.net/html/Internet_Chat_Sites.html?315,computers,video,internet,computers
+http://rex.skyline.net/html/Computers_-_Hardware.html?14,computers,video,internet,computers
+http://194.128.65.4/pa/cm199899/cmhansrd/vo990216/text/90216w20.htm
+http://pub14.ezboard.com/fyamguyskoflastblade.showMessage?topicID=3.topic
+http://plant.reedexpo.ca/www.partnership.ca/?S=A
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=168&discrim=109,5,168
+http://www.aelita.net/products/~archive/Download_redirect/solutions/solutions/services/products/default.htm
+http://www.jpc-music.com/7041801.htm
+http://home.c2i.net/entreprenor/java/ra.html
+http://gxschool.beelink.com.cn/mid_edu/midschool/geography3/t4cd7z/4d7z3.3_1.htm
+http://ricoh.co.jp/SHOGI/emate/basic/mate3003a.html
+http://www.diogenes.ch/4DACTION/web_rd_aut_frlist_az/ID=483385&chr=K
+http://www.ebigchina.com/msg_post.phtml?cu=1003
+http://www.bemi-immobilien.de/allgemeine-ib/startseite/Gemeinsam/erreichenPartner/Gemeinsam/versicherungen/lebensversicherung/Gemeinsam/immolink/Gemeinsam/MarketingStrategie/Gemeinsam/Inserieren/onlineInserieren.htm
+http://ftp.tku.edu.tw/OS/Linux/distributions/RedHat/rawhide/i386/doc/rhinst/stylesheet-images/?S=A
+http://www.egroups.com/message/kicken/284
+http://www.guangmingdaily.com.cn/0_gm/1999/12/19991222/big5/gm^18278^2^GM2-2216.htm
+http://brightnet.pda.tucows.com/www.psionsite.rcsed.ac.uk/
+http://www.symatrixinc.com/website/website.nsf/0/3e40df86fb357cd5882568720079613f!OpenDocument&ExpandSection=9,22,1,11
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=durereste&l=it
+http://click-to.tell-a-friend.boardhost.com/tell-a-friend-confirm.cgi?ylihilseen&msg=25
+http://www.gbgm-umc.org/EllisvilleMO/10-04-00.pdf
+http://www.marketingtool.com/contribute/webfirm/b.435.r.2626.g.4134.html
+http://www.chaos.dk/sexriddle/h/a/w/l/
+http://www.chaos.dk/sexriddle/h/a/w/t/
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=3,0+9,5-0,3+(
+http://www.guba.net/101/136/125E/index-4.phtml
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=3,0+9,5-0,3+21,0
+http://www.guba.net/101/136/125E/index-7.phtml
+http://www.guba.net/101/136/125E/index-15.phtml
+http://ftpsearch.belnet.be/ftp/mirror2/ftp.cert.dfn.de/pub/vendor/sun/security-alert/security-alert-108.txt
+http://ftpsearch.belnet.be/ftp/mirror2/ftp.cert.dfn.de/pub/vendor/sun/security-alert/security-alert-170.txt
+http://www.tente.de/us/produkte/rubriksuche/ad000000699.htm
+http://www.angelfire.com/ky/kysweetpea/
+http://yp.gates96.com/7/69/60/1.html
+http://www.amulation.com/md-l-archive/199908/frm00208.html
+http://yp.gates96.com/7/69/60/4.html
+http://yp.gates96.com/7/69/60/33.html
+http://yp.gates96.com/7/69/60/49.html
+http://yp.gates96.com/7/69/60/71.html
+http://nanjingnews.jlonline.com/nanjingnews/njrb/20000226/04tiyu.htm
+http://yp.gates96.com/7/69/61/44.html
+http://yp.gates96.com/7/69/61/69.html
+http://yp.gates96.com/7/69/61/82.html
+http://yp.gates96.com/7/69/61/85.html
+http://yp.gates96.com/7/69/62/4.html
+http://yp.gates96.com/7/69/63/34.html
+http://yp.gates96.com/7/69/63/48.html
+http://yp.gates96.com/7/69/63/66.html
+http://yp.gates96.com/7/69/64/22.html
+http://www.bemi-immobilien.de/IIM-Teil/Startseite/Gemeinsam/MarketingStrategie/Gemeinsam/Inserieren/Startseite/Gemeinsam/versicherungen/unfall/Gemeinsam/3d-service/info.htm
+http://yp.gates96.com/7/69/64/26.html
+http://yp.gates96.com/7/69/65/89.html
+http://yp.gates96.com/7/69/67/11.html
+http://yp.gates96.com/7/69/67/28.html
+http://yp.gates96.com/7/69/67/33.html
+http://yp.gates96.com/7/69/67/70.html
+http://yp.gates96.com/7/69/68/22.html
+http://yp.gates96.com/7/69/68/72.html
+http://yp.gates96.com/7/69/68/92.html
+http://members.tripod.com/~katenleo/fading21.html
+http://yp.gates96.com/7/69/69/6.html
+http://members.tripod.com/~katenleo/fading26.html
+http://yp.gates96.com/7/69/69/36.html
+http://yp.gates96.com/7/69/69/91.html
+http://yp.gates96.com/7/69/69/98.html
+http://www.tribuneindia.com/98oct11/head1.htm
+http://fi.egroups.com/message/internet-sig-announce/3
+http://info.verwaltung.uni-freiburg.de/doc/susehilf/pak/paket_inhalt_libxml.html
+http://www.planetweb.com/cgi-bin/listmanager.pl/NETLINK-CUST/archives/1998Mar30-Apr05.archive/Date/article-23.html
+http://www.maasvlakte-cam.nl/webcams/11/katowice__poland/2000/06/13/
+http://www.eveclub.com/cgi-bin/eveclub.front/972959521459/Home
+http://totalsports.aol.com/stats/bbo/int/20000413/nor.at.lou.box.html
+http://totalsports.aol.com/stats/bbo/int/20000413/ott.at.buf.game.html
+http://fi.egroups.com/message/stccg-badlands/67
+http://www.fogdog.com/cedroID/ssd3040183315704/nav/stores/books_videos/
+http://xf-bbs.hb.cninfo.net/~socrates/sportold/images/football/_vti_cnf/
+http://cisc.tu-graz.ac.at/igi/lehre/semD_ss99/gruppe3/node10.html
+http://in.egroups.com/message/sfconsim-l/8643
+http://ftp.cc.chuo-u.ac.jp/home/pub/lang/perl/CPAN/modules/by-authors/Karl_Glazebrook/ExtUtils-F77-1.13.readme
+http://ftp.cc.chuo-u.ac.jp/home/pub/lang/perl/CPAN/modules/by-authors/Karl_Glazebrook/PGPLOT-2.17.readme
+http://coe.ier.hit-u.ac.jp/BibEc/data/Papers/wopwobaiu2243.html
+http://coe.ier.hit-u.ac.jp/BibEc/data/Papers/wopwobaiu2386.html
+http://books.hyperlink.co.uk/bookinfo/Travel_Journal/0864427972
+http://dbc.copystar.com.tw/DelphiChat/200001/msg0650.htm
+http://dbc.copystar.com.tw/DelphiChat/200001/msg0655.htm
+http://dbc.copystar.com.tw/DelphiChat/200001/msg0666.htm
+http://dbc.copystar.com.tw/DelphiChat/200001/msg0673.htm
+http://dbc.copystar.com.tw/DelphiChat/200001/msg0681.htm
+http://dbc.copystar.com.tw/DelphiChat/200001/msg0692.htm
+http://www.expage.com/page/cavypigsponser
+http://kernel2.adver.com.tw/Counter/log/kernel2.adver.com.tw/SaveCounter/2000-10-05/13/?S=A
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=210&discrim=214,253
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=2&discrim=247,212,237
+http://wwwtios.cs.utwente.nl/archive/wilyfans/frm01740.html
+http://z-06.land-sbg.gv.at/pressebuero/lpb/unserland/apr00/3.htm
+http://z-06.land-sbg.gv.at/pressebuero/lpb/unserland/apr00/52.htm
+http://gladstone.uoregon.edu/~sola/Stories/
+http://adetti.iscte.pt/RSI/HowTo/Java/jdk1.2.1/docs/guide/2d/api-jpeg/serialized-form.html
+http://ocean.ntou.edu.tw/search*chi/aSloan,+Richard+P.,+jt.+ed./asloan+richard+p/-5,-1,0,E/frameset&F=asloan+irving+j&2,,0
+http://ttzcomputers.subportal.com/sn/Programming/C_and_C___Tools_and_Components/13286.html
+http://ttzcomputers.subportal.com/sn/Programming/C_and_C___Tools_and_Components/1551.html
+http://ftp.uni-stuttgart.de/pub/unix/tools/system/top/m/?N=D
+http://no.egroups.com/message/romtrade/5216
+http://dk.egroups.com/message/Gunsmithing/80
+http://www.msb.malmo.se/search*swe/dMichelsen,+Hans/dmichelsen+hans/-5,-1,0,B/frameset&F=dmichels+robert&1,1
+http://solar.rtd.utk.edu/friends/news/omri/1998/05/980506I.html(opt,mozilla,pc,russian,koi8,default)
+http://www.geocities.co.jp/HeartLand/6163/link8.htm
+http://tucows.austria.com/sync95_size.html
+http://tucows.austria.com/adnload/1082_30337.html
+http://www.hotelboulevard.com/fr/paris/standard/html7752b1d358fd6459ebca66776e896614/sessionLang/ANG/prov/browse/cp/75015/resultatSearch.html
+http://210.178.135.1/netbbs/Bbs.cgi/nhic30872/qry/zka/B2-kB2-o/pno/0/qqo/000A/qqatt/^
+http://210.178.135.1/netbbs/Bbs.cgi/nhic30872/new/pno/0/pno/0/qqo/000A
+http://cometweb01.comet.co.uk/do!tid=20&rtid=2&vsid=700&session=132041&mid=1000&rid=1060&cid=37030&chid=1713&url=eqqLmwlGltt5tkZHljbLqkZHlkrHhlZHdfjKYfkLlkZ5ljjLboZLbplG5ubLZDXLZolLl3l5jbqLlci5XqVLkXsLkao4tloHbmlLoq5
+http://polygraph.ircache.net:8181/http_-2www.webtechs.com/html-val-svc/f-agents.html
+http://www.linux.com/networking/network/development/communications/server/distro/
+http://www.linux.com/networking/network/development/communications/server/competition/
+http://www.linux.com/networking/network/development/communications/server/certification/
+http://www.linux.com/networking/network/development/communications/server/future/
+http://www.linux.com/networking/network/development/communications/server/Updates/
+http://people.freebsd.org/~knu/cgi-bin/cvsweb.cgi/ports/net/epic4/pkg/Attic/
+http://polygraph.ircache.net:8181/mo/mo_links/http_-2www.whowhere.com/tax_cuts.html
+http://www.gov.ie/iveagh/angloirish/bloodysunday/summary4.htm
+http://polygraph.ircache.net:8181/http_-2www.real-e-video.com/ftp_-2ftp.mpgn.com/Gaming/ADND/Worlds/BirthRight/MailingListArchive/Contents.htm
+http://www.centc251.org/forums/aca-1/dispatch.cgi/isowg4/showNextUnseen/fol/100001/1323398
+http://www.centc251.org/forums/aca-1/dispatch.cgi/isowg4/folderFrame/100008/0/def/1323639
+http://user.alpha.co.kr/~selly/profile/main2.htm
+http://polygraph.ircache.net:8181/company/http_-2www.aaainvestments.com/http_-2triad.cyberserv.com/http_-2207.90.134.3/miami/
+http://ring.htcn.ne.jp/pub/FreeBSD/FreeBSD-current/ports/archivers/zip/
+http://www.medoc-ias.u-psud.fr:81/synoptic/gif/950902/?S=A
+http://in.egroups.com/message/GQRP/975
+http://idgnow.uol.com.br/idgnow/pcnews/2000/07/0046
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/kdebase/po/Attic/kdmconfig.pot?only_with_tag=beta1-0_2
+http://us.mandrakesoft.com/cgi-bin/cvsweb.cgi/kdebase/po/Attic/kwm.pot?only_with_tag=beta1-0_2
+http://lists.omnipotent.net/mysql/199912/msg02189.html
+http://kyoto.cool.ne.jp/ryou_1125/lmax/list2.html
+http://www.infodog.com/RESULTS/1998092302/1998092302800.HTM
+http://www.infodog.com/RESULTS/1998092302/1998092302575.HTM
+http://bedandbreakfast.com/bbc/p618230.asp
+http://solaris.license.virginia.edu/os_product_patches/patches/5.5.1/103640-28/SUNWscpu/
+http://www.secinfo.com/d1Z36p.5n.htm
+http://cn.egroups.com/messages/conscious_creation/2087
+http://www.brio.de/BRIO.catalog/39fdb4fb08541c02273fd472aa7806a2/UserTemplate/13
+http://www.chaos.dk/sexriddle/o/m/e/z/
+http://cgi.tbs.co.jp/cdtv/songdb/song1897-j.html
+http://www.niwl.se/wais/new/12/12116.htm
+http://bsdweb.pasta.cs.uit.no/bsdweb.cgi/~checkout~/pkgsrc/editors/vim-xaw/pkg/?sortby=log
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=boguerait&l=fr
+http://www.medbulletin.com/scripts/medscape/jobsbystate.pl/diima00001/ND
+http://ttz.soyou.edu.cn/tgyd/item/2000-05-31/3214.html
+http://ttz.soyou.edu.cn/tgyd/item/2000-05-25/2973.html
+http://ttz.soyou.edu.cn/tgyd/item/2000-05-23/2825.html
+http://javatest.a-net.nl/servlet/pedit.Main/http://salon.com/tech/feature/2000/02/25/chatscan/
+http://javatest.a-net.nl/servlet/pedit.Main/http://www.wired.com/news/news/technology/story/20734.html
+http://www.jps.net/fehlberg/diem9.html
+http://chellobe.linux.tucows.com/x11html/adnload/9798_3876.html
+http://chellobe.linux.tucows.com/x11html/preview/58190.html
+http://internet.exit.de/akpolitik/Extern.htm
+http://www.launch.com/music/albumpage/pvn_content/0,5258,163242_track,00.html
+http://merumo.ne.jp/backno/i/00005163/20001001060103_024859.html
+http://ftpsearch.belnet.be/mirrors/ftp.isc.org/pub/usenet/control/bc/?N=D
+http://www-lehre.inf.uos.de/manuals/jdk1.2/docs/api/javax/swing/text/html/parser/class-use/Element.html
+http://ftp.tku.edu.tw/OS/FreeBSD/ports/biology/deft/distinfo
+http://javatest.a-net.nl/servlet/pedit.Main/http://www.cavejunction.com/phones/gower1.html
+http://javatest.a-net.nl/servlet/pedit.Main/http://www.cavejunction.com/phones/contel1.html
+http://www.allkorea.co.jp/cgi-bin/allkorea.front/972959966349/Catalog/1000002
+http://yp.gates96.com/5/82/41/1.html
+http://yp.gates96.com/5/82/41/52.html
+http://yp.gates96.com/5/82/41/59.html
+http://yp.gates96.com/5/82/42/40.html
+http://yp.gates96.com/5/82/42/73.html
+http://yp.gates96.com/5/82/43/4.html
+http://yp.gates96.com/5/82/43/20.html
+http://yp.gates96.com/5/82/44/60.html
+http://yp.gates96.com/5/82/44/95.html
+http://yp.gates96.com/5/82/45/36.html
+http://yp.gates96.com/5/82/45/43.html
+http://yp.gates96.com/5/82/45/90.html
+http://yp.gates96.com/5/82/46/37.html
+http://yp.gates96.com/5/82/46/83.html
+http://yp.gates96.com/5/82/47/22.html
+http://yp.gates96.com/5/82/47/53.html
+http://yp.gates96.com/5/82/48/8.html
+http://yp.gates96.com/5/82/48/23.html
+http://yp.gates96.com/5/82/48/41.html
+http://yp.gates96.com/5/82/48/76.html
+http://yp.gates96.com/5/82/49/5.html
+http://yp.gates96.com/5/82/49/22.html
+http://yp.gates96.com/5/82/49/37.html
+http://yp.gates96.com/5/82/49/39.html
+http://yp.gates96.com/5/82/49/65.html
+http://yp.gates96.com/5/82/49/90.html
+http://www.mirror.kiev.ua:8084/paper/1998/35/1251/power.htm
+http://www.science.uva.nl/pub/NetBSD/NetBSD-current/pkgsrc/textproc/html/Makefile
+http://www.fiss.at/1Root/Kontinent/6/Staat/7/Bundesland/16/Ort/708/Infrastruktur/7435/Homepage/homepage...1.html
+http://linux.tnc.edu.tw/CPAN/authors/id/C/CH/CHOGAN/Apache-SetWWWTheme-1.02.readme
+http://linux.tnc.edu.tw/CPAN/authors/id/C/CH/CHOGAN/Apache-SetWWWTheme-1.04.readme
+http://linux.tnc.edu.tw/CPAN/authors/id/C/CH/CHOGAN/Apache-SetWWWTheme-1.05.readme
+http://wufs.wustl.edu/vlander/vl_0002/browse/html/B0XX/22b090b4.htm
+http://www.dnet.org/My_Locality/View_Statement.dnet/OH/43230-1863&SubjectItemID=6406&IssueID=47541&ElectionActivityID=4443&SubjectHolder=3462&type=Office&debate=yes
+http://members.tripod.co.jp/suguruE/_private/
+http://members.tripod.lycos.nl/Kreeklaan/id19_cf.htm
+http://forums.multimania.fr/general/login/login.phtml?_login=%2Flire%2Fjeuxvideospro%2Findex.phtml%3Fcollapse%3D1
+http://excite.de.netscape.com/jobs/katalog/30434
+http://excite.de.netscape.com/jobs/katalog/27370
+http://excite.de.netscape.com/jobs/katalog/127
+http://yp.gates96.com/2/54/20/79.html
+http://yp.gates96.com/2/54/21/27.html
+http://yp.gates96.com/2/54/22/14.html
+http://yp.gates96.com/2/54/22/48.html
+http://yp.gates96.com/2/54/22/78.html
+http://yp.gates96.com/2/54/23/20.html
+http://yp.gates96.com/2/54/23/62.html
+http://yp.gates96.com/2/54/23/69.html
+http://yp.gates96.com/2/54/24/1.html
+http://yp.gates96.com/2/54/24/61.html
+http://yp.gates96.com/2/54/24/95.html
+http://yp.gates96.com/2/54/25/2.html
+http://yp.gates96.com/2/54/25/16.html
+http://yp.gates96.com/2/54/25/53.html
+http://yp.gates96.com/2/54/25/67.html
+http://yp.gates96.com/2/54/25/94.html
+http://yp.gates96.com/2/54/26/3.html
+http://yp.gates96.com/2/54/26/30.html
+http://yp.gates96.com/2/54/26/65.html
+http://yp.gates96.com/2/54/27/31.html
+http://yp.gates96.com/2/54/27/41.html
+http://yp.gates96.com/2/54/27/53.html
+http://yp.gates96.com/2/54/27/71.html
+http://yp.gates96.com/2/54/27/79.html
+http://yp.gates96.com/2/54/27/80.html
+http://yp.gates96.com/2/54/28/13.html
+http://yp.gates96.com/2/54/28/14.html
+http://yp.gates96.com/2/54/28/24.html
+http://yp.gates96.com/2/54/28/34.html
+http://yp.gates96.com/2/54/28/96.html
+http://yp.gates96.com/2/54/29/49.html
+http://ftp.sunet.se/pub/NT/mirror-microsoft/KB/Q134/3/40.TXT
+http://members.tripod.com/joellogan/_cranedisc/000001d9.htm
+http://members.tripod.com/joellogan/_cranedisc/000001cd.htm
+http://www.ualberta.ca/CNS/RESEARCH/Software/SAS/vms/z-inf-zd.htm
+http://www1.galaxy.com/galaxy/Leisure-and-Recreation/Games/Computer-Games/Titles/Virtual-Reality/Golf.html
+http://www1.galaxy.com/galaxy/Leisure-and-Recreation/Games/Computer-Games/Titles/Virtual-Reality/Red-Planet.html
+http://www.uni-duesseldorf.de/ftp/ftp/software/opt/zlib-1.1.2/?N=D
+http://acbanks.know-where.com/acbanks/cgi/selection?place=Cavecreek&state=AZ
+http://yp.gates96.com/10/26/70/49.html
+http://yp.gates96.com/10/26/70/83.html
+http://yp.gates96.com/10/26/72/40.html
+http://yp.gates96.com/10/26/74/89.html
+http://yp.gates96.com/10/26/75/15.html
+http://yp.gates96.com/10/26/75/19.html
+http://yp.gates96.com/10/26/76/87.html
+http://yp.gates96.com/10/26/78/18.html
+http://yp.gates96.com/10/26/78/76.html
+http://yp.gates96.com/10/26/78/78.html
+http://yp.gates96.com/10/26/78/81.html
+http://cpan.nitco.com/modules/by-module/Devel/ADESC/Pod-DocBook-0.03.readme
+http://www2.el-mundo.es/nuevaeconomia/2000/NE047/NE047-03b.html
+http://www.familyeducation.com/whatworks/inappr_material/entry/1,2549,1-10119-1948-3469,00.html
+http://ftp.nodomainname.net/pub/linux/daemons/raid/beta/
+http://192.80.57.161/corp/press/vannet.html
+http://digilander.iol.it/mirkodeli/Stagioni/CI6_index.html
+http://www.world-of-webs.de/magdeburg-in-bildern/_inhalt/_statnif/rechts/035.htm
+http://ftpsearch.belnet.be/mirrors/src.doc.ic.ac.uk/usenet/usenet-by-hierarchy/rec/travel/?D=A
+http://mirrortucows.technet.it/winme/netmiscme_rating.html
+http://my.egroups.com/message/imperiumlarp/3148
+http://ep.com/js/about/c7857/b0/34551.html
+http://webcrawler-sports.excite.com/ncaab/matchup/pafmax/
+http://www2.dbusiness.com/Quotes/1,1125,MSP_CORE,00.html?Ticker=CORE
+http://tucows.wlink.com.np/regist95_size.html
+http://www.babyheirlooms.com/catalog/htmlos.cat/041162.1.5960744054
+http://www.v2music.com/Scripts/WebObjects-ISAPI.dll/V2_New_Publisher.woa/71113000008423000000947720000021551/Labels.wo/168310000011551/1.0.1/3/Webobjects1
+http://www.v2music.com/Scripts/WebObjects-ISAPI.dll/V2_New_Publisher.woa/71113000008423000000947720000021551/Labels.wo/168310000011551/1.1.3.0.0/3/Webobjects1
+http://www.adcentral.com/cgi-bin/w3com/pws/adsites/vNhIXgVh_sji0rjcKc_GbuSlgBaEnCmKXU4ARmeefaqktCE3zwLsoXKDK_dlzoBzk2Ygr2cAuqN51PKOA0JxjzLEpPe-kic9TtvUJMbXG9Dlw8SggmHugQpwzjo-NiuofbUz4obq
+http://ring.omp.ad.jp/archives/NetBSD/NetBSD-current/src/distrib/i386/floppies/ramdisk-big/Makefile
+http://unofficial.capital.edu/students/alittle/
+http://213.36.119.69/do/session/153005/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/reserver/promotions/promo9.html
+http://213.36.119.69/do/session/153005/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/GB_EN/
+http://www.riello-hamburg.de/mSerieRSBLU_130_465kw.htm
+http://tucows.knoware.nl/winnt/filesplitnt_license.html
+http://www.kaos.dk/sex-riddle/k/a/k/i/n/h/b/b/
+http://www.kaos.dk/sex-riddle/k/a/k/i/n/h/b/c/
+http://caller-times.com/1999/july/13/today/national/3143.html
+http://news.fm365.com/jiaoyu/20000804/113896.htm
+http://variety.studiostore.com/browse/ILOVELUCY/CAP/b.FAVORITES%20NOSTALGI%20CLASTV%20ILOVELUCY/s.qyPsT2fz
+http://www.ferien-immobilien.de/bayern/ingolstadt/Verkauf/Gemeinsam/Immolink/3d-service/Private-IB/Startseite/Gemeinsam/vertriebspartner.htm
+http://jefferson.village.virginia.edu/wax/japanese/0front/cd/1/1a2a9a2.html
+http://space.tin.it/scuola/ermenegh/thewall/il2.htm
+http://www.maasvlakte-cam.nl/webcams/17/kremlin__moscou__russia/2000/02/29/?D=A
+http://pub17.ezboard.com/fecilordsoflightgeneral.showMessage?topicID=211.topic
+http://pub17.ezboard.com/fecilordsoflightgeneral.showMessage?topicID=214.topic
+http://pub17.ezboard.com/fecilordsoflightgeneral.showMessage?topicID=210.topic
+http://www.kaos.dk/sexriddle/x/u/e/s/p/
+http://www.kaos.dk/sexriddle/x/u/e/s/q/
+http://amc.hollywood.com/maltin/k/kellysheroes-1970.htm
+http://amc.hollywood.com/maltin/k/kidsarealrightthe-1979.htm
+http://amc.hollywood.com/maltin/k/killingofsistergeorgethe-1968.htm
+http://amc.hollywood.com/maltin/k/kingandcountry-1964.htm
+http://amc.hollywood.com/maltin/k/kinglear-1987.htm
+http://amc.hollywood.com/maltin/k/kingofthezombies-1941.htm
+http://amc.hollywood.com/maltin/k/kingqueenknave-1972.htm
+http://amc.hollywood.com/maltin/k/kissthe-1988.htm
+http://www.egroups.com/login.cgi?login_target=%2Fgroup%2Ft-ida
+http://polygraph.ircache.net:8181/faculty/http_-2www.stopwaste.org/freecontent.html
+http://kutschen.de/Schoner/literature/Literatur/models/collections/
+http://www.incestpornstories.com/cum-sex-pics/anal-sexone-night-stand/big-bonedpleasantly-plump/smallwomen/{hardcorelink}
+http://www.nytimes.com/library/financial/102897market-turmoil.html
+http://polygraph.ircache.net:8181/services/define/http_-2www.microsoft.com/ie/http_-2www.ci.alameda.ca.us/main_left.html
+http://polygraph.ircache.net:8181/services/define/http_-2www.microsoft.com/ie/http_-2www.ci.alameda.ca.us/dream.htm
+http://www.chiayi.gob.tw/
+http://www.maas.ccr.it/cgi-win/hiweb.exe/a17/d77/b77,c,4d,51,51,df1,df1,,4e,2b62,4d,4e,2b62,,
+http://citeseer.nj.nec.com/cidcontext/6361
+http://citeseer.nj.nec.com/cidcontext/6456
+http://utenti.tripod.it/Psychozine/Grunge/Creed_MyOwnPrison.htm
+http://tucows.multiweb.net/winme/adnload/138210_30315.html
+http://tucows.multiweb.net/winme/adnload/138190_29551.html
+http://tucows.multiweb.net/winme/adnload/138218_29576.html
+http://tucows.multiweb.net/winme/preview/138219.html
+http://playsky.home.chinaren.com/star_region/11.htm
+http://tucows.phnet.fi/winme/adnload/137614_29054.html
+http://www.fortunecity.com/millennium/blyton/118/www.bih.net.ba/~sda
+http://www11.informatik.tu-muenchen.de/lehre/lectures/ws2000-01/hypermedia/extension/html-kurz/hm2.2.4.2-navigation.html
+http://ads.puntopartenza.com/cgi-bin/redirect.cgi/31033737
+http://www.eud.com/1997/03/20/20324A.shtml
+http://ftp.net.uni-c.dk/pub/linux/mandrake/i586/Mandrake/mdkinst/usr/share/locale/gl/?N=D
+http://no.sport.yahoo.com/s/snowboard-1.html
+http://www.egroups.com/login.cgi?login_target=%2Fmessages%2Fshamanism%2F1311
+http://yp.gates96.com/5/82/70/13.html
+http://yp.gates96.com/5/82/70/74.html
+http://yp.gates96.com/5/82/71/30.html
+http://yp.gates96.com/5/82/71/44.html
+http://yp.gates96.com/5/82/72/22.html
+http://yp.gates96.com/5/82/72/72.html
+http://yp.gates96.com/5/82/72/88.html
+http://yp.gates96.com/5/82/73/60.html
+http://yp.gates96.com/5/82/73/79.html
+http://yp.gates96.com/5/82/74/21.html
+http://yp.gates96.com/5/82/74/59.html
+http://yp.gates96.com/5/82/74/62.html
+http://yp.gates96.com/5/82/74/75.html
+http://yp.gates96.com/5/82/74/78.html
+http://yp.gates96.com/5/82/75/30.html
+http://yp.gates96.com/5/82/75/32.html
+http://yp.gates96.com/5/82/75/82.html
+http://yp.gates96.com/5/82/76/16.html
+http://yp.gates96.com/5/82/76/43.html
+http://yp.gates96.com/5/82/76/72.html
+http://yp.gates96.com/5/82/77/48.html
+http://yp.gates96.com/5/82/77/99.html
+http://yp.gates96.com/5/82/78/73.html
+http://yp.gates96.com/5/82/79/28.html
+http://yp.gates96.com/5/82/79/70.html
+http://yp.gates96.com/5/82/79/83.html
+http://polygraph.ircache.net:8181/http_-2www.microsoft.com/ie/http_-2www.petrophysics.com/http_-2www.uio.no/~thomas/lists/info.html
+http://www.munster-express.ie/000623/sports1.htm
+http://cisne.sim.ucm.es/search*spi/aThiollier,+FranÃ\83Â\83Ã\82§ois-JoÃ\83Â\83Ã\82«l,+int./athiollier+francois+joel+int/-5,-1,0,B/marc&F=athion+soriano+molla+dolores&2,,2
+http://www.zjdaily.com.cn/gb/2000/10/05/zjrb0625/guoji/6.htm
+http://commerce.was-inc.com/cgi-bin/abtwsam.dll/LbkWebCommerceStoreCategories-BBC70A38_9815_E7A26CDF19A4AB167DD4B69EFB5B17FC
+http://commerce.was-inc.com/cgi-bin/abtwsam.dll/LbkWebCommerceUserProfile-BBC70A38_9815_E7A26CDF19A4AB167DD4B69EFB5B17FC
+http://www.shopworks.com/tools/index.cfm/action/search/userid/0003875B-2E5B-19FE-AF65010C0A0A8CF2
+http://www.doofpot.nl/~lists/bugtraq/October-99/frm00087.html
+http://shop.citde.net/b79923.htm
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=divinizzarono&l=it
+http://pub8.ezboard.com/fwrestlecarwwf.showAddReplyScreenFromWeb?topicID=38.topic
+http://amrr.com/agents/contact.html?Agents_id=4046
+http://www.intellicast.com/LocalWeather/World/UnitedStates/Southeast/NorthCarolina/CarolinaBeach/RAINcast/d1_12/bannerAd.shtml
+http://www.ferien-immobilien.de/schleswig-holstein/nordfriesland/Verkauf/Gemeinsam/versicherungen/gebaeude/Allgemeine-IB/IIM-Teil/Startseite/Gemeinsam/Inserieren/inserieren.htm
+http://www.ferien-immobilien.de/schleswig-holstein/nordfriesland/Verkauf/Gemeinsam/versicherungen/gebaeude/Allgemeine-IB/IIM-Teil/Startseite/Gemeinsam/feedback.html
+http://de.excite.com/jobs/katalog/10349
+http://pub16.ezboard.com/frealitycheck95307youadoreus.showAddReplyScreenFromWeb?topicID=33.topic
+http://www.maas.ccr.it/cgi-win/hiweb.exe/a17/d2424/b77,e,4d,51,51,df1,df1,,978,,51,978,815,,51,815,
+http://dk.egroups.com/message/noholdsbarred/2138
+http://kr.news.yahoo.com/headlines/so/20001029/hankook/2000102919513187338.html
+http://www.buybuddy.com/sleuth/27/1/11002/508910/
+http://yp.gates96.com/13/95/50/10.html
+http://yp.gates96.com/13/95/50/47.html
+http://yp.gates96.com/13/95/51/16.html
+http://yp.gates96.com/13/95/51/17.html
+http://yp.gates96.com/13/95/51/21.html
+http://yp.gates96.com/13/95/51/76.html
+http://yp.gates96.com/13/95/53/5.html
+http://yp.gates96.com/13/95/54/17.html
+http://yp.gates96.com/13/95/54/44.html
+http://yp.gates96.com/13/95/54/67.html
+http://yp.gates96.com/13/95/54/80.html
+http://yp.gates96.com/13/95/55/67.html
+http://yp.gates96.com/13/95/56/15.html
+http://yp.gates96.com/13/95/56/91.html
+http://yp.gates96.com/13/95/57/9.html
+http://yp.gates96.com/13/95/57/12.html
+http://yp.gates96.com/13/95/57/24.html
+http://yp.gates96.com/13/95/57/30.html
+http://yp.gates96.com/13/95/57/46.html
+http://yp.gates96.com/13/95/58/38.html
+http://yp.gates96.com/13/95/58/52.html
+http://yp.gates96.com/13/95/58/80.html
+http://yp.gates96.com/13/95/59/40.html
+http://yp.gates96.com/13/95/59/78.html
+http://ftp.net.uni-c.dk/pub/linux/mandrake/i586/Mandrake/mdkinst/usr/share/locale/gv/?S=A
+http://home.swipnet.se/~w-10458/sksida.htm
+http://www.irishnews.com/k_archive/260799/nnews14.html
+http://dennou-q.geo.kyushu-u.ac.jp/library/Linux/debian-jp/dists/potato-jp/contrib/binary-all/admin/?M=A
+http://ayasii.virtualspace.net/html/1104/11041141_syuuei_yosimi008.htm
+http://ayasii.virtualspace.net/html/1104/11041104_nakamura_yuma_2_027.htm
+http://kikakusvr3.city.yokohama.jp/yhspot/ysc/prelaunch.html
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=0,1-20,0-9,1-9,2
+http://209.52.189.2/discussion.cfm/disco_music/7738/79749
+http://www.du-et.net/cgi/mail.cgi?NickName=coota
+http://ustlib.ust.hk/search*chi/a%7B214c7d%7D%7B213837%7D%7B213c44%7D%7B213779%7D%7B214267%7D%7B21586d%7D%7B21515b%7D%7B21517c%7D%7B213966%7D/a{214c7d}{213837}{213c44}{213779}{214267}{21586d}{21515b}{21517c}{213966}/7,-1,0,B/browse
+http://user.alpha.co.kr/~backspin/CGI-BIN/upload/files/
+http://194.174.50.23/cgi-bin/FisRun/InsertExhibitorIntoNotebook/1/interpack99/e/1217
+http://www.paxcapital.com/news/datacenter/200010/27/20001027180508_01.shtml
+http://www.paxcapital.com/news/datacenter/200010/27/20001027175828_07.shtml
+http://www.paxcapital.com/news/datacenter/200010/27/20001027173309_53.shtml
+http://www.paxcapital.com/news/datacenter/200010/27/20001027165004_52.shtml
+http://genforum.genealogy.com/cgi-bin/print.cgi?lantz::325.html
+http://mirror.cc.utsunomiya-u.ac.jp/mirror/FreeBSD/ports/alpha/packages-current/x11-toolkits/?D=A
+http://hotop.on.net.cn/diguo/club/disp.asp?owner=A205&ID=914
+http://www.babyheirlooms.com/catalog/htmlos.cat/041137.1.3501106310
+http://debian.linux.org.tw/debian/dists/frozen/non-free/binary-m68k/mail/?N=D
+http://cafe5.daum.net/Cafe-bin/Cafe.cgi/member?cafe=LOTTEcleaning
+http://www-d0.fnal.gov/cgi-bin/cvsweb.cgi/root_gui/data/?sortby=date
+http://www.concentric.net/~Psaros/DbzUncensored/editorial/edit06-07-98.html
+http://www.jobvillage.com/channel/jobs/travel/travel_guide/b.4897.g.5093.html
+http://www.jobvillage.com/channel/jobs/travel/travel_guide/b.4897.g.5070.html
+http://www.cricket.org/link_to_database/ARCHIVE/1999/OTHERS+ICC/NL_LOCAL/EERSTEKL/VCC_ASIAN-SHAH_EERSTEKL_16MAY1999.html
+http://health.phinfo.sc.cn/navigator/illness_treatment/diseases_conditions/bone_diseases/spinal_column_injury/default.htm
+http://cn.egroups.com/message/dfwscan/1412
+http://www.babyheirlooms.com/catalog/htmlos.cat/001255.1.1999922108
+http://ibm1.cicrp.jussieu.fr/ibmc/classref/ref/UFullStopNumber_DSC.htm
+http://pda.tucows.fi/palm/adnload/33651_21862.html
+http://www.fogdog.com/cedroID/ssd3040183330232/nav/products/nhl/chicago_blackhawks/fan/gender/fashion_polo_shirts/
+http://www.fogdog.com/cedroID/ssd3040183330232/nav/products/nhl/chicago_blackhawks/fan/gender/nylon_jackets/
+http://www.5a8.com/book/wg/zpj/d/delaisai/mgbj/004.htm
+http://www.5a8.com/book/wg/zpj/d/delaisai/mgbj/050.htm
+http://jars.developer.com//classes/jresout.cgi?resource=1133
+http://dwp.bigplanet.com/billbritton/files/edit.nhtml
+http://members.tripod.co.jp/snow4/?D=A
+http://www.lanoticia.com.ni/cronologico/2000/julio/15sabado/capital/capital5.html
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/151/1996/4/0/870960/
+http://mayu.sourceforge.net/cgi-bin/nph-ml.cgi/000/http/www.geocrawler.com/archives/3/151/1996/4/0/870950/
+http://ftp.ccu.edu.tw/pub/packages/dns/bind/src/8.1.1/
+http://www.chez.com/photographies/photos/paysage/page8.htm
+http://www.ayto-malaga.es/Organismos/Urbanismo/PGMOM/Hojas/calificacion/3/47/34734.htm
+http://www.symatrixinc.com/website/website.nsf/0/3e40df86fb357cd5882568720079613f!OpenDocument&ExpandSection=3,24,5,18
+http://www.symatrixinc.com/website/website.nsf/0/3e40df86fb357cd5882568720079613f!OpenDocument&ExpandSection=9,24,5,18
+http://variety.studiostore.com/browse/STARWARSTRIL/PHOTO/b.MOVIES%20STARWARSSAGA%20STARWARSTRIL/s.5FhZToe4
+http://www.stud.ntnu.no/~kjonigse/pod/
+http://eastday.com/epublish/gb/paper10/20001025/class001000011/hwz225792.htm
+http://eastday.com/epublish/gb/paper10/20001025/class001000011/hwz225253.htm
+http://www.jamba.de/KNet/_KNet-KdS8j1-IHd-13g8y/browse.de/node.0/cergpnwyt
+http://www.la-verdad.com/pg000828/suscr/primera.htm
+http://www.centc251.org/forums/aca-1/dispatch.cgi/hsi/listUnseen/fol/100020/20,0/1338881
+http://ftp.du.se/disk4/FreeBSD/ports/ports/japanese/libicq/pkg-comment
+http://www.geocities.com/SunsetStrip/Towers/2395/
+http://www.geocities.com/joanna_luo
+http://www.geocities.com/eric_wang_tafe
+http://www.geocities.com/shsugiharto
+http://wynnsystems.com/79I_5ase/seek/modifyUser.html
+http://www.uk.cricket.org/link_to_database/INTERACTIVE/REVIEWS/BOOKS/barry14.html
+http://perso.wanadoo.fr/alain.falgas/poesie1.htm
+http://www.linux.com/networking/network/windows_nt/support/tools/SAP/
+http://www.rdnet.nl/provstaten1999/491ps.html
+http://www.thisislancashire.co.uk/lancashire/archive/1998/03/19/FEATURES3VQ.html
+http://myhome.naver.com/myclass46
+http://www.bride.ru/htcgi/ladies/in-26-30/index3.html
+http://www.internet-verzeichnis.de/branchen/schuhreparaturen/nordrhein-westfalen/
+http://dk.egroups.com/post/SonyMavica?act=reply&messageNum=3370
+http://www.sneezy.org/Databases/Composers/Instrumentation/008889.html
+http://www.sneezy.org/Databases/Composers/Instrumentation/009161.html
+http://fatema2.math.nat.tu-bs.de/doc/sdb/de/html/keylist.LARGEEBDA.html
+http://ssb.no/kommuner/hoyre_side.cgi?region=1931
+http://www.egroups.com/subscribe/mentemalata
+http://www.debian.org.cn/Bugs/db/67/67056-b.html
+http://dk.egroups.com/message/ssrdistribution/775?source=1
+http://link.fastpartner.com/do/session/600429/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/shopnett.php
+http://ftp.uk.debian.org/debian/dists/stable/main/binary-arm/text/?D=A
+http://www.bemi-immobilien.de/IIM-Teil/Startseite/Top-Darlehens-Konditionen/Gemeinsam/3d-service/Startseite/Gemeinsam/erreichenPartner/Top-Darlehens-Konditionen/anforderungsformular.htm
+http://www.fujian-window.com/Fujian_w/news/mdrb/000816t/1_4.html
+http://scholar.lib.vt.edu/VA-news/WDBJ-7/script_archives/98/0798/070498/?D=A
+http://polygraph.ircache.net:8181/services/define/html/President.asp
+http://old-maps.co.uk/10lancs191/HTML/nav_19034001g.htm
+http://www.hanter21.co.kr/NetBBS/Bbs.dll/prdata/lst/qqa/f/qqo/000D/zka/B2-kB2-r
+http://w3.webtourist.net/travel/europe/italy/milan/quarkallsuites.htm
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=9,5+0,0-9,6-0,1
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=brillantant&l=fr
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=brillantais&l=fr
+http://www.mathquest.com/~sarah/HTMLthreads/geopre.descriptions.html
+http://www.retrobytes.org/classiccmp/9706/msg00827.html
+http://www.retrobytes.org/classiccmp/9706/msg01408.html
+http://www.rdnet.nl/provstaten1999/552ps.html
+http://retailer.gocollect.com/do/session/1912828/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/checkout/shopping_cart.asp
+http://retailer.gocollect.com/do/session/1912828/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/exclusives/limited_editions.asp
+http://retailer.gocollect.com/do/session/1912828/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/company_info/privacy_policy.asp
+http://de.news.yahoo.com/000322/36/nfqj.html
+http://www.kl.gz.cn/~cco/FUNA022K.htm
+http://www.launch.com/music/artistpage/pvn_content/0,5219,1013738_videos,00.html
+http://www14.freeweb.ne.jp/play/kiryuus/keith-burn1-end.htm
+http://variety.studiostore.com/help/b.MOVIES%20STARWARSSAGA%20STARWARSTRIL/s.BmesFhV7
+http://biblioteca.upv.es/bib/doc/doc_siglibros/1828105/26/25/////MLTPAID/Materia%20Lengua%20inglesa%20técnica:%20254/V
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/_AhIPkFr0_eq7P6TUMbkQGJgpHJOXqtNLZQ55qFmeZARJaJUKHP9RBX3tPWaLEWVLZ_-PAErnbukTTJzs-x0hew4G_r3S85M8fDFaJcIVi3EA4TxNjTbbGIaSLhr8VdNICuBwhPmgZEt662B
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/IxhI6dPotFAZDugwPbV2pjvsgvIvAP-oFtIZfMptEKMo48cUO8RmvG3Akuk2tktzM_RYBY3yIQE6nl7I2moLEV_nScO7wTfWpFfPR7LHZ3ntJxKS8-a_IukWT4q_o6mjhGw8SSwm
+http://www.rge.com/pub/languages/perl/clpa/1995-11/171
+http://www.rge.com/pub/languages/perl/clpa/1995-11/186
+http://www.newmgm.com/cgi-bin/c2k/title_talent.html&id=146091&title_star=FOURFEAT
+http://www.koreaweekly.co.kr/entertain/book/200009/en20000922185938E701133.htm
+http://www.koreaweekly.co.kr/entertain/book/200008/en20000824183337E701112.htm
+http://www.genome.wustl.edu:8021/pub/gsc10/nci/wl/wl72/?N=D
+http://yp.gates96.com/13/50/70/33.html
+http://yp.gates96.com/13/50/70/36.html
+http://yp.gates96.com/13/50/70/53.html
+http://yp.gates96.com/13/50/71/74.html
+http://yp.gates96.com/13/50/72/13.html
+http://yp.gates96.com/13/50/72/17.html
+http://yp.gates96.com/13/50/72/83.html
+http://yp.gates96.com/13/50/73/48.html
+http://yp.gates96.com/13/50/73/79.html
+http://yp.gates96.com/13/50/73/96.html
+http://yp.gates96.com/13/50/74/14.html
+http://yp.gates96.com/13/50/74/57.html
+http://yp.gates96.com/13/50/75/13.html
+http://yp.gates96.com/13/50/75/19.html
+http://yp.gates96.com/13/50/75/30.html
+http://yp.gates96.com/13/50/75/42.html
+http://yp.gates96.com/13/50/75/53.html
+http://yp.gates96.com/13/50/75/90.html
+http://yp.gates96.com/13/50/77/45.html
+http://yp.gates96.com/13/50/77/51.html
+http://yp.gates96.com/13/50/77/79.html
+http://yp.gates96.com/13/50/78/12.html
+http://yp.gates96.com/13/50/78/47.html
+http://yp.gates96.com/13/50/78/69.html
+http://yp.gates96.com/13/50/78/96.html
+http://www.tel.de/s/M/MSS.htm
+http://linux.usu.edu/LDP/LDP/LG/issue23/shoham/node4.html
+http://www.monaco.gouv.mc/dataweb/gouvmc.nsf/(NewsActu)/d28eaee29b3287d4c1256905004e1ef1!OpenDocument&ExpandSection=9,3,10.1,7,10.4,10.2,5,8,4
+http://fi.egroups.com/post/romtrade?act=reply&messageNum=5198
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/erhIHCd-6X--WwWIQBR9tYYraJWo8ugur0GyAl8pg21sE-lotAURKodv9HAYnRuTT4ZM0aCKsA5ZVLlq8sgiFNqA4DyAY_GVTyPIEARrzArj8JrWabVCSpg03afQ_Xg3DaCQA17080y7T4EZ
+http://oneplace.adbureau.net/accipiter/adclick/site=ONEPLACE/area=INDEX/POSITION=BLOCK_1/AAMSZ=120x90/ACC_RANDOM=619055616855
+http://cafe6.daum.net/Cafe-bin/Bbs.cgi/MyLoveNYpds/qry/zka/B2-kB23m/qqatt/^
+http://cafe6.daum.net/Cafe-bin/Bbs.cgi/MyLoveNYpds/qry/zka/B2-kB2-s/qqatt/^
+http://sas.uoregon.edu/sashtml/proc/z0292518.htm
+http://www02.geocities.co.jp/PowderRoom-Rose/1346/flower02image.html
+http://www02.geocities.co.jp/PowderRoom-Rose/1346/sozaiheart2.html
+http://www.jamba.de/KNet/_KNet-sXN8j1-9Hd-13ej3/admLogin.de/node.0/cdn3r3qy3
+http://iccardreader.co.kr/
+http://online.linux.tucows.com/conhtml/ser_irc_size.html
+http://www.fogdog.com/cedroID/ssd3040183339940/nav/products/winter_sports/1b/bibs/
+http://www.fogdog.com/cedroID/ssd3040183339940/nav/products/winter_sports/1c/jackets/
+http://www.fogdog.com/cedroID/ssd3040183339940/nav/products/winter_sports/1d/heavyweight_tops/
+http://www.affiliate.hpstore.hp.co.uk/do/session/380883/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/assistance/entry.asp
+http://www.kaos.dk/sex-riddle/k/a/k/i/l/y/t/c/
+http://www.kaos.dk/sex-riddle/k/a/k/i/l/y/t/o/
+http://ftp1.se.debian.org/debian/dists/stable/main/disks-alpha/2.2.8-2000-03-08/jensen/
+http://213.36.119.69/do/session/153006/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/FR/contact/recrute.htm
+http://www10.freeweb.ne.jp/photo/myukun2/cosplay/000130/0130_40.htm
+http://l-infonet.phkk.fi/fi/TIETOPALVELUT/JULKINEN+HALLINTO/tiedonhaku/artikkelit/hakupalvelut/l%E4%E4ketiede/tietokannat/
+http://202.109.72.57/article/20000903/67099.htm
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/5xhIsrJ5LBhn_gBogN2-VgQ1DA6WvBlLMjSoxYeQAJ1ig69sK1i1DhQ5hA3iOw7y6Wb_HDA2rkG5aJy9DrUMZxD31cyUqEqg7LeZ3pssb70DsyPc1sGCTVIRFBz1Nb_1ikEcJ3ds
+http://ftp.gwdg.de/pub/misc/standards/infomagic/nist/oiw/agreemnt/read_me.txt
+http://linuxberg.arrakis.es/conhtml/adnload/8894_17109.html
+http://ring.toyama-ix.net/archives/pc/winsock-l/WWW-Browsers/Plug-In/ppp16124.txt
+http://opac.lib.ntnu.edu.tw/search*chi/++ftlist/bp20040288/-5,-1,0,B/frameset&F=bp20040286&1,1
+http://ftp.darenet.dk/tucows/winme/adnload/137475_28966.html
+http://ftp.darenet.dk/tucows/winme/adnload/137525_29009.html
+http://elib.zib.de/pub/UserHome/Mueller/Course/Tutorial/Postscript/US/?M=A
+http://greenpeace.lu/Admin/usage/weekly/1999/01/03/
+http://greenpeace.lu/Admin/usage/weekly/1998/04/26/
+http://greenpeace.lu/Admin/usage/weekly/1998/08/16/
+http://greenpeace.lu/Admin/usage/weekly/1997/10/12/
+http://retailer.gocollect.com/do/session/1912819/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/clubhouse/index.asp
+http://www.kusastro.kyoto-u.ac.jp/LCs/index/AURAU.html
+http://www.linux.com/networking/network/windows_nt/support/microsoft/Red_Hat/
+http://www.linux.com/networking/network/windows_nt/support/microsoft/operating_system/
+http://www.linux.com/networking/network/windows_nt/support/microsoft/SAP/
+http://www.linux.com/networking/network/windows_nt/support/microsoft/Unix/
+http://www.linux.com/networking/network/windows_nt/support/microsoft/pop-3/
+http://www.cs.rit.edu/photo_album/smr3632.html
+http://www.cpan.dk/CPAN/modules/by-authors/id/C/CH/CHRMASTO/?D=A
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/lit/misc/unitest/lit/music/midi/ego.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/lit/misc/unitest/lit/music/midi/lit/multiple.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/lit/misc/unitest/lit/music/midi/misc/dissert.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/computers/lit/misc/unitest/lit/music/midi/misc/peanuts.html
+http://www.eastsidejournal.com/sited/retr_story.pl/25409
+http://yp.gates96.com/8/46/50/23.html
+http://yp.gates96.com/8/46/52/6.html
+http://yp.gates96.com/8/46/52/10.html
+http://yp.gates96.com/8/46/52/18.html
+http://yp.gates96.com/8/46/52/25.html
+http://yp.gates96.com/8/46/53/78.html
+http://yp.gates96.com/8/46/53/95.html
+http://yp.gates96.com/8/46/54/26.html
+http://yp.gates96.com/8/46/54/41.html
+http://yp.gates96.com/8/46/54/64.html
+http://yp.gates96.com/8/46/54/76.html
+http://yp.gates96.com/8/46/54/92.html
+http://yp.gates96.com/8/46/55/62.html
+http://yp.gates96.com/8/46/55/94.html
+http://yp.gates96.com/8/46/55/98.html
+http://yp.gates96.com/8/46/56/19.html
+http://yp.gates96.com/8/46/56/42.html
+http://yp.gates96.com/8/46/56/86.html
+http://yp.gates96.com/8/46/58/53.html
+http://yp.gates96.com/8/46/58/57.html
+http://yp.gates96.com/8/46/59/41.html
+http://yp.gates96.com/8/46/59/44.html
+http://yp.gates96.com/8/46/59/84.html
+http://yp.gates96.com/8/46/59/99.html
+http://www.158.com.cn/news/2000/09/03/58946.htm
+http://www.pobladores.com/territorios/juegos/Shanodin/pagina/2
+http://www.otemachi.ibm.co.jp/pc/vlp/ca20/32l9068/price.html
+http://www.gutenberg2000.de/lessing/sinnged/sinna10.htm
+http://www.gutenberg2000.de/lessing/sinnged/sinn138.htm
+http://www.gutenberg2000.de/lessing/sinnged/sinnc27.htm
+http://www.gutenberg2000.de/lessing/sinnged/sinnc06.htm
+http://calcul.si.uji.es/Programes/SAS/stat/chap4/sect5.htm
+http://calcul.si.uji.es/Programes/SAS/stat/chap4/sect6.htm
+http://link.fastpartner.com/do/session/600436/vsid/3194/tid/3194/cid/137201/mid/1060/rid/2105/chid/3194/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/learn.htm
+http://www.linux.com/networking/network/red_hat/performance/workstations/business/
+http://ftp.dei.uc.pt/pub/faqs/backrubs/faq/?D=A
+http://www2.el-mundo.es/nuevaeconomia/2000/NE022/NE022-16b.html
+http://ring.toyama-ix.net/pub/linux/linuxppc-jp/2.0/UsersGuide/?N=D
+http://www.egroups.com/message/swchicks-rpg/763
+http://webraft.its.unimelb.edu.au/705195/students/caitlinb/pub/?N=D
+http://cn.egroups.com/message/indexinvesting/17
+http://networkdesigner.subportal.com/sn/Programming/Setup_Utilities/11753.html
+http://www.imagestation.com/member/?name=Mermaid34v&c=1
+http://crn.com/Components/TalkBack/tb-read.asp?ArticleId=8463
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/misc/lit/computers/music/linux/misc/thoughts/turingtest.html
+http://www.egroups.com/message/house_caliburnus/1479
+http://pub14.ezboard.com/BBSForum.showForumSearch?boardName=bleemtest
+http://spaceports.tucows.com/winme/adnload/136943_28461.html
+http://www.cerent.com/warp/public/767/spcl/vaccess/req-lab.html
+http://www.ualberta.ca/icons/icons/numbers/Big-orange-thin/
+http://www.gencat.es/cgi-bin/bc/drawer.cgi/LD/0004/A00027?98
+http://interhotel.com/romania/en/hoteles/49235.html
+http://www.infoscape.com.cn:8171/nf/0001/19/nfzx1908.htm
+http://www.hurriyetim.com/akdeniz/turk/00/05/25/akdhab/62akd.htm
+http://www.hurriyetim.com/akdeniz/turk/00/05/25/akdhab/38akd.htm
+http://dennou-t.ms.u-tokyo.ac.jp/arch/cc-env/Linux/debian-jp/dists/woody-jp/contrib/binary-ia64/misc/?M=A
+http://www.angelfire.com/vt/Mystical2
+http://www.indonesiansources.com/HELP/COOKIES.HTM
+http://members.nbci.com/cmeadows/gvi/45regt/45gvibat.html
+http://members.nbci.com/cmeadows/gvi/45regt/45gvicob.html
+http://landview.census.gov/hhes/www/housing/soma/char96/ch96tab5.html
+http://www.legis.state.pa.us/WU01/LI/BI/TI/1985/0/MNPENNSYLVANIAdENERGYdASSISTANCEdANDdCONSERVATIONdACT.HTM
+http://www.legis.state.pa.us/WU01/LI/BI/TI/1985/0/MNPENNSYLVANIAdSEWAGEdFACILITIESdACT.HTM
+http://www.legis.state.pa.us/WU01/LI/BI/TI/1985/0/MNPODIATRYdPRACTICEdACT.HTM
+http://www.legis.state.pa.us/WU01/LI/BI/TI/1985/0/MNPRESIDENT.HTM
+http://www.legis.state.pa.us/WU01/LI/BI/TI/1985/0/MNPRIVATEdMORTGAGEdINSURANCEdACT.HTM
+http://www.legis.state.pa.us/WU01/LI/BI/TI/1985/0/MNPROJECTd500.HTM
+http://www.legis.state.pa.us/WU01/LI/BI/TI/1985/0/MNPUBLICdWORKSdCONTRACTdREGULATIONdLAW.HTM
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/inventor/apps/samples/4view/Attic/Imakefile?only_with_tag=MAIN
+http://oss.sgi.com/cgi-bin/cvsweb.cgi/inventor/apps/samples/4view/Attic/Imakefile?only_with_tag=HEAD
+http://www4.50megs.com/justiceinn/charpages/leaves/707.html
+http://www4.50megs.com/justiceinn/charpages/leaves/859.html
+http://www4.50megs.com/justiceinn/charpages/leaves/171.html
+http://www4.50megs.com/justiceinn/charpages/leaves/114.html
+http://megalink.tucows.com/win2k/adnload/38582_28844.html
+http://members.tripod.lycos.nl/monthlysports/hello_and_welkom_at_the_new.htm
+http://coe.ier.hit-u.ac.jp/BibEc/data/Papers/nbrnberwo4558.html
+http://coe.ier.hit-u.ac.jp/BibEc/data/Papers/nbrnberwo4462.html
+http://coe.ier.hit-u.ac.jp/BibEc/data/Papers/nbrnberwo4813.html
+http://pub4.ezboard.com/factiveprodiscussioncommunityhottopicsresidentsandalcohol.showMessage?topicID=3.topic
+http://207.138.41.133/subscribe/IndoVStudio
+http://www.biuemountain.com/eng3/karen/EArejoice.html
+http://polygraph.ircache.net:8181/wwwboard/capabilities/http_-2www.westnebr.net/http_-2www.excite.com/grservic.htm
+http://pub7.ezboard.com/fturonneuemissionennebenwerteundsonstigewerte.showAddReplyScreenFromWeb?topicID=58.topic
+http://dk.egroups.com/post/badbart-showdown?act=forward&messageNum=679
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus62920/eus62921/eus64894/eus170276/eus163832/
+http://www.algonet.se/~d88628/engelsk/various.htm
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=220&discrim=220,215,11
+http://www.z-plus.de/TEXTE/INETCO/AUSG20000524/text7.html
+http://www.gbnf.com/genealog2/varner/html/d0059/I11636.HTM
+http://www.musiciansfriend.com/ex/ds/live/001030183152064208037007463633
+http://www.musiciansfriend.com/ex/ds/home/001030183152064208037007463633?dbase=info,order_info.html
+http://www.musiciansfriend.com/ex/ds/guitar/amps/001030183152064208037007463633?dbase=info,contact.html
+http://pix.egroups.com/message/ipe/1642?source=1
+http://213.36.119.69/do/session/153008/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://resa.travelprice.com/CallCenter/InitCommunicationAgence
+http://213.36.119.69/do/session/153008/vsid/1113/tid/1113/cid/28507/mid/1020/rid/1041/chid/1103/parser/yes/imref/eqqLmwlGltt5tkqHoXsLbimLofZLbkZHljlK6IlK/url/http://www.travelprice.com/DE_DE/
+http://www.egroups.com/message/peninsulaserv/567
+http://www.scifi.com/bboard/browse.cgi/1/5/545/12425?pnum=3
+http://no.egroups.com/post/icc-info?act=reply&messageNum=759
+http://www.chaos.dk/sexriddle/s/e/x/e/c/s/l/
+http://www.chaos.dk/sexriddle/s/e/x/e/c/s/t/
+http://www.nissan.co.jp/RENAULT-DEALERS/PASSPORT/view.cgi/search/972959630--
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=6,29,20,36,32
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=7,29,20,36,32
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=27,29,20,36,32
+http://dada.linuxberg.com/gnomehtml/adnload/31471_2540.html
+http://augustasports.com/football99/college/box_50347.shtml
+http://augustasports.com/football99/college/box_50365.shtml
+http://augustasports.com/football99/college/box_50423.shtml
+http://www.linux.com/networking/network/enterprise/e-commerce/management/open_source/
+http://usol.pdacentral.com/winnt/preview/1946.html
+http://usol.pdacentral.com/winnt/preview/78287.html
+http://usol.pdacentral.com/winnt/preview/1338.html
+http://usol.pdacentral.com/winnt/preview/12860.html
+http://usol.pdacentral.com/winnt/preview/6920.html
+http://usol.pdacentral.com/winnt/preview/51381.html
+http://ring.htcn.ne.jp/pub/lang/perl/CPAN/authors/id/W/WO/?N=D
+http://grybrd.subportal.com/sn/Network_and_Internet/Text_Chat_Clients/index1.html
+http://www.gurlpages.com/lacej/part13.html
+http://ring.shibaura-it.ac.jp/archives/mac/info-mac/game/com/wolf/?D=A
+http://cgi.cnnsi.com/baseball/mlb/nl/gamelog/2000/10/07/mets_giants/
+http://my.egroups.com/messages/not_honyaku/236
+http://members.tripod.com/agran_gassendi/Countdown.htm
+http://www.tccomputers.com/cgi-bin/bp/1878637479/showcase/showcase.htm
+http://207.138.41.133/message/AikensTrivia/264
+http://207.138.41.133/message/AikensTrivia/276
+http://www.shumway.org/thetree/ped13583.htm
+http://link.fastpartner.com/do/session/600421/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/dk/
+http://link.fastpartner.com/do/session/600421/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/politiken.php
+http://link.fastpartner.com/do/session/600421/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/company/jobs.htm
+http://in.egroups.com/message/canada/856
+http://in.egroups.com/message/canada/883
+http://debian.tod.net/OpenBSD/src/lib/libssl/README.OPENBSD
+http://www.emerchandise.com/main/EMERCH/s.1M38gYrZ
+http://www.emerchandise.com/browse/TOYSTORY2/FIGURINE/b.FAVORITES%20COMICS%20ANIMFEAT%20TOYSTORY2/s.1M38gYrZ
+http://quotidiano.monrif.net/chan/cronaca_nazionale:410879.1:/1999/12/24
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=baignes&l=fr
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=baignas&l=fr
+http://www.egroups.com/message/swchicks-rpg/93
+http://usuarios.tripod.es/jlgolis/id142_l.htm
+http://www9.freeweb.ne.jp/shopping/nossy/baby/200-59.html
+http://www9.freeweb.ne.jp/shopping/nossy/baby/305-36.html
+http://ftp.tku.edu.tw/OS/NetBSD/NetBSD-1.3.2/alpha/binary/kernel/?D=A
+http://www-1.cisco.com/univercd/cc/td/doc/product/wanbu/82/access/fpmpmm12/fpmmappe.pdf
+http://pub17.ezboard.com/fartofnorrathfavoritepaintings.threadControl?topicID=56.topic
+http://itcareers.careercast.com/texis/it/itjs/+pwwBmew_D86eGrwwwqFqygdMpwDOeWXqqBcneWkjnwBneWkxqBOeWRlmmOtFqewyXwotoBwcaMwDwtnanmowcdt1naqconDBaGncwBodD5ropa5BGwBnton5amnVncdpaMwGAnBoDtanMwocaGn51MnaMFqryfHfREIDzmbwwwpBmFe-B-dehxwww5rmXmwwBrmeZpwww/morelike.html
+http://www.thestateofcolorado.com/aoubicycling.html
+http://www.freespeech.org/DISjak/disnews/maillist.html
+http://www.freespeech.org/DISjak/sport/schwimm/bestlist.html
+http://www.amigos.com/cgi-bin/w3com/pws/ffe/_MhIXE2wgPJZ1X047wqRwM-olUgaV3vI6fBPmDsoD0c26y7TrHjLUhhhTSIZ2PRmqLmBVyInWJLkLGkKScrdFyX1uyXCZhvaWFvbnSFioewAURJcXQC-hJE5KczVcMUiq3ncgKjQh7nynQEu662C
+http://m.home.cern.ch/m/mrashid/www/cuisine/cuisin13.htm
+http://m.home.cern.ch/m/mrashid/www/cuisine/cuisin28.htm
+http://www.dayoo.com/channel/stock/news/cjzh/09/0921/06.htm
+http://webcvs.kde.org/cgi-bin/cvsweb.cgi/KodeKnight/lib/Makefile.am?r1=1.3&sortby=rev
+http://www.fogdog.com/cedroID/ssd3040183315779/nav/products/featured_brands/12p/all/
+http://www.fogdog.com/cedroID/ssd3040183315779/nav/stores/baseball/
+http://www.fogdog.com/cedroID/ssd3040183315779/nav/stores/squash/
+http://www9.hmv.co.uk:5555/do/session/1347832/vsid/199/tid/199/cid/1061396/mid/1020/rid/1052/chid/1029/parser/yes/imref/eqqLmwlGltt5tkeHjskKZlkKrhlK/url/http://www.hmv.co.uk/hmv/newmenu.html
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=9,36,8
+http://www.arm.com/sitearchitek/support.ns4/html/cores_faq!OpenDocument&ExpandSection=24,36,8
+http://www.hig.se/(append,countdown,set,sqloutput,sqltable)/~jackson/roxen/
+http://ring.jec.ad.jp/archives/linux/kernel.org/kernel/people/mingo/raid-patches/raid-2.2.17-A0
+http://www.wsrn.com/apps/links/?s=BKIRF
+http://www.auto.ru/wwwboards/mercedes/0163/
+http://www.auto.ru/wwwboards/mercedes/0142/
+http://www.auto.ru/wwwboards/mercedes/0132/
+http://www.auto.ru/wwwboards/mercedes/0002/
+http://www.auto.ru/wwwboard/mercedes/0014/
+http://www.presa.spb.ru/newspapers/dp/arts/dp-178-art-12.html
+http://pub8.ezboard.com/fnirlcomcenterracetalk.showMessage?topicID=8.topic
+http://www.allhealth.com/pregnancy/labor/qa/0,3105,599,00.html
+http://www3.newstimes.com/archive99/sep0499/lce.htm
+http://jupiter.u-3mrs.fr/~msc41www/PSHTM/PS4330.HTM
+http://www.gpul.org/ftp/os/linux/cd-images/other/suse/dosutils/pfdisktc/
+http://platsbanken.amv.se/kap/text/88/001025,010050,240907,10,0107051488.shtml
+http://www.angel-bastel-zoo.de/detail/detail_811_3.htm
+http://members.nbci.com/cmeadows/gvi/3battn/3bgvicob.html
+http://www.chaos.dk/sexriddle/s/e/x/x/p/o/r/
+http://www.asiastockwatch.com/sg/Forum/ForumDetails/0,1819,561_1_2:15,00.html
+http://mysanantonio.sportshuddle.com/sports/football/health/advisors/workouts/huff12.asp
+http://mysanantonio.sportshuddle.com/sports/football/health/advisors/workouts/huff1.asp
+http://ring.data-hotel.net/pub/linux/debian/debian-jp/dists/unstable/contrib/source/math/
+http://www.tel.de/s/I/IFG.htm
+http://www.tel.de/s/I/IFHV.htm
+http://chat.hr-online.de/fs/buecherbuecher/buch/kerr.html
+http://mirror.cc.utsunomiya-u.ac.jp/mirror/FreeBSD/branches/2.2-stable/src/sys/dev/
+http://mirror.cc.utsunomiya-u.ac.jp/mirror/FreeBSD/branches/2.2-stable/src/sys/nfs/
+http://www.malaysia.net/lists/sangkancil/1998-12/msg01044.html
+http://biblio.cesga.es:81/search*gag/aFerreiro,+MartÃ\83Â\83Ã\82Â\83Ã\83Â\82Ã\82­n/aferreiro+martin/-5,1,1,E/frameset&F=aferreiro+manuel&4,,4
+http://www.ferien-immobilien.de/DominikanischeRep/verkauf/Exklusiv-IB/Startseite/Gemeinsam/MarketingStrategie/Exklusiv-IB/Startseite/Gemeinsam/erreichenPartner/email3d.htm
+http://www.ferien-immobilien.de/DominikanischeRep/verkauf/Exklusiv-IB/Startseite/Gemeinsam/MarketingStrategie/Exklusiv-IB/Startseite/Gemeinsam/IIMMitglieder.htm
+http://chunma.yeungnam.ac.kr/~home/home13/msgboard/msgboard.cgi?cmd=list&stat=start
+http://link.fastpartner.com/do/session/600413/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/local/redirect.php
+http://www.eyeball.symantec.co.uk/region/se/sepress/20000418111220.htm
+http://www.rezel.enst.fr/ftp/linux/distributions/debian/CD-1/dists/frozen/main/binary-all/news/?D=A
+http://www.latimes.com/editions/orange/20001028/p000103070_ome0014.html
+http://www.chaos.dk/sexriddle/j/c/u/t/
+http://cometweb01.comet.co.uk/do!session=132050&vsid=694&tid=20&cid=37044&mid=1000&rid=1060&chid=1711&url=eqqLmwlGltt5tkkHbqpLZXmLbkZHljlKaltLkilLXalKfkaLbukKeqjLi1
+http://perso.wanadoo.fr/jm.michaud/electronique_index.htm
+http://dk.egroups.com/messages/Gunsmithing/1446?viscount=-30
+http://www-d0.fnal.gov/d0dist/dist/releases/psim01.02.00/pmcs_met/VERSION
+http://mirror.cc.utsunomiya-u.ac.jp/mirror/CPAN/authors/id/P/PM/?N=D
+http://www.movieguide.com/pressroom/events/amcinema96/award_amcinema965.html
+http://www.sda.t-online.de/reise/index/aktrex201.htm
+http://dic.empas.com/show.tsp/SMASHER
+http://www.3w-posters.com/tomlinson.htm
+http://www.3w-posters.com/tuttle.htm
+http://www.xmission.com/(art,dots,ftp,geek,misc,music,caffiene,art,toys,dots,edge,misc,shopping,ftp,places,privacy,geek,cuseeme,apocalypse,people,stuffiuse,places,stuffiuse)/~bill/links.html
+http://www.osiris.978.org/~brianr/mirrors/olga/main/g/gangi_mike/?N=D
+http://www.best.com/~workpage/g/57/300g.htm
+http://www.cyd.com.cn/zqb/19991109/GB/9677^Q212.htm
+http://edu.news.chinaren.com/161/10112157.shtml
+http://users.info.unicaen.fr/~jjousset/perso/html/entrainperso/page.html
+http://www.wordtheque.com/owa-wt/wordtheque_dba.w.t?w=destituiscono&l=it
+http://www.uk.multimap.com/p/browse.cgi?pc=B771AA&cat=loc
+http://www.auxerre.culture.gouv.fr/culture/actualites/conferen/bonneuil-duffour.htm
+http://www.auxerre.culture.gouv.fr/culture/actualites/communiq/mediaBonneuil-Duffour.htm
+http://www.ancientsites.com/~Ftagn_Sithathor
+http://biblioteca.upv.es/bib/doc/doc_fisbd/86/127697//C/1820009/0////25/N/MLTPAI
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus53930/eus169714/eus169722/eus542057/eus542410/
+http://www.kfi640.com/shared/mod_perl/looksmart/looksmart/eus1/eus53930/eus169714/eus169722/eus542057/eus542106/
+http://pub26.ezboard.com/fathanasiafrm1.showMessage?topicID=113.topic
+http://www.sourceforge.net/softwaremap/trove_list.php?form_cat=186&discrim=186,226,251
+http://www.linux.com/networking/network/community/future/news/services/
+http://www.linux.com/networking/network/community/future/news/operating_system/
+http://www.linux.com/networking/network/community/future/news/?kw_offset=50
+http://www.linux.com/networking/network/development/unix/open_source/commercial/
+http://ring.shibaura-it.ac.jp/pub/misc/ham/funet/packet/00Index
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=3,0+20,0+17,0-(
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=3,0+20,0+17,0-9,1
+http://www.vorlesungen.uni-osnabrueck.de/informatik/c98/aufgaben/code/aufg50/ProcessInfo/ProcessInfo.bundle/Resources/?D=A
+http://wap.jamba.de/KNet/_KNet-xOQ8j1-xHd-13fk7/showInfo-special1.de/node.0/cde7f1uou
+http://nx5.salon.com/books/col/keil/2000/05/02/too_old/index2.html
+http://pcmagazin.de/news/artikel/1999/04/29016-wf.htm
+http://www.redrival.com/rgrascher/
+http://208.184.36.144/cwi/subscriptions/privacy_policy/0,1323,NAV47-68-85-98_STO52856,00.html
+http://www.staroriental.net/nav/soeg_c/ihf,aol,n12,1,TVB香港小姐2000.html
+http://www.staroriental.net/nav/soeg_c/ihf,aol,n12,6,TVB香港小姐2000.html
+http://166.111.104.242/uscode/30/541b.head.html
+http://stocks.tradingcharts.com/stocks/charts/fwrx/dchart.php?S=fwrx&T=d
+http://genforum.genealogy.com/cgi-bin/print.cgi?plemmons::57.html
+http://www.geocities.co.jp/Hollywood-Studio/3572/geodiary.html
+http://www.luf.org/~jwills/LufWiki/view.cgi/Tech/
+http://www.doc.ic.ac.uk/lab/labsrc_area/firstyear/submissions/cs1/labs/Ex01/arr00/?M=A
+http://citeseer.nj.nec.com/ps/332798
+http://citeseer.nj.nec.com/addcomment/332798
+http://citeseer.nj.nec.com/cidcontext/4075337
+http://ftp.te.fcu.edu.tw/cpatch/helputil/answerworks/?M=A
+http://ftp.te.fcu.edu.tw/cpatch/helputil/answerworks/d2hpro4ethanks.htm
+http://link.fastpartner.com/do/session/600423/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/join/programmes/mondosoft.php
+http://link.fastpartner.com/do/session/600423/vsid/2870/tid/2870/cid/136966/mid/1060/rid/1926/chid/2870/parser/yes/imref/eqqLmwlGltt5tkcHXpqLmXoLqkbLokZHljlK/url/http://www.fastpartner.com/company/
+http://library.cuhk.edu.hk/search*chi/dEnglish+language+--+Clauses./denglish+language+clauses/7,-1,0,B/browse
+http://www04.u-page.so-net.ne.jp/yd5/yuma/top/home.html
+http://www.smartshop.com/cgi-bin/main.cgi?c=1905&ssa=26
+http://www.smartshop.com/cgi-bin/main.cgi?c=1943&ssa=26
+http://se.egroups.com/dir/Business/Management/Project_and_Program_Management/Training?st=10
+http://www.hpl.online.sh.cn/WENXUE/tongsuo/wuxia/gulong/xueying/_vti_cnf/hs~001.htm
+http://news.medscape.com/adis/PEON/public/archive/1999/toc-0221.html
+http://news.medscape.com/adis/PEON/public/archive/1999/toc-0197.html
+http://tucows.hongkong.com/winnt/adnload/4256_29575.html
+http://www.etang.com/local/shenzhen/shopping/shop/0318mans02.htm
+http://www.etang.com/local/shenzhen/shopping/shop/0319foll.htm
+http://www.etang.com/local/shenzhen/shopping/shop/0319jialjs.htm
+http://www.staffan.addr.com/cgi-bin/woda/icq.cgi/Edit?_id=2a5e
+http://www.linux.com/networking/network/operating_system/kernel/distro/?printable=yes
+http://www.linux.com/networking/network/operating_system/kernel/distro/commercial/
+http://www.linux.com/networking/network/operating_system/kernel/distro/white_dwarf/
+http://dir.dig.co.kr/parents/textbook/20301030101.html
+http://www.affiliate.hpstore.hp.co.uk/do/session/380895/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/fr/CASHBACK/entry.asp
+http://ccuftp.ccu.edu.tw/pub1/chinese/linux/clinux/c1/?N=D
+http://cgi.cnnsi.com/basketball/college/women/boxscores/2000/03/07/cbp_rak
+http://www.adcentral.com/cgi-bin/w3com/pws/adsites/5BRIztXQWHs_H_kyq8hmyrHpmCLb5RfQ09-DcKP1B6mZibAiJTLy1w3iiFS15WkFiCHMuMtjNK5FtHPDtZ7rxwckgoj0GaicnAZxhJLQ3zWaLoNUq8eTpG7wCxe3TWAb66jt
+http://www.varsity.cam.ac.uk/varsity/live/2000/listings.nsf/44bbd1c2a6305036802567fb0081c76b!OpenView&Grid=1&Date=1999-04-06
+http://students.lsu.edu/students/main.nsf/Pages/CSISAJ1!OpenDocument&ExpandSection=15,21,5,4
+http://students.lsu.edu/students/main.nsf/Pages/CSISAJ1!OpenDocument&ExpandSection=18,21,5,4
+http://www.getplus.co.jp/category/catinet.homepagew2.asp
+http://www.motorradversand.de/cgi-bin/antrieb/kettensatz_komplett_suzuki/RK82K872/beurteilung.htm
+http://202.99.23.245/zdxw/13/20000328/200003281335.html
+http://proxy.tiscover.com/1Root/Kontinent/6/Staat/7/Bundesland/22/Ort/120/Infrastruktur/299270/Homepage/homepage...1.html
+http://www.jamba.de/KNet/_KNet-RcO8j1-cHd-13eq4/browse.de/node.0/cdel3j591
+http://www.jamba.de/KNet/_KNet-RcO8j1-cHd-13eqf/showInfo-wir.de/node.0/cde7f1uou
+http://pub6.ezboard.com/fcrazyassmb47001generalshiznit.threadControl?topicID=685.topic
+http://perso.infonie.fr/imagestld/photojyg5/images/alive5/?D=A
+http://members.spree.com/sip1/take5planet/videos.htm
+http://ae.boston.com/haiku/vote?haiku_id=4484
+http://adex3.flycast.com/server/socket/127.0.0.1:2800/click/OnlineCitiesSM/OnlineCitiesInteractiveCityGuides/bd129601192
+http://www.digitaldrucke.de/(aktuell,computer,marktplatz,shopping,verkehr)/suche/uebersicht.html
+http://www.digitaldrucke.de/(aktuell,computer,hersteller,marktplatz,verkehr)/_fort/html/themen/computer/hard/herstell.htm
+http://bbs.kcm.co.kr/NetBBS/Bbs.dll/kcmmission/lst/qqeq/1/zka/B2-kD2-l/qqo/004A
+http://bbs.kcm.co.kr/NetBBS/Bbs.dll/kcmmission/rcm/zka/B2-kD2-l/qqo/004A/qqatt/^
+http://ftp.eq.uc.pt/software/lang/tcl/ftp.scriptics.com/nightly-cvs/tk/library/?S=A
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9704/Subject/article-141.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9704/Subject/article-165.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9704/Subject/article-241.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9704/Subject/article-239.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9704/Subject/article-150.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9704/Subject/article-44.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9704/Subject/article-12.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9704/Subject/article-4.html
+http://www.infomedia.it/cgi-bin/lwgate/JAVA-IT/archives/java-it.log.9704/Subject/article-27.html
+http://yp.gates96.com/5/88/50/47.html
+http://yp.gates96.com/5/88/50/94.html
+http://yp.gates96.com/5/88/51/20.html
+http://yp.gates96.com/5/88/52/11.html
+http://yp.gates96.com/5/88/52/26.html
+http://yp.gates96.com/5/88/53/86.html
+http://yp.gates96.com/5/88/53/99.html
+http://yp.gates96.com/5/88/54/48.html
+http://yp.gates96.com/5/88/55/29.html
+http://yp.gates96.com/5/88/55/31.html
+http://yp.gates96.com/5/88/55/41.html
+http://yp.gates96.com/5/88/55/62.html
+http://yp.gates96.com/5/88/55/77.html
+http://yp.gates96.com/5/88/56/62.html
+http://yp.gates96.com/5/88/56/93.html
+http://yp.gates96.com/5/88/59/61.html
+http://ceu.fi.udc.es:8000/mc/maillist/99-02/2090.918081010.176207534.html
+http://ceu.fi.udc.es:8000/mc/maillist/99-02/1123.920140263.921690399.html
+http://ceu.fi.udc.es:8000/mc/maillist/99-02/19089.918231855.610311830.html
+http://ceu.fi.udc.es:8000/mc/maillist/99-02/16059.919279797.801472096.html
+http://ceu.fi.udc.es:8000/mc/maillist/99-02/24001.919906575.275033199.html
+http://ceu.fi.udc.es:8000/mc/maillist/99-02/14848.918256026.548154577.html
+http://ceu.fi.udc.es:8000/mc/maillist/99-02/10783.918253985.660158806.html
+http://ceu.fi.udc.es:8000/mc/maillist/99-02/27581.918670666.1055622954.html
+http://www.activedayton.com/sportsticker/stnd/current/BBH.STAT.FSLKISLTRT.html
+http://www.teenplatinum.com/barelylegal/japanesewomen/boots/petitesmall/explodingblowjob/eunuchbodyshots/homosexualass.html
+http://books.hyperlink.co.uk/xt1/Methodology_for_the_Harmonization_of_European_Occupational_Accident_Statistics/9282641007
+http://www.jpc-music.com/2563637.htm
+http://www.jpc-music.com/8168850.htm
+http://www.expage.com/sugarshackstablesapryl
+http://www.egroups.com/messages/svlug/31105
+http://www.chinawolf.com/~warson/japan/chichuan/bride/mldxn/009.htm
+http://www.chinawolf.com/~warson/japan/chichuan/bride/mldxn/011.htm
+http://yp.gates96.com/11/78/70/19.html
+http://yp.gates96.com/11/78/70/95.html
+http://yp.gates96.com/11/78/71/64.html
+http://yp.gates96.com/11/78/71/65.html
+http://yp.gates96.com/11/78/72/30.html
+http://yp.gates96.com/11/78/73/35.html
+http://yp.gates96.com/11/78/74/0.html
+http://yp.gates96.com/11/78/75/58.html
+http://yp.gates96.com/11/78/76/75.html
+http://yp.gates96.com/11/78/77/36.html
+http://yp.gates96.com/11/78/77/64.html
+http://yp.gates96.com/11/78/78/20.html
+http://yp.gates96.com/11/78/78/33.html
+http://yp.gates96.com/11/78/78/70.html
+http://yp.gates96.com/11/78/78/93.html
+http://yp.gates96.com/11/78/79/3.html
+http://yp.gates96.com/11/78/79/50.html
+http://ben.aspads.net/ex/c/190/649604396
+http://www.lifl.fr/PRIVATE/Manuals/java/jdk1.2/docs/api/java/applet/class-use/AudioClip.html
+http://dic.empas.com/show.tsp/?q=cea&f=B
+http://beautifulthemes.subportal.com/sn/Utilities/Disk_Maintenance_and_Repair_Utilities/5294.html
+http://ustlib.ust.hk/search*chi/anational+bureau+of+economic+research/anational+bureau+of+economic+research/-5,-1,0,E/frameset&F=anational+bureau+of+asian+and+soviet+research+u+s&1,,0
+http://www.canlii.org/ca/regl/dors99-120/art5.html
+http://www.canlii.org/ca/regl/dors99-120/partie144284.html
+http://www.incestpornstories.com/freshmanteen/eggbirth-canal/loverdrag-queen/birth-canalfull-term/stomachvagina.html
+http://www.fashion-j.com/bs/013/013/19.html
+http://www.fjtcm.edu.cn/Fujian_w/news/fjgsb/990311t/1-3.htm
+http://www.kaos.dk/sex-riddle/k/a/k/i/s/z/r/d/
+http://www.kaos.dk/sex-riddle/k/a/k/i/s/z/r/f/
+http://www.tccomputers.com/cgi-bin/bp/41291345/products/specials/mbbundle.htm
+http://www.tccomputers.com/cgi-bin/bp/41291345/services/insight.htm
+http://www.tccomputers.com/cgi-bin/bp/41291345/products/batterybackups/batterybackups.htm
+http://cartografia.comune.modena.it/Ril_Whip/menuogg/001-100/ME0068c.htm
+http://library.bangor.ac.uk/search/cWS+5+V196a+2000/cws++++5+v196+a+2000/7,-1,0,B/frameset&F=cws+++21+e84+1989&5,,12
+http://mindit.netmind.com/proxy/http://www.exposure.aust.com/~promote1/auspalaeo/tectonix/tect1.htm
+http://ftp.fi.debian.org/debian/dists/unstable/non-free/binary-i386/shells/?S=A
+http://excite.de.netscape.com/unterhaltung/katalog/19344
+http://www.symatrixinc.com/website/website.nsf/0/3e40df86fb357cd5882568720079613f!OpenDocument&ExpandSection=25,20,21,29
+http://www.burstnet.com/ads/ad7826a-map.cgi/1708189811
+http://dic.empas.com/show.tsp/?s=b&q=CONSIDERABLE
+http://www.kaos.dk/sex-riddle/k/a/k/i/p/g/t/c/
+http://www.kaos.dk/sex-riddle/k/a/k/i/p/g/t/h/
+http://www.kaos.dk/sex-riddle/k/a/k/i/p/g/t/n/
+http://www.kaos.dk/sex-riddle/k/a/k/i/p/g/t/x/
+http://www.cbe21.com.cn/xueke/dili/jiaoxuezs/ziliaojn/tupianhc/i0602.htm
+http://babycenter.netscape.com/bbs/3788/thread530/message9.html
+http://polygraph.ircache.net:8181/http_-2www.harborbay.com/home/webstuff/companyprofile.htm
+http://dante.bdp.it/cgi-bin/poseidon_v2.0/reflect/poseidon/disc/bibl-uno/512098188/threadconfig
+http://dante.bdp.it/cgi-bin/poseidon_v2.0/reflect/poseidon/disc/bibl-uno/512098188/newconfig
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=5,1,16,25,13
+http://www2.hgo.se/Kurskatalogen.nsf/a49e2126c83c4922412566f60052f831/f24cc45affc890eec12565d80055e0b9!OpenDocument&ExpandSection=28,1,16,25,13
+http://ftp.sunet.se/pub/lang/perl/CPAN/authors/id/R/RH/?D=A
+http://www.geocities.co.jp/SilkRoad/1618/nixxki/010799.html
+http://genforum.genealogy.com/cgi-genforum/forums/americanrev.cgi?4444
+http://in.egroups.com/message/djgppgames/358
+http://freehost.crazyhost.com/teengallery/apbh/panty.html
+http://buffy.acmecity.com/xander/366/EDpt2.htm
+http://www.tccomputers.com/cgi-bin/bp/505218695/promotional/deals.htm
+http://www.tccomputers.com/cgi-bin/bp/505218695/products/cooling/cooling.htm
+http://www.tccomputers.com/cgi-bin/bp/505218695/products/dvds/dvds.htm
+http://www.tccomputers.com/cgi-bin/bp/505218695/products/mice/mice.htm
+http://www.tccomputers.com/cgi-bin/bp/505218695/services/register.htm
+http://www.foxsports.com/nba/scores/2000/000129_playbyplay_clewas.sml
+http://pub1.ezboard.com/fcellofuncellistsbynightsemiprooramateur.showAddReplyScreenFromWeb?topicID=513.topic&index=9
+http://yp.gates96.com/0/22/30/81.html
+http://yp.gates96.com/0/22/31/89.html
+http://yp.gates96.com/0/22/32/1.html
+http://yp.gates96.com/0/22/32/12.html
+http://yp.gates96.com/0/22/32/48.html
+http://yp.gates96.com/0/22/32/78.html
+http://yp.gates96.com/0/22/34/48.html
+http://yp.gates96.com/0/22/34/75.html
+http://yp.gates96.com/0/22/34/85.html
+http://yp.gates96.com/0/22/35/38.html
+http://yp.gates96.com/0/22/35/73.html
+http://yp.gates96.com/0/22/36/40.html
+http://yp.gates96.com/0/22/36/92.html
+http://yp.gates96.com/0/22/37/0.html
+http://yp.gates96.com/0/22/37/61.html
+http://yp.gates96.com/0/22/37/96.html
+http://yp.gates96.com/0/22/39/13.html
+http://yp.gates96.com/0/22/39/94.html
+http://www.incestpornstories.com/underageflashing/plus-sizereal-size/beautiesasian/purpleanal-sex/maledomfantasy/high-schoolpretty/cherrybest-friends.html
+http://variety.studiostore.com/browse/ELMOINGROU/TOY/s.2vzELAA2
+http://members.tripod.lycos.nl/BOGAERT/off2.htm
+http://www.eveclub.com/cgi-bin/eveclub.front/972959555004/Catalog/2000019
+http://genforum.genealogy.com/cgi-genforum/forums/noel.cgi?662
+http://www.affiliate.hpstore.hp.co.uk/do/session/380888/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-expo.com/FR/REGISTRATION/entry.asp
+http://yp.gates96.com/5/88/10/35.html
+http://yp.gates96.com/5/88/10/44.html
+http://yp.gates96.com/5/88/11/36.html
+http://yp.gates96.com/5/88/13/1.html
+http://yp.gates96.com/5/88/13/23.html
+http://yp.gates96.com/5/88/13/77.html
+http://yp.gates96.com/5/88/13/86.html
+http://yp.gates96.com/5/88/14/47.html
+http://yp.gates96.com/5/88/14/83.html
+http://yp.gates96.com/5/88/15/11.html
+http://yp.gates96.com/5/88/16/43.html
+http://yp.gates96.com/5/88/16/86.html
+http://yp.gates96.com/5/88/17/6.html
+http://yp.gates96.com/5/88/17/12.html
+http://yp.gates96.com/5/88/17/73.html
+http://yp.gates96.com/5/88/18/1.html
+http://yp.gates96.com/5/88/18/38.html
+http://yp.gates96.com/5/88/18/47.html
+http://yp.gates96.com/5/88/18/79.html
+http://newnova.tucows.com/winme/adnload/138430_29763.html
+http://yp.gates96.com/8/43/60/48.html
+http://yp.gates96.com/8/43/60/55.html
+http://yp.gates96.com/8/43/61/22.html
+http://yp.gates96.com/8/43/62/40.html
+http://yp.gates96.com/8/43/62/52.html
+http://yp.gates96.com/8/43/62/94.html
+http://yp.gates96.com/8/43/63/79.html
+http://yp.gates96.com/8/43/64/73.html
+http://yp.gates96.com/8/43/64/80.html
+http://yp.gates96.com/8/43/66/26.html
+http://yp.gates96.com/8/43/66/70.html
+http://yp.gates96.com/8/43/67/16.html
+http://yp.gates96.com/8/43/68/11.html
+http://yp.gates96.com/8/43/69/74.html
+http://www.fogdog.com/cedroID/ssd3040183354487/nav/products/winter_sports/1d/mid-weight_bottoms/
+http://www.fogdog.com/cedroID/ssd3040183354487/nav/products/winter_sports/1r/avalanche_safety/
+http://www.fogdog.com/cedroID/ssd3040183354487/boutique/marmot/
+http://www.affiliate.hpstore.hp.co.uk/do/session/380898/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.france.hp.com/Main/acheterhp/
+http://www.nd.edu/~dtl/cheg258/unix/unixhelp1.2/Pages/tasks_rm1.1.1.html
+http://se.egroups.com/post/cyclesi?act=reply&messageNum=137
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=22,0+18,0+22,0+9,4
+http://cidade.subportal.com/sn/Games/Action_Games/8120.html
+http://wiem.onet.pl/wiem/0115d9-rp1.html
+http://www.ferien-immobilien.de/detmold/Verkauf/Gemeinsam/Inserieren/Allgemeine-IB/Startseite/Gemeinsam/MarketingStrategie/Gemeinsam/erreichen.htm
+http://retailer.gocollect.com/do/session/1912826/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/product_display/products/product_lines.asp
+http://retailer.gocollect.com/do/session/1912826/vsid/2092/tid/2092/cid/569192/mid/1540/rid/1980/chid/2085/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLl0/url/http://www.gocollect.com/halloween/halloween.asp
+http://www.iabusnet.org:90/forums/aca-1/dispatch.exe/survey/listUnseen/fol/100001/20,0/2542788
+http://www.dispatch.co.za/1998/06/25/easterncape/BISHO.HTM
+http://pub24.ezboard.com/fsosatanfrm1.showMessage?topicID=48.topic
+http://ftpsearch.belnet.be/ftp/packages/Linux-docs/howto/other-formats/INDEX
+http://www.crosswinds.net/~mluotto/noframe/feedback/form2.htm
+http://www.schoolweb.nl/studentensteden/Rotterdam/SVRGaudium/info.cfm
+http://www.shopworks.com/index.cfm/action/directory/userid/0000BD9A-2F67-19FE-9038010B0A0ADCF2
+http://findmail.com/messages/masterhuen/802
+http://www.t-dialin.net/navkopf/service/websvkaa.htm
+http://gallery2.simplenet.com/lobby/main/videocaps/ebaral/bigvalley/ebbva19.htm
+http://gallery2.simplenet.com/lobby/main/videocaps/ebaral/bigvalley/ebbva31.htm
+http://www.outpersonals.com/cgi-bin/w3com/pws/out/44hIVEhY5ZrKWoMKb0FtjCXhqcpntVLId5WTaJdeZmonn200jiiswYnK2vORJkjpm-x643ZCeLyy6kJnIAKa5rNx_42I13Ud9N03G9xPob7Hoci92HJhOlbEv4WsB85Au-cLXFlIHPd866jS
+http://ftp.debian.org/debian/dists/Debian2.2r0/main/binary-all/editors/?D=A
+http://ftp1.support.compaq.com/patches/public/Digital_UNIX/v3.2g/mailworks/2.0/?S=A
+http://www.digitalhearth.com/Recipes/World_Cuisines/South_Asian/Indian/index5.html
+http://ftp.gigabell.net/pub/Stormix/dists/rain/main/?M=A
+http://www.stas.net/1/theparamanor/apartment.htm
+http://www.netcom.com/~gfenzil/free.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/misc/misc/thoughts/math/legendes/pages_new.html
+http://www.eleves.ens.fr:8080/home/madore/index.shtml.fr/lit/misc/misc/thoughts/math/legendes/misc/orders_mag.html
+http://dandini.cranfield.ac.uk/vl=-39658948/cl=171/nw=1/rpsv/catchword/routledg/13606719/contp1-1.htm
+http://genforum.genealogy.com/cgi-genforum/forums/pugsley.cgi?81
+http://www.users.globalnet.co.uk/~mmayes/pages/cross.htm
+http://dic.empas.com/show.tsp/?s=d&q=%C4%A7%BD%C7
+http://www.jamba.de/KNet/_KNet-rHP8j1-lHd-13f16/browse.de/node.0/cde7f1uou
+http://library.bangor.ac.uk/search/aHolmgren,+Nils+Fritiof,+1877-1954/aholmgren+nils+fritiof+1877+1954/7,1,1,B/marc&F=aholmlund+chris&1,1,
+http://www.spiral.at/Katalog/Artikel/0181030/
+http://www.spiral.at/Katalog/Artikel/0181242/
+http://www.generation-formation.fr/navig.htm---o21zAo06L2o0Ol9A074fo6VJGezMkEeIgI8eOkn2ApvFFo6Td4ezyr6feZJPdspt6dsSAtdsNhJdspt6dsrvrdjlhkfbz.htm
+http://www.nextmedia.com.hk/netgirl/sport/images/chelsea/ch-30.htm
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=9,5-9,0-15,0-17,0
+http://www.realize.com/i82.htm,qt=35665aa9=645a273f-1a-31fa805-1-0-0-0--
+http://www.eud.com/1998/06/21/21121AA.shtml
+http://www.eud.com/1998/06/21/21414AA.shtml
+http://www.eud.com/1998/06/21/21434AA.shtml
+http://chemtech.chinamarket.com.cn/E/Showdetail_company/5569.html
+http://chemtech.chinamarket.com.cn/E/Showdetail_company/1095.html
+http://www.ferien-immobilien.de/baden-wuertemberg/konstanz/Verkauf/Private-IB/Allgemeine-IB/Startseite/Gemeinsam/Immolink/Gemeinsam/MarketingStrategie/inhalt.htm
+http://www.ferien-immobilien.de/baden-wuertemberg/konstanz/Verkauf/Private-IB/Allgemeine-IB/Startseite/Gemeinsam/Immolink/Gemeinsam/versicherungen/gebaeude/deckungsumfang.htm
+http://retailer.gocollect.com/do/session/1912886/vsid/2312/tid/2312/cid/573127/mid/1020/rid/2147/chid/2210/parser/yes/imtarget/ImMainFrame/imref/eqqLmwlGltt5tkdHlZlLiibLZqkKZljLlZe5ofpLqjXLpl4/url/http://www.gocollect.com/company_info/terms_and_conditions.asp
+http://eagle.synet.edu.cn/mirror/www.tuc.org.uk/
+http://eagle.synet.edu.cn/mirror/dcarolco.lanminds.com/home/
+http://www.chez.com/carabanon/Pagecabanon.htm
+http://poetry.lezlisoft.com/kikelet/spiritualitas/lelekszinpad.shtml
+http://lateline.muzi.net/ll/fanti/81373.shtml
+http://www.egroups.com/message/vacuum/1140
+http://www.egroups.com/message/vacuum/1153
+http://www.egroups.com/message/vacuum/1157
+http://no.egroups.com/message/-1friendsliste/401
+http://no.egroups.com/message/-1friendsliste/411
+http://pike-community.org/(base=/forums/show.html,explode=146,forum=7,t=972959520359311)/forums/show.html
+http://pike-community.org/(base=/forums/show.html,explode=512,forum=7,t=972959520359311)/forums/show.html
+http://pike-community.org/(base=/forums/show.html,forum=7,show=413,t=972959520359311)/forums/show.html
+http://pike-community.org/(base=/forums/show.html,forum=7,show=423,t=972959520359311)/forums/show.html
+http://pike-community.org/(base=/forums/show.html,forum=7,show=761,t=972959520359311)/forums/show.html
+http://pike-community.org/(base=/forums/show.html,forum=7,show=777,t=972959520359311)/forums/show.html
+http://pike-community.org/(base=/forums/show.html,forum=7,show=831,t=972959520359311)/forums/show.html
+http://astro1.cnu.ac.kr/NetBBS/Bbs.dll/bulletin/qry/zka/B2-kC2Jo/qqa/r
+http://www.gbnf.com/genealog2/brothers/html/d0049/I1011.HTM
+http://www.intellicast.com/Golf/World/UnitedStates/Midwest/Ohio/Zanesville/CurrentWinds/
+http://www.nada.kth.se/systemgruppen/docs/javadoc/jdk-1.3/docs/api/javax/swing/text/class-use/TabSet.html
+http://www.my-cat.de/hunde/zucht/file24.htm
+http://194.128.65.4/pa/cm199899/cmwib/wb981128/edms.htm
+http://www.gutenberg2000.de/sagen/austria/tirol/adasbub.htm
+http://www1.onelist.com/message/osaki/22
+http://www.highwired.net/ESchoolDrive/JumpPage/1,5565,25179-46,00.html
+http://pcmagazin.de/download/library/deADW-wc.htm
+http://www.affiliate.hpstore.hp.co.uk/do/session/380873/vsid/1148/tid/1148/cid/74115/mid/1001/rid/1003/chid/1050/parser/yes/imref/eqqLmwlGltt5tkeHmjbHumlLkZl5jlcHol4/url/http://www.hp-creativeworld.com/creativeworld.asp?lang=f
+http://cscns.csc.gifu.gifu.jp/pushcorn-kit/tanigumi/paged/0300214020000147.html
+http://cscns.csc.gifu.gifu.jp/pushcorn-kit/tanigumi/paged/0300214020002363.html
+http://cscns.csc.gifu.gifu.jp/pushcorn-kit/tanigumi/paged/0300214020001617.html
+http://cpan.nitco.com/modules/by-module/String/MLEHMANN/?N=D
+http://www.rge.com/pub/tex/language/ethiopia/ethtex/lqh_fonts/
+http://130.158.208.53/WWW/PDB2/PCD4711/htmls/41.html
+http://www.thisislancashire.co.uk/lancashire/archive/1997/05/15/LEIGH0VQ.html
+http://www.thisislancashire.co.uk/lancashire/archive/1997/05/15/LEIGH10VQ.html
+http://southwind.tukids.tucows.com/mac/parents/adnload/72310_26093.html
+http://ftp1.support.compaq.com/public/vms/vax/v7.2/dsnlink/2.2/dsnlinke022.a-dcx_vaxexe
+http://wynnsystems.com/i.I_5aGd/search/listCompanies.html
+http://www.pobladores.com/territorios/juegos/Zhief_Fantasy_World/info
+http://www.pobladores.com/territorios/juegos/Zhief_Fantasy_World/pagina/9
+http://www.aebius.com/rpm2html/contrib/libc5/i386/usr_sbin_Tree.html
+http://info.rutgers.edu/cgi-bin/RUInfo/TallyStats/name=WebRequest&exec=buildlimit&limit=9,0-22,0-0,0-9,4
+http://polygraph.ircache.net:8181/services/define/http_-2www.fastcounter.com/noframes/specials.htm
+http://polygraph.ircache.net:8181/services/define/http_-2www.fastcounter.com/noframes/sitebuilder.htm
+http://www.jamba.nl/KNet/_KNet-7YT8j1-nD4-pxan/browse.nl/node.0/cdmvcam7k
+http://www.outdoorwire.com/content/lists/jeepoffroad/200010/msg00234.html?{LoadingFrameset}
+http://www-uk8.cricket.org/link_to_database/ARCHIVE/2000-01/ENG_IN_PAK/ENG_IN_PAK_OCT-DEC2000_ENG-SQUAD.html
+http://www-uk8.cricket.org/link_to_database/ARCHIVE/CRICKET_NEWS/2000/OCT/057670_CI_25OCT2000.html
+http://www.chaos.dk/sexriddle/c/c/e/k/
+http://ben.aspads.net/ex/c/190/608504034
+http://forum.rai.it/aca-finestre/dispatch.cgi/FORUM/folderFrame/100001/0/alpha/2040958
+http://www.teacherformation.org/html/od/facilitators.cfm/task1,help/discussion_id,2/xid,5237/yid,3113916
+http://www.mirror.edu.cn/res/www.isoc.org/inet98/proceedings/7d/
+http://www.sumthin.nu/archives/bugtraq/Nov_1998/msg00058.html
+http://proxy.tiscover.com/1Root/Kontinent/6/Staat/7/Bundesland/20/Regionen/regionen_az...2.html
+http://www.streetprices.com/products/sortdetailbylowprice/SP142252.html
+http://www.streetprices.com/products/sortdetailby1day/SP142252.html
+http://pp3.shef.ac.uk:4040/form/path=1,+%3A%22countryName%3DGB%40organizationName%3DUniversity+of+Sheffield%40organizationalUnitName%3DFinance%40commonName%3DS+Green%22
+http://travelocity-dest.excite.com/DestGuides/0,1840,TRAVELOCITY|2662|3|1|239114,00.html
+http://www.maastrek.de/maas/4a73999ddfd2d79be20a/1/0/5
+http://aol.weather.com/weather/cities/us_pa_fairview.html
+http://aol.weather.com/weather/cities/us_pa_fort_loudon.html
+http://javatest.a-net.nl/servlet/pedit.Main/http://www.tigerden.com/junkmail/compladdr.html
+http://ftp.dti.ad.jp/pub/windows/forest/file/backup/press1/?M=A
+http://www.contest.edu.tw/85/endshow/5/baseball/news/97feb/0225t_1c.html
+http://www.contest.edu.tw/85/endshow/5/baseball/news/97feb/0225c_3c.html
+http://www.contest.edu.tw/85/endshow/5/baseball/news/97feb/0217c_2c.html
+http://www.contest.edu.tw/85/endshow/5/baseball/news/97feb/0216c_play.html
+http://www.contest.edu.tw/85/endshow/5/baseball/news/97feb/0214co_1c.html
+http://preview.egroups.com/messages/decoratingplusnews/6
+http://astro1.chungnam.ac.kr/NetBBS/Bbs.dll/bulletin/rcm/zka/B2-kC23n/qqatt/^
\ No newline at end of file
diff --git a/snappy/snappy-1.0.5/testdata/xargs.1 b/snappy/snappy-1.0.5/testdata/xargs.1
new file mode 100644 (file)
index 0000000..a9f39a7
--- /dev/null
@@ -0,0 +1,112 @@
+.TH XARGS 1L \" -*- nroff -*-
+.SH NAME
+xargs \- build and execute command lines from standard input
+.SH SYNOPSIS
+.B xargs
+[\-0prtx] [\-e[eof-str]] [\-i[replace-str]] [\-l[max-lines]]
+[\-n max-args] [\-s max-chars] [\-P max-procs] [\-\-null] [\-\-eof[=eof-str]]
+[\-\-replace[=replace-str]] [\-\-max-lines[=max-lines]] [\-\-interactive]
+[\-\-max-chars=max-chars] [\-\-verbose] [\-\-exit] [\-\-max-procs=max-procs]
+[\-\-max-args=max-args] [\-\-no-run-if-empty] [\-\-version] [\-\-help]
+[command [initial-arguments]]
+.SH DESCRIPTION
+This manual page
+documents the GNU version of
+.BR xargs .
+.B xargs
+reads arguments from the standard input, delimited by blanks (which can be
+protected with double or single quotes or a backslash) or newlines,
+and executes the
+.I command
+(default is /bin/echo) one or more times with any
+.I initial-arguments
+followed by arguments read from standard input.  Blank lines on the
+standard input are ignored.
+.P
+.B xargs
+exits with the following status:
+.nf
+0 if it succeeds
+123 if any invocation of the command exited with status 1-125
+124 if the command exited with status 255
+125 if the command is killed by a signal
+126 if the command cannot be run
+127 if the command is not found
+1 if some other error occurred.
+.fi
+.SS OPTIONS
+.TP
+.I "\-\-null, \-0"
+Input filenames are terminated by a null character instead of by
+whitespace, and the quotes and backslash are not special (every
+character is taken literally).  Disables the end of file string, which
+is treated like any other argument.  Useful when arguments might
+contain white space, quote marks, or backslashes.  The GNU find
+\-print0 option produces input suitable for this mode.
+.TP
+.I "\-\-eof[=eof-str], \-e[eof-str]"
+Set the end of file string to \fIeof-str\fR.  If the end of file
+string occurs as a line of input, the rest of the input is ignored.
+If \fIeof-str\fR is omitted, there is no end of file string.  If this
+option is not given, the end of file string defaults to "_".
+.TP
+.I "\-\-help"
+Print a summary of the options to
+.B xargs
+and exit.
+.TP
+.I "\-\-replace[=replace-str], \-i[replace-str]"
+Replace occurences of \fIreplace-str\fR in the initial arguments with
+names read from standard input.
+Also, unquoted blanks do not terminate arguments.
+If \fIreplace-str\fR is omitted, it
+defaults to "{}" (like for `find \-exec').  Implies \fI\-x\fP and
+\fI\-l 1\fP.
+.TP
+.I "\-\-max-lines[=max-lines], -l[max-lines]"
+Use at most \fImax-lines\fR nonblank input lines per command line;
+\fImax-lines\fR defaults to 1 if omitted.  Trailing blanks cause an
+input line to be logically continued on the next input line.  Implies
+\fI\-x\fR.
+.TP
+.I "\-\-max-args=max-args, \-n max-args"
+Use at most \fImax-args\fR arguments per command line.  Fewer than
+\fImax-args\fR arguments will be used if the size (see the \-s option)
+is exceeded, unless the \-x option is given, in which case \fBxargs\fR
+will exit.
+.TP
+.I "\-\-interactive, \-p"
+Prompt the user about whether to run each command line and read a line
+from the terminal.  Only run the command line if the response starts
+with `y' or `Y'.  Implies \fI\-t\fR.
+.TP
+.I "\-\-no-run-if-empty, \-r"
+If the standard input does not contain any nonblanks, do not run the
+command.  Normally, the command is run once even if there is no input.
+.TP
+.I "\-\-max-chars=max-chars, \-s max-chars"
+Use at most \fImax-chars\fR characters per command line, including the
+command and initial arguments and the terminating nulls at the ends of
+the argument strings.  The default is as large as possible, up to 20k
+characters.
+.TP
+.I "\-\-verbose, \-t"
+Print the command line on the standard error output before executing
+it.
+.TP
+.I "\-\-version"
+Print the version number of
+.B xargs
+and exit.
+.TP
+.I "\-\-exit, \-x"
+Exit if the size (see the \fI\-s\fR option) is exceeded.
+.TP
+.I "\-\-max-procs=max-procs, \-P max-procs"
+Run up to \fImax-procs\fR processes at a time; the default is 1.  If
+\fImax-procs\fR is 0, \fBxargs\fR will run as many processes as
+possible at a time.  Use the \fI\-n\fR option with \fI\-P\fR;
+otherwise chances are that only one exec will be done.
+.SH "SEE ALSO"
+\fBfind\fP(1L), \fBlocate\fP(1L), \fBlocatedb\fP(5L), \fBupdatedb\fP(1)
+\fBFinding Files\fP (on-line in Info, or printed)
diff --git a/snappy/snappy-stubs-public.h b/snappy/snappy-stubs-public.h
new file mode 120000 (symlink)
index 0000000..46987f1
--- /dev/null
@@ -0,0 +1 @@
+snappy-1.0.5/snappy-stubs-public.h
\ No newline at end of file
diff --git a/snappy/snappy.h b/snappy/snappy.h
new file mode 120000 (symlink)
index 0000000..ae5bee7
--- /dev/null
@@ -0,0 +1 @@
+snappy-1.0.5/snappy.h
\ No newline at end of file
diff --git a/static/facebookcode.png b/static/facebookcode.png
new file mode 100644 (file)
index 0000000..01944c6
Binary files /dev/null and b/static/facebookcode.png differ
diff --git a/static/favicon.ico b/static/favicon.ico
new file mode 100644 (file)
index 0000000..fdd809e
Binary files /dev/null and b/static/favicon.ico differ
diff --git a/static/fbos.css b/static/fbos.css
new file mode 100644 (file)
index 0000000..74c6b34
--- /dev/null
@@ -0,0 +1,250 @@
+/* mobile first */
+
+* {
+    padding: 0;
+    margin: 0;
+}
+
+html {
+    -webkit-font-smoothing: antialiased;
+    background-color: #fafafa;
+}
+
+body {
+    font-family: 'Helvetica Neue', Helvetica, Arial, 'lucida grande', tahoma, verdana, arial, sans-serif;
+    color: #222222;
+    margin: 0;
+    line-height: 1.5em;
+}
+
+h1, h2, h3, h4 {
+    color: #374665;
+    font-weight: normal;
+    margin: 1.5em 0 0.5em;
+}
+
+h1:first-child, h2:first-child, h3:first-child, h4:first-child {
+    margin-top: 0;
+}
+
+h1 {
+    font-size: 1.5em;
+}
+
+h2 {
+    font-size: 1.4em;
+}
+
+h3 {
+    font-size: 1.3em;
+}
+
+h4 {
+    font-size: 1.2em;
+}
+
+p, pre, ul {
+    margin: 1em 0;
+}
+
+p {
+    text-align: justify;
+}
+
+pre {
+    border: 1px solid #ccc;
+    padding: 1em;
+    overflow-x: scroll;
+    background: #fff;
+    border-radius: 5px;
+}
+
+ul {
+    list-style-position: inside;
+    line-height: 2em;
+}
+
+a {
+    text-decoration: none;
+    font-weight: bold;
+    color: #3b5998;
+}
+
+.width {
+    margin: 0 auto !important;
+    padding: 0 20px !important;
+}
+
+header:after, section.content:after, footer:after {
+    clear: both;
+    content: ".";
+    display: block;
+    font-size: 0;
+    height: 0;
+    line-height: 0;
+    visibility: hidden;
+}
+
+header.topbar {
+    background: #000;
+    padding: 10px 0;
+}
+
+header.topbar h1 {
+    background-image: url(facebookcode.png);
+    background-size: 123px 16px;
+    background-position: 0 50%;
+    background-repeat: no-repeat;
+    float: left;
+    line-height: 60px;
+    margin: 0 10px 0 0;
+    overflow: hidden;
+    text-indent: 100%;
+    white-space: nowrap;
+    width: 240px;
+}
+
+header.topbar nav ul {
+    float: right;
+    text-align: right;
+    margin: 0 0 0 10px;
+    padding: 0;
+}
+
+header.topbar nav ul li {
+    display: inline;
+    text-transform: uppercase;
+}
+
+header.topbar nav ul li a {
+    color: #fff;
+    font-size: 12px;
+    margin: 0 0 0 10px;
+    text-decoration: none;
+    font-weight: bold;
+    line-height: 60px;
+}
+
+header.topbar nav ul li a.active {
+    color: #3b5998;
+}
+
+header.hero {
+    background: #374665;
+    padding: 20px 0;
+}
+
+header.hero hgroup h1 {
+    font-size: 2em;
+    font-weight: normal;
+    color: #fff;
+    margin: 0;
+    line-height: 2em;
+}
+
+header.hero hgroup a.button {
+    background: #102747;
+    color: #fff;
+    font-weight: bold;
+    text-transform: uppercase;
+    padding: 10px 20px;
+    border-radius: 5px;
+    display: inline-block;
+    margin-top: 1em;
+}
+
+header.hero aside {
+    display: none;
+}
+
+header.hero aside * {
+    max-width: 100%;
+}
+
+section.content {
+    padding: 30px 0;
+}
+
+section.content article h2 {
+    color: #888888;
+    font-weight: bold;
+}
+
+section.content article img {
+    display: block;
+    margin: 1em auto;
+}
+
+section.content article blockquote {
+    padding: 0px 20px;
+    margin: 0 0 20px;
+    border-left: 5px solid #eee;
+}
+
+section.content article blockquote p {
+    font-style: italic;
+}
+
+section.content article blockquote small:before {
+    content: '\2014 \00A0';
+}
+
+section.content aside .fb-like {
+    top: 4px;
+    left: 4px;
+}
+
+footer {
+    background: #000;
+    padding: 10px 0;
+    color: #fff;
+}
+
+/* tabletish */
+
+@media (min-width: 480px) {
+
+    header.topbar nav ul li a {
+        font-weight: bold;
+        letter-spacing: 0.1em;
+        margin-left: 20px;
+    }
+
+}
+
+/* desktopish */
+
+@media (min-width: 1000px) {
+
+    header.topbar nav ul li a {
+        font-size: 15px;
+        margin-left: 30px;
+    }
+
+    .width {
+        width: 960px;
+        /* make columns add to <880 for 60 gutter */
+    }
+
+    header.hero hgroup {
+        float: left;
+        width: 440px;
+    }
+
+    header.hero aside {
+        display: block;
+        float: right;
+        width: 440px;
+    }
+
+    section.content article {
+        float: left;
+        width: 660px;
+    }
+
+    section.content aside {
+        float: right;
+        width: 220px;
+    }
+
+}
diff --git a/static/rocksdb.css b/static/rocksdb.css
new file mode 100644 (file)
index 0000000..76b535a
--- /dev/null
@@ -0,0 +1,24 @@
+@import url("fbos.css");
+
+header.topbar h1 {
+    background-image: url(rocksdb.png);
+    background-size: 188px 55px;
+}
+
+header.hero {
+    background: #FFE084;
+}
+
+header.hero hgroup h1 {
+    color: #000;
+}
+
+header.hero hgroup a.button {
+    background: #000;
+    color: #ffbe00;
+}
+
+header.hero aside img {
+    border: solid 1px #fff;
+    box-shadow: 0 2px 10px #000;
+}
\ No newline at end of file
diff --git a/static/rocksdb.png b/static/rocksdb.png
new file mode 100644 (file)
index 0000000..4e2759e
Binary files /dev/null and b/static/rocksdb.png differ
diff --git a/static/rocksdbhero.png b/static/rocksdbhero.png
new file mode 100644 (file)
index 0000000..9c7f632
Binary files /dev/null and b/static/rocksdbhero.png differ
diff --git a/table/block.cc b/table/block.cc
new file mode 100644 (file)
index 0000000..3f969fe
--- /dev/null
@@ -0,0 +1,274 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+//
+// Decodes the blocks generated by block_builder.cc.
+
+#include "table/block.h"
+
+#include <vector>
+#include <algorithm>
+#include "rocksdb/comparator.h"
+#include "table/format.h"
+#include "util/coding.h"
+#include "util/logging.h"
+
+namespace rocksdb {
+
+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),
+      cachable_(contents.cachable),
+      compression_type_(contents.compression_type) {
+  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<const unsigned char*>(p)[0];
+  *non_shared = reinterpret_cast<const unsigned char*>(p)[1];
+  *value_length = reinterpret_cast<const unsigned char*>(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<uint32_t>(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 rocksdb
diff --git a/table/block.h b/table/block.h
new file mode 100644 (file)
index 0000000..7fac006
--- /dev/null
@@ -0,0 +1,51 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <stddef.h>
+#include <stdint.h>
+#include "rocksdb/iterator.h"
+#include "rocksdb/options.h"
+
+namespace rocksdb {
+
+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_; }
+  bool   isCachable() const { return cachable_; }
+  CompressionType compressionType() const { return compression_type_; }
+  Iterator* NewIterator(const Comparator* comparator);
+  const char* data() { return data_; }
+
+ 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_[]
+  bool cachable_;
+  CompressionType compression_type_;
+
+  // No copying allowed
+  Block(const Block&);
+  void operator=(const Block&);
+
+  class Iter;
+};
+
+}  // namespace rocksdb
diff --git a/table/block_based_table_builder.cc b/table/block_based_table_builder.cc
new file mode 100644 (file)
index 0000000..55a2e3d
--- /dev/null
@@ -0,0 +1,506 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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/block_based_table_builder.h"
+
+#include <assert.h>
+#include <map>
+
+#include "rocksdb/flush_block_policy.h"
+#include "rocksdb/cache.h"
+#include "rocksdb/comparator.h"
+#include "rocksdb/table.h"
+#include "rocksdb/env.h"
+#include "rocksdb/filter_policy.h"
+#include "rocksdb/options.h"
+#include "table/block_based_table_reader.h"
+#include "table/block.h"
+#include "table/block_builder.h"
+#include "table/filter_block.h"
+#include "table/format.h"
+#include "util/coding.h"
+#include "util/crc32c.h"
+#include "util/stop_watch.h"
+
+namespace rocksdb {
+
+namespace {
+
+struct BytewiseLessThan {
+  bool operator()(const std::string& key1, const std::string& key2) const {
+    // smaller entries will be placed in front.
+    return comparator->Compare(key1, key2) <= 0;
+  }
+  const Comparator* comparator = BytewiseComparator();
+};
+
+// When writing to a block that requires entries to be sorted by
+// `BytewiseComparator`, we can buffer the content to `BytewiseSortedMap`
+// before writng to store.
+typedef std::map<std::string, std::string, BytewiseLessThan> BytewiseSortedMap;
+
+void AddStats(BytewiseSortedMap& stats, std::string name, uint64_t val) {
+  assert(stats.find(name) == stats.end());
+
+  std::string dst;
+  PutVarint64(&dst, val);
+
+  stats.insert(
+      std::make_pair(name, dst)
+  );
+}
+
+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);
+}
+
+// Were we encounter any error occurs during user-defined statistics collection,
+// we'll write the warning message to info log.
+void LogStatsCollectionError(
+    Logger* info_log, const std::string& method, const std::string& name) {
+  assert(method == "Add" || method == "Finish");
+
+  std::string msg =
+    "[Warning] encountered error when calling TableStatsCollector::" +
+    method + "() with collector name: " + name;
+  Log(info_log, "%s", msg.c_str());
+}
+
+}  // anonymous namespace
+
+struct BlockBasedTableBuilder::Rep {
+  Options options;
+  Options index_block_options;
+  WritableFile* file;
+  uint64_t offset = 0;
+  Status status;
+  BlockBuilder data_block;
+  BlockBuilder index_block;
+  std::string last_key;
+  CompressionType compression_type;
+
+  uint64_t num_entries = 0;
+  uint64_t num_data_blocks = 0;
+  uint64_t raw_key_size = 0;
+  uint64_t raw_value_size = 0;
+  uint64_t data_size = 0;
+
+  bool closed = false;  // Either Finish() or Abandon() has been called.
+  FilterBlockBuilder* filter_block;
+  char compressed_cache_key_prefix[BlockBasedTable::kMaxCacheKeyPrefixSize];
+  size_t compressed_cache_key_prefix_size;
+
+
+  BlockHandle pending_handle;  // Handle to add to index block
+
+  std::string compressed_output;
+  std::unique_ptr<FlushBlockPolicy> flush_block_policy;
+
+  Rep(const Options& opt, WritableFile* f, CompressionType compression_type)
+      : options(opt),
+        index_block_options(opt),
+        file(f),
+        data_block(&options),
+        index_block(1, index_block_options.comparator),
+        compression_type(compression_type),
+        filter_block(opt.filter_policy == nullptr ? nullptr
+                     : new FilterBlockBuilder(opt)) {
+    assert(options.flush_block_policy_factory);
+    auto factory = options.flush_block_policy_factory;
+    flush_block_policy.reset(factory->NewFlushBlockPolicy(data_block));
+  }
+};
+
+BlockBasedTableBuilder::BlockBasedTableBuilder(const Options& options,
+                                               WritableFile* file,
+                                               CompressionType compression_type)
+    : rep_(new Rep(options, file, compression_type)) {
+  if (rep_->filter_block != nullptr) {
+    rep_->filter_block->StartBlock(0);
+  }
+  if (options.block_cache_compressed.get() != nullptr) {
+    BlockBasedTable::GenerateCachePrefix(options.block_cache_compressed, file,
+                               &rep_->compressed_cache_key_prefix[0],
+                               &rep_->compressed_cache_key_prefix_size);
+  }
+}
+
+BlockBasedTableBuilder::~BlockBasedTableBuilder() {
+  assert(rep_->closed);  // Catch errors where caller forgot to call Finish()
+  delete rep_->filter_block;
+  delete rep_;
+}
+
+void BlockBasedTableBuilder::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);
+  }
+
+  auto should_flush = r->flush_block_policy->Update(key, value);
+  if (should_flush) {
+    assert(!r->data_block.empty());
+    Flush();
+
+    // Add item to index 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.
+    if (ok()) {
+      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));
+    }
+  }
+
+  if (r->filter_block != nullptr) {
+    r->filter_block->AddKey(key);
+  }
+
+  r->last_key.assign(key.data(), key.size());
+  r->data_block.Add(key, value);
+  r->num_entries++;
+  r->raw_key_size += key.size();
+  r->raw_value_size += value.size();
+
+  for (auto collector : r->options.table_stats_collectors) {
+    Status s = collector->Add(key, value);
+    if (!s.ok()) {
+      LogStatsCollectionError(
+          r->options.info_log.get(),
+          "Add", /* method */
+          collector->Name()
+      );
+    }
+  }
+}
+
+void BlockBasedTableBuilder::Flush() {
+  Rep* r = rep_;
+  assert(!r->closed);
+  if (!ok()) return;
+  if (r->data_block.empty()) return;
+  WriteBlock(&r->data_block, &r->pending_handle);
+  if (ok()) {
+    r->status = r->file->Flush();
+  }
+  if (r->filter_block != nullptr) {
+    r->filter_block->StartBlock(r->offset);
+  }
+  r->data_size = r->offset;
+  ++r->num_data_blocks;
+}
+
+void BlockBasedTableBuilder::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 = r->compression_type;
+  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 BlockBasedTableBuilder::WriteRawBlock(const Slice& block_contents,
+                                           CompressionType type,
+                                           BlockHandle* handle) {
+  Rep* r = rep_;
+  StopWatch sw(r->options.env, r->options.statistics, WRITE_RAW_BLOCK_MICROS);
+  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->status = InsertBlockInCache(block_contents, type, handle);
+    }
+    if (r->status.ok()) {
+      r->offset += block_contents.size() + kBlockTrailerSize;
+    }
+  }
+}
+
+Status BlockBasedTableBuilder::status() const {
+  return rep_->status;
+}
+
+static void DeleteCachedBlock(const Slice& key, void* value) {
+  Block* block = reinterpret_cast<Block*>(value);
+  delete block;
+}
+
+//
+// Make a copy of the block contents and insert into compressed block cache
+//
+Status BlockBasedTableBuilder::InsertBlockInCache(const Slice& block_contents,
+                                 const CompressionType type,
+                                 const BlockHandle* handle) {
+  Rep* r = rep_;
+  Cache* block_cache_compressed = r->options.block_cache_compressed.get();
+
+  if (type != kNoCompression && block_cache_compressed != nullptr) {
+
+    Cache::Handle* cache_handle = nullptr;
+    size_t size = block_contents.size();
+
+    char* ubuf = new char[size];             // make a new copy
+    memcpy(ubuf, block_contents.data(), size);
+
+    BlockContents results;
+    Slice sl(ubuf, size);
+    results.data = sl;
+    results.cachable = true; // XXX
+    results.heap_allocated = true;
+    results.compression_type = type;
+
+    Block* block = new Block(results);
+
+    // make cache key by appending the file offset to the cache prefix id
+    char* end = EncodeVarint64(
+                  r->compressed_cache_key_prefix +
+                  r->compressed_cache_key_prefix_size,
+                  handle->offset());
+    Slice key(r->compressed_cache_key_prefix, static_cast<size_t>
+              (end - r->compressed_cache_key_prefix));
+
+    // Insert into compressed block cache.
+    cache_handle = block_cache_compressed->Insert(key, block, block->size(),
+                                                  &DeleteCachedBlock);
+    block_cache_compressed->Release(cache_handle);
+
+    // Invalidate OS cache.
+    r->file->InvalidateCache(r->offset, size);
+  }
+  return Status::OK();
+}
+
+Status BlockBasedTableBuilder::Finish() {
+  Rep* r = rep_;
+  bool empty_data_block = r->data_block.empty();
+  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);
+  }
+
+  // To make sure stats block is able to keep the accurate size of index
+  // block, we will finish writing all index entries here and flush them
+  // to storage after metaindex block is written.
+  if (ok() && !empty_data_block) {
+    r->options.comparator->FindShortSuccessor(&r->last_key);
+
+    std::string handle_encoding;
+    r->pending_handle.EncodeTo(&handle_encoding);
+    r->index_block.Add(r->last_key, handle_encoding);
+  }
+
+  // Write meta blocks and metaindex block with the following order.
+  //    1. [meta block: filter]
+  //    2. [meta block: stats]
+  //    3. [metaindex block]
+  if (ok()) {
+    // We use `BytewiseComparator` as the comparator for meta block.
+    BlockBuilder meta_index_block(
+        r->options.block_restart_interval,
+        BytewiseComparator()
+    );
+    // Key: meta block name
+    // Value: block handle to that meta block
+    BytewiseSortedMap meta_block_handles;
+
+    // Write filter block.
+    if (r->filter_block != nullptr) {
+      // Add mapping from "<filter_block_prefix>.Name" to location
+      // of filter data.
+      std::string key = BlockBasedTable::kFilterBlockPrefix;
+      key.append(r->options.filter_policy->Name());
+      std::string handle_encoding;
+      filter_block_handle.EncodeTo(&handle_encoding);
+      meta_block_handles.insert(
+          std::make_pair(key, handle_encoding)
+      );
+    }
+
+    // Write stats block.
+    {
+      BlockBuilder stats_block(
+          r->options.block_restart_interval,
+          BytewiseComparator()
+      );
+
+      BytewiseSortedMap stats;
+
+      // Add basic stats
+      AddStats(stats, BlockBasedTableStatsNames::kRawKeySize, r->raw_key_size);
+      AddStats(stats, BlockBasedTableStatsNames::kRawValueSize,
+               r->raw_value_size);
+      AddStats(stats, BlockBasedTableStatsNames::kDataSize, r->data_size);
+      AddStats(
+          stats,
+          BlockBasedTableStatsNames::kIndexSize,
+          r->index_block.CurrentSizeEstimate() + kBlockTrailerSize
+      );
+      AddStats(stats, BlockBasedTableStatsNames::kNumEntries, r->num_entries);
+      AddStats(stats, BlockBasedTableStatsNames::kNumDataBlocks,
+               r->num_data_blocks);
+      if (r->filter_block != nullptr) {
+        stats.insert(std::make_pair(
+              BlockBasedTableStatsNames::kFilterPolicy,
+              r->options.filter_policy->Name()
+        ));
+      }
+
+      for (auto collector : r->options.table_stats_collectors) {
+        TableStats::UserCollectedStats user_collected_stats;
+        Status s =
+          collector->Finish(&user_collected_stats);
+
+        if (!s.ok()) {
+          LogStatsCollectionError(
+              r->options.info_log.get(),
+              "Finish", /* method */
+              collector->Name()
+          );
+        } else {
+          stats.insert(
+              user_collected_stats.begin(),
+              user_collected_stats.end()
+          );
+        }
+      }
+
+      for (const auto& stat : stats) {
+        stats_block.Add(stat.first, stat.second);
+      }
+
+      BlockHandle stats_block_handle;
+      WriteBlock(&stats_block, &stats_block_handle);
+
+      std::string handle_encoding;
+      stats_block_handle.EncodeTo(&handle_encoding);
+      meta_block_handles.insert(
+          std::make_pair(BlockBasedTable::kStatsBlock, handle_encoding)
+      );
+    }  // end of stats block writing
+
+    for (const auto& metablock : meta_block_handles) {
+      meta_index_block.Add(metablock.first, metablock.second);
+    }
+
+    WriteBlock(&meta_index_block, &metaindex_block_handle);
+  }  // meta blocks and metaindex block.
+
+  // Write index block
+  if (ok()) {
+    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 BlockBasedTableBuilder::Abandon() {
+  Rep* r = rep_;
+  assert(!r->closed);
+  r->closed = true;
+}
+
+uint64_t BlockBasedTableBuilder::NumEntries() const {
+  return rep_->num_entries;
+}
+
+uint64_t BlockBasedTableBuilder::FileSize() const {
+  return rep_->offset;
+}
+
+}  // namespace rocksdb
diff --git a/table/block_based_table_builder.h b/table/block_based_table_builder.h
new file mode 100644 (file)
index 0000000..87307a0
--- /dev/null
@@ -0,0 +1,82 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <stdint.h>
+#include "rocksdb/options.h"
+#include "rocksdb/status.h"
+#include "rocksdb/table.h"
+
+namespace rocksdb {
+
+class BlockBuilder;
+class BlockHandle;
+class WritableFile;
+
+
+class BlockBasedTableBuilder : public 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().
+  BlockBasedTableBuilder(const Options& options, WritableFile* file,
+                         CompressionType compression_type);
+
+  // REQUIRES: Either Finish() or Abandon() has been called.
+  ~BlockBasedTableBuilder();
+
+  // 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) override;
+
+  // Return non-ok iff some error has been detected.
+  Status status() const override;
+
+  // 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() override;
+
+  // 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() override;
+
+  // Number of calls to Add() so far.
+  uint64_t NumEntries() const override;
+
+  // 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 override;
+
+ private:
+  bool ok() const { return status().ok(); }
+  void WriteBlock(BlockBuilder* block, BlockHandle* handle);
+  void WriteRawBlock(const Slice& data, CompressionType, BlockHandle* handle);
+  Status InsertBlockInCache(const Slice& block_contents,
+                         const CompressionType type, const BlockHandle* handle);
+  struct Rep;
+  Rep* rep_;
+
+  // 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();
+
+  // No copying allowed
+  BlockBasedTableBuilder(const BlockBasedTableBuilder&) = delete;
+  void operator=(const BlockBasedTableBuilder&) = delete;
+};
+
+}  // namespace rocksdb
+
diff --git a/table/block_based_table_factory.cc b/table/block_based_table_factory.cc
new file mode 100644 (file)
index 0000000..0944c7f
--- /dev/null
@@ -0,0 +1,34 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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/block_based_table_factory.h"
+
+#include <memory>
+#include <stdint.h>
+#include "table/block_based_table_builder.h"
+#include "table/block_based_table_reader.h"
+#include "port/port.h"
+
+namespace rocksdb {
+
+Status BlockBasedTableFactory::GetTableReader(
+    const Options& options, const EnvOptions& soptions,
+    unique_ptr<RandomAccessFile> && file, uint64_t file_size,
+    unique_ptr<TableReader>* table_reader) const {
+  return BlockBasedTable::Open(options, soptions, std::move(file), file_size,
+                               table_reader);
+}
+
+TableBuilder* BlockBasedTableFactory::GetTableBuilder(
+    const Options& options, WritableFile* file,
+    CompressionType compression_type) const {
+  return new BlockBasedTableBuilder(options, file, compression_type);
+}
+}  // namespace rocksdb
diff --git a/table/block_based_table_factory.h b/table/block_based_table_factory.h
new file mode 100644 (file)
index 0000000..677979f
--- /dev/null
@@ -0,0 +1,49 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <memory>
+#include <stdint.h>
+
+#include "rocksdb/table.h"
+
+namespace rocksdb {
+
+struct Options;
+struct EnvOptions;
+
+using std::unique_ptr;
+class Status;
+class RandomAccessFile;
+class WritableFile;
+class Table;
+class TableBuilder;
+class BlockBasedTable;
+class BlockBasedTableBuilder;
+
+class BlockBasedTableFactory: public TableFactory {
+public:
+  ~BlockBasedTableFactory() {
+  }
+  BlockBasedTableFactory() {
+  }
+  const char* Name() const override {
+    return "BlockBasedTable";
+  }
+  Status GetTableReader(const Options& options, const EnvOptions& soptions,
+                        unique_ptr<RandomAccessFile> && file,
+                        uint64_t file_size,
+                        unique_ptr<TableReader>* table_reader) const override;
+
+  TableBuilder* GetTableBuilder(const Options& options, WritableFile* file,
+                                CompressionType compression_type) const
+                                    override;
+};
+
+}  // namespace rocksdb
diff --git a/table/block_based_table_reader.cc b/table/block_based_table_reader.cc
new file mode 100644 (file)
index 0000000..4a45be6
--- /dev/null
@@ -0,0 +1,1085 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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/block_based_table_reader.h"
+
+#include "db/dbformat.h"
+
+#include "rocksdb/comparator.h"
+#include "rocksdb/env.h"
+#include "rocksdb/filter_policy.h"
+#include "rocksdb/options.h"
+#include "rocksdb/statistics.h"
+#include "rocksdb/table.h"
+
+#include "table/block.h"
+#include "table/filter_block.h"
+#include "table/format.h"
+#include "table/two_level_iterator.h"
+
+#include "util/coding.h"
+#include "util/perf_context_imp.h"
+#include "util/stop_watch.h"
+
+namespace rocksdb {
+
+// 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;
+using std::unique_ptr;
+
+struct BlockBasedTable::Rep {
+  Rep(const EnvOptions& storage_options) :
+    soptions(storage_options) {
+  }
+
+  Options options;
+  const EnvOptions& soptions;
+  Status status;
+  unique_ptr<RandomAccessFile> file;
+  char cache_key_prefix[kMaxCacheKeyPrefixSize];
+  size_t cache_key_prefix_size;
+  char compressed_cache_key_prefix[kMaxCacheKeyPrefixSize];
+  size_t compressed_cache_key_prefix_size;
+
+  // Handle to metaindex_block: saved from footer
+  BlockHandle metaindex_handle;
+  // Handle to index: saved from footer
+  BlockHandle index_handle;
+  // index_block will be populated and used only when options.block_cache is
+  // NULL; otherwise we will get the index block via the block cache.
+  unique_ptr<Block> index_block;
+  unique_ptr<FilterBlockReader> filter;
+
+  TableStats table_stats;
+};
+
+BlockBasedTable::~BlockBasedTable() {
+  delete rep_;
+}
+
+// CachableEntry represents the entries that *may* be fetched from block cache.
+//  field `value` is the item we want to get.
+//  field `cache_handle` is the cache handle to the block cache. If the value
+//    was not read from cache, `cache_handle` will be nullptr.
+template <class TValue>
+struct BlockBasedTable::CachableEntry {
+  CachableEntry(TValue* value, Cache::Handle* cache_handle)
+    : value(value)
+    , cache_handle(cache_handle) {
+  }
+  CachableEntry(): CachableEntry(nullptr, nullptr) { }
+  void Release(Cache* cache) {
+    if (cache_handle) {
+      cache->Release(cache_handle);
+      value = nullptr;
+      cache_handle = nullptr;
+    }
+  }
+
+  TValue* value = nullptr;
+  // if the entry is from the cache, cache_handle will be populated.
+  Cache::Handle* cache_handle = nullptr;
+};
+
+// Helper function to setup the cache key's prefix for the Table.
+void BlockBasedTable::SetupCacheKeyPrefix(Rep* rep) {
+  assert(kMaxCacheKeyPrefixSize >= 10);
+  rep->cache_key_prefix_size = 0;
+  rep->compressed_cache_key_prefix_size = 0;
+  if (rep->options.block_cache != nullptr) {
+    GenerateCachePrefix(rep->options.block_cache, rep->file.get(),
+                        &rep->cache_key_prefix[0],
+                        &rep->cache_key_prefix_size);
+  }
+  if (rep->options.block_cache_compressed != nullptr) {
+    GenerateCachePrefix(rep->options.block_cache_compressed, rep->file.get(),
+                        &rep->compressed_cache_key_prefix[0],
+                        &rep->compressed_cache_key_prefix_size);
+  }
+}
+
+void BlockBasedTable::GenerateCachePrefix(shared_ptr<Cache> cc,
+    RandomAccessFile* file, char* buffer, size_t* size) {
+
+  // generate an id from the file
+  *size = file->GetUniqueId(buffer, kMaxCacheKeyPrefixSize);
+
+  // If the prefix wasn't generated or was too long,
+  // create one from the cache.
+  if (*size == 0) {
+    char* end = EncodeVarint64(buffer, cc->NewId());
+    *size = static_cast<size_t>(end - buffer);
+  }
+}
+
+void BlockBasedTable::GenerateCachePrefix(shared_ptr<Cache> cc,
+    WritableFile* file, char* buffer, size_t* size) {
+
+  // generate an id from the file
+  *size = file->GetUniqueId(buffer, kMaxCacheKeyPrefixSize);
+
+  // If the prefix wasn't generated or was too long,
+  // create one from the cache.
+  if (*size == 0) {
+    char* end = EncodeVarint64(buffer, cc->NewId());
+    *size = static_cast<size_t>(end - buffer);
+  }
+}
+
+namespace {  // anonymous namespace, not visible externally
+
+// Read the block identified by "handle" from "file".
+// The only relevant option is options.verify_checksums for now.
+// Set *didIO to true if didIO is not null.
+// On failure return non-OK.
+// On success fill *result and return OK - caller owns *result
+Status ReadBlockFromFile(
+    RandomAccessFile* file,
+    const ReadOptions& options,
+    const BlockHandle& handle,
+    Block** result,
+    Env* env,
+    bool* didIO = nullptr,
+    bool do_uncompress = true) {
+  BlockContents contents;
+  Status s = ReadBlockContents(file, options, handle, &contents,
+                               env, do_uncompress);
+  if (s.ok()) {
+    *result = new Block(contents);
+  }
+
+  if (didIO) {
+    *didIO = true;
+  }
+  return s;
+}
+
+void DeleteBlock(void* arg, void* ignored) {
+  delete reinterpret_cast<Block*>(arg);
+}
+
+void DeleteCachedBlock(const Slice& key, void* value) {
+  Block* block = reinterpret_cast<Block*>(value);
+  delete block;
+}
+
+void DeleteCachedFilter(const Slice& key, void* value) {
+  auto filter = reinterpret_cast<FilterBlockReader*>(value);
+  delete filter;
+}
+
+void ReleaseBlock(void* arg, void* h) {
+  Cache* cache = reinterpret_cast<Cache*>(arg);
+  Cache::Handle* handle = reinterpret_cast<Cache::Handle*>(h);
+  cache->Release(handle);
+}
+
+Slice GetCacheKey(const char* cache_key_prefix,
+                  size_t cache_key_prefix_size,
+                  const BlockHandle& handle,
+                  char* cache_key) {
+  assert(cache_key != nullptr);
+  assert(cache_key_prefix_size != 0);
+  assert(cache_key_prefix_size <= kMaxCacheKeyPrefixSize);
+  memcpy(cache_key, cache_key_prefix, cache_key_prefix_size);
+  char* end = EncodeVarint64(cache_key + cache_key_prefix_size,
+                             handle.offset());
+  return Slice(cache_key, static_cast<size_t>(end - cache_key));
+}
+
+Cache::Handle* GetFromBlockCache(
+    Cache* block_cache,
+    const Slice& key,
+    Tickers block_cache_miss_ticker,
+    Tickers block_cache_hit_ticker,
+    std::shared_ptr<Statistics> statistics) {
+  auto cache_handle = block_cache->Lookup(key);
+  if (cache_handle != nullptr) {
+    BumpPerfCount(&perf_context.block_cache_hit_count);
+    // overall cache hit
+    RecordTick(statistics, BLOCK_CACHE_HIT);
+    // block-type specific cache hit
+    RecordTick(statistics, block_cache_hit_ticker);
+  } else {
+    // overall cache miss
+    RecordTick(statistics, BLOCK_CACHE_MISS);
+    // block-type specific cache miss
+    RecordTick(statistics, block_cache_miss_ticker);
+  }
+
+  return cache_handle;
+}
+
+} // end of anonymous namespace
+
+Status BlockBasedTable::Open(const Options& options,
+                             const EnvOptions& soptions,
+                             unique_ptr<RandomAccessFile> && file,
+                             uint64_t size,
+                             unique_ptr<TableReader>* table_reader) {
+  table_reader->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;
+
+  // We've successfully read the footer and the index block: we're
+  // ready to serve requests.
+  Rep* rep = new BlockBasedTable::Rep(soptions);
+  rep->options = options;
+  rep->file = std::move(file);
+  rep->metaindex_handle = footer.metaindex_handle();
+  rep->index_handle = footer.index_handle();
+  SetupCacheKeyPrefix(rep);
+  unique_ptr<BlockBasedTable> new_table(new BlockBasedTable(rep));
+
+  // Read meta index
+  std::unique_ptr<Block> meta;
+  std::unique_ptr<Iterator> meta_iter;
+  s = ReadMetaBlock(rep, &meta, &meta_iter);
+
+  // Read the stats
+  meta_iter->Seek(kStatsBlock);
+  if (meta_iter->Valid() && meta_iter->key() == Slice(kStatsBlock)) {
+    s = meta_iter->status();
+    if (s.ok()) {
+      s = ReadStats(meta_iter->value(), rep, &rep->table_stats);
+    }
+
+    if (!s.ok()) {
+      auto err_msg =
+        "[Warning] Encountered error while reading data from stats block " +
+        s.ToString();
+      Log(rep->options.info_log, err_msg.c_str());
+    }
+  }
+
+  // Initialize index/filter blocks. If block cache is not specified,
+  // these blocks will be kept in member variables in Rep, which will
+  // reside in the memory as long as this table object is alive; otherwise
+  // they will be added to block cache.
+  if (!options.block_cache) {
+    Block* index_block = nullptr;
+    // TODO: we never really verify check sum for index block
+    s = ReadBlockFromFile(
+        rep->file.get(),
+        ReadOptions(),
+        footer.index_handle(),
+        &index_block,
+        options.env
+    );
+
+    if (s.ok()) {
+      assert(index_block->compressionType() == kNoCompression);
+      rep->index_block.reset(index_block);
+
+      // Set index block
+      if (rep->options.filter_policy) {
+        std::string key = kFilterBlockPrefix;
+        key.append(rep->options.filter_policy->Name());
+        meta_iter->Seek(key);
+
+        if (meta_iter->Valid() && meta_iter->key() == Slice(key)) {
+          rep->filter.reset(ReadFilter(meta_iter->value(), rep));
+        }
+      }
+    } else {
+      delete index_block;
+    }
+  } else {
+    // Call IndexBlockReader() to implicitly add index to the block_cache
+    unique_ptr<Iterator> iter(
+        new_table->IndexBlockReader(ReadOptions())
+    );
+    s = iter->status();
+
+    if (s.ok()) {
+      // Call GetFilter() to implicitly add filter to the block_cache
+      auto filter_entry = new_table->GetFilter();
+      filter_entry.Release(options.block_cache.get());
+    }
+  }
+
+  if (s.ok()) {
+    *table_reader = std::move(new_table);
+  }
+
+  return s;
+}
+
+void BlockBasedTable::SetupForCompaction() {
+  switch (rep_->options.access_hint_on_compaction_start) {
+    case Options::NONE:
+      break;
+    case Options::NORMAL:
+      rep_->file->Hint(RandomAccessFile::NORMAL);
+      break;
+    case Options::SEQUENTIAL:
+      rep_->file->Hint(RandomAccessFile::SEQUENTIAL);
+      break;
+    case Options::WILLNEED:
+      rep_->file->Hint(RandomAccessFile::WILLNEED);
+      break;
+    default:
+      assert(false);
+  }
+  compaction_optimized_ = true;
+}
+
+TableStats& BlockBasedTable::GetTableStats() {
+  return rep_->table_stats;
+}
+
+// Load the meta-block from the file. On success, return the loaded meta block
+// and its iterator.
+Status BlockBasedTable::ReadMetaBlock(
+    Rep* rep,
+    std::unique_ptr<Block>* meta_block,
+    std::unique_ptr<Iterator>* iter) {
+  // TODO(sanjay): Skip this if footer.metaindex_handle() size indicates
+  // it is an empty block.
+  //  TODO: we never really verify check sum for meta index block
+  Block* meta = nullptr;
+  Status s = ReadBlockFromFile(
+      rep->file.get(),
+      ReadOptions(),
+      rep->metaindex_handle,
+      &meta,
+      rep->options.env);
+
+    if (!s.ok()) {
+      auto err_msg =
+        "[Warning] Encountered error while reading data from stats block " +
+        s.ToString();
+      Log(rep->options.info_log, "%s", err_msg.c_str());
+    }
+  if (!s.ok()) {
+    delete meta;
+    return s;
+  }
+
+  meta_block->reset(meta);
+  // meta block uses bytewise comparator.
+  iter->reset(meta->NewIterator(BytewiseComparator()));
+  return Status::OK();
+}
+
+FilterBlockReader* BlockBasedTable::ReadFilter (
+    const Slice& filter_handle_value,
+    BlockBasedTable::Rep* rep,
+    size_t* filter_size) {
+  Slice v = filter_handle_value;
+  BlockHandle filter_handle;
+  if (!filter_handle.DecodeFrom(&v).ok()) {
+    return nullptr;
+  }
+
+  // TODO: We might want to unify with ReadBlockFromFile() if we start
+  // requiring checksum verification in Table::Open.
+  ReadOptions opt;
+  BlockContents block;
+  if (!ReadBlockContents(rep->file.get(), opt, filter_handle, &block,
+                        rep->options.env, false).ok()) {
+    return nullptr;
+  }
+
+  if (filter_size) {
+    *filter_size = block.data.size();
+  }
+
+  return new FilterBlockReader(
+       rep->options, block.data, block.heap_allocated);
+}
+
+Status BlockBasedTable::ReadStats(
+    const Slice& handle_value, Rep* rep, TableStats* table_stats) {
+  assert(table_stats);
+
+  Slice v = handle_value;
+  BlockHandle handle;
+  if (!handle.DecodeFrom(&v).ok()) {
+    return Status::InvalidArgument("Failed to decode stats block handle");
+  }
+
+  BlockContents block_contents;
+  Status s = ReadBlockContents(
+      rep->file.get(),
+      ReadOptions(),
+      handle,
+      &block_contents,
+      rep->options.env,
+      false
+  );
+
+  if (!s.ok()) {
+    return s;
+  }
+
+  Block stats_block(block_contents);
+  std::unique_ptr<Iterator> iter(
+      stats_block.NewIterator(BytewiseComparator())
+  );
+
+  // All pre-defined stats of type uint64_t
+  std::unordered_map<std::string, uint64_t*> predefined_uint64_stats = {
+    { BlockBasedTableStatsNames::kDataSize, &table_stats->data_size },
+    { BlockBasedTableStatsNames::kIndexSize, &table_stats->index_size },
+    { BlockBasedTableStatsNames::kRawKeySize, &table_stats->raw_key_size },
+    { BlockBasedTableStatsNames::kRawValueSize, &table_stats->raw_value_size },
+    { BlockBasedTableStatsNames::kNumDataBlocks,
+      &table_stats->num_data_blocks },
+    { BlockBasedTableStatsNames::kNumEntries, &table_stats->num_entries },
+  };
+
+  std::string last_key;
+  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
+    s = iter->status();
+    if (!s.ok()) {
+      break;
+    }
+
+    auto key = iter->key().ToString();
+    // stats block is strictly sorted with no duplicate key.
+    assert(
+        last_key.empty() ||
+        BytewiseComparator()->Compare(key, last_key) > 0
+    );
+    last_key = key;
+
+    auto raw_val = iter->value();
+    auto pos = predefined_uint64_stats.find(key);
+
+    if (pos != predefined_uint64_stats.end()) {
+      // handle predefined rocksdb stats
+      uint64_t val;
+      if (!GetVarint64(&raw_val, &val)) {
+        // skip malformed value
+        auto error_msg =
+          "[Warning] detect malformed value in stats meta-block:"
+          "\tkey: " + key + "\tval: " + raw_val.ToString();
+        Log(rep->options.info_log, "%s", error_msg.c_str());
+        continue;
+      }
+      *(pos->second) = val;
+    } else if (key == BlockBasedTableStatsNames::kFilterPolicy) {
+      table_stats->filter_policy_name = raw_val.ToString();
+    } else {
+      // handle user-collected
+      table_stats->user_collected_stats.insert(
+          std::make_pair(key, raw_val.ToString())
+      );
+    }
+  }
+
+  return s;
+}
+
+Status BlockBasedTable::GetBlock(
+    const BlockBasedTable* table,
+    const BlockHandle& handle,
+    const ReadOptions& options,
+    const bool for_compaction,
+    const Tickers block_cache_miss_ticker,
+    const Tickers block_cache_hit_ticker,
+    bool* didIO,
+    CachableEntry<Block>* entry) {
+  bool no_io = options.read_tier == kBlockCacheTier;
+  Cache* block_cache = table->rep_->options.block_cache.get();
+  auto statistics = table->rep_->options.statistics;
+  Status s;
+
+  if (block_cache != nullptr) {
+    char cache_key[kMaxCacheKeyPrefixSize + kMaxVarint64Length];
+    auto key = GetCacheKey(
+        table->rep_->cache_key_prefix,
+        table->rep_->cache_key_prefix_size,
+        handle,
+        cache_key
+    );
+
+    entry->cache_handle = GetFromBlockCache(
+        block_cache,
+        key,
+        block_cache_miss_ticker,
+        block_cache_hit_ticker,
+        table->rep_->options.statistics
+    );
+
+    if (entry->cache_handle != nullptr) {
+      entry->value =
+        reinterpret_cast<Block*>(block_cache->Value(entry->cache_handle));
+    } else if (no_io) {
+      // Did not find in block_cache and can't do IO
+      return Status::Incomplete("no blocking io");
+    } else {
+      Histograms histogram = for_compaction ?
+        READ_BLOCK_COMPACTION_MICROS : READ_BLOCK_GET_MICROS;
+      {
+        // block for stop watch
+        StopWatch sw(table->rep_->options.env, statistics, histogram);
+        s = ReadBlockFromFile(
+              table->rep_->file.get(),
+              options,
+              handle,
+              &entry->value,
+              table->rep_->options.env,
+              didIO
+            );
+      }
+      if (s.ok()) {
+        if (options.fill_cache && entry->value->isCachable()) {
+          entry->cache_handle = block_cache->Insert(
+            key, entry->value, entry->value->size(), &DeleteCachedBlock);
+          RecordTick(statistics, BLOCK_CACHE_ADD);
+        }
+      }
+    }
+  } else if (no_io) {
+    // Could not read from block_cache and can't do IO
+    return Status::Incomplete("no blocking io");
+  } else {
+    s = ReadBlockFromFile(
+        table->rep_->file.get(),
+        options,
+        handle,
+        &entry->value,
+        table->rep_->options.env,
+        didIO
+      );
+  }
+
+  return s;
+}
+
+// Convert an index iterator value (i.e., an encoded BlockHandle)
+// into an iterator over the contents of the corresponding block.
+Iterator* BlockBasedTable::BlockReader(void* arg,
+                                       const ReadOptions& options,
+                                       const Slice& index_value,
+                                       bool* didIO,
+                                       bool for_compaction) {
+  const bool no_io = (options.read_tier == kBlockCacheTier);
+  BlockBasedTable* table = reinterpret_cast<BlockBasedTable*>(arg);
+  Cache* block_cache = table->rep_->options.block_cache.get();
+  Cache* block_cache_compressed = table->rep_->options.
+                                    block_cache_compressed.get();
+  std::shared_ptr<Statistics> statistics = table->rep_->options.statistics;
+  Block* block = nullptr;
+  Block* cblock = nullptr;
+  Cache::Handle* cache_handle = nullptr;
+  Cache::Handle* compressed_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()) {
+    return NewErrorIterator(s);
+  }
+
+  if (block_cache != nullptr || block_cache_compressed != nullptr) {
+    char cache_key[kMaxCacheKeyPrefixSize + kMaxVarint64Length];
+    char compressed_cache_key[kMaxCacheKeyPrefixSize + kMaxVarint64Length];
+    Slice key,  /* key to the block cache */
+          ckey /* key to the compressed block cache */ ;
+
+    // create key for block cache
+    if (block_cache != nullptr) {
+      key = GetCacheKey(
+          table->rep_->cache_key_prefix,
+          table->rep_->cache_key_prefix_size,
+          handle,
+          cache_key
+      );
+    }
+
+    if (block_cache_compressed != nullptr) {
+      ckey = GetCacheKey(
+          table->rep_->compressed_cache_key_prefix,
+          table->rep_->compressed_cache_key_prefix_size,
+          handle,
+          compressed_cache_key
+      );
+    }
+
+    // Lookup uncompressed cache first
+    if (block_cache != nullptr) {
+      assert(!key.empty());
+      cache_handle = block_cache->Lookup(key);
+      if (cache_handle != nullptr) {
+        block = reinterpret_cast<Block*>(block_cache->Value(cache_handle));
+        RecordTick(statistics, BLOCK_CACHE_HIT);
+        RecordTick(statistics, BLOCK_CACHE_DATA_HIT);
+      } else {
+        RecordTick(statistics, BLOCK_CACHE_MISS);
+        RecordTick(statistics, BLOCK_CACHE_DATA_MISS);
+      }
+    }
+
+    // If not found in uncompressed cache, lookup compressed cache
+    if (block == nullptr && block_cache_compressed != nullptr) {
+      assert(!ckey.empty());
+      compressed_cache_handle = block_cache_compressed->Lookup(ckey);
+
+      // if we found in the compressed cache, then uncompress and
+      // insert into uncompressed cache
+      if (compressed_cache_handle != nullptr) {
+        // found compressed block
+        cblock = reinterpret_cast<Block*>(block_cache_compressed->
+                        Value(compressed_cache_handle));
+        assert(cblock->compressionType() != kNoCompression);
+
+        // Retrieve the uncompressed contents into a new buffer
+        BlockContents contents;
+        s = UncompressBlockContents(cblock->data(), cblock->size(),
+                                    &contents);
+
+        // Insert uncompressed block into block cache
+        if (s.ok()) {
+          block = new Block(contents); // uncompressed block
+          assert(block->compressionType() == kNoCompression);
+          if (block_cache != nullptr && block->isCachable() &&
+              options.fill_cache) {
+            cache_handle = block_cache->Insert(key, block, block->size(),
+                                               &DeleteCachedBlock);
+            assert(reinterpret_cast<Block*>(block_cache->Value(cache_handle))
+                   == block);
+          }
+        }
+        // Release hold on compressed cache entry
+        block_cache_compressed->Release(compressed_cache_handle);
+        RecordTick(statistics, BLOCK_CACHE_COMPRESSED_HIT);
+      }
+    }
+
+    if (block != nullptr) {
+      BumpPerfCount(&perf_context.block_cache_hit_count);
+    } else if (no_io) {
+      // Did not find in block_cache and can't do IO
+      return NewErrorIterator(Status::Incomplete("no blocking io"));
+    } else {
+      Histograms histogram = for_compaction ?
+        READ_BLOCK_COMPACTION_MICROS : READ_BLOCK_GET_MICROS;
+      {  // block for stop watch
+        StopWatch sw(table->rep_->options.env, statistics, histogram);
+        s = ReadBlockFromFile(
+              table->rep_->file.get(),
+              options,
+              handle,
+              &cblock,
+              table->rep_->options.env,
+              didIO,
+              block_cache_compressed == nullptr
+            );
+      }
+      if (s.ok()) {
+        assert(cblock->compressionType() == kNoCompression ||
+               block_cache_compressed != nullptr);
+
+        // Retrieve the uncompressed contents into a new buffer
+        BlockContents contents;
+        if (cblock->compressionType() != kNoCompression) {
+          s = UncompressBlockContents(cblock->data(), cblock->size(),
+                                      &contents);
+        }
+        if (s.ok()) {
+          if (cblock->compressionType() != kNoCompression) {
+            block = new Block(contents); // uncompressed block
+          } else {
+            block = cblock;
+            cblock = nullptr;
+          }
+          if (block->isCachable() && options.fill_cache) {
+            // Insert compressed block into compressed block cache.
+            // Release the hold on the compressed cache entry immediately.
+            if (block_cache_compressed != nullptr && cblock != nullptr) {
+              compressed_cache_handle = block_cache_compressed->Insert(
+                          ckey, cblock, cblock->size(), &DeleteCachedBlock);
+              block_cache_compressed->Release(compressed_cache_handle);
+              RecordTick(statistics, BLOCK_CACHE_COMPRESSED_MISS);
+              cblock = nullptr;
+            }
+            // insert into uncompressed block cache
+            assert((block->compressionType() == kNoCompression));
+            if (block_cache != nullptr) {
+              cache_handle = block_cache->Insert(
+                key, block, block->size(), &DeleteCachedBlock);
+              RecordTick(statistics, BLOCK_CACHE_ADD);
+              assert(reinterpret_cast<Block*>(block_cache->Value(
+                     cache_handle))== block);
+            }
+          }
+        }
+      }
+      if (cblock != nullptr) {
+        delete cblock;
+      }
+    }
+  } else if (no_io) {
+    // Could not read from block_cache and can't do IO
+    return NewErrorIterator(Status::Incomplete("no blocking io"));
+  } else {
+    s = ReadBlockFromFile(
+        table->rep_->file.get(),
+        options,
+        handle,
+        &block,
+        table->rep_->options.env,
+        didIO
+      );
+  }
+
+  Iterator* iter;
+  if (block != nullptr) {
+    iter = block->NewIterator(table->rep_->options.comparator);
+    if (cache_handle != nullptr) {
+      iter->RegisterCleanup(&ReleaseBlock, block_cache, cache_handle);
+    } else {
+      iter->RegisterCleanup(&DeleteBlock, block, nullptr);
+    }
+  } else {
+    iter = NewErrorIterator(s);
+  }
+  return iter;
+}
+
+BlockBasedTable::CachableEntry<FilterBlockReader>
+BlockBasedTable::GetFilter(bool no_io) const {
+  if (!rep_->options.filter_policy || !rep_->options.block_cache) {
+    return {rep_->filter.get(), nullptr};
+  }
+
+  // Fetching from the cache
+  Cache* block_cache = rep_->options.block_cache.get();
+  char cache_key[kMaxCacheKeyPrefixSize + kMaxVarint64Length];
+  auto key = GetCacheKey(
+      rep_->cache_key_prefix,
+      rep_->cache_key_prefix_size,
+      rep_->metaindex_handle,
+      cache_key
+  );
+
+  auto cache_handle = GetFromBlockCache(
+    block_cache,
+    key,
+    BLOCK_CACHE_FILTER_MISS,
+    BLOCK_CACHE_FILTER_HIT,
+    rep_->options.statistics
+  );
+
+  FilterBlockReader* filter = nullptr;
+  if (cache_handle != nullptr) {
+     filter = reinterpret_cast<FilterBlockReader*>(
+         block_cache->Value(cache_handle));
+  } else if (no_io) {
+    // Do not invoke any io.
+    return CachableEntry<FilterBlockReader>();
+  } else {
+    size_t filter_size = 0;
+    std::unique_ptr<Block> meta;
+    std::unique_ptr<Iterator> iter;
+    auto s = ReadMetaBlock(rep_, &meta, &iter);
+
+    if (s.ok()) {
+      std::string filter_block_key = kFilterBlockPrefix;
+      filter_block_key.append(rep_->options.filter_policy->Name());
+      iter->Seek(filter_block_key);
+
+      if (iter->Valid() && iter->key() == Slice(filter_block_key)) {
+        filter = ReadFilter(iter->value(), rep_, &filter_size);
+        assert(filter);
+        assert(filter_size > 0);
+
+        cache_handle = block_cache->Insert(
+          key, filter, filter_size, &DeleteCachedFilter);
+        RecordTick(rep_->options.statistics, BLOCK_CACHE_ADD);
+      }
+    }
+  }
+
+  return { filter, cache_handle };
+}
+
+// Get the iterator from the index block.
+Iterator* BlockBasedTable::IndexBlockReader(const ReadOptions& options) const {
+  if (rep_->index_block) {
+    assert (!rep_->options.block_cache);
+    return rep_->index_block->NewIterator(rep_->options.comparator);
+  }
+
+  // get index block from cache
+  assert (rep_->options.block_cache);
+  bool didIO = false;
+  CachableEntry<Block> entry;
+
+  auto s = GetBlock(
+      this,
+      rep_->index_handle,
+      options,
+      false,  /* for compaction */
+      BLOCK_CACHE_INDEX_MISS,
+      BLOCK_CACHE_INDEX_HIT,
+      &didIO,
+      &entry
+  );
+
+  Iterator* iter;
+  if (entry.value != nullptr) {
+    iter = entry.value->NewIterator(rep_->options.comparator);
+    if (entry.cache_handle) {
+      iter->RegisterCleanup(
+          &ReleaseBlock, rep_->options.block_cache.get(), entry.cache_handle
+      );
+    } else {
+      iter->RegisterCleanup(&DeleteBlock, entry.value, nullptr);
+    }
+  } else {
+    iter = NewErrorIterator(s);
+  }
+  return iter;
+}
+
+Iterator* BlockBasedTable::BlockReader(void* arg,
+                                       const ReadOptions& options,
+                                       const EnvOptions& soptions,
+                                       const Slice& index_value,
+                                       bool for_compaction) {
+  return BlockReader(arg, options, index_value, nullptr, for_compaction);
+}
+
+// This will be broken if the user specifies an unusual implementation
+// of Options.comparator, or if the user specifies an unusual
+// definition of prefixes in Options.filter_policy.  In particular, we
+// require the following three properties:
+//
+// 1) key.starts_with(prefix(key))
+// 2) Compare(prefix(key), key) <= 0.
+// 3) If Compare(key1, key2) <= 0, then Compare(prefix(key1), prefix(key2)) <= 0
+//
+// Otherwise, this method guarantees no I/O will be incurred.
+//
+// REQUIRES: this method shouldn't be called while the DB lock is held.
+bool BlockBasedTable::PrefixMayMatch(const Slice& internal_prefix) {
+  bool may_match = true;
+  Status s;
+
+  if (!rep_->options.filter_policy) {
+    return true;
+  }
+
+  // To prevent any io operation in this method, we set `read_tier` to make
+  // sure we always read index or filter only when they have already been
+  // loaded to memory.
+  ReadOptions no_io_read_options;
+  no_io_read_options.read_tier = kBlockCacheTier;
+  unique_ptr<Iterator> iiter(
+      IndexBlockReader(no_io_read_options)
+  );
+  iiter->Seek(internal_prefix);
+
+  if (!iiter->Valid()) {
+    // we're past end of file
+    // if it's incomplete, it means that we avoided I/O
+    // and we're not really sure that we're past the end
+    // of the file
+    may_match = iiter->status().IsIncomplete();
+  } else if (ExtractUserKey(iiter->key()).starts_with(
+              ExtractUserKey(internal_prefix))) {
+    // we need to check for this subtle case because our only
+    // guarantee is that "the key is a string >= last key in that data
+    // block" according to the doc/table_format.txt spec.
+    //
+    // Suppose iiter->key() starts with the desired prefix; it is not
+    // necessarily the case that the corresponding data block will
+    // contain the prefix, since iiter->key() need not be in the
+    // block.  However, the next data block may contain the prefix, so
+    // we return true to play it safe.
+    may_match = true;
+  } else {
+    // iiter->key() does NOT start with the desired prefix.  Because
+    // Seek() finds the first key that is >= the seek target, this
+    // means that iiter->key() > prefix.  Thus, any data blocks coming
+    // after the data block corresponding to iiter->key() cannot
+    // possibly contain the key.  Thus, the corresponding data block
+    // is the only one which could potentially contain the prefix.
+    Slice handle_value = iiter->value();
+    BlockHandle handle;
+    s = handle.DecodeFrom(&handle_value);
+    assert(s.ok());
+    auto filter_entry = GetFilter(true /* no io */);
+    may_match =
+      filter_entry.value == nullptr ||
+      filter_entry.value->PrefixMayMatch(handle.offset(), internal_prefix);
+    filter_entry.Release(rep_->options.block_cache.get());
+  }
+
+  RecordTick(rep_->options.statistics, BLOOM_FILTER_PREFIX_CHECKED);
+  if (!may_match) {
+    RecordTick(rep_->options.statistics, BLOOM_FILTER_PREFIX_USEFUL);
+  }
+
+  return may_match;
+}
+
+Iterator* BlockBasedTable::NewIterator(const ReadOptions& options) {
+  if (options.prefix) {
+    InternalKey internal_prefix(*options.prefix, 0, kTypeValue);
+    if (!PrefixMayMatch(internal_prefix.Encode())) {
+      // nothing in this file can match the prefix, so we should not
+      // bother doing I/O to this file when iterating.
+      return NewEmptyIterator();
+    }
+  }
+
+  return NewTwoLevelIterator(
+           IndexBlockReader(options),
+           &BlockBasedTable::BlockReader,
+           const_cast<BlockBasedTable*>(this),
+           options,
+           rep_->soptions
+         );
+}
+
+Status BlockBasedTable::Get(
+    const ReadOptions& readOptions,
+    const Slice& key,
+    void* handle_context,
+    bool (*result_handler)(void* handle_context, const Slice& k,
+                           const Slice& v, bool didIO),
+    void (*mark_key_may_exist_handler)(void* handle_context)) {
+  Status s;
+  Iterator* iiter = IndexBlockReader(readOptions);
+  auto filter_entry = GetFilter(readOptions.read_tier == kBlockCacheTier);
+  FilterBlockReader* filter = filter_entry.value;
+  bool done = false;
+  for (iiter->Seek(key); iiter->Valid() && !done; iiter->Next()) {
+    Slice handle_value = iiter->value();
+
+    BlockHandle handle;
+    bool may_not_exist_in_filter =
+      filter != nullptr &&
+      handle.DecodeFrom(&handle_value).ok() &&
+      !filter->KeyMayMatch(handle.offset(), key);
+
+    if (may_not_exist_in_filter) {
+      // Not found
+      // TODO: think about interaction with Merge. If a user key cannot
+      // cross one data block, we should be fine.
+      RecordTick(rep_->options.statistics, BLOOM_FILTER_USEFUL);
+      break;
+    } else {
+      bool didIO = false;
+      unique_ptr<Iterator> block_iter(
+        BlockReader(this, readOptions, iiter->value(), &didIO));
+
+      if (readOptions.read_tier && block_iter->status().IsIncomplete()) {
+        // couldn't get block from block_cache
+        // Update Saver.state to Found because we are only looking for whether
+        // we can guarantee the key is not there when "no_io" is set
+        (*mark_key_may_exist_handler)(handle_context);
+        break;
+      }
+
+      // Call the *saver function on each entry/block until it returns false
+      for (block_iter->Seek(key); block_iter->Valid(); block_iter->Next()) {
+        if (!(*result_handler)(handle_context, block_iter->key(),
+                               block_iter->value(), didIO)) {
+          done = true;
+          break;
+        }
+      }
+      s = block_iter->status();
+    }
+  }
+
+  filter_entry.Release(rep_->options.block_cache.get());
+  if (s.ok()) {
+    s = iiter->status();
+  }
+  delete iiter;
+  return s;
+}
+
+bool SaveDidIO(void* arg, const Slice& key, const Slice& value, bool didIO) {
+  *reinterpret_cast<bool*>(arg) = didIO;
+  return false;
+}
+bool BlockBasedTable::TEST_KeyInCache(const ReadOptions& options,
+                                      const Slice& key) {
+  // We use Get() as it has logic that checks whether we read the
+  // block from the disk or not.
+  bool didIO = false;
+  Status s = Get(options, key, &didIO, SaveDidIO);
+  assert(s.ok());
+  return !didIO;
+}
+
+uint64_t BlockBasedTable::ApproximateOffsetOf(const Slice& key) {
+  Iterator* index_iter = IndexBlockReader(ReadOptions());
+
+  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;
+}
+
+const std::string BlockBasedTable::kFilterBlockPrefix = "filter.";
+const std::string BlockBasedTable::kStatsBlock = "rocksdb.stats";
+
+const std::string BlockBasedTableStatsNames::kDataSize  = "rocksdb.data.size";
+const std::string BlockBasedTableStatsNames::kIndexSize = "rocksdb.index.size";
+const std::string BlockBasedTableStatsNames::kRawKeySize =
+    "rocksdb.raw.key.size";
+const std::string BlockBasedTableStatsNames::kRawValueSize =
+    "rocksdb.raw.value.size";
+const std::string BlockBasedTableStatsNames::kNumDataBlocks =
+    "rocksdb.num.data.blocks";
+const std::string BlockBasedTableStatsNames::kNumEntries =
+    "rocksdb.num.entries";
+const std::string BlockBasedTableStatsNames::kFilterPolicy =
+    "rocksdb.filter.policy";
+
+}  // namespace rocksdb
diff --git a/table/block_based_table_reader.h b/table/block_based_table_reader.h
new file mode 100644 (file)
index 0000000..aba6085
--- /dev/null
@@ -0,0 +1,194 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <memory>
+#include <stdint.h>
+#include "rocksdb/cache.h"
+#include "rocksdb/env.h"
+#include "rocksdb/iterator.h"
+#include "rocksdb/statistics.h"
+#include "rocksdb/table_stats.h"
+#include "rocksdb/table.h"
+#include "util/coding.h"
+
+namespace rocksdb {
+
+class Block;
+class BlockHandle;
+class Footer;
+struct Options;
+class RandomAccessFile;
+struct ReadOptions;
+class TableCache;
+class TableReader;
+class FilterBlockReader;
+
+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 BlockBasedTable : public TableReader {
+ public:
+  static const std::string kFilterBlockPrefix;
+  static const std::string kStatsBlock;
+
+  // 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_reader" to the newly opened
+  // table.  The client should delete "*table_reader" when no longer needed.
+  // If there was an error while initializing the table, sets "*table_reader"
+  // to nullptr and returns a non-ok status.
+  //
+  // *file must remain live while this Table is in use.
+  static Status Open(const Options& options,
+                     const EnvOptions& soptions,
+                     unique_ptr<RandomAccessFile>&& file,
+                     uint64_t file_size,
+                     unique_ptr<TableReader>* table_reader);
+
+  bool PrefixMayMatch(const Slice& internal_prefix) override;
+
+  // 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&) override;
+
+  Status Get(
+        const ReadOptions& readOptions,
+        const Slice& key,
+        void* handle_context,
+        bool (*result_handler)(void* handle_context, const Slice& k,
+                               const Slice& v, bool didIO),
+        void (*mark_key_may_exist_handler)(void* handle_context) = nullptr)
+    override;
+
+  // 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) override;
+
+  // 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) override;
+
+  // Set up the table for Compaction. Might change some parameters with
+  // posix_fadvise
+  void SetupForCompaction() override;
+
+  TableStats& GetTableStats() override;
+
+  ~BlockBasedTable();
+
+ private:
+  template <class TValue>
+  struct CachableEntry;
+
+  struct Rep;
+  Rep* rep_;
+  bool compaction_optimized_;
+
+  static Iterator* BlockReader(void*, const ReadOptions&,
+                               const EnvOptions& soptions, const Slice&,
+                               bool for_compaction);
+
+  static Iterator* BlockReader(void*, const ReadOptions&, const Slice&,
+                               bool* didIO, bool for_compaction = false);
+
+  // if `no_io == true`, we will not try to read filter from sst file
+  // if it is not cached yet.
+  CachableEntry<FilterBlockReader> GetFilter(bool no_io = false) const;
+
+  Iterator* IndexBlockReader(const ReadOptions& options) const;
+
+  // Read the block, either from sst file or from cache. This method will try
+  // to read from cache only when block_cache is set or ReadOption doesn't
+  // explicitly prohibit storage IO.
+  //
+  // If the block is read from cache, the statistics for cache miss/hit of the
+  // the given type of block will be updated. User can specify
+  // `block_cache_miss_ticker` and `block_cache_hit_ticker` for the statistics
+  // update.
+  //
+  // On success, the `result` parameter will be populated, which contains a
+  // pointer to the block and its cache handle, which will be nullptr if it's
+  // not read from the cache.
+  static Status GetBlock(const BlockBasedTable* table,
+                         const BlockHandle& handle,
+                         const ReadOptions& options,
+                         bool for_compaction,
+                         Tickers block_cache_miss_ticker,
+                         Tickers block_cache_hit_ticker,
+                         bool* didIO,
+                         CachableEntry<Block>* result);
+
+  // Calls (*handle_result)(arg, ...) repeatedly, starting with the entry found
+  // after a call to Seek(key), until handle_result returns false.
+  // May not make such a call if filter policy says that key is not present.
+  friend class TableCache;
+  friend class BlockBasedTableBuilder;
+
+  void ReadMeta(const Footer& footer);
+  void ReadFilter(const Slice& filter_handle_value);
+  static Status ReadStats(const Slice& handle_value, Rep* rep);
+
+  // Read the meta block from sst.
+  static Status ReadMetaBlock(
+      Rep* rep,
+      std::unique_ptr<Block>* meta_block,
+      std::unique_ptr<Iterator>* iter);
+
+  // Create the filter from the filter block.
+  static FilterBlockReader* ReadFilter(
+      const Slice& filter_handle_value,
+      Rep* rep,
+      size_t* filter_size = nullptr);
+
+  // Read the table stats from stats block.
+  static Status ReadStats(
+      const Slice& handle_value, Rep* rep, TableStats* stats);
+
+  static void SetupCacheKeyPrefix(Rep* rep);
+
+  explicit BlockBasedTable(Rep* rep) :
+      compaction_optimized_(false) {
+    rep_ = rep;
+  }
+  // Generate a cache key prefix from the file
+  static void GenerateCachePrefix(shared_ptr<Cache> cc,
+    RandomAccessFile* file, char* buffer, size_t* size);
+  static void GenerateCachePrefix(shared_ptr<Cache> cc,
+    WritableFile* file, char* buffer, size_t* size);
+
+  // The longest prefix of the cache key used to identify blocks.
+  // For Posix files the unique ID is three varints.
+  static const size_t kMaxCacheKeyPrefixSize = kMaxVarint64Length*3+1;
+
+  // No copying allowed
+  explicit BlockBasedTable(const TableReader&) = delete;
+  void operator=(const TableReader&) = delete;
+};
+
+struct BlockBasedTableStatsNames {
+  static const std::string kDataSize;
+  static const std::string kIndexSize;
+  static const std::string kRawKeySize;
+  static const std::string kRawValueSize;
+  static const std::string kNumDataBlocks;
+  static const std::string kNumEntries;
+  static const std::string kFilterPolicy;
+};
+
+}  // namespace rocksdb
diff --git a/table/block_builder.cc b/table/block_builder.cc
new file mode 100644 (file)
index 0000000..0382dfc
--- /dev/null
@@ -0,0 +1,134 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <algorithm>
+#include <assert.h>
+#include "rocksdb/comparator.h"
+#include "util/coding.h"
+
+namespace rocksdb {
+
+BlockBuilder::BlockBuilder(int block_restart_interval,
+                           const Comparator* comparator)
+    : block_restart_interval_(block_restart_interval),
+      comparator_(comparator),
+      restarts_(),
+      counter_(0),
+      finished_(false) {
+  assert(block_restart_interval_ >= 1);
+  restarts_.push_back(0);       // First restart point is at offset 0
+}
+
+BlockBuilder::BlockBuilder(const Options* options)
+    : BlockBuilder(options->block_restart_interval, options->comparator) {
+}
+
+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
+}
+
+size_t BlockBuilder::EstimateSizeAfterKV(const Slice& key, const Slice& value)
+  const {
+  size_t estimate = CurrentSizeEstimate();
+  estimate += key.size() + value.size();
+  if (counter_ >= block_restart_interval_) {
+    estimate += sizeof(uint32_t); // a new restart entry.
+  }
+
+  estimate += sizeof(int32_t); // varint for shared prefix length.
+  estimate += VarintLength(key.size()); // varint for key length.
+  estimate += VarintLength(value.size()); // varint for value length.
+
+  return estimate;
+}
+
+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_ <= block_restart_interval_);
+  assert(buffer_.empty() // No values yet?
+         || comparator_->Compare(key, last_key_piece) > 0);
+  size_t shared = 0;
+  if (counter_ < 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 "<shared><non_shared><value_size>" 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 rocksdb
diff --git a/table/block_builder.h b/table/block_builder.h
new file mode 100644 (file)
index 0000000..c5ea669
--- /dev/null
@@ -0,0 +1,65 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <vector>
+
+#include <stdint.h>
+#include "rocksdb/slice.h"
+
+namespace rocksdb {
+
+struct Options;
+class Comparator;
+
+class BlockBuilder {
+ public:
+  BlockBuilder(int block_restart_interval, const Comparator* comparator);
+  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;
+
+  // Returns an estimated block size after appending key and value.
+  size_t EstimateSizeAfterKV(const Slice& key, const Slice& value) const;
+
+  // Return true iff no entries have been added since the last Reset()
+  bool empty() const {
+    return buffer_.empty();
+  }
+
+ private:
+  const int          block_restart_interval_;
+  const Comparator*  comparator_;
+
+  std::string           buffer_;    // Destination buffer
+  std::vector<uint32_t> 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 rocksdb
diff --git a/table/block_test.cc b/table/block_test.cc
new file mode 100644 (file)
index 0000000..f1b16fa
--- /dev/null
@@ -0,0 +1,105 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include <string>
+#include "db/dbformat.h"
+#include "db/memtable.h"
+#include "db/write_batch_internal.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/iterator.h"
+#include "rocksdb/table.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 rocksdb {
+
+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<std::string> keys;
+  std::vector<std::string> 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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/table/filter_block.cc b/table/filter_block.cc
new file mode 100644 (file)
index 0000000..98030a4
--- /dev/null
@@ -0,0 +1,184 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "db/dbformat.h"
+#include "rocksdb/filter_policy.h"
+#include "util/coding.h"
+
+namespace rocksdb {
+
+// 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 Options& opt)
+                 : policy_(opt.filter_policy),
+                   prefix_extractor_(opt.prefix_extractor),
+                   whole_key_filtering_(opt.whole_key_filtering),
+                   comparator_(opt.comparator){}
+
+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();
+  }
+}
+
+bool FilterBlockBuilder::SamePrefix(const Slice &key1,
+                                    const Slice &key2) const {
+  if (!prefix_extractor_->InDomain(key1) &&
+      !prefix_extractor_->InDomain(key2)) {
+    return true;
+  } else if (!prefix_extractor_->InDomain(key1) ||
+             !prefix_extractor_->InDomain(key2)) {
+    return false;
+  } else {
+    return (prefix_extractor_->Transform(key1) ==
+            prefix_extractor_->Transform(key2));
+  }
+}
+
+void FilterBlockBuilder::AddKey(const Slice& key) {
+  // get slice for most recently added entry
+  Slice prev;
+  if (start_.size() > 0) {
+    size_t prev_start = start_[start_.size() - 1];
+    const char* base = entries_.data() + prev_start;
+    size_t length = entries_.size() - prev_start;
+    prev = Slice(base, length);
+  }
+
+  // add key to filter if needed
+  if (whole_key_filtering_) {
+    start_.push_back(entries_.size());
+    entries_.append(key.data(), key.size());
+  }
+
+  // add prefix to filter if needed
+  if (prefix_extractor_ && prefix_extractor_->InDomain(ExtractUserKey(key))) {
+    // If prefix_extractor_, this filter_block layer assumes we only
+    // operate on internal keys.
+    Slice user_key = ExtractUserKey(key);
+    // this assumes prefix(prefix(key)) == prefix(key), as the last
+    // entry in entries_ may be either a key or prefix, and we use
+    // prefix(last entry) to get the prefix of the last key.
+    if (prev.size() == 0 ||
+        !SamePrefix(user_key, ExtractUserKey(prev))) {
+      Slice prefix = prefix_extractor_->Transform(user_key);
+      InternalKey internal_prefix_tmp(prefix, 0, kTypeValue);
+      Slice internal_prefix = internal_prefix_tmp.Encode();
+      assert(comparator_->Compare(internal_prefix, key) <= 0);
+      start_.push_back(entries_.size());
+      entries_.append(internal_prefix.data(), internal_prefix.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_entries = start_.size();
+  if (num_entries == 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(entries_.size());  // Simplify length computation
+  tmp_entries_.resize(num_entries);
+  for (size_t i = 0; i < num_entries; i++) {
+    const char* base = entries_.data() + start_[i];
+    size_t length = start_[i+1] - start_[i];
+    tmp_entries_[i] = Slice(base, length);
+  }
+
+  // Generate filter for current set of keys and append to result_.
+  filter_offsets_.push_back(result_.size());
+  policy_->CreateFilter(&tmp_entries_[0], num_entries, &result_);
+
+  tmp_entries_.clear();
+  entries_.clear();
+  start_.clear();
+}
+
+FilterBlockReader::FilterBlockReader(
+    const Options& opt, const Slice& contents, bool delete_contents_after_use)
+    : policy_(opt.filter_policy),
+      prefix_extractor_(opt.prefix_extractor),
+      whole_key_filtering_(opt.whole_key_filtering),
+      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;
+  if (delete_contents_after_use) {
+    filter_data.reset(contents.data());
+  }
+}
+
+bool FilterBlockReader::KeyMayMatch(uint64_t block_offset,
+                                    const Slice& key) {
+  if (!whole_key_filtering_) {
+    return true;
+  }
+  return MayMatch(block_offset, key);
+}
+
+bool FilterBlockReader::PrefixMayMatch(uint64_t block_offset,
+                                       const Slice& prefix) {
+  if (!prefix_extractor_) {
+    return true;
+  }
+  return MayMatch(block_offset, prefix);
+}
+
+bool FilterBlockReader::MayMatch(uint64_t block_offset, const Slice& entry) {
+  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(entry, filter);
+    } else if (start == limit) {
+      // Empty filters do not match any entries
+      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 (file)
index 0000000..e47f946
--- /dev/null
@@ -0,0 +1,88 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <stddef.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include "rocksdb/options.h"
+#include "rocksdb/slice.h"
+#include "rocksdb/slice_transform.h"
+#include "util/hash.h"
+
+namespace rocksdb {
+
+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 Options& opt);
+
+  void StartBlock(uint64_t block_offset);
+  void AddKey(const Slice& key);
+  Slice Finish();
+
+ private:
+  bool SamePrefix(const Slice &key1, const Slice &key2) const;
+  void GenerateFilter();
+
+  const FilterPolicy* policy_;
+  const SliceTransform* prefix_extractor_;
+  bool whole_key_filtering_;
+  const Comparator* comparator_;
+
+  std::string entries_;         // Flattened entry contents
+  std::vector<size_t> start_;   // Starting index in entries_ of each entry
+  std::string result_;          // Filter data computed so far
+  std::vector<Slice> tmp_entries_; // policy_->CreateFilter() argument
+  std::vector<uint32_t> 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 Options& opt,
+    const Slice& contents,
+    bool delete_contents_after_use = false);
+  bool KeyMayMatch(uint64_t block_offset, const Slice& key);
+  bool PrefixMayMatch(uint64_t block_offset, const Slice& prefix);
+
+ private:
+  const FilterPolicy* policy_;
+  const SliceTransform* prefix_extractor_;
+  bool whole_key_filtering_;
+  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)
+  std::unique_ptr<const char[]> filter_data;
+
+
+  bool MayMatch(uint64_t block_offset, const Slice& entry);
+};
+
+}
diff --git a/table/filter_block_test.cc b/table/filter_block_test.cc
new file mode 100644 (file)
index 0000000..bc1a0d0
--- /dev/null
@@ -0,0 +1,139 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/filter_policy.h"
+#include "util/coding.h"
+#include "util/hash.h"
+#include "util/logging.h"
+#include "util/testharness.h"
+#include "util/testutil.h"
+
+namespace rocksdb {
+
+// 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_;
+  Options options_;
+
+  FilterBlockTest() {
+    options_ = Options();
+    options_.filter_policy = &policy_;
+  }
+};
+
+TEST(FilterBlockTest, EmptyBuilder) {
+  FilterBlockBuilder builder(options_);
+  Slice block = builder.Finish();
+  ASSERT_EQ("\\x00\\x00\\x00\\x00\\x0b", EscapeString(block));
+  FilterBlockReader reader(options_, block);
+  ASSERT_TRUE(reader.KeyMayMatch(0, "foo"));
+  ASSERT_TRUE(reader.KeyMayMatch(100000, "foo"));
+}
+
+TEST(FilterBlockTest, SingleChunk) {
+  FilterBlockBuilder builder(options_);
+  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(options_, 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(options_);
+
+  // 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(options_, 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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/table/flush_block_policy.cc b/table/flush_block_policy.cc
new file mode 100644 (file)
index 0000000..a953a78
--- /dev/null
@@ -0,0 +1,70 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+
+#include "rocksdb/flush_block_policy.h"
+#include "rocksdb/slice.h"
+#include "table/block_builder.h"
+
+#include <cassert>
+
+namespace rocksdb {
+
+// Flush block by size
+class FlushBlockBySizePolicy : public FlushBlockPolicy {
+ public:
+  // @params block_size:           Approximate size of user data packed per
+  //                               block.
+  // @params block_size_deviation: This is used to close a block before it
+  //                               reaches the configured
+  FlushBlockBySizePolicy(const uint64_t block_size,
+                         const uint64_t block_size_deviation,
+                         const BlockBuilder& data_block_builder) :
+      block_size_(block_size),
+      block_size_deviation_(block_size_deviation),
+      data_block_builder_(data_block_builder) {
+  }
+
+  virtual bool Update(const Slice& key,
+                      const Slice& value) override {
+    // it makes no sense to flush when the data block is empty
+    if (data_block_builder_.empty()) {
+      return false;
+    }
+
+    auto curr_size = data_block_builder_.CurrentSizeEstimate();
+
+    // Do flush if one of the below two conditions is true:
+    // 1) if the current estimated size already exceeds the block size,
+    // 2) block_size_deviation is set and the estimated size after appending
+    // the kv will exceed the block size and the current size is under the
+    // the deviation.
+    return curr_size >= block_size_ || BlockAlmostFull(key, value);
+  }
+
+ private:
+  bool BlockAlmostFull(const Slice& key, const Slice& value) const {
+    const auto curr_size = data_block_builder_.CurrentSizeEstimate();
+    const auto estimated_size_after =
+      data_block_builder_.EstimateSizeAfterKV(key, value);
+
+    return
+      estimated_size_after > block_size_ &&
+      block_size_deviation_ > 0 &&
+      curr_size * 100 > block_size_ * (100 - block_size_deviation_);
+  }
+
+  const uint64_t block_size_;
+  const uint64_t block_size_deviation_;
+  const BlockBuilder& data_block_builder_;
+};
+
+FlushBlockPolicy* FlushBlockBySizePolicyFactory::NewFlushBlockPolicy(
+    const BlockBuilder& data_block_builder) const {
+  return new FlushBlockBySizePolicy(block_size_,
+                                    block_size_deviation_,
+                                    data_block_builder);
+}
+
+}  // namespace rocksdb
diff --git a/table/format.cc b/table/format.cc
new file mode 100644 (file)
index 0000000..ff6d8fa
--- /dev/null
@@ -0,0 +1,203 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "port/port.h"
+#include "rocksdb/env.h"
+#include "table/block.h"
+#include "util/coding.h"
+#include "util/crc32c.h"
+#include "util/perf_context_imp.h"
+
+namespace rocksdb {
+
+void BlockHandle::EncodeTo(std::string* dst) const {
+  // Sanity check that all fields have been set
+  assert(offset_ != ~static_cast<uint64_t>(0));
+  assert(size_ != ~static_cast<uint64_t>(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<uint32_t>(kTableMagicNumber & 0xffffffffu));
+  PutFixed32(dst, static_cast<uint32_t>(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<uint64_t>(magic_hi) << 32) |
+                          (static_cast<uint64_t>(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 ReadBlockContents(RandomAccessFile* file,
+                         const ReadOptions& options,
+                         const BlockHandle& handle,
+                         BlockContents* result,
+                         Env* env,
+                         bool do_uncompress) {
+  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<size_t>(handle.size());
+  char* buf = new char[n + kBlockTrailerSize];
+  Slice contents;
+
+  StopWatchNano timer(env);
+  StartPerfTimer(&timer);
+  Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf);
+  BumpPerfCount(&perf_context.block_read_count);
+  BumpPerfCount(&perf_context.block_read_byte, n + kBlockTrailerSize);
+  BumpPerfTime(&perf_context.block_read_time, &timer);
+
+  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;
+    }
+    BumpPerfTime(&perf_context.block_checksum_time, &timer);
+  }
+
+  // If the caller has requested that the block not be uncompressed
+  if (!do_uncompress || data[n] == 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;
+    }
+    result->compression_type = (rocksdb::CompressionType)data[n];
+    s =  Status::OK();
+  } else {
+    s = UncompressBlockContents(data, n, result);
+    delete[] buf;
+  }
+  BumpPerfTime(&perf_context.block_decompress_time, &timer);
+  return s;
+}
+
+//
+// The 'data' points to the raw block contents that was read in from file.
+// This method allocates a new heap buffer and the raw block
+// contents are uncompresed into this buffer. This
+// buffer is returned via 'result' and it is upto the caller to
+// free this buffer.
+Status UncompressBlockContents(const char* data, size_t n,
+                               BlockContents* result) {
+  char* ubuf = nullptr;
+  int decompress_size = 0;
+  assert(data[n] != kNoCompression);
+  switch (data[n]) {
+    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)) {
+        return Status::Corruption(snappy_corrupt_msg);
+      }
+      ubuf = new char[ulength];
+      if (!port::Snappy_Uncompress(data, n, ubuf)) {
+        delete[] ubuf;
+        return Status::Corruption(snappy_corrupt_msg);
+      }
+      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) {
+        return Status::Corruption(zlib_corrupt_msg);
+      }
+      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) {
+        return Status::Corruption(bzip2_corrupt_msg);
+      }
+      result->data = Slice(ubuf, decompress_size);
+      result->heap_allocated = true;
+      result->cachable = true;
+      break;
+    default:
+      return Status::Corruption("bad block type");
+  }
+  result->compression_type = kNoCompression; // not compressed any more
+  return Status::OK();
+}
+
+}  // namespace rocksdb
diff --git a/table/format.h b/table/format.h
new file mode 100644 (file)
index 0000000..2f1c1e8
--- /dev/null
@@ -0,0 +1,122 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <string>
+#include <stdint.h>
+#include "rocksdb/slice.h"
+#include "rocksdb/status.h"
+#include "rocksdb/options.h"
+#include "rocksdb/table.h"
+
+namespace rocksdb {
+
+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()
+  CompressionType compression_type;
+};
+
+// Read the block identified by "handle" from "file".  On failure
+// return non-OK.  On success fill *result and return OK.
+extern Status ReadBlockContents(RandomAccessFile* file,
+                                const ReadOptions& options,
+                                const BlockHandle& handle,
+                                BlockContents* result,
+                                Env* env,
+                                bool do_uncompress);
+
+// The 'data' points to the raw block contents read in from file.
+// This method allocates a new heap buffer and the raw block
+// contents are uncompresed into this buffer. This buffer is
+// returned via 'result' and it is upto the caller to
+// free this buffer.
+extern Status UncompressBlockContents(const char* data,
+                                      size_t n,
+                                      BlockContents* result);
+
+// Implementation details follow.  Clients should ignore,
+
+inline BlockHandle::BlockHandle()
+    : offset_(~static_cast<uint64_t>(0)),
+      size_(~static_cast<uint64_t>(0)) {
+}
+
+}  // namespace rocksdb
diff --git a/table/iter_heap.h b/table/iter_heap.h
new file mode 100644 (file)
index 0000000..af8834e
--- /dev/null
@@ -0,0 +1,64 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+
+#pragma once
+#include <queue>
+
+#include "rocksdb/comparator.h"
+#include "table/iterator_wrapper.h"
+
+namespace rocksdb {
+
+// 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<IteratorWrapper*>,
+          MaxIteratorComparator> MaxIterHeap;
+
+typedef std::priority_queue<
+          IteratorWrapper*,
+          std::vector<IteratorWrapper*>,
+          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 rocksdb
diff --git a/table/iterator.cc b/table/iterator.cc
new file mode 100644 (file)
index 0000000..a3d4f63
--- /dev/null
@@ -0,0 +1,72 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/iterator.h"
+
+namespace rocksdb {
+
+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 rocksdb
diff --git a/table/iterator_wrapper.h b/table/iterator_wrapper.h
new file mode 100644 (file)
index 0000000..cb8520b
--- /dev/null
@@ -0,0 +1,64 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+namespace rocksdb {
+
+// 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 rocksdb
diff --git a/table/merger.cc b/table/merger.cc
new file mode 100644 (file)
index 0000000..f5ce744
--- /dev/null
@@ -0,0 +1,228 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/comparator.h"
+#include "rocksdb/iterator.h"
+#include "table/iter_heap.h"
+#include "table/iterator_wrapper.h"
+
+#include <vector>
+
+namespace rocksdb {
+
+namespace {
+
+class MergingIterator : public Iterator {
+ public:
+  MergingIterator(const Comparator* comparator, Iterator** children, int n)
+      : comparator_(comparator),
+        children_(n),
+        current_(nullptr),
+        direction_(kForward),
+        maxHeap_(NewMaxIterHeap(comparator_)),
+        minHeap_ (NewMinIterHeap(comparator_)) {
+    for (int i = 0; i < n; i++) {
+      children_[i].Set(children[i]);
+    }
+    for (auto& child : children_) {
+      if (child.Valid()) {
+        minHeap_.push(&child);
+      }
+    }
+  }
+
+  virtual ~MergingIterator() { }
+
+  virtual bool Valid() const {
+    return (current_ != nullptr);
+  }
+
+  virtual void SeekToFirst() {
+    ClearHeaps();
+    for (auto& child : children_) {
+      child.SeekToFirst();
+      if (child.Valid()) {
+        minHeap_.push(&child);
+      }
+    }
+    FindSmallest();
+    direction_ = kForward;
+  }
+
+  virtual void SeekToLast() {
+    ClearHeaps();
+    for (auto& child : children_) {
+      child.SeekToLast();
+      if (child.Valid()) {
+        maxHeap_.push(&child);
+      }
+    }
+    FindLargest();
+    direction_ = kReverse;
+  }
+
+  virtual void Seek(const Slice& target) {
+    ClearHeaps();
+    for (auto& child : children_) {
+      child.Seek(target);
+      if (child.Valid()) {
+        minHeap_.push(&child);
+      }
+    }
+    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 (auto& child : children_) {
+        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 (auto& child : children_) {
+        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 (auto& child : children_) {
+      status = child.status();
+      if (!status.ok()) {
+        break;
+      }
+    }
+    return status;
+  }
+
+ private:
+  void FindSmallest();
+  void FindLargest();
+  void ClearHeaps();
+
+  const Comparator* comparator_;
+  std::vector<IteratorWrapper> children_;
+  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 rocksdb
diff --git a/table/merger.h b/table/merger.h
new file mode 100644 (file)
index 0000000..dbc1f69
--- /dev/null
@@ -0,0 +1,28 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+
+namespace rocksdb {
+
+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 rocksdb
diff --git a/table/table_reader_bench.cc b/table/table_reader_bench.cc
new file mode 100644 (file)
index 0000000..2c4c503
--- /dev/null
@@ -0,0 +1,163 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+
+#include <gflags/gflags.h>
+
+#include "rocksdb/db.h"
+#include "rocksdb/table.h"
+#include "db/db_impl.h"
+#include "table/block_based_table_factory.h"
+#include "util/histogram.h"
+#include "util/testharness.h"
+#include "util/testutil.h"
+
+namespace rocksdb {
+// Make a key that i determines the first 4 characters and j determines the
+// last 4 characters.
+static std::string MakeKey(int i, int j) {
+  char buf[100];
+  snprintf(buf, sizeof(buf), "%04d__key___%04d        ", i, j);
+  return std::string(buf);
+}
+
+static bool DummySaveValue(void* arg, const Slice& ikey, const Slice& v,
+                           bool didIO) {
+  return false;
+}
+
+// A very simple benchmark that.
+// Create a table with roughly numKey1 * numKey2 keys,
+// where there are numKey1 prefixes of the key, each has numKey2 number of
+// distinguished key, differing in the suffix part.
+// If if_query_empty_keys = false, query the existing keys numKey1 * numKey2
+// times randomly.
+// If if_query_empty_keys = true, query numKey1 * numKey2 random empty keys.
+// Print out the total time.
+//
+// If for_terator=true, instead of just query one key each time, it queries
+// a range sharing the same prefix.
+void TableReaderBenchmark(Options& opts, EnvOptions& env_options,
+                          ReadOptions& read_options, TableFactory* tf,
+                          int num_keys1, int num_keys2, int num_iter,
+                          bool if_query_empty_keys, bool for_iterator) {
+  std::string file_name = test::TmpDir()
+      + "/rocksdb_table_reader_benchmark";
+  ReadOptions ro;
+  unique_ptr<WritableFile> file;
+  Env* env = Env::Default();
+  env->NewWritableFile(file_name, &file, env_options);
+  TableBuilder* tb = tf->GetTableBuilder(opts, file.get(),
+                                         CompressionType::kNoCompression);
+
+  // Populate slightly more than 1M keys
+  for (int i = 0; i < num_keys1; i++) {
+    for (int j = 0; j < num_keys2; j++) {
+      std::string key = MakeKey(i * 2, j);
+      tb->Add(key, key);
+    }
+  }
+  tb->Finish();
+  file->Close();
+
+  unique_ptr<TableReader> table_reader;
+  unique_ptr<RandomAccessFile> raf;
+  Status s = env->NewRandomAccessFile(file_name, &raf, env_options);
+  uint64_t file_size;
+  env->GetFileSize(file_name, &file_size);
+  s = tf->GetTableReader(opts, env_options, std::move(raf), file_size,
+                         &table_reader);
+
+  Random rnd(301);
+  HistogramImpl hist;
+
+  void* arg = nullptr;
+  for (int it = 0; it < num_iter; it++) {
+    for (int i = 0; i < num_keys1; i++) {
+      for (int j = 0; j < num_keys2; j++) {
+        int r1 = rnd.Uniform(num_keys1) * 2;
+        int r2 = rnd.Uniform(num_keys2);
+        if (!for_iterator) {
+          if (if_query_empty_keys) {
+            r1++;
+            r2 = num_keys2 * 2 - r2;
+          }
+          // Query one existing key;
+          std::string key = MakeKey(r1, r2);
+          uint64_t start_micros = env->NowMicros();
+          s = table_reader->Get(ro, key, arg, DummySaveValue, nullptr);
+          hist.Add(env->NowMicros() - start_micros);
+        } else {
+          int r2_len = rnd.Uniform(num_keys2) + 1;
+          if (r2_len + r2 > num_keys2) {
+            r2_len = num_keys2 - r2;
+          }
+          std::string start_key = MakeKey(r1, r2);
+          std::string end_key = MakeKey(r1, r2 + r2_len);
+          uint64_t total_time = 0;
+          uint64_t start_micros = env->NowMicros();
+          Iterator* iter = table_reader->NewIterator(read_options);
+          int count = 0;
+          for(iter->Seek(start_key); iter->Valid(); iter->Next()) {
+            // verify key;
+            total_time += env->NowMicros() - start_micros;
+            assert(Slice(MakeKey(r1, r2 + count)) == iter->key());
+            start_micros = env->NowMicros();
+            if (++count >= r2_len) {
+              break;
+            }
+          }
+          if (count != r2_len) {
+            fprintf(
+                stderr, "Iterator cannot iterate expected number of entries. "
+                "Expected %d but got %d\n", r2_len, count);
+            assert(false);
+          }
+          delete iter;
+          total_time += env->NowMicros() - start_micros;
+          hist.Add(total_time);
+        }
+      }
+    }
+  }
+
+  fprintf(
+      stderr,
+      "==================================================="
+      "====================================================\n"
+      "InMemoryTableSimpleBenchmark: %20s   num_key1:  %5d   "
+      "num_key2: %5d  %10s\n"
+      "==================================================="
+      "===================================================="
+      "\nHistogram (unit: microseconds): \n%s",
+      tf->Name(), num_keys1, num_keys2,
+      for_iterator? "iterator" : (if_query_empty_keys ? "empty" : "non_empty"),
+      hist.ToString().c_str());
+  env->DeleteFile(file_name);
+}
+} // namespace rocksdb
+
+DEFINE_bool(query_empty, false, "query non-existing keys instead of existing "
+            "ones.");
+DEFINE_int32(num_keys1, 4096, "number of distinguish prefix of keys");
+DEFINE_int32(num_keys2, 512, "number of distinguish keys for each prefix");
+DEFINE_int32(iter, 3, "query non-existing keys instead of existing ones");
+DEFINE_bool(iterator, false, "For test iterator");
+
+int main(int argc, char** argv) {
+  google::SetUsageMessage(std::string("\nUSAGE:\n") + std::string(argv[0]) +
+                          " [OPTIONS]...");
+  google::ParseCommandLineFlags(&argc, &argv, true);
+
+  rocksdb::TableFactory* tf;
+  rocksdb::Options options;
+  rocksdb::ReadOptions ro;
+  rocksdb::EnvOptions env_options;
+  tf = new rocksdb::BlockBasedTableFactory();
+  TableReaderBenchmark(options, env_options, ro, tf, FLAGS_num_keys1,
+                       FLAGS_num_keys2, FLAGS_iter, FLAGS_query_empty,
+                       FLAGS_iterator);
+  delete tf;
+  return 0;
+}
diff --git a/table/table_test.cc b/table/table_test.cc
new file mode 100644 (file)
index 0000000..9fa687b
--- /dev/null
@@ -0,0 +1,1306 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <map>
+#include <string>
+#include <memory>
+#include <vector>
+
+#include "db/dbformat.h"
+#include "db/db_statistics.h"
+#include "db/memtable.h"
+#include "db/write_batch_internal.h"
+#include "rocksdb/cache.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/iterator.h"
+#include "rocksdb/memtablerep.h"
+#include "table/block_based_table_builder.h"
+#include "table/block_based_table_reader.h"
+#include "table/block_builder.h"
+#include "table/block.h"
+#include "table/format.h"
+#include "util/random.h"
+#include "util/testharness.h"
+#include "util/testutil.h"
+
+namespace rocksdb {
+
+namespace {
+// 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;
+}
+
+static Options GetDefaultOptions() {
+  Options options;
+  options.SetUpDefaultFlushBlockPolicyFactory();
+  return options;
+}
+
+class ReverseKeyComparator : public Comparator {
+ public:
+  virtual const char* Name() const {
+    return "rocksdb.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<size_t>(rid-id);
+  }
+
+ private:
+  std::string contents_;
+  uint64_t uniq_id_;
+};
+
+typedef std::map<std::string, std::string, anon::STLLessThan> 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<std::string>* 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 BlockBasedTableConstructor: public Constructor {
+ public:
+  explicit BlockBasedTableConstructor(
+      const Comparator* cmp)
+      : Constructor(cmp) {
+  }
+  ~BlockBasedTableConstructor() {
+    Reset();
+  }
+  virtual Status FinishImpl(const Options& options, const KVMap& data) {
+    Reset();
+    sink_.reset(new StringSink());
+    BlockBasedTableBuilder builder(options, sink_.get(), options.compression);
+
+    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_));
+    unique_ptr<TableFactory> table_factory;
+    return options.table_factory->GetTableReader(options, soptions,
+                                                 std::move(source_),
+                                                 sink_->contents().size(),
+                                                 &table_reader_);
+  }
+
+  virtual Iterator* NewIterator() const {
+    return table_reader_->NewIterator(ReadOptions());
+  }
+
+  uint64_t ApproximateOffsetOf(const Slice& key) const {
+    return table_reader_->ApproximateOffsetOf(key);
+  }
+
+  virtual Status Reopen(const Options& options) {
+    source_.reset(new StringSource(sink_->contents(), uniq_id_));
+    return options.table_factory->GetTableReader(options, soptions,
+                                                 std::move(source_),
+                                                 sink_->contents().size(),
+                                                 &table_reader_);
+  }
+
+  virtual TableReader* table_reader() {
+    return table_reader_.get();
+  }
+
+ private:
+  void Reset() {
+    uniq_id_ = 0;
+    table_reader_.reset();
+    sink_.reset();
+    source_.reset();
+  }
+
+  uint64_t uniq_id_;
+  unique_ptr<StringSink> sink_;
+  unique_ptr<StringSource> source_;
+  unique_ptr<TableReader> table_reader_;
+
+  BlockBasedTableConstructor();
+
+  static uint64_t cur_uniq_id_;
+  const EnvOptions soptions;
+};
+uint64_t BlockBasedTableConstructor::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),
+        table_factory_(new SkipListFactory) {
+    memtable_ = new MemTable(internal_comparator_, table_factory_);
+    memtable_->Ref();
+  }
+  ~MemTableConstructor() {
+    memtable_->Unref();
+  }
+  virtual Status FinishImpl(const Options& options, const KVMap& data) {
+    memtable_->Unref();
+    memtable_ = new MemTable(internal_comparator_, table_factory_);
+    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_;
+  std::shared_ptr<SkipListFactory> table_factory_;
+};
+
+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 = GetDefaultOptions();
+    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(GetDefaultOptions().compression_opts,
+                               in.data(), in.size(),
+                               &out);
+}
+
+static bool ZlibCompressionSupported() {
+  std::string out;
+  Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+  return port::Zlib_Compress(GetDefaultOptions().compression_opts,
+                             in.data(), in.size(),
+                             &out);
+}
+
+#ifdef BZIP2
+static bool BZip2CompressionSupported() {
+  std::string out;
+  Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+  return port::BZip2_Compress(GetDefaultOptions().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<TestArgs> Generate_Arg_List() {
+  std::vector<TestArgs> 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<CompressionType> 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_ = GetDefaultOptions();
+
+    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;
+    options_.SetUpDefaultFlushBlockPolicyFactory();
+    if (args.reverse_compare) {
+      options_.comparator = &reverse_key_comparator;
+    }
+    switch (args.type) {
+      case TABLE_TEST:
+        constructor_ = new BlockBasedTableConstructor(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<std::string> keys;
+    KVMap data;
+    constructor_->Finish(options_, &keys, &data);
+
+    TestForwardScan(keys, data);
+    TestBackwardScan(keys, data);
+    TestRandomAccess(rnd, keys, data);
+  }
+
+  void TestForwardScan(const std::vector<std::string>& 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<std::string>& 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<std::string>& 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<std::string>& 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_ = GetDefaultOptions();
+  Constructor* constructor_;
+};
+
+// Test the empty key
+TEST(Harness, SimpleEmptyKey) {
+  std::vector<TestArgs> 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<TestArgs> 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<TestArgs> 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<TestArgs> 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);
+  }
+}
+
+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 { };
+
+// This test include all the basic checks except those for index size and block
+// size, which will be conducted in separated unit tests.
+TEST(TableTest, BasicTableStats) {
+  BlockBasedTableConstructor c(BytewiseComparator());
+
+  c.Add("a1", "val1");
+  c.Add("b2", "val2");
+  c.Add("c3", "val3");
+  c.Add("d4", "val4");
+  c.Add("e5", "val5");
+  c.Add("f6", "val6");
+  c.Add("g7", "val7");
+  c.Add("h8", "val8");
+  c.Add("j9", "val9");
+
+  std::vector<std::string> keys;
+  KVMap kvmap;
+  Options options = GetDefaultOptions();
+  options.compression = kNoCompression;
+  options.block_restart_interval = 1;
+
+  c.Finish(options, &keys, &kvmap);
+
+  auto& stats = c.table_reader()->GetTableStats();
+  ASSERT_EQ(kvmap.size(), stats.num_entries);
+
+  auto raw_key_size = kvmap.size() * 2ul;
+  auto raw_value_size = kvmap.size() * 4ul;
+
+  ASSERT_EQ(raw_key_size, stats.raw_key_size);
+  ASSERT_EQ(raw_value_size, stats.raw_value_size);
+  ASSERT_EQ(1ul, stats.num_data_blocks);
+  ASSERT_EQ("", stats.filter_policy_name);  // no filter policy is used
+
+  // Verify data size.
+  BlockBuilder block_builder(&options);
+  for (const auto& item : kvmap) {
+    block_builder.Add(item.first, item.second);
+  }
+  Slice content = block_builder.Finish();
+  ASSERT_EQ(
+      content.size() + kBlockTrailerSize,
+      stats.data_size
+  );
+}
+
+TEST(TableTest, FilterPolicyNameStats) {
+  BlockBasedTableConstructor c(BytewiseComparator());
+  c.Add("a1", "val1");
+  std::vector<std::string> keys;
+  KVMap kvmap;
+  Options options = GetDefaultOptions();
+  std::unique_ptr<const FilterPolicy> filter_policy(
+    NewBloomFilterPolicy(10)
+  );
+  options.filter_policy = filter_policy.get();
+
+  c.Finish(options, &keys, &kvmap);
+  auto& stats = c.table_reader()->GetTableStats();
+  ASSERT_EQ("rocksdb.BuiltinBloomFilter", stats.filter_policy_name);
+}
+
+static std::string RandomString(Random* rnd, int len) {
+  std::string r;
+  test::RandomString(rnd, len, &r);
+  return r;
+}
+
+// It's very hard to figure out the index block size of a block accurately.
+// To make sure we get the index size, we just make sure as key number
+// grows, the filter block size also grows.
+TEST(TableTest, IndexSizeStat) {
+  uint64_t last_index_size = 0;
+
+  // we need to use random keys since the pure human readable texts
+  // may be well compressed, resulting insignifcant change of index
+  // block size.
+  Random rnd(test::RandomSeed());
+  std::vector<std::string> keys;
+
+  for (int i = 0; i < 100; ++i) {
+    keys.push_back(RandomString(&rnd, 10000));
+  }
+
+  // Each time we load one more key to the table. the table index block
+  // size is expected to be larger than last time's.
+  for (size_t i = 1; i < keys.size(); ++i) {
+    BlockBasedTableConstructor c(BytewiseComparator());
+    for (size_t j = 0; j < i; ++j) {
+      c.Add(keys[j], "val");
+    }
+
+    std::vector<std::string> ks;
+    KVMap kvmap;
+    Options options = GetDefaultOptions();
+    options.compression = kNoCompression;
+    options.block_restart_interval = 1;
+
+    c.Finish(options, &ks, &kvmap);
+    auto index_size =
+      c.table_reader()->GetTableStats().index_size;
+    ASSERT_GT(index_size, last_index_size);
+    last_index_size = index_size;
+  }
+}
+
+TEST(TableTest, NumBlockStat) {
+  Random rnd(test::RandomSeed());
+  BlockBasedTableConstructor c(BytewiseComparator());
+  Options options;
+  options.compression = kNoCompression;
+  options.block_restart_interval = 1;
+  options.block_size = 1000;
+  options.SetUpDefaultFlushBlockPolicyFactory();
+
+  // Block Size changed, need to set up a new flush policy to reflect the
+  // change.
+  options.SetUpDefaultFlushBlockPolicyFactory();
+
+  for (int i = 0; i < 10; ++i) {
+    // the key/val are slightly smaller than block size, so that each block
+    // holds roughly one key/value pair.
+    c.Add(RandomString(&rnd, 900), "val");
+  }
+
+  std::vector<std::string> ks;
+  KVMap kvmap;
+  c.Finish(options, &ks, &kvmap);
+  ASSERT_EQ(
+      kvmap.size(),
+      c.table_reader()->GetTableStats().num_data_blocks
+  );
+}
+
+class BlockCacheStats {
+ public:
+  explicit BlockCacheStats(std::shared_ptr<Statistics> statistics) {
+    block_cache_miss =
+      statistics.get()->getTickerCount(BLOCK_CACHE_MISS);
+    block_cache_hit =
+      statistics.get()->getTickerCount(BLOCK_CACHE_HIT);
+    index_block_cache_miss =
+      statistics.get()->getTickerCount(BLOCK_CACHE_INDEX_MISS);
+    index_block_cache_hit =
+      statistics.get()->getTickerCount(BLOCK_CACHE_INDEX_HIT);
+    data_block_cache_miss =
+      statistics.get()->getTickerCount(BLOCK_CACHE_DATA_MISS);
+    data_block_cache_hit =
+      statistics.get()->getTickerCount(BLOCK_CACHE_DATA_HIT);
+  }
+
+  // Check if the fetched stats matches the expected ones.
+  void AssertEqual(
+      long index_block_cache_miss,
+      long index_block_cache_hit,
+      long data_block_cache_miss,
+      long data_block_cache_hit) const {
+    ASSERT_EQ(index_block_cache_miss, this->index_block_cache_miss);
+    ASSERT_EQ(index_block_cache_hit, this->index_block_cache_hit);
+    ASSERT_EQ(data_block_cache_miss, this->data_block_cache_miss);
+    ASSERT_EQ(data_block_cache_hit, this->data_block_cache_hit);
+    ASSERT_EQ(
+        index_block_cache_miss + data_block_cache_miss,
+        this->block_cache_miss
+    );
+    ASSERT_EQ(
+        index_block_cache_hit + data_block_cache_hit,
+        this->block_cache_hit
+    );
+  }
+
+ private:
+  long block_cache_miss = 0;
+  long block_cache_hit = 0;
+  long index_block_cache_miss = 0;
+  long index_block_cache_hit = 0;
+  long data_block_cache_miss = 0;
+  long data_block_cache_hit = 0;
+};
+
+TEST(TableTest, BlockCacheTest) {
+  // -- Table construction
+  Options options = GetDefaultOptions();
+  options.create_if_missing = true;
+  options.statistics = CreateDBStatistics();
+  options.block_cache = NewLRUCache(1024);
+  std::vector<std::string> keys;
+  KVMap kvmap;
+
+  BlockBasedTableConstructor c(BytewiseComparator());
+  c.Add("key", "value");
+  c.Finish(options, &keys, &kvmap);
+
+  // -- PART 1: Open with regular block cache.
+  // Since block_cache is disabled, no cache activities will be involved.
+  unique_ptr<Iterator> iter;
+
+  // At first, no block will be accessed.
+  {
+    BlockCacheStats stats(options.statistics);
+    // index will be added to block cache.
+    stats.AssertEqual(
+        1,  // index block miss
+        0,
+        0,
+        0
+    );
+  }
+
+  // Only index block will be accessed
+  {
+    iter.reset(c.NewIterator());
+    BlockCacheStats stats(options.statistics);
+    // NOTE: to help better highlight the "detla" of each ticker, I use
+    // <last_value> + <added_value> to indicate the increment of changed
+    // value; other numbers remain the same.
+    stats.AssertEqual(
+        1,
+        0 + 1,  // index block hit
+        0,
+        0
+    );
+  }
+
+  // Only data block will be accessed
+  {
+    iter->SeekToFirst();
+    BlockCacheStats stats(options.statistics);
+    stats.AssertEqual(
+        1,
+        1,
+        0 + 1,  // data block miss
+        0
+    );
+  }
+
+  // Data block will be in cache
+  {
+    iter.reset(c.NewIterator());
+    iter->SeekToFirst();
+    BlockCacheStats stats(options.statistics);
+    stats.AssertEqual(
+        1,
+        1 + 1,  // index block hit
+        1,
+        0 + 1  // data block hit
+    );
+  }
+  // release the iterator so that the block cache can reset correctly.
+  iter.reset();
+
+  // -- PART 2: Open without block cache
+  options.block_cache.reset();
+  options.statistics = CreateDBStatistics();  // reset the stats
+  c.Reopen(options);
+
+  {
+    iter.reset(c.NewIterator());
+    iter->SeekToFirst();
+    ASSERT_EQ("key", iter->key().ToString());
+    BlockCacheStats stats(options.statistics);
+    // Nothing is affected at all
+    stats.AssertEqual(0, 0, 0, 0);
+  }
+
+  // -- PART 3: Open with very small block cache
+  // In this test, no block will ever get hit since the block cache is
+  // too small to fit even one entry.
+  options.block_cache = NewLRUCache(1);
+  c.Reopen(options);
+  {
+    BlockCacheStats stats(options.statistics);
+    stats.AssertEqual(
+        1,  // index block miss
+        0,
+        0,
+        0
+    );
+  }
+
+
+  {
+    // Both index and data block get accessed.
+    // It first cache index block then data block. But since the cache size
+    // is only 1, index block will be purged after data block is inserted.
+    iter.reset(c.NewIterator());
+    BlockCacheStats stats(options.statistics);
+    stats.AssertEqual(
+        1 + 1,  // index block miss
+        0,
+        0,  // data block miss
+        0
+    );
+  }
+
+  {
+    // SeekToFirst() accesses data block. With similar reason, we expect data
+    // block's cache miss.
+    iter->SeekToFirst();
+    BlockCacheStats stats(options.statistics);
+    stats.AssertEqual(
+        2,
+        0,
+        0 + 1,  // data block miss
+        0
+    );
+  }
+}
+
+TEST(TableTest, ApproximateOffsetOfPlain) {
+  BlockBasedTableConstructor 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<std::string> keys;
+  KVMap kvmap;
+  Options options = GetDefaultOptions();
+  options.block_size = 1024;
+  options.SetUpDefaultFlushBlockPolicyFactory();
+  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);
+  BlockBasedTableConstructor 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<std::string> keys;
+  KVMap kvmap;
+  Options options = GetDefaultOptions();
+  options.block_size = 1024;
+  options.SetUpDefaultFlushBlockPolicyFactory();
+  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 = GetDefaultOptions();
+  opt.block_size = 1024;
+  opt.SetUpDefaultFlushBlockPolicyFactory();
+  opt.compression = kNoCompression;
+  opt.block_cache = NewLRUCache(16*1024*1024); // big enough so we don't ever
+                                               // lose cached values.
+
+  BlockBasedTableConstructor 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<std::string> keys;
+  KVMap kvmap;
+  c.Finish(opt, &keys, &kvmap);
+
+  unique_ptr<Iterator> 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_reader()->TEST_KeyInCache(ReadOptions(), key));
+  }
+}
+
+TEST(Harness, Randomized) {
+  std::vector<TestArgs> 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), "rocksdb.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());
+  auto table_factory = std::make_shared<SkipListFactory>();
+  MemTable* memtable = new MemTable(cmp, table_factory);
+  memtable->Ref();
+  WriteBatch batch;
+  Options options = GetDefaultOptions();
+  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, &options).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();
+}
+
+
+}  // namespace rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/table/two_level_iterator.cc b/table/two_level_iterator.cc
new file mode 100644 (file)
index 0000000..ac2d8d3
--- /dev/null
@@ -0,0 +1,205 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/options.h"
+#include "rocksdb/table.h"
+#include "table/block.h"
+#include "table/format.h"
+#include "table/iterator_wrapper.h"
+
+namespace rocksdb {
+
+namespace {
+
+typedef Iterator* (*BlockFunction)(void*, const ReadOptions&,
+                                   const EnvOptions& soptions, const Slice&,
+                                   bool for_compaction);
+
+class TwoLevelIterator: public Iterator {
+ public:
+  TwoLevelIterator(
+    Iterator* index_iter,
+    BlockFunction block_function,
+    void* arg,
+    const ReadOptions& options,
+    const EnvOptions& soptions,
+    bool for_compaction);
+
+  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_;
+  const EnvOptions& soptions_;
+  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_;
+  bool for_compaction_;
+};
+
+TwoLevelIterator::TwoLevelIterator(
+    Iterator* index_iter,
+    BlockFunction block_function,
+    void* arg,
+    const ReadOptions& options,
+    const EnvOptions& soptions,
+    bool for_compaction)
+    : block_function_(block_function),
+      arg_(arg),
+      options_(options),
+      soptions_(soptions),
+      index_iter_(index_iter),
+      data_iter_(nullptr),
+      for_compaction_(for_compaction) {
+}
+
+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() &&
+        !data_iter_.status().IsIncomplete())) {
+    // 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() &&
+        !data_iter_.status().IsIncomplete())) {
+    // 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_, soptions_, handle,
+                                          for_compaction_);
+      data_block_handle_.assign(handle.data(), handle.size());
+      SetDataIterator(iter);
+    }
+  }
+}
+
+}  // namespace
+
+Iterator* NewTwoLevelIterator(
+    Iterator* index_iter,
+    BlockFunction block_function,
+    void* arg,
+    const ReadOptions& options,
+    const EnvOptions& soptions,
+    bool for_compaction) {
+  return new TwoLevelIterator(index_iter, block_function, arg,
+                              options, soptions, for_compaction);
+}
+
+}  // namespace rocksdb
diff --git a/table/two_level_iterator.h b/table/two_level_iterator.h
new file mode 100644 (file)
index 0000000..85aed3f
--- /dev/null
@@ -0,0 +1,40 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include "rocksdb/iterator.h"
+#include "rocksdb/env.h"
+
+namespace rocksdb {
+
+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 EnvOptions& soptions,
+        const Slice& index_value,
+        bool for_compaction),
+    void* arg,
+    const ReadOptions& options,
+    const EnvOptions& soptions,
+    bool for_compaction = false);
+
+}  // namespace rocksdb
diff --git a/tools/blob_store_bench.cc b/tools/blob_store_bench.cc
new file mode 100644 (file)
index 0000000..70ece2c
--- /dev/null
@@ -0,0 +1,269 @@
+#include <cstdio>
+#include <vector>
+#include <atomic>
+
+#include "rocksdb/env.h"
+#include "util/blob_store.h"
+#include "util/testutil.h"
+
+#define KB 1024LL
+#define MB 1024*1024LL
+// BlobStore does costly asserts to make sure it's running correctly, which
+// significantly impacts benchmark runtime.
+// NDEBUG will compile out those asserts.
+#ifndef NDEBUG
+#define NDEBUG
+#endif
+
+using namespace rocksdb;
+using namespace std;
+
+// used by all threads
+uint64_t timeout_sec;
+Env *env;
+BlobStore* bs;
+
+static std::string RandomString(Random* rnd, uint64_t len) {
+  std::string r;
+  test::RandomString(rnd, len, &r);
+  return r;
+}
+
+struct Result {
+  uint32_t writes;
+  uint32_t reads;
+  uint32_t deletes;
+  uint64_t data_written;
+  uint64_t data_read;
+
+  void print() {
+    printf("Total writes = %u\n", writes);
+    printf("Total reads = %u\n", reads);
+    printf("Total deletes = %u\n", deletes);
+    printf("Write throughput = %lf MB/s\n",
+           (double)data_written / (1024*1024.0) / timeout_sec);
+    printf("Read throughput = %lf MB/s\n",
+           (double)data_read / (1024*1024.0) / timeout_sec);
+    printf("Total throughput = %lf MB/s\n",
+           (double)(data_read + data_written) / (1024*1024.0) / timeout_sec);
+  }
+
+  Result() {
+    writes = reads = deletes = data_read = data_written = 0;
+  }
+
+  Result (uint32_t writes, uint32_t reads, uint32_t deletes,
+          uint64_t data_written, uint64_t data_read) :
+    writes(writes), reads(reads), deletes(deletes),
+    data_written(data_written), data_read(data_read) {}
+
+};
+
+Result operator + (const Result &a, const Result &b) {
+  return Result(a.writes + b.writes, a.reads + b.reads,
+                a.deletes + b.deletes, a.data_written + b.data_written,
+                a.data_read + b.data_read);
+}
+
+struct WorkerThread {
+  uint64_t data_size_from, data_size_to;
+  double read_ratio;
+  uint64_t working_set_size; // start deleting once you reach this
+  Result result;
+  atomic<bool> stopped;
+
+  WorkerThread(uint64_t data_size_from, uint64_t data_size_to,
+                double read_ratio, uint64_t working_set_size) :
+    data_size_from(data_size_from), data_size_to(data_size_to),
+    read_ratio(read_ratio), working_set_size(working_set_size),
+    stopped(false) {}
+
+  WorkerThread(const WorkerThread& wt) :
+    data_size_from(wt.data_size_from), data_size_to(wt.data_size_to),
+    read_ratio(wt.read_ratio), working_set_size(wt.working_set_size),
+    stopped(false) {}
+};
+
+static void WorkerThreadBody(void* arg) {
+  WorkerThread* t = reinterpret_cast<WorkerThread*>(arg);
+  Random rnd(5);
+  string buf;
+  vector<pair<Blob, uint64_t>> blobs;
+  vector<string> random_strings;
+
+  for (int i = 0; i < 10; ++i) {
+    random_strings.push_back(RandomString(&rnd, t->data_size_to));
+  }
+
+  uint64_t total_size = 0;
+
+  uint64_t start_micros = env->NowMicros();
+  while (env->NowMicros() - start_micros < timeout_sec * 1000 * 1000) {
+    if (blobs.size() && rand() < RAND_MAX * t->read_ratio) {
+      // read
+      int bi = rand() % blobs.size();
+      Status s = bs->Get(blobs[bi].first, &buf);
+      assert(s.ok());
+      t->result.data_read += buf.size();
+      t->result.reads++;
+    } else {
+      // write
+      uint64_t size = rand() % (t->data_size_to - t->data_size_from) +
+        t->data_size_from;
+      total_size += size;
+      string put_str = random_strings[rand() % random_strings.size()];
+      blobs.push_back(make_pair(Blob(), size));
+      Status s = bs->Put(Slice(put_str.data(), size), &blobs.back().first);
+      assert(s.ok());
+      t->result.data_written += size;
+      t->result.writes++;
+    }
+
+    while (total_size >= t->working_set_size) {
+      // delete random
+      int bi = rand() % blobs.size();
+      total_size -= blobs[bi].second;
+      bs->Delete(blobs[bi].first);
+      blobs.erase(blobs.begin() + bi);
+      t->result.deletes++;
+    }
+  }
+  t->stopped.store(true);
+}
+
+Result StartBenchmark(vector<WorkerThread*>& config) {
+  for (auto w : config) {
+    env->StartThread(WorkerThreadBody, w);
+  }
+
+  Result result;
+
+  for (auto w : config) {
+    while (!w->stopped.load());
+    result = result + w->result;
+  }
+
+  for (auto w : config) {
+    delete w;
+  }
+
+  delete bs;
+
+  return result;
+}
+
+vector<WorkerThread*> SetupBenchmarkBalanced() {
+  string test_path;
+  env->GetTestDirectory(&test_path);
+  test_path.append("/blob_store");
+
+  // config start
+  uint32_t block_size = 16*KB;
+  uint32_t file_size = 1*MB;
+  double read_write_ratio = 0.5;
+  uint64_t data_read_from = 16*KB;
+  uint64_t data_read_to = 32*KB;
+  int number_of_threads = 10;
+  uint64_t working_set_size = 5*MB;
+  timeout_sec = 5;
+  // config end
+
+  bs = new BlobStore(test_path, block_size, file_size / block_size, 10000, env);
+
+  vector <WorkerThread*> config;
+
+  for (int i = 0; i < number_of_threads; ++i) {
+    config.push_back(new WorkerThread(data_read_from,
+                                      data_read_to,
+                                      read_write_ratio,
+                                      working_set_size));
+  };
+
+  return config;
+}
+
+vector<WorkerThread*> SetupBenchmarkWriteHeavy() {
+  string test_path;
+  env->GetTestDirectory(&test_path);
+  test_path.append("/blob_store");
+
+  // config start
+  uint32_t block_size = 16*KB;
+  uint32_t file_size = 1*MB;
+  double read_write_ratio = 0.1;
+  uint64_t data_read_from = 16*KB;
+  uint64_t data_read_to = 32*KB;
+  int number_of_threads = 10;
+  uint64_t working_set_size = 5*MB;
+  timeout_sec = 5;
+  // config end
+
+  bs = new BlobStore(test_path, block_size, file_size / block_size, 10000, env);
+
+  vector <WorkerThread*> config;
+
+  for (int i = 0; i < number_of_threads; ++i) {
+    config.push_back(new WorkerThread(data_read_from,
+                                      data_read_to,
+                                      read_write_ratio,
+                                      working_set_size));
+  };
+
+  return config;
+}
+
+vector<WorkerThread*> SetupBenchmarkReadHeavy() {
+  string test_path;
+  env->GetTestDirectory(&test_path);
+  test_path.append("/blob_store");
+
+  // config start
+  uint32_t block_size = 16*KB;
+  uint32_t file_size = 1*MB;
+  double read_write_ratio = 0.9;
+  uint64_t data_read_from = 16*KB;
+  uint64_t data_read_to = 32*KB;
+  int number_of_threads = 10;
+  uint64_t working_set_size = 5*MB;
+  timeout_sec = 5;
+  // config end
+
+  bs = new BlobStore(test_path, block_size, file_size / block_size, 10000, env);
+
+  vector <WorkerThread*> config;
+
+  for (int i = 0; i < number_of_threads; ++i) {
+    config.push_back(new WorkerThread(data_read_from,
+                                      data_read_to,
+                                      read_write_ratio,
+                                      working_set_size));
+  };
+
+  return config;
+}
+
+int main(int argc, const char** argv) {
+  srand(33);
+  env = Env::Default();
+
+  {
+    printf("--- Balanced read/write benchmark ---\n");
+    vector <WorkerThread*> config = SetupBenchmarkBalanced();
+    Result r = StartBenchmark(config);
+    r.print();
+  }
+  {
+    printf("--- Write heavy benchmark ---\n");
+    vector <WorkerThread*> config = SetupBenchmarkWriteHeavy();
+    Result r = StartBenchmark(config);
+    r.print();
+  }
+  {
+    printf("--- Read heavy benchmark ---\n");
+    vector <WorkerThread*> config = SetupBenchmarkReadHeavy();
+    Result r = StartBenchmark(config);
+    r.print();
+  }
+
+  return 0;
+}
diff --git a/tools/db_crashtest.py b/tools/db_crashtest.py
new file mode 100644 (file)
index 0000000..6270d69
--- /dev/null
@@ -0,0 +1,136 @@
+#! /usr/bin/env python
+import os
+import re
+import sys
+import time
+import random
+import getopt
+import logging
+import tempfile
+import subprocess
+
+# This script runs and kills db_stress multiple times. It checks consistency
+# in case of unsafe crashes in Rocksdb.
+
+def main(argv):
+    try:
+        opts, args = getopt.getopt(argv, "hd:t:i:o:b:")
+    except getopt.GetoptError:
+        print("db_crashtest.py -d <duration_test> -t <#threads> "
+              "-i <interval for one run> -o <ops_per_thread> "
+              "-b <write_buffer_size>\n")
+        sys.exit(2)
+
+    # default values, will be overridden by cmdline args
+    interval = 120  # time for one db_stress instance to run
+    duration = 6000  # total time for this script to test db_stress
+    threads = 32
+    # since we will be killing anyway, use large value for ops_per_thread
+    ops_per_thread = 100000000
+    write_buf_size = 4 * 1024 * 1024
+
+    for opt, arg in opts:
+        if opt == '-h':
+            print("db_crashtest.py -d <duration_test>"
+                  " -t <#threads> -i <interval for one run>"
+                  " -o <ops_per_thread> -b <write_buffer_size>\n")
+            sys.exit()
+        elif opt == "-d":
+            duration = int(arg)
+        elif opt == "-t":
+            threads = int(arg)
+        elif opt == "-i":
+            interval = int(arg)
+        elif opt == "-o":
+            ops_per_thread = int(arg)
+        elif opt == "-b":
+            write_buf_size = int(arg)
+        else:
+            print("db_crashtest.py -d <duration_test>"
+                  " -t <#threads> -i <interval for one run>"
+                  " -o <ops_per_thread> -b <write_buffer_size>\n")
+            sys.exit(2)
+
+    exit_time = time.time() + duration
+
+    print("Running blackbox-crash-test with \ninterval_between_crash="
+          + str(interval) + "\ntotal-duration=" + str(duration)
+          + "\nthreads=" + str(threads) + "\nops_per_thread="
+          + str(ops_per_thread) + "\nwrite_buffer_size="
+          + str(write_buf_size) + "\n")
+
+    while time.time() < exit_time:
+        run_had_errors = False
+        killtime = time.time() + interval
+
+        cmd = re.sub('\s+', ' ', """
+            ./db_stress
+            --test_batches_snapshots=1
+            --ops_per_thread=%s
+            --threads=%s
+            --write_buffer_size=%s
+            --destroy_db_initially=0
+            --reopen=0
+            --readpercent=45
+            --prefixpercent=5
+            --writepercent=35
+            --delpercent=5
+            --iterpercent=10
+            --db=%s
+            --max_key=100000000
+            --disable_seek_compaction=%s
+            --mmap_read=%s
+            --block_size=16384
+            --cache_size=1048576
+            --open_files=500000
+            --verify_checksum=1
+            --sync=%s
+            --disable_wal=0
+            --disable_data_sync=%s
+            --target_file_size_base=2097152
+            --target_file_size_multiplier=2
+            --max_write_buffer_number=3
+            --max_background_compactions=20
+            --max_bytes_for_level_base=10485760
+            --filter_deletes=%s
+            """ % (ops_per_thread,
+                   threads,
+                   write_buf_size,
+                   tempfile.mkdtemp(),
+                   random.randint(0, 1),
+                   random.randint(0, 1),
+                   random.randint(0, 1),
+                   random.randint(0, 1),
+                   random.randint(0, 1)))
+
+        child = subprocess.Popen([cmd],
+                                 stderr=subprocess.PIPE, shell=True)
+        print("Running db_stress with pid=%d: %s\n\n"
+              % (child.pid, cmd))
+
+        while time.time() < killtime:
+            time.sleep(10)
+
+        if child.poll() is not None:
+            print("WARNING: db_stress ended before kill: exitcode=%d\n"
+                  % child.returncode)
+        else:
+            child.kill()
+            print("KILLED %d\n" % child.pid)
+            time.sleep(1)  # time to stabilize after a kill
+
+        while True:
+            line = child.stderr.readline().strip()
+            if line != '':
+                run_had_errors = True
+                print('***' + line + '^')
+            else:
+                break
+
+        if run_had_errors:
+            sys.exit(2)
+
+        time.sleep(1)  # time to stabilize before the next run
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv[1:]))
diff --git a/tools/db_crashtest2.py b/tools/db_crashtest2.py
new file mode 100644 (file)
index 0000000..a5c6649
--- /dev/null
@@ -0,0 +1,163 @@
+#! /usr/bin/env python
+import os
+import re
+import sys
+import time
+import random
+import getopt
+import logging
+import tempfile
+import subprocess
+
+# This python script runs db_stress multiple times. Some runs with
+# kill_random_test that causes rocksdb to crash at various points in code.
+
+def main(argv):
+    try:
+        opts, args = getopt.getopt(argv, "hd:t:k:o:b:")
+    except getopt.GetoptError:
+        print str(getopt.GetoptError)
+        print "db_crashtest2.py -d <duration_test> -t <#threads> " \
+              "-k <kills with prob 1/k> -o <ops_per_thread> "\
+              "-b <write_buffer_size>\n"
+        sys.exit(2)
+
+    # default values, will be overridden by cmdline args
+    kill_random_test = 97  # kill with probability 1/97 by default
+    duration = 10000  # total time for this script to test db_stress
+    threads = 32
+    ops_per_thread = 200000
+    write_buf_size = 4 * 1024 * 1024
+
+    for opt, arg in opts:
+        if opt == '-h':
+            print "db_crashtest2.py -d <duration_test> -t <#threads> " \
+                  "-k <kills with prob 1/k> -o <ops_per_thread> " \
+                  "-b <write_buffer_size>\n"
+            sys.exit()
+        elif opt == "-d":
+            duration = int(arg)
+        elif opt == "-t":
+            threads = int(arg)
+        elif opt == "-k":
+            kill_random_test = int(arg)
+        elif opt == "-o":
+            ops_per_thread = int(arg)
+        elif opt == "-b":
+            write_buf_size = int(arg)
+        else:
+            print "unrecognized option " + str(opt) + "\n"
+            print "db_crashtest2.py -d <duration_test> -t <#threads> " \
+                  "-k <kills with prob 1/k> -o <ops_per_thread> " \
+                  "-b <write_buffer_size>\n"
+            sys.exit(2)
+
+    exit_time = time.time() + duration
+
+    print "Running whitebox-crash-test with \ntotal-duration=" + str(duration) \
+          + "\nthreads=" + str(threads) + "\nops_per_thread=" \
+          + str(ops_per_thread) + "\nwrite_buffer_size=" \
+          + str(write_buf_size) + "\n"
+
+    total_check_mode = 3
+    check_mode = 0
+
+    while time.time() < exit_time:
+        killoption = ""
+        if check_mode == 0:
+            # run with kill_random_test
+            killoption = " --kill_random_test=" + str(kill_random_test)
+            # use large ops per thread since we will kill it anyway
+            additional_opts = "--ops_per_thread=" + \
+                              str(100 * ops_per_thread) + killoption
+        elif check_mode == 1:
+            # normal run with universal compaction mode
+            additional_opts = "--ops_per_thread=" + str(ops_per_thread) + \
+                              " --compaction_style=1"
+        else:
+            # nomral run
+            additional_opts = "--ops_per_thread=" + str(ops_per_thread)
+
+        cmd = re.sub('\s+', ' ', """
+            ./db_stress
+            --test_batches_snapshots=%s
+            --threads=%s
+            --write_buffer_size=%s
+            --destroy_db_initially=0
+            --reopen=0
+            --readpercent=45
+            --prefixpercent=5
+            --writepercent=35
+            --delpercent=5
+            --iterpercent=10
+            --db=%s
+            --max_key=100000000
+            --disable_seek_compaction=%s
+            --mmap_read=%s
+            --block_size=16384
+            --cache_size=1048576
+            --open_files=500000
+            --verify_checksum=1
+            --sync=%s
+            --disable_wal=0
+            --disable_data_sync=%s
+            --target_file_size_base=2097152
+            --target_file_size_multiplier=2
+            --max_write_buffer_number=3
+            --max_background_compactions=20
+            --max_bytes_for_level_base=10485760
+            --filter_deletes=%s
+            %s
+            """ % (random.randint(0, 1),
+                   threads,
+                   write_buf_size,
+                   tempfile.mkdtemp(),
+                   random.randint(0, 1),
+                   random.randint(0, 1),
+                   random.randint(0, 1),
+                   random.randint(0, 1),
+                   random.randint(0, 1),
+                   additional_opts))
+
+        print "Running:" + cmd + "\n"
+
+        popen = subprocess.Popen([cmd], stdout=subprocess.PIPE,
+                                 stderr=subprocess.STDOUT,
+                                 shell=True)
+        stdoutdata, stderrdata = popen.communicate()
+        retncode = popen.returncode
+        msg = ("check_mode={0}, kill option={1}, exitcode={2}\n".format(
+               check_mode, killoption, retncode))
+        print msg
+        print stdoutdata
+
+        expected = False
+        if (killoption == '') and (retncode == 0):
+            # we expect zero retncode if no kill option
+            expected = True
+        elif killoption != '' and retncode < 0:
+            # we expect negative retncode if kill option was given
+            expected = True
+
+        if not expected:
+            print "TEST FAILED. See kill option and exit code above!!!\n"
+            sys.exit(1)
+
+        stdoutdata = stdoutdata.lower()
+        errorcount = (stdoutdata.count('error') -
+                      stdoutdata.count('got errors 0 times'))
+        print "#times error occured in output is " + str(errorcount) + "\n"
+
+        if (errorcount > 0):
+            print "TEST FAILED. Output has 'error'!!!\n"
+            sys.exit(2)
+        if (stdoutdata.find('fail') >= 0):
+            print "TEST FAILED. Output has 'fail'!!!\n"
+            sys.exit(2)
+
+        check_mode = (check_mode + 1) % total_check_mode
+
+        time.sleep(1)  # time to stabilize after a kill
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv[1:]))
diff --git a/tools/db_repl_stress.cc b/tools/db_repl_stress.cc
new file mode 100644 (file)
index 0000000..c22d31e
--- /dev/null
@@ -0,0 +1,132 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include <cstdio>
+
+#include <gflags/gflags.h>
+
+#include "db/write_batch_internal.h"
+#include "rocksdb/db.h"
+#include "rocksdb/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 rocksdb;
+
+struct DataPumpThread {
+  size_t no_records;
+  DB* db; // Assumption DB is Open'ed already.
+};
+
+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<DataPumpThread*>(arg);
+  DB* db = t->db;
+  Random rnd(301);
+  size_t i = 0;
+  while(i++ < t->no_records) {
+    if(!db->Put(WriteOptions(), Slice(RandomString(&rnd, 500)),
+                Slice(RandomString(&rnd, 500))).ok()) {
+      fprintf(stderr, "Error in put\n");
+      exit(1);
+    }
+  }
+}
+
+struct ReplicationThread {
+  port::AtomicPointer stop;
+  DB* db;
+  volatile size_t no_read;
+};
+
+static void ReplicationThreadBody(void* arg) {
+  ReplicationThread* t = reinterpret_cast<ReplicationThread*>(arg);
+  DB* db = t->db;
+  unique_ptr<TransactionLogIterator> iter;
+  SequenceNumber currentSeqNum = 1;
+  while (t->stop.Acquire_Load() != nullptr) {
+    iter.reset();
+    Status s;
+    while(!db->GetUpdatesSince(currentSeqNum, &iter).ok()) {
+      if (t->stop.Acquire_Load() == nullptr) {
+        return;
+      }
+    }
+    fprintf(stderr, "Refreshing iterator\n");
+    for(;iter->Valid(); iter->Next(), t->no_read++, currentSeqNum++) {
+      BatchResult res = iter->GetBatch();
+      if (res.sequence != currentSeqNum) {
+        fprintf(stderr, "Missed a seq no. b/w %ld and %ld\n", currentSeqNum,
+                        res.sequence);
+        exit(1);
+      }
+    }
+  }
+}
+
+DEFINE_uint64(num_inserts, 1000, "the num of inserts the first thread should"
+              " perform.");
+DEFINE_uint64(wal_ttl_seconds, 1000, "the wal ttl for the run(in seconds)");
+DEFINE_uint64(wal_size_limit_MB, 10, "the wal size limit for the run"
+              "(in MB)");
+
+int main(int argc, const char** argv) {
+  google::SetUsageMessage(std::string("\nUSAGE:\n") + std::string(argv[0]) +
+    " --num_inserts=<num_inserts> --wal_ttl_seconds=<WAL_ttl_seconds>" +
+    " --wal_size_limit_MB=<WAL_size_limit_MB>");
+  google::ParseCommandLineFlags(&argc, const_cast<char***>(&argv), true);
+
+  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;
+  options.WAL_size_limit_MB = FLAGS_wal_size_limit_MB;
+  DB* db;
+  DestroyDB(default_db_path, options);
+
+  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());
+    exit(1);
+  }
+
+  DataPumpThread dataPump;
+  dataPump.no_records = FLAGS_num_inserts;
+  dataPump.db = db;
+  env->StartThread(DataPumpThreadBody, &dataPump);
+
+  ReplicationThread replThread;
+  replThread.db = db;
+  replThread.no_read = 0;
+  replThread.stop.Release_Store(env); // store something to make it non-null.
+
+  env->StartThread(ReplicationThreadBody, &replThread);
+  while(replThread.no_read < FLAGS_num_inserts);
+  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\n", replThread.no_read, dataPump.no_records);
+    exit(1);
+  }
+  fprintf(stderr, "Successful!\n");
+  exit(0);
+}
diff --git a/tools/db_stress.cc b/tools/db_stress.cc
new file mode 100644 (file)
index 0000000..60324ae
--- /dev/null
@@ -0,0 +1,1539 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 function 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. To shorten/elongate the running
+// time, you could change the settings: FLAGS_max_key, FLAGS_ops_per_thread,
+// (sometimes also FLAGS_threads).
+//
+// NOTE that if FLAGS_test_batches_snapshots is set, the test will have
+// different behavior. See comment of the flag for details.
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <gflags/gflags.h>
+#include "db/db_impl.h"
+#include "db/version_set.h"
+#include "db/db_statistics.h"
+#include "rocksdb/cache.h"
+#include "utilities/utility_db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/write_batch.h"
+#include "rocksdb/statistics.h"
+#include "port/port.h"
+#include "util/coding.h"
+#include "util/crc32c.h"
+#include "util/histogram.h"
+#include "util/mutexlock.h"
+#include "util/random.h"
+#include "util/testutil.h"
+#include "util/logging.h"
+#include "utilities/ttl/db_ttl.h"
+#include "hdfs/env_hdfs.h"
+#include "utilities/merge_operators.h"
+
+static const long KB = 1024;
+
+
+static bool ValidateUint32Range(const char* flagname, uint64_t value) {
+  if (value > std::numeric_limits<uint32_t>::max()) {
+    fprintf(stderr, "Invalid value for --%s: %lu, overflow\n", flagname, value);
+    return false;
+  }
+  return true;
+}
+DEFINE_uint64(seed, 2341234, "Seed for PRNG");
+static const bool FLAGS_seed_dummy =
+  google::RegisterFlagValidator(&FLAGS_seed, &ValidateUint32Range);
+
+DEFINE_int64(max_key, 1 * KB * KB * KB,
+             "Max number of key/values to place in database");
+
+DEFINE_bool(test_batches_snapshots, false,
+            "If set, the test uses MultiGet(), MultiPut() and MultiDelete()"
+            " which read/write/delete multiple keys in a batch. In this mode,"
+            " we do not verify db content by comparing the content with the "
+            "pre-allocated array. Instead, we do partial verification inside"
+            " MultiGet() by checking various values in a batch. Benefit of"
+            " this mode:\n"
+            "\t(a) No need to acquire mutexes during writes (less cache "
+            "flushes in multi-core leading to speed up)\n"
+            "\t(b) No long validation at the end (more speed up)\n"
+            "\t(c) Test snapshot and atomicity of batch writes");
+
+DEFINE_int32(threads, 32, "Number of concurrent threads to run.");
+
+DEFINE_int32(ttl, -1,
+             "Opens the db with this ttl value if this is not -1. "
+             "Carefully specify a large value such that verifications on "
+             "deleted values don't fail");
+
+DEFINE_int32(value_size_mult, 8,
+             "Size of value will be this number times rand_int(1,3) bytes");
+
+DEFINE_bool(verify_before_write, false, "Verify before write");
+
+DEFINE_bool(histogram, false, "Print histogram of operation timings");
+
+DEFINE_bool(destroy_db_initially, true,
+            "Destroys the database dir before start if this is true");
+
+DEFINE_bool (verbose, false, "Verbose");
+
+DEFINE_int32(write_buffer_size, rocksdb::Options().write_buffer_size,
+             "Number of bytes to buffer in memtable before compacting");
+
+DEFINE_int32(max_write_buffer_number,
+             rocksdb::Options().max_write_buffer_number,
+             "The number of in-memory memtables. "
+             "Each memtable is of size FLAGS_write_buffer_size.");
+
+DEFINE_int32(min_write_buffer_number_to_merge,
+             rocksdb::Options().min_write_buffer_number_to_merge,
+             "The minimum number of write buffers that will be merged together "
+             "before writing to storage. This is cheap because it is an "
+             "in-memory merge. If this feature is not enabled, then all these "
+             "write buffers are flushed to L0 as separate files and this "
+             "increases read amplification because a get request has to check "
+             "in all of these files. Also, an in-memory merge may result in "
+             "writing less data to storage if there are duplicate records in"
+             " each of these individual write buffers.");
+
+DEFINE_int32(open_files, rocksdb::Options().max_open_files,
+             "Maximum number of files to keep open at the same time "
+             "(use default if == 0)");
+
+DEFINE_int64(compressed_cache_size, -1,
+             "Number of bytes to use as a cache of compressed data."
+             " Negative means use default settings.");
+
+DEFINE_int32(compaction_style, rocksdb::Options().compaction_style, "");
+
+DEFINE_int32(level0_file_num_compaction_trigger,
+             rocksdb::Options().level0_file_num_compaction_trigger,
+             "Level0 compaction start trigger");
+
+DEFINE_int32(level0_slowdown_writes_trigger,
+             rocksdb::Options().level0_slowdown_writes_trigger,
+             "Number of files in level-0 that will slow down writes");
+
+DEFINE_int32(level0_stop_writes_trigger,
+             rocksdb::Options().level0_stop_writes_trigger,
+             "Number of files in level-0 that will trigger put stop.");
+
+DEFINE_int32(block_size, rocksdb::Options().block_size,
+             "Number of bytes in a block.");
+
+DEFINE_int32(max_background_compactions,
+             rocksdb::Options().max_background_compactions,
+             "The maximum number of concurrent background compactions "
+             "that can occur in parallel.");
+
+DEFINE_int32(universal_size_ratio, 0, "The ratio of file sizes that trigger"
+             " compaction in universal style");
+
+DEFINE_int32(universal_min_merge_width, 0, "The minimum number of files to "
+             "compact in universal style compaction");
+
+DEFINE_int32(universal_max_merge_width, 0, "The max number of files to compact"
+             " in universal style compaction");
+
+DEFINE_int32(universal_max_size_amplification_percent, 0,
+             "The max size amplification for universal style compaction");
+
+DEFINE_int64(cache_size, 2 * KB * KB * KB,
+             "Number of bytes to use as a cache of uncompressed data.");
+
+static bool ValidateInt32Positive(const char* flagname, int32_t value) {
+  if (value < 0) {
+    fprintf(stderr, "Invalid value for --%s: %d, must be >=0\n",
+            flagname, value);
+    return false;
+  }
+  return true;
+}
+DEFINE_int32(reopen, 10, "Number of times database reopens");
+static const bool FLAGS_reopen_dummy =
+  google::RegisterFlagValidator(&FLAGS_reopen, &ValidateInt32Positive);
+
+DEFINE_int32(bloom_bits, 10, "Bloom filter bits per key. "
+             "Negative means use default settings.");
+
+DEFINE_string(db, "", "Use the db with the following name.");
+
+DEFINE_bool(verify_checksum, false,
+            "Verify checksum for every block read from storage");
+
+DEFINE_bool(mmap_read, rocksdb::EnvOptions().use_mmap_reads,
+            "Allow reads to occur via mmap-ing files");
+
+// Database statistics
+static std::shared_ptr<rocksdb::Statistics> dbstats;
+DEFINE_bool(statistics, false, "Create database statistics");
+
+DEFINE_bool(sync, false, "Sync all writes to disk");
+
+DEFINE_bool(disable_data_sync, false,
+            "If true, do not wait until data is synced to disk.");
+
+DEFINE_bool(use_fsync, false, "If true, issue fsync instead of fdatasync");
+
+DEFINE_int32(kill_random_test, 0,
+             "If non-zero, kill at various points in source code with "
+             "probability 1/this");
+static const bool FLAGS_kill_random_test_dummy =
+  google::RegisterFlagValidator(&FLAGS_kill_random_test,
+                                &ValidateInt32Positive);
+extern int rocksdb_kill_odds;
+
+DEFINE_bool(disable_wal, false, "If true, do not write WAL for write.");
+
+DEFINE_int32(target_file_size_base, 64 * KB,
+             "Target level-1 file size for compaction");
+
+DEFINE_int32(target_file_size_multiplier, 1,
+             "A multiplier to compute targe level-N file size (N >= 2)");
+
+DEFINE_uint64(max_bytes_for_level_base, 256 * KB, "Max bytes for level-1");
+
+DEFINE_int32(max_bytes_for_level_multiplier, 2,
+             "A multiplier to compute max bytes for level-N (N >= 2)");
+
+static bool ValidateInt32Percent(const char* flagname, int32_t value) {
+  if (value < 0 || value>100) {
+    fprintf(stderr, "Invalid value for --%s: %d, 0<= pct <=100 \n",
+            flagname, value);
+    return false;
+  }
+  return true;
+}
+DEFINE_int32(readpercent, 10,
+             "Ratio of reads to total workload (expressed as a percentage)");
+static const bool FLAGS_readpercent_dummy =
+  google::RegisterFlagValidator(&FLAGS_readpercent, &ValidateInt32Percent);
+
+DEFINE_int32(prefixpercent, 20,
+             "Ratio of prefix iterators to total workload (expressed as a"
+             " percentage)");
+static const bool FLAGS_prefixpercent_dummy =
+  google::RegisterFlagValidator(&FLAGS_prefixpercent, &ValidateInt32Percent);
+
+DEFINE_int32(writepercent, 45,
+             " Ratio of deletes to total workload (expressed as a percentage)");
+static const bool FLAGS_writepercent_dummy =
+  google::RegisterFlagValidator(&FLAGS_writepercent, &ValidateInt32Percent);
+
+DEFINE_int32(delpercent, 15,
+             "Ratio of deletes to total workload (expressed as a percentage)");
+static const bool FLAGS_delpercent_dummy =
+  google::RegisterFlagValidator(&FLAGS_delpercent, &ValidateInt32Percent);
+
+DEFINE_int32(iterpercent, 10, "Ratio of iterations to total workload"
+             " (expressed as a percentage)");
+static const bool FLAGS_iterpercent_dummy =
+  google::RegisterFlagValidator(&FLAGS_iterpercent, &ValidateInt32Percent);
+
+DEFINE_uint64(num_iterations, 10, "Number of iterations per MultiIterate run");
+static const bool FLAGS_num_iterations_dummy =
+  google::RegisterFlagValidator(&FLAGS_num_iterations, &ValidateUint32Range);
+
+DEFINE_bool(disable_seek_compaction, false,
+            "Option to disable compation triggered by read.");
+
+DEFINE_uint64(delete_obsolete_files_period_micros, 0,
+              "Option to delete obsolete files periodically"
+              "0 means that obsolete files are "
+              " deleted after every compaction run.");
+
+enum rocksdb::CompressionType StringToCompressionType(const char* ctype) {
+  assert(ctype);
+
+  if (!strcasecmp(ctype, "none"))
+    return rocksdb::kNoCompression;
+  else if (!strcasecmp(ctype, "snappy"))
+    return rocksdb::kSnappyCompression;
+  else if (!strcasecmp(ctype, "zlib"))
+    return rocksdb::kZlibCompression;
+  else if (!strcasecmp(ctype, "bzip2"))
+    return rocksdb::kBZip2Compression;
+
+  fprintf(stdout, "Cannot parse compression type '%s'\n", ctype);
+  return rocksdb::kSnappyCompression; //default value
+}
+DEFINE_string(compression_type, "snappy",
+              "Algorithm to use to compress the database");
+static enum rocksdb::CompressionType FLAGS_compression_type_e =
+    rocksdb::kSnappyCompression;
+
+DEFINE_string(hdfs, "", "Name of hdfs environment");
+// posix or hdfs environment
+static rocksdb::Env* FLAGS_env = rocksdb::Env::Default();
+
+DEFINE_uint64(ops_per_thread, 600000, "Number of operations per thread.");
+static const bool FLAGS_ops_per_thread_dummy =
+  google::RegisterFlagValidator(&FLAGS_ops_per_thread, &ValidateUint32Range);
+
+DEFINE_uint64(log2_keys_per_lock, 2, "Log2 of number of keys per lock");
+static const bool FLAGS_log2_keys_per_lock_dummy =
+  google::RegisterFlagValidator(&FLAGS_log2_keys_per_lock,
+                                &ValidateUint32Range);
+
+DEFINE_int32(purge_redundant_percent, 50,
+             "Percentage of times we want to purge redundant keys in memory "
+             "before flushing");
+static const bool FLAGS_purge_redundant_percent_dummy =
+  google::RegisterFlagValidator(&FLAGS_purge_redundant_percent,
+                                &ValidateInt32Percent);
+
+DEFINE_bool(filter_deletes, false, "On true, deletes use KeyMayExist to drop"
+            " the delete if key not present");
+
+enum RepFactory {
+  kSkipList,
+  kPrefixHash,
+  kUnsorted,
+  kVectorRep
+};
+enum RepFactory StringToRepFactory(const char* ctype) {
+  assert(ctype);
+
+  if (!strcasecmp(ctype, "skip_list"))
+    return kSkipList;
+  else if (!strcasecmp(ctype, "prefix_hash"))
+    return kPrefixHash;
+  else if (!strcasecmp(ctype, "unsorted"))
+    return kUnsorted;
+  else if (!strcasecmp(ctype, "vector"))
+    return kVectorRep;
+
+  fprintf(stdout, "Cannot parse memreptable %s\n", ctype);
+  return kSkipList;
+}
+static enum RepFactory FLAGS_rep_factory;
+DEFINE_string(memtablerep, "skip_list", "");
+
+static bool ValidatePrefixSize(const char* flagname, int32_t value) {
+  if (value < 0 || value>=2000000000) {
+    fprintf(stderr, "Invalid value for --%s: %d. 0<= PrefixSize <=2000000000\n",
+            flagname, value);
+    return false;
+  }
+  return true;
+}
+DEFINE_int32(prefix_size, 0, "Control the prefix size for PrefixHashRep");
+static const bool FLAGS_prefix_size_dummy =
+  google::RegisterFlagValidator(&FLAGS_prefix_size, &ValidatePrefixSize);
+
+DEFINE_bool(use_merge, false, "On true, replaces all writes with a Merge "
+            "that behaves like a Put");
+
+
+namespace rocksdb {
+
+// convert long to a big-endian slice key
+static std::string Key(long val) {
+  std::string little_endian_key;
+  std::string big_endian_key;
+  PutFixed64(&little_endian_key, val);
+  assert(little_endian_key.size() == sizeof(val));
+  big_endian_key.resize(sizeof(val));
+  for (int i=0; i<(int)sizeof(val); i++) {
+    big_endian_key[i] = little_endian_key[sizeof(val) - 1 - i];
+  }
+  return big_endian_key;
+}
+
+class StressTest;
+namespace {
+
+class Stats {
+ private:
+  double start_;
+  double finish_;
+  double seconds_;
+  long done_;
+  long gets_;
+  long prefixes_;
+  long writes_;
+  long deletes_;
+  long iterator_size_sums_;
+  long founds_;
+  long iterations_;
+  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;
+    gets_ = 0;
+    prefixes_ = 0;
+    writes_ = 0;
+    deletes_ = 0;
+    iterator_size_sums_ = 0;
+    founds_ = 0;
+    iterations_ = 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_;
+    gets_ += other.gets_;
+    prefixes_ += other.prefixes_;
+    writes_ += other.writes_;
+    deletes_ += other.deletes_;
+    iterator_size_sums_ += other.iterator_size_sums_;
+    founds_ += other.founds_;
+    iterations_ += other.iterations_;
+    errors_ += other.errors_;
+    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(stdout, "long op: %.1f micros%30s\r", micros, "");
+      }
+      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(stdout, "... finished %ld ops%30s\r", done_, "");
+    }
+  }
+
+  void AddBytesForWrites(int nwrites, size_t nbytes) {
+    writes_ += nwrites;
+    bytes_ += nbytes;
+  }
+
+  void AddGets(int ngets, int nfounds) {
+    founds_ += nfounds;
+    gets_ += ngets;
+  }
+
+  void AddPrefixes(int nprefixes, int count) {
+    prefixes_ += nprefixes;
+    iterator_size_sums_ += count;
+  }
+
+  void AddIterations(int n) {
+    iterations_ += n;
+  }
+
+  void AddDeletes(int n) {
+    deletes_ += 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: Wrote %ld times\n", "", writes_);
+    fprintf(stdout, "%-12s: Deleted %ld times\n", "", deletes_);
+    fprintf(stdout, "%-12s: %ld read and %ld found the key\n", "",
+            gets_, founds_);
+    fprintf(stdout, "%-12s: Prefix scanned %ld times\n", "", prefixes_);
+    fprintf(stdout, "%-12s: Iterator size sum is %ld\n", "",
+            iterator_size_sums_);
+    fprintf(stdout, "%-12s: Iterated %ld times\n", "", iterations_);
+    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)),
+        compressed_cache_(FLAGS_compressed_cache_size >= 0 ?
+                          NewLRUCache(FLAGS_compressed_cache_size) :
+                          nullptr),
+        filter_policy_(FLAGS_bloom_bits >= 0
+                       ? NewBloomFilterPolicy(FLAGS_bloom_bits)
+                       : nullptr),
+        prefix_extractor_(NewFixedPrefixTransform(
+                          FLAGS_test_batches_snapshots ?
+                          sizeof(long) : sizeof(long)-1)),
+        db_(nullptr),
+        num_times_reopened_(0) {
+    if (FLAGS_destroy_db_initially) {
+      std::vector<std::string> 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(FLAGS_db + "/" + files[i]);
+        }
+      }
+      DestroyDB(FLAGS_db, Options());
+    }
+  }
+
+  ~StressTest() {
+    delete db_;
+    delete filter_policy_;
+    delete prefix_extractor_;
+  }
+
+  void Run() {
+    PrintEnv();
+    Open();
+    SharedState shared(this);
+    uint32_t n = shared.GetNumThreads();
+
+    std::vector<ThreadState*> 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();
+      if (FLAGS_test_batches_snapshots) {
+        fprintf(stdout, "%s Limited verification already done during gets\n",
+                FLAGS_env->TimeToString((uint64_t) now/1000000).c_str());
+      } else {
+        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();
+    if (!FLAGS_test_batches_snapshots) {
+      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<ThreadState*>(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);
+    }
+
+    {
+      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];
+      if (FLAGS_use_merge) {
+        batch.Merge(keys[i], value_slices[i]);
+      } else {
+        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] = "";
+        thread->stats.AddGets(1, 0);
+      } else {
+        values[i] = *value;
+
+        char expected_prefix = (keys[i])[0];
+        char actual_prefix = (values[i])[0];
+        if (actual_prefix != expected_prefix) {
+          fprintf(stderr, "error expected prefix = %c actual = %c\n",
+                  expected_prefix, actual_prefix);
+        }
+        (values[i])[0] = ' '; // blank out the differing character
+        thread->stats.AddGets(1, 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, "error : 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;
+  }
+
+  // Given a prefix P, this does prefix scans for "0"+P, "1"+P,..."9"+P
+  // in the same snapshot.  Each of these 10 scans returns a series of
+  // values; each series should be the same length, and it is verified
+  // for each index i that all the i'th values are of the form "0"+V,
+  // "1"+V,..."9"+V.
+  // ASSUMES that MultiPut was used to put (K, V)
+  Status MultiPrefixScan(ThreadState* thread,
+                         const ReadOptions& readoptions,
+                         const Slice& prefix) {
+    std::string prefixes[10] = {"0", "1", "2", "3", "4",
+                                "5", "6", "7", "8", "9"};
+    Slice prefix_slices[10];
+    ReadOptions readoptionscopy[10];
+    const Snapshot* snapshot = db_->GetSnapshot();
+    Iterator* iters[10];
+    Status s = Status::OK();
+    for (int i = 0; i < 10; i++) {
+      prefixes[i] += prefix.ToString();
+      prefix_slices[i] = prefixes[i];
+      readoptionscopy[i] = readoptions;
+      readoptionscopy[i].prefix = &prefix_slices[i];
+      readoptionscopy[i].snapshot = snapshot;
+      iters[i] = db_->NewIterator(readoptionscopy[i]);
+      iters[i]->SeekToFirst();
+    }
+
+    int count = 0;
+    while (iters[0]->Valid()) {
+      count++;
+      std::string values[10];
+      // get list of all values for this iteration
+      for (int i = 0; i < 10; i++) {
+        // no iterator should finish before the first one
+        assert(iters[i]->Valid());
+        values[i] = iters[i]->value().ToString();
+
+        char expected_first = (prefixes[i])[0];
+        char actual_first = (values[i])[0];
+
+        if (actual_first != expected_first) {
+          fprintf(stderr, "error expected first = %c actual = %c\n",
+                  expected_first, actual_first);
+        }
+        (values[i])[0] = ' '; // blank out the differing character
+      }
+      // make sure all values are equivalent
+      for (int i = 0; i < 10; i++) {
+        if (values[i] != values[0]) {
+          fprintf(stderr, "error : inconsistent values for prefix %s: %s, %s\n",
+                  prefix.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
+        }
+        iters[i]->Next();
+      }
+    }
+
+    // cleanup iterators and snapshot
+    for (int i = 0; i < 10; i++) {
+      // if the first iterator finished, they should have all finished
+      assert(!iters[i]->Valid());
+      assert(iters[i]->status().ok());
+      delete iters[i];
+    }
+    db_->ReleaseSnapshot(snapshot);
+
+    if (s.ok()) {
+      thread->stats.AddPrefixes(1, count);
+    } else {
+      thread->stats.AddErrors(1);
+    }
+
+    return s;
+  }
+
+  // Given a key K, this creates an iterator which scans to K and then
+  // does a random sequence of Next/Prev operations.
+  Status MultiIterate(ThreadState* thread,
+                      const ReadOptions& readoptions,
+                      const Slice& key) {
+    Status s;
+    const Snapshot* snapshot = db_->GetSnapshot();
+    ReadOptions readoptionscopy = readoptions;
+    readoptionscopy.snapshot = snapshot;
+    unique_ptr<Iterator> iter(db_->NewIterator(readoptionscopy));
+
+    iter->Seek(key);
+    for (uint64_t i = 0; i < FLAGS_num_iterations && iter->Valid(); i++) {
+      if (thread->rand.OneIn(2)) {
+        iter->Next();
+      } else {
+        iter->Prev();
+      }
+    }
+
+    if (s.ok()) {
+      thread->stats.AddIterations(1);
+    } else {
+      thread->stats.AddErrors(1);
+    }
+
+    db_->ReleaseSnapshot(snapshot);
+
+    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;
+    const int prefixBound = (int)FLAGS_readpercent + (int)FLAGS_prefixpercent;
+    const int writeBound = prefixBound + (int)FLAGS_writepercent;
+    const int delBound = writeBound + (int)FLAGS_delpercent;
+
+    thread->stats.Start();
+    for (uint64_t 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();
+          }
+          // Commenting this out as we don't want to reset stats on each open.
+          // thread->stats.Start();
+        }
+      }
+
+      long rand_key = thread->rand.Next() % max_key;
+      std::string keystr = Key(rand_key);
+      Slice key = keystr;
+      int prob_op = thread->rand.Uniform(100);
+
+      if (prob_op >= 0 && prob_op < (int)FLAGS_readpercent) {
+        // OPERATION read
+        if (!FLAGS_test_batches_snapshots) {
+          Status s = db_->Get(read_opts, key, &from_db);
+          if (s.ok()) {
+            // found case
+            thread->stats.AddGets(1, 1);
+          } else if (s.IsNotFound()) {
+            // not found case
+            thread->stats.AddGets(1, 0);
+          } else {
+            // errors case
+            thread->stats.AddErrors(1);
+          }
+        } else {
+          MultiGet(thread, read_opts, key, &from_db);
+        }
+      } else if ((int)FLAGS_readpercent <= prob_op && prob_op < prefixBound) {
+        // OPERATION prefix scan
+        // keys are longs (e.g., 8 bytes), so we let prefixes be
+        // everything except the last byte.  So there will be 2^8=256
+        // keys per prefix.
+        Slice prefix = Slice(key.data(), key.size() - 1);
+        if (!FLAGS_test_batches_snapshots) {
+          read_opts.prefix = &prefix;
+          Iterator* iter = db_->NewIterator(read_opts);
+          int count = 0;
+          for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
+            assert(iter->key().starts_with(prefix));
+            count++;
+          }
+          assert(count <= 256);
+          if (iter->status().ok()) {
+            thread->stats.AddPrefixes(1, count);
+          } else {
+            thread->stats.AddErrors(1);
+          }
+          delete iter;
+        } else {
+          MultiPrefixScan(thread, read_opts, prefix);
+        }
+      } else if (prefixBound <= prob_op && prob_op < writeBound) {
+        // OPERATION write
+        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) {
+            std::string keystr = Key(rand_key);
+            Slice k = keystr;
+            Status s = db_->Get(read_opts, k, &from_db);
+            VerifyValue(rand_key,
+                        read_opts,
+                        *(thread->shared),
+                        from_db,
+                        s,
+                        true);
+          }
+          thread->shared->Put(rand_key, value_base);
+          if (FLAGS_use_merge) {
+            db_->Merge(write_opts, key, v);
+          } else {
+            db_->Put(write_opts, key, v);
+          }
+          thread->stats.AddBytesForWrites(1, sz);
+        } else {
+          MultiPut(thread, write_opts, key, v, sz);
+        }
+        PrintKeyValue(rand_key, value, sz);
+      } else if (writeBound <= prob_op && prob_op < delBound) {
+        // OPERATION delete
+        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 {
+        // OPERATION iterate
+        MultiIterate(thread, read_opts, key);
+      }
+      thread->stats.FinishedSingleOp();
+    }
+
+    thread->stats.Stop();
+  }
+
+  void VerifyDb(ThreadState* thread) const {
+    ReadOptions options(FLAGS_verify_checksum, true);
+    const SharedState& shared = *(thread->shared);
+    static const long max_key = shared.GetMaxKey();
+    static const long keys_per_thread = max_key / shared.GetNumThreads();
+    long start = keys_per_thread * thread->tid;
+    long end = start + keys_per_thread;
+    if (thread->tid == shared.GetNumThreads() - 1) {
+      end = max_key;
+    }
+    if (!thread->rand.OneIn(2)) {
+      // Use iterator to verify this range
+      unique_ptr<Iterator> iter(db_->NewIterator(options));
+      iter->Seek(Key(start));
+      for (long i = start; i < end; i++) {
+        std::string from_db;
+        std::string keystr = Key(i);
+        Slice k = keystr;
+        Status s = iter->status();
+        if (iter->Valid()) {
+          if (iter->key().compare(k) > 0) {
+            s = Status::NotFound(Slice());
+          } else if (iter->key().compare(k) == 0) {
+            from_db = iter->value().ToString();
+            iter->Next();
+          } else if (iter->key().compare(k) < 0) {
+            VerificationAbort("An out of range key was found", i);
+          }
+        } else {
+          // The iterator found no value for the key in question, so do not
+          // move to the next item in the iterator
+          s = Status::NotFound(Slice());
+        }
+        VerifyValue(i, options, shared, from_db, s, true);
+        if (from_db.length()) {
+          PrintKeyValue(i, from_db.data(), from_db.length());
+        }
+      }
+    }
+    else {
+      // Use Get to verify this range
+      for (long i = start; i < end; i++) {
+        std::string from_db;
+        std::string keystr = Key(i);
+        Slice k = keystr;
+        Status s = db_->Get(options, k, &from_db);
+        VerifyValue(i, options, shared, from_db, s, 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,
+                   const std::string &value_from_db,
+                   Status s,
+                   bool strict=false) const {
+    // compare value_from_db with the value in the shared state
+    char value[100];
+    uint32_t value_base = shared.Get(key);
+    if (value_base == SharedState::SENTINEL && !strict) {
+      return;
+    }
+
+    if (s.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<sz; i++) {
+      fprintf(stdout, "%X", value[i]);
+    }
+    fprintf(stdout, "\n");
+  }
+
+  static size_t GenerateValue(uint32_t rand, char *v, size_t max_sz) {
+    size_t value_sz = ((rand % 3) + 1) * FLAGS_value_size_mult;
+    assert(value_sz <= max_sz && value_sz >= sizeof(uint32_t));
+    *((uint32_t*)v) = rand;
+    for (size_t i=sizeof(uint32_t); i < value_sz; i++) {
+      v[i] = (char)(rand ^ i);
+    }
+    v[value_sz] = '\0';
+    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      : %lu\n", FLAGS_ops_per_thread);
+    std::string ttl_state("unused");
+    if (FLAGS_ttl > 0) {
+      ttl_state = NumberToString(FLAGS_ttl);
+    }
+    fprintf(stdout, "Time to live(sec)   : %s\n", ttl_state.c_str());
+    fprintf(stdout, "Read percentage     : %d%%\n", FLAGS_readpercent);
+    fprintf(stdout, "Prefix percentage   : %d%%\n", FLAGS_prefixpercent);
+    fprintf(stdout, "Write percentage    : %d%%\n", FLAGS_writepercent);
+    fprintf(stdout, "Delete percentage   : %d%%\n", FLAGS_delpercent);
+    fprintf(stdout, "Iterate percentage  : %d%%\n", FLAGS_iterpercent);
+    fprintf(stdout, "Write-buffer-size   : %d\n", FLAGS_write_buffer_size);
+    fprintf(stdout, "Iterations          : %lu\n", FLAGS_num_iterations);
+    fprintf(stdout, "Max key             : %ld\n", FLAGS_max_key);
+    fprintf(stdout, "Ratio #ops/#keys    : %f\n",
+            (1.0 * 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, "Deletes use filter  : %d\n",
+            FLAGS_filter_deletes);
+    fprintf(stdout, "Num keys per lock   : %d\n",
+            1 << FLAGS_log2_keys_per_lock);
+
+    const char* compression = "";
+    switch (FLAGS_compression_type_e) {
+      case rocksdb::kNoCompression:
+        compression = "none";
+        break;
+      case rocksdb::kSnappyCompression:
+        compression = "snappy";
+        break;
+      case rocksdb::kZlibCompression:
+        compression = "zlib";
+        break;
+      case rocksdb::kBZip2Compression:
+        compression = "bzip2";
+        break;
+    }
+
+    fprintf(stdout, "Compression         : %s\n", compression);
+
+    const char* memtablerep = "";
+    switch (FLAGS_rep_factory) {
+      case kSkipList:
+        memtablerep = "skip_list";
+        break;
+      case kPrefixHash:
+        memtablerep = "prefix_hash";
+        break;
+      case kUnsorted:
+        memtablerep = "unsorted";
+        break;
+      case kVectorRep:
+        memtablerep = "vector";
+        break;
+    }
+
+    fprintf(stdout, "Memtablerep         : %s\n", memtablerep);
+
+    fprintf(stdout, "------------------------------------------------\n");
+  }
+
+  void Open() {
+    assert(db_ == nullptr);
+    Options options;
+    options.block_cache = cache_;
+    options.block_cache_compressed = compressed_cache_;
+    options.write_buffer_size = FLAGS_write_buffer_size;
+    options.max_write_buffer_number = FLAGS_max_write_buffer_number;
+    options.min_write_buffer_number_to_merge =
+      FLAGS_min_write_buffer_number_to_merge;
+    options.max_background_compactions = FLAGS_max_background_compactions;
+    options.compaction_style =
+      static_cast<rocksdb::CompactionStyle>(FLAGS_compaction_style);
+    options.block_size = FLAGS_block_size;
+    options.filter_policy = filter_policy_;
+    options.prefix_extractor = prefix_extractor_;
+    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.allow_mmap_reads = FLAGS_mmap_read;
+    rocksdb_kill_odds = FLAGS_kill_random_test;
+    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.level0_file_num_compaction_trigger =
+      FLAGS_level0_file_num_compaction_trigger;
+    options.compression = FLAGS_compression_type_e;
+    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;
+    options.filter_deletes = FLAGS_filter_deletes;
+    if ((FLAGS_prefix_size == 0) == (FLAGS_rep_factory == kPrefixHash)) {
+      fprintf(stderr,
+            "prefix_size should be non-zero iff memtablerep == prefix_hash\n");
+      exit(1);
+    }
+    switch (FLAGS_rep_factory) {
+      case kPrefixHash:
+        options.memtable_factory.reset(
+          new PrefixHashRepFactory(NewFixedPrefixTransform(FLAGS_prefix_size))
+        );
+        break;
+      case kUnsorted:
+        options.memtable_factory.reset(
+          new UnsortedRepFactory()
+        );
+        break;
+      case kSkipList:
+        // no need to do anything
+        break;
+      case kVectorRep:
+        options.memtable_factory.reset(
+          new VectorRepFactory()
+        );
+        break;
+    }
+    static Random purge_percent(1000); // no benefit from non-determinism here
+    if (static_cast<int32_t>(purge_percent.Uniform(100)) <
+        FLAGS_purge_redundant_percent - 1) {
+      options.purge_redundant_kvs_while_flush = false;
+    }
+
+    if (FLAGS_use_merge) {
+      options.merge_operator = MergeOperators::CreatePutOperator();
+    }
+
+    // set universal style compaction configurations, if applicable
+    if (FLAGS_universal_size_ratio != 0) {
+      options.compaction_options_universal.size_ratio =
+        FLAGS_universal_size_ratio;
+    }
+    if (FLAGS_universal_min_merge_width != 0) {
+      options.compaction_options_universal.min_merge_width =
+        FLAGS_universal_min_merge_width;
+    }
+    if (FLAGS_universal_max_merge_width != 0) {
+      options.compaction_options_universal.max_merge_width =
+        FLAGS_universal_max_merge_width;
+    }
+    if (FLAGS_universal_max_size_amplification_percent != 0) {
+      options.compaction_options_universal.max_size_amplification_percent =
+        FLAGS_universal_max_size_amplification_percent;
+    }
+
+    fprintf(stdout, "DB path: [%s]\n", FLAGS_db.c_str());
+
+    Status s;
+    if (FLAGS_ttl == -1) {
+      s = DB::Open(options, FLAGS_db, &db_);
+    } else {
+      s = UtilityDB::OpenTtlDB(options, FLAGS_db, &sdb_, FLAGS_ttl);
+      db_ = sdb_;
+    }
+    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.
+    if (FLAGS_ttl != -1) {
+      ((DBWithTTL*) db_)->TEST_Destroy_DBWithTtl();
+    } else {
+      ((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, "STATISTICS:\n%s\n", dbstats->ToString().c_str());
+    }
+  }
+
+ private:
+  shared_ptr<Cache> cache_;
+  shared_ptr<Cache> compressed_cache_;
+  const FilterPolicy* filter_policy_;
+  const SliceTransform* prefix_extractor_;
+  DB* db_;
+  StackableDB* sdb_;
+  int num_times_reopened_;
+};
+
+}  // namespace rocksdb
+
+
+
+int main(int argc, char** argv) {
+  google::SetUsageMessage(std::string("\nUSAGE:\n") + std::string(argv[0]) +
+                          " [OPTIONS]...");
+  google::ParseCommandLineFlags(&argc, &argv, true);
+
+  if (FLAGS_statistics) {
+    dbstats = rocksdb::CreateDBStatistics();
+  }
+  FLAGS_compression_type_e =
+    StringToCompressionType(FLAGS_compression_type.c_str());
+  if (!FLAGS_hdfs.empty()) {
+    FLAGS_env  = new rocksdb::HdfsEnv(FLAGS_hdfs);
+  }
+  FLAGS_rep_factory = StringToRepFactory(FLAGS_memtablerep.c_str());
+
+  // 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_prefixpercent +
+       FLAGS_writepercent + FLAGS_delpercent + FLAGS_iterpercent) != 100) {
+      fprintf(stderr,
+              "Error: Read+Prefix+Write+Delete+Iterate percents != 100!\n");
+      exit(1);
+  }
+  if (FLAGS_disable_wal == 1 && FLAGS_reopen > 0) {
+      fprintf(stderr, "Error: Db cannot reopen safely with disable_wal set!\n");
+      exit(1);
+  }
+  if ((unsigned)FLAGS_reopen >= FLAGS_ops_per_thread) {
+      fprintf(stderr, "Error: #DB-reopens should be < ops_per_thread\n"
+        "Provided reopens = %d and ops_per_thread = %lu\n", FLAGS_reopen,
+        FLAGS_ops_per_thread);
+      exit(1);
+  }
+
+  // Choose a location for the test database if none given with --db=<path>
+  if (FLAGS_db.empty()) {
+      std::string default_db_path;
+      rocksdb::Env::Default()->GetTestDirectory(&default_db_path);
+      default_db_path += "/dbstress";
+      FLAGS_db = default_db_path;
+  }
+
+  rocksdb::StressTest stress;
+  stress.Run();
+  return 0;
+}
diff --git a/tools/ldb.cc b/tools/ldb.cc
new file mode 100644 (file)
index 0000000..4581b80
--- /dev/null
@@ -0,0 +1,13 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+
+#include "rocksdb/ldb_tool.h"
+
+int main(int argc, char** argv) {
+  rocksdb::LDBTool tool;
+  tool.Run(argc, argv);
+  return 0;
+}
diff --git a/tools/ldb_test.py b/tools/ldb_test.py
new file mode 100644 (file)
index 0000000..a549b89
--- /dev/null
@@ -0,0 +1,356 @@
+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(stderr=subprocess.PIPE, 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
+
+def run_err_null(cmd):
+    return os.system(cmd + " 2>/dev/null ")
+
+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, unexpected=False):
+        """
+        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)
+        if not unexpected:
+            self.assertEqual(output.strip(), expectedOutput.strip())
+        else:
+            self.assertNotEqual(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 >/dev/null 2>&1 |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, unexpected=False):
+        """
+        Uses the default test db.
+
+        """
+        self.assertRunOKFull("%s %s" % (self.dbParam(self.DB_NAME), params),
+                             expectedOutput, unexpected)
+
+    def assertRunFAIL(self, params):
+        """
+        Uses the default test db.
+        """
+        self.assertRunFAILFull("%s %s" % (self.dbParam(self.DB_NAME), params))
+
+    def testSimpleStringPutGet(self):
+        print "Running testSimpleStringPutGet..."
+        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 weird that GET and SCAN raise exception for
+        # non-existent key, while delete does not
+
+    def dumpDb(self, params, dumpFile):
+        return 0 == run_err_null("./ldb dump %s > %s" % (params, dumpFile))
+
+    def loadDb(self, params, dumpFile):
+        return 0 == run_err_null("cat %s | ./ldb load %s" % (dumpFile, params))
+
+    def testStringBatchPut(self):
+        print "Running testStringBatchPut..."
+        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 testCountDelimDump(self):
+        print "Running testCountDelimDump..."
+        self.assertRunOK("batchput x.1 x1 --create_if_missing", "OK")
+        self.assertRunOK("batchput y.abc abc y.2 2 z.13c pqr", "OK")
+        self.assertRunOK("dump --count_delim", "x => count:1\tsize:5\ny => count:2\tsize:12\nz => count:1\tsize:8")
+        self.assertRunOK("dump --count_delim=\".\"", "x => count:1\tsize:5\ny => count:2\tsize:12\nz => count:1\tsize:8")
+        self.assertRunOK("batchput x,2 x2 x,abc xabc", "OK")
+        self.assertRunOK("dump --count_delim=\",\"", "x => count:2\tsize:14\nx.1 => count:1\tsize:5\ny.2 => count:1\tsize:4\ny.abc => count:1\tsize:8\nz.13c => count:1\tsize:8")
+
+    def testCountDelimIDump(self):
+        print "Running testCountDelimIDump..."
+        self.assertRunOK("batchput x.1 x1 --create_if_missing", "OK")
+        self.assertRunOK("batchput y.abc abc y.2 2 z.13c pqr", "OK")
+        self.assertRunOK("dump --count_delim", "x => count:1\tsize:5\ny => count:2\tsize:12\nz => count:1\tsize:8")
+        self.assertRunOK("dump --count_delim=\".\"", "x => count:1\tsize:5\ny => count:2\tsize:12\nz => count:1\tsize:8")
+        self.assertRunOK("batchput x,2 x2 x,abc xabc", "OK")
+        self.assertRunOK("dump --count_delim=\",\"", "x => count:2\tsize:14\nx.1 => count:1\tsize:5\ny.2 => count:1\tsize:4\ny.abc => count:1\tsize:8\nz.13c => count:1\tsize:8")
+
+    def testInvalidCmdLines(self):
+        print "Running testInvalidCmdLines..."
+        # 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
+
+    def testHexPutGet(self):
+        print "Running testHexPutGet..."
+        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 testTtlPutGet(self):
+        print "Running testTtlPutGet..."
+        self.assertRunOK("put a1 b1 --ttl --create_if_missing", "OK")
+        self.assertRunOK("scan ", "a1 : b1", True)
+        self.assertRunOK("dump --ttl ", "a1 ==> b1", True)
+        self.assertRunOK("scan --hex --ttl", "0x6131 : 0x6231")
+        self.assertRunOK("get a1", "b1", True)
+        self.assertRunOK("get --ttl a1", "b1")
+        self.assertRunOK("put a3 b3 --create_if_missing", "OK")
+        # fails because timstamp's length is greater than value's
+        self.assertRunFAIL("get --ttl a3")
+
+    def testInvalidCmdLines(self):
+        print "Running testInvalidCmdLines..."
+        # 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):
+        print "Running testDumpLoad..."
+        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):
+        print "Running testMiscAdminTask..."
+        # 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 == run_err_null(
+            "./ldb compact --db=%s" % origDbPath))
+        self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
+
+        self.assertTrue(0 == run_err_null(
+            "./ldb reduce_levels --db=%s --new_levels=2" % origDbPath))
+        self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
+
+        self.assertTrue(0 == run_err_null(
+            "./ldb reduce_levels --db=%s --new_levels=3" % origDbPath))
+        self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
+
+        self.assertTrue(0 == run_err_null(
+            "./ldb compact --db=%s --from=x1 --to=x3" % origDbPath))
+        self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
+
+        self.assertTrue(0 == run_err_null(
+            "./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 == run_err_null(
+            "./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/reduce_levels_test.cc b/tools/reduce_levels_test.cc
new file mode 100644 (file)
index 0000000..b588b52
--- /dev/null
@@ -0,0 +1,197 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "rocksdb/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 rocksdb {
+
+class ReduceLevelTest {
+public:
+  ReduceLevelTest() {
+    dbname_ = test::TmpDir() + "/db_reduce_levels_test";
+    DestroyDB(dbname_, Options());
+    db_ = nullptr;
+  }
+
+  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_ == nullptr) {
+      return Status::InvalidArgument("DB not opened.");
+    }
+    DBImpl* db_impl = reinterpret_cast<DBImpl*>(db_);
+    return db_impl->TEST_FlushMemTable();
+  }
+
+  void CloseDB() {
+    if (db_ != nullptr) {
+      delete db_;
+      db_ = nullptr;
+    }
+  }
+
+  bool ReduceLevels(int target_level);
+
+  int FilesOnLevel(int level) {
+    std::string property;
+    ASSERT_TRUE(
+        db_->GetProperty("rocksdb.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) {
+  rocksdb::Options opt;
+  opt.num_levels = num_levels;
+  opt.create_if_missing = create_if_missing;
+  opt.max_mem_compaction_level = mem_table_compact_level;
+  rocksdb::Status st = rocksdb::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<std::string> args = rocksdb::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 rocksdb::test::RunAllTests();
+}
diff --git a/tools/shell/DBClientProxy.cpp b/tools/shell/DBClientProxy.cpp
new file mode 100644 (file)
index 0000000..93277ac
--- /dev/null
@@ -0,0 +1,271 @@
+
+#include <boost/shared_ptr.hpp>
+
+#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 rocksdb {
+
+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<TSocket> socket(new TSocket(host_, port_));
+    boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
+    boost::shared_ptr<TBinaryProtocol> 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<string, DBHandle>::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<string, DBHandle>::iterator
+DBClientProxy::getHandle(const string & db) {
+  map<string, DBHandle>::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<string, DBHandle>::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<string, DBHandle>::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<pair<string, string> > & 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<string, DBHandle>::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 (file)
index 0000000..fba228b
--- /dev/null
@@ -0,0 +1,64 @@
+
+#ifndef TOOLS_SHELL_DBCLIENTPROXY
+#define TOOLS_SHELL_DBCLIENTPROXY
+
+#include <vector>
+#include <map>
+#include <string>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "DB.h"
+
+/*
+ * class DBClientProxy maintains:
+ * 1. a connection to rocksdb service
+ * 2. a map from db names to opened db handles
+ *
+ * it's client codes' responsibility to catch all possible exceptions.
+ */
+
+namespace rocksdb {
+
+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<std::pair<std::string, std::string> > & 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<std::string, Trocksdb::DBHandle>::iterator getHandle(const std::string & db);
+
+  const std::string host_;
+  const int port_;
+  std::map<std::string, Trocksdb::DBHandle> dbToHandle_;
+  boost::shared_ptr<Trocksdb::DBClient> dbClient_;
+};
+
+} // namespace
+#endif
diff --git a/tools/shell/LeveldbShell.cpp b/tools/shell/LeveldbShell.cpp
new file mode 100644 (file)
index 0000000..e6274d3
--- /dev/null
@@ -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 (file)
index 0000000..05a9bb8
--- /dev/null
@@ -0,0 +1,104 @@
+
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+
+#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 rocksdb;
+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<pair<string, string> > 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 (file)
index 0000000..5c2b944
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef TOOLS_SHELL_SHELLCONTEXT
+#define TOOLS_SHELL_SHELLCONTEXT
+
+#include <map>
+#include <string>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+
+#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<rocksdb::DBClientProxy> clientProxy_;
+};
+
+#endif
diff --git a/tools/shell/ShellState.cpp b/tools/shell/ShellState.cpp
new file mode 100644 (file)
index 0000000..057a337
--- /dev/null
@@ -0,0 +1,139 @@
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#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<string> 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 (file)
index 0000000..ce3f676
--- /dev/null
@@ -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 rocksdb 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 (file)
index 0000000..3b64ffc
--- /dev/null
@@ -0,0 +1,182 @@
+/**
+ * Tests for DBClientProxy class for leveldb
+ * @author Bo Liu (newpoo.liu@gmail.com)
+ * Copyright 2012 Facebook
+ */
+
+#include <algorithm>
+#include <vector>
+#include <string>
+#include <protocol/TBinaryProtocol.h>
+#include <transport/TSocket.h>
+#include <transport/TBufferTransports.h>
+#include <util/testharness.h>
+#include <DB.h>
+#include <AssocService.h>
+#include <leveldb_types.h>
+
+#include "server_options.h"
+
+
+#include "../DBClientProxy.h"
+using namespace rocksdb;
+
+
+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<string> keys, values;
+  vector<pair<string, string> > 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<pair<string, string> > 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<pair<string, string> > 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<pair<string, string> > 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 (file)
index 0000000..9038895
--- /dev/null
@@ -0,0 +1,261 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "db/dbformat.h"
+#include "db/memtable.h"
+#include "db/write_batch_internal.h"
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/iterator.h"
+#include "rocksdb/table.h"
+#include "table/block.h"
+#include "table/block_builder.h"
+#include "table/format.h"
+#include "util/ldb_cmd.h"
+#include "util/random.h"
+#include "util/testharness.h"
+#include "util/testutil.h"
+
+namespace rocksdb {
+
+class SstFileReader {
+ public:
+  explicit SstFileReader(const std::string& file_name,
+                         bool verify_checksum,
+                         bool output_hex);
+
+  Status ReadSequential(bool print_kv,
+                        uint64_t read_num,
+                        bool has_from,
+                        const std::string& from_key,
+                        bool has_to,
+                        const std::string& to_key);
+
+  uint64_t GetReadNumber() { return read_num_; }
+
+private:
+  std::string file_name_;
+  uint64_t read_num_;
+  bool verify_checksum_;
+  bool output_hex_;
+  EnvOptions soptions_;
+};
+
+SstFileReader::SstFileReader(const 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) {
+  std::cout << "Process " << file_path << "\n";
+}
+
+Status SstFileReader::ReadSequential(bool print_kv,
+                                     uint64_t read_num,
+                                     bool has_from,
+                                     const std::string& from_key,
+                                     bool has_to,
+                                     const std::string& to_key)
+{
+  unique_ptr<TableReader> table_reader;
+  InternalKeyComparator internal_comparator_(BytewiseComparator());
+  Options table_options;
+  table_options.comparator = &internal_comparator_;
+  unique_ptr<RandomAccessFile> file;
+  Status s = table_options.env->NewRandomAccessFile(file_name_, &file,
+                                                    soptions_);
+  if(!s.ok()) {
+   return s;
+  }
+  uint64_t file_size;
+  table_options.env->GetFileSize(file_name_, &file_size);
+  unique_ptr<TableFactory> table_factory;
+  s = table_options.table_factory->GetTableReader(table_options, soptions_,
+                                                  std::move(file), file_size,
+                                                  &table_reader);
+  if(!s.ok()) {
+   return s;
+  }
+
+  Iterator* iter = table_reader->NewIterator(ReadOptions(verify_checksum_,
+                                                         false));
+  uint64_t i = 0;
+  if (has_from) {
+    InternalKey ikey(from_key, kMaxSequenceNumber, kValueTypeForSeek);
+    iter->Seek(ikey.Encode());
+  } else {
+    iter->SeekToFirst();
+  }
+  for (; iter->Valid(); iter->Next()) {
+    Slice key = iter->key();
+    Slice value = iter->value();
+    ++i;
+    if (read_num > 0 && i > read_num)
+      break;
+
+    ParsedInternalKey ikey;
+    if (!ParseInternalKey(key, &ikey)) {
+      std::cerr << "Internal Key ["
+                << key.ToString(true /* in hex*/)
+                << "] parse error!\n";
+      continue;
+    }
+
+    // If end marker was specified, we stop before it
+    if (has_to && BytewiseComparator()->Compare(ikey.user_key, to_key) >= 0) {
+      break;
+    }
+
+    if (print_kv) {
+      std::cout << ikey.DebugString(output_hex_)
+                << " => "
+                << value.ToString(output_hex_) << "\n";
+    }
+
+   }
+
+   read_num_ += i;
+
+   Status ret = iter->status();
+   delete iter;
+   return ret;
+}
+
+} // namespace rocksdb
+
+static void print_help() {
+  fprintf(stderr,
+      "sst_dump [--command=check|scan] [--verify_checksum] "
+      "--file=data_dir_OR_sst_file"
+      " [--output_hex]"
+      " [--input_key_hex]"
+      " [--from=<user_key>]"
+      " [--to=<user_key>]"
+      " [--read_num=NUM]\n");
+}
+
+string HexToString(const string& str) {
+  string parsed;
+  if (str[0] != '0' || str[1] != 'x') {
+    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;
+}
+
+int main(int argc, char** argv) {
+
+  const char* dir_or_file = nullptr;
+  uint64_t read_num = -1;
+  std::string command;
+
+  char junk;
+  uint64_t n;
+  bool verify_checksum = false;
+  bool output_hex = false;
+  bool input_key_hex = false;
+  bool has_from = false;
+  bool has_to = false;
+  std::string from_key;
+  std::string to_key;
+  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 (strcmp(argv[i], "--input_key_hex") == 0) {
+      input_key_hex = true;
+    } else if (sscanf(argv[i],
+               "--read_num=%lu%c",
+               (unsigned long*)&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 if (strncmp(argv[i], "--from=", 7) == 0) {
+      from_key = argv[i] + 7;
+      has_from = true;
+    } else if (strncmp(argv[i], "--to=", 5) == 0) {
+      to_key = argv[i] + 5;
+      has_to = true;
+    }else {
+      print_help();
+      exit(1);
+    }
+  }
+
+
+  if (input_key_hex) {
+    if (has_from) {
+      from_key = HexToString(from_key);
+    }
+    if (has_to) {
+      to_key = HexToString(to_key);
+    }
+  }
+
+  if(dir_or_file == nullptr) {
+    print_help();
+    exit(1);
+  }
+
+  std::vector<std::string> filenames;
+  rocksdb::Env* env = rocksdb::Env::Default();
+  rocksdb::Status st = env->GetChildren(dir_or_file, &filenames);
+  bool dir = true;
+  if (!st.ok()) {
+    filenames.clear();
+    filenames.push_back(dir_or_file);
+    dir = false;
+  }
+
+  std::cout << "from [" << rocksdb::Slice(from_key).ToString(true)
+            << "] to [" << rocksdb::Slice(to_key).ToString(true) << "]\n";
+
+  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;
+    }
+    rocksdb::SstFileReader reader(filename, verify_checksum,
+                                  output_hex);
+    rocksdb::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,
+                                 has_from, from_key, has_to, to_key);
+      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_impl.cc b/util/arena_impl.cc
new file mode 100644 (file)
index 0000000..d5c2a53
--- /dev/null
@@ -0,0 +1,78 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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_impl.h"
+
+namespace rocksdb {
+
+ArenaImpl::ArenaImpl(size_t block_size) {
+  if (block_size < kMinBlockSize) {
+    block_size_ = kMinBlockSize;
+  } else if (block_size > kMaxBlockSize) {
+    block_size_ = kMaxBlockSize;
+  } else {
+    block_size_ = block_size;
+  }
+
+  blocks_memory_ = 0;
+  alloc_ptr_ = nullptr;  // First allocation will allocate a block
+  alloc_bytes_remaining_ = 0;
+}
+
+ArenaImpl::~ArenaImpl() {
+  for (size_t i = 0; i < blocks_.size(); i++) {
+    delete[] blocks_[i];
+  }
+}
+
+char* ArenaImpl::AllocateFallback(size_t bytes) {
+  if (bytes > block_size_ / 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(block_size_);
+  alloc_bytes_remaining_ = block_size_;
+
+  char* result = alloc_ptr_;
+  alloc_ptr_ += bytes;
+  alloc_bytes_remaining_ -= bytes;
+  return result;
+}
+
+char* ArenaImpl::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<uintptr_t>(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<uintptr_t>(result) & (align-1)) == 0);
+  return result;
+}
+
+char* ArenaImpl::AllocateNewBlock(size_t block_bytes) {
+  char* result = new char[block_bytes];
+  blocks_memory_ += block_bytes;
+  blocks_.push_back(result);
+  return result;
+}
+
+}  // namespace rocksdb
diff --git a/util/arena_impl.h b/util/arena_impl.h
new file mode 100644 (file)
index 0000000..b5a6842
--- /dev/null
@@ -0,0 +1,84 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+// ArenaImpl is an implementation of Arena class. For a request of small size,
+// it allocates a block with pre-defined block size. For a request of big
+// size, it uses malloc to directly get the requested size.
+
+#pragma once
+#include <cstddef>
+#include <vector>
+#include <assert.h>
+#include <stdint.h>
+#include "rocksdb/arena.h"
+
+namespace rocksdb {
+
+class ArenaImpl : public Arena {
+ public:
+  explicit ArenaImpl(size_t block_size = kMinBlockSize);
+  virtual ~ArenaImpl();
+
+  virtual char* Allocate(size_t bytes);
+
+  virtual 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).
+  //
+  // TODO: Do we need to exclude space allocated but not used?
+  virtual const size_t ApproximateMemoryUsage() {
+    return blocks_memory_ + blocks_.capacity() * sizeof(char*);
+  }
+
+  virtual const size_t MemoryAllocatedBytes() {
+    return blocks_memory_;
+  }
+
+ private:
+  char* AllocateFallback(size_t bytes);
+  char* AllocateNewBlock(size_t block_bytes);
+
+  static const size_t kMinBlockSize = 4096;
+  static const size_t kMaxBlockSize = 2 << 30;
+
+  // Number of bytes allocated in one block
+  size_t block_size_;
+
+  // Allocation state
+  char* alloc_ptr_;
+  size_t alloc_bytes_remaining_;
+
+  // Array of new[] allocated memory blocks
+  std::vector<char*> blocks_;
+
+  // Bytes of memory in blocks allocated so far
+  size_t blocks_memory_;
+
+  // No copying allowed
+  ArenaImpl(const ArenaImpl&);
+  void operator=(const ArenaImpl&);
+};
+
+inline char* ArenaImpl::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 rocksdb
diff --git a/util/arena_test.cc b/util/arena_test.cc
new file mode 100644 (file)
index 0000000..12aa7f7
--- /dev/null
@@ -0,0 +1,110 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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_impl.h"
+#include "util/random.h"
+#include "util/testharness.h"
+
+namespace rocksdb {
+
+class ArenaImplTest { };
+
+TEST(ArenaImplTest, Empty) {
+  ArenaImpl arena0;
+}
+
+TEST(ArenaImplTest, MemoryAllocatedBytes) {
+  const int N = 17;
+  size_t req_sz;  //requested size
+  size_t bsz = 8192;  // block size
+  size_t expected_memory_allocated;
+
+  ArenaImpl arena_impl(bsz);
+
+  // requested size > quarter of a block:
+  //   allocate requested size separately
+  req_sz = 3001;
+  for (int i = 0; i < N; i++) {
+    arena_impl.Allocate(req_sz);
+  }
+  expected_memory_allocated = req_sz * N;
+  ASSERT_EQ(arena_impl.MemoryAllocatedBytes(), expected_memory_allocated);
+
+  // requested size < quarter of a block:
+  //   allocate a block with the default size, then try to use unused part
+  //   of the block. So one new block will be allocated for the first
+  //   Allocate(99) call. All the remaining calls won't lead to new allocation.
+  req_sz = 99;
+  for (int i = 0; i < N; i++) {
+    arena_impl.Allocate(req_sz);
+  }
+  expected_memory_allocated += bsz;
+  ASSERT_EQ(arena_impl.MemoryAllocatedBytes(), expected_memory_allocated);
+
+  // requested size > quarter of a block:
+  //   allocate requested size separately
+  req_sz = 99999999;
+  for (int i = 0; i < N; i++) {
+    arena_impl.Allocate(req_sz);
+  }
+  expected_memory_allocated += req_sz * N;
+  ASSERT_EQ(arena_impl.MemoryAllocatedBytes(), expected_memory_allocated);
+}
+
+TEST(ArenaImplTest, Simple) {
+  std::vector<std::pair<size_t, char*> > allocated;
+  ArenaImpl arena_impl;
+  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_impl.AllocateAligned(s);
+    } else {
+      r = arena_impl.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_impl.ApproximateMemoryUsage(), bytes);
+    if (i > N/10) {
+      ASSERT_LE(arena_impl.ApproximateMemoryUsage(), 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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/auto_roll_logger.cc b/util/auto_roll_logger.cc
new file mode 100644 (file)
index 0000000..95f2fae
--- /dev/null
@@ -0,0 +1,108 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "util/auto_roll_logger.h"
+#include "util/mutexlock.h"
+
+using namespace std;
+
+namespace rocksdb {
+
+// -- 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<uint64_t>(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());
+
+  std::shared_ptr<Logger> logger;
+  {
+    MutexLock l(&mutex_);
+    if ((kLogFileTimeToRoll > 0 && LogExpired()) ||
+        (kMaxLogFileSize > 0 && logger_->GetLogFileSize() >= kMaxLogFileSize)) {
+      RollLogFile();
+      ResetLogger();
+    }
+
+    // pin down the current logger_ instance before releasing the mutex.
+    logger = logger_;
+  }
+
+  // Another thread could have put a new Logger instance into logger_ by now.
+  // However, since logger is still hanging on to the previous instance
+  // (reference count is not zero), we don't have to worry about it being
+  // deleted while we are accessing it.
+  // Note that logv itself is not mutex protected to allow maximum concurrency,
+  // as thread safety should have been handled by the underlying logger.
+  logger->Logv(format, ap);
+}
+
+bool AutoRollLogger::LogExpired() {
+  if (cached_now_access_count >= call_NowMicros_every_N_records_) {
+    cached_now = static_cast<uint64_t>(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>* 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 rocksdb
diff --git a/util/auto_roll_logger.h b/util/auto_roll_logger.h
new file mode 100644 (file)
index 0000000..db70f15
--- /dev/null
@@ -0,0 +1,90 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// Logger implementation that can be shared by all environments
+// where enough posix functionality is available.
+
+#pragma once
+#include "db/filename.h"
+#include "port/port.h"
+#include "util/posix_logger.h"
+
+namespace rocksdb {
+
+// 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<uint64_t>(env_->NowMicros() * 1e-6)),
+     ctime_(cached_now),
+     cached_now_access_count(0),
+     call_NowMicros_every_N_records_(100),
+     mutex_() {
+    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> 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_;
+  port::Mutex mutex_;
+};
+
+// 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>* logger);
+
+}  // namespace rocksdb
diff --git a/util/auto_roll_logger_test.cc b/util/auto_roll_logger_test.cc
new file mode 100755 (executable)
index 0000000..2fd2c51
--- /dev/null
@@ -0,0 +1,262 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include <string>
+#include <cmath>
+#include "util/testharness.h"
+#include "util/auto_roll_logger.h"
+#include "rocksdb/db.h"
+#include <sys/stat.h>
+#include <errno.h>
+#include <iostream>
+
+using namespace std;
+
+namespace rocksdb {
+
+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<uint64_t>(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());
+  // Since rotation is checked before actual logging, we need to
+  // trigger the rotation by logging another message.
+  LogMessage(logger, log_message.c_str());
+
+  ASSERT_TRUE(message_size == 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(Env::Default(), kTestDir, "", log_max_size, 0);
+
+    RollLogFileBySizeTest(&logger, log_max_size,
+                          kSampleMessage + ":RollLogFileBySize");
+
+}
+
+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(Env::Default(), kTestDir, "", log_size, 1);
+    ASSERT_TRUE(env->FileExists(kLogFile));
+
+    RollLogFileByTimeTest(&logger, time, kSampleMessage + ":RollLogFileByTime");
+}
+
+TEST(AutoRollLoggerTest,
+     OpenLogFilesMultipleTimesWithOptionLog_max_size) {
+  // If only 'log_max_size' options is specified, then every time
+  // when rocksdb 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(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> logger;
+
+  // Normal logger
+  ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger));
+  ASSERT_TRUE(dynamic_cast<PosixLogger*>(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<AutoRollLogger*>(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<AutoRollLogger*>(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<AutoRollLogger*>(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<std::string> files;
+  Env::Default()->GetChildren(dir, &files);
+  int log_file_count = 0;
+
+  for (std::vector<std::string>::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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/bit_set.h b/util/bit_set.h
new file mode 100644 (file)
index 0000000..0172706
--- /dev/null
@@ -0,0 +1,71 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+#include <cassert>
+
+namespace rocksdb {
+
+class BitSet {
+ public:
+  /**
+   * Create a bit set of numBits, with the bits set to either true or false.
+   */
+  explicit BitSet(size_t numBits, bool initial=false)
+    : numBits_(numBits),
+      data_(numWords(), initial ? ~0UL : 0UL) {
+  }
+
+  /**
+   * Set bit b to 1.
+   */
+  void set(size_t b) {
+    assert(b >= 0 && b < numBits_);
+    data_[word(b)] |= wordOffsetMask(b);
+  }
+
+  /**
+   * Set bit b to 0;
+   */
+  void reset(size_t b) {
+    assert(b >= 0 && b < numBits_);
+    data_[word(b)] &= ~wordOffsetMask(b);
+  }
+
+  /**
+   * Get a bit.
+   */
+  bool test(int b) const {
+    return data_[word(b)] & wordOffsetMask(b);
+  }
+
+ /**
+   * Return the size of the BitSet, in bits.
+   */
+  size_t size() const {
+    return numBits_;
+  }
+
+ private:
+
+ inline size_t numWords() const {
+    if (numBits_ == 0) return 0;
+    return 1 + (numBits_-1) / (8*sizeof(unsigned long));
+  }
+  inline static size_t word(int b) {
+    return b / (8*sizeof(unsigned long));
+  }
+  inline static int wordOffset(int b) {
+    return b % (8*sizeof(unsigned long));
+  }
+  inline static unsigned long wordOffsetMask(int b) {
+    return 1UL << wordOffset(b);
+  }
+
+  size_t numBits_;
+  std::vector<unsigned long> data_;
+};
+
+}  // namespace facebook
diff --git a/util/blob_store.cc b/util/blob_store.cc
new file mode 100644 (file)
index 0000000..9f06712
--- /dev/null
@@ -0,0 +1,264 @@
+// 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/blob_store.h"
+
+namespace rocksdb {
+
+using namespace std;
+
+// BlobChunk
+bool BlobChunk::ImmediatelyBefore(const BlobChunk& chunk) const {
+  // overlapping!?
+  assert(!Overlap(chunk));
+  // size == 0 is a marker, not a block
+  return size != 0 &&
+    bucket_id == chunk.bucket_id &&
+    offset + size == chunk.offset;
+}
+
+bool BlobChunk::Overlap(const BlobChunk &chunk) const {
+  return size != 0 && chunk.size != 0 && bucket_id == chunk.bucket_id &&
+    ((offset >= chunk.offset && offset < chunk.offset + chunk.size) ||
+     (chunk.offset >= offset && chunk.offset < offset + size));
+}
+
+// Blob
+string Blob::ToString() const {
+  string ret;
+  for (auto chunk : chunks) {
+    PutFixed32(&ret, chunk.bucket_id);
+    PutFixed32(&ret, chunk.offset);
+    PutFixed32(&ret, chunk.size);
+  }
+  return ret;
+}
+
+Blob::Blob(const std::string& blob) {
+  for (uint32_t i = 0; i < blob.size(); ) {
+    uint32_t t[3] = {0};
+    for (int j = 0; j < 3 && i + sizeof(uint32_t) - 1 < blob.size();
+                    ++j, i += sizeof(uint32_t)) {
+      t[j] = DecodeFixed32(blob.data() + i);
+    }
+    chunks.push_back(BlobChunk(t[0], t[1], t[2]));
+  }
+}
+
+// FreeList
+Status FreeList::Free(const Blob& blob) {
+  // add it back to the free list
+  for (auto chunk : blob.chunks) {
+    free_blocks_ += chunk.size;
+    if (fifo_free_chunks_.size() &&
+        fifo_free_chunks_.back().ImmediatelyBefore(chunk)) {
+      fifo_free_chunks_.back().size += chunk.size;
+    } else {
+      fifo_free_chunks_.push_back(chunk);
+    }
+  }
+
+  return Status::OK();
+}
+
+Status FreeList::Allocate(uint32_t blocks, Blob* blob) {
+  if (free_blocks_ < blocks) {
+    return Status::Incomplete("");
+  }
+
+  blob->chunks.clear();
+  free_blocks_ -= blocks;
+
+  while (blocks > 0) {
+    assert(fifo_free_chunks_.size() > 0);
+    auto& front = fifo_free_chunks_.front();
+    if (front.size > blocks) {
+      blob->chunks.push_back(BlobChunk(front.bucket_id, front.offset, blocks));
+      front.offset += blocks;
+      front.size -= blocks;
+      blocks = 0;
+    } else {
+      blob->chunks.push_back(front);
+      blocks -= front.size;
+      fifo_free_chunks_.pop_front();
+    }
+  }
+  assert(blocks == 0);
+
+  return Status::OK();
+}
+
+bool FreeList::Overlap(const Blob &blob) const {
+  for (auto chunk : blob.chunks) {
+    for (auto itr = fifo_free_chunks_.begin();
+         itr != fifo_free_chunks_.end();
+         ++itr) {
+      if (itr->Overlap(chunk)) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+// BlobStore
+BlobStore::BlobStore(const string& directory,
+                     uint64_t block_size,
+                     uint32_t blocks_per_bucket,
+                     uint32_t max_buckets,
+                     Env* env) :
+    directory_(directory),
+    block_size_(block_size),
+    blocks_per_bucket_(blocks_per_bucket),
+    env_(env),
+    max_buckets_(max_buckets) {
+  env_->CreateDirIfMissing(directory_);
+
+  storage_options_.use_mmap_writes = false;
+  storage_options_.use_mmap_reads = false;
+
+  buckets_size_ = 0;
+  buckets_ = new unique_ptr<RandomRWFile>[max_buckets_];
+
+  CreateNewBucket();
+}
+
+BlobStore::~BlobStore() {
+  // TODO we don't care about recovery for now
+  delete [] buckets_;
+}
+
+Status BlobStore::Put(const Slice& value, Blob* blob) {
+  // convert size to number of blocks
+  Status s = Allocate((value.size() + block_size_ - 1) / block_size_, blob);
+  if (!s.ok()) {
+    return s;
+  }
+  auto size_left = (uint64_t) value.size();
+
+  uint64_t offset = 0; // in bytes, not blocks
+  for (auto chunk : blob->chunks) {
+    uint64_t write_size = min(chunk.size * block_size_, size_left);
+    assert(chunk.bucket_id < buckets_size_);
+    s = buckets_[chunk.bucket_id].get()->Write(chunk.offset * block_size_,
+                                               Slice(value.data() + offset,
+                                                     write_size));
+    if (!s.ok()) {
+      Delete(*blob);
+      return s;
+    }
+    offset += write_size;
+    size_left -= write_size;
+    if (write_size < chunk.size * block_size_) {
+      // if we have any space left in the block, fill it up with zeros
+      string zero_string(chunk.size * block_size_ - write_size, 0);
+      s = buckets_[chunk.bucket_id].get()->Write(chunk.offset * block_size_ +
+                                                    write_size,
+                                                 Slice(zero_string));
+    }
+  }
+
+  if (size_left > 0) {
+    Delete(*blob);
+    return Status::IOError("Tried to write more data than fits in the blob");
+  }
+
+  return Status::OK();
+}
+
+Status BlobStore::Get(const Blob& blob,
+                      string* value) const {
+  {
+    // assert that it doesn't overlap with free list
+    // it will get compiled out for release
+    MutexLock l(&free_list_mutex_);
+    assert(!free_list_.Overlap(blob));
+  }
+
+  value->resize(blob.Size() * block_size_);
+
+  uint64_t offset = 0; // in bytes, not blocks
+  for (auto chunk : blob.chunks) {
+    Slice result;
+    assert(chunk.bucket_id < buckets_size_);
+    Status s;
+    s = buckets_[chunk.bucket_id].get()->Read(chunk.offset * block_size_,
+                                              chunk.size * block_size_,
+                                              &result,
+                                              &value->at(offset));
+    if (!s.ok() || result.size() < chunk.size * block_size_) {
+      value->clear();
+      return Status::IOError("Could not read in from file");
+    }
+    offset += chunk.size * block_size_;
+  }
+
+  // remove the '\0's at the end of the string
+  value->erase(find(value->begin(), value->end(), '\0'), value->end());
+
+  return Status::OK();
+}
+
+Status BlobStore::Delete(const Blob& blob) {
+  MutexLock l(&free_list_mutex_);
+  return free_list_.Free(blob);
+}
+
+Status BlobStore::Sync() {
+  for (size_t i = 0; i < buckets_size_; ++i) {
+    Status s = buckets_[i].get()->Sync();
+    if (!s.ok()) {
+      return s;
+    }
+  }
+  return Status::OK();
+}
+
+Status BlobStore::Allocate(uint32_t blocks, Blob* blob) {
+  MutexLock l(&free_list_mutex_);
+  Status s;
+
+  s = free_list_.Allocate(blocks, blob);
+  if (!s.ok()) {
+    s = CreateNewBucket();
+    if (!s.ok()) {
+      return s;
+    }
+    s = free_list_.Allocate(blocks, blob);
+  }
+
+  return s;
+}
+
+// called with free_list_mutex_ held
+Status BlobStore::CreateNewBucket() {
+  MutexLock l(&buckets_mutex_);
+
+  if (buckets_size_ >= max_buckets_) {
+    return Status::IOError("Max size exceeded\n");
+  }
+
+  int new_bucket_id = buckets_size_;
+
+  char fname[200];
+  sprintf(fname, "%s/%d.bs", directory_.c_str(), new_bucket_id);
+
+  Status s = env_->NewRandomRWFile(string(fname),
+                                   &buckets_[new_bucket_id],
+                                   storage_options_);
+  if (!s.ok()) {
+    return s;
+  }
+
+  // whether Allocate succeeds or not, does not affect the overall correctness
+  // of this function - calling Allocate is really optional
+  // (also, tmpfs does not support allocate)
+  buckets_[new_bucket_id].get()->Allocate(0, block_size_ * blocks_per_bucket_);
+
+  buckets_size_ = new_bucket_id + 1;
+
+  return free_list_.Free(Blob(new_bucket_id, 0, blocks_per_bucket_));
+}
+
+} // namespace rocksdb
diff --git a/util/blob_store.h b/util/blob_store.h
new file mode 100644 (file)
index 0000000..0a81d01
--- /dev/null
@@ -0,0 +1,161 @@
+// 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.
+
+#pragma once
+#include "rocksdb/env.h"
+#include "rocksdb/status.h"
+#include "port/port.h"
+#include "util/mutexlock.h"
+#include "util/coding.h"
+
+#include <list>
+#include <deque>
+#include <cstdint>
+#include <iostream>
+#include <stdexcept>
+#include <algorithm>
+#include <cstdio>
+
+namespace rocksdb {
+
+struct BlobChunk {
+  uint32_t bucket_id;
+  uint32_t offset; // in blocks
+  uint32_t size; // in blocks
+  BlobChunk() {}
+  BlobChunk(uint32_t bucket_id, uint32_t offset, uint32_t size) :
+    bucket_id(bucket_id), offset(offset), size(size) {}
+
+  // returns true if it's immediately before chunk
+  bool ImmediatelyBefore(const BlobChunk& chunk) const;
+  // returns true if chunks overlap
+  bool Overlap(const BlobChunk &chunk) const;
+};
+
+// We represent each Blob as a string in format:
+// bucket_id offset size|bucket_id offset size...
+// The string can be used to reference the Blob stored on external
+// device/file
+// Not thread-safe!
+struct Blob {
+  // Generates the string
+  std::string ToString() const;
+  // Parses the previously generated string
+  explicit Blob(const std::string& blob);
+  // Creates unfragmented Blob
+  Blob(uint32_t bucket_id, uint32_t offset, uint32_t size) {
+    SetOneChunk(bucket_id, offset, size);
+  }
+  Blob() {}
+
+  void SetOneChunk(uint32_t bucket_id, uint32_t offset, uint32_t size) {
+    chunks.clear();
+    chunks.push_back(BlobChunk(bucket_id, offset, size));
+  }
+
+  uint32_t Size() const { // in blocks
+    uint32_t ret = 0;
+    for (auto chunk : chunks) {
+      ret += chunk.size;
+    }
+    assert(ret > 0);
+    return ret;
+  }
+
+  // bucket_id, offset, size
+  std::vector<BlobChunk> chunks;
+};
+
+// Keeps a list of free chunks
+// NOT thread-safe. Externally synchronized
+class FreeList {
+ public:
+  FreeList() :
+    free_blocks_(0) {}
+  ~FreeList() {}
+
+  // Allocates a a blob. Stores the allocated blob in
+  // 'blob'. Returns non-OK status if it failed to allocate.
+  // Thread-safe
+  Status Allocate(uint32_t blocks, Blob* blob);
+  // Frees the blob for reuse. Thread-safe
+  Status Free(const Blob& blob);
+
+  // returns true if blob is overlapping with any of the
+  // chunks stored in free list
+  bool Overlap(const Blob &blob) const;
+
+ private:
+  std::deque<BlobChunk> fifo_free_chunks_;
+  uint32_t free_blocks_;
+  mutable port::Mutex mutex_;
+};
+
+// thread-safe
+class BlobStore {
+ public:
+   // directory - wherever the blobs should be stored. It will be created
+   //   if missing
+   // block_size - self explanatory
+   // blocks_per_bucket - how many blocks we want to keep in one bucket.
+   //   Bucket is a device or a file that we use to store the blobs.
+   //   If we don't have enough blocks to allocate a new blob, we will
+   //   try to create a new file or device.
+   // max_buckets - maximum number of buckets BlobStore will create
+   //   BlobStore max size in bytes is
+   //     max_buckets * blocks_per_bucket * block_size
+   // env - env for creating new files
+  BlobStore(const std::string& directory,
+            uint64_t block_size,
+            uint32_t blocks_per_bucket,
+            uint32_t max_buckets,
+            Env* env);
+  ~BlobStore();
+
+  // Allocates space for value.size bytes (rounded up to be multiple of
+  // block size) and writes value.size bytes from value.data to a backing store.
+  // Sets Blob blob that can than be used for addressing the
+  // stored value. Returns non-OK status on error.
+  Status Put(const Slice& value, Blob* blob);
+  // Value needs to have enough space to store all the loaded stuff.
+  // This function is thread safe!
+  Status Get(const Blob& blob, std::string* value) const;
+  // Frees the blob for reuse, but does not delete the data
+  // on the backing store.
+  Status Delete(const Blob& blob);
+  // Sync all opened files that are modified
+  Status Sync();
+
+ private:
+  const std::string directory_;
+  // block_size_ is uint64_t because when we multiply with
+  // blocks_size_ we want the result to be uint64_t or
+  // we risk overflowing
+  const uint64_t block_size_;
+  const uint32_t blocks_per_bucket_;
+  Env* env_;
+  EnvOptions storage_options_;
+  // protected by free_list_mutex_
+  FreeList free_list_;
+  // free_list_mutex_ is locked BEFORE buckets_mutex_
+  mutable port::Mutex free_list_mutex_;
+  // protected by buckets_mutex_
+  // array of buckets
+  unique_ptr<RandomRWFile>* buckets_;
+  // number of buckets in the array
+  uint32_t buckets_size_;
+  uint32_t max_buckets_;
+  mutable port::Mutex buckets_mutex_;
+
+  // Calls FreeList allocate. If free list can't allocate
+  // new blob, creates new bucket and tries again
+  // Thread-safe
+  Status Allocate(uint32_t blocks, Blob* blob);
+
+  // Creates a new backing store and adds all the blocks
+  // from the new backing store to the free list
+  Status CreateNewBucket();
+};
+
+} // namespace rocksdb
diff --git a/util/blob_store_test.cc b/util/blob_store_test.cc
new file mode 100644 (file)
index 0000000..bc49007
--- /dev/null
@@ -0,0 +1,200 @@
+// 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/blob_store.h"
+
+#include "util/testharness.h"
+#include "util/testutil.h"
+#include "util/random.h"
+
+#include <cstdlib>
+#include <string>
+
+namespace rocksdb {
+
+using namespace std;
+
+class BlobStoreTest { };
+
+TEST(BlobStoreTest, RangeParseTest) {
+  Blob e;
+  for (int i = 0; i < 5; ++i) {
+    e.chunks.push_back(BlobChunk(rand(), rand(), rand()));
+  }
+  string x = e.ToString();
+  Blob nx(x);
+
+  ASSERT_EQ(nx.ToString(), x);
+}
+
+// make sure we're reusing the freed space
+TEST(BlobStoreTest, SanityTest) {
+  const uint64_t block_size = 10;
+  const uint32_t blocks_per_file = 20;
+  Random random(5);
+
+  BlobStore blob_store(test::TmpDir() + "/blob_store_test",
+                       block_size,
+                       blocks_per_file,
+                       1000,
+                       Env::Default());
+
+  string buf;
+
+  // put string of size 170
+  test::RandomString(&random, 170, &buf);
+  Blob r1;
+  ASSERT_OK(blob_store.Put(Slice(buf), &r1));
+  // use the first file
+  for (size_t i = 0; i < r1.chunks.size(); ++i) {
+    ASSERT_EQ(r1.chunks[0].bucket_id, 0u);
+  }
+
+  // put string of size 30
+  test::RandomString(&random, 30, &buf);
+  Blob r2;
+  ASSERT_OK(blob_store.Put(Slice(buf), &r2));
+  // use the first file
+  for (size_t i = 0; i < r2.chunks.size(); ++i) {
+    ASSERT_EQ(r2.chunks[0].bucket_id, 0u);
+  }
+
+  // delete blob of size 170
+  ASSERT_OK(blob_store.Delete(r1));
+
+  // put a string of size 100
+  test::RandomString(&random, 100, &buf);
+  Blob r3;
+  ASSERT_OK(blob_store.Put(Slice(buf), &r3));
+  // use the first file
+  for (size_t i = 0; i < r3.chunks.size(); ++i) {
+    ASSERT_EQ(r3.chunks[0].bucket_id, 0u);
+  }
+
+  // put a string of size 70
+  test::RandomString(&random, 70, &buf);
+  Blob r4;
+  ASSERT_OK(blob_store.Put(Slice(buf), &r4));
+  // use the first file
+  for (size_t i = 0; i < r4.chunks.size(); ++i) {
+    ASSERT_EQ(r4.chunks[0].bucket_id, 0u);
+  }
+
+  // put a string of size 5
+  test::RandomString(&random, 5, &buf);
+  Blob r5;
+  ASSERT_OK(blob_store.Put(Slice(buf), &r5));
+  // now you get to use the second file
+  for (size_t i = 0; i < r5.chunks.size(); ++i) {
+    ASSERT_EQ(r5.chunks[0].bucket_id, 1u);
+  }
+}
+
+TEST(BlobStoreTest, FragmentedChunksTest) {
+  const uint64_t block_size = 10;
+  const uint32_t blocks_per_file = 20;
+  Random random(5);
+
+  BlobStore blob_store(test::TmpDir() + "/blob_store_test",
+                       block_size,
+                       blocks_per_file,
+                       1000,
+                       Env::Default());
+
+  string buf;
+
+  vector <Blob> r(4);
+
+  // put 4 strings of size 50
+  for (int k = 0; k < 4; ++k)  {
+    test::RandomString(&random, 50, &buf);
+    ASSERT_OK(blob_store.Put(Slice(buf), &r[k]));
+    // use the first file
+    for (size_t i = 0; i < r[k].chunks.size(); ++i) {
+      ASSERT_EQ(r[k].chunks[0].bucket_id, 0u);
+    }
+  }
+
+  // delete the first and third
+  ASSERT_OK(blob_store.Delete(r[0]));
+  ASSERT_OK(blob_store.Delete(r[2]));
+
+  // put string of size 100. it should reuse space that we deleting
+  // by deleting first and third strings of size 50
+  test::RandomString(&random, 100, &buf);
+  Blob r2;
+  ASSERT_OK(blob_store.Put(Slice(buf), &r2));
+  // use the first file
+  for (size_t i = 0; i < r2.chunks.size(); ++i) {
+    ASSERT_EQ(r2.chunks[0].bucket_id, 0u);
+  }
+}
+
+TEST(BlobStoreTest, CreateAndStoreTest) {
+  const uint64_t block_size = 10;
+  const uint32_t blocks_per_file = 1000;
+  const int max_blurb_size = 300;
+  Random random(5);
+
+  BlobStore blob_store(test::TmpDir() + "/blob_store_test",
+                       block_size,
+                       blocks_per_file,
+                       10000,
+                       Env::Default());
+  vector<pair<Blob, string>> ranges;
+
+  for (int i = 0; i < 20000; ++i) {
+    int decision = rand() % 5;
+    if (decision <= 2 || ranges.size() == 0) {
+      string buf;
+      int size_blocks = (rand() % max_blurb_size + 1);
+      int string_size = size_blocks * block_size - (rand() % block_size);
+      test::RandomString(&random, string_size, &buf);
+      Blob r;
+      ASSERT_OK(blob_store.Put(Slice(buf), &r));
+      ranges.push_back(make_pair(r, buf));
+    } else if (decision == 3) {
+      int ti = rand() % ranges.size();
+      string out_buf;
+      ASSERT_OK(blob_store.Get(ranges[ti].first, &out_buf));
+      ASSERT_EQ(ranges[ti].second, out_buf);
+    } else {
+      int ti = rand() % ranges.size();
+      ASSERT_OK(blob_store.Delete(ranges[ti].first));
+      ranges.erase(ranges.begin() + ti);
+    }
+  }
+  ASSERT_OK(blob_store.Sync());
+}
+
+TEST(BlobStoreTest, MaxSizeTest) {
+  const uint64_t block_size = 10;
+  const uint32_t blocks_per_file = 100;
+  const int max_buckets = 10;
+  Random random(5);
+
+  BlobStore blob_store(test::TmpDir() + "/blob_store_test",
+                       block_size,
+                       blocks_per_file,
+                       max_buckets,
+                       Env::Default());
+  string buf;
+  for (int i = 0; i < max_buckets; ++i) {
+    test::RandomString(&random, 1000, &buf);
+    Blob r;
+    ASSERT_OK(blob_store.Put(Slice(buf), &r));
+  }
+
+  test::RandomString(&random, 1000, &buf);
+  Blob r;
+  // should fail because max size
+  Status s = blob_store.Put(Slice(buf), &r);
+  ASSERT_EQ(s.ok(), false);
+}
+
+}  // namespace rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/bloom.cc b/util/bloom.cc
new file mode 100644 (file)
index 0000000..78ae04a
--- /dev/null
@@ -0,0 +1,111 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/filter_policy.h"
+
+#include "rocksdb/slice.h"
+#include "util/hash.h"
+
+namespace rocksdb {
+
+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<size_t>(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 "rocksdb.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<char>(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 rocksdb
diff --git a/util/bloom_test.cc b/util/bloom_test.cc
new file mode 100644 (file)
index 0000000..9dbd5d2
--- /dev/null
@@ -0,0 +1,164 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/filter_policy.h"
+
+#include "util/logging.h"
+#include "util/testharness.h"
+#include "util/testutil.h"
+
+namespace rocksdb {
+
+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<std::string> 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<Slice> 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<unsigned int>(filter_[i]);
+      for (int j = 0; j < 8; j++) {
+        fprintf(stderr, "%c", (c & (1 <<j)) ? '1' : '.');
+      }
+    }
+    fprintf(stderr, ")\n");
+  }
+
+  bool Matches(const Slice& s) {
+    if (!keys_.empty()) {
+      Build();
+    }
+    return policy_->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<int>(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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/build_version.h b/util/build_version.h
new file mode 100644 (file)
index 0000000..266aad3
--- /dev/null
@@ -0,0 +1,13 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+// these variables tell us about the git config and time
+extern const char* rocksdb_build_git_sha;
+
+// these variables tell us when the compilation occured
+extern const char* rocksdb_build_compile_time;
+extern const char* rocksdb_build_compile_date;
+
diff --git a/util/cache.cc b/util/cache.cc
new file mode 100644 (file)
index 0000000..deec528
--- /dev/null
@@ -0,0 +1,432 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <list>
+
+#include "rocksdb/cache.h"
+#include "port/port.h"
+#include "util/hash.h"
+#include "util/mutexlock.h"
+
+namespace rocksdb {
+
+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<Slice*>(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; }
+  void SetRemoveScanCountLimit(size_t remove_scan_count_limit) {
+    remove_scan_count_limit_ = remove_scan_count_limit;
+  }
+
+  // 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);
+  // Just reduce the reference count by 1.
+  // Return true if last reference
+  bool Unref(LRUHandle* e);
+  // Call deleter and free
+  void FreeEntry(LRUHandle* e);
+
+  // Initialized before use.
+  size_t capacity_;
+  uint32_t remove_scan_count_limit_;
+
+  // mutex_ protects the following state.
+  port::Mutex mutex_;
+  size_t usage_;
+
+  // Dummy head of LRU list.
+  // lru.prev is newest entry, lru.next is oldest entry.
+  LRUHandle lru_;
+
+  HandleTable table_;
+};
+
+LRUCache::LRUCache()
+    : usage_(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
+    if (Unref(e)) {
+      FreeEntry(e);
+    }
+    e = next;
+  }
+}
+
+bool LRUCache::Unref(LRUHandle* e) {
+  assert(e->refs > 0);
+  e->refs--;
+  return e->refs == 0;
+}
+
+void LRUCache::FreeEntry(LRUHandle* e) {
+  assert(e->refs == 0);
+  (*e->deleter)(e->key(), e->value);
+  free(e);
+}
+
+void LRUCache::LRU_Remove(LRUHandle* e) {
+  e->next->prev = e->prev;
+  e->prev->next = e->next;
+  usage_ -= e->charge;
+}
+
+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;
+  usage_ += e->charge;
+}
+
+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<Cache::Handle*>(e);
+}
+
+void LRUCache::Release(Cache::Handle* handle) {
+  LRUHandle* e = reinterpret_cast<LRUHandle*>(handle);
+  bool last_reference = false;
+  {
+    MutexLock l(&mutex_);
+    last_reference = Unref(e);
+  }
+  if (last_reference) {
+    FreeEntry(e);
+  }
+}
+
+Cache::Handle* LRUCache::Insert(
+    const Slice& key, uint32_t hash, void* value, size_t charge,
+    void (*deleter)(const Slice& key, void* value)) {
+
+  LRUHandle* e = reinterpret_cast<LRUHandle*>(
+      malloc(sizeof(LRUHandle)-1 + key.size()));
+  std::list<LRUHandle*> last_reference_list;
+
+  {
+    MutexLock l(&mutex_);
+
+    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);
+
+    LRUHandle* old = table_.Insert(e);
+    if (old != nullptr) {
+      LRU_Remove(old);
+      if (Unref(old)) {
+        last_reference_list.push_back(old);
+      }
+    }
+
+    if (remove_scan_count_limit_ > 0) {
+      // Try to free the space by evicting the entries that are only
+      // referenced by the cache first.
+      LRUHandle* cur = lru_.next;
+      for (unsigned int scanCount = 0;
+           usage_ > capacity_ && cur != &lru_
+           && scanCount < remove_scan_count_limit_; scanCount++) {
+        LRUHandle* next = cur->next;
+        if (cur->refs <= 1) {
+          LRU_Remove(cur);
+          table_.Remove(cur->key(), cur->hash);
+          if (Unref(cur)) {
+            last_reference_list.push_back(cur);
+          }
+        }
+        cur = next;
+      }
+    }
+
+    // Free the space following strict LRU policy until enough space
+    // is freed.
+    while (usage_ > capacity_ && lru_.next != &lru_) {
+      LRUHandle* old = lru_.next;
+      LRU_Remove(old);
+      table_.Remove(old->key(), old->hash);
+      if (Unref(old)) {
+        last_reference_list.push_back(old);
+      }
+    }
+  }
+
+  // we free the entries here outside of mutex for
+  // performance reasons
+  for (auto entry : last_reference_list) {
+    FreeEntry(entry);
+  }
+
+  return reinterpret_cast<Cache::Handle*>(e);
+}
+
+void LRUCache::Erase(const Slice& key, uint32_t hash) {
+  LRUHandle* e;
+  bool last_reference = false;
+  {
+    MutexLock l(&mutex_);
+    e = table_.Remove(key, hash);
+    if (e != nullptr) {
+      LRU_Remove(e);
+      last_reference = Unref(e);
+    }
+  }
+  // mutex not held here
+  // last_reference will only be true if e != nullptr
+  if (last_reference) {
+    FreeEntry(e);
+  }
+}
+
+static int kNumShardBits = 4;          // default values, can be overridden
+static int kRemoveScanCountLimit = 0; // 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) {
+    // Note, hash >> 32 yields hash in gcc, not the zero we expect!
+    return (numShardBits > 0) ? (hash >> (32 - numShardBits)) : 0;
+  }
+
+  void init(size_t capacity, int numbits, int removeScanCountLimit) {
+    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);
+      shard_[s].SetRemoveScanCountLimit(removeScanCountLimit);
+    }
+  }
+
+ public:
+  explicit ShardedLRUCache(size_t capacity)
+      : last_id_(0) {
+    init(capacity, kNumShardBits, kRemoveScanCountLimit);
+  }
+  ShardedLRUCache(size_t capacity, int numShardBits,
+                  int removeScanCountLimit)
+     : last_id_(0) {
+    init(capacity, numShardBits, removeScanCountLimit);
+  }
+  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<LRUHandle*>(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<LRUHandle*>(handle)->value;
+  }
+  virtual uint64_t NewId() {
+    MutexLock l(&id_mutex_);
+    return ++(last_id_);
+  }
+  virtual size_t GetCapacity() {
+    return capacity_;
+  }
+};
+
+}  // end anonymous namespace
+
+shared_ptr<Cache> NewLRUCache(size_t capacity) {
+  return NewLRUCache(capacity, kNumShardBits);
+}
+
+shared_ptr<Cache> NewLRUCache(size_t capacity, int numShardBits) {
+  return NewLRUCache(capacity, numShardBits, kRemoveScanCountLimit);
+}
+
+shared_ptr<Cache> NewLRUCache(size_t capacity, int numShardBits,
+                              int removeScanCountLimit) {
+  if (numShardBits >= 20) {
+    return nullptr;  // the cache cannot be sharded into too many fine pieces
+  }
+  return std::make_shared<ShardedLRUCache>(capacity,
+                                           numShardBits,
+                                           removeScanCountLimit);
+}
+
+}  // namespace rocksdb
diff --git a/util/cache_test.cc b/util/cache_test.cc
new file mode 100644 (file)
index 0000000..87ab913
--- /dev/null
@@ -0,0 +1,391 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/cache.h"
+
+#include <vector>
+#include <string>
+#include <iostream>
+#include "util/coding.h"
+#include "util/testharness.h"
+
+namespace rocksdb {
+
+// 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<void*>(v); }
+static int DecodeValue(void* v) { return reinterpret_cast<uintptr_t>(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;
+  static const int kNumShardBits = 4;
+  static const int kRemoveScanCountLimit = 16;
+
+  static const int kCacheSize2 = 100;
+  static const int kNumShardBits2 = 2;
+  static const int kRemoveScanCountLimit2 = 200;
+
+  std::vector<int> deleted_keys_;
+  std::vector<int> deleted_values_;
+  shared_ptr<Cache> cache_;
+  shared_ptr<Cache> cache2_;
+
+  CacheTest() :
+      cache_(NewLRUCache(kCacheSize, kNumShardBits, kRemoveScanCountLimit)),
+      cache2_(NewLRUCache(kCacheSize2, kNumShardBits2,
+                          kRemoveScanCountLimit2)) {
+    current_ = this;
+  }
+
+  ~CacheTest() {
+  }
+
+  int Lookup(shared_ptr<Cache> cache, 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(shared_ptr<Cache> cache, int key, int value, int charge = 1) {
+    cache->Release(cache->Insert(EncodeKey(key), EncodeValue(value), charge,
+                                  &CacheTest::Deleter));
+  }
+
+  void Erase(shared_ptr<Cache> cache, int key) {
+    cache->Erase(EncodeKey(key));
+  }
+
+
+  int Lookup(int key) {
+    return Lookup(cache_, key);
+  }
+
+  void Insert(int key, int value, int charge = 1) {
+    Insert(cache_, key, value, charge);
+  }
+
+  void Erase(int key) {
+    Erase(cache_, key);
+  }
+
+  int Lookup2(int key) {
+    return Lookup(cache2_, key);
+  }
+
+  void Insert2(int key, int value, int charge = 1) {
+    Insert(cache2_, key, value, charge);
+  }
+
+  void Erase2(int key) {
+    Erase(cache2_, 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, EvictionPolicyRef) {
+  Insert(100, 101);
+  Insert(101, 102);
+  Insert(102, 103);
+  Insert(103, 104);
+  Insert(200, 101);
+  Insert(201, 102);
+  Insert(202, 103);
+  Insert(203, 104);
+  Cache::Handle* h201 = cache_->Lookup(EncodeKey(200));
+  Cache::Handle* h202 = cache_->Lookup(EncodeKey(201));
+  Cache::Handle* h203 = cache_->Lookup(EncodeKey(202));
+  Cache::Handle* h204 = cache_->Lookup(EncodeKey(203));
+  Insert(300, 101);
+  Insert(301, 102);
+  Insert(302, 103);
+  Insert(303, 104);
+
+  // Insert entries much more than Cache capacity
+  for (int i = 0; i < kCacheSize + 100; i++) {
+    Insert(1000 + i, 2000 + i);
+  }
+
+  // Check whether the entries inserted in the beginning
+  // are evicted. Ones without extra ref are evicted and
+  // those with are not.
+  ASSERT_EQ(-1, Lookup(100));
+  ASSERT_EQ(-1, Lookup(101));
+  ASSERT_EQ(-1, Lookup(102));
+  ASSERT_EQ(-1, Lookup(103));
+
+  ASSERT_EQ(-1, Lookup(300));
+  ASSERT_EQ(-1, Lookup(301));
+  ASSERT_EQ(-1, Lookup(302));
+  ASSERT_EQ(-1, Lookup(303));
+
+  ASSERT_EQ(101, Lookup(200));
+  ASSERT_EQ(102, Lookup(201));
+  ASSERT_EQ(103, Lookup(202));
+  ASSERT_EQ(104, Lookup(203));
+
+  // Cleaning up all the handles
+  cache_->Release(h201);
+  cache_->Release(h202);
+  cache_->Release(h203);
+  cache_->Release(h204);
+}
+
+TEST(CacheTest, EvictionPolicyRef2) {
+  std::vector<Cache::Handle*> handles;
+
+  Insert(100, 101);
+  // Insert entries much more than Cache capacity
+  for (int i = 0; i < kCacheSize + 100; i++) {
+    Insert(1000 + i, 2000 + i);
+    if (i < kCacheSize ) {
+      handles.push_back(cache_->Lookup(EncodeKey(1000 + i)));
+    }
+  }
+
+  // Make sure referenced keys are also possible to be deleted
+  // if there are not sufficient non-referenced keys
+  for (int i = 0; i < 5; i++) {
+    ASSERT_EQ(-1, Lookup(1000 + i));
+  }
+
+  for (int i = kCacheSize; i < kCacheSize + 100; i++) {
+    ASSERT_EQ(2000 + i, Lookup(1000 + i));
+  }
+  ASSERT_EQ(-1, Lookup(100));
+
+  // Cleaning up all the handles
+  while (handles.size() > 0) {
+    cache_->Release(handles.back());
+    handles.pop_back();
+  }
+}
+
+TEST(CacheTest, EvictionPolicyRefLargeScanLimit) {
+  std::vector<Cache::Handle*> handles2;
+
+  // Cache2 has a cache RemoveScanCountLimit higher than cache size
+  // so it would trigger a boundary condition.
+
+  // Populate the cache with 10 more keys than its size.
+  // Reference all keys except one close to the end.
+  for (int i = 0; i < kCacheSize2 + 10; i++) {
+    Insert2(1000 + i, 2000+i);
+    if (i != kCacheSize2 ) {
+      handles2.push_back(cache2_->Lookup(EncodeKey(1000 + i)));
+    }
+  }
+
+  // Make sure referenced keys are also possible to be deleted
+  // if there are not sufficient non-referenced keys
+  for (int i = 0; i < 3; i++) {
+    ASSERT_EQ(-1, Lookup2(1000 + i));
+  }
+  // The non-referenced value is deleted even if it's accessed
+  // recently.
+  ASSERT_EQ(-1, Lookup2(1000 + kCacheSize2));
+  // Other values recently accessed are not deleted since they
+  // are referenced.
+  for (int i = kCacheSize2 - 10; i < kCacheSize2 + 10; i++) {
+    if (i != kCacheSize2) {
+      ASSERT_EQ(2000 + i, Lookup2(1000 + i));
+    }
+  }
+
+  // Cleaning up all the handles
+  while (handles2.size() > 0) {
+    cache2_->Release(handles2.back());
+    handles2.pop_back();
+  }
+}
+
+
+
+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);
+}
+
+
+class Value {
+ private:
+  int v_;
+ public:
+  explicit Value(int v) : v_(v) { }
+
+  ~Value() { std::cout << v_ << " is destructed\n"; }
+};
+
+void deleter(const Slice& key, void* value) {
+  delete (Value *)value;
+}
+
+
+TEST(CacheTest, BadEviction) {
+  int n = 10;
+
+  // a LRUCache with n entries and one shard only
+  std::shared_ptr<Cache> cache = NewLRUCache(n, 0);
+
+  std::vector<Cache::Handle*> handles(n+1);
+
+  // Insert n+1 entries, but not releasing.
+  for (int i = 0; i < n+1; i++) {
+    std::string key = std::to_string(i+1);
+    handles[i] = cache->Insert(key, new Value(i+1), 1, &deleter);
+  }
+
+  // Guess what's in the cache now?
+  for (int i = 0; i < n+1; i++) {
+    std::string key = std::to_string(i+1);
+    auto h = cache->Lookup(key);
+    std::cout << key << (h?" found\n":" not found\n");
+    // Only the first entry should be missing
+    ASSERT_TRUE(h || i == 0);
+    if (h) cache->Release(h);
+  }
+
+  for (int i = 0; i < n+1; i++) {
+    cache->Release(handles[i]);
+  }
+  std::cout << "Poor entries\n";
+}
+
+}  // namespace rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/coding.cc b/util/coding.cc
new file mode 100644 (file)
index 0000000..2d70647
--- /dev/null
@@ -0,0 +1,318 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <algorithm>
+
+namespace rocksdb {
+
+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<unsigned char*>(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<char*>(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<unsigned char*>(dst);
+  while (v >= B) {
+    *(ptr++) = (v & (B-1)) | B;
+    v >>= 7;
+  }
+  *(ptr++) = static_cast<unsigned char>(v);
+  return reinterpret_cast<char*>(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());
+}
+
+void PutLengthPrefixedSliceParts(std::string* dst,
+                                 const SliceParts& slice_parts) {
+  uint32_t total_bytes = 0;
+  for (int i = 0; i < slice_parts.num_parts; ++i) {
+    total_bytes += slice_parts.parts[i].size();
+  }
+  PutVarint32(dst, total_bytes);
+  for (int i = 0; i < slice_parts.num_parts; ++i) {
+    dst->append(slice_parts.parts[i].data(), slice_parts.parts[i].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<const unsigned char*>(p));
+    p++;
+    if (byte & 128) {
+      // More bytes are present
+      result |= ((byte & 127) << shift);
+    } else {
+      result |= (byte << shift);
+      *value = result;
+      return reinterpret_cast<const char*>(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<const unsigned char*>(p));
+    p++;
+    if (byte & 128) {
+      // More bytes are present
+      result |= ((byte & 127) << shift);
+    } else {
+      result |= (byte << shift);
+      *value = result;
+      return reinterpret_cast<const char*>(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;
+  }
+}
+
+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);
+}
+
+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<unsigned char*>(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<size_t>(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<const unsigned char*>(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<size_t>(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 rocksdb
diff --git a/util/coding.h b/util/coding.h
new file mode 100644 (file)
index 0000000..3fd892f
--- /dev/null
@@ -0,0 +1,137 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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
+
+#pragma once
+#include <stdint.h>
+#include <string.h>
+#include <string>
+#include "port/port.h"
+
+namespace rocksdb {
+
+// 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);
+extern void PutLengthPrefixedSliceParts(std::string* dst,
+                                        const SliceParts& slice_parts);
+
+// 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);
+extern Slice GetLengthPrefixedSlice(const char* data);
+
+// 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<uint32_t>(static_cast<unsigned char>(ptr[0])))
+        | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[1])) << 8)
+        | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[2])) << 16)
+        | (static_cast<uint32_t>(static_cast<unsigned char>(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<const unsigned char*>(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 rocksdb
diff --git a/util/coding_test.cc b/util/coding_test.cc
new file mode 100644 (file)
index 0000000..fb06132
--- /dev/null
@@ -0,0 +1,296 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 rocksdb {
+
+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<uint64_t>(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<uint64_t>(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<int>(dst[0]));
+  ASSERT_EQ(0x02, static_cast<int>(dst[1]));
+  ASSERT_EQ(0x03, static_cast<int>(dst[2]));
+  ASSERT_EQ(0x04, static_cast<int>(dst[3]));
+
+  dst.clear();
+  PutFixed64(&dst, 0x0807060504030201ull);
+  ASSERT_EQ(8U, dst.size());
+  ASSERT_EQ(0x01, static_cast<int>(dst[0]));
+  ASSERT_EQ(0x02, static_cast<int>(dst[1]));
+  ASSERT_EQ(0x03, static_cast<int>(dst[2]));
+  ASSERT_EQ(0x04, static_cast<int>(dst[3]));
+  ASSERT_EQ(0x05, static_cast<int>(dst[4]));
+  ASSERT_EQ(0x06, static_cast<int>(dst[5]));
+  ASSERT_EQ(0x07, static_cast<int>(dst[6]));
+  ASSERT_EQ(0x08, static_cast<int>(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<uint64_t> values;
+  // Some special values
+  values.push_back(0);
+  values.push_back(100);
+  values.push_back(~static_cast<uint64_t>(0));
+  values.push_back(~static_cast<uint64_t>(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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/comparator.cc b/util/comparator.cc
new file mode 100644 (file)
index 0000000..adeacac
--- /dev/null
@@ -0,0 +1,86 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <algorithm>
+#include <stdint.h>
+#include "rocksdb/comparator.h"
+#include "rocksdb/slice.h"
+#include "port/port.h"
+#include "util/logging.h"
+
+namespace rocksdb {
+
+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<uint8_t>((*start)[diff_index]);
+      if (diff_byte < static_cast<uint8_t>(0xff) &&
+          diff_byte + 1 < static_cast<uint8_t>(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<uint8_t>(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 rocksdb
diff --git a/util/crc32c.cc b/util/crc32c.cc
new file mode 100644 (file)
index 0000000..bca955a
--- /dev/null
@@ -0,0 +1,393 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <stdint.h>
+#ifdef __SSE4_2__
+#include <nmmintrin.h>
+#endif
+#include "util/coding.h"
+
+namespace rocksdb {
+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<const char*>(p));
+}
+
+static inline uint64_t LE_LOAD64(const uint8_t *p) {
+  return DecodeFixed64(reinterpret_cast<const char*>(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<const uint8_t *>(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<uintptr_t>(p);
+  const uint8_t* x = reinterpret_cast<const uint8_t*>(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 rocksdb
diff --git a/util/crc32c.h b/util/crc32c.h
new file mode 100644 (file)
index 0000000..e5e6e14
--- /dev/null
@@ -0,0 +1,46 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <stddef.h>
+#include <stdint.h>
+
+namespace rocksdb {
+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 rocksdb
diff --git a/util/crc32c_test.cc b/util/crc32c_test.cc
new file mode 100644 (file)
index 0000000..300c9d3
--- /dev/null
@@ -0,0 +1,77 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 rocksdb {
+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<char*>(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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/env.cc b/util/env.cc
new file mode 100644 (file)
index 0000000..bd19d48
--- /dev/null
@@ -0,0 +1,142 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/env.h"
+#include "rocksdb/options.h"
+
+namespace rocksdb {
+
+Env::~Env() {
+}
+
+SequentialFile::~SequentialFile() {
+}
+
+RandomAccessFile::~RandomAccessFile() {
+}
+
+WritableFile::~WritableFile() {
+}
+
+Logger::~Logger() {
+}
+
+FileLock::~FileLock() {
+}
+
+void LogFlush(Logger *info_log) {
+  if (info_log) {
+    info_log->Flush();
+  }
+}
+
+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 LogFlush(const shared_ptr<Logger>& info_log) {
+  if (info_log) {
+    info_log->Flush();
+  }
+}
+
+void Log(const shared_ptr<Logger>& 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<WritableFile> file;
+  EnvOptions soptions;
+  Status s = env->NewWritableFile(fname, &file, soptions);
+  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) {
+  EnvOptions soptions;
+  data->clear();
+  unique_ptr<SequentialFile> file;
+  Status s = env->NewSequentialFile(fname, &file, soptions);
+  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 {  // anonymous namespace
+
+void AssignEnvOptions(EnvOptions* env_options, const Options& options) {
+  env_options->use_os_buffer = options.allow_os_buffer;
+  env_options->use_mmap_reads = options.allow_mmap_reads;
+  env_options->use_mmap_writes = options.allow_mmap_writes;
+  env_options->set_fd_cloexec = options.is_fd_close_on_exec;
+  env_options->bytes_per_sync = options.bytes_per_sync;
+}
+
+}
+
+EnvOptions::EnvOptions(const Options& options) {
+  AssignEnvOptions(this, options);
+}
+
+EnvOptions::EnvOptions() {
+  Options options;
+  AssignEnvOptions(this, options);
+}
+
+
+}  // namespace rocksdb
diff --git a/util/env_hdfs.cc b/util/env_hdfs.cc
new file mode 100644 (file)
index 0000000..0f8fe0d
--- /dev/null
@@ -0,0 +1,517 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#ifdef USE_HDFS
+#ifndef ROCKSDB_HDFS_FILE_C
+#define ROCKSDB_HDFS_FILE_C
+
+#include <algorithm>
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+#include <iostream>
+#include <sstream>
+#include "rocksdb/env.h"
+#include "rocksdb/status.h"
+#include "hdfs/hdfs.h"
+#include "hdfs/env_hdfs.h"
+
+//
+// This file defines an HDFS environment for rocksdb. It uses the libhdfs
+// api to access HDFS. All HDFS files created by one instance of rocksdb
+// will reside on the same HDFS cluster.
+//
+
+namespace rocksdb {
+
+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 rocksdb::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<int>(now_tv.tv_usec),
+                    static_cast<long long unsigned int>(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<SequentialFile*>(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<RandomAccessFile*>(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<WritableFile*>(f);
+  return Status::OK();
+}
+
+Status HdfsEnv::NewRandomRWFile(const std::string& fname,
+                                unique_ptr<RandomRWFile>* result,
+                                const EnvOptions& options) {
+  return Status::NotSupported("NewRandomRWFile not supported on HdfsEnv");
+}
+
+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<std::string>* 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<uint64_t>(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<Logger>* 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 rocksdb
+
+#endif // ROCKSDB_HDFS_FILE_C
+
+#else // USE_HDFS
+
+// dummy placeholders used when HDFS is not available
+#include "rocksdb/env.h"
+#include "hdfs/env_hdfs.h"
+namespace rocksdb {
+ Status HdfsEnv::NewSequentialFile(const std::string& fname,
+                                   unique_ptr<SequentialFile>* result,
+                                   const EnvOptions& options) {
+   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 (file)
index 0000000..b85e0af
--- /dev/null
@@ -0,0 +1,1423 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <deque>
+#include <set>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/vfs.h>
+#include <time.h>
+#include <unistd.h>
+#if defined(OS_LINUX)
+#include <linux/fs.h>
+#include <fcntl.h>
+#endif
+#if defined(LEVELDB_PLATFORM_ANDROID)
+#include <sys/stat.h>
+#endif
+#include "rocksdb/env.h"
+#include "rocksdb/slice.h"
+#include "port/port.h"
+#include "util/coding.h"
+#include "util/logging.h"
+#include "util/posix_logger.h"
+#include "util/random.h"
+#include <signal.h>
+
+#if !defined(TMPFS_MAGIC)
+#define TMPFS_MAGIC 0x01021994
+#endif
+#if !defined(XFS_SUPER_MAGIC)
+#define XFS_SUPER_MAGIC 0x58465342
+#endif
+#if !defined(EXT4_SUPER_MAGIC)
+#define EXT4_SUPER_MAGIC 0xEF53
+#endif
+
+// This is only set from db_stress.cc and for testing only.
+// If non-zero, kill at various points in source code with probability 1/this
+int rocksdb_kill_odds = 0;
+
+namespace rocksdb {
+
+
+namespace {
+
+// list of pathnames that are locked
+static std::set<std::string> lockedFiles;
+static port::Mutex mutex_lockedFiles;
+
+static Status IOError(const std::string& context, int err_number) {
+  return Status::IOError(context, strerror(err_number));
+}
+
+#ifdef NDEBUG
+// empty in release build
+#define TEST_KILL_RANDOM(rocksdb_kill_odds)
+#else
+
+// Kill the process with probablity 1/odds for testing.
+static void TestKillRandom(int odds, const std::string& srcfile,
+                           int srcline) {
+  time_t curtime = time(nullptr);
+  Random r((uint32_t)curtime);
+
+  assert(odds > 0);
+  bool crash = r.OneIn(odds);
+  if (crash) {
+    fprintf(stdout, "Crashing at %s:%d\n", srcfile.c_str(), srcline);
+    fflush(stdout);
+    kill(getpid(), SIGTERM);
+  }
+}
+
+// To avoid crashing always at some frequently executed codepaths (during
+// kill random test), use this factor to reduce odds
+#define REDUCE_ODDS 2
+#define REDUCE_ODDS2 4
+
+#define TEST_KILL_RANDOM(rocksdb_kill_odds) {   \
+  if (rocksdb_kill_odds > 0) { \
+    TestKillRandom(rocksdb_kill_odds, __FILE__, __LINE__);     \
+  } \
+}
+
+#endif
+
+#if defined(OS_LINUX)
+namespace {
+  static size_t GetUniqueIdFromFile(int fd, char* id, size_t max_size) {
+    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<size_t>(rid-id);
+  }
+}
+#endif
+
+class PosixSequentialFile: public SequentialFile {
+ private:
+  std::string filename_;
+  FILE* file_;
+  int fd_;
+  bool use_os_buffer_;
+
+ public:
+  PosixSequentialFile(const std::string& fname, FILE* f,
+      const EnvOptions& options)
+      : filename_(fname), file_(f), fd_(fileno(f)),
+        use_os_buffer_(options.use_os_buffer) {
+  }
+  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);
+      }
+    }
+    if (!use_os_buffer_) {
+      // 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;
+  }
+
+  virtual Status Skip(uint64_t n) {
+    if (fseek(file_, n, SEEK_CUR)) {
+      return IOError(filename_, errno);
+    }
+    return Status::OK();
+  }
+
+  virtual Status InvalidateCache(size_t offset, size_t length) {
+    // free OS pages
+    int ret = posix_fadvise(fd_, offset, length, POSIX_FADV_DONTNEED);
+    if (ret == 0) {
+      return Status::OK();
+    }
+    return IOError(filename_, errno);
+  }
+};
+
+// pread() based random-access
+class PosixRandomAccessFile: public RandomAccessFile {
+ private:
+  std::string filename_;
+  int fd_;
+  bool use_os_buffer_;
+
+ public:
+  PosixRandomAccessFile(const std::string& fname, int fd,
+                        const EnvOptions& options)
+      : filename_(fname), fd_(fd), use_os_buffer_(options.use_os_buffer) {
+    assert(!options.use_mmap_reads);
+  }
+  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<off_t>(offset));
+    *result = Slice(scratch, (r < 0) ? 0 : r);
+    if (r < 0) {
+      // An error: return a non-ok status
+      s = IOError(filename_, errno);
+    }
+    if (!use_os_buffer_) {
+      // 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 {
+    return GetUniqueIdFromFile(fd_, id, max_size);
+  }
+#endif
+
+  virtual void Hint(AccessPattern pattern) {
+    switch(pattern) {
+      case NORMAL:
+        posix_fadvise(fd_, 0, 0, POSIX_FADV_NORMAL);
+        break;
+      case RANDOM:
+        posix_fadvise(fd_, 0, 0, POSIX_FADV_RANDOM);
+        break;
+      case SEQUENTIAL:
+        posix_fadvise(fd_, 0, 0, POSIX_FADV_SEQUENTIAL);
+        break;
+      case WILLNEED:
+        posix_fadvise(fd_, 0, 0, POSIX_FADV_WILLNEED);
+        break;
+      case DONTNEED:
+        posix_fadvise(fd_, 0, 0, POSIX_FADV_DONTNEED);
+        break;
+      default:
+        assert(false);
+        break;
+    }
+  }
+
+  virtual Status InvalidateCache(size_t offset, size_t length) {
+    // free OS pages
+    int ret = posix_fadvise(fd_, offset, length, POSIX_FADV_DONTNEED);
+    if (ret == 0) {
+      return Status::OK();
+    }
+    return IOError(filename_, errno);
+  }
+};
+
+// mmap() based random-access
+class PosixMmapReadableFile: public RandomAccessFile {
+ private:
+  int fd_;
+  std::string filename_;
+  void* mmapped_region_;
+  size_t length_;
+
+ public:
+  // base[0,length-1] contains the mmapped contents of the file.
+  PosixMmapReadableFile(const int fd, const std::string& fname,
+                        void* base, size_t length,
+                        const EnvOptions& options)
+      : fd_(fd), filename_(fname), mmapped_region_(base), length_(length) {
+    assert(options.use_mmap_reads);
+    assert(options.use_os_buffer);
+  }
+  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<char*>(mmapped_region_) + offset, n);
+    }
+    return s;
+  }
+  virtual Status InvalidateCache(size_t offset, size_t length) {
+    // free OS pages
+    int ret = posix_fadvise(fd_, offset, length, POSIX_FADV_DONTNEED);
+    if (ret == 0) {
+      return Status::OK();
+    }
+    return IOError(filename_, errno);
+  }
+};
+
+// 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;
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    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;
+  }
+
+  Status MapNewRegion() {
+    assert(base_ == nullptr);
+
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    int alloc_status = posix_fallocate(fd_, file_offset_, map_size_);
+    if (alloc_status != 0) {
+      return Status::IOError("Error allocating space to file : " + filename_ +
+        "Error : " + strerror(alloc_status));
+    }
+
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    void* ptr = mmap(nullptr, map_size_, PROT_READ | PROT_WRITE, MAP_SHARED,
+                     fd_, file_offset_);
+    if (ptr == MAP_FAILED) {
+      return Status::IOError("MMap failed on " + filename_);
+    }
+
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+
+    base_ = reinterpret_cast<char*>(ptr);
+    limit_ = base_ + map_size_;
+    dst_ = base_;
+    last_sync_ = base_;
+    return Status::OK();
+  }
+
+ public:
+  PosixMmapFile(const std::string& fname, int fd, size_t page_size,
+                const EnvOptions& options)
+      : 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);
+    assert(options.use_mmap_writes);
+  }
+
+
+  ~PosixMmapFile() {
+    if (fd_ >= 0) {
+      PosixMmapFile::Close();
+    }
+  }
+
+  virtual Status Append(const Slice& data) {
+    const char* src = data.data();
+    size_t left = data.size();
+    TEST_KILL_RANDOM(rocksdb_kill_odds * REDUCE_ODDS);
+    PrepareWrite(GetFileSize(), left);
+    while (left > 0) {
+      assert(base_ <= dst_);
+      assert(dst_ <= limit_);
+      size_t avail = limit_ - dst_;
+      if (avail == 0) {
+        if (UnmapCurrentRegion()) {
+          Status s = MapNewRegion();
+          if (!s.ok()) {
+            return s;
+          }
+          TEST_KILL_RANDOM(rocksdb_kill_odds);
+        }
+      }
+
+      size_t n = (left <= avail) ? left : avail;
+      memcpy(dst_, src, n);
+      dst_ += n;
+      src += n;
+      left -= n;
+    }
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    return Status::OK();
+  }
+
+  virtual Status Close() {
+    Status s;
+    size_t unused = limit_ - dst_;
+
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+
+    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);
+      }
+    }
+
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+
+    if (close(fd_) < 0) {
+      if (s.ok()) {
+        s = IOError(filename_, errno);
+      }
+    }
+
+    fd_ = -1;
+    base_ = nullptr;
+    limit_ = nullptr;
+    return s;
+  }
+
+  virtual Status Flush() {
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    return Status::OK();
+  }
+
+  virtual Status Sync() {
+    Status s;
+
+    if (pending_sync_) {
+      // Some unmapped data was not synced
+      TEST_KILL_RANDOM(rocksdb_kill_odds);
+      pending_sync_ = false;
+      if (fdatasync(fd_) < 0) {
+        s = IOError(filename_, errno);
+      }
+      TEST_KILL_RANDOM(rocksdb_kill_odds * REDUCE_ODDS);
+    }
+
+    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_;
+      TEST_KILL_RANDOM(rocksdb_kill_odds);
+      if (msync(base_ + p1, p2 - p1 + page_size_, MS_SYNC) < 0) {
+        s = IOError(filename_, errno);
+      }
+      TEST_KILL_RANDOM(rocksdb_kill_odds);
+    }
+
+    return s;
+  }
+
+  /**
+   * Flush data as well as metadata to stable storage.
+   */
+  virtual Status Fsync() {
+    if (pending_sync_) {
+      // Some unmapped data was not synced
+      TEST_KILL_RANDOM(rocksdb_kill_odds);
+      pending_sync_ = false;
+      if (fsync(fd_) < 0) {
+        return IOError(filename_, errno);
+      }
+      TEST_KILL_RANDOM(rocksdb_kill_odds);
+    }
+    // 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;
+  }
+
+  virtual Status InvalidateCache(size_t offset, size_t length) {
+    // free OS pages
+    int ret = posix_fadvise(fd_, offset, length, POSIX_FADV_DONTNEED);
+    if (ret == 0) {
+      return Status::OK();
+    }
+    return IOError(filename_, errno);
+  }
+
+#ifdef OS_LINUX
+  virtual Status Allocate(off_t offset, off_t len) {
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    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_
+  unique_ptr<char[]> buf_;           // a buffer to cache writes
+  uint64_t filesize_;
+  bool pending_sync_;
+  bool pending_fsync_;
+  uint64_t last_sync_size_;
+  uint64_t bytes_per_sync_;
+
+ public:
+  PosixWritableFile(const std::string& fname, int fd, size_t capacity,
+                    const EnvOptions& options) :
+    filename_(fname),
+    fd_(fd),
+    cursize_(0),
+    capacity_(capacity),
+    buf_(new char[capacity]),
+    filesize_(0),
+    pending_sync_(false),
+    pending_fsync_(false),
+    last_sync_size_(0),
+    bytes_per_sync_(options.bytes_per_sync) {
+    assert(!options.use_mmap_writes);
+  }
+
+  ~PosixWritableFile() {
+    if (fd_ >= 0) {
+      PosixWritableFile::Close();
+    }
+  }
+
+  virtual Status Append(const Slice& data) {
+    const char* src = data.data();
+    size_t left = data.size();
+    Status s;
+    pending_sync_ = true;
+    pending_fsync_ = true;
+
+    TEST_KILL_RANDOM(rocksdb_kill_odds * REDUCE_ODDS2);
+
+    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)) {
+        capacity_ *= 2;
+        buf_.reset(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_.get()+cursize_, src, left);
+      cursize_ += left;
+    } else {
+      while (left != 0) {
+        ssize_t done = write(fd_, src, left);
+        if (done < 0) {
+          return IOError(filename_, errno);
+        }
+        TEST_KILL_RANDOM(rocksdb_kill_odds);
+
+        left -= done;
+        src += done;
+      }
+    }
+    filesize_ += data.size();
+    return Status::OK();
+  }
+
+  virtual Status Close() {
+    Status s;
+    s = Flush(); // flush cache to OS
+    if (!s.ok()) {
+    }
+
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+
+    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() {
+    TEST_KILL_RANDOM(rocksdb_kill_odds * REDUCE_ODDS2);
+    size_t left = cursize_;
+    char* src = buf_.get();
+    while (left != 0) {
+      ssize_t done = write(fd_, src, left);
+      if (done < 0) {
+        return IOError(filename_, errno);
+      }
+      TEST_KILL_RANDOM(rocksdb_kill_odds * REDUCE_ODDS2);
+      left -= done;
+      src += done;
+    }
+    cursize_ = 0;
+
+    // sync OS cache to disk for every bytes_per_sync_
+    // TODO: give log file and sst file different options (log
+    // files could be potentially cached in OS for their whole
+    // life time, thus we might not want to flush at all).
+    if (bytes_per_sync_ &&
+        filesize_ - last_sync_size_ >= bytes_per_sync_) {
+      RangeSync(last_sync_size_, filesize_ - last_sync_size_);
+      last_sync_size_ = filesize_;
+    }
+
+    return Status::OK();
+  }
+
+  virtual Status Sync() {
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    if (pending_sync_ && fdatasync(fd_) < 0) {
+      return IOError(filename_, errno);
+    }
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    pending_sync_ = false;
+    return Status::OK();
+  }
+
+  virtual Status Fsync() {
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    if (pending_fsync_ && fsync(fd_) < 0) {
+      return IOError(filename_, errno);
+    }
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    pending_fsync_ = false;
+    pending_sync_ = false;
+    return Status::OK();
+  }
+
+  virtual uint64_t GetFileSize() {
+    return filesize_;
+  }
+
+  virtual Status InvalidateCache(size_t offset, size_t length) {
+    // free OS pages
+    int ret = posix_fadvise(fd_, offset, length, POSIX_FADV_DONTNEED);
+    if (ret == 0) {
+      return Status::OK();
+    }
+    return IOError(filename_, errno);
+  }
+
+#ifdef OS_LINUX
+  virtual Status Allocate(off_t offset, off_t len) {
+    TEST_KILL_RANDOM(rocksdb_kill_odds);
+    if (!fallocate(fd_, FALLOC_FL_KEEP_SIZE, offset, len)) {
+      return Status::OK();
+    } else {
+      return IOError(filename_, errno);
+    }
+  }
+
+  virtual Status RangeSync(off64_t offset, off64_t nbytes) {
+    if (sync_file_range(fd_, offset, nbytes, SYNC_FILE_RANGE_WRITE) == 0) {
+      return Status::OK();
+    } else {
+      return IOError(filename_, errno);
+    }
+  }
+  virtual size_t GetUniqueId(char* id, size_t max_size) const {
+    return GetUniqueIdFromFile(fd_, id, max_size);
+  }
+#endif
+};
+
+class PosixRandomRWFile : public RandomRWFile {
+ private:
+  const std::string filename_;
+  int fd_;
+  bool pending_sync_;
+  bool pending_fsync_;
+
+ public:
+  PosixRandomRWFile(const std::string& fname, int fd,
+                    const EnvOptions& options) :
+      filename_(fname),
+      fd_(fd),
+      pending_sync_(false),
+      pending_fsync_(false) {
+    assert(!options.use_mmap_writes && !options.use_mmap_reads);
+  }
+
+  ~PosixRandomRWFile() {
+    if (fd_ >= 0) {
+      Close();
+    }
+  }
+
+  virtual Status Write(uint64_t offset, const Slice& data) {
+    const char* src = data.data();
+    size_t left = data.size();
+    Status s;
+    pending_sync_ = true;
+    pending_fsync_ = true;
+
+    while (left != 0) {
+      ssize_t done = pwrite(fd_, src, left, offset);
+      if (done < 0) {
+        return IOError(filename_, errno);
+      }
+
+      left -= done;
+      src += done;
+      offset += done;
+    }
+
+    return Status::OK();
+  }
+
+  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<off_t>(offset));
+    *result = Slice(scratch, (r < 0) ? 0 : r);
+    if (r < 0) {
+      s = IOError(filename_, errno);
+    }
+    return s;
+  }
+
+  virtual Status Close() {
+    Status s = Status::OK();
+    if (fd_ >= 0 && close(fd_) < 0) {
+      s = IOError(filename_, errno);
+    }
+    fd_ = -1;
+    return s;
+  }
+
+  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();
+  }
+
+#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;
+};
+
+
+namespace {
+void PthreadCall(const char* label, int result) {
+  if (result != 0) {
+    fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
+    exit(1);
+  }
+}
+}
+
+class PosixEnv : public Env {
+ public:
+  PosixEnv();
+
+  virtual ~PosixEnv(){
+    for (const auto tid : threads_to_join_) {
+      pthread_join(tid, nullptr);
+    }
+  }
+
+  void SetFD_CLOEXEC(int fd, const EnvOptions* options) {
+    if ((options == nullptr || options->set_fd_cloexec) && fd > 0) {
+      fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+    }
+  }
+
+  virtual Status NewSequentialFile(const std::string& fname,
+                                   unique_ptr<SequentialFile>* result,
+                                   const EnvOptions& options) {
+    result->reset();
+    FILE* f = fopen(fname.c_str(), "r");
+    if (f == nullptr) {
+      *result = nullptr;
+      return IOError(fname, errno);
+    } else {
+      int fd = fileno(f);
+      SetFD_CLOEXEC(fd, &options);
+      result->reset(new PosixSequentialFile(fname, f, options));
+      return Status::OK();
+    }
+  }
+
+  virtual Status NewRandomAccessFile(const std::string& fname,
+                                     unique_ptr<RandomAccessFile>* result,
+                                     const EnvOptions& options) {
+    result->reset();
+    Status s;
+    int fd = open(fname.c_str(), O_RDONLY);
+    SetFD_CLOEXEC(fd, &options);
+    if (fd < 0) {
+      s = IOError(fname, errno);
+    } else if (options.use_mmap_reads && 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(fd, fname, base,
+                                                  size, options));
+        } else {
+          s = IOError(fname, errno);
+        }
+      }
+      close(fd);
+    } else {
+      result->reset(new PosixRandomAccessFile(fname, fd, options));
+    }
+    return s;
+  }
+
+  virtual Status NewWritableFile(const std::string& fname,
+                                 unique_ptr<WritableFile>* result,
+                                 const EnvOptions& options) {
+    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 {
+      SetFD_CLOEXEC(fd, &options);
+      if (options.use_mmap_writes) {
+        if (!checkedDiskForMmap_) {
+          // this will be executed once in the program's lifetime.
+          // do not use mmapWrite on non ext-3/xfs/tmpfs systems.
+          if (!SupportsFastAllocate(fname)) {
+            forceMmapOff = true;
+          }
+          checkedDiskForMmap_ = true;
+        }
+      }
+      if (options.use_mmap_writes && !forceMmapOff) {
+        result->reset(new PosixMmapFile(fname, fd, page_size_, options));
+      } else {
+        result->reset(new PosixWritableFile(fname, fd, 65536, options));
+      }
+    }
+    return s;
+  }
+
+  virtual Status NewRandomRWFile(const std::string& fname,
+                                 unique_ptr<RandomRWFile>* result,
+                                 const EnvOptions& options) {
+    result->reset();
+    Status s;
+    const int fd = open(fname.c_str(), O_CREAT | O_RDWR, 0644);
+    if (fd < 0) {
+      s = IOError(fname, errno);
+    } else {
+      SetFD_CLOEXEC(fd, &options);
+      // no support for mmap yet
+      if (options.use_mmap_writes || options.use_mmap_reads) {
+        return Status::NotSupported("No support for mmap read/write yet");
+      }
+      result->reset(new PosixRandomRWFile(fname, fd, options));
+    }
+    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<std::string>* 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<uint64_t>(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 {
+      SetFD_CLOEXEC(fd, nullptr);
+      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<PosixFileLock*>(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, Priority pri = LOW);
+
+  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/rocksdbtest-%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<Logger>* result) {
+    FILE* f = fopen(fname.c_str(), "w");
+    if (f == nullptr) {
+      result->reset();
+      return IOError(fname, errno);
+    } else {
+      int fd = fileno(f);
+      SetFD_CLOEXEC(fd, nullptr);
+      result->reset(new PosixLogger(f, &PosixEnv::gettid, this));
+      return Status::OK();
+    }
+  }
+
+  virtual uint64_t NowMicros() {
+    struct timeval tv;
+    gettimeofday(&tv, nullptr);
+    return static_cast<uint64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;
+  }
+
+  virtual uint64_t NowNanos() {
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    return static_cast<uint64_t>(ts.tv_sec) * 1000000000 + ts.tv_nsec;
+  }
+
+  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, Priority pri) {
+    assert(pri >= Priority::LOW && pri <= Priority::HIGH);
+    thread_pools_[pri].SetBackgroundThreads(num);
+  }
+
+  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:
+  bool checkedDiskForMmap_;
+  bool forceMmapOff; // do we override Env options?
+
+
+  // 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
+  }
+
+  bool SupportsFastAllocate(const std::string& path) {
+    struct statfs s;
+    if (statfs(path.c_str(), &s)){
+      return false;
+    }
+    switch (s.f_type) {
+      case EXT4_SUPER_MAGIC:
+        return true;
+      case XFS_SUPER_MAGIC:
+        return true;
+      case TMPFS_MAGIC:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  size_t page_size_;
+
+
+  class ThreadPool {
+   public:
+
+    ThreadPool() :
+        total_threads_limit_(1),
+        bgthreads_(0),
+        queue_(),
+        exit_all_threads_(false) {
+      PthreadCall("mutex_init", pthread_mutex_init(&mu_, nullptr));
+      PthreadCall("cvar_init", pthread_cond_init(&bgsignal_, nullptr));
+    }
+
+    ~ThreadPool() {
+      PthreadCall("lock", pthread_mutex_lock(&mu_));
+      assert(!exit_all_threads_);
+      exit_all_threads_ = true;
+      PthreadCall("signalall", pthread_cond_broadcast(&bgsignal_));
+      PthreadCall("unlock", pthread_mutex_unlock(&mu_));
+      for (const auto tid : bgthreads_) {
+        pthread_join(tid, nullptr);
+      }
+    }
+
+    void BGThread() {
+      while (true) {
+        // Wait until there is an item that is ready to run
+        PthreadCall("lock", pthread_mutex_lock(&mu_));
+        while (queue_.empty() && !exit_all_threads_) {
+          PthreadCall("wait", pthread_cond_wait(&bgsignal_, &mu_));
+        }
+        if (exit_all_threads_) { // mechanism to let BG threads exit safely
+          PthreadCall("unlock", pthread_mutex_unlock(&mu_));
+          break;
+        }
+        void (*function)(void*) = queue_.front().function;
+        void* arg = queue_.front().arg;
+        queue_.pop_front();
+
+        PthreadCall("unlock", pthread_mutex_unlock(&mu_));
+        (*function)(arg);
+      }
+    }
+
+    static void* BGThreadWrapper(void* arg) {
+      reinterpret_cast<ThreadPool*>(arg)->BGThread();
+      return nullptr;
+    }
+
+    void SetBackgroundThreads(int num) {
+      PthreadCall("lock", pthread_mutex_lock(&mu_));
+      if (num > total_threads_limit_) {
+        total_threads_limit_ = num;
+      }
+      assert(total_threads_limit_ > 0);
+      PthreadCall("unlock", pthread_mutex_unlock(&mu_));
+    }
+
+    void Schedule(void (*function)(void*), void* arg) {
+      PthreadCall("lock", pthread_mutex_lock(&mu_));
+
+      if (exit_all_threads_) {
+        PthreadCall("unlock", pthread_mutex_unlock(&mu_));
+        return;
+      }
+      // Start background thread if necessary
+      while ((int)bgthreads_.size() < total_threads_limit_) {
+        pthread_t t;
+        PthreadCall(
+          "create thread",
+          pthread_create(&t,
+                         nullptr,
+                         &ThreadPool::BGThreadWrapper,
+                         this));
+        fprintf(stdout, "Created bg thread 0x%lx\n", t);
+        bgthreads_.push_back(t);
+      }
+
+      // Add to priority queue
+      queue_.push_back(BGItem());
+      queue_.back().function = function;
+      queue_.back().arg = arg;
+
+      // always wake up at least one waiting thread.
+      PthreadCall("signal", pthread_cond_signal(&bgsignal_));
+
+      PthreadCall("unlock", pthread_mutex_unlock(&mu_));
+    }
+
+   private:
+    // Entry per Schedule() call
+    struct BGItem { void* arg; void (*function)(void*); };
+    typedef std::deque<BGItem> BGQueue;
+
+    pthread_mutex_t mu_;
+    pthread_cond_t bgsignal_;
+    int total_threads_limit_;
+    std::vector<pthread_t> bgthreads_;
+    BGQueue queue_;
+    bool exit_all_threads_;
+  };
+
+  std::vector<ThreadPool> thread_pools_;
+
+  pthread_mutex_t mu_;
+  std::vector<pthread_t> threads_to_join_;
+
+};
+
+PosixEnv::PosixEnv() : checkedDiskForMmap_(false),
+                       forceMmapOff(false),
+                       page_size_(getpagesize()),
+                       thread_pools_(Priority::TOTAL) {
+  PthreadCall("mutex_init", pthread_mutex_init(&mu_, nullptr));
+}
+
+void PosixEnv::Schedule(void (*function)(void*), void* arg, Priority pri) {
+  assert(pri >= Priority::LOW && pri <= Priority::HIGH);
+  thread_pools_[pri].Schedule(function, arg);
+}
+
+namespace {
+struct StartThreadState {
+  void (*user_function)(void*);
+  void* arg;
+};
+}
+static void* StartThreadWrapper(void* arg) {
+  StartThreadState* state = reinterpret_cast<StartThreadState*>(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));
+  PthreadCall("lock", pthread_mutex_lock(&mu_));
+  threads_to_join_.push_back(t);
+  PthreadCall("unlock", pthread_mutex_unlock(&mu_));
+}
+
+}  // namespace
+
+std::string Env::GenerateUniqueId() {
+  std::string uuid_file = "/proc/sys/kernel/random/uuid";
+  if (FileExists(uuid_file)) {
+    std::string uuid;
+    Status s = ReadFileToString(this, uuid_file, &uuid);
+    if (s.ok()) {
+      return uuid;
+    }
+  }
+  // Could not read uuid_file - generate uuid using "nanos-random"
+  Random64 r(time(nullptr));
+  uint64_t random_uuid_portion =
+    r.Uniform(std::numeric_limits<uint64_t>::max());
+  uint64_t nanos_uuid_portion = NowNanos();
+  char uuid2[200];
+  snprintf(uuid2, 200, "%lx-%lx", nanos_uuid_portion, random_uuid_portion);
+  return uuid2;
+}
+
+Env* Env::Default() {
+  static PosixEnv default_env;
+  return &default_env;
+}
+
+}  // namespace rocksdb
diff --git a/util/env_test.cc b/util/env_test.cc
new file mode 100644 (file)
index 0000000..82a2743
--- /dev/null
@@ -0,0 +1,391 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <iostream>
+#include <unordered_set>
+
+#include "rocksdb/env.h"
+#include "port/port.h"
+#include "util/coding.h"
+#include "util/mutexlock.h"
+#include "util/testharness.h"
+
+namespace rocksdb {
+
+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<port::AtomicPointer*>(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<CB*>(v);
+      void* cur = cb->last_id_ptr->NoBarrier_Load();
+      ASSERT_EQ(cb->id-1, reinterpret_cast<uintptr_t>(cur));
+      cb->last_id_ptr->Release_Store(reinterpret_cast<void*>(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<uintptr_t>(cur));
+}
+
+struct State {
+  port::Mutex mu;
+  int val;
+  int num_running;
+};
+
+static void ThreadBody(void* arg) {
+  State* s = reinterpret_cast<State*>(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);
+}
+
+TEST(EnvPosixTest, TwoPools) {
+
+  class CB {
+   public:
+    CB(const std::string& pool_name, int pool_size)
+        : mu_(),
+          num_running_(0),
+          num_finished_(0),
+          pool_size_(pool_size),
+          pool_name_(pool_name) { }
+
+    static void Run(void* v) {
+      CB* cb = reinterpret_cast<CB*>(v);
+      cb->Run();
+    }
+
+    void Run() {
+      {
+        MutexLock l(&mu_);
+        num_running_++;
+        std::cout << "Pool " << pool_name_ << ": "
+                  << num_running_ << " running threads.\n";
+        // make sure we don't have more than pool_size_ jobs running.
+        ASSERT_LE(num_running_, pool_size_);
+      }
+
+      // sleep for 1 sec
+      Env::Default()->SleepForMicroseconds(1000000);
+
+      {
+        MutexLock l(&mu_);
+        num_running_--;
+        num_finished_++;
+      }
+    }
+
+    int NumFinished() {
+      MutexLock l(&mu_);
+      return num_finished_;
+    }
+
+   private:
+    port::Mutex mu_;
+    int num_running_;
+    int num_finished_;
+    int pool_size_;
+    std::string pool_name_;
+  };
+
+  const int kLowPoolSize = 2;
+  const int kHighPoolSize = 4;
+  const int kJobs = 8;
+
+  CB low_pool_job("low", kLowPoolSize);
+  CB high_pool_job("high", kHighPoolSize);
+
+  env_->SetBackgroundThreads(kLowPoolSize);
+  env_->SetBackgroundThreads(kHighPoolSize, Env::Priority::HIGH);
+
+  // schedule same number of jobs in each pool
+  for (int i = 0; i < kJobs; i++) {
+    env_->Schedule(&CB::Run, &low_pool_job);
+    env_->Schedule(&CB::Run, &high_pool_job, Env::Priority::HIGH);
+  }
+
+  // wait for all jobs to finish
+  while (low_pool_job.NumFinished() < kJobs ||
+         high_pool_job.NumFinished() < kJobs) {
+    env_->SleepForMicroseconds(kDelayMicros);
+  }
+}
+
+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.
+  const EnvOptions soptions;
+  std::string fname = test::TmpDir() + "/" + "testfile";
+  unique_ptr<WritableFile> wfile;
+  ASSERT_OK(env_->NewWritableFile(fname, &wfile, soptions));
+
+  unique_ptr<RandomAccessFile> file;
+
+  // Get Unique ID
+  ASSERT_OK(env_->NewRandomAccessFile(fname, &file, soptions));
+  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, soptions));
+  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, soptions));
+  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<std::string>& 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.
+  const EnvOptions soptions;
+
+  // Create the files
+  std::vector<std::string> fnames;
+  for (int i = 0; i < 1000; ++i) {
+    fnames.push_back(test::TmpDir() + "/" + "testfile" + std::to_string(i));
+
+    // Create file.
+    unique_ptr<WritableFile> wfile;
+    ASSERT_OK(env_->NewWritableFile(fnames[i], &wfile, soptions));
+  }
+
+  // Collect and check whether the IDs are unique.
+  std::unordered_set<std::string> ids;
+  for (const std::string fname: fnames) {
+    unique_ptr<RandomAccessFile> file;
+    std::string unique_id;
+    ASSERT_OK(env_->NewRandomAccessFile(fname, &file, soptions));
+    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) {
+  const EnvOptions soptions;
+  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<std::string> ids;
+  for (int i = 0; i < 1000; ++i) {
+    // Create file.
+    {
+      unique_ptr<WritableFile> wfile;
+      ASSERT_OK(env_->NewWritableFile(fname, &wfile, soptions));
+    }
+
+    // Get Unique ID
+    std::string unique_id;
+    {
+      unique_ptr<RandomAccessFile> file;
+      ASSERT_OK(env_->NewRandomAccessFile(fname, &file, soptions));
+      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));
+}
+
+TEST(EnvPosixTest, InvalidateCache) {
+  const EnvOptions soptions;
+  std::string fname = test::TmpDir() + "/" + "testfile";
+
+  // Create file.
+  {
+    unique_ptr<WritableFile> wfile;
+    ASSERT_OK(env_->NewWritableFile(fname, &wfile, soptions));
+    ASSERT_OK(wfile.get()->Append(Slice("Hello world")));
+    ASSERT_OK(wfile.get()->InvalidateCache(0, 0));
+    ASSERT_OK(wfile.get()->Close());
+  }
+
+  // Random Read
+  {
+    unique_ptr<RandomAccessFile> file;
+    char scratch[100];
+    Slice result;
+    ASSERT_OK(env_->NewRandomAccessFile(fname, &file, soptions));
+    ASSERT_OK(file.get()->Read(0, 11, &result, scratch));
+    ASSERT_EQ(memcmp(scratch, "Hello world", 11), 0);
+    ASSERT_OK(file.get()->InvalidateCache(0, 11));
+    ASSERT_OK(file.get()->InvalidateCache(0, 0));
+  }
+
+  // Sequential Read
+  {
+    unique_ptr<SequentialFile> file;
+    char scratch[100];
+    Slice result;
+    ASSERT_OK(env_->NewSequentialFile(fname, &file, soptions));
+    ASSERT_OK(file.get()->Read(11, &result, scratch));
+    ASSERT_EQ(memcmp(scratch, "Hello world", 11), 0);
+    ASSERT_OK(file.get()->InvalidateCache(0, 11));
+    ASSERT_OK(file.get()->InvalidateCache(0, 0));
+  }
+  // Delete the file
+  ASSERT_OK(env_->DeleteFile(fname));
+}
+
+TEST(EnvPosixTest, PosixRandomRWFileTest) {
+  EnvOptions soptions;
+  soptions.use_mmap_writes = soptions.use_mmap_reads = false;
+  std::string fname = test::TmpDir() + "/" + "testfile";
+
+  unique_ptr<RandomRWFile> file;
+  ASSERT_OK(env_->NewRandomRWFile(fname, &file, soptions));
+  // If you run the unit test on tmpfs, then tmpfs might not
+  // support fallocate. It is still better to trigger that
+  // code-path instead of eliminating it completely.
+  file.get()->Allocate(0, 10*1024*1024);
+  ASSERT_OK(file.get()->Write(100, Slice("Hello world")));
+  ASSERT_OK(file.get()->Write(105, Slice("Hello world")));
+  ASSERT_OK(file.get()->Sync());
+  ASSERT_OK(file.get()->Fsync());
+  char scratch[100];
+  Slice result;
+  ASSERT_OK(file.get()->Read(100, 16, &result, scratch));
+  ASSERT_EQ(result.compare("HelloHello world"), 0);
+  ASSERT_OK(file.get()->Close());
+}
+
+}  // namespace rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/filelock_test.cc b/util/filelock_test.cc
new file mode 100644 (file)
index 0000000..a9e30a5
--- /dev/null
@@ -0,0 +1,58 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "rocksdb/status.h"
+#include "rocksdb/env.h"
+
+#include <vector>
+#include "util/coding.h"
+#include "util/testharness.h"
+
+namespace rocksdb {
+
+class LockTest {
+ public:
+  static LockTest* current_;
+  std::string file_;
+  rocksdb::Env* env_;
+
+  LockTest() : file_(test::TmpDir() + "/db_testlock_file"),
+               env_(rocksdb::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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/filter_policy.cc b/util/filter_policy.cc
new file mode 100644 (file)
index 0000000..e950b75
--- /dev/null
@@ -0,0 +1,16 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/filter_policy.h"
+
+namespace rocksdb {
+
+FilterPolicy::~FilterPolicy() { }
+
+}  // namespace rocksdb
diff --git a/util/hash.cc b/util/hash.cc
new file mode 100644 (file)
index 0000000..6f0e9cc
--- /dev/null
@@ -0,0 +1,50 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <string.h>
+#include "util/coding.h"
+#include "util/hash.h"
+
+namespace rocksdb {
+
+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 rocksdb
diff --git a/util/hash.h b/util/hash.h
new file mode 100644 (file)
index 0000000..c9eb659
--- /dev/null
@@ -0,0 +1,20 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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
+
+#pragma once
+#include <stddef.h>
+#include <stdint.h>
+
+namespace rocksdb {
+
+extern uint32_t Hash(const char* data, size_t n, uint32_t seed);
+
+}
diff --git a/util/hash_skiplist_rep.cc b/util/hash_skiplist_rep.cc
new file mode 100644 (file)
index 0000000..b67911f
--- /dev/null
@@ -0,0 +1,330 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+
+#include "rocksdb/memtablerep.h"
+#include "rocksdb/arena.h"
+#include "rocksdb/slice.h"
+#include "rocksdb/slice_transform.h"
+#include "port/port.h"
+#include "port/atomic_pointer.h"
+#include "util/murmurhash.h"
+#include "db/skiplist.h"
+
+namespace rocksdb {
+namespace {
+
+class HashSkipListRep : public MemTableRep {
+ public:
+  HashSkipListRep(MemTableRep::KeyComparator& compare, Arena* arena,
+    const SliceTransform* transform, size_t bucket_size);
+
+  virtual void Insert(const char* key) override;
+
+  virtual bool Contains(const char* key) const override;
+
+  virtual size_t ApproximateMemoryUsage() override;
+
+  virtual ~HashSkipListRep();
+
+  virtual std::shared_ptr<MemTableRep::Iterator> GetIterator() override;
+
+  virtual std::shared_ptr<MemTableRep::Iterator> GetIterator(
+      const Slice& slice) override;
+
+  virtual std::shared_ptr<MemTableRep::Iterator> GetPrefixIterator(
+      const Slice& prefix) override;
+
+  virtual std::shared_ptr<MemTableRep::Iterator> GetDynamicPrefixIterator()
+      override;
+
+ private:
+  friend class DynamicIterator;
+  typedef SkipList<const char*, MemTableRep::KeyComparator&> Bucket;
+
+  size_t bucket_size_;
+
+  // Maps slices (which are transformed user keys) to buckets of keys sharing
+  // the same transform.
+  port::AtomicPointer* buckets_;
+
+  // The user-supplied transform whose domain is the user keys.
+  const SliceTransform* transform_;
+
+  MemTableRep::KeyComparator& compare_;
+  // immutable after construction
+  Arena* const arena_;
+
+  inline size_t GetHash(const Slice& slice) const {
+    return MurmurHash(slice.data(), slice.size(), 0) % bucket_size_;
+  }
+  inline Bucket* GetBucket(size_t i) const {
+    return static_cast<Bucket*>(buckets_[i].Acquire_Load());
+  }
+  inline Bucket* GetBucket(const Slice& slice) const {
+    return GetBucket(GetHash(slice));
+  }
+  // Get a bucket from buckets_. If the bucket hasn't been initialized yet,
+  // initialize it before returning.
+  Bucket* GetInitializedBucket(const Slice& transformed);
+
+  class Iterator : public MemTableRep::Iterator {
+   public:
+    explicit Iterator(Bucket* list, bool own_list = true)
+      : list_(list),
+        iter_(list),
+        own_list_(own_list) {}
+
+    virtual ~Iterator() {
+      // if we own the list, we should also delete it
+      if (own_list_) {
+        assert(list_ != nullptr);
+        delete list_;
+      }
+    }
+
+    // Returns true iff the iterator is positioned at a valid node.
+    virtual bool Valid() const {
+      return list_ != nullptr && iter_.Valid();
+    }
+
+    // Returns the key at the current position.
+    // REQUIRES: Valid()
+    virtual const char* key() const {
+      assert(Valid());
+      return iter_.key();
+    }
+
+    // Advances to the next position.
+    // REQUIRES: Valid()
+    virtual void Next() {
+      assert(Valid());
+      iter_.Next();
+    }
+
+    // Advances to the previous position.
+    // REQUIRES: Valid()
+    virtual void Prev() {
+      assert(Valid());
+      iter_.Prev();
+    }
+
+    // Advance to the first entry with a key >= target
+    virtual void Seek(const char* target) {
+      if (list_ != nullptr) {
+        iter_.Seek(target);
+      }
+    }
+
+    // Position at the first entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToFirst() {
+      if (list_ != nullptr) {
+        iter_.SeekToFirst();
+      }
+    }
+
+    // Position at the last entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToLast() {
+      if (list_ != nullptr) {
+        iter_.SeekToLast();
+      }
+    }
+   protected:
+    void Reset(Bucket* list) {
+      if (own_list_) {
+        assert(list_ != nullptr);
+        delete list_;
+      }
+      list_ = list;
+      iter_.SetList(list);
+      own_list_ = false;
+    }
+   private:
+    // if list_ is nullptr, we should NEVER call any methods on iter_
+    // if list_ is nullptr, this Iterator is not Valid()
+    Bucket* list_;
+    Bucket::Iterator iter_;
+    // here we track if we own list_. If we own it, we are also
+    // responsible for it's cleaning. This is a poor man's shared_ptr
+    bool own_list_;
+  };
+
+  class DynamicIterator : public HashSkipListRep::Iterator {
+   public:
+    explicit DynamicIterator(const HashSkipListRep& memtable_rep)
+      : HashSkipListRep::Iterator(nullptr, false),
+        memtable_rep_(memtable_rep) {}
+
+    // Advance to the first entry with a key >= target
+    virtual void Seek(const char* target) {
+      auto transformed = memtable_rep_.transform_->Transform(
+        memtable_rep_.UserKey(target));
+      Reset(memtable_rep_.GetBucket(transformed));
+      HashSkipListRep::Iterator::Seek(target);
+    }
+
+    // Position at the first entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToFirst() {
+      // Prefix iterator does not support total order.
+      // We simply set the iterator to invalid state
+      Reset(nullptr);
+    }
+
+    // Position at the last entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToLast() {
+      // Prefix iterator does not support total order.
+      // We simply set the iterator to invalid state
+      Reset(nullptr);
+    }
+   private:
+    // the underlying memtable
+    const HashSkipListRep& memtable_rep_;
+  };
+
+  class EmptyIterator : public MemTableRep::Iterator {
+    // This is used when there wasn't a bucket. It is cheaper than
+    // instantiating an empty bucket over which to iterate.
+   public:
+    EmptyIterator() { }
+    virtual bool Valid() const {
+      return false;
+    }
+    virtual const char* key() const {
+      assert(false);
+      return nullptr;
+    }
+    virtual void Next() { }
+    virtual void Prev() { }
+    virtual void Seek(const char* target) { }
+    virtual void SeekToFirst() { }
+    virtual void SeekToLast() { }
+   private:
+  };
+
+  std::shared_ptr<EmptyIterator> empty_iterator_;
+};
+
+HashSkipListRep::HashSkipListRep(MemTableRep::KeyComparator& compare,
+    Arena* arena, const SliceTransform* transform, size_t bucket_size)
+  : bucket_size_(bucket_size),
+    transform_(transform),
+    compare_(compare),
+    arena_(arena),
+    empty_iterator_(std::make_shared<EmptyIterator>()) {
+
+  buckets_ = new port::AtomicPointer[bucket_size];
+
+  for (size_t i = 0; i < bucket_size_; ++i) {
+    buckets_[i].NoBarrier_Store(nullptr);
+  }
+}
+
+HashSkipListRep::~HashSkipListRep() {
+  delete[] buckets_;
+}
+
+HashSkipListRep::Bucket* HashSkipListRep::GetInitializedBucket(
+    const Slice& transformed) {
+  size_t hash = GetHash(transformed);
+  auto bucket = GetBucket(hash);
+  if (bucket == nullptr) {
+    auto addr = arena_->AllocateAligned(sizeof(Bucket));
+    bucket = new (addr) Bucket(compare_, arena_);
+    buckets_[hash].Release_Store(static_cast<void*>(bucket));
+  }
+  return bucket;
+}
+
+void HashSkipListRep::Insert(const char* key) {
+  assert(!Contains(key));
+  auto transformed = transform_->Transform(UserKey(key));
+  auto bucket = GetInitializedBucket(transformed);
+  bucket->Insert(key);
+}
+
+bool HashSkipListRep::Contains(const char* key) const {
+  auto transformed = transform_->Transform(UserKey(key));
+  auto bucket = GetBucket(transformed);
+  if (bucket == nullptr) {
+    return false;
+  }
+  return bucket->Contains(key);
+}
+
+size_t HashSkipListRep::ApproximateMemoryUsage() {
+  return sizeof(buckets_);
+}
+
+std::shared_ptr<MemTableRep::Iterator> HashSkipListRep::GetIterator() {
+  auto list = new Bucket(compare_, arena_);
+  for (size_t i = 0; i < bucket_size_; ++i) {
+    auto bucket = GetBucket(i);
+    if (bucket != nullptr) {
+      Bucket::Iterator itr(bucket);
+      for (itr.SeekToFirst(); itr.Valid(); itr.Next()) {
+        list->Insert(itr.key());
+      }
+    }
+  }
+  return std::make_shared<Iterator>(list);
+}
+
+std::shared_ptr<MemTableRep::Iterator> HashSkipListRep::GetPrefixIterator(
+  const Slice& prefix) {
+  auto bucket = GetBucket(prefix);
+  if (bucket == nullptr) {
+    return empty_iterator_;
+  }
+  return std::make_shared<Iterator>(bucket, false);
+}
+
+std::shared_ptr<MemTableRep::Iterator> HashSkipListRep::GetIterator(
+    const Slice& slice) {
+  return GetPrefixIterator(transform_->Transform(slice));
+}
+
+std::shared_ptr<MemTableRep::Iterator>
+    HashSkipListRep::GetDynamicPrefixIterator() {
+  return std::make_shared<DynamicIterator>(*this);
+}
+
+} // anon namespace
+
+class HashSkipListRepFactory : public MemTableRepFactory {
+ public:
+  explicit HashSkipListRepFactory(const SliceTransform* transform,
+      size_t bucket_count = 1000000)
+    : transform_(transform),
+      bucket_count_(bucket_count) { }
+
+  virtual ~HashSkipListRepFactory() { delete transform_; }
+
+  virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
+      MemTableRep::KeyComparator& compare, Arena* arena) override {
+    return std::make_shared<HashSkipListRep>(compare, arena, transform_,
+        bucket_count_);
+  }
+
+  virtual const char* Name() const override {
+    return "HashSkipListRepFactory";
+  }
+
+  const SliceTransform* GetTransform() { return transform_; }
+
+ private:
+  const SliceTransform* transform_;
+  const size_t bucket_count_;
+};
+
+MemTableRepFactory* NewHashSkipListRepFactory(
+    const SliceTransform* transform, size_t bucket_count) {
+  return new HashSkipListRepFactory(transform, bucket_count);
+}
+
+} // namespace rocksdb
diff --git a/util/histogram.cc b/util/histogram.cc
new file mode 100644 (file)
index 0000000..e839980
--- /dev/null
@@ -0,0 +1,194 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <cassert>
+#include <math.h>
+#include <stdio.h>
+#include "port/port.h"
+
+namespace rocksdb {
+
+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<uint64_t, uint64_t>::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<uint64_t>(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::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 (unsigned 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 (unsigned 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 P99.99: %.2f\n",
+           Percentile(50), Percentile(75), Percentile(99), Percentile(99.9),
+           Percentile(99.99));
+  r.append(buf);
+  r.append("------------------------------------------------------\n");
+  const double mult = 100.0 / num_;
+  double sum = 0;
+  for (unsigned int b = 0; b < bucketMapper.BucketCount(); b++) {
+    if (buckets_[b] <= 0.0) continue;
+    sum += buckets_[b];
+    snprintf(buf, sizeof(buf),
+             "[ %7lu, %7lu ) %8lu %7.3f%% %7.3f%% ",
+             // left
+             (unsigned long)((b == 0) ? 0 : bucketMapper.BucketLimit(b-1)),
+             (unsigned long)bucketMapper.BucketLimit(b), // right
+             (unsigned long)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<int>(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 (file)
index 0000000..c01594d
--- /dev/null
@@ -0,0 +1,79 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include "rocksdb/statistics.h"
+
+#include <cassert>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace rocksdb {
+
+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<uint64_t> bucketValues_;
+  const uint64_t maxBucketValue_;
+  const uint64_t minBucketValue_;
+  std::map<uint64_t, uint64_t> valueIndexMap_;
+};
+
+class HistogramImpl {
+ public:
+  HistogramImpl();
+  virtual ~HistogramImpl() {}
+  virtual void Clear();
+  virtual void Add(uint64_t 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<uint64_t> buckets_;
+
+};
+
+}  // namespace rocksdb
diff --git a/util/histogram_test.cc b/util/histogram_test.cc
new file mode 100644 (file)
index 0000000..065f957
--- /dev/null
@@ -0,0 +1,62 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "util/histogram.h"
+
+#include "util/testharness.h"
+
+namespace rocksdb {
+
+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 rocksdb
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/ldb_cmd.cc b/util/ldb_cmd.cc
new file mode 100644 (file)
index 0000000..e255f81
--- /dev/null
@@ -0,0 +1,1766 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "util/ldb_cmd.h"
+
+#include "db/dbformat.h"
+#include "db/db_impl.h"
+#include "db/log_reader.h"
+#include "db/filename.h"
+#include "db/write_batch_internal.h"
+#include "rocksdb/write_batch.h"
+#include "util/coding.h"
+
+#include <ctime>
+#include <dirent.h>
+#include <sstream>
+#include <string>
+#include <stdexcept>
+
+namespace rocksdb {
+
+using namespace std;
+
+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_TTL = "ttl";
+const string LDBCommand::ARG_TTL_START = "start_time";
+const string LDBCommand::ARG_TTL_END = "end_time";
+const string LDBCommand::ARG_TIMESTAMP = "timestamp";
+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,
+  const Options& options
+) {
+  vector<string> args;
+  for (int i = 1; i < argc; i++) {
+    args.push_back(argv[i]);
+  }
+  return InitFromCmdLineArgs(args, options);
+}
+
+/**
+ * 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 <PARAM1> <PARAM2> ... [-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<string>& args,
+  const Options& options
+) {
+  // --x=y command line arguments are added as x->y map entries.
+  map<string, string> option_map;
+
+  // Command-line arguments of the form --hex end up in this array as hex
+  vector<string> flags;
+
+  // Everything other than option_map and flags. Represents commands
+  // and their parameters.  For eg: put key1 value1 go into this vector.
+  vector<string> cmdTokens;
+
+  const string OPTION_PREFIX = "--";
+
+  for (const auto& arg : args) {
+    if (arg[0] == '-' && arg[1] == '-'){
+      vector<string> splits = stringSplit(arg, '=');
+      if (splits.size() == 2) {
+        string optionKey = splits[0].substr(OPTION_PREFIX.size());
+        option_map[optionKey] = splits[1];
+      } else {
+        string optionKey = splits[0].substr(OPTION_PREFIX.size());
+        flags.push_back(optionKey);
+      }
+    } else {
+      cmdTokens.push_back(arg);
+    }
+  }
+
+  if (cmdTokens.size() < 1) {
+    fprintf(stderr, "Command not specified!");
+    return nullptr;
+  }
+
+  string cmd = cmdTokens[0];
+  vector<string> cmdParams(cmdTokens.begin()+1, cmdTokens.end());
+  LDBCommand* command = LDBCommand::SelectCommand(
+    cmd,
+    cmdParams,
+    option_map,
+    flags
+  );
+
+  if (command) {
+    command->SetOptions(options);
+  }
+  return command;
+}
+
+LDBCommand* LDBCommand::SelectCommand(
+    const std::string& cmd,
+    const vector<string>& cmdParams,
+    const map<string, string>& option_map,
+    const vector<string>& flags
+  ) {
+
+  if (cmd == GetCommand::Name()) {
+    return new GetCommand(cmdParams, option_map, flags);
+  } else if (cmd == PutCommand::Name()) {
+    return new PutCommand(cmdParams, option_map, flags);
+  } else if (cmd == BatchPutCommand::Name()) {
+    return new BatchPutCommand(cmdParams, option_map, flags);
+  } else if (cmd == ScanCommand::Name()) {
+    return new ScanCommand(cmdParams, option_map, flags);
+  } else if (cmd == DeleteCommand::Name()) {
+    return new DeleteCommand(cmdParams, option_map, flags);
+  } else if (cmd == ApproxSizeCommand::Name()) {
+    return new ApproxSizeCommand(cmdParams, option_map, flags);
+  } else if (cmd == DBQuerierCommand::Name()) {
+    return new DBQuerierCommand(cmdParams, option_map, flags);
+  } else if (cmd == CompactorCommand::Name()) {
+    return new CompactorCommand(cmdParams, option_map, flags);
+  } else if (cmd == WALDumperCommand::Name()) {
+    return new WALDumperCommand(cmdParams, option_map, flags);
+  } else if (cmd == ReduceDBLevelsCommand::Name()) {
+    return new ReduceDBLevelsCommand(cmdParams, option_map, flags);
+  } else if (cmd == ChangeCompactionStyleCommand::Name()) {
+    return new ChangeCompactionStyleCommand(cmdParams, option_map, flags);
+  } else if (cmd == DBDumperCommand::Name()) {
+    return new DBDumperCommand(cmdParams, option_map, flags);
+  } else if (cmd == DBLoaderCommand::Name()) {
+    return new DBLoaderCommand(cmdParams, option_map, flags);
+  } else if (cmd == ManifestDumpCommand::Name()) {
+    return new ManifestDumpCommand(cmdParams, option_map, flags);
+  } else if (cmd == InternalDumpCommand::Name()) {
+    return new InternalDumpCommand(cmdParams, option_map, 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<string, string>& options,
+                                const string& option, int& value,
+                                LDBCommandExecuteResult& exec_state) {
+
+  map<string, string>::const_iterator itr = option_map_.find(option);
+  if (itr != option_map_.end()) {
+    try {
+      value = stoi(itr->second);
+      return true;
+    } catch(const invalid_argument&) {
+      exec_state = LDBCommandExecuteResult::FAILED(option +
+                      " has an invalid value.");
+    } catch(const out_of_range&) {
+      exec_state = LDBCommandExecuteResult::FAILED(option +
+                      " has a value out-of-range.");
+    }
+  }
+  return false;
+}
+
+/**
+ * Parses the specified option and fills in the value.
+ * Returns true if the option is found.
+ * Returns false otherwise.
+ */
+bool LDBCommand::ParseStringOption(const map<string, string>& options,
+                                   const string& option, string* value) {
+  auto itr = option_map_.find(option);
+  if (itr != option_map_.end()) {
+    *value = itr->second;
+    return true;
+  }
+  return false;
+}
+
+Options LDBCommand::PrepareOptionsForOpenDB() {
+
+  Options opt = options_;
+  opt.create_if_missing = false;
+
+  map<string, string>::const_iterator itr;
+
+  int bits;
+  if (ParseIntOption(option_map_, ARG_BLOOM_BITS, bits, exec_state_)) {
+    if (bits > 0) {
+      opt.filter_policy = NewBloomFilterPolicy(bits);
+    } else {
+      exec_state_ = LDBCommandExecuteResult::FAILED(ARG_BLOOM_BITS +
+                      " must be > 0.");
+    }
+  }
+
+  int block_size;
+  if (ParseIntOption(option_map_, 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 = option_map_.find(ARG_AUTO_COMPACTION);
+  if (itr != option_map_.end()) {
+    opt.disable_auto_compactions = ! StringToBool(itr->second);
+  }
+
+  itr = option_map_.find(ARG_COMPRESSION_TYPE);
+  if (itr != option_map_.end()) {
+    string comp = itr->second;
+    if (comp == "no") {
+      opt.compression = kNoCompression;
+    } else if (comp == "snappy") {
+      opt.compression = kSnappyCompression;
+    } else if (comp == "zlib") {
+      opt.compression = kZlibCompression;
+    } else if (comp == "bzip2") {
+      opt.compression = kBZip2Compression;
+    } else {
+      // Unknown compression.
+      exec_state_ = LDBCommandExecuteResult::FAILED(
+                      "Unknown compression level: " + comp);
+    }
+  }
+
+  int write_buffer_size;
+  if (ParseIntOption(option_map_, 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(option_map_, 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 != 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<string, string>::const_iterator itr = option_map_.begin();
+        itr != option_map_.end(); itr++) {
+    if (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<string>::const_iterator itr = flags_.begin();
+        itr != flags_.end(); itr++) {
+    if (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 (!NoDBOpen() && option_map_.find(ARG_DB) == option_map_.end()) {
+    fprintf(stderr, "%s must be specified\n", ARG_DB.c_str());
+    return false;
+  }
+
+  return true;
+}
+
+CompactorCommand::CompactorCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& flags) :
+    LDBCommand(options, flags, false,
+               BuildCmdLineOptions({ARG_FROM, ARG_TO, ARG_HEX, ARG_KEY_HEX,
+                                    ARG_VALUE_HEX, ARG_TTL})),
+    null_from_(true), null_to_(true) {
+
+  map<string, string>::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() {
+
+  Slice* begin = nullptr;
+  Slice* end = nullptr;
+  if (!null_from_) {
+    begin = new Slice(from_);
+  }
+  if (!null_to_) {
+    end = new 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<string>& params,
+      const map<string, string>& options, const vector<string>& 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");
+}
+
+Options DBLoaderCommand::PrepareOptionsForOpenDB() {
+  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 (getline(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) {
+    cout << "Warning: " << bad_lines << " bad lines ignored." << endl;
+  }
+  if (compact_) {
+    db_->CompactRange(nullptr, nullptr);
+  }
+}
+
+// ----------------------------------------------------------------------------
+
+const string ManifestDumpCommand::ARG_VERBOSE = "verbose";
+const string ManifestDumpCommand::ARG_PATH    = "path";
+
+void ManifestDumpCommand::Help(string& ret) {
+  ret.append("  ");
+  ret.append(ManifestDumpCommand::Name());
+  ret.append(" [--" + ARG_VERBOSE + "]");
+  ret.append(" [--" + ARG_PATH + "=<path_to_manifest_file>]");
+  ret.append("\n");
+}
+
+ManifestDumpCommand::ManifestDumpCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& flags) :
+    LDBCommand(options, flags, false,
+               BuildCmdLineOptions({ARG_VERBOSE, ARG_PATH, ARG_HEX})),
+    verbose_(false),
+    path_("")
+{
+  verbose_ = IsFlagPresent(flags, ARG_VERBOSE);
+
+  map<string, string>::const_iterator itr = options.find(ARG_PATH);
+  if (itr != options.end()) {
+    path_ = itr->second;
+    if (path_.empty()) {
+      exec_state_ = LDBCommandExecuteResult::FAILED("--path: missing pathname");
+    }
+  }
+}
+
+void ManifestDumpCommand::DoCommand() {
+
+  std::string manifestfile;
+
+  if (!path_.empty()) {
+    manifestfile = path_;
+  } else {
+    bool found = false;
+    // We need to find the manifest file by searching the directory
+    // containing the db for files of the form MANIFEST_[0-9]+
+    DIR* d = opendir(db_path_.c_str());
+    if (d == nullptr) {
+      exec_state_ = LDBCommandExecuteResult::FAILED(
+        db_path_ + " is not a directory");
+      return;
+    }
+    struct dirent* entry;
+    while ((entry = readdir(d)) != nullptr) {
+      unsigned int match;
+      unsigned long long num;
+      if (sscanf(entry->d_name,
+                 "MANIFEST-%ln%ln",
+                 (unsigned long*)&num,
+                 (unsigned long*)&match)
+          && match == strlen(entry->d_name)) {
+        if (!found) {
+          manifestfile = db_path_ + "/" + std::string(entry->d_name);
+          found = true;
+        } else {
+          exec_state_ = LDBCommandExecuteResult::FAILED(
+            "Multiple MANIFEST files found; use --path to select one");
+          return;
+        }
+      }
+    }
+    closedir(d);
+  }
+
+  if (verbose_) {
+    printf("Processing Manifest file %s\n", manifestfile.c_str());
+  }
+
+  Options options;
+  EnvOptions sopt;
+  std::string file(manifestfile);
+  std::string dbname("dummy");
+  TableCache* tc = new TableCache(dbname, &options, sopt, 10);
+  const InternalKeyComparator* cmp =
+    new InternalKeyComparator(options.comparator);
+
+  VersionSet* versions = new VersionSet(dbname, &options, sopt, tc, cmp);
+  Status s = versions->DumpManifest(options, file, verbose_, is_key_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());
+  }
+}
+
+// ----------------------------------------------------------------------------
+
+string ReadableTime(int unixtime) {
+  char time_buffer [80];
+  time_t rawtime = unixtime;
+  struct tm * timeinfo = localtime(&rawtime);
+  strftime(time_buffer, 80, "%c", timeinfo);
+  return string(time_buffer);
+}
+
+// This function only called when it's the sane case of >1 buckets in time-range
+// Also called only when timekv falls between ttl_start and ttl_end provided
+void IncBucketCounts(vector<uint64_t>& bucket_counts, int ttl_start,
+      int time_range, int bucket_size, int timekv, int num_buckets) {
+  assert(time_range > 0 && timekv >= ttl_start && bucket_size > 0 &&
+    timekv < (ttl_start + time_range) && num_buckets > 1);
+  int bucket = (timekv - ttl_start) / bucket_size;
+  bucket_counts[bucket]++;
+}
+
+void PrintBucketCounts(const vector<uint64_t>& bucket_counts, int ttl_start,
+      int ttl_end, int bucket_size, int num_buckets) {
+  int time_point = ttl_start;
+  for(int i = 0; i < num_buckets - 1; i++, time_point += bucket_size) {
+    fprintf(stdout, "Keys in range %s to %s : %lu\n",
+            ReadableTime(time_point).c_str(),
+            ReadableTime(time_point + bucket_size).c_str(),
+            (unsigned long)bucket_counts[i]);
+  }
+  fprintf(stdout, "Keys in range %s to %s : %lu\n",
+          ReadableTime(time_point).c_str(),
+          ReadableTime(ttl_end).c_str(),
+          (unsigned long)bucket_counts[num_buckets - 1]);
+}
+
+const string InternalDumpCommand::ARG_COUNT_ONLY = "count_only";
+const string InternalDumpCommand::ARG_COUNT_DELIM = "count_delim";
+const string InternalDumpCommand::ARG_STATS = "stats";
+const string InternalDumpCommand::ARG_INPUT_KEY_HEX = "input_key_hex";
+
+InternalDumpCommand::InternalDumpCommand(const vector<string>& params,
+                                         const map<string, string>& options,
+                                         const vector<string>& 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_COUNT_DELIM, ARG_STATS,
+                                     ARG_INPUT_KEY_HEX})),
+    has_from_(false),
+    has_to_(false),
+    max_keys_(-1),
+    delim_("."),
+    count_only_(false),
+    count_delim_(false),
+    print_stats_(false),
+    is_input_key_hex_(false) {
+
+  has_from_ = ParseStringOption(options, ARG_FROM, &from_);
+  has_to_ = ParseStringOption(options, ARG_TO, &to_);
+
+  ParseIntOption(options, ARG_MAX_KEYS, max_keys_, exec_state_);
+  map<string, string>::const_iterator itr = options.find(ARG_COUNT_DELIM);
+  if (itr != options.end()) {
+    delim_ = itr->second;
+    count_delim_ = true;
+   // fprintf(stdout,"delim = %c\n",delim_[0]);
+  } else {
+    count_delim_ = IsFlagPresent(flags, ARG_COUNT_DELIM);
+    delim_=".";
+  }
+
+  print_stats_ = IsFlagPresent(flags, ARG_STATS);
+  count_only_ = IsFlagPresent(flags, ARG_COUNT_ONLY);
+  is_input_key_hex_ = IsFlagPresent(flags, ARG_INPUT_KEY_HEX);
+
+  if (is_input_key_hex_) {
+    if (has_from_) {
+      from_ = HexToString(from_);
+    }
+    if (has_to_) {
+      to_ = HexToString(to_);
+    }
+  }
+}
+
+void InternalDumpCommand::Help(string& ret) {
+  ret.append("  ");
+  ret.append(InternalDumpCommand::Name());
+  ret.append(HelpRangeCmdArgs());
+  ret.append(" [--" + ARG_INPUT_KEY_HEX + "]");
+  ret.append(" [--" + ARG_MAX_KEYS + "=<N>]");
+  ret.append(" [--" + ARG_COUNT_ONLY + "]");
+  ret.append(" [--" + ARG_COUNT_DELIM + "=<char>]");
+  ret.append(" [--" + ARG_STATS + "]");
+  ret.append("\n");
+}
+
+void InternalDumpCommand::DoCommand() {
+  if (!db_) {
+    return;
+  }
+
+  if (print_stats_) {
+    string stats;
+    if (db_->GetProperty("rocksdb.stats", &stats)) {
+      fprintf(stdout, "%s\n", stats.c_str());
+    }
+  }
+
+  // Cast as DBImpl to get internal iterator
+  DBImpl* idb = dynamic_cast<DBImpl*>(db_);
+  if (!idb) {
+    exec_state_ = LDBCommandExecuteResult::FAILED("DB is not DBImpl");
+    return;
+  }
+  string rtype1,rtype2,row,val;
+  rtype2 = "";
+  uint64_t c=0;
+  uint64_t s1=0,s2=0;
+  // Setup internal key iterator
+  auto iter = unique_ptr<Iterator>(idb->TEST_NewInternalIterator());
+  Status st = iter->status();
+  if (!st.ok()) {
+    exec_state_ = LDBCommandExecuteResult::FAILED("Iterator error:"
+                                                  + st.ToString());
+  }
+
+  if (has_from_) {
+    InternalKey ikey(from_, kMaxSequenceNumber, kValueTypeForSeek);
+    iter->Seek(ikey.Encode());
+  } else {
+    iter->SeekToFirst();
+  }
+
+  long long count = 0;
+  for (; iter->Valid(); iter->Next()) {
+    ParsedInternalKey ikey;
+    if (!ParseInternalKey(iter->key(), &ikey)) {
+      fprintf(stderr, "Internal Key [%s] parse error!\n",
+              iter->key().ToString(true /* in hex*/).data());
+      // TODO: add error counter
+      continue;
+    }
+
+    // If end marker was specified, we stop before it
+    if (has_to_ && options_.comparator->Compare(ikey.user_key, to_) >= 0) {
+      break;
+    }
+
+    ++count;
+    int k;
+    if (count_delim_) {
+      rtype1 = "";
+      s1=0;
+      row = iter->key().ToString();
+      val = iter->value().ToString();
+      for(k=0;row[k]!='\x01' && row[k]!='\0';k++)
+        s1++;
+      for(k=0;val[k]!='\x01' && val[k]!='\0';k++)
+        s1++;
+      for(int j=0;row[j]!=delim_[0] && row[j]!='\0' && row[j]!='\x01';j++)
+        rtype1+=row[j];
+      if(rtype2.compare("") && rtype2.compare(rtype1)!=0) {
+        fprintf(stdout,"%s => count:%lld\tsize:%lld\n",rtype2.c_str(),
+            (long long)c,(long long)s2);
+        c=1;
+        s2=s1;
+        rtype2 = rtype1;
+      } else {
+        c++;
+        s2+=s1;
+        rtype2=rtype1;
+    }
+  }
+
+    if (!count_only_ && !count_delim_) {
+      string key = ikey.DebugString(is_key_hex_);
+      string value = iter->value().ToString(is_value_hex_);
+      std::cout << key << " => " << value << "\n";
+    }
+
+    // Terminate if maximum number of keys have been dumped
+    if (max_keys_ > 0 && count >= max_keys_) break;
+  }
+  if(count_delim_) {
+    fprintf(stdout,"%s => count:%lld\tsize:%lld\n", rtype2.c_str(),
+        (long long)c,(long long)s2);
+  } else
+  fprintf(stdout, "Internal keys in range: %lld\n", (long long) count);
+}
+
+
+const string DBDumperCommand::ARG_COUNT_ONLY = "count_only";
+const string DBDumperCommand::ARG_COUNT_DELIM = "count_delim";
+const string DBDumperCommand::ARG_STATS = "stats";
+const string DBDumperCommand::ARG_TTL_BUCKET = "bucket";
+
+DBDumperCommand::DBDumperCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& flags) :
+    LDBCommand(options, flags, true,
+               BuildCmdLineOptions({ARG_TTL, ARG_HEX, ARG_KEY_HEX,
+                                    ARG_VALUE_HEX, ARG_FROM, ARG_TO,
+                                    ARG_MAX_KEYS, ARG_COUNT_ONLY,
+                                    ARG_COUNT_DELIM, ARG_STATS, ARG_TTL_START,
+                                    ARG_TTL_END, ARG_TTL_BUCKET,
+                                    ARG_TIMESTAMP})),
+    null_from_(true),
+    null_to_(true),
+    max_keys_(-1),
+    count_only_(false),
+    count_delim_(false),
+    print_stats_(false) {
+
+  map<string, string>::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_ = stoi(itr->second);
+    } catch(const invalid_argument&) {
+      exec_state_ = LDBCommandExecuteResult::FAILED(ARG_MAX_KEYS +
+                        " has an invalid value");
+    } catch(const out_of_range&) {
+      exec_state_ = LDBCommandExecuteResult::FAILED(ARG_MAX_KEYS +
+                        " has a value out-of-range");
+    }
+  }
+  itr = options.find(ARG_COUNT_DELIM);
+  if (itr != options.end()) {
+    delim_ = itr->second;
+    count_delim_ = true;
+  } else {
+    count_delim_ = IsFlagPresent(flags, ARG_COUNT_DELIM);
+    delim_=".";
+  }
+
+  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_TTL + "]");
+  ret.append(" [--" + ARG_MAX_KEYS + "=<N>]");
+  ret.append(" [--" + ARG_TIMESTAMP + "]");
+  ret.append(" [--" + ARG_COUNT_ONLY + "]");
+  ret.append(" [--" + ARG_COUNT_DELIM + "=<char>]");
+  ret.append(" [--" + ARG_STATS + "]");
+  ret.append(" [--" + ARG_TTL_BUCKET + "=<N>]");
+  ret.append(" [--" + ARG_TTL_START + "=<N>:- is inclusive]");
+  ret.append(" [--" + ARG_TTL_END + "=<N>:- is exclusive]");
+  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("rocksdb.stats", &stats)) {
+      fprintf(stdout, "%s\n", stats.c_str());
+    }
+  }
+
+  // Setup key iterator
+  Iterator* iter = db_->NewIterator(ReadOptions());
+  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_;
+  int ttl_start;
+  if (!ParseIntOption(option_map_, ARG_TTL_START, ttl_start, exec_state_)) {
+    ttl_start = DBWithTTL::kMinTimestamp; // TTL introduction time
+  }
+  int ttl_end;
+  if (!ParseIntOption(option_map_, ARG_TTL_END, ttl_end, exec_state_)) {
+    ttl_end = DBWithTTL::kMaxTimestamp; // Max time allowed by TTL feature
+  }
+  if (ttl_end < ttl_start) {
+    fprintf(stderr, "Error: End time can't be less than start time\n");
+    delete iter;
+    return;
+  }
+  int time_range = ttl_end - ttl_start;
+  int bucket_size;
+  if (!ParseIntOption(option_map_, ARG_TTL_BUCKET, bucket_size, exec_state_) ||
+      bucket_size <= 0) {
+    bucket_size = time_range; // Will have just 1 bucket by default
+  }
+  //cretaing variables for row count of each type
+  string rtype1,rtype2,row,val;
+  rtype2 = "";
+  uint64_t c=0;
+  uint64_t s1=0,s2=0;
+
+  // At this point, bucket_size=0 => time_range=0
+  uint64_t num_buckets = (bucket_size >= time_range) ? 1 :
+    ((time_range + bucket_size - 1) / bucket_size);
+  vector<uint64_t> bucket_counts(num_buckets, 0);
+  if (is_db_ttl_ && !count_only_ && timestamp_ && !count_delim_) {
+    fprintf(stdout, "Dumping key-values from %s to %s\n",
+            ReadableTime(ttl_start).c_str(), ReadableTime(ttl_end).c_str());
+  }
+
+  for (; iter->Valid(); iter->Next()) {
+    int rawtime = 0;
+    // 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 (is_db_ttl_) {
+      TtlIterator* it_ttl = dynamic_cast<TtlIterator*>(iter);
+      assert(it_ttl);
+      rawtime = it_ttl->timestamp();
+      if (rawtime < ttl_start || rawtime >= ttl_end) {
+        continue;
+      }
+    }
+    if (max_keys > 0) {
+      --max_keys;
+    }
+    if (is_db_ttl_ && num_buckets > 1) {
+      IncBucketCounts(bucket_counts, ttl_start, time_range, bucket_size,
+                      rawtime, num_buckets);
+    }
+    ++count;
+    if (count_delim_) {
+      rtype1 = "";
+      row = iter->key().ToString();
+      val = iter->value().ToString();
+      s1 = row.size()+val.size();
+      for(int j=0;row[j]!=delim_[0] && row[j]!='\0';j++)
+        rtype1+=row[j];
+      if(rtype2.compare("") && rtype2.compare(rtype1)!=0) {
+        fprintf(stdout,"%s => count:%lld\tsize:%lld\n",rtype2.c_str(),
+            (long long )c,(long long)s2);
+        c=1;
+        s2=s1;
+        rtype2 = rtype1;
+      } else {
+          c++;
+          s2+=s1;
+          rtype2=rtype1;
+      }
+
+    }
+
+
+
+    if (!count_only_ && !count_delim_) {
+      if (is_db_ttl_ && timestamp_) {
+        fprintf(stdout, "%s ", ReadableTime(rawtime).c_str());
+      }
+      string str = PrintKeyValue(iter->key().ToString(),
+                                 iter->value().ToString(), is_key_hex_,
+                                 is_value_hex_);
+      fprintf(stdout, "%s\n", str.c_str());
+    }
+  }
+
+  if (num_buckets > 1 && is_db_ttl_) {
+    PrintBucketCounts(bucket_counts, ttl_start, ttl_end, bucket_size,
+                      num_buckets);
+  } else if(count_delim_) {
+    fprintf(stdout,"%s => count:%lld\tsize:%lld\n",rtype2.c_str(),
+        (long long )c,(long long)s2);
+  } else {
+    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<string>& params,
+      const map<string, string>& options, const vector<string>& 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(option_map_, 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<string> ReduceDBLevelsCommand::PrepareArgs(const string& db_path,
+    int new_levels, bool print_old_level) {
+  vector<string> ret;
+  ret.push_back("reduce_levels");
+  ret.push_back("--" + ARG_DB + "=" + db_path);
+  ret.push_back("--" + ARG_NEW_LEVELS + "=" + 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 + "=<New number of levels>");
+  ret.append(" [--" + ARG_PRINT_OLD_LEVELS + "]");
+  ret.append("\n");
+}
+
+Options ReduceDBLevelsCommand::PrepareOptionsForOpenDB() {
+  Options opt = LDBCommand::PrepareOptionsForOpenDB();
+  opt.num_levels = old_levels_;
+  opt.max_bytes_for_level_multiplier_additional.resize(opt.num_levels, 1);
+  // 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(Options& opt,
+    int* levels) {
+  EnvOptions soptions;
+  TableCache tc(db_path_, &opt, soptions, 10);
+  const InternalKeyComparator cmp(opt.comparator);
+  VersionSet versions(db_path_, &opt, soptions, &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;
+  return st;
+}
+
+void ReduceDBLevelsCommand::DoCommand() {
+  if (new_levels_ <= 1) {
+    exec_state_ = LDBCommandExecuteResult::FAILED(
+        "Invalid number of levels.\n");
+    return;
+  }
+
+  Status st;
+  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();
+
+  EnvOptions soptions;
+  TableCache tc(db_path_, &opt, soptions, 10);
+  const InternalKeyComparator cmp(opt.comparator);
+  VersionSet versions(db_path_, &opt, soptions, &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;
+  }
+}
+
+const string ChangeCompactionStyleCommand::ARG_OLD_COMPACTION_STYLE =
+  "old_compaction_style";
+const string ChangeCompactionStyleCommand::ARG_NEW_COMPACTION_STYLE =
+  "new_compaction_style";
+
+ChangeCompactionStyleCommand::ChangeCompactionStyleCommand(
+      const vector<string>& params, const map<string, string>& options,
+      const vector<string>& flags) :
+    LDBCommand(options, flags, false,
+               BuildCmdLineOptions({ARG_OLD_COMPACTION_STYLE,
+                                    ARG_NEW_COMPACTION_STYLE})),
+    old_compaction_style_(-1),
+    new_compaction_style_(-1) {
+
+  ParseIntOption(option_map_, ARG_OLD_COMPACTION_STYLE, old_compaction_style_,
+    exec_state_);
+  if (old_compaction_style_ != kCompactionStyleLevel &&
+     old_compaction_style_ != kCompactionStyleUniversal) {
+    exec_state_ = LDBCommandExecuteResult::FAILED(
+      "Use --" + ARG_OLD_COMPACTION_STYLE + " to specify old compaction " +
+      "style. Check ldb help for proper compaction style value.\n");
+    return;
+  }
+
+  ParseIntOption(option_map_, ARG_NEW_COMPACTION_STYLE, new_compaction_style_,
+    exec_state_);
+  if (new_compaction_style_ != kCompactionStyleLevel &&
+     new_compaction_style_ != kCompactionStyleUniversal) {
+    exec_state_ = LDBCommandExecuteResult::FAILED(
+      "Use --" + ARG_NEW_COMPACTION_STYLE + " to specify new compaction " +
+      "style. Check ldb help for proper compaction style value.\n");
+    return;
+  }
+
+  if (new_compaction_style_ == old_compaction_style_) {
+    exec_state_ = LDBCommandExecuteResult::FAILED(
+      "Old compaction style is the same as new compaction style. "
+      "Nothing to do.\n");
+    return;
+  }
+
+  if (old_compaction_style_ == kCompactionStyleUniversal &&
+      new_compaction_style_ == kCompactionStyleLevel) {
+    exec_state_ = LDBCommandExecuteResult::FAILED(
+      "Convert from universal compaction to level compaction. "
+      "Nothing to do.\n");
+    return;
+  }
+}
+
+void ChangeCompactionStyleCommand::Help(string& ret) {
+  ret.append("  ");
+  ret.append(ChangeCompactionStyleCommand::Name());
+  ret.append(" --" + ARG_OLD_COMPACTION_STYLE + "=<Old compaction style: 0 " +
+             "for level compaction, 1 for universal compaction>");
+  ret.append(" --" + ARG_NEW_COMPACTION_STYLE + "=<New compaction style: 0 " +
+             "for level compaction, 1 for universal compaction>");
+  ret.append("\n");
+}
+
+Options ChangeCompactionStyleCommand::PrepareOptionsForOpenDB() {
+  Options opt = LDBCommand::PrepareOptionsForOpenDB();
+
+  if (old_compaction_style_ == kCompactionStyleLevel &&
+      new_compaction_style_ == kCompactionStyleUniversal) {
+    // In order to convert from level compaction to universal compaction, we
+    // need to compact all data into a single file and move it to level 0.
+    opt.disable_auto_compactions = true;
+    opt.target_file_size_base = INT_MAX;
+    opt.target_file_size_multiplier = 1;
+    opt.max_bytes_for_level_base = INT_MAX;
+    opt.max_bytes_for_level_multiplier = 1;
+  }
+
+  return opt;
+}
+
+void ChangeCompactionStyleCommand::DoCommand() {
+  // print db stats before we have made any change
+  std::string property;
+  std::string files_per_level;
+  for (int i = 0; i < db_->NumberLevels(); i++) {
+    db_->GetProperty("rocksdb.num-files-at-level" + NumberToString(i),
+                     &property);
+
+    // format print string
+    char buf[100];
+    snprintf(buf, sizeof(buf), "%s%s", (i ? "," : ""), property.c_str());
+    files_per_level += buf;
+  }
+  fprintf(stdout, "files per level before compaction: %s\n",
+          files_per_level.c_str());
+
+  // manual compact into a single file and move the file to level 0
+  db_->CompactRange(nullptr, nullptr,
+                    true /* reduce level */,
+                    0    /* reduce to level 0 */);
+
+  // verify compaction result
+  files_per_level = "";
+  int num_files = 0;
+  for (int i = 0; i < db_->NumberLevels(); i++) {
+    db_->GetProperty("rocksdb.num-files-at-level" + NumberToString(i),
+                     &property);
+
+    // format print string
+    char buf[100];
+    snprintf(buf, sizeof(buf), "%s%s", (i ? "," : ""), property.c_str());
+    files_per_level += buf;
+
+    num_files = atoi(property.c_str());
+
+    // level 0 should have only 1 file
+    if (i == 0 && num_files != 1) {
+      exec_state_ = LDBCommandExecuteResult::FAILED("Number of db files at "
+        "level 0 after compaction is " + std::to_string(num_files) +
+        ", not 1.\n");
+      return;
+    }
+    // other levels should have no file
+    if (i > 0 && num_files != 0) {
+      exec_state_ = LDBCommandExecuteResult::FAILED("Number of db files at "
+        "level " + std::to_string(i) + " after compaction is " +
+        std::to_string(num_files) + ", not 0.\n");
+      return;
+    }
+  }
+
+  fprintf(stdout, "files per level after compaction: %s\n",
+          files_per_level.c_str());
+}
+
+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<string, string> PutMap() {
+    return putMap_;
+  }
+  vector<string> DeleteList() {
+    return deleteList_;
+  }
+
+ private:
+  map<string, string> putMap_;
+  vector<string> 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<string>& params,
+      const map<string, string>& options, const vector<string>& 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<string, string>::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 + "=<write_ahead_log_file_path>");
+  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) {
+      cerr<<"Corruption detected in log file "<<s.ToString()<<"\n";
+    }
+  };
+
+  unique_ptr<SequentialFile> file;
+  Env* env_ = Env::Default();
+  EnvOptions soptions;
+  Status status = env_->NewSequentialFile(wal_file_, &file, soptions);
+  if (!status.ok()) {
+    exec_state_ = LDBCommandExecuteResult::FAILED("Failed to open WAL file " +
+      status.ToString());
+  } else {
+    StdErrReporter reporter;
+    log::Reader reader(move(file), &reporter, true, 0);
+    string scratch;
+    WriteBatch batch;
+    Slice record;
+    stringstream row;
+    if (print_header_) {
+      cout<<"Sequence,Count,ByteSize,Physical Offset,Key(s)";
+      if (print_values_) {
+        cout << " : value ";
+      }
+      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<<WriteBatchInternal::Sequence(&batch)<<",";
+        row<<WriteBatchInternal::Count(&batch)<<",";
+        row<<WriteBatchInternal::ByteSize(&batch)<<",";
+        row<<reader.LastRecordOffset()<<",";
+        InMemoryHandler handler;
+        batch.Iterate(&handler);
+        row << "PUT : ";
+        if (print_values_) {
+          for (auto& kv : handler.PutMap()) {
+            string k = StringToHex(kv.first);
+            string v = StringToHex(kv.second);
+            row << k << " : ";
+            row << v << " ";
+          }
+        }
+        else {
+          for(auto& kv : handler.PutMap()) {
+            row << StringToHex(kv.first) << " ";
+          }
+        }
+        row<<",DELETE : ";
+        for(string& s : handler.DeleteList()) {
+          row << StringToHex(s) << " ";
+        }
+        row<<"\n";
+      }
+      cout<<row.str();
+    }
+  }
+}
+
+
+GetCommand::GetCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& flags) :
+  LDBCommand(options, flags, true, BuildCmdLineOptions({ARG_TTL, ARG_HEX,
+                                                        ARG_KEY_HEX,
+                                                        ARG_VALUE_HEX})) {
+
+  if (params.size() != 1) {
+    exec_state_ = LDBCommandExecuteResult::FAILED(
+                    "<key> 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(" <key>");
+  ret.append(" [--" + ARG_TTL + "]");
+  ret.append("\n");
+}
+
+void GetCommand::DoCommand() {
+  string value;
+  Status st = db_->Get(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<string>& params,
+      const map<string, string>& options, const vector<string>& 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() {
+
+  Range ranges[1];
+  ranges[0] = Range(start_key_, end_key_);
+  uint64_t sizes[1];
+  db_->GetApproximateSizes(ranges, 1, sizes);
+  fprintf(stdout, "%lu\n", (unsigned long)sizes[0]);
+  /* Weird 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<string>& params,
+      const map<string, string>& options, const vector<string>& flags) :
+  LDBCommand(options, flags, false,
+             BuildCmdLineOptions({ARG_TTL, ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX,
+                                  ARG_CREATE_IF_MISSING})) {
+
+  if (params.size() < 2) {
+    exec_state_ = LDBCommandExecuteResult::FAILED(
+        "At least one <key> <value> pair must be specified batchput.");
+  } else if (params.size() % 2 != 0) {
+    exec_state_ = LDBCommandExecuteResult::FAILED(
+        "Equal number of <key>s and <value>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(pair<string, string>(
+                    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(" <key> <value> [<key> <value>] [..]");
+  ret.append(" [--" + ARG_TTL + "]");
+  ret.append("\n");
+}
+
+void BatchPutCommand::DoCommand() {
+  WriteBatch batch;
+
+  for (vector<pair<string, string>>::const_iterator itr
+        = key_values_.begin(); itr != key_values_.end(); itr++) {
+      batch.Put(itr->first, itr->second);
+  }
+  Status st = db_->Write(WriteOptions(), &batch);
+  if (st.ok()) {
+    fprintf(stdout, "OK\n");
+  } else {
+    exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString());
+  }
+}
+
+Options BatchPutCommand::PrepareOptionsForOpenDB() {
+  Options opt = LDBCommand::PrepareOptionsForOpenDB();
+  opt.create_if_missing = IsFlagPresent(flags_, ARG_CREATE_IF_MISSING);
+  return opt;
+}
+
+
+ScanCommand::ScanCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& flags) :
+    LDBCommand(options, flags, true,
+               BuildCmdLineOptions({ARG_TTL, ARG_HEX, ARG_KEY_HEX, ARG_TO,
+                                    ARG_VALUE_HEX, ARG_FROM, ARG_TIMESTAMP,
+                                    ARG_MAX_KEYS, ARG_TTL_START, ARG_TTL_END})),
+    start_key_specified_(false),
+    end_key_specified_(false),
+    max_keys_scanned_(-1) {
+
+  map<string, string>::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_ = stoi(itr->second);
+    } catch(const invalid_argument&) {
+      exec_state_ = LDBCommandExecuteResult::FAILED(ARG_MAX_KEYS +
+                        " has an invalid value");
+    } catch(const out_of_range&) {
+      exec_state_ = LDBCommandExecuteResult::FAILED(ARG_MAX_KEYS +
+                        " has a value out-of-range");
+    }
+  }
+}
+
+void ScanCommand::Help(string& ret) {
+  ret.append("  ");
+  ret.append(ScanCommand::Name());
+  ret.append(HelpRangeCmdArgs());
+  ret.append(" [--" + ARG_TTL + "]");
+  ret.append(" [--" + ARG_TIMESTAMP + "]");
+  ret.append(" [--" + ARG_MAX_KEYS + "=<N>q] ");
+  ret.append(" [--" + ARG_TTL_START + "=<N>:- is inclusive]");
+  ret.append(" [--" + ARG_TTL_END + "=<N>:- is exclusive]");
+  ret.append("\n");
+}
+
+void ScanCommand::DoCommand() {
+
+  int num_keys_scanned = 0;
+  Iterator* it = db_->NewIterator(ReadOptions());
+  if (start_key_specified_) {
+    it->Seek(start_key_);
+  } else {
+    it->SeekToFirst();
+  }
+  int ttl_start;
+  if (!ParseIntOption(option_map_, ARG_TTL_START, ttl_start, exec_state_)) {
+    ttl_start = DBWithTTL::kMinTimestamp; // TTL introduction time
+  }
+  int ttl_end;
+  if (!ParseIntOption(option_map_, ARG_TTL_END, ttl_end, exec_state_)) {
+    ttl_end = DBWithTTL::kMaxTimestamp; // Max time allowed by TTL feature
+  }
+  if (ttl_end < ttl_start) {
+    fprintf(stderr, "Error: End time can't be less than start time\n");
+    delete it;
+    return;
+  }
+  if (is_db_ttl_ && timestamp_) {
+    fprintf(stdout, "Scanning key-values from %s to %s\n",
+            ReadableTime(ttl_start).c_str(), ReadableTime(ttl_end).c_str());
+  }
+  for ( ;
+        it->Valid() && (!end_key_specified_ || it->key().ToString() < end_key_);
+        it->Next()) {
+    string key = it->key().ToString();
+    if (is_db_ttl_) {
+      TtlIterator* it_ttl = dynamic_cast<TtlIterator*>(it);
+      assert(it_ttl);
+      int rawtime = it_ttl->timestamp();
+      if (rawtime < ttl_start || rawtime >= ttl_end) {
+        continue;
+      }
+      if (timestamp_) {
+        fprintf(stdout, "%s ", ReadableTime(rawtime).c_str());
+      }
+    }
+    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<string>& params,
+      const map<string, string>& options, const vector<string>& 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() + " <key>");
+  ret.append("\n");
+}
+
+void DeleteCommand::DoCommand() {
+  Status st = db_->Delete(WriteOptions(), key_);
+  if (st.ok()) {
+    fprintf(stdout, "OK\n");
+  } else {
+    exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString());
+  }
+}
+
+
+PutCommand::PutCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& flags) :
+  LDBCommand(options, flags, false,
+             BuildCmdLineOptions({ARG_TTL, ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX,
+                                  ARG_CREATE_IF_MISSING})) {
+
+  if (params.size() != 2) {
+    exec_state_ = LDBCommandExecuteResult::FAILED(
+                    "<key> and <value> 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(" <key> <value> ");
+  ret.append(" [--" + ARG_TTL + "]");
+  ret.append("\n");
+}
+
+void PutCommand::DoCommand() {
+  Status st = db_->Put(WriteOptions(), key_, value_);
+  if (st.ok()) {
+    fprintf(stdout, "OK\n");
+  } else {
+    exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString());
+  }
+}
+
+Options PutCommand::PrepareOptionsForOpenDB() {
+  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<string>& params,
+    const map<string, string>& options, const vector<string>& flags) :
+  LDBCommand(options, flags, false,
+             BuildCmdLineOptions({ARG_TTL, ARG_HEX, ARG_KEY_HEX,
+                                  ARG_VALUE_HEX})) {
+
+}
+
+void DBQuerierCommand::Help(string& ret) {
+  ret.append("  ");
+  ret.append(DBQuerierCommand::Name());
+  ret.append(" [--" + ARG_TTL + "]");
+  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;
+  }
+
+  ReadOptions read_options;
+  WriteOptions write_options;
+
+  string line;
+  string key;
+  string value;
+  while (getline(cin, line, '\n')) {
+
+    // Parse line into vector<string>
+    vector<string> 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 <key>\n"
+              "put <key> <value>\n"
+              "delete <key>\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 (file)
index 0000000..022f5fa
--- /dev/null
@@ -0,0 +1,689 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <stdlib.h>
+#include <algorithm>
+#include <stdio.h>
+
+#include "db/version_set.h"
+#include "rocksdb/env.h"
+#include "rocksdb/options.h"
+#include "rocksdb/iterator.h"
+#include "rocksdb/slice.h"
+#include "util/logging.h"
+#include "util/ldb_cmd_execute_result.h"
+#include "util/string_util.h"
+#include "utilities/utility_db.h"
+#include "utilities/ttl/db_ttl.h"
+
+using std::string;
+using std::map;
+using std::vector;
+using std::ostringstream;
+
+namespace rocksdb {
+
+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_TTL;
+  static const string ARG_TTL_START;
+  static const string ARG_TTL_END;
+  static const string ARG_TIMESTAMP;
+  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<string>& args,
+    const Options& options = Options()
+  );
+
+  static LDBCommand* InitFromCmdLineArgs(
+    int argc,
+    char** argv,
+    const Options& options = Options()
+  );
+
+  bool ValidateCmdLineOptions();
+
+  virtual Options PrepareOptionsForOpenDB();
+
+  virtual void SetOptions(Options options) {
+    options_ = options;
+  }
+
+  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 (str[0] != '0' || str[1] != 'x') {
+      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_;
+  string db_path_;
+  DB* db_;
+  StackableDB* sdb_;
+
+  /**
+   * 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_;
+
+  /** If true, the value is treated as timestamp suffixed */
+  bool is_db_ttl_;
+
+  // If true, the kvs are output with their insert/modify timestamp in a ttl db
+  bool timestamp_;
+
+  /**
+   * Map of options passed on the command-line.
+   */
+  const map<string, string> option_map_;
+
+  /**
+   * Flags passed on the command-line.
+   */
+  const vector<string> flags_;
+
+  /** List of command-line options valid for this command */
+  const vector<string> valid_cmd_line_options_;
+
+  bool ParseKeyValue(const string& line, string* key, string* value,
+                      bool is_key_hex, bool is_value_hex);
+
+  LDBCommand(const map<string, string>& options, const vector<string>& flags,
+             bool is_read_only, const vector<string>& valid_cmd_line_options) :
+      db_(nullptr),
+      is_read_only_(is_read_only),
+      is_key_hex_(false),
+      is_value_hex_(false),
+      is_db_ttl_(false),
+      timestamp_(false),
+      option_map_(options),
+      flags_(flags),
+      valid_cmd_line_options_(valid_cmd_line_options) {
+
+    map<string, string>::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);
+    is_db_ttl_ = IsFlagPresent(flags, ARG_TTL);
+    timestamp_ = IsFlagPresent(flags, ARG_TIMESTAMP);
+  }
+
+  void OpenDB() {
+    Options opt = PrepareOptionsForOpenDB();
+    if (!exec_state_.IsNotStarted()) {
+      return;
+    }
+    // Open the DB.
+    Status st;
+    if (is_db_ttl_) {
+      if (is_read_only_) {
+        st = UtilityDB::OpenTtlDB(opt, db_path_, &sdb_, 0, true);
+      } else {
+        st = UtilityDB::OpenTtlDB(opt, db_path_, &sdb_);
+      }
+      db_ = sdb_;
+    } else if (is_read_only_) {
+      st = DB::OpenForReadOnly(opt, db_path_, &db_);
+    } else {
+      st = DB::Open(opt, db_path_, &db_);
+    }
+    if (!st.ok()) {
+      string msg = st.ToString();
+      exec_state_ = LDBCommandExecuteResult::FAILED(msg);
+    }
+
+    options_ = opt;
+  }
+
+  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<string>& 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<string> BuildCmdLineOptions(vector<string> options) {
+    vector<string> 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<string, string>& options, const string& option,
+                      int& value, LDBCommandExecuteResult& exec_state);
+
+  bool ParseStringOption(const map<string, string>& options,
+                         const string& option, string* value);
+
+  Options options_;
+
+private:
+
+  /**
+   * Interpret command line options and flags to determine if the key
+   * should be input/output in hex.
+   */
+  bool IsKeyHex(const map<string, string>& options,
+      const vector<string>& 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<string, string>& options,
+      const vector<string>& 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<string, string>& options,
+      const string& option, bool default_val) {
+
+    map<string, string>::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) {
+    std::transform(val.begin(), val.end(), val.begin(), ::tolower);
+    if (val == "true") {
+      return true;
+    } else if (val == "false") {
+      return false;
+    } else {
+      throw "Invalid value for boolean argument";
+    }
+  }
+
+  static LDBCommand* SelectCommand(
+    const string& cmd,
+    const vector<string>& cmdParams,
+    const map<string, string>& option_map,
+    const vector<string>& flags
+  );
+
+};
+
+class CompactorCommand: public LDBCommand {
+public:
+  static string Name() { return "compact"; }
+
+  CompactorCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& 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<string>& params,
+      const map<string, string>& options, const vector<string>& flags);
+
+  static void Help(string& ret);
+
+  virtual void DoCommand();
+
+private:
+  bool null_from_;
+  string from_;
+  bool null_to_;
+  string to_;
+  int max_keys_;
+  string delim_;
+  bool count_only_;
+  bool count_delim_;
+  bool print_stats_;
+
+  static const string ARG_COUNT_ONLY;
+  static const string ARG_COUNT_DELIM;
+  static const string ARG_STATS;
+  static const string ARG_TTL_BUCKET;
+};
+
+class InternalDumpCommand: public LDBCommand {
+public:
+  static string Name() { return "idump"; }
+
+  InternalDumpCommand(const vector<string>& params,
+                      const map<string, string>& options,
+                      const vector<string>& flags);
+
+  static void Help(string& ret);
+
+  virtual void DoCommand();
+
+private:
+  bool has_from_;
+  string from_;
+  bool has_to_;
+  string to_;
+  int max_keys_;
+  string delim_;
+  bool count_only_;
+  bool count_delim_;
+  bool print_stats_;
+  bool is_input_key_hex_;
+
+  static const string ARG_DELIM;
+  static const string ARG_COUNT_ONLY;
+  static const string ARG_COUNT_DELIM;
+  static const string ARG_STATS;
+  static const string ARG_INPUT_KEY_HEX;
+};
+
+class DBLoaderCommand: public LDBCommand {
+public:
+  static string Name() { return "load"; }
+
+  DBLoaderCommand(string& db_name, vector<string>& args);
+
+  DBLoaderCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& flags);
+
+  static void Help(string& ret);
+  virtual void DoCommand();
+
+  virtual 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 ManifestDumpCommand: public LDBCommand {
+public:
+  static string Name() { return "manifest_dump"; }
+
+  ManifestDumpCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& flags);
+
+  static void Help(string& ret);
+  virtual void DoCommand();
+
+  virtual bool NoDBOpen() {
+    return true;
+  }
+
+private:
+  bool verbose_;
+  string path_;
+
+  static const string ARG_VERBOSE;
+  static const string ARG_PATH;
+};
+
+class ReduceDBLevelsCommand : public LDBCommand {
+public:
+  static string Name() { return "reduce_levels"; }
+
+  ReduceDBLevelsCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& flags);
+
+  virtual Options PrepareOptionsForOpenDB();
+
+  virtual void DoCommand();
+
+  virtual bool NoDBOpen() {
+    return true;
+  }
+
+  static void Help(string& msg);
+
+  static vector<string> 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(Options& opt, int* levels);
+};
+
+class ChangeCompactionStyleCommand : public LDBCommand {
+public:
+  static string Name() { return "change_compaction_style"; }
+
+  ChangeCompactionStyleCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& flags);
+
+  virtual Options PrepareOptionsForOpenDB();
+
+  virtual void DoCommand();
+
+  static void Help(string& msg);
+
+private:
+  int old_compaction_style_;
+  int new_compaction_style_;
+
+  static const string ARG_OLD_COMPACTION_STYLE;
+  static const string ARG_NEW_COMPACTION_STYLE;
+};
+
+class WALDumperCommand : public LDBCommand {
+public:
+  static string Name() { return "dump_wal"; }
+
+  WALDumperCommand(const vector<string>& params,
+      const map<string, string>& options, const vector<string>& 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<string>& params, const map<string, string>& options,
+      const vector<string>& 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<string>& params,
+      const map<string, string>& options, const vector<string>& 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<string>& params,
+      const map<string, string>& options, const vector<string>& flags);
+
+  virtual void DoCommand();
+
+  static void Help(string& ret);
+
+  virtual Options PrepareOptionsForOpenDB();
+
+private:
+  /**
+   * The key-values to be inserted.
+   */
+  vector<std::pair<string, string>> key_values_;
+};
+
+class ScanCommand : public LDBCommand {
+public:
+  static string Name() { return "scan"; }
+
+  ScanCommand(const vector<string>& params, const map<string, string>& options,
+      const vector<string>& 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<string>& params,
+      const map<string, string>& options, const vector<string>& 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<string>& params, const map<string, string>& options,
+      const vector<string>& flags);
+
+  virtual void DoCommand();
+
+  static void Help(string& ret);
+
+  virtual 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<string>& params,
+      const map<string, string>& options, const vector<string>& 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;
+};
+
+} // namespace rocksdb
diff --git a/util/ldb_cmd_execute_result.h b/util/ldb_cmd_execute_result.h
new file mode 100644 (file)
index 0000000..b9121b2
--- /dev/null
@@ -0,0 +1,76 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+
+namespace rocksdb {
+
+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&);
+};
+
+}
diff --git a/util/ldb_tool.cc b/util/ldb_tool.cc
new file mode 100644 (file)
index 0000000..2dbbbf8
--- /dev/null
@@ -0,0 +1,103 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "rocksdb/ldb_tool.h"
+#include "util/ldb_cmd.h"
+
+namespace rocksdb {
+
+class LDBCommandRunner {
+public:
+
+  static void PrintHelp(const char* exec_name) {
+    string ret;
+
+    ret.append("ldb - LevelDB Tool");
+    ret.append("\n\n");
+    ret.append("commands MUST specify --" + LDBCommand::ARG_DB +
+        "=<full_path_to_db_directory> when necessary\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_TTL +
+        " with 'put','get','scan','dump','query','batchput'"
+        " : DB supports ttl and value is internally timestamp-suffixed\n");
+    ret.append("  --" + LDBCommand::ARG_BLOOM_BITS + "=<int,e.g.:14>\n");
+    ret.append("  --" + LDBCommand::ARG_COMPRESSION_TYPE +
+        "=<no|snappy|zlib|bzip2>\n");
+    ret.append("  --" + LDBCommand::ARG_BLOCK_SIZE +
+        "=<block_size_in_bytes>\n");
+    ret.append("  --" + LDBCommand::ARG_AUTO_COMPACTION + "=<true|false>\n");
+    ret.append("  --" + LDBCommand::ARG_WRITE_BUFFER_SIZE +
+        "=<int,e.g.:4194304>\n");
+    ret.append("  --" + LDBCommand::ARG_FILE_SIZE + "=<int,e.g.:2097152>\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);
+    ChangeCompactionStyleCommand::Help(ret);
+    DBDumperCommand::Help(ret);
+    DBLoaderCommand::Help(ret);
+    ManifestDumpCommand::Help(ret);
+    InternalDumpCommand::Help(ret);
+
+    fprintf(stderr, "%s\n", ret.c_str());
+  }
+
+  static void RunCommand(int argc, char** argv, Options options) {
+    if (argc <= 2) {
+      PrintHelp(argv[0]);
+      exit(1);
+    }
+
+    LDBCommand* cmdObj = LDBCommand::InitFromCmdLineArgs(argc, argv, options);
+    if (cmdObj == nullptr) {
+      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());
+  }
+
+};
+
+
+void LDBTool::Run(int argc, char** argv, Options options) {
+  LDBCommandRunner::RunCommand(argc, argv, options);
+}
+} // namespace rocksdb
+
diff --git a/util/logging.cc b/util/logging.cc
new file mode 100644 (file)
index 0000000..6973413
--- /dev/null
@@ -0,0 +1,86 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rocksdb/env.h"
+#include "rocksdb/slice.h"
+
+namespace rocksdb {
+
+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<unsigned int>(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<uint64_t>(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 rocksdb
diff --git a/util/logging.h b/util/logging.h
new file mode 100644 (file)
index 0000000..411c83b
--- /dev/null
@@ -0,0 +1,48 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <stdio.h>
+#include <stdint.h>
+#include <string>
+#include "port/port.h"
+
+namespace rocksdb {
+
+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 rocksdb
diff --git a/util/manual_compaction_test.cc b/util/manual_compaction_test.cc
new file mode 100644 (file)
index 0000000..ebe1339
--- /dev/null
@@ -0,0 +1,93 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// Test for issue 178: a manual compaction causes deleted data to reappear.
+#include <iostream>
+#include <sstream>
+#include <cstdlib>
+
+#include "rocksdb/db.h"
+#include "rocksdb/write_batch.h"
+#include "util/testharness.h"
+
+namespace {
+
+const int kNumKeys = 1100000;
+
+std::string Key1(int i) {
+  char buf[100];
+  snprintf(buf, sizeof(buf), "my_key_%d", i);
+  return buf;
+}
+
+std::string Key2(int i) {
+  return Key1(i) + "_xxx";
+}
+
+class ManualCompactionTest { };
+
+TEST(ManualCompactionTest, Test) {
+  // Get rid of any state from an old run.
+  std::string dbpath = rocksdb::test::TmpDir() + "/rocksdb_cbug_test";
+  DestroyDB(dbpath, rocksdb::Options());
+
+  // Open database.  Disable compression since it affects the creation
+  // of layers and the code below is trying to test against a very
+  // specific scenario.
+  rocksdb::DB* db;
+  rocksdb::Options db_options;
+  db_options.create_if_missing = true;
+  db_options.compression = rocksdb::kNoCompression;
+  ASSERT_OK(rocksdb::DB::Open(db_options, dbpath, &db));
+
+  // create first key range
+  rocksdb::WriteBatch batch;
+  for (int i = 0; i < kNumKeys; i++) {
+    batch.Put(Key1(i), "value for range 1 key");
+  }
+  ASSERT_OK(db->Write(rocksdb::WriteOptions(), &batch));
+
+  // create second key range
+  batch.Clear();
+  for (int i = 0; i < kNumKeys; i++) {
+    batch.Put(Key2(i), "value for range 2 key");
+  }
+  ASSERT_OK(db->Write(rocksdb::WriteOptions(), &batch));
+
+  // delete second key range
+  batch.Clear();
+  for (int i = 0; i < kNumKeys; i++) {
+    batch.Delete(Key2(i));
+  }
+  ASSERT_OK(db->Write(rocksdb::WriteOptions(), &batch));
+
+  // compact database
+  std::string start_key = Key1(0);
+  std::string end_key = Key1(kNumKeys - 1);
+  rocksdb::Slice least(start_key.data(), start_key.size());
+  rocksdb::Slice greatest(end_key.data(), end_key.size());
+
+  // commenting out the line below causes the example to work correctly
+  db->CompactRange(&least, &greatest);
+
+  // count the keys
+  rocksdb::Iterator* iter = db->NewIterator(rocksdb::ReadOptions());
+  int num_keys = 0;
+  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
+    num_keys++;
+  }
+  delete iter;
+  ASSERT_EQ(kNumKeys, num_keys) << "Bad number of keys";
+
+  // close database
+  delete db;
+  DestroyDB(dbpath, rocksdb::Options());
+}
+
+}  // anonymous namespace
+
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}
diff --git a/util/murmurhash.cc b/util/murmurhash.cc
new file mode 100644 (file)
index 0000000..d9d8b70
--- /dev/null
@@ -0,0 +1,183 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+/*
+  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 (file)
index 0000000..9707e56
--- /dev/null
@@ -0,0 +1,33 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+/*
+  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.
+*/
+#pragma once
+#include <stdint.h>
+
+#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
diff --git a/util/mutexlock.h b/util/mutexlock.h
new file mode 100644 (file)
index 0000000..0f4e5c8
--- /dev/null
@@ -0,0 +1,78 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include "port/port.h"
+
+namespace rocksdb {
+
+// 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 rocksdb
diff --git a/util/options.cc b/util/options.cc
new file mode 100644 (file)
index 0000000..6e59711
--- /dev/null
@@ -0,0 +1,341 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/options.h"
+
+#include <limits>
+
+#include "rocksdb/cache.h"
+#include "rocksdb/compaction_filter.h"
+#include "rocksdb/comparator.h"
+#include "rocksdb/env.h"
+#include "rocksdb/filter_policy.h"
+#include "rocksdb/flush_block_policy.h"
+#include "rocksdb/merge_operator.h"
+#include "table/block_based_table_factory.h"
+
+namespace rocksdb {
+
+Options::Options()
+    : comparator(BytewiseComparator()),
+      merge_operator(nullptr),
+      compaction_filter(nullptr),
+      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),
+      min_write_buffer_number_to_merge(1),
+      max_open_files(1000),
+      block_cache(nullptr),
+      block_cache_compressed(nullptr),
+      block_size(4096),
+      block_restart_interval(16),
+      compression(kSnappyCompression),
+      filter_policy(nullptr),
+      prefix_extractor(nullptr),
+      whole_key_filtering(true),
+      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),
+      max_bytes_for_level_multiplier_additional(num_levels, 1),
+      expanded_compaction_factor(25),
+      source_compaction_factor(1),
+      max_grandparent_overlap_factor(10),
+      disableDataSync(false),
+      use_fsync(false),
+      db_stats_log_interval(1800),
+      db_log_dir(""),
+      wal_dir(""),
+      disable_seek_compaction(false),
+      delete_obsolete_files_period_micros(6 * 60 * 60 * 1000000UL),
+      max_background_compactions(1),
+      max_background_flushes(0),
+      max_log_file_size(0),
+      log_file_time_to_roll(0),
+      keep_log_file_num(1000),
+      soft_rate_limit(0.0),
+      hard_rate_limit(0.0),
+      rate_limit_delay_max_milliseconds(1000),
+      max_manifest_file_size(std::numeric_limits<uint64_t>::max()),
+      no_block_cache(false),
+      table_cache_numshardbits(4),
+      table_cache_remove_scan_count_limit(16),
+      arena_block_size(0),
+      disable_auto_compactions(false),
+      WAL_ttl_seconds(0),
+      WAL_size_limit_MB(0),
+      manifest_preallocation_size(4 * 1024 * 1024),
+      purge_redundant_kvs_while_flush(true),
+      allow_os_buffer(true),
+      allow_mmap_reads(false),
+      allow_mmap_writes(true),
+      is_fd_close_on_exec(true),
+      skip_log_error_on_recovery(false),
+      stats_dump_period_sec(3600),
+      block_size_deviation (10),
+      advise_random_on_open(true),
+      access_hint_on_compaction_start(NORMAL),
+      use_adaptive_mutex(false),
+      bytes_per_sync(0),
+      compaction_style(kCompactionStyleLevel),
+      filter_deletes(false),
+      max_sequential_skip_in_iterations(8),
+      memtable_factory(std::shared_ptr<SkipListFactory>(new SkipListFactory)),
+      table_factory(
+        std::shared_ptr<TableFactory>(new BlockBasedTableFactory())),
+      compaction_filter_factory(
+          std::shared_ptr<CompactionFilterFactory>(
+            new DefaultCompactionFilterFactory())),
+      inplace_update_support(false),
+      inplace_update_num_locks(10000) {
+  assert(memtable_factory.get() != nullptr);
+}
+
+static const char* const access_hints[] = {
+  "NONE", "NORMAL", "SEQUENTIAL", "WILLNEED"
+};
+
+void
+Options::Dump(Logger* log) const
+{
+    Log(log,"              Options.comparator: %s", comparator->Name());
+    Log(log,"          Options.merge_operator: %s",
+        merge_operator? merge_operator->Name() : "None");
+    Log(log,"       Options.compaction_filter: %s",
+        compaction_filter? compaction_filter->Name() : "None");
+    Log(log,"       Options.compaction_filter_factory: %s",
+        compaction_filter_factory->Name());
+    Log(log,"        Options.memtable_factory: %s",
+        memtable_factory->Name());
+    Log(log,"           Options.table_factory: %s", table_factory->Name());
+    Log(log,"         Options.error_if_exists: %d", error_if_exists);
+    Log(log,"       Options.create_if_missing: %d", create_if_missing);
+    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());
+    Log(log,"  Options.block_cache_compressed: %p",
+        block_cache_compressed.get());
+    if (block_cache) {
+      Log(log,"        Options.block_cache_size: %zd",
+          block_cache->GetCapacity());
+    }
+    if (block_cache_compressed) {
+      Log(log,"Options.block_cache_compressed_size: %zd",
+          block_cache_compressed->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 (unsigned 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.prefix_extractor: %s",
+        prefix_extractor == nullptr ? "nullptr" : prefix_extractor->Name());
+    Log(log,"   Options.whole_key_filtering: %d", whole_key_filtering);
+    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: %lu",
+        (unsigned long)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.allow_os_buffer: %d", allow_os_buffer);
+    Log(log,"      Options.allow_mmap_reads: %d", allow_mmap_reads);
+    Log(log,"     Options.allow_mmap_writes: %d", allow_mmap_writes);
+    Log(log,"       Options.min_write_buffer_number_to_merge: %d",
+        min_write_buffer_number_to_merge);
+    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: %lu",
+        (unsigned long)max_bytes_for_level_base);
+    Log(log,"         Options.max_bytes_for_level_multiplier: %d",
+        max_bytes_for_level_multiplier);
+    for (int i = 0; i < num_levels; i++) {
+      Log(log,"Options.max_bytes_for_level_multiplier_addtl[%d]: %d",
+          i, max_bytes_for_level_multiplier_additional[i]);
+    }
+    Log(log,"      Options.max_sequential_skip_in_iterations: %lu",
+        (unsigned long)max_sequential_skip_in_iterations);
+    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.wal_dir: %s",
+        wal_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.table_cache_remove_scan_count_limit: %d",
+        table_cache_remove_scan_count_limit);
+    Log(log,"                       Options.arena_block_size: %ld",
+        arena_block_size);
+    Log(log,"    Options.delete_obsolete_files_period_micros: %lu",
+        (unsigned long)delete_obsolete_files_period_micros);
+    Log(log,"             Options.max_background_compactions: %d",
+        max_background_compactions);
+    Log(log,"                 Options.max_background_flushes: %d",
+        max_background_flushes);
+    Log(log,"                      Options.soft_rate_limit: %.2f",
+        soft_rate_limit);
+    Log(log,"                      Options.hard_rate_limit: %.2f",
+        hard_rate_limit);
+    Log(log,"      Options.rate_limit_delay_max_milliseconds: %u",
+        rate_limit_delay_max_milliseconds);
+    Log(log,"               Options.disable_auto_compactions: %d",
+        disable_auto_compactions);
+    Log(log,"                        Options.WAL_ttl_seconds: %lu",
+        (unsigned long)WAL_ttl_seconds);
+    Log(log,"                      Options.WAL_size_limit_MB: %lu",
+        (unsigned long)WAL_size_limit_MB);
+    Log(log,"            Options.manifest_preallocation_size: %ld",
+        manifest_preallocation_size);
+    Log(log,"         Options.purge_redundant_kvs_while_flush: %d",
+        purge_redundant_kvs_while_flush);
+    Log(log,"                         Options.allow_os_buffer: %d",
+        allow_os_buffer);
+    Log(log,"                        Options.allow_mmap_reads: %d",
+        allow_mmap_reads);
+    Log(log,"                       Options.allow_mmap_writes: %d",
+        allow_mmap_writes);
+    Log(log,"                     Options.is_fd_close_on_exec: %d",
+        is_fd_close_on_exec);
+    Log(log,"              Options.skip_log_error_on_recovery: %d",
+        skip_log_error_on_recovery);
+    Log(log,"                   Options.stats_dump_period_sec: %u",
+        stats_dump_period_sec);
+    Log(log,"                    Options.block_size_deviation: %d",
+        block_size_deviation);
+    Log(log,"                   Options.advise_random_on_open: %d",
+        advise_random_on_open);
+    Log(log,"         Options.access_hint_on_compaction_start: %s",
+        access_hints[access_hint_on_compaction_start]);
+    Log(log,"                      Options.use_adaptive_mutex: %d",
+        use_adaptive_mutex);
+    Log(log,"                          Options.bytes_per_sync: %lu",
+        (unsigned long)bytes_per_sync);
+    Log(log,"                          Options.filter_deletes: %d",
+        filter_deletes);
+    Log(log,"                        Options.compaction_style: %d",
+        compaction_style);
+    Log(log," Options.compaction_options_universal.size_ratio: %u",
+        compaction_options_universal.size_ratio);
+    Log(log,"Options.compaction_options_universal.min_merge_width: %u",
+        compaction_options_universal.min_merge_width);
+    Log(log,"Options.compaction_options_universal.max_merge_width: %u",
+        compaction_options_universal.max_merge_width);
+    Log(log,"Options.compaction_options_universal."
+            "max_size_amplification_percent: %u",
+        compaction_options_universal.max_size_amplification_percent);
+    std::string collector_names;
+    for (auto collector : table_stats_collectors) {
+      collector_names.append(collector->Name());
+      collector_names.append("; ");
+    }
+    Log(log, "                  Options.table_stats_collectors: %s",
+        collector_names.c_str());
+    Log(log, "                  Options.inplace_update_support: %d",
+        inplace_update_support);
+    Log(log, "                Options.inplace_update_num_locks: %zd",
+        inplace_update_num_locks);
+    Log(log, "              Options.flush_block_policy_factory: %s",
+        flush_block_policy_factory ? flush_block_policy_factory->Name() : "");
+}   // Options::Dump
+
+//
+// The goal of this method is to create a configuration that
+// allows an application to write all files into L0 and
+// then do a single compaction to output all files into L1.
+Options*
+Options::PrepareForBulkLoad()
+{
+  // never slowdown ingest.
+  level0_file_num_compaction_trigger = (1<<30);
+  level0_slowdown_writes_trigger = (1<<30);
+  level0_stop_writes_trigger = (1<<30);
+
+  // no auto compactions please. The application should issue a
+  // manual compaction after all data is loaded into L0.
+  disable_auto_compactions = true;
+  disable_seek_compaction = true;
+  disableDataSync = true;
+
+  // A manual compaction run should pick all files in L0 in
+  // a single compaction run.
+  source_compaction_factor = (1<<30);
+
+  // It is better to have only 2 levels, otherwise a manual
+  // compaction would compact at every possible level, thereby
+  // increasing the total time needed for compactions.
+  num_levels = 2;
+
+  // Prevent a memtable flush to automatically promote files
+  // to L1. This is helpful so that all files that are
+  // input to the manual compaction are all at L0.
+  max_background_compactions = 2;
+
+  // The compaction would create large files in L1.
+  target_file_size_base = 256 * 1024 * 1024;
+  return this;
+}
+
+Options* Options::SetUpDefaultFlushBlockPolicyFactory() {
+  flush_block_policy_factory =
+    std::make_shared<FlushBlockBySizePolicyFactory>(
+        block_size, block_size_deviation);
+  return this;
+}
+
+}  // namespace rocksdb
diff --git a/util/perf_context.cc b/util/perf_context.cc
new file mode 100644 (file)
index 0000000..1e8ddfb
--- /dev/null
@@ -0,0 +1,30 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "util/perf_context_imp.h"
+
+namespace rocksdb {
+
+// by default, enable counts only
+PerfLevel perf_level = kEnableCount;
+
+void SetPerfLevel(PerfLevel level) { perf_level = level; }
+
+void PerfContext::Reset() {
+  user_key_comparison_count = 0;
+  block_cache_hit_count = 0;
+  block_read_count = 0;
+  block_read_byte = 0;
+  block_read_time = 0;
+  block_checksum_time = 0;
+  block_decompress_time = 0;
+  internal_key_skipped_count = 0;
+  internal_delete_skipped_count = 0;
+  wal_write_time = 0;
+}
+
+__thread PerfContext perf_context;
+
+}
diff --git a/util/perf_context_imp.h b/util/perf_context_imp.h
new file mode 100644 (file)
index 0000000..f7818e6
--- /dev/null
@@ -0,0 +1,34 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+#include "rocksdb/perf_context.h"
+#include "util/stop_watch.h"
+
+namespace rocksdb {
+
+extern enum PerfLevel perf_level;
+
+inline void StartPerfTimer(StopWatchNano* timer) {
+  if (perf_level >= PerfLevel::kEnableTime) {
+    timer->Start();
+  }
+}
+
+inline void BumpPerfCount(uint64_t* count, uint64_t delta = 1) {
+  if (perf_level >= PerfLevel::kEnableCount) {
+    *count += delta;
+  }
+}
+
+inline void BumpPerfTime(uint64_t* time,
+                         StopWatchNano* timer,
+                         bool reset = true) {
+  if (perf_level >= PerfLevel::kEnableTime) {
+    *time += timer->ElapsedNanos(reset);
+  }
+}
+
+}
diff --git a/util/posix_logger.h b/util/posix_logger.h
new file mode 100644 (file)
index 0000000..0a09bd1
--- /dev/null
@@ -0,0 +1,148 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <algorithm>
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef OS_LINUX
+#include <linux/falloc.h>
+#endif
+#include "rocksdb/env.h"
+#include <atomic>
+
+namespace rocksdb {
+
+const int kDebugLogChunkSize = 128 * 1024;
+
+class PosixLogger : public Logger {
+ private:
+  FILE* file_;
+  uint64_t (*gettid_)();  // Return the thread id for the current thread
+  std::atomic_size_t log_size_;
+  int fd_;
+  const static uint64_t flush_every_seconds_ = 5;
+  std::atomic_uint_fast64_t last_flush_micros_;
+  Env* env_;
+ public:
+  PosixLogger(FILE* f, uint64_t (*gettid)(), Env* env) :
+    file_(f), gettid_(gettid), log_size_(0), fd_(fileno(f)),
+    last_flush_micros_(0), env_(env) { }
+  virtual ~PosixLogger() {
+    fclose(file_);
+  }
+  virtual void Flush() {
+    fflush(file_);
+    last_flush_micros_ = env_->NowMicros();
+  }
+  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<int>(now_tv.tv_usec),
+                    static_cast<long long unsigned int>(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);
+      const size_t write_size = p - base;
+
+#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 log_size = log_size_;
+      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
+
+      size_t sz = fwrite(base, 1, write_size, file_);
+      assert(sz == write_size);
+      if (sz > 0) {
+        log_size_ += write_size;
+      }
+      uint64_t now_micros = static_cast<uint64_t>(now_tv.tv_sec) * 1000000 +
+        now_tv.tv_usec;
+      if (now_micros - last_flush_micros_ >= flush_every_seconds_ * 1000000) {
+        fflush(file_);
+        last_flush_micros_ = now_micros;
+      }
+      if (base != buffer) {
+        delete[] base;
+      }
+      break;
+    }
+  }
+  size_t GetLogFileSize() const {
+    return log_size_;
+  }
+};
+
+}  // namespace rocksdb
diff --git a/util/random.h b/util/random.h
new file mode 100644 (file)
index 0000000..e5b3315
--- /dev/null
@@ -0,0 +1,90 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include <random>
+#include <stdint.h>
+
+namespace rocksdb {
+
+// 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<uint32_t>((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));
+  }
+};
+
+// A simple 64bit random number generator based on std::mt19937_64
+class Random64 {
+ private:
+  std::mt19937_64 generator_;
+
+ public:
+  explicit Random64(uint64_t s) : generator_(s) { }
+
+  // Generates the next random number
+  uint64_t Next() { return generator_(); }
+
+  // Returns a uniformly distributed value in the range [0..n-1]
+  // REQUIRES: n > 0
+  uint64_t Uniform(uint64_t n) {
+    return std::uniform_int_distribution<uint64_t>(0, n - 1)(generator_);
+  }
+
+  // Randomly returns true ~"1/n" of the time, and false otherwise.
+  // REQUIRES: n > 0
+  bool OneIn(uint64_t n) { return Uniform(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.
+  uint64_t Skewed(int max_log) {
+    return Uniform(1 << Uniform(max_log + 1));
+  }
+};
+
+}  // namespace rocksdb
diff --git a/util/signal_test.cc b/util/signal_test.cc
new file mode 100644 (file)
index 0000000..bffc298
--- /dev/null
@@ -0,0 +1,32 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "util/stack_trace.h"
+#include <assert.h>
+
+void f0() {
+  char *p = nullptr;
+  *p = 10;  /* SIGSEGV here!! */
+}
+
+void f1() {
+  f0();
+}
+
+void f2() {
+  f1();
+}
+
+void f3() {
+  f2();
+}
+
+int main() {
+  rocksdb::InstallStackTraceHandler();
+
+  f3();
+
+  return 0;
+}
diff --git a/util/skiplistrep.cc b/util/skiplistrep.cc
new file mode 100644 (file)
index 0000000..955d754
--- /dev/null
@@ -0,0 +1,104 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "rocksdb/memtablerep.h"
+#include "db/memtable.h"
+#include "db/skiplist.h"
+
+namespace rocksdb {
+namespace {
+class SkipListRep : public MemTableRep {
+  SkipList<const char*, MemTableRep::KeyComparator&> skip_list_;
+public:
+  explicit SkipListRep(MemTableRep::KeyComparator& compare, Arena* arena)
+    : skip_list_(compare, arena) {
+}
+
+  // Insert key into the list.
+  // REQUIRES: nothing that compares equal to key is currently in the list.
+  virtual void Insert(const char* key) override {
+    skip_list_.Insert(key);
+  }
+
+  // Returns true iff an entry that compares equal to key is in the list.
+  virtual bool Contains(const char* key) const override {
+    return skip_list_.Contains(key);
+  }
+
+  virtual size_t ApproximateMemoryUsage() override {
+    // All memory is allocated through arena; nothing to report here
+    return 0;
+  }
+
+  virtual ~SkipListRep() override { }
+
+  // Iteration over the contents of a skip list
+  class Iterator : public MemTableRep::Iterator {
+    SkipList<const char*, MemTableRep::KeyComparator&>::Iterator iter_;
+   public:
+    // Initialize an iterator over the specified list.
+    // The returned iterator is not valid.
+    explicit Iterator(
+      const SkipList<const char*, MemTableRep::KeyComparator&>* list
+    ) : iter_(list) { }
+
+    virtual ~Iterator() override { }
+
+    // Returns true iff the iterator is positioned at a valid node.
+    virtual bool Valid() const override {
+      return iter_.Valid();
+    }
+
+    // Returns the key at the current position.
+    // REQUIRES: Valid()
+    virtual const char* key() const override {
+      return iter_.key();
+    }
+
+    // Advances to the next position.
+    // REQUIRES: Valid()
+    virtual void Next() override {
+      iter_.Next();
+    }
+
+    // Advances to the previous position.
+    // REQUIRES: Valid()
+    virtual void Prev() override {
+      iter_.Prev();
+    }
+
+    // Advance to the first entry with a key >= target
+    virtual void Seek(const char* target) override {
+      iter_.Seek(target);
+    }
+
+    // Position at the first entry in list.
+    // Final state of iterator is Valid() iff list is not empty.
+    virtual void SeekToFirst() override {
+      iter_.SeekToFirst();
+    }
+
+    // Position at the last entry in list.
+    // Final state of iterator is Valid() iff list is not empty.
+    virtual void SeekToLast() override {
+      iter_.SeekToLast();
+    }
+  };
+
+  // Unhide default implementations of GetIterator
+  using MemTableRep::GetIterator;
+
+  virtual std::shared_ptr<MemTableRep::Iterator> GetIterator() override {
+    return std::make_shared<SkipListRep::Iterator>(&skip_list_);
+  }
+};
+}
+
+std::shared_ptr<MemTableRep> SkipListFactory::CreateMemTableRep (
+  MemTableRep::KeyComparator& compare, Arena* arena) {
+    return std::shared_ptr<MemTableRep>(new SkipListRep(compare, arena));
+}
+
+} // namespace rocksdb
diff --git a/util/slice.cc b/util/slice.cc
new file mode 100644 (file)
index 0000000..55f561f
--- /dev/null
@@ -0,0 +1,73 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 "rocksdb/slice_transform.h"
+#include "rocksdb/slice.h"
+
+namespace rocksdb {
+
+namespace {
+
+class FixedPrefixTransform : public SliceTransform {
+ private:
+  size_t prefix_len_;
+
+ public:
+  explicit FixedPrefixTransform(size_t prefix_len) : prefix_len_(prefix_len) { }
+
+  virtual const char* Name() const {
+    return "rocksdb.FixedPrefix";
+  }
+
+  virtual Slice Transform(const Slice& src) const {
+    assert(InDomain(src));
+    return Slice(src.data(), prefix_len_);
+  }
+
+  virtual bool InDomain(const Slice& src) const {
+    return (src.size() >= prefix_len_);
+  }
+
+  virtual bool InRange(const Slice& dst) const {
+    return (dst.size() == prefix_len_);
+  }
+};
+
+class NoopTransform : public SliceTransform {
+ public:
+  explicit NoopTransform() { }
+
+  virtual const char* Name() const {
+    return "rocksdb.Noop";
+  }
+
+  virtual Slice Transform(const Slice& src) const {
+    return src;
+  }
+
+  virtual bool InDomain(const Slice& src) const {
+    return true;
+  }
+
+  virtual bool InRange(const Slice& dst) const {
+    return true;
+  }
+};
+
+}
+
+const SliceTransform* NewFixedPrefixTransform(size_t prefix_len) {
+  return new FixedPrefixTransform(prefix_len);
+}
+
+const SliceTransform* NewNoopTransform() {
+  return new NoopTransform;
+}
+
+}  // namespace rocksdb
diff --git a/util/stack_trace.h b/util/stack_trace.h
new file mode 100644 (file)
index 0000000..8883044
--- /dev/null
@@ -0,0 +1,14 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+namespace rocksdb {
+
+// Install a signal handler to print callstack on the following signals:
+// SIGILL SIGSEGV SIGBUS SIGABRT
+// Currently supports linux only. No-op otherwise.
+void InstallStackTraceHandler();
+
+}   // namespace rocksdb
diff --git a/util/statistics.cc b/util/statistics.cc
new file mode 100644 (file)
index 0000000..5f7a5ba
--- /dev/null
@@ -0,0 +1,60 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "rocksdb/statistics.h"
+#include <cstdio>
+
+namespace rocksdb {
+
+namespace {
+// a buffer size used for temp string buffers
+const int kBufferSize = 200;
+
+std::string HistogramToString (
+    Statistics* dbstats,
+    const Histograms& histogram_type,
+    const std::string& name) {
+
+  char buffer[kBufferSize];
+  HistogramData histogramData;
+  dbstats->histogramData(histogram_type, &histogramData);
+  snprintf(
+      buffer,
+      kBufferSize,
+      "%s statistics Percentiles :=> 50 : %f 95 : %f 99 : %f\n",
+      name.c_str(),
+      histogramData.median,
+      histogramData.percentile95,
+      histogramData.percentile99
+  );
+  return std::string(buffer);
+};
+
+std::string TickerToString (
+    Statistics* dbstats,
+    const Tickers& ticker,
+    const std::string& name) {
+
+  char buffer[kBufferSize];
+  snprintf(buffer, kBufferSize, "%s COUNT : %ld\n",
+            name.c_str(), dbstats->getTickerCount(ticker));
+  return std::string(buffer);
+};
+} // namespace
+
+std::string Statistics::ToString() {
+  std::string res;
+  res.reserve(20000);
+  for (const auto& t : TickersNameMap) {
+    res.append(TickerToString(this, t.first, t.second));
+  }
+  for (const auto& h : HistogramsNameMap) {
+    res.append(HistogramToString(this, h.first, h.second));
+  }
+  res.shrink_to_fit();
+  return res;
+}
+
+} // namespace rocksdb
diff --git a/util/stats_logger.h b/util/stats_logger.h
new file mode 100644 (file)
index 0000000..f0b4540
--- /dev/null
@@ -0,0 +1,26 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+
+namespace rocksdb {
+
+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() {}
+
+};
+
+}
diff --git a/util/status.cc b/util/status.cc
new file mode 100644 (file)
index 0000000..f7c40e9
--- /dev/null
@@ -0,0 +1,83 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <stdio.h>
+#include "port/port.h"
+#include "rocksdb/status.h"
+
+namespace rocksdb {
+
+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<char>(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;
+      case kMergeInProgress:
+        type = "Merge In Progress: ";
+        break;
+      default:
+        snprintf(tmp, sizeof(tmp), "Unknown code(%d): ",
+                 static_cast<int>(code()));
+        type = tmp;
+        break;
+    }
+    std::string result(type);
+    uint32_t length;
+    memcpy(&length, state_, sizeof(length));
+    result.append(state_ + 5, length);
+    return result;
+  }
+}
+
+}  // namespace rocksdb
diff --git a/util/stl_wrappers.h b/util/stl_wrappers.h
new file mode 100644 (file)
index 0000000..b42a584
--- /dev/null
@@ -0,0 +1,51 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+
+#include "util/murmurhash.h"
+#include "util/coding.h"
+
+#include "rocksdb/memtablerep.h"
+#include "rocksdb/slice.h"
+
+namespace rocksdb {
+namespace stl_wrappers {
+  class Base {
+   protected:
+    const MemTableRep::KeyComparator& compare_;
+    explicit Base(const MemTableRep::KeyComparator& compare)
+      : compare_(compare) { }
+  };
+
+  struct Compare : private Base {
+    explicit Compare(const MemTableRep::KeyComparator& compare)
+      : Base(compare) { }
+    inline bool operator()(const char* a, const char* b) const {
+      return compare_(a, b) < 0;
+    }
+  };
+
+  struct Hash {
+    inline size_t operator()(const char* buf) const {
+      Slice internal_key = GetLengthPrefixedSlice(buf);
+      Slice value =
+        GetLengthPrefixedSlice(internal_key.data() + internal_key.size());
+      unsigned int hval = MurmurHash(internal_key.data(), internal_key.size(),
+        0);
+      hval = MurmurHash(value.data(), value.size(), hval);
+      return hval;
+    }
+  };
+
+  struct KeyEqual : private Base {
+    explicit KeyEqual(const MemTableRep::KeyComparator& compare)
+      : Base(compare) { }
+    inline bool operator()(const char* a, const char* b) const {
+      return this->compare_(a, b) == 0;
+    }
+  };
+}
+}
diff --git a/util/stop_watch.h b/util/stop_watch.h
new file mode 100644 (file)
index 0000000..f251b6b
--- /dev/null
@@ -0,0 +1,70 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+#include "rocksdb/env.h"
+#include "rocksdb/statistics.h"
+
+namespace rocksdb {
+// Auto-scoped.
+// Records the statistic into the corresponding histogram.
+class StopWatch {
+ public:
+  StopWatch(
+    Env * const env,
+    std::shared_ptr<Statistics> statistics = nullptr,
+    const Histograms histogram_name = DB_GET) :
+      env_(env),
+      start_time_(env->NowMicros()),
+      statistics_(statistics),
+      histogram_name_(histogram_name) {}
+
+
+
+  uint64_t ElapsedMicros() {
+    return env_->NowMicros() - start_time_;
+  }
+
+  ~StopWatch() {
+    if (statistics_) {
+      statistics_->measureTime(histogram_name_, ElapsedMicros());
+    }
+  }
+
+ private:
+  Env* const env_;
+  const uint64_t start_time_;
+  std::shared_ptr<Statistics> statistics_;
+  const Histograms histogram_name_;
+
+};
+
+// a nano second precision stopwatch
+class StopWatchNano {
+ public:
+  StopWatchNano(Env* const env, bool auto_start = false)
+      : env_(env), start_(0) {
+    if (auto_start) {
+      Start();
+    }
+  }
+
+  void Start() { start_ = env_->NowNanos(); }
+
+  uint64_t ElapsedNanos(bool reset = false) {
+    auto now = env_->NowNanos();
+    auto elapsed = now - start_;
+    if (reset) {
+      start_ = now;
+    }
+    return elapsed;
+  }
+
+ private:
+  Env* const env_;
+  uint64_t start_;
+};
+
+} // namespace rocksdb
diff --git a/util/string_util.cc b/util/string_util.cc
new file mode 100644 (file)
index 0000000..33f84d9
--- /dev/null
@@ -0,0 +1,26 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace rocksdb {
+
+using namespace std;
+using std::string;
+using std::vector;
+using std::stringstream;
+
+vector<string> stringSplit(string arg, char delim) {
+  vector<string> splits;
+  stringstream ss(arg);
+  string item;
+  while(getline(ss, item, delim)) {
+    splits.push_back(item);
+  }
+  return splits;
+}
+}
diff --git a/util/string_util.h b/util/string_util.h
new file mode 100644 (file)
index 0000000..7dfd68a
--- /dev/null
@@ -0,0 +1,11 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#pragma once
+namespace rocksdb {
+
+extern std::vector<std::string> stringSplit(std::string arg, char delim);
+
+}
diff --git a/util/testharness.cc b/util/testharness.cc
new file mode 100644 (file)
index 0000000..85716cd
--- /dev/null
@@ -0,0 +1,82 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 <string>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+namespace rocksdb {
+namespace test {
+
+namespace {
+struct Test {
+  const char* base;
+  const char* name;
+  void (*func)();
+};
+std::vector<Test>* tests;
+}
+
+bool RegisterTest(const char* base, const char* name, void (*func)()) {
+  if (tests == nullptr) {
+    tests = new std::vector<Test>;
+  }
+  Test t;
+  t.base = base;
+  t.name = name;
+  t.func = func;
+  tests->push_back(t);
+  return true;
+}
+
+int RunAllTests() {
+  const char* matcher = getenv("ROCKSDB_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 rocksdb
diff --git a/util/testharness.h b/util/testharness.h
new file mode 100644 (file)
index 0000000..936ee8b
--- /dev/null
@@ -0,0 +1,140 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sstream>
+#include "rocksdb/env.h"
+#include "rocksdb/slice.h"
+#include "util/random.h"
+
+namespace rocksdb {
+namespace test {
+
+// Run some of the tests registered by the TEST() macro.  If the
+// environment variable "ROCKSDB_TESTS" is not set, runs all tests.
+// Otherwise, runs only the tests whose name contains the value of
+// "ROCKSDB_TESTS" as a substring.  E.g., suppose the tests are:
+//    TEST(Foo, Hello) { ... }
+//    TEST(Foo, World) { ... }
+// ROCKSDB_TESTS=Hello will run the first test
+// ROCKSDB_TESTS=o     will run both tests
+// ROCKSDB_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 <class X, class Y>                           \
+  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 <class V>
+  Tester& operator<<(const V& value) {
+    if (!ok_) {
+      ss_ << " " << value;
+    }
+    return *this;
+  }
+};
+
+#define ASSERT_TRUE(c) ::rocksdb::test::Tester(__FILE__, __LINE__).Is((c), #c)
+#define ASSERT_OK(s) ::rocksdb::test::Tester(__FILE__, __LINE__).IsOk((s))
+#define ASSERT_EQ(a,b) ::rocksdb::test::Tester(__FILE__, __LINE__).IsEq((a),(b))
+#define ASSERT_NE(a,b) ::rocksdb::test::Tester(__FILE__, __LINE__).IsNe((a),(b))
+#define ASSERT_GE(a,b) ::rocksdb::test::Tester(__FILE__, __LINE__).IsGe((a),(b))
+#define ASSERT_GT(a,b) ::rocksdb::test::Tester(__FILE__, __LINE__).IsGt((a),(b))
+#define ASSERT_LE(a,b) ::rocksdb::test::Tester(__FILE__, __LINE__).IsLe((a),(b))
+#define ASSERT_LT(a,b) ::rocksdb::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) =                                     \
+  ::rocksdb::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 rocksdb
diff --git a/util/testutil.cc b/util/testutil.cc
new file mode 100644 (file)
index 0000000..13e781e
--- /dev/null
@@ -0,0 +1,56 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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 rocksdb {
+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<char>(' ' + 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<int>(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 rocksdb
diff --git a/util/testutil.h b/util/testutil.h
new file mode 100644 (file)
index 0000000..c73210f
--- /dev/null
@@ -0,0 +1,55 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+// 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.
+
+#pragma once
+#include "rocksdb/env.h"
+#include "rocksdb/slice.h"
+#include "util/random.h"
+
+namespace rocksdb {
+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<WritableFile>* result,
+                                 const EnvOptions& soptions) {
+    result->reset();
+    if (writable_file_error_) {
+      ++num_writable_file_errors_;
+      return Status::IOError(fname, "fake error");
+    }
+    return target()->NewWritableFile(fname, result, soptions);
+  }
+};
+
+}  // namespace test
+}  // namespace rocksdb
diff --git a/util/transformrep.cc b/util/transformrep.cc
new file mode 100644 (file)
index 0000000..4c7df13
--- /dev/null
@@ -0,0 +1,422 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include <unordered_map>
+#include <set>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+
+#include "rocksdb/memtablerep.h"
+#include "rocksdb/arena.h"
+#include "rocksdb/slice.h"
+#include "rocksdb/slice_transform.h"
+#include "port/port.h"
+#include "util/mutexlock.h"
+#include "util/murmurhash.h"
+#include "util/stl_wrappers.h"
+
+namespace std {
+template <>
+struct hash<rocksdb::Slice> {
+  size_t operator()(const rocksdb::Slice& slice) const {
+    return MurmurHash(slice.data(), slice.size(), 0);
+  }
+};
+}
+
+namespace rocksdb {
+namespace {
+
+using namespace stl_wrappers;
+
+class TransformRep : public MemTableRep {
+ public:
+  TransformRep(const KeyComparator& compare, Arena* arena,
+    const SliceTransform* transform, size_t bucket_size,
+    size_t num_locks);
+
+  virtual void Insert(const char* key) override;
+
+  virtual bool Contains(const char* key) const override;
+
+  virtual size_t ApproximateMemoryUsage() override;
+
+  virtual ~TransformRep() { }
+
+  virtual std::shared_ptr<MemTableRep::Iterator> GetIterator() override;
+
+  virtual std::shared_ptr<MemTableRep::Iterator> GetIterator(
+    const Slice& slice) override;
+
+  virtual std::shared_ptr<MemTableRep::Iterator> GetDynamicPrefixIterator()
+      override {
+    return std::make_shared<DynamicPrefixIterator>(*this);
+  }
+
+  std::shared_ptr<MemTableRep::Iterator> GetTransformIterator(
+    const Slice& transformed);
+
+ private:
+  friend class DynamicPrefixIterator;
+  typedef std::set<const char*, Compare> Bucket;
+  typedef std::unordered_map<Slice, std::shared_ptr<Bucket>> BucketMap;
+
+  // Maps slices (which are transformed user keys) to buckets of keys sharing
+  // the same transform.
+  BucketMap buckets_;
+
+  // rwlock_ protects access to the buckets_ data structure itself. Each bucket
+  // has its own read-write lock as well.
+  mutable port::RWMutex rwlock_;
+
+  // Keep track of approximately how much memory is being used.
+  size_t memory_usage_ = 0;
+
+  // The user-supplied transform whose domain is the user keys.
+  const SliceTransform* transform_;
+
+  // Get a bucket from buckets_. If the bucket hasn't been initialized yet,
+  // initialize it before returning. Must be externally synchronized.
+  std::shared_ptr<Bucket>& GetBucket(const Slice& transformed);
+
+  port::RWMutex* GetLock(const Slice& transformed) const;
+
+  mutable std::vector<port::RWMutex> locks_;
+
+  const KeyComparator& compare_;
+
+  class Iterator : public MemTableRep::Iterator {
+   public:
+    explicit Iterator(std::shared_ptr<Bucket> items);
+
+    virtual ~Iterator() { };
+
+    // Returns true iff the iterator is positioned at a valid node.
+    virtual bool Valid() const;
+
+    // Returns the key at the current position.
+    // REQUIRES: Valid()
+    virtual const char* key() const;
+
+    // Advances to the next position.
+    // REQUIRES: Valid()
+    virtual void Next();
+
+    // Advances to the previous position.
+    // REQUIRES: Valid()
+    virtual void Prev();
+
+    // Advance to the first entry with a key >= target
+    virtual void Seek(const char* target);
+
+    // Position at the first entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToFirst();
+
+    // Position at the last entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToLast();
+   private:
+    std::shared_ptr<Bucket> items_;
+    Bucket::const_iterator cit_;
+  };
+
+  class EmptyIterator : public MemTableRep::Iterator {
+    // This is used when there wasn't a bucket. It is cheaper than
+    // instantiating an empty bucket over which to iterate.
+   public:
+    virtual bool Valid() const {
+      return false;
+    }
+    virtual const char* key() const {
+      assert(false);
+      return nullptr;
+    }
+    virtual void Next() { }
+    virtual void Prev() { }
+    virtual void Seek(const char* target) { }
+    virtual void SeekToFirst() { }
+    virtual void SeekToLast() { }
+    static std::shared_ptr<EmptyIterator> GetInstance();
+   private:
+    static std::shared_ptr<EmptyIterator> instance;
+    EmptyIterator() { }
+  };
+
+  class TransformIterator : public Iterator {
+   public:
+    explicit TransformIterator(std::shared_ptr<Bucket> items,
+      port::RWMutex* rwlock);
+    virtual ~TransformIterator() { }
+   private:
+    const ReadLock l_;
+  };
+
+
+  class DynamicPrefixIterator : public MemTableRep::Iterator {
+   private:
+    // the underlying memtable rep
+    const TransformRep& memtable_rep_;
+    // the result of a prefix seek
+    std::unique_ptr<MemTableRep::Iterator> bucket_iterator_;
+
+   public:
+    explicit DynamicPrefixIterator(const TransformRep& memtable_rep)
+    : memtable_rep_(memtable_rep) {}
+
+    virtual ~DynamicPrefixIterator() { };
+
+    // Returns true iff the iterator is positioned at a valid node.
+    virtual bool Valid() const {
+      return bucket_iterator_ && bucket_iterator_->Valid();
+    }
+
+    // Returns the key at the current position.
+    // REQUIRES: Valid()
+    virtual const char* key() const {
+      assert(Valid());
+      return bucket_iterator_->key();
+    }
+
+    // Advances to the next position.
+    // REQUIRES: Valid()
+    virtual void Next() {
+      assert(Valid());
+      bucket_iterator_->Next();
+    }
+
+    // Advances to the previous position.
+    // REQUIRES: Valid()
+    virtual void Prev() {
+      assert(Valid());
+      bucket_iterator_->Prev();
+    }
+
+    // Advance to the first entry with a key >= target within the
+    // same bucket as target
+    virtual void Seek(const char* target) {
+      Slice prefix = memtable_rep_.transform_->Transform(
+        memtable_rep_.UserKey(target));
+
+      ReadLock l(&memtable_rep_.rwlock_);
+      auto bucket = memtable_rep_.buckets_.find(prefix);
+      if (bucket == memtable_rep_.buckets_.end()) {
+        bucket_iterator_.reset(nullptr);
+      } else {
+        bucket_iterator_.reset(
+          new TransformIterator(bucket->second, memtable_rep_.GetLock(prefix)));
+        bucket_iterator_->Seek(target);
+      }
+    }
+
+    // Position at the first entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToFirst() {
+      // Prefix iterator does not support total order.
+      // We simply set the iterator to invalid state
+      bucket_iterator_.reset(nullptr);
+    }
+
+    // Position at the last entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToLast() {
+      // Prefix iterator does not support total order.
+      // We simply set the iterator to invalid state
+      bucket_iterator_.reset(nullptr);
+    }
+  };
+};
+
+class PrefixHashRep : public TransformRep {
+ public:
+  PrefixHashRep(const KeyComparator& compare, Arena* arena,
+    const SliceTransform* transform, size_t bucket_size,
+    size_t num_locks)
+  : TransformRep(compare, arena, transform,
+    bucket_size, num_locks) { }
+
+  virtual std::shared_ptr<MemTableRep::Iterator> GetPrefixIterator(
+    const Slice& prefix) override;
+};
+
+std::shared_ptr<TransformRep::Bucket>& TransformRep::GetBucket(
+  const Slice& transformed) {
+  WriteLock l(&rwlock_);
+  auto& bucket = buckets_[transformed];
+  if (!bucket) {
+    bucket.reset(
+      new decltype(buckets_)::mapped_type::element_type(Compare(compare_)));
+    // To memory_usage_ we add the size of the std::set and the size of the
+    // std::pair (decltype(buckets_)::value_type) which includes the
+    // Slice and the std::shared_ptr
+    memory_usage_ += sizeof(*bucket) +
+                     sizeof(decltype(buckets_)::value_type);
+  }
+  return bucket;
+}
+
+port::RWMutex* TransformRep::GetLock(const Slice& transformed) const {
+  return &locks_[std::hash<Slice>()(transformed) % locks_.size()];
+}
+
+TransformRep::TransformRep(const KeyComparator& compare, Arena* arena,
+  const SliceTransform* transform, size_t bucket_size,
+  size_t num_locks)
+  : buckets_(bucket_size),
+    transform_(transform),
+    locks_(num_locks),
+    compare_(compare) { }
+
+void TransformRep::Insert(const char* key) {
+  assert(!Contains(key));
+  auto transformed = transform_->Transform(UserKey(key));
+  auto& bucket = GetBucket(transformed);
+  WriteLock bl(GetLock(transformed));
+  bucket->insert(key);
+  memory_usage_ += sizeof(key);
+}
+
+bool TransformRep::Contains(const char* key) const {
+  ReadLock l(&rwlock_);
+  auto transformed = transform_->Transform(UserKey(key));
+  auto bucket = buckets_.find(transformed);
+  if (bucket == buckets_.end()) {
+    return false;
+  }
+  ReadLock bl(GetLock(transformed));
+  return bucket->second->count(key) != 0;
+}
+
+size_t TransformRep::ApproximateMemoryUsage() {
+  return memory_usage_;
+}
+
+std::shared_ptr<TransformRep::EmptyIterator>
+  TransformRep::EmptyIterator::GetInstance() {
+  if (!instance) {
+    instance.reset(new TransformRep::EmptyIterator);
+  }
+  return instance;
+}
+
+TransformRep::Iterator::Iterator(std::shared_ptr<Bucket> items)
+  : items_(items),
+    cit_(items_->begin()) { }
+
+// Returns true iff the iterator is positioned at a valid node.
+bool TransformRep::Iterator::Valid() const {
+  return cit_ != items_->end();
+}
+
+// Returns the key at the current position.
+// REQUIRES: Valid()
+const char* TransformRep::Iterator::key() const {
+  assert(Valid());
+  return *cit_;
+}
+
+// Advances to the next position.
+// REQUIRES: Valid()
+void TransformRep::Iterator::Next() {
+  assert(Valid());
+  if (cit_ == items_->end()) {
+    return;
+  }
+  ++cit_;
+}
+
+// Advances to the previous position.
+// REQUIRES: Valid()
+void TransformRep::Iterator::Prev() {
+  assert(Valid());
+  if (cit_ == items_->begin()) {
+    // If you try to go back from the first element, the iterator should be
+    // invalidated. So we set it to past-the-end. This means that you can
+    // treat the container circularly.
+    cit_ = items_->end();
+  } else {
+    --cit_;
+  }
+}
+
+// Advance to the first entry with a key >= target
+void TransformRep::Iterator::Seek(const char* target) {
+  cit_ = items_->lower_bound(target);
+}
+
+// Position at the first entry in collection.
+// Final state of iterator is Valid() iff collection is not empty.
+void TransformRep::Iterator::SeekToFirst() {
+  cit_ = items_->begin();
+}
+
+void TransformRep::Iterator::SeekToLast() {
+  cit_ = items_->end();
+  if (items_->size() != 0) {
+    --cit_;
+  }
+}
+
+TransformRep::TransformIterator::TransformIterator(
+  std::shared_ptr<Bucket> items, port::RWMutex* rwlock)
+  : Iterator(items), l_(rwlock) { }
+
+std::shared_ptr<MemTableRep::Iterator> TransformRep::GetIterator() {
+  auto items = std::make_shared<Bucket>(Compare(compare_));
+  // Hold read locks on all locks
+  ReadLock l(&rwlock_);
+  std::for_each(locks_.begin(), locks_.end(), [] (port::RWMutex& lock) {
+    lock.ReadLock();
+  });
+  for (auto& bucket : buckets_) {
+    items->insert(bucket.second->begin(), bucket.second->end());
+  }
+  std::for_each(locks_.begin(), locks_.end(), [] (port::RWMutex& lock) {
+    lock.Unlock();
+  });
+  return std::make_shared<Iterator>(std::move(items));
+}
+
+std::shared_ptr<MemTableRep::Iterator> TransformRep::GetTransformIterator(
+  const Slice& transformed) {
+  ReadLock l(&rwlock_);
+  auto bucket = buckets_.find(transformed);
+  if (bucket == buckets_.end()) {
+    return EmptyIterator::GetInstance();
+  }
+  return std::make_shared<TransformIterator>(bucket->second,
+    GetLock(transformed));
+}
+
+std::shared_ptr<MemTableRep::Iterator> TransformRep::GetIterator(
+  const Slice& slice) {
+  auto transformed = transform_->Transform(slice);
+  return GetTransformIterator(transformed);
+}
+
+std::shared_ptr<TransformRep::EmptyIterator>
+  TransformRep::EmptyIterator::instance;
+
+} // anon namespace
+
+std::shared_ptr<MemTableRep> TransformRepFactory::CreateMemTableRep(
+  MemTableRep::KeyComparator& compare, Arena* arena) {
+  return std::make_shared<TransformRep>(compare, arena, transform_,
+    bucket_count_, num_locks_);
+}
+
+std::shared_ptr<MemTableRep> PrefixHashRepFactory::CreateMemTableRep(
+  MemTableRep::KeyComparator& compare, Arena* arena) {
+  return std::make_shared<PrefixHashRep>(compare, arena, transform_,
+    bucket_count_, num_locks_);
+}
+
+std::shared_ptr<MemTableRep::Iterator> PrefixHashRep::GetPrefixIterator(
+  const Slice& prefix) {
+  return TransformRep::GetTransformIterator(prefix);
+}
+
+} // namespace rocksdb
diff --git a/util/vectorrep.cc b/util/vectorrep.cc
new file mode 100644 (file)
index 0000000..8d3ccc9
--- /dev/null
@@ -0,0 +1,249 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#include "rocksdb/memtablerep.h"
+
+#include <unordered_set>
+#include <set>
+#include <memory>
+#include <algorithm>
+#include <type_traits>
+
+#include "rocksdb/arena.h"
+#include "port/port.h"
+#include "util/mutexlock.h"
+#include "util/stl_wrappers.h"
+
+namespace rocksdb {
+namespace {
+
+using namespace stl_wrappers;
+
+class VectorRep : public MemTableRep {
+ public:
+  VectorRep(const KeyComparator& compare, Arena* arena, size_t count);
+
+  // Insert key into the collection. (The caller will pack key and value into a
+  // single buffer and pass that in as the parameter to Insert)
+  // REQUIRES: nothing that compares equal to key is currently in the
+  // collection.
+  virtual void Insert(const char* key) override;
+
+  // Returns true iff an entry that compares equal to key is in the collection.
+  virtual bool Contains(const char* key) const override;
+
+  virtual void MarkReadOnly() override;
+
+  virtual size_t ApproximateMemoryUsage() override;
+
+  virtual ~VectorRep() override { }
+
+  class Iterator : public MemTableRep::Iterator {
+    class VectorRep* vrep_;
+    std::shared_ptr<std::vector<const char*>> bucket_;
+    typename std::vector<const char*>::const_iterator mutable cit_;
+    const KeyComparator& compare_;
+    bool mutable sorted_;
+    void DoSort() const;
+   public:
+    explicit Iterator(class VectorRep* vrep,
+      std::shared_ptr<std::vector<const char*>> bucket,
+      const KeyComparator& compare);
+
+    // Initialize an iterator over the specified collection.
+    // The returned iterator is not valid.
+    // explicit Iterator(const MemTableRep* collection);
+    virtual ~Iterator() override { };
+
+    // Returns true iff the iterator is positioned at a valid node.
+    virtual bool Valid() const override;
+
+    // Returns the key at the current position.
+    // REQUIRES: Valid()
+    virtual const char* key() const override;
+
+    // Advances to the next position.
+    // REQUIRES: Valid()
+    virtual void Next() override;
+
+    // Advances to the previous position.
+    // REQUIRES: Valid()
+    virtual void Prev() override;
+
+    // Advance to the first entry with a key >= target
+    virtual void Seek(const char* target) override;
+
+    // Position at the first entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToFirst() override;
+
+    // Position at the last entry in collection.
+    // Final state of iterator is Valid() iff collection is not empty.
+    virtual void SeekToLast() override;
+  };
+
+  // Unhide default implementations of GetIterator()
+  using MemTableRep::GetIterator;
+
+  // Return an iterator over the keys in this representation.
+  virtual std::shared_ptr<MemTableRep::Iterator> GetIterator() override;
+
+ private:
+  friend class Iterator;
+  typedef std::vector<const char*> Bucket;
+  std::shared_ptr<Bucket> bucket_;
+  mutable port::RWMutex rwlock_;
+  bool immutable_;
+  bool sorted_;
+  const KeyComparator& compare_;
+};
+
+void VectorRep::Insert(const char* key) {
+  assert(!Contains(key));
+  WriteLock l(&rwlock_);
+  assert(!immutable_);
+  bucket_->push_back(key);
+}
+
+// Returns true iff an entry that compares equal to key is in the collection.
+bool VectorRep::Contains(const char* key) const {
+  ReadLock l(&rwlock_);
+  return std::find(bucket_->begin(), bucket_->end(), key) != bucket_->end();
+}
+
+void VectorRep::MarkReadOnly() {
+  WriteLock l(&rwlock_);
+  immutable_ = true;
+}
+
+size_t VectorRep::ApproximateMemoryUsage() {
+  return
+    sizeof(bucket_) + sizeof(*bucket_) +
+    bucket_->size() *
+    sizeof(
+      std::remove_reference<decltype(*bucket_)>::type::value_type
+    );
+}
+
+VectorRep::VectorRep(const KeyComparator& compare, Arena* arena, size_t count)
+  : bucket_(new Bucket()),
+    immutable_(false),
+    sorted_(false),
+    compare_(compare) { bucket_.get()->reserve(count); }
+
+VectorRep::Iterator::Iterator(class VectorRep* vrep,
+                   std::shared_ptr<std::vector<const char*>> bucket,
+                   const KeyComparator& compare)
+: vrep_(vrep),
+  bucket_(bucket),
+  cit_(bucket_->end()),
+  compare_(compare),
+  sorted_(false) { }
+
+void VectorRep::Iterator::DoSort() const {
+  // vrep is non-null means that we are working on an immutable memtable
+  if (!sorted_ && vrep_ != nullptr) {
+    WriteLock l(&vrep_->rwlock_);
+    if (!vrep_->sorted_) {
+      std::sort(bucket_->begin(), bucket_->end(), Compare(compare_));
+      cit_ = bucket_->begin();
+      vrep_->sorted_ = true;
+    }
+    sorted_ = true;
+  }
+  if (!sorted_) {
+    std::sort(bucket_->begin(), bucket_->end(), Compare(compare_));
+    cit_ = bucket_->begin();
+    sorted_ = true;
+  }
+  assert(sorted_);
+  assert(vrep_ == nullptr || vrep_->sorted_);
+}
+
+// Returns true iff the iterator is positioned at a valid node.
+bool VectorRep::Iterator::Valid() const {
+  DoSort();
+  return cit_ != bucket_->end();
+}
+
+// Returns the key at the current position.
+// REQUIRES: Valid()
+const char* VectorRep::Iterator::key() const {
+  assert(Valid());
+  return *cit_;
+}
+
+// Advances to the next position.
+// REQUIRES: Valid()
+void VectorRep::Iterator::Next() {
+  assert(Valid());
+  if (cit_ == bucket_->end()) {
+    return;
+  }
+  ++cit_;
+}
+
+// Advances to the previous position.
+// REQUIRES: Valid()
+void VectorRep::Iterator::Prev() {
+  assert(Valid());
+  if (cit_ == bucket_->begin()) {
+    // If you try to go back from the first element, the iterator should be
+    // invalidated. So we set it to past-the-end. This means that you can
+    // treat the container circularly.
+    cit_ = bucket_->end();
+  } else {
+    --cit_;
+  }
+}
+
+// Advance to the first entry with a key >= target
+void VectorRep::Iterator::Seek(const char* target) {
+  DoSort();
+  // Do binary search to find first value not less than the target
+  cit_ = std::equal_range(bucket_->begin(),
+                          bucket_->end(),
+                          target,
+                          [this] (const char* a, const char* b) {
+                            return compare_(a, b) < 0;
+                          }).first;
+}
+
+// Position at the first entry in collection.
+// Final state of iterator is Valid() iff collection is not empty.
+void VectorRep::Iterator::SeekToFirst() {
+  DoSort();
+  cit_ = bucket_->begin();
+}
+
+// Position at the last entry in collection.
+// Final state of iterator is Valid() iff collection is not empty.
+void VectorRep::Iterator::SeekToLast() {
+  DoSort();
+  cit_ = bucket_->end();
+  if (bucket_->size() != 0) {
+    --cit_;
+  }
+}
+
+std::shared_ptr<MemTableRep::Iterator> VectorRep::GetIterator() {
+  ReadLock l(&rwlock_);
+  // Do not sort here. The sorting would be done the first time
+  // a Seek is performed on the iterator.
+  if (immutable_) {
+    return std::make_shared<Iterator>(this, bucket_, compare_);
+  } else {
+    std::shared_ptr<Bucket> tmp;
+    tmp.reset(new Bucket(*bucket_)); // make a copy
+    return std::make_shared<Iterator>(nullptr, tmp, compare_);
+  }
+}
+} // anon namespace
+
+std::shared_ptr<MemTableRep> VectorRepFactory::CreateMemTableRep(
+  MemTableRep::KeyComparator& compare, Arena* arena) {
+  return std::make_shared<VectorRep>(compare, arena, count_);
+}
+} // namespace rocksdb
diff --git a/utilities/.DS_Store b/utilities/.DS_Store
new file mode 100644 (file)
index 0000000..daeccc0
Binary files /dev/null and b/utilities/.DS_Store differ
diff --git a/utilities/merge_operators.h b/utilities/merge_operators.h
new file mode 100644 (file)
index 0000000..fdf0664
--- /dev/null
@@ -0,0 +1,45 @@
+//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under the BSD-style license found in the
+//  LICENSE file in the root directory of this source tree. An additional grant
+//  of patent rights can be found in the PATENTS file in the same directory.
+//
+#ifndef MERGE_OPERATORS_H
+#define MERGE_OPERATORS_H
+
+#include <memory>
+#include <stdio.h>
+
+#include "rocksdb/merge_operator.h"
+
+namespace rocksdb {
+
+class MergeOperators {
+ public:
+  static std::shared_ptr<MergeOperator> CreatePutOperator();
+  static std::shared_ptr<MergeOperator> CreateUInt64AddOperator();
+  static std::shared_ptr<MergeOperator> CreateStringAppendOperator();
+  static std::shared_ptr<MergeOperator> CreateStringAppendTESTOperator();
+
+  // Will return a different merge operator depending on the string.
+  // TODO: Hook the "name" up to the actual Name() of the MergeOperators?
+  static std::shared_ptr<MergeOperator> CreateFromStringId(
+      const std::string& name) {
+    if (name == "put") {
+      return CreatePutOperator();
+    } else if ( name == "uint64add") {
+      return CreateUInt64AddOperator();
+    } else if (name == "stringappend") {
+      return CreateStringAppendOperator();
+    } else if (name == "stringappendtest") {
+      return CreateStringAppendTESTOperator();
+    } else {
+      // Empty or unknown, just return nullptr
+      return nullptr;
+    }
+  }
+
+};
+
+} // namespace rocksdb
+
+#endif
diff --git a/utilities/merge_operators/.DS_Store b/utilities/merge_operators/.DS_Store
new file mode 100644 (file)
index 0000000..5008ddf
Binary files /dev/null and b/utilities/merge_operators/.DS_Store differ
diff --git a/utilities/merge_operators/put.cc b/utilities/merge_operators/put.cc
new file mode 100644 (file)
index 0000000..e77449d
--- /dev/null
@@ -0,0 +1,54 @@
+#include <memory>
+#include "rocksdb/slice.h"
+#include "rocksdb/merge_operator.h"
+#include "utilities/merge_operators.h"
+
+using namespace rocksdb;
+
+namespace { // anonymous namespace
+
+// A merge operator that mimics Put semantics
+// Since this merge-operator will not be used in production,
+// it is implemented as a non-associative merge operator to illustrate the
+// new interface and for testing purposes. (That is, we inherit from
+// the MergeOperator class rather than the AssociativeMergeOperator
+// which would be simpler in this case).
+//
+// From the client-perspective, semantics are the same.
+class PutOperator : public MergeOperator {
+ public:
+  virtual bool FullMerge(const Slice& key,
+                         const Slice* existing_value,
+                         const std::deque<std::string>& operand_sequence,
+                         std::string* new_value,
+                         Logger* logger) const override {
+    // Put basically only looks at the current/latest value
+    assert(!operand_sequence.empty());
+    assert(new_value != nullptr);
+    new_value->assign(operand_sequence.back());
+    return true;
+  }
+
+  virtual bool PartialMerge(const Slice& key,
+                            const Slice& left_operand,
+                            const Slice& right_operand,
+                            std::string* new_value,
+                            Logger* logger) const override {
+    new_value->assign(right_operand.data(), right_operand.size());
+    return true;
+  }
+
+  virtual const char* Name() const override {
+    return "PutOperator";
+  }
+};
+
+} // end of anonymous namespace
+
+namespace rocksdb {
+
+std::shared_ptr<MergeOperator> MergeOperators::CreatePutOperator() {
+  return std::make_shared<PutOperator>();
+}
+
+}
diff --git a/utilities/merge_operators/string_append/stringappend.cc b/utilities/merge_operators/string_append/stringappend.cc
new file mode 100644 (file)
index 0000000..38cd22e
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * A MergeOperator for rocksdb that implements string append.
+ * @author Deon Nicholas (dnicholas@fb.com)
+ * Copyright 2013 Facebook
+ */
+
+#include "stringappend.h"
+
+#include <memory>
+#include <assert.h>
+
+#include "rocksdb/slice.h"
+#include "rocksdb/merge_operator.h"
+#include "utilities/merge_operators.h"
+
+namespace rocksdb {
+
+// Constructor: also specify the delimiter character.
+StringAppendOperator::StringAppendOperator(char delim_char)
+    : delim_(delim_char) {
+}
+
+// Implementation for the merge operation (concatenates two strings)
+bool StringAppendOperator::Merge(const Slice& key,
+                                 const Slice* existing_value,
+                                 const Slice& value,
+                                 std::string* new_value,
+                                 Logger* logger) const {
+
+  // Clear the *new_value for writing.
+  assert(new_value);
+  new_value->clear();
+
+  if (!existing_value) {
+    // No existing_value. Set *new_value = value
+    new_value->assign(value.data(),value.size());
+  } else {
+    // Generic append (existing_value != null).
+    // Reserve *new_value to correct size, and apply concatenation.
+    new_value->reserve(existing_value->size() + 1 + value.size());
+    new_value->assign(existing_value->data(),existing_value->size());
+    new_value->append(1,delim_);
+    new_value->append(value.data(), value.size());
+  }
+
+  return true;
+}
+
+const char* StringAppendOperator::Name() const  {
+  return "StringAppendOperator";
+}
+
+std::shared_ptr<MergeOperator> MergeOperators::CreateStringAppendOperator() {
+  return std::make_shared<StringAppendOperator>(',');
+}
+
+} // namespace rocksdb
+
+
+
diff --git a/utilities/merge_operators/string_append/stringappend.h b/utilities/merge_operators/string_append/stringappend.h
new file mode 100644 (file)
index 0000000..ca5b97e
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * A MergeOperator for rocksdb that implements string append.
+ * @author Deon Nicholas (dnicholas@fb.com)
+ * Copyright 2013 Facebook
+ */
+
+#pragma once
+#include "rocksdb/merge_operator.h"
+#include "rocksdb/slice.h"
+
+namespace rocksdb {
+
+class StringAppendOperator : public AssociativeMergeOperator {
+ public:
+  StringAppendOperator(char delim_char);    /// Constructor: specify delimiter
+
+  virtual bool Merge(const Slice& key,
+                     const Slice* existing_value,
+                     const Slice& value,
+                     std::string* new_value,
+                     Logger* logger) const override;
+
+  virtual const char* Name() const override;
+
+ private:
+  char delim_;         // The delimiter is inserted between elements
+
+};
+
+} // namespace rocksdb
+
diff --git a/utilities/merge_operators/string_append/stringappend2.cc b/utilities/merge_operators/string_append/stringappend2.cc
new file mode 100644 (file)
index 0000000..e153a38
--- /dev/null
@@ -0,0 +1,104 @@
+/**
+ * @author Deon Nicholas (dnicholas@fb.com)
+ * Copyright 2013 Facebook
+ */
+
+#include "stringappend2.h"
+
+#include <memory>
+#include <assert.h>
+
+#include "rocksdb/slice.h"
+#include "rocksdb/merge_operator.h"
+#include "utilities/merge_operators.h"
+
+namespace rocksdb {
+
+// Constructor: also specify the delimiter character.
+StringAppendTESTOperator::StringAppendTESTOperator(char delim_char)
+    : delim_(delim_char) {
+}
+
+// Implementation for the merge operation (concatenates two strings)
+bool StringAppendTESTOperator::FullMerge(
+    const Slice& key,
+    const Slice* existing_value,
+    const std::deque<std::string>& operands,
+    std::string* new_value,
+    Logger* logger) const {
+
+  // Clear the *new_value for writing.
+  assert(new_value);
+  new_value->clear();
+
+  // Compute the space needed for the final result.
+  int numBytes = 0;
+  for(auto it = operands.begin(); it != operands.end(); ++it) {
+    numBytes += it->size() + 1;   // Plus 1 for the delimiter
+  }
+
+  // Only print the delimiter after the first entry has been printed
+  bool printDelim = false;
+
+  // Prepend the *existing_value if one exists.
+  if (existing_value) {
+    new_value->reserve(numBytes + existing_value->size());
+    new_value->append(existing_value->data(), existing_value->size());
+    printDelim = true;
+  } else if (numBytes) {
+    new_value->reserve(numBytes-1); // Minus 1 since we have one less delimiter
+  }
+
+  // Concatenate the sequence of strings (and add a delimiter between each)
+  for(auto it = operands.begin(); it != operands.end(); ++it) {
+    if (printDelim) {
+      new_value->append(1,delim_);
+    }
+    new_value->append(*it);
+    printDelim = true;
+  }
+
+  return true;
+}
+
+bool StringAppendTESTOperator::PartialMerge(const Slice& key,
+                                            const Slice& left_operand,
+                                            const Slice& right_operand,
+                                            std::string* new_value,
+                                            Logger* logger) const {
+  return false;
+}
+
+// A version of PartialMerge that actually performs "partial merging".
+// Use this to simulate the exact behaviour of the StringAppendOperator.
+bool StringAppendTESTOperator::_AssocPartialMerge(const Slice& key,
+                                            const Slice& left_operand,
+                                            const Slice& right_operand,
+                                            std::string* new_value,
+                                            Logger* logger) const {
+  // Clear the *new_value for writing.
+  assert(new_value);
+  new_value->clear();
+
+  // Generic append
+  // Reserve correct size for *new_value, and apply concatenation.
+  new_value->reserve(left_operand.size() + 1 + right_operand.size());
+  new_value->assign(left_operand.data(), left_operand.size());
+  new_value->append(1,delim_);
+  new_value->append(right_operand.data(), right_operand.size());
+
+  return true;
+}
+
+const char* StringAppendTESTOperator::Name() const  {
+  return "StringAppendTESTOperator";
+}
+
+
+std::shared_ptr<MergeOperator>
+MergeOperators::CreateStringAppendTESTOperator() {
+  return std::make_shared<StringAppendTESTOperator>(',');
+}
+
+} // namespace rocksdb
+
diff --git a/utilities/merge_operators/string_append/stringappend2.h b/utilities/merge_operators/string_append/stringappend2.h
new file mode 100644 (file)
index 0000000..01a4be4
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ * A TEST MergeOperator for rocksdb that implements string append.
+ * It is built using the MergeOperator interface rather than the simpler
+ * AssociativeMergeOperator interface. This is useful for testing/benchmarking.
+ * While the two operators are semantically the same, all production code
+ * should use the StringAppendOperator defined in stringappend.{h,cc}. The
+ * operator defined in the present file is primarily for testing.
+ *
+ * @author Deon Nicholas (dnicholas@fb.com)
+ * Copyright 2013 Facebook
+ */
+
+#pragma once
+#include "rocksdb/merge_operator.h"
+#include "rocksdb/slice.h"
+
+namespace rocksdb {
+
+class StringAppendTESTOperator : public MergeOperator {
+ public:
+
+  StringAppendTESTOperator(char delim_char);    /// Constructor with delimiter
+
+  virtual bool FullMerge(const Slice& key,
+                         const Slice* existing_value,
+                         const std::deque<std::string>& operand_sequence,
+                         std::string* new_value,
+                         Logger* logger) const override;
+
+  virtual bool PartialMerge(const Slice& key,
+                            const Slice& left_operand,
+                            const Slice& right_operand,
+                            std::string* new_value,
+                            Logger* logger) const override;
+
+  virtual const char* Name() const override;
+
+ private:
+  // A version of PartialMerge that actually performs "partial merging".
+  // Use this to simulate the exact behaviour of the StringAppendOperator.
+  bool _AssocPartialMerge(const Slice& key,
+                          const Slice& left_operand,
+                          const Slice& right_operand,
+                          std::string* new_value,
+                          Logger* logger) const;
+
+  char delim_;         // The delimiter is inserted between elements
+
+};
+
+} // namespace rocksdb
diff --git a/utilities/merge_operators/string_append/stringappend_test.cc b/utilities/merge_operators/string_append/stringappend_test.cc
new file mode 100644 (file)
index 0000000..57386da
--- /dev/null
@@ -0,0 +1,594 @@
+/**
+ * An persistent map : key -> (list of strings), using rocksdb merge.
+ * This file is a test-harness / use-case for the StringAppendOperator.
+ *
+ * @author Deon Nicholas (dnicholas@fb.com)
+ * Copyright 2013 Facebook, Inc.
+*/
+
+#include <iostream>
+#include <map>
+
+#include "rocksdb/db.h"
+#include "rocksdb/merge_operator.h"
+#include "utilities/merge_operators.h"
+#include "utilities/merge_operators/string_append/stringappend.h"
+#include "utilities/merge_operators/string_append/stringappend2.h"
+#include "utilities/ttl/db_ttl.h"
+#include "util/testharness.h"
+#include "util/random.h"
+
+using namespace rocksdb;
+
+namespace rocksdb {
+
+// Path to the database on file system
+const std::string kDbName = "/tmp/mergetestdb";
+
+// OpenDb opens a (possibly new) rocksdb database with a StringAppendOperator
+std::shared_ptr<DB> OpenNormalDb(char delim_char) {
+  DB* db;
+  Options options;
+  options.create_if_missing = true;
+  options.merge_operator.reset(new StringAppendOperator(delim_char));
+  ASSERT_OK(DB::Open(options, kDbName,  &db));
+  return std::shared_ptr<DB>(db);
+}
+
+// Open a TtlDB with a non-associative StringAppendTESTOperator
+std::shared_ptr<DB> OpenTtlDb(char delim_char) {
+  StackableDB* db;
+  Options options;
+  options.create_if_missing = true;
+  options.merge_operator.reset(new StringAppendTESTOperator(delim_char));
+  Status s;
+  db = new DBWithTTL(123456, options, kDbName, s, false);
+  ASSERT_OK(s);
+  return std::shared_ptr<DB>(db);
+}
+
+/// StringLists represents a set of string-lists, each with a key-index.
+/// Supports Append(list, string) and Get(list)
+class StringLists {
+ public:
+
+  //Constructor: specifies the rocksdb db
+  StringLists(std::shared_ptr<DB> db)
+      : db_(db),
+        merge_option_(),
+        get_option_() {
+    assert(db);
+  }
+
+  // Append string val onto the list defined by key; return true on success
+  bool Append(const std::string& key, const std::string& val){
+    Slice valSlice(val.data(), val.size());
+    auto s = db_->Merge(merge_option_, key, valSlice);
+
+    if (s.ok()) {
+      return true;
+    } else {
+      std::cerr << "ERROR " << s.ToString() << std::endl;
+      return false;
+    }
+  }
+
+  // Returns the list of strings associated with key (or "" if does not exist)
+  bool Get(const std::string& key, std::string* const result){
+    assert(result != NULL); // we should have a place to store the result
+    auto s = db_->Get(get_option_, key, result);
+
+    if (s.ok()) {
+      return true;
+    }
+
+    // Either key does not exist, or there is some error.
+    *result = "";       // Always return empty string (just for convenvtion)
+
+    //NotFound is okay; just return empty (similar to std::map)
+    //But network or db errors, etc, should fail the test (or at least yell)
+    if (!s.IsNotFound()) {
+      std::cerr << "ERROR " << s.ToString() << std::endl;
+    }
+
+    // Always return false if s.ok() was not true
+    return false;
+  }
+
+
+ private:
+  std::shared_ptr<DB> db_;
+  WriteOptions merge_option_;
+  ReadOptions get_option_;
+
+};
+
+
+// The class for unit-testing
+class StringAppendOperatorTest {
+ public:
+  StringAppendOperatorTest() {
+    DestroyDB(kDbName, Options());    // Start each test with a fresh DB
+  }
+
+  typedef std::shared_ptr<DB> (* OpenFuncPtr)(char);
+
+  // Allows user to open databases with different configurations.
+  // e.g.: Can open a DB or a TtlDB, etc.
+  static void SetOpenDbFunction(OpenFuncPtr func) {
+    OpenDb = func;
+  }
+
+ protected:
+  static OpenFuncPtr OpenDb;
+};
+StringAppendOperatorTest::OpenFuncPtr StringAppendOperatorTest::OpenDb = nullptr;
+
+// THE TEST CASES BEGIN HERE
+
+TEST(StringAppendOperatorTest, IteratorTest) {
+  auto db_ = OpenDb(',');
+  StringLists slists(db_);
+
+  slists.Append("k1", "v1");
+  slists.Append("k1", "v2");
+  slists.Append("k1", "v3");
+
+  slists.Append("k2", "a1");
+  slists.Append("k2", "a2");
+  slists.Append("k2", "a3");
+
+  std::string res;
+  std::unique_ptr<rocksdb::Iterator> it(db_->NewIterator(ReadOptions()));
+  std::string k1("k1");
+  std::string k2("k2");
+  bool first = true;
+  for (it->Seek(k1); it->Valid(); it->Next()) {
+    res = it->value().ToString();
+    if (first) {
+      ASSERT_EQ(res, "v1,v2,v3");
+      first = false;
+    } else {
+      ASSERT_EQ(res, "a1,a2,a3");
+    }
+  }
+  slists.Append("k2", "a4");
+  slists.Append("k1", "v4");
+
+  // Snapshot should still be the same. Should ignore a4 and v4.
+  first = true;
+  for (it->Seek(k1); it->Valid(); it->Next()) {
+    res = it->value().ToString();
+    if (first) {
+      ASSERT_EQ(res, "v1,v2,v3");
+      first = false;
+    } else {
+      ASSERT_EQ(res, "a1,a2,a3");
+    }
+  }
+
+
+  // Should release the snapshot and be aware of the new stuff now
+  it.reset(db_->NewIterator(ReadOptions()));
+  first = true;
+  for (it->Seek(k1); it->Valid(); it->Next()) {
+    res = it->value().ToString();
+    if (first) {
+      ASSERT_EQ(res, "v1,v2,v3,v4");
+      first = false;
+    } else {
+      ASSERT_EQ(res, "a1,a2,a3,a4");
+    }
+  }
+
+  // start from k2 this time.
+  for (it->Seek(k2); it->Valid(); it->Next()) {
+    res = it->value().ToString();
+    if (first) {
+      ASSERT_EQ(res, "v1,v2,v3,v4");
+      first = false;
+    } else {
+      ASSERT_EQ(res, "a1,a2,a3,a4");
+    }
+  }
+
+  slists.Append("k3", "g1");
+
+  it.reset(db_->NewIterator(ReadOptions()));
+  first = true;
+  std::string k3("k3");
+  for(it->Seek(k2); it->Valid(); it->Next()) {
+    res = it->value().ToString();
+    if (first) {
+      ASSERT_EQ(res, "a1,a2,a3,a4");
+      first = false;
+    } else {
+      ASSERT_EQ(res, "g1");
+    }
+  }
+  for(it->Seek(k3); it->Valid(); it->Next()) {
+    res = it->value().ToString();
+    if (first) {
+      // should not be hit
+      ASSERT_EQ(res, "a1,a2,a3,a4");
+      first = false;
+    } else {
+      ASSERT_EQ(res, "g1");
+    }
+  }
+
+}
+
+TEST(StringAppendOperatorTest, SimpleTest) {
+  auto db = OpenDb(',');
+  StringLists slists(db);
+
+  slists.Append("k1", "v1");
+  slists.Append("k1", "v2");
+  slists.Append("k1", "v3");
+
+  std::string res;
+  bool status = slists.Get("k1", &res);
+
+  ASSERT_TRUE(status);
+  ASSERT_EQ(res, "v1,v2,v3");
+}
+
+TEST(StringAppendOperatorTest, SimpleDelimiterTest) {
+  auto db = OpenDb('|');
+  StringLists slists(db);
+
+  slists.Append("k1", "v1");
+  slists.Append("k1", "v2");
+  slists.Append("k1", "v3");
+
+  std::string res;
+  slists.Get("k1", &res);
+  ASSERT_EQ(res, "v1|v2|v3");
+}
+
+TEST(StringAppendOperatorTest, OneValueNoDelimiterTest) {
+  auto db = OpenDb('!');
+  StringLists slists(db);
+
+  slists.Append("random_key", "single_val");
+
+  std::string res;
+  slists.Get("random_key", &res);
+  ASSERT_EQ(res, "single_val");
+}
+
+TEST(StringAppendOperatorTest, VariousKeys) {
+  auto db = OpenDb('\n');
+  StringLists slists(db);
+
+  slists.Append("c", "asdasd");
+  slists.Append("a", "x");
+  slists.Append("b", "y");
+  slists.Append("a", "t");
+  slists.Append("a", "r");
+  slists.Append("b", "2");
+  slists.Append("c", "asdasd");
+
+  std::string a, b, c;
+  bool sa, sb, sc;
+  sa = slists.Get("a", &a);
+  sb = slists.Get("b", &b);
+  sc = slists.Get("c", &c);
+
+  ASSERT_TRUE(sa && sb && sc); // All three keys should have been found
+
+  ASSERT_EQ(a, "x\nt\nr");
+  ASSERT_EQ(b, "y\n2");
+  ASSERT_EQ(c, "asdasd\nasdasd");
+}
+
+// Generate semi random keys/words from a small distribution.
+TEST(StringAppendOperatorTest, RandomMixGetAppend) {
+  auto db = OpenDb(' ');
+  StringLists slists(db);
+
+  // Generate a list of random keys and values
+  const int kWordCount = 15;
+  std::string words[] = {"sdasd", "triejf", "fnjsdfn", "dfjisdfsf", "342839",
+                         "dsuha", "mabuais", "sadajsid", "jf9834hf", "2d9j89",
+                         "dj9823jd", "a", "dk02ed2dh", "$(jd4h984$(*", "mabz"};
+  const int kKeyCount = 6;
+  std::string keys[] = {"dhaiusdhu", "denidw", "daisda", "keykey", "muki",
+                        "shzassdianmd"};
+
+  // Will store a local copy of all data in order to verify correctness
+  std::map<std::string, std::string> parallel_copy;
+
+  // Generate a bunch of random queries (Append and Get)!
+  enum query_t  { APPEND_OP, GET_OP, NUM_OPS };
+  Random randomGen(1337);       //deterministic seed; always get same results!
+
+  const int kNumQueries = 30;
+  for (int q=0; q<kNumQueries; ++q) {
+    // Generate a random query (Append or Get) and random parameters
+    query_t query = (query_t)randomGen.Uniform((int)NUM_OPS);
+    std::string key = keys[randomGen.Uniform((int)kKeyCount)];
+    std::string word = words[randomGen.Uniform((int)kWordCount)];
+
+    // Apply the query and any checks.
+    if (query == APPEND_OP) {
+
+      // Apply the rocksdb test-harness Append defined above
+      slists.Append(key, word);  //apply the rocksdb append
+
+      // Apply the similar "Append" to the parallel copy
+      if (parallel_copy[key].size() > 0) {
+        parallel_copy[key] += " " + word;
+      } else {
+        parallel_copy[key] = word;
+      }
+
+    } else if (query == GET_OP) {
+      // Assumes that a non-existent key just returns <empty>
+      std::string res;
+      slists.Get(key, &res);
+      ASSERT_EQ(res, parallel_copy[key]);
+    }
+
+  }
+
+}
+
+TEST(StringAppendOperatorTest, BIGRandomMixGetAppend) {
+  auto db = OpenDb(' ');
+  StringLists slists(db);
+
+  // Generate a list of random keys and values
+  const int kWordCount = 15;
+  std::string words[] = {"sdasd", "triejf", "fnjsdfn", "dfjisdfsf", "342839",
+                         "dsuha", "mabuais", "sadajsid", "jf9834hf", "2d9j89",
+                         "dj9823jd", "a", "dk02ed2dh", "$(jd4h984$(*", "mabz"};
+  const int kKeyCount = 6;
+  std::string keys[] = {"dhaiusdhu", "denidw", "daisda", "keykey", "muki",
+                        "shzassdianmd"};
+
+  // Will store a local copy of all data in order to verify correctness
+  std::map<std::string, std::string> parallel_copy;
+
+  // Generate a bunch of random queries (Append and Get)!
+  enum query_t  { APPEND_OP, GET_OP, NUM_OPS };
+  Random randomGen(9138204);       // deterministic seed
+
+  const int kNumQueries = 1000;
+  for (int q=0; q<kNumQueries; ++q) {
+    // Generate a random query (Append or Get) and random parameters
+    query_t query = (query_t)randomGen.Uniform((int)NUM_OPS);
+    std::string key = keys[randomGen.Uniform((int)kKeyCount)];
+    std::string word = words[randomGen.Uniform((int)kWordCount)];
+
+    //Apply the query and any checks.
+    if (query == APPEND_OP) {
+
+      // Apply the rocksdb test-harness Append defined above
+      slists.Append(key, word);  //apply the rocksdb append
+
+      // Apply the similar "Append" to the parallel copy
+      if (parallel_copy[key].size() > 0) {
+        parallel_copy[key] += " " + word;
+      } else {
+        parallel_copy[key] = word;
+      }
+
+    } else if (query == GET_OP) {
+      // Assumes that a non-existent key just returns <empty>
+      std::string res;
+      slists.Get(key, &res);
+      ASSERT_EQ(res, parallel_copy[key]);
+    }
+
+  }
+
+}
+
+
+TEST(StringAppendOperatorTest, PersistentVariousKeys) {
+  // Perform the following operations in limited scope
+  {
+    auto db = OpenDb('\n');
+    StringLists slists(db);
+
+    slists.Append("c", "asdasd");
+    slists.Append("a", "x");
+    slists.Append("b", "y");
+    slists.Append("a", "t");
+    slists.Append("a", "r");
+    slists.Append("b", "2");
+    slists.Append("c", "asdasd");
+
+    std::string a, b, c;
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+
+    ASSERT_EQ(a, "x\nt\nr");
+    ASSERT_EQ(b, "y\n2");
+    ASSERT_EQ(c, "asdasd\nasdasd");
+  }
+
+  // Reopen the database (the previous changes should persist / be remembered)
+  {
+    auto db = OpenDb('\n');
+    StringLists slists(db);
+
+    slists.Append("c", "bbnagnagsx");
+    slists.Append("a", "sa");
+    slists.Append("b", "df");
+    slists.Append("a", "gh");
+    slists.Append("a", "jk");
+    slists.Append("b", "l;");
+    slists.Append("c", "rogosh");
+
+    // The previous changes should be on disk (L0)
+    // The most recent changes should be in memory (MemTable)
+    // Hence, this will test both Get() paths.
+    std::string a, b, c;
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+
+    ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
+    ASSERT_EQ(b, "y\n2\ndf\nl;");
+    ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
+  }
+
+  // Reopen the database (the previous changes should persist / be remembered)
+  {
+    auto db = OpenDb('\n');
+    StringLists slists(db);
+
+    // All changes should be on disk. This will test VersionSet Get()
+    std::string a, b, c;
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+
+    ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
+    ASSERT_EQ(b, "y\n2\ndf\nl;");
+    ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
+  }
+}
+
+TEST(StringAppendOperatorTest, PersistentFlushAndCompaction) {
+  // Perform the following operations in limited scope
+  {
+    auto db = OpenDb('\n');
+    StringLists slists(db);
+    std::string a, b, c;
+    bool success;
+
+    // Append, Flush, Get
+    slists.Append("c", "asdasd");
+    db->Flush(rocksdb::FlushOptions());
+    success = slists.Get("c", &c);
+    ASSERT_TRUE(success);
+    ASSERT_EQ(c, "asdasd");
+
+    // Append, Flush, Append, Get
+    slists.Append("a", "x");
+    slists.Append("b", "y");
+    db->Flush(rocksdb::FlushOptions());
+    slists.Append("a", "t");
+    slists.Append("a", "r");
+    slists.Append("b", "2");
+
+    success = slists.Get("a", &a);
+    assert(success == true);
+    ASSERT_EQ(a, "x\nt\nr");
+
+    success = slists.Get("b", &b);
+    assert(success == true);
+    ASSERT_EQ(b, "y\n2");
+
+    // Append, Get
+    success = slists.Append("c", "asdasd");
+    assert(success);
+    success = slists.Append("b", "monkey");
+    assert(success);
+
+    // I omit the "assert(success)" checks here.
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+
+    ASSERT_EQ(a, "x\nt\nr");
+    ASSERT_EQ(b, "y\n2\nmonkey");
+    ASSERT_EQ(c, "asdasd\nasdasd");
+  }
+
+  // Reopen the database (the previous changes should persist / be remembered)
+  {
+    auto db = OpenDb('\n');
+    StringLists slists(db);
+    std::string a, b, c;
+
+    // Get (Quick check for persistence of previous database)
+    slists.Get("a", &a);
+    ASSERT_EQ(a, "x\nt\nr");
+
+    //Append, Compact, Get
+    slists.Append("c", "bbnagnagsx");
+    slists.Append("a", "sa");
+    slists.Append("b", "df");
+    db->CompactRange(nullptr, nullptr);
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+    ASSERT_EQ(a, "x\nt\nr\nsa");
+    ASSERT_EQ(b, "y\n2\nmonkey\ndf");
+    ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx");
+
+    // Append, Get
+    slists.Append("a", "gh");
+    slists.Append("a", "jk");
+    slists.Append("b", "l;");
+    slists.Append("c", "rogosh");
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+    ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
+    ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;");
+    ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
+
+    // Compact, Get
+    db->CompactRange(nullptr, nullptr);
+    ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
+    ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;");
+    ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
+
+    // Append, Flush, Compact, Get
+    slists.Append("b", "afcg");
+    db->Flush(rocksdb::FlushOptions());
+    db->CompactRange(nullptr, nullptr);
+    slists.Get("b", &b);
+    ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;\nafcg");
+  }
+}
+
+TEST(StringAppendOperatorTest, SimpleTestNullDelimiter) {
+  auto db = OpenDb('\0');
+  StringLists slists(db);
+
+  slists.Append("k1", "v1");
+  slists.Append("k1", "v2");
+  slists.Append("k1", "v3");
+
+  std::string res;
+  bool status = slists.Get("k1", &res);
+  ASSERT_TRUE(status);
+
+  // Construct the desired string. Default constructor doesn't like '\0' chars.
+  std::string checker("v1,v2,v3");    // Verify that the string is right size.
+  checker[2] = '\0';                  // Use null delimiter instead of comma.
+  checker[5] = '\0';
+  assert(checker.size() == 8);        // Verify it is still the correct size
+
+  // Check that the rocksdb result string matches the desired string
+  assert(res.size() == checker.size());
+  ASSERT_EQ(res, checker);
+}
+
+} // namespace rocksdb
+
+int main(int arc, char** argv) {
+  // Run with regular database
+  {
+    fprintf(stderr, "Running tests with regular db and operator.\n");
+    StringAppendOperatorTest::SetOpenDbFunction(&OpenNormalDb);
+    rocksdb::test::RunAllTests();
+  }
+
+  // Run with TTL
+  {
+    fprintf(stderr, "Running tests with ttl db and generic operator.\n");
+    StringAppendOperatorTest::SetOpenDbFunction(&OpenTtlDb);
+    rocksdb::test::RunAllTests();
+  }
+
+  return 0;
+}
diff --git a/utilities/merge_operators/uint64add.cc b/utilities/merge_operators/uint64add.cc
new file mode 100644 (file)
index 0000000..bd96e19
--- /dev/null
@@ -0,0 +1,65 @@
+#include <memory>
+#include "rocksdb/env.h"
+#include "rocksdb/merge_operator.h"
+#include "rocksdb/slice.h"
+#include "util/coding.h"
+#include "utilities/merge_operators.h"
+
+using namespace rocksdb;
+
+namespace { // anonymous namespace
+
+// A 'model' merge operator with uint64 addition semantics
+// Implemented as an AssociativeMergeOperator for simplicty and example.
+class UInt64AddOperator : public AssociativeMergeOperator {
+ public:
+  virtual bool Merge(const Slice& key,
+                     const Slice* existing_value,
+                     const Slice& value,
+                     std::string* new_value,
+                     Logger* logger) const override {
+    uint64_t orig_value = 0;
+    if (existing_value){
+      orig_value = DecodeInteger(*existing_value, logger);
+    }
+    uint64_t operand = DecodeInteger(value, logger);
+
+    assert(new_value);
+    new_value->clear();
+    PutFixed64(new_value, orig_value + operand);
+
+    return true;  // Return true always since corruption will be treated as 0
+  }
+
+  virtual const char* Name() const override {
+    return "UInt64AddOperator";
+  }
+
+ private:
+  // Takes the string and decodes it into a uint64_t
+  // On error, prints a message and returns 0
+  uint64_t DecodeInteger(const Slice& value, Logger* logger) const {
+    uint64_t result = 0;
+
+    if (value.size() == sizeof(uint64_t)) {
+      result = DecodeFixed64(value.data());
+    } else if (logger != nullptr) {
+      // If value is corrupted, treat it as 0
+      Log(logger, "uint64 value corruption, size: %zu > %zu",
+          value.size(), sizeof(uint64_t));
+    }
+
+    return result;
+  }
+
+};
+
+}
+
+namespace rocksdb {
+
+std::shared_ptr<MergeOperator> MergeOperators::CreateUInt64AddOperator() {
+  return std::make_shared<UInt64AddOperator>();
+}
+
+}
diff --git a/utilities/redis/README b/utilities/redis/README
new file mode 100644 (file)
index 0000000..8b17bc0
--- /dev/null
@@ -0,0 +1,14 @@
+This folder defines a REDIS-style interface for Rocksdb.
+Right now it is written as a simple tag-on in the rocksdb::RedisLists class.
+It implements Redis Lists, and supports only the "non-blocking operations".
+
+Internally, the set of lists are stored in a rocksdb database, mapping keys to
+values. Each "value" is the list itself, storing a sequence of "elements".
+Each element is stored as a 32-bit-integer, followed by a sequence of bytes.
+The 32-bit-integer represents the length of the element (that is, the number
+of bytes that follow). And then that many bytes follow.
+
+
+NOTE: This README file may be old. See the actual redis_lists.cc file for
+definitive details on the implementation. There should be a header at the top
+of that file, explaining a bit of the implementation details.
diff --git a/utilities/redis/redis_list_exception.h b/utilities/redis/redis_list_exception.h
new file mode 100644 (file)
index 0000000..d409095
--- /dev/null
@@ -0,0 +1,20 @@
+/**
+ * A simple structure for exceptions in RedisLists.
+ *
+ * @author Deon Nicholas (dnicholas@fb.com)
+ * Copyright 2013 Facebook
+ */
+
+#pragma once
+#include <exception>
+
+namespace rocksdb {
+
+class RedisListException: public std::exception {
+ public:
+  const char* what() const throw() {
+    return "Invalid operation or corrupt data in Redis List.";
+  }
+};
+
+} // namespace rocksdb
diff --git a/utilities/redis/redis_list_iterator.h b/utilities/redis/redis_list_iterator.h
new file mode 100644 (file)
index 0000000..d57f8ac
--- /dev/null
@@ -0,0 +1,308 @@
+/**
+ * RedisListIterator:
+ * An abstraction over the "list" concept (e.g.: for redis lists).
+ * Provides functionality to read, traverse, edit, and write these lists.
+ *
+ * Upon construction, the RedisListIterator is given a block of list data.
+ * Internally, it stores a pointer to the data and a pointer to current item.
+ * It also stores a "result" list that will be mutated over time.
+ *
+ * Traversal and mutation are done by "forward iteration".
+ * The Push() and Skip() methods will advance the iterator to the next item.
+ * However, Push() will also "write the current item to the result".
+ * Skip() will simply move to next item, causing current item to be dropped.
+ *
+ * Upon completion, the result (accessible by WriteResult()) will be saved.
+ * All "skipped" items will be gone; all "pushed" items will remain.
+ *
+ * @throws Any of the operations may throw a RedisListException if an invalid
+ *          operation is performed or if the data is found to be corrupt.
+ *
+ * @notes By default, if WriteResult() is called part-way through iteration,
+ *        it will automatically advance the iterator to the end, and Keep()
+ *        all items that haven't been traversed yet. This may be subject
+ *        to review.
+ *
+ * @notes Can access the "current" item via GetCurrent(), and other
+ *        list-specific information such as Length().
+ *
+ * @notes The internal representation is due to change at any time. Presently,
+ *        the list is represented as follows:
+ *          - 32-bit integer header: the number of items in the list
+ *          - For each item:
+ *              - 32-bit int (n): the number of bytes representing this item
+ *              - n bytes of data: the actual data.
+ *
+ * @author Deon Nicholas (dnicholas@fb.com)
+ * Copyright 2013 Facebook
+ */
+
+#pragma once
+
+#include <string>
+
+#include "redis_list_exception.h"
+#include "rocksdb/slice.h"
+#include "util/coding.h"
+
+namespace rocksdb {
+
+/// An abstraction over the "list" concept.
+/// All operations may throw a RedisListException
+class RedisListIterator {
+ public:
+  /// Construct a redis-list-iterator based on data.
+  /// If the data is non-empty, it must formatted according to @notes above.
+  ///
+  /// If the data is valid, we can assume the following invariant(s):
+  ///  a) length_, num_bytes_ are set correctly.
+  ///  b) cur_byte_ always refers to the start of the current element,
+  ///       just before the bytes that specify element length.
+  ///  c) cur_elem_ is always the index of the current element.
+  ///  d) cur_elem_length_ is always the number of bytes in current element,
+  ///       excluding the 4-byte header itself.
+  ///  e) result_ will always contain data_[0..cur_byte_) and a header
+  ///  f) Whenever corrupt data is encountered or an invalid operation is
+  ///      attempted, a RedisListException will immediately be thrown.
+  RedisListIterator(const std::string& list_data)
+      : data_(list_data.data()),
+        num_bytes_(list_data.size()),
+        cur_byte_(0),
+        cur_elem_(0),
+        cur_elem_length_(0),
+        length_(0),
+        result_() {
+
+    // Initialize the result_ (reserve enough space for header)
+    InitializeResult();
+
+    // Parse the data only if it is not empty.
+    if (num_bytes_ == 0) {
+      return;
+    }
+
+    // If non-empty, but less than 4 bytes, data must be corrupt
+    if (num_bytes_ < sizeof(length_)) {
+      ThrowError("Corrupt header.");    // Will break control flow
+    }
+
+    // Good. The first bytes specify the number of elements
+    length_ = DecodeFixed32(data_);
+    cur_byte_ = sizeof(length_);
+
+    // If we have at least one element, point to that element.
+    // Also, read the first integer of the element (specifying the size),
+    //   if possible.
+    if (length_ > 0) {
+      if (cur_byte_ + sizeof(cur_elem_length_) <= num_bytes_) {
+        cur_elem_length_ = DecodeFixed32(data_+cur_byte_);
+      } else {
+        ThrowError("Corrupt data for first element.");
+      }
+    }
+
+    // At this point, we are fully set-up.
+    // The invariants described in the header should now be true.
+  }
+
+  /// Reserve some space for the result_.
+  /// Equivalent to result_.reserve(bytes).
+  void Reserve(int bytes) {
+    result_.reserve(bytes);
+  }
+
+  /// Go to next element in data file.
+  /// Also writes the current element to result_.
+  RedisListIterator& Push() {
+    WriteCurrentElement();
+    MoveNext();
+    return *this;
+  }
+
+  /// Go to next element in data file.
+  /// Drops/skips the current element. It will not be written to result_.
+  RedisListIterator& Skip() {
+    MoveNext();
+    --length_;          // One less item
+    --cur_elem_;        // We moved one forward, but index did not change
+    return *this;
+  }
+
+  /// Insert elem into the result_ (just BEFORE the current element / byte)
+  /// Note: if Done() (i.e.: iterator points to end), this will append elem.
+  void InsertElement(const Slice& elem) {
+    // Ensure we are in a valid state
+    CheckErrors();
+
+    const int kOrigSize = result_.size();
+    result_.resize(kOrigSize + SizeOf(elem));
+    EncodeFixed32(result_.data() + kOrigSize, elem.size());
+    memcpy(result_.data() + kOrigSize + sizeof(uint32_t),
+           elem.data(),
+           elem.size());
+    ++length_;
+    ++cur_elem_;
+  }
+
+  /// Access the current element, and save the result into *curElem
+  void GetCurrent(Slice* curElem) {
+    // Ensure we are in a valid state
+    CheckErrors();
+
+    // Ensure that we are not past the last element.
+    if (Done()) {
+      ThrowError("Invalid dereferencing.");
+    }
+
+    // Dereference the element
+    *curElem = Slice(data_+cur_byte_+sizeof(cur_elem_length_),
+                     cur_elem_length_);
+  }
+
+  // Number of elements
+  int Length() const {
+    return length_;
+  }
+
+  // Number of bytes in the final representation (i.e: WriteResult().size())
+  int Size() const {
+    // result_ holds the currently written data
+    // data_[cur_byte..num_bytes-1] is the remainder of the data
+    return result_.size() + (num_bytes_ - cur_byte_);
+  }
+
+  // Reached the end?
+  bool Done() const {
+    return cur_byte_ >= num_bytes_ || cur_elem_ >= length_;
+  }
+
+  /// Returns a string representing the final, edited, data.
+  /// Assumes that all bytes of data_ in the range [0,cur_byte_) have been read
+  ///  and that result_ contains this data.
+  /// The rest of the data must still be written.
+  /// So, this method ADVANCES THE ITERATOR TO THE END before writing.
+  Slice WriteResult() {
+    CheckErrors();
+
+    // The header should currently be filled with dummy data (0's)
+    // Correctly update the header.
+    // Note, this is safe since result_ is a vector (guaranteed contiguous)
+    EncodeFixed32(&result_[0],length_);
+
+    // Append the remainder of the data to the result.
+    result_.insert(result_.end(),data_+cur_byte_, data_ +num_bytes_);
+
+    // Seek to end of file
+    cur_byte_ = num_bytes_;
+    cur_elem_ = length_;
+    cur_elem_length_ = 0;
+
+    // Return the result
+    return Slice(result_.data(),result_.size());
+  }
+
+ public: // Static public functions
+
+  /// An upper-bound on the amount of bytes needed to store this element.
+  /// This is used to hide representation information from the client.
+  /// E.G. This can be used to compute the bytes we want to Reserve().
+  static uint32_t SizeOf(const Slice& elem) {
+    // [Integer Length . Data]
+    return sizeof(uint32_t) + elem.size();
+  }
+
+ private: // Private functions
+
+  /// Initializes the result_ string.
+  /// It will fill the first few bytes with 0's so that there is
+  ///  enough space for header information when we need to write later.
+  /// Currently, "header information" means: the length (number of elements)
+  /// Assumes that result_ is empty to begin with
+  void InitializeResult() {
+    assert(result_.empty());            // Should always be true.
+    result_.resize(sizeof(uint32_t),0); // Put a block of 0's as the header
+  }
+
+  /// Go to the next element (used in Push() and Skip())
+  void MoveNext() {
+    CheckErrors();
+
+    // Check to make sure we are not already in a finished state
+    if (Done()) {
+      ThrowError("Attempting to iterate past end of list.");
+    }
+
+    // Move forward one element.
+    cur_byte_ += sizeof(cur_elem_length_) + cur_elem_length_;
+    ++cur_elem_;
+
+    // If we are at the end, finish
+    if (Done()) {
+      cur_elem_length_ = 0;
+      return;
+    }
+
+    // Otherwise, we should be able to read the new element's length
+    if (cur_byte_ + sizeof(cur_elem_length_) > num_bytes_) {
+      ThrowError("Corrupt element data.");
+    }
+
+    // Set the new element's length
+    cur_elem_length_ = DecodeFixed32(data_+cur_byte_);
+
+    return;
+  }
+
+  /// Append the current element (pointed to by cur_byte_) to result_
+  /// Assumes result_ has already been reserved appropriately.
+  void WriteCurrentElement() {
+    // First verify that the iterator is still valid.
+    CheckErrors();
+    if (Done()) {
+      ThrowError("Attempting to write invalid element.");
+    }
+
+    // Append the cur element.
+    result_.insert(result_.end(),
+                   data_+cur_byte_,
+                   data_+cur_byte_+ sizeof(uint32_t) + cur_elem_length_);
+  }
+
+  /// Will ThrowError() if neccessary.
+  /// Checks for common/ubiquitous errors that can arise after most operations.
+  /// This method should be called before any reading operation.
+  /// If this function succeeds, then we are guaranteed to be in a valid state.
+  /// Other member functions should check for errors and ThrowError() also
+  ///  if an error occurs that is specific to it even while in a valid state.
+  void CheckErrors() {
+    // Check if any crazy thing has happened recently
+    if ((cur_elem_ > length_) ||                              // Bad index
+        (cur_byte_ > num_bytes_) ||                           // No more bytes
+        (cur_byte_ + cur_elem_length_ > num_bytes_) ||        // Item too large
+        (cur_byte_ == num_bytes_ && cur_elem_ != length_) ||  // Too many items
+        (cur_elem_ == length_ && cur_byte_ != num_bytes_)) {  // Too many bytes
+      ThrowError("Corrupt data.");
+    }
+  }
+
+  /// Will throw an exception based on the passed-in message.
+  /// This function is guaranteed to STOP THE CONTROL-FLOW.
+  /// (i.e.: you do not have to call "return" after calling ThrowError)
+  void ThrowError(const char* const msg = NULL) {
+    // TODO: For now we ignore the msg parameter. This can be expanded later.
+    throw RedisListException();
+  }
+
+ private:
+  const char* const data_;      // A pointer to the data (the first byte)
+  const uint32_t num_bytes_;    // The number of bytes in this list
+
+  uint32_t cur_byte_;           // The current byte being read
+  uint32_t cur_elem_;           // The current element being read
+  uint32_t cur_elem_length_;    // The number of bytes in current element
+
+  uint32_t length_;             // The number of elements in this list
+  std::vector<char> result_;    // The output data
+};
+
+} // namespace rocksdb
diff --git a/utilities/redis/redis_lists.cc b/utilities/redis/redis_lists.cc
new file mode 100644 (file)
index 0000000..50c544a
--- /dev/null
@@ -0,0 +1,551 @@
+/**
+ * A (persistent) Redis API built using the rocksdb backend.
+ * Implements Redis Lists as described on: http://redis.io/commands#list
+ *
+ * @throws All functions may throw a RedisListException on error/corruption.
+ *
+ * @notes Internally, the set of lists is stored in a rocksdb database,
+ *        mapping keys to values. Each "value" is the list itself, storing
+ *        some kind of internal representation of the data. All the
+ *        representation details are handled by the RedisListIterator class.
+ *        The present file should be oblivious to the representation details,
+ *        handling only the client (Redis) API, and the calls to rocksdb.
+ *
+ * @TODO  Presently, all operations take at least O(NV) time where
+ *        N is the number of elements in the list, and V is the average
+ *        number of bytes per value in the list. So maybe, with merge operator
+ *        we can improve this to an optimal O(V) amortized time, since we
+ *        wouldn't have to read and re-write the entire list.
+ *
+ * @author Deon Nicholas (dnicholas@fb.com)
+ * Copyright 2013 Facebook
+ */
+
+#include "redis_lists.h"
+
+#include <iostream>
+#include <memory>
+#include <cmath>
+
+#include "rocksdb/slice.h"
+#include "util/coding.h"
+
+namespace rocksdb
+{
+
+/// Constructors
+
+RedisLists::RedisLists(const std::string& db_path,
+                       Options options, bool destructive)
+    : put_option_(),
+      get_option_() {
+
+  // Store the name of the database
+  db_name_ = db_path;
+
+  // If destructive, destroy the DB before re-opening it.
+  if (destructive) {
+    DestroyDB(db_name_, Options());
+  }
+
+  // Now open and deal with the db
+  DB* db;
+  Status s = DB::Open(options, db_name_, &db);
+  if (!s.ok()) {
+    std::cerr << "ERROR " << s.ToString() << std::endl;
+    assert(false);
+  }
+
+  db_ = std::unique_ptr<DB>(db);
+}
+
+
+/// Accessors
+
+// Number of elements in the list associated with key
+//   : throws RedisListException
+int RedisLists::Length(const std::string& key) {
+  // Extract the string data representing the list.
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Return the length
+  RedisListIterator it(data);
+  return it.Length();
+}
+
+// Get the element at the specified index in the (list: key)
+// Returns <empty> ("") on out-of-bounds
+//   : throws RedisListException
+bool RedisLists::Index(const std::string& key, int32_t index,
+                       std::string* result) {
+  // Extract the string data representing the list.
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Handle REDIS negative indices (from the end); fast iff Length() takes O(1)
+  if (index < 0) {
+    index = Length(key) - (-index);  //replace (-i) with (N-i).
+  }
+
+  // Iterate through the list until the desired index is found.
+  int curIndex = 0;
+  RedisListIterator it(data);
+  while(curIndex < index && !it.Done()) {
+    ++curIndex;
+    it.Skip();
+  }
+
+  // If we actually found the index
+  if (curIndex == index && !it.Done()) {
+    Slice elem;
+    it.GetCurrent(&elem);
+    if (result != NULL) {
+      *result = elem.ToString();
+    }
+
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Return a truncated version of the list.
+// First, negative values for first/last are interpreted as "end of list".
+// So, if first == -1, then it is re-set to index: (Length(key) - 1)
+// Then, return exactly those indices i such that first <= i <= last.
+//   : throws RedisListException
+std::vector<std::string> RedisLists::Range(const std::string& key,
+                                           int32_t first, int32_t last) {
+  // Extract the string data representing the list.
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Handle negative bounds (-1 means last element, etc.)
+  int listLen = Length(key);
+  if (first < 0) {
+    first = listLen - (-first);           // Replace (-x) with (N-x)
+  }
+  if (last < 0) {
+    last = listLen - (-last);
+  }
+
+  // Verify bounds (and truncate the range so that it is valid)
+  first = std::max(first, 0);
+  last = std::min(last, listLen-1);
+  int len = std::max(last-first+1, 0);
+
+  // Initialize the resulting list
+  std::vector<std::string> result(len);
+
+  // Traverse the list and update the vector
+  int curIdx = 0;
+  Slice elem;
+  for (RedisListIterator it(data); !it.Done() && curIdx<=last; it.Skip()) {
+    if (first <= curIdx && curIdx <= last) {
+      it.GetCurrent(&elem);
+      result[curIdx-first].assign(elem.data(),elem.size());
+    }
+
+    ++curIdx;
+  }
+
+  // Return the result. Might be empty
+  return result;
+}
+
+// Print the (list: key) out to stdout. For debugging mostly. Public for now.
+void RedisLists::Print(const std::string& key) {
+  // Extract the string data representing the list.
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Iterate through the list and print the items
+  Slice elem;
+  for (RedisListIterator it(data); !it.Done(); it.Skip()) {
+    it.GetCurrent(&elem);
+    std::cout << "ITEM " << elem.ToString() << std::endl;
+  }
+
+  //Now print the byte data
+  RedisListIterator it(data);
+  std::cout << "==Printing data==" << std::endl;
+  std::cout << data.size() << std::endl;
+  std::cout << it.Size() << " " << it.Length() << std::endl;
+  Slice result = it.WriteResult();
+  std::cout << result.data() << std::endl;
+  if (true) {
+    std::cout << "size: " << result.size() << std::endl;
+    const char* val = result.data();
+    for(int i=0; i<(int)result.size(); ++i) {
+      std::cout << (int)val[i] << " " << (val[i]>=32?val[i]:' ') << std::endl;
+    }
+    std::cout << std::endl;
+  }
+}
+
+/// Insert/Update Functions
+/// Note: The "real" insert function is private. See below.
+
+// InsertBefore and InsertAfter are simply wrappers around the Insert function.
+int RedisLists::InsertBefore(const std::string& key, const std::string& pivot,
+                             const std::string& value) {
+  return Insert(key, pivot, value, false);
+}
+
+int RedisLists::InsertAfter(const std::string& key, const std::string& pivot,
+                            const std::string& value) {
+  return Insert(key, pivot, value, true);
+}
+
+// Prepend value onto beginning of (list: key)
+//   : throws RedisListException
+int RedisLists::PushLeft(const std::string& key, const std::string& value) {
+  // Get the original list data
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Construct the result
+  RedisListIterator it(data);
+  it.Reserve(it.Size() + it.SizeOf(value));
+  it.InsertElement(value);
+
+  // Push the data back to the db and return the length
+  db_->Put(put_option_, key, it.WriteResult());
+  return it.Length();
+}
+
+// Append value onto end of (list: key)
+// TODO: Make this O(1) time. Might require MergeOperator.
+//   : throws RedisListException
+int RedisLists::PushRight(const std::string& key, const std::string& value) {
+  // Get the original list data
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Create an iterator to the data and seek to the end.
+  RedisListIterator it(data);
+  it.Reserve(it.Size() + it.SizeOf(value));
+  while (!it.Done()) {
+    it.Push();    // Write each element as we go
+  }
+
+  // Insert the new element at the current position (the end)
+  it.InsertElement(value);
+
+  // Push it back to the db, and return length
+  db_->Put(put_option_, key, it.WriteResult());
+  return it.Length();
+}
+
+// Set (list: key)[idx] = val. Return true on success, false on fail.
+//   : throws RedisListException
+bool RedisLists::Set(const std::string& key, int32_t index,
+                     const std::string& value) {
+  // Get the original list data
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Handle negative index for REDIS (meaning -index from end of list)
+  if (index < 0) {
+    index = Length(key) - (-index);
+  }
+
+  // Iterate through the list until we find the element we want
+  int curIndex = 0;
+  RedisListIterator it(data);
+  it.Reserve(it.Size() + it.SizeOf(value));  // Over-estimate is fine
+  while(curIndex < index && !it.Done()) {
+    it.Push();
+    ++curIndex;
+  }
+
+  // If not found, return false (this occurs when index was invalid)
+  if (it.Done() || curIndex != index) {
+    return false;
+  }
+
+  // Write the new element value, and drop the previous element value
+  it.InsertElement(value);
+  it.Skip();
+
+  // Write the data to the database
+  // Check status, since it needs to return true/false guarantee
+  Status s = db_->Put(put_option_, key, it.WriteResult());
+
+  // Success
+  return s.ok();
+}
+
+/// Delete / Remove / Pop functions
+
+// Trim (list: key) so that it will only contain the indices from start..stop
+//  Invalid indices will not generate an error, just empty,
+//  or the portion of the list that fits in this interval
+//   : throws RedisListException
+bool RedisLists::Trim(const std::string& key, int32_t start, int32_t stop) {
+  // Get the original list data
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Handle negative indices in REDIS
+  int listLen = Length(key);
+  if (start < 0) {
+    start = listLen - (-start);
+  }
+  if (stop < 0) {
+    stop = listLen - (-stop);
+  }
+
+  // Truncate bounds to only fit in the list
+  start = std::max(start, 0);
+  stop = std::min(stop, listLen-1);
+
+  // Construct an iterator for the list. Drop all undesired elements.
+  int curIndex = 0;
+  RedisListIterator it(data);
+  it.Reserve(it.Size());          // Over-estimate
+  while(!it.Done()) {
+    // If not within the range, just skip the item (drop it).
+    // Otherwise, continue as usual.
+    if (start <= curIndex && curIndex <= stop) {
+      it.Push();
+    } else {
+      it.Skip();
+    }
+
+    // Increment the current index
+    ++curIndex;
+  }
+
+  // Write the (possibly empty) result to the database
+  Status s = db_->Put(put_option_, key, it.WriteResult());
+
+  // Return true as long as the write succeeded
+  return s.ok();
+}
+
+// Return and remove the first element in the list (or "" if empty)
+//   : throws RedisListException
+bool RedisLists::PopLeft(const std::string& key, std::string* result) {
+  // Get the original list data
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Point to first element in the list (if it exists), and get its value/size
+  RedisListIterator it(data);
+  if (it.Length() > 0) {            // Proceed only if list is non-empty
+    Slice elem;
+    it.GetCurrent(&elem);           // Store the value of the first element
+    it.Reserve(it.Size() - it.SizeOf(elem));
+    it.Skip();                      // DROP the first item and move to next
+
+    // Update the db
+    db_->Put(put_option_, key, it.WriteResult());
+
+    // Return the value
+    if (result != NULL) {
+      *result = elem.ToString();
+    }
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Remove and return the last element in the list (or "" if empty)
+// TODO: Make this O(1). Might require MergeOperator.
+//   : throws RedisListException
+bool RedisLists::PopRight(const std::string& key, std::string* result) {
+  // Extract the original list data
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Construct an iterator to the data and move to last element
+  RedisListIterator it(data);
+  it.Reserve(it.Size());
+  int len = it.Length();
+  int curIndex = 0;
+  while(curIndex < (len-1) && !it.Done()) {
+    it.Push();
+    ++curIndex;
+  }
+
+  // Extract and drop/skip the last element
+  if (curIndex == len-1) {
+    assert(!it.Done());         // Sanity check. Should not have ended here.
+
+    // Extract and pop the element
+    Slice elem;
+    it.GetCurrent(&elem);       // Save value of element.
+    it.Skip();                  // Skip the element
+
+    // Write the result to the database
+    db_->Put(put_option_, key, it.WriteResult());
+
+    // Return the value
+    if (result != NULL) {
+      *result = elem.ToString();
+    }
+    return true;
+  } else {
+    // Must have been an empty list
+    assert(it.Done() && len==0 && curIndex == 0);
+    return false;
+  }
+}
+
+// Remove the (first or last) "num" occurrences of value in (list: key)
+//   : throws RedisListException
+int RedisLists::Remove(const std::string& key, int32_t num,
+                       const std::string& value) {
+  // Negative num ==> RemoveLast; Positive num ==> Remove First
+  if (num < 0) {
+    return RemoveLast(key, -num, value);
+  } else if (num > 0) {
+    return RemoveFirst(key, num, value);
+  } else {
+    return RemoveFirst(key, Length(key), value);
+  }
+}
+
+// Remove the first "num" occurrences of value in (list: key).
+//   : throws RedisListException
+int RedisLists::RemoveFirst(const std::string& key, int32_t num,
+                            const std::string& value) {
+  // Ensure that the number is positive
+  assert(num >= 0);
+
+  // Extract the original list data
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Traverse the list, appending all but the desired occurrences of value
+  int numSkipped = 0;         // Keep track of the number of times value is seen
+  Slice elem;
+  RedisListIterator it(data);
+  it.Reserve(it.Size());
+  while (!it.Done()) {
+    it.GetCurrent(&elem);
+
+    if (elem == value && numSkipped < num) {
+      // Drop this item if desired
+      it.Skip();
+      ++numSkipped;
+    } else {
+      // Otherwise keep the item and proceed as normal
+      it.Push();
+    }
+  }
+
+  // Put the result back to the database
+  db_->Put(put_option_, key, it.WriteResult());
+
+  // Return the number of elements removed
+  return numSkipped;
+}
+
+
+// Remove the last "num" occurrences of value in (list: key).
+// TODO: I traverse the list 2x. Make faster. Might require MergeOperator.
+//   : throws RedisListException
+int RedisLists::RemoveLast(const std::string& key, int32_t num,
+                           const std::string& value) {
+  // Ensure that the number is positive
+  assert(num >= 0);
+
+  // Extract the original list data
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Temporary variable to hold the "current element" in the blocks below
+  Slice elem;
+
+  // Count the total number of occurrences of value
+  int totalOccs = 0;
+  for (RedisListIterator it(data); !it.Done(); it.Skip()) {
+    it.GetCurrent(&elem);
+    if (elem == value) {
+      ++totalOccs;
+    }
+  }
+
+  // Construct an iterator to the data. Reserve enough space for the result.
+  RedisListIterator it(data);
+  int bytesRemoved = std::min(num,totalOccs)*it.SizeOf(value);
+  it.Reserve(it.Size() - bytesRemoved);
+
+  // Traverse the list, appending all but the desired occurrences of value.
+  // Note: "Drop the last k occurrences" is equivalent to
+  //  "keep only the first n-k occurrences", where n is total occurrences.
+  int numKept = 0;          // Keep track of the number of times value is kept
+  while(!it.Done()) {
+    it.GetCurrent(&elem);
+
+    // If we are within the deletion range and equal to value, drop it.
+    // Otherwise, append/keep/push it.
+    if (elem == value) {
+      if (numKept < totalOccs - num) {
+        it.Push();
+        ++numKept;
+      } else {
+        it.Skip();
+      }
+    } else {
+      // Always append the others
+      it.Push();
+    }
+  }
+
+  // Put the result back to the database
+  db_->Put(put_option_, key, it.WriteResult());
+
+  // Return the number of elements removed
+  return totalOccs - numKept;
+}
+
+/// Private functions
+
+// Insert element value into (list: key), right before/after
+//  the first occurrence of pivot
+//   : throws RedisListException
+int RedisLists::Insert(const std::string& key, const std::string& pivot,
+                       const std::string& value, bool insert_after) {
+  // Get the original list data
+  std::string data;
+  db_->Get(get_option_, key, &data);
+
+  // Construct an iterator to the data and reserve enough space for result.
+  RedisListIterator it(data);
+  it.Reserve(it.Size() + it.SizeOf(value));
+
+  // Iterate through the list until we find the element we want
+  Slice elem;
+  bool found = false;
+  while(!it.Done() && !found) {
+    it.GetCurrent(&elem);
+
+    // When we find the element, insert the element and mark found
+    if (elem == pivot) {                // Found it!
+      found = true;
+      if (insert_after == true) {       // Skip one more, if inserting after it
+        it.Push();
+      }
+      it.InsertElement(value);
+    } else {
+      it.Push();
+    }
+
+  }
+
+  // Put the data (string) into the database
+  if (found) {
+    db_->Put(put_option_, key, it.WriteResult());
+  }
+
+  // Returns the new (possibly unchanged) length of the list
+  return it.Length();
+}
+
+
+}
diff --git a/utilities/redis/redis_lists.h b/utilities/redis/redis_lists.h
new file mode 100644 (file)
index 0000000..8c149bc
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+ * A (persistent) Redis API built using the rocksdb backend.
+ * Implements Redis Lists as described on: http://redis.io/commands#list
+ *
+ * @throws All functions may throw a RedisListException
+ *
+ * @author Deon Nicholas (dnicholas@fb.com)
+ * Copyright 2013 Facebook
+ */
+
+#pragma once
+
+#include <string>
+#include "rocksdb/db.h"
+#include "redis_list_iterator.h"
+#include "redis_list_exception.h"
+
+namespace rocksdb {
+
+/// The Redis functionality (see http://redis.io/commands#list)
+/// All functions may THROW a RedisListException
+class RedisLists {
+ public: // Constructors / Destructors
+  /// Construct a new RedisLists database, with name/path of db.
+  /// Will clear the database on open iff destructive is true (default false).
+  /// Otherwise, it will restore saved changes.
+  /// May throw RedisListException
+  RedisLists(const std::string& db_path,
+             Options options, bool destructive = false);
+
+ public:  // Accessors
+  /// The number of items in (list: key)
+  int Length(const std::string& key);
+
+  /// Search the list for the (index)'th item (0-based) in (list:key)
+  /// A negative index indicates: "from end-of-list"
+  /// If index is within range: return true, and return the value in *result.
+  /// If (index < -length OR index>=length), then index is out of range:
+  ///   return false (and *result is left unchanged)
+  /// May throw RedisListException
+  bool Index(const std::string& key, int32_t index,
+             std::string* result);
+
+  /// Return (list: key)[first..last] (inclusive)
+  /// May throw RedisListException
+  std::vector<std::string> Range(const std::string& key,
+                                 int32_t first, int32_t last);
+
+  /// Prints the entire (list: key), for debugging.
+  void Print(const std::string& key);
+
+ public: // Insert/Update
+  /// Insert value before/after pivot in (list: key). Return the length.
+  /// May throw RedisListException
+  int InsertBefore(const std::string& key, const std::string& pivot,
+                   const std::string& value);
+  int InsertAfter(const std::string& key, const std::string& pivot,
+                  const std::string& value);
+
+  /// Push / Insert value at beginning/end of the list. Return the length.
+  /// May throw RedisListException
+  int PushLeft(const std::string& key, const std::string& value);
+  int PushRight(const std::string& key, const std::string& value);
+
+  /// Set (list: key)[idx] = val. Return true on success, false on fail
+  /// May throw RedisListException
+  bool Set(const std::string& key, int32_t index, const std::string& value);
+
+ public: // Delete / Remove / Pop / Trim
+  /// Trim (list: key) so that it will only contain the indices from start..stop
+  /// Returns true on success
+  /// May throw RedisListException
+  bool Trim(const std::string& key, int32_t start, int32_t stop);
+
+  /// If list is empty, return false and leave *result unchanged.
+  /// Else, remove the first/last elem, store it in *result, and return true
+  bool PopLeft(const std::string& key, std::string* result);  // First
+  bool PopRight(const std::string& key, std::string* result); // Last
+
+  /// Remove the first (or last) num occurrences of value from the list (key)
+  /// Return the number of elements removed.
+  /// May throw RedisListException
+  int Remove(const std::string& key, int32_t num,
+             const std::string& value);
+  int RemoveFirst(const std::string& key, int32_t num,
+                  const std::string& value);
+  int RemoveLast(const std::string& key, int32_t num,
+                 const std::string& value);
+
+ private: // Private Functions
+  /// Calls InsertBefore or InsertAfter
+  int Insert(const std::string& key, const std::string& pivot,
+             const std::string& value, bool insert_after);
+ private:
+  std::string db_name_;       // The actual database name/path
+  WriteOptions put_option_;
+  ReadOptions get_option_;
+
+  /// The backend rocksdb database.
+  /// Map : key --> list
+  ///       where a list is a sequence of elements
+  ///       and an element is a 4-byte integer (n), followed by n bytes of data
+  std::unique_ptr<DB> db_;
+};
+
+} // namespace rocksdb
diff --git a/utilities/redis/redis_lists_test.cc b/utilities/redis/redis_lists_test.cc
new file mode 100644 (file)
index 0000000..7a28ad8
--- /dev/null
@@ -0,0 +1,875 @@
+/**
+ * A test harness for the Redis API built on rocksdb.
+ *
+ * USAGE: Build with: "make redis_test" (in rocksdb directory).
+ *        Run unit tests with: "./redis_test"
+ *        Manual/Interactive user testing: "./redis_test -m"
+ *        Manual user testing + restart database: "./redis_test -m -d"
+ *
+ * TODO:  Add LARGE random test cases to verify efficiency and scalability
+ *
+ * @author Deon Nicholas (dnicholas@fb.com)
+ * Copyright 2013 Facebook
+ */
+
+
+#include <iostream>
+#include <cctype>
+
+#include "redis_lists.h"
+#include "util/testharness.h"
+#include "util/random.h"
+
+using namespace rocksdb;
+using namespace std;
+
+namespace rocksdb {
+
+class RedisListsTest {
+ public:
+  static const string kDefaultDbName;
+  static Options options;
+
+  RedisListsTest() {
+    options.create_if_missing = true;
+  }
+};
+
+const string RedisListsTest::kDefaultDbName = "/tmp/redisdefaultdb/";
+Options RedisListsTest::options = Options();
+
+// operator== and operator<< are defined below for vectors (lists)
+// Needed for ASSERT_EQ
+
+void AssertListEq(const std::vector<std::string>& result,
+                  const std::vector<std::string>& expected_result) {
+  ASSERT_EQ(result.size(), expected_result.size());
+  for (size_t i = 0; i < result.size(); ++i) {
+    ASSERT_EQ(result[i], expected_result[i]);
+  }
+}
+
+// PushRight, Length, Index, Range
+TEST(RedisListsTest, SimpleTest) {
+  RedisLists redis(kDefaultDbName, options, true);   // Destructive
+
+  string tempv; // Used below for all Index(), PopRight(), PopLeft()
+
+  // Simple PushRight (should return the new length each time)
+  ASSERT_EQ(redis.PushRight("k1", "v1"), 1);
+  ASSERT_EQ(redis.PushRight("k1", "v2"), 2);
+  ASSERT_EQ(redis.PushRight("k1", "v3"), 3);
+
+  // Check Length and Index() functions
+  ASSERT_EQ(redis.Length("k1"), 3);        // Check length
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "v1");   // Check valid indices
+  ASSERT_TRUE(redis.Index("k1", 1, &tempv));
+  ASSERT_EQ(tempv, "v2");
+  ASSERT_TRUE(redis.Index("k1", 2, &tempv));
+  ASSERT_EQ(tempv, "v3");
+
+  // Check range function and vectors
+  std::vector<std::string> result = redis.Range("k1", 0, 2);   // Get the list
+  std::vector<std::string> expected_result(3);
+  expected_result[0] = "v1";
+  expected_result[1] = "v2";
+  expected_result[2] = "v3";
+  AssertListEq(result, expected_result);
+}
+
+// PushLeft, Length, Index, Range
+TEST(RedisListsTest, SimpleTest2) {
+  RedisLists redis(kDefaultDbName, options, true);   // Destructive
+
+  string tempv; // Used below for all Index(), PopRight(), PopLeft()
+
+  // Simple PushRight
+  ASSERT_EQ(redis.PushLeft("k1", "v3"), 1);
+  ASSERT_EQ(redis.PushLeft("k1", "v2"), 2);
+  ASSERT_EQ(redis.PushLeft("k1", "v1"), 3);
+
+  // Check Length and Index() functions
+  ASSERT_EQ(redis.Length("k1"), 3);        // Check length
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "v1");   // Check valid indices
+  ASSERT_TRUE(redis.Index("k1", 1, &tempv));
+  ASSERT_EQ(tempv, "v2");
+  ASSERT_TRUE(redis.Index("k1", 2, &tempv));
+  ASSERT_EQ(tempv, "v3");
+
+  // Check range function and vectors
+  std::vector<std::string> result = redis.Range("k1", 0, 2);   // Get the list
+  std::vector<std::string> expected_result(3);
+  expected_result[0] = "v1";
+  expected_result[1] = "v2";
+  expected_result[2] = "v3";
+  AssertListEq(result, expected_result);
+}
+
+// Exhaustive test of the Index() function
+TEST(RedisListsTest, IndexTest) {
+  RedisLists redis(kDefaultDbName, options, true);   // Destructive
+
+  string tempv; // Used below for all Index(), PopRight(), PopLeft()
+
+  // Empty Index check (return empty and should not crash or edit tempv)
+  tempv = "yo";
+  ASSERT_TRUE(!redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "yo");
+  ASSERT_TRUE(!redis.Index("fda", 3, &tempv));
+  ASSERT_EQ(tempv, "yo");
+  ASSERT_TRUE(!redis.Index("random", -12391, &tempv));
+  ASSERT_EQ(tempv, "yo");
+
+  // Simple Pushes (will yield: [v6, v4, v4, v1, v2, v3]
+  redis.PushRight("k1", "v1");
+  redis.PushRight("k1", "v2");
+  redis.PushRight("k1", "v3");
+  redis.PushLeft("k1", "v4");
+  redis.PushLeft("k1", "v4");
+  redis.PushLeft("k1", "v6");
+
+  // Simple, non-negative indices
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "v6");
+  ASSERT_TRUE(redis.Index("k1", 1, &tempv));
+  ASSERT_EQ(tempv, "v4");
+  ASSERT_TRUE(redis.Index("k1", 2, &tempv));
+  ASSERT_EQ(tempv, "v4");
+  ASSERT_TRUE(redis.Index("k1", 3, &tempv));
+  ASSERT_EQ(tempv, "v1");
+  ASSERT_TRUE(redis.Index("k1", 4, &tempv));
+  ASSERT_EQ(tempv, "v2");
+  ASSERT_TRUE(redis.Index("k1", 5, &tempv));
+  ASSERT_EQ(tempv, "v3");
+
+  // Negative indices
+  ASSERT_TRUE(redis.Index("k1", -6, &tempv));
+  ASSERT_EQ(tempv, "v6");
+  ASSERT_TRUE(redis.Index("k1", -5, &tempv));
+  ASSERT_EQ(tempv, "v4");
+  ASSERT_TRUE(redis.Index("k1", -4, &tempv));
+  ASSERT_EQ(tempv, "v4");
+  ASSERT_TRUE(redis.Index("k1", -3, &tempv));
+  ASSERT_EQ(tempv, "v1");
+  ASSERT_TRUE(redis.Index("k1", -2, &tempv));
+  ASSERT_EQ(tempv, "v2");
+  ASSERT_TRUE(redis.Index("k1", -1, &tempv));
+  ASSERT_EQ(tempv, "v3");
+
+  // Out of bounds (return empty, no crash)
+  ASSERT_TRUE(!redis.Index("k1", 6, &tempv));
+  ASSERT_TRUE(!redis.Index("k1", 123219, &tempv));
+  ASSERT_TRUE(!redis.Index("k1", -7, &tempv));
+  ASSERT_TRUE(!redis.Index("k1", -129, &tempv));
+}
+
+
+// Exhaustive test of the Range() function
+TEST(RedisListsTest, RangeTest) {
+  RedisLists redis(kDefaultDbName, options, true);   // Destructive
+
+  string tempv; // Used below for all Index(), PopRight(), PopLeft()
+
+  // Simple Pushes (will yield: [v6, v4, v4, v1, v2, v3])
+  redis.PushRight("k1", "v1");
+  redis.PushRight("k1", "v2");
+  redis.PushRight("k1", "v3");
+  redis.PushLeft("k1", "v4");
+  redis.PushLeft("k1", "v4");
+  redis.PushLeft("k1", "v6");
+
+  // Sanity check (check the length;  make sure it's 6)
+  ASSERT_EQ(redis.Length("k1"), 6);
+
+  // Simple range
+  std::vector<std::string> res = redis.Range("k1", 1, 4);
+  ASSERT_EQ((int)res.size(), 4);
+  ASSERT_EQ(res[0], "v4");
+  ASSERT_EQ(res[1], "v4");
+  ASSERT_EQ(res[2], "v1");
+  ASSERT_EQ(res[3], "v2");
+
+  // Negative indices (i.e.: measured from the end)
+  res = redis.Range("k1", 2, -1);
+  ASSERT_EQ((int)res.size(), 4);
+  ASSERT_EQ(res[0], "v4");
+  ASSERT_EQ(res[1], "v1");
+  ASSERT_EQ(res[2], "v2");
+  ASSERT_EQ(res[3], "v3");
+
+  res = redis.Range("k1", -6, -4);
+  ASSERT_EQ((int)res.size(), 3);
+  ASSERT_EQ(res[0], "v6");
+  ASSERT_EQ(res[1], "v4");
+  ASSERT_EQ(res[2], "v4");
+
+  res = redis.Range("k1", -1, 5);
+  ASSERT_EQ((int)res.size(), 1);
+  ASSERT_EQ(res[0], "v3");
+
+  // Partial / Broken indices
+  res = redis.Range("k1", -3, 1000000);
+  ASSERT_EQ((int)res.size(), 3);
+  ASSERT_EQ(res[0], "v1");
+  ASSERT_EQ(res[1], "v2");
+  ASSERT_EQ(res[2], "v3");
+
+  res = redis.Range("k1", -1000000, 1);
+  ASSERT_EQ((int)res.size(), 2);
+  ASSERT_EQ(res[0], "v6");
+  ASSERT_EQ(res[1], "v4");
+
+  // Invalid indices
+  res = redis.Range("k1", 7, 9);
+  ASSERT_EQ((int)res.size(), 0);
+
+  res = redis.Range("k1", -8, -7);
+  ASSERT_EQ((int)res.size(), 0);
+
+  res = redis.Range("k1", 3, 2);
+  ASSERT_EQ((int)res.size(), 0);
+
+  res = redis.Range("k1", 5, -2);
+  ASSERT_EQ((int)res.size(), 0);
+
+  // Range matches Index
+  res = redis.Range("k1", -6, -4);
+  ASSERT_TRUE(redis.Index("k1", -6, &tempv));
+  ASSERT_EQ(tempv, res[0]);
+  ASSERT_TRUE(redis.Index("k1", -5, &tempv));
+  ASSERT_EQ(tempv, res[1]);
+  ASSERT_TRUE(redis.Index("k1", -4, &tempv));
+  ASSERT_EQ(tempv, res[2]);
+
+  // Last check
+  res = redis.Range("k1", 0, -6);
+  ASSERT_EQ((int)res.size(), 1);
+  ASSERT_EQ(res[0], "v6");
+}
+
+// Exhaustive test for InsertBefore(), and InsertAfter()
+TEST(RedisListsTest, InsertTest) {
+  RedisLists redis(kDefaultDbName, options, true);
+
+  string tempv; // Used below for all Index(), PopRight(), PopLeft()
+
+  // Insert on empty list (return 0, and do not crash)
+  ASSERT_EQ(redis.InsertBefore("k1", "non-exist", "a"), 0);
+  ASSERT_EQ(redis.InsertAfter("k1", "other-non-exist", "c"), 0);
+  ASSERT_EQ(redis.Length("k1"), 0);
+
+  // Push some preliminary stuff [g, f, e, d, c, b, a]
+  redis.PushLeft("k1", "a");
+  redis.PushLeft("k1", "b");
+  redis.PushLeft("k1", "c");
+  redis.PushLeft("k1", "d");
+  redis.PushLeft("k1", "e");
+  redis.PushLeft("k1", "f");
+  redis.PushLeft("k1", "g");
+  ASSERT_EQ(redis.Length("k1"), 7);
+
+  // Test InsertBefore
+  int newLength = redis.InsertBefore("k1", "e", "hello");
+  ASSERT_EQ(newLength, 8);
+  ASSERT_EQ(redis.Length("k1"), newLength);
+  ASSERT_TRUE(redis.Index("k1", 1, &tempv));
+  ASSERT_EQ(tempv, "f");
+  ASSERT_TRUE(redis.Index("k1", 3, &tempv));
+  ASSERT_EQ(tempv, "e");
+  ASSERT_TRUE(redis.Index("k1", 2, &tempv));
+  ASSERT_EQ(tempv, "hello");
+
+  // Test InsertAfter
+  newLength =  redis.InsertAfter("k1", "c", "bye");
+  ASSERT_EQ(newLength, 9);
+  ASSERT_EQ(redis.Length("k1"), newLength);
+  ASSERT_TRUE(redis.Index("k1", 6, &tempv));
+  ASSERT_EQ(tempv, "bye");
+
+  // Test bad value on InsertBefore
+  newLength = redis.InsertBefore("k1", "yo", "x");
+  ASSERT_EQ(newLength, 9);
+  ASSERT_EQ(redis.Length("k1"), newLength);
+
+  // Test bad value on InsertAfter
+  newLength = redis.InsertAfter("k1", "xxxx", "y");
+  ASSERT_EQ(newLength, 9);
+  ASSERT_EQ(redis.Length("k1"), newLength);
+
+  // Test InsertBefore beginning
+  newLength = redis.InsertBefore("k1", "g", "begggggggggggggggg");
+  ASSERT_EQ(newLength, 10);
+  ASSERT_EQ(redis.Length("k1"), newLength);
+
+  // Test InsertAfter end
+  newLength = redis.InsertAfter("k1", "a", "enddd");
+  ASSERT_EQ(newLength, 11);
+  ASSERT_EQ(redis.Length("k1"), newLength);
+
+  // Make sure nothing weird happened.
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "begggggggggggggggg");
+  ASSERT_TRUE(redis.Index("k1", 1, &tempv));
+  ASSERT_EQ(tempv, "g");
+  ASSERT_TRUE(redis.Index("k1", 2, &tempv));
+  ASSERT_EQ(tempv, "f");
+  ASSERT_TRUE(redis.Index("k1", 3, &tempv));
+  ASSERT_EQ(tempv, "hello");
+  ASSERT_TRUE(redis.Index("k1", 4, &tempv));
+  ASSERT_EQ(tempv, "e");
+  ASSERT_TRUE(redis.Index("k1", 5, &tempv));
+  ASSERT_EQ(tempv, "d");
+  ASSERT_TRUE(redis.Index("k1", 6, &tempv));
+  ASSERT_EQ(tempv, "c");
+  ASSERT_TRUE(redis.Index("k1", 7, &tempv));
+  ASSERT_EQ(tempv, "bye");
+  ASSERT_TRUE(redis.Index("k1", 8, &tempv));
+  ASSERT_EQ(tempv, "b");
+  ASSERT_TRUE(redis.Index("k1", 9, &tempv));
+  ASSERT_EQ(tempv, "a");
+  ASSERT_TRUE(redis.Index("k1", 10, &tempv));
+  ASSERT_EQ(tempv, "enddd");
+}
+
+// Exhaustive test of Set function
+TEST(RedisListsTest, SetTest) {
+  RedisLists redis(kDefaultDbName, options, true);
+
+  string tempv; // Used below for all Index(), PopRight(), PopLeft()
+
+  // Set on empty list (return false, and do not crash)
+  ASSERT_EQ(redis.Set("k1", 7, "a"), false);
+  ASSERT_EQ(redis.Set("k1", 0, "a"), false);
+  ASSERT_EQ(redis.Set("k1", -49, "cx"), false);
+  ASSERT_EQ(redis.Length("k1"), 0);
+
+  // Push some preliminary stuff [g, f, e, d, c, b, a]
+  redis.PushLeft("k1", "a");
+  redis.PushLeft("k1", "b");
+  redis.PushLeft("k1", "c");
+  redis.PushLeft("k1", "d");
+  redis.PushLeft("k1", "e");
+  redis.PushLeft("k1", "f");
+  redis.PushLeft("k1", "g");
+  ASSERT_EQ(redis.Length("k1"), 7);
+
+  // Test Regular Set
+  ASSERT_TRUE(redis.Set("k1", 0, "0"));
+  ASSERT_TRUE(redis.Set("k1", 3, "3"));
+  ASSERT_TRUE(redis.Set("k1", 6, "6"));
+  ASSERT_TRUE(redis.Set("k1", 2, "2"));
+  ASSERT_TRUE(redis.Set("k1", 5, "5"));
+  ASSERT_TRUE(redis.Set("k1", 1, "1"));
+  ASSERT_TRUE(redis.Set("k1", 4, "4"));
+
+  ASSERT_EQ(redis.Length("k1"), 7); // Size should not change
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "0");
+  ASSERT_TRUE(redis.Index("k1", 1, &tempv));
+  ASSERT_EQ(tempv, "1");
+  ASSERT_TRUE(redis.Index("k1", 2, &tempv));
+  ASSERT_EQ(tempv, "2");
+  ASSERT_TRUE(redis.Index("k1", 3, &tempv));
+  ASSERT_EQ(tempv, "3");
+  ASSERT_TRUE(redis.Index("k1", 4, &tempv));
+  ASSERT_EQ(tempv, "4");
+  ASSERT_TRUE(redis.Index("k1", 5, &tempv));
+  ASSERT_EQ(tempv, "5");
+  ASSERT_TRUE(redis.Index("k1", 6, &tempv));
+  ASSERT_EQ(tempv, "6");
+
+  // Set with negative indices
+  ASSERT_TRUE(redis.Set("k1", -7, "a"));
+  ASSERT_TRUE(redis.Set("k1", -4, "d"));
+  ASSERT_TRUE(redis.Set("k1", -1, "g"));
+  ASSERT_TRUE(redis.Set("k1", -5, "c"));
+  ASSERT_TRUE(redis.Set("k1", -2, "f"));
+  ASSERT_TRUE(redis.Set("k1", -6, "b"));
+  ASSERT_TRUE(redis.Set("k1", -3, "e"));
+
+  ASSERT_EQ(redis.Length("k1"), 7); // Size should not change
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "a");
+  ASSERT_TRUE(redis.Index("k1", 1, &tempv));
+  ASSERT_EQ(tempv, "b");
+  ASSERT_TRUE(redis.Index("k1", 2, &tempv));
+  ASSERT_EQ(tempv, "c");
+  ASSERT_TRUE(redis.Index("k1", 3, &tempv));
+  ASSERT_EQ(tempv, "d");
+  ASSERT_TRUE(redis.Index("k1", 4, &tempv));
+  ASSERT_EQ(tempv, "e");
+  ASSERT_TRUE(redis.Index("k1", 5, &tempv));
+  ASSERT_EQ(tempv, "f");
+  ASSERT_TRUE(redis.Index("k1", 6, &tempv));
+  ASSERT_EQ(tempv, "g");
+
+  // Bad indices (just out-of-bounds / off-by-one check)
+  ASSERT_EQ(redis.Set("k1", -8, "off-by-one in negative index"), false);
+  ASSERT_EQ(redis.Set("k1", 7, "off-by-one-error in positive index"), false);
+  ASSERT_EQ(redis.Set("k1", 43892, "big random index should fail"), false);
+  ASSERT_EQ(redis.Set("k1", -21391, "large negative index should fail"), false);
+
+  // One last check (to make sure nothing weird happened)
+  ASSERT_EQ(redis.Length("k1"), 7); // Size should not change
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "a");
+  ASSERT_TRUE(redis.Index("k1", 1, &tempv));
+  ASSERT_EQ(tempv, "b");
+  ASSERT_TRUE(redis.Index("k1", 2, &tempv));
+  ASSERT_EQ(tempv, "c");
+  ASSERT_TRUE(redis.Index("k1", 3, &tempv));
+  ASSERT_EQ(tempv, "d");
+  ASSERT_TRUE(redis.Index("k1", 4, &tempv));
+  ASSERT_EQ(tempv, "e");
+  ASSERT_TRUE(redis.Index("k1", 5, &tempv));
+  ASSERT_EQ(tempv, "f");
+  ASSERT_TRUE(redis.Index("k1", 6, &tempv));
+  ASSERT_EQ(tempv, "g");
+}
+
+// Testing Insert, Push, and Set, in a mixed environment
+TEST(RedisListsTest, InsertPushSetTest) {
+  RedisLists redis(kDefaultDbName, options, true);   // Destructive
+
+  string tempv; // Used below for all Index(), PopRight(), PopLeft()
+
+  // A series of pushes and insertions
+  // Will result in [newbegin, z, a, aftera, x, newend]
+  // Also, check the return value sometimes (should return length)
+  int lengthCheck;
+  lengthCheck = redis.PushLeft("k1", "a");
+  ASSERT_EQ(lengthCheck, 1);
+  redis.PushLeft("k1", "z");
+  redis.PushRight("k1", "x");
+  lengthCheck = redis.InsertAfter("k1", "a", "aftera");
+  ASSERT_EQ(lengthCheck , 4);
+  redis.InsertBefore("k1", "z", "newbegin");  // InsertBefore beginning of list
+  redis.InsertAfter("k1", "x", "newend");     // InsertAfter end of list
+
+  // Check
+  std::vector<std::string> res = redis.Range("k1", 0, -1); // Get the list
+  ASSERT_EQ((int)res.size(), 6);
+  ASSERT_EQ(res[0], "newbegin");
+  ASSERT_EQ(res[5], "newend");
+  ASSERT_EQ(res[3], "aftera");
+
+  // Testing duplicate values/pivots (multiple occurrences of 'a')
+  ASSERT_TRUE(redis.Set("k1", 0, "a"));     // [a, z, a, aftera, x, newend]
+  redis.InsertAfter("k1", "a", "happy");    // [a, happy, z, a, aftera, ...]
+  ASSERT_TRUE(redis.Index("k1", 1, &tempv));
+  ASSERT_EQ(tempv, "happy");
+  redis.InsertBefore("k1", "a", "sad");     // [sad, a, happy, z, a, aftera, ...]
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "sad");
+  ASSERT_TRUE(redis.Index("k1", 2, &tempv));
+  ASSERT_EQ(tempv, "happy");
+  ASSERT_TRUE(redis.Index("k1", 5, &tempv));
+  ASSERT_EQ(tempv, "aftera");
+  redis.InsertAfter("k1", "a", "zz");         // [sad, a, zz, happy, z, a, aftera, ...]
+  ASSERT_TRUE(redis.Index("k1", 2, &tempv));
+  ASSERT_EQ(tempv, "zz");
+  ASSERT_TRUE(redis.Index("k1", 6, &tempv));
+  ASSERT_EQ(tempv, "aftera");
+  ASSERT_TRUE(redis.Set("k1", 1, "nota"));    // [sad, nota, zz, happy, z, a, ...]
+  redis.InsertBefore("k1", "a", "ba");        // [sad, nota, zz, happy, z, ba, a, ...]
+  ASSERT_TRUE(redis.Index("k1", 4, &tempv));
+  ASSERT_EQ(tempv, "z");
+  ASSERT_TRUE(redis.Index("k1", 5, &tempv));
+  ASSERT_EQ(tempv, "ba");
+  ASSERT_TRUE(redis.Index("k1", 6, &tempv));
+  ASSERT_EQ(tempv, "a");
+
+  // We currently have: [sad, nota, zz, happy, z, ba, a, aftera, x, newend]
+  // redis.Print("k1");   // manually check
+
+  // Test Inserting before/after non-existent values
+  lengthCheck = redis.Length("k1"); // Ensure that the length doesnt change
+  ASSERT_EQ(lengthCheck, 10);
+  ASSERT_EQ(redis.InsertBefore("k1", "non-exist", "randval"), lengthCheck);
+  ASSERT_EQ(redis.InsertAfter("k1", "nothing", "a"), lengthCheck);
+  ASSERT_EQ(redis.InsertAfter("randKey", "randVal", "ranValue"), 0); // Empty
+  ASSERT_EQ(redis.Length("k1"), lengthCheck); // The length should not change
+
+  // Simply Test the Set() function
+  redis.Set("k1", 5, "ba2");
+  redis.InsertBefore("k1", "ba2", "beforeba2");
+  ASSERT_TRUE(redis.Index("k1", 4, &tempv));
+  ASSERT_EQ(tempv, "z");
+  ASSERT_TRUE(redis.Index("k1", 5, &tempv));
+  ASSERT_EQ(tempv, "beforeba2");
+  ASSERT_TRUE(redis.Index("k1", 6, &tempv));
+  ASSERT_EQ(tempv, "ba2");
+  ASSERT_TRUE(redis.Index("k1", 7, &tempv));
+  ASSERT_EQ(tempv, "a");
+
+  // We have: [sad, nota, zz, happy, z, beforeba2, ba2, a, aftera, x, newend]
+
+  // Set() with negative indices
+  redis.Set("k1", -1, "endprank");
+  ASSERT_TRUE(!redis.Index("k1", 11, &tempv));
+  ASSERT_TRUE(redis.Index("k1", 10, &tempv));
+  ASSERT_EQ(tempv, "endprank"); // Ensure Set worked correctly
+  redis.Set("k1", -11, "t");
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "t");
+
+  // Test out of bounds Set
+  ASSERT_EQ(redis.Set("k1", -12, "ssd"), false);
+  ASSERT_EQ(redis.Set("k1", 11, "sasd"), false);
+  ASSERT_EQ(redis.Set("k1", 1200, "big"), false);
+}
+
+// Testing Trim, Pop
+TEST(RedisListsTest, TrimPopTest) {
+  RedisLists redis(kDefaultDbName, options, true);   // Destructive
+
+  string tempv; // Used below for all Index(), PopRight(), PopLeft()
+
+  // A series of pushes and insertions
+  // Will result in [newbegin, z, a, aftera, x, newend]
+  redis.PushLeft("k1", "a");
+  redis.PushLeft("k1", "z");
+  redis.PushRight("k1", "x");
+  redis.InsertBefore("k1", "z", "newbegin");    // InsertBefore start of list
+  redis.InsertAfter("k1", "x", "newend");       // InsertAfter end of list
+  redis.InsertAfter("k1", "a", "aftera");
+
+  // Simple PopLeft/Right test
+  ASSERT_TRUE(redis.PopLeft("k1", &tempv));
+  ASSERT_EQ(tempv, "newbegin");
+  ASSERT_EQ(redis.Length("k1"), 5);
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "z");
+  ASSERT_TRUE(redis.PopRight("k1", &tempv));
+  ASSERT_EQ(tempv, "newend");
+  ASSERT_EQ(redis.Length("k1"), 4);
+  ASSERT_TRUE(redis.Index("k1", -1, &tempv));
+  ASSERT_EQ(tempv, "x");
+
+  // Now have: [z, a, aftera, x]
+
+  // Test Trim
+  ASSERT_TRUE(redis.Trim("k1", 0, -1));       // [z, a, aftera, x] (do nothing)
+  ASSERT_EQ(redis.Length("k1"), 4);
+  ASSERT_TRUE(redis.Trim("k1", 0, 2));                     // [z, a, aftera]
+  ASSERT_EQ(redis.Length("k1"), 3);
+  ASSERT_TRUE(redis.Index("k1", -1, &tempv));
+  ASSERT_EQ(tempv, "aftera");
+  ASSERT_TRUE(redis.Trim("k1", 1, 1));                     // [a]
+  ASSERT_EQ(redis.Length("k1"), 1);
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "a");
+
+  // Test out of bounds (empty) trim
+  ASSERT_TRUE(redis.Trim("k1", 1, 0));
+  ASSERT_EQ(redis.Length("k1"), 0);
+
+  // Popping with empty list (return empty without error)
+  ASSERT_TRUE(!redis.PopLeft("k1", &tempv));
+  ASSERT_TRUE(!redis.PopRight("k1", &tempv));
+  ASSERT_TRUE(redis.Trim("k1", 0, 5));
+
+  // Exhaustive Trim test (negative and invalid indices)
+  // Will start in [newbegin, z, a, aftera, x, newend]
+  redis.PushLeft("k1", "a");
+  redis.PushLeft("k1", "z");
+  redis.PushRight("k1", "x");
+  redis.InsertBefore("k1", "z", "newbegin");    // InsertBefore start of list
+  redis.InsertAfter("k1", "x", "newend");       // InsertAfter end of list
+  redis.InsertAfter("k1", "a", "aftera");
+  ASSERT_TRUE(redis.Trim("k1", -6, -1));                     // Should do nothing
+  ASSERT_EQ(redis.Length("k1"), 6);
+  ASSERT_TRUE(redis.Trim("k1", 1, -2));
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "z");
+  ASSERT_TRUE(redis.Index("k1", 3, &tempv));
+  ASSERT_EQ(tempv, "x");
+  ASSERT_EQ(redis.Length("k1"), 4);
+  ASSERT_TRUE(redis.Trim("k1", -3, -2));
+  ASSERT_EQ(redis.Length("k1"), 2);
+}
+
+// Testing Remove, RemoveFirst, RemoveLast
+TEST(RedisListsTest, RemoveTest) {
+  RedisLists redis(kDefaultDbName, options, true);   // Destructive
+
+  string tempv; // Used below for all Index(), PopRight(), PopLeft()
+
+  // A series of pushes and insertions
+  // Will result in [newbegin, z, a, aftera, x, newend, a, a]
+  redis.PushLeft("k1", "a");
+  redis.PushLeft("k1", "z");
+  redis.PushRight("k1", "x");
+  redis.InsertBefore("k1", "z", "newbegin");    // InsertBefore start of list
+  redis.InsertAfter("k1", "x", "newend");       // InsertAfter end of list
+  redis.InsertAfter("k1", "a", "aftera");
+  redis.PushRight("k1", "a");
+  redis.PushRight("k1", "a");
+
+  // Verify
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "newbegin");
+  ASSERT_TRUE(redis.Index("k1", -1, &tempv));
+  ASSERT_EQ(tempv, "a");
+
+  // Check RemoveFirst (Remove the first two 'a')
+  // Results in [newbegin, z, aftera, x, newend, a]
+  int numRemoved = redis.Remove("k1", 2, "a");
+  ASSERT_EQ(numRemoved, 2);
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "newbegin");
+  ASSERT_TRUE(redis.Index("k1", 1, &tempv));
+  ASSERT_EQ(tempv, "z");
+  ASSERT_TRUE(redis.Index("k1", 4, &tempv));
+  ASSERT_EQ(tempv, "newend");
+  ASSERT_TRUE(redis.Index("k1", 5, &tempv));
+  ASSERT_EQ(tempv, "a");
+  ASSERT_EQ(redis.Length("k1"), 6);
+
+  // Repopulate some stuff
+  // Results in: [x, x, x, x, x, newbegin, z, x, aftera, x, newend, a, x]
+  redis.PushLeft("k1", "x");
+  redis.PushLeft("k1", "x");
+  redis.PushLeft("k1", "x");
+  redis.PushLeft("k1", "x");
+  redis.PushLeft("k1", "x");
+  redis.PushRight("k1", "x");
+  redis.InsertAfter("k1", "z", "x");
+
+  // Test removal from end
+  numRemoved = redis.Remove("k1", -2, "x");
+  ASSERT_EQ(numRemoved, 2);
+  ASSERT_TRUE(redis.Index("k1", 8, &tempv));
+  ASSERT_EQ(tempv, "aftera");
+  ASSERT_TRUE(redis.Index("k1", 9, &tempv));
+  ASSERT_EQ(tempv, "newend");
+  ASSERT_TRUE(redis.Index("k1", 10, &tempv));
+  ASSERT_EQ(tempv, "a");
+  ASSERT_TRUE(!redis.Index("k1", 11, &tempv));
+  numRemoved = redis.Remove("k1", -2, "x");
+  ASSERT_EQ(numRemoved, 2);
+  ASSERT_TRUE(redis.Index("k1", 4, &tempv));
+  ASSERT_EQ(tempv, "newbegin");
+  ASSERT_TRUE(redis.Index("k1", 6, &tempv));
+  ASSERT_EQ(tempv, "aftera");
+
+  // We now have: [x, x, x, x, newbegin, z, aftera, newend, a]
+  ASSERT_EQ(redis.Length("k1"), 9);
+  ASSERT_TRUE(redis.Index("k1", -1, &tempv));
+  ASSERT_EQ(tempv, "a");
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "x");
+
+  // Test over-shooting (removing more than there exists)
+  numRemoved = redis.Remove("k1", -9000, "x");
+  ASSERT_EQ(numRemoved , 4);    // Only really removed 4
+  ASSERT_EQ(redis.Length("k1"), 5);
+  ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+  ASSERT_EQ(tempv, "newbegin");
+  numRemoved = redis.Remove("k1", 1, "x");
+  ASSERT_EQ(numRemoved, 0);
+
+  // Try removing ALL!
+  numRemoved = redis.Remove("k1", 0, "newbegin");   // REMOVE 0 will remove all!
+  ASSERT_EQ(numRemoved, 1);
+
+  // Removal from an empty-list
+  ASSERT_TRUE(redis.Trim("k1", 1, 0));
+  numRemoved = redis.Remove("k1", 1, "z");
+  ASSERT_EQ(numRemoved, 0);
+}
+
+
+// Test Multiple keys and Persistence
+TEST(RedisListsTest, PersistenceMultiKeyTest) {
+
+  string tempv; // Used below for all Index(), PopRight(), PopLeft()
+
+  // Block one: populate a single key in the database
+  {
+    RedisLists redis(kDefaultDbName, options, true);   // Destructive
+
+    // A series of pushes and insertions
+    // Will result in [newbegin, z, a, aftera, x, newend, a, a]
+    redis.PushLeft("k1", "a");
+    redis.PushLeft("k1", "z");
+    redis.PushRight("k1", "x");
+    redis.InsertBefore("k1", "z", "newbegin");    // InsertBefore start of list
+    redis.InsertAfter("k1", "x", "newend");       // InsertAfter end of list
+    redis.InsertAfter("k1", "a", "aftera");
+    redis.PushRight("k1", "a");
+    redis.PushRight("k1", "a");
+
+    ASSERT_TRUE(redis.Index("k1", 3, &tempv));
+    ASSERT_EQ(tempv, "aftera");
+  }
+
+  // Block two: make sure changes were saved and add some other key
+  {
+    RedisLists redis(kDefaultDbName, options, false); // Persistent, non-destructive
+
+    // Check
+    ASSERT_EQ(redis.Length("k1"), 8);
+    ASSERT_TRUE(redis.Index("k1", 3, &tempv));
+    ASSERT_EQ(tempv, "aftera");
+
+    redis.PushRight("k2", "randomkey");
+    redis.PushLeft("k2", "sas");
+
+    redis.PopLeft("k1", &tempv);
+  }
+
+  // Block three: Verify the changes from block 2
+  {
+    RedisLists redis(kDefaultDbName, options, false); // Presistent, non-destructive
+
+    // Check
+    ASSERT_EQ(redis.Length("k1"), 7);
+    ASSERT_EQ(redis.Length("k2"), 2);
+    ASSERT_TRUE(redis.Index("k1", 0, &tempv));
+    ASSERT_EQ(tempv, "z");
+    ASSERT_TRUE(redis.Index("k2", -2, &tempv));
+    ASSERT_EQ(tempv, "sas");
+  }
+}
+
+/// THE manual REDIS TEST begins here
+/// THIS WILL ONLY OCCUR IF YOU RUN: ./redis_test -m
+
+void MakeUpper(std::string* const s) {
+  int len = s->length();
+  for(int i=0; i<len; ++i) {
+    (*s)[i] = toupper((*s)[i]); // C-version defined in <ctype.h>
+  }
+}
+
+/// Allows the user to enter in REDIS commands into the command-line.
+/// This is useful for manual / interacticve testing / debugging.
+///  Use destructive=true to clean the database before use.
+///  Use destructive=false to remember the previous state (i.e.: persistent)
+/// Should be called from main function.
+int manual_redis_test(bool destructive){
+  RedisLists redis(RedisListsTest::kDefaultDbName,
+                   RedisListsTest::options,
+                   destructive);
+
+  // TODO: Right now, please use spaces to separate each word.
+  //  In actual redis, you can use quotes to specify compound values
+  //  Example: RPUSH mylist "this is a compound value"
+
+  std::string command;
+  while(true) {
+    cin >> command;
+    MakeUpper(&command);
+
+    if (command == "LINSERT") {
+      std::string k, t, p, v;
+      cin >> k >> t >> p >> v;
+      MakeUpper(&t);
+      if (t=="BEFORE") {
+        std::cout << redis.InsertBefore(k, p, v) << std::endl;
+      } else if (t=="AFTER") {
+        std::cout << redis.InsertAfter(k, p, v) << std::endl;
+      }
+    } else if (command == "LPUSH") {
+      std::string k, v;
+      std::cin >> k >> v;
+      redis.PushLeft(k, v);
+    } else if (command == "RPUSH") {
+      std::string k, v;
+      std::cin >> k >> v;
+      redis.PushRight(k, v);
+    } else if (command == "LPOP") {
+      std::string k;
+      std::cin >> k;
+      string res;
+      redis.PopLeft(k, &res);
+      std::cout << res << std::endl;
+    } else if (command == "RPOP") {
+      std::string k;
+      std::cin >> k;
+      string res;
+      redis.PopRight(k, &res);
+      std::cout << res << std::endl;
+    } else if (command == "LREM") {
+      std::string k;
+      int amt;
+      std::string v;
+
+      std::cin >> k >> amt >> v;
+      std::cout << redis.Remove(k, amt, v) << std::endl;
+    } else if (command == "LLEN") {
+      std::string k;
+      std::cin >> k;
+      std::cout << redis.Length(k) << std::endl;
+    } else if (command == "LRANGE") {
+      std::string k;
+      int i, j;
+      std::cin >> k >> i >> j;
+      std::vector<std::string> res = redis.Range(k, i, j);
+      for (auto it = res.begin(); it != res.end(); ++it) {
+        std::cout << " " << (*it);
+      }
+      std::cout << std::endl;
+    } else if (command == "LTRIM") {
+      std::string k;
+      int i, j;
+      std::cin >> k >> i >> j;
+      redis.Trim(k, i, j);
+    } else if (command == "LSET") {
+      std::string k;
+      int idx;
+      std::string v;
+      cin >> k >> idx >> v;
+      redis.Set(k, idx, v);
+    } else if (command == "LINDEX") {
+      std::string k;
+      int idx;
+      std::cin >> k >> idx;
+      string res;
+      redis.Index(k, idx, &res);
+      std::cout << res << std::endl;
+    } else if (command == "PRINT") {      // Added by Deon
+      std::string k;
+      cin >> k;
+      redis.Print(k);
+    } else if (command == "QUIT") {
+      return 0;
+    } else {
+      std::cout << "unknown command: " << command << std::endl;
+    }
+  }
+}
+
+} // namespace rocksdb
+
+
+// USAGE: "./redis_test" for default (unit tests)
+//        "./redis_test -m" for manual testing (redis command api)
+//        "./redis_test -m -d" for destructive manual test (erase db before use)
+
+
+// Check for "want" argument in the argument list
+bool found_arg(int argc, char* argv[], const char* want){
+  for(int i=1; i<argc; ++i){
+    if (strcmp(argv[i], want) == 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Will run unit tests.
+// However, if -m is specified, it will do user manual/interactive testing
+// -m -d is manual and destructive (will clear the database before use)
+int main(int argc, char* argv[]) {
+  if (found_arg(argc, argv, "-m")) {
+    bool destructive = found_arg(argc, argv, "-d");
+    return rocksdb::manual_redis_test(destructive);
+  } else {
+    return rocksdb::test::RunAllTests();
+  }
+}
+
diff --git a/utilities/ttl/db_ttl.cc b/utilities/ttl/db_ttl.cc
new file mode 100644 (file)
index 0000000..d8843d1
--- /dev/null
@@ -0,0 +1,296 @@
+// 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 "utilities/ttl/db_ttl.h"
+#include "db/filename.h"
+#include "util/coding.h"
+#include "include/rocksdb/env.h"
+#include "include/rocksdb/iterator.h"
+
+namespace rocksdb {
+
+// Open the db inside DBWithTTL because options needs pointer to its ttl
+DBWithTTL::DBWithTTL(const int32_t ttl,
+                     const Options& options,
+                     const std::string& dbname,
+                     Status& st,
+                     bool read_only)
+    : StackableDB(nullptr) {
+  Options options_to_open = options;
+
+  if (options.compaction_filter) {
+    ttl_comp_filter_.reset(
+        new TtlCompactionFilter(ttl, options.compaction_filter));
+    options_to_open.compaction_filter = ttl_comp_filter_.get();
+  } else {
+    options_to_open.compaction_filter_factory =
+      std::shared_ptr<CompactionFilterFactory>(
+          new TtlCompactionFilterFactory(
+            ttl, options.compaction_filter_factory));
+  }
+
+  if (options.merge_operator) {
+    options_to_open.merge_operator.reset(
+      new TtlMergeOperator(options.merge_operator));
+  }
+
+  if (read_only) {
+    st = DB::OpenForReadOnly(options_to_open, dbname, &db_);
+  } else {
+    st = DB::Open(options_to_open, dbname, &db_);
+  }
+}
+
+DBWithTTL::~DBWithTTL() {
+  delete db_;
+}
+
+Status UtilityDB::OpenTtlDB(
+    const Options& options,
+    const std::string& dbname,
+    StackableDB** dbptr,
+    int32_t ttl,
+    bool read_only) {
+  Status st;
+  *dbptr = new DBWithTTL(ttl, options, dbname, st, read_only);
+  if (!st.ok()) {
+    delete *dbptr;
+  }
+  return st;
+}
+
+// Gives back the current time
+Status DBWithTTL::GetCurrentTime(int32_t& curtime) {
+  return Env::Default()->GetCurrentTime((int64_t*)&curtime);
+}
+
+// Appends the current timestamp to the string.
+// Returns false if could not get the current_time, true if append succeeds
+Status DBWithTTL::AppendTS(const Slice& val, std::string& val_with_ts) {
+  val_with_ts.reserve(kTSLength + val.size());
+  char ts_string[kTSLength];
+  int32_t curtime;
+  Status st = GetCurrentTime(curtime);
+  if (!st.ok()) {
+    return st;
+  }
+  EncodeFixed32(ts_string, curtime);
+  val_with_ts.append(val.data(), val.size());
+  val_with_ts.append(ts_string, kTSLength);
+  return st;
+}
+
+// Returns corruption if the length of the string is lesser than timestamp, or
+// timestamp refers to a time lesser than ttl-feature release time
+Status DBWithTTL::SanityCheckTimestamp(const Slice& str) {
+  if (str.size() < kTSLength) {
+    return Status::Corruption("Error: value's length less than timestamp's\n");
+  }
+  // Checks that TS is not lesser than kMinTimestamp
+  // Gaurds against corruption & normal database opened incorrectly in ttl mode
+  int32_t timestamp_value =
+    DecodeFixed32(str.data() + str.size() - kTSLength);
+  if (timestamp_value < kMinTimestamp){
+    return Status::Corruption("Error: Timestamp < ttl feature release time!\n");
+  }
+  return Status::OK();
+}
+
+// Checks if the string is stale or not according to TTl provided
+bool DBWithTTL::IsStale(const Slice& value, int32_t ttl) {
+  if (ttl <= 0) { // Data is fresh if TTL is non-positive
+    return false;
+  }
+  int32_t curtime;
+  if (!GetCurrentTime(curtime).ok()) {
+    return false; // Treat the data as fresh if could not get current time
+  }
+  int32_t timestamp_value =
+    DecodeFixed32(value.data() + value.size() - kTSLength);
+  return (timestamp_value + ttl) < curtime;
+}
+
+// Strips the TS from the end of the string
+Status DBWithTTL::StripTS(std::string* str) {
+  Status st;
+  if (str->length() < kTSLength) {
+    return Status::Corruption("Bad timestamp in key-value");
+  }
+  // Erasing characters which hold the TS
+  str->erase(str->length() - kTSLength, kTSLength);
+  return st;
+}
+
+Status DBWithTTL::Put(
+    const WriteOptions& opt,
+    const Slice& key,
+    const Slice& val) {
+  WriteBatch batch;
+  batch.Put(key, val);
+  return Write(opt, &batch);
+}
+
+Status DBWithTTL::Get(const ReadOptions& options,
+                      const Slice& key,
+                      std::string* value) {
+  Status st = db_->Get(options, key, value);
+  if (!st.ok()) {
+    return st;
+  }
+  st = SanityCheckTimestamp(*value);
+  if (!st.ok()) {
+    return st;
+  }
+  return StripTS(value);
+}
+
+std::vector<Status> DBWithTTL::MultiGet(const ReadOptions& options,
+                                        const std::vector<Slice>& keys,
+                                        std::vector<std::string>* values) {
+  return std::vector<Status>(keys.size(),
+                             Status::NotSupported("MultiGet not\
+                               supported with TTL"));
+}
+
+bool DBWithTTL::KeyMayExist(const ReadOptions& options,
+                            const Slice& key,
+                            std::string* value,
+                            bool* value_found) {
+  bool ret = db_->KeyMayExist(options, key, value, value_found);
+  if (ret && value != nullptr && value_found != nullptr && *value_found) {
+    if (!SanityCheckTimestamp(*value).ok() || !StripTS(value).ok()) {
+      return false;
+    }
+  }
+  return ret;
+}
+
+Status DBWithTTL::Delete(const WriteOptions& wopts, const Slice& key) {
+  return db_->Delete(wopts, key);
+}
+
+Status DBWithTTL::Merge(const WriteOptions& opt,
+                        const Slice& key,
+                        const Slice& value) {
+  WriteBatch batch;
+  batch.Merge(key, value);
+  return Write(opt, &batch);
+}
+
+Status DBWithTTL::Write(const WriteOptions& opts, WriteBatch* updates) {
+  class Handler : public WriteBatch::Handler {
+   public:
+    WriteBatch updates_ttl;
+    Status batch_rewrite_status;
+    virtual void Put(const Slice& key, const Slice& value) {
+      std::string value_with_ts;
+      Status st = AppendTS(value, value_with_ts);
+      if (!st.ok()) {
+        batch_rewrite_status = st;
+      } else {
+        updates_ttl.Put(key, value_with_ts);
+      }
+    }
+    virtual void Merge(const Slice& key, const Slice& value) {
+      std::string value_with_ts;
+      Status st = AppendTS(value, value_with_ts);
+      if (!st.ok()) {
+        batch_rewrite_status = st;
+      } else {
+        updates_ttl.Merge(key, value_with_ts);
+      }
+    }
+    virtual void Delete(const Slice& key) {
+      updates_ttl.Delete(key);
+    }
+    virtual void LogData(const Slice& blob) {
+      updates_ttl.PutLogData(blob);
+    }
+  };
+  Handler handler;
+  updates->Iterate(&handler);
+  if (!handler.batch_rewrite_status.ok()) {
+    return handler.batch_rewrite_status;
+  } else {
+    return db_->Write(opts, &(handler.updates_ttl));
+  }
+}
+
+Iterator* DBWithTTL::NewIterator(const ReadOptions& opts) {
+  return new TtlIterator(db_->NewIterator(opts));
+}
+
+const Snapshot* DBWithTTL::GetSnapshot() {
+  return db_->GetSnapshot();
+}
+
+void DBWithTTL::ReleaseSnapshot(const Snapshot* snapshot) {
+  db_->ReleaseSnapshot(snapshot);
+}
+
+bool DBWithTTL::GetProperty(const Slice& property, std::string* value) {
+  return db_->GetProperty(property, value);
+}
+
+void DBWithTTL::GetApproximateSizes(const Range* r, int n, uint64_t* sizes) {
+  db_->GetApproximateSizes(r, n, sizes);
+}
+
+void DBWithTTL::CompactRange(const Slice* begin, const Slice* end,
+                             bool reduce_level, int target_level) {
+  db_->CompactRange(begin, end, reduce_level, target_level);
+}
+
+int DBWithTTL::NumberLevels() {
+  return db_->NumberLevels();
+}
+
+int DBWithTTL::MaxMemCompactionLevel() {
+  return db_->MaxMemCompactionLevel();
+}
+
+int DBWithTTL::Level0StopWriteTrigger() {
+  return db_->Level0StopWriteTrigger();
+}
+
+Status DBWithTTL::Flush(const FlushOptions& fopts) {
+  return db_->Flush(fopts);
+}
+
+Status DBWithTTL::DisableFileDeletions() {
+  return db_->DisableFileDeletions();
+}
+
+Status DBWithTTL::EnableFileDeletions() {
+  return db_->EnableFileDeletions();
+}
+
+Status DBWithTTL::GetLiveFiles(std::vector<std::string>& vec, uint64_t* mfs,
+                               bool flush_memtable) {
+  return db_->GetLiveFiles(vec, mfs, flush_memtable);
+}
+
+SequenceNumber DBWithTTL::GetLatestSequenceNumber() const {
+  return db_->GetLatestSequenceNumber();
+}
+
+Status DBWithTTL::GetSortedWalFiles(VectorLogPtr& files) {
+  return db_->GetSortedWalFiles(files);
+}
+
+Status DBWithTTL::DeleteFile(std::string name) {
+  return db_->DeleteFile(name);
+}
+
+Status DBWithTTL::GetUpdatesSince(
+    SequenceNumber seq_number,
+    unique_ptr<TransactionLogIterator>* iter) {
+  return db_->GetUpdatesSince(seq_number, iter);
+}
+
+void DBWithTTL::TEST_Destroy_DBWithTtl() {
+  ((DBImpl*) db_)->TEST_Destroy_DBImpl();
+}
+
+}  // namespace rocksdb
diff --git a/utilities/ttl/db_ttl.h b/utilities/ttl/db_ttl.h
new file mode 100644 (file)
index 0000000..ee6382b
--- /dev/null
@@ -0,0 +1,362 @@
+// 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.
+
+#pragma once
+#include "rocksdb/db.h"
+#include "rocksdb/env.h"
+#include "rocksdb/compaction_filter.h"
+#include "rocksdb/merge_operator.h"
+#include "utilities/utility_db.h"
+#include "db/db_impl.h"
+
+namespace rocksdb {
+
+class DBWithTTL : public StackableDB {
+ public:
+  DBWithTTL(const int32_t ttl,
+            const Options& options,
+            const std::string& dbname,
+            Status& st,
+            bool read_only);
+
+  virtual ~DBWithTTL();
+
+  virtual Status Put(const WriteOptions& o,
+                     const Slice& key,
+                     const Slice& val);
+
+  virtual Status Get(const ReadOptions& options,
+                     const Slice& key,
+                     std::string* value);
+
+  virtual std::vector<Status> MultiGet(const ReadOptions& options,
+                                       const std::vector<Slice>& keys,
+                                       std::vector<std::string>* values);
+
+  virtual bool KeyMayExist(const ReadOptions& options,
+                           const Slice& key,
+                           std::string* value,
+                           bool* value_found = nullptr) override;
+
+  virtual Status Delete(const WriteOptions& wopts, const Slice& key);
+
+  virtual Status Merge(const WriteOptions& options,
+                       const Slice& key,
+                       const Slice& value);
+
+
+  virtual Status Write(const WriteOptions& opts, WriteBatch* updates);
+
+  virtual Iterator* NewIterator(const ReadOptions& opts);
+
+  virtual const Snapshot* GetSnapshot();
+
+  virtual void ReleaseSnapshot(const Snapshot* snapshot);
+
+  virtual bool GetProperty(const Slice& property, std::string* value);
+
+  virtual void GetApproximateSizes(const Range* r, int n, uint64_t* sizes);
+
+  virtual void CompactRange(const Slice* begin, const Slice* end,
+                            bool reduce_level = false, int target_level = -1);
+
+  virtual int NumberLevels();
+
+  virtual int MaxMemCompactionLevel();
+
+  virtual int Level0StopWriteTrigger();
+
+  virtual Status Flush(const FlushOptions& fopts);
+
+  virtual Status DisableFileDeletions();
+
+  virtual Status EnableFileDeletions();
+
+  virtual Status GetLiveFiles(std::vector<std::string>& vec, uint64_t* mfs,
+                              bool flush_memtable = true);
+
+  virtual Status GetSortedWalFiles(VectorLogPtr& files);
+
+  virtual Status DeleteFile(std::string name);
+
+  virtual SequenceNumber GetLatestSequenceNumber() const;
+
+  virtual Status GetUpdatesSince(SequenceNumber seq_number,
+                                 unique_ptr<TransactionLogIterator>* iter);
+
+  // Simulate a db crash, no elegant closing of database.
+  void TEST_Destroy_DBWithTtl();
+
+  virtual DB* GetRawDB() {
+    return db_;
+  }
+
+  static bool IsStale(const Slice& value, int32_t ttl);
+
+  static Status AppendTS(const Slice& val, std::string& val_with_ts);
+
+  static Status SanityCheckTimestamp(const Slice& str);
+
+  static Status StripTS(std::string* str);
+
+  static Status GetCurrentTime(int32_t& curtime);
+
+  static const uint32_t kTSLength = sizeof(int32_t); // size of timestamp
+
+  static const int32_t kMinTimestamp = 1368146402; // 05/09/2013:5:40PM GMT-8
+
+  static const int32_t kMaxTimestamp = 2147483647; // 01/18/2038:7:14PM GMT-8
+
+ private:
+  DB* db_;
+  unique_ptr<CompactionFilter> ttl_comp_filter_;
+};
+
+class TtlIterator : public Iterator {
+
+ public:
+  explicit TtlIterator(Iterator* iter)
+    : iter_(iter) {
+    assert(iter_);
+  }
+
+  ~TtlIterator() {
+    delete iter_;
+  }
+
+  bool Valid() const {
+    return iter_->Valid();
+  }
+
+  void SeekToFirst() {
+    iter_->SeekToFirst();
+  }
+
+  void SeekToLast() {
+    iter_->SeekToLast();
+  }
+
+  void Seek(const Slice& target) {
+    iter_->Seek(target);
+  }
+
+  void Next() {
+    iter_->Next();
+  }
+
+  void Prev() {
+    iter_->Prev();
+  }
+
+  Slice key() const {
+    return iter_->key();
+  }
+
+  int32_t timestamp() const {
+    return DecodeFixed32(
+      iter_->value().data() + iter_->value().size() - DBWithTTL::kTSLength);
+  }
+
+  Slice value() const {
+    //TODO: handle timestamp corruption like in general iterator semantics
+    assert(DBWithTTL::SanityCheckTimestamp(iter_->value()).ok());
+    Slice trimmed_value = iter_->value();
+    trimmed_value.size_ -= DBWithTTL::kTSLength;
+    return trimmed_value;
+  }
+
+  Status status() const {
+    return iter_->status();
+  }
+
+ private:
+  Iterator* iter_;
+};
+
+class TtlCompactionFilter : public CompactionFilter {
+
+ public:
+  TtlCompactionFilter(
+      int32_t ttl,
+      const CompactionFilter* user_comp_filter,
+      std::unique_ptr<const CompactionFilter>
+      user_comp_filter_from_factory = nullptr)
+    : ttl_(ttl),
+      user_comp_filter_(user_comp_filter),
+      user_comp_filter_from_factory_(std::move(user_comp_filter_from_factory)) {
+    // Unlike the merge operator, compaction filter is necessary for TTL, hence
+    // this would be called even if user doesn't specify any compaction-filter
+    if (!user_comp_filter_) {
+      user_comp_filter_ = user_comp_filter_from_factory_.get();
+    }
+  }
+
+  virtual bool Filter(int level,
+                      const Slice& key,
+                      const Slice& old_val,
+                      std::string* new_val,
+                      bool* value_changed) const override {
+    if (DBWithTTL::IsStale(old_val, ttl_)) {
+      return true;
+    }
+    if (user_comp_filter_ == nullptr) {
+      return false;
+    }
+    assert(old_val.size() >= DBWithTTL::kTSLength);
+    Slice old_val_without_ts(old_val.data(),
+                             old_val.size() - DBWithTTL::kTSLength);
+    if (user_comp_filter_->Filter(level, key, old_val_without_ts, new_val,
+                                  value_changed)) {
+      return true;
+    }
+    if (*value_changed) {
+      new_val->append(old_val.data() + old_val.size() - DBWithTTL::kTSLength,
+                      DBWithTTL::kTSLength);
+    }
+    return false;
+  }
+
+  virtual const char* Name() const override {
+    return "Delete By TTL";
+  }
+
+ private:
+  int32_t ttl_;
+  const CompactionFilter* user_comp_filter_;
+  std::unique_ptr<const CompactionFilter> user_comp_filter_from_factory_;
+};
+
+class TtlCompactionFilterFactory : public CompactionFilterFactory {
+  public:
+    TtlCompactionFilterFactory(
+        int32_t ttl,
+        std::shared_ptr<CompactionFilterFactory> comp_filter_factory)
+    : ttl_(ttl),
+      user_comp_filter_factory_(comp_filter_factory) { }
+
+    virtual std::unique_ptr<CompactionFilter> CreateCompactionFilter(
+        const CompactionFilter::Context& context) {
+      return std::unique_ptr<TtlCompactionFilter>(
+        new TtlCompactionFilter(
+          ttl_,
+          nullptr,
+          std::move(user_comp_filter_factory_->CreateCompactionFilter(context))
+        )
+      );
+    }
+
+    virtual const char* Name() const override {
+      return "TtlCompactionFilterFactory";
+    }
+
+  private:
+    int32_t ttl_;
+    std::shared_ptr<CompactionFilterFactory> user_comp_filter_factory_;
+};
+
+class TtlMergeOperator : public MergeOperator {
+
+ public:
+  explicit TtlMergeOperator(const std::shared_ptr<MergeOperator> merge_op)
+    : user_merge_op_(merge_op) {
+    assert(merge_op);
+  }
+
+  virtual bool FullMerge(const Slice& key,
+                         const Slice* existing_value,
+                         const std::deque<std::string>& operands,
+                         std::string* new_value,
+                         Logger* logger) const override {
+    const uint32_t ts_len = DBWithTTL::kTSLength;
+    if (existing_value && existing_value->size() < ts_len) {
+      Log(logger, "Error: Could not remove timestamp from existing value.");
+      return false;
+    }
+
+    // Extract time-stamp from each operand to be passed to user_merge_op_
+    std::deque<std::string> operands_without_ts;
+    for (const auto &operand : operands) {
+      if (operand.size() < ts_len) {
+        Log(logger, "Error: Could not remove timestamp from operand value.");
+        return false;
+      }
+      operands_without_ts.push_back(operand.substr(0, operand.size() - ts_len));
+    }
+
+    // Apply the user merge operator (store result in *new_value)
+    bool good = true;
+    if (existing_value) {
+      Slice existing_value_without_ts(existing_value->data(),
+                                      existing_value->size() - ts_len);
+      good = user_merge_op_->FullMerge(key, &existing_value_without_ts,
+                                       operands_without_ts, new_value, logger);
+    } else {
+      good = user_merge_op_->FullMerge(key, nullptr, operands_without_ts,
+                                       new_value, logger);
+    }
+
+    // Return false if the user merge operator returned false
+    if (!good) {
+      return false;
+    }
+
+    // Augment the *new_value with the ttl time-stamp
+    int32_t curtime;
+    if (!DBWithTTL::GetCurrentTime(curtime).ok()) {
+      Log(logger, "Error: Could not get current time to be attached internally "
+                  "to the new value.");
+      return false;
+    } else {
+      char ts_string[ts_len];
+      EncodeFixed32(ts_string, curtime);
+      new_value->append(ts_string, ts_len);
+      return true;
+    }
+  }
+
+  virtual bool PartialMerge(const Slice& key,
+                            const Slice& left_operand,
+                            const Slice& right_operand,
+                            std::string* new_value,
+                            Logger* logger) const override {
+    const uint32_t ts_len = DBWithTTL::kTSLength;
+
+    if (left_operand.size() < ts_len || right_operand.size() < ts_len) {
+      Log(logger, "Error: Could not remove timestamp from value.");
+      return false;
+    }
+
+    // Apply the user partial-merge operator (store result in *new_value)
+    assert(new_value);
+    Slice left_without_ts(left_operand.data(), left_operand.size() - ts_len);
+    Slice right_without_ts(right_operand.data(), right_operand.size() - ts_len);
+    if (!user_merge_op_->PartialMerge(key, left_without_ts, right_without_ts,
+                                      new_value, logger)) {
+      return false;
+    }
+
+    // Augment the *new_value with the ttl time-stamp
+    int32_t curtime;
+    if (!DBWithTTL::GetCurrentTime(curtime).ok()) {
+      Log(logger, "Error: Could not get current time to be attached internally "
+                  "to the new value.");
+      return false;
+    } else {
+      char ts_string[ts_len];
+      EncodeFixed32(ts_string, curtime);
+      new_value->append(ts_string, ts_len);
+      return true;
+    }
+
+  }
+
+  virtual const char* Name() const override {
+    return "Merge By TTL";
+  }
+
+ private:
+  std::shared_ptr<MergeOperator> user_merge_op_;
+};
+
+}
diff --git a/utilities/ttl/ttl_test.cc b/utilities/ttl/ttl_test.cc
new file mode 100644 (file)
index 0000000..b5241f7
--- /dev/null
@@ -0,0 +1,505 @@
+// 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 <memory>
+#include "rocksdb/compaction_filter.h"
+#include "utilities/utility_db.h"
+#include "util/testharness.h"
+#include "util/logging.h"
+#include <map>
+#include <unistd.h>
+
+namespace rocksdb {
+
+namespace {
+
+typedef std::map<std::string, std::string> KVMap;
+
+enum BatchOperation {
+  PUT = 0,
+  DELETE = 1
+};
+
+}
+
+class TtlTest {
+ public:
+  TtlTest() {
+    dbname_ = test::TmpDir() + "/db_ttl";
+    options_.create_if_missing = true;
+    // ensure that compaction is kicked in to always strip timestamp from kvs
+    options_.max_grandparent_overlap_factor = 0;
+    // compaction should take place always from level0 for determinism
+    options_.max_mem_compaction_level = 0;
+    db_ttl_ = nullptr;
+    DestroyDB(dbname_, Options());
+  }
+
+  ~TtlTest() {
+    CloseTtl();
+    DestroyDB(dbname_, Options());
+  }
+
+  // Open database with TTL support when TTL not provided with db_ttl_ pointer
+  void OpenTtl() {
+    assert(db_ttl_ == nullptr); //  db should be closed before opening again
+    ASSERT_OK(UtilityDB::OpenTtlDB(options_, dbname_, &db_ttl_));
+  }
+
+  // Open database with TTL support when TTL provided with db_ttl_ pointer
+  void OpenTtl(int32_t ttl) {
+    assert(db_ttl_ == nullptr);
+    ASSERT_OK(UtilityDB::OpenTtlDB(options_, dbname_, &db_ttl_, ttl));
+  }
+
+  // Open with TestFilter compaction filter
+  void OpenTtlWithTestCompaction(int32_t ttl) {
+    options_.compaction_filter_factory =
+      std::shared_ptr<CompactionFilterFactory>(
+          new TestFilterFactory(kSampleSize_, kNewValue_));
+    OpenTtl(ttl);
+  }
+
+  // Open database with TTL support in read_only mode
+  void OpenReadOnlyTtl(int32_t ttl) {
+    assert(db_ttl_ == nullptr);
+    ASSERT_OK(UtilityDB::OpenTtlDB(options_, dbname_, &db_ttl_, ttl, true));
+  }
+
+  void CloseTtl() {
+    delete db_ttl_;
+    db_ttl_ = nullptr;
+  }
+
+  // Populates and returns a kv-map
+  void MakeKVMap(int64_t num_entries) {
+    kvmap_.clear();
+    int digits = 1;
+    for (int dummy = num_entries; dummy /= 10 ; ++digits);
+    int digits_in_i = 1;
+    for (int64_t i = 0; i < num_entries; i++) {
+      std::string key = "key";
+      std::string value = "value";
+      if (i % 10 == 0) {
+        digits_in_i++;
+      }
+      for(int j = digits_in_i; j < digits; j++) {
+        key.append("0");
+        value.append("0");
+      }
+      AppendNumberTo(&key, i);
+      AppendNumberTo(&value, i);
+      kvmap_[key] = value;
+    }
+    ASSERT_EQ((int)kvmap_.size(), num_entries);//check all insertions done
+  }
+
+  // Makes a write-batch with key-vals from kvmap_ and 'Write''s it
+  void MakePutWriteBatch(const BatchOperation* batch_ops, int num_ops) {
+    assert(num_ops <= (int)kvmap_.size());
+    static WriteOptions wopts;
+    static FlushOptions flush_opts;
+    WriteBatch batch;
+    kv_it_ = kvmap_.begin();
+    for (int i = 0; i < num_ops && kv_it_ != kvmap_.end(); i++, kv_it_++) {
+      switch (batch_ops[i]) {
+        case PUT:
+          batch.Put(kv_it_->first, kv_it_->second);
+          break;
+        case DELETE:
+          batch.Delete(kv_it_->first);
+          break;
+        default:
+          assert(false);
+      }
+    }
+    db_ttl_->Write(wopts, &batch);
+    db_ttl_->Flush(flush_opts);
+  }
+
+  // Puts num_entries starting from start_pos_map from kvmap_ into the database
+  void PutValues(int start_pos_map, int num_entries, bool flush = true) {
+    assert(db_ttl_);
+    ASSERT_LE(start_pos_map + num_entries, (int)kvmap_.size());
+    static WriteOptions wopts;
+    static FlushOptions flush_opts;
+    kv_it_ = kvmap_.begin();
+    advance(kv_it_, start_pos_map);
+    for (int i = 0; kv_it_ != kvmap_.end() && i < num_entries; i++, kv_it_++) {
+      ASSERT_OK(db_ttl_->Put(wopts, kv_it_->first, kv_it_->second));
+    }
+    // Put a mock kv at the end because CompactionFilter doesn't delete last key
+    ASSERT_OK(db_ttl_->Put(wopts, "keymock", "valuemock"));
+    if (flush) {
+      db_ttl_->Flush(flush_opts);
+    }
+  }
+
+  // Runs a manual compaction
+  void ManualCompact() {
+    db_ttl_->CompactRange(nullptr, nullptr);
+  }
+
+  // checks the whole kvmap_ to return correct values using KeyMayExist
+  void SimpleKeyMayExistCheck() {
+    static ReadOptions ropts;
+    bool value_found;
+    std::string val;
+    for(auto &kv : kvmap_) {
+      bool ret = db_ttl_->KeyMayExist(ropts, kv.first, &val, &value_found);
+      if (ret == false || value_found == false) {
+        fprintf(stderr, "KeyMayExist could not find key=%s in the database but"
+                        " should have\n", kv.first.c_str());
+        assert(false);
+      } else if (val.compare(kv.second) != 0) {
+        fprintf(stderr, " value for key=%s present in database is %s but"
+                        " should be %s\n", kv.first.c_str(), val.c_str(),
+                        kv.second.c_str());
+        assert(false);
+      }
+    }
+  }
+
+  // Sleeps for slp_tim then runs a manual compaction
+  // Checks span starting from st_pos from kvmap_ in the db and
+  // Gets should return true if check is true and false otherwise
+  // Also checks that value that we got is the same as inserted; and =kNewValue
+  //   if test_compaction_change is true
+  void SleepCompactCheck(int slp_tim, int st_pos, int span, bool check = true,
+                         bool test_compaction_change = false) {
+    assert(db_ttl_);
+    sleep(slp_tim);
+    ManualCompact();
+    static ReadOptions ropts;
+    kv_it_ = kvmap_.begin();
+    advance(kv_it_, st_pos);
+    std::string v;
+    for (int i = 0; kv_it_ != kvmap_.end() && i < span; i++, kv_it_++) {
+      Status s = db_ttl_->Get(ropts, kv_it_->first, &v);
+      if (s.ok() != check) {
+        fprintf(stderr, "key=%s ", kv_it_->first.c_str());
+        if (!s.ok()) {
+          fprintf(stderr, "is absent from db but was expected to be present\n");
+        } else {
+          fprintf(stderr, "is present in db but was expected to be absent\n");
+        }
+        assert(false);
+      } else if (s.ok()) {
+          if (test_compaction_change && v.compare(kNewValue_) != 0) {
+            fprintf(stderr, " value for key=%s present in database is %s but "
+                            " should be %s\n", kv_it_->first.c_str(), v.c_str(),
+                            kNewValue_.c_str());
+            assert(false);
+          } else if (!test_compaction_change && v.compare(kv_it_->second) !=0) {
+            fprintf(stderr, " value for key=%s present in database is %s but "
+                            " should be %s\n", kv_it_->first.c_str(), v.c_str(),
+                            kv_it_->second.c_str());
+            assert(false);
+          }
+      }
+    }
+  }
+
+  // Similar as SleepCompactCheck but uses TtlIterator to read from db
+  void SleepCompactCheckIter(int slp, int st_pos, int span, bool check=true) {
+    assert(db_ttl_);
+    sleep(slp);
+    ManualCompact();
+    static ReadOptions ropts;
+    Iterator *dbiter = db_ttl_->NewIterator(ropts);
+    kv_it_ = kvmap_.begin();
+    advance(kv_it_, st_pos);
+
+    dbiter->Seek(kv_it_->first);
+    if (!check) {
+      if (dbiter->Valid()) {
+        ASSERT_NE(dbiter->value().compare(kv_it_->second), 0);
+      }
+    } else {  // dbiter should have found out kvmap_[st_pos]
+      for (int i = st_pos;
+           kv_it_ != kvmap_.end() && i < st_pos + span;
+           i++, kv_it_++)  {
+        ASSERT_TRUE(dbiter->Valid());
+        ASSERT_EQ(dbiter->value().compare(kv_it_->second), 0);
+        dbiter->Next();
+      }
+    }
+    delete dbiter;
+  }
+
+  class TestFilter : public CompactionFilter {
+   public:
+    TestFilter(const int64_t kSampleSize, const std::string kNewValue)
+      : kSampleSize_(kSampleSize),
+        kNewValue_(kNewValue) {
+    }
+
+    // Works on keys of the form "key<number>"
+    // Drops key if number at the end of key is in [0, kSampleSize_/3),
+    // Keeps key if it is in [kSampleSize_/3, 2*kSampleSize_/3),
+    // Change value if it is in [2*kSampleSize_/3, kSampleSize_)
+    // Eg. kSampleSize_=6. Drop:key0-1...Keep:key2-3...Change:key4-5...
+    virtual bool Filter(int level, const Slice& key,
+                        const Slice& value, std::string* new_value,
+                        bool* value_changed) const override {
+      assert(new_value != nullptr);
+
+      std::string search_str = "0123456789";
+      std::string key_string = key.ToString();
+      size_t pos = key_string.find_first_of(search_str);
+      int num_key_end;
+      if (pos != std::string::npos) {
+        num_key_end = stoi(key_string.substr(pos, key.size() - pos));
+      } else {
+        return false; // Keep keys not matching the format "key<NUMBER>"
+      }
+
+      int partition = kSampleSize_ / 3;
+      if (num_key_end < partition) {
+        return true;
+      } else if (num_key_end < partition * 2) {
+        return false;
+      } else {
+        *new_value = kNewValue_;
+        *value_changed = true;
+        return false;
+      }
+    }
+
+    virtual const char* Name() const override {
+      return "TestFilter";
+    }
+
+   private:
+    const int64_t kSampleSize_;
+    const std::string kNewValue_;
+  };
+
+  class TestFilterFactory : public CompactionFilterFactory {
+    public:
+      TestFilterFactory(const int64_t kSampleSize, const std::string kNewValue)
+        : kSampleSize_(kSampleSize),
+          kNewValue_(kNewValue) {
+      }
+
+      virtual std::unique_ptr<CompactionFilter>
+      CreateCompactionFilter(
+          const CompactionFilter::Context& context) override {
+        return std::unique_ptr<CompactionFilter>(
+            new TestFilter(kSampleSize_, kNewValue_));
+      }
+
+      virtual const char* Name() const override {
+        return "TestFilterFactory";
+      }
+
+    private:
+      const int64_t kSampleSize_;
+      const std::string kNewValue_;
+  };
+
+
+  // Choose carefully so that Put, Gets & Compaction complete in 1 second buffer
+  const int64_t kSampleSize_ = 100;
+
+ private:
+  std::string dbname_;
+  StackableDB* db_ttl_;
+  Options options_;
+  KVMap kvmap_;
+  KVMap::iterator kv_it_;
+  const std::string kNewValue_ = "new_value";
+  unique_ptr<CompactionFilter> test_comp_filter_;
+}; // class TtlTest
+
+// If TTL is non positive or not provided, the behaviour is TTL = infinity
+// This test opens the db 3 times with such default behavior and inserts a
+// bunch of kvs each time. All kvs should accummulate in the db till the end
+// Partitions the sample-size provided into 3 sets over boundary1 and boundary2
+TEST(TtlTest, NoEffect) {
+  MakeKVMap(kSampleSize_);
+  int boundary1 = kSampleSize_ / 3;
+  int boundary2 = 2 * boundary1;
+
+  OpenTtl();
+  PutValues(0, boundary1);                       //T=0: Set1 never deleted
+  SleepCompactCheck(1, 0, boundary1);            //T=1: Set1 still there
+  CloseTtl();
+
+  OpenTtl(0);
+  PutValues(boundary1, boundary2 - boundary1);   //T=1: Set2 never deleted
+  SleepCompactCheck(1, 0, boundary2);            //T=2: Sets1 & 2 still there
+  CloseTtl();
+
+  OpenTtl(-1);
+  PutValues(boundary2, kSampleSize_ - boundary2); //T=3: Set3 never deleted
+  SleepCompactCheck(1, 0, kSampleSize_, true);    //T=4: Sets 1,2,3 still there
+  CloseTtl();
+}
+
+// Puts a set of values and checks its presence using Get during ttl
+TEST(TtlTest, PresentDuringTTL) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtl(2);                                 // T=0:Open the db with ttl = 2
+  PutValues(0, kSampleSize_);                  // T=0:Insert Set1. Delete at t=2
+  SleepCompactCheck(1, 0, kSampleSize_, true); // T=1:Set1 should still be there
+  CloseTtl();
+}
+
+// Puts a set of values and checks its absence using Get after ttl
+TEST(TtlTest, AbsentAfterTTL) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtl(1);                                  // T=0:Open the db with ttl = 2
+  PutValues(0, kSampleSize_);                  // T=0:Insert Set1. Delete at t=2
+  SleepCompactCheck(2, 0, kSampleSize_, false); // T=2:Set1 should not be there
+  CloseTtl();
+}
+
+// Resets the timestamp of a set of kvs by updating them and checks that they
+// are not deleted according to the old timestamp
+TEST(TtlTest, ResetTimestamp) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtl(3);
+  PutValues(0, kSampleSize_);            // T=0: Insert Set1. Delete at t=3
+  sleep(2);                             // T=2
+  PutValues(0, kSampleSize_);            // T=2: Insert Set1. Delete at t=5
+  SleepCompactCheck(2, 0, kSampleSize_); // T=4: Set1 should still be there
+  CloseTtl();
+}
+
+// Similar to PresentDuringTTL but uses Iterator
+TEST(TtlTest, IterPresentDuringTTL) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtl(2);
+  PutValues(0, kSampleSize_);                 // T=0: Insert. Delete at t=2
+  SleepCompactCheckIter(1, 0, kSampleSize_);  // T=1: Set should be there
+  CloseTtl();
+}
+
+// Similar to AbsentAfterTTL but uses Iterator
+TEST(TtlTest, IterAbsentAfterTTL) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtl(1);
+  PutValues(0, kSampleSize_);                      // T=0: Insert. Delete at t=1
+  SleepCompactCheckIter(2, 0, kSampleSize_, false); // T=2: Should not be there
+  CloseTtl();
+}
+
+// Checks presence while opening the same db more than once with the same ttl
+// Note: The second open will open the same db
+TEST(TtlTest, MultiOpenSamePresent) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtl(2);
+  PutValues(0, kSampleSize_);                   // T=0: Insert. Delete at t=2
+  CloseTtl();
+
+  OpenTtl(2);                                  // T=0. Delete at t=2
+  SleepCompactCheck(1, 0, kSampleSize_);        // T=1: Set should be there
+  CloseTtl();
+}
+
+// Checks absence while opening the same db more than once with the same ttl
+// Note: The second open will open the same db
+TEST(TtlTest, MultiOpenSameAbsent) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtl(1);
+  PutValues(0, kSampleSize_);                   // T=0: Insert. Delete at t=1
+  CloseTtl();
+
+  OpenTtl(1);                                  // T=0.Delete at t=1
+  SleepCompactCheck(2, 0, kSampleSize_, false); // T=2: Set should not be there
+  CloseTtl();
+}
+
+// Checks presence while opening the same db more than once with bigger ttl
+TEST(TtlTest, MultiOpenDifferent) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtl(1);
+  PutValues(0, kSampleSize_);            // T=0: Insert. Delete at t=1
+  CloseTtl();
+
+  OpenTtl(3);                           // T=0: Set deleted at t=3
+  SleepCompactCheck(2, 0, kSampleSize_); // T=2: Set should be there
+  CloseTtl();
+}
+
+// Checks presence during ttl in read_only mode
+TEST(TtlTest, ReadOnlyPresentForever) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtl(1);                                 // T=0:Open the db normally
+  PutValues(0, kSampleSize_);                  // T=0:Insert Set1. Delete at t=1
+  CloseTtl();
+
+  OpenReadOnlyTtl(1);
+  SleepCompactCheck(2, 0, kSampleSize_);       // T=2:Set1 should still be there
+  CloseTtl();
+}
+
+// Checks whether WriteBatch works well with TTL
+// Puts all kvs in kvmap_ in a batch and writes first, then deletes first half
+TEST(TtlTest, WriteBatchTest) {
+  MakeKVMap(kSampleSize_);
+  BatchOperation batch_ops[kSampleSize_];
+  for (int i = 0; i < kSampleSize_; i++) {
+    batch_ops[i] = PUT;
+  }
+
+  OpenTtl(2);
+  MakePutWriteBatch(batch_ops, kSampleSize_);
+  for (int i = 0; i < kSampleSize_ / 2; i++) {
+    batch_ops[i] = DELETE;
+  }
+  MakePutWriteBatch(batch_ops, kSampleSize_ / 2);
+  SleepCompactCheck(0, 0, kSampleSize_ / 2, false);
+  SleepCompactCheck(0, kSampleSize_ / 2, kSampleSize_ - kSampleSize_ / 2);
+  CloseTtl();
+}
+
+// Checks user's compaction filter for correctness with TTL logic
+TEST(TtlTest, CompactionFilter) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtlWithTestCompaction(1);
+  PutValues(0, kSampleSize_);                  // T=0:Insert Set1. Delete at t=1
+  // T=2: TTL logic takes precedence over TestFilter:-Set1 should not be there
+  SleepCompactCheck(2, 0, kSampleSize_, false);
+  CloseTtl();
+
+  OpenTtlWithTestCompaction(3);
+  PutValues(0, kSampleSize_);                   // T=0:Insert Set1.
+  int partition = kSampleSize_ / 3;
+  SleepCompactCheck(1, 0, partition, false);   // Part dropped
+  SleepCompactCheck(0, partition, partition);  // Part kept
+  SleepCompactCheck(0, 2 * partition, partition, true, true); // Part changed
+  CloseTtl();
+}
+
+// Insert some key-values which KeyMayExist should be able to get and check that
+// values returned are fine
+TEST(TtlTest, KeyMayExist) {
+  MakeKVMap(kSampleSize_);
+
+  OpenTtl();
+  PutValues(0, kSampleSize_, false);
+
+  SimpleKeyMayExistCheck();
+
+  CloseTtl();
+}
+
+} //  namespace rocksdb
+
+// A black-box test for the ttl wrapper around rocksdb
+int main(int argc, char** argv) {
+  return rocksdb::test::RunAllTests();
+}