Beispiel #1
0
        /// <summary>
        /// Consumes messages from Kafka.
        /// </summary>
        /// <param name="request">The request to send to Kafka.</param>
        /// <returns>A list of messages from Kafka.</returns>
        public List <Message> Consume(ConsumerRequest request)
        {
            List <Message> messages = new List <Message>();

            using (KafkaConnection connection = new KafkaConnection(Server, Port))
            {
                connection.Write(request.GetBytes());
                int dataLength = BitConverter.ToInt32(BitWorks.ReverseBytes(connection.Read(4)), 0);

                if (dataLength > 0)
                {
                    byte[] data = connection.Read(dataLength);

                    // TODO: need to check in on kafka error codes...assume all's good for now
                    byte[] unbufferedData = data.Skip(2).ToArray();

                    int processed   = 0;
                    int length      = unbufferedData.Length - 4;
                    int messageSize = 0;
                    while (processed <= length)
                    {
                        messageSize = BitConverter.ToInt32(BitWorks.ReverseBytes(unbufferedData.Skip(processed).Take(4).ToArray <byte>()), 0);
                        messages.Add(Message.ParseFrom(unbufferedData.Skip(processed).Take(messageSize + 4).ToArray <byte>()));
                        processed += 4 + messageSize;
                    }
                }
            }

            return(messages);
        }
Beispiel #2
0
 public void ReverseBytesZeroLengthArray()
 {
     byte[] arr         = new byte[0];
     byte[] reversedArr = BitWorks.ReverseBytes(arr);
     Assert.IsNotNull(reversedArr);
     Assert.AreEqual(0, reversedArr.Length);
 }
Beispiel #3
0
        public void GetBytesValidFormat()
        {
            List <FetchRequest> requests = new List <FetchRequest>
            {
                new FetchRequest("topic a", 0, 0),
                new FetchRequest("topic a", 0, 0),
                new FetchRequest("topic b", 0, 0),
                new FetchRequest("topic c", 0, 0)
            };

            MultiFetchRequest request = new MultiFetchRequest(requests);

            // format = len(request) + requesttype + requestcount + requestpackage
            // total byte count = 4 + (2 + 2 + 100)
            byte[] bytes = request.GetBytes();
            Assert.IsNotNull(bytes);
            Assert.AreEqual(108, bytes.Length);

            // first 4 bytes = the length of the request
            Assert.AreEqual(104, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Take(4).ToArray <byte>()), 0));

            // next 2 bytes = the RequestType which in this case should be Produce
            Assert.AreEqual((short)RequestType.MultiFetch, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(4).Take(2).ToArray <byte>()), 0));

            // next 2 bytes = the number of messages
            Assert.AreEqual((short)4, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(6).Take(2).ToArray <byte>()), 0));
        }
Beispiel #4
0
        public void GetBytesValidStructure()
        {
            string          topicName = "topic";
            ConsumerRequest request   = new ConsumerRequest(topicName, 1, 10L, 100);

            // REQUEST TYPE ID + TOPIC LENGTH + TOPIC + PARTITION + OFFSET + MAX SIZE
            int requestSize = 2 + 2 + topicName.Length + 4 + 8 + 4;

            byte[] bytes = request.GetBytes();
            Assert.IsNotNull(bytes);

            // add 4 bytes for the length of the message at the beginning
            Assert.AreEqual(requestSize + 4, bytes.Length);

            // first 4 bytes = the message length
            Assert.AreEqual(25, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Take(4).ToArray <byte>()), 0));

            // next 2 bytes = the request type
            Assert.AreEqual((short)RequestType.Fetch, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(4).Take(2).ToArray <byte>()), 0));

            // next 2 bytes = the topic length
            Assert.AreEqual((short)topicName.Length, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(6).Take(2).ToArray <byte>()), 0));

            // next few bytes = the topic
            Assert.AreEqual(topicName, Encoding.ASCII.GetString(bytes.Skip(8).Take(topicName.Length).ToArray <byte>()));

            // next 4 bytes = the partition
            Assert.AreEqual(1, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(8 + topicName.Length).Take(4).ToArray <byte>()), 0));

            // next 8 bytes = the offset
            Assert.AreEqual(10, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(12 + topicName.Length).Take(8).ToArray <byte>()), 0));

            // last 4 bytes = the max size
            Assert.AreEqual(100, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(20 + +topicName.Length).Take(4).ToArray <byte>()), 0));
        }
