libcouchbase 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.gitmodules +3 -0
- data/.rspec +1 -0
- data/.travis.yml +35 -0
- data/Gemfile +4 -0
- data/LICENSE +24 -0
- data/README.md +389 -0
- data/Rakefile +75 -0
- data/ext/README.md +6 -0
- data/ext/Rakefile +20 -0
- data/ext/libcouchbase/.gitignore +130 -0
- data/ext/libcouchbase/.travis.yml +19 -0
- data/ext/libcouchbase/CMakeLists.txt +429 -0
- data/ext/libcouchbase/CONTRIBUTING.md +124 -0
- data/ext/libcouchbase/LICENSE +202 -0
- data/ext/libcouchbase/README.markdown +163 -0
- data/ext/libcouchbase/RELEASE_NOTES.markdown +2691 -0
- data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +27 -0
- data/ext/libcouchbase/cmake/Modules/CopyPDB.cmake +42 -0
- data/ext/libcouchbase/cmake/Modules/DistScript.cmake +17 -0
- data/ext/libcouchbase/cmake/Modules/DownloadLcbDep.cmake +20 -0
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseHdrHistogram.cmake +15 -0
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibev.cmake +73 -0
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibevent.cmake +52 -0
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibuv.cmake +56 -0
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseSnappy.cmake +11 -0
- data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +29 -0
- data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +133 -0
- data/ext/libcouchbase/cmake/Modules/GetPlatformCCInfo.cmake +45 -0
- data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +70 -0
- data/ext/libcouchbase/cmake/config-cmake.h.in +60 -0
- data/ext/libcouchbase/cmake/configure +357 -0
- data/ext/libcouchbase/cmake/defs.mk.in +8 -0
- data/ext/libcouchbase/cmake/dtrace-instr-link.pl +38 -0
- data/ext/libcouchbase/cmake/source_files.cmake +73 -0
- data/ext/libcouchbase/configure.pl +1 -0
- data/ext/libcouchbase/contrib/cJSON/cJSON.c +624 -0
- data/ext/libcouchbase/contrib/cJSON/cJSON.h +158 -0
- data/ext/libcouchbase/contrib/cbsasl/CMakeLists.txt +9 -0
- data/ext/libcouchbase/contrib/cbsasl/COPYING +202 -0
- data/ext/libcouchbase/contrib/cbsasl/include/cbsasl/cbsasl.h +217 -0
- data/ext/libcouchbase/contrib/cbsasl/src/client.c +205 -0
- data/ext/libcouchbase/contrib/cbsasl/src/common.c +46 -0
- data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/hmac.c +67 -0
- data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/hmac.h +33 -0
- data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/md5.c +296 -0
- data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/md5.h +45 -0
- data/ext/libcouchbase/contrib/cbsasl/src/hash.c +573 -0
- data/ext/libcouchbase/contrib/cbsasl/src/hash.h +15 -0
- data/ext/libcouchbase/contrib/cbsasl/src/util.h +31 -0
- data/ext/libcouchbase/contrib/cliopts/CMakeLists.txt +2 -0
- data/ext/libcouchbase/contrib/cliopts/cliopts.c +747 -0
- data/ext/libcouchbase/contrib/cliopts/cliopts.h +493 -0
- data/ext/libcouchbase/contrib/genhash/genhash.c +372 -0
- data/ext/libcouchbase/contrib/genhash/genhash.h +235 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/CHANGES +157 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/CMakeLists.txt +252 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/CONTRIBUTORS +37 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/LICENSE +28 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/MINIFY.sh +15 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/README +435 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/cmake/internal_utils.cmake +227 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-death-test.h +294 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-message.h +250 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-param-test.h +1421 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-param-test.h.pump +487 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-printers.h +855 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-spi.h +232 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-test-part.h +179 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-typed-test.h +259 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest.h +2291 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest_pred_impl.h +358 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest_prod.h +58 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h +319 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h +206 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-internal.h +1158 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h +233 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h +5143 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h.pump +301 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h +619 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-port.h +1947 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-string.h +167 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-tuple.h +1012 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-tuple.h.pump +339 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h +3331 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h.pump +297 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-all.cc +48 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-death-test.cc +1344 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-filepath.cc +382 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-internal-inl.h +1218 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-port.cc +805 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-printers.cc +363 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-test-part.cc +110 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-typed-test.cc +110 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest.cc +5015 -0
- data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest_main.cc +38 -0
- data/ext/libcouchbase/contrib/http_parser/LICENSE-MIT +23 -0
- data/ext/libcouchbase/contrib/http_parser/README.md +178 -0
- data/ext/libcouchbase/contrib/http_parser/http_parser.c +2060 -0
- data/ext/libcouchbase/contrib/http_parser/http_parser.h +321 -0
- data/ext/libcouchbase/contrib/jsonsl/LICENSE +20 -0
- data/ext/libcouchbase/contrib/jsonsl/jsonsl.c +1452 -0
- data/ext/libcouchbase/contrib/jsonsl/jsonsl.h +971 -0
- data/ext/libcouchbase/contrib/lcb-jsoncpp/CMakeLists.txt +6 -0
- data/ext/libcouchbase/contrib/lcb-jsoncpp/LICENSE +55 -0
- data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp-forwards.h +255 -0
- data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp.cpp +4892 -0
- data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp.h +1961 -0
- data/ext/libcouchbase/contrib/snappy/CMakeLists.txt +8 -0
- data/ext/libcouchbase/contrib/snappy/COPYING +28 -0
- data/ext/libcouchbase/contrib/snappy/snappy-c.cc +90 -0
- data/ext/libcouchbase/contrib/snappy/snappy-c.h +138 -0
- data/ext/libcouchbase/contrib/snappy/snappy-internal.h +150 -0
- data/ext/libcouchbase/contrib/snappy/snappy-lcb-msvc.h +5 -0
- data/ext/libcouchbase/contrib/snappy/snappy-sinksource.cc +71 -0
- data/ext/libcouchbase/contrib/snappy/snappy-sinksource.h +137 -0
- data/ext/libcouchbase/contrib/snappy/snappy-stubs-internal.cc +42 -0
- data/ext/libcouchbase/contrib/snappy/snappy-stubs-internal.h +491 -0
- data/ext/libcouchbase/contrib/snappy/snappy-stubs-public.h +98 -0
- data/ext/libcouchbase/contrib/snappy/snappy.cc +1307 -0
- data/ext/libcouchbase/contrib/snappy/snappy.h +184 -0
- data/ext/libcouchbase/contrib/win32-defs/iocpdefs.h +133 -0
- data/ext/libcouchbase/contrib/win32-defs/mingwdefs.h +4396 -0
- data/ext/libcouchbase/contrib/win32-defs/win_stdint.h +258 -0
- data/ext/libcouchbase/example/CMakeLists.txt +37 -0
- data/ext/libcouchbase/example/README.markdown +47 -0
- data/ext/libcouchbase/example/db/db.c +167 -0
- data/ext/libcouchbase/example/db/vb.c +227 -0
- data/ext/libcouchbase/example/instancepool/main.cc +102 -0
- data/ext/libcouchbase/example/instancepool/pool.cc +102 -0
- data/ext/libcouchbase/example/instancepool/pool.h +69 -0
- data/ext/libcouchbase/example/libeventdirect/main.c +148 -0
- data/ext/libcouchbase/example/mcc/mcc.cc +246 -0
- data/ext/libcouchbase/example/minimal/minimal.c +130 -0
- data/ext/libcouchbase/example/observe/observe.c +146 -0
- data/ext/libcouchbase/example/subdoc/subdoc-multi.cc +132 -0
- data/ext/libcouchbase/example/subdoc/subdoc-simple.cc +191 -0
- data/ext/libcouchbase/example/tick/tick.c +119 -0
- data/ext/libcouchbase/example/views/views-example.cc +83 -0
- data/ext/libcouchbase/include/libcouchbase/_cxxwrap.h +150 -0
- data/ext/libcouchbase/include/libcouchbase/api-legacy.h +1689 -0
- data/ext/libcouchbase/include/libcouchbase/api3.h +2 -0
- data/ext/libcouchbase/include/libcouchbase/assert.h +44 -0
- data/ext/libcouchbase/include/libcouchbase/cbft.h +109 -0
- data/ext/libcouchbase/include/libcouchbase/cntl-private.h +356 -0
- data/ext/libcouchbase/include/libcouchbase/cntl.h +937 -0
- data/ext/libcouchbase/include/libcouchbase/configuration.h.in +23 -0
- data/ext/libcouchbase/include/libcouchbase/couchbase.h +3677 -0
- data/ext/libcouchbase/include/libcouchbase/deprecated.h +300 -0
- data/ext/libcouchbase/include/libcouchbase/error.h +595 -0
- data/ext/libcouchbase/include/libcouchbase/http.h +1 -0
- data/ext/libcouchbase/include/libcouchbase/iops.h +1050 -0
- data/ext/libcouchbase/include/libcouchbase/ixmgmt.h +263 -0
- data/ext/libcouchbase/include/libcouchbase/kvbuf.h +132 -0
- data/ext/libcouchbase/include/libcouchbase/n1ql.h +364 -0
- data/ext/libcouchbase/include/libcouchbase/pktfwd.h +270 -0
- data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +367 -0
- data/ext/libcouchbase/include/libcouchbase/plugins/io/wsaerr-inl.c +76 -0
- data/ext/libcouchbase/include/libcouchbase/plugins/io/wsaerr.h +199 -0
- data/ext/libcouchbase/include/libcouchbase/subdoc.h +312 -0
- data/ext/libcouchbase/include/libcouchbase/sysdefs.h +98 -0
- data/ext/libcouchbase/include/libcouchbase/vbucket.h +643 -0
- data/ext/libcouchbase/include/libcouchbase/views.h +298 -0
- data/ext/libcouchbase/include/libcouchbase/visibility.h +65 -0
- data/ext/libcouchbase/include/memcached/COPYING +30 -0
- data/ext/libcouchbase/include/memcached/README +10 -0
- data/ext/libcouchbase/include/memcached/protocol_binary.h +1916 -0
- data/ext/libcouchbase/include/memcached/vbucket.h +42 -0
- data/ext/libcouchbase/packaging/README +7 -0
- data/ext/libcouchbase/packaging/abicheck/.gitignore +4 -0
- data/ext/libcouchbase/packaging/abicheck/Makefile +17 -0
- data/ext/libcouchbase/packaging/abicheck/README.md +27 -0
- data/ext/libcouchbase/packaging/abicheck/template.xml +3 -0
- data/ext/libcouchbase/packaging/deb/compat +1 -0
- data/ext/libcouchbase/packaging/deb/control +73 -0
- data/ext/libcouchbase/packaging/deb/copyright +10 -0
- data/ext/libcouchbase/packaging/deb/libcouchbase-dev.docs +3 -0
- data/ext/libcouchbase/packaging/deb/package.mk +31 -0
- data/ext/libcouchbase/packaging/deb/rules +46 -0
- data/ext/libcouchbase/packaging/deb/source/format +1 -0
- data/ext/libcouchbase/packaging/distinfo/README +1 -0
- data/ext/libcouchbase/packaging/distinfo/distinfo.cmake.in +4 -0
- data/ext/libcouchbase/packaging/dllversion.rc.in +39 -0
- data/ext/libcouchbase/packaging/libcouchbase.pc.in +10 -0
- data/ext/libcouchbase/packaging/nuget/libcouchbase.autopkg +76 -0
- data/ext/libcouchbase/packaging/parse-git-describe.pl +166 -0
- data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +108 -0
- data/ext/libcouchbase/packaging/rpm/package.mk +40 -0
- data/ext/libcouchbase/plugins/io/iocp/CMakeLists.txt +9 -0
- data/ext/libcouchbase/plugins/io/iocp/iocp_iops.c +466 -0
- data/ext/libcouchbase/plugins/io/iocp/iocp_iops.h +217 -0
- data/ext/libcouchbase/plugins/io/iocp/iocp_loop.c +295 -0
- data/ext/libcouchbase/plugins/io/iocp/iocp_timer.c +79 -0
- data/ext/libcouchbase/plugins/io/iocp/iocp_util.c +229 -0
- data/ext/libcouchbase/plugins/io/libev/CMakeLists.txt +29 -0
- data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +65 -0
- data/ext/libcouchbase/plugins/io/libev/plugin-libev.c +289 -0
- data/ext/libcouchbase/plugins/io/libevent/CMakeLists.txt +29 -0
- data/ext/libcouchbase/plugins/io/libevent/libevent_io_opts.h +67 -0
- data/ext/libcouchbase/plugins/io/libevent/plugin-libevent.c +292 -0
- data/ext/libcouchbase/plugins/io/libuv/CMakeLists.txt +42 -0
- data/ext/libcouchbase/plugins/io/libuv/libuv_compat.h +212 -0
- data/ext/libcouchbase/plugins/io/libuv/libuv_io_opts.h +118 -0
- data/ext/libcouchbase/plugins/io/libuv/plugin-internal.h +148 -0
- data/ext/libcouchbase/plugins/io/libuv/plugin-libuv.c +648 -0
- data/ext/libcouchbase/plugins/io/select/CMakeLists.txt +11 -0
- data/ext/libcouchbase/plugins/io/select/plugin-select.c +448 -0
- data/ext/libcouchbase/plugins/io/select/select_io_opts.h +39 -0
- data/ext/libcouchbase/src/README.md +103 -0
- data/ext/libcouchbase/src/aspend.h +106 -0
- data/ext/libcouchbase/src/auth.cc +74 -0
- data/ext/libcouchbase/src/auth.h +54 -0
- data/ext/libcouchbase/src/bootstrap.c +269 -0
- data/ext/libcouchbase/src/bootstrap.h +129 -0
- data/ext/libcouchbase/src/bucketconfig/bc_cccp.c +495 -0
- data/ext/libcouchbase/src/bucketconfig/bc_file.c +347 -0
- data/ext/libcouchbase/src/bucketconfig/bc_http.c +630 -0
- data/ext/libcouchbase/src/bucketconfig/bc_http.h +82 -0
- data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +150 -0
- data/ext/libcouchbase/src/bucketconfig/clconfig.h +681 -0
- data/ext/libcouchbase/src/bucketconfig/confmon.c +474 -0
- data/ext/libcouchbase/src/callbacks.c +378 -0
- data/ext/libcouchbase/src/cbft.cc +210 -0
- data/ext/libcouchbase/src/cntl.cc +847 -0
- data/ext/libcouchbase/src/config_static.h +159 -0
- data/ext/libcouchbase/src/connspec.cc +462 -0
- data/ext/libcouchbase/src/connspec.h +105 -0
- data/ext/libcouchbase/src/ctx-log-inl.h +27 -0
- data/ext/libcouchbase/src/dump.c +98 -0
- data/ext/libcouchbase/src/getconfig.c +100 -0
- data/ext/libcouchbase/src/gethrtime.c +109 -0
- data/ext/libcouchbase/src/handler.c +922 -0
- data/ext/libcouchbase/src/hashset.c +164 -0
- data/ext/libcouchbase/src/hashset.h +86 -0
- data/ext/libcouchbase/src/hashtable.c +75 -0
- data/ext/libcouchbase/src/hdr_timings.c +92 -0
- data/ext/libcouchbase/src/hostlist.cc +301 -0
- data/ext/libcouchbase/src/hostlist.h +171 -0
- data/ext/libcouchbase/src/http/http-priv.h +307 -0
- data/ext/libcouchbase/src/http/http.cc +633 -0
- data/ext/libcouchbase/src/http/http.h +34 -0
- data/ext/libcouchbase/src/http/http_io.cc +307 -0
- data/ext/libcouchbase/src/instance.cc +722 -0
- data/ext/libcouchbase/src/internal.h +244 -0
- data/ext/libcouchbase/src/iofactory.c +575 -0
- data/ext/libcouchbase/src/jsparse/parser.cc +519 -0
- data/ext/libcouchbase/src/jsparse/parser.h +173 -0
- data/ext/libcouchbase/src/lcbht/lcbht.c +282 -0
- data/ext/libcouchbase/src/lcbht/lcbht.h +199 -0
- data/ext/libcouchbase/src/lcbio/connect.c +557 -0
- data/ext/libcouchbase/src/lcbio/connect.h +364 -0
- data/ext/libcouchbase/src/lcbio/ctx.c +611 -0
- data/ext/libcouchbase/src/lcbio/ctx.h +405 -0
- data/ext/libcouchbase/src/lcbio/iotable.c +290 -0
- data/ext/libcouchbase/src/lcbio/iotable.h +84 -0
- data/ext/libcouchbase/src/lcbio/ioutils.c +350 -0
- data/ext/libcouchbase/src/lcbio/ioutils.h +203 -0
- data/ext/libcouchbase/src/lcbio/lcbio.h +51 -0
- data/ext/libcouchbase/src/lcbio/manager.c +584 -0
- data/ext/libcouchbase/src/lcbio/manager.h +156 -0
- data/ext/libcouchbase/src/lcbio/protoctx.c +84 -0
- data/ext/libcouchbase/src/lcbio/rw-inl.h +115 -0
- data/ext/libcouchbase/src/lcbio/ssl.h +149 -0
- data/ext/libcouchbase/src/lcbio/timer-ng.h +179 -0
- data/ext/libcouchbase/src/lcbio/timer.c +132 -0
- data/ext/libcouchbase/src/legacy.c +430 -0
- data/ext/libcouchbase/src/list.c +144 -0
- data/ext/libcouchbase/src/list.h +127 -0
- data/ext/libcouchbase/src/logging.c +244 -0
- data/ext/libcouchbase/src/logging.h +86 -0
- data/ext/libcouchbase/src/mc/compress.c +90 -0
- data/ext/libcouchbase/src/mc/compress.h +61 -0
- data/ext/libcouchbase/src/mc/forward.c +186 -0
- data/ext/libcouchbase/src/mc/forward.h +90 -0
- data/ext/libcouchbase/src/mc/iovcursor-inl.h +279 -0
- data/ext/libcouchbase/src/mc/iovcursor.h +66 -0
- data/ext/libcouchbase/src/mc/mcreq-flush-inl.h +111 -0
- data/ext/libcouchbase/src/mc/mcreq.c +954 -0
- data/ext/libcouchbase/src/mc/mcreq.h +977 -0
- data/ext/libcouchbase/src/mcserver/mcserver.c +784 -0
- data/ext/libcouchbase/src/mcserver/mcserver.h +121 -0
- data/ext/libcouchbase/src/mcserver/negotiate.c +656 -0
- data/ext/libcouchbase/src/mcserver/negotiate.h +119 -0
- data/ext/libcouchbase/src/n1ql/ixmgmt.cc +860 -0
- data/ext/libcouchbase/src/n1ql/n1ql-internal.h +22 -0
- data/ext/libcouchbase/src/n1ql/n1ql.cc +729 -0
- data/ext/libcouchbase/src/n1ql/params.cc +215 -0
- data/ext/libcouchbase/src/netbuf/netbuf-defs.h +89 -0
- data/ext/libcouchbase/src/netbuf/netbuf-mblock.h +235 -0
- data/ext/libcouchbase/src/netbuf/netbuf.c +929 -0
- data/ext/libcouchbase/src/netbuf/netbuf.h +452 -0
- data/ext/libcouchbase/src/newconfig.c +385 -0
- data/ext/libcouchbase/src/nodeinfo.cc +194 -0
- data/ext/libcouchbase/src/operations/cbflush.c +71 -0
- data/ext/libcouchbase/src/operations/counter.c +116 -0
- data/ext/libcouchbase/src/operations/durability-cas.c +224 -0
- data/ext/libcouchbase/src/operations/durability-seqno.c +157 -0
- data/ext/libcouchbase/src/operations/durability.c +668 -0
- data/ext/libcouchbase/src/operations/durability_internal.h +199 -0
- data/ext/libcouchbase/src/operations/get.c +409 -0
- data/ext/libcouchbase/src/operations/observe-seqno.c +96 -0
- data/ext/libcouchbase/src/operations/observe.c +340 -0
- data/ext/libcouchbase/src/operations/pktfwd.c +86 -0
- data/ext/libcouchbase/src/operations/remove.c +83 -0
- data/ext/libcouchbase/src/operations/stats.c +461 -0
- data/ext/libcouchbase/src/operations/store.c +360 -0
- data/ext/libcouchbase/src/operations/subdoc.cc +510 -0
- data/ext/libcouchbase/src/operations/touch.c +81 -0
- data/ext/libcouchbase/src/packetutils.c +60 -0
- data/ext/libcouchbase/src/packetutils.h +147 -0
- data/ext/libcouchbase/src/probes.d +211 -0
- data/ext/libcouchbase/src/rdb/bigalloc.c +225 -0
- data/ext/libcouchbase/src/rdb/bigalloc.h +73 -0
- data/ext/libcouchbase/src/rdb/chunkalloc.c +174 -0
- data/ext/libcouchbase/src/rdb/libcalloc.c +94 -0
- data/ext/libcouchbase/src/rdb/rope.c +419 -0
- data/ext/libcouchbase/src/rdb/rope.h +488 -0
- data/ext/libcouchbase/src/retrychk.c +113 -0
- data/ext/libcouchbase/src/retryq.c +424 -0
- data/ext/libcouchbase/src/retryq.h +157 -0
- data/ext/libcouchbase/src/ringbuffer.c +442 -0
- data/ext/libcouchbase/src/ringbuffer.h +100 -0
- data/ext/libcouchbase/src/settings.c +95 -0
- data/ext/libcouchbase/src/settings.h +188 -0
- data/ext/libcouchbase/src/simplestring.c +211 -0
- data/ext/libcouchbase/src/simplestring.h +228 -0
- data/ext/libcouchbase/src/sllist-inl.h +197 -0
- data/ext/libcouchbase/src/sllist.h +76 -0
- data/ext/libcouchbase/src/ssl/CMakeLists.txt +23 -0
- data/ext/libcouchbase/src/ssl/ssl_c.c +415 -0
- data/ext/libcouchbase/src/ssl/ssl_common.c +454 -0
- data/ext/libcouchbase/src/ssl/ssl_e.c +408 -0
- data/ext/libcouchbase/src/ssl/ssl_iot_common.h +180 -0
- data/ext/libcouchbase/src/ssobuf.h +82 -0
- data/ext/libcouchbase/src/strcodecs/base64.c +123 -0
- data/ext/libcouchbase/src/strcodecs/strcodecs.h +285 -0
- data/ext/libcouchbase/src/timings.c +208 -0
- data/ext/libcouchbase/src/trace.h +105 -0
- data/ext/libcouchbase/src/utilities.c +171 -0
- data/ext/libcouchbase/src/vbucket/CMakeLists.txt +2 -0
- data/ext/libcouchbase/src/vbucket/aliases.h +35 -0
- data/ext/libcouchbase/src/vbucket/crc32.h +83 -0
- data/ext/libcouchbase/src/vbucket/hash.h +30 -0
- data/ext/libcouchbase/src/vbucket/json-inl.h +112 -0
- data/ext/libcouchbase/src/vbucket/ketama.c +66 -0
- data/ext/libcouchbase/src/vbucket/rfc1321/global.h +32 -0
- data/ext/libcouchbase/src/vbucket/rfc1321/md5.h +35 -0
- data/ext/libcouchbase/src/vbucket/rfc1321/md5c-inl.h +335 -0
- data/ext/libcouchbase/src/vbucket/vbucket.c +1543 -0
- data/ext/libcouchbase/src/views/docreq.c +194 -0
- data/ext/libcouchbase/src/views/docreq.h +83 -0
- data/ext/libcouchbase/src/views/viewreq.c +358 -0
- data/ext/libcouchbase/src/views/viewreq.h +36 -0
- data/ext/libcouchbase/src/wait.c +161 -0
- data/ext/libcouchbase/tests/CMakeLists.txt +140 -0
- data/ext/libcouchbase/tests/basic/t_base64.cc +81 -0
- data/ext/libcouchbase/tests/basic/t_ccbc103.cc +95 -0
- data/ext/libcouchbase/tests/basic/t_connstr.cc +404 -0
- data/ext/libcouchbase/tests/basic/t_creds.cc +32 -0
- data/ext/libcouchbase/tests/basic/t_ctlcodes.cc +92 -0
- data/ext/libcouchbase/tests/basic/t_hashset.cc +262 -0
- data/ext/libcouchbase/tests/basic/t_host.cc +198 -0
- data/ext/libcouchbase/tests/basic/t_jsparse.cc +137 -0
- data/ext/libcouchbase/tests/basic/t_jsparse.h +589 -0
- data/ext/libcouchbase/tests/basic/t_list.cc +155 -0
- data/ext/libcouchbase/tests/basic/t_logger.cc +65 -0
- data/ext/libcouchbase/tests/basic/t_misc.cc +24 -0
- data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +18 -0
- data/ext/libcouchbase/tests/basic/t_netbuf.cc +446 -0
- data/ext/libcouchbase/tests/basic/t_packet.cc +222 -0
- data/ext/libcouchbase/tests/basic/t_ringbuffer.cc +278 -0
- data/ext/libcouchbase/tests/basic/t_slist.cc +429 -0
- data/ext/libcouchbase/tests/basic/t_strerror.cc +64 -0
- data/ext/libcouchbase/tests/basic/t_string.cc +112 -0
- data/ext/libcouchbase/tests/basic/t_urlencode.cc +132 -0
- data/ext/libcouchbase/tests/check-all.cc +608 -0
- data/ext/libcouchbase/tests/htparse/t_basic.cc +193 -0
- data/ext/libcouchbase/tests/ioserver/connection.cc +166 -0
- data/ext/libcouchbase/tests/ioserver/future.cc +50 -0
- data/ext/libcouchbase/tests/ioserver/ioserver.cc +104 -0
- data/ext/libcouchbase/tests/ioserver/ioserver.h +478 -0
- data/ext/libcouchbase/tests/ioserver/socket.cc +88 -0
- data/ext/libcouchbase/tests/ioserver/ssl_connection.cc +145 -0
- data/ext/libcouchbase/tests/ioserver/threads-pthreads.cc +119 -0
- data/ext/libcouchbase/tests/ioserver/threads-win32.cc +117 -0
- data/ext/libcouchbase/tests/ioserver/threads.h +66 -0
- data/ext/libcouchbase/tests/iotests/iotests.h +15 -0
- data/ext/libcouchbase/tests/iotests/mock-environment.cc +524 -0
- data/ext/libcouchbase/tests/iotests/mock-environment.h +385 -0
- data/ext/libcouchbase/tests/iotests/mock-unit-test.cc +67 -0
- data/ext/libcouchbase/tests/iotests/mock-unit-test.h +61 -0
- data/ext/libcouchbase/tests/iotests/serverparams.h +76 -0
- data/ext/libcouchbase/tests/iotests/t_arithmetic.cc +143 -0
- data/ext/libcouchbase/tests/iotests/t_behavior.cc +226 -0
- data/ext/libcouchbase/tests/iotests/t_configcache.cc +117 -0
- data/ext/libcouchbase/tests/iotests/t_confmon.cc +241 -0
- data/ext/libcouchbase/tests/iotests/t_durability.cc +1059 -0
- data/ext/libcouchbase/tests/iotests/t_forward.cc +110 -0
- data/ext/libcouchbase/tests/iotests/t_get.cc +512 -0
- data/ext/libcouchbase/tests/iotests/t_http.cc +438 -0
- data/ext/libcouchbase/tests/iotests/t_iops.cc +175 -0
- data/ext/libcouchbase/tests/iotests/t_lock.cc +275 -0
- data/ext/libcouchbase/tests/iotests/t_misc.cc +713 -0
- data/ext/libcouchbase/tests/iotests/t_mutate.cc +609 -0
- data/ext/libcouchbase/tests/iotests/t_n1ql.cc +270 -0
- data/ext/libcouchbase/tests/iotests/t_netfail.cc +654 -0
- data/ext/libcouchbase/tests/iotests/t_obseqno.cc +157 -0
- data/ext/libcouchbase/tests/iotests/t_regression.cc +321 -0
- data/ext/libcouchbase/tests/iotests/t_sched.cc +88 -0
- data/ext/libcouchbase/tests/iotests/t_serverops.cc +230 -0
- data/ext/libcouchbase/tests/iotests/t_smoke.cc +528 -0
- data/ext/libcouchbase/tests/iotests/t_subdoc.cc +822 -0
- data/ext/libcouchbase/tests/iotests/t_syncmode.cc +64 -0
- data/ext/libcouchbase/tests/iotests/t_views.cc +405 -0
- data/ext/libcouchbase/tests/iotests/testutil.cc +250 -0
- data/ext/libcouchbase/tests/iotests/testutil.h +163 -0
- data/ext/libcouchbase/tests/mc/mctest.h +119 -0
- data/ext/libcouchbase/tests/mc/pktmaker.h +101 -0
- data/ext/libcouchbase/tests/mc/t_alloc.cc +269 -0
- data/ext/libcouchbase/tests/mc/t_context.cc +100 -0
- data/ext/libcouchbase/tests/mc/t_flush.cc +185 -0
- data/ext/libcouchbase/tests/mc/t_forward.cc +239 -0
- data/ext/libcouchbase/tests/mc/t_ioflush.cc +102 -0
- data/ext/libcouchbase/tests/mc/t_iovcursor.cc +173 -0
- data/ext/libcouchbase/tests/mocksupport/procutil.c +305 -0
- data/ext/libcouchbase/tests/mocksupport/procutil.h +89 -0
- data/ext/libcouchbase/tests/mocksupport/server.c +391 -0
- data/ext/libcouchbase/tests/mocksupport/server.h +72 -0
- data/ext/libcouchbase/tests/mocksupport/timeout.c +69 -0
- data/ext/libcouchbase/tests/nonio_tests.cc +23 -0
- data/ext/libcouchbase/tests/rdb/rdbtest.h +133 -0
- data/ext/libcouchbase/tests/rdb/t_basic.cc +128 -0
- data/ext/libcouchbase/tests/rdb/t_bigalloc.cc +93 -0
- data/ext/libcouchbase/tests/rdb/t_refs.cc +112 -0
- data/ext/libcouchbase/tests/socktests/socktest.cc +347 -0
- data/ext/libcouchbase/tests/socktests/socktest.h +448 -0
- data/ext/libcouchbase/tests/socktests/t_basic.cc +143 -0
- data/ext/libcouchbase/tests/socktests/t_ctx.cc +73 -0
- data/ext/libcouchbase/tests/socktests/t_manager.cc +179 -0
- data/ext/libcouchbase/tests/socktests/t_putex.cc +256 -0
- data/ext/libcouchbase/tests/socktests/t_read.cc +187 -0
- data/ext/libcouchbase/tests/socktests/t_reentrant.cc +143 -0
- data/ext/libcouchbase/tests/socktests/t_ssl.cc +80 -0
- data/ext/libcouchbase/tests/socktests/t_write.cc +95 -0
- data/ext/libcouchbase/tests/start_mock.bat +15 -0
- data/ext/libcouchbase/tests/start_mock.sh +42 -0
- data/ext/libcouchbase/tests/unit_tests.cc +43 -0
- data/ext/libcouchbase/tests/vbucket/confdata/bad.json +101 -0
- data/ext/libcouchbase/tests/vbucket/confdata/full_25.json +363 -0
- data/ext/libcouchbase/tests/vbucket/confdata/memd_25.json +90 -0
- data/ext/libcouchbase/tests/vbucket/confdata/memd_30.json +1 -0
- data/ext/libcouchbase/tests/vbucket/confdata/memd_45.json +1 -0
- data/ext/libcouchbase/tests/vbucket/confdata/terse_25.json +291 -0
- data/ext/libcouchbase/tests/vbucket/confdata/terse_30.json +1 -0
- data/ext/libcouchbase/tests/vbucket/t_config.cc +341 -0
- data/ext/libcouchbase/tools/CMakeLists.txt +51 -0
- data/ext/libcouchbase/tools/cbc-handlers.h +462 -0
- data/ext/libcouchbase/tools/cbc-n1qlback.cc +439 -0
- data/ext/libcouchbase/tools/cbc-pillowfight.cc +822 -0
- data/ext/libcouchbase/tools/cbc.cc +1541 -0
- data/ext/libcouchbase/tools/common/histogram.cc +43 -0
- data/ext/libcouchbase/tools/common/histogram.h +23 -0
- data/ext/libcouchbase/tools/common/my_inttypes.h +22 -0
- data/ext/libcouchbase/tools/common/options.cc +420 -0
- data/ext/libcouchbase/tools/common/options.h +81 -0
- data/ext/libcouchbase/tools/docgen/docgen.h +469 -0
- data/ext/libcouchbase/tools/docgen/loc.h +210 -0
- data/ext/libcouchbase/tools/docgen/placeholders.h +211 -0
- data/ext/libcouchbase/tools/docgen/seqgen.h +94 -0
- data/lib/libcouchbase.rb +36 -0
- data/lib/libcouchbase/bucket.rb +819 -0
- data/lib/libcouchbase/callbacks.rb +72 -0
- data/lib/libcouchbase/connection.rb +790 -0
- data/lib/libcouchbase/design_docs.rb +86 -0
- data/lib/libcouchbase/error.rb +68 -0
- data/lib/libcouchbase/ext/libcouchbase.rb +1135 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdbase.rb +23 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdcounter.rb +36 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdendure.rb +26 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdfts.rb +24 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdget.rb +30 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdgetreplica.rb +49 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdhttp.rb +58 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdn1ql.rb +40 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdobseqno.rb +33 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdobserve.rb +30 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdstore.rb +40 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdstoredur.rb +45 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +49 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdverbosity.rb +29 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdviewquery.rb +61 -0
- data/lib/libcouchbase/ext/libcouchbase/contigbuf.rb +14 -0
- data/lib/libcouchbase/ext/libcouchbase/create_st.rb +15 -0
- data/lib/libcouchbase/ext/libcouchbase/create_st0.rb +23 -0
- data/lib/libcouchbase/ext/libcouchbase/create_st1.rb +26 -0
- data/lib/libcouchbase/ext/libcouchbase/create_st2.rb +32 -0
- data/lib/libcouchbase/ext/libcouchbase/create_st3.rb +26 -0
- data/lib/libcouchbase/ext/libcouchbase/crst_u.rb +20 -0
- data/lib/libcouchbase/ext/libcouchbase/durability_opts_st_v.rb +11 -0
- data/lib/libcouchbase/ext/libcouchbase/durability_opts_t.rb +14 -0
- data/lib/libcouchbase/ext/libcouchbase/durabilityopt_sv0.rb +63 -0
- data/lib/libcouchbase/ext/libcouchbase/enums.rb +991 -0
- data/lib/libcouchbase/ext/libcouchbase/fragbuf.rb +18 -0
- data/lib/libcouchbase/ext/libcouchbase/ftshandle.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase/histogram.rb +34 -0
- data/lib/libcouchbase/ext/libcouchbase/http_request_t.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase/keybuf.rb +20 -0
- data/lib/libcouchbase/ext/libcouchbase/multicmd_ctx.rb +30 -0
- data/lib/libcouchbase/ext/libcouchbase/mutation_token.rb +17 -0
- data/lib/libcouchbase/ext/libcouchbase/n1qlhandle.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase/n1qlparams.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase/respbase.rb +29 -0
- data/lib/libcouchbase/ext/libcouchbase/respcounter.rb +32 -0
- data/lib/libcouchbase/ext/libcouchbase/respendure.rb +49 -0
- data/lib/libcouchbase/ext/libcouchbase/respfts.rb +40 -0
- data/lib/libcouchbase/ext/libcouchbase/respget.rb +44 -0
- data/lib/libcouchbase/ext/libcouchbase/resphttp.rb +48 -0
- data/lib/libcouchbase/ext/libcouchbase/respmcversion.rb +38 -0
- data/lib/libcouchbase/ext/libcouchbase/respn1ql.rb +41 -0
- data/lib/libcouchbase/ext/libcouchbase/respobseqno.rb +52 -0
- data/lib/libcouchbase/ext/libcouchbase/respobserve.rb +41 -0
- data/lib/libcouchbase/ext/libcouchbase/respserverbase.rb +32 -0
- data/lib/libcouchbase/ext/libcouchbase/respstats.rb +38 -0
- data/lib/libcouchbase/ext/libcouchbase/respstore.rb +32 -0
- data/lib/libcouchbase/ext/libcouchbase/respstoredur.rb +38 -0
- data/lib/libcouchbase/ext/libcouchbase/respsubdoc.rb +35 -0
- data/lib/libcouchbase/ext/libcouchbase/respviewquery.rb +67 -0
- data/lib/libcouchbase/ext/libcouchbase/sdentry.rb +22 -0
- data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +26 -0
- data/lib/libcouchbase/ext/libcouchbase/t.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase/valbuf.rb +22 -0
- data/lib/libcouchbase/ext/libcouchbase/valbuf_u_buf.rb +14 -0
- data/lib/libcouchbase/ext/libcouchbase/viewhandle.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase_iocp.rb +26 -0
- data/lib/libcouchbase/ext/libcouchbase_libuv.rb +18 -0
- data/lib/libcouchbase/ext/tasks.rb +87 -0
- data/lib/libcouchbase/n1ql.rb +73 -0
- data/lib/libcouchbase/query_full_text.rb +147 -0
- data/lib/libcouchbase/query_n1ql.rb +121 -0
- data/lib/libcouchbase/query_view.rb +129 -0
- data/lib/libcouchbase/results_fiber.rb +262 -0
- data/lib/libcouchbase/results_native.rb +211 -0
- data/lib/libcouchbase/version.rb +5 -0
- data/libcouchbase.gemspec +61 -0
- data/spec/bucket_spec.rb +270 -0
- data/spec/connection_spec.rb +277 -0
- data/spec/design_docs_spec.rb +23 -0
- data/spec/error_spec.rb +26 -0
- data/spec/fts_spec.rb +129 -0
- data/spec/n1ql_spec.rb +201 -0
- data/spec/results_libuv_spec.rb +229 -0
- data/spec/results_native_spec.rb +259 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/design.json +1 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/data-0000.cbb +0 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/failover.json +1 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/meta.json +1 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/seqno.json +1 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/snapshot_markers.json +1 -0
- data/spec/view_spec.rb +195 -0
- metadata +775 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2015 Couchbase, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#define LCB_NO_DEPR_CXX_CTORS
|
|
18
|
+
|
|
19
|
+
#include "config.h"
|
|
20
|
+
#include <sys/types.h>
|
|
21
|
+
#include <libcouchbase/couchbase.h>
|
|
22
|
+
#include <libcouchbase/api3.h>
|
|
23
|
+
#include <libcouchbase/n1ql.h>
|
|
24
|
+
#include <libcouchbase/vbucket.h>
|
|
25
|
+
#include <iostream>
|
|
26
|
+
#include <list>
|
|
27
|
+
#include <cassert>
|
|
28
|
+
#include <cstdio>
|
|
29
|
+
#include <cstdlib>
|
|
30
|
+
#include <cerrno>
|
|
31
|
+
#include <fstream>
|
|
32
|
+
#include <algorithm> // random_shuffle
|
|
33
|
+
#include <stdexcept>
|
|
34
|
+
#include <sstream>
|
|
35
|
+
#ifndef WIN32
|
|
36
|
+
#include <pthread.h>
|
|
37
|
+
#include <unistd.h> // isatty()
|
|
38
|
+
#endif
|
|
39
|
+
#include "common/options.h"
|
|
40
|
+
#include "common/histogram.h"
|
|
41
|
+
|
|
42
|
+
using namespace cbc;
|
|
43
|
+
using namespace cliopts;
|
|
44
|
+
using std::vector;
|
|
45
|
+
using std::string;
|
|
46
|
+
using std::cerr;
|
|
47
|
+
using std::endl;
|
|
48
|
+
|
|
49
|
+
#ifndef _WIN32
|
|
50
|
+
static bool use_ansi_codes = true;
|
|
51
|
+
#else
|
|
52
|
+
static bool use_ansi_codes = false;
|
|
53
|
+
#endif
|
|
54
|
+
|
|
55
|
+
static void do_or_die(lcb_error_t rc)
|
|
56
|
+
{
|
|
57
|
+
if (rc != LCB_SUCCESS) {
|
|
58
|
+
std::stringstream ss;
|
|
59
|
+
ss << "[" << std::hex << rc << "] " << lcb_strerror(NULL, rc);
|
|
60
|
+
throw std::runtime_error(ss.str());
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
class Metrics {
|
|
65
|
+
public:
|
|
66
|
+
Metrics()
|
|
67
|
+
: n_rows(0), n_queries(0), n_errors(0), last_update(time(NULL)), hg(NULL)
|
|
68
|
+
{
|
|
69
|
+
#ifndef _WIN32
|
|
70
|
+
if (pthread_mutex_init(&m_lock, NULL) != 0) {
|
|
71
|
+
abort();
|
|
72
|
+
}
|
|
73
|
+
#endif
|
|
74
|
+
start_time = last_update;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
void update_row(size_t n = 1) { n_rows += n; update_display(); }
|
|
78
|
+
void update_done(size_t n = 1) { n_queries += n; update_display(); }
|
|
79
|
+
void update_error(size_t n = 1) { n_errors += n; update_display(); }
|
|
80
|
+
|
|
81
|
+
void update_timings(lcb_U64 duration) {
|
|
82
|
+
if (hg != NULL) {
|
|
83
|
+
hg->record(duration);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#ifndef _WIN32
|
|
88
|
+
bool is_tty() const { return isatty(STDOUT_FILENO); }
|
|
89
|
+
void lock() { pthread_mutex_lock(&m_lock); }
|
|
90
|
+
void unlock() { pthread_mutex_unlock(&m_lock); }
|
|
91
|
+
#else
|
|
92
|
+
void lock(){}
|
|
93
|
+
void unlock(){}
|
|
94
|
+
bool is_tty() const { return false; }
|
|
95
|
+
#endif
|
|
96
|
+
void prepare_screen()
|
|
97
|
+
{
|
|
98
|
+
if (is_tty() && use_ansi_codes) {
|
|
99
|
+
printf("\n\n\n");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void prepare_timings()
|
|
104
|
+
{
|
|
105
|
+
if (hg == NULL) {
|
|
106
|
+
hg = new Histogram();
|
|
107
|
+
hg->installStandalone(stdout);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private:
|
|
112
|
+
void update_display()
|
|
113
|
+
{
|
|
114
|
+
time_t now = time(NULL);
|
|
115
|
+
time_t duration = now - last_update;
|
|
116
|
+
|
|
117
|
+
if (!duration) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
last_update = now;
|
|
122
|
+
|
|
123
|
+
const char *prefix = use_ansi_codes ? "\x1B[K" : "";
|
|
124
|
+
const char *final_suffix;
|
|
125
|
+
|
|
126
|
+
// Only use "ticker" style updates if we're a TTY and we have no
|
|
127
|
+
// following timings.
|
|
128
|
+
if (use_ansi_codes && is_tty() && hg == NULL) {
|
|
129
|
+
// Move up 3 cursors
|
|
130
|
+
printf("\x1B[2A");
|
|
131
|
+
prefix = "\x1B[K";
|
|
132
|
+
final_suffix = "\r";
|
|
133
|
+
} else {
|
|
134
|
+
// Determine the total number of time
|
|
135
|
+
unsigned total_duration = now - start_time;
|
|
136
|
+
printf("\n"); // Clear line..
|
|
137
|
+
printf("+%us\n", total_duration);
|
|
138
|
+
prefix = "";
|
|
139
|
+
final_suffix = "\n";
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
printf("%sQUERIES/SEC: %lu\n", prefix, n_queries / duration);
|
|
143
|
+
printf("%sROWS/SEC: %lu\n", prefix, n_rows / duration);
|
|
144
|
+
printf("%sERRORS: %lu%s", prefix, n_errors, final_suffix);
|
|
145
|
+
|
|
146
|
+
if (hg != NULL) {
|
|
147
|
+
hg->write();
|
|
148
|
+
}
|
|
149
|
+
fflush(stdout);
|
|
150
|
+
|
|
151
|
+
n_queries = 0;
|
|
152
|
+
n_rows = 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
size_t n_rows;
|
|
156
|
+
size_t n_queries;
|
|
157
|
+
size_t n_errors;
|
|
158
|
+
time_t last_update;
|
|
159
|
+
time_t start_time;
|
|
160
|
+
cbc::Histogram *hg;
|
|
161
|
+
#ifndef _WIN32
|
|
162
|
+
pthread_mutex_t m_lock;
|
|
163
|
+
#endif
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
Metrics GlobalMetrics;
|
|
167
|
+
|
|
168
|
+
class Configuration
|
|
169
|
+
{
|
|
170
|
+
public:
|
|
171
|
+
Configuration() : o_file("queryfile"), o_threads("num-threads") {
|
|
172
|
+
o_file.mandatory(true);
|
|
173
|
+
o_file.description(
|
|
174
|
+
"Path to a file containing all the queries to execute. "
|
|
175
|
+
"Each line should contain the full query body");
|
|
176
|
+
o_file.abbrev('f');
|
|
177
|
+
|
|
178
|
+
o_threads.description("Number of threads to run");
|
|
179
|
+
o_threads.abbrev('t');
|
|
180
|
+
o_threads.setDefault(1);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
void addToParser(Parser& parser)
|
|
184
|
+
{
|
|
185
|
+
parser.addOption(o_file);
|
|
186
|
+
parser.addOption(o_threads);
|
|
187
|
+
m_params.addToParser(parser);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
void processOptions()
|
|
191
|
+
{
|
|
192
|
+
std::ifstream ifs(o_file.const_result().c_str());
|
|
193
|
+
if (!ifs.is_open()) {
|
|
194
|
+
int ec_save = errno;
|
|
195
|
+
string errstr(o_file.const_result());
|
|
196
|
+
errstr += ": ";
|
|
197
|
+
errstr += strerror(ec_save);
|
|
198
|
+
throw std::runtime_error(errstr);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
string curline;
|
|
202
|
+
while (std::getline(ifs, curline).good() && !ifs.eof()) {
|
|
203
|
+
m_queries.push_back(curline);
|
|
204
|
+
}
|
|
205
|
+
if (m_params.useTimings()) {
|
|
206
|
+
GlobalMetrics.prepare_timings();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
void set_cropts(lcb_create_st &opts) { m_params.fillCropts(opts); }
|
|
211
|
+
const vector<string>& queries() const { return m_queries; }
|
|
212
|
+
size_t nthreads() { return o_threads.result(); }
|
|
213
|
+
|
|
214
|
+
private:
|
|
215
|
+
vector<string> m_queries;
|
|
216
|
+
StringOption o_file;
|
|
217
|
+
UIntOption o_threads;
|
|
218
|
+
ConnParams m_params;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
extern "C" { static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp); }
|
|
222
|
+
extern "C" { static void* pthrfunc(void*); }
|
|
223
|
+
|
|
224
|
+
class ThreadContext;
|
|
225
|
+
struct QueryContext {
|
|
226
|
+
lcb_U64 begin;
|
|
227
|
+
bool received; // whether any row was received
|
|
228
|
+
ThreadContext *ctx; // Parent
|
|
229
|
+
|
|
230
|
+
QueryContext(ThreadContext *tctx)
|
|
231
|
+
: begin(lcb_nstime()), received(false), ctx(tctx) {}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
class ThreadContext {
|
|
235
|
+
public:
|
|
236
|
+
void run()
|
|
237
|
+
{
|
|
238
|
+
while (!m_cancelled) {
|
|
239
|
+
vector<string>::const_iterator ii = m_queries.begin();
|
|
240
|
+
for (; ii != m_queries.end(); ++ii) {
|
|
241
|
+
run_one_query(*ii);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
#ifndef _WIN32
|
|
247
|
+
void start()
|
|
248
|
+
{
|
|
249
|
+
assert(m_thr == NULL);
|
|
250
|
+
m_thr = new pthread_t;
|
|
251
|
+
int rc = pthread_create(m_thr, NULL, pthrfunc, this);
|
|
252
|
+
if (rc != 0) {
|
|
253
|
+
throw std::runtime_error(strerror(rc));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
void join()
|
|
258
|
+
{
|
|
259
|
+
assert(m_thr != NULL);
|
|
260
|
+
void *arg = NULL;
|
|
261
|
+
pthread_join(*m_thr, &arg);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
~ThreadContext()
|
|
265
|
+
{
|
|
266
|
+
if (m_thr != NULL) {
|
|
267
|
+
join();
|
|
268
|
+
delete m_thr;
|
|
269
|
+
m_thr = NULL;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
#else
|
|
273
|
+
void start() { run(); }
|
|
274
|
+
void join() {}
|
|
275
|
+
#endif
|
|
276
|
+
|
|
277
|
+
void handle_response(const lcb_RESPN1QL *resp, QueryContext *ctx)
|
|
278
|
+
{
|
|
279
|
+
if (!ctx->received) {
|
|
280
|
+
lcb_U64 duration = lcb_nstime() - ctx->begin;
|
|
281
|
+
m_metrics->lock();
|
|
282
|
+
m_metrics->update_timings(duration);
|
|
283
|
+
m_metrics->unlock();
|
|
284
|
+
|
|
285
|
+
ctx->received = true;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (resp->rflags & LCB_RESP_F_FINAL) {
|
|
289
|
+
if (resp->rc != LCB_SUCCESS) {
|
|
290
|
+
log_error(resp->rc);
|
|
291
|
+
}
|
|
292
|
+
} else {
|
|
293
|
+
last_nrow++;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
ThreadContext(lcb_t instance, const vector<string>& initial_queries)
|
|
298
|
+
: m_instance(instance), last_nerr(0), last_nrow(0),
|
|
299
|
+
m_metrics(&GlobalMetrics), m_cancelled(false), m_thr(NULL)
|
|
300
|
+
{
|
|
301
|
+
memset(&m_cmd, 0, sizeof m_cmd);
|
|
302
|
+
m_cmd.content_type = "application/json";
|
|
303
|
+
m_cmd.callback = n1qlcb;
|
|
304
|
+
|
|
305
|
+
// Shuffle the list
|
|
306
|
+
m_queries = initial_queries;
|
|
307
|
+
std::random_shuffle(m_queries.begin(), m_queries.end());
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private:
|
|
311
|
+
|
|
312
|
+
void log_error(lcb_error_t)
|
|
313
|
+
{
|
|
314
|
+
m_metrics->lock();
|
|
315
|
+
m_metrics->update_error();
|
|
316
|
+
m_metrics->unlock();
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
void run_one_query(const string& txt)
|
|
320
|
+
{
|
|
321
|
+
// Reset counters
|
|
322
|
+
last_nrow = 0;
|
|
323
|
+
last_nerr = 0;
|
|
324
|
+
|
|
325
|
+
m_cmd.query = txt.c_str();
|
|
326
|
+
m_cmd.nquery = txt.size();
|
|
327
|
+
|
|
328
|
+
// Set up our context
|
|
329
|
+
QueryContext qctx(this);
|
|
330
|
+
|
|
331
|
+
lcb_error_t rc = lcb_n1ql_query(m_instance, &qctx, &m_cmd);
|
|
332
|
+
if (rc != LCB_SUCCESS) {
|
|
333
|
+
log_error(rc);
|
|
334
|
+
} else {
|
|
335
|
+
lcb_wait(m_instance);
|
|
336
|
+
m_metrics->lock();
|
|
337
|
+
m_metrics->update_row(last_nrow);
|
|
338
|
+
m_metrics->update_done(1);
|
|
339
|
+
m_metrics->unlock();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
lcb_t m_instance;
|
|
344
|
+
vector<string> m_queries;
|
|
345
|
+
size_t last_nerr;
|
|
346
|
+
size_t last_nrow;
|
|
347
|
+
lcb_CMDN1QL m_cmd;
|
|
348
|
+
Metrics *m_metrics;
|
|
349
|
+
volatile bool m_cancelled;
|
|
350
|
+
#ifndef _WIN32
|
|
351
|
+
pthread_t *m_thr;
|
|
352
|
+
#else
|
|
353
|
+
void *m_thr;
|
|
354
|
+
#endif
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp)
|
|
358
|
+
{
|
|
359
|
+
QueryContext *qctx = reinterpret_cast<QueryContext*>(resp->cookie);
|
|
360
|
+
qctx->ctx->handle_response(resp, qctx);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
static void* pthrfunc(void *arg)
|
|
364
|
+
{
|
|
365
|
+
reinterpret_cast<ThreadContext*>(arg)->run();
|
|
366
|
+
return NULL;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
static bool
|
|
370
|
+
instance_has_n1ql(lcb_t instance) {
|
|
371
|
+
// Check that the instance supports N1QL
|
|
372
|
+
lcbvb_CONFIG *vbc;
|
|
373
|
+
do_or_die(lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_VBCONFIG, &vbc));
|
|
374
|
+
|
|
375
|
+
int sslmode = 0;
|
|
376
|
+
lcbvb_SVCMODE svcmode = LCBVB_SVCMODE_PLAIN;
|
|
377
|
+
|
|
378
|
+
do_or_die(lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_SSL_MODE, &sslmode));
|
|
379
|
+
|
|
380
|
+
if (sslmode & LCB_SSL_ENABLED) {
|
|
381
|
+
svcmode = LCBVB_SVCMODE_SSL;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
int hix = lcbvb_get_randhost(vbc, LCBVB_SVCTYPE_N1QL, svcmode);
|
|
385
|
+
return hix > -1;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
static void real_main(int argc, char **argv) {
|
|
389
|
+
Configuration config;
|
|
390
|
+
Parser parser;
|
|
391
|
+
config.addToParser(parser);
|
|
392
|
+
parser.parse(argc, argv);
|
|
393
|
+
|
|
394
|
+
vector<ThreadContext*> threads;
|
|
395
|
+
vector<lcb_t> instances;
|
|
396
|
+
|
|
397
|
+
lcb_create_st cropts = { 0 };
|
|
398
|
+
config.set_cropts(cropts);
|
|
399
|
+
config.processOptions();
|
|
400
|
+
|
|
401
|
+
for (size_t ii = 0; ii < config.nthreads(); ii++) {
|
|
402
|
+
lcb_t instance;
|
|
403
|
+
do_or_die(lcb_create(&instance, &cropts));
|
|
404
|
+
do_or_die(lcb_connect(instance));
|
|
405
|
+
lcb_wait(instance);
|
|
406
|
+
do_or_die(lcb_get_bootstrap_status(instance));
|
|
407
|
+
|
|
408
|
+
if (ii == 0 && !instance_has_n1ql(instance)) {
|
|
409
|
+
throw std::runtime_error("Cluster does not support N1QL!");
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
ThreadContext* cx = new ThreadContext(instance, config.queries());
|
|
413
|
+
threads.push_back(cx);
|
|
414
|
+
instances.push_back(instance);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
GlobalMetrics.prepare_screen();
|
|
418
|
+
|
|
419
|
+
for (size_t ii = 0; ii < threads.size(); ++ii) {
|
|
420
|
+
threads[ii]->start();
|
|
421
|
+
}
|
|
422
|
+
for (size_t ii = 0; ii < threads.size(); ++ii) {
|
|
423
|
+
threads[ii]->join();
|
|
424
|
+
}
|
|
425
|
+
for (size_t ii = 0; ii < instances.size(); ++ii) {
|
|
426
|
+
lcb_destroy(instances[ii]);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
int main(int argc, char **argv)
|
|
431
|
+
{
|
|
432
|
+
try {
|
|
433
|
+
real_main(argc, argv);
|
|
434
|
+
return 0;
|
|
435
|
+
} catch (std::exception& exc) {
|
|
436
|
+
cerr << exc.what() << endl;
|
|
437
|
+
exit(EXIT_FAILURE);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
@@ -0,0 +1,822 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2011-2012 Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
#define NOMINMAX // Because MS' CRT headers #define min and max :(
|
|
18
|
+
#include "config.h"
|
|
19
|
+
#include <sys/types.h>
|
|
20
|
+
#include <libcouchbase/couchbase.h>
|
|
21
|
+
#include <errno.h>
|
|
22
|
+
#include <iostream>
|
|
23
|
+
#include <map>
|
|
24
|
+
#include <sstream>
|
|
25
|
+
#include <queue>
|
|
26
|
+
#include <list>
|
|
27
|
+
#include <cstring>
|
|
28
|
+
#include <cassert>
|
|
29
|
+
#include <cstdio>
|
|
30
|
+
#include <cstdlib>
|
|
31
|
+
#include <fstream>
|
|
32
|
+
#include <signal.h>
|
|
33
|
+
#ifndef WIN32
|
|
34
|
+
#include <pthread.h>
|
|
35
|
+
#else
|
|
36
|
+
#define usleep(n) Sleep(n/1000)
|
|
37
|
+
#endif
|
|
38
|
+
#include <cstdarg>
|
|
39
|
+
#include <exception>
|
|
40
|
+
#include <stdexcept>
|
|
41
|
+
#include "common/options.h"
|
|
42
|
+
#include "common/histogram.h"
|
|
43
|
+
#include "contrib/lcb-jsoncpp/lcb-jsoncpp.h"
|
|
44
|
+
|
|
45
|
+
#include "docgen/seqgen.h"
|
|
46
|
+
#include "docgen/docgen.h"
|
|
47
|
+
|
|
48
|
+
using namespace std;
|
|
49
|
+
using namespace cbc;
|
|
50
|
+
using namespace cliopts;
|
|
51
|
+
using namespace Pillowfight;
|
|
52
|
+
using std::vector;
|
|
53
|
+
using std::string;
|
|
54
|
+
|
|
55
|
+
// Deprecated options which still exist from previous versions.
|
|
56
|
+
struct DeprecatedOptions {
|
|
57
|
+
UIntOption iterations;
|
|
58
|
+
UIntOption instances;
|
|
59
|
+
BoolOption loop;
|
|
60
|
+
|
|
61
|
+
DeprecatedOptions() :
|
|
62
|
+
iterations("iterations"), instances("num-instances"), loop("loop")
|
|
63
|
+
{
|
|
64
|
+
iterations.abbrev('i').hide().setDefault(1000);
|
|
65
|
+
instances.abbrev('Q').hide().setDefault(1);
|
|
66
|
+
loop.abbrev('l').hide().setDefault(false);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
void addOptions(Parser &p) {
|
|
70
|
+
p.addOption(instances);
|
|
71
|
+
p.addOption(loop);
|
|
72
|
+
p.addOption(iterations);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
static TemplateSpec
|
|
77
|
+
parseTemplateSpec(const string& input)
|
|
78
|
+
{
|
|
79
|
+
TemplateSpec spec;
|
|
80
|
+
// Just need to find the path
|
|
81
|
+
size_t endpos = input.find(',');
|
|
82
|
+
if (endpos == string::npos) {
|
|
83
|
+
throw std::runtime_error("invalid template spec: need field,min,max");
|
|
84
|
+
}
|
|
85
|
+
spec.term = input.substr(0, endpos);
|
|
86
|
+
unsigned is_sequential = 0;
|
|
87
|
+
int rv = sscanf(input.c_str() + endpos + 1, "%u,%u,%u",
|
|
88
|
+
&spec.minval, &spec.maxval, &is_sequential);
|
|
89
|
+
if (rv < 2) {
|
|
90
|
+
throw std::runtime_error("invalid template spec: need field,min,max");
|
|
91
|
+
}
|
|
92
|
+
spec.sequential = is_sequential;
|
|
93
|
+
if (spec.minval > spec.maxval) {
|
|
94
|
+
throw std::runtime_error("min cannot be higher than max");
|
|
95
|
+
}
|
|
96
|
+
return spec;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
class Configuration
|
|
100
|
+
{
|
|
101
|
+
public:
|
|
102
|
+
Configuration() :
|
|
103
|
+
o_multiSize("batch-size"),
|
|
104
|
+
o_numItems("num-items"),
|
|
105
|
+
o_keyPrefix("key-prefix"),
|
|
106
|
+
o_numThreads("num-threads"),
|
|
107
|
+
o_randSeed("random-seed"),
|
|
108
|
+
o_setPercent("set-pct"),
|
|
109
|
+
o_minSize("min-size"),
|
|
110
|
+
o_maxSize("max-size"),
|
|
111
|
+
o_noPopulate("no-population"),
|
|
112
|
+
o_pauseAtEnd("pause-at-end"),
|
|
113
|
+
o_numCycles("num-cycles"),
|
|
114
|
+
o_sequential("sequential"),
|
|
115
|
+
o_startAt("start-at"),
|
|
116
|
+
o_rateLimit("rate-limit"),
|
|
117
|
+
o_userdocs("docs"),
|
|
118
|
+
o_writeJson("json"),
|
|
119
|
+
o_templatePairs("template"),
|
|
120
|
+
o_subdoc("subdoc"),
|
|
121
|
+
o_sdPathCount("pathcount"),
|
|
122
|
+
o_populateOnly("populate-only"),
|
|
123
|
+
o_exptime("expiry")
|
|
124
|
+
{
|
|
125
|
+
o_multiSize.setDefault(100).abbrev('B').description("Number of operations to batch");
|
|
126
|
+
o_numItems.setDefault(1000).abbrev('I').description("Number of items to operate on");
|
|
127
|
+
o_keyPrefix.abbrev('p').description("key prefix to use");
|
|
128
|
+
o_numThreads.setDefault(1).abbrev('t').description("The number of threads to use");
|
|
129
|
+
o_randSeed.setDefault(0).abbrev('s').description("Specify random seed").hide();
|
|
130
|
+
o_setPercent.setDefault(33).abbrev('r').description("The percentage of operations which should be mutations");
|
|
131
|
+
o_minSize.setDefault(50).abbrev('m').description("Set minimum payload size");
|
|
132
|
+
o_maxSize.setDefault(5120).abbrev('M').description("Set maximum payload size");
|
|
133
|
+
o_noPopulate.setDefault(false).abbrev('n').description("Skip population");
|
|
134
|
+
o_pauseAtEnd.setDefault(false).abbrev('E').description("Pause at end of run (holding connections open) until user input");
|
|
135
|
+
o_numCycles.setDefault(-1).abbrev('c').description("Number of cycles to be run until exiting. Set to -1 to loop infinitely");
|
|
136
|
+
o_sequential.setDefault(false).description("Use sequential access (instead of random)");
|
|
137
|
+
o_startAt.setDefault(0).description("For sequential access, set the first item");
|
|
138
|
+
o_rateLimit.setDefault(0).description("Set operations per second limit (per thread)");
|
|
139
|
+
o_userdocs.description("User documents to load (overrides --min-size and --max-size");
|
|
140
|
+
o_writeJson.description("Enable writing JSON values (rather than bytes)");
|
|
141
|
+
o_templatePairs.description("Values for templates to be inserted into user documents");
|
|
142
|
+
o_templatePairs.argdesc("FIELD,MIN,MAX[,SEQUENTIAL]").hide();
|
|
143
|
+
o_subdoc.description("Use subdoc instead of fulldoc operations");
|
|
144
|
+
o_sdPathCount.description("Number of subdoc paths per command").setDefault(1);
|
|
145
|
+
o_populateOnly.description("Exit after documents have been populated");
|
|
146
|
+
o_exptime.description("Set TTL for items").abbrev('e');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
void processOptions() {
|
|
150
|
+
opsPerCycle = o_multiSize.result();
|
|
151
|
+
prefix = o_keyPrefix.result();
|
|
152
|
+
setprc = o_setPercent.result();
|
|
153
|
+
shouldPopulate = !o_noPopulate.result();
|
|
154
|
+
|
|
155
|
+
if (depr.loop.passed()) {
|
|
156
|
+
fprintf(stderr, "The --loop/-l option is deprecated. Use --num-cycles\n");
|
|
157
|
+
maxCycles = -1;
|
|
158
|
+
} else {
|
|
159
|
+
maxCycles = o_numCycles.result();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (o_populateOnly.passed()) {
|
|
163
|
+
// Determine how many iterations are required.
|
|
164
|
+
if (o_numCycles.passed()) {
|
|
165
|
+
throw std::runtime_error("--num-cycles incompatible with --populate-only");
|
|
166
|
+
}
|
|
167
|
+
size_t est = (o_numItems / o_numThreads) / o_multiSize;
|
|
168
|
+
while (est * o_numThreads * o_multiSize < o_numItems) {
|
|
169
|
+
est++;
|
|
170
|
+
}
|
|
171
|
+
maxCycles = est;
|
|
172
|
+
o_sequential.setDefault(true);
|
|
173
|
+
fprintf(stderr, "Populating using %lu cycles\n", maxCycles);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (depr.iterations.passed()) {
|
|
177
|
+
fprintf(stderr, "The --num-iterations/-I option is deprecated. Use --batch-size\n");
|
|
178
|
+
opsPerCycle = depr.iterations.result();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
vector<TemplateSpec> specs;
|
|
182
|
+
vector<string> userdocs;
|
|
183
|
+
|
|
184
|
+
if (o_templatePairs.passed()) {
|
|
185
|
+
vector<string> specs_str = o_templatePairs.result();
|
|
186
|
+
for (size_t ii = 0; ii < specs_str.size(); ii++) {
|
|
187
|
+
specs.push_back(parseTemplateSpec(specs_str[ii]));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Set the document sizes..
|
|
192
|
+
if (o_userdocs.passed()) {
|
|
193
|
+
if (o_minSize.passed() || o_maxSize.passed()) {
|
|
194
|
+
fprintf(stderr, "--min-size/--max-size invalid with userdocs\n");
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
vector<string> filenames = o_userdocs.result();
|
|
198
|
+
for (size_t ii = 0; ii < filenames.size(); ii++) {
|
|
199
|
+
std::stringstream ss;
|
|
200
|
+
std::ifstream ifs(filenames[ii].c_str());
|
|
201
|
+
if (!ifs.is_open()) {
|
|
202
|
+
perror(filenames[ii].c_str());
|
|
203
|
+
exit(EXIT_FAILURE);
|
|
204
|
+
}
|
|
205
|
+
ss << ifs.rdbuf();
|
|
206
|
+
userdocs.push_back(ss.str());
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (specs.empty()) {
|
|
211
|
+
if (o_writeJson.result()) {
|
|
212
|
+
docgen = new JsonDocGenerator(o_minSize.result(), o_maxSize.result());
|
|
213
|
+
} else if (!userdocs.empty()) {
|
|
214
|
+
docgen = new PresetDocGenerator(userdocs);
|
|
215
|
+
} else {
|
|
216
|
+
docgen = new RawDocGenerator(o_minSize.result(), o_maxSize.result());
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
if (o_writeJson.result()) {
|
|
220
|
+
if (userdocs.empty()) {
|
|
221
|
+
docgen = new PlaceholderJsonGenerator(
|
|
222
|
+
o_minSize.result(), o_maxSize.result(), specs);
|
|
223
|
+
} else {
|
|
224
|
+
docgen = new PlaceholderJsonGenerator(userdocs, specs);
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
if (userdocs.empty()) {
|
|
228
|
+
throw std::runtime_error("Must provide documents with placeholders!");
|
|
229
|
+
}
|
|
230
|
+
docgen = new PlaceholderDocGenerator(userdocs, specs);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
sdOpsPerCmd = o_sdPathCount.result();
|
|
235
|
+
if (o_sdPathCount.passed()) {
|
|
236
|
+
o_subdoc.setDefault(true);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
void addOptions(Parser& parser) {
|
|
241
|
+
parser.addOption(o_multiSize);
|
|
242
|
+
parser.addOption(o_numItems);
|
|
243
|
+
parser.addOption(o_keyPrefix);
|
|
244
|
+
parser.addOption(o_numThreads);
|
|
245
|
+
parser.addOption(o_randSeed);
|
|
246
|
+
parser.addOption(o_setPercent);
|
|
247
|
+
parser.addOption(o_noPopulate);
|
|
248
|
+
parser.addOption(o_minSize);
|
|
249
|
+
parser.addOption(o_maxSize);
|
|
250
|
+
parser.addOption(o_pauseAtEnd);
|
|
251
|
+
parser.addOption(o_numCycles);
|
|
252
|
+
parser.addOption(o_sequential);
|
|
253
|
+
parser.addOption(o_startAt);
|
|
254
|
+
parser.addOption(o_rateLimit);
|
|
255
|
+
parser.addOption(o_userdocs);
|
|
256
|
+
parser.addOption(o_writeJson);
|
|
257
|
+
parser.addOption(o_templatePairs);
|
|
258
|
+
parser.addOption(o_subdoc);
|
|
259
|
+
parser.addOption(o_sdPathCount);
|
|
260
|
+
parser.addOption(o_populateOnly);
|
|
261
|
+
parser.addOption(o_exptime);
|
|
262
|
+
params.addToParser(parser);
|
|
263
|
+
depr.addOptions(parser);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
bool isTimings(void) { return params.useTimings(); }
|
|
267
|
+
|
|
268
|
+
bool isLoopDone(size_t niter) {
|
|
269
|
+
if (maxCycles == -1) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
return niter >= (size_t)maxCycles;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
uint32_t getRandomSeed() { return o_randSeed; }
|
|
276
|
+
uint32_t getNumThreads() { return o_numThreads; }
|
|
277
|
+
string& getKeyPrefix() { return prefix; }
|
|
278
|
+
bool shouldPauseAtEnd() { return o_pauseAtEnd; }
|
|
279
|
+
bool sequentialAccess() { return o_sequential; }
|
|
280
|
+
bool isSubdoc() { return o_subdoc; }
|
|
281
|
+
unsigned firstKeyOffset() { return o_startAt; }
|
|
282
|
+
uint32_t getNumItems() { return o_numItems; }
|
|
283
|
+
uint32_t getRateLimit() { return o_rateLimit; }
|
|
284
|
+
unsigned getExptime() { return o_exptime; }
|
|
285
|
+
|
|
286
|
+
uint32_t opsPerCycle;
|
|
287
|
+
uint32_t sdOpsPerCmd;
|
|
288
|
+
unsigned setprc;
|
|
289
|
+
string prefix;
|
|
290
|
+
volatile int maxCycles;
|
|
291
|
+
bool shouldPopulate;
|
|
292
|
+
bool hasTemplates;
|
|
293
|
+
ConnParams params;
|
|
294
|
+
const DocGeneratorBase *docgen;
|
|
295
|
+
|
|
296
|
+
private:
|
|
297
|
+
UIntOption o_multiSize;
|
|
298
|
+
UIntOption o_numItems;
|
|
299
|
+
StringOption o_keyPrefix;
|
|
300
|
+
UIntOption o_numThreads;
|
|
301
|
+
UIntOption o_randSeed;
|
|
302
|
+
UIntOption o_setPercent;
|
|
303
|
+
UIntOption o_minSize;
|
|
304
|
+
UIntOption o_maxSize;
|
|
305
|
+
BoolOption o_noPopulate;
|
|
306
|
+
BoolOption o_pauseAtEnd; // Should pillowfight pause execution (with
|
|
307
|
+
// connections open) before exiting?
|
|
308
|
+
IntOption o_numCycles;
|
|
309
|
+
BoolOption o_sequential;
|
|
310
|
+
UIntOption o_startAt;
|
|
311
|
+
UIntOption o_rateLimit;
|
|
312
|
+
|
|
313
|
+
// List of paths to user documents to load.. They should all be valid JSON
|
|
314
|
+
ListOption o_userdocs;
|
|
315
|
+
|
|
316
|
+
// Whether generated values should be JSON
|
|
317
|
+
BoolOption o_writeJson;
|
|
318
|
+
|
|
319
|
+
// List of template ranges for value generation
|
|
320
|
+
ListOption o_templatePairs;
|
|
321
|
+
BoolOption o_subdoc;
|
|
322
|
+
UIntOption o_sdPathCount;
|
|
323
|
+
|
|
324
|
+
// Compound option
|
|
325
|
+
BoolOption o_populateOnly;
|
|
326
|
+
|
|
327
|
+
UIntOption o_exptime;
|
|
328
|
+
|
|
329
|
+
DeprecatedOptions depr;
|
|
330
|
+
} config;
|
|
331
|
+
|
|
332
|
+
void log(const char *format, ...)
|
|
333
|
+
{
|
|
334
|
+
char buffer[512];
|
|
335
|
+
va_list args;
|
|
336
|
+
|
|
337
|
+
va_start(args, format);
|
|
338
|
+
vsprintf(buffer, format, args);
|
|
339
|
+
if (config.isTimings()) {
|
|
340
|
+
std::cerr << "[" << std::fixed << lcb_nstime() / 1000000000.0 << "] ";
|
|
341
|
+
}
|
|
342
|
+
std::cerr << buffer << std::endl;
|
|
343
|
+
va_end(args);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
extern "C" {
|
|
349
|
+
static void operationCallback(lcb_t, int, const lcb_RESPBASE*);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
class InstanceCookie {
|
|
353
|
+
public:
|
|
354
|
+
InstanceCookie(lcb_t instance) {
|
|
355
|
+
lcb_set_cookie(instance, this);
|
|
356
|
+
lastPrint = 0;
|
|
357
|
+
if (config.isTimings()) {
|
|
358
|
+
hg.install(instance, stdout);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
static InstanceCookie* get(lcb_t instance) {
|
|
363
|
+
return (InstanceCookie *)lcb_get_cookie(instance);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
static void dumpTimings(lcb_t instance, const char *header, bool force=false) {
|
|
368
|
+
time_t now = time(NULL);
|
|
369
|
+
InstanceCookie *ic = get(instance);
|
|
370
|
+
|
|
371
|
+
if (now - ic->lastPrint > 0) {
|
|
372
|
+
ic->lastPrint = now;
|
|
373
|
+
} else if (!force) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
Histogram &h = ic->hg;
|
|
378
|
+
printf("[%f %s]\n", lcb_nstime() / 1000000000.0, header);
|
|
379
|
+
printf(" +---------+---------+---------+---------+\n");
|
|
380
|
+
h.write();
|
|
381
|
+
printf(" +----------------------------------------\n");
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
private:
|
|
385
|
+
time_t lastPrint;
|
|
386
|
+
Histogram hg;
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
struct NextOp {
|
|
390
|
+
NextOp() : m_seqno(0), m_mode(GET) {}
|
|
391
|
+
|
|
392
|
+
string m_key;
|
|
393
|
+
uint32_t m_seqno;
|
|
394
|
+
vector<lcb_IOV> m_valuefrags;
|
|
395
|
+
vector<lcb_SDSPEC> m_specs;
|
|
396
|
+
// The mode here is for future use with subdoc
|
|
397
|
+
enum Mode { STORE, GET, SDSTORE, SDGET };
|
|
398
|
+
Mode m_mode;
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
/** Stateful, per-thread generator */
|
|
402
|
+
class KeyGenerator {
|
|
403
|
+
public:
|
|
404
|
+
KeyGenerator(int ix)
|
|
405
|
+
: m_gencount(0), m_force_sequential(false),
|
|
406
|
+
m_in_population(config.shouldPopulate)
|
|
407
|
+
{
|
|
408
|
+
srand(config.getRandomSeed());
|
|
409
|
+
|
|
410
|
+
m_genrandom = new SeqGenerator(
|
|
411
|
+
config.firstKeyOffset(),
|
|
412
|
+
config.getNumItems() + config.firstKeyOffset());
|
|
413
|
+
|
|
414
|
+
m_gensequence = new SeqGenerator(
|
|
415
|
+
config.firstKeyOffset(),
|
|
416
|
+
config.getNumItems() + config.firstKeyOffset(),
|
|
417
|
+
config.getNumThreads(),
|
|
418
|
+
ix);
|
|
419
|
+
|
|
420
|
+
if (m_in_population) {
|
|
421
|
+
m_force_sequential = true;
|
|
422
|
+
} else {
|
|
423
|
+
m_force_sequential = config.sequentialAccess();
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
m_id = ix;
|
|
427
|
+
m_local_genstate = config.docgen->createState(config.getNumThreads(), ix);
|
|
428
|
+
if (config.isSubdoc()) {
|
|
429
|
+
m_mode_read = NextOp::SDGET;
|
|
430
|
+
m_mode_write = NextOp::SDSTORE;
|
|
431
|
+
m_sdgenstate = config.docgen->createSubdocState(config.getNumThreads(), ix);
|
|
432
|
+
if (!m_sdgenstate) {
|
|
433
|
+
std::cerr << "Current generator does not support subdoc. Did you try --json?" << std::endl;
|
|
434
|
+
exit(EXIT_FAILURE);
|
|
435
|
+
}
|
|
436
|
+
} else {
|
|
437
|
+
m_mode_read = NextOp::GET;
|
|
438
|
+
m_mode_write = NextOp::STORE;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
void setNextOp(NextOp& op) {
|
|
443
|
+
bool store_override = false;
|
|
444
|
+
|
|
445
|
+
if (m_in_population) {
|
|
446
|
+
if (m_gencount++ < m_gensequence->maxItems()) {
|
|
447
|
+
store_override = true;
|
|
448
|
+
} else {
|
|
449
|
+
printf("Thread %d has finished populating.\n", m_id);
|
|
450
|
+
m_in_population = false;
|
|
451
|
+
m_force_sequential = config.sequentialAccess();
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (m_force_sequential) {
|
|
456
|
+
op.m_seqno = m_gensequence->next();
|
|
457
|
+
} else {
|
|
458
|
+
op.m_seqno = m_genrandom->next();
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (store_override) {
|
|
462
|
+
// Populate
|
|
463
|
+
op.m_mode = NextOp::STORE;
|
|
464
|
+
m_local_genstate->populateIov(op.m_seqno, op.m_valuefrags);
|
|
465
|
+
|
|
466
|
+
} else if (shouldStore(op.m_seqno)) {
|
|
467
|
+
op.m_mode = m_mode_write;
|
|
468
|
+
if (op.m_mode == NextOp::STORE) {
|
|
469
|
+
m_local_genstate->populateIov(op.m_seqno, op.m_valuefrags);
|
|
470
|
+
} else if (op.m_mode == NextOp::SDSTORE) {
|
|
471
|
+
op.m_specs.resize(config.sdOpsPerCmd);
|
|
472
|
+
m_sdgenstate->populateMutate(op.m_seqno, op.m_specs);
|
|
473
|
+
} else {
|
|
474
|
+
fprintf(stderr, "Invalid mode for op: %d\n", op.m_mode);
|
|
475
|
+
abort();
|
|
476
|
+
}
|
|
477
|
+
} else {
|
|
478
|
+
op.m_mode = m_mode_read;
|
|
479
|
+
if (op.m_mode == NextOp::SDGET) {
|
|
480
|
+
op.m_specs.resize(config.sdOpsPerCmd);
|
|
481
|
+
m_sdgenstate->populateLookup(op.m_seqno, op.m_specs);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
generateKey(op);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
bool shouldStore(uint32_t seqno) {
|
|
489
|
+
if (config.setprc == 0) {
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
float seqno_f = seqno % 100;
|
|
494
|
+
float pct_f = seqno_f / config.setprc;
|
|
495
|
+
return pct_f < 1;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
void generateKey(NextOp& op) {
|
|
499
|
+
uint32_t seqno = op.m_seqno;
|
|
500
|
+
char buffer[21];
|
|
501
|
+
snprintf(buffer, sizeof(buffer), "%020d", seqno);
|
|
502
|
+
op.m_key.assign(config.getKeyPrefix() + buffer);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const char *getStageString() const {
|
|
506
|
+
if (m_in_population) {
|
|
507
|
+
return "Populate";
|
|
508
|
+
} else {
|
|
509
|
+
return "Run";
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
private:
|
|
514
|
+
SeqGenerator *m_genrandom;
|
|
515
|
+
SeqGenerator *m_gensequence;
|
|
516
|
+
size_t m_gencount;
|
|
517
|
+
int m_id;
|
|
518
|
+
|
|
519
|
+
bool m_force_sequential;
|
|
520
|
+
bool m_in_population;
|
|
521
|
+
NextOp::Mode m_mode_read;
|
|
522
|
+
NextOp::Mode m_mode_write;
|
|
523
|
+
GeneratorState *m_local_genstate;
|
|
524
|
+
SubdocGeneratorState *m_sdgenstate;
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
class ThreadContext
|
|
528
|
+
{
|
|
529
|
+
public:
|
|
530
|
+
ThreadContext(lcb_t handle, int ix) : kgen(ix), niter(0), instance(handle) {
|
|
531
|
+
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
void singleLoop() {
|
|
535
|
+
bool hasItems = false;
|
|
536
|
+
lcb_sched_enter(instance);
|
|
537
|
+
NextOp opinfo;
|
|
538
|
+
unsigned exptime = config.getExptime();
|
|
539
|
+
|
|
540
|
+
for (size_t ii = 0; ii < config.opsPerCycle; ++ii) {
|
|
541
|
+
kgen.setNextOp(opinfo);
|
|
542
|
+
|
|
543
|
+
switch (opinfo.m_mode) {
|
|
544
|
+
case NextOp::STORE: {
|
|
545
|
+
lcb_CMDSTORE scmd = { 0 };
|
|
546
|
+
scmd.operation = LCB_SET;
|
|
547
|
+
scmd.exptime = exptime;
|
|
548
|
+
LCB_CMD_SET_KEY(&scmd, opinfo.m_key.c_str(), opinfo.m_key.size());
|
|
549
|
+
LCB_CMD_SET_VALUEIOV(&scmd, &opinfo.m_valuefrags[0], opinfo.m_valuefrags.size());
|
|
550
|
+
error = lcb_store3(instance, this, &scmd);
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
553
|
+
case NextOp::GET: {
|
|
554
|
+
lcb_CMDGET gcmd = { 0 };
|
|
555
|
+
LCB_CMD_SET_KEY(&gcmd, opinfo.m_key.c_str(), opinfo.m_key.size());
|
|
556
|
+
gcmd.exptime = exptime;
|
|
557
|
+
error = lcb_get3(instance, this, &gcmd);
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
case NextOp::SDSTORE:
|
|
561
|
+
case NextOp::SDGET: {
|
|
562
|
+
lcb_CMDSUBDOC sdcmd = { 0 };
|
|
563
|
+
if (opinfo.m_mode == NextOp::SDSTORE) {
|
|
564
|
+
sdcmd.exptime = exptime;
|
|
565
|
+
}
|
|
566
|
+
LCB_CMD_SET_KEY(&sdcmd, opinfo.m_key.c_str(), opinfo.m_key.size());
|
|
567
|
+
sdcmd.specs = &opinfo.m_specs[0];
|
|
568
|
+
sdcmd.nspecs = opinfo.m_specs.size();
|
|
569
|
+
error = lcb_subdoc3(instance, this, &sdcmd);
|
|
570
|
+
break;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
if (error != LCB_SUCCESS) {
|
|
575
|
+
hasItems = false;
|
|
576
|
+
log("Failed to schedule operation: [0x%x] %s", error, lcb_strerror(instance, error));
|
|
577
|
+
} else {
|
|
578
|
+
hasItems = true;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
if (hasItems) {
|
|
582
|
+
lcb_sched_leave(instance);
|
|
583
|
+
lcb_wait(instance);
|
|
584
|
+
if (error != LCB_SUCCESS) {
|
|
585
|
+
log("Operation(s) failed: [0x%x] %s", error, lcb_strerror(instance, error));
|
|
586
|
+
}
|
|
587
|
+
} else {
|
|
588
|
+
lcb_sched_fail(instance);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
bool run() {
|
|
593
|
+
do {
|
|
594
|
+
singleLoop();
|
|
595
|
+
|
|
596
|
+
if (config.isTimings()) {
|
|
597
|
+
InstanceCookie::dumpTimings(instance, kgen.getStageString());
|
|
598
|
+
}
|
|
599
|
+
if (config.params.shouldDump()) {
|
|
600
|
+
lcb_dump(instance, stderr, LCB_DUMP_ALL);
|
|
601
|
+
}
|
|
602
|
+
if (config.getRateLimit() > 0) {
|
|
603
|
+
rateLimitThrottle();
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
} while (!config.isLoopDone(++niter));
|
|
607
|
+
|
|
608
|
+
if (config.isTimings()) {
|
|
609
|
+
InstanceCookie::dumpTimings(instance, kgen.getStageString(), true);
|
|
610
|
+
}
|
|
611
|
+
return true;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
#ifndef WIN32
|
|
615
|
+
pthread_t thr;
|
|
616
|
+
#endif
|
|
617
|
+
|
|
618
|
+
protected:
|
|
619
|
+
// the callback methods needs to be able to set the error handler..
|
|
620
|
+
friend void operationCallback(lcb_t, int, const lcb_RESPBASE*);
|
|
621
|
+
Histogram histogram;
|
|
622
|
+
|
|
623
|
+
void setError(lcb_error_t e) { error = e; }
|
|
624
|
+
|
|
625
|
+
private:
|
|
626
|
+
|
|
627
|
+
void rateLimitThrottle() {
|
|
628
|
+
lcb_U64 now = lcb_nstime();
|
|
629
|
+
static lcb_U64 previous_time = now;
|
|
630
|
+
|
|
631
|
+
const lcb_U64 elapsed_ns = now - previous_time;
|
|
632
|
+
const lcb_U64 wanted_duration_ns =
|
|
633
|
+
config.opsPerCycle * 1e9 / config.getRateLimit();
|
|
634
|
+
// On first invocation no previous_time, so skip attempting to sleep.
|
|
635
|
+
if (elapsed_ns > 0 && elapsed_ns < wanted_duration_ns) {
|
|
636
|
+
// Dampen the sleep time by averaging with the previous
|
|
637
|
+
// sleep time.
|
|
638
|
+
static lcb_U64 last_sleep_ns = 0;
|
|
639
|
+
const lcb_U64 sleep_ns =
|
|
640
|
+
(last_sleep_ns + wanted_duration_ns - elapsed_ns) / 2;
|
|
641
|
+
usleep(sleep_ns / 1000);
|
|
642
|
+
now += sleep_ns;
|
|
643
|
+
last_sleep_ns = sleep_ns;
|
|
644
|
+
}
|
|
645
|
+
previous_time = now;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
KeyGenerator kgen;
|
|
649
|
+
size_t niter;
|
|
650
|
+
lcb_error_t error;
|
|
651
|
+
lcb_t instance;
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
static void operationCallback(lcb_t, int, const lcb_RESPBASE *resp)
|
|
655
|
+
{
|
|
656
|
+
ThreadContext *tc;
|
|
657
|
+
|
|
658
|
+
tc = const_cast<ThreadContext *>(reinterpret_cast<const ThreadContext *>(resp->cookie));
|
|
659
|
+
tc->setError(resp->rc);
|
|
660
|
+
|
|
661
|
+
#ifndef WIN32
|
|
662
|
+
static volatile unsigned long nops = 1;
|
|
663
|
+
static time_t start_time = time(NULL);
|
|
664
|
+
static int is_tty = isatty(STDOUT_FILENO);
|
|
665
|
+
if (is_tty) {
|
|
666
|
+
if (++nops % 1000 == 0) {
|
|
667
|
+
time_t now = time(NULL);
|
|
668
|
+
time_t nsecs = now - start_time;
|
|
669
|
+
if (!nsecs) { nsecs = 1; }
|
|
670
|
+
unsigned long ops_sec = nops / nsecs;
|
|
671
|
+
printf("OPS/SEC: %10lu\r", ops_sec);
|
|
672
|
+
fflush(stdout);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
#endif
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
std::list<ThreadContext *> contexts;
|
|
680
|
+
|
|
681
|
+
extern "C" {
|
|
682
|
+
typedef void (*handler_t)(int);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
#ifndef WIN32
|
|
686
|
+
static void sigint_handler(int)
|
|
687
|
+
{
|
|
688
|
+
static int ncalled = 0;
|
|
689
|
+
ncalled++;
|
|
690
|
+
|
|
691
|
+
if (ncalled < 2) {
|
|
692
|
+
log("Termination requested. Waiting threads to finish. Ctrl-C to force termination.");
|
|
693
|
+
signal(SIGINT, sigint_handler); // Reinstall
|
|
694
|
+
config.maxCycles = 0;
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
std::list<ThreadContext *>::iterator it;
|
|
699
|
+
for (it = contexts.begin(); it != contexts.end(); ++it) {
|
|
700
|
+
delete *it;
|
|
701
|
+
}
|
|
702
|
+
contexts.clear();
|
|
703
|
+
exit(EXIT_FAILURE);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
static void setup_sigint_handler()
|
|
707
|
+
{
|
|
708
|
+
struct sigaction action;
|
|
709
|
+
sigemptyset(&action.sa_mask);
|
|
710
|
+
action.sa_handler = sigint_handler;
|
|
711
|
+
action.sa_flags = 0;
|
|
712
|
+
sigaction(SIGINT, &action, NULL);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
extern "C" {
|
|
716
|
+
static void* thread_worker(void*);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
static void start_worker(ThreadContext *ctx)
|
|
720
|
+
{
|
|
721
|
+
pthread_attr_t attr;
|
|
722
|
+
pthread_attr_init(&attr);
|
|
723
|
+
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
|
724
|
+
int rc = pthread_create(&ctx->thr, &attr, thread_worker, ctx);
|
|
725
|
+
if (rc != 0) {
|
|
726
|
+
log("Couldn't create thread: (%d)", errno);
|
|
727
|
+
exit(EXIT_FAILURE);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
static void join_worker(ThreadContext *ctx)
|
|
731
|
+
{
|
|
732
|
+
void *arg = NULL;
|
|
733
|
+
int rc = pthread_join(ctx->thr, &arg);
|
|
734
|
+
if (rc != 0) {
|
|
735
|
+
log("Couldn't join thread (%d)", errno);
|
|
736
|
+
exit(EXIT_FAILURE);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
#else
|
|
741
|
+
static void setup_sigint_handler() {}
|
|
742
|
+
static void start_worker(ThreadContext *ctx) { ctx->run(); }
|
|
743
|
+
static void join_worker(ThreadContext *ctx) { (void)ctx; }
|
|
744
|
+
#endif
|
|
745
|
+
|
|
746
|
+
extern "C" {
|
|
747
|
+
static void *thread_worker(void *arg)
|
|
748
|
+
{
|
|
749
|
+
ThreadContext *ctx = static_cast<ThreadContext *>(arg);
|
|
750
|
+
ctx->run();
|
|
751
|
+
return NULL;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
int main(int argc, char **argv)
|
|
756
|
+
{
|
|
757
|
+
int exit_code = EXIT_SUCCESS;
|
|
758
|
+
setup_sigint_handler();
|
|
759
|
+
|
|
760
|
+
Parser parser("cbc-pillowfight");
|
|
761
|
+
config.addOptions(parser);
|
|
762
|
+
try {
|
|
763
|
+
parser.parse(argc, argv, false);
|
|
764
|
+
config.processOptions();
|
|
765
|
+
} catch (std::string& e) {
|
|
766
|
+
std::cerr << e << std::endl;
|
|
767
|
+
exit(EXIT_FAILURE);
|
|
768
|
+
} catch (std::exception& e) {
|
|
769
|
+
std::cerr << e.what() << std::endl;
|
|
770
|
+
exit(EXIT_FAILURE);
|
|
771
|
+
}
|
|
772
|
+
size_t nthreads = config.getNumThreads();
|
|
773
|
+
log("Running. Press Ctrl-C to terminate...");
|
|
774
|
+
|
|
775
|
+
#ifdef WIN32
|
|
776
|
+
if (nthreads > 1) {
|
|
777
|
+
log("WARNING: More than a single thread on Windows not supported. Forcing 1");
|
|
778
|
+
nthreads = 1;
|
|
779
|
+
}
|
|
780
|
+
#endif
|
|
781
|
+
|
|
782
|
+
struct lcb_create_st options;
|
|
783
|
+
ConnParams& cp = config.params;
|
|
784
|
+
lcb_error_t error;
|
|
785
|
+
|
|
786
|
+
for (uint32_t ii = 0; ii < nthreads; ++ii) {
|
|
787
|
+
cp.fillCropts(options);
|
|
788
|
+
lcb_t instance = NULL;
|
|
789
|
+
error = lcb_create(&instance, &options);
|
|
790
|
+
if (error != LCB_SUCCESS) {
|
|
791
|
+
log("Failed to create instance: %s", lcb_strerror(NULL, error));
|
|
792
|
+
exit(EXIT_FAILURE);
|
|
793
|
+
}
|
|
794
|
+
lcb_install_callback3(instance, LCB_CALLBACK_STORE, operationCallback);
|
|
795
|
+
lcb_install_callback3(instance, LCB_CALLBACK_GET, operationCallback);
|
|
796
|
+
lcb_install_callback3(instance, LCB_CALLBACK_SDMUTATE, operationCallback);
|
|
797
|
+
lcb_install_callback3(instance, LCB_CALLBACK_SDLOOKUP, operationCallback);
|
|
798
|
+
cp.doCtls(instance);
|
|
799
|
+
|
|
800
|
+
new InstanceCookie(instance);
|
|
801
|
+
|
|
802
|
+
lcb_connect(instance);
|
|
803
|
+
lcb_wait(instance);
|
|
804
|
+
error = lcb_get_bootstrap_status(instance);
|
|
805
|
+
|
|
806
|
+
if (error != LCB_SUCCESS) {
|
|
807
|
+
std::cout << std::endl;
|
|
808
|
+
log("Failed to connect: %s", lcb_strerror(instance, error));
|
|
809
|
+
exit(EXIT_FAILURE);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
ThreadContext *ctx = new ThreadContext(instance, ii);
|
|
813
|
+
contexts.push_back(ctx);
|
|
814
|
+
start_worker(ctx);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
for (std::list<ThreadContext *>::iterator it = contexts.begin();
|
|
818
|
+
it != contexts.end(); ++it) {
|
|
819
|
+
join_worker(*it);
|
|
820
|
+
}
|
|
821
|
+
return exit_code;
|
|
822
|
+
}
|