Coverage Report

Created: 2026-08-09 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fluent-bit/lib/librdkafka-2.15.0/src/rdkafka_metadata.c
Line
Count
Source
1
/*
2
 * librdkafka - Apache Kafka C library
3
 *
4
 * Copyright (c) 2012-2022, Magnus Edenhill
5
 *               2023, Confluent Inc.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 *
11
 * 1. Redistributions of source code must retain the above copyright notice,
12
 *    this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright notice,
14
 *    this list of conditions and the following disclaimer in the documentation
15
 *    and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
 * POSSIBILITY OF SUCH DAMAGE.
28
 */
29
30
31
#include "rd.h"
32
#include "rdkafka_int.h"
33
#include "rdkafka_topic.h"
34
#include "rdkafka_broker.h"
35
#include "rdkafka_request.h"
36
#include "rdkafka_idempotence.h"
37
#include "rdkafka_metadata.h"
38
39
#include <string.h>
40
#include <stdarg.h>
41
42
/**
43
 * @brief Id comparator for rd_kafka_metadata_broker_internal_t
44
 */
45
0
int rd_kafka_metadata_broker_internal_cmp(const void *_a, const void *_b) {
46
0
        const rd_kafka_metadata_broker_internal_t *a = _a;
47
0
        const rd_kafka_metadata_broker_internal_t *b = _b;
48
0
        return RD_CMP(a->id, b->id);
49
0
}
50
51
52
/**
53
 * @brief Id comparator for struct rd_kafka_metadata_broker*
54
 */
55
0
int rd_kafka_metadata_broker_cmp(const void *_a, const void *_b) {
56
0
        const struct rd_kafka_metadata_broker *a = _a;
57
0
        const struct rd_kafka_metadata_broker *b = _b;
58
0
        return RD_CMP(a->id, b->id);
59
0
}
60
61
62
/**
63
 * @brief Id comparator for rd_kafka_metadata_partition_internal_t
64
 */
65
static int rd_kafka_metadata_partition_internal_cmp(const void *_a,
66
0
                                                    const void *_b) {
67
0
        const rd_kafka_metadata_partition_internal_t *a = _a;
68
0
        const rd_kafka_metadata_partition_internal_t *b = _b;
69
0
        return RD_CMP(a->id, b->id);
70
0
}
71
72
/**
73
 * @brief Helper function to clear a rd_kafka_metadata_partition.
74
 *
75
 * @note Does not deallocate the rd_kafka_metadata_partition itself.
76
 * @note Should not be used if there is an metadata struct allocated with
77
 * tmpabuf in which rd_kafka_metadata_partition is contained.
78
 */
79
void rd_kafka_metadata_partition_clear(
80
0
    struct rd_kafka_metadata_partition *rkmp) {
81
0
        RD_IF_FREE(rkmp->isrs, rd_free);
82
0
        RD_IF_FREE(rkmp->replicas, rd_free);
83
0
}
84
85
86
rd_kafka_resp_err_t
87
rd_kafka_metadata(rd_kafka_t *rk,
88
                  int all_topics,
89
                  rd_kafka_topic_t *only_rkt,
90
                  const struct rd_kafka_metadata **metadatap,
91
0
                  int timeout_ms) {
92
0
        rd_kafka_q_t *rkq;
93
0
        rd_kafka_broker_t *rkb;
94
0
        rd_kafka_op_t *rko;
95
0
        rd_kafka_resp_err_t err;
96
0
        rd_ts_t ts_end = rd_timeout_init(timeout_ms);
97
0
        rd_list_t topics;
98
0
        rd_bool_t allow_auto_create_topics =
99
0
            rk->rk_conf.allow_auto_create_topics;
100
101
0
        do {
102
                /* Query any broker that is up, and if none are up pick the
103
                 * first one, if we're lucky it will be up before the timeout.
104
                 * Previous decommissioning brokers won't be returned by the
105
                 * function after receiving the _DESTROY_BROKER error
106
                 * below. */
107
0
                rkb =
108
0
                    rd_kafka_broker_any_usable(rk, timeout_ms, RD_DO_LOCK, 0,
109
0
                                               "application metadata request");
110
0
                if (!rkb)
111
0
                        return RD_KAFKA_RESP_ERR__TRANSPORT;
112
113
0
                rkq = rd_kafka_q_new(rk);
114
115
0
                rd_list_init(&topics, 0, rd_free);
116
0
                if (!all_topics) {
117
0
                        if (only_rkt)
118
0
                                rd_list_add(
119
0
                                    &topics,
120
0
                                    rd_strdup(rd_kafka_topic_name(only_rkt)));
121
0
                        else {
122
0
                                int cache_cnt;
123
0
                                rd_kafka_local_topics_to_list(
124
0
                                    rkb->rkb_rk, &topics, &cache_cnt);
125
                                /* Don't trigger auto-create
126
                                 * for cached topics */
127
0
                                if (rd_list_cnt(&topics) == cache_cnt)
128
0
                                        allow_auto_create_topics = rd_true;
129
0
                        }
130
0
                }
131
132
                /* Async: request metadata */
133
0
                rko = rd_kafka_op_new(RD_KAFKA_OP_METADATA);
134
0
                rd_kafka_op_set_replyq(rko, rkq, 0);
135
0
                rko->rko_u.metadata.force =
136
0
                    1; /* Force metadata request regardless
137
                        * of outstanding metadata requests. */
138
0
                rd_kafka_MetadataRequest(
139
0
                    rkb, &topics, NULL, "application requested",
140
0
                    allow_auto_create_topics,
141
                    /* cgrp_update:
142
                     * Only update consumer group state
143
                     * on response if this lists all
144
                     * topics in the cluster, since a
145
                     * partial request may make it seem
146
                     * like some subscribed topics are missing. */
147
0
                    all_topics ? rd_true : rd_false,
148
0
                    -1 /* same subscription version */,
149
0
                    rd_false /* force_racks */, rko);
150
151
0
                rd_list_destroy(&topics);
152
0
                rd_kafka_broker_destroy(rkb);
153
154
                /* Wait for reply (or timeout) */
155
0
                rko = rd_kafka_q_pop(rkq, rd_timeout_remains_us(ts_end), 0);
156
157
0
                rd_kafka_q_destroy_owner(rkq);
158
159
                /* Timeout */
160
0
                if (!rko)
161
0
                        return RD_KAFKA_RESP_ERR__TIMED_OUT;
162
163
                /* Error */
164
0
                err = rko->rko_err;
165
0
                if (err) {
166
0
                        rd_kafka_op_destroy(rko);
167
0
                        if (err != RD_KAFKA_RESP_ERR__DESTROY_BROKER)
168
0
                                return err;
169
0
                }
170
171
                /* In case selected broker was decommissioned,
172
                 * try again with a different broker. */
173
0
        } while (err == RD_KAFKA_RESP_ERR__DESTROY_BROKER);
174
175
        /* Reply: pass metadata pointer to application who now owns it*/
176
0
        rd_kafka_assert(rk, rko->rko_u.metadata.md);
177
0
        *metadatap              = rko->rko_u.metadata.md;
178
0
        rko->rko_u.metadata.md  = NULL;
179
0
        rko->rko_u.metadata.mdi = NULL;
180
0
        rd_kafka_op_destroy(rko);
181
182
0
        return RD_KAFKA_RESP_ERR_NO_ERROR;
183
0
}
184
185
186
187
0
void rd_kafka_metadata_destroy(const struct rd_kafka_metadata *metadata) {
188
0
        rd_free((void *)metadata);
189
0
}
190
191
192
static rd_kafka_metadata_internal_t *rd_kafka_metadata_copy_internal(
193
    const rd_kafka_metadata_internal_t *src_internal,
194
    size_t size,
195
0
    rd_bool_t populate_racks) {
196
0
        struct rd_kafka_metadata *md;
197
0
        rd_kafka_metadata_internal_t *mdi;
198
0
        const struct rd_kafka_metadata *src = &src_internal->metadata;
199
0
        rd_tmpabuf_t tbuf;
200
0
        int i;
201
202
        /* metadata is stored in one contigious buffer where structs and
203
         * and pointed-to fields are layed out in a memory aligned fashion.
204
         * rd_tmpabuf_t provides the infrastructure to do this.
205
         * Because of this we copy all the structs verbatim but
206
         * any pointer fields needs to be copied explicitly to update
207
         * the pointer address. */
208
0
        rd_tmpabuf_new(&tbuf, size, rd_true /*assert on fail*/);
209
0
        rd_tmpabuf_finalize(&tbuf);
210
0
        mdi = rd_tmpabuf_write(&tbuf, src, sizeof(*mdi));
211
0
        md  = &mdi->metadata;
212
213
0
        rd_tmpabuf_write_str(&tbuf, src->orig_broker_name);
214
215
216
        /* Copy Brokers */
217
0
        md->brokers = rd_tmpabuf_write(&tbuf, src->brokers,
218
0
                                       src->broker_cnt * sizeof(*src->brokers));
219
        /* Copy internal Brokers */
220
0
        mdi->brokers =
221
0
            rd_tmpabuf_write(&tbuf, src_internal->brokers,
222
0
                             src->broker_cnt * sizeof(*src_internal->brokers));
223
224
0
        for (i = 0; i < md->broker_cnt; i++) {
225
0
                md->brokers[i].host =
226
0
                    rd_tmpabuf_write_str(&tbuf, src->brokers[i].host);
227
0
                if (src_internal->brokers[i].rack_id) {
228
0
                        mdi->brokers[i].rack_id = rd_tmpabuf_write_str(
229
0
                            &tbuf, src_internal->brokers[i].rack_id);
230
0
                }
231
0
        }
232
233
234
        /* Copy TopicMetadata */
235
0
        md->topics = rd_tmpabuf_write(&tbuf, src->topics,
236
0
                                      md->topic_cnt * sizeof(*md->topics));
237
        /* Copy internal TopicMetadata */
238
0
        mdi->topics =
239
0
            rd_tmpabuf_write(&tbuf, src_internal->topics,
240
0
                             md->topic_cnt * sizeof(*src_internal->topics));
241
242
0
        for (i = 0; i < md->topic_cnt; i++) {
243
0
                int j;
244
245
0
                md->topics[i].topic =
246
0
                    rd_tmpabuf_write_str(&tbuf, src->topics[i].topic);
247
248
249
                /* Copy partitions */
250
0
                md->topics[i].partitions =
251
0
                    rd_tmpabuf_write(&tbuf, src->topics[i].partitions,
252
0
                                     md->topics[i].partition_cnt *
253
0
                                         sizeof(*md->topics[i].partitions));
254
                /* Copy internal partitions */
255
0
                mdi->topics[i].partitions = rd_tmpabuf_write(
256
0
                    &tbuf, src_internal->topics[i].partitions,
257
0
                    md->topics[i].partition_cnt *
258
0
                        sizeof(*src_internal->topics[i].partitions));
259
260
0
                for (j = 0; j < md->topics[i].partition_cnt; j++) {
261
0
                        int k;
262
0
                        char *rack;
263
0
                        rd_list_t *curr_list;
264
265
                        /* Copy replicas and ISRs */
266
0
                        md->topics[i].partitions[j].replicas = rd_tmpabuf_write(
267
0
                            &tbuf, src->topics[i].partitions[j].replicas,
268
0
                            md->topics[i].partitions[j].replica_cnt *
269
0
                                sizeof(*md->topics[i].partitions[j].replicas));
270
271
0
                        md->topics[i].partitions[j].isrs = rd_tmpabuf_write(
272
0
                            &tbuf, src->topics[i].partitions[j].isrs,
273
0
                            md->topics[i].partitions[j].isr_cnt *
274
0
                                sizeof(*md->topics[i].partitions[j].isrs));
275
276
0
                        mdi->topics[i].partitions[j].racks_cnt = 0;
277
0
                        mdi->topics[i].partitions[j].racks     = NULL;
278
279
                        /* Iterate through replicas and populate racks, if
280
                         * needed. */
281
0
                        if (!populate_racks)
282
0
                                continue;
283
284
                        /* This is quite possibly a recomputation, because we've
285
                         * already done this for the src_internal. However,
286
                         * since the racks need to point inside the tmpbuf, we
287
                         * make this calculation again. Since this is done only
288
                         * in a case of a full metadata refresh, this will be
289
                         * fairly rare. */
290
0
                        curr_list = rd_list_new(0, NULL);
291
0
                        for (k = 0; k < md->topics[i].partitions[j].replica_cnt;
292
0
                             k++) {
293
0
                                rd_kafka_metadata_broker_internal_t key = {
294
0
                                    .id = md->topics[i]
295
0
                                              .partitions[j]
296
0
                                              .replicas[k]};
297
0
                                rd_kafka_metadata_broker_internal_t *found =
298
0
                                    bsearch(
299
0
                                        &key, mdi->brokers, md->broker_cnt,
300
0
                                        sizeof(
301
0
                                            rd_kafka_metadata_broker_internal_t),
302
0
                                        rd_kafka_metadata_broker_internal_cmp);
303
0
                                if (!found || !found->rack_id)
304
0
                                        continue;
305
0
                                rd_list_add(curr_list, found->rack_id);
306
0
                        }
307
308
0
                        if (!rd_list_cnt(curr_list)) {
309
0
                                rd_list_destroy(curr_list);
310
0
                                continue;
311
0
                        }
312
313
0
                        rd_list_deduplicate(&curr_list, rd_strcmp2);
314
315
0
                        mdi->topics[i].partitions[j].racks_cnt =
316
0
                            rd_list_cnt(curr_list);
317
0
                        mdi->topics[i].partitions[j].racks = rd_tmpabuf_alloc(
318
0
                            &tbuf, sizeof(char *) * rd_list_cnt(curr_list));
319
0
                        RD_LIST_FOREACH(rack, curr_list, k) {
320
                                /* We don't copy here,`rack` points to memory
321
                                 * inside `mdi` already, and it's allocated
322
                                 * within a tmpabuf. So, the lifetime of
323
                                 * mdi->topics[i].partitions[j].racks[k] is the
324
                                 * same as the lifetime of the outer `mdi`. */
325
0
                                mdi->topics[i].partitions[j].racks[k] = rack;
326
0
                        }
327
0
                        rd_list_destroy(curr_list);
328
0
                }
329
0
        }
330
331
        /* Check for tmpabuf errors */
332
0
        if (rd_tmpabuf_failed(&tbuf))
333
0
                rd_kafka_assert(NULL, !*"metadata copy failed");
334
335
        /* Deliberately not destroying the tmpabuf since we return
336
         * its allocated memory. */
337
338
0
        return mdi;
339
0
}
340
341
342
/**
343
 * @returns a newly allocated copy of metadata \p src of size \p size
344
 */