Beispiel #5
0
        public void GetBytesValid()
        {
            string        topicName = "topic";
            OffsetRequest request   = new OffsetRequest(topicName, 0, OffsetRequest.LatestTime, 10);

            // format = len(request) + requesttype + len(topic) + topic + partition + time + max
            // total byte count = 4 + (2 + 2 + 5 + 4 + 8 + 4)
            byte[] bytes = request.GetBytes();
            Assert.IsNotNull(bytes);
            Assert.AreEqual(29, bytes.Length);

            // first 4 bytes = the length of the request
            Assert.AreEqual(25, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Take(4).ToArray <byte>()), 0));

            // next 2 bytes = the RequestType which in this case should be Produce
            Assert.AreEqual((short)RequestType.Offsets, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(4).Take(2).ToArray <byte>()), 0));

            // next 2 bytes = the length of the topic
            Assert.AreEqual((short)5, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(6).Take(2).ToArray <byte>()), 0));

            // next 5 bytes = the topic
            Assert.AreEqual(topicName, Encoding.ASCII.GetString(bytes.Skip(8).Take(5).ToArray <byte>()));

            // next 4 bytes = the partition
            Assert.AreEqual(0, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(13).Take(4).ToArray <byte>()), 0));

            // next 8 bytes = time
            Assert.AreEqual(OffsetRequest.LatestTime, BitConverter.ToInt64(BitWorks.ReverseBytes(bytes.Skip(17).Take(8).ToArray <byte>()), 0));

            // next 4 bytes = max offsets
            Assert.AreEqual(10, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(25).Take(4).ToArray <byte>()), 0));
        }
Beispiel #6
0
        public void GetBytesValidFormat()
        {
            string          topicName = "topic";
            ProducerRequest request   = new ProducerRequest(
                topicName, 0, new List <Message> {
                new Message(new byte[10])
            });

            // format = len(request) + requesttype + len(topic) + topic + partition + len(messagepack) + message
            // total byte count = 4 + (2 + 2 + 5 + 4 + 4 + 19)
            byte[] bytes = request.GetBytes();
            Assert.IsNotNull(bytes);
            Assert.AreEqual(40, bytes.Length);

            // first 4 bytes = the length of the request
            Assert.AreEqual(36, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Take(4).ToArray <byte>()), 0));

            // next 2 bytes = the RequestType which in this case should be Produce
            Assert.AreEqual((short)RequestType.Produce, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(4).Take(2).ToArray <byte>()), 0));

            // next 2 bytes = the length of the topic
            Assert.AreEqual((short)5, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(6).Take(2).ToArray <byte>()), 0));

            // next 5 bytes = the topic
            Assert.AreEqual(topicName, Encoding.ASCII.GetString(bytes.Skip(8).Take(5).ToArray <byte>()));

            // next 4 bytes = the partition
            Assert.AreEqual(0, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(13).Take(4).ToArray <byte>()), 0));

            // next 4 bytes = the length of the individual messages in the pack
            Assert.AreEqual(19, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(17).Take(4).ToArray <byte>()), 0));

            // fianl bytes = the individual messages in the pack
            Assert.AreEqual(19, bytes.Skip(21).ToArray <byte>().Length);
        }
Beispiel #7
0
        /// <summary>
        /// Get a list of valid offsets (up to maxSize) before the given time.
        /// </summary>
        /// <param name="request">The offset request.</param>
        /// <returns>List of offsets, in descending order.</returns>
        public IList <long> GetOffsetsBefore(OffsetRequest request)
        {
            List <long> offsets = new List <long>();

            using (KafkaConnection connection = new KafkaConnection(Server, Port))
            {
                connection.Write(request.GetBytes());

                int dataLength = BitConverter.ToInt32(BitWorks.ReverseBytes(connection.Read(4)), 0);

                if (dataLength > 0)
                {
                    byte[] data = connection.Read(dataLength);

                    // TODO: need to check in on kafka error codes...assume all's good for now
                    byte[] unbufferedData = data.Skip(2).ToArray();

                    // first four bytes are the number of offsets
                    int numOfOffsets = BitConverter.ToInt32(BitWorks.ReverseBytes(unbufferedData.Take(4).ToArray <byte>()), 0);

                    int position = 0;
                    for (int ix = 0; ix < numOfOffsets; ix++)
                    {
                        position = (ix * 8) + 4;
                        offsets.Add(BitConverter.ToInt64(BitWorks.ReverseBytes(unbufferedData.Skip(position).Take(8).ToArray <byte>()), 0));
                    }
                }
            }

            return(offsets);
        }
