/*
         *  allTopics  - if true: request info about all topics in cluster,
         *               else: only request info about locally known topics.
         *  onlyTopic  - only request info about this topic
         *  timeout    - maximum response time before failing.
         */
        internal Metadata Metadata(bool allTopics,
                                   SafeTopicHandle onlyTopic,
                                   bool includeInternal,
                                   TimeSpan timeout)
        {
            if (timeout == default(TimeSpan))
            {
                timeout = TimeSpan.FromSeconds(10);
            }

            IntPtr    metaPtr;
            ErrorCode err = LibRdKafka.metadata(
                handle, allTopics,
                onlyTopic?.DangerousGetHandle() ?? IntPtr.Zero,
                /* const struct rd_kafka_metadata ** */ out metaPtr,
                (IntPtr)timeout.TotalMilliseconds);

            if (err == ErrorCode.NO_ERROR)
            {
                try {
                    var meta = (rd_kafka_metadata)Marshal.PtrToStructure <rd_kafka_metadata>(metaPtr);

                    var brokers = Enumerable.Range(0, meta.broker_cnt)
                                  .Select(i => Marshal.PtrToStructure <rd_kafka_metadata_broker>(
                                              meta.brokers + i * Marshal.SizeOf <rd_kafka_metadata_broker>()))
                                  .Select(b => new BrokerMetadata()
                    {
                        BrokerId = b.id, Host = b.host, Port = b.port
                    })
                                  .ToList();

                    // TODO: filter our topics starting with __, as those are internal. Maybe add a flag to not ignore them.
                    var topics = Enumerable.Range(0, meta.topic_cnt)
                                 .Select(i => Marshal.PtrToStructure <rd_kafka_metadata_topic>(
                                             meta.topics + i * Marshal.SizeOf <rd_kafka_metadata_topic>()))
                                 .Where(t => includeInternal || !t.topic.StartsWith("__"))
                                 .Select(t => new TopicMetadata()
                    {
                        Topic      = t.topic,
                        Error      = t.err,
                        Partitions =
                            Enumerable.Range(0, t.partition_cnt)
                            .Select(j => Marshal.PtrToStructure <rd_kafka_metadata_partition>(
                                        t.partitions + j * Marshal.SizeOf <rd_kafka_metadata_partition>()))
                            .Select(p => new PartitionMetadata()
                        {
                            PartitionId    = p.id,
                            Error          = p.err,
                            Leader         = p.leader,
                            Replicas       = MarshalCopy(p.replicas, p.replica_cnt),
                            InSyncReplicas = MarshalCopy(p.isrs, p.isr_cnt)
                        })
                            .ToList()
                    })
                                 .ToList();

                    return(new Metadata()
                    {
                        Brokers = brokers,
                        Topics = topics,
                        OriginatingBrokerId = meta.orig_broker_id,
                        OriginatingBrokerName = meta.orig_broker_name
                    });
                }
                finally
                {
                    LibRdKafka.metadata_destroy(metaPtr);
                }
            }
            else
            {
                throw RdKafkaException.FromErr(err, "Could not retrieve metadata");
            }
        }