345
rd_kafka_metadata_internal_t *
346
rd_kafka_metadata_copy(const rd_kafka_metadata_internal_t *src_internal,
347
0
                       size_t size) {
348
0
        return rd_kafka_metadata_copy_internal(src_internal, size, rd_false);
349
0
}
350
351
352
/**
353
 * @returns a newly allocated copy of metadata \p src of size \p size, with
354
 * partition racks included.
355
 */
356
rd_kafka_metadata_internal_t *rd_kafka_metadata_copy_add_racks(
357
    const rd_kafka_metadata_internal_t *src_internal,
358
0
    size_t size) {
359
0
        return rd_kafka_metadata_copy_internal(src_internal, size, rd_true);
360
0
}
361
362
/**
363
 * @brief Update topic state and information based on topic metadata.
364
 *
365
 * @param mdt Topic metadata.
366
 * @param mdit Topic internal metadata.
367
 *
368
 * @locality rdkafka main thread
369
 * @locks_acquired rd_kafka_wrlock(rk)
370
 */
371
static void rd_kafka_parse_Metadata_update_topic(
372
    rd_kafka_broker_t *rkb,
373
    const rd_kafka_metadata_topic_t *mdt,
374
0
    const rd_kafka_metadata_topic_internal_t *mdit) {
375
376
0
        rd_rkb_dbg(rkb, METADATA, "METADATA",
377
                   /* The indent below is intentional */
378
0
                   "  Topic %s with %i partitions%s%s",
379
0
                   rd_kafka_topic_name_str_safe(mdt->topic), mdt->partition_cnt,
380
0
                   mdt->err ? ": " : "",
381
0
                   mdt->err ? rd_kafka_err2str(mdt->err) : "");
382
383
        /* Ignore metadata completely for temporary errors. (issue #513)
384
         *   LEADER_NOT_AVAILABLE: Broker is rebalancing
385
         */
386
0
        if (mdt->err == RD_KAFKA_RESP_ERR_LEADER_NOT_AVAILABLE &&
387
0
            mdt->partition_cnt == 0) {
388
0
                rd_rkb_dbg(rkb, TOPIC, "METADATA",
389
0
                           "Temporary error in metadata reply for "
390
0
                           "topic %s (PartCnt %i): %s: ignoring",
391
0
                           rd_kafka_topic_name_str_safe(mdt->topic),
392
0
                           mdt->partition_cnt, rd_kafka_err2str(mdt->err));
393
0
        } else {
394
                /* Update local topic & partition state based
395
                 * on metadata */
396
0
                rd_kafka_topic_metadata_update2(rkb, mdt, mdit);
397
0
        }
398
0
}
399
400
/**
401
 * @brief Only brokers with Metadata version >= 9 have reliable leader
402
 *        epochs. Before that version, leader epoch must be treated
403
 *        as missing (-1).
404
 *
405
 * @param rkb The broker
406
 * @return Is this a broker version with reliable leader epochs?
407
 *
408
 * @locality rdkafka main thread
409
 */
410
0
rd_bool_t rd_kafka_has_reliable_leader_epochs(rd_kafka_broker_t *rkb) {
411
0
        return rd_kafka_broker_ApiVersion_at_least(rkb, RD_KAFKAP_Metadata, 9);
412
0
}
413
414
/* Populates the topic partition to rack mapping for the the topic given by
415
 * `topic_idx` in the `mdi`. It's assumed that the internal broker metadata is
416
 * already populated. */
417
static void
418
rd_kafka_populate_metadata_topic_racks(rd_tmpabuf_t *tbuf,
419
                                       size_t topic_idx,
420
0
                                       rd_kafka_metadata_internal_t *mdi) {
421
0
        rd_kafka_metadata_broker_internal_t *brokers_internal;
422
0
        size_t broker_cnt;
423
0
        int i;
424
0
        rd_kafka_metadata_topic_t *mdt;
425
0
        rd_kafka_metadata_topic_internal_t *mdti;
426
427
0
        rd_dassert(mdi->brokers);
428
0
        rd_dassert(mdi->metadata.topic_cnt > (int)topic_idx);
429
430
0
        brokers_internal = mdi->brokers;
431
0
        broker_cnt       = mdi->metadata.broker_cnt;
432
433
0
        mdt  = &mdi->metadata.topics[topic_idx];
434
0
        mdti = &mdi->topics[topic_idx];
435
436
0
        for (i = 0; i < mdt->partition_cnt; i++) {
437
0
                int j;
438
0
                rd_kafka_metadata_partition_t *mdp = &mdt->partitions[i];
439
0
                rd_kafka_metadata_partition_internal_t *mdpi =
440
0
                    &mdti->partitions[i];
441
442
0
                rd_list_t *curr_list;
443
0
                char *rack;
444
445
0
                if (mdp->replica_cnt == 0)
446
0
                        continue;
447
448
0
                curr_list =
449
0
                    rd_list_new(0, NULL); /* use a list for de-duplication */
450
0
                for (j = 0; j < mdp->replica_cnt; j++) {
451
0
                        rd_kafka_metadata_broker_internal_t key = {
452
0
                            .id = mdp->replicas[j]};
453
0
                        rd_kafka_metadata_broker_internal_t *broker =
454
0
                            bsearch(&key, brokers_internal, broker_cnt,
455
0
                                    sizeof(rd_kafka_metadata_broker_internal_t),
456
0
                                    rd_kafka_metadata_broker_internal_cmp);
457
0
                        if (!broker || !broker->rack_id)
458
0
                                continue;
459
0
                        rd_list_add(curr_list, broker->rack_id);
460
0
                }
461
0
                rd_list_deduplicate(&curr_list, rd_strcmp2);
462
463
0
                mdpi->racks_cnt = rd_list_cnt(curr_list);
464
0
                mdpi->racks =
465
0
                    rd_tmpabuf_alloc(tbuf, sizeof(char *) * mdpi->racks_cnt);
466
0
                RD_LIST_FOREACH(rack, curr_list, j) {
467
0
                        mdpi->racks[j] = rack; /* Don't copy, rack points inside
468
                                                  tbuf already*/
469
0
                }
470
0
                rd_list_destroy(curr_list);
471
0
        }
472
0
}
473
474
/**
475
 * @brief Decommission brokers that are not in the metadata.
476
 */