Beispiel #8
0
        public void ReverseBytesValid()
        {
            byte[] arr      = BitConverter.GetBytes((short)1);
            byte[] original = new byte[2];
            arr.CopyTo(original, 0);
            byte[] reversedArr = BitWorks.ReverseBytes(arr);

            TestReversedArray(original, reversedArr);
        }
Beispiel #9
0
        /// <summary>
        /// Parses a message from a byte array given the format Kafka likes.
        /// </summary>
        /// <param name="data">The data for a message.</param>
        /// <returns>The message.</returns>
        public static Message ParseFrom(byte[] data)
        {
            int  size  = BitConverter.ToInt32(BitWorks.ReverseBytes(data.Take(4).ToArray <byte>()), 0);
            byte magic = data[4];

            byte[] checksum = data.Skip(5).Take(4).ToArray <byte>();
            byte[] payload  = data.Skip(9).Take(size).ToArray <byte>();

            return(new Message(payload, magic, checksum));
        }
Beispiel #10
0
        internal static BufferedMessageSet ParseFrom(byte[] bytes)
        {
            var messages  = new List <Message>();
            int processed = 0;
            int length    = bytes.Length - 4;

            while (processed <= length)
            {
                int messageSize = BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(processed).Take(4).ToArray()), 0);
                messages.Add(Message.ParseFrom(bytes.Skip(processed).Take(messageSize + 4).ToArray()));
                processed += 4 + messageSize;
            }

            return(new BufferedMessageSet(messages));
        }
Beispiel #11
0
 public FetchResponse Fetch(FetchRequest request)
 {
     using (KafkaConnection connection = new KafkaConnection(server, port))
     {
         connection.Write(request.GetRequestBytes().ToArray());
         int dataLength = BitConverter.ToInt32(BitWorks.ReverseBytes(connection.Read(4)), 0);
         if (dataLength > 0)
         {
             byte[] data          = connection.Read(dataLength);
             var    fetchResponse = new FetchResponse(data);
             return(fetchResponse);
         }
         return(null);
     }
 }
Beispiel #12
0
        /// <summary>
        /// Get a list of valid offsets (up to maxSize) before the given time.
        /// </summary>
        /// <param name="request">The offset request.</param>
        /// <returns>List of offsets, in descending order.</returns>
        public OffsetResponse GetOffsetResponseBefore(OffsetRequest request)
        {
            using (var connection = new KafkaConnection(server, port))
            {
                connection.Write(request.GetRequestBytes().ToArray());

                int dataLength = BitConverter.ToInt32(BitWorks.ReverseBytes(connection.Read(4)), 0);

                if (dataLength == 0)
                {
                    return(null);
                }
                byte[] data           = connection.Read(dataLength);
                var    offsetResponse = new OffsetResponse(data);
                return(offsetResponse);
            }
        }
Beispiel #13
0
        public ProduceResponse Produce(int correlationId, string clientId, int timeOut, string topicName, int partitionId, byte[] payLoad)
        {
            var request = new ProduceRequest(timeOut, correlationId, clientId);

            request.AddMessage(topicName, partitionId, payLoad);
            using (var connection = new KafkaConnection(server, port))
            {
                connection.Write(request.GetRequestBytes().ToArray());

                int dataLength = BitConverter.ToInt32(BitWorks.ReverseBytes(connection.Read(4)), 0);

                var response = new ProduceResponse();
                if (dataLength != 0)
                {
                    byte[] data = connection.Read(dataLength);
                    response.Parse(data);
                }
                return(response);
            }
        }
