@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.
Files changed (707) hide show
  1. package/LICENSE.txt +20 -0
  2. package/README.md +636 -0
  3. package/binding.gyp +154 -0
  4. package/deps/librdkafka/.clang-format +136 -0
  5. package/deps/librdkafka/.clang-format-cpp +103 -0
  6. package/deps/librdkafka/.dir-locals.el +10 -0
  7. package/deps/librdkafka/.formatignore +33 -0
  8. package/deps/librdkafka/.gdbmacros +19 -0
  9. package/deps/librdkafka/.github/CODEOWNERS +1 -0
  10. package/deps/librdkafka/.github/ISSUE_TEMPLATE +34 -0
  11. package/deps/librdkafka/.semaphore/run-all-tests.yml +77 -0
  12. package/deps/librdkafka/.semaphore/semaphore-integration.yml +250 -0
  13. package/deps/librdkafka/.semaphore/semaphore.yml +378 -0
  14. package/deps/librdkafka/.semaphore/verify-linux-packages.yml +41 -0
  15. package/deps/librdkafka/CHANGELOG.md +2208 -0
  16. package/deps/librdkafka/CMakeLists.txt +291 -0
  17. package/deps/librdkafka/CODE_OF_CONDUCT.md +46 -0
  18. package/deps/librdkafka/CONFIGURATION.md +209 -0
  19. package/deps/librdkafka/CONTRIBUTING.md +431 -0
  20. package/deps/librdkafka/Doxyfile +2375 -0
  21. package/deps/librdkafka/INTRODUCTION.md +2481 -0
  22. package/deps/librdkafka/LICENSE +26 -0
  23. package/deps/librdkafka/LICENSE.cjson +22 -0
  24. package/deps/librdkafka/LICENSE.crc32c +28 -0
  25. package/deps/librdkafka/LICENSE.fnv1a +18 -0
  26. package/deps/librdkafka/LICENSE.hdrhistogram +27 -0
  27. package/deps/librdkafka/LICENSE.lz4 +26 -0
  28. package/deps/librdkafka/LICENSE.murmur2 +25 -0
  29. package/deps/librdkafka/LICENSE.nanopb +22 -0
  30. package/deps/librdkafka/LICENSE.opentelemetry +203 -0
  31. package/deps/librdkafka/LICENSE.pycrc +23 -0
  32. package/deps/librdkafka/LICENSE.queue +31 -0
  33. package/deps/librdkafka/LICENSE.regexp +5 -0
  34. package/deps/librdkafka/LICENSE.snappy +36 -0
  35. package/deps/librdkafka/LICENSE.tinycthread +26 -0
  36. package/deps/librdkafka/LICENSE.wingetopt +49 -0
  37. package/deps/librdkafka/LICENSES.txt +625 -0
  38. package/deps/librdkafka/Makefile +125 -0
  39. package/deps/librdkafka/README.md +199 -0
  40. package/deps/librdkafka/README.win32 +26 -0
  41. package/deps/librdkafka/STATISTICS.md +624 -0
  42. package/deps/librdkafka/configure +214 -0
  43. package/deps/librdkafka/configure.self +331 -0
  44. package/deps/librdkafka/debian/changelog +111 -0
  45. package/deps/librdkafka/debian/compat +1 -0
  46. package/deps/librdkafka/debian/control +71 -0
  47. package/deps/librdkafka/debian/copyright +99 -0
  48. package/deps/librdkafka/debian/gbp.conf +9 -0
  49. package/deps/librdkafka/debian/librdkafka++1.install +1 -0
  50. package/deps/librdkafka/debian/librdkafka-dev.examples +2 -0
  51. package/deps/librdkafka/debian/librdkafka-dev.install +9 -0
  52. package/deps/librdkafka/debian/librdkafka1.docs +5 -0
  53. package/deps/librdkafka/debian/librdkafka1.install +1 -0
  54. package/deps/librdkafka/debian/librdkafka1.symbols +135 -0
  55. package/deps/librdkafka/debian/rules +19 -0
  56. package/deps/librdkafka/debian/source/format +1 -0
  57. package/deps/librdkafka/debian/watch +2 -0
  58. package/deps/librdkafka/dev-conf.sh +123 -0
  59. package/deps/librdkafka/examples/CMakeLists.txt +79 -0
  60. package/deps/librdkafka/examples/Makefile +167 -0
  61. package/deps/librdkafka/examples/README.md +42 -0
  62. package/deps/librdkafka/examples/alter_consumer_group_offsets.c +338 -0
  63. package/deps/librdkafka/examples/consumer.c +271 -0
  64. package/deps/librdkafka/examples/delete_records.c +233 -0
  65. package/deps/librdkafka/examples/describe_cluster.c +322 -0
  66. package/deps/librdkafka/examples/describe_consumer_groups.c +455 -0
  67. package/deps/librdkafka/examples/describe_topics.c +427 -0
  68. package/deps/librdkafka/examples/elect_leaders.c +317 -0
  69. package/deps/librdkafka/examples/globals.json +11 -0
  70. package/deps/librdkafka/examples/idempotent_producer.c +344 -0
  71. package/deps/librdkafka/examples/incremental_alter_configs.c +347 -0
  72. package/deps/librdkafka/examples/kafkatest_verifiable_client.cpp +945 -0
  73. package/deps/librdkafka/examples/list_consumer_group_offsets.c +359 -0
  74. package/deps/librdkafka/examples/list_consumer_groups.c +365 -0
  75. package/deps/librdkafka/examples/list_offsets.c +327 -0
  76. package/deps/librdkafka/examples/misc.c +287 -0
  77. package/deps/librdkafka/examples/openssl_engine_example.cpp +248 -0
  78. package/deps/librdkafka/examples/producer.c +251 -0
  79. package/deps/librdkafka/examples/producer.cpp +228 -0
  80. package/deps/librdkafka/examples/rdkafka_complex_consumer_example.c +617 -0
  81. package/deps/librdkafka/examples/rdkafka_complex_consumer_example.cpp +467 -0
  82. package/deps/librdkafka/examples/rdkafka_consume_batch.cpp +264 -0
  83. package/deps/librdkafka/examples/rdkafka_example.c +853 -0
  84. package/deps/librdkafka/examples/rdkafka_example.cpp +679 -0
  85. package/deps/librdkafka/examples/rdkafka_performance.c +1781 -0
  86. package/deps/librdkafka/examples/transactions-older-broker.c +668 -0
  87. package/deps/librdkafka/examples/transactions.c +665 -0
  88. package/deps/librdkafka/examples/user_scram.c +491 -0
  89. package/deps/librdkafka/examples/win_ssl_cert_store.cpp +396 -0
  90. package/deps/librdkafka/lds-gen.py +73 -0
  91. package/deps/librdkafka/mainpage.doxy +40 -0
  92. package/deps/librdkafka/mklove/Makefile.base +329 -0
  93. package/deps/librdkafka/mklove/modules/configure.atomics +144 -0
  94. package/deps/librdkafka/mklove/modules/configure.base +2484 -0
  95. package/deps/librdkafka/mklove/modules/configure.builtin +70 -0
  96. package/deps/librdkafka/mklove/modules/configure.cc +186 -0
  97. package/deps/librdkafka/mklove/modules/configure.cxx +8 -0
  98. package/deps/librdkafka/mklove/modules/configure.fileversion +65 -0
  99. package/deps/librdkafka/mklove/modules/configure.gitversion +29 -0
  100. package/deps/librdkafka/mklove/modules/configure.good_cflags +18 -0
  101. package/deps/librdkafka/mklove/modules/configure.host +132 -0
  102. package/deps/librdkafka/mklove/modules/configure.lib +49 -0
  103. package/deps/librdkafka/mklove/modules/configure.libcurl +99 -0
  104. package/deps/librdkafka/mklove/modules/configure.libsasl2 +36 -0
  105. package/deps/librdkafka/mklove/modules/configure.libssl +147 -0
  106. package/deps/librdkafka/mklove/modules/configure.libzstd +58 -0
  107. package/deps/librdkafka/mklove/modules/configure.parseversion +95 -0
  108. package/deps/librdkafka/mklove/modules/configure.pic +16 -0
  109. package/deps/librdkafka/mklove/modules/configure.socket +20 -0
  110. package/deps/librdkafka/mklove/modules/configure.zlib +61 -0
  111. package/deps/librdkafka/mklove/modules/patches/README.md +8 -0
  112. package/deps/librdkafka/mklove/modules/patches/libcurl.0000-no-runtime-linking-check.patch +11 -0
  113. package/deps/librdkafka/mklove/modules/patches/libssl.0000-osx-rand-include-fix-OpenSSL-PR16409.patch +56 -0
  114. package/deps/librdkafka/packaging/RELEASE.md +319 -0
  115. package/deps/librdkafka/packaging/alpine/build-alpine.sh +38 -0
  116. package/deps/librdkafka/packaging/archlinux/PKGBUILD +30 -0
  117. package/deps/librdkafka/packaging/cmake/Config.cmake.in +37 -0
  118. package/deps/librdkafka/packaging/cmake/Modules/FindLZ4.cmake +38 -0
  119. package/deps/librdkafka/packaging/cmake/Modules/FindZSTD.cmake +27 -0
  120. package/deps/librdkafka/packaging/cmake/Modules/LICENSE.FindZstd +178 -0
  121. package/deps/librdkafka/packaging/cmake/README.md +38 -0
  122. package/deps/librdkafka/packaging/cmake/config.h.in +52 -0
  123. package/deps/librdkafka/packaging/cmake/parseversion.cmake +60 -0
  124. package/deps/librdkafka/packaging/cmake/rdkafka.pc.in +12 -0
  125. package/deps/librdkafka/packaging/cmake/try_compile/atomic_32_test.c +8 -0
  126. package/deps/librdkafka/packaging/cmake/try_compile/atomic_64_test.c +8 -0
  127. package/deps/librdkafka/packaging/cmake/try_compile/c11threads_test.c +14 -0
  128. package/deps/librdkafka/packaging/cmake/try_compile/crc32c_hw_test.c +27 -0
  129. package/deps/librdkafka/packaging/cmake/try_compile/dlopen_test.c +11 -0
  130. package/deps/librdkafka/packaging/cmake/try_compile/libsasl2_test.c +7 -0
  131. package/deps/librdkafka/packaging/cmake/try_compile/pthread_setname_darwin_test.c +6 -0
  132. package/deps/librdkafka/packaging/cmake/try_compile/pthread_setname_freebsd_test.c +7 -0
  133. package/deps/librdkafka/packaging/cmake/try_compile/pthread_setname_gnu_test.c +5 -0
  134. package/deps/librdkafka/packaging/cmake/try_compile/rand_r_test.c +7 -0
  135. package/deps/librdkafka/packaging/cmake/try_compile/rdkafka_setup.cmake +122 -0
  136. package/deps/librdkafka/packaging/cmake/try_compile/regex_test.c +10 -0
  137. package/deps/librdkafka/packaging/cmake/try_compile/strndup_test.c +5 -0
  138. package/deps/librdkafka/packaging/cmake/try_compile/sync_32_test.c +8 -0
  139. package/deps/librdkafka/packaging/cmake/try_compile/sync_64_test.c +8 -0
  140. package/deps/librdkafka/packaging/cp/README.md +16 -0
  141. package/deps/librdkafka/packaging/cp/check_features.c +72 -0
  142. package/deps/librdkafka/packaging/cp/verify-deb.sh +33 -0
  143. package/deps/librdkafka/packaging/cp/verify-packages.sh +69 -0
  144. package/deps/librdkafka/packaging/cp/verify-rpm.sh +32 -0
  145. package/deps/librdkafka/packaging/debian/changelog +66 -0
  146. package/deps/librdkafka/packaging/debian/compat +1 -0
  147. package/deps/librdkafka/packaging/debian/control +49 -0
  148. package/deps/librdkafka/packaging/debian/copyright +84 -0
  149. package/deps/librdkafka/packaging/debian/docs +5 -0
  150. package/deps/librdkafka/packaging/debian/gbp.conf +9 -0
  151. package/deps/librdkafka/packaging/debian/librdkafka-dev.dirs +2 -0
  152. package/deps/librdkafka/packaging/debian/librdkafka-dev.examples +2 -0
  153. package/deps/librdkafka/packaging/debian/librdkafka-dev.install +6 -0
  154. package/deps/librdkafka/packaging/debian/librdkafka-dev.substvars +1 -0
  155. package/deps/librdkafka/packaging/debian/librdkafka.dsc +16 -0
  156. package/deps/librdkafka/packaging/debian/librdkafka1-dbg.substvars +1 -0
  157. package/deps/librdkafka/packaging/debian/librdkafka1.dirs +1 -0
  158. package/deps/librdkafka/packaging/debian/librdkafka1.install +2 -0
  159. package/deps/librdkafka/packaging/debian/librdkafka1.postinst.debhelper +5 -0
  160. package/deps/librdkafka/packaging/debian/librdkafka1.postrm.debhelper +5 -0
  161. package/deps/librdkafka/packaging/debian/librdkafka1.symbols +64 -0
  162. package/deps/librdkafka/packaging/debian/rules +19 -0
  163. package/deps/librdkafka/packaging/debian/source/format +1 -0
  164. package/deps/librdkafka/packaging/debian/watch +2 -0
  165. package/deps/librdkafka/packaging/get_version.py +21 -0
  166. package/deps/librdkafka/packaging/homebrew/README.md +15 -0
  167. package/deps/librdkafka/packaging/homebrew/brew-update-pr.sh +31 -0
  168. package/deps/librdkafka/packaging/mingw-w64/configure-build-msys2-mingw-static.sh +52 -0
  169. package/deps/librdkafka/packaging/mingw-w64/configure-build-msys2-mingw.sh +21 -0
  170. package/deps/librdkafka/packaging/mingw-w64/export-variables.sh +13 -0
  171. package/deps/librdkafka/packaging/mingw-w64/run-tests.sh +6 -0
  172. package/deps/librdkafka/packaging/mingw-w64/semaphoreci-build.sh +38 -0
  173. package/deps/librdkafka/packaging/nuget/README.md +84 -0
  174. package/deps/librdkafka/packaging/nuget/artifact.py +177 -0
  175. package/deps/librdkafka/packaging/nuget/cleanup-s3.py +143 -0
  176. package/deps/librdkafka/packaging/nuget/common/p-common__plat-windows__arch-win32__bldtype-Release/msvcr120.zip +0 -0
  177. package/deps/librdkafka/packaging/nuget/common/p-common__plat-windows__arch-win32__bldtype-Release/msvcr140.zip +0 -0
  178. package/deps/librdkafka/packaging/nuget/common/p-common__plat-windows__arch-x64__bldtype-Release/msvcr120.zip +0 -0
  179. package/deps/librdkafka/packaging/nuget/common/p-common__plat-windows__arch-x64__bldtype-Release/msvcr140.zip +0 -0
  180. package/deps/librdkafka/packaging/nuget/nuget.sh +21 -0
  181. package/deps/librdkafka/packaging/nuget/nugetpackage.py +278 -0
  182. package/deps/librdkafka/packaging/nuget/packaging.py +448 -0
  183. package/deps/librdkafka/packaging/nuget/push-to-nuget.sh +21 -0
  184. package/deps/librdkafka/packaging/nuget/release.py +167 -0
  185. package/deps/librdkafka/packaging/nuget/requirements.txt +3 -0
  186. package/deps/librdkafka/packaging/nuget/staticpackage.py +178 -0
  187. package/deps/librdkafka/packaging/nuget/templates/librdkafka.redist.nuspec +21 -0
  188. package/deps/librdkafka/packaging/nuget/templates/librdkafka.redist.props +18 -0
  189. package/deps/librdkafka/packaging/nuget/templates/librdkafka.redist.targets +19 -0
  190. package/deps/librdkafka/packaging/nuget/zfile/__init__.py +0 -0
  191. package/deps/librdkafka/packaging/nuget/zfile/zfile.py +98 -0
  192. package/deps/librdkafka/packaging/rpm/Makefile +92 -0
  193. package/deps/librdkafka/packaging/rpm/README.md +23 -0
  194. package/deps/librdkafka/packaging/rpm/el7-x86_64.cfg +40 -0
  195. package/deps/librdkafka/packaging/rpm/librdkafka.spec +118 -0
  196. package/deps/librdkafka/packaging/rpm/mock-on-docker.sh +96 -0
  197. package/deps/librdkafka/packaging/rpm/tests/Makefile +25 -0
  198. package/deps/librdkafka/packaging/rpm/tests/README.md +8 -0
  199. package/deps/librdkafka/packaging/rpm/tests/run-test.sh +42 -0
  200. package/deps/librdkafka/packaging/rpm/tests/test-on-docker.sh +56 -0
  201. package/deps/librdkafka/packaging/rpm/tests/test.c +77 -0
  202. package/deps/librdkafka/packaging/rpm/tests/test.cpp +34 -0
  203. package/deps/librdkafka/packaging/tools/Dockerfile +31 -0
  204. package/deps/librdkafka/packaging/tools/build-configurations-checks.sh +12 -0
  205. package/deps/librdkafka/packaging/tools/build-deb-package.sh +64 -0
  206. package/deps/librdkafka/packaging/tools/build-debian.sh +65 -0
  207. package/deps/librdkafka/packaging/tools/build-manylinux.sh +68 -0
  208. package/deps/librdkafka/packaging/tools/build-release-artifacts.sh +139 -0
  209. package/deps/librdkafka/packaging/tools/distro-build.sh +38 -0
  210. package/deps/librdkafka/packaging/tools/gh-release-checksums.py +39 -0
  211. package/deps/librdkafka/packaging/tools/rdutcoverage.sh +25 -0
  212. package/deps/librdkafka/packaging/tools/requirements.txt +2 -0
  213. package/deps/librdkafka/packaging/tools/run-in-docker.sh +28 -0
  214. package/deps/librdkafka/packaging/tools/run-integration-tests.sh +31 -0
  215. package/deps/librdkafka/packaging/tools/run-style-check.sh +4 -0
  216. package/deps/librdkafka/packaging/tools/style-format.sh +149 -0
  217. package/deps/librdkafka/packaging/tools/update_rpcs_max_versions.py +100 -0
  218. package/deps/librdkafka/service.yml +172 -0
  219. package/deps/librdkafka/src/CMakeLists.txt +374 -0
  220. package/deps/librdkafka/src/Makefile +103 -0
  221. package/deps/librdkafka/src/README.lz4.md +30 -0
  222. package/deps/librdkafka/src/cJSON.c +2834 -0
  223. package/deps/librdkafka/src/cJSON.h +398 -0
  224. package/deps/librdkafka/src/crc32c.c +430 -0
  225. package/deps/librdkafka/src/crc32c.h +38 -0
  226. package/deps/librdkafka/src/generate_proto.sh +66 -0
  227. package/deps/librdkafka/src/librdkafka_cgrp_synch.png +0 -0
  228. package/deps/librdkafka/src/lz4.c +2727 -0
  229. package/deps/librdkafka/src/lz4.h +842 -0
  230. package/deps/librdkafka/src/lz4frame.c +2078 -0
  231. package/deps/librdkafka/src/lz4frame.h +692 -0
  232. package/deps/librdkafka/src/lz4frame_static.h +47 -0
  233. package/deps/librdkafka/src/lz4hc.c +1631 -0
  234. package/deps/librdkafka/src/lz4hc.h +413 -0
  235. package/deps/librdkafka/src/nanopb/pb.h +917 -0
  236. package/deps/librdkafka/src/nanopb/pb_common.c +388 -0
  237. package/deps/librdkafka/src/nanopb/pb_common.h +49 -0
  238. package/deps/librdkafka/src/nanopb/pb_decode.c +1727 -0
  239. package/deps/librdkafka/src/nanopb/pb_decode.h +193 -0
  240. package/deps/librdkafka/src/nanopb/pb_encode.c +1000 -0
  241. package/deps/librdkafka/src/nanopb/pb_encode.h +185 -0
  242. package/deps/librdkafka/src/opentelemetry/common.pb.c +32 -0
  243. package/deps/librdkafka/src/opentelemetry/common.pb.h +170 -0
  244. package/deps/librdkafka/src/opentelemetry/metrics.options +2 -0
  245. package/deps/librdkafka/src/opentelemetry/metrics.pb.c +67 -0
  246. package/deps/librdkafka/src/opentelemetry/metrics.pb.h +966 -0
  247. package/deps/librdkafka/src/opentelemetry/resource.pb.c +12 -0
  248. package/deps/librdkafka/src/opentelemetry/resource.pb.h +58 -0
  249. package/deps/librdkafka/src/queue.h +850 -0
  250. package/deps/librdkafka/src/rd.h +584 -0
  251. package/deps/librdkafka/src/rdaddr.c +255 -0
  252. package/deps/librdkafka/src/rdaddr.h +202 -0
  253. package/deps/librdkafka/src/rdatomic.h +230 -0
  254. package/deps/librdkafka/src/rdavg.h +260 -0
  255. package/deps/librdkafka/src/rdavl.c +210 -0
  256. package/deps/librdkafka/src/rdavl.h +250 -0
  257. package/deps/librdkafka/src/rdbase64.c +200 -0
  258. package/deps/librdkafka/src/rdbase64.h +43 -0
  259. package/deps/librdkafka/src/rdbuf.c +1884 -0
  260. package/deps/librdkafka/src/rdbuf.h +375 -0
  261. package/deps/librdkafka/src/rdcrc32.c +114 -0
  262. package/deps/librdkafka/src/rdcrc32.h +170 -0
  263. package/deps/librdkafka/src/rddl.c +179 -0
  264. package/deps/librdkafka/src/rddl.h +43 -0
  265. package/deps/librdkafka/src/rdendian.h +175 -0
  266. package/deps/librdkafka/src/rdfloat.h +67 -0
  267. package/deps/librdkafka/src/rdfnv1a.c +113 -0
  268. package/deps/librdkafka/src/rdfnv1a.h +35 -0
  269. package/deps/librdkafka/src/rdgz.c +120 -0
  270. package/deps/librdkafka/src/rdgz.h +46 -0
  271. package/deps/librdkafka/src/rdhdrhistogram.c +721 -0
  272. package/deps/librdkafka/src/rdhdrhistogram.h +87 -0
  273. package/deps/librdkafka/src/rdhttp.c +830 -0
  274. package/deps/librdkafka/src/rdhttp.h +101 -0
  275. package/deps/librdkafka/src/rdinterval.h +177 -0
  276. package/deps/librdkafka/src/rdkafka.c +5505 -0
  277. package/deps/librdkafka/src/rdkafka.h +10686 -0
  278. package/deps/librdkafka/src/rdkafka_admin.c +9794 -0
  279. package/deps/librdkafka/src/rdkafka_admin.h +661 -0
  280. package/deps/librdkafka/src/rdkafka_assignment.c +1010 -0
  281. package/deps/librdkafka/src/rdkafka_assignment.h +73 -0
  282. package/deps/librdkafka/src/rdkafka_assignor.c +1786 -0
  283. package/deps/librdkafka/src/rdkafka_assignor.h +402 -0
  284. package/deps/librdkafka/src/rdkafka_aux.c +409 -0
  285. package/deps/librdkafka/src/rdkafka_aux.h +174 -0
  286. package/deps/librdkafka/src/rdkafka_background.c +221 -0
  287. package/deps/librdkafka/src/rdkafka_broker.c +6337 -0
  288. package/deps/librdkafka/src/rdkafka_broker.h +744 -0
  289. package/deps/librdkafka/src/rdkafka_buf.c +543 -0
  290. package/deps/librdkafka/src/rdkafka_buf.h +1525 -0
  291. package/deps/librdkafka/src/rdkafka_cert.c +576 -0
  292. package/deps/librdkafka/src/rdkafka_cert.h +62 -0
  293. package/deps/librdkafka/src/rdkafka_cgrp.c +7587 -0
  294. package/deps/librdkafka/src/rdkafka_cgrp.h +477 -0
  295. package/deps/librdkafka/src/rdkafka_conf.c +4880 -0
  296. package/deps/librdkafka/src/rdkafka_conf.h +732 -0
  297. package/deps/librdkafka/src/rdkafka_confval.h +97 -0
  298. package/deps/librdkafka/src/rdkafka_coord.c +623 -0
  299. package/deps/librdkafka/src/rdkafka_coord.h +132 -0
  300. package/deps/librdkafka/src/rdkafka_error.c +228 -0
  301. package/deps/librdkafka/src/rdkafka_error.h +80 -0
  302. package/deps/librdkafka/src/rdkafka_event.c +502 -0
  303. package/deps/librdkafka/src/rdkafka_event.h +126 -0
  304. package/deps/librdkafka/src/rdkafka_feature.c +898 -0
  305. package/deps/librdkafka/src/rdkafka_feature.h +104 -0
  306. package/deps/librdkafka/src/rdkafka_fetcher.c +1422 -0
  307. package/deps/librdkafka/src/rdkafka_fetcher.h +44 -0
  308. package/deps/librdkafka/src/rdkafka_header.c +220 -0
  309. package/deps/librdkafka/src/rdkafka_header.h +76 -0
  310. package/deps/librdkafka/src/rdkafka_idempotence.c +807 -0
  311. package/deps/librdkafka/src/rdkafka_idempotence.h +144 -0
  312. package/deps/librdkafka/src/rdkafka_int.h +1260 -0
  313. package/deps/librdkafka/src/rdkafka_interceptor.c +819 -0
  314. package/deps/librdkafka/src/rdkafka_interceptor.h +104 -0
  315. package/deps/librdkafka/src/rdkafka_lz4.c +450 -0
  316. package/deps/librdkafka/src/rdkafka_lz4.h +49 -0
  317. package/deps/librdkafka/src/rdkafka_metadata.c +2209 -0
  318. package/deps/librdkafka/src/rdkafka_metadata.h +345 -0
  319. package/deps/librdkafka/src/rdkafka_metadata_cache.c +1183 -0
  320. package/deps/librdkafka/src/rdkafka_mock.c +3661 -0
  321. package/deps/librdkafka/src/rdkafka_mock.h +610 -0
  322. package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1876 -0
  323. package/deps/librdkafka/src/rdkafka_mock_handlers.c +3113 -0
  324. package/deps/librdkafka/src/rdkafka_mock_int.h +710 -0
  325. package/deps/librdkafka/src/rdkafka_msg.c +2589 -0
  326. package/deps/librdkafka/src/rdkafka_msg.h +614 -0
  327. package/deps/librdkafka/src/rdkafka_msgbatch.h +62 -0
  328. package/deps/librdkafka/src/rdkafka_msgset.h +98 -0
  329. package/deps/librdkafka/src/rdkafka_msgset_reader.c +1806 -0
  330. package/deps/librdkafka/src/rdkafka_msgset_writer.c +1474 -0
  331. package/deps/librdkafka/src/rdkafka_offset.c +1565 -0
  332. package/deps/librdkafka/src/rdkafka_offset.h +150 -0
  333. package/deps/librdkafka/src/rdkafka_op.c +997 -0
  334. package/deps/librdkafka/src/rdkafka_op.h +858 -0
  335. package/deps/librdkafka/src/rdkafka_partition.c +4896 -0
  336. package/deps/librdkafka/src/rdkafka_partition.h +1182 -0
  337. package/deps/librdkafka/src/rdkafka_pattern.c +228 -0
  338. package/deps/librdkafka/src/rdkafka_pattern.h +70 -0
  339. package/deps/librdkafka/src/rdkafka_plugin.c +213 -0
  340. package/deps/librdkafka/src/rdkafka_plugin.h +41 -0
  341. package/deps/librdkafka/src/rdkafka_proto.h +736 -0
  342. package/deps/librdkafka/src/rdkafka_protocol.h +128 -0
  343. package/deps/librdkafka/src/rdkafka_queue.c +1230 -0
  344. package/deps/librdkafka/src/rdkafka_queue.h +1220 -0
  345. package/deps/librdkafka/src/rdkafka_range_assignor.c +1748 -0
  346. package/deps/librdkafka/src/rdkafka_request.c +7089 -0
  347. package/deps/librdkafka/src/rdkafka_request.h +732 -0
  348. package/deps/librdkafka/src/rdkafka_roundrobin_assignor.c +123 -0
  349. package/deps/librdkafka/src/rdkafka_sasl.c +530 -0
  350. package/deps/librdkafka/src/rdkafka_sasl.h +63 -0
  351. package/deps/librdkafka/src/rdkafka_sasl_cyrus.c +722 -0
  352. package/deps/librdkafka/src/rdkafka_sasl_int.h +89 -0
  353. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +1833 -0
  354. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.h +52 -0
  355. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1666 -0
  356. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +47 -0
  357. package/deps/librdkafka/src/rdkafka_sasl_plain.c +142 -0
  358. package/deps/librdkafka/src/rdkafka_sasl_scram.c +858 -0
  359. package/deps/librdkafka/src/rdkafka_sasl_win32.c +550 -0
  360. package/deps/librdkafka/src/rdkafka_ssl.c +2129 -0
  361. package/deps/librdkafka/src/rdkafka_ssl.h +86 -0
  362. package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4785 -0
  363. package/deps/librdkafka/src/rdkafka_subscription.c +278 -0
  364. package/deps/librdkafka/src/rdkafka_telemetry.c +760 -0
  365. package/deps/librdkafka/src/rdkafka_telemetry.h +52 -0
  366. package/deps/librdkafka/src/rdkafka_telemetry_decode.c +1053 -0
  367. package/deps/librdkafka/src/rdkafka_telemetry_decode.h +59 -0
  368. package/deps/librdkafka/src/rdkafka_telemetry_encode.c +997 -0
  369. package/deps/librdkafka/src/rdkafka_telemetry_encode.h +301 -0
  370. package/deps/librdkafka/src/rdkafka_timer.c +402 -0
  371. package/deps/librdkafka/src/rdkafka_timer.h +117 -0
  372. package/deps/librdkafka/src/rdkafka_topic.c +2161 -0
  373. package/deps/librdkafka/src/rdkafka_topic.h +334 -0
  374. package/deps/librdkafka/src/rdkafka_transport.c +1309 -0
  375. package/deps/librdkafka/src/rdkafka_transport.h +99 -0
  376. package/deps/librdkafka/src/rdkafka_transport_int.h +100 -0
  377. package/deps/librdkafka/src/rdkafka_txnmgr.c +3256 -0
  378. package/deps/librdkafka/src/rdkafka_txnmgr.h +171 -0
  379. package/deps/librdkafka/src/rdkafka_zstd.c +226 -0
  380. package/deps/librdkafka/src/rdkafka_zstd.h +57 -0
  381. package/deps/librdkafka/src/rdlist.c +576 -0
  382. package/deps/librdkafka/src/rdlist.h +434 -0
  383. package/deps/librdkafka/src/rdlog.c +89 -0
  384. package/deps/librdkafka/src/rdlog.h +41 -0
  385. package/deps/librdkafka/src/rdmap.c +508 -0
  386. package/deps/librdkafka/src/rdmap.h +492 -0
  387. package/deps/librdkafka/src/rdmurmur2.c +167 -0
  388. package/deps/librdkafka/src/rdmurmur2.h +35 -0
  389. package/deps/librdkafka/src/rdports.c +61 -0
  390. package/deps/librdkafka/src/rdports.h +38 -0
  391. package/deps/librdkafka/src/rdposix.h +250 -0
  392. package/deps/librdkafka/src/rdrand.c +80 -0
  393. package/deps/librdkafka/src/rdrand.h +43 -0
  394. package/deps/librdkafka/src/rdregex.c +156 -0
  395. package/deps/librdkafka/src/rdregex.h +43 -0
  396. package/deps/librdkafka/src/rdsignal.h +57 -0
  397. package/deps/librdkafka/src/rdstring.c +645 -0
  398. package/deps/librdkafka/src/rdstring.h +98 -0
  399. package/deps/librdkafka/src/rdsysqueue.h +404 -0
  400. package/deps/librdkafka/src/rdtime.h +356 -0
  401. package/deps/librdkafka/src/rdtypes.h +86 -0
  402. package/deps/librdkafka/src/rdunittest.c +549 -0
  403. package/deps/librdkafka/src/rdunittest.h +232 -0
  404. package/deps/librdkafka/src/rdvarint.c +134 -0
  405. package/deps/librdkafka/src/rdvarint.h +165 -0
  406. package/deps/librdkafka/src/rdwin32.h +382 -0
  407. package/deps/librdkafka/src/rdxxhash.c +1030 -0
  408. package/deps/librdkafka/src/rdxxhash.h +328 -0
  409. package/deps/librdkafka/src/regexp.c +1352 -0
  410. package/deps/librdkafka/src/regexp.h +41 -0
  411. package/deps/librdkafka/src/snappy.c +1866 -0
  412. package/deps/librdkafka/src/snappy.h +62 -0
  413. package/deps/librdkafka/src/snappy_compat.h +138 -0
  414. package/deps/librdkafka/src/statistics_schema.json +444 -0
  415. package/deps/librdkafka/src/tinycthread.c +932 -0
  416. package/deps/librdkafka/src/tinycthread.h +503 -0
  417. package/deps/librdkafka/src/tinycthread_extra.c +199 -0
  418. package/deps/librdkafka/src/tinycthread_extra.h +212 -0
  419. package/deps/librdkafka/src/win32_config.h +58 -0
  420. package/deps/librdkafka/src-cpp/CMakeLists.txt +90 -0
  421. package/deps/librdkafka/src-cpp/ConfImpl.cpp +84 -0
  422. package/deps/librdkafka/src-cpp/ConsumerImpl.cpp +244 -0
  423. package/deps/librdkafka/src-cpp/HandleImpl.cpp +436 -0
  424. package/deps/librdkafka/src-cpp/HeadersImpl.cpp +48 -0
  425. package/deps/librdkafka/src-cpp/KafkaConsumerImpl.cpp +296 -0
  426. package/deps/librdkafka/src-cpp/Makefile +55 -0
  427. package/deps/librdkafka/src-cpp/MessageImpl.cpp +38 -0
  428. package/deps/librdkafka/src-cpp/MetadataImpl.cpp +170 -0
  429. package/deps/librdkafka/src-cpp/ProducerImpl.cpp +197 -0
  430. package/deps/librdkafka/src-cpp/QueueImpl.cpp +70 -0
  431. package/deps/librdkafka/src-cpp/README.md +16 -0
  432. package/deps/librdkafka/src-cpp/RdKafka.cpp +59 -0
  433. package/deps/librdkafka/src-cpp/TopicImpl.cpp +124 -0
  434. package/deps/librdkafka/src-cpp/TopicPartitionImpl.cpp +57 -0
  435. package/deps/librdkafka/src-cpp/rdkafkacpp.h +3797 -0
  436. package/deps/librdkafka/src-cpp/rdkafkacpp_int.h +1641 -0
  437. package/deps/librdkafka/tests/0000-unittests.c +72 -0
  438. package/deps/librdkafka/tests/0001-multiobj.c +102 -0
  439. package/deps/librdkafka/tests/0002-unkpart.c +244 -0
  440. package/deps/librdkafka/tests/0003-msgmaxsize.c +173 -0
  441. package/deps/librdkafka/tests/0004-conf.c +934 -0
  442. package/deps/librdkafka/tests/0005-order.c +133 -0
  443. package/deps/librdkafka/tests/0006-symbols.c +163 -0
  444. package/deps/librdkafka/tests/0007-autotopic.c +136 -0
  445. package/deps/librdkafka/tests/0008-reqacks.c +179 -0
  446. package/deps/librdkafka/tests/0009-mock_cluster.c +97 -0
  447. package/deps/librdkafka/tests/0011-produce_batch.c +753 -0
  448. package/deps/librdkafka/tests/0012-produce_consume.c +537 -0
  449. package/deps/librdkafka/tests/0013-null-msgs.c +473 -0
  450. package/deps/librdkafka/tests/0014-reconsume-191.c +512 -0
  451. package/deps/librdkafka/tests/0015-offset_seeks.c +172 -0
  452. package/deps/librdkafka/tests/0016-client_swname.c +181 -0
  453. package/deps/librdkafka/tests/0017-compression.c +140 -0
  454. package/deps/librdkafka/tests/0018-cgrp_term.c +338 -0
  455. package/deps/librdkafka/tests/0019-list_groups.c +289 -0
  456. package/deps/librdkafka/tests/0020-destroy_hang.c +162 -0
  457. package/deps/librdkafka/tests/0021-rkt_destroy.c +72 -0
  458. package/deps/librdkafka/tests/0022-consume_batch.c +279 -0
  459. package/deps/librdkafka/tests/0025-timers.c +147 -0
  460. package/deps/librdkafka/tests/0026-consume_pause.c +547 -0
  461. package/deps/librdkafka/tests/0028-long_topicnames.c +79 -0
  462. package/deps/librdkafka/tests/0029-assign_offset.c +202 -0
  463. package/deps/librdkafka/tests/0030-offset_commit.c +589 -0
  464. package/deps/librdkafka/tests/0031-get_offsets.c +235 -0
  465. package/deps/librdkafka/tests/0033-regex_subscribe.c +536 -0
  466. package/deps/librdkafka/tests/0034-offset_reset.c +398 -0
  467. package/deps/librdkafka/tests/0035-api_version.c +73 -0
  468. package/deps/librdkafka/tests/0036-partial_fetch.c +87 -0
  469. package/deps/librdkafka/tests/0037-destroy_hang_local.c +85 -0
  470. package/deps/librdkafka/tests/0038-performance.c +121 -0
  471. package/deps/librdkafka/tests/0039-event.c +284 -0
  472. package/deps/librdkafka/tests/0040-io_event.c +257 -0
  473. package/deps/librdkafka/tests/0041-fetch_max_bytes.c +97 -0
  474. package/deps/librdkafka/tests/0042-many_topics.c +252 -0
  475. package/deps/librdkafka/tests/0043-no_connection.c +77 -0
  476. package/deps/librdkafka/tests/0044-partition_cnt.c +94 -0
  477. package/deps/librdkafka/tests/0045-subscribe_update.c +1010 -0
  478. package/deps/librdkafka/tests/0046-rkt_cache.c +65 -0
  479. package/deps/librdkafka/tests/0047-partial_buf_tmout.c +98 -0
  480. package/deps/librdkafka/tests/0048-partitioner.c +283 -0
  481. package/deps/librdkafka/tests/0049-consume_conn_close.c +162 -0
  482. package/deps/librdkafka/tests/0050-subscribe_adds.c +145 -0
  483. package/deps/librdkafka/tests/0051-assign_adds.c +126 -0
  484. package/deps/librdkafka/tests/0052-msg_timestamps.c +238 -0
  485. package/deps/librdkafka/tests/0053-stats_cb.cpp +527 -0
  486. package/deps/librdkafka/tests/0054-offset_time.cpp +236 -0
  487. package/deps/librdkafka/tests/0055-producer_latency.c +539 -0
  488. package/deps/librdkafka/tests/0056-balanced_group_mt.c +315 -0
  489. package/deps/librdkafka/tests/0057-invalid_topic.cpp +112 -0
  490. package/deps/librdkafka/tests/0058-log.cpp +123 -0
  491. package/deps/librdkafka/tests/0059-bsearch.cpp +241 -0
  492. package/deps/librdkafka/tests/0060-op_prio.cpp +163 -0
  493. package/deps/librdkafka/tests/0061-consumer_lag.cpp +295 -0
  494. package/deps/librdkafka/tests/0062-stats_event.c +126 -0
  495. package/deps/librdkafka/tests/0063-clusterid.cpp +180 -0
  496. package/deps/librdkafka/tests/0064-interceptors.c +481 -0
  497. package/deps/librdkafka/tests/0065-yield.cpp +140 -0
  498. package/deps/librdkafka/tests/0066-plugins.cpp +129 -0
  499. package/deps/librdkafka/tests/0067-empty_topic.cpp +151 -0
  500. package/deps/librdkafka/tests/0068-produce_timeout.c +136 -0
  501. package/deps/librdkafka/tests/0069-consumer_add_parts.c +119 -0
  502. package/deps/librdkafka/tests/0070-null_empty.cpp +197 -0
  503. package/deps/librdkafka/tests/0072-headers_ut.c +448 -0
  504. package/deps/librdkafka/tests/0073-headers.c +381 -0
  505. package/deps/librdkafka/tests/0074-producev.c +87 -0
  506. package/deps/librdkafka/tests/0075-retry.c +290 -0
  507. package/deps/librdkafka/tests/0076-produce_retry.c +452 -0
  508. package/deps/librdkafka/tests/0077-compaction.c +363 -0
  509. package/deps/librdkafka/tests/0078-c_from_cpp.cpp +96 -0
  510. package/deps/librdkafka/tests/0079-fork.c +93 -0
  511. package/deps/librdkafka/tests/0080-admin_ut.c +3095 -0
  512. package/deps/librdkafka/tests/0081-admin.c +5633 -0
  513. package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +137 -0
  514. package/deps/librdkafka/tests/0083-cb_event.c +233 -0
  515. package/deps/librdkafka/tests/0084-destroy_flags.c +208 -0
  516. package/deps/librdkafka/tests/0085-headers.cpp +392 -0
  517. package/deps/librdkafka/tests/0086-purge.c +368 -0
  518. package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +162 -0
  519. package/deps/librdkafka/tests/0089-max_poll_interval.c +511 -0
  520. package/deps/librdkafka/tests/0090-idempotence.c +171 -0
  521. package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +295 -0
  522. package/deps/librdkafka/tests/0092-mixed_msgver.c +103 -0
  523. package/deps/librdkafka/tests/0093-holb.c +200 -0
  524. package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +231 -0
  525. package/deps/librdkafka/tests/0095-all_brokers_down.cpp +122 -0
  526. package/deps/librdkafka/tests/0097-ssl_verify.cpp +658 -0
  527. package/deps/librdkafka/tests/0098-consumer-txn.cpp +1218 -0
  528. package/deps/librdkafka/tests/0099-commit_metadata.c +194 -0
  529. package/deps/librdkafka/tests/0100-thread_interceptors.cpp +195 -0
  530. package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +446 -0
  531. package/deps/librdkafka/tests/0102-static_group_rebalance.c +836 -0
  532. package/deps/librdkafka/tests/0103-transactions.c +1383 -0
  533. package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +625 -0
  534. package/deps/librdkafka/tests/0105-transactions_mock.c +3930 -0
  535. package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +318 -0
  536. package/deps/librdkafka/tests/0107-topic_recreate.c +259 -0
  537. package/deps/librdkafka/tests/0109-auto_create_topics.cpp +278 -0
  538. package/deps/librdkafka/tests/0110-batch_size.cpp +182 -0
  539. package/deps/librdkafka/tests/0111-delay_create_topics.cpp +127 -0
  540. package/deps/librdkafka/tests/0112-assign_unknown_part.c +87 -0
  541. package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +3473 -0
  542. package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +176 -0
  543. package/deps/librdkafka/tests/0115-producer_auth.cpp +182 -0
  544. package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +216 -0
  545. package/deps/librdkafka/tests/0117-mock_errors.c +331 -0
  546. package/deps/librdkafka/tests/0118-commit_rebalance.c +154 -0
  547. package/deps/librdkafka/tests/0119-consumer_auth.cpp +167 -0
  548. package/deps/librdkafka/tests/0120-asymmetric_subscription.c +185 -0
  549. package/deps/librdkafka/tests/0121-clusterid.c +115 -0
  550. package/deps/librdkafka/tests/0122-buffer_cleaning_after_rebalance.c +227 -0
  551. package/deps/librdkafka/tests/0123-connections_max_idle.c +98 -0
  552. package/deps/librdkafka/tests/0124-openssl_invalid_engine.c +69 -0
  553. package/deps/librdkafka/tests/0125-immediate_flush.c +144 -0
  554. package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +528 -0
  555. package/deps/librdkafka/tests/0127-fetch_queue_backoff.cpp +165 -0
  556. package/deps/librdkafka/tests/0128-sasl_callback_queue.cpp +125 -0
  557. package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +79 -0
  558. package/deps/librdkafka/tests/0130-store_offsets.c +178 -0
  559. package/deps/librdkafka/tests/0131-connect_timeout.c +81 -0
  560. package/deps/librdkafka/tests/0132-strategy_ordering.c +179 -0
  561. package/deps/librdkafka/tests/0133-ssl_keys.c +150 -0
  562. package/deps/librdkafka/tests/0134-ssl_provider.c +92 -0
  563. package/deps/librdkafka/tests/0135-sasl_credentials.cpp +143 -0
  564. package/deps/librdkafka/tests/0136-resolve_cb.c +181 -0
  565. package/deps/librdkafka/tests/0137-barrier_batch_consume.c +619 -0
  566. package/deps/librdkafka/tests/0138-admin_mock.c +281 -0
  567. package/deps/librdkafka/tests/0139-offset_validation_mock.c +950 -0
  568. package/deps/librdkafka/tests/0140-commit_metadata.cpp +108 -0
  569. package/deps/librdkafka/tests/0142-reauthentication.c +515 -0
  570. package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +552 -0
  571. package/deps/librdkafka/tests/0144-idempotence_mock.c +373 -0
  572. package/deps/librdkafka/tests/0145-pause_resume_mock.c +119 -0
  573. package/deps/librdkafka/tests/0146-metadata_mock.c +505 -0
  574. package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +952 -0
  575. package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +563 -0
  576. package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
  577. package/deps/librdkafka/tests/0150-telemetry_mock.c +651 -0
  578. package/deps/librdkafka/tests/0151-purge-brokers.c +566 -0
  579. package/deps/librdkafka/tests/0152-rebootstrap.c +59 -0
  580. package/deps/librdkafka/tests/0153-memberid.c +128 -0
  581. package/deps/librdkafka/tests/1000-unktopic.c +164 -0
  582. package/deps/librdkafka/tests/8000-idle.cpp +60 -0
  583. package/deps/librdkafka/tests/8001-fetch_from_follower_mock_manual.c +113 -0
  584. package/deps/librdkafka/tests/CMakeLists.txt +170 -0
  585. package/deps/librdkafka/tests/LibrdkafkaTestApp.py +291 -0
  586. package/deps/librdkafka/tests/Makefile +182 -0
  587. package/deps/librdkafka/tests/README.md +509 -0
  588. package/deps/librdkafka/tests/autotest.sh +33 -0
  589. package/deps/librdkafka/tests/backtrace.gdb +30 -0
  590. package/deps/librdkafka/tests/broker_version_tests.py +315 -0
  591. package/deps/librdkafka/tests/buildbox.sh +17 -0
  592. package/deps/librdkafka/tests/cleanup-checker-tests.sh +20 -0
  593. package/deps/librdkafka/tests/cluster_testing.py +191 -0
  594. package/deps/librdkafka/tests/delete-test-topics.sh +56 -0
  595. package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
  596. package/deps/librdkafka/tests/fixtures/ssl/Makefile +8 -0
  597. package/deps/librdkafka/tests/fixtures/ssl/README.md +13 -0
  598. package/deps/librdkafka/tests/fixtures/ssl/client.keystore.intermediate.p12 +0 -0
  599. package/deps/librdkafka/tests/fixtures/ssl/client.keystore.p12 +0 -0
  600. package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.intermediate.pem +72 -0
  601. package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.pem +50 -0
  602. package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
  603. package/deps/librdkafka/tests/fixtures/ssl/client2.key +46 -0
  604. package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +168 -0
  605. package/deps/librdkafka/tests/fuzzers/Makefile +12 -0
  606. package/deps/librdkafka/tests/fuzzers/README.md +31 -0
  607. package/deps/librdkafka/tests/fuzzers/fuzz_regex.c +74 -0
  608. package/deps/librdkafka/tests/fuzzers/helpers.h +90 -0
  609. package/deps/librdkafka/tests/gen-ssl-certs.sh +165 -0
  610. package/deps/librdkafka/tests/interactive_broker_version.py +170 -0
  611. package/deps/librdkafka/tests/interceptor_test/CMakeLists.txt +16 -0
  612. package/deps/librdkafka/tests/interceptor_test/Makefile +22 -0
  613. package/deps/librdkafka/tests/interceptor_test/interceptor_test.c +314 -0
  614. package/deps/librdkafka/tests/interceptor_test/interceptor_test.h +54 -0
  615. package/deps/librdkafka/tests/java/IncrementalRebalanceCli.java +97 -0
  616. package/deps/librdkafka/tests/java/Makefile +13 -0
  617. package/deps/librdkafka/tests/java/Murmur2Cli.java +46 -0
  618. package/deps/librdkafka/tests/java/README.md +14 -0
  619. package/deps/librdkafka/tests/java/TransactionProducerCli.java +162 -0
  620. package/deps/librdkafka/tests/java/run-class.sh +11 -0
  621. package/deps/librdkafka/tests/librdkafka.suppressions +483 -0
  622. package/deps/librdkafka/tests/lz4_manual_test.sh +59 -0
  623. package/deps/librdkafka/tests/multi-broker-version-test.sh +50 -0
  624. package/deps/librdkafka/tests/parse-refcnt.sh +43 -0
  625. package/deps/librdkafka/tests/performance_plot.py +115 -0
  626. package/deps/librdkafka/tests/plugin_test/Makefile +19 -0
  627. package/deps/librdkafka/tests/plugin_test/plugin_test.c +58 -0
  628. package/deps/librdkafka/tests/requirements.txt +2 -0
  629. package/deps/librdkafka/tests/run-all-tests.sh +79 -0
  630. package/deps/librdkafka/tests/run-consumer-tests.sh +16 -0
  631. package/deps/librdkafka/tests/run-producer-tests.sh +16 -0
  632. package/deps/librdkafka/tests/run-test-batches.py +157 -0
  633. package/deps/librdkafka/tests/run-test.sh +140 -0
  634. package/deps/librdkafka/tests/rusage.c +249 -0
  635. package/deps/librdkafka/tests/sasl_test.py +289 -0
  636. package/deps/librdkafka/tests/scenarios/README.md +6 -0
  637. package/deps/librdkafka/tests/scenarios/ak23.json +6 -0
  638. package/deps/librdkafka/tests/scenarios/default.json +5 -0
  639. package/deps/librdkafka/tests/scenarios/noautocreate.json +5 -0
  640. package/deps/librdkafka/tests/sockem.c +801 -0
  641. package/deps/librdkafka/tests/sockem.h +85 -0
  642. package/deps/librdkafka/tests/sockem_ctrl.c +145 -0
  643. package/deps/librdkafka/tests/sockem_ctrl.h +61 -0
  644. package/deps/librdkafka/tests/test.c +7778 -0
  645. package/deps/librdkafka/tests/test.conf.example +27 -0
  646. package/deps/librdkafka/tests/test.h +1028 -0
  647. package/deps/librdkafka/tests/testcpp.cpp +131 -0
  648. package/deps/librdkafka/tests/testcpp.h +388 -0
  649. package/deps/librdkafka/tests/testshared.h +416 -0
  650. package/deps/librdkafka/tests/tools/README.md +4 -0
  651. package/deps/librdkafka/tests/tools/stats/README.md +21 -0
  652. package/deps/librdkafka/tests/tools/stats/filter.jq +42 -0
  653. package/deps/librdkafka/tests/tools/stats/graph.py +150 -0
  654. package/deps/librdkafka/tests/tools/stats/requirements.txt +3 -0
  655. package/deps/librdkafka/tests/tools/stats/to_csv.py +124 -0
  656. package/deps/librdkafka/tests/trivup/trivup-0.14.0.tar.gz +0 -0
  657. package/deps/librdkafka/tests/until-fail.sh +87 -0
  658. package/deps/librdkafka/tests/xxxx-assign_partition.c +122 -0
  659. package/deps/librdkafka/tests/xxxx-metadata.cpp +159 -0
  660. package/deps/librdkafka/vcpkg.json +23 -0
  661. package/deps/librdkafka/win32/README.md +5 -0
  662. package/deps/librdkafka/win32/build-package.bat +3 -0
  663. package/deps/librdkafka/win32/build.bat +19 -0
  664. package/deps/librdkafka/win32/common.vcxproj +84 -0
  665. package/deps/librdkafka/win32/interceptor_test/interceptor_test.vcxproj +87 -0
  666. package/deps/librdkafka/win32/librdkafka.autopkg.template +54 -0
  667. package/deps/librdkafka/win32/librdkafka.master.testing.targets +13 -0
  668. package/deps/librdkafka/win32/librdkafka.sln +226 -0
  669. package/deps/librdkafka/win32/librdkafka.vcxproj +276 -0
  670. package/deps/librdkafka/win32/librdkafkacpp/librdkafkacpp.vcxproj +104 -0
  671. package/deps/librdkafka/win32/msbuild.ps1 +15 -0
  672. package/deps/librdkafka/win32/openssl_engine_example/openssl_engine_example.vcxproj +132 -0
  673. package/deps/librdkafka/win32/package-zip.ps1 +46 -0
  674. package/deps/librdkafka/win32/packages/repositories.config +4 -0
  675. package/deps/librdkafka/win32/push-package.bat +4 -0
  676. package/deps/librdkafka/win32/rdkafka_complex_consumer_example_cpp/rdkafka_complex_consumer_example_cpp.vcxproj +67 -0
  677. package/deps/librdkafka/win32/rdkafka_example/rdkafka_example.vcxproj +97 -0
  678. package/deps/librdkafka/win32/rdkafka_performance/rdkafka_performance.vcxproj +97 -0
  679. package/deps/librdkafka/win32/setup-msys2.ps1 +47 -0
  680. package/deps/librdkafka/win32/setup-vcpkg.ps1 +34 -0
  681. package/deps/librdkafka/win32/tests/test.conf.example +25 -0
  682. package/deps/librdkafka/win32/tests/tests.vcxproj +253 -0
  683. package/deps/librdkafka/win32/win_ssl_cert_store/win_ssl_cert_store.vcxproj +132 -0
  684. package/deps/librdkafka/win32/wingetopt.c +564 -0
  685. package/deps/librdkafka/win32/wingetopt.h +101 -0
  686. package/deps/librdkafka/win32/wintime.h +33 -0
  687. package/deps/librdkafka.gyp +62 -0
  688. package/lib/admin.js +233 -0
  689. package/lib/client.js +573 -0
  690. package/lib/error.js +500 -0
  691. package/lib/index.js +34 -0
  692. package/lib/kafka-consumer-stream.js +397 -0
  693. package/lib/kafka-consumer.js +698 -0
  694. package/lib/producer/high-level-producer.js +323 -0
  695. package/lib/producer-stream.js +307 -0
  696. package/lib/producer.js +375 -0
  697. package/lib/tools/ref-counter.js +52 -0
  698. package/lib/topic-partition.js +88 -0
  699. package/lib/topic.js +42 -0
  700. package/lib/util.js +29 -0
  701. package/package.json +61 -0
  702. package/prebuilds/darwin-arm64/@point3+node-rdkafka.node +0 -0
  703. package/prebuilds/linux-x64/@point3+node-rdkafka.node +0 -0
  704. package/util/configure.js +30 -0
  705. package/util/get-env.js +6 -0
  706. package/util/test-compile.js +11 -0
  707. 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
+ }