477
static void rd_kafka_metadata_decommission_unavailable_brokers(
478
    rd_kafka_t *rk,
479
    rd_kafka_metadata_t *md,
480
0
    rd_kafka_broker_t *rkb_current) {
481
0
        rd_kafka_broker_t *rkb;
482
0
        rd_bool_t has_learned_brokers = rd_false;
483
0
        rd_list_t brokers_to_decommission;
484
0
        int i;
485
486
0
        rd_kafka_wrlock(rk);
487
0
        TAILQ_FOREACH(rkb, &rk->rk_brokers, rkb_link) {
488
0
                if (rkb->rkb_source == RD_KAFKA_LEARNED) {
489
0
                        has_learned_brokers = rd_true;
490
0
                        break;
491
0
                }
492
0
        }
493
0
        if (!has_learned_brokers) {
494
0
                rd_kafka_wrunlock(rk);
495
0
                return;
496
0
        }
497
498
0
        rd_list_init(&brokers_to_decommission,
499
0
                     rd_atomic32_get(&rk->rk_broker_cnt), NULL);
500
0
        TAILQ_FOREACH(rkb, &rk->rk_brokers, rkb_link) {
501
0
                rd_bool_t purge_broker;
502
503
0
                if (rkb->rkb_source == RD_KAFKA_LOGICAL)
504
0
                        continue;
505
506
0
                purge_broker = rd_true;
507
0
                if (rkb->rkb_source == RD_KAFKA_LEARNED) {
508
                        /* Don't purge the broker if it's available in
509
                         * metadata. */
510
0
                        for (i = 0; i < md->broker_cnt; i++) {
511
0
                                if (md->brokers[i].id == rkb->rkb_nodeid) {
512
0
                                        purge_broker = rd_false;
513
0
                                        break;
514
0
                                }
515
0
                        }
516
0
                }
517
518
0
                if (!purge_broker)
519
0
                        continue;
520
521
                /* Don't try to decommission already decommissioning brokers
522
                 * otherwise they could be already destroyed when
523
                 * `rd_kafka_broker_decommission` is called below. */
524
0
                if (rd_list_find(&rk->wait_decommissioned_brokers, rkb,
525
0
                                 rd_list_cmp_ptr) != NULL)
526
0
                        continue;
527
528
0
                rd_list_add(&brokers_to_decommission, rkb);
529
0
        }
530
0
        RD_LIST_FOREACH(rkb, &brokers_to_decommission, i) {
531
0
                rd_kafka_broker_decommission(rk, rkb,
532
0
                                             &rk->wait_decommissioned_thrds);
533
0
                rd_list_add(&rk->wait_decommissioned_brokers, rkb);
534
0
        }
535
0
        rd_list_destroy(&brokers_to_decommission);
536
0
        rd_kafka_wrunlock(rk);
537
0
}
538
539
/* Internal implementation for parsing Metadata. */
540
static rd_kafka_resp_err_t
541
rd_kafka_parse_Metadata0(rd_kafka_broker_t *rkb,
542
                         rd_kafka_buf_t *request,
543
                         rd_kafka_buf_t *rkbuf,
544
                         rd_kafka_metadata_internal_t **mdip,
545
                         rd_list_t *request_topics,
546
0
                         const char *reason) {
547
0
        rd_kafka_t *rk = rkb->rkb_rk;
548
0
        int i, j, k;
549
0
        rd_tmpabuf_t tbuf;
550
0
        rd_kafka_metadata_internal_t *mdi = NULL;
551
0
        rd_kafka_metadata_t *md           = NULL;
552
0
        size_t rkb_namelen;
553
0
        const int log_decode_errors  = LOG_ERR;
554
0
        rd_list_t *missing_topics    = NULL;
555
0
        rd_list_t *missing_topic_ids = NULL;
556
557
0
        const rd_list_t *requested_topics    = request_topics;
558
0
        const rd_list_t *requested_topic_ids = NULL;
559
0
        rd_bool_t all_topics                 = rd_false;
560
0
        rd_bool_t cgrp_update                = rd_false;
561
0
        rd_bool_t has_reliable_leader_epochs =
562
0
            rd_kafka_has_reliable_leader_epochs(rkb);
563
0
        int ApiVersion                = rkbuf->rkbuf_reqhdr.ApiVersion;
564
0
        rd_kafkap_str_t cluster_id    = RD_ZERO_INIT;
565
0
        int32_t controller_id         = -1;
566
0
        rd_kafka_resp_err_t err       = RD_KAFKA_RESP_ERR_NO_ERROR;
567
0
        int broker_changes            = 0;
568
0
        int cache_changes             = 0;
569
0
        int cgrp_subscription_version = -1;
570
0
        int16_t ErrorCode             = 0;
571
572
        /* If client rack is present, the metadata cache (topic or full) needs
573
         * to contain the partition to rack map. */
574
0
        rd_bool_t has_client_rack = rk->rk_conf.client_rack &&
575
0
                                    RD_KAFKAP_STR_LEN(rk->rk_conf.client_rack);
576
0
        rd_bool_t compute_racks = has_client_rack;
577
578
0
        if (request) {
579
0
                requested_topics    = request->rkbuf_u.Metadata.topics;
580
0
                requested_topic_ids = request->rkbuf_u.Metadata.topic_ids;
581
0
                all_topics          = request->rkbuf_u.Metadata.all_topics;
582
0
                cgrp_update =
583
0
                    request->rkbuf_u.Metadata.cgrp_update && rk->rk_cgrp;
584
0
                compute_racks |= request->rkbuf_u.Metadata.force_racks;
585
0
                cgrp_subscription_version =
586
0
                    request->rkbuf_u.Metadata.cgrp_subscription_version;
587
0
        }
588
589
        /* If there's reason is NULL, set it to a human-readable string. */
590
0
        if (!reason)
591
0
                reason = "(no reason)";
592
593
        /* Ignore metadata updates when terminating */
594
0
        if (rd_kafka_terminating(rkb->rkb_rk)) {
595
0
                err = RD_KAFKA_RESP_ERR__DESTROY;
596
0
                goto done;
597
0
        }
598
599
0
        rd_kafka_assert(NULL, thrd_is_current(rk->rk_thread));
600
601
        /* Remove topics from missing_topics as they are seen in Metadata. */
602
0
        if (requested_topics)
603
0
                missing_topics =
604
0
                    rd_list_copy(requested_topics, rd_list_string_copy, NULL);
605
0
        if (requested_topic_ids)
606
0
                missing_topic_ids =
607
0
                    rd_list_copy(requested_topic_ids, rd_list_Uuid_copy, NULL);
608
609
0
        rd_kafka_broker_lock(rkb);
610
0
        rkb_namelen = strlen(rkb->rkb_name) + 1;
611
        /* We assume that the marshalled representation is
612
         * no more than 4 times larger than the wire representation.
613
         * This is increased to 5 times in case if we want to compute partition
614
         * to rack mapping. */
615
0
        rd_tmpabuf_new(&tbuf, 0, rd_false /*dont assert on fail*/);
616
0
        rd_tmpabuf_add_alloc(&tbuf, sizeof(*mdi));
617
0
        rd_tmpabuf_add_alloc(&tbuf, rkb_namelen);
618
0
        rd_tmpabuf_add_alloc(&tbuf, rkbuf->rkbuf_totlen *
619
0
                                        (4 + (compute_racks ? 1 : 0)));
620
621
0
        rd_tmpabuf_finalize(&tbuf);
622
623
0
        if (!(mdi = rd_tmpabuf_alloc(&tbuf, sizeof(*mdi)))) {
624
0
                rd_kafka_broker_unlock(rkb);
625
0
                err = RD_KAFKA_RESP_ERR__CRIT_SYS_RESOURCE;
626
0
                goto err;
627
0
        }
628
629
0
        md                 = &mdi->metadata;
630
0
        md->orig_broker_id = rkb->rkb_nodeid;
631
0
        md->orig_broker_name =
632
0
            rd_tmpabuf_write(&tbuf, rkb->rkb_name, rkb_namelen);
633
0
        rd_kafka_broker_unlock(rkb);
634
635
0
        if (ApiVersion >= 3)
636
0
                rd_kafka_buf_read_throttle_time(rkbuf);
637
638
        /* Read Brokers */
639
0
        rd_kafka_buf_read_arraycnt(rkbuf, &md->broker_cnt,
640
0
                                   RD_KAFKAP_BROKERS_MAX);
641
642
0
        if (!(md->brokers = rd_tmpabuf_alloc(&tbuf, md->broker_cnt *
643
0
                                                        sizeof(*md->brokers))))
644
0
                rd_kafka_buf_parse_fail(rkbuf,
645
0
                                        "%d brokers: tmpabuf memory shortage",
646
0
                                        md->broker_cnt);
647
648
0
        if (!(mdi->brokers = rd_tmpabuf_alloc(
649
0
                  &tbuf, md->broker_cnt * sizeof(*mdi->brokers))))
650
0
                rd_kafka_buf_parse_fail(
651
0
                    rkbuf, "%d internal brokers: tmpabuf memory shortage",
652
0
                    md->broker_cnt);
653
654
0
        if (!(mdi->brokers_sorted = rd_tmpabuf_alloc(
655
0
                  &tbuf, md->broker_cnt * sizeof(*mdi->brokers_sorted))))
656
0
                rd_kafka_buf_parse_fail(
657
0
                    rkbuf, "%d sorted brokers: tmpabuf memory shortage",
658
0
                    md->broker_cnt);
659
660
0
        for (i = 0; i < md->broker_cnt; i++) {
661
0
                rd_kafka_buf_read_i32a(rkbuf, md->brokers[i].id);
662
0
                rd_kafka_buf_read_str_tmpabuf(rkbuf, &tbuf,
663
0
                                              md->brokers[i].host);
664
0
                rd_kafka_buf_read_i32a(rkbuf, md->brokers[i].port);
665
666
0
                mdi->brokers[i].id = md->brokers[i].id;
667
0
                if (ApiVersion >= 1) {
668
0
                        rd_kafka_buf_read_str_tmpabuf(rkbuf, &tbuf,
669
0
                                                      mdi->brokers[i].rack_id);
670
0
                } else {
671
0
                        mdi->brokers[i].rack_id = NULL;
672
0
                }
673
674
0
                rd_kafka_buf_skip_tags(rkbuf);
675
0
        }
676
677
0
        mdi->cluster_id = NULL;
678
0
        if (ApiVersion >= 2) {
679
0
                rd_kafka_buf_read_str(rkbuf, &cluster_id);
680
0
                if (cluster_id.str)
681
0
                        mdi->cluster_id =
682
0
                            rd_tmpabuf_write_str(&tbuf, cluster_id.str);
683
0
        }
684
685
0
        mdi->controller_id = -1;
686
0
        if (ApiVersion >= 1) {
687
0
                rd_kafka_buf_read_i32(rkbuf, &controller_id);
688
0
                mdi->controller_id = controller_id;
689
0
                rd_rkb_dbg(rkb, METADATA, "METADATA",
690
0
                           "ClusterId: %.*s, ControllerId: %" PRId32,
691
0
                           RD_KAFKAP_STR_PR(&cluster_id), controller_id);
692
0
        }
693
694
0
        qsort(mdi->brokers, md->broker_cnt, sizeof(mdi->brokers[i]),
695
0
              rd_kafka_metadata_broker_internal_cmp);
696
0
        memcpy(mdi->brokers_sorted, md->brokers,
697
0
               sizeof(*mdi->brokers_sorted) * md->broker_cnt);
698
0
        qsort(mdi->brokers_sorted, md->broker_cnt, sizeof(*mdi->brokers_sorted),
699
0
              rd_kafka_metadata_broker_cmp);
700
701
        /* Read TopicMetadata */
702
0
        rd_kafka_buf_read_arraycnt(rkbuf, &md->topic_cnt, RD_KAFKAP_TOPICS_MAX);
703
0
        rd_rkb_dbg(rkb, METADATA, "METADATA", "%i brokers, %i topics",
704
0
                   md->broker_cnt, md->topic_cnt);
705
706
0
        if (!(md->topics =
707
0
                  rd_tmpabuf_alloc(&tbuf, md->topic_cnt * sizeof(*md->topics))))
708
0
                rd_kafka_buf_parse_fail(
709
0
                    rkbuf, "%d topics: tmpabuf memory shortage", md->topic_cnt);
710
711
0
        if (!(mdi->topics = rd_tmpabuf_alloc(&tbuf, md->topic_cnt *
712
0
                                                        sizeof(*mdi->topics))))
713
0
                rd_kafka_buf_parse_fail(
714
0
                    rkbuf, "%d internal topics: tmpabuf memory shortage",
715
0
                    md->topic_cnt);
716
717
0
        for (i = 0; i < md->topic_cnt; i++) {
718
0
                rd_kafka_buf_read_i16a(rkbuf, md->topics[i].err);
719
0
                rd_kafka_buf_read_str_tmpabuf(rkbuf, &tbuf,
720
0
                                              md->topics[i].topic);
721
722
0
                if (ApiVersion >= 10) {
723
0
                        rd_kafka_buf_read_uuid(rkbuf, &mdi->topics[i].topic_id);
724
0
                } else {
725
0
                        mdi->topics[i].topic_id = RD_KAFKA_UUID_ZERO;
726
0
                }
727
728
0
                if (ApiVersion >= 1)
729
0
                        rd_kafka_buf_read_bool(rkbuf,
730
0
                                               &mdi->topics[i].is_internal);
731
732
                /* PartitionMetadata */
733
0
                rd_kafka_buf_read_arraycnt(rkbuf, &md->topics[i].partition_cnt,
734
0
                                           RD_KAFKAP_PARTITIONS_MAX);
735
736
0
                if (!(md->topics[i].partitions = rd_tmpabuf_alloc(
737
0
                          &tbuf, md->topics[i].partition_cnt *
738
0
                                     sizeof(*md->topics[i].partitions))))
739
0
                        rd_kafka_buf_parse_fail(
740
0
                            rkbuf,
741
0
                            "%s: %d partitions: "
742
0
                            "tmpabuf memory shortage",
743
0
                            rd_kafka_topic_name_str_safe(md->topics[i].topic),
744
0
                            md->topics[i].partition_cnt);
745
746
0
                if (!(mdi->topics[i].partitions = rd_tmpabuf_alloc(
747
0
                          &tbuf, md->topics[i].partition_cnt *
748
0
                                     sizeof(*mdi->topics[i].partitions))))
749
0
                        rd_kafka_buf_parse_fail(
750
0
                            rkbuf,
751
0
                            "%s: %d internal partitions: "
752
0
                            "tmpabuf memory shortage",
753
0
                            rd_kafka_topic_name_str_safe(md->topics[i].topic),
754
0
                            md->topics[i].partition_cnt);
755
756
757
0
                for (j = 0; j < md->topics[i].partition_cnt; j++) {
758
0
                        rd_kafka_buf_read_i16a(rkbuf,
759
0
                                               md->topics[i].partitions[j].err);
760
0
                        rd_kafka_buf_read_i32a(rkbuf,
761
0
                                               md->topics[i].partitions[j].id);
762
0
                        rd_kafka_buf_read_i32a(
763
0
                            rkbuf, md->topics[i].partitions[j].leader);
764
765
0
                        mdi->topics[i].partitions[j].id =
766
0
                            md->topics[i].partitions[j].id;
767
0
                        if (ApiVersion >= 7) {
768
0
                                rd_kafka_buf_read_i32(
769
0
                                    rkbuf,
770
0
                                    &mdi->topics[i].partitions[j].leader_epoch);
771
0
                                if (!has_reliable_leader_epochs)
772
0
                                        mdi->topics[i]
773
0
                                            .partitions[j]
774
0
                                            .leader_epoch = -1;
775
0
                        } else {
776
0
                                mdi->topics[i].partitions[j].leader_epoch = -1;
777
0
                        }
778
0
                        mdi->topics[i].partitions[j].racks_cnt = 0;
779
0
                        mdi->topics[i].partitions[j].racks     = NULL;
780
781
                        /* Replicas */
782
0
                        rd_kafka_buf_read_arraycnt(
783
0
                            rkbuf, &md->topics[i].partitions[j].replica_cnt,
784
0
                            RD_KAFKAP_BROKERS_MAX);
785
786
0
                        if (!(md->topics[i].partitions[j].replicas =
787
0
                                  rd_tmpabuf_alloc(
788
0
                                      &tbuf,
789
0
                                      md->topics[i].partitions[j].replica_cnt *
790
0
                                          sizeof(*md->topics[i]
791
0
                                                      .partitions[j]
792
0
                                                      .replicas))))
793
0
                                rd_kafka_buf_parse_fail(
794
0
                                    rkbuf,
795
0
                                    "%s [%" PRId32
796
0
                                    "]: %d replicas: "
797
0
                                    "tmpabuf memory shortage",
798
0
                                    rd_kafka_topic_name_str_safe(
799
0
                                        md->topics[i].topic),
800
0
                                    md->topics[i].partitions[j].id,
801
0
                                    md->topics[i].partitions[j].replica_cnt);
802
803
804
0
                        for (k = 0; k < md->topics[i].partitions[j].replica_cnt;
805
0
                             k++)
806
0
                                rd_kafka_buf_read_i32a(
807
0
                                    rkbuf,
808
0
                                    md->topics[i].partitions[j].replicas[k]);
809
810
                        /* Isrs */
811
0
                        rd_kafka_buf_read_arraycnt(
812
0
                            rkbuf, &md->topics[i].partitions[j].isr_cnt,
813
0
                            RD_KAFKAP_BROKERS_MAX);
814
815
0
                        if (!(md->topics[i]
816
0
                                  .partitions[j]
817
0
                                  .isrs = rd_tmpabuf_alloc(
818
0
                                  &tbuf,
819
0
                                  md->topics[i].partitions[j].isr_cnt *
820
0
                                      sizeof(
821
0
                                          *md->topics[i].partitions[j].isrs))))
822
0
                                rd_kafka_buf_parse_fail(
823
0
                                    rkbuf,
824
0
                                    "%s [%" PRId32
825
0
                                    "]: %d isrs: "
826
0
                                    "tmpabuf memory shortage",
827
0
                                    rd_kafka_topic_name_str_safe(
828
0
                                        md->topics[i].topic),
829
0
                                    md->topics[i].partitions[j].id,
830
0
                                    md->topics[i].partitions[j].isr_cnt);
831
832
833
0
                        for (k = 0; k < md->topics[i].partitions[j].isr_cnt;
834
0
                             k++)
835
0
                                rd_kafka_buf_read_i32a(
836
0
                                    rkbuf, md->topics[i].partitions[j].isrs[k]);
837
838
0
                        if (ApiVersion >= 5) {
839
                                /* OfflineReplicas int32 array (ignored) */
840
0
                                int32_t offline_replicas_cnt;
841
842
                                /* #OfflineReplicas */
843
0
                                rd_kafka_buf_read_arraycnt(
844
0
                                    rkbuf, &offline_replicas_cnt,
845
0
                                    RD_KAFKAP_BROKERS_MAX);
846
0
                                rd_kafka_buf_skip(rkbuf, offline_replicas_cnt *
847
0
                                                             sizeof(int32_t));
848
0
                        }
849
850
0
                        rd_kafka_buf_skip_tags(rkbuf);
851
0
                }
852
853
0
                mdi->topics[i].topic_authorized_operations = -1;
854
0
                if (ApiVersion >= 8) {
855
0
                        int32_t TopicAuthorizedOperations;
856
                        /* TopicAuthorizedOperations */
857
0
                        rd_kafka_buf_read_i32(rkbuf,
858
0
                                              &TopicAuthorizedOperations);
859
0
                        mdi->topics[i].topic_authorized_operations =
860
0
                            TopicAuthorizedOperations;
861
0
                }
862
863
0
                rd_kafka_buf_skip_tags(rkbuf);
864
0
        }
865
866
0
        mdi->cluster_authorized_operations = -1;
867
0
        if (ApiVersion >= 8 && ApiVersion <= 10) {
868
0
                int32_t ClusterAuthorizedOperations;
869
                /* ClusterAuthorizedOperations */
870
0
                rd_kafka_buf_read_i32(rkbuf, &ClusterAuthorizedOperations);
871
0
                mdi->cluster_authorized_operations =
872
0
                    ClusterAuthorizedOperations;
873
0
        }
874
875
0
        if (ApiVersion >= 13) {
876
0
                rd_kafka_buf_read_i16(rkbuf, &ErrorCode);
877
0
        }
878
879
0
        rd_kafka_buf_skip_tags(rkbuf);
880
881
0
        if (ErrorCode) {
882
0
                rd_rkb_dbg(rkb, METADATA, "METADATA",
883
0
                           "Metadata response: received top level "
884
0
                           "error code %" PRId16 ": %s",
885
0
                           ErrorCode, rd_kafka_err2str(ErrorCode));
886
0
                err = ErrorCode;
887
0
                goto err;
888
0
        }
889
890
        /* Entire Metadata response now parsed without errors:
891
         * update our internal state according to the response. */
892
893
0
        if (md->broker_cnt == 0 && md->topic_cnt == 0) {
894
0
                rd_rkb_dbg(rkb, METADATA, "METADATA",
895
0
                           "No brokers or topics in metadata: should retry");
896
0
                err = RD_KAFKA_RESP_ERR__PARTIAL;
897
0
                goto err;
898
0
        }
899
900
        /* Update our list of brokers. */
901
0
        for (i = 0; i < md->broker_cnt; i++) {
902
0
                rd_rkb_dbg(rkb, METADATA, "METADATA",
903
0
                           "  Broker #%i/%i: %s:%i NodeId %" PRId32, i,
904
0
                           md->broker_cnt, md->brokers[i].host,
905
0
                           md->brokers[i].port, md->brokers[i].id);
906
0
                rd_kafka_broker_update(rkb->rkb_rk, rkb->rkb_proto,
907
0
                                       &md->brokers[i], NULL);
908
0
        }
909
910
0
        rd_kafka_metadata_decommission_unavailable_brokers(rk, md, rkb);
911
912
0
        for (i = 0; i < md->topic_cnt; i++) {
913
914
                /* Ignore topics in blacklist. Skip when the broker
915
                 * returned a NULL topic name (e.g. UNKNOWN_TOPIC_ID
916
                 * response from a by-id Metadata request) — the
917
                 * blacklist matches on name only, so there is nothing
918
                 * to compare against. */
919
0
                if (rkb->rkb_rk->rk_conf.topic_blacklist &&
920
0
                    md->topics[i].topic &&
921
0
                    rd_kafka_pattern_match(rkb->rkb_rk->rk_conf.topic_blacklist,
922
0
                                           md->topics[i].topic)) {
923
0
                        rd_rkb_dbg(rkb, TOPIC | RD_KAFKA_DBG_METADATA,
924
0
                                   "BLACKLIST",
925
0
                                   "Ignoring blacklisted topic \"%s\" "
926
0
                                   "in metadata",
927
0
                                   md->topics[i].topic);
928
0
                        continue;
929
0
                }
930
931
                /* Sort partitions by partition id */
932
0
                qsort(md->topics[i].partitions, md->topics[i].partition_cnt,
933
0
                      sizeof(*md->topics[i].partitions),
934
0
                      rd_kafka_metadata_partition_id_cmp);
935
0
                qsort(mdi->topics[i].partitions, md->topics[i].partition_cnt,
936
0
                      sizeof(*mdi->topics[i].partitions),
937
0
                      rd_kafka_metadata_partition_internal_cmp);
938
939
0
                if (compute_racks)
940
0
                        rd_kafka_populate_metadata_topic_racks(&tbuf, i, mdi);
941
942
                /* Update topic state based on the topic metadata */
943
0
                rd_kafka_parse_Metadata_update_topic(rkb, &md->topics[i],
944
0
                                                     &mdi->topics[i]);
945
946
                /* Skip the by-name dedup if the response carries a
947
                 * NULL topic name; strcmp(NULL, ...) is UB. The
948
                 * missing_topics list is keyed by name, so a
949
                 * NULL-name response cannot match any entry. */
950
0
                if (requested_topics && md->topics[i].topic)
951
0
                        rd_list_free_cb(missing_topics,
952
0
                                        rd_list_remove_cmp(missing_topics,
953
0
                                                           md->topics[i].topic,
954
0
                                                           (void *)strcmp));
955
0
                if (requested_topic_ids)
956
0
                        rd_list_free_cb(
957
0
                            missing_topic_ids,
958
0
                            rd_list_remove_cmp(missing_topic_ids,
959
0
                                               &mdi->topics[i].topic_id,
960
0
                                               (void *)rd_kafka_Uuid_ptr_cmp));
961
                /* Only update cache when not asking
962
                 * for all topics or cache entry
963
                 * already exists. */
964
0
                rd_kafka_wrlock(rk);
965
0
                cache_changes += rd_kafka_metadata_cache_topic_update(
966
0
                    rk, &md->topics[i], &mdi->topics[i],
967
0
                    rd_false /*propagate later*/,
968
                    /* use has_client_rack rather than
969
                    compute_racks. We need cached rack ids
970
                    only in case we need to rejoin the group
971
                    if they change and client.rack is set
972
                    (KIP-881). */
973
0
                    has_client_rack, rd_kafka_has_reliable_leader_epochs(rkb));
974
0
                rd_kafka_wrunlock(rk);
975
0
        }
976
977
        /* Requested topics not seen in metadata? Propogate to topic code. */
978
0
        if (missing_topics) {
979
0
                char *topic;
980
0
                rd_rkb_dbg(rkb, TOPIC, "METADATA",
981
0
                           "%d/%d requested topic(s) seen in metadata"
982
0
                           " (lookup by name)",
983
0
                           rd_list_cnt(requested_topics) -
984
0
                               rd_list_cnt(missing_topics),
985
0
                           rd_list_cnt(requested_topics));
986
0
                for (i = 0; i < rd_list_cnt(missing_topics); i++)
987
0
                        rd_rkb_dbg(rkb, TOPIC, "METADATA", "wanted %s",
988
0
                                   (char *)(missing_topics->rl_elems[i]));
989
0
                RD_LIST_FOREACH(topic, missing_topics, i) {
990
0
                        rd_kafka_topic_t *rkt;
991
992
0
                        rkt =
993
0
                            rd_kafka_topic_find(rkb->rkb_rk, topic, 1 /*lock*/);
994
0
                        if (rkt) {
995
                                /* Received metadata response contained no
996
                                 * information about topic 'rkt' and thus
997
                                 * indicates the topic is not available in the
998
                                 *  cluster.
999
                                 * Mark the topic as non-existent */
1000
0
                                rd_kafka_topic_wrlock(rkt);
1001
0
                                rd_kafka_topic_set_notexists(
1002
0
                                    rkt, RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC);
1003
0
                                rd_kafka_topic_wrunlock(rkt);
1004
1005
0
                                rd_kafka_topic_destroy0(rkt);
1006
0
                        }
1007
0
                }
1008
0
        }
1009
0
        if (missing_topic_ids) {
1010
0
                rd_kafka_Uuid_t *topic_id;
1011
0
                rd_rkb_dbg(rkb, TOPIC, "METADATA",
1012
0
                           "%d/%d requested topic(s) seen in metadata"
1013
0
                           " (lookup by id)",
1014
0
                           rd_list_cnt(requested_topic_ids) -
1015
0
                               rd_list_cnt(missing_topic_ids),
1016
0
                           rd_list_cnt(requested_topic_ids));
1017
0
                for (i = 0; i < rd_list_cnt(missing_topic_ids); i++) {
1018
0
                        rd_kafka_Uuid_t *missing_topic_id =
1019
0
                            missing_topic_ids->rl_elems[i];
1020
0
                        rd_rkb_dbg(rkb, TOPIC, "METADATA", "wanted %s",
1021
0
                                   rd_kafka_Uuid_base64str(missing_topic_id));
1022
0
                }
1023
0
                RD_LIST_FOREACH(topic_id, missing_topic_ids, i) {
1024
0
                        rd_kafka_topic_t *rkt;
1025
1026
0
                        rd_kafka_rdlock(rk);
1027
0
                        rkt = rd_kafka_topic_find_by_topic_id(rkb->rkb_rk,
1028
0
                                                              *topic_id);
1029
0
                        rd_kafka_rdunlock(rk);
1030
0
                        if (rkt) {
1031
                                /* Received metadata response contained no
1032
                                 * information about topic 'rkt' and thus
1033
                                 * indicates the topic is not available in the
1034
                                 *  cluster.
1035
                                 * Mark the topic as non-existent */
1036
0
                                rd_kafka_topic_wrlock(rkt);
1037
0
                                rd_kafka_topic_set_notexists(
1038
0
                                    rkt, RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC);
1039
0
                                rd_kafka_topic_wrunlock(rkt);
1040
1041
0
                                rd_kafka_topic_destroy0(rkt);
1042
0
                        }
1043
0
                }
1044
0
        }
1045
1046
1047
0
        rd_kafka_wrlock(rkb->rkb_rk);
1048
1049
0
        rkb->rkb_rk->rk_ts_metadata = rd_clock();
1050
1051
        /* Update cached cluster id. */
1052
0
        if (RD_KAFKAP_STR_LEN(&cluster_id) > 0 &&
1053
0
            (!rk->rk_clusterid ||
1054
0
             rd_kafkap_str_cmp_str(&cluster_id, rk->rk_clusterid))) {
1055
0
                rd_rkb_dbg(rkb, BROKER | RD_KAFKA_DBG_GENERIC, "CLUSTERID",
1056
0
                           "ClusterId update \"%s\" -> \"%.*s\"",
1057
0
                           rk->rk_clusterid ? rk->rk_clusterid : "",
1058
0
                           RD_KAFKAP_STR_PR(&cluster_id));
1059
0
                if (rk->rk_clusterid) {
1060
0
                        rd_kafka_log(rk, LOG_WARNING, "CLUSTERID",
1061
0
                                     "Broker %s reports different ClusterId "
1062
0
                                     "\"%.*s\" than previously known \"%s\": "
1063
0
                                     "a client must not be simultaneously "
1064
0
                                     "connected to multiple clusters",
1065
0
                                     rd_kafka_broker_name(rkb),
1066
0
                                     RD_KAFKAP_STR_PR(&cluster_id),
1067
0
                                     rk->rk_clusterid);
1068
0
                        rd_free(rk->rk_clusterid);
1069
0
                }
1070
1071
0
                rk->rk_clusterid = RD_KAFKAP_STR_DUP(&cluster_id);
1072
                /* rd_kafka_clusterid() waits for a cache update even though
1073
                 * the clusterid is not in the cache itself. (#3620) */
1074
0
                cache_changes++;
1075
0
        }
1076
1077
        /* Update controller id. */
1078
0
        if (rkb->rkb_rk->rk_controllerid != controller_id) {
1079
0
                rd_rkb_dbg(rkb, BROKER, "CONTROLLERID",
1080
0
                           "ControllerId update %" PRId32 " -> %" PRId32,
1081
0
                           rkb->rkb_rk->rk_controllerid, controller_id);
1082
0
                rkb->rkb_rk->rk_controllerid = controller_id;
1083
0
                broker_changes++;
1084
0
        }
1085
1086
0
        if (all_topics) {
1087
0
                rkb->rkb_rk->rk_ts_full_metadata = rkb->rkb_rk->rk_ts_metadata;
1088
0
                rd_rkb_dbg(rkb, METADATA, "METADATA",
1089
0
                           "Cached full metadata with "
1090
0
                           " %d topic(s): %s",
1091
0
                           md->topic_cnt, reason);
1092
0
        }
1093
        /* Remove cache hints for the originally requested topics. */
1094
0
        if (requested_topics)
1095
0
                rd_kafka_metadata_cache_purge_hints(rk, requested_topics);
1096
0
        if (requested_topic_ids)
1097
0
                rd_kafka_metadata_cache_purge_hints_by_id(rk,
1098
0
                                                          requested_topic_ids);
1099
1100
0
        if (cache_changes) {
1101
0
                rd_kafka_metadata_cache_propagate_changes(rk);
1102
0
                rd_kafka_metadata_cache_expiry_start(rk);
1103
0
        }
1104
1105
0
        rd_kafka_wrunlock(rkb->rkb_rk);
1106
1107
0
        if (broker_changes) {
1108
                /* Broadcast broker metadata changes to listeners. */
1109
0
                rd_kafka_brokers_broadcast_state_change(rkb->rkb_rk);
1110
0
        }
1111
1112
        /* Check if cgrp effective subscription is affected by
1113
         * new topic metadata.
1114
         * Ignore if this was a broker-only refresh (no topics), or
1115
         * the request was from the partition assignor (!cgrp_update)
1116
         * which may contain only a sub-set of the subscribed topics (namely
1117
         * the effective subscription of available topics) as to not
1118
         * propagate non-included topics as non-existent. */
1119
0
        if (cgrp_update &&
1120
0
            (all_topics ||
1121
0
             ((requested_topics || requested_topic_ids) &&
1122
0
              rd_kafka_cgrp_same_subscription_version(
1123
0
                  rkb->rkb_rk->rk_cgrp, cgrp_subscription_version))))
1124
0
                rd_kafka_cgrp_metadata_update_check(rkb->rkb_rk->rk_cgrp,
1125
0
                                                    rd_true /*do join*/);
1126
1127
0
        if (rk->rk_cgrp && RD_KAFKA_IS_SHARE_CONSUMER(rk))
1128
0
                rd_kafka_share_topic_err_propagate(rk->rk_cgrp);
1129
1130
0
        if (rk->rk_type == RD_KAFKA_CONSUMER && rk->rk_cgrp &&
1131
0
            rk->rk_cgrp->rkcg_group_protocol == RD_KAFKA_GROUP_PROTOCOL_CLASSIC)
1132
0
                rd_interval_reset(&rk->rk_cgrp->rkcg_join_intvl);
1133
1134
        /* Try to acquire a Producer ID from this broker if we
1135
         * don't have one. */
1136
0
        if (rd_kafka_is_idempotent(rkb->rkb_rk)) {
1137
0
                rd_kafka_wrlock(rkb->rkb_rk);
1138
0
                rd_kafka_idemp_pid_fsm(rkb->rkb_rk);
1139
0
                rd_kafka_wrunlock(rkb->rkb_rk);
1140
0
        }
1141
1142
0
done:
1143
0
        if (missing_topics)
1144
0
                rd_list_destroy(missing_topics);
1145
0
        if (missing_topic_ids)
1146
0
                rd_list_destroy(missing_topic_ids);
1147
1148
        /* This metadata request was triggered by someone wanting
1149
         * the metadata information back as a reply, so send that reply now.
1150
         * In this case we must not rd_free the metadata memory here,
1151
         * the requestee will do.
1152
         * The tbuf is explicitly not destroyed as we return its memory
1153
         * to the caller. */
1154
0
        *mdip = mdi;
1155
1156
0
        return RD_KAFKA_RESP_ERR_NO_ERROR;
1157
1158
0
err_parse:
1159
0
        err = rkbuf->rkbuf_err;
1160
0
err:
1161
0
        if (requested_topics) {
1162
                /* Failed requests shall purge cache hints for
1163
                 * the requested topics. */
1164
0
                rd_kafka_wrlock(rkb->rkb_rk);
1165
0
                rd_kafka_metadata_cache_purge_hints(rk, requested_topics);
1166
0
                rd_kafka_wrunlock(rkb->rkb_rk);
1167
0
        }
1168
0
        if (requested_topic_ids) {
1169
                /* Failed requests shall purge cache hints for
1170
                 * the requested topics. */
1171
0
                rd_kafka_wrlock(rkb->rkb_rk);
1172
0
                rd_kafka_metadata_cache_purge_hints_by_id(rk,
1173
0
                                                          requested_topic_ids);
1174
0
                rd_kafka_wrunlock(rkb->rkb_rk);
1175
0
        }
1176
1177
0
        if (missing_topics)
1178
0
                rd_list_destroy(missing_topics);
1179
0
        if (missing_topic_ids)
1180
0
                rd_list_destroy(missing_topic_ids);
1181
0
        rd_tmpabuf_destroy(&tbuf);
1182
1183
0
        return err;
1184
0
}
1185
1186
1187
/**
1188
 * @brief Handle a Metadata response message.
1189
 *
1190
 * @param request Initial Metadata request, containing the topic information.
1191
 *                Must not be NULL.
1192
 *                We require the topic information while parsing to make sure
1193
 *                that there are no missing topics.
1194
 * @param mdip A pointer to (rd_kafka_metadata_internal_t *) into which the
1195
 *             metadata will be marshalled (set to NULL on error.)
1196
 *
1197
 * @returns an error code on parse failure, else NO_ERROR.
1198
 *
1199
 * @locality rdkafka main thread
1200
 */
