@point3/node-rdkafka 3.6.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.
- package/LICENSE.txt +20 -0
- package/README.md +636 -0
- package/binding.gyp +154 -0
- package/deps/librdkafka/.clang-format +136 -0
- package/deps/librdkafka/.clang-format-cpp +103 -0
- package/deps/librdkafka/.dir-locals.el +10 -0
- package/deps/librdkafka/.formatignore +33 -0
- package/deps/librdkafka/.gdbmacros +19 -0
- package/deps/librdkafka/.github/CODEOWNERS +1 -0
- package/deps/librdkafka/.github/ISSUE_TEMPLATE +34 -0
- package/deps/librdkafka/.semaphore/run-all-tests.yml +77 -0
- package/deps/librdkafka/.semaphore/semaphore-integration.yml +250 -0
- package/deps/librdkafka/.semaphore/semaphore.yml +378 -0
- package/deps/librdkafka/.semaphore/verify-linux-packages.yml +41 -0
- package/deps/librdkafka/CHANGELOG.md +2208 -0
- package/deps/librdkafka/CMakeLists.txt +291 -0
- package/deps/librdkafka/CODE_OF_CONDUCT.md +46 -0
- package/deps/librdkafka/CONFIGURATION.md +209 -0
- package/deps/librdkafka/CONTRIBUTING.md +431 -0
- package/deps/librdkafka/Doxyfile +2375 -0
- package/deps/librdkafka/INTRODUCTION.md +2481 -0
- package/deps/librdkafka/LICENSE +26 -0
- package/deps/librdkafka/LICENSE.cjson +22 -0
- package/deps/librdkafka/LICENSE.crc32c +28 -0
- package/deps/librdkafka/LICENSE.fnv1a +18 -0
- package/deps/librdkafka/LICENSE.hdrhistogram +27 -0
- package/deps/librdkafka/LICENSE.lz4 +26 -0
- package/deps/librdkafka/LICENSE.murmur2 +25 -0
- package/deps/librdkafka/LICENSE.nanopb +22 -0
- package/deps/librdkafka/LICENSE.opentelemetry +203 -0
- package/deps/librdkafka/LICENSE.pycrc +23 -0
- package/deps/librdkafka/LICENSE.queue +31 -0
- package/deps/librdkafka/LICENSE.regexp +5 -0
- package/deps/librdkafka/LICENSE.snappy +36 -0
- package/deps/librdkafka/LICENSE.tinycthread +26 -0
- package/deps/librdkafka/LICENSE.wingetopt +49 -0
- package/deps/librdkafka/LICENSES.txt +625 -0
- package/deps/librdkafka/Makefile +125 -0
- package/deps/librdkafka/README.md +199 -0
- package/deps/librdkafka/README.win32 +26 -0
- package/deps/librdkafka/STATISTICS.md +624 -0
- package/deps/librdkafka/configure +214 -0
- package/deps/librdkafka/configure.self +331 -0
- package/deps/librdkafka/debian/changelog +111 -0
- package/deps/librdkafka/debian/compat +1 -0
- package/deps/librdkafka/debian/control +71 -0
- package/deps/librdkafka/debian/copyright +99 -0
- package/deps/librdkafka/debian/gbp.conf +9 -0
- package/deps/librdkafka/debian/librdkafka++1.install +1 -0
- package/deps/librdkafka/debian/librdkafka-dev.examples +2 -0
- package/deps/librdkafka/debian/librdkafka-dev.install +9 -0
- package/deps/librdkafka/debian/librdkafka1.docs +5 -0
- package/deps/librdkafka/debian/librdkafka1.install +1 -0
- package/deps/librdkafka/debian/librdkafka1.symbols +135 -0
- package/deps/librdkafka/debian/rules +19 -0
- package/deps/librdkafka/debian/source/format +1 -0
- package/deps/librdkafka/debian/watch +2 -0
- package/deps/librdkafka/dev-conf.sh +123 -0
- package/deps/librdkafka/examples/CMakeLists.txt +79 -0
- package/deps/librdkafka/examples/Makefile +167 -0
- package/deps/librdkafka/examples/README.md +42 -0
- package/deps/librdkafka/examples/alter_consumer_group_offsets.c +338 -0
- package/deps/librdkafka/examples/consumer.c +271 -0
- package/deps/librdkafka/examples/delete_records.c +233 -0
- package/deps/librdkafka/examples/describe_cluster.c +322 -0
- package/deps/librdkafka/examples/describe_consumer_groups.c +455 -0
- package/deps/librdkafka/examples/describe_topics.c +427 -0
- package/deps/librdkafka/examples/elect_leaders.c +317 -0
- package/deps/librdkafka/examples/globals.json +11 -0
- package/deps/librdkafka/examples/idempotent_producer.c +344 -0
- package/deps/librdkafka/examples/incremental_alter_configs.c +347 -0
- package/deps/librdkafka/examples/kafkatest_verifiable_client.cpp +945 -0
- package/deps/librdkafka/examples/list_consumer_group_offsets.c +359 -0
- package/deps/librdkafka/examples/list_consumer_groups.c +365 -0
- package/deps/librdkafka/examples/list_offsets.c +327 -0
- package/deps/librdkafka/examples/misc.c +287 -0
- package/deps/librdkafka/examples/openssl_engine_example.cpp +248 -0
- package/deps/librdkafka/examples/producer.c +251 -0
- package/deps/librdkafka/examples/producer.cpp +228 -0
- package/deps/librdkafka/examples/rdkafka_complex_consumer_example.c +617 -0
- package/deps/librdkafka/examples/rdkafka_complex_consumer_example.cpp +467 -0
- package/deps/librdkafka/examples/rdkafka_consume_batch.cpp +264 -0
- package/deps/librdkafka/examples/rdkafka_example.c +853 -0
- package/deps/librdkafka/examples/rdkafka_example.cpp +679 -0
- package/deps/librdkafka/examples/rdkafka_performance.c +1781 -0
- package/deps/librdkafka/examples/transactions-older-broker.c +668 -0
- package/deps/librdkafka/examples/transactions.c +665 -0
- package/deps/librdkafka/examples/user_scram.c +491 -0
- package/deps/librdkafka/examples/win_ssl_cert_store.cpp +396 -0
- package/deps/librdkafka/lds-gen.py +73 -0
- package/deps/librdkafka/mainpage.doxy +40 -0
- package/deps/librdkafka/mklove/Makefile.base +329 -0
- package/deps/librdkafka/mklove/modules/configure.atomics +144 -0
- package/deps/librdkafka/mklove/modules/configure.base +2484 -0
- package/deps/librdkafka/mklove/modules/configure.builtin +70 -0
- package/deps/librdkafka/mklove/modules/configure.cc +186 -0
- package/deps/librdkafka/mklove/modules/configure.cxx +8 -0
- package/deps/librdkafka/mklove/modules/configure.fileversion +65 -0
- package/deps/librdkafka/mklove/modules/configure.gitversion +29 -0
- package/deps/librdkafka/mklove/modules/configure.good_cflags +18 -0
- package/deps/librdkafka/mklove/modules/configure.host +132 -0
- package/deps/librdkafka/mklove/modules/configure.lib +49 -0
- package/deps/librdkafka/mklove/modules/configure.libcurl +99 -0
- package/deps/librdkafka/mklove/modules/configure.libsasl2 +36 -0
- package/deps/librdkafka/mklove/modules/configure.libssl +147 -0
- package/deps/librdkafka/mklove/modules/configure.libzstd +58 -0
- package/deps/librdkafka/mklove/modules/configure.parseversion +95 -0
- package/deps/librdkafka/mklove/modules/configure.pic +16 -0
- package/deps/librdkafka/mklove/modules/configure.socket +20 -0
- package/deps/librdkafka/mklove/modules/configure.zlib +61 -0
- package/deps/librdkafka/mklove/modules/patches/README.md +8 -0
- package/deps/librdkafka/mklove/modules/patches/libcurl.0000-no-runtime-linking-check.patch +11 -0
- package/deps/librdkafka/mklove/modules/patches/libssl.0000-osx-rand-include-fix-OpenSSL-PR16409.patch +56 -0
- package/deps/librdkafka/packaging/RELEASE.md +319 -0
- package/deps/librdkafka/packaging/alpine/build-alpine.sh +38 -0
- package/deps/librdkafka/packaging/archlinux/PKGBUILD +30 -0
- package/deps/librdkafka/packaging/cmake/Config.cmake.in +37 -0
- package/deps/librdkafka/packaging/cmake/Modules/FindLZ4.cmake +38 -0
- package/deps/librdkafka/packaging/cmake/Modules/FindZSTD.cmake +27 -0
- package/deps/librdkafka/packaging/cmake/Modules/LICENSE.FindZstd +178 -0
- package/deps/librdkafka/packaging/cmake/README.md +38 -0
- package/deps/librdkafka/packaging/cmake/config.h.in +52 -0
- package/deps/librdkafka/packaging/cmake/parseversion.cmake +60 -0
- package/deps/librdkafka/packaging/cmake/rdkafka.pc.in +12 -0
- package/deps/librdkafka/packaging/cmake/try_compile/atomic_32_test.c +8 -0
- package/deps/librdkafka/packaging/cmake/try_compile/atomic_64_test.c +8 -0
- package/deps/librdkafka/packaging/cmake/try_compile/c11threads_test.c +14 -0
- package/deps/librdkafka/packaging/cmake/try_compile/crc32c_hw_test.c +27 -0
- package/deps/librdkafka/packaging/cmake/try_compile/dlopen_test.c +11 -0
- package/deps/librdkafka/packaging/cmake/try_compile/libsasl2_test.c +7 -0
- package/deps/librdkafka/packaging/cmake/try_compile/pthread_setname_darwin_test.c +6 -0
- package/deps/librdkafka/packaging/cmake/try_compile/pthread_setname_freebsd_test.c +7 -0
- package/deps/librdkafka/packaging/cmake/try_compile/pthread_setname_gnu_test.c +5 -0
- package/deps/librdkafka/packaging/cmake/try_compile/rand_r_test.c +7 -0
- package/deps/librdkafka/packaging/cmake/try_compile/rdkafka_setup.cmake +122 -0
- package/deps/librdkafka/packaging/cmake/try_compile/regex_test.c +10 -0
- package/deps/librdkafka/packaging/cmake/try_compile/strndup_test.c +5 -0
- package/deps/librdkafka/packaging/cmake/try_compile/sync_32_test.c +8 -0
- package/deps/librdkafka/packaging/cmake/try_compile/sync_64_test.c +8 -0
- package/deps/librdkafka/packaging/cp/README.md +16 -0
- package/deps/librdkafka/packaging/cp/check_features.c +72 -0
- package/deps/librdkafka/packaging/cp/verify-deb.sh +33 -0
- package/deps/librdkafka/packaging/cp/verify-packages.sh +69 -0
- package/deps/librdkafka/packaging/cp/verify-rpm.sh +32 -0
- package/deps/librdkafka/packaging/debian/changelog +66 -0
- package/deps/librdkafka/packaging/debian/compat +1 -0
- package/deps/librdkafka/packaging/debian/control +49 -0
- package/deps/librdkafka/packaging/debian/copyright +84 -0
- package/deps/librdkafka/packaging/debian/docs +5 -0
- package/deps/librdkafka/packaging/debian/gbp.conf +9 -0
- package/deps/librdkafka/packaging/debian/librdkafka-dev.dirs +2 -0
- package/deps/librdkafka/packaging/debian/librdkafka-dev.examples +2 -0
- package/deps/librdkafka/packaging/debian/librdkafka-dev.install +6 -0
- package/deps/librdkafka/packaging/debian/librdkafka-dev.substvars +1 -0
- package/deps/librdkafka/packaging/debian/librdkafka.dsc +16 -0
- package/deps/librdkafka/packaging/debian/librdkafka1-dbg.substvars +1 -0
- package/deps/librdkafka/packaging/debian/librdkafka1.dirs +1 -0
- package/deps/librdkafka/packaging/debian/librdkafka1.install +2 -0
- package/deps/librdkafka/packaging/debian/librdkafka1.postinst.debhelper +5 -0
- package/deps/librdkafka/packaging/debian/librdkafka1.postrm.debhelper +5 -0
- package/deps/librdkafka/packaging/debian/librdkafka1.symbols +64 -0
- package/deps/librdkafka/packaging/debian/rules +19 -0
- package/deps/librdkafka/packaging/debian/source/format +1 -0
- package/deps/librdkafka/packaging/debian/watch +2 -0
- package/deps/librdkafka/packaging/get_version.py +21 -0
- package/deps/librdkafka/packaging/homebrew/README.md +15 -0
- package/deps/librdkafka/packaging/homebrew/brew-update-pr.sh +31 -0
- package/deps/librdkafka/packaging/mingw-w64/configure-build-msys2-mingw-static.sh +52 -0
- package/deps/librdkafka/packaging/mingw-w64/configure-build-msys2-mingw.sh +21 -0
- package/deps/librdkafka/packaging/mingw-w64/export-variables.sh +13 -0
- package/deps/librdkafka/packaging/mingw-w64/run-tests.sh +6 -0
- package/deps/librdkafka/packaging/mingw-w64/semaphoreci-build.sh +38 -0
- package/deps/librdkafka/packaging/nuget/README.md +84 -0
- package/deps/librdkafka/packaging/nuget/artifact.py +177 -0
- package/deps/librdkafka/packaging/nuget/cleanup-s3.py +143 -0
- package/deps/librdkafka/packaging/nuget/common/p-common__plat-windows__arch-win32__bldtype-Release/msvcr120.zip +0 -0
- package/deps/librdkafka/packaging/nuget/common/p-common__plat-windows__arch-win32__bldtype-Release/msvcr140.zip +0 -0
- package/deps/librdkafka/packaging/nuget/common/p-common__plat-windows__arch-x64__bldtype-Release/msvcr120.zip +0 -0
- package/deps/librdkafka/packaging/nuget/common/p-common__plat-windows__arch-x64__bldtype-Release/msvcr140.zip +0 -0
- package/deps/librdkafka/packaging/nuget/nuget.sh +21 -0
- package/deps/librdkafka/packaging/nuget/nugetpackage.py +278 -0
- package/deps/librdkafka/packaging/nuget/packaging.py +448 -0
- package/deps/librdkafka/packaging/nuget/push-to-nuget.sh +21 -0
- package/deps/librdkafka/packaging/nuget/release.py +167 -0
- package/deps/librdkafka/packaging/nuget/requirements.txt +3 -0
- package/deps/librdkafka/packaging/nuget/staticpackage.py +178 -0
- package/deps/librdkafka/packaging/nuget/templates/librdkafka.redist.nuspec +21 -0
- package/deps/librdkafka/packaging/nuget/templates/librdkafka.redist.props +18 -0
- package/deps/librdkafka/packaging/nuget/templates/librdkafka.redist.targets +19 -0
- package/deps/librdkafka/packaging/nuget/zfile/__init__.py +0 -0
- package/deps/librdkafka/packaging/nuget/zfile/zfile.py +98 -0
- package/deps/librdkafka/packaging/rpm/Makefile +92 -0
- package/deps/librdkafka/packaging/rpm/README.md +23 -0
- package/deps/librdkafka/packaging/rpm/el7-x86_64.cfg +40 -0
- package/deps/librdkafka/packaging/rpm/librdkafka.spec +118 -0
- package/deps/librdkafka/packaging/rpm/mock-on-docker.sh +96 -0
- package/deps/librdkafka/packaging/rpm/tests/Makefile +25 -0
- package/deps/librdkafka/packaging/rpm/tests/README.md +8 -0
- package/deps/librdkafka/packaging/rpm/tests/run-test.sh +42 -0
- package/deps/librdkafka/packaging/rpm/tests/test-on-docker.sh +56 -0
- package/deps/librdkafka/packaging/rpm/tests/test.c +77 -0
- package/deps/librdkafka/packaging/rpm/tests/test.cpp +34 -0
- package/deps/librdkafka/packaging/tools/Dockerfile +31 -0
- package/deps/librdkafka/packaging/tools/build-configurations-checks.sh +12 -0
- package/deps/librdkafka/packaging/tools/build-deb-package.sh +64 -0
- package/deps/librdkafka/packaging/tools/build-debian.sh +65 -0
- package/deps/librdkafka/packaging/tools/build-manylinux.sh +68 -0
- package/deps/librdkafka/packaging/tools/build-release-artifacts.sh +139 -0
- package/deps/librdkafka/packaging/tools/distro-build.sh +38 -0
- package/deps/librdkafka/packaging/tools/gh-release-checksums.py +39 -0
- package/deps/librdkafka/packaging/tools/rdutcoverage.sh +25 -0
- package/deps/librdkafka/packaging/tools/requirements.txt +2 -0
- package/deps/librdkafka/packaging/tools/run-in-docker.sh +28 -0
- package/deps/librdkafka/packaging/tools/run-integration-tests.sh +31 -0
- package/deps/librdkafka/packaging/tools/run-style-check.sh +4 -0
- package/deps/librdkafka/packaging/tools/style-format.sh +149 -0
- package/deps/librdkafka/packaging/tools/update_rpcs_max_versions.py +100 -0
- package/deps/librdkafka/service.yml +172 -0
- package/deps/librdkafka/src/CMakeLists.txt +374 -0
- package/deps/librdkafka/src/Makefile +103 -0
- package/deps/librdkafka/src/README.lz4.md +30 -0
- package/deps/librdkafka/src/cJSON.c +2834 -0
- package/deps/librdkafka/src/cJSON.h +398 -0
- package/deps/librdkafka/src/crc32c.c +430 -0
- package/deps/librdkafka/src/crc32c.h +38 -0
- package/deps/librdkafka/src/generate_proto.sh +66 -0
- package/deps/librdkafka/src/librdkafka_cgrp_synch.png +0 -0
- package/deps/librdkafka/src/lz4.c +2727 -0
- package/deps/librdkafka/src/lz4.h +842 -0
- package/deps/librdkafka/src/lz4frame.c +2078 -0
- package/deps/librdkafka/src/lz4frame.h +692 -0
- package/deps/librdkafka/src/lz4frame_static.h +47 -0
- package/deps/librdkafka/src/lz4hc.c +1631 -0
- package/deps/librdkafka/src/lz4hc.h +413 -0
- package/deps/librdkafka/src/nanopb/pb.h +917 -0
- package/deps/librdkafka/src/nanopb/pb_common.c +388 -0
- package/deps/librdkafka/src/nanopb/pb_common.h +49 -0
- package/deps/librdkafka/src/nanopb/pb_decode.c +1727 -0
- package/deps/librdkafka/src/nanopb/pb_decode.h +193 -0
- package/deps/librdkafka/src/nanopb/pb_encode.c +1000 -0
- package/deps/librdkafka/src/nanopb/pb_encode.h +185 -0
- package/deps/librdkafka/src/opentelemetry/common.pb.c +32 -0
- package/deps/librdkafka/src/opentelemetry/common.pb.h +170 -0
- package/deps/librdkafka/src/opentelemetry/metrics.options +2 -0
- package/deps/librdkafka/src/opentelemetry/metrics.pb.c +67 -0
- package/deps/librdkafka/src/opentelemetry/metrics.pb.h +966 -0
- package/deps/librdkafka/src/opentelemetry/resource.pb.c +12 -0
- package/deps/librdkafka/src/opentelemetry/resource.pb.h +58 -0
- package/deps/librdkafka/src/queue.h +850 -0
- package/deps/librdkafka/src/rd.h +584 -0
- package/deps/librdkafka/src/rdaddr.c +255 -0
- package/deps/librdkafka/src/rdaddr.h +202 -0
- package/deps/librdkafka/src/rdatomic.h +230 -0
- package/deps/librdkafka/src/rdavg.h +260 -0
- package/deps/librdkafka/src/rdavl.c +210 -0
- package/deps/librdkafka/src/rdavl.h +250 -0
- package/deps/librdkafka/src/rdbase64.c +200 -0
- package/deps/librdkafka/src/rdbase64.h +43 -0
- package/deps/librdkafka/src/rdbuf.c +1884 -0
- package/deps/librdkafka/src/rdbuf.h +375 -0
- package/deps/librdkafka/src/rdcrc32.c +114 -0
- package/deps/librdkafka/src/rdcrc32.h +170 -0
- package/deps/librdkafka/src/rddl.c +179 -0
- package/deps/librdkafka/src/rddl.h +43 -0
- package/deps/librdkafka/src/rdendian.h +175 -0
- package/deps/librdkafka/src/rdfloat.h +67 -0
- package/deps/librdkafka/src/rdfnv1a.c +113 -0
- package/deps/librdkafka/src/rdfnv1a.h +35 -0
- package/deps/librdkafka/src/rdgz.c +120 -0
- package/deps/librdkafka/src/rdgz.h +46 -0
- package/deps/librdkafka/src/rdhdrhistogram.c +721 -0
- package/deps/librdkafka/src/rdhdrhistogram.h +87 -0
- package/deps/librdkafka/src/rdhttp.c +830 -0
- package/deps/librdkafka/src/rdhttp.h +101 -0
- package/deps/librdkafka/src/rdinterval.h +177 -0
- package/deps/librdkafka/src/rdkafka.c +5505 -0
- package/deps/librdkafka/src/rdkafka.h +10686 -0
- package/deps/librdkafka/src/rdkafka_admin.c +9794 -0
- package/deps/librdkafka/src/rdkafka_admin.h +661 -0
- package/deps/librdkafka/src/rdkafka_assignment.c +1010 -0
- package/deps/librdkafka/src/rdkafka_assignment.h +73 -0
- package/deps/librdkafka/src/rdkafka_assignor.c +1786 -0
- package/deps/librdkafka/src/rdkafka_assignor.h +402 -0
- package/deps/librdkafka/src/rdkafka_aux.c +409 -0
- package/deps/librdkafka/src/rdkafka_aux.h +174 -0
- package/deps/librdkafka/src/rdkafka_background.c +221 -0
- package/deps/librdkafka/src/rdkafka_broker.c +6337 -0
- package/deps/librdkafka/src/rdkafka_broker.h +744 -0
- package/deps/librdkafka/src/rdkafka_buf.c +543 -0
- package/deps/librdkafka/src/rdkafka_buf.h +1525 -0
- package/deps/librdkafka/src/rdkafka_cert.c +576 -0
- package/deps/librdkafka/src/rdkafka_cert.h +62 -0
- package/deps/librdkafka/src/rdkafka_cgrp.c +7587 -0
- package/deps/librdkafka/src/rdkafka_cgrp.h +477 -0
- package/deps/librdkafka/src/rdkafka_conf.c +4880 -0
- package/deps/librdkafka/src/rdkafka_conf.h +732 -0
- package/deps/librdkafka/src/rdkafka_confval.h +97 -0
- package/deps/librdkafka/src/rdkafka_coord.c +623 -0
- package/deps/librdkafka/src/rdkafka_coord.h +132 -0
- package/deps/librdkafka/src/rdkafka_error.c +228 -0
- package/deps/librdkafka/src/rdkafka_error.h +80 -0
- package/deps/librdkafka/src/rdkafka_event.c +502 -0
- package/deps/librdkafka/src/rdkafka_event.h +126 -0
- package/deps/librdkafka/src/rdkafka_feature.c +898 -0
- package/deps/librdkafka/src/rdkafka_feature.h +104 -0
- package/deps/librdkafka/src/rdkafka_fetcher.c +1422 -0
- package/deps/librdkafka/src/rdkafka_fetcher.h +44 -0
- package/deps/librdkafka/src/rdkafka_header.c +220 -0
- package/deps/librdkafka/src/rdkafka_header.h +76 -0
- package/deps/librdkafka/src/rdkafka_idempotence.c +807 -0
- package/deps/librdkafka/src/rdkafka_idempotence.h +144 -0
- package/deps/librdkafka/src/rdkafka_int.h +1260 -0
- package/deps/librdkafka/src/rdkafka_interceptor.c +819 -0
- package/deps/librdkafka/src/rdkafka_interceptor.h +104 -0
- package/deps/librdkafka/src/rdkafka_lz4.c +450 -0
- package/deps/librdkafka/src/rdkafka_lz4.h +49 -0
- package/deps/librdkafka/src/rdkafka_metadata.c +2209 -0
- package/deps/librdkafka/src/rdkafka_metadata.h +345 -0
- package/deps/librdkafka/src/rdkafka_metadata_cache.c +1183 -0
- package/deps/librdkafka/src/rdkafka_mock.c +3661 -0
- package/deps/librdkafka/src/rdkafka_mock.h +610 -0
- package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1876 -0
- package/deps/librdkafka/src/rdkafka_mock_handlers.c +3113 -0
- package/deps/librdkafka/src/rdkafka_mock_int.h +710 -0
- package/deps/librdkafka/src/rdkafka_msg.c +2589 -0
- package/deps/librdkafka/src/rdkafka_msg.h +614 -0
- package/deps/librdkafka/src/rdkafka_msgbatch.h +62 -0
- package/deps/librdkafka/src/rdkafka_msgset.h +98 -0
- package/deps/librdkafka/src/rdkafka_msgset_reader.c +1806 -0
- package/deps/librdkafka/src/rdkafka_msgset_writer.c +1474 -0
- package/deps/librdkafka/src/rdkafka_offset.c +1565 -0
- package/deps/librdkafka/src/rdkafka_offset.h +150 -0
- package/deps/librdkafka/src/rdkafka_op.c +997 -0
- package/deps/librdkafka/src/rdkafka_op.h +858 -0
- package/deps/librdkafka/src/rdkafka_partition.c +4896 -0
- package/deps/librdkafka/src/rdkafka_partition.h +1182 -0
- package/deps/librdkafka/src/rdkafka_pattern.c +228 -0
- package/deps/librdkafka/src/rdkafka_pattern.h +70 -0
- package/deps/librdkafka/src/rdkafka_plugin.c +213 -0
- package/deps/librdkafka/src/rdkafka_plugin.h +41 -0
- package/deps/librdkafka/src/rdkafka_proto.h +736 -0
- package/deps/librdkafka/src/rdkafka_protocol.h +128 -0
- package/deps/librdkafka/src/rdkafka_queue.c +1230 -0
- package/deps/librdkafka/src/rdkafka_queue.h +1220 -0
- package/deps/librdkafka/src/rdkafka_range_assignor.c +1748 -0
- package/deps/librdkafka/src/rdkafka_request.c +7089 -0
- package/deps/librdkafka/src/rdkafka_request.h +732 -0
- package/deps/librdkafka/src/rdkafka_roundrobin_assignor.c +123 -0
- package/deps/librdkafka/src/rdkafka_sasl.c +530 -0
- package/deps/librdkafka/src/rdkafka_sasl.h +63 -0
- package/deps/librdkafka/src/rdkafka_sasl_cyrus.c +722 -0
- package/deps/librdkafka/src/rdkafka_sasl_int.h +89 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +1833 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.h +52 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1666 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +47 -0
- package/deps/librdkafka/src/rdkafka_sasl_plain.c +142 -0
- package/deps/librdkafka/src/rdkafka_sasl_scram.c +858 -0
- package/deps/librdkafka/src/rdkafka_sasl_win32.c +550 -0
- package/deps/librdkafka/src/rdkafka_ssl.c +2129 -0
- package/deps/librdkafka/src/rdkafka_ssl.h +86 -0
- package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4785 -0
- package/deps/librdkafka/src/rdkafka_subscription.c +278 -0
- package/deps/librdkafka/src/rdkafka_telemetry.c +760 -0
- package/deps/librdkafka/src/rdkafka_telemetry.h +52 -0
- package/deps/librdkafka/src/rdkafka_telemetry_decode.c +1053 -0
- package/deps/librdkafka/src/rdkafka_telemetry_decode.h +59 -0
- package/deps/librdkafka/src/rdkafka_telemetry_encode.c +997 -0
- package/deps/librdkafka/src/rdkafka_telemetry_encode.h +301 -0
- package/deps/librdkafka/src/rdkafka_timer.c +402 -0
- package/deps/librdkafka/src/rdkafka_timer.h +117 -0
- package/deps/librdkafka/src/rdkafka_topic.c +2161 -0
- package/deps/librdkafka/src/rdkafka_topic.h +334 -0
- package/deps/librdkafka/src/rdkafka_transport.c +1309 -0
- package/deps/librdkafka/src/rdkafka_transport.h +99 -0
- package/deps/librdkafka/src/rdkafka_transport_int.h +100 -0
- package/deps/librdkafka/src/rdkafka_txnmgr.c +3256 -0
- package/deps/librdkafka/src/rdkafka_txnmgr.h +171 -0
- package/deps/librdkafka/src/rdkafka_zstd.c +226 -0
- package/deps/librdkafka/src/rdkafka_zstd.h +57 -0
- package/deps/librdkafka/src/rdlist.c +576 -0
- package/deps/librdkafka/src/rdlist.h +434 -0
- package/deps/librdkafka/src/rdlog.c +89 -0
- package/deps/librdkafka/src/rdlog.h +41 -0
- package/deps/librdkafka/src/rdmap.c +508 -0
- package/deps/librdkafka/src/rdmap.h +492 -0
- package/deps/librdkafka/src/rdmurmur2.c +167 -0
- package/deps/librdkafka/src/rdmurmur2.h +35 -0
- package/deps/librdkafka/src/rdports.c +61 -0
- package/deps/librdkafka/src/rdports.h +38 -0
- package/deps/librdkafka/src/rdposix.h +250 -0
- package/deps/librdkafka/src/rdrand.c +80 -0
- package/deps/librdkafka/src/rdrand.h +43 -0
- package/deps/librdkafka/src/rdregex.c +156 -0
- package/deps/librdkafka/src/rdregex.h +43 -0
- package/deps/librdkafka/src/rdsignal.h +57 -0
- package/deps/librdkafka/src/rdstring.c +645 -0
- package/deps/librdkafka/src/rdstring.h +98 -0
- package/deps/librdkafka/src/rdsysqueue.h +404 -0
- package/deps/librdkafka/src/rdtime.h +356 -0
- package/deps/librdkafka/src/rdtypes.h +86 -0
- package/deps/librdkafka/src/rdunittest.c +549 -0
- package/deps/librdkafka/src/rdunittest.h +232 -0
- package/deps/librdkafka/src/rdvarint.c +134 -0
- package/deps/librdkafka/src/rdvarint.h +165 -0
- package/deps/librdkafka/src/rdwin32.h +382 -0
- package/deps/librdkafka/src/rdxxhash.c +1030 -0
- package/deps/librdkafka/src/rdxxhash.h +328 -0
- package/deps/librdkafka/src/regexp.c +1352 -0
- package/deps/librdkafka/src/regexp.h +41 -0
- package/deps/librdkafka/src/snappy.c +1866 -0
- package/deps/librdkafka/src/snappy.h +62 -0
- package/deps/librdkafka/src/snappy_compat.h +138 -0
- package/deps/librdkafka/src/statistics_schema.json +444 -0
- package/deps/librdkafka/src/tinycthread.c +932 -0
- package/deps/librdkafka/src/tinycthread.h +503 -0
- package/deps/librdkafka/src/tinycthread_extra.c +199 -0
- package/deps/librdkafka/src/tinycthread_extra.h +212 -0
- package/deps/librdkafka/src/win32_config.h +58 -0
- package/deps/librdkafka/src-cpp/CMakeLists.txt +90 -0
- package/deps/librdkafka/src-cpp/ConfImpl.cpp +84 -0
- package/deps/librdkafka/src-cpp/ConsumerImpl.cpp +244 -0
- package/deps/librdkafka/src-cpp/HandleImpl.cpp +436 -0
- package/deps/librdkafka/src-cpp/HeadersImpl.cpp +48 -0
- package/deps/librdkafka/src-cpp/KafkaConsumerImpl.cpp +296 -0
- package/deps/librdkafka/src-cpp/Makefile +55 -0
- package/deps/librdkafka/src-cpp/MessageImpl.cpp +38 -0
- package/deps/librdkafka/src-cpp/MetadataImpl.cpp +170 -0
- package/deps/librdkafka/src-cpp/ProducerImpl.cpp +197 -0
- package/deps/librdkafka/src-cpp/QueueImpl.cpp +70 -0
- package/deps/librdkafka/src-cpp/README.md +16 -0
- package/deps/librdkafka/src-cpp/RdKafka.cpp +59 -0
- package/deps/librdkafka/src-cpp/TopicImpl.cpp +124 -0
- package/deps/librdkafka/src-cpp/TopicPartitionImpl.cpp +57 -0
- package/deps/librdkafka/src-cpp/rdkafkacpp.h +3797 -0
- package/deps/librdkafka/src-cpp/rdkafkacpp_int.h +1641 -0
- package/deps/librdkafka/tests/0000-unittests.c +72 -0
- package/deps/librdkafka/tests/0001-multiobj.c +102 -0
- package/deps/librdkafka/tests/0002-unkpart.c +244 -0
- package/deps/librdkafka/tests/0003-msgmaxsize.c +173 -0
- package/deps/librdkafka/tests/0004-conf.c +934 -0
- package/deps/librdkafka/tests/0005-order.c +133 -0
- package/deps/librdkafka/tests/0006-symbols.c +163 -0
- package/deps/librdkafka/tests/0007-autotopic.c +136 -0
- package/deps/librdkafka/tests/0008-reqacks.c +179 -0
- package/deps/librdkafka/tests/0009-mock_cluster.c +97 -0
- package/deps/librdkafka/tests/0011-produce_batch.c +753 -0
- package/deps/librdkafka/tests/0012-produce_consume.c +537 -0
- package/deps/librdkafka/tests/0013-null-msgs.c +473 -0
- package/deps/librdkafka/tests/0014-reconsume-191.c +512 -0
- package/deps/librdkafka/tests/0015-offset_seeks.c +172 -0
- package/deps/librdkafka/tests/0016-client_swname.c +181 -0
- package/deps/librdkafka/tests/0017-compression.c +140 -0
- package/deps/librdkafka/tests/0018-cgrp_term.c +338 -0
- package/deps/librdkafka/tests/0019-list_groups.c +289 -0
- package/deps/librdkafka/tests/0020-destroy_hang.c +162 -0
- package/deps/librdkafka/tests/0021-rkt_destroy.c +72 -0
- package/deps/librdkafka/tests/0022-consume_batch.c +279 -0
- package/deps/librdkafka/tests/0025-timers.c +147 -0
- package/deps/librdkafka/tests/0026-consume_pause.c +547 -0
- package/deps/librdkafka/tests/0028-long_topicnames.c +79 -0
- package/deps/librdkafka/tests/0029-assign_offset.c +202 -0
- package/deps/librdkafka/tests/0030-offset_commit.c +589 -0
- package/deps/librdkafka/tests/0031-get_offsets.c +235 -0
- package/deps/librdkafka/tests/0033-regex_subscribe.c +536 -0
- package/deps/librdkafka/tests/0034-offset_reset.c +398 -0
- package/deps/librdkafka/tests/0035-api_version.c +73 -0
- package/deps/librdkafka/tests/0036-partial_fetch.c +87 -0
- package/deps/librdkafka/tests/0037-destroy_hang_local.c +85 -0
- package/deps/librdkafka/tests/0038-performance.c +121 -0
- package/deps/librdkafka/tests/0039-event.c +284 -0
- package/deps/librdkafka/tests/0040-io_event.c +257 -0
- package/deps/librdkafka/tests/0041-fetch_max_bytes.c +97 -0
- package/deps/librdkafka/tests/0042-many_topics.c +252 -0
- package/deps/librdkafka/tests/0043-no_connection.c +77 -0
- package/deps/librdkafka/tests/0044-partition_cnt.c +94 -0
- package/deps/librdkafka/tests/0045-subscribe_update.c +1010 -0
- package/deps/librdkafka/tests/0046-rkt_cache.c +65 -0
- package/deps/librdkafka/tests/0047-partial_buf_tmout.c +98 -0
- package/deps/librdkafka/tests/0048-partitioner.c +283 -0
- package/deps/librdkafka/tests/0049-consume_conn_close.c +162 -0
- package/deps/librdkafka/tests/0050-subscribe_adds.c +145 -0
- package/deps/librdkafka/tests/0051-assign_adds.c +126 -0
- package/deps/librdkafka/tests/0052-msg_timestamps.c +238 -0
- package/deps/librdkafka/tests/0053-stats_cb.cpp +527 -0
- package/deps/librdkafka/tests/0054-offset_time.cpp +236 -0
- package/deps/librdkafka/tests/0055-producer_latency.c +539 -0
- package/deps/librdkafka/tests/0056-balanced_group_mt.c +315 -0
- package/deps/librdkafka/tests/0057-invalid_topic.cpp +112 -0
- package/deps/librdkafka/tests/0058-log.cpp +123 -0
- package/deps/librdkafka/tests/0059-bsearch.cpp +241 -0
- package/deps/librdkafka/tests/0060-op_prio.cpp +163 -0
- package/deps/librdkafka/tests/0061-consumer_lag.cpp +295 -0
- package/deps/librdkafka/tests/0062-stats_event.c +126 -0
- package/deps/librdkafka/tests/0063-clusterid.cpp +180 -0
- package/deps/librdkafka/tests/0064-interceptors.c +481 -0
- package/deps/librdkafka/tests/0065-yield.cpp +140 -0
- package/deps/librdkafka/tests/0066-plugins.cpp +129 -0
- package/deps/librdkafka/tests/0067-empty_topic.cpp +151 -0
- package/deps/librdkafka/tests/0068-produce_timeout.c +136 -0
- package/deps/librdkafka/tests/0069-consumer_add_parts.c +119 -0
- package/deps/librdkafka/tests/0070-null_empty.cpp +197 -0
- package/deps/librdkafka/tests/0072-headers_ut.c +448 -0
- package/deps/librdkafka/tests/0073-headers.c +381 -0
- package/deps/librdkafka/tests/0074-producev.c +87 -0
- package/deps/librdkafka/tests/0075-retry.c +290 -0
- package/deps/librdkafka/tests/0076-produce_retry.c +452 -0
- package/deps/librdkafka/tests/0077-compaction.c +363 -0
- package/deps/librdkafka/tests/0078-c_from_cpp.cpp +96 -0
- package/deps/librdkafka/tests/0079-fork.c +93 -0
- package/deps/librdkafka/tests/0080-admin_ut.c +3095 -0
- package/deps/librdkafka/tests/0081-admin.c +5633 -0
- package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +137 -0
- package/deps/librdkafka/tests/0083-cb_event.c +233 -0
- package/deps/librdkafka/tests/0084-destroy_flags.c +208 -0
- package/deps/librdkafka/tests/0085-headers.cpp +392 -0
- package/deps/librdkafka/tests/0086-purge.c +368 -0
- package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +162 -0
- package/deps/librdkafka/tests/0089-max_poll_interval.c +511 -0
- package/deps/librdkafka/tests/0090-idempotence.c +171 -0
- package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +295 -0
- package/deps/librdkafka/tests/0092-mixed_msgver.c +103 -0
- package/deps/librdkafka/tests/0093-holb.c +200 -0
- package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +231 -0
- package/deps/librdkafka/tests/0095-all_brokers_down.cpp +122 -0
- package/deps/librdkafka/tests/0097-ssl_verify.cpp +658 -0
- package/deps/librdkafka/tests/0098-consumer-txn.cpp +1218 -0
- package/deps/librdkafka/tests/0099-commit_metadata.c +194 -0
- package/deps/librdkafka/tests/0100-thread_interceptors.cpp +195 -0
- package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +446 -0
- package/deps/librdkafka/tests/0102-static_group_rebalance.c +836 -0
- package/deps/librdkafka/tests/0103-transactions.c +1383 -0
- package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +625 -0
- package/deps/librdkafka/tests/0105-transactions_mock.c +3930 -0
- package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +318 -0
- package/deps/librdkafka/tests/0107-topic_recreate.c +259 -0
- package/deps/librdkafka/tests/0109-auto_create_topics.cpp +278 -0
- package/deps/librdkafka/tests/0110-batch_size.cpp +182 -0
- package/deps/librdkafka/tests/0111-delay_create_topics.cpp +127 -0
- package/deps/librdkafka/tests/0112-assign_unknown_part.c +87 -0
- package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +3473 -0
- package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +176 -0
- package/deps/librdkafka/tests/0115-producer_auth.cpp +182 -0
- package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +216 -0
- package/deps/librdkafka/tests/0117-mock_errors.c +331 -0
- package/deps/librdkafka/tests/0118-commit_rebalance.c +154 -0
- package/deps/librdkafka/tests/0119-consumer_auth.cpp +167 -0
- package/deps/librdkafka/tests/0120-asymmetric_subscription.c +185 -0
- package/deps/librdkafka/tests/0121-clusterid.c +115 -0
- package/deps/librdkafka/tests/0122-buffer_cleaning_after_rebalance.c +227 -0
- package/deps/librdkafka/tests/0123-connections_max_idle.c +98 -0
- package/deps/librdkafka/tests/0124-openssl_invalid_engine.c +69 -0
- package/deps/librdkafka/tests/0125-immediate_flush.c +144 -0
- package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +528 -0
- package/deps/librdkafka/tests/0127-fetch_queue_backoff.cpp +165 -0
- package/deps/librdkafka/tests/0128-sasl_callback_queue.cpp +125 -0
- package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +79 -0
- package/deps/librdkafka/tests/0130-store_offsets.c +178 -0
- package/deps/librdkafka/tests/0131-connect_timeout.c +81 -0
- package/deps/librdkafka/tests/0132-strategy_ordering.c +179 -0
- package/deps/librdkafka/tests/0133-ssl_keys.c +150 -0
- package/deps/librdkafka/tests/0134-ssl_provider.c +92 -0
- package/deps/librdkafka/tests/0135-sasl_credentials.cpp +143 -0
- package/deps/librdkafka/tests/0136-resolve_cb.c +181 -0
- package/deps/librdkafka/tests/0137-barrier_batch_consume.c +619 -0
- package/deps/librdkafka/tests/0138-admin_mock.c +281 -0
- package/deps/librdkafka/tests/0139-offset_validation_mock.c +950 -0
- package/deps/librdkafka/tests/0140-commit_metadata.cpp +108 -0
- package/deps/librdkafka/tests/0142-reauthentication.c +515 -0
- package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +552 -0
- package/deps/librdkafka/tests/0144-idempotence_mock.c +373 -0
- package/deps/librdkafka/tests/0145-pause_resume_mock.c +119 -0
- package/deps/librdkafka/tests/0146-metadata_mock.c +505 -0
- package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +952 -0
- package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +563 -0
- package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
- package/deps/librdkafka/tests/0150-telemetry_mock.c +651 -0
- package/deps/librdkafka/tests/0151-purge-brokers.c +566 -0
- package/deps/librdkafka/tests/0152-rebootstrap.c +59 -0
- package/deps/librdkafka/tests/0153-memberid.c +128 -0
- package/deps/librdkafka/tests/1000-unktopic.c +164 -0
- package/deps/librdkafka/tests/8000-idle.cpp +60 -0
- package/deps/librdkafka/tests/8001-fetch_from_follower_mock_manual.c +113 -0
- package/deps/librdkafka/tests/CMakeLists.txt +170 -0
- package/deps/librdkafka/tests/LibrdkafkaTestApp.py +291 -0
- package/deps/librdkafka/tests/Makefile +182 -0
- package/deps/librdkafka/tests/README.md +509 -0
- package/deps/librdkafka/tests/autotest.sh +33 -0
- package/deps/librdkafka/tests/backtrace.gdb +30 -0
- package/deps/librdkafka/tests/broker_version_tests.py +315 -0
- package/deps/librdkafka/tests/buildbox.sh +17 -0
- package/deps/librdkafka/tests/cleanup-checker-tests.sh +20 -0
- package/deps/librdkafka/tests/cluster_testing.py +191 -0
- package/deps/librdkafka/tests/delete-test-topics.sh +56 -0
- package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
- package/deps/librdkafka/tests/fixtures/ssl/Makefile +8 -0
- package/deps/librdkafka/tests/fixtures/ssl/README.md +13 -0
- package/deps/librdkafka/tests/fixtures/ssl/client.keystore.intermediate.p12 +0 -0
- package/deps/librdkafka/tests/fixtures/ssl/client.keystore.p12 +0 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.intermediate.pem +72 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.pem +50 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.key +46 -0
- package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +168 -0
- package/deps/librdkafka/tests/fuzzers/Makefile +12 -0
- package/deps/librdkafka/tests/fuzzers/README.md +31 -0
- package/deps/librdkafka/tests/fuzzers/fuzz_regex.c +74 -0
- package/deps/librdkafka/tests/fuzzers/helpers.h +90 -0
- package/deps/librdkafka/tests/gen-ssl-certs.sh +165 -0
- package/deps/librdkafka/tests/interactive_broker_version.py +170 -0
- package/deps/librdkafka/tests/interceptor_test/CMakeLists.txt +16 -0
- package/deps/librdkafka/tests/interceptor_test/Makefile +22 -0
- package/deps/librdkafka/tests/interceptor_test/interceptor_test.c +314 -0
- package/deps/librdkafka/tests/interceptor_test/interceptor_test.h +54 -0
- package/deps/librdkafka/tests/java/IncrementalRebalanceCli.java +97 -0
- package/deps/librdkafka/tests/java/Makefile +13 -0
- package/deps/librdkafka/tests/java/Murmur2Cli.java +46 -0
- package/deps/librdkafka/tests/java/README.md +14 -0
- package/deps/librdkafka/tests/java/TransactionProducerCli.java +162 -0
- package/deps/librdkafka/tests/java/run-class.sh +11 -0
- package/deps/librdkafka/tests/librdkafka.suppressions +483 -0
- package/deps/librdkafka/tests/lz4_manual_test.sh +59 -0
- package/deps/librdkafka/tests/multi-broker-version-test.sh +50 -0
- package/deps/librdkafka/tests/parse-refcnt.sh +43 -0
- package/deps/librdkafka/tests/performance_plot.py +115 -0
- package/deps/librdkafka/tests/plugin_test/Makefile +19 -0
- package/deps/librdkafka/tests/plugin_test/plugin_test.c +58 -0
- package/deps/librdkafka/tests/requirements.txt +2 -0
- package/deps/librdkafka/tests/run-all-tests.sh +79 -0
- package/deps/librdkafka/tests/run-consumer-tests.sh +16 -0
- package/deps/librdkafka/tests/run-producer-tests.sh +16 -0
- package/deps/librdkafka/tests/run-test-batches.py +157 -0
- package/deps/librdkafka/tests/run-test.sh +140 -0
- package/deps/librdkafka/tests/rusage.c +249 -0
- package/deps/librdkafka/tests/sasl_test.py +289 -0
- package/deps/librdkafka/tests/scenarios/README.md +6 -0
- package/deps/librdkafka/tests/scenarios/ak23.json +6 -0
- package/deps/librdkafka/tests/scenarios/default.json +5 -0
- package/deps/librdkafka/tests/scenarios/noautocreate.json +5 -0
- package/deps/librdkafka/tests/sockem.c +801 -0
- package/deps/librdkafka/tests/sockem.h +85 -0
- package/deps/librdkafka/tests/sockem_ctrl.c +145 -0
- package/deps/librdkafka/tests/sockem_ctrl.h +61 -0
- package/deps/librdkafka/tests/test.c +7778 -0
- package/deps/librdkafka/tests/test.conf.example +27 -0
- package/deps/librdkafka/tests/test.h +1028 -0
- package/deps/librdkafka/tests/testcpp.cpp +131 -0
- package/deps/librdkafka/tests/testcpp.h +388 -0
- package/deps/librdkafka/tests/testshared.h +416 -0
- package/deps/librdkafka/tests/tools/README.md +4 -0
- package/deps/librdkafka/tests/tools/stats/README.md +21 -0
- package/deps/librdkafka/tests/tools/stats/filter.jq +42 -0
- package/deps/librdkafka/tests/tools/stats/graph.py +150 -0
- package/deps/librdkafka/tests/tools/stats/requirements.txt +3 -0
- package/deps/librdkafka/tests/tools/stats/to_csv.py +124 -0
- package/deps/librdkafka/tests/trivup/trivup-0.14.0.tar.gz +0 -0
- package/deps/librdkafka/tests/until-fail.sh +87 -0
- package/deps/librdkafka/tests/xxxx-assign_partition.c +122 -0
- package/deps/librdkafka/tests/xxxx-metadata.cpp +159 -0
- package/deps/librdkafka/vcpkg.json +23 -0
- package/deps/librdkafka/win32/README.md +5 -0
- package/deps/librdkafka/win32/build-package.bat +3 -0
- package/deps/librdkafka/win32/build.bat +19 -0
- package/deps/librdkafka/win32/common.vcxproj +84 -0
- package/deps/librdkafka/win32/interceptor_test/interceptor_test.vcxproj +87 -0
- package/deps/librdkafka/win32/librdkafka.autopkg.template +54 -0
- package/deps/librdkafka/win32/librdkafka.master.testing.targets +13 -0
- package/deps/librdkafka/win32/librdkafka.sln +226 -0
- package/deps/librdkafka/win32/librdkafka.vcxproj +276 -0
- package/deps/librdkafka/win32/librdkafkacpp/librdkafkacpp.vcxproj +104 -0
- package/deps/librdkafka/win32/msbuild.ps1 +15 -0
- package/deps/librdkafka/win32/openssl_engine_example/openssl_engine_example.vcxproj +132 -0
- package/deps/librdkafka/win32/package-zip.ps1 +46 -0
- package/deps/librdkafka/win32/packages/repositories.config +4 -0
- package/deps/librdkafka/win32/push-package.bat +4 -0
- package/deps/librdkafka/win32/rdkafka_complex_consumer_example_cpp/rdkafka_complex_consumer_example_cpp.vcxproj +67 -0
- package/deps/librdkafka/win32/rdkafka_example/rdkafka_example.vcxproj +97 -0
- package/deps/librdkafka/win32/rdkafka_performance/rdkafka_performance.vcxproj +97 -0
- package/deps/librdkafka/win32/setup-msys2.ps1 +47 -0
- package/deps/librdkafka/win32/setup-vcpkg.ps1 +34 -0
- package/deps/librdkafka/win32/tests/test.conf.example +25 -0
- package/deps/librdkafka/win32/tests/tests.vcxproj +253 -0
- package/deps/librdkafka/win32/win_ssl_cert_store/win_ssl_cert_store.vcxproj +132 -0
- package/deps/librdkafka/win32/wingetopt.c +564 -0
- package/deps/librdkafka/win32/wingetopt.h +101 -0
- package/deps/librdkafka/win32/wintime.h +33 -0
- package/deps/librdkafka.gyp +62 -0
- package/lib/admin.js +233 -0
- package/lib/client.js +573 -0
- package/lib/error.js +500 -0
- package/lib/index.js +34 -0
- package/lib/kafka-consumer-stream.js +397 -0
- package/lib/kafka-consumer.js +698 -0
- package/lib/producer/high-level-producer.js +323 -0
- package/lib/producer-stream.js +307 -0
- package/lib/producer.js +375 -0
- package/lib/tools/ref-counter.js +52 -0
- package/lib/topic-partition.js +88 -0
- package/lib/topic.js +42 -0
- package/lib/util.js +29 -0
- package/package.json +61 -0
- package/prebuilds/darwin-arm64/@point3+node-rdkafka.node +0 -0
- package/prebuilds/linux-x64/@point3+node-rdkafka.node +0 -0
- package/util/configure.js +30 -0
- package/util/get-env.js +6 -0
- package/util/test-compile.js +11 -0
- package/util/test-producer-delivery.js +100 -0
|
@@ -0,0 +1,2161 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* librdkafka - Apache Kafka C library
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2012-2022, Magnus Edenhill
|
|
5
|
+
* 2023, Confluent Inc.
|
|
6
|
+
* All rights reserved.
|
|
7
|
+
*
|
|
8
|
+
* Redistribution and use in source and binary forms, with or without
|
|
9
|
+
* modification, are permitted provided that the following conditions are met:
|
|
10
|
+
*
|
|
11
|
+
* 1. Redistributions of source code must retain the above copyright notice,
|
|
12
|
+
* this list of conditions and the following disclaimer.
|
|
13
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
14
|
+
* this list of conditions and the following disclaimer in the documentation
|
|
15
|
+
* and/or other materials provided with the distribution.
|
|
16
|
+
*
|
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
18
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
19
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
20
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
21
|
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
22
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
23
|
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
24
|
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
25
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
26
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
27
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
#include "rd.h"
|
|
31
|
+
#include "rdkafka_int.h"
|
|
32
|
+
#include "rdkafka_msg.h"
|
|
33
|
+
#include "rdkafka_topic.h"
|
|
34
|
+
#include "rdkafka_partition.h"
|
|
35
|
+
#include "rdkafka_broker.h"
|
|
36
|
+
#include "rdkafka_cgrp.h"
|
|
37
|
+
#include "rdkafka_metadata.h"
|
|
38
|
+
#include "rdkafka_offset.h"
|
|
39
|
+
#include "rdlog.h"
|
|
40
|
+
#include "rdsysqueue.h"
|
|
41
|
+
#include "rdtime.h"
|
|
42
|
+
#include "rdregex.h"
|
|
43
|
+
#include "rdkafka_fetcher.h"
|
|
44
|
+
|
|
45
|
+
#if WITH_ZSTD
|
|
46
|
+
#include <zstd.h>
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
const char *rd_kafka_topic_state_names[] = {"unknown", "exists", "notexists",
|
|
51
|
+
"error"};
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
static int
|
|
55
|
+
rd_kafka_topic_metadata_update(rd_kafka_topic_t *rkt,
|
|
56
|
+
const struct rd_kafka_metadata_topic *mdt,
|
|
57
|
+
const rd_kafka_metadata_topic_internal_t *mdit,
|
|
58
|
+
rd_ts_t ts_age);
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @brief Increases the app's topic reference count.
|
|
63
|
+
*
|
|
64
|
+
* The app refcounts are implemented separately from the librdkafka refcounts,
|
|
65
|
+
* they are increased/decreased in a separate rkt_app_refcnt to keep track of
|
|
66
|
+
* its use.
|
|
67
|
+
*
|
|
68
|
+
* This only covers topic_new() & topic_destroy().
|
|
69
|
+
* The topic_t exposed in rd_kafka_message_t is NOT covered and is handled
|
|
70
|
+
* like a standard internal -> app pointer conversion (keep_a()).
|
|
71
|
+
*/
|
|
72
|
+
static void rd_kafka_topic_keep_app(rd_kafka_topic_t *rkt) {
|
|
73
|
+
if (rd_refcnt_add(&rkt->rkt_app_refcnt) == 1)
|
|
74
|
+
rd_kafka_topic_keep(rkt);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @brief drop rkt app reference
|
|
79
|
+
*/
|
|
80
|
+
static void rd_kafka_topic_destroy_app(rd_kafka_topic_t *app_rkt) {
|
|
81
|
+
rd_kafka_topic_t *rkt = app_rkt;
|
|
82
|
+
|
|
83
|
+
rd_assert(!rd_kafka_rkt_is_lw(app_rkt));
|
|
84
|
+
|
|
85
|
+
if (unlikely(rd_refcnt_sub(&rkt->rkt_app_refcnt) == 0))
|
|
86
|
+
rd_kafka_topic_destroy0(rkt); /* final app reference lost,
|
|
87
|
+
* loose reference from
|
|
88
|
+
* keep_app() */
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Final destructor for topic. Refcnt must be 0.
|
|
94
|
+
*/
|
|
95
|
+
void rd_kafka_topic_destroy_final(rd_kafka_topic_t *rkt) {
|
|
96
|
+
rd_kafka_partition_msgid_t *partmsgid, *partmsgid_tmp;
|
|
97
|
+
|
|
98
|
+
rd_kafka_assert(rkt->rkt_rk, rd_refcnt_get(&rkt->rkt_refcnt) == 0);
|
|
99
|
+
|
|
100
|
+
rd_kafka_wrlock(rkt->rkt_rk);
|
|
101
|
+
TAILQ_REMOVE(&rkt->rkt_rk->rk_topics, rkt, rkt_link);
|
|
102
|
+
rkt->rkt_rk->rk_topic_cnt--;
|
|
103
|
+
rd_kafka_wrunlock(rkt->rkt_rk);
|
|
104
|
+
|
|
105
|
+
TAILQ_FOREACH_SAFE(partmsgid, &rkt->rkt_saved_partmsgids, link,
|
|
106
|
+
partmsgid_tmp) {
|
|
107
|
+
rd_free(partmsgid);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
rd_kafka_assert(rkt->rkt_rk, rd_list_empty(&rkt->rkt_desp));
|
|
111
|
+
rd_list_destroy(&rkt->rkt_desp);
|
|
112
|
+
|
|
113
|
+
rd_avg_destroy(&rkt->rkt_avg_batchsize);
|
|
114
|
+
rd_avg_destroy(&rkt->rkt_avg_batchcnt);
|
|
115
|
+
|
|
116
|
+
if (rkt->rkt_topic)
|
|
117
|
+
rd_kafkap_str_destroy(rkt->rkt_topic);
|
|
118
|
+
|
|
119
|
+
rd_kafka_anyconf_destroy(_RK_TOPIC, &rkt->rkt_conf);
|
|
120
|
+
|
|
121
|
+
rwlock_destroy(&rkt->rkt_lock);
|
|
122
|
+
rd_refcnt_destroy(&rkt->rkt_app_refcnt);
|
|
123
|
+
rd_refcnt_destroy(&rkt->rkt_refcnt);
|
|
124
|
+
|
|
125
|
+
rd_free(rkt);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @brief Application topic object destroy.
|
|
130
|
+
* @warning MUST ONLY BE CALLED BY THE APPLICATION.
|
|
131
|
+
* Use rd_kafka_topic_destroy0() for all internal use.
|
|
132
|
+
*/
|
|
133
|
+
void rd_kafka_topic_destroy(rd_kafka_topic_t *app_rkt) {
|
|
134
|
+
rd_kafka_lwtopic_t *lrkt;
|
|
135
|
+
if (unlikely((lrkt = rd_kafka_rkt_get_lw(app_rkt)) != NULL))
|
|
136
|
+
rd_kafka_lwtopic_destroy(lrkt);
|
|
137
|
+
else
|
|
138
|
+
rd_kafka_topic_destroy_app(app_rkt);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Finds and returns a topic based on its name, or NULL if not found.
|
|
144
|
+
* The 'rkt' refcount is increased by one and the caller must call
|
|
145
|
+
* rd_kafka_topic_destroy() when it is done with the topic to decrease
|
|
146
|
+
* the refcount.
|
|
147
|
+
*
|
|
148
|
+
* Locality: any thread
|
|
149
|
+
*/
|
|
150
|
+
rd_kafka_topic_t *rd_kafka_topic_find_fl(const char *func,
|
|
151
|
+
int line,
|
|
152
|
+
rd_kafka_t *rk,
|
|
153
|
+
const char *topic,
|
|
154
|
+
int do_lock) {
|
|
155
|
+
rd_kafka_topic_t *rkt;
|
|
156
|
+
|
|
157
|
+
if (do_lock)
|
|
158
|
+
rd_kafka_rdlock(rk);
|
|
159
|
+
TAILQ_FOREACH(rkt, &rk->rk_topics, rkt_link) {
|
|
160
|
+
if (!rd_kafkap_str_cmp_str(rkt->rkt_topic, topic)) {
|
|
161
|
+
rd_kafka_topic_keep(rkt);
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (do_lock)
|
|
166
|
+
rd_kafka_rdunlock(rk);
|
|
167
|
+
|
|
168
|
+
return rkt;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Same semantics as ..find() but takes a Kafka protocol string instead.
|
|
173
|
+
*/
|
|
174
|
+
rd_kafka_topic_t *rd_kafka_topic_find0_fl(const char *func,
|
|
175
|
+
int line,
|
|
176
|
+
rd_kafka_t *rk,
|
|
177
|
+
const rd_kafkap_str_t *topic) {
|
|
178
|
+
rd_kafka_topic_t *rkt;
|
|
179
|
+
|
|
180
|
+
rd_kafka_rdlock(rk);
|
|
181
|
+
TAILQ_FOREACH(rkt, &rk->rk_topics, rkt_link) {
|
|
182
|
+
if (!rd_kafkap_str_cmp(rkt->rkt_topic, topic)) {
|
|
183
|
+
rd_kafka_topic_keep(rkt);
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
rd_kafka_rdunlock(rk);
|
|
188
|
+
|
|
189
|
+
return rkt;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Same semantics as ..find() but takes a Uuid instead.
|
|
194
|
+
*/
|
|
195
|
+
rd_kafka_topic_t *rd_kafka_topic_find_by_topic_id(rd_kafka_t *rk,
|
|
196
|
+
rd_kafka_Uuid_t topic_id) {
|
|
197
|
+
rd_kafka_topic_t *rkt;
|
|
198
|
+
|
|
199
|
+
TAILQ_FOREACH(rkt, &rk->rk_topics, rkt_link) {
|
|
200
|
+
if (!rd_kafka_Uuid_cmp(rkt->rkt_topic_id, topic_id)) {
|
|
201
|
+
rd_kafka_topic_keep(rkt);
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return rkt;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @brief rd_kafka_topic_t comparator.
|
|
211
|
+
*/
|
|
212
|
+
int rd_kafka_topic_cmp_rkt(const void *_a, const void *_b) {
|
|
213
|
+
rd_kafka_topic_t *rkt_a = (void *)_a, *rkt_b = (void *)_b;
|
|
214
|
+
|
|
215
|
+
if (rkt_a == rkt_b)
|
|
216
|
+
return 0;
|
|
217
|
+
|
|
218
|
+
return rd_kafkap_str_cmp(rkt_a->rkt_topic, rkt_b->rkt_topic);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @brief Destroy/free a light-weight topic object.
|
|
224
|
+
*/
|
|
225
|
+
void rd_kafka_lwtopic_destroy(rd_kafka_lwtopic_t *lrkt) {
|
|
226
|
+
rd_assert(rd_kafka_rkt_is_lw((const rd_kafka_topic_t *)lrkt));
|
|
227
|
+
if (rd_refcnt_sub(&lrkt->lrkt_refcnt) > 0)
|
|
228
|
+
return;
|
|
229
|
+
|
|
230
|
+
rd_refcnt_destroy(&lrkt->lrkt_refcnt);
|
|
231
|
+
rd_free(lrkt);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* @brief Create a new light-weight topic name-only handle.
|
|
237
|
+
*
|
|
238
|
+
* This type of object is a light-weight non-linked alternative
|
|
239
|
+
* to the proper rd_kafka_itopic_t for outgoing APIs
|
|
240
|
+
* (such as rd_kafka_message_t) when there is no full topic object available.
|
|
241
|
+
*/
|
|
242
|
+
rd_kafka_lwtopic_t *rd_kafka_lwtopic_new(rd_kafka_t *rk, const char *topic) {
|
|
243
|
+
rd_kafka_lwtopic_t *lrkt;
|
|
244
|
+
size_t topic_len = strlen(topic);
|
|
245
|
+
|
|
246
|
+
lrkt = rd_malloc(sizeof(*lrkt) + topic_len + 1);
|
|
247
|
+
|
|
248
|
+
memcpy(lrkt->lrkt_magic, "LRKT", 4);
|
|
249
|
+
lrkt->lrkt_rk = rk;
|
|
250
|
+
rd_refcnt_init(&lrkt->lrkt_refcnt, 1);
|
|
251
|
+
lrkt->lrkt_topic = (char *)(lrkt + 1);
|
|
252
|
+
memcpy(lrkt->lrkt_topic, topic, topic_len + 1);
|
|
253
|
+
|
|
254
|
+
return lrkt;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @returns a proper rd_kafka_topic_t object (not light-weight)
|
|
260
|
+
* based on the input rd_kafka_topic_t app object which may
|
|
261
|
+
* either be a proper topic (which is then returned) or a light-weight
|
|
262
|
+
* topic in which case it will look up or create the proper topic
|
|
263
|
+
* object.
|
|
264
|
+
*
|
|
265
|
+
* This allows the application to (unknowingly) pass a light-weight
|
|
266
|
+
* topic object to any proper-aware public API.
|
|
267
|
+
*/
|
|
268
|
+
rd_kafka_topic_t *rd_kafka_topic_proper(rd_kafka_topic_t *app_rkt) {
|
|
269
|
+
rd_kafka_lwtopic_t *lrkt;
|
|
270
|
+
|
|
271
|
+
if (likely(!(lrkt = rd_kafka_rkt_get_lw(app_rkt))))
|
|
272
|
+
return app_rkt;
|
|
273
|
+
|
|
274
|
+
/* Create proper topic object */
|
|
275
|
+
return rd_kafka_topic_new0(lrkt->lrkt_rk, lrkt->lrkt_topic, NULL, NULL,
|
|
276
|
+
0);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* @brief Create new topic handle.
|
|
282
|
+
*
|
|
283
|
+
* @locality any
|
|
284
|
+
*/
|
|
285
|
+
rd_kafka_topic_t *rd_kafka_topic_new0(rd_kafka_t *rk,
|
|
286
|
+
const char *topic,
|
|
287
|
+
rd_kafka_topic_conf_t *conf,
|
|
288
|
+
int *existing,
|
|
289
|
+
int do_lock) {
|
|
290
|
+
rd_kafka_topic_t *rkt;
|
|
291
|
+
const struct rd_kafka_metadata_cache_entry *rkmce;
|
|
292
|
+
const char *conf_err;
|
|
293
|
+
const char *used_conf_str;
|
|
294
|
+
|
|
295
|
+
/* Verify configuration.
|
|
296
|
+
* Maximum topic name size + headers must never exceed message.max.bytes
|
|
297
|
+
* which is min-capped to 1000.
|
|
298
|
+
* See rd_kafka_broker_produce_toppar() and rdkafka_conf.c */
|
|
299
|
+
if (!topic || strlen(topic) > 512) {
|
|
300
|
+
if (conf)
|
|
301
|
+
rd_kafka_topic_conf_destroy(conf);
|
|
302
|
+
rd_kafka_set_last_error(RD_KAFKA_RESP_ERR__INVALID_ARG, EINVAL);
|
|
303
|
+
return NULL;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (do_lock)
|
|
307
|
+
rd_kafka_wrlock(rk);
|
|
308
|
+
if ((rkt = rd_kafka_topic_find(rk, topic, 0 /*no lock*/))) {
|
|
309
|
+
if (do_lock)
|
|
310
|
+
rd_kafka_wrunlock(rk);
|
|
311
|
+
if (conf)
|
|
312
|
+
rd_kafka_topic_conf_destroy(conf);
|
|
313
|
+
if (existing)
|
|
314
|
+
*existing = 1;
|
|
315
|
+
return rkt;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (!conf) {
|
|
319
|
+
if (rk->rk_conf.topic_conf) {
|
|
320
|
+
conf = rd_kafka_topic_conf_dup(rk->rk_conf.topic_conf);
|
|
321
|
+
used_conf_str = "default_topic_conf";
|
|
322
|
+
} else {
|
|
323
|
+
conf = rd_kafka_topic_conf_new();
|
|
324
|
+
used_conf_str = "empty";
|
|
325
|
+
}
|
|
326
|
+
} else {
|
|
327
|
+
used_conf_str = "user-supplied";
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
/* Verify and finalize topic configuration */
|
|
332
|
+
if ((conf_err = rd_kafka_topic_conf_finalize(rk->rk_type, &rk->rk_conf,
|
|
333
|
+
conf))) {
|
|
334
|
+
if (do_lock)
|
|
335
|
+
rd_kafka_wrunlock(rk);
|
|
336
|
+
/* Incompatible configuration settings */
|
|
337
|
+
rd_kafka_log(rk, LOG_ERR, "TOPICCONF",
|
|
338
|
+
"Incompatible configuration settings "
|
|
339
|
+
"for topic \"%s\": %s",
|
|
340
|
+
topic, conf_err);
|
|
341
|
+
rd_kafka_topic_conf_destroy(conf);
|
|
342
|
+
rd_kafka_set_last_error(RD_KAFKA_RESP_ERR__INVALID_ARG, EINVAL);
|
|
343
|
+
return NULL;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (existing)
|
|
347
|
+
*existing = 0;
|
|
348
|
+
|
|
349
|
+
rkt = rd_calloc(1, sizeof(*rkt));
|
|
350
|
+
|
|
351
|
+
memcpy(rkt->rkt_magic, "IRKT", 4);
|
|
352
|
+
|
|
353
|
+
rkt->rkt_topic = rd_kafkap_str_new(topic, -1);
|
|
354
|
+
rkt->rkt_rk = rk;
|
|
355
|
+
|
|
356
|
+
rkt->rkt_ts_create = rd_clock();
|
|
357
|
+
rkt->rkt_ts_state = rkt->rkt_ts_create;
|
|
358
|
+
|
|
359
|
+
rkt->rkt_conf = *conf;
|
|
360
|
+
rd_free(conf); /* explicitly not rd_kafka_topic_destroy()
|
|
361
|
+
* since we dont want to rd_free internal members,
|
|
362
|
+
* just the placeholder. The internal members
|
|
363
|
+
* were copied on the line above. */
|
|
364
|
+
|
|
365
|
+
/* Partitioner */
|
|
366
|
+
if (!rkt->rkt_conf.partitioner) {
|
|
367
|
+
const struct {
|
|
368
|
+
const char *str;
|
|
369
|
+
void *part;
|
|
370
|
+
} part_map[] = {
|
|
371
|
+
{"random", (void *)rd_kafka_msg_partitioner_random},
|
|
372
|
+
{"consistent", (void *)rd_kafka_msg_partitioner_consistent},
|
|
373
|
+
{"consistent_random",
|
|
374
|
+
(void *)rd_kafka_msg_partitioner_consistent_random},
|
|
375
|
+
{"murmur2", (void *)rd_kafka_msg_partitioner_murmur2},
|
|
376
|
+
{"murmur2_random",
|
|
377
|
+
(void *)rd_kafka_msg_partitioner_murmur2_random},
|
|
378
|
+
{"fnv1a", (void *)rd_kafka_msg_partitioner_fnv1a},
|
|
379
|
+
{"fnv1a_random",
|
|
380
|
+
(void *)rd_kafka_msg_partitioner_fnv1a_random},
|
|
381
|
+
{NULL}};
|
|
382
|
+
int i;
|
|
383
|
+
|
|
384
|
+
/* Use "partitioner" configuration property string, if set */
|
|
385
|
+
for (i = 0; rkt->rkt_conf.partitioner_str && part_map[i].str;
|
|
386
|
+
i++) {
|
|
387
|
+
if (!strcmp(rkt->rkt_conf.partitioner_str,
|
|
388
|
+
part_map[i].str)) {
|
|
389
|
+
rkt->rkt_conf.partitioner = part_map[i].part;
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/* Default partitioner: consistent_random */
|
|
395
|
+
if (!rkt->rkt_conf.partitioner) {
|
|
396
|
+
/* Make sure part_map matched something, otherwise
|
|
397
|
+
* there is a discreprency between this code
|
|
398
|
+
* and the validator in rdkafka_conf.c */
|
|
399
|
+
assert(!rkt->rkt_conf.partitioner_str);
|
|
400
|
+
|
|
401
|
+
rkt->rkt_conf.partitioner =
|
|
402
|
+
rd_kafka_msg_partitioner_consistent_random;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (rkt->rkt_rk->rk_conf.sticky_partition_linger_ms > 0 &&
|
|
407
|
+
rkt->rkt_conf.partitioner != rd_kafka_msg_partitioner_consistent &&
|
|
408
|
+
rkt->rkt_conf.partitioner != rd_kafka_msg_partitioner_murmur2 &&
|
|
409
|
+
rkt->rkt_conf.partitioner != rd_kafka_msg_partitioner_fnv1a) {
|
|
410
|
+
rkt->rkt_conf.random_partitioner = rd_false;
|
|
411
|
+
} else {
|
|
412
|
+
rkt->rkt_conf.random_partitioner = rd_true;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/* Sticky partition assignment interval */
|
|
416
|
+
rd_interval_init(&rkt->rkt_sticky_intvl);
|
|
417
|
+
|
|
418
|
+
if (rkt->rkt_conf.queuing_strategy == RD_KAFKA_QUEUE_FIFO)
|
|
419
|
+
rkt->rkt_conf.msg_order_cmp = rd_kafka_msg_cmp_msgid;
|
|
420
|
+
else
|
|
421
|
+
rkt->rkt_conf.msg_order_cmp = rd_kafka_msg_cmp_msgid_lifo;
|
|
422
|
+
|
|
423
|
+
if (rkt->rkt_conf.compression_codec == RD_KAFKA_COMPRESSION_INHERIT)
|
|
424
|
+
rkt->rkt_conf.compression_codec = rk->rk_conf.compression_codec;
|
|
425
|
+
|
|
426
|
+
/* Translate compression level to library-specific level and check
|
|
427
|
+
* upper bound */
|
|
428
|
+
switch (rkt->rkt_conf.compression_codec) {
|
|
429
|
+
#if WITH_ZLIB
|
|
430
|
+
case RD_KAFKA_COMPRESSION_GZIP:
|
|
431
|
+
if (rkt->rkt_conf.compression_level ==
|
|
432
|
+
RD_KAFKA_COMPLEVEL_DEFAULT)
|
|
433
|
+
rkt->rkt_conf.compression_level = Z_DEFAULT_COMPRESSION;
|
|
434
|
+
else if (rkt->rkt_conf.compression_level >
|
|
435
|
+
RD_KAFKA_COMPLEVEL_GZIP_MAX)
|
|
436
|
+
rkt->rkt_conf.compression_level =
|
|
437
|
+
RD_KAFKA_COMPLEVEL_GZIP_MAX;
|
|
438
|
+
break;
|
|
439
|
+
#endif
|
|
440
|
+
case RD_KAFKA_COMPRESSION_LZ4:
|
|
441
|
+
if (rkt->rkt_conf.compression_level ==
|
|
442
|
+
RD_KAFKA_COMPLEVEL_DEFAULT)
|
|
443
|
+
/* LZ4 has no notion of system-wide default compression
|
|
444
|
+
* level, use zero in this case */
|
|
445
|
+
rkt->rkt_conf.compression_level = 0;
|
|
446
|
+
else if (rkt->rkt_conf.compression_level >
|
|
447
|
+
RD_KAFKA_COMPLEVEL_LZ4_MAX)
|
|
448
|
+
rkt->rkt_conf.compression_level =
|
|
449
|
+
RD_KAFKA_COMPLEVEL_LZ4_MAX;
|
|
450
|
+
break;
|
|
451
|
+
#if WITH_ZSTD
|
|
452
|
+
case RD_KAFKA_COMPRESSION_ZSTD:
|
|
453
|
+
if (rkt->rkt_conf.compression_level ==
|
|
454
|
+
RD_KAFKA_COMPLEVEL_DEFAULT)
|
|
455
|
+
rkt->rkt_conf.compression_level = 3;
|
|
456
|
+
else if (rkt->rkt_conf.compression_level >
|
|
457
|
+
RD_KAFKA_COMPLEVEL_ZSTD_MAX)
|
|
458
|
+
rkt->rkt_conf.compression_level =
|
|
459
|
+
RD_KAFKA_COMPLEVEL_ZSTD_MAX;
|
|
460
|
+
break;
|
|
461
|
+
#endif
|
|
462
|
+
case RD_KAFKA_COMPRESSION_SNAPPY:
|
|
463
|
+
default:
|
|
464
|
+
/* Compression level has no effect in this case */
|
|
465
|
+
rkt->rkt_conf.compression_level = RD_KAFKA_COMPLEVEL_DEFAULT;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
rd_avg_init(&rkt->rkt_avg_batchsize, RD_AVG_GAUGE, 0,
|
|
469
|
+
rk->rk_conf.max_msg_size, 2,
|
|
470
|
+
rk->rk_conf.stats_interval_ms ? 1 : 0);
|
|
471
|
+
rd_avg_init(&rkt->rkt_avg_batchcnt, RD_AVG_GAUGE, 0,
|
|
472
|
+
rk->rk_conf.batch_num_messages, 2,
|
|
473
|
+
rk->rk_conf.stats_interval_ms ? 1 : 0);
|
|
474
|
+
|
|
475
|
+
rd_kafka_dbg(rk, TOPIC, "TOPIC", "New local topic: %.*s",
|
|
476
|
+
RD_KAFKAP_STR_PR(rkt->rkt_topic));
|
|
477
|
+
|
|
478
|
+
rd_list_init(&rkt->rkt_desp, 16, NULL);
|
|
479
|
+
rd_interval_init(&rkt->rkt_desp_refresh_intvl);
|
|
480
|
+
TAILQ_INIT(&rkt->rkt_saved_partmsgids);
|
|
481
|
+
rd_refcnt_init(&rkt->rkt_refcnt, 0);
|
|
482
|
+
rd_refcnt_init(&rkt->rkt_app_refcnt, 0);
|
|
483
|
+
|
|
484
|
+
rd_kafka_topic_keep(rkt);
|
|
485
|
+
|
|
486
|
+
rwlock_init(&rkt->rkt_lock);
|
|
487
|
+
|
|
488
|
+
/* Create unassigned partition */
|
|
489
|
+
rkt->rkt_ua = rd_kafka_toppar_new(rkt, RD_KAFKA_PARTITION_UA);
|
|
490
|
+
|
|
491
|
+
TAILQ_INSERT_TAIL(&rk->rk_topics, rkt, rkt_link);
|
|
492
|
+
rk->rk_topic_cnt++;
|
|
493
|
+
|
|
494
|
+
/* Populate from metadata cache. */
|
|
495
|
+
if ((rkmce = rd_kafka_metadata_cache_find(rk, topic, 1 /*valid*/)) &&
|
|
496
|
+
!rkmce->rkmce_mtopic.err) {
|
|
497
|
+
if (existing)
|
|
498
|
+
*existing = 1;
|
|
499
|
+
|
|
500
|
+
rd_kafka_topic_metadata_update(
|
|
501
|
+
rkt, &rkmce->rkmce_mtopic,
|
|
502
|
+
&rkmce->rkmce_metadata_internal_topic,
|
|
503
|
+
rkmce->rkmce_ts_insert);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (do_lock)
|
|
507
|
+
rd_kafka_wrunlock(rk);
|
|
508
|
+
|
|
509
|
+
if (rk->rk_conf.debug & RD_KAFKA_DBG_CONF) {
|
|
510
|
+
char desc[256];
|
|
511
|
+
rd_snprintf(desc, sizeof(desc),
|
|
512
|
+
"Topic \"%s\" configuration (%s)", topic,
|
|
513
|
+
used_conf_str);
|
|
514
|
+
rd_kafka_anyconf_dump_dbg(rk, _RK_TOPIC, &rkt->rkt_conf, desc);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return rkt;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* @brief Create new app topic handle.
|
|
524
|
+
*
|
|
525
|
+
* @locality application thread
|
|
526
|
+
*/
|
|
527
|
+
rd_kafka_topic_t *rd_kafka_topic_new(rd_kafka_t *rk,
|
|
528
|
+
const char *topic,
|
|
529
|
+
rd_kafka_topic_conf_t *conf) {
|
|
530
|
+
rd_kafka_topic_t *rkt;
|
|
531
|
+
int existing;
|
|
532
|
+
|
|
533
|
+
rkt = rd_kafka_topic_new0(rk, topic, conf, &existing, 1 /*lock*/);
|
|
534
|
+
if (!rkt)
|
|
535
|
+
return NULL;
|
|
536
|
+
|
|
537
|
+
/* Increase application refcount. */
|
|
538
|
+
rd_kafka_topic_keep_app(rkt);
|
|
539
|
+
|
|
540
|
+
/* Query for the topic leader (async) */
|
|
541
|
+
if (!existing)
|
|
542
|
+
rd_kafka_topic_fast_leader_query(rk, rd_true /* force */);
|
|
543
|
+
|
|
544
|
+
/* Drop our reference since there is already/now an app refcnt */
|
|
545
|
+
rd_kafka_topic_destroy0(rkt);
|
|
546
|
+
|
|
547
|
+
return rkt;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Sets the state for topic.
|
|
554
|
+
* NOTE: rd_kafka_topic_wrlock(rkt) MUST be held
|
|
555
|
+
*/
|
|
556
|
+
static void rd_kafka_topic_set_state(rd_kafka_topic_t *rkt, int state) {
|
|
557
|
+
|
|
558
|
+
if ((int)rkt->rkt_state == state)
|
|
559
|
+
return;
|
|
560
|
+
|
|
561
|
+
rd_kafka_dbg(rkt->rkt_rk, TOPIC, "STATE",
|
|
562
|
+
"Topic %s changed state %s -> %s", rkt->rkt_topic->str,
|
|
563
|
+
rd_kafka_topic_state_names[rkt->rkt_state],
|
|
564
|
+
rd_kafka_topic_state_names[state]);
|
|
565
|
+
|
|
566
|
+
if (rkt->rkt_state == RD_KAFKA_TOPIC_S_ERROR)
|
|
567
|
+
rkt->rkt_err = RD_KAFKA_RESP_ERR_NO_ERROR;
|
|
568
|
+
|
|
569
|
+
rkt->rkt_state = state;
|
|
570
|
+
rkt->rkt_ts_state = rd_clock();
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Returns the name of a topic.
|
|
575
|
+
* NOTE:
|
|
576
|
+
* The topic Kafka String representation is crafted with an extra byte
|
|
577
|
+
* at the end for the Nul that is not included in the length, this way
|
|
578
|
+
* we can use the topic's String directly.
|
|
579
|
+
* This is not true for Kafka Strings read from the network.
|
|
580
|
+
*/
|
|
581
|
+
const char *rd_kafka_topic_name(const rd_kafka_topic_t *app_rkt) {
|
|
582
|
+
if (rd_kafka_rkt_is_lw(app_rkt))
|
|
583
|
+
return rd_kafka_rkt_lw_const(app_rkt)->lrkt_topic;
|
|
584
|
+
else
|
|
585
|
+
return app_rkt->rkt_topic->str;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* @brief Update the broker that a topic+partition is delegated to.
|
|
591
|
+
*
|
|
592
|
+
* @param broker_id The id of the broker to associate the toppar with.
|
|
593
|
+
* @param rkb A reference to the broker to delegate to (must match
|
|
594
|
+
* broker_id) or NULL if the toppar should be undelegated for
|
|
595
|
+
* any reason.
|
|
596
|
+
* @param reason Human-readable reason for the update, included in debug log.
|
|
597
|
+
*
|
|
598
|
+
* @returns 1 if the broker delegation was changed, -1 if the broker
|
|
599
|
+
* delegation was changed and is now undelegated, else 0.
|
|
600
|
+
*
|
|
601
|
+
* @locks caller must have rd_kafka_toppar_lock(rktp)
|
|
602
|
+
* @locality any
|
|
603
|
+
*/
|
|
604
|
+
int rd_kafka_toppar_broker_update(rd_kafka_toppar_t *rktp,
|
|
605
|
+
int32_t broker_id,
|
|
606
|
+
rd_kafka_broker_t *rkb,
|
|
607
|
+
const char *reason) {
|
|
608
|
+
|
|
609
|
+
rktp->rktp_broker_id = broker_id;
|
|
610
|
+
|
|
611
|
+
if (!rkb) {
|
|
612
|
+
int had_broker = rktp->rktp_broker ? 1 : 0;
|
|
613
|
+
rd_kafka_toppar_broker_delegate(rktp, NULL);
|
|
614
|
+
return had_broker ? -1 : 0;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
if (rktp->rktp_broker) {
|
|
618
|
+
if (rktp->rktp_broker == rkb) {
|
|
619
|
+
/* No change in broker */
|
|
620
|
+
return 0;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC | RD_KAFKA_DBG_FETCH,
|
|
624
|
+
"TOPICUPD",
|
|
625
|
+
"Topic %s [%" PRId32
|
|
626
|
+
"]: migrating from "
|
|
627
|
+
"broker %" PRId32 " to %" PRId32
|
|
628
|
+
" (leader is "
|
|
629
|
+
"%" PRId32 "): %s",
|
|
630
|
+
rktp->rktp_rkt->rkt_topic->str,
|
|
631
|
+
rktp->rktp_partition,
|
|
632
|
+
rktp->rktp_broker->rkb_nodeid, rkb->rkb_nodeid,
|
|
633
|
+
rktp->rktp_leader_id, reason);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
rd_kafka_toppar_broker_delegate(rktp, rkb);
|
|
637
|
+
|
|
638
|
+
return 1;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* @brief Update a topic+partition for a new leader.
|
|
644
|
+
*
|
|
645
|
+
* @remark If a toppar is currently delegated to a preferred replica,
|
|
646
|
+
* it will not be delegated to the leader broker unless there
|
|
647
|
+
* has been a leader change.
|
|
648
|
+
* @remark The new leader, if present, should not be terminating.
|
|
649
|
+
*
|
|
650
|
+
* @param leader_id The id of the new leader broker.
|
|
651
|
+
* @param leader A reference to the leader broker or NULL if the
|
|
652
|
+
* toppar should be undelegated for any reason.
|
|
653
|
+
* @param leader_epoch Partition leader's epoch (KIP-320), or -1 if not known.
|
|
654
|
+
*
|
|
655
|
+
* @returns 1 if the broker delegation was changed, -1 if the broker
|
|
656
|
+
* delegation was changed and is now undelegated, else 0.
|
|
657
|
+
*
|
|
658
|
+
* @locks caller must have rd_kafka_topic_wrlock(rkt)
|
|
659
|
+
* AND NOT rd_kafka_toppar_lock(rktp)
|
|
660
|
+
* @locality any
|
|
661
|
+
*/
|
|
662
|
+
static int rd_kafka_toppar_leader_update(rd_kafka_topic_t *rkt,
|
|
663
|
+
int32_t partition,
|
|
664
|
+
int32_t leader_id,
|
|
665
|
+
rd_kafka_broker_t *leader,
|
|
666
|
+
int32_t leader_epoch) {
|
|
667
|
+
rd_kafka_toppar_t *rktp;
|
|
668
|
+
rd_bool_t need_epoch_validation = rd_false;
|
|
669
|
+
rd_bool_t fetching_from_follower;
|
|
670
|
+
int r = 0;
|
|
671
|
+
|
|
672
|
+
rktp = rd_kafka_toppar_get(rkt, partition, 0);
|
|
673
|
+
if (unlikely(!rktp)) {
|
|
674
|
+
/* Have only seen this in issue #132.
|
|
675
|
+
* Probably caused by corrupt broker state. */
|
|
676
|
+
rd_kafka_log(rkt->rkt_rk, LOG_WARNING, "BROKER",
|
|
677
|
+
"%s [%" PRId32
|
|
678
|
+
"] is unknown "
|
|
679
|
+
"(partition_cnt %i): "
|
|
680
|
+
"ignoring leader (%" PRId32 ") update",
|
|
681
|
+
rkt->rkt_topic->str, partition,
|
|
682
|
+
rkt->rkt_partition_cnt, leader_id);
|
|
683
|
+
return -1;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
rd_kafka_toppar_lock(rktp);
|
|
687
|
+
|
|
688
|
+
/* -1 (null) is excluded to allow to switch back to a
|
|
689
|
+
* leader not supporting KIP-320 still, for example
|
|
690
|
+
* during a cluster roll for upgrading brokers to
|
|
691
|
+
* a version supporting that KIP. */
|
|
692
|
+
if (leader_epoch != -1 && leader_epoch < rktp->rktp_leader_epoch) {
|
|
693
|
+
rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC, "BROKER",
|
|
694
|
+
"%s [%" PRId32
|
|
695
|
+
"]: ignoring outdated metadata update with "
|
|
696
|
+
"leader epoch %" PRId32
|
|
697
|
+
" which is older than "
|
|
698
|
+
"our cached epoch %" PRId32,
|
|
699
|
+
rktp->rktp_rkt->rkt_topic->str,
|
|
700
|
+
rktp->rktp_partition, leader_epoch,
|
|
701
|
+
rktp->rktp_leader_epoch);
|
|
702
|
+
rd_kafka_toppar_unlock(rktp);
|
|
703
|
+
rd_kafka_toppar_destroy(rktp); /* from get() */
|
|
704
|
+
return 0;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC, "BROKER",
|
|
708
|
+
"%s [%" PRId32 "]: leader %" PRId32 " epoch %" PRId32
|
|
709
|
+
" -> leader %" PRId32 " epoch %" PRId32,
|
|
710
|
+
rktp->rktp_rkt->rkt_topic->str, rktp->rktp_partition,
|
|
711
|
+
rktp->rktp_leader_id, rktp->rktp_leader_epoch, leader_id,
|
|
712
|
+
leader_epoch);
|
|
713
|
+
|
|
714
|
+
if (leader_epoch > rktp->rktp_leader_epoch ||
|
|
715
|
+
rktp->rktp_fetch_state ==
|
|
716
|
+
RD_KAFKA_TOPPAR_FETCH_VALIDATE_EPOCH_WAIT) {
|
|
717
|
+
/* Epoch increased and needs to be validated (leader_epoch > -1)
|
|
718
|
+
* or we need to complete the validation. */
|
|
719
|
+
need_epoch_validation = rd_true;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
rktp->rktp_leader_epoch = leader_epoch;
|
|
723
|
+
|
|
724
|
+
fetching_from_follower =
|
|
725
|
+
leader != NULL && rktp->rktp_broker != NULL &&
|
|
726
|
+
rktp->rktp_broker->rkb_source != RD_KAFKA_INTERNAL &&
|
|
727
|
+
rktp->rktp_broker != leader;
|
|
728
|
+
|
|
729
|
+
if (fetching_from_follower && rktp->rktp_leader_id == leader_id) {
|
|
730
|
+
rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC, "BROKER",
|
|
731
|
+
"Topic %s [%" PRId32 "]: leader %" PRId32
|
|
732
|
+
" unchanged, "
|
|
733
|
+
"not migrating away from preferred "
|
|
734
|
+
"replica %" PRId32,
|
|
735
|
+
rktp->rktp_rkt->rkt_topic->str,
|
|
736
|
+
rktp->rktp_partition, leader_id,
|
|
737
|
+
rktp->rktp_broker_id);
|
|
738
|
+
r = 0;
|
|
739
|
+
|
|
740
|
+
} else {
|
|
741
|
+
|
|
742
|
+
if (rktp->rktp_leader_id != leader_id ||
|
|
743
|
+
rktp->rktp_leader != leader) {
|
|
744
|
+
/* Update leader if it has changed */
|
|
745
|
+
rktp->rktp_leader_id = leader_id;
|
|
746
|
+
if (rktp->rktp_leader)
|
|
747
|
+
rd_kafka_broker_destroy(rktp->rktp_leader);
|
|
748
|
+
if (leader)
|
|
749
|
+
rd_kafka_broker_keep(leader);
|
|
750
|
+
rktp->rktp_leader = leader;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/* Update handling broker */
|
|
754
|
+
r = rd_kafka_toppar_broker_update(rktp, leader_id, leader,
|
|
755
|
+
"leader updated");
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
if (need_epoch_validation) {
|
|
759
|
+
/* Set offset validation position,
|
|
760
|
+
* depending it if should continue with current position or
|
|
761
|
+
* with next fetch start position. */
|
|
762
|
+
rd_kafka_toppar_set_offset_validation_position(
|
|
763
|
+
rktp,
|
|
764
|
+
rd_kafka_toppar_fetch_decide_next_fetch_start_pos(rktp));
|
|
765
|
+
rd_kafka_offset_validate(rktp, "epoch updated from metadata");
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
rd_kafka_toppar_unlock(rktp);
|
|
769
|
+
|
|
770
|
+
rd_kafka_toppar_destroy(rktp); /* from get() */
|
|
771
|
+
|
|
772
|
+
return r;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* @brief Revert the topic+partition delegation to the leader from
|
|
778
|
+
* a preferred replica.
|
|
779
|
+
*
|
|
780
|
+
* @returns 1 if the broker delegation was changed, -1 if the broker
|
|
781
|
+
* delegation was changed and is now undelegated, else 0.
|
|
782
|
+
*
|
|
783
|
+
* @locks none
|
|
784
|
+
* @locality any
|
|
785
|
+
*/
|
|
786
|
+
int rd_kafka_toppar_delegate_to_leader(rd_kafka_toppar_t *rktp) {
|
|
787
|
+
rd_kafka_broker_t *leader;
|
|
788
|
+
int r;
|
|
789
|
+
|
|
790
|
+
rd_kafka_rdlock(rktp->rktp_rkt->rkt_rk);
|
|
791
|
+
rd_kafka_toppar_lock(rktp);
|
|
792
|
+
|
|
793
|
+
if (rktp->rktp_leader_id == rktp->rktp_broker_id) {
|
|
794
|
+
/* Given lock was released we need to check again */
|
|
795
|
+
rd_kafka_toppar_unlock(rktp);
|
|
796
|
+
rd_kafka_rdunlock(rktp->rktp_rkt->rkt_rk);
|
|
797
|
+
return 0;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
rd_kafka_dbg(rktp->rktp_rkt->rkt_rk, TOPIC, "BROKER",
|
|
801
|
+
"Topic %s [%" PRId32
|
|
802
|
+
"]: Reverting from preferred "
|
|
803
|
+
"replica %" PRId32 " to leader %" PRId32,
|
|
804
|
+
rktp->rktp_rkt->rkt_topic->str, rktp->rktp_partition,
|
|
805
|
+
rktp->rktp_broker_id, rktp->rktp_leader_id);
|
|
806
|
+
|
|
807
|
+
leader = rd_kafka_broker_find_by_nodeid(rktp->rktp_rkt->rkt_rk,
|
|
808
|
+
rktp->rktp_leader_id);
|
|
809
|
+
|
|
810
|
+
rd_kafka_toppar_unlock(rktp);
|
|
811
|
+
rd_kafka_rdunlock(rktp->rktp_rkt->rkt_rk);
|
|
812
|
+
|
|
813
|
+
rd_kafka_toppar_lock(rktp);
|
|
814
|
+
r = rd_kafka_toppar_broker_update(
|
|
815
|
+
rktp, rktp->rktp_leader_id, leader,
|
|
816
|
+
"reverting from preferred replica to leader");
|
|
817
|
+
rd_kafka_toppar_unlock(rktp);
|
|
818
|
+
|
|
819
|
+
if (leader)
|
|
820
|
+
rd_kafka_broker_destroy(leader);
|
|
821
|
+
|
|
822
|
+
return r;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* @brief Forgets current rktp leader, to reduce reference count
|
|
828
|
+
* and allow the broker to be destroyed.
|
|
829
|
+
*
|
|
830
|
+
* @locks none
|
|
831
|
+
* @locks_acquired rk rdlock, rktp
|
|
832
|
+
* @locality any
|
|
833
|
+
*/
|
|
834
|
+
void rd_kafka_toppar_forget_leader(rd_kafka_toppar_t *rktp) {
|
|
835
|
+
rd_kafka_rdlock(rktp->rktp_rkt->rkt_rk);
|
|
836
|
+
rd_kafka_toppar_lock(rktp);
|
|
837
|
+
|
|
838
|
+
if (rktp->rktp_leader) {
|
|
839
|
+
rd_kafka_broker_destroy(rktp->rktp_leader);
|
|
840
|
+
rktp->rktp_leader = NULL;
|
|
841
|
+
rktp->rktp_leader_id = -1;
|
|
842
|
+
rktp->rktp_leader_epoch = -1;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
rd_kafka_toppar_unlock(rktp);
|
|
846
|
+
rd_kafka_rdunlock(rktp->rktp_rkt->rkt_rk);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* @brief Revert the topic+partition delegation to the internal broker.
|
|
851
|
+
*
|
|
852
|
+
* @locks none
|
|
853
|
+
* @locks_acquired rk rdlock, rktp
|
|
854
|
+
* @locality any
|
|
855
|
+
*/
|
|
856
|
+
void rd_kafka_toppar_undelegate(rd_kafka_toppar_t *rktp) {
|
|
857
|
+
rd_kafka_rdlock(rktp->rktp_rkt->rkt_rk);
|
|
858
|
+
rd_kafka_toppar_lock(rktp);
|
|
859
|
+
|
|
860
|
+
rd_kafka_toppar_broker_delegate(rktp, NULL);
|
|
861
|
+
|
|
862
|
+
rd_kafka_toppar_unlock(rktp);
|
|
863
|
+
rd_kafka_rdunlock(rktp->rktp_rkt->rkt_rk);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* @brief Save idempotent producer state for a partition that is about to
|
|
868
|
+
* be removed.
|
|
869
|
+
*
|
|
870
|
+
* @locks_required rd_kafka_wrlock(rkt), rd_kafka_toppar_lock(rktp)
|
|
871
|
+
*/
|
|
872
|
+
static void rd_kafka_toppar_idemp_msgid_save(rd_kafka_topic_t *rkt,
|
|
873
|
+
const rd_kafka_toppar_t *rktp) {
|
|
874
|
+
rd_kafka_partition_msgid_t *partmsgid = rd_malloc(sizeof(*partmsgid));
|
|
875
|
+
partmsgid->partition = rktp->rktp_partition;
|
|
876
|
+
partmsgid->msgid = rktp->rktp_msgid;
|
|
877
|
+
partmsgid->pid = rktp->rktp_eos.pid;
|
|
878
|
+
partmsgid->epoch_base_msgid = rktp->rktp_eos.epoch_base_msgid;
|
|
879
|
+
partmsgid->ts = rd_clock();
|
|
880
|
+
|
|
881
|
+
TAILQ_INSERT_TAIL(&rkt->rkt_saved_partmsgids, partmsgid, link);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* @brief Restore idempotent producer state for a new/resurfacing partition.
|
|
887
|
+
*
|
|
888
|
+
* @locks_required rd_kafka_wrlock(rkt), rd_kafka_toppar_lock(rktp)
|
|
889
|
+
*/
|
|
890
|
+
static void rd_kafka_toppar_idemp_msgid_restore(rd_kafka_topic_t *rkt,
|
|
891
|
+
rd_kafka_toppar_t *rktp) {
|
|
892
|
+
rd_kafka_partition_msgid_t *partmsgid;
|
|
893
|
+
|
|
894
|
+
TAILQ_FOREACH(partmsgid, &rkt->rkt_saved_partmsgids, link) {
|
|
895
|
+
if (partmsgid->partition == rktp->rktp_partition)
|
|
896
|
+
break;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
if (!partmsgid)
|
|
900
|
+
return;
|
|
901
|
+
|
|
902
|
+
rktp->rktp_msgid = partmsgid->msgid;
|
|
903
|
+
rktp->rktp_eos.pid = partmsgid->pid;
|
|
904
|
+
rktp->rktp_eos.epoch_base_msgid = partmsgid->epoch_base_msgid;
|
|
905
|
+
|
|
906
|
+
rd_kafka_dbg(rkt->rkt_rk, EOS | RD_KAFKA_DBG_TOPIC, "MSGID",
|
|
907
|
+
"Topic %s [%" PRId32 "]: restored %s with MsgId %" PRIu64
|
|
908
|
+
" and "
|
|
909
|
+
"epoch base MsgId %" PRIu64
|
|
910
|
+
" that was saved upon removal %dms ago",
|
|
911
|
+
rkt->rkt_topic->str, rktp->rktp_partition,
|
|
912
|
+
rd_kafka_pid2str(partmsgid->pid), partmsgid->msgid,
|
|
913
|
+
partmsgid->epoch_base_msgid,
|
|
914
|
+
(int)((rd_clock() - partmsgid->ts) / 1000));
|
|
915
|
+
|
|
916
|
+
TAILQ_REMOVE(&rkt->rkt_saved_partmsgids, partmsgid, link);
|
|
917
|
+
rd_free(partmsgid);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
* @brief Update the number of partitions for a topic and takes actions
|
|
923
|
+
* accordingly.
|
|
924
|
+
*
|
|
925
|
+
* @returns 1 if the partition count changed, else 0.
|
|
926
|
+
*
|
|
927
|
+
* @locks rd_kafka_topic_wrlock(rkt) MUST be held.
|
|
928
|
+
*/
|
|
929
|
+
static int rd_kafka_topic_partition_cnt_update(rd_kafka_topic_t *rkt,
|
|
930
|
+
int32_t partition_cnt) {
|
|
931
|
+
rd_kafka_t *rk = rkt->rkt_rk;
|
|
932
|
+
rd_kafka_toppar_t **rktps;
|
|
933
|
+
rd_kafka_toppar_t *rktp;
|
|
934
|
+
rd_bool_t is_idempodent = rd_kafka_is_idempotent(rk);
|
|
935
|
+
int32_t i;
|
|
936
|
+
|
|
937
|
+
if (likely(rkt->rkt_partition_cnt == partition_cnt))
|
|
938
|
+
return 0; /* No change in partition count */
|
|
939
|
+
|
|
940
|
+
if (unlikely(rkt->rkt_partition_cnt != 0 &&
|
|
941
|
+
!rd_kafka_terminating(rkt->rkt_rk)))
|
|
942
|
+
rd_kafka_log(rk, LOG_NOTICE, "PARTCNT",
|
|
943
|
+
"Topic %s partition count changed "
|
|
944
|
+
"from %" PRId32 " to %" PRId32,
|
|
945
|
+
rkt->rkt_topic->str, rkt->rkt_partition_cnt,
|
|
946
|
+
partition_cnt);
|
|
947
|
+
else
|
|
948
|
+
rd_kafka_dbg(rk, TOPIC, "PARTCNT",
|
|
949
|
+
"Topic %s partition count changed "
|
|
950
|
+
"from %" PRId32 " to %" PRId32,
|
|
951
|
+
rkt->rkt_topic->str, rkt->rkt_partition_cnt,
|
|
952
|
+
partition_cnt);
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
/* Create and assign new partition list */
|
|
956
|
+
if (partition_cnt > 0)
|
|
957
|
+
rktps = rd_calloc(partition_cnt, sizeof(*rktps));
|
|
958
|
+
else
|
|
959
|
+
rktps = NULL;
|
|
960
|
+
|
|
961
|
+
for (i = 0; i < partition_cnt; i++) {
|
|
962
|
+
if (i >= rkt->rkt_partition_cnt) {
|
|
963
|
+
/* New partition. Check if its in the list of
|
|
964
|
+
* desired partitions first. */
|
|
965
|
+
|
|
966
|
+
rktp = rd_kafka_toppar_desired_get(rkt, i);
|
|
967
|
+
if (rktp) {
|
|
968
|
+
rd_kafka_toppar_lock(rktp);
|
|
969
|
+
rktp->rktp_flags &=
|
|
970
|
+
~(RD_KAFKA_TOPPAR_F_UNKNOWN |
|
|
971
|
+
RD_KAFKA_TOPPAR_F_REMOVE);
|
|
972
|
+
|
|
973
|
+
/* Remove from desp list since the
|
|
974
|
+
* partition is now known. */
|
|
975
|
+
rd_kafka_toppar_desired_unlink(rktp);
|
|
976
|
+
} else {
|
|
977
|
+
rktp = rd_kafka_toppar_new(rkt, i);
|
|
978
|
+
|
|
979
|
+
rd_kafka_toppar_lock(rktp);
|
|
980
|
+
rktp->rktp_flags &=
|
|
981
|
+
~(RD_KAFKA_TOPPAR_F_UNKNOWN |
|
|
982
|
+
RD_KAFKA_TOPPAR_F_REMOVE);
|
|
983
|
+
}
|
|
984
|
+
rktps[i] = rktp;
|
|
985
|
+
|
|
986
|
+
if (is_idempodent)
|
|
987
|
+
/* Restore idempotent producer state for
|
|
988
|
+
* this partition, if any. */
|
|
989
|
+
rd_kafka_toppar_idemp_msgid_restore(rkt, rktp);
|
|
990
|
+
|
|
991
|
+
rd_kafka_toppar_unlock(rktp);
|
|
992
|
+
|
|
993
|
+
} else {
|
|
994
|
+
/* Existing partition, grab our own reference. */
|
|
995
|
+
rktps[i] = rd_kafka_toppar_keep(rkt->rkt_p[i]);
|
|
996
|
+
/* Loose previous ref */
|
|
997
|
+
rd_kafka_toppar_destroy(rkt->rkt_p[i]);
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
/* Propagate notexist errors for desired partitions */
|
|
1002
|
+
RD_LIST_FOREACH(rktp, &rkt->rkt_desp, i) {
|
|
1003
|
+
rd_kafka_dbg(rkt->rkt_rk, TOPIC, "DESIRED",
|
|
1004
|
+
"%s [%" PRId32
|
|
1005
|
+
"]: "
|
|
1006
|
+
"desired partition does not exist in cluster",
|
|
1007
|
+
rkt->rkt_topic->str, rktp->rktp_partition);
|
|
1008
|
+
rd_kafka_toppar_enq_error(
|
|
1009
|
+
rktp,
|
|
1010
|
+
rkt->rkt_err ? rkt->rkt_err
|
|
1011
|
+
: RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION,
|
|
1012
|
+
"desired partition is not available");
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
/* Remove excessive partitions */
|
|
1016
|
+
for (i = partition_cnt; i < rkt->rkt_partition_cnt; i++) {
|
|
1017
|
+
rktp = rkt->rkt_p[i];
|
|
1018
|
+
|
|
1019
|
+
rd_kafka_dbg(rkt->rkt_rk, TOPIC, "REMOVE",
|
|
1020
|
+
"%s [%" PRId32 "] no longer reported in metadata",
|
|
1021
|
+
rkt->rkt_topic->str, rktp->rktp_partition);
|
|
1022
|
+
|
|
1023
|
+
rd_kafka_toppar_lock(rktp);
|
|
1024
|
+
|
|
1025
|
+
/* Idempotent/Transactional producer:
|
|
1026
|
+
* We need to save each removed partition's base msgid for
|
|
1027
|
+
* the (rare) chance the partition comes back,
|
|
1028
|
+
* in which case we must continue with the correct msgid
|
|
1029
|
+
* in future ProduceRequests.
|
|
1030
|
+
*
|
|
1031
|
+
* These base msgsid are restored (above) if/when partitions
|
|
1032
|
+
* come back and the PID,Epoch hasn't changed.
|
|
1033
|
+
*
|
|
1034
|
+
* One situation where this might happen is if a broker goes
|
|
1035
|
+
* out of sync and starts to wrongfully report an existing
|
|
1036
|
+
* topic as non-existent, triggering the removal of partitions
|
|
1037
|
+
* on the producer client. When metadata is eventually correct
|
|
1038
|
+
* again and the topic is "re-created" on the producer, it
|
|
1039
|
+
* must continue with the next msgid/baseseq. */
|
|
1040
|
+
if (is_idempodent && rd_kafka_pid_valid(rktp->rktp_eos.pid))
|
|
1041
|
+
rd_kafka_toppar_idemp_msgid_save(rkt, rktp);
|
|
1042
|
+
|
|
1043
|
+
rktp->rktp_flags |= RD_KAFKA_TOPPAR_F_UNKNOWN;
|
|
1044
|
+
|
|
1045
|
+
if (rktp->rktp_flags & RD_KAFKA_TOPPAR_F_DESIRED) {
|
|
1046
|
+
rd_kafka_dbg(rkt->rkt_rk, TOPIC, "DESIRED",
|
|
1047
|
+
"Topic %s [%" PRId32
|
|
1048
|
+
"] is desired "
|
|
1049
|
+
"but no longer known: "
|
|
1050
|
+
"moving back on desired list",
|
|
1051
|
+
rkt->rkt_topic->str, rktp->rktp_partition);
|
|
1052
|
+
|
|
1053
|
+
/* If this is a desired partition move it back on to
|
|
1054
|
+
* the desired list since partition is no longer known*/
|
|
1055
|
+
rd_kafka_toppar_desired_link(rktp);
|
|
1056
|
+
|
|
1057
|
+
if (!rd_kafka_terminating(rkt->rkt_rk))
|
|
1058
|
+
rd_kafka_toppar_enq_error(
|
|
1059
|
+
rktp,
|
|
1060
|
+
rkt->rkt_err
|
|
1061
|
+
? rkt->rkt_err
|
|
1062
|
+
: RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION,
|
|
1063
|
+
"desired partition is no longer "
|
|
1064
|
+
"available");
|
|
1065
|
+
|
|
1066
|
+
rd_kafka_toppar_broker_delegate(rktp, NULL);
|
|
1067
|
+
|
|
1068
|
+
} else {
|
|
1069
|
+
/* Tell handling broker to let go of the toppar */
|
|
1070
|
+
rd_kafka_toppar_broker_leave_for_remove(rktp);
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
rd_kafka_toppar_unlock(rktp);
|
|
1074
|
+
|
|
1075
|
+
rd_kafka_toppar_destroy(rktp);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
if (rkt->rkt_p)
|
|
1079
|
+
rd_free(rkt->rkt_p);
|
|
1080
|
+
|
|
1081
|
+
rkt->rkt_p = rktps;
|
|
1082
|
+
|
|
1083
|
+
rkt->rkt_partition_cnt = partition_cnt;
|
|
1084
|
+
|
|
1085
|
+
return 1;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* Topic 'rkt' does not exist: propagate to interested parties.
|
|
1092
|
+
* The topic's state must have been set to NOTEXISTS and
|
|
1093
|
+
* rd_kafka_topic_partition_cnt_update() must have been called prior to
|
|
1094
|
+
* calling this function.
|
|
1095
|
+
*
|
|
1096
|
+
* Locks: rd_kafka_topic_*lock() must be held.
|
|
1097
|
+
*/
|
|
1098
|
+
static void rd_kafka_topic_propagate_notexists(rd_kafka_topic_t *rkt,
|
|
1099
|
+
rd_kafka_resp_err_t err) {
|
|
1100
|
+
rd_kafka_toppar_t *rktp;
|
|
1101
|
+
int i;
|
|
1102
|
+
|
|
1103
|
+
if (rkt->rkt_rk->rk_type != RD_KAFKA_CONSUMER)
|
|
1104
|
+
return;
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
/* Notify consumers that the topic doesn't exist. */
|
|
1108
|
+
RD_LIST_FOREACH(rktp, &rkt->rkt_desp, i)
|
|
1109
|
+
rd_kafka_toppar_enq_error(rktp, err, "topic does not exist");
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
/**
|
|
1114
|
+
* Assign messages on the UA partition to available partitions.
|
|
1115
|
+
* Locks: rd_kafka_topic_*lock() must be held.
|
|
1116
|
+
*/
|
|
1117
|
+
static void rd_kafka_topic_assign_uas(rd_kafka_topic_t *rkt,
|
|
1118
|
+
rd_kafka_resp_err_t err) {
|
|
1119
|
+
rd_kafka_t *rk = rkt->rkt_rk;
|
|
1120
|
+
rd_kafka_toppar_t *rktp_ua;
|
|
1121
|
+
rd_kafka_msg_t *rkm, *tmp;
|
|
1122
|
+
rd_kafka_msgq_t uas = RD_KAFKA_MSGQ_INITIALIZER(uas);
|
|
1123
|
+
rd_kafka_msgq_t failed = RD_KAFKA_MSGQ_INITIALIZER(failed);
|
|
1124
|
+
rd_kafka_resp_err_t err_all = RD_KAFKA_RESP_ERR_NO_ERROR;
|
|
1125
|
+
int cnt;
|
|
1126
|
+
|
|
1127
|
+
if (rkt->rkt_rk->rk_type != RD_KAFKA_PRODUCER)
|
|
1128
|
+
return;
|
|
1129
|
+
|
|
1130
|
+
rktp_ua = rd_kafka_toppar_get(rkt, RD_KAFKA_PARTITION_UA, 0);
|
|
1131
|
+
if (unlikely(!rktp_ua)) {
|
|
1132
|
+
rd_kafka_dbg(rk, TOPIC, "ASSIGNUA",
|
|
1133
|
+
"No UnAssigned partition available for %s",
|
|
1134
|
+
rkt->rkt_topic->str);
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/* Assign all unassigned messages to new topics. */
|
|
1139
|
+
rd_kafka_toppar_lock(rktp_ua);
|
|
1140
|
+
|
|
1141
|
+
if (rkt->rkt_state == RD_KAFKA_TOPIC_S_ERROR) {
|
|
1142
|
+
err_all = rkt->rkt_err;
|
|
1143
|
+
rd_kafka_dbg(rk, TOPIC, "PARTCNT",
|
|
1144
|
+
"Failing all %i unassigned messages in "
|
|
1145
|
+
"topic %.*s due to permanent topic error: %s",
|
|
1146
|
+
rktp_ua->rktp_msgq.rkmq_msg_cnt,
|
|
1147
|
+
RD_KAFKAP_STR_PR(rkt->rkt_topic),
|
|
1148
|
+
rd_kafka_err2str(err_all));
|
|
1149
|
+
} else if (rkt->rkt_state == RD_KAFKA_TOPIC_S_NOTEXISTS) {
|
|
1150
|
+
err_all = err;
|
|
1151
|
+
rd_kafka_dbg(rk, TOPIC, "PARTCNT",
|
|
1152
|
+
"Failing all %i unassigned messages in "
|
|
1153
|
+
"topic %.*s since topic does not exist: %s",
|
|
1154
|
+
rktp_ua->rktp_msgq.rkmq_msg_cnt,
|
|
1155
|
+
RD_KAFKAP_STR_PR(rkt->rkt_topic),
|
|
1156
|
+
rd_kafka_err2str(err_all));
|
|
1157
|
+
} else {
|
|
1158
|
+
rd_kafka_dbg(rk, TOPIC, "PARTCNT",
|
|
1159
|
+
"Partitioning %i unassigned messages in "
|
|
1160
|
+
"topic %.*s to %" PRId32 " partitions",
|
|
1161
|
+
rktp_ua->rktp_msgq.rkmq_msg_cnt,
|
|
1162
|
+
RD_KAFKAP_STR_PR(rkt->rkt_topic),
|
|
1163
|
+
rkt->rkt_partition_cnt);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
rd_kafka_msgq_move(&uas, &rktp_ua->rktp_msgq);
|
|
1167
|
+
cnt = uas.rkmq_msg_cnt;
|
|
1168
|
+
rd_kafka_toppar_unlock(rktp_ua);
|
|
1169
|
+
|
|
1170
|
+
TAILQ_FOREACH_SAFE(rkm, &uas.rkmq_msgs, rkm_link, tmp) {
|
|
1171
|
+
/* Fast-path for failing messages with forced partition or
|
|
1172
|
+
* when all messages are to fail. */
|
|
1173
|
+
if (err_all || (rkm->rkm_partition != RD_KAFKA_PARTITION_UA &&
|
|
1174
|
+
rkm->rkm_partition >= rkt->rkt_partition_cnt &&
|
|
1175
|
+
rkt->rkt_state != RD_KAFKA_TOPIC_S_UNKNOWN)) {
|
|
1176
|
+
rd_kafka_msgq_enq(&failed, rkm);
|
|
1177
|
+
continue;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
if (unlikely(rd_kafka_msg_partitioner(rkt, rkm, 0) != 0)) {
|
|
1181
|
+
/* Desired partition not available */
|
|
1182
|
+
rd_kafka_msgq_enq(&failed, rkm);
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
rd_kafka_dbg(rk, TOPIC, "UAS",
|
|
1187
|
+
"%i/%i messages were partitioned in topic %s",
|
|
1188
|
+
cnt - failed.rkmq_msg_cnt, cnt, rkt->rkt_topic->str);
|
|
1189
|
+
|
|
1190
|
+
if (failed.rkmq_msg_cnt > 0) {
|
|
1191
|
+
/* Fail the messages */
|
|
1192
|
+
rd_kafka_dbg(rk, TOPIC, "UAS",
|
|
1193
|
+
"%" PRId32
|
|
1194
|
+
"/%i messages failed partitioning "
|
|
1195
|
+
"in topic %s",
|
|
1196
|
+
failed.rkmq_msg_cnt, cnt, rkt->rkt_topic->str);
|
|
1197
|
+
rd_kafka_dr_msgq(
|
|
1198
|
+
rkt, &failed,
|
|
1199
|
+
err_all ? err_all : RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
rd_kafka_toppar_destroy(rktp_ua); /* from get() */
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
|
|
1206
|
+
/**
|
|
1207
|
+
* @brief Mark topic as non-existent, unless metadata propagation configuration
|
|
1208
|
+
* disallows it.
|
|
1209
|
+
*
|
|
1210
|
+
* @param err Propagate non-existent topic using this error code.
|
|
1211
|
+
* If \p err is RD_KAFKA_RESP_ERR_TOPIC_EXCEPTION it means the
|
|
1212
|
+
* topic is invalid and no propagation delay will be used.
|
|
1213
|
+
*
|
|
1214
|
+
* @returns true if the topic was marked as non-existent, else false.
|
|
1215
|
+
*
|
|
1216
|
+
* @locks topic_wrlock() MUST be held.
|
|
1217
|
+
*/
|
|
1218
|
+
rd_bool_t rd_kafka_topic_set_notexists(rd_kafka_topic_t *rkt,
|
|
1219
|
+
rd_kafka_resp_err_t err) {
|
|
1220
|
+
rd_ts_t remains_us;
|
|
1221
|
+
rd_bool_t permanent = err == RD_KAFKA_RESP_ERR_TOPIC_EXCEPTION;
|
|
1222
|
+
|
|
1223
|
+
if (unlikely(rd_kafka_terminating(rkt->rkt_rk))) {
|
|
1224
|
+
/* Dont update metadata while terminating. */
|
|
1225
|
+
return rd_false;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
rd_assert(err != RD_KAFKA_RESP_ERR_NO_ERROR);
|
|
1229
|
+
|
|
1230
|
+
remains_us =
|
|
1231
|
+
(rkt->rkt_ts_state +
|
|
1232
|
+
(rkt->rkt_rk->rk_conf.metadata_propagation_max_ms * 1000)) -
|
|
1233
|
+
rkt->rkt_ts_metadata;
|
|
1234
|
+
|
|
1235
|
+
if (!permanent &&
|
|
1236
|
+
(rkt->rkt_state == RD_KAFKA_TOPIC_S_UNKNOWN ||
|
|
1237
|
+
rkt->rkt_state == RD_KAFKA_TOPIC_S_ERROR ||
|
|
1238
|
+
rkt->rkt_state == RD_KAFKA_TOPIC_S_EXISTS) &&
|
|
1239
|
+
remains_us > 0) {
|
|
1240
|
+
/* Still allowing topic metadata to propagate. */
|
|
1241
|
+
rd_kafka_dbg(
|
|
1242
|
+
rkt->rkt_rk, TOPIC | RD_KAFKA_DBG_METADATA, "TOPICPROP",
|
|
1243
|
+
"Topic %.*s does not exist, allowing %dms "
|
|
1244
|
+
"for metadata propagation before marking topic "
|
|
1245
|
+
"as non-existent",
|
|
1246
|
+
RD_KAFKAP_STR_PR(rkt->rkt_topic), (int)(remains_us / 1000));
|
|
1247
|
+
return rd_false;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
rd_kafka_topic_set_state(rkt, RD_KAFKA_TOPIC_S_NOTEXISTS);
|
|
1251
|
+
|
|
1252
|
+
rkt->rkt_flags &= ~RD_KAFKA_TOPIC_F_LEADER_UNAVAIL;
|
|
1253
|
+
|
|
1254
|
+
/* Update number of partitions */
|
|
1255
|
+
rd_kafka_topic_partition_cnt_update(rkt, 0);
|
|
1256
|
+
|
|
1257
|
+
/* Purge messages with forced partition */
|
|
1258
|
+
rd_kafka_topic_assign_uas(rkt, err);
|
|
1259
|
+
|
|
1260
|
+
/* Propagate nonexistent topic info */
|
|
1261
|
+
rd_kafka_topic_propagate_notexists(rkt, err);
|
|
1262
|
+
|
|
1263
|
+
return rd_true;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
/**
|
|
1267
|
+
* @brief Mark topic as existent, unless metadata propagation configuration
|
|
1268
|
+
* disallows it.
|
|
1269
|
+
*
|
|
1270
|
+
* @returns true if the topic was marked as existent, else false.
|
|
1271
|
+
*
|
|
1272
|
+
* @locks topic_wrlock() MUST be held.
|
|
1273
|
+
*/
|
|
1274
|
+
rd_bool_t rd_kafka_topic_set_exists(rd_kafka_topic_t *rkt,
|
|
1275
|
+
rd_kafka_Uuid_t topic_id) {
|
|
1276
|
+
rd_ts_t remains_us;
|
|
1277
|
+
|
|
1278
|
+
if (unlikely(rd_kafka_terminating(rkt->rkt_rk))) {
|
|
1279
|
+
/* Dont update metadata while terminating. */
|
|
1280
|
+
return rd_false;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
remains_us =
|
|
1284
|
+
(rkt->rkt_ts_state +
|
|
1285
|
+
(rkt->rkt_rk->rk_conf.metadata_propagation_max_ms * 1000)) -
|
|
1286
|
+
rkt->rkt_ts_metadata;
|
|
1287
|
+
|
|
1288
|
+
if (/* Same topic id */
|
|
1289
|
+
rd_kafka_Uuid_cmp(rkt->rkt_topic_id, topic_id) == 0 &&
|
|
1290
|
+
rkt->rkt_state == RD_KAFKA_TOPIC_S_NOTEXISTS && remains_us > 0) {
|
|
1291
|
+
/* Still allowing topic metadata to propagate. */
|
|
1292
|
+
rd_kafka_dbg(
|
|
1293
|
+
rkt->rkt_rk, TOPIC | RD_KAFKA_DBG_METADATA, "TOPICPROP",
|
|
1294
|
+
"Topic %.*s exists after being deleted, "
|
|
1295
|
+
" allowing %dms for metadata propagation before marking "
|
|
1296
|
+
"topic "
|
|
1297
|
+
"as existent",
|
|
1298
|
+
RD_KAFKAP_STR_PR(rkt->rkt_topic), (int)(remains_us / 1000));
|
|
1299
|
+
return rd_false;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
rd_kafka_topic_set_state(rkt, RD_KAFKA_TOPIC_S_EXISTS);
|
|
1303
|
+
|
|
1304
|
+
return rd_true;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
/**
|
|
1308
|
+
* @brief Mark topic as errored, such as when topic authorization fails.
|
|
1309
|
+
*
|
|
1310
|
+
* @param err Propagate error using this error code.
|
|
1311
|
+
*
|
|
1312
|
+
* @returns true if the topic was marked as errored, else false.
|
|
1313
|
+
*
|
|
1314
|
+
* @locality any
|
|
1315
|
+
* @locks topic_wrlock() MUST be held.
|
|
1316
|
+
*/
|
|
1317
|
+
rd_bool_t rd_kafka_topic_set_error(rd_kafka_topic_t *rkt,
|
|
1318
|
+
rd_kafka_resp_err_t err) {
|
|
1319
|
+
|
|
1320
|
+
if (unlikely(rd_kafka_terminating(rkt->rkt_rk))) {
|
|
1321
|
+
/* Dont update metadata while terminating. */
|
|
1322
|
+
return rd_false;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
rd_assert(err != RD_KAFKA_RESP_ERR_NO_ERROR);
|
|
1326
|
+
|
|
1327
|
+
/* Same error, ignore. */
|
|
1328
|
+
if (rkt->rkt_state == RD_KAFKA_TOPIC_S_ERROR && rkt->rkt_err == err)
|
|
1329
|
+
return rd_true;
|
|
1330
|
+
|
|
1331
|
+
rd_kafka_dbg(rkt->rkt_rk, TOPIC, "TOPICERROR",
|
|
1332
|
+
"Topic %s has permanent error: %s", rkt->rkt_topic->str,
|
|
1333
|
+
rd_kafka_err2str(err));
|
|
1334
|
+
|
|
1335
|
+
rd_kafka_topic_set_state(rkt, RD_KAFKA_TOPIC_S_ERROR);
|
|
1336
|
+
|
|
1337
|
+
rkt->rkt_err = err;
|
|
1338
|
+
|
|
1339
|
+
/* Update number of partitions */
|
|
1340
|
+
rd_kafka_topic_partition_cnt_update(rkt, 0);
|
|
1341
|
+
|
|
1342
|
+
/* Purge messages with forced partition */
|
|
1343
|
+
rd_kafka_topic_assign_uas(rkt, err);
|
|
1344
|
+
|
|
1345
|
+
return rd_true;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
|
|
1350
|
+
/**
|
|
1351
|
+
* @brief Update a topic from metadata.
|
|
1352
|
+
*
|
|
1353
|
+
* @param mdt Topic metadata.
|
|
1354
|
+
* @param mdit Topic internal metadata.
|
|
1355
|
+
* @param ts_age absolute age (timestamp) of metadata.
|
|
1356
|
+
* @returns 1 if the number of partitions changed, 0 if not, and -1 if the
|
|
1357
|
+
* topic is unknown.
|
|
1358
|
+
|
|
1359
|
+
*
|
|
1360
|
+
* @locks_required rd_kafka_*lock() MUST be held.
|
|
1361
|
+
*/
|
|
1362
|
+
static int
|
|
1363
|
+
rd_kafka_topic_metadata_update(rd_kafka_topic_t *rkt,
|
|
1364
|
+
const struct rd_kafka_metadata_topic *mdt,
|
|
1365
|
+
const rd_kafka_metadata_topic_internal_t *mdit,
|
|
1366
|
+
rd_ts_t ts_age) {
|
|
1367
|
+
rd_kafka_t *rk = rkt->rkt_rk;
|
|
1368
|
+
int upd = 0;
|
|
1369
|
+
int j;
|
|
1370
|
+
rd_kafka_broker_t **partbrokers;
|
|
1371
|
+
int leader_cnt = 0;
|
|
1372
|
+
int old_state;
|
|
1373
|
+
rd_bool_t partition_exists_with_no_leader_epoch = rd_false;
|
|
1374
|
+
rd_bool_t partition_exists_with_stale_leader_epoch = rd_false;
|
|
1375
|
+
|
|
1376
|
+
if (mdt->err != RD_KAFKA_RESP_ERR_NO_ERROR)
|
|
1377
|
+
rd_kafka_dbg(rk, TOPIC | RD_KAFKA_DBG_METADATA, "METADATA",
|
|
1378
|
+
"Error in metadata reply for "
|
|
1379
|
+
"topic %s (PartCnt %i): %s",
|
|
1380
|
+
rkt->rkt_topic->str, mdt->partition_cnt,
|
|
1381
|
+
rd_kafka_err2str(mdt->err));
|
|
1382
|
+
|
|
1383
|
+
if (unlikely(rd_kafka_terminating(rk))) {
|
|
1384
|
+
/* Dont update metadata while terminating, do this
|
|
1385
|
+
* after acquiring lock for proper synchronisation */
|
|
1386
|
+
return -1;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
/* Look up brokers before acquiring rkt lock to preserve lock order */
|
|
1390
|
+
partbrokers = rd_malloc(mdt->partition_cnt * sizeof(*partbrokers));
|
|
1391
|
+
|
|
1392
|
+
for (j = 0; j < mdt->partition_cnt; j++) {
|
|
1393
|
+
if (mdt->partitions[j].leader == -1) {
|
|
1394
|
+
partbrokers[j] = NULL;
|
|
1395
|
+
continue;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
partbrokers[j] = rd_kafka_broker_find_by_nodeid(
|
|
1399
|
+
rk, mdt->partitions[j].leader);
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
|
|
1403
|
+
rd_kafka_topic_wrlock(rkt);
|
|
1404
|
+
|
|
1405
|
+
old_state = rkt->rkt_state;
|
|
1406
|
+
rkt->rkt_ts_metadata = ts_age;
|
|
1407
|
+
|
|
1408
|
+
/* Set topic state.
|
|
1409
|
+
* UNKNOWN_TOPIC_* may indicate that auto.create.topics failed */
|
|
1410
|
+
if (mdt->err == RD_KAFKA_RESP_ERR_TOPIC_EXCEPTION /*invalid topic*/ ||
|
|
1411
|
+
mdt->err == RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART ||
|
|
1412
|
+
mdt->err == RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_ID)
|
|
1413
|
+
rd_kafka_topic_set_notexists(rkt, mdt->err);
|
|
1414
|
+
else if (mdt->err == RD_KAFKA_RESP_ERR_NO_ERROR &&
|
|
1415
|
+
mdt->partition_cnt > 0)
|
|
1416
|
+
rd_kafka_topic_set_exists(rkt, mdit->topic_id);
|
|
1417
|
+
else if (mdt->err == RD_KAFKA_RESP_ERR_TOPIC_AUTHORIZATION_FAILED)
|
|
1418
|
+
/* Only set an error when it's permanent and it needs
|
|
1419
|
+
* to be surfaced to the application. */
|
|
1420
|
+
rd_kafka_topic_set_error(rkt, mdt->err);
|
|
1421
|
+
|
|
1422
|
+
/* Update number of partitions, but not if there are
|
|
1423
|
+
* (possibly intermittent) errors (e.g., "Leader not available"). */
|
|
1424
|
+
if (mdt->err == RD_KAFKA_RESP_ERR_NO_ERROR) {
|
|
1425
|
+
rd_bool_t different_topic_id =
|
|
1426
|
+
rd_kafka_Uuid_cmp(mdit->topic_id, rkt->rkt_topic_id) != 0;
|
|
1427
|
+
if (different_topic_id ||
|
|
1428
|
+
mdt->partition_cnt > rkt->rkt_partition_cnt)
|
|
1429
|
+
upd += rd_kafka_topic_partition_cnt_update(
|
|
1430
|
+
rkt, mdt->partition_cnt);
|
|
1431
|
+
if (different_topic_id) {
|
|
1432
|
+
/* FIXME: an offset reset must be triggered.
|
|
1433
|
+
* when rkt_topic_id wasn't zero.
|
|
1434
|
+
* There are no problems
|
|
1435
|
+
* in test 0107_topic_recreate if offsets in new
|
|
1436
|
+
* topic are lower than in previous one,
|
|
1437
|
+
* causing an out of range and an offset reset,
|
|
1438
|
+
* but the rarer case where they're higher needs
|
|
1439
|
+
* to be checked. */
|
|
1440
|
+
rd_kafka_dbg(
|
|
1441
|
+
rk, TOPIC | RD_KAFKA_DBG_METADATA, "METADATA",
|
|
1442
|
+
"Topic %s changed id from %s to %s",
|
|
1443
|
+
rkt->rkt_topic->str,
|
|
1444
|
+
rd_kafka_Uuid_base64str(&rkt->rkt_topic_id),
|
|
1445
|
+
rd_kafka_Uuid_base64str(&mdit->topic_id));
|
|
1446
|
+
rkt->rkt_topic_id = mdit->topic_id;
|
|
1447
|
+
}
|
|
1448
|
+
/* If the metadata times out for a topic (because all brokers
|
|
1449
|
+
* are down) the state will transition to S_UNKNOWN.
|
|
1450
|
+
* When updated metadata is eventually received there might
|
|
1451
|
+
* not be any change to partition count or leader,
|
|
1452
|
+
* but there may still be messages in the UA partition that
|
|
1453
|
+
* needs to be assigned, so trigger an update for this case too.
|
|
1454
|
+
* Issue #1985. */
|
|
1455
|
+
if (old_state == RD_KAFKA_TOPIC_S_UNKNOWN)
|
|
1456
|
+
upd++;
|
|
1457
|
+
|
|
1458
|
+
/* Update leader for each partition
|
|
1459
|
+
* only when topic response has no errors. */
|
|
1460
|
+
for (j = 0;
|
|
1461
|
+
j < mdt->partition_cnt && j < rkt->rkt_partition_cnt;
|
|
1462
|
+
j++) {
|
|
1463
|
+
int r = 0;
|
|
1464
|
+
rd_kafka_broker_t *leader;
|
|
1465
|
+
int32_t leader_epoch = mdit->partitions[j].leader_epoch;
|
|
1466
|
+
rd_kafka_toppar_t *rktp =
|
|
1467
|
+
rd_kafka_toppar_get(rkt, mdt->partitions[j].id, 0);
|
|
1468
|
+
|
|
1469
|
+
rd_kafka_dbg(rk, TOPIC | RD_KAFKA_DBG_METADATA,
|
|
1470
|
+
"METADATA",
|
|
1471
|
+
"Topic %s [%" PRId32 "] Leader %" PRId32
|
|
1472
|
+
" Epoch %" PRId32,
|
|
1473
|
+
rkt->rkt_topic->str, mdt->partitions[j].id,
|
|
1474
|
+
mdt->partitions[j].leader, leader_epoch);
|
|
1475
|
+
|
|
1476
|
+
leader = partbrokers[j];
|
|
1477
|
+
partbrokers[j] = NULL;
|
|
1478
|
+
|
|
1479
|
+
/* If broker does not support leaderEpoch(KIP 320) then
|
|
1480
|
+
* it is set to -1, we assume that metadata is not
|
|
1481
|
+
* stale. */
|
|
1482
|
+
if (leader_epoch == -1)
|
|
1483
|
+
partition_exists_with_no_leader_epoch = rd_true;
|
|
1484
|
+
else if (rktp && leader_epoch < rktp->rktp_leader_epoch)
|
|
1485
|
+
partition_exists_with_stale_leader_epoch =
|
|
1486
|
+
rd_true;
|
|
1487
|
+
|
|
1488
|
+
|
|
1489
|
+
/* Update leader for partition */
|
|
1490
|
+
r = rd_kafka_toppar_leader_update(
|
|
1491
|
+
rkt, mdt->partitions[j].id,
|
|
1492
|
+
mdt->partitions[j].leader, leader, leader_epoch);
|
|
1493
|
+
|
|
1494
|
+
upd += (r != 0 ? 1 : 0);
|
|
1495
|
+
|
|
1496
|
+
if (leader) {
|
|
1497
|
+
if (r != -1)
|
|
1498
|
+
leader_cnt++;
|
|
1499
|
+
/* Drop reference to broker (from find()) */
|
|
1500
|
+
rd_kafka_broker_destroy(leader);
|
|
1501
|
+
}
|
|
1502
|
+
RD_IF_FREE(rktp, rd_kafka_toppar_destroy);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
/* If all partitions have leaders, and this metadata update was not
|
|
1507
|
+
* stale, we can turn off fast leader query. */
|
|
1508
|
+
if (rkt->rkt_partition_cnt > 0 &&
|
|
1509
|
+
leader_cnt == rkt->rkt_partition_cnt &&
|
|
1510
|
+
(partition_exists_with_no_leader_epoch ||
|
|
1511
|
+
!partition_exists_with_stale_leader_epoch))
|
|
1512
|
+
rkt->rkt_flags &= ~RD_KAFKA_TOPIC_F_LEADER_UNAVAIL;
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
|
+
/* If there was an update to the partitions try to assign
|
|
1516
|
+
* unassigned messages to new partitions, or fail them */
|
|
1517
|
+
if (upd > 0)
|
|
1518
|
+
rd_kafka_topic_assign_uas(
|
|
1519
|
+
rkt,
|
|
1520
|
+
mdt->err ? mdt->err : RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC);
|
|
1521
|
+
|
|
1522
|
+
rd_kafka_topic_wrunlock(rkt);
|
|
1523
|
+
|
|
1524
|
+
/* Loose broker references */
|
|
1525
|
+
for (j = 0; j < mdt->partition_cnt; j++)
|
|
1526
|
+
if (partbrokers[j])
|
|
1527
|
+
rd_kafka_broker_destroy(partbrokers[j]);
|
|
1528
|
+
|
|
1529
|
+
rd_free(partbrokers);
|
|
1530
|
+
|
|
1531
|
+
return upd;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
/**
|
|
1535
|
+
* @brief Update topic by metadata, if topic is locally known.
|
|
1536
|
+
* @sa rd_kafka_topic_metadata_update()
|
|
1537
|
+
* @locks none
|
|
1538
|
+
*/
|
|
1539
|
+
int rd_kafka_topic_metadata_update2(
|
|
1540
|
+
rd_kafka_broker_t *rkb,
|
|
1541
|
+
const struct rd_kafka_metadata_topic *mdt,
|
|
1542
|
+
const rd_kafka_metadata_topic_internal_t *mdit) {
|
|
1543
|
+
rd_kafka_topic_t *rkt;
|
|
1544
|
+
int r;
|
|
1545
|
+
|
|
1546
|
+
rd_kafka_wrlock(rkb->rkb_rk);
|
|
1547
|
+
|
|
1548
|
+
if (likely(mdt->topic != NULL)) {
|
|
1549
|
+
rkt = rd_kafka_topic_find(rkb->rkb_rk, mdt->topic, 0 /*!lock*/);
|
|
1550
|
+
} else {
|
|
1551
|
+
rkt = rd_kafka_topic_find_by_topic_id(rkb->rkb_rk,
|
|
1552
|
+
mdit->topic_id);
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
if (!rkt) {
|
|
1556
|
+
rd_kafka_wrunlock(rkb->rkb_rk);
|
|
1557
|
+
return -1; /* Ignore topics that we dont have locally. */
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
r = rd_kafka_topic_metadata_update(rkt, mdt, mdit, rd_clock());
|
|
1561
|
+
|
|
1562
|
+
rd_kafka_wrunlock(rkb->rkb_rk);
|
|
1563
|
+
|
|
1564
|
+
rd_kafka_topic_destroy0(rkt); /* from find() */
|
|
1565
|
+
|
|
1566
|
+
return r;
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
|
|
1570
|
+
|
|
1571
|
+
/**
|
|
1572
|
+
* @returns a list of all partitions (rktp's) for a topic.
|
|
1573
|
+
* @remark rd_kafka_topic_*lock() MUST be held.
|
|
1574
|
+
*/
|
|
1575
|
+
static rd_list_t *rd_kafka_topic_get_all_partitions(rd_kafka_topic_t *rkt) {
|
|
1576
|
+
rd_list_t *list;
|
|
1577
|
+
rd_kafka_toppar_t *rktp;
|
|
1578
|
+
int i;
|
|
1579
|
+
|
|
1580
|
+
list = rd_list_new(rkt->rkt_partition_cnt +
|
|
1581
|
+
rd_list_cnt(&rkt->rkt_desp) + 1 /*ua*/,
|
|
1582
|
+
NULL);
|
|
1583
|
+
|
|
1584
|
+
for (i = 0; i < rkt->rkt_partition_cnt; i++)
|
|
1585
|
+
rd_list_add(list, rd_kafka_toppar_keep(rkt->rkt_p[i]));
|
|
1586
|
+
|
|
1587
|
+
RD_LIST_FOREACH(rktp, &rkt->rkt_desp, i)
|
|
1588
|
+
rd_list_add(list, rd_kafka_toppar_keep(rktp));
|
|
1589
|
+
|
|
1590
|
+
if (rkt->rkt_ua)
|
|
1591
|
+
rd_list_add(list, rd_kafka_toppar_keep(rkt->rkt_ua));
|
|
1592
|
+
|
|
1593
|
+
return list;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
|
|
1597
|
+
|
|
1598
|
+
/**
|
|
1599
|
+
* Remove all partitions from a topic, including the ua.
|
|
1600
|
+
* Must only be called during rd_kafka_t termination.
|
|
1601
|
+
*
|
|
1602
|
+
* Locality: main thread
|
|
1603
|
+
*/
|
|
1604
|
+
void rd_kafka_topic_partitions_remove(rd_kafka_topic_t *rkt) {
|
|
1605
|
+
rd_kafka_toppar_t *rktp;
|
|
1606
|
+
rd_list_t *partitions;
|
|
1607
|
+
int i;
|
|
1608
|
+
|
|
1609
|
+
/* Purge messages for all partitions outside the topic_wrlock since
|
|
1610
|
+
* a message can hold a reference to the topic_t and thus
|
|
1611
|
+
* would trigger a recursive lock dead-lock. */
|
|
1612
|
+
rd_kafka_topic_rdlock(rkt);
|
|
1613
|
+
partitions = rd_kafka_topic_get_all_partitions(rkt);
|
|
1614
|
+
rd_kafka_topic_rdunlock(rkt);
|
|
1615
|
+
|
|
1616
|
+
RD_LIST_FOREACH(rktp, partitions, i) {
|
|
1617
|
+
rd_kafka_toppar_lock(rktp);
|
|
1618
|
+
rd_kafka_msgq_purge(rkt->rkt_rk, &rktp->rktp_msgq);
|
|
1619
|
+
rd_kafka_toppar_purge_and_disable_queues(rktp);
|
|
1620
|
+
rd_kafka_toppar_unlock(rktp);
|
|
1621
|
+
|
|
1622
|
+
rd_kafka_toppar_destroy(rktp);
|
|
1623
|
+
}
|
|
1624
|
+
rd_list_destroy(partitions);
|
|
1625
|
+
|
|
1626
|
+
rd_kafka_topic_keep(rkt);
|
|
1627
|
+
rd_kafka_topic_wrlock(rkt);
|
|
1628
|
+
|
|
1629
|
+
/* Setting the partition count to 0 moves all partitions to
|
|
1630
|
+
* the desired list (rktp_desp). */
|
|
1631
|
+
rd_kafka_topic_partition_cnt_update(rkt, 0);
|
|
1632
|
+
|
|
1633
|
+
/* Now clean out the desired partitions list.
|
|
1634
|
+
* Use reverse traversal to avoid excessive memory shuffling
|
|
1635
|
+
* in rd_list_remove() */
|
|
1636
|
+
RD_LIST_FOREACH_REVERSE(rktp, &rkt->rkt_desp, i) {
|
|
1637
|
+
/* Keep a reference while deleting from desired list */
|
|
1638
|
+
rd_kafka_toppar_keep(rktp);
|
|
1639
|
+
|
|
1640
|
+
rd_kafka_toppar_lock(rktp);
|
|
1641
|
+
rd_kafka_toppar_desired_del(rktp);
|
|
1642
|
+
rd_kafka_toppar_unlock(rktp);
|
|
1643
|
+
|
|
1644
|
+
rd_kafka_toppar_destroy(rktp);
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
rd_kafka_assert(rkt->rkt_rk, rkt->rkt_partition_cnt == 0);
|
|
1648
|
+
|
|
1649
|
+
if (rkt->rkt_p)
|
|
1650
|
+
rd_free(rkt->rkt_p);
|
|
1651
|
+
|
|
1652
|
+
rkt->rkt_p = NULL;
|
|
1653
|
+
rkt->rkt_partition_cnt = 0;
|
|
1654
|
+
|
|
1655
|
+
if ((rktp = rkt->rkt_ua)) {
|
|
1656
|
+
rkt->rkt_ua = NULL;
|
|
1657
|
+
rd_kafka_toppar_destroy(rktp);
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
rd_kafka_topic_wrunlock(rkt);
|
|
1661
|
+
|
|
1662
|
+
rd_kafka_topic_destroy0(rkt);
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
/**
|
|
1668
|
+
* @returns the broker state (as a human readable string) if a query
|
|
1669
|
+
* for the partition leader is necessary, else NULL.
|
|
1670
|
+
* @locality any
|
|
1671
|
+
* @locks rd_kafka_toppar_lock MUST be held
|
|
1672
|
+
*/
|
|
1673
|
+
static const char *rd_kafka_toppar_needs_query(rd_kafka_t *rk,
|
|
1674
|
+
rd_kafka_toppar_t *rktp) {
|
|
1675
|
+
int broker_state;
|
|
1676
|
+
|
|
1677
|
+
if (!rktp->rktp_broker)
|
|
1678
|
+
return "not delegated";
|
|
1679
|
+
|
|
1680
|
+
if (rktp->rktp_broker->rkb_source == RD_KAFKA_INTERNAL)
|
|
1681
|
+
return "internal";
|
|
1682
|
+
|
|
1683
|
+
broker_state = rd_kafka_broker_get_state(rktp->rktp_broker);
|
|
1684
|
+
|
|
1685
|
+
if (broker_state >= RD_KAFKA_BROKER_STATE_UP)
|
|
1686
|
+
return NULL;
|
|
1687
|
+
|
|
1688
|
+
if (!rk->rk_conf.sparse_connections)
|
|
1689
|
+
return "down";
|
|
1690
|
+
|
|
1691
|
+
/* Partition assigned to broker but broker does not
|
|
1692
|
+
* need a persistent connection, this typically means
|
|
1693
|
+
* the partition is not being fetched or not being produced to,
|
|
1694
|
+
* so there is no need to re-query the leader. */
|
|
1695
|
+
if (broker_state == RD_KAFKA_BROKER_STATE_INIT)
|
|
1696
|
+
return NULL;
|
|
1697
|
+
|
|
1698
|
+
/* This is most likely a persistent broker,
|
|
1699
|
+
* which means the partition leader should probably
|
|
1700
|
+
* be re-queried to see if it needs changing. */
|
|
1701
|
+
return "down";
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
|
|
1705
|
+
|
|
1706
|
+
/**
|
|
1707
|
+
* @brief Scan all topics and partitions for:
|
|
1708
|
+
* - timed out messages in UA partitions.
|
|
1709
|
+
* - topics that needs to be created on the broker.
|
|
1710
|
+
* - topics who's metadata is too old.
|
|
1711
|
+
* - partitions with unknown leaders that require leader query.
|
|
1712
|
+
*
|
|
1713
|
+
* @locality rdkafka main thread
|
|
1714
|
+
*/
|
|
1715
|
+
void rd_kafka_topic_scan_all(rd_kafka_t *rk, rd_ts_t now) {
|
|
1716
|
+
rd_kafka_topic_t *rkt;
|
|
1717
|
+
rd_kafka_toppar_t *rktp;
|
|
1718
|
+
rd_list_t query_topics;
|
|
1719
|
+
|
|
1720
|
+
rd_list_init(&query_topics, 0, rd_free);
|
|
1721
|
+
|
|
1722
|
+
rd_kafka_rdlock(rk);
|
|
1723
|
+
TAILQ_FOREACH(rkt, &rk->rk_topics, rkt_link) {
|
|
1724
|
+
int p;
|
|
1725
|
+
int query_this = 0;
|
|
1726
|
+
rd_kafka_msgq_t timedout = RD_KAFKA_MSGQ_INITIALIZER(timedout);
|
|
1727
|
+
|
|
1728
|
+
rd_kafka_topic_wrlock(rkt);
|
|
1729
|
+
|
|
1730
|
+
/* Check if metadata information has timed out. */
|
|
1731
|
+
if (rkt->rkt_state != RD_KAFKA_TOPIC_S_UNKNOWN &&
|
|
1732
|
+
!rd_kafka_metadata_cache_topic_get(
|
|
1733
|
+
rk, rkt->rkt_topic->str, NULL, 1 /*only valid*/)) {
|
|
1734
|
+
rd_kafka_dbg(rk, TOPIC, "NOINFO",
|
|
1735
|
+
"Topic %s metadata information timed out "
|
|
1736
|
+
"(%" PRId64 "ms old)",
|
|
1737
|
+
rkt->rkt_topic->str,
|
|
1738
|
+
(rd_clock() - rkt->rkt_ts_metadata) /
|
|
1739
|
+
1000);
|
|
1740
|
+
rd_kafka_topic_set_state(rkt, RD_KAFKA_TOPIC_S_UNKNOWN);
|
|
1741
|
+
|
|
1742
|
+
query_this = 1;
|
|
1743
|
+
} else if (rkt->rkt_state == RD_KAFKA_TOPIC_S_UNKNOWN) {
|
|
1744
|
+
rd_kafka_dbg(rk, TOPIC, "NOINFO",
|
|
1745
|
+
"Topic %s metadata information unknown",
|
|
1746
|
+
rkt->rkt_topic->str);
|
|
1747
|
+
query_this = 1;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
/* Just need a read-lock from here on. */
|
|
1751
|
+
rd_kafka_topic_wrunlock(rkt);
|
|
1752
|
+
rd_kafka_topic_rdlock(rkt);
|
|
1753
|
+
|
|
1754
|
+
if (rkt->rkt_partition_cnt == 0) {
|
|
1755
|
+
/* If this topic is unknown by brokers try
|
|
1756
|
+
* to create it by sending a topic-specific
|
|
1757
|
+
* metadata request.
|
|
1758
|
+
* This requires "auto.create.topics.enable=true"
|
|
1759
|
+
* on the brokers. */
|
|
1760
|
+
rd_kafka_dbg(rk, TOPIC, "NOINFO",
|
|
1761
|
+
"Topic %s partition count is zero: "
|
|
1762
|
+
"should refresh metadata",
|
|
1763
|
+
rkt->rkt_topic->str);
|
|
1764
|
+
|
|
1765
|
+
query_this = 1;
|
|
1766
|
+
|
|
1767
|
+
} else if (!rd_list_empty(&rkt->rkt_desp) &&
|
|
1768
|
+
rd_interval_immediate(&rkt->rkt_desp_refresh_intvl,
|
|
1769
|
+
10 * 1000 * 1000, 0) > 0) {
|
|
1770
|
+
/* Query topic metadata if there are
|
|
1771
|
+
* desired (non-existent) partitions.
|
|
1772
|
+
* At most every 10 seconds. */
|
|
1773
|
+
rd_kafka_dbg(rk, TOPIC, "DESIRED",
|
|
1774
|
+
"Topic %s has %d desired partition(s): "
|
|
1775
|
+
"should refresh metadata",
|
|
1776
|
+
rkt->rkt_topic->str,
|
|
1777
|
+
rd_list_cnt(&rkt->rkt_desp));
|
|
1778
|
+
|
|
1779
|
+
query_this = 1;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
for (p = RD_KAFKA_PARTITION_UA; p < rkt->rkt_partition_cnt;
|
|
1783
|
+
p++) {
|
|
1784
|
+
|
|
1785
|
+
if (!(rktp = rd_kafka_toppar_get(
|
|
1786
|
+
rkt, p,
|
|
1787
|
+
p == RD_KAFKA_PARTITION_UA ? rd_true
|
|
1788
|
+
: rd_false)))
|
|
1789
|
+
continue;
|
|
1790
|
+
|
|
1791
|
+
rd_kafka_toppar_lock(rktp);
|
|
1792
|
+
|
|
1793
|
+
/* Check that partition is delegated to a broker that
|
|
1794
|
+
* is up, else add topic to query list. */
|
|
1795
|
+
if (p != RD_KAFKA_PARTITION_UA) {
|
|
1796
|
+
const char *leader_reason =
|
|
1797
|
+
rd_kafka_toppar_needs_query(rk, rktp);
|
|
1798
|
+
|
|
1799
|
+
if (leader_reason) {
|
|
1800
|
+
rd_kafka_dbg(rk, TOPIC, "QRYLEADER",
|
|
1801
|
+
"Topic %s [%" PRId32
|
|
1802
|
+
"]: "
|
|
1803
|
+
"broker is %s: re-query",
|
|
1804
|
+
rkt->rkt_topic->str,
|
|
1805
|
+
rktp->rktp_partition,
|
|
1806
|
+
leader_reason);
|
|
1807
|
+
query_this = 1;
|
|
1808
|
+
}
|
|
1809
|
+
} else {
|
|
1810
|
+
if (rk->rk_type == RD_KAFKA_PRODUCER) {
|
|
1811
|
+
/* Scan UA partition for message
|
|
1812
|
+
* timeouts.
|
|
1813
|
+
* Proper partitions are scanned by
|
|
1814
|
+
* their toppar broker thread. */
|
|
1815
|
+
rd_kafka_msgq_age_scan(
|
|
1816
|
+
rktp, &rktp->rktp_msgq, &timedout,
|
|
1817
|
+
now, NULL);
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
rd_kafka_toppar_unlock(rktp);
|
|
1822
|
+
rd_kafka_toppar_destroy(rktp);
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
rd_kafka_topic_rdunlock(rkt);
|
|
1826
|
+
|
|
1827
|
+
/* Propagate delivery reports for timed out messages */
|
|
1828
|
+
if (rd_kafka_msgq_len(&timedout) > 0) {
|
|
1829
|
+
rd_kafka_dbg(
|
|
1830
|
+
rk, MSG, "TIMEOUT", "%s: %d message(s) timed out",
|
|
1831
|
+
rkt->rkt_topic->str, rd_kafka_msgq_len(&timedout));
|
|
1832
|
+
rd_kafka_dr_msgq(rkt, &timedout,
|
|
1833
|
+
RD_KAFKA_RESP_ERR__MSG_TIMED_OUT);
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
/* Need to re-query this topic's leader. */
|
|
1837
|
+
if (query_this &&
|
|
1838
|
+
!rd_list_find(&query_topics, rkt->rkt_topic->str,
|
|
1839
|
+
(void *)strcmp))
|
|
1840
|
+
rd_list_add(&query_topics,
|
|
1841
|
+
rd_strdup(rkt->rkt_topic->str));
|
|
1842
|
+
}
|
|
1843
|
+
rd_kafka_rdunlock(rk);
|
|
1844
|
+
|
|
1845
|
+
if (!rd_list_empty(&query_topics))
|
|
1846
|
+
rd_kafka_metadata_refresh_topics(
|
|
1847
|
+
rk, NULL, &query_topics, rd_true /*force even if cached
|
|
1848
|
+
* info exists*/
|
|
1849
|
+
,
|
|
1850
|
+
rk->rk_conf.allow_auto_create_topics,
|
|
1851
|
+
rd_false /*!cgrp_update*/, -1,
|
|
1852
|
+
"refresh unavailable topics");
|
|
1853
|
+
rd_list_destroy(&query_topics);
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
|
|
1857
|
+
/**
|
|
1858
|
+
* Locks: rd_kafka_topic_*lock() must be held.
|
|
1859
|
+
*/
|
|
1860
|
+
int rd_kafka_topic_partition_available(const rd_kafka_topic_t *app_rkt,
|
|
1861
|
+
int32_t partition) {
|
|
1862
|
+
int avail;
|
|
1863
|
+
rd_kafka_toppar_t *rktp;
|
|
1864
|
+
rd_kafka_broker_t *rkb;
|
|
1865
|
+
|
|
1866
|
+
/* This API must only be called from a partitioner and the
|
|
1867
|
+
* partitioner is always passed a proper topic */
|
|
1868
|
+
rd_assert(!rd_kafka_rkt_is_lw(app_rkt));
|
|
1869
|
+
|
|
1870
|
+
rktp = rd_kafka_toppar_get(app_rkt, partition, 0 /*no ua-on-miss*/);
|
|
1871
|
+
if (unlikely(!rktp))
|
|
1872
|
+
return 0;
|
|
1873
|
+
|
|
1874
|
+
rkb = rd_kafka_toppar_broker(rktp, 1 /*proper broker*/);
|
|
1875
|
+
avail = rkb ? 1 : 0;
|
|
1876
|
+
if (rkb)
|
|
1877
|
+
rd_kafka_broker_destroy(rkb);
|
|
1878
|
+
rd_kafka_toppar_destroy(rktp);
|
|
1879
|
+
return avail;
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
void *rd_kafka_topic_opaque(const rd_kafka_topic_t *app_rkt) {
|
|
1884
|
+
const rd_kafka_lwtopic_t *lrkt;
|
|
1885
|
+
|
|
1886
|
+
lrkt = rd_kafka_rkt_get_lw((rd_kafka_topic_t *)app_rkt);
|
|
1887
|
+
if (unlikely(lrkt != NULL)) {
|
|
1888
|
+
void *opaque;
|
|
1889
|
+
rd_kafka_topic_t *rkt;
|
|
1890
|
+
|
|
1891
|
+
if (!(rkt = rd_kafka_topic_find(lrkt->lrkt_rk, lrkt->lrkt_topic,
|
|
1892
|
+
1 /*lock*/)))
|
|
1893
|
+
return NULL;
|
|
1894
|
+
|
|
1895
|
+
opaque = rkt->rkt_conf.opaque;
|
|
1896
|
+
|
|
1897
|
+
rd_kafka_topic_destroy0(rkt); /* loose refcnt from find() */
|
|
1898
|
+
|
|
1899
|
+
return opaque;
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
return app_rkt->rkt_conf.opaque;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
|
|
1906
|
+
int rd_kafka_topic_info_cmp(const void *_a, const void *_b) {
|
|
1907
|
+
const rd_kafka_topic_info_t *a = _a, *b = _b;
|
|
1908
|
+
int r, i;
|
|
1909
|
+
|
|
1910
|
+
if ((r = strcmp(a->topic, b->topic)))
|
|
1911
|
+
return r;
|
|
1912
|
+
|
|
1913
|
+
if ((r = RD_CMP(a->partition_cnt, b->partition_cnt)))
|
|
1914
|
+
return r;
|
|
1915
|
+
|
|
1916
|
+
if (a->partitions_internal == NULL && b->partitions_internal == NULL)
|
|
1917
|
+
return 0;
|
|
1918
|
+
|
|
1919
|
+
if (a->partitions_internal == NULL || b->partitions_internal == NULL)
|
|
1920
|
+
return (a->partitions_internal == NULL) ? 1 : -1;
|
|
1921
|
+
|
|
1922
|
+
/* We're certain partitions_internal exist for a/b and have the same
|
|
1923
|
+
* count. */
|
|
1924
|
+
for (i = 0; i < a->partition_cnt; i++) {
|
|
1925
|
+
size_t k;
|
|
1926
|
+
if ((r = RD_CMP(a->partitions_internal[i].racks_cnt,
|
|
1927
|
+
b->partitions_internal[i].racks_cnt)))
|
|
1928
|
+
return r;
|
|
1929
|
+
|
|
1930
|
+
for (k = 0; k < a->partitions_internal[i].racks_cnt; k++) {
|
|
1931
|
+
if ((r = rd_strcmp(a->partitions_internal[i].racks[k],
|
|
1932
|
+
b->partitions_internal[i].racks[k])))
|
|
1933
|
+
return r;
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
return 0;
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
|
|
1941
|
+
/**
|
|
1942
|
+
* @brief string compare two topics.
|
|
1943
|
+
*
|
|
1944
|
+
* @param _a topic string (type char *)
|
|
1945
|
+
* @param _b rd_kafka_topic_info_t * pointer.
|
|
1946
|
+
*/
|
|
1947
|
+
int rd_kafka_topic_info_topic_cmp(const void *_a, const void *_b) {
|
|
1948
|
+
const char *a = _a;
|
|
1949
|
+
const rd_kafka_topic_info_t *b = _b;
|
|
1950
|
+
return strcmp(a, b->topic);
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
|
|
1954
|
+
/**
|
|
1955
|
+
* Allocate new topic_info.
|
|
1956
|
+
* \p topic is copied.
|
|
1957
|
+
*/
|
|
1958
|
+
rd_kafka_topic_info_t *rd_kafka_topic_info_new(const char *topic,
|
|
1959
|
+
int partition_cnt) {
|
|
1960
|
+
rd_kafka_topic_info_t *ti;
|
|
1961
|
+
size_t tlen = strlen(topic) + 1;
|
|
1962
|
+
|
|
1963
|
+
/* Allocate space for the topic along with the struct */
|
|
1964
|
+
ti = rd_malloc(sizeof(*ti) + tlen);
|
|
1965
|
+
ti->topic = (char *)(ti + 1);
|
|
1966
|
+
memcpy((char *)ti->topic, topic, tlen);
|
|
1967
|
+
ti->partition_cnt = partition_cnt;
|
|
1968
|
+
ti->partitions_internal = NULL;
|
|
1969
|
+
|
|
1970
|
+
return ti;
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
/**
|
|
1974
|
+
* Allocate new topic_info, including rack information.
|
|
1975
|
+
* \p topic is copied.
|
|
1976
|
+
*/
|
|
1977
|
+
rd_kafka_topic_info_t *rd_kafka_topic_info_new_with_rack(
|
|
1978
|
+
const char *topic,
|
|
1979
|
+
int partition_cnt,
|
|
1980
|
+
const rd_kafka_metadata_partition_internal_t *mdpi) {
|
|
1981
|
+
rd_kafka_topic_info_t *ti;
|
|
1982
|
+
rd_tmpabuf_t tbuf;
|
|
1983
|
+
int i;
|
|
1984
|
+
rd_bool_t has_racks = rd_false;
|
|
1985
|
+
|
|
1986
|
+
rd_tmpabuf_new(&tbuf, 0, rd_true /* assert on fail */);
|
|
1987
|
+
|
|
1988
|
+
rd_tmpabuf_add_alloc(&tbuf, sizeof(*ti));
|
|
1989
|
+
rd_tmpabuf_add_alloc(&tbuf, strlen(topic) + 1);
|
|
1990
|
+
for (i = 0; i < partition_cnt; i++) {
|
|
1991
|
+
size_t j;
|
|
1992
|
+
if (!mdpi[i].racks)
|
|
1993
|
+
continue;
|
|
1994
|
+
|
|
1995
|
+
if (unlikely(!has_racks))
|
|
1996
|
+
has_racks = rd_true;
|
|
1997
|
+
|
|
1998
|
+
for (j = 0; j < mdpi[i].racks_cnt; j++) {
|
|
1999
|
+
rd_tmpabuf_add_alloc(&tbuf,
|
|
2000
|
+
strlen(mdpi[i].racks[j]) + 1);
|
|
2001
|
+
}
|
|
2002
|
+
rd_tmpabuf_add_alloc(&tbuf, sizeof(char *) * mdpi[i].racks_cnt);
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
/* Only bother allocating this if at least one
|
|
2006
|
+
* rack is there. */
|
|
2007
|
+
if (has_racks) {
|
|
2008
|
+
rd_tmpabuf_add_alloc(
|
|
2009
|
+
&tbuf, sizeof(rd_kafka_metadata_partition_internal_t) *
|
|
2010
|
+
partition_cnt);
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
rd_tmpabuf_finalize(&tbuf);
|
|
2014
|
+
|
|
2015
|
+
ti = rd_tmpabuf_alloc(&tbuf, sizeof(*ti));
|
|
2016
|
+
ti->topic = rd_tmpabuf_write_str(&tbuf, topic);
|
|
2017
|
+
ti->partition_cnt = partition_cnt;
|
|
2018
|
+
ti->partitions_internal = NULL;
|
|
2019
|
+
|
|
2020
|
+
if (has_racks) {
|
|
2021
|
+
ti->partitions_internal = rd_tmpabuf_alloc(
|
|
2022
|
+
&tbuf, sizeof(*ti->partitions_internal) * partition_cnt);
|
|
2023
|
+
|
|
2024
|
+
for (i = 0; i < partition_cnt; i++) {
|
|
2025
|
+
size_t j;
|
|
2026
|
+
ti->partitions_internal[i].id = mdpi[i].id;
|
|
2027
|
+
ti->partitions_internal[i].racks = NULL;
|
|
2028
|
+
|
|
2029
|
+
if (!mdpi[i].racks)
|
|
2030
|
+
continue;
|
|
2031
|
+
|
|
2032
|
+
ti->partitions_internal[i].racks_cnt =
|
|
2033
|
+
mdpi[i].racks_cnt;
|
|
2034
|
+
ti->partitions_internal[i].racks = rd_tmpabuf_alloc(
|
|
2035
|
+
&tbuf, sizeof(char *) * mdpi[i].racks_cnt);
|
|
2036
|
+
|
|
2037
|
+
for (j = 0; j < mdpi[i].racks_cnt; j++) {
|
|
2038
|
+
ti->partitions_internal[i].racks[j] =
|
|
2039
|
+
rd_tmpabuf_write_str(&tbuf,
|
|
2040
|
+
mdpi[i].racks[j]);
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
return ti;
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
/**
|
|
2049
|
+
* Destroy/free topic_info
|
|
2050
|
+
*/
|
|
2051
|
+
void rd_kafka_topic_info_destroy_free(void *ti) {
|
|
2052
|
+
rd_free(ti);
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
|
|
2056
|
+
/**
|
|
2057
|
+
* @brief Match \p topic to \p pattern.
|
|
2058
|
+
*
|
|
2059
|
+
* If pattern begins with "^" it is considered a regexp,
|
|
2060
|
+
* otherwise a simple string comparison is performed.
|
|
2061
|
+
*
|
|
2062
|
+
* @returns 1 on match, else 0.
|
|
2063
|
+
*/
|
|
2064
|
+
int rd_kafka_topic_match(rd_kafka_t *rk,
|
|
2065
|
+
const char *pattern,
|
|
2066
|
+
const char *topic) {
|
|
2067
|
+
char errstr[128];
|
|
2068
|
+
|
|
2069
|
+
if (*pattern == '^') {
|
|
2070
|
+
int r = rd_regex_match(pattern, topic, errstr, sizeof(errstr));
|
|
2071
|
+
if (unlikely(r == -1))
|
|
2072
|
+
rd_kafka_dbg(rk, TOPIC, "TOPICREGEX",
|
|
2073
|
+
"Topic \"%s\" regex \"%s\" "
|
|
2074
|
+
"matching failed: %s",
|
|
2075
|
+
topic, pattern, errstr);
|
|
2076
|
+
return r == 1;
|
|
2077
|
+
} else
|
|
2078
|
+
return !strcmp(pattern, topic);
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
|
|
2083
|
+
/**
|
|
2084
|
+
* @brief Trigger broker metadata query for topic leader.
|
|
2085
|
+
*
|
|
2086
|
+
* @locks none
|
|
2087
|
+
*/
|
|
2088
|
+
void rd_kafka_topic_leader_query0(rd_kafka_t *rk,
|
|
2089
|
+
rd_kafka_topic_t *rkt,
|
|
2090
|
+
int do_rk_lock,
|
|
2091
|
+
rd_bool_t force) {
|
|
2092
|
+
rd_list_t topics;
|
|
2093
|
+
|
|
2094
|
+
rd_list_init(&topics, 1, rd_free);
|
|
2095
|
+
rd_list_add(&topics, rd_strdup(rkt->rkt_topic->str));
|
|
2096
|
+
|
|
2097
|
+
rd_kafka_metadata_refresh_topics(
|
|
2098
|
+
rk, NULL, &topics, force, rk->rk_conf.allow_auto_create_topics,
|
|
2099
|
+
rd_false /*!cgrp_update*/, -1, "leader query");
|
|
2100
|
+
|
|
2101
|
+
rd_list_destroy(&topics);
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
|
|
2105
|
+
|
|
2106
|
+
/**
|
|
2107
|
+
* @brief Populate list \p topics with the topic names (strdupped char *) of
|
|
2108
|
+
* all locally known or cached topics.
|
|
2109
|
+
*
|
|
2110
|
+
* @param cache_cntp is an optional pointer to an int that will be set to the
|
|
2111
|
+
* number of entries added to \p topics from the
|
|
2112
|
+
* metadata cache.
|
|
2113
|
+
* @remark \p rk lock MUST NOT be held
|
|
2114
|
+
*/
|
|
2115
|
+
void rd_kafka_local_topics_to_list(rd_kafka_t *rk,
|
|
2116
|
+
rd_list_t *topics,
|
|
2117
|
+
int *cache_cntp) {
|
|
2118
|
+
rd_kafka_topic_t *rkt;
|
|
2119
|
+
int cache_cnt;
|
|
2120
|
+
|
|
2121
|
+
rd_kafka_rdlock(rk);
|
|
2122
|
+
rd_list_grow(topics, rk->rk_topic_cnt);
|
|
2123
|
+
TAILQ_FOREACH(rkt, &rk->rk_topics, rkt_link)
|
|
2124
|
+
rd_list_add(topics, rd_strdup(rkt->rkt_topic->str));
|
|
2125
|
+
cache_cnt = rd_kafka_metadata_cache_topics_to_list(rk, topics, rd_true);
|
|
2126
|
+
if (cache_cntp)
|
|
2127
|
+
*cache_cntp = cache_cnt;
|
|
2128
|
+
rd_kafka_rdunlock(rk);
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
|
|
2132
|
+
/**
|
|
2133
|
+
* @brief Unit test helper to set a topic's state to EXISTS
|
|
2134
|
+
* with the given number of partitions.
|
|
2135
|
+
*/
|
|
2136
|
+
void rd_ut_kafka_topic_set_topic_exists(rd_kafka_topic_t *rkt,
|
|
2137
|
+
int partition_cnt,
|
|
2138
|
+
int32_t leader_id) {
|
|
2139
|
+
rd_kafka_metadata_partition_internal_t *partitions =
|
|
2140
|
+
rd_calloc(partition_cnt, sizeof(*partitions));
|
|
2141
|
+
struct rd_kafka_metadata_topic mdt = {.topic =
|
|
2142
|
+
(char *)rkt->rkt_topic->str,
|
|
2143
|
+
.partition_cnt = partition_cnt};
|
|
2144
|
+
rd_kafka_metadata_topic_internal_t mdit = {.partitions = partitions};
|
|
2145
|
+
int i;
|
|
2146
|
+
|
|
2147
|
+
mdt.partitions = rd_alloca(sizeof(*mdt.partitions) * partition_cnt);
|
|
2148
|
+
|
|
2149
|
+
for (i = 0; i < partition_cnt; i++) {
|
|
2150
|
+
memset(&mdt.partitions[i], 0, sizeof(mdt.partitions[i]));
|
|
2151
|
+
mdt.partitions[i].id = i;
|
|
2152
|
+
mdt.partitions[i].leader = leader_id;
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
rd_kafka_wrlock(rkt->rkt_rk);
|
|
2156
|
+
rd_kafka_metadata_cache_topic_update(rkt->rkt_rk, &mdt, &mdit, rd_true,
|
|
2157
|
+
rd_false, rd_true);
|
|
2158
|
+
rd_kafka_topic_metadata_update(rkt, &mdt, &mdit, rd_clock());
|
|
2159
|
+
rd_kafka_wrunlock(rkt->rkt_rk);
|
|
2160
|
+
rd_free(partitions);
|
|
2161
|
+
}
|