Beispiel #14
0
        /// <summary>
        /// Get meta data for a topic
        /// </summary>
        /// <param name="correlationId"></param>Id used by the client to identify this transaction. Returned in the response
        /// <param name="clientId"></param>Name to identify the client. Used in server logs
        /// <param name="topicName"></param> Name of the requested topic. If topic name is null metadata for all topics will be returned
        /// <returns></returns>
        public MetadataResponse Metadata(int correlationId, string clientId, String topicName)
        {
            MetadataRequest request = new MetadataRequest(correlationId, clientId, topicName);

            using (var connection = new KafkaConnection(server, port))
            {
                connection.Write(request.GetRequestBytes().ToArray());

                int dataLength = BitConverter.ToInt32(BitWorks.ReverseBytes(connection.Read(4)), 0);

                if (dataLength == 0)
                {
                    return(null);
                }
                byte[]           data             = connection.Read(dataLength);
                MetadataResponse metadataResponse = new MetadataResponse();
                metadataResponse.Parse(data, 0);
                return(metadataResponse);
            }
        }
        public void WriteToValidFormat()
        {
            List <ProducerRequest> requests = new List <ProducerRequest>
            {
                new ProducerRequest("topic a", 0, new List <Message> {
                    new Message(new byte[10])
                }),
                new ProducerRequest("topic a", 0, new List <Message> {
                    new Message(new byte[10])
                }),
                new ProducerRequest("topic b", 0, new List <Message> {
                    new Message(new byte[10])
                }),
                new ProducerRequest("topic c", 0, new List <Message> {
                    new Message(new byte[10])
                })
            };

            MultiProducerRequest request = new MultiProducerRequest(requests);

            // format = len(request) + requesttype + requestcount + requestpackage
            // total byte count = 4 + (2 + 2 + 144)
            MemoryStream ms = new MemoryStream();

            request.WriteTo(ms);
            byte[] bytes = ms.ToArray();
            Assert.IsNotNull(bytes);
            Assert.AreEqual(156, bytes.Length);

            // first 4 bytes = the length of the request
            Assert.AreEqual(152, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Take(4).ToArray <byte>()), 0));

            // next 2 bytes = the RequestType which in this case should be Produce
            Assert.AreEqual((short)RequestTypes.MultiProduce, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(4).Take(2).ToArray <byte>()), 0));

            // next 2 bytes = the number of messages
            Assert.AreEqual((short)4, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(6).Take(2).ToArray <byte>()), 0));
        }
Beispiel #16
0
        public static Message ParseFrom(byte[] data)
        {
            int  size  = BitConverter.ToInt32(BitWorks.ReverseBytes(data.Take(4).ToArray()), 0);
            byte magic = data[4];

            byte[] checksum;
            byte[] payload;
            byte   attributes;

            if (magic == 1)
            {
                attributes = data[5];
                checksum   = data.Skip(6).Take(4).ToArray();
                payload    = data.Skip(10).Take(size).ToArray();
                return(new Message(payload, checksum, Messages.CompressionCodec.GetCompressionCodec(attributes & CompressionCodeMask)));
            }
            else
            {
                checksum = data.Skip(5).Take(4).ToArray();
                payload  = data.Skip(9).Take(size).ToArray();
                return(new Message(payload, checksum));
            }
        }
Beispiel #17
0
        /// <summary>
        /// Get a list of valid offsets (up to maxSize) before the given time.
        /// </summary>
        /// <param name="request">The offset request.</param>
        /// <returns>List of offsets, in descending order.</returns>
        public IList <long> GetOffsetsBefore(OffsetRequest request)
        {
            List <long> offsets = new List <long>();

            using (KafkaConnection connection = new KafkaConnection(Server, Port))
            {
                connection.Write(request.GetBytes());

                int dataLength = BitConverter.ToInt32(BitWorks.ReverseBytes(connection.Read(4)), 0);

                if (dataLength > 0)
                {
                    byte[] data = connection.Read(dataLength);

                    int errorCode = BitConverter.ToInt16(BitWorks.ReverseBytes(data.Take(2).ToArray <byte>()), 0);
                    if (errorCode != KafkaException.NoError)
                    {
                        throw new KafkaException(errorCode);
                    }

                    // skip the error code and process the rest
                    byte[] unbufferedData = data.Skip(2).ToArray();

                    // first four bytes are the number of offsets
                    int numOfOffsets = BitConverter.ToInt32(BitWorks.ReverseBytes(unbufferedData.Take(4).ToArray <byte>()), 0);

                    int position = 0;
                    for (int ix = 0; ix < numOfOffsets; ix++)
                    {
                        position = (ix * 8) + 4;
                        offsets.Add(BitConverter.ToInt64(BitWorks.ReverseBytes(unbufferedData.Skip(position).Take(8).ToArray <byte>()), 0));
                    }
                }
            }

            return(offsets);
        }