1201
rd_kafka_resp_err_t
1202
rd_kafka_parse_Metadata(rd_kafka_broker_t *rkb,
1203
                        rd_kafka_buf_t *request,
1204
                        rd_kafka_buf_t *rkbuf,
1205
0
                        rd_kafka_metadata_internal_t **mdip) {
1206
0
        const char *reason = request->rkbuf_u.Metadata.reason;
1207
0
        return rd_kafka_parse_Metadata0(rkb, request, rkbuf, mdip, NULL,
1208
0
                                        reason);
1209
0
}
1210
1211
/**
1212
 * @brief Handle a Metadata response message for admin requests.
1213
 *
1214
 * @param request_topics List containing topics in Metadata request. Must not
1215
 *                       be NULL. It is more convenient in the Admin flow to
1216
 *                       preserve the topic names rather than the initial
1217
 *                       Metadata request.
1218
 *                       We require the topic information while parsing to make
1219
 *                      sure that there are no missing topics.
1220
 * @param mdip A pointer to (rd_kafka_metadata_internal_t *) into which the
1221
 *             metadata will be marshalled (set to NULL on error.)
1222
 *
1223
 * @returns an error code on parse failure, else NO_ERROR.
1224
 *
1225
 * @locality rdkafka main thread
1226
 */
