@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,1786 @@
1
+ /*
2
+ * librdkafka - The Apache Kafka C/C++ library
3
+ *
4
+ * Copyright (c) 2015-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
+ #include "rdkafka_int.h"
30
+ #include "rdkafka_assignor.h"
31
+ #include "rdkafka_request.h"
32
+ #include "rdunittest.h"
33
+
34
+ #include <ctype.h>
35
+
36
+ /**
37
+ * Clear out and free any memory used by the member, but not the rkgm itself.
38
+ */
39
+ void rd_kafka_group_member_clear(rd_kafka_group_member_t *rkgm) {
40
+ if (rkgm->rkgm_owned)
41
+ rd_kafka_topic_partition_list_destroy(rkgm->rkgm_owned);
42
+
43
+ if (rkgm->rkgm_subscription)
44
+ rd_kafka_topic_partition_list_destroy(rkgm->rkgm_subscription);
45
+
46
+ if (rkgm->rkgm_assignment)
47
+ rd_kafka_topic_partition_list_destroy(rkgm->rkgm_assignment);
48
+
49
+ rd_list_destroy(&rkgm->rkgm_eligible);
50
+
51
+ if (rkgm->rkgm_member_id)
52
+ rd_kafkap_str_destroy(rkgm->rkgm_member_id);
53
+
54
+ if (rkgm->rkgm_group_instance_id)
55
+ rd_kafkap_str_destroy(rkgm->rkgm_group_instance_id);
56
+
57
+ if (rkgm->rkgm_userdata)
58
+ rd_kafkap_bytes_destroy(rkgm->rkgm_userdata);
59
+
60
+ if (rkgm->rkgm_member_metadata)
61
+ rd_kafkap_bytes_destroy(rkgm->rkgm_member_metadata);
62
+
63
+ if (rkgm->rkgm_rack_id)
64
+ rd_kafkap_str_destroy(rkgm->rkgm_rack_id);
65
+
66
+ memset(rkgm, 0, sizeof(*rkgm));
67
+ }
68
+
69
+
70
+ /**
71
+ * @brief Group member comparator (takes rd_kafka_group_member_t *)
72
+ */
73
+ int rd_kafka_group_member_cmp(const void *_a, const void *_b) {
74
+ const rd_kafka_group_member_t *a = (const rd_kafka_group_member_t *)_a;
75
+ const rd_kafka_group_member_t *b = (const rd_kafka_group_member_t *)_b;
76
+
77
+ /* Use the group instance id to compare static group members */
78
+ if (!RD_KAFKAP_STR_IS_NULL(a->rkgm_group_instance_id) &&
79
+ !RD_KAFKAP_STR_IS_NULL(b->rkgm_group_instance_id))
80
+ return rd_kafkap_str_cmp(a->rkgm_group_instance_id,
81
+ b->rkgm_group_instance_id);
82
+
83
+ return rd_kafkap_str_cmp(a->rkgm_member_id, b->rkgm_member_id);
84
+ }
85
+
86
+
87
+ /**
88
+ * Returns true if member subscribes to topic, else false.
89
+ */
90
+ int rd_kafka_group_member_find_subscription(rd_kafka_t *rk,
91
+ const rd_kafka_group_member_t *rkgm,
92
+ const char *topic) {
93
+ int i;
94
+
95
+ /* Match against member's subscription. */
96
+ for (i = 0; i < rkgm->rkgm_subscription->cnt; i++) {
97
+ const rd_kafka_topic_partition_t *rktpar =
98
+ &rkgm->rkgm_subscription->elems[i];
99
+
100
+ if (rd_kafka_topic_partition_match(rk, rkgm, rktpar, topic,
101
+ NULL))
102
+ return 1;
103
+ }
104
+
105
+ return 0;
106
+ }
107
+
108
+
109
+ rd_kafkap_bytes_t *rd_kafka_consumer_protocol_member_metadata_new(
110
+ const rd_list_t *topics,
111
+ const void *userdata,
112
+ size_t userdata_size,
113
+ const rd_kafka_topic_partition_list_t *owned_partitions,
114
+ int generation,
115
+ const rd_kafkap_str_t *rack_id) {
116
+
117
+ rd_kafka_buf_t *rkbuf;
118
+ rd_kafkap_bytes_t *kbytes;
119
+ int i;
120
+ int topic_cnt = rd_list_cnt(topics);
121
+ const rd_kafka_topic_info_t *tinfo;
122
+ size_t len;
123
+
124
+ /*
125
+ * MemberMetadata => Version Subscription AssignmentStrategies
126
+ * Version => int16
127
+ * Subscription => Topics UserData
128
+ * Topics => [String]
129
+ * UserData => Bytes
130
+ * OwnedPartitions => [Topic Partitions] // added in v1
131
+ * Topic => string
132
+ * Partitions => [int32]
133
+ * GenerationId => int32 // added in v2
134
+ * RackId => string // added in v3
135
+ */
136
+
137
+ rkbuf = rd_kafka_buf_new(1, 100 + (topic_cnt * 100) + userdata_size);
138
+
139
+ /* Version */
140
+ rd_kafka_buf_write_i16(rkbuf, 3);
141
+ rd_kafka_buf_write_i32(rkbuf, topic_cnt);
142
+ RD_LIST_FOREACH(tinfo, topics, i)
143
+ rd_kafka_buf_write_str(rkbuf, tinfo->topic, -1);
144
+ if (userdata)
145
+ rd_kafka_buf_write_bytes(rkbuf, userdata, userdata_size);
146
+ else /* Kafka 0.9.0.0 can't parse NULL bytes, so we provide empty,
147
+ * which is compatible with all of the built-in Java client
148
+ * assignors at the present time (up to and including v2.5) */
149
+ rd_kafka_buf_write_bytes(rkbuf, "", 0);
150
+ /* Following data is ignored by v0 consumers */
151
+ if (!owned_partitions)
152
+ /* If there are no owned partitions, this is specified as an
153
+ * empty array, not NULL. */
154
+ rd_kafka_buf_write_i32(rkbuf, 0); /* Topic count */
155
+ else {
156
+ const rd_kafka_topic_partition_field_t fields[] = {
157
+ RD_KAFKA_TOPIC_PARTITION_FIELD_PARTITION,
158
+ RD_KAFKA_TOPIC_PARTITION_FIELD_END};
159
+ rd_kafka_buf_write_topic_partitions(
160
+ rkbuf, owned_partitions,
161
+ rd_false /*don't skip invalid offsets*/,
162
+ rd_false /*any offset*/, rd_false /*don't use topic id*/,
163
+ rd_true /*use topic name*/, fields);
164
+ }
165
+
166
+ /* Following data is ignored by consumer version < 2 */
167
+ rd_kafka_buf_write_i32(rkbuf, generation);
168
+
169
+ /* Following data is ignored by consumer version < 3 */
170
+ rd_kafka_buf_write_kstr(rkbuf, rack_id);
171
+
172
+ /* Get binary buffer and allocate a new Kafka Bytes with a copy. */
173
+ rd_slice_init_full(&rkbuf->rkbuf_reader, &rkbuf->rkbuf_buf);
174
+ len = rd_slice_remains(&rkbuf->rkbuf_reader);
175
+ kbytes = rd_kafkap_bytes_new(NULL, (int32_t)len);
176
+ rd_slice_read(&rkbuf->rkbuf_reader, (void *)kbytes->data, len);
177
+ rd_kafka_buf_destroy(rkbuf);
178
+
179
+ return kbytes;
180
+ }
181
+
182
+
183
+
184
+ rd_kafkap_bytes_t *rd_kafka_assignor_get_metadata_with_empty_userdata(
185
+ const rd_kafka_assignor_t *rkas,
186
+ void *assignor_state,
187
+ const rd_list_t *topics,
188
+ const rd_kafka_topic_partition_list_t *owned_partitions,
189
+ const rd_kafkap_str_t *rack_id) {
190
+ /* Generation was earlier populated inside userData, and older versions
191
+ * of clients still expect that. So, in case the userData is empty, we
192
+ * set the explicit generation field to the default value, -1 */
193
+ return rd_kafka_consumer_protocol_member_metadata_new(
194
+ topics, NULL, 0, owned_partitions, -1 /* generation */, rack_id);
195
+ }
196
+
197
+
198
+
199
+ /**
200
+ * Returns 1 if all subscriptions are satifised for this member, else 0.
201
+ */
202
+ static int rd_kafka_member_subscription_match(
203
+ rd_kafka_cgrp_t *rkcg,
204
+ rd_kafka_group_member_t *rkgm,
205
+ const rd_kafka_metadata_topic_t *topic_metadata,
206
+ rd_kafka_assignor_topic_t *eligible_topic) {
207
+ int i;
208
+ int has_regex = 0;
209
+ int matched = 0;
210
+
211
+ /* Match against member's subscription. */
212
+ for (i = 0; i < rkgm->rkgm_subscription->cnt; i++) {
213
+ const rd_kafka_topic_partition_t *rktpar =
214
+ &rkgm->rkgm_subscription->elems[i];
215
+ int matched_by_regex = 0;
216
+
217
+ if (rd_kafka_topic_partition_match(rkcg->rkcg_rk, rkgm, rktpar,
218
+ topic_metadata->topic,
219
+ &matched_by_regex)) {
220
+ rd_list_add(&rkgm->rkgm_eligible,
221
+ (void *)topic_metadata);
222
+ matched++;
223
+ has_regex += matched_by_regex;
224
+ }
225
+ }
226
+
227
+ if (matched)
228
+ rd_list_add(&eligible_topic->members, rkgm);
229
+
230
+ if (!has_regex &&
231
+ rd_list_cnt(&rkgm->rkgm_eligible) == rkgm->rkgm_subscription->cnt)
232
+ return 1; /* All subscriptions matched */
233
+ else
234
+ return 0;
235
+ }
236
+
237
+
238
+ static void rd_kafka_assignor_topic_destroy(rd_kafka_assignor_topic_t *at) {
239
+ rd_list_destroy(&at->members);
240
+ rd_free(at);
241
+ }
242
+
243
+ int rd_kafka_assignor_topic_cmp(const void *_a, const void *_b) {
244
+ const rd_kafka_assignor_topic_t *a =
245
+ *(const rd_kafka_assignor_topic_t *const *)_a;
246
+ const rd_kafka_assignor_topic_t *b =
247
+ *(const rd_kafka_assignor_topic_t *const *)_b;
248
+
249
+ return strcmp(a->metadata->topic, b->metadata->topic);
250
+ }
251
+
252
+ /**
253
+ * Determine the complete set of topics that match at least one of
254
+ * the group member subscriptions. Associate with each of these the
255
+ * complete set of members that are subscribed to it. The result is
256
+ * returned in `eligible_topics`.
257
+ */
258
+ static void
259
+ rd_kafka_member_subscriptions_map(rd_kafka_cgrp_t *rkcg,
260
+ rd_list_t *eligible_topics,
261
+ const rd_kafka_metadata_t *metadata,
262
+ rd_kafka_group_member_t *members,
263
+ int member_cnt) {
264
+ int ti;
265
+ rd_kafka_assignor_topic_t *eligible_topic = NULL;
266
+ rd_kafka_metadata_internal_t *mdi =
267
+ rd_kafka_metadata_get_internal(metadata);
268
+
269
+ rd_list_init(eligible_topics, RD_MIN(metadata->topic_cnt, 10),
270
+ (void *)rd_kafka_assignor_topic_destroy);
271
+
272
+ /* For each topic in the cluster, scan through the member list
273
+ * to find matching subscriptions. */
274
+ for (ti = 0; ti < metadata->topic_cnt; ti++) {
275
+ int i;
276
+
277
+ /* Ignore topics in blacklist */
278
+ if (rkcg->rkcg_rk->rk_conf.topic_blacklist &&
279
+ rd_kafka_pattern_match(
280
+ rkcg->rkcg_rk->rk_conf.topic_blacklist,
281
+ metadata->topics[ti].topic)) {
282
+ rd_kafka_dbg(rkcg->rkcg_rk,
283
+ TOPIC | RD_KAFKA_DBG_ASSIGNOR, "BLACKLIST",
284
+ "Assignor ignoring blacklisted "
285
+ "topic \"%s\"",
286
+ metadata->topics[ti].topic);
287
+ continue;
288
+ }
289
+
290
+ if (!eligible_topic)
291
+ eligible_topic = rd_calloc(1, sizeof(*eligible_topic));
292
+
293
+ rd_list_init(&eligible_topic->members, member_cnt, NULL);
294
+
295
+ /* For each member: scan through its topic subscription */
296
+ for (i = 0; i < member_cnt; i++) {
297
+ /* Match topic against existing metadata,
298
+ incl regex matching. */
299
+ rd_kafka_member_subscription_match(
300
+ rkcg, &members[i], &metadata->topics[ti],
301
+ eligible_topic);
302
+ }
303
+
304
+ if (rd_list_empty(&eligible_topic->members)) {
305
+ rd_list_destroy(&eligible_topic->members);
306
+ continue;
307
+ }
308
+
309
+ eligible_topic->metadata = &metadata->topics[ti];
310
+ eligible_topic->metadata_internal = &mdi->topics[ti];
311
+ rd_list_add(eligible_topics, eligible_topic);
312
+ eligible_topic = NULL;
313
+ }
314
+
315
+ if (eligible_topic)
316
+ rd_free(eligible_topic);
317
+ }
318
+
319
+
320
+ rd_kafka_resp_err_t rd_kafka_assignor_run(rd_kafka_cgrp_t *rkcg,
321
+ const rd_kafka_assignor_t *rkas,
322
+ rd_kafka_metadata_t *metadata,
323
+ rd_kafka_group_member_t *members,
324
+ int member_cnt,
325
+ char *errstr,
326
+ size_t errstr_size) {
327
+ rd_kafka_resp_err_t err;
328
+ rd_ts_t ts_start = rd_clock();
329
+ int i;
330
+ rd_list_t eligible_topics;
331
+ int j;
332
+
333
+ /* Construct eligible_topics, a map of:
334
+ * topic -> set of members that are subscribed to it. */
335
+ rd_kafka_member_subscriptions_map(rkcg, &eligible_topics, metadata,
336
+ members, member_cnt);
337
+
338
+
339
+ if (rkcg->rkcg_rk->rk_conf.debug &
340
+ (RD_KAFKA_DBG_CGRP | RD_KAFKA_DBG_ASSIGNOR)) {
341
+ rd_kafka_dbg(
342
+ rkcg->rkcg_rk, CGRP | RD_KAFKA_DBG_ASSIGNOR, "ASSIGN",
343
+ "Group \"%s\" running %s assignor for "
344
+ "%d member(s) and "
345
+ "%d eligible subscribed topic(s):",
346
+ rkcg->rkcg_group_id->str, rkas->rkas_protocol_name->str,
347
+ member_cnt, eligible_topics.rl_cnt);
348
+
349
+ for (i = 0; i < member_cnt; i++) {
350
+ const rd_kafka_group_member_t *member = &members[i];
351
+
352
+ rd_kafka_dbg(
353
+ rkcg->rkcg_rk, CGRP | RD_KAFKA_DBG_ASSIGNOR,
354
+ "ASSIGN",
355
+ " Member \"%.*s\"%s with "
356
+ "%d owned partition(s) and "
357
+ "%d subscribed topic(s):",
358
+ RD_KAFKAP_STR_PR(member->rkgm_member_id),
359
+ !rd_kafkap_str_cmp(member->rkgm_member_id,
360
+ rkcg->rkcg_member_id)
361
+ ? " (me)"
362
+ : "",
363
+ member->rkgm_owned ? member->rkgm_owned->cnt : 0,
364
+ member->rkgm_subscription->cnt);
365
+ for (j = 0; j < member->rkgm_subscription->cnt; j++) {
366
+ const rd_kafka_topic_partition_t *p =
367
+ &member->rkgm_subscription->elems[j];
368
+ rd_kafka_dbg(rkcg->rkcg_rk,
369
+ CGRP | RD_KAFKA_DBG_ASSIGNOR,
370
+ "ASSIGN", " %s [%" PRId32 "]",
371
+ p->topic, p->partition);
372
+ }
373
+ }
374
+ }
375
+
376
+ /* Call assignors assign callback */
377
+ err = rkas->rkas_assign_cb(
378
+ rkcg->rkcg_rk, rkas, rkcg->rkcg_member_id->str, metadata, members,
379
+ member_cnt, (rd_kafka_assignor_topic_t **)eligible_topics.rl_elems,
380
+ eligible_topics.rl_cnt, errstr, errstr_size, rkas->rkas_opaque);
381
+
382
+ if (err) {
383
+ rd_kafka_dbg(
384
+ rkcg->rkcg_rk, CGRP | RD_KAFKA_DBG_ASSIGNOR, "ASSIGN",
385
+ "Group \"%s\" %s assignment failed "
386
+ "for %d member(s): %s",
387
+ rkcg->rkcg_group_id->str, rkas->rkas_protocol_name->str,
388
+ (int)member_cnt, errstr);
389
+ } else if (rkcg->rkcg_rk->rk_conf.debug &
390
+ (RD_KAFKA_DBG_CGRP | RD_KAFKA_DBG_ASSIGNOR)) {
391
+ rd_kafka_dbg(
392
+ rkcg->rkcg_rk, CGRP | RD_KAFKA_DBG_ASSIGNOR, "ASSIGN",
393
+ "Group \"%s\" %s assignment for %d member(s) "
394
+ "finished in %.3fms:",
395
+ rkcg->rkcg_group_id->str, rkas->rkas_protocol_name->str,
396
+ (int)member_cnt, (float)(rd_clock() - ts_start) / 1000.0f);
397
+ for (i = 0; i < member_cnt; i++) {
398
+ const rd_kafka_group_member_t *member = &members[i];
399
+
400
+ rd_kafka_dbg(rkcg->rkcg_rk,
401
+ CGRP | RD_KAFKA_DBG_ASSIGNOR, "ASSIGN",
402
+ " Member \"%.*s\"%s assigned "
403
+ "%d partition(s):",
404
+ RD_KAFKAP_STR_PR(member->rkgm_member_id),
405
+ !rd_kafkap_str_cmp(member->rkgm_member_id,
406
+ rkcg->rkcg_member_id)
407
+ ? " (me)"
408
+ : "",
409
+ member->rkgm_assignment->cnt);
410
+ for (j = 0; j < member->rkgm_assignment->cnt; j++) {
411
+ const rd_kafka_topic_partition_t *p =
412
+ &member->rkgm_assignment->elems[j];
413
+ rd_kafka_dbg(rkcg->rkcg_rk,
414
+ CGRP | RD_KAFKA_DBG_ASSIGNOR,
415
+ "ASSIGN", " %s [%" PRId32 "]",
416
+ p->topic, p->partition);
417
+ }
418
+ }
419
+ }
420
+
421
+ rd_list_destroy(&eligible_topics);
422
+
423
+ return err;
424
+ }
425
+
426
+
427
+ /**
428
+ * Assignor protocol string comparator
429
+ */
430
+ static int rd_kafka_assignor_cmp_str(const void *_a, const void *_b) {
431
+ const char *a = _a;
432
+ const rd_kafka_assignor_t *b = _b;
433
+
434
+ return rd_kafkap_str_cmp_str2(a, b->rkas_protocol_name);
435
+ }
436
+
437
+ /**
438
+ * Find assignor by protocol name.
439
+ *
440
+ * Locality: any
441
+ * Locks: none
442
+ */
443
+ rd_kafka_assignor_t *rd_kafka_assignor_find(rd_kafka_t *rk,
444
+ const char *protocol) {
445
+ return (rd_kafka_assignor_t *)rd_list_find(
446
+ &rk->rk_conf.partition_assignors, protocol,
447
+ rd_kafka_assignor_cmp_str);
448
+ }
449
+
450
+
451
+ /**
452
+ * Destroys an assignor (but does not unlink).
453
+ */
454
+ static void rd_kafka_assignor_destroy(rd_kafka_assignor_t *rkas) {
455
+ rd_kafkap_str_destroy(rkas->rkas_protocol_type);
456
+ rd_kafkap_str_destroy(rkas->rkas_protocol_name);
457
+ rd_free(rkas);
458
+ }
459
+
460
+
461
+ /**
462
+ * @brief Check that the rebalance protocol of all enabled assignors is
463
+ * the same.
464
+ */
465
+ rd_kafka_resp_err_t
466
+ rd_kafka_assignor_rebalance_protocol_check(const rd_kafka_conf_t *conf) {
467
+ int i;
468
+ rd_kafka_assignor_t *rkas;
469
+ rd_kafka_rebalance_protocol_t rebalance_protocol =
470
+ RD_KAFKA_REBALANCE_PROTOCOL_NONE;
471
+
472
+ RD_LIST_FOREACH(rkas, &conf->partition_assignors, i) {
473
+ if (!rkas->rkas_enabled)
474
+ continue;
475
+
476
+ if (rebalance_protocol == RD_KAFKA_REBALANCE_PROTOCOL_NONE)
477
+ rebalance_protocol = rkas->rkas_protocol;
478
+ else if (rebalance_protocol != rkas->rkas_protocol)
479
+ return RD_KAFKA_RESP_ERR__CONFLICT;
480
+ }
481
+
482
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
483
+ }
484
+
485
+
486
+ /**
487
+ * @brief Add an assignor.
488
+ */
489
+ rd_kafka_resp_err_t rd_kafka_assignor_add(
490
+ rd_kafka_t *rk,
491
+ const char *protocol_type,
492
+ const char *protocol_name,
493
+ rd_kafka_rebalance_protocol_t rebalance_protocol,
494
+ rd_kafka_resp_err_t (*assign_cb)(
495
+ rd_kafka_t *rk,
496
+ const struct rd_kafka_assignor_s *rkas,
497
+ const char *member_id,
498
+ const rd_kafka_metadata_t *metadata,
499
+ rd_kafka_group_member_t *members,
500
+ size_t member_cnt,
501
+ rd_kafka_assignor_topic_t **eligible_topics,
502
+ size_t eligible_topic_cnt,
503
+ char *errstr,
504
+ size_t errstr_size,
505
+ void *opaque),
506
+ rd_kafkap_bytes_t *(*get_metadata_cb)(
507
+ const struct rd_kafka_assignor_s *rkas,
508
+ void *assignor_state,
509
+ const rd_list_t *topics,
510
+ const rd_kafka_topic_partition_list_t *owned_partitions,
511
+ const rd_kafkap_str_t *rack_id),
512
+ void (*on_assignment_cb)(const struct rd_kafka_assignor_s *rkas,
513
+ void **assignor_state,
514
+ const rd_kafka_topic_partition_list_t *assignment,
515
+ const rd_kafkap_bytes_t *userdata,
516
+ const rd_kafka_consumer_group_metadata_t *rkcgm),
517
+ void (*destroy_state_cb)(void *assignor_state),
518
+ int (*unittest_cb)(void),
519
+ void *opaque) {
520
+ rd_kafka_assignor_t *rkas;
521
+
522
+ if (rd_kafkap_str_cmp_str(rk->rk_conf.group_protocol_type,
523
+ protocol_type))
524
+ return RD_KAFKA_RESP_ERR__UNKNOWN_PROTOCOL;
525
+
526
+ if (rebalance_protocol != RD_KAFKA_REBALANCE_PROTOCOL_COOPERATIVE &&
527
+ rebalance_protocol != RD_KAFKA_REBALANCE_PROTOCOL_EAGER)
528
+ return RD_KAFKA_RESP_ERR__UNKNOWN_PROTOCOL;
529
+
530
+ /* Dont overwrite application assignors */
531
+ if ((rkas = rd_kafka_assignor_find(rk, protocol_name)))
532
+ return RD_KAFKA_RESP_ERR__CONFLICT;
533
+
534
+ rkas = rd_calloc(1, sizeof(*rkas));
535
+
536
+ rkas->rkas_protocol_name = rd_kafkap_str_new(protocol_name, -1);
537
+ rkas->rkas_protocol_type = rd_kafkap_str_new(protocol_type, -1);
538
+ rkas->rkas_protocol = rebalance_protocol;
539
+ rkas->rkas_assign_cb = assign_cb;
540
+ rkas->rkas_get_metadata_cb = get_metadata_cb;
541
+ rkas->rkas_on_assignment_cb = on_assignment_cb;
542
+ rkas->rkas_destroy_state_cb = destroy_state_cb;
543
+ rkas->rkas_unittest = unittest_cb;
544
+ rkas->rkas_opaque = opaque;
545
+ rkas->rkas_index = INT_MAX;
546
+
547
+ rd_list_add(&rk->rk_conf.partition_assignors, rkas);
548
+
549
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
550
+ }
551
+
552
+
553
+ /* Right trim string of whitespaces */
554
+ static void rtrim(char *s) {
555
+ char *e = s + strlen(s);
556
+
557
+ if (e == s)
558
+ return;
559
+
560
+ while (e >= s && isspace(*e))
561
+ e--;
562
+
563
+ *e = '\0';
564
+ }
565
+
566
+
567
+ static int rd_kafka_assignor_cmp_idx(const void *ptr1, const void *ptr2) {
568
+ const rd_kafka_assignor_t *rkas1 = (const rd_kafka_assignor_t *)ptr1;
569
+ const rd_kafka_assignor_t *rkas2 = (const rd_kafka_assignor_t *)ptr2;
570
+ return rkas1->rkas_index - rkas2->rkas_index;
571
+ }
572
+
573
+
574
+ /**
575
+ * Initialize assignor list based on configuration.
576
+ */
577
+ int rd_kafka_assignors_init(rd_kafka_t *rk, char *errstr, size_t errstr_size) {
578
+ char *wanted;
579
+ char *s;
580
+ int idx = 0;
581
+
582
+ rd_list_init(&rk->rk_conf.partition_assignors, 3,
583
+ (void *)rd_kafka_assignor_destroy);
584
+
585
+ /* Initialize builtin assignors (ignore errors) */
586
+ rd_kafka_range_assignor_init(rk);
587
+ rd_kafka_roundrobin_assignor_init(rk);
588
+ rd_kafka_sticky_assignor_init(rk);
589
+
590
+ rd_strdupa(&wanted, rk->rk_conf.partition_assignment_strategy);
591
+
592
+ s = wanted;
593
+ while (*s) {
594
+ rd_kafka_assignor_t *rkas = NULL;
595
+ char *t;
596
+
597
+ /* Left trim */
598
+ while (*s == ' ' || *s == ',')
599
+ s++;
600
+
601
+ if ((t = strchr(s, ','))) {
602
+ *t = '\0';
603
+ t++;
604
+ } else {
605
+ t = s + strlen(s);
606
+ }
607
+
608
+ /* Right trim */
609
+ rtrim(s);
610
+
611
+ rkas = rd_kafka_assignor_find(rk, s);
612
+ if (!rkas) {
613
+ rd_snprintf(errstr, errstr_size,
614
+ "Unsupported partition.assignment.strategy:"
615
+ " %s",
616
+ s);
617
+ return -1;
618
+ }
619
+
620
+ if (!rkas->rkas_enabled) {
621
+ rkas->rkas_enabled = 1;
622
+ rk->rk_conf.enabled_assignor_cnt++;
623
+ rkas->rkas_index = idx;
624
+ idx++;
625
+ }
626
+
627
+ s = t;
628
+ }
629
+
630
+ /* Sort the assignors according to the input strategy order
631
+ * since assignors will be scaned from the list sequentially
632
+ * and the strategies earlier in the list have higher priority. */
633
+ rd_list_sort(&rk->rk_conf.partition_assignors,
634
+ rd_kafka_assignor_cmp_idx);
635
+
636
+ /* Clear the SORTED flag because the list is sorted according to the
637
+ * rkas_index, but will do the search using rkas_protocol_name. */
638
+ rk->rk_conf.partition_assignors.rl_flags &= ~RD_LIST_F_SORTED;
639
+
640
+ if (rd_kafka_assignor_rebalance_protocol_check(&rk->rk_conf)) {
641
+ rd_snprintf(errstr, errstr_size,
642
+ "All partition.assignment.strategy (%s) assignors "
643
+ "must have the same protocol type, "
644
+ "online migration between assignors with "
645
+ "different protocol types is not supported",
646
+ rk->rk_conf.partition_assignment_strategy);
647
+ return -1;
648
+ }
649
+
650
+ return 0;
651
+ }
652
+
653
+
654
+
655
+ /**
656
+ * Free assignors
657
+ */
658
+ void rd_kafka_assignors_term(rd_kafka_t *rk) {
659
+ rd_list_destroy(&rk->rk_conf.partition_assignors);
660
+ }
661
+
662
+ /**
663
+ * @brief Computes whether rack-aware assignment needs to be used, or not.
664
+ */
665
+ rd_bool_t
666
+ rd_kafka_use_rack_aware_assignment(rd_kafka_assignor_topic_t **topics,
667
+ size_t topic_cnt,
668
+ const rd_kafka_metadata_internal_t *mdi) {
669
+ /* Computing needs_rack_aware_assignment requires the evaluation of
670
+ three criteria:
671
+
672
+ 1. At least one of the member has a non-null rack.
673
+ 2. At least one common rack exists between members and partitions.
674
+ 3. There is a partition which doesn't have replicas on all possible
675
+ racks, or in other words, all partitions don't have replicas on all
676
+ racks. Note that 'all racks' here means racks across all replicas of
677
+ all partitions, not including consumer racks. Also note that 'all
678
+ racks' are computed per-topic for range assignor, and across topics
679
+ for sticky assignor.
680
+ */
681
+
682
+ int i;
683
+ size_t t;
684
+ rd_kafka_group_member_t *member;
685
+ rd_list_t *all_consumer_racks = NULL; /* Contained Type: char* */
686
+ rd_list_t *all_partition_racks = NULL; /* Contained Type: char* */
687
+ char *rack_id = NULL;
688
+ rd_bool_t needs_rack_aware_assignment = rd_true; /* assume true */
689
+
690
+ /* Criteria 1 */
691
+ /* We don't copy racks, so the free function is NULL. */
692
+ all_consumer_racks = rd_list_new(0, NULL);
693
+
694
+ for (t = 0; t < topic_cnt; t++) {
695
+ RD_LIST_FOREACH(member, &topics[t]->members, i) {
696
+ if (member->rkgm_rack_id &&
697
+ RD_KAFKAP_STR_LEN(member->rkgm_rack_id)) {
698
+ /* Repetitions are fine, we will dedup it later.
699
+ */
700
+ rd_list_add(
701
+ all_consumer_racks,
702
+ /* The const qualifier has to be discarded
703
+ because of how rd_list_t and
704
+ rd_kafkap_str_t are, but we never modify
705
+ items in all_consumer_racks. */
706
+ (char *)member->rkgm_rack_id->str);
707
+ }
708
+ }
709
+ }
710
+ if (rd_list_cnt(all_consumer_racks) == 0) {
711
+ needs_rack_aware_assignment = rd_false;
712
+ goto done;
713
+ }
714
+
715
+
716
+ /* Critera 2 */
717
+ /* We don't copy racks, so the free function is NULL. */
718
+ all_partition_racks = rd_list_new(0, NULL);
719
+
720
+ for (t = 0; t < topic_cnt; t++) {
721
+ const int partition_cnt = topics[t]->metadata->partition_cnt;
722
+ for (i = 0; i < partition_cnt; i++) {
723
+ size_t j;
724
+ for (j = 0; j < topics[t]
725
+ ->metadata_internal->partitions[i]
726
+ .racks_cnt;
727
+ j++) {
728
+ char *rack =
729
+ topics[t]
730
+ ->metadata_internal->partitions[i]
731
+ .racks[j];
732
+ rd_list_add(all_partition_racks, rack);
733
+ }
734
+ }
735
+ }
736
+
737
+ /* If there are no partition racks, Criteria 2 cannot possibly be met.
738
+ */
739
+ if (rd_list_cnt(all_partition_racks) == 0) {
740
+ needs_rack_aware_assignment = rd_false;
741
+ goto done;
742
+ }
743
+
744
+ /* Sort and dedup the racks. */
745
+ rd_list_deduplicate(&all_consumer_racks, rd_strcmp2);
746
+ rd_list_deduplicate(&all_partition_racks, rd_strcmp2);
747
+
748
+
749
+ /* Iterate through each list in order, and see if there's anything in
750
+ * common */
751
+ RD_LIST_FOREACH(rack_id, all_consumer_racks, i) {
752
+ /* Break if there's even a single match. */
753
+ if (rd_list_find(all_partition_racks, rack_id, rd_strcmp2)) {
754
+ break;
755
+ }
756
+ }
757
+ if (i == rd_list_cnt(all_consumer_racks)) {
758
+ needs_rack_aware_assignment = rd_false;
759
+ goto done;
760
+ }
761
+
762
+ /* Criteria 3 */
763
+ for (t = 0; t < topic_cnt; t++) {
764
+ const int partition_cnt = topics[t]->metadata->partition_cnt;
765
+ for (i = 0; i < partition_cnt; i++) {
766
+ /* Since partition_racks[i] is a subset of
767
+ * all_partition_racks, and both of them are deduped,
768
+ * the same size indicates that they're equal. */
769
+ if ((size_t)(rd_list_cnt(all_partition_racks)) !=
770
+ topics[t]
771
+ ->metadata_internal->partitions[i]
772
+ .racks_cnt) {
773
+ break;
774
+ }
775
+ }
776
+ if (i < partition_cnt) {
777
+ /* Break outer loop if inner loop was broken. */
778
+ break;
779
+ }
780
+ }
781
+
782
+ /* Implies that all partitions have replicas on all racks. */
783
+ if (t == topic_cnt)
784
+ needs_rack_aware_assignment = rd_false;
785
+
786
+ done:
787
+ RD_IF_FREE(all_consumer_racks, rd_list_destroy);
788
+ RD_IF_FREE(all_partition_racks, rd_list_destroy);
789
+
790
+ return needs_rack_aware_assignment;
791
+ }
792
+
793
+
794
+ /* Helper to populate the racks for brokers in the metadata for unit tests.
795
+ * Passing num_broker_racks = 0 will return NULL racks. */
796
+ void ut_populate_internal_broker_metadata(rd_kafka_metadata_internal_t *mdi,
797
+ int num_broker_racks,
798
+ rd_kafkap_str_t *all_racks[],
799
+ size_t all_racks_cnt) {
800
+ int i;
801
+
802
+ rd_assert(num_broker_racks < (int)all_racks_cnt);
803
+
804
+ for (i = 0; i < mdi->metadata.broker_cnt; i++) {
805
+ mdi->brokers[i].id = i;
806
+ /* Cast from const to non-const. We don't intend to modify it,
807
+ * but unfortunately neither implementation of rd_kafkap_str_t
808
+ * or rd_kafka_metadata_broker_internal_t can be changed. So,
809
+ * this cast is used - in unit tests only. */
810
+ mdi->brokers[i].rack_id =
811
+ (char *)(num_broker_racks
812
+ ? all_racks[i % num_broker_racks]->str
813
+ : NULL);
814
+ }
815
+ }
816
+
817
+ /* Helper to populate the deduplicated racks inside each partition. It's assumed
818
+ * that `mdi->brokers` is set, maybe using
819
+ * `ut_populate_internal_broker_metadata`. */
820
+ void ut_populate_internal_topic_metadata(rd_kafka_metadata_internal_t *mdi) {
821
+ int ti;
822
+ rd_kafka_metadata_broker_internal_t *brokers_internal;
823
+ size_t broker_cnt;
824
+
825
+ rd_assert(mdi->brokers);
826
+
827
+ brokers_internal = mdi->brokers;
828
+ broker_cnt = mdi->metadata.broker_cnt;
829
+
830
+ for (ti = 0; ti < mdi->metadata.topic_cnt; ti++) {
831
+ int i;
832
+ rd_kafka_metadata_topic_t *mdt = &mdi->metadata.topics[ti];
833
+ rd_kafka_metadata_topic_internal_t *mdti = &mdi->topics[ti];
834
+
835
+ for (i = 0; i < mdt->partition_cnt; i++) {
836
+ int j;
837
+ rd_kafka_metadata_partition_t *partition =
838
+ &mdt->partitions[i];
839
+ rd_kafka_metadata_partition_internal_t
840
+ *partition_internal = &mdti->partitions[i];
841
+
842
+ rd_list_t *curr_list;
843
+ char *rack;
844
+
845
+ if (partition->replica_cnt == 0)
846
+ continue;
847
+
848
+ curr_list = rd_list_new(
849
+ 0, NULL); /* use a list for de-duplication */
850
+ for (j = 0; j < partition->replica_cnt; j++) {
851
+ rd_kafka_metadata_broker_internal_t key = {
852
+ .id = partition->replicas[j]};
853
+ rd_kafka_metadata_broker_internal_t *broker =
854
+ bsearch(
855
+ &key, brokers_internal, broker_cnt,
856
+ sizeof(
857
+ rd_kafka_metadata_broker_internal_t),
858
+ rd_kafka_metadata_broker_internal_cmp);
859
+ if (!broker || !broker->rack_id)
860
+ continue;
861
+ rd_list_add(curr_list, broker->rack_id);
862
+ }
863
+ rd_list_deduplicate(&curr_list, rd_strcmp2);
864
+
865
+ partition_internal->racks_cnt = rd_list_cnt(curr_list);
866
+ partition_internal->racks = rd_malloc(
867
+ sizeof(char *) * partition_internal->racks_cnt);
868
+ RD_LIST_FOREACH(rack, curr_list, j) {
869
+ partition_internal->racks[j] =
870
+ rack; /* no duplication */
871
+ }
872
+ rd_list_destroy(curr_list);
873
+ }
874
+ }
875
+ }
876
+
877
+ /* Helper to destroy test metadata. Destroying the metadata has some additional
878
+ * steps in case of tests. */
879
+ void ut_destroy_metadata(rd_kafka_metadata_t *md) {
880
+ int ti;
881
+ rd_kafka_metadata_internal_t *mdi = rd_kafka_metadata_get_internal(md);
882
+
883
+ for (ti = 0; ti < md->topic_cnt; ti++) {
884
+ int i;
885
+ rd_kafka_metadata_topic_t *mdt = &md->topics[ti];
886
+ rd_kafka_metadata_topic_internal_t *mdti = &mdi->topics[ti];
887
+
888
+ for (i = 0; mdti && i < mdt->partition_cnt; i++) {
889
+ rd_free(mdti->partitions[i].racks);
890
+ }
891
+ }
892
+
893
+ rd_kafka_metadata_destroy(md);
894
+ }
895
+
896
+
897
+ /**
898
+ * @brief Set a member's owned partitions based on its assignment.
899
+ *
900
+ * For use between assignor_run(). This is mimicing a consumer receiving
901
+ * its new assignment and including it in the next rebalance as its
902
+ * owned-partitions.
903
+ */
904
+ void ut_set_owned(rd_kafka_group_member_t *rkgm) {
905
+ if (rkgm->rkgm_owned)
906
+ rd_kafka_topic_partition_list_destroy(rkgm->rkgm_owned);
907
+
908
+ rkgm->rkgm_owned =
909
+ rd_kafka_topic_partition_list_copy(rkgm->rkgm_assignment);
910
+ }
911
+
912
+
913
+ void ut_print_toppar_list(const rd_kafka_topic_partition_list_t *partitions) {
914
+ int i;
915
+
916
+ for (i = 0; i < partitions->cnt; i++)
917
+ RD_UT_SAY(" %s [%" PRId32 "]", partitions->elems[i].topic,
918
+ partitions->elems[i].partition);
919
+ }
920
+
921
+
922
+ /* Implementation for ut_init_member and ut_init_member_with_rackv. */
923
+ static void ut_init_member_internal(rd_kafka_group_member_t *rkgm,
924
+ const char *member_id,
925
+ const rd_kafkap_str_t *rack_id,
926
+ va_list ap) {
927
+ const char *topic;
928
+
929
+ memset(rkgm, 0, sizeof(*rkgm));
930
+
931
+ rkgm->rkgm_member_id = rd_kafkap_str_new(member_id, -1);
932
+ rkgm->rkgm_group_instance_id = rd_kafkap_str_new(member_id, -1);
933
+ rkgm->rkgm_rack_id = rack_id ? rd_kafkap_str_copy(rack_id) : NULL;
934
+
935
+ rd_list_init(&rkgm->rkgm_eligible, 0, NULL);
936
+
937
+ rkgm->rkgm_subscription = rd_kafka_topic_partition_list_new(4);
938
+
939
+ while ((topic = va_arg(ap, const char *)))
940
+ rd_kafka_topic_partition_list_add(rkgm->rkgm_subscription,
941
+ topic, RD_KAFKA_PARTITION_UA);
942
+
943
+ rkgm->rkgm_assignment =
944
+ rd_kafka_topic_partition_list_new(rkgm->rkgm_subscription->size);
945
+
946
+ rkgm->rkgm_generation = 1;
947
+ }
948
+
949
+ /**
950
+ * @brief Initialize group member struct for testing.
951
+ *
952
+ * va-args is a NULL-terminated list of (const char *) topics.
953
+ *
954
+ * Use rd_kafka_group_member_clear() to free fields.
955
+ */
956
+ void ut_init_member(rd_kafka_group_member_t *rkgm, const char *member_id, ...) {
957
+ va_list ap;
958
+ va_start(ap, member_id);
959
+ ut_init_member_internal(rkgm, member_id, NULL, ap);
960
+ va_end(ap);
961
+ }
962
+
963
+ /**
964
+ * @brief Initialize group member struct for testing with a rackid.
965
+ *
966
+ * va-args is a NULL-terminated list of (const char *) topics.
967
+ *
968
+ * Use rd_kafka_group_member_clear() to free fields.
969
+ */
970
+ void ut_init_member_with_rackv(rd_kafka_group_member_t *rkgm,
971
+ const char *member_id,
972
+ const rd_kafkap_str_t *rack_id,
973
+ ...) {
974
+ va_list ap;
975
+ va_start(ap, rack_id);
976
+ ut_init_member_internal(rkgm, member_id, rack_id, ap);
977
+ va_end(ap);
978
+ }
979
+
980
+ /**
981
+ * @brief Initialize group member struct for testing with a rackid.
982
+ *
983
+ * Topics that the member is subscribed to are specified in an array with the
984
+ * size specified separately.
985
+ *
986
+ * Use rd_kafka_group_member_clear() to free fields.
987
+ */
988
+ void ut_init_member_with_rack(rd_kafka_group_member_t *rkgm,
989
+ const char *member_id,
990
+ const rd_kafkap_str_t *rack_id,
991
+ char *topics[],
992
+ size_t topic_cnt) {
993
+ size_t i;
994
+
995
+ memset(rkgm, 0, sizeof(*rkgm));
996
+
997
+ rkgm->rkgm_member_id = rd_kafkap_str_new(member_id, -1);
998
+ rkgm->rkgm_group_instance_id = rd_kafkap_str_new(member_id, -1);
999
+ rkgm->rkgm_rack_id = rack_id ? rd_kafkap_str_copy(rack_id) : NULL;
1000
+ rd_list_init(&rkgm->rkgm_eligible, 0, NULL);
1001
+
1002
+ rkgm->rkgm_subscription = rd_kafka_topic_partition_list_new(4);
1003
+
1004
+ for (i = 0; i < topic_cnt; i++) {
1005
+ rd_kafka_topic_partition_list_add(
1006
+ rkgm->rkgm_subscription, topics[i], RD_KAFKA_PARTITION_UA);
1007
+ }
1008
+ rkgm->rkgm_assignment =
1009
+ rd_kafka_topic_partition_list_new(rkgm->rkgm_subscription->size);
1010
+ }
1011
+
1012
+ /**
1013
+ * @brief Verify that member's assignment matches the expected partitions.
1014
+ *
1015
+ * The va-list is a NULL-terminated list of (const char *topic, int partition)
1016
+ * tuples.
1017
+ *
1018
+ * @returns 0 on success, else raises a unittest error and returns 1.
1019
+ */
1020
+ int verifyAssignment0(const char *function,
1021
+ int line,
1022
+ rd_kafka_group_member_t *rkgm,
1023
+ ...) {
1024
+ va_list ap;
1025
+ int cnt = 0;
1026
+ const char *topic;
1027
+ int fails = 0;
1028
+
1029
+ va_start(ap, rkgm);
1030
+ while ((topic = va_arg(ap, const char *))) {
1031
+ int partition = va_arg(ap, int);
1032
+ cnt++;
1033
+
1034
+ if (!rd_kafka_topic_partition_list_find(rkgm->rkgm_assignment,
1035
+ topic, partition)) {
1036
+ RD_UT_WARN(
1037
+ "%s:%d: Expected %s [%d] not found in %s's "
1038
+ "assignment (%d partition(s))",
1039
+ function, line, topic, partition,
1040
+ rkgm->rkgm_member_id->str,
1041
+ rkgm->rkgm_assignment->cnt);
1042
+ fails++;
1043
+ }
1044
+ }
1045
+ va_end(ap);
1046
+
1047
+ if (cnt != rkgm->rkgm_assignment->cnt) {
1048
+ RD_UT_WARN(
1049
+ "%s:%d: "
1050
+ "Expected %d assigned partition(s) for %s, not %d",
1051
+ function, line, cnt, rkgm->rkgm_member_id->str,
1052
+ rkgm->rkgm_assignment->cnt);
1053
+ fails++;
1054
+ }
1055
+
1056
+ if (fails)
1057
+ ut_print_toppar_list(rkgm->rkgm_assignment);
1058
+
1059
+ RD_UT_ASSERT(!fails, "%s:%d: See previous errors", function, line);
1060
+
1061
+ return 0;
1062
+ }
1063
+
1064
+ /**
1065
+ * @brief Verify that all members' assignment matches the expected partitions.
1066
+ *
1067
+ * The va-list is a list of (const char *topic, int partition)
1068
+ * tuples, and NULL to demarcate different members' assignment.
1069
+ *
1070
+ * @returns 0 on success, else raises a unittest error and returns 1.
1071
+ */
1072
+ int verifyMultipleAssignment0(const char *function,
1073
+ int line,
1074
+ rd_kafka_group_member_t *rkgms,
1075
+ size_t member_cnt,
1076
+ ...) {
1077
+ va_list ap;
1078
+ const char *topic;
1079
+ int fails = 0;
1080
+ size_t i = 0;
1081
+
1082
+ if (member_cnt == 0) {
1083
+ return 0;
1084
+ }
1085
+
1086
+ va_start(ap, member_cnt);
1087
+ for (i = 0; i < member_cnt; i++) {
1088
+ rd_kafka_group_member_t *rkgm = &rkgms[i];
1089
+ int cnt = 0;
1090
+ int local_fails = 0;
1091
+
1092
+ while ((topic = va_arg(ap, const char *))) {
1093
+ int partition = va_arg(ap, int);
1094
+ cnt++;
1095
+
1096
+ if (!rd_kafka_topic_partition_list_find(
1097
+ rkgm->rkgm_assignment, topic, partition)) {
1098
+ RD_UT_WARN(
1099
+ "%s:%d: Expected %s [%d] not found in %s's "
1100
+ "assignment (%d partition(s))",
1101
+ function, line, topic, partition,
1102
+ rkgm->rkgm_member_id->str,
1103
+ rkgm->rkgm_assignment->cnt);
1104
+ local_fails++;
1105
+ }
1106
+ }
1107
+
1108
+ if (cnt != rkgm->rkgm_assignment->cnt) {
1109
+ RD_UT_WARN(
1110
+ "%s:%d: "
1111
+ "Expected %d assigned partition(s) for %s, not %d",
1112
+ function, line, cnt, rkgm->rkgm_member_id->str,
1113
+ rkgm->rkgm_assignment->cnt);
1114
+ fails++;
1115
+ }
1116
+
1117
+ if (local_fails)
1118
+ ut_print_toppar_list(rkgm->rkgm_assignment);
1119
+ fails += local_fails;
1120
+ }
1121
+ va_end(ap);
1122
+
1123
+ RD_UT_ASSERT(!fails, "%s:%d: See previous errors", function, line);
1124
+
1125
+ return 0;
1126
+ }
1127
+
1128
+
1129
+ #define verifyNumPartitionsWithRackMismatchPartition(rktpar, metadata, \
1130
+ increase) \
1131
+ do { \
1132
+ if (!rktpar) \
1133
+ break; \
1134
+ int i; \
1135
+ rd_bool_t noneMatch = rd_true; \
1136
+ rd_kafka_metadata_internal_t *metadata_internal = \
1137
+ rd_kafka_metadata_get_internal(metadata); \
1138
+ \
1139
+ for (i = 0; i < metadata->topics[j].partitions[k].replica_cnt; \
1140
+ i++) { \
1141
+ int32_t replica_id = \
1142
+ metadata->topics[j].partitions[k].replicas[i]; \
1143
+ rd_kafka_metadata_broker_internal_t *broker; \
1144
+ rd_kafka_metadata_broker_internal_find( \
1145
+ metadata_internal, replica_id, broker); \
1146
+ \
1147
+ if (broker && !strcmp(rack_id, broker->rack_id)) { \
1148
+ noneMatch = rd_false; \
1149
+ break; \
1150
+ } \
1151
+ } \
1152
+ \
1153
+ if (noneMatch) \
1154
+ increase++; \
1155
+ } while (0);
1156
+
1157
+ /**
1158
+ * @brief Verify number of partitions with rack mismatch.
1159
+ */
1160
+ int verifyNumPartitionsWithRackMismatch0(const char *function,
1161
+ int line,
1162
+ rd_kafka_metadata_t *metadata,
1163
+ rd_kafka_group_member_t *rkgms,
1164
+ size_t member_cnt,
1165
+ int expectedNumMismatch) {
1166
+ size_t i;
1167
+ int j, k;
1168
+
1169
+ int numMismatched = 0;
1170
+ for (i = 0; i < member_cnt; i++) {
1171
+ rd_kafka_group_member_t *rkgm = &rkgms[i];
1172
+ const char *rack_id = rkgm->rkgm_rack_id->str;
1173
+ if (rack_id) {
1174
+ for (j = 0; j < metadata->topic_cnt; j++) {
1175
+ for (k = 0;
1176
+ k < metadata->topics[j].partition_cnt;
1177
+ k++) {
1178
+ rd_kafka_topic_partition_t *rktpar =
1179
+ rd_kafka_topic_partition_list_find(
1180
+ rkgm->rkgm_assignment,
1181
+ metadata->topics[j].topic, k);
1182
+ verifyNumPartitionsWithRackMismatchPartition(
1183
+ rktpar, metadata, numMismatched);
1184
+ }
1185
+ }
1186
+ }
1187
+ }
1188
+
1189
+ RD_UT_ASSERT(expectedNumMismatch == numMismatched,
1190
+ "%s:%d: Expected %d mismatches, got %d", function, line,
1191
+ expectedNumMismatch, numMismatched);
1192
+
1193
+ return 0;
1194
+ }
1195
+
1196
+
1197
+ int verifyValidityAndBalance0(const char *func,
1198
+ int line,
1199
+ rd_kafka_group_member_t *members,
1200
+ size_t member_cnt,
1201
+ const rd_kafka_metadata_t *metadata) {
1202
+ int fails = 0;
1203
+ int i;
1204
+ rd_bool_t verbose = rd_false; /* Enable for troubleshooting */
1205
+
1206
+ RD_UT_SAY("%s:%d: verifying assignment for %d member(s):", func, line,
1207
+ (int)member_cnt);
1208
+
1209
+ for (i = 0; i < (int)member_cnt; i++) {
1210
+ const char *consumer = members[i].rkgm_member_id->str;
1211
+ const rd_kafka_topic_partition_list_t *partitions =
1212
+ members[i].rkgm_assignment;
1213
+ int p, j;
1214
+
1215
+ if (verbose)
1216
+ RD_UT_SAY(
1217
+ "%s:%d: "
1218
+ "consumer \"%s\", %d subscribed topic(s), "
1219
+ "%d assigned partition(s):",
1220
+ func, line, consumer,
1221
+ members[i].rkgm_subscription->cnt, partitions->cnt);
1222
+
1223
+ for (p = 0; p < partitions->cnt; p++) {
1224
+ const rd_kafka_topic_partition_t *partition =
1225
+ &partitions->elems[p];
1226
+
1227
+ if (verbose)
1228
+ RD_UT_SAY("%s:%d: %s [%" PRId32 "]", func,
1229
+ line, partition->topic,
1230
+ partition->partition);
1231
+
1232
+ if (!rd_kafka_topic_partition_list_find(
1233
+ members[i].rkgm_subscription, partition->topic,
1234
+ RD_KAFKA_PARTITION_UA)) {
1235
+ RD_UT_WARN("%s [%" PRId32
1236
+ "] is assigned to "
1237
+ "%s but it is not subscribed to "
1238
+ "that topic",
1239
+ partition->topic,
1240
+ partition->partition, consumer);
1241
+ fails++;
1242
+ }
1243
+ }
1244
+
1245
+ /* Update the member's owned partitions to match
1246
+ * the assignment. */
1247
+ ut_set_owned(&members[i]);
1248
+
1249
+ if (i == (int)member_cnt - 1)
1250
+ continue;
1251
+
1252
+ for (j = i + 1; j < (int)member_cnt; j++) {
1253
+ const char *otherConsumer =
1254
+ members[j].rkgm_member_id->str;
1255
+ const rd_kafka_topic_partition_list_t *otherPartitions =
1256
+ members[j].rkgm_assignment;
1257
+ rd_bool_t balanced =
1258
+ abs(partitions->cnt - otherPartitions->cnt) <= 1;
1259
+
1260
+ for (p = 0; p < partitions->cnt; p++) {
1261
+ const rd_kafka_topic_partition_t *partition =
1262
+ &partitions->elems[p];
1263
+
1264
+ if (rd_kafka_topic_partition_list_find(
1265
+ otherPartitions, partition->topic,
1266
+ partition->partition)) {
1267
+ RD_UT_WARN(
1268
+ "Consumer %s and %s are both "
1269
+ "assigned %s [%" PRId32 "]",
1270
+ consumer, otherConsumer,
1271
+ partition->topic,
1272
+ partition->partition);
1273
+ fails++;
1274
+ }
1275
+
1276
+
1277
+ /* If assignment is imbalanced and this topic
1278
+ * is also subscribed by the other consumer
1279
+ * it means the assignment strategy failed to
1280
+ * properly balance the partitions. */
1281
+ if (!balanced &&
1282
+ rd_kafka_topic_partition_list_find_topic_by_name(
1283
+ otherPartitions, partition->topic)) {
1284
+ RD_UT_WARN(
1285
+ "Some %s partition(s) can be "
1286
+ "moved from "
1287
+ "%s (%d partition(s)) to "
1288
+ "%s (%d partition(s)) to "
1289
+ "achieve a better balance",
1290
+ partition->topic, consumer,
1291
+ partitions->cnt, otherConsumer,
1292
+ otherPartitions->cnt);
1293
+ fails++;
1294
+ }
1295
+ }
1296
+ }
1297
+ }
1298
+
1299
+ RD_UT_ASSERT(!fails, "%s:%d: See %d previous errors", func, line,
1300
+ fails);
1301
+
1302
+ return 0;
1303
+ }
1304
+
1305
+ /**
1306
+ * @brief Checks that all assigned partitions are fully balanced.
1307
+ *
1308
+ * Only works for symmetrical subscriptions.
1309
+ */
1310
+ int isFullyBalanced0(const char *function,
1311
+ int line,
1312
+ const rd_kafka_group_member_t *members,
1313
+ size_t member_cnt) {
1314
+ int min_assignment = INT_MAX;
1315
+ int max_assignment = -1;
1316
+ size_t i;
1317
+
1318
+ for (i = 0; i < member_cnt; i++) {
1319
+ int size = members[i].rkgm_assignment->cnt;
1320
+ if (size < min_assignment)
1321
+ min_assignment = size;
1322
+ if (size > max_assignment)
1323
+ max_assignment = size;
1324
+ }
1325
+
1326
+ RD_UT_ASSERT(max_assignment - min_assignment <= 1,
1327
+ "%s:%d: Assignment not balanced: min %d, max %d", function,
1328
+ line, min_assignment, max_assignment);
1329
+
1330
+ return 0;
1331
+ }
1332
+
1333
+
1334
+ /**
1335
+ * @brief Unittest for assignors
1336
+ */
1337
+ static int ut_assignors(void) {
1338
+ const struct {
1339
+ const char *name;
1340
+ int topic_cnt;
1341
+ struct {
1342
+ const char *name;
1343
+ int partition_cnt;
1344
+ } topics[12];
1345
+ int member_cnt;
1346
+ struct {
1347
+ const char *name;
1348
+ int topic_cnt;
1349
+ const char *topics[12];
1350
+ } members[3];
1351
+ int expect_cnt;
1352
+ struct {
1353
+ const char *protocol_name;
1354
+ struct {
1355
+ int partition_cnt;
1356
+ const char *partitions[12]; /* "topic:part" */
1357
+ } members[3];
1358
+ } expect[2];
1359
+ } tests[] = {
1360
+ /*
1361
+ * Test cases
1362
+ */
1363
+ {
1364
+ .name = "Symmetrical subscription",
1365
+ .topic_cnt = 4,
1366
+ .topics =
1367
+ {
1368
+ {"a", 3}, /* a:0 a:1 a:2 */
1369
+ {
1370
+ "b",
1371
+ 4,
1372
+ }, /* b:0 b:1 b:2 b:3 */
1373
+ {"c", 2}, /* c:0 c:1 */
1374
+ {"d", 1}, /* d:0 */
1375
+ },
1376
+ .member_cnt = 2,
1377
+ .members =
1378
+ {
1379
+ {.name = "consumer1",
1380
+ .topic_cnt = 4,
1381
+ .topics = {"d", "b", "a", "c"}},
1382
+ {.name = "consumer2",
1383
+ .topic_cnt = 4,
1384
+ .topics = {"a", "b", "c", "d"}},
1385
+ },
1386
+ .expect_cnt = 2,
1387
+ .expect =
1388
+ {
1389
+ {
1390
+ .protocol_name = "range",
1391
+ .members =
1392
+ {
1393
+ /* Consumer1 */
1394
+ {6,
1395
+ {"a:0", "a:1", "b:0", "b:1", "c:0",
1396
+ "d:0"}},
1397
+ /* Consumer2 */
1398
+ {4, {"a:2", "b:2", "b:3", "c:1"}},
1399
+ },
1400
+ },
1401
+ {
1402
+ .protocol_name = "roundrobin",
1403
+ .members =
1404
+ {
1405
+ /* Consumer1 */
1406
+ {5, {"a:0", "a:2", "b:1", "b:3", "c:1"}},
1407
+ /* Consumer2 */
1408
+ {5, {"a:1", "b:0", "b:2", "c:0", "d:0"}},
1409
+ },
1410
+ },
1411
+ },
1412
+ },
1413
+ {
1414
+ .name = "1*3 partitions (asymmetrical)",
1415
+ .topic_cnt = 1,
1416
+ .topics =
1417
+ {
1418
+ {"a", 3},
1419
+ },
1420
+ .member_cnt = 2,
1421
+ .members =
1422
+ {
1423
+ {.name = "consumer1",
1424
+ .topic_cnt = 3,
1425
+ .topics = {"a", "b", "c"}},
1426
+ {.name = "consumer2", .topic_cnt = 1, .topics = {"a"}},
1427
+ },
1428
+ .expect_cnt = 2,
1429
+ .expect =
1430
+ {
1431
+ {
1432
+ .protocol_name = "range",
1433
+ .members =
1434
+ {
1435
+ /* Consumer1.
1436
+ * range assignor applies
1437
+ * per topic. */
1438
+ {2, {"a:0", "a:1"}},
1439
+ /* Consumer2 */
1440
+ {1, {"a:2"}},
1441
+ },
1442
+ },
1443
+ {
1444
+ .protocol_name = "roundrobin",
1445
+ .members =
1446
+ {
1447
+ /* Consumer1 */
1448
+ {2, {"a:0", "a:2"}},
1449
+ /* Consumer2 */
1450
+ {1, {"a:1"}},
1451
+ },
1452
+ },
1453
+ },
1454
+ },
1455
+ {
1456
+ .name = "#2121 (asymmetrical)",
1457
+ .topic_cnt = 12,
1458
+ .topics =
1459
+ {
1460
+ {"a", 1},
1461
+ {"b", 1},
1462
+ {"c", 1},
1463
+ {"d", 1},
1464
+ {"e", 1},
1465
+ {"f", 1},
1466
+ {"g", 1},
1467
+ {"h", 1},
1468
+ {"i", 1},
1469
+ {"j", 1},
1470
+ {"k", 1},
1471
+ {"l", 1},
1472
+ },
1473
+ .member_cnt = 2,
1474
+ .members =
1475
+ {
1476
+ {
1477
+ .name = "consumer1",
1478
+ .topic_cnt = 12,
1479
+ .topics =
1480
+ {
1481
+ "a",
1482
+ "b",
1483
+ "c",
1484
+ "d",
1485
+ "e",
1486
+ "f",
1487
+ "g",
1488
+ "h",
1489
+ "i",
1490
+ "j",
1491
+ "k",
1492
+ "l",
1493
+ },
1494
+ },
1495
+ {
1496
+ .name = "consumer2", /* must be second */
1497
+ .topic_cnt = 5,
1498
+ .topics =
1499
+ {
1500
+ "b",
1501
+ "d",
1502
+ "f",
1503
+ "h",
1504
+ "l",
1505
+ },
1506
+ },
1507
+ },
1508
+ .expect_cnt = 2,
1509
+ .expect =
1510
+ {
1511
+ {
1512
+ .protocol_name = "range",
1513
+ .members =
1514
+ {
1515
+ /* Consumer1.
1516
+ * All partitions. */
1517
+ {12,
1518
+ {
1519
+ "a:0",
1520
+ "b:0",
1521
+ "c:0",
1522
+ "d:0",
1523
+ "e:0",
1524
+ "f:0",
1525
+ "g:0",
1526
+ "h:0",
1527
+ "i:0",
1528
+ "j:0",
1529
+ "k:0",
1530
+ "l:0",
1531
+ }},
1532
+ /* Consumer2 */
1533
+ {0},
1534
+ },
1535
+ },
1536
+ {
1537
+ .protocol_name = "roundrobin",
1538
+ .members =
1539
+ {
1540
+ /* Consumer1 */
1541
+ {
1542
+ 7,
1543
+ {
1544
+ "a:0",
1545
+ "c:0",
1546
+ "e:0",
1547
+ "g:0",
1548
+ "i:0",
1549
+ "j:0",
1550
+ "k:0",
1551
+ },
1552
+ },
1553
+ /* Consumer2 */
1554
+ {5, {"b:0", "d:0", "f:0", "h:0", "l:0"}},
1555
+ },
1556
+ },
1557
+ },
1558
+ },
1559
+ {NULL},
1560
+ };
1561
+ rd_kafka_conf_t *conf;
1562
+ rd_kafka_t *rk;
1563
+ const rd_kafka_assignor_t *rkas;
1564
+ int fails = 0;
1565
+ int i;
1566
+
1567
+ conf = rd_kafka_conf_new();
1568
+ rd_kafka_conf_set(conf, "group.id", "group", NULL, 0);
1569
+ rd_kafka_conf_set(conf, "debug", rd_getenv("TEST_DEBUG", NULL), NULL,
1570
+ 0);
1571
+ rk = rd_kafka_new(RD_KAFKA_CONSUMER, conf, NULL, 0);
1572
+ RD_UT_ASSERT(rk != NULL, "Failed to create consumer");
1573
+
1574
+ /* Run through test cases */
1575
+ for (i = 0; tests[i].name; i++) {
1576
+ int ie, it, im;
1577
+ rd_kafka_metadata_internal_t metadata_internal;
1578
+ rd_kafka_metadata_t metadata;
1579
+ rd_kafka_group_member_t *members;
1580
+
1581
+ /* Create topic metadata */
1582
+ metadata.topic_cnt = tests[i].topic_cnt;
1583
+ metadata.topics =
1584
+ rd_alloca(sizeof(*metadata.topics) * metadata.topic_cnt);
1585
+ metadata_internal.topics = rd_alloca(
1586
+ sizeof(*metadata_internal.topics) * metadata.topic_cnt);
1587
+
1588
+ memset(metadata.topics, 0,
1589
+ sizeof(*metadata.topics) * metadata.topic_cnt);
1590
+ memset(metadata_internal.topics, 0,
1591
+ sizeof(*metadata_internal.topics) * metadata.topic_cnt);
1592
+
1593
+ for (it = 0; it < metadata.topic_cnt; it++) {
1594
+ int pt;
1595
+ metadata.topics[it].topic =
1596
+ (char *)tests[i].topics[it].name;
1597
+ metadata.topics[it].partition_cnt =
1598
+ tests[i].topics[it].partition_cnt;
1599
+ metadata.topics[it].partitions =
1600
+ rd_alloca(metadata.topics[it].partition_cnt *
1601
+ sizeof(rd_kafka_metadata_partition_t));
1602
+ metadata_internal.topics[it].partitions = rd_alloca(
1603
+ metadata.topics[it].partition_cnt *
1604
+ sizeof(rd_kafka_metadata_partition_internal_t));
1605
+ for (pt = 0; pt < metadata.topics[it].partition_cnt;
1606
+ pt++) {
1607
+ metadata.topics[it].partitions[pt].id = pt;
1608
+ metadata.topics[it].partitions[pt].replica_cnt =
1609
+ 0;
1610
+ metadata_internal.topics[it]
1611
+ .partitions[pt]
1612
+ .racks_cnt = 0;
1613
+ metadata_internal.topics[it]
1614
+ .partitions[pt]
1615
+ .racks = NULL;
1616
+ }
1617
+ }
1618
+
1619
+ /* Create members */
1620
+ members = rd_alloca(sizeof(*members) * tests[i].member_cnt);
1621
+ memset(members, 0, sizeof(*members) * tests[i].member_cnt);
1622
+
1623
+ for (im = 0; im < tests[i].member_cnt; im++) {
1624
+ rd_kafka_group_member_t *rkgm = &members[im];
1625
+ rkgm->rkgm_member_id =
1626
+ rd_kafkap_str_new(tests[i].members[im].name, -1);
1627
+ rkgm->rkgm_group_instance_id =
1628
+ rd_kafkap_str_new(tests[i].members[im].name, -1);
1629
+ rd_list_init(&rkgm->rkgm_eligible,
1630
+ tests[i].members[im].topic_cnt, NULL);
1631
+
1632
+ rkgm->rkgm_subscription =
1633
+ rd_kafka_topic_partition_list_new(
1634
+ tests[i].members[im].topic_cnt);
1635
+ for (it = 0; it < tests[i].members[im].topic_cnt; it++)
1636
+ rd_kafka_topic_partition_list_add(
1637
+ rkgm->rkgm_subscription,
1638
+ tests[i].members[im].topics[it],
1639
+ RD_KAFKA_PARTITION_UA);
1640
+
1641
+ rkgm->rkgm_userdata = NULL;
1642
+
1643
+ rkgm->rkgm_assignment =
1644
+ rd_kafka_topic_partition_list_new(
1645
+ rkgm->rkgm_subscription->size);
1646
+ }
1647
+
1648
+ /* For each assignor verify that the assignment
1649
+ * matches the expection set out in the test case. */
1650
+ for (ie = 0; ie < tests[i].expect_cnt; ie++) {
1651
+ rd_kafka_resp_err_t err;
1652
+ char errstr[256];
1653
+
1654
+ RD_UT_SAY("Test case %s: %s assignor", tests[i].name,
1655
+ tests[i].expect[ie].protocol_name);
1656
+
1657
+ if (!(rkas = rd_kafka_assignor_find(
1658
+ rk, tests[i].expect[ie].protocol_name))) {
1659
+ RD_UT_FAIL(
1660
+ "Assignor test case %s for %s failed: "
1661
+ "assignor not found",
1662
+ tests[i].name,
1663
+ tests[i].expect[ie].protocol_name);
1664
+ }
1665
+
1666
+ /* Run assignor */
1667
+ metadata_internal.metadata = metadata;
1668
+ err = rd_kafka_assignor_run(
1669
+ rk->rk_cgrp, rkas,
1670
+ (rd_kafka_metadata_t *)(&metadata_internal),
1671
+ members, tests[i].member_cnt, errstr,
1672
+ sizeof(errstr));
1673
+
1674
+ RD_UT_ASSERT(!err, "Assignor case %s for %s failed: %s",
1675
+ tests[i].name,
1676
+ tests[i].expect[ie].protocol_name, errstr);
1677
+
1678
+ /* Verify assignments */
1679
+ for (im = 0; im < tests[i].member_cnt; im++) {
1680
+ rd_kafka_group_member_t *rkgm = &members[im];
1681
+ int ia;
1682
+
1683
+ if (rkgm->rkgm_assignment->cnt !=
1684
+ tests[i]
1685
+ .expect[ie]
1686
+ .members[im]
1687
+ .partition_cnt) {
1688
+ RD_UT_WARN(
1689
+ " Member %.*s assignment count "
1690
+ "mismatch: %d != %d",
1691
+ RD_KAFKAP_STR_PR(
1692
+ rkgm->rkgm_member_id),
1693
+ rkgm->rkgm_assignment->cnt,
1694
+ tests[i]
1695
+ .expect[ie]
1696
+ .members[im]
1697
+ .partition_cnt);
1698
+ fails++;
1699
+ }
1700
+
1701
+ if (rkgm->rkgm_assignment->cnt > 0)
1702
+ rd_kafka_topic_partition_list_sort_by_topic(
1703
+ rkgm->rkgm_assignment);
1704
+
1705
+ for (ia = 0; ia < rkgm->rkgm_assignment->cnt;
1706
+ ia++) {
1707
+ rd_kafka_topic_partition_t *p =
1708
+ &rkgm->rkgm_assignment->elems[ia];
1709
+ char part[64];
1710
+ const char *exp =
1711
+ ia < tests[i]
1712
+ .expect[ie]
1713
+ .members[im]
1714
+ .partition_cnt
1715
+ ? tests[i]
1716
+ .expect[ie]
1717
+ .members[im]
1718
+ .partitions[ia]
1719
+ : "(none)";
1720
+
1721
+ rd_snprintf(part, sizeof(part), "%s:%d",
1722
+ p->topic,
1723
+ (int)p->partition);
1724
+
1725
+ #if 0 /* Enable to print actual assignment */
1726
+ RD_UT_SAY(" Member %.*s assignment "
1727
+ "%d/%d %s =? %s",
1728
+ RD_KAFKAP_STR_PR(
1729
+ rkgm->rkgm_member_id),
1730
+ ia,
1731
+ rkgm->rkgm_assignment->cnt-1,
1732
+ part, exp);
1733
+ #endif
1734
+
1735
+ if (strcmp(part, exp)) {
1736
+ RD_UT_WARN(
1737
+ " Member %.*s "
1738
+ "assignment %d/%d "
1739
+ "mismatch: %s != %s",
1740
+ RD_KAFKAP_STR_PR(
1741
+ rkgm->rkgm_member_id),
1742
+ ia,
1743
+ rkgm->rkgm_assignment->cnt -
1744
+ 1,
1745
+ part, exp);
1746
+ fails++;
1747
+ }
1748
+ }
1749
+
1750
+ /* Reset assignment for next loop */
1751
+ rd_kafka_topic_partition_list_destroy(
1752
+ rkgm->rkgm_assignment);
1753
+ rkgm->rkgm_assignment =
1754
+ rd_kafka_topic_partition_list_new(
1755
+ rkgm->rkgm_subscription->size);
1756
+ }
1757
+ }
1758
+
1759
+ for (im = 0; im < tests[i].member_cnt; im++) {
1760
+ rd_kafka_group_member_t *rkgm = &members[im];
1761
+ rd_kafka_group_member_clear(rkgm);
1762
+ }
1763
+ }
1764
+
1765
+
1766
+ /* Run assignor-specific unittests */
1767
+ RD_LIST_FOREACH(rkas, &rk->rk_conf.partition_assignors, i) {
1768
+ if (rkas->rkas_unittest)
1769
+ fails += rkas->rkas_unittest();
1770
+ }
1771
+
1772
+ rd_kafka_destroy(rk);
1773
+
1774
+ if (fails)
1775
+ return 1;
1776
+
1777
+ RD_UT_PASS();
1778
+ }
1779
+
1780
+
1781
+ /**
1782
+ * @brief Unit tests for assignors
1783
+ */
1784
+ int unittest_assignors(void) {
1785
+ return ut_assignors();
1786
+ }