Beispiel #18
0
        /// <summary>
        /// Consumes messages from Kafka.
        /// </summary>
        /// <param name="request">The request to send to Kafka.</param>
        /// <returns>A list of messages from Kafka.</returns>
        public List <Message> Consume(FetchRequest request)
        {
            List <Message> messages = new List <Message>();

            using (KafkaConnection connection = new KafkaConnection(Server, Port))
            {
                connection.Write(request.GetBytes());
                int dataLength = BitConverter.ToInt32(BitWorks.ReverseBytes(connection.Read(4)), 0);

                if (dataLength > 0)
                {
                    byte[] data = connection.Read(dataLength);

                    int errorCode = BitConverter.ToInt16(BitWorks.ReverseBytes(data.Take(2).ToArray <byte>()), 0);
                    if (errorCode != KafkaException.NoError)
                    {
                        throw new KafkaException(errorCode);
                    }

                    // skip the error code and process the rest
                    byte[] unbufferedData = data.Skip(2).ToArray();

                    int processed   = 0;
                    int length      = unbufferedData.Length - 4;
                    int messageSize = 0;
                    while (processed <= length)
                    {
                        messageSize = BitConverter.ToInt32(BitWorks.ReverseBytes(unbufferedData.Skip(processed).Take(4).ToArray <byte>()), 0);
                        messages.Add(Message.ParseFrom(unbufferedData.Skip(processed).Take(messageSize + 4).ToArray <byte>()));
                        processed += 4 + messageSize;
                    }
                }
            }

            return(messages);
        }
Beispiel #19
0
        public void GetBytesValidStructure()
        {
            string topicName     = "topic";
            int    correlationId = 1;
            string clientId      = "TestClient";
            int    maxWait       = 234;
            int    minBytes      = 345;

            var requestMap = new Dictionary <string, List <PartitionFetchInfo> >();

            requestMap[topicName] = new List <PartitionFetchInfo>()
            {
                new PartitionFetchInfo(2, 4000, 777)
            };


            var request = new FetchRequest(correlationId, clientId, maxWait, minBytes, requestMap);


            int requestSize = 4 +                                                                        //request size
                              2 +                                                                        //request type id
                              2 +                                                                        //versionId
                              4 +                                                                        //correlation id
                              BitWorks.GetShortStringLength(clientId, AbstractRequest.DefaultEncoding) + // client id length
                              4 +                                                                        //replica id
                              4 +                                                                        //max wait
                              4 +                                                                        //min bytes
                              4 +                                                                        //offset info count
                                                                                                         //=== offset info part
                              request.OffsetInfo.Keys.Sum(x => BitWorks.GetShortStringLength(x, AbstractRequest.DefaultEncoding)) +
                              request.OffsetInfo.Values.Select(pl => 4 + pl.Sum(p => p.SizeInBytes)).Sum();

            var ms = new MemoryStream();

            request.WriteTo(ms);
            byte[] bytes = ms.ToArray();
            Assert.IsNotNull(bytes);

            // add 4 bytes for the length of the message at the beginning
            Assert.AreEqual(requestSize, bytes.Length);

            // first 4 bytes = the message length
            Assert.AreEqual(requestSize - 4, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Take(4).ToArray <byte>()), 0));

            // next 2 bytes = the request type
            Assert.AreEqual((short)RequestTypes.Fetch,
                            BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(4).Take(2).ToArray <byte>()), 0));

            // next 2 bytes = the version id
            Assert.AreEqual((short)FetchRequest.CurrentVersion,
                            BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(6).Take(2).ToArray <byte>()), 0));

            // next 2 bytes = the correlation id
            Assert.AreEqual(correlationId,
                            BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(8).Take(4).ToArray <byte>()), 0));

            // next 2 bytes = the client id length
            Assert.AreEqual((short)clientId.Length,
                            BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(12).Take(2).ToArray <byte>()), 0));

            // next few bytes = the client id
            Assert.AreEqual(clientId, Encoding.ASCII.GetString(bytes.Skip(14).Take(clientId.Length).ToArray <byte>()));

            // next 4 bytes = replica id
            Assert.AreEqual(-1,
                            BitConverter.ToInt32(
                                BitWorks.ReverseBytes(bytes.Skip(14 + clientId.Length).Take(4).ToArray <byte>()), 0));

            // next 4 bytes = max wait
            Assert.AreEqual(maxWait,
                            BitConverter.ToInt32(
                                BitWorks.ReverseBytes(bytes.Skip(18 + clientId.Length).Take(4).ToArray <byte>()), 0));

            // next 4 bytes = min bytes
            Assert.AreEqual(minBytes,
                            BitConverter.ToInt32(
                                BitWorks.ReverseBytes(bytes.Skip(22 + clientId.Length).Take(4).ToArray <byte>()), 0));

            // next 4 bytes = offset info count
            Assert.AreEqual(1,
                            BitConverter.ToInt32(
                                BitWorks.ReverseBytes(bytes.Skip(26 + clientId.Length).Take(4).ToArray <byte>()), 0));

            //=== offset info part

            // next 2 bytes = the topic length
            Assert.AreEqual((short)topicName.Length,
                            BitConverter.ToInt16(
                                BitWorks.ReverseBytes(bytes.Skip(30 + clientId.Length).Take(2).ToArray <byte>()), 0));

            // next few bytes = the topic
            Assert.AreEqual(topicName,
                            Encoding.ASCII.GetString(
                                bytes.Skip(32 + clientId.Length).Take(topicName.Length).ToArray <byte>()));

            // next 4 bytes = partitions count
            Assert.AreEqual(1,
                            BitConverter.ToInt32(
                                BitWorks.ReverseBytes(
                                    bytes.Skip(32 + clientId.Length + topicName.Length).Take(4).ToArray <byte>()), 0));

            // next 4 bytes = partition
            Assert.AreEqual(2,
                            BitConverter.ToInt32(
                                BitWorks.ReverseBytes(
                                    bytes.Skip(36 + clientId.Length + topicName.Length).Take(4).ToArray <byte>()), 0));

            // next 4 bytes = offset
            Assert.AreEqual(4000,
                            BitConverter.ToInt64(
                                BitWorks.ReverseBytes(
                                    bytes.Skip(40 + clientId.Length + topicName.Length).Take(8).ToArray <byte>()), 0));

            // next 4 bytes = fetch size
            Assert.AreEqual(777,
                            BitConverter.ToInt32(
                                BitWorks.ReverseBytes(
                                    bytes.Skip(48 + clientId.Length + topicName.Length).Take(8).ToArray <byte>()), 0));
        }
Beispiel #20
0
        /// <summary>
        /// Executes a multi-fetch operation.
        /// </summary>
        /// <param name="request">The request to push to Kafka.</param>
        /// <returns>
        /// A list containing sets of messages. The message sets should match the request order.
        /// </returns>
        public List <List <Message> > Consume(MultiFetchRequest request)
        {
            int fetchRequests = request.ConsumerRequests.Count;

            List <List <Message> > messages = new List <List <Message> >();

            using (KafkaConnection connection = new KafkaConnection(Server, Port))
            {
                connection.Write(request.GetBytes());
                int dataLength = BitConverter.ToInt32(BitWorks.ReverseBytes(connection.Read(4)), 0);

                if (dataLength > 0)
                {
                    byte[] data = connection.Read(dataLength);

                    int position = 0;

                    int errorCode = BitConverter.ToInt16(BitWorks.ReverseBytes(data.Take(2).ToArray <byte>()), 0);
                    if (errorCode != KafkaException.NoError)
                    {
                        throw new KafkaException(errorCode);
                    }

                    // skip the error code and process the rest
                    position = position + 2;

                    for (int ix = 0; ix < fetchRequests; ix++)
                    {
                        messages.Add(new List <Message>());

                        int messageSetSize = BitConverter.ToInt32(BitWorks.ReverseBytes(data.Skip(position).Take(4).ToArray <byte>()), 0);
                        position = position + 4;

                        errorCode = BitConverter.ToInt16(BitWorks.ReverseBytes(data.Skip(position).Take(2).ToArray <byte>()), 0);
                        if (errorCode != KafkaException.NoError)
                        {
                            throw new KafkaException(errorCode);
                        }

                        // skip the error code and process the rest
                        position = position + 2;

                        byte[] messageSetBytes = data.Skip(position).ToArray <byte>().Take(messageSetSize).ToArray <byte>();

                        int processed   = 0;
                        int messageSize = 0;

                        // dropped 2 bytes at the end...padding???
                        while (processed < messageSetBytes.Length - 2)
                        {
                            messageSize = BitConverter.ToInt32(BitWorks.ReverseBytes(messageSetBytes.Skip(processed).Take(4).ToArray <byte>()), 0);
                            messages[ix].Add(Message.ParseFrom(messageSetBytes.Skip(processed).Take(messageSize + 4).ToArray <byte>()));
                            processed += 4 + messageSize;
                        }

                        position = position + processed;
                    }
                }
            }

            return(messages);
        }