1227
rd_kafka_resp_err_t
1228
rd_kafka_parse_Metadata_admin(rd_kafka_broker_t *rkb,
1229
                              rd_kafka_buf_t *rkbuf,
1230
                              rd_list_t *request_topics,
1231
0
                              rd_kafka_metadata_internal_t **mdip) {
1232
0
        return rd_kafka_parse_Metadata0(rkb, NULL, rkbuf, mdip, request_topics,
1233
0
                                        "(admin request)");
1234
0
}
1235
1236
typedef RD_MAP_TYPE(const char *, const char *) map_str_str_t;
1237
1238
/**
1239
 * @brief Add all topics in current cached full metadata
1240
 *        that matches the topics in \p match
1241
 *        to \p tinfos (rd_kafka_topic_info_t *).
1242
 *
1243
 * @param errored Any topic or wildcard pattern that did not match
1244
 *                an available topic will be added to this list with
1245
 *                the appropriate error set.
1246
 *
1247
 * @returns the number of topics matched and added to \p tinfos
1248
 *
1249
 * @locks none
1250
 * @locality any
1251
 */
1252
size_t
1253
rd_kafka_metadata_topic_match(rd_kafka_t *rk,
1254
                              rd_list_t *tinfos,
1255
                              const rd_kafka_topic_partition_list_t *match,
1256
0
                              rd_kafka_topic_partition_list_t *errored) {
1257
0
        int i;
1258
0
        size_t cnt = 0;
1259
0
        rd_kafka_topic_partition_list_t *unmatched;
1260
0
        const struct rd_kafka_metadata_cache_entry *rkmce;
1261
0
        map_str_str_t map;
1262
1263
0
        rd_kafka_rdlock(rk);
1264
0
        map = (map_str_str_t)RD_MAP_INITIALIZER(
1265
0
            rk->rk_metadata_cache.rkmc_cnt, rd_map_str_cmp, rd_map_str_hash,
1266
0
            NULL /* topic list element */, NULL /* topic list element */);
1267
        /* To keep track of which patterns and topics in `match` that
1268
         * did not match any topic (or matched an errored topic), we
1269
         * create a set of all topics to match in `unmatched` and then
1270
         * remove from this set as a match is found.
1271
         * Whatever remains in `unmatched` after all matching is performed
1272
         * are the topics and patterns that did not match a topic. */
1273
0
        unmatched = rd_kafka_topic_partition_list_copy(match);
1274
1275
        /* For each topic in the cluster, scan through the match list
1276
         * to find matching topic. */
1277
0
        TAILQ_FOREACH(rkmce, &rk->rk_metadata_cache.rkmc_expiry, rkmce_link) {
1278
0
                const rd_kafka_metadata_topic_internal_t *mdti;
1279
0
                const rd_kafka_metadata_topic_t *mdt;
1280
0
                const char *topic = rkmce->rkmce_mtopic.topic;
1281
0
                rd_bool_t matched = rd_false;
1282
1283
0
                if (!RD_KAFKA_METADATA_CACHE_VALID(rkmce) || !topic ||
1284
0
                    RD_MAP_GET(&map, topic))
1285
                        /* We could have multiple cache entries
1286
                         * with different topic id and same topic name
1287
                         * in some cases */
1288
0
                        continue;
1289
1290
0
                RD_MAP_SET(&map, topic, topic);
1291
1292
0
                mdt  = &rkmce->rkmce_mtopic;
1293
0
                mdti = &rkmce->rkmce_metadata_internal_topic;
1294
1295
1296
                /* Ignore topics in blacklist */
1297
0
                if (rk->rk_conf.topic_blacklist &&
1298
0
                    rd_kafka_pattern_match(rk->rk_conf.topic_blacklist, topic))
1299
0
                        continue;
1300
1301
                /* Scan for matches */
1302
0
                for (i = 0; i < match->cnt; i++) {
1303
0
                        if (!rd_kafka_topic_match(rk, match->elems[i].topic,
1304
0
                                                  topic))
1305
0
                                continue;
1306
1307
                        /* Remove from unmatched */
1308
0
                        rd_kafka_topic_partition_list_del(
1309
0
                            unmatched, match->elems[i].topic,
1310
0
                            RD_KAFKA_PARTITION_UA);
1311
1312
0
                        if (matched)
1313
                                /*
1314
                                 * Just remove it from unmatched.
1315
                                 * Topic was already added to
1316
                                 * `tinfos` or `errored`.
1317
                                 */
1318
0
                                continue;
1319
0
                        matched = rd_true;
1320
1321
0
                        if (mdt->err) {
1322
0
                                rd_kafka_topic_partition_list_add(
1323
0
                                    errored, topic, RD_KAFKA_PARTITION_UA)
1324
0
                                    ->err = mdt->err;
1325
0
                                continue; /* Skip errored topics */
1326
0
                        }
1327
1328
0
                        rd_list_add(tinfos, rd_kafka_topic_info_new_with_rack(
1329
0
                                                topic, mdt->partition_cnt,
1330
0
                                                mdti->partitions));
1331
1332
0
                        cnt++;
1333
0
                }
1334
0
        }
1335
0
        rd_kafka_rdunlock(rk);
1336
0
        RD_MAP_DESTROY(&map);
1337
1338
        /* Any topics/patterns still in unmatched did not match any
1339
         * existing topics, add them to `errored`. */
1340
0
        for (i = 0; i < unmatched->cnt; i++) {
1341
0
                rd_kafka_topic_partition_t *elem = &unmatched->elems[i];
1342
1343
0
                rd_kafka_topic_partition_list_add(errored, elem->topic,
1344
0
                                                  RD_KAFKA_PARTITION_UA)
1345
0
                    ->err = RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC;
1346
0
        }
1347
1348
0
        rd_kafka_topic_partition_list_destroy(unmatched);
1349
1350
0
        return cnt;
1351
0
}
1352
1353
1354
/**
1355
 * @brief Add all topics in \p match that matches cached metadata.
1356
 * @remark MUST NOT be used with wildcard topics,
1357
 *         see rd_kafka_metadata_topic_match() for that.
1358
 *
1359
 * @param errored Non-existent and unauthorized topics are added to this
1360
 *                list with the appropriate error code.
1361
 *
1362
 * @returns the number of topics matched and added to \p tinfos
1363
 * @locks none
1364
 */
1365
size_t
1366
rd_kafka_metadata_topic_filter(rd_kafka_t *rk,
1367
                               rd_list_t *tinfos,
1368
                               const rd_kafka_topic_partition_list_t *match,
1369
0
                               rd_kafka_topic_partition_list_t *errored) {
1370
0
        int i;
1371
0
        size_t cnt = 0;
1372
1373
0
        rd_kafka_rdlock(rk);
1374
        /* For each topic in match, look up the topic in the cache. */
1375
0
        for (i = 0; i < match->cnt; i++) {
1376
0
                const char *topic                       = match->elems[i].topic;
1377
0
                const rd_kafka_metadata_topic_t *mtopic = NULL;
1378
1379
                /* Ignore topics in blacklist */
1380
0
                if (rk->rk_conf.topic_blacklist &&
1381
0
                    rd_kafka_pattern_match(rk->rk_conf.topic_blacklist, topic))
1382
0
                        continue;
1383
1384
0
                struct rd_kafka_metadata_cache_entry *rkmce =
1385
0
                    rd_kafka_metadata_cache_find(rk, topic, 1 /* valid */);
1386
0
                if (rkmce)
1387
0
                        mtopic = &rkmce->rkmce_mtopic;
1388
1389
0
                if (!mtopic)
1390
0
                        rd_kafka_topic_partition_list_add(errored, topic,
1391
0
                                                          RD_KAFKA_PARTITION_UA)
1392
0
                            ->err = RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC;
1393
0
                else if (mtopic->err)
1394
0
                        rd_kafka_topic_partition_list_add(errored, topic,
1395
0
                                                          RD_KAFKA_PARTITION_UA)
1396
0
                            ->err = mtopic->err;
1397
0
                else {
1398
0
                        rd_list_add(tinfos,
1399
0
                                    rd_kafka_topic_info_new_with_rack(
1400
0
                                        topic, mtopic->partition_cnt,
1401
0
                                        rkmce->rkmce_metadata_internal_topic
1402
0
                                            .partitions));
1403
1404
0
                        cnt++;
1405
0
                }
1406
0
        }
1407
0
        rd_kafka_rdunlock(rk);
1408
1409
0
        return cnt;
1410
0
}
1411
1412
1413
void rd_kafka_metadata_log(rd_kafka_t *rk,
1414
                           const char *fac,
1415
0
                           const struct rd_kafka_metadata *md) {
1416
0
        int i;
1417
1418
0
        rd_kafka_dbg(rk, METADATA, fac,
1419
0
                     "Metadata with %d broker(s) and %d topic(s):",
1420
0
                     md->broker_cnt, md->topic_cnt);
1421
1422
0
        for (i = 0; i < md->broker_cnt; i++) {
1423
0
                rd_kafka_dbg(rk, METADATA, fac,
1424
0
                             "  Broker #%i/%i: %s:%i NodeId %" PRId32, i,
1425
0
                             md->broker_cnt, md->brokers[i].host,
1426
0
                             md->brokers[i].port, md->brokers[i].id);
1427
0
        }
1428
1429
0
        for (i = 0; i < md->topic_cnt; i++) {
1430
0
                rd_kafka_dbg(
1431
0
                    rk, METADATA, fac,
1432
0
                    "  Topic #%i/%i: %s with %i partitions%s%s", i,
1433
0
                    md->topic_cnt,
1434
0
                    rd_kafka_topic_name_str_safe(md->topics[i].topic),
1435
0
                    md->topics[i].partition_cnt, md->topics[i].err ? ": " : "",
1436
0
                    md->topics[i].err ? rd_kafka_err2str(md->topics[i].err)
1437
0
                                      : "");
1438
0
        }
1439
0
}
1440
1441
1442
1443
/**
1444
 * @brief Refresh metadata for \p topics
1445
 *
1446
 * @param rk: used to look up usable broker if \p rkb is NULL.
1447
 * @param rkb: use this broker, unless NULL then any usable broker from \p rk
1448
 * @param force: force refresh even if topics are up-to-date in cache
1449
 * @param allow_auto_create: Enable/disable auto creation of topics
1450
 *                           (through MetadataRequest). Requires a modern
1451
 *                           broker version.
1452
 *                           Takes precedence over allow.auto.create.topics.
1453
 * @param cgrp_update: Allow consumer group state update on response.
1454
 *
1455
 * @returns an error code
1456
 *
1457
 * @locality any
1458
 * @locks none
1459
 */