Beispiel #21
0
 public void ReverseBytesNullArray()
 {
     byte[] arr = null;
     Assert.IsNull(BitWorks.ReverseBytes(arr));
 }
        public void GetBytesValidStructure()
        {
            string topicName     = "topic";
            int    correlationId = 1;
            string clientId      = "TestClient";
            short  requiredAcks  = 5;
            int    ackTimeout    = 345;

            var   partition = 2;
            short error     = 0;
            var   payload   = Encoding.UTF8.GetBytes("testMessage");
            BufferedMessageSet messageSet = new BufferedMessageSet(new List <Message>()
            {
                new Message(payload)
            }, 0);

            var partitionData = new PartitionData(partition, ErrorMapper.ToError(error), messageSet);

            var topicData = new TopicData(topicName, new List <PartitionData>()
            {
                partitionData
            });

            var request = new ProducerRequest(correlationId, clientId, requiredAcks, ackTimeout, new List <TopicData>()
            {
                topicData
            });

            int requestSize = 2 +                                            //request type id
                              2 +                                            //versionId
                              4 +                                            //correlation id
                              request.GetShortStringWriteLength(clientId) +  // actual client id
                              2 +                                            //required acks
                              4 +                                            //ack timeout
                              4 +                                            //data count
                                                                             //=== data part
                              request.GetShortStringWriteLength(topicName) + //topic
                              4 +                                            //partition data count
                              4 +                                            //partition id
                              4 +                                            //messages set size
                              messageSet.SetSize;

            var ms = new MemoryStream();

            request.WriteTo(ms);
            byte[] bytes = ms.ToArray();
            Assert.IsNotNull(bytes);

            // add 4 bytes for the length of the message at the beginning
            Assert.AreEqual(requestSize + 4, bytes.Length);

            // first 4 bytes = the message length
            Assert.AreEqual(requestSize, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Take(4).ToArray <byte>()), 0));

            // next 2 bytes = the request type
            Assert.AreEqual((short)RequestTypes.Produce, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(4).Take(2).ToArray <byte>()), 0));

            // next 2 bytes = the version id
            Assert.AreEqual((short)ProducerRequest.CurrentVersion, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(6).Take(2).ToArray <byte>()), 0));

            // next 2 bytes = the correlation id
            Assert.AreEqual(correlationId, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(8).Take(4).ToArray <byte>()), 0));

            // next 2 bytes = the client id length
            Assert.AreEqual((short)clientId.Length, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(12).Take(2).ToArray <byte>()), 0));

            // next few bytes = the client id
            Assert.AreEqual(clientId, Encoding.ASCII.GetString(bytes.Skip(14).Take(clientId.Length).ToArray <byte>()));

            // next 2 bytes = the required acks
            Assert.AreEqual((short)requiredAcks, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(14 + clientId.Length).Take(2).ToArray <byte>()), 0));

            // next 4 bytes = the ack timeout
            Assert.AreEqual(ackTimeout, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(16 + clientId.Length).Take(4).ToArray <byte>()), 0));

            // next 4 bytes = the data count
            Assert.AreEqual(1, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(20 + clientId.Length).Take(4).ToArray <byte>()), 0));

            // next 2 bytes = the tppic length
            Assert.AreEqual((short)topicName.Length, BitConverter.ToInt16(BitWorks.ReverseBytes(bytes.Skip(24 + clientId.Length).Take(2).ToArray <byte>()), 0));

            // next few bytes = the topic
            Assert.AreEqual(topicName, Encoding.ASCII.GetString(bytes.Skip(26 + clientId.Length).Take(topicName.Length).ToArray <byte>()));

            // next 4 bytes = the partition data count
            Assert.AreEqual(topicData.PartitionData.Count(), BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(26 + clientId.Length + topicName.Length).Take(4).ToArray <byte>()), 0));

            // next 4 bytes = the partition
            Assert.AreEqual(partition, BitConverter.ToInt32(BitWorks.ReverseBytes(bytes.Skip(30 + clientId.Length + topicName.Length).Take(4).ToArray <byte>()), 0));

            // skipping MessageSet check - this could be done separately in another unit test
        }