1460
rd_kafka_resp_err_t
1461
rd_kafka_metadata_refresh_topics(rd_kafka_t *rk,
1462
                                 rd_kafka_broker_t *rkb,
1463
                                 const rd_list_t *topics,
1464
                                 rd_bool_t force,
1465
                                 rd_bool_t allow_auto_create,
1466
                                 rd_bool_t cgrp_update,
1467
                                 int32_t cgrp_subscription_version,
1468
0
                                 const char *reason) {
1469
0
        rd_list_t q_topics;
1470
0
        int destroy_rkb = 0;
1471
1472
0
        if (!rk) {
1473
0
                rd_assert(rkb);
1474
0
                rk = rkb->rkb_rk;
1475
0
        }
1476
1477
0
        rd_kafka_wrlock(rk);
1478
1479
0
        if (!rkb) {
1480
0
                if (!(rkb = rd_kafka_broker_any_usable(
1481
0
                          rk, RD_POLL_NOWAIT, RD_DONT_LOCK, 0, reason))) {
1482
                        /* Hint cache that something is interested in
1483
                         * these topics so that they will be included in
1484
                         * a future all known_topics query. */
1485
0
                        rd_kafka_metadata_cache_hint(rk, topics, NULL,
1486
0
                                                     RD_KAFKA_RESP_ERR__NOENT);
1487
1488
0
                        rd_kafka_wrunlock(rk);
1489
0
                        rd_kafka_dbg(rk, METADATA, "METADATA",
1490
0
                                     "Skipping metadata refresh of %d topic(s):"
1491
0
                                     " %s: no usable brokers",
1492
0
                                     rd_list_cnt(topics), reason);
1493
1494
0
                        return RD_KAFKA_RESP_ERR__TRANSPORT;
1495
0
                }
1496
0
                destroy_rkb = 1;
1497
0
        }
1498
1499
0
        rd_list_init(&q_topics, rd_list_cnt(topics), rd_free);
1500
1501
0
        if (!force) {
1502
1503
                /* Hint cache of upcoming MetadataRequest and filter
1504
                 * out any topics that are already being requested.
1505
                 * q_topics will contain remaining topics to query. */
1506
0
                rd_kafka_metadata_cache_hint(rk, topics, &q_topics,
1507
0
                                             RD_KAFKA_RESP_ERR__WAIT_CACHE);
1508
0
                rd_kafka_wrunlock(rk);
1509
1510
0
                if (rd_list_cnt(&q_topics) == 0) {
1511
                        /* No topics need new query. */
1512
0
                        rd_kafka_dbg(rk, METADATA, "METADATA",
1513
0
                                     "Skipping metadata refresh of "
1514
0
                                     "%d topic(s): %s: "
1515
0
                                     "already being requested",
1516
0
                                     rd_list_cnt(topics), reason);
1517
0
                        rd_list_destroy(&q_topics);
1518
0
                        if (destroy_rkb)
1519
0
                                rd_kafka_broker_destroy(rkb);
1520
0
                        return RD_KAFKA_RESP_ERR_NO_ERROR;
1521
0
                }
1522
1523
0
        } else {
1524
0
                rd_kafka_wrunlock(rk);
1525
0
                rd_list_copy_to(&q_topics, topics, rd_list_string_copy, NULL);
1526
0
        }
1527
1528
0
        rd_kafka_dbg(rk, METADATA, "METADATA",
1529
0
                     "Requesting metadata for %d/%d topics: %s",
1530
0
                     rd_list_cnt(&q_topics), rd_list_cnt(topics), reason);
1531
1532
0
        rd_kafka_MetadataRequest(
1533
0
            rkb, &q_topics, NULL, reason, allow_auto_create, cgrp_update,
1534
0
            cgrp_subscription_version, rd_false /* force_racks */, NULL);
1535
1536
0
        rd_list_destroy(&q_topics);
1537
1538
0
        if (destroy_rkb)
1539
0
                rd_kafka_broker_destroy(rkb);
1540
1541
0
        return RD_KAFKA_RESP_ERR_NO_ERROR;
1542
0
}
1543
1544
1545
/**
1546
 * @brief Refresh metadata for topics identified by topic_id.
1547
 *
1548
 *        For consumer paths whose canonical identity is topic_id
1549
 *        (share consumer today): a by-id request lets the broker tell
1550
 *        us which of our locally known topic_ids no longer correspond
1551
 *        to a live topic, so stale rkts (e.g. those left behind by a
1552
 *        topic delete+recreate) can be marked as non-existent and
1553
 *        their broker-side share-session entries released.
1554
 *
1555
 *        No by-id cache hint / dedup is performed; every call sends
1556
 *        the request. Auto-creation, cgrp update, and subscription
1557
 *        version are not exposed: auto-creation requires a topic
1558
 *        name, and the cgrp-update hook is only consumed by the
1559
 *        classic consumer protocol.
1560
 *
1561
 * @param rk used to look up usable broker if \p rkb is NULL.
1562
 * @param rkb use this broker, unless NULL then any usable broker
1563
 *            from \p rk.
1564
 * @param topic_ids list of rd_kafka_Uuid_t * to query.
1565
 * @param reason reason of refresh, used in debug logs.
1566
 *
1567
 * @returns an error code; __UNKNOWN_TOPIC if topic_ids is empty;
1568
 *          __TRANSPORT if no broker is available.
1569
 *
1570
 * @locality any
1571
 * @locks none
1572
 */
1573
rd_kafka_resp_err_t
1574
rd_kafka_metadata_refresh_topic_ids(rd_kafka_t *rk,
1575
                                    rd_kafka_broker_t *rkb,
1576
                                    const rd_list_t *topic_ids,
1577
0
                                    const char *reason) {
1578
0
        rd_list_t q_topic_ids;
1579
0
        int destroy_rkb = 0;
1580
1581
0
        if (!rk) {
1582
0
                rd_assert(rkb);
1583
0
                rk = rkb->rkb_rk;
1584
0
        }
1585
1586
0
        if (rd_list_cnt(topic_ids) == 0)
1587
0
                return RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC;
1588
1589
0
        if (!rkb) {
1590
0
                if (!(rkb = rd_kafka_broker_any_usable(
1591
0
                          rk, RD_POLL_NOWAIT, RD_DO_LOCK, 0, reason))) {
1592
0
                        rd_kafka_dbg(rk, METADATA, "METADATA",
1593
0
                                     "Skipping metadata refresh of %d "
1594
0
                                     "topic(s) using id: %s: no usable "
1595
0
                                     "brokers",
1596
0
                                     rd_list_cnt(topic_ids), reason);
1597
0
                        return RD_KAFKA_RESP_ERR__TRANSPORT;
1598
0
                }
1599
0
                destroy_rkb = 1;
1600
0
        }
1601
1602
0
        rd_list_init(&q_topic_ids, rd_list_cnt(topic_ids),
1603
0
                     rd_list_Uuid_destroy);
1604
0
        rd_list_copy_to(&q_topic_ids, topic_ids, rd_list_Uuid_copy, NULL);
1605
1606
0
        rd_kafka_dbg(rk, METADATA, "METADATA",
1607
0
                     "Requesting metadata for %d topic(s) using id: %s",
1608
0
                     rd_list_cnt(&q_topic_ids), reason);
1609
1610
0
        rd_kafka_MetadataRequest(
1611
0
            rkb, NULL, &q_topic_ids, reason, rd_false /* allow_auto_create */,
1612
0
            rd_false /* cgrp_update */, -1 /* cgrp_subscription_version */,
1613
0
            rd_false /* force_racks */, NULL);
1614
1615
0
        rd_list_destroy(&q_topic_ids);
1616
1617
0
        if (destroy_rkb)
1618
0
                rd_kafka_broker_destroy(rkb);
1619
1620
0
        return RD_KAFKA_RESP_ERR_NO_ERROR;
1621
0
}
1622
1623
1624
/**
1625
 * @brief Refresh metadata for known topics
1626
 *
1627
 * @param rk: used to look up usable broker if \p rkb is NULL.
1628
 * @param rkb: use this broker, unless NULL then any usable broker from \p rk
1629
 * @param force: refresh even if cache is up-to-date
1630
 *
1631
 * @returns an error code (__UNKNOWN_TOPIC if there are no local topics)
1632
 *
1633
 * @locality any
1634
 * @locks none
1635
 */
1636
rd_kafka_resp_err_t
1637
rd_kafka_metadata_refresh_known_topics(rd_kafka_t *rk,
1638
                                       rd_kafka_broker_t *rkb,
1639
                                       rd_bool_t force,
1640
0
                                       const char *reason) {
1641
0
        rd_list_t topics;
1642
0
        rd_kafka_resp_err_t err;
1643
0
        int cache_cnt = 0;
1644
0
        rd_bool_t allow_auto_create_topics;
1645
1646
0
        if (!rk)
1647
0
                rk = rkb->rkb_rk;
1648
1649
0
        rd_list_init(&topics, 8, rd_free);
1650
0
        rd_kafka_local_topics_to_list(rk, &topics, &cache_cnt);
1651
1652
        /* Allow topic auto creation if there are locally known topics (rkt)
1653
         * and not just cached (to be queried) topics. */
1654
0
        allow_auto_create_topics = rk->rk_conf.allow_auto_create_topics &&
1655
0
                                   rd_list_cnt(&topics) > cache_cnt;
1656
1657
0
        if (rd_list_cnt(&topics) == 0)
1658
0
                err = RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC;
1659
0
        else
1660
0
                err = rd_kafka_metadata_refresh_topics(
1661
0
                    rk, rkb, &topics, force, allow_auto_create_topics,
1662
0
                    rd_false /*!cgrp_update*/, -1, reason);
1663
1664
0
        rd_list_destroy(&topics);
1665
1666
0
        return err;
1667
0
}
1668
1669
1670
/**
1671
 * @brief Refresh metadata for known and subscribed topics.
1672
 *
1673
 * @param rk used to look up usable broker if \p rkb is NULL..
1674
 * @param rkb use this broker, unless NULL then any usable broker from \p rk.
1675
 * @param reason reason of refresh, used in debug logs.
1676
 *
1677
 * @returns an error code (ERR__UNKNOWN_TOPIC if no topics are desired).
1678
 *
1679
 * @locality rdkafka main thread
1680
 * @locks_required none
1681
 * @locks_acquired rk(read)
1682
 */
1683
rd_kafka_resp_err_t
1684
rd_kafka_metadata_refresh_consumer_topics(rd_kafka_t *rk,
1685
                                          rd_kafka_broker_t *rkb,
1686
0
                                          const char *reason) {
1687
0
        rd_list_t topics;
1688
0
        rd_list_t topic_ids;
1689
0
        rd_kafka_resp_err_t err;
1690
0
        rd_kafka_cgrp_t *rkcg;
1691
0
        rd_bool_t allow_auto_create_topics =
1692
0
            rk->rk_conf.allow_auto_create_topics;
1693
0
        int cache_cnt = 0;
1694
1695
0
        if (!rk) {
1696
0
                rd_assert(rkb);
1697
0
                rk = rkb->rkb_rk;
1698
0
        }
1699
1700
0
        rkcg = rk->rk_cgrp;
1701
0
        rd_assert(rkcg != NULL);
1702
1703
0
        if (rkcg->rkcg_group_protocol == RD_KAFKA_GROUP_PROTOCOL_CLASSIC &&
1704
0
            rkcg->rkcg_flags & RD_KAFKA_CGRP_F_WILDCARD_SUBSCRIPTION) {
1705
                /* If there is a wildcard subscription we need to request
1706
                 * all topics in the cluster so that we can perform
1707
                 * regexp matching. */
1708
0
                return rd_kafka_metadata_refresh_all(rk, rkb, reason);
1709
0
        }
1710
1711
0
        if (RD_KAFKA_IS_SHARE_CONSUMER(rk)) {
1712
                /* Share consumer identifies topics by id. Subscription
1713
                 * names are resolved server-side via
1714
                 * ShareGroupHeartbeat, so the only thing this
1715
                 * periodic path needs to do is status-check the
1716
                 * locally known topic ids. The broker's response
1717
                 * marks stale ids (e.g. those left behind by a
1718
                 * delete+recreate) as unknown, which drives cleanup
1719
                 * of the corresponding rkts. */
1720
0
                rd_list_init(&topic_ids, 8, rd_list_Uuid_destroy);
1721
0
                rd_kafka_local_topic_ids_to_list(rk, &topic_ids);
1722
0
                err = rd_kafka_metadata_refresh_topic_ids(rk, rkb, &topic_ids,
1723
0
                                                          reason);
1724
0
                rd_list_destroy(&topic_ids);
1725
0
                return err;
1726
0
        }
1727
1728
0
        rd_list_init(&topics, 8, rd_free);
1729
1730
        /* Add locally known topics, i.e., those that are currently
1731
         * being consumed or otherwise referenced through topic_t objects. */
1732
0
        rd_kafka_local_topics_to_list(rk, &topics, &cache_cnt);
1733
0
        if (rd_list_cnt(&topics) == cache_cnt)
1734
0
                allow_auto_create_topics = rd_false;
1735
1736
        /* Add subscribed (non-wildcard) topics, if any. */
1737
0
        if (rkcg->rkcg_subscription)
1738
0
                rd_kafka_topic_partition_list_get_topic_names(
1739
0
                    rkcg->rkcg_subscription, &topics,
1740
0
                    rd_false /*no wildcards*/);
1741
1742
0
        if (rd_list_cnt(&topics) == 0)
1743
0
                err = RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC;
1744
0
        else
1745
0
                err = rd_kafka_metadata_refresh_topics(
1746
0
                    rk, rkb, &topics, rd_true /*force*/,
1747
0
                    allow_auto_create_topics, rd_true /*cgrp_update*/,
1748
0
                    rd_atomic32_get(&rkcg->rkcg_subscription_version), reason);
1749
1750
0
        rd_list_destroy(&topics);
1751
1752
0
        return err;
1753
0
}
1754
1755
1756
/**
1757
 * @brief Refresh broker list by metadata.
1758
 *
1759
 * Attempts to use sparse metadata request if possible, else falls back
1760
 * on a full metadata request. (NOTE: sparse not implemented, KIP-4)
1761
 *
1762
 * @param rk: used to look up usable broker if \p rkb is NULL.
1763
 * @param rkb: use this broker, unless NULL then any usable broker from \p rk
1764
 *
1765
 * @returns an error code
1766
 *
1767
 * @locality any
1768
 * @locks none
1769
 */
1770
rd_kafka_resp_err_t rd_kafka_metadata_refresh_brokers(rd_kafka_t *rk,
1771
                                                      rd_kafka_broker_t *rkb,
1772
0
                                                      const char *reason) {
1773
0
        return rd_kafka_metadata_request(rk, rkb, NULL /*brokers only*/,
1774
0
                                         rd_false /*!allow auto create topics*/,
1775
0
                                         rd_false /*no cgrp update */,
1776
0
                                         -1 /* same subscription version */,
1777
0
                                         reason, NULL);
1778
0
}
1779
1780
1781
1782
/**
1783
 * @brief Refresh metadata for all topics in cluster.
1784
 *        This is a full metadata request which might be taxing on the
1785
 *        broker if the cluster has many topics.
1786
 *
1787
 * @locality any
1788
 * @locks none
1789
 */
1790
rd_kafka_resp_err_t rd_kafka_metadata_refresh_all(rd_kafka_t *rk,
1791
                                                  rd_kafka_broker_t *rkb,
1792
0
                                                  const char *reason) {
1793
0
        int destroy_rkb = 0;
1794
0
        rd_list_t topics;
1795
1796
0
        if (!rk) {
1797
0
                rd_assert(rkb);
1798
0
                rk = rkb->rkb_rk;
1799
0
        }
1800
1801
0
        if (!rkb) {
1802
0
                if (!(rkb = rd_kafka_broker_any_usable(rk, RD_POLL_NOWAIT,
1803
0
                                                       RD_DO_LOCK, 0, reason)))
1804
0
                        return RD_KAFKA_RESP_ERR__TRANSPORT;
1805
0
                destroy_rkb = 1;
1806
0
        }
1807
1808
0
        rd_list_init(&topics, 0, NULL); /* empty list = all topics */
1809
0
        rd_kafka_MetadataRequest(
1810
0
            rkb, &topics, NULL, reason, rd_false /*no auto create*/,
1811
0
            rd_true /*cgrp update*/, -1 /* same subscription version */,
1812
0
            rd_false /* force_rack */, NULL);
1813
0
        rd_list_destroy(&topics);
1814
1815
0
        if (destroy_rkb)
1816
0
                rd_kafka_broker_destroy(rkb);
1817
1818
0
        return RD_KAFKA_RESP_ERR_NO_ERROR;
1819
0
}
1820
1821
1822
/**
1823
1824
 * @brief Lower-level Metadata request that takes a callback (with replyq set)
1825
 *        which will be triggered after parsing is complete.
1826
 *
1827
 * @param cgrp_update Allow consumer group updates from the response.
1828
 *
1829
 * @locks none
1830
 * @locality any
1831
 */
1832
rd_kafka_resp_err_t
1833
rd_kafka_metadata_request(rd_kafka_t *rk,
1834
                          rd_kafka_broker_t *rkb,
1835
                          const rd_list_t *topics,
1836
                          rd_bool_t allow_auto_create_topics,
1837
                          rd_bool_t cgrp_update,
1838
                          int32_t cgrp_subscription_version,
1839
                          const char *reason,
1840
0
                          rd_kafka_op_t *rko) {
1841
0
        int destroy_rkb = 0;
1842
1843
0
        if (!rkb) {
1844
0
                if (!(rkb = rd_kafka_broker_any_usable(rk, RD_POLL_NOWAIT,
1845
0
                                                       RD_DO_LOCK, 0, reason)))
1846
0
                        return RD_KAFKA_RESP_ERR__TRANSPORT;
1847
0
                destroy_rkb = 1;
1848
0
        }
1849
1850
0
        rd_kafka_MetadataRequest(
1851
0
            rkb, topics, NULL, reason, allow_auto_create_topics, cgrp_update,
1852
0
            cgrp_subscription_version, rd_false /* force racks */, rko);
1853
1854
0
        if (destroy_rkb)
1855
0
                rd_kafka_broker_destroy(rkb);
1856
1857
0
        return RD_KAFKA_RESP_ERR_NO_ERROR;
1858
0
}
1859
1860
1861
/**
1862
 * @brief Query timer callback to trigger refresh for topics
1863
 *        that have partitions missing their leaders.
1864
 *
1865
 * @locks none
1866
 * @locality rdkafka main thread
1867
 */
1868
static void rd_kafka_metadata_leader_query_tmr_cb(rd_kafka_timers_t *rkts,
1869
0
                                                  void *arg) {
1870
0
        rd_kafka_t *rk         = rkts->rkts_rk;
1871
0
        rd_kafka_timer_t *rtmr = &rk->rk_metadata_cache.rkmc_query_tmr;
1872
0
        rd_kafka_topic_t *rkt;
1873
0
        rd_list_t topics;
1874
1875
0
        rd_kafka_wrlock(rk);
1876
0
        rd_list_init(&topics, rk->rk_topic_cnt, rd_free);
1877
1878
0
        TAILQ_FOREACH(rkt, &rk->rk_topics, rkt_link) {
1879
0
                int i, require_metadata;
1880
0
                rd_kafka_topic_rdlock(rkt);
1881
1882
0
                if (rkt->rkt_state == RD_KAFKA_TOPIC_S_NOTEXISTS) {
1883
                        /* Skip topics that are known to not exist. */
1884
0
                        rd_kafka_topic_rdunlock(rkt);
1885
0
                        continue;
1886
0
                }
1887
1888
0
                require_metadata =
1889
0
                    rkt->rkt_flags & RD_KAFKA_TOPIC_F_LEADER_UNAVAIL;
1890
1891
                /* Check if any partitions are missing brokers. */
1892
0
                for (i = 0; !require_metadata && i < rkt->rkt_partition_cnt;
1893
0
                     i++) {
1894
0
                        rd_kafka_toppar_t *rktp = rkt->rkt_p[i];
1895
0
                        rd_kafka_toppar_lock(rktp);
1896
0
                        require_metadata =
1897
0
                            !rktp->rktp_broker && !rktp->rktp_next_broker;
1898
0
                        rd_kafka_toppar_unlock(rktp);
1899
0
                }
1900
1901
0
                if (require_metadata || rkt->rkt_partition_cnt == 0)
1902
0
                        rd_list_add(&topics, rd_strdup(rkt->rkt_topic->str));
1903
1904
0
                rd_kafka_topic_rdunlock(rkt);
1905
0
        }
1906
1907
0
        rd_kafka_wrunlock(rk);
1908
1909
0
        if (rd_list_cnt(&topics) == 0) {
1910
                /* No leader-less topics+partitions, stop the timer. */
1911
0
                rd_kafka_timer_stop(rkts, rtmr, 1 /*lock*/);
1912
0
        } else {
1913
0
                rd_kafka_metadata_refresh_topics(
1914
0
                    rk, NULL, &topics, rd_true /*force*/,
1915
0
                    rk->rk_conf.allow_auto_create_topics,
1916
0
                    rd_false /*!cgrp_update*/, -1, "partition leader query");
1917
1918
                /* Back off next query exponentially till we reach
1919
                 * the retry backoff max ms */
1920
0
                rd_kafka_timer_exp_backoff(
1921
0
                    rkts, rtmr, rk->rk_conf.retry_backoff_ms * 1000,
1922
0
                    rk->rk_conf.retry_backoff_max_ms * 1000,
1923
0
                    RD_KAFKA_RETRY_JITTER_PERCENT);
1924
0
        }
1925
1926
0
        rd_list_destroy(&topics);
1927
0
}
1928
1929
1930
1931
/**
1932
 * @brief Trigger fast leader query to quickly pick up on leader changes.
1933
 *        The fast leader query is a quick query followed by later queries at
1934
 *        exponentially increased intervals until no topics are missing
1935
 *        leaders.
1936
 *
1937
 * @param force If true, run the query immediately without waiting for the
1938
 * interval.
1939
 *
1940
 * @locks none
1941
 * @locality any
1942
 */
1943
0
void rd_kafka_metadata_fast_leader_query(rd_kafka_t *rk, rd_bool_t force) {
1944
0
        rd_ts_t next;
1945
1946
        /* Restart the timer if it will speed things up, or if forced. */
1947
0
        next = rd_kafka_timer_next(
1948
0
            &rk->rk_timers, &rk->rk_metadata_cache.rkmc_query_tmr, 1 /*lock*/);
1949
0
        if (force || next == -1 /* not started */ ||
1950
0
            next >
1951
0
                (rd_ts_t)rk->rk_conf.metadata_refresh_fast_interval_ms * 1000) {
1952
0
                rd_kafka_dbg(rk, METADATA | RD_KAFKA_DBG_TOPIC, "FASTQUERY",
1953
0
                             "Starting fast leader query");
1954
0
                rd_kafka_timer_start(
1955
0
                    &rk->rk_timers, &rk->rk_metadata_cache.rkmc_query_tmr,
1956
0
                    0 /* First request should be tried immediately */,
1957
0
                    rd_kafka_metadata_leader_query_tmr_cb, NULL);
1958
0
        }
1959
0
}
1960
1961
1962
1963
/**
1964
 * @brief Create mock Metadata (for testing) based on the provided topics.
1965
 *
1966
 * @param topics elements are checked for .topic and .partition_cnt
1967
 * @param topic_cnt is the number of topic elements in \p topics.
1968
 * @param replication_factor is the number of replicas of each partition (set to
1969
 * -1 to ignore).
1970
 * @param num_brokers is the number of brokers in the cluster.
1971
 *
1972
 * @returns a newly allocated metadata object that must be freed with
1973
 *          rd_kafka_metadata_destroy().
1974
 *
1975
 * @note \p replication_factor and \p num_brokers must be used together for
1976
 * setting replicas of each partition.
1977
 *
1978
 * @sa rd_kafka_metadata_copy()
1979
 */
1980
rd_kafka_metadata_t *
1981
rd_kafka_metadata_new_topic_mock(const rd_kafka_metadata_topic_t *topics,
1982
                                 size_t topic_cnt,
1983
                                 int replication_factor,
1984
0
                                 int num_brokers) {
1985
0
        rd_kafka_metadata_internal_t *mdi;
1986
0
        rd_kafka_metadata_t *md;
1987
0
        rd_tmpabuf_t tbuf;
1988
0
        size_t i;
1989
0
        int curr_broker = 0;
1990
1991
        /* If the replication factor is given, num_brokers must also be given */
1992
0
        rd_assert(replication_factor <= 0 || num_brokers > 0);
1993
1994
        /* Allocate contiguous buffer which will back all the memory
1995
         * needed by the final metadata_t object */
1996
0
        rd_tmpabuf_new(&tbuf, sizeof(*mdi), rd_true /*assert on fail*/);
1997
1998
0
        rd_tmpabuf_add_alloc(&tbuf, topic_cnt * sizeof(*md->topics));
1999
0
        rd_tmpabuf_add_alloc(&tbuf, topic_cnt * sizeof(*mdi->topics));
2000
0
        rd_tmpabuf_add_alloc(&tbuf, num_brokers * sizeof(*md->brokers));
2001
2002
        /* Calculate total partition count and topic names size before
2003
         * allocating memory. */
2004
0
        for (i = 0; i < topic_cnt; i++) {
2005
0
                rd_tmpabuf_add_alloc(&tbuf, 1 + strlen(topics[i].topic));
2006
0
                rd_tmpabuf_add_alloc(&tbuf,
2007
0
                                     topics[i].partition_cnt *
2008
0
                                         sizeof(*md->topics[i].partitions));
2009
0
                rd_tmpabuf_add_alloc(&tbuf,
2010
0
                                     topics[i].partition_cnt *
2011
0
                                         sizeof(*mdi->topics[i].partitions));
2012
0
                if (replication_factor > 0)
2013
0
                        rd_tmpabuf_add_alloc_times(
2014
0
                            &tbuf, replication_factor * sizeof(int),
2015
0
                            topics[i].partition_cnt);
2016
0
        }
2017
2018
0
        rd_tmpabuf_finalize(&tbuf);
2019
2020
0
        mdi = rd_tmpabuf_alloc(&tbuf, sizeof(*mdi));
2021
0
        memset(mdi, 0, sizeof(*mdi));
2022
0
        md = &mdi->metadata;
2023
2024
0
        md->topic_cnt = (int)topic_cnt;
2025
0
        md->topics =
2026
0
            rd_tmpabuf_alloc(&tbuf, md->topic_cnt * sizeof(*md->topics));
2027
0
        mdi->topics =
2028
0
            rd_tmpabuf_alloc(&tbuf, md->topic_cnt * sizeof(*mdi->topics));
2029
2030
0
        md->broker_cnt = num_brokers;
2031
0
        mdi->brokers =
2032
0
            rd_tmpabuf_alloc(&tbuf, md->broker_cnt * sizeof(*mdi->brokers));
2033
2034
0
        for (i = 0; i < (size_t)md->topic_cnt; i++) {
2035
0
                int j;
2036
2037
0
                md->topics[i].topic =
2038
0
                    rd_tmpabuf_write_str(&tbuf, topics[i].topic);
2039
0
                md->topics[i].partition_cnt = topics[i].partition_cnt;
2040
0
                md->topics[i].err           = RD_KAFKA_RESP_ERR_NO_ERROR;
2041
2042
0
                md->topics[i].partitions = rd_tmpabuf_alloc(
2043
0
                    &tbuf, md->topics[i].partition_cnt *
2044
0
                               sizeof(*md->topics[i].partitions));
2045
0
                mdi->topics[i].partitions = rd_tmpabuf_alloc(
2046
0
                    &tbuf, md->topics[i].partition_cnt *
2047
0
                               sizeof(*mdi->topics[i].partitions));
2048
2049
0
                for (j = 0; j < md->topics[i].partition_cnt; j++) {
2050
0
                        int k;
2051
0
                        memset(&md->topics[i].partitions[j], 0,
2052
0
                               sizeof(md->topics[i].partitions[j]));
2053
0
                        memset(&mdi->topics[i].partitions[j], 0,
2054
0
                               sizeof(mdi->topics[i].partitions[j]));
2055
0
                        md->topics[i].partitions[j].id            = j;
2056
0
                        mdi->topics[i].partitions[j].id           = j;
2057
0
                        mdi->topics[i].partitions[j].leader_epoch = -1;
2058
0
                        mdi->topics[i].partitions[j].racks_cnt    = 0;
2059
0
                        mdi->topics[i].partitions[j].racks        = NULL;
2060
0
                        md->topics[i].partitions[j].id            = j;
2061
2062
                        /* In case replication_factor is not given, don't set
2063
                         * replicas. */
2064
0
                        if (replication_factor <= 0)
2065
0
                                continue;
2066
2067
0
                        md->topics[i].partitions[j].replicas = rd_tmpabuf_alloc(
2068
0
                            &tbuf, replication_factor * sizeof(int));
2069
0
                        md->topics[i].partitions[j].leader = curr_broker;
2070
0
                        md->topics[i].partitions[j].replica_cnt =
2071
0
                            replication_factor;
2072
0
                        for (k = 0; k < replication_factor; k++) {
2073
0
                                md->topics[i].partitions[j].replicas[k] =
2074
0
                                    (j + k + curr_broker) % num_brokers;
2075
0
                        }
2076
0
                }
2077
0
                if (num_brokers > 0)
2078
0
                        curr_broker =
2079
0
                            (curr_broker + md->topics[i].partition_cnt) %
2080
0
                            num_brokers;
2081
0
        }
2082
2083
        /* Check for tmpabuf errors */
2084
0
        if (rd_tmpabuf_failed(&tbuf))
2085
0
                rd_assert(!*"metadata mock failed");
2086
2087
        /* Not destroying the tmpabuf since we return
2088
         * its allocated memory. */
2089
0
        return md;
2090
0
}
2091
2092
/* Implementation for rd_kafka_metadata_new_topic*mockv() */
2093
static rd_kafka_metadata_t *
2094
rd_kafka_metadata_new_topic_mockv_internal(size_t topic_cnt,
2095
                                           int replication_factor,
2096
                                           int num_brokers,
2097
0
                                           va_list args) {
2098
0
        rd_kafka_metadata_topic_t *topics;
2099
0
        size_t i;
2100
2101
0
        topics = rd_alloca(sizeof(*topics) * topic_cnt);
2102
0
        for (i = 0; i < topic_cnt; i++) {
2103
0
                topics[i].topic         = va_arg(args, char *);
2104
0
                topics[i].partition_cnt = va_arg(args, int);
2105
0
        }
2106
2107
0
        return rd_kafka_metadata_new_topic_mock(
2108
0
            topics, topic_cnt, replication_factor, num_brokers);
2109
0
}
2110
2111
/**
2112
 * @brief Create mock Metadata (for testing) based on the
2113
 *        var-arg tuples of (const char *topic, int partition_cnt).
2114
 *
2115
 * @param topic_cnt is the number of topic,partition_cnt tuples.
2116
 *
2117
 * @returns a newly allocated metadata object that must be freed with
2118
 *          rd_kafka_metadata_destroy().
2119
 *
2120
 * @sa rd_kafka_metadata_new_topic_mock()
2121
 */
2122
0
rd_kafka_metadata_t *rd_kafka_metadata_new_topic_mockv(size_t topic_cnt, ...) {
2123
0
        rd_kafka_metadata_t *metadata;
2124
0
        va_list ap;
2125
2126
0
        va_start(ap, topic_cnt);
2127
0
        metadata =
2128
0
            rd_kafka_metadata_new_topic_mockv_internal(topic_cnt, -1, 0, ap);
2129
0
        va_end(ap);
2130
2131
0
        return metadata;
2132
0
}
2133
2134
/**
2135
 * @brief Create mock Metadata (for testing) based on the
2136
 *        var-arg tuples of (const char *topic, int partition_cnt).
2137
 *
2138
 * @param replication_factor is the number of replicas of each partition.
2139
 * @param num_brokers is the number of brokers in the cluster.
2140
 * @param topic_cnt is the number of topic,partition_cnt tuples.
2141
 *
2142
 * @returns a newly allocated metadata object that must be freed with
2143
 *          rd_kafka_metadata_destroy().
2144
 *
2145
 * @sa rd_kafka_metadata_new_topic_mock()
2146
 */
2147
rd_kafka_metadata_t *rd_kafka_metadata_new_topic_with_partition_replicas_mockv(
2148
    int replication_factor,
2149
    int num_brokers,
2150
    size_t topic_cnt,
2151
0
    ...) {
2152
0
        rd_kafka_metadata_t *metadata;
2153
0
        va_list ap;
2154
2155
0
        va_start(ap, topic_cnt);
2156
0
        metadata = rd_kafka_metadata_new_topic_mockv_internal(
2157
0
            topic_cnt, replication_factor, num_brokers, ap);
2158
0
        va_end(ap);
2159
2160
0
        return metadata;
2161
0
}
2162
2163
/**
2164
 * @brief Create mock Metadata (for testing) based on arrays topic_names and
2165
 * partition_cnts.
2166
 *
2167
 * @param replication_factor is the number of replicas of each partition.
2168
 * @param num_brokers is the number of brokers in the cluster.
2169
 * @param topic_names names of topics.
2170
 * @param partition_cnts number of partitions in each topic.
2171
 * @param topic_cnt number of topics.
2172
 *
2173
 * @return rd_kafka_metadata_t*
2174
 *
2175
 * @sa rd_kafka_metadata_new_topic_mock()
2176
 */
2177
rd_kafka_metadata_t *
2178
rd_kafka_metadata_new_topic_with_partition_replicas_mock(int replication_factor,
2179
                                                         int num_brokers,
2180
                                                         char *topic_names[],
2181
                                                         int *partition_cnts,
2182
0
                                                         size_t topic_cnt) {
2183
0
        rd_kafka_metadata_topic_t *topics;
2184
0
        size_t i;
2185
2186
0
        topics = rd_alloca(sizeof(*topics) * topic_cnt);
2187
0
        for (i = 0; i < topic_cnt; i++) {
2188
0
                topics[i].topic         = topic_names[i];
2189
0
                topics[i].partition_cnt = partition_cnts[i];
2190
0
        }
2191
2192
0
        return rd_kafka_metadata_new_topic_mock(
2193
0
            topics, topic_cnt, replication_factor, num_brokers);
2194
0
}
2195
2196
/**
2197
 * @brief Handle update of metadata received in the produce or fetch tags.
2198
 *
2199
 * @param rk Client instance.
2200
 * @param rko Metadata update operation.
2201
 *
2202
 * @locality main thread
2203
 * @locks none
2204
 *
2205
 * @return always RD_KAFKA_OP_RES_HANDLED
2206
 */
2207
rd_kafka_op_res_t
2208
0
rd_kafka_metadata_update_op(rd_kafka_t *rk, rd_kafka_metadata_internal_t *mdi) {
2209
0
        int i, j;
2210
0
        rd_kafka_metadata_t *md       = &mdi->metadata;
2211
0
        rd_bool_t cache_updated       = rd_false;
2212
0
        rd_kafka_secproto_t rkb_proto = rk->rk_conf.security_protocol;
2213
2214
2215
0
        for (i = 0; i < md->broker_cnt; i++) {
2216
0
                rd_kafka_broker_update(rk, rkb_proto, &md->brokers[i], NULL);
2217
0
        }
2218
2219
0
        for (i = 0; i < md->topic_cnt; i++) {
2220
0
                struct rd_kafka_metadata_cache_entry *rkmce;
2221
0
                int32_t partition_cache_changes = 0;
2222
0
                rd_bool_t by_id =
2223
0
                    !RD_KAFKA_UUID_IS_ZERO(mdi->topics[i].topic_id);
2224
0
                rd_kafka_Uuid_t topic_id = RD_KAFKA_UUID_ZERO;
2225
0
                char *topic              = NULL;
2226
2227
0
                if (by_id) {
2228
0
                        rkmce = rd_kafka_metadata_cache_find_by_id(
2229
0
                            rk, mdi->topics[i].topic_id, 1);
2230
0
                        topic_id = mdi->topics[i].topic_id;
2231
0
                } else {
2232
0
                        rkmce = rd_kafka_metadata_cache_find(
2233
0
                            rk, md->topics[i].topic, 1);
2234
0
                        topic = md->topics[i].topic;
2235
0
                }
2236
2237
0
                if (!rkmce) {
2238
0
                        if (by_id) {
2239
0
                                rd_kafka_log(
2240
0
                                    rk, LOG_WARNING, "METADATAUPDATE",
2241
0
                                    "Topic id %s not found in cache",
2242
0
                                    rd_kafka_Uuid_base64str(&topic_id));
2243
0
                        } else {
2244
0
                                rd_kafka_log(
2245
0
                                    rk, LOG_WARNING, "METADATAUPDATE",
2246
0
                                    "Topic %s not found in cache",
2247
0
                                    rd_kafka_topic_name_str_safe(topic));
2248
0
                        }
2249
0
                        continue;
2250
0
                }
2251
0
                topic    = rkmce->rkmce_mtopic.topic;
2252
0
                topic_id = rkmce->rkmce_metadata_internal_topic.topic_id;
2253
2254
0
                for (j = 0; j < md->topics[i].partition_cnt; j++) {
2255
0
                        rd_kafka_broker_t *rkb;
2256
0
                        rd_kafka_metadata_partition_t *mdp =
2257
0
                            &md->topics[i].partitions[j];
2258
0
                        ;
2259
0
                        rd_kafka_metadata_partition_internal_t *mdpi =
2260
0
                            &mdi->topics[i].partitions[j];
2261
0
                        int32_t part = mdp->id, current_leader_epoch;
2262
2263
0
                        if (part >= rkmce->rkmce_mtopic.partition_cnt) {
2264
0
                                rd_kafka_log(rk, LOG_WARNING, "METADATAUPDATE",
2265
0
                                             "Partition %s(%s)[%" PRId32
2266
0
                                             "]: not found "
2267
0
                                             "in cache",
2268
0
                                             topic,
2269
0
                                             rd_kafka_Uuid_base64str(&topic_id),
2270
0
                                             part);
2271
2272
0
                                continue;
2273
0
                        }
2274
2275
0
                        rkb = rd_kafka_broker_find_by_nodeid(rk, mdp->leader);
2276
0
                        if (!rkb) {
2277
0
                                rd_kafka_log(rk, LOG_WARNING, "METADATAUPDATE",
2278
0
                                             "Partition %s(%s)[%" PRId32
2279
0
                                             "]: new leader"
2280
0
                                             "%" PRId32 " not found in cache",
2281
0
                                             topic,
2282
0
                                             rd_kafka_Uuid_base64str(&topic_id),
2283
0
                                             part, mdp->leader);
2284
0
                                continue;
2285
0
                        }
2286
2287
0
                        current_leader_epoch =
2288
0
                            rkmce->rkmce_metadata_internal_topic
2289
0
                                .partitions[part]
2290
0
                                .leader_epoch;
2291
2292
0
                        if (mdpi->leader_epoch != -1 &&
2293
0
                            current_leader_epoch > mdpi->leader_epoch) {
2294
0
                                rd_kafka_broker_destroy(rkb);
2295
0
                                rd_kafka_dbg(
2296
0
                                    rk, METADATA, "METADATAUPDATE",
2297
0
                                    "Partition %s(%s)[%" PRId32
2298
0
                                    "]: leader epoch "
2299
0
                                    "is "
2300
0
                                    "not newer %" PRId32 " >= %" PRId32,
2301
0
                                    topic, rd_kafka_Uuid_base64str(&topic_id),
2302
0
                                    part, current_leader_epoch,
2303
0
                                    mdpi->leader_epoch);
2304
0
                                continue;
2305
0
                        }
2306
0
                        partition_cache_changes++;
2307
2308
                        /* Need to acquire the write lock to avoid dirty reads
2309
                         * from other threads acquiring read locks. */
2310
0
                        rd_kafka_wrlock(rk);
2311
0
                        rkmce->rkmce_metadata_internal_topic.partitions[part]
2312
0
                            .leader_epoch = mdpi->leader_epoch;
2313
0
                        rkmce->rkmce_mtopic.partitions[part].leader =
2314
0
                            mdp->leader;
2315
0
                        rd_kafka_wrunlock(rk);
2316
0
                        rd_kafka_broker_destroy(rkb);
2317
2318
0
                        rd_kafka_dbg(rk, METADATA, "METADATAUPDATE",
2319
0
                                     "Partition %s(%s)[%" PRId32
2320
0
                                     "]:"
2321
0
                                     " updated with leader %" PRId32
2322
0
                                     " and epoch %" PRId32,
2323
0
                                     topic, rd_kafka_Uuid_base64str(&topic_id),
2324
0
                                     part, mdp->leader, mdpi->leader_epoch);
2325
0
                }
2326
2327
0
                if (partition_cache_changes > 0) {
2328
0
                        cache_updated = rd_true;
2329
0
                        rd_kafka_topic_metadata_update2(
2330
0
                            rk->rk_internal_rkb, &rkmce->rkmce_mtopic,
2331
0
                            &rkmce->rkmce_metadata_internal_topic);
2332
0
                }
2333
0
        }
2334
2335
0
        if (!cache_updated) {
2336
0
                rd_kafka_dbg(rk, METADATA, "METADATAUPDATE",
2337
0
                             "Cache was not updated");
2338
0
                return RD_KAFKA_OP_RES_HANDLED;
2339
0
        }
2340
2341
0
        rd_kafka_dbg(rk, METADATA, "METADATAUPDATE",
2342
0
                     "Metadata cache updated, propagating changes");
2343
0
        rd_kafka_metadata_cache_propagate_changes(rk);
2344
0
        rd_kafka_metadata_cache_expiry_start(rk);
2345
2346
0
        return RD_KAFKA_OP_RES_HANDLED;
2347
0
}