From a78e0cba8edf3c143bda240e67bc3a52f1507edd Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Thu, 2 Feb 2017 18:26:18 +0000 Subject: [PATCH] Add kafka and postgres clients to vendor directory --- vendor/manifest | 80 + .../github.com/Shopify/sarama/CHANGELOG.md | 355 +++ .../src/github.com/Shopify/sarama/MIT-LICENSE | 20 + vendor/src/github.com/Shopify/sarama/Makefile | 21 + .../src/github.com/Shopify/sarama/README.md | 36 + .../src/github.com/Shopify/sarama/Vagrantfile | 20 + .../Shopify/sarama/api_versions_request.go | 24 + .../sarama/api_versions_request_test.go | 14 + .../Shopify/sarama/api_versions_response.go | 86 + .../sarama/api_versions_response_test.go | 32 + .../Shopify/sarama/async_producer.go | 905 ++++++++ .../Shopify/sarama/async_producer_test.go | 841 +++++++ .../src/github.com/Shopify/sarama/broker.go | 674 ++++++ .../github.com/Shopify/sarama/broker_test.go | 315 +++ .../src/github.com/Shopify/sarama/client.go | 749 +++++++ .../github.com/Shopify/sarama/client_test.go | 608 +++++ .../src/github.com/Shopify/sarama/config.go | 417 ++++ .../github.com/Shopify/sarama/config_test.go | 70 + .../src/github.com/Shopify/sarama/consumer.go | 735 ++++++ .../Shopify/sarama/consumer_group_members.go | 94 + .../sarama/consumer_group_members_test.go | 73 + .../sarama/consumer_metadata_request.go | 26 + .../sarama/consumer_metadata_request_test.go | 19 + .../sarama/consumer_metadata_response.go | 85 + .../sarama/consumer_metadata_response_test.go | 35 + .../Shopify/sarama/consumer_test.go | 854 +++++++ .../github.com/Shopify/sarama/crc32_field.go | 36 + .../Shopify/sarama/describe_groups_request.go | 30 + .../sarama/describe_groups_request_test.go | 34 + .../sarama/describe_groups_response.go | 186 ++ .../sarama/describe_groups_response_test.go | 91 + vendor/src/github.com/Shopify/sarama/dev.yml | 13 + .../Shopify/sarama/encoder_decoder.go | 89 + .../src/github.com/Shopify/sarama/errors.go | 197 ++ .../Shopify/sarama/examples/README.md | 9 + .../sarama/examples/http_server/README.md | 7 + .../examples/http_server/http_server.go | 247 +++ .../examples/http_server/http_server_test.go | 109 + .../Shopify/sarama/fetch_request.go | 136 ++ .../Shopify/sarama/fetch_request_test.go | 34 + .../Shopify/sarama/fetch_response.go | 210 ++ .../Shopify/sarama/fetch_response_test.go | 84 + .../Shopify/sarama/functional_client_test.go | 90 + .../sarama/functional_consumer_test.go | 61 + .../sarama/functional_offset_manager_test.go | 47 + .../sarama/functional_producer_test.go | 323 +++ .../Shopify/sarama/functional_test.go | 148 ++ .../Shopify/sarama/heartbeat_request.go | 47 + .../Shopify/sarama/heartbeat_request_test.go | 21 + .../Shopify/sarama/heartbeat_response.go | 32 + .../Shopify/sarama/heartbeat_response_test.go | 18 + .../Shopify/sarama/join_group_request.go | 108 + .../Shopify/sarama/join_group_request_test.go | 41 + .../Shopify/sarama/join_group_response.go | 114 + .../sarama/join_group_response_test.go | 98 + .../Shopify/sarama/leave_group_request.go | 40 + .../sarama/leave_group_request_test.go | 19 + .../Shopify/sarama/leave_group_response.go | 32 + .../sarama/leave_group_response_test.go | 24 + .../github.com/Shopify/sarama/length_field.go | 29 + .../Shopify/sarama/list_groups_request.go | 24 + .../sarama/list_groups_request_test.go | 7 + .../Shopify/sarama/list_groups_response.go | 68 + .../sarama/list_groups_response_test.go | 58 + .../src/github.com/Shopify/sarama/message.go | 196 ++ .../github.com/Shopify/sarama/message_set.go | 89 + .../github.com/Shopify/sarama/message_test.go | 165 ++ .../Shopify/sarama/metadata_request.go | 52 + .../Shopify/sarama/metadata_request_test.go | 29 + .../Shopify/sarama/metadata_response.go | 239 ++ .../Shopify/sarama/metadata_response_test.go | 139 ++ .../src/github.com/Shopify/sarama/metrics.go | 51 + .../github.com/Shopify/sarama/metrics_test.go | 172 ++ .../github.com/Shopify/sarama/mockbroker.go | 324 +++ .../Shopify/sarama/mockresponses.go | 455 ++++ .../github.com/Shopify/sarama/mocks/README.md | 13 + .../Shopify/sarama/mocks/async_producer.go | 174 ++ .../sarama/mocks/async_producer_test.go | 132 ++ .../Shopify/sarama/mocks/consumer.go | 315 +++ .../Shopify/sarama/mocks/consumer_test.go | 249 +++ .../github.com/Shopify/sarama/mocks/mocks.go | 48 + .../Shopify/sarama/mocks/sync_producer.go | 148 ++ .../sarama/mocks/sync_producer_test.go | 124 ++ .../Shopify/sarama/offset_commit_request.go | 190 ++ .../sarama/offset_commit_request_test.go | 90 + .../Shopify/sarama/offset_commit_response.go | 85 + .../sarama/offset_commit_response_test.go | 24 + .../Shopify/sarama/offset_fetch_request.go | 81 + .../sarama/offset_fetch_request_test.go | 31 + .../Shopify/sarama/offset_fetch_response.go | 143 ++ .../sarama/offset_fetch_response_test.go | 22 + .../Shopify/sarama/offset_manager.go | 542 +++++ .../Shopify/sarama/offset_manager_test.go | 369 ++++ .../Shopify/sarama/offset_request.go | 132 ++ .../Shopify/sarama/offset_request_test.go | 43 + .../Shopify/sarama/offset_response.go | 174 ++ .../Shopify/sarama/offset_response_test.go | 111 + .../Shopify/sarama/packet_decoder.go | 45 + .../Shopify/sarama/packet_encoder.go | 50 + .../github.com/Shopify/sarama/partitioner.go | 123 ++ .../Shopify/sarama/partitioner_test.go | 215 ++ .../github.com/Shopify/sarama/prep_encoder.go | 121 + .../Shopify/sarama/produce_request.go | 209 ++ .../Shopify/sarama/produce_request_test.go | 47 + .../Shopify/sarama/produce_response.go | 158 ++ .../Shopify/sarama/produce_response_test.go | 67 + .../github.com/Shopify/sarama/produce_set.go | 176 ++ .../Shopify/sarama/produce_set_test.go | 185 ++ .../github.com/Shopify/sarama/real_decoder.go | 259 +++ .../github.com/Shopify/sarama/real_encoder.go | 129 ++ .../src/github.com/Shopify/sarama/request.go | 119 + .../github.com/Shopify/sarama/request_test.go | 91 + .../Shopify/sarama/response_header.go | 21 + .../Shopify/sarama/response_header_test.go | 21 + .../src/github.com/Shopify/sarama/sarama.go | 99 + .../Shopify/sarama/sasl_handshake_request.go | 33 + .../sarama/sasl_handshake_request_test.go | 17 + .../Shopify/sarama/sasl_handshake_response.go | 38 + .../sarama/sasl_handshake_response_test.go | 24 + .../Shopify/sarama/sync_group_request.go | 100 + .../Shopify/sarama/sync_group_request_test.go | 38 + .../Shopify/sarama/sync_group_response.go | 40 + .../sarama/sync_group_response_test.go | 40 + .../Shopify/sarama/sync_producer.go | 164 ++ .../Shopify/sarama/sync_producer_test.go | 199 ++ .../github.com/Shopify/sarama/tools/README.md | 10 + .../tools/kafka-console-consumer/README.md | 29 + .../kafka-console-consumer.go | 145 ++ .../kafka-console-partitionconsumer/README.md | 28 + .../kafka-console-partitionconsumer.go | 102 + .../tools/kafka-console-producer/README.md | 34 + .../kafka-console-producer.go | 124 ++ vendor/src/github.com/Shopify/sarama/utils.go | 152 ++ .../github.com/Shopify/sarama/utils_test.go | 21 + .../Shopify/sarama/vagrant/boot_cluster.sh | 22 + .../Shopify/sarama/vagrant/create_topics.sh | 8 + .../Shopify/sarama/vagrant/install_cluster.sh | 49 + .../Shopify/sarama/vagrant/kafka.conf | 9 + .../Shopify/sarama/vagrant/provision.sh | 15 + .../Shopify/sarama/vagrant/run_toxiproxy.sh | 22 + .../Shopify/sarama/vagrant/server.properties | 127 ++ .../Shopify/sarama/vagrant/setup_services.sh | 29 + .../Shopify/sarama/vagrant/toxiproxy.conf | 6 + .../Shopify/sarama/vagrant/zookeeper.conf | 7 + .../sarama/vagrant/zookeeper.properties | 36 + .../github.com/davecgh/go-spew/spew/bypass.go | 152 ++ .../davecgh/go-spew/spew/bypasssafe.go | 38 + .../github.com/davecgh/go-spew/spew/common.go | 341 +++ .../davecgh/go-spew/spew/common_test.go | 298 +++ .../github.com/davecgh/go-spew/spew/config.go | 306 +++ .../github.com/davecgh/go-spew/spew/doc.go | 211 ++ .../github.com/davecgh/go-spew/spew/dump.go | 509 +++++ .../davecgh/go-spew/spew/dump_test.go | 1042 +++++++++ .../davecgh/go-spew/spew/dumpcgo_test.go | 99 + .../davecgh/go-spew/spew/dumpnocgo_test.go | 26 + .../davecgh/go-spew/spew/example_test.go | 226 ++ .../github.com/davecgh/go-spew/spew/format.go | 419 ++++ .../davecgh/go-spew/spew/format_test.go | 1558 +++++++++++++ .../davecgh/go-spew/spew/internal_test.go | 87 + .../go-spew/spew/internalunsafe_test.go | 102 + .../github.com/davecgh/go-spew/spew/spew.go | 148 ++ .../davecgh/go-spew/spew/spew_test.go | 320 +++ .../davecgh/go-spew/spew/testdata/dumpcgo.go | 82 + .../eapache/go-resiliency/breaker/README.md | 34 + .../eapache/go-resiliency/breaker/breaker.go | 161 ++ .../go-resiliency/breaker/breaker_test.go | 196 ++ .../eapache/go-xerial-snappy/LICENSE | 21 + .../eapache/go-xerial-snappy/README.md | 13 + .../eapache/go-xerial-snappy/snappy.go | 43 + .../eapache/go-xerial-snappy/snappy_test.go | 49 + vendor/src/github.com/eapache/queue/LICENSE | 21 + vendor/src/github.com/eapache/queue/README.md | 16 + vendor/src/github.com/eapache/queue/queue.go | 102 + .../github.com/eapache/queue/queue_test.go | 178 ++ vendor/src/github.com/golang/snappy/AUTHORS | 15 + .../src/github.com/golang/snappy/CONTRIBUTORS | 37 + vendor/src/github.com/golang/snappy/LICENSE | 27 + vendor/src/github.com/golang/snappy/README | 107 + .../golang/snappy/cmd/snappytool/main.cpp | 77 + vendor/src/github.com/golang/snappy/decode.go | 237 ++ .../github.com/golang/snappy/decode_amd64.go | 14 + .../github.com/golang/snappy/decode_amd64.s | 490 ++++ .../github.com/golang/snappy/decode_other.go | 101 + vendor/src/github.com/golang/snappy/encode.go | 285 +++ .../github.com/golang/snappy/encode_amd64.go | 29 + .../github.com/golang/snappy/encode_amd64.s | 730 ++++++ .../github.com/golang/snappy/encode_other.go | 238 ++ .../github.com/golang/snappy/golden_test.go | 1965 +++++++++++++++++ vendor/src/github.com/golang/snappy/snappy.go | 87 + .../github.com/golang/snappy/snappy_test.go | 1353 ++++++++++++ .../snappy/testdata/Mark.Twain-Tom.Sawyer.txt | 396 ++++ .../Mark.Twain-Tom.Sawyer.txt.rawsnappy | Bin 0 -> 9871 bytes vendor/src/github.com/klauspost/crc32/LICENSE | 28 + .../src/github.com/klauspost/crc32/README.md | 87 + .../src/github.com/klauspost/crc32/crc32.go | 207 ++ .../github.com/klauspost/crc32/crc32_amd64.go | 230 ++ .../github.com/klauspost/crc32/crc32_amd64.s | 319 +++ .../klauspost/crc32/crc32_amd64p32.go | 43 + .../klauspost/crc32/crc32_amd64p32.s | 67 + .../klauspost/crc32/crc32_generic.go | 89 + .../klauspost/crc32/crc32_otherarch.go | 15 + .../github.com/klauspost/crc32/crc32_s390x.go | 91 + .../github.com/klauspost/crc32/crc32_s390x.s | 249 +++ .../github.com/klauspost/crc32/crc32_test.go | 284 +++ .../klauspost/crc32/example_test.go | 28 + vendor/src/github.com/lib/pq/CONTRIBUTING.md | 29 + vendor/src/github.com/lib/pq/LICENSE.md | 8 + vendor/src/github.com/lib/pq/README.md | 105 + vendor/src/github.com/lib/pq/array.go | 756 +++++++ vendor/src/github.com/lib/pq/array_test.go | 1317 +++++++++++ vendor/src/github.com/lib/pq/bench_test.go | 435 ++++ vendor/src/github.com/lib/pq/buf.go | 91 + vendor/src/github.com/lib/pq/certs/README | 3 + .../github.com/lib/pq/certs/bogus_root.crt | 19 + .../github.com/lib/pq/certs/postgresql.crt | 69 + .../github.com/lib/pq/certs/postgresql.key | 15 + vendor/src/github.com/lib/pq/certs/root.crt | 24 + vendor/src/github.com/lib/pq/certs/server.crt | 81 + vendor/src/github.com/lib/pq/certs/server.key | 27 + vendor/src/github.com/lib/pq/conn.go | 1811 +++++++++++++++ vendor/src/github.com/lib/pq/conn_go18.go | 92 + vendor/src/github.com/lib/pq/conn_test.go | 1495 +++++++++++++ vendor/src/github.com/lib/pq/copy.go | 282 +++ vendor/src/github.com/lib/pq/copy_test.go | 465 ++++ vendor/src/github.com/lib/pq/doc.go | 235 ++ vendor/src/github.com/lib/pq/encode.go | 595 +++++ vendor/src/github.com/lib/pq/encode_test.go | 758 +++++++ vendor/src/github.com/lib/pq/error.go | 508 +++++ vendor/src/github.com/lib/pq/go18_test.go | 165 ++ vendor/src/github.com/lib/pq/hstore/hstore.go | 118 + .../github.com/lib/pq/hstore/hstore_test.go | 148 ++ vendor/src/github.com/lib/pq/issues_test.go | 26 + .../github.com/lib/pq/listen_example/doc.go | 102 + vendor/src/github.com/lib/pq/notify.go | 782 +++++++ vendor/src/github.com/lib/pq/notify_test.go | 574 +++++ vendor/src/github.com/lib/pq/oid/doc.go | 6 + vendor/src/github.com/lib/pq/oid/gen.go | 74 + vendor/src/github.com/lib/pq/oid/types.go | 161 ++ vendor/src/github.com/lib/pq/ssl.go | 175 ++ vendor/src/github.com/lib/pq/ssl_go1.7.go | 14 + .../src/github.com/lib/pq/ssl_permissions.go | 16 + .../github.com/lib/pq/ssl_renegotiation.go | 8 + vendor/src/github.com/lib/pq/ssl_test.go | 269 +++ vendor/src/github.com/lib/pq/ssl_windows.go | 9 + vendor/src/github.com/lib/pq/url.go | 76 + vendor/src/github.com/lib/pq/url_test.go | 66 + vendor/src/github.com/lib/pq/user_posix.go | 24 + vendor/src/github.com/lib/pq/user_windows.go | 27 + vendor/src/github.com/lib/pq/uuid.go | 23 + vendor/src/github.com/lib/pq/uuid_test.go | 46 + vendor/src/github.com/pierrec/lz4/LICENSE | 28 + vendor/src/github.com/pierrec/lz4/README.md | 31 + vendor/src/github.com/pierrec/lz4/block.go | 474 ++++ .../src/github.com/pierrec/lz4/export_test.go | 13 + ...1572067d493db8dc8161f05c339a5192b0b4087-22 | Bin 0 -> 105 bytes ...02766f768fbfbd81b752cce427eb5242a44929cc-5 | Bin 0 -> 19 bytes ...32f04032e12567057782672bb12670c20d38439-10 | Bin 0 -> 23 bytes ...367b985641aca66e6e4eeea68acf5e2a02c62a8-16 | Bin 0 -> 38 bytes ...03e85abc49352b2f7cc83efd7e4274da02d78b84-6 | Bin 0 -> 13 bytes ...049f82a81bb6b4d7cf69fac5e413f6ce299d48cf-8 | Bin 0 -> 19 bytes ...04c05c7956f17e57a91a47909bd0706135cf17a6-1 | Bin 0 -> 46 bytes ...50e2af2a57d8044139ba21375f0ac6fcb7ab0b1-12 | Bin 0 -> 84 bytes ...0547c73efb9b6a345fd9a52aa0798b48dd9aca62-2 | Bin 0 -> 33 bytes ...5aae2cf8756f66066cf623618042ebaa92ec745-14 | Bin 0 -> 73 bytes ...07fe3e792f0d2862dccc04db22c0e4aef4d41b49-6 | Bin 0 -> 12 bytes ...990ac54decbca1a97893e83c7feb2be89cb10ea-14 | Bin 0 -> 68 bytes ...9f2eda28ecc97304659afded4d13a188baf2107-22 | Bin 0 -> 51 bytes ...a4ff2ab3a01888686c5bc358b72be108bbb4721-16 | Bin 0 -> 20 bytes ...a7fddf3c8aa1c781223748129c9dc0807de3a6b-28 | Bin 0 -> 51 bytes ...0b5bec228930b2cfcda3be9a39107a6bc8044f1e-3 | Bin 0 -> 16 bytes ...ca5fd3841a6777873c7ef26f65a384e7b15d065-18 | Bin 0 -> 61 bytes ...0ce9c3bac93df0ea1f6343d223d5220f9eb2383a-8 | Bin 0 -> 22 bytes ...cf885cd35e7124005b0ba0c3c4431ddfaeff84d-11 | Bin 0 -> 48 bytes ...0d7c02d4e91d82b0355baaca1237062639442db6-3 | 1 + ...0e1b2b0c49dfb86fe01d3453dd24e39482e132e8-7 | Bin 0 -> 21 bytes .../github.com/pierrec/lz4/fuzz/corpus/1.bz2 | Bin 0 -> 42 bytes .../github.com/pierrec/lz4/fuzz/corpus/10.bz2 | Bin 0 -> 14 bytes ...06b9d718c97bb7c872847d3070a570e99d9fa3e-22 | Bin 0 -> 82 bytes ...0fa5d9f0fe75f73c0e92a1fe1c00f0041ec8f39-24 | Bin 0 -> 51 bytes .../github.com/pierrec/lz4/fuzz/corpus/11.bz2 | Bin 0 -> 14 bytes ...113a12cbb28b83fcee714d58c35bbf52c0740e90-7 | Bin 0 -> 21 bytes .../github.com/pierrec/lz4/fuzz/corpus/12.bz2 | Bin 0 -> 14 bytes ...288161f8ce422490f63f257ce7338ef90fb8827-15 | Bin 0 -> 70 bytes .../github.com/pierrec/lz4/fuzz/corpus/13.bz2 | Bin 0 -> 14 bytes ...36f7224ae337a61df2e72b80af8b1aaa5933af3-10 | Bin 0 -> 21 bytes ...3c3c26f7a34d01fc89c92ca8ba2ba5ae430c225-16 | Bin 0 -> 38 bytes ...3db64707d1ea3070b4a37b6c1291d6125acbbd3-10 | Bin 0 -> 22 bytes .../github.com/pierrec/lz4/fuzz/corpus/14.bz2 | Bin 0 -> 14 bytes ...4193748a7b6cda204b11d042a35635151e90dbb-20 | Bin 0 -> 65 bytes ...42d4f8cb427dd3562d72d889dfc0ea3a2b03d98-22 | Bin 0 -> 83 bytes .../github.com/pierrec/lz4/fuzz/corpus/15.bz2 | Bin 0 -> 14 bytes ...5663b854e9a4f193502ea6463dae38b4d8fca90-19 | Bin 0 -> 71 bytes ...15e223354eb5378a7ee74a41dfab28ffc895ca33-1 | Bin 0 -> 55 bytes .../github.com/pierrec/lz4/fuzz/corpus/16.bz2 | Bin 0 -> 14 bytes .../github.com/pierrec/lz4/fuzz/corpus/17.bz2 | Bin 0 -> 14 bytes ...177c1c68fead4507aa47dd2455fd17a10ceda5ea-1 | Bin 0 -> 31 bytes .../github.com/pierrec/lz4/fuzz/corpus/18.bz2 | Bin 0 -> 14 bytes ...80a2772b126d31abcb3ef692a14b13cf47f103e-17 | Bin 0 -> 38 bytes .../github.com/pierrec/lz4/fuzz/corpus/19.bz2 | Bin 0 -> 48 bytes ...91e0dd24b8c7f8babeae4839768df39acc17eb1-17 | Bin 0 -> 32 bytes ...1a582381781f264f551bd6f0f2284a931147e6d9-4 | Bin 0 -> 9 bytes ...c2781a1ffae4059ce3e93a55ec8d8cbf8bdecdf-22 | Bin 0 -> 105 bytes ...1d37fb332301cf7de0bd51a8c1aa9be4935e89fc-1 | 1 + ...1d6b87b52e62cb84be834478ad88129f5e1f247b-9 | Bin 0 -> 32 bytes ...1ec2f11a8d8b9cf188a58f673a0b4a8608a926ca-3 | 1 + ...fc2ba0bb981fec47badea1c80219452c9e3c76c-22 | Bin 0 -> 88 bytes ...1fd8444ac43541c44a1c6ed8df2f688b1fa09681-1 | Bin 0 -> 29 bytes .../github.com/pierrec/lz4/fuzz/corpus/2.bz2 | Bin 0 -> 42 bytes .../github.com/pierrec/lz4/fuzz/corpus/20.bz2 | Bin 0 -> 48 bytes ...02a9c8b188cae90f29bce3bf0438a035c504eb4-20 | Bin 0 -> 62 bytes ...0cf0057443ecb322ff1169ecbe6cf20250f15af-13 | Bin 0 -> 32 bytes ...0d1a26afe563ad77e7a95fbee6ff59ebf3e61ab-13 | Bin 0 -> 46 bytes .../github.com/pierrec/lz4/fuzz/corpus/21.bz2 | Bin 0 -> 48 bytes .../github.com/pierrec/lz4/fuzz/corpus/22.bz2 | Bin 0 -> 48 bytes ...2201e32d052c15874f0323a09c330f3666029a72-1 | Bin 0 -> 1473 bytes ...26780b32ba8f87ec614fdb376aa0884011c4ca9-17 | Bin 0 -> 32 bytes ...2897c61698649d7570de91613afdc19b66e6965-20 | Bin 0 -> 71 bytes .../github.com/pierrec/lz4/fuzz/corpus/23.bz2 | Bin 0 -> 48 bytes ...34cc427d9be32470f3c2e11a6bc16567f558e55-22 | Bin 0 -> 37 bytes .../github.com/pierrec/lz4/fuzz/corpus/24.bz2 | Bin 0 -> 48 bytes ...2486a84bf0f161f45b050d9c19ea9e35f5def864-8 | Bin 0 -> 25 bytes .../github.com/pierrec/lz4/fuzz/corpus/25.bz2 | Bin 0 -> 48 bytes ...5252b16cd4afa8ef86122448688c7095684c86b-12 | Bin 0 -> 25 bytes .../github.com/pierrec/lz4/fuzz/corpus/26.bz2 | Bin 0 -> 48 bytes ...63fb3d738b862ec4050e5a9fbabfbd99cb0d9a5-16 | Bin 0 -> 32 bytes .../github.com/pierrec/lz4/fuzz/corpus/27.bz2 | Bin 0 -> 48 bytes ...76580343a14eec04143e89a778dae3e14df472c-17 | Bin 0 -> 52 bytes ...27fb5dc4016dc640e55a60719a222c38c604fa6b-2 | Bin 0 -> 14 bytes .../github.com/pierrec/lz4/fuzz/corpus/28.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/29.bz2 | Bin 0 -> 157 bytes ...2a08d7c56ff9959698688f19ddd2e1e4d4651270-3 | 1 + ...a33d8514fb512aa20b0a56800cd3e12f3952b6b-26 | Bin 0 -> 51 bytes ...2a52400dd3aa2d2a40657d1e51c47c1929912927-3 | Bin 0 -> 18 bytes ...ab005ac79cd4dada693dd2a747c001898d45e1e-16 | Bin 0 -> 43 bytes ...2b39aa66ecfac58e61185c9664a968233931496a-9 | 1 + ...c2a5947341d76797a7e2299f39d01e3aebb2eb8-19 | Bin 0 -> 70 bytes ...cc2308b75a2e8f7eafcf69370767e5fce314892-13 | Bin 0 -> 32 bytes ...cdafdadb156e2759c389b6b8edf6a402034886c-26 | Bin 0 -> 51 bytes ...2d7f0171116eec9984eaa9138e1312e90a7d67ee-1 | Bin 0 -> 47 bytes ...de93224b5f0db491ced1ec491a9f41d71820671-11 | Bin 0 -> 23 bytes ...2e8487cf61feda70c0d74f12bfb5b692b684f82a-9 | Bin 0 -> 25 bytes ...2f0ee9cf4bb951a37efc6460d5709442bc3de54e-6 | Bin 0 -> 23 bytes ...f1ba7fe1cd90a4023706a2ea9c7c9dca8128119-30 | Bin 0 -> 167 bytes ...fad20024167a500cdb8df5334a614f113efae00-20 | Bin 0 -> 76 bytes .../github.com/pierrec/lz4/fuzz/corpus/3.bz2 | Bin 0 -> 42 bytes .../github.com/pierrec/lz4/fuzz/corpus/30.bz2 | Bin 0 -> 157 bytes ...00579a548d96d64c9da8470efa15e787f1a36f1-28 | Bin 0 -> 51 bytes .../github.com/pierrec/lz4/fuzz/corpus/31.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/32.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/33.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/34.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/35.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/36.bz2 | Bin 0 -> 157 bytes ...363d4559cac10516289fe1b6029590c4c7a6d8eb-5 | Bin 0 -> 12 bytes .../github.com/pierrec/lz4/fuzz/corpus/37.bz2 | Bin 0 -> 58 bytes ...771c6e8ea0f20350dae0180a9b14e36b8aef244-22 | Bin 0 -> 71 bytes ...37ee7fab504f2d2039753d73dd0290c884bd57bf-8 | Bin 0 -> 25 bytes .../github.com/pierrec/lz4/fuzz/corpus/38.bz2 | Bin 0 -> 58 bytes .../github.com/pierrec/lz4/fuzz/corpus/39.bz2 | Bin 0 -> 58 bytes ...96101a712463bb336a18f4096fc3eb5923600c1-10 | Bin 0 -> 74 bytes ...97127b75cb59b253ed49206082b0428b6b23d02-17 | Bin 0 -> 43 bytes ...9ccf446395ef707cf92a04b5508deda399372c2-15 | Bin 0 -> 32 bytes ...3de3c5c394a3cf05620bb80871a1f10e9e36f25b-8 | Bin 0 -> 25 bytes ...3dee65f1cf51dfe2e5be498150ce22d2ac5a07fd-1 | Bin 0 -> 22 bytes ...3e34341fb51769fd9d948bdd20c011e335b145f4-1 | Bin 0 -> 64 bytes ...3ee211efb3d5d8058cd9a8c59e40c8d0f7a3df53-1 | Bin 0 -> 51 bytes .../github.com/pierrec/lz4/fuzz/corpus/4.bz2 | Bin 0 -> 42 bytes .../github.com/pierrec/lz4/fuzz/corpus/40.bz2 | Bin 0 -> 58 bytes ...05726718b3f54a0cfae1666f06d3cc1ee747104-14 | Bin 0 -> 27 bytes ...07188676d45d6f9dd5f3c84e7df0e763c7cca57-22 | Bin 0 -> 82 bytes ...08ac1a4a83e082e848c208eed903930d81e81b6-17 | Bin 0 -> 67 bytes .../github.com/pierrec/lz4/fuzz/corpus/41.bz2 | Bin 0 -> 58 bytes ...413e39442f005279560ddad02bbdd1a05c9f0eaf-4 | 1 + ...41b7eaf8892043eccf381ccbc46ab024eb9c503c-4 | Bin 0 -> 9 bytes .../github.com/pierrec/lz4/fuzz/corpus/42.bz2 | Bin 0 -> 58 bytes ...208b7fe7ac3a530c159a1c8fd09dd3078b5650f-15 | Bin 0 -> 35 bytes ...421bd1daa317c5d67fa21879de29d062c342294b-5 | Bin 0 -> 19 bytes ...2b056f9dac9cc658c80092e490b3dbcd436e3f8-15 | Bin 0 -> 32 bytes .../github.com/pierrec/lz4/fuzz/corpus/43.bz2 | Bin 0 -> 58 bytes ...432c09281c46537c98864bc7d601780562b68410-1 | Bin 0 -> 22 bytes .../github.com/pierrec/lz4/fuzz/corpus/44.bz2 | Bin 0 -> 58 bytes ...46dc91ff0ddc34c3b02f741e3f6f079a4dfcae8-17 | Bin 0 -> 81 bytes .../github.com/pierrec/lz4/fuzz/corpus/45.bz2 | Bin 0 -> 58 bytes ...51831159c1afb87077066147630b4b6caeb54c3-11 | Bin 0 -> 25 bytes .../github.com/pierrec/lz4/fuzz/corpus/46.bz2 | Bin 0 -> 82 bytes .../github.com/pierrec/lz4/fuzz/corpus/47.bz2 | Bin 0 -> 82 bytes .../github.com/pierrec/lz4/fuzz/corpus/48.bz2 | Bin 0 -> 82 bytes .../github.com/pierrec/lz4/fuzz/corpus/49.bz2 | Bin 0 -> 82 bytes ...49861b3d9bca3e2857d806aaecaac09af4bff1dd-2 | Bin 0 -> 35 bytes ...9a3ead0ad96e8da5a4c8f89bd140e1d8af8995a-17 | Bin 0 -> 128 bytes ...a625a4b4f3069707e88f16db88e993dabc41aa2-27 | Bin 0 -> 51 bytes ...a6464c2aba2492f5122856de7ac451994eadda4-10 | Bin 0 -> 20 bytes ...b0ab2fc1fdfc56066c5c1f2751b292f4ddc557e-16 | Bin 0 -> 71 bytes ...4b55f37e6637f4246a41caa490da4bec632379d4-7 | Bin 0 -> 21 bytes ...4bb422b835278e4aca92d076331d9c8cc5752345-1 | Bin 0 -> 47 bytes ...bd00d26b893ce064dad6e771f30541b541d43b9-18 | Bin 0 -> 114 bytes ...cde5adc216a29fff2ec39e23ccc6fca80cd4a15-21 | Bin 0 -> 83 bytes ...d1b64babe1f045b8374f4d74949622591546eb5-17 | Bin 0 -> 56 bytes ...d49686993529cfe29473c50b9b0fb2b6ea4f6bf-13 | Bin 0 -> 25 bytes ...4ea726d6736026a733707e695d9c2cdc83efc05b-5 | Bin 0 -> 32 bytes ...ef3e6d20ccec24376a526ab9ec9f6f2cc604129-25 | Bin 0 -> 147 bytes .../github.com/pierrec/lz4/fuzz/corpus/5.bz2 | Bin 0 -> 42 bytes .../github.com/pierrec/lz4/fuzz/corpus/50.bz2 | Bin 0 -> 82 bytes ...0a87eb0c097a7ebf7f1bf3be2c6a7dbe6b6c5c3-23 | Bin 0 -> 105 bytes ...0e3ac1126c605158726db6f2cca3120f99b8e73-22 | Bin 0 -> 105 bytes .../github.com/pierrec/lz4/fuzz/corpus/51.bz2 | Bin 0 -> 82 bytes ...12ed5fb4e92818b75bd7633f58d6ca5340ffd94-27 | Bin 0 -> 195 bytes ...514a62216c761adf23d946f11c0d1a0410990641-3 | Bin 0 -> 15 bytes ...16d84c21ac984bd1cae56910d71b62e39610c5d-29 | Bin 0 -> 51 bytes .../github.com/pierrec/lz4/fuzz/corpus/52.bz2 | Bin 0 -> 82 bytes .../github.com/pierrec/lz4/fuzz/corpus/53.bz2 | Bin 0 -> 82 bytes .../github.com/pierrec/lz4/fuzz/corpus/54.bz2 | Bin 0 -> 82 bytes ...5431cabbc58d8dc143ece079de40300c1ce6e101-1 | Bin 0 -> 144 bytes ...5700385089e16e44968ea410c6b90206b16d72a-14 | Bin 0 -> 20 bytes ...55b9a902445e2bfa2f0f37d630779d329eeda20e-1 | Bin 0 -> 33 bytes ...620a492eaf067734e5b8b64517b28ec3beaa97e-12 | Bin 0 -> 46 bytes ...5699fea659964d8ab94069d08b0b97834c0a42df-2 | 1 + ...765fc21629571e51adf2fc2bc8b64541a1ea08d-18 | Bin 0 -> 81 bytes ...768ea5d1911143f4b1c0585b9b864ebe16aa004-12 | Bin 0 -> 33 bytes ...7b780437f4abf2d5cba0775bf802a4dfdb067d6-25 | Bin 0 -> 195 bytes ...8f53d40265c9a49c0d3b4292cb637464a4e376a-17 | Bin 0 -> 35 bytes ...59b254c3565c9eed2bc93385b821da897afcbb15-1 | Bin 0 -> 44 bytes ...a962e3d6a128983afe9ea78a28cce0f40a790c0-14 | Bin 0 -> 42 bytes ...af52ef91b6f717ffdd805585e24806407e9621b-14 | Bin 0 -> 114 bytes ...5b01aeb030dc1dc9568fd32f1647d92f0692a411-6 | 1 + ...bbd27cea704a4e6ff3f42f4792a91eb7839bc0d-12 | Bin 0 -> 28 bytes ...5bd895c23369df9505dd99ffcd035dc5e897264b-1 | Bin 0 -> 49 bytes ...5bfd84d7b2ba6b6325d5135fb0a9ae1ec5d7d3e1-2 | Bin 0 -> 48 bytes ...5c4f347c3567baf700dfccf49a91192c83b89da2-8 | 1 + ...5dd8001f8a87c24f866074c36b6b80f42b298ff0-1 | Bin 0 -> 38 bytes ...ddf63d61aa38da1d409e37b301e0fe5a207a051-27 | Bin 0 -> 156 bytes ...e54c67050ee8583c7453ff13d6eec15b2255288-20 | Bin 0 -> 83 bytes ...5fbebd9edd144c4b9869ed4ab40c7cc3c46a4a8f-4 | 1 + .../github.com/pierrec/lz4/fuzz/corpus/6.bz2 | Bin 0 -> 42 bytes ...046b14dd1f6925bcfe470a8484353f525db6a9c-19 | Bin 0 -> 57 bytes ...608a9993a51ec7bf252ac76b163def5f7002d2e4-4 | 1 + ...610d8dc3cf4012e4e2d070988b0720285a4c361e-7 | Bin 0 -> 21 bytes ...1b196987682fb64ef9c4ff37532bf9b2ac201bc-14 | Bin 0 -> 30 bytes ...26f8b6efa3ea0f254789fe6cf52f6e52538f357-25 | Bin 0 -> 219 bytes ...6277f2e0a6df2ac61660ee1965c690b87c26b556-7 | Bin 0 -> 21 bytes ...2c738f00c488f493989b2037d9cf1781f0bbd40-11 | Bin 0 -> 38 bytes ...631ffa88df9713a124b3ba6c704c0c75727af2ff-6 | Bin 0 -> 16 bytes ...35d5de257a1910a7fd0db2e567edfa348e47270-11 | Bin 0 -> 38 bytes ...64c500b5addcbf8c673188a1477e4159851ae04f-1 | Bin 0 -> 124 bytes ...60387064a3cf4cb81046989929abe1b4fbfc815-17 | Bin 0 -> 51 bytes ...66068a7e7bdfd1038a84aeb3dec6e3cb4d17ad57-2 | Bin 0 -> 16 bytes ...7ab3037ff49f082a877224d68e35069cc4d45eb-16 | Bin 0 -> 32 bytes ...69dcc80940a26844b0afe7898fea9cf68b698214-4 | Bin 0 -> 12 bytes ...a04b54e1511633ec895326b4e043e186fa5693b-29 | Bin 0 -> 171 bytes ...6a3e8935204dcd3dc48a1ff7415c305f0e5863aa-9 | Bin 0 -> 28 bytes ...b351674a45f2d9be602fe8d3fb84229551b4ce3-16 | Bin 0 -> 69 bytes ...b7f4ac7aa8b357dee3067d7a60143c03b54bb8d-16 | Bin 0 -> 42 bytes ...6bc138796e9b80572a6cb1b4a7ba30c97c22359d-1 | Bin 0 -> 46636 bytes ...6e14a407faae939957b80e641a836735bbdcad5a-2 | 1 + ...6f24be0bcac848e4e5b4b85bc60f70f12388a5ed-4 | 1 + .../github.com/pierrec/lz4/fuzz/corpus/7.bz2 | Bin 0 -> 42 bytes ...102c7f297296821114661e00e5bf54d0891d105-21 | Bin 0 -> 76 bytes ...151692dfebfc82876676e65ee9b807d83a3df54-22 | Bin 0 -> 92 bytes ...1a24ce771fb7f1a4163e57a478c3044ad42e62d-24 | Bin 0 -> 51 bytes ...2f032947602f1be74f01c91165c5118121f36c7-24 | Bin 0 -> 51 bytes ...3b6bd1462a0521b4bf76abb1fd80df6e180dc80-17 | Bin 0 -> 62 bytes ...3c81fef0997a4929b303e02a99f3977870f2013-29 | Bin 0 -> 159 bytes ...3efed803abadf6167fc3f04e0674cc39c30f6af-21 | Bin 0 -> 37 bytes ...603f5f266de813608c4cc1ccd1c798ef8065c5c-23 | Bin 0 -> 51 bytes ...67d1943125a0f6e9397779cc757c9cdd1e05631-17 | Bin 0 -> 62 bytes ...6d22068e2ed4a5952d4adc7ea8dada5509a784c-13 | Bin 0 -> 30 bytes ...740102922cb9933980bb800c1115daf38edf654-24 | Bin 0 -> 72 bytes ...83270b1e353ba3895b7d0c4135b8592e22f6508-12 | Bin 0 -> 56 bytes ...7851a406571c6b4c1aeed0af16db8c48444c3f2b-1 | Bin 0 -> 34 bytes ...78981d313038119ac4f7017349e50a1cba56b382-7 | Bin 0 -> 23 bytes ...8c88c4afaf5962056b1aea720509b9f6f286b91-15 | Bin 0 -> 64 bytes ...9c5ac978f5aee35e123f523369aa46b1d0a995d-11 | Bin 0 -> 26 bytes ...adf4aa021efaa953268c817467959fa3c42ca42-13 | Bin 0 -> 25 bytes ...7b8c99ded96973a6e8f523bc1c6ed4ef5c515aa1-1 | 1 + ...7ba80199cbce9a2eb47da15f0c62fd1fb8fa67d9-3 | 1 + ...cdc0917ad63ce7a7c98301a366c31635f0f099d-14 | Bin 0 -> 32 bytes ...7ce37ad19bfe9f52eeadda03e6b8448e5bf57800-3 | Bin 0 -> 1452 bytes ...7e3132012be223fd55e5e7a7fc2ea602361ed2b4-5 | Bin 0 -> 8 bytes ...e9a88118e4c41e61f5c501e6edf9a5bd2432be3-23 | Bin 0 -> 135 bytes ...7f081c89cfb6344f4aac5f813da1fd15f8bab022-1 | Bin 0 -> 26 bytes ...f970f16026c689c096a19fef1a3282a13ee69dc-20 | Bin 0 -> 65 bytes ...7fa96d28faf45062eb803ea84a334b607e966f90-1 | Bin 0 -> 31 bytes .../github.com/pierrec/lz4/fuzz/corpus/8.bz2 | Bin 0 -> 42 bytes ...261f0c1799ca71c411f6d3f34069b25dac8b739-18 | Bin 0 -> 52 bytes ...82afa534de59025bf1e3358919286525ae7d3347-2 | 1 + ...496965f7aa6cea3e080dbfb911a7034e6623cb7-10 | Bin 0 -> 23 bytes ...84a9bda8369d33ffe0d6f520c24331ae64e9dc88-3 | Bin 0 -> 10 bytes ...86513e3435adaf7c493dd50eb5de372010185e36-1 | 1 + ...6637b211f4fa0118ccab9ee193c66286126bb5d-20 | Bin 0 -> 35 bytes ...695984335fa005895377a8a60000a921d7efd99-10 | Bin 0 -> 25 bytes ...6baa53eb98a9a342b0d5b79dfa5c58aa9c1b05e-16 | Bin 0 -> 35 bytes ...8e6e46ab1ec92ce694b8d4c3d816491169d2bb6-10 | Bin 0 -> 25 bytes ...9216c662a46d50f37cfa08963acad8c6f7aace7-11 | Bin 0 -> 20 bytes ...8e533f8a1e58710d99d6b7d39af7034961aa4fbe-5 | 1 + ...f0d2862c49eebbcd473a38c8fa1e76288f47127-26 | Bin 0 -> 51 bytes ...f61ea021e02cc609baafbdf714b9577e4bcb05f-16 | Bin 0 -> 74 bytes ...8f7a47710904981ffaa1fefa21fa95fd2d818487-7 | Bin 0 -> 23 bytes .../github.com/pierrec/lz4/fuzz/corpus/9.bz2 | Bin 0 -> 42 bytes ...0a227d3beab730ed6eecd63657f5406beccabdf-12 | Bin 0 -> 39 bytes ...2197169aded0d5d0407e3925959e922257a101d-28 | Bin 0 -> 195 bytes ...24e17974cd194fa756d23394676d37cc3641f64-17 | Bin 0 -> 25 bytes ...92a785b5ea93d36e27029e281e9a34377d81ce55-5 | 1 + ...92fda3aa2adbe37ff690c59939ca1e1b2a8a7936-1 | Bin 0 -> 40 bytes ...363b81db6b35e8beebcc32d560f786472829bd8-21 | Bin 0 -> 88 bytes ...48b1ce043c82d0cfbaa910b6989a1b35a19b8ae-16 | Bin 0 -> 32 bytes ...505b43fcbc3139441e35bdaaec138e28af076f6-25 | Bin 0 -> 91 bytes ...51bb02c199adb52e9e300e9fc070bf55980b910-14 | Bin 0 -> 25 bytes ...55404fe3f375361f5c3be1dbcd28eb9a28f06e4-13 | Bin 0 -> 23 bytes ...67e50c6c1bc99aa5e7fa07c2de14564f52b0fd3-20 | Bin 0 -> 28 bytes ...6c9a1fa8b0184ad486f8f68a9ddc88434579080-30 | Bin 0 -> 159 bytes ...6cc45abef3bc9fb6659714b9743cda92ec0abb9-16 | Bin 0 -> 38 bytes ...719ea029fdf8c837f991ac3548145485cc1f06e-13 | Bin 0 -> 73 bytes ...84480af27d1640fd02f40e736ffcde3a91e4abb-22 | Bin 0 -> 88 bytes ...8d40a50ee58c05727777e242ecbc0d4e214f7fe-21 | Bin 0 -> 35 bytes ...915e9bb007bc2c1f3d346123933923279f0dec1-27 | Bin 0 -> 51 bytes ...992413e17d64968cb04af34c7761182f20fc97b6-2 | Bin 0 -> 30 bytes ...9cfa74a1fea5d16168dd9efc720425b85e95eb7-15 | Bin 0 -> 32 bytes ...a552bab72f174ede3b9bdb7a663c963fd1463d3-16 | Bin 0 -> 32 bytes ...9aa3050cb38a6ad276cb5e5ca0c4776d92cb7b0f-1 | 1 + ...9be44693435bc6c51980f30418bcc690d8c25fe7-6 | 1 + ...c0420bf00f888487d543f42fc48b407c65d4717-17 | Bin 0 -> 95 bytes ...ca2a086f1f08c7dec54d52425bd72f17c11056e-21 | Bin 0 -> 37 bytes ...db70b1edad2317d94dcaafe7f5c5e3145084167-12 | Bin 0 -> 37 bytes .../fuzz/corpus/Mark.Twain-Tom.Sawyer.txt.bz2 | Bin 0 -> 124744 bytes ...01e13c3e401957031defb62b05434c65b01d5c4-10 | Bin 0 -> 31 bytes ...059044bdb0402471dbe9aaaa555a063a6bc1e6a-16 | Bin 0 -> 38 bytes ...06b1a08fcda463f1d51c485b0e7271ff9048b41-16 | Bin 0 -> 35 bytes ...0f3d67e96968a267366be380147cbc7b17e5b2b-16 | Bin 0 -> 68 bytes ...18d849dc2a98c4ebb6000b2cc853f21fb64d9e5-24 | Bin 0 -> 195 bytes ...2e5916be780e35e9ecb7c42be52dd5e134f3363-25 | Bin 0 -> 195 bytes ...33252a74974fc86df30c311d501a1f363d350cd-12 | Bin 0 -> 33 bytes ...462f03ee666a20244d3331e3635b7eb796d906d-15 | Bin 0 -> 60 bytes ...a56e983782e49f8267a61d4375e98b1a862862ac-9 | Bin 0 -> 17 bytes ...58a9f9caca5e73b4296b931201a5ea870974c26-15 | Bin 0 -> 116 bytes ...a628194a08ff63e98625b1786175026c5f02c716-5 | Bin 0 -> 38 bytes ...64f2336fd4a9ec8153b95f40c383e1ecfed9e73-25 | Bin 0 -> 51 bytes ...a6a5682a6663e0c548c9e5acbad4958e2c256b32-7 | Bin 0 -> 60 bytes ...6dbaac639f3b82609ec27c80fbd003684c28867-21 | Bin 0 -> 61 bytes ...8c6a4509b61d8baa71f59f9e1eb95712b10626c-23 | Bin 0 -> 51 bytes ...9e348d9896cc740f7e910d0a70c080adb65cc77-13 | Bin 0 -> 34 bytes ...a04575587509ffc65a6b0224d24ad1125cb0f63-26 | Bin 0 -> 91 bytes ...a290b4dcc8198945311c8149fc1252f14555e70-15 | Bin 0 -> 63 bytes ...abb8fa4913c79f0a42494ad2215a32927adbd45-16 | Bin 0 -> 63 bytes ...c7077c5220abe6cd481318c42dfe6cb2cb2c666-10 | Bin 0 -> 40 bytes ...cbef0322169a93c7421902883cc8057675c953b-26 | Bin 0 -> 195 bytes ...ec95871bc7d87cae16c36a0d30955b43076aec5-17 | Bin 0 -> 35 bytes ...20e3f27f4e8d41f16124881f92546f0fb2edc16-13 | Bin 0 -> 33 bytes ...27fb21ecbe6e77c91341738621ad7092c29bca5-17 | Bin 0 -> 89 bytes ...38ce47b707326024fb24860c4365d58ab9f3528-29 | Bin 0 -> 166 bytes ...b3eaea244bd47b64c8de3d81c7b5e94e421d7f32-5 | Bin 0 -> 9 bytes ...3fd355dc090a732d5cf3b25151f165ea901a682-24 | Bin 0 -> 51 bytes ...58846d79a8dc960a718ef88dd3a06ad49b1fe72-16 | Bin 0 -> 35 bytes ...b5b5b895b4619fa039ea99520b9947de2996c38f-6 | Bin 0 -> 16 bytes ...b6aca5c55295d93491e47817f46ca372c9078cec-3 | 1 + ...b6ddb90092b3087158dc32669529db2012f14c3c-7 | Bin 0 -> 20 bytes ...b6e7a519d013ddb67313af02a9ce966877949487-4 | Bin 0 -> 24 bytes ...b71a5a7c576e5cc5ba23845d352b2af16737c03c-7 | Bin 0 -> 17 bytes ...7815c3b5649d9a367ba99e7e09cf1f251ab6f83-18 | Bin 0 -> 44 bytes ...7a5b15c9e2d4d659d421de8e3b463200f71f1ec-23 | Bin 0 -> 143 bytes ...83b3d04ada1403578065d7f10aa7441830dea3c-11 | Bin 0 -> 20 bytes ...94b7ebc6d153e0c99a97864f58b26f7192f66a5-20 | Bin 0 -> 35 bytes ...ba98469ede70309f18893f0ff95380f5a0486fcd-6 | Bin 0 -> 52 bytes ...c0c31f304c1a1f8be0c8a0d9daa3b8aa1f23799-14 | Bin 0 -> 41 bytes ...c650b6a5356c1935f64f6fb755e43bc5f5187c4-26 | Bin 0 -> 195 bytes ...be06bb3c3b604660fd36b2af8860d35e31c8bbf3-8 | Bin 0 -> 66 bytes ...e5767f4d79c5a0b2643d8eddb74eca0598674dc-19 | Bin 0 -> 75 bytes ...07f4e4cb1d0a34dc6899097fd27ee9f1744cb70-12 | Bin 0 -> 19 bytes ...2ac55a7fb702dd9a527b576d99008fe9b4f376f-14 | Bin 0 -> 36 bytes ...2c3d29bce8aae89fed326832b3e1e1077cef1da-18 | Bin 0 -> 61 bytes ...c321670bbcd985327045dd1468bf2ac4ae7333e5-7 | Bin 0 -> 32 bytes ...34998d9a8893eca9cdeafe7b2482469ad98192b-25 | Bin 0 -> 51 bytes ...5522d11f314fc46de58e15116b6910d52acf866-17 | Bin 0 -> 69 bytes ...c652c46aba3567521f912bae6dc263b668c34c9c-7 | Bin 0 -> 17 bytes ...c6610b87900912d462229a5259dab51ea0aeef33-4 | 1 + ...c6c37f6c89fe55768f8b3f7b28b99467c239703a-1 | Bin 0 -> 39 bytes ...c71abfffdcf530a6d28fd99cd2c3505c61ef0ac5-8 | Bin 0 -> 26 bytes ...77304b250e887b39b5447d19b9c106fcebe7e66-20 | Bin 0 -> 71 bytes ...78cd8530e6d8a606a28797552ce3f5494763621-25 | Bin 0 -> 195 bytes ...790308a65efa1b895bc57abe53e4fbcdb2b7d0e-13 | Bin 0 -> 88 bytes ...c7fe1fe2e3fc19fab3766f9fdb1d22c848d49aed-2 | Bin 0 -> 53 bytes ...a5d375d8a66727221d3e198d4ad360782944de7-27 | Bin 0 -> 195 bytes ...cb635ef244cb6affc005c63d0bf8b52aecb1d986-4 | 1 + ...d67bf90feaeb1912792508afa01a09fe1f044c6-13 | Bin 0 -> 33 bytes ...cda434677d4bdd969a3bbf84086349f821e39c80-1 | Bin 0 -> 48 bytes ...fe7201e28d42484764264c231663e6372e95ef7-14 | Bin 0 -> 32 bytes ...ff88dd94ee94e1901d25a74e29ad863bb78b1e4-16 | Bin 0 -> 32 bytes ...cffc7573debb5af80aaddfa752538825275fd6a9-7 | 1 + ...0ae058f71e53a7afd648b859cd7485886be550d-22 | Bin 0 -> 127 bytes ...0e6298a63ffc2695cf7d016a124db7375f197cf-21 | Bin 0 -> 88 bytes ...24f23a23508dd6bc93ea6283ed49c8ba4b737ed-15 | Bin 0 -> 49 bytes ...d295ca4c78f7fd3ff10b0520b09a0a346310e0a9-1 | Bin 0 -> 58 bytes ...3ddffcd038a5646a53d48b684eac5b721c7062a-18 | Bin 0 -> 59 bytes ...4275f1f814a5b24f7b4788d15f3fef7b2be8aef-23 | Bin 0 -> 72 bytes ...d57eaf0fada8726afac2287cafb7720af7417b16-1 | 1 + ...d5c9dc3b5b4e71d902fe4cf5c44b237b104a32a9-4 | Bin 0 -> 30 bytes ...d7855c38db11bfeeb474a4782f1ea293192f786f-1 | Bin 0 -> 42 bytes ...7912c5e2a776c408e7640f10bd7d655a6a0f31b-27 | Bin 0 -> 51 bytes .../da39a3ee5e6b4b0d3255bfef95601890afd80709 | 0 ...da39a3ee5e6b4b0d3255bfef95601890afd80709-1 | 0 ...dba53c14b92561071ccd7762550d53cf43027bdf-1 | Bin 0 -> 32 bytes ...c61bdd2fb983111d1392cd79ba9b39e0a3b869f-20 | Bin 0 -> 71 bytes ...dcb49d3d45d32601fa27208cec33813e03ff6179-1 | Bin 0 -> 47 bytes ...dce9966b94744440d75a845a48c806041f5a6612-3 | Bin 0 -> 31 bytes ...d799919262810add464dbb4ee39a38f1e4ed258-13 | Bin 0 -> 25 bytes .../dd92516fbea2d0f96abc78f325d731053a451e16 | 1 + ...df986569f89016184b5b6e924d5ba827c9980ca-28 | Bin 0 -> 156 bytes ...e0acf1136a1e05cd27345ce135ea26abd32bbfe-18 | Bin 0 -> 36 bytes ...e33e3ef8a5780c7d3458188a423c00f470904d0-15 | Bin 0 -> 32 bytes ...de501127da94246b2d3aa947637b49fbc17d5e47-1 | 1 + ...e702cd20caeb08a843e0c09b0ce87a74e300415-20 | Bin 0 -> 71 bytes ...e8abda1b9bd5628ca99c8f97237fa885a857bb5-19 | Bin 0 -> 35 bytes ...def6a9e986daf0b268ef29ef7e821a9f6840ef2c-8 | Bin 0 -> 20 bytes ...f0768cf0c709a1ff1a93cc0dad23979501c54ff-21 | Bin 0 -> 115 bytes ...dfad565009b0667ef2ee10ea9c1286ee5c3ce6b2-1 | 1 + .../pierrec/lz4/fuzz/corpus/e.txt.bz2 | Bin 0 -> 43149 bytes ...1556049ba9794a15ee21aa283876bf63e531a4f-24 | Bin 0 -> 147 bytes ...e17af76e8c119233dbd2888ab519bd76d7aa7fe9-6 | Bin 0 -> 19 bytes ...346c715ac3187598d8c0453d9e741fae1232c99-11 | Bin 0 -> 29 bytes ...3acf6f2b5a1b97f5a82ebf7d1822077561583fe-26 | Bin 0 -> 195 bytes ...e4a2a1469de980756c607cdc2584fc94bc109382-1 | Bin 0 -> 58 bytes ...68b04a675d8d4192565a808955764c77ae510e6-16 | Bin 0 -> 122 bytes ...7ea1bfd65ca7db84f0984474658bfc3b063c63a-13 | Bin 0 -> 32 bytes ...ea212596f8a7aec4eb2e85fd2cdb5c2816b58495-5 | Bin 0 -> 12 bytes ...a9af92f89e6889b523461ae7b2b9fecee5a7280-18 | Bin 0 -> 130 bytes ...bc69b7ca13ae23b075c9b21ebc283278714e3aa-18 | Bin 0 -> 32 bytes ...c8e760e79dc08a79af0d79c510cafb74e504472-18 | Bin 0 -> 28 bytes ...c984b6fb8e41dbcd4299ecd1dd6fd0a77347122-13 | Bin 0 -> 32 bytes ...cbd6bdea50b52d263b4e9cdb96c7ce078d2b780-25 | Bin 0 -> 147 bytes ...cdd1df7d975c8cf8d015b2f1d0d7c6e00eb578b-15 | Bin 0 -> 33 bytes ...da1ee9cf85f3f71ec8a4eec7534ed2677b47775-15 | Bin 0 -> 32 bytes ...dbc11de7dd074c367a69532db023cd810bb3978-13 | Bin 0 -> 43 bytes ...ee6afbf375619a2bd6fb0abe0e42e51ab3b0ab13-6 | Bin 0 -> 20 bytes ...ee907d38c1394c4971b389a99a3be0913836212b-9 | Bin 0 -> 72 bytes ...ebbefa1983c9e1aeb5217aabcac7ab24dfe166f-17 | Bin 0 -> 75 bytes ...ee3d4a9a8b297f016c23f50a9792c30a621720e-21 | Bin 0 -> 71 bytes ...ef87432939473264357babc06257b0280ffd15ee-5 | 1 + ...fdd522fe3abb88204f63b1fe7312f62b6ee593d-16 | Bin 0 -> 67 bytes ...35bdf2e8b4af93c6a73e564055aa4eacd9f0d0c-13 | Bin 0 -> 25 bytes ...f3a2381d6f39defe22520aea46201e6ce6d37f80-1 | Bin 0 -> 31 bytes ...f3e916907eab3412b5875e5eca05bf3eac8a8d5e-1 | Bin 0 -> 37 bytes ...f493376c3eda80cbe822ac456486734b72f891fc-2 | Bin 0 -> 44 bytes ...55efbb04cd32f7828e951d067319db00627153f-28 | Bin 0 -> 51 bytes ...71b4776ecbbe47746fb53d7749751c5c5bbff05-22 | Bin 0 -> 61 bytes ...724d4c839c012c7772618e28ef68d478cc00c74-21 | Bin 0 -> 37 bytes ...f86152e5ce510dc674fa73d20b324e2d3c4d145b-1 | 1 + ...f931bee2e7f1fefd8bb2fabf88f8f3d2b3ea78fa-2 | Bin 0 -> 36 bytes ...ac6c4165067ef2d87a23a2530a59eb560d470e0-23 | Bin 0 -> 51 bytes ...fb56a1001599e07354ce3101af111554c6c9bb40-1 | Bin 0 -> 60 bytes ...fb75f3059f8835a7e8781c899af756f22d1c06b4-7 | Bin 0 -> 13 bytes ...bfe35b0485040874ed564b94ba764bdd17e80fc-10 | Bin 0 -> 20 bytes ...cb1c8b1893ca85647581cadec481754d8f35c96-12 | Bin 0 -> 25 bytes ...cb33fb48e48acd9155fd7ed8e82e71c850ffd22-16 | Bin 0 -> 32 bytes ...fcd47a15e10a21e1eb13aeac223becc89aac4c69-2 | Bin 0 -> 38 bytes ...d4f0dc77a022a8140ffe5b2e1a5ff577e844878-27 | Bin 0 -> 51 bytes ...db78af507e72288b059ff902ae5e76538d1e6ea-14 | Bin 0 -> 32 bytes ...fe002e4c7731ecb4c09c09a4e1fa29c0c61874bc-7 | Bin 0 -> 15 bytes ...e78d4faf4ce717d84938010f92ca5e844f9980b-13 | Bin 0 -> 24 bytes ...f3b7ea844eb197dc6bd59d9f8e4a4a5718a6771-18 | Bin 0 -> 36 bytes ...f47856b8fa7323572c8b4a6d8028dcb2663a37a-11 | Bin 0 -> 84 bytes ...fa97253e1ab365b84eebb9d257f9370b7796fbf-28 | Bin 0 -> 51 bytes .../pierrec/lz4/fuzz/corpus/pss-vect.txt.bz2 | Bin 0 -> 28526 bytes .../0b8f7fcd1f53d5bd839e5728ba92db050f5e0968 | Bin 0 -> 27 bytes ...fcd1f53d5bd839e5728ba92db050f5e0968.output | 51 + ...fcd1f53d5bd839e5728ba92db050f5e0968.quoted | 2 + .../169b44c5a64fec4d8e969d25d3e4764c9c3b604b | Bin 0 -> 66 bytes ...4c5a64fec4d8e969d25d3e4764c9c3b604b.output | 54 + ...4c5a64fec4d8e969d25d3e4764c9c3b604b.quoted | 4 + .../ea0a00651ba4143c05fe7b5c85f69fe16a29a458 | Bin 0 -> 19 bytes ...0651ba4143c05fe7b5c85f69fe16a29a458.output | 23 + ...0651ba4143c05fe7b5c85f69fe16a29a458.quoted | 1 + .../github.com/pierrec/lz4/fuzz/lz4-fuzz.zip | Bin 0 -> 2361685 bytes vendor/src/github.com/pierrec/lz4/fuzz/lz4.go | 45 + .../a596442269a13f32d85889a173f2d36187a768c6 | 1 + .../d159e91cdd6fcbee9e37460f96c597b70c590886 | 10 + vendor/src/github.com/pierrec/lz4/lz4.go | 118 + vendor/src/github.com/pierrec/lz4/lz4_test.go | 646 ++++++ .../src/github.com/pierrec/lz4/lz4c/main.go | 108 + vendor/src/github.com/pierrec/lz4/reader.go | 364 +++ vendor/src/github.com/pierrec/lz4/writer.go | 383 ++++ .../pierrec/xxHash/xxHash32/example_test.go | 21 + .../pierrec/xxHash/xxHash32/xxHash32.go | 205 ++ .../pierrec/xxHash/xxHash32/xxHash32_test.go | 150 ++ .../github.com/rcrowley/go-metrics/LICENSE | 29 + .../github.com/rcrowley/go-metrics/README.md | 153 ++ .../cmd/metrics-bench/metrics-bench.go | 20 + .../cmd/metrics-example/metrics-example.go | 154 ++ .../go-metrics/cmd/never-read/never-read.go | 22 + .../github.com/rcrowley/go-metrics/counter.go | 112 + .../rcrowley/go-metrics/counter_test.go | 77 + .../github.com/rcrowley/go-metrics/debug.go | 76 + .../rcrowley/go-metrics/debug_test.go | 48 + .../github.com/rcrowley/go-metrics/ewma.go | 118 + .../rcrowley/go-metrics/ewma_test.go | 225 ++ .../github.com/rcrowley/go-metrics/exp/exp.go | 156 ++ .../github.com/rcrowley/go-metrics/gauge.go | 120 + .../rcrowley/go-metrics/gauge_float64.go | 127 ++ .../rcrowley/go-metrics/gauge_float64_test.go | 59 + .../rcrowley/go-metrics/gauge_test.go | 68 + .../rcrowley/go-metrics/graphite.go | 113 + .../rcrowley/go-metrics/graphite_test.go | 22 + .../rcrowley/go-metrics/healthcheck.go | 61 + .../rcrowley/go-metrics/histogram.go | 202 ++ .../rcrowley/go-metrics/histogram_test.go | 95 + .../github.com/rcrowley/go-metrics/json.go | 87 + .../rcrowley/go-metrics/json_test.go | 28 + .../rcrowley/go-metrics/librato/client.go | 102 + .../rcrowley/go-metrics/librato/librato.go | 235 ++ .../src/github.com/rcrowley/go-metrics/log.go | 80 + .../github.com/rcrowley/go-metrics/memory.md | 285 +++ .../github.com/rcrowley/go-metrics/meter.go | 233 ++ .../rcrowley/go-metrics/meter_test.go | 60 + .../github.com/rcrowley/go-metrics/metrics.go | 13 + .../rcrowley/go-metrics/metrics_test.go | 124 ++ .../rcrowley/go-metrics/opentsdb.go | 119 + .../rcrowley/go-metrics/opentsdb_test.go | 21 + .../rcrowley/go-metrics/registry.go | 270 +++ .../rcrowley/go-metrics/registry_test.go | 288 +++ .../github.com/rcrowley/go-metrics/runtime.go | 212 ++ .../rcrowley/go-metrics/runtime_cgo.go | 10 + .../go-metrics/runtime_gccpufraction.go | 9 + .../rcrowley/go-metrics/runtime_no_cgo.go | 7 + .../go-metrics/runtime_no_gccpufraction.go | 9 + .../rcrowley/go-metrics/runtime_test.go | 88 + .../github.com/rcrowley/go-metrics/sample.go | 616 ++++++ .../rcrowley/go-metrics/sample_test.go | 363 +++ .../rcrowley/go-metrics/stathat/stathat.go | 69 + .../github.com/rcrowley/go-metrics/syslog.go | 78 + .../github.com/rcrowley/go-metrics/timer.go | 311 +++ .../rcrowley/go-metrics/timer_test.go | 89 + .../rcrowley/go-metrics/validate.sh | 10 + .../github.com/rcrowley/go-metrics/writer.go | 100 + .../rcrowley/go-metrics/writer_test.go | 22 + .../gopkg.in/Shopify/sarama.v1/CHANGELOG.md | 350 +++ .../gopkg.in/Shopify/sarama.v1/MIT-LICENSE | 20 + .../src/gopkg.in/Shopify/sarama.v1/Makefile | 21 + .../src/gopkg.in/Shopify/sarama.v1/README.md | 36 + .../gopkg.in/Shopify/sarama.v1/Vagrantfile | 20 + .../Shopify/sarama.v1/api_versions_request.go | 24 + .../sarama.v1/api_versions_request_test.go | 14 + .../sarama.v1/api_versions_response.go | 86 + .../sarama.v1/api_versions_response_test.go | 32 + .../Shopify/sarama.v1/async_producer.go | 905 ++++++++ .../Shopify/sarama.v1/async_producer_test.go | 841 +++++++ .../src/gopkg.in/Shopify/sarama.v1/broker.go | 674 ++++++ .../gopkg.in/Shopify/sarama.v1/broker_test.go | 315 +++ .../src/gopkg.in/Shopify/sarama.v1/client.go | 736 ++++++ .../gopkg.in/Shopify/sarama.v1/client_test.go | 608 +++++ .../src/gopkg.in/Shopify/sarama.v1/config.go | 417 ++++ .../gopkg.in/Shopify/sarama.v1/config_test.go | 70 + .../gopkg.in/Shopify/sarama.v1/consumer.go | 735 ++++++ .../sarama.v1/consumer_group_members.go | 94 + .../sarama.v1/consumer_group_members_test.go | 73 + .../sarama.v1/consumer_metadata_request.go | 26 + .../consumer_metadata_request_test.go | 19 + .../sarama.v1/consumer_metadata_response.go | 85 + .../consumer_metadata_response_test.go | 35 + .../Shopify/sarama.v1/consumer_test.go | 854 +++++++ .../gopkg.in/Shopify/sarama.v1/crc32_field.go | 36 + .../sarama.v1/describe_groups_request.go | 30 + .../sarama.v1/describe_groups_request_test.go | 34 + .../sarama.v1/describe_groups_response.go | 186 ++ .../describe_groups_response_test.go | 91 + vendor/src/gopkg.in/Shopify/sarama.v1/dev.yml | 13 + .../Shopify/sarama.v1/encoder_decoder.go | 89 + .../src/gopkg.in/Shopify/sarama.v1/errors.go | 197 ++ .../Shopify/sarama.v1/examples/README.md | 9 + .../sarama.v1/examples/http_server/README.md | 7 + .../examples/http_server/http_server.go | 247 +++ .../examples/http_server/http_server_test.go | 109 + .../Shopify/sarama.v1/fetch_request.go | 136 ++ .../Shopify/sarama.v1/fetch_request_test.go | 34 + .../Shopify/sarama.v1/fetch_response.go | 210 ++ .../Shopify/sarama.v1/fetch_response_test.go | 84 + .../sarama.v1/functional_client_test.go | 90 + .../sarama.v1/functional_consumer_test.go | 61 + .../functional_offset_manager_test.go | 47 + .../sarama.v1/functional_producer_test.go | 323 +++ .../Shopify/sarama.v1/functional_test.go | 148 ++ .../Shopify/sarama.v1/heartbeat_request.go | 47 + .../sarama.v1/heartbeat_request_test.go | 21 + .../Shopify/sarama.v1/heartbeat_response.go | 32 + .../sarama.v1/heartbeat_response_test.go | 18 + .../Shopify/sarama.v1/join_group_request.go | 108 + .../sarama.v1/join_group_request_test.go | 41 + .../Shopify/sarama.v1/join_group_response.go | 114 + .../sarama.v1/join_group_response_test.go | 98 + .../Shopify/sarama.v1/leave_group_request.go | 40 + .../sarama.v1/leave_group_request_test.go | 19 + .../Shopify/sarama.v1/leave_group_response.go | 32 + .../sarama.v1/leave_group_response_test.go | 24 + .../Shopify/sarama.v1/length_field.go | 29 + .../Shopify/sarama.v1/list_groups_request.go | 24 + .../sarama.v1/list_groups_request_test.go | 7 + .../Shopify/sarama.v1/list_groups_response.go | 68 + .../sarama.v1/list_groups_response_test.go | 58 + .../src/gopkg.in/Shopify/sarama.v1/message.go | 196 ++ .../gopkg.in/Shopify/sarama.v1/message_set.go | 89 + .../Shopify/sarama.v1/message_test.go | 165 ++ .../Shopify/sarama.v1/metadata_request.go | 52 + .../sarama.v1/metadata_request_test.go | 29 + .../Shopify/sarama.v1/metadata_response.go | 239 ++ .../sarama.v1/metadata_response_test.go | 139 ++ .../src/gopkg.in/Shopify/sarama.v1/metrics.go | 51 + .../Shopify/sarama.v1/metrics_test.go | 172 ++ .../gopkg.in/Shopify/sarama.v1/mockbroker.go | 324 +++ .../Shopify/sarama.v1/mockresponses.go | 455 ++++ .../Shopify/sarama.v1/mocks/README.md | 13 + .../Shopify/sarama.v1/mocks/async_producer.go | 174 ++ .../sarama.v1/mocks/async_producer_test.go | 132 ++ .../Shopify/sarama.v1/mocks/consumer.go | 315 +++ .../Shopify/sarama.v1/mocks/consumer_test.go | 249 +++ .../gopkg.in/Shopify/sarama.v1/mocks/mocks.go | 48 + .../Shopify/sarama.v1/mocks/sync_producer.go | 148 ++ .../sarama.v1/mocks/sync_producer_test.go | 124 ++ .../sarama.v1/offset_commit_request.go | 190 ++ .../sarama.v1/offset_commit_request_test.go | 90 + .../sarama.v1/offset_commit_response.go | 85 + .../sarama.v1/offset_commit_response_test.go | 24 + .../Shopify/sarama.v1/offset_fetch_request.go | 81 + .../sarama.v1/offset_fetch_request_test.go | 31 + .../sarama.v1/offset_fetch_response.go | 143 ++ .../sarama.v1/offset_fetch_response_test.go | 22 + .../Shopify/sarama.v1/offset_manager.go | 542 +++++ .../Shopify/sarama.v1/offset_manager_test.go | 369 ++++ .../Shopify/sarama.v1/offset_request.go | 132 ++ .../Shopify/sarama.v1/offset_request_test.go | 43 + .../Shopify/sarama.v1/offset_response.go | 174 ++ .../Shopify/sarama.v1/offset_response_test.go | 111 + .../Shopify/sarama.v1/packet_decoder.go | 45 + .../Shopify/sarama.v1/packet_encoder.go | 50 + .../gopkg.in/Shopify/sarama.v1/partitioner.go | 123 ++ .../Shopify/sarama.v1/partitioner_test.go | 215 ++ .../Shopify/sarama.v1/prep_encoder.go | 121 + .../Shopify/sarama.v1/produce_request.go | 209 ++ .../Shopify/sarama.v1/produce_request_test.go | 47 + .../Shopify/sarama.v1/produce_response.go | 158 ++ .../sarama.v1/produce_response_test.go | 67 + .../gopkg.in/Shopify/sarama.v1/produce_set.go | 176 ++ .../Shopify/sarama.v1/produce_set_test.go | 185 ++ .../Shopify/sarama.v1/real_decoder.go | 259 +++ .../Shopify/sarama.v1/real_encoder.go | 129 ++ .../src/gopkg.in/Shopify/sarama.v1/request.go | 119 + .../Shopify/sarama.v1/request_test.go | 91 + .../Shopify/sarama.v1/response_header.go | 21 + .../Shopify/sarama.v1/response_header_test.go | 21 + .../src/gopkg.in/Shopify/sarama.v1/sarama.go | 99 + .../sarama.v1/sasl_handshake_request.go | 33 + .../sarama.v1/sasl_handshake_request_test.go | 17 + .../sarama.v1/sasl_handshake_response.go | 38 + .../sarama.v1/sasl_handshake_response_test.go | 24 + .../Shopify/sarama.v1/sync_group_request.go | 100 + .../sarama.v1/sync_group_request_test.go | 38 + .../Shopify/sarama.v1/sync_group_response.go | 40 + .../sarama.v1/sync_group_response_test.go | 40 + .../Shopify/sarama.v1/sync_producer.go | 164 ++ .../Shopify/sarama.v1/sync_producer_test.go | 199 ++ .../Shopify/sarama.v1/tools/README.md | 10 + .../tools/kafka-console-consumer/README.md | 29 + .../kafka-console-consumer.go | 145 ++ .../kafka-console-partitionconsumer/README.md | 28 + .../kafka-console-partitionconsumer.go | 102 + .../tools/kafka-console-producer/README.md | 34 + .../kafka-console-producer.go | 124 ++ .../src/gopkg.in/Shopify/sarama.v1/utils.go | 152 ++ .../gopkg.in/Shopify/sarama.v1/utils_test.go | 21 + .../Shopify/sarama.v1/vagrant/boot_cluster.sh | 22 + .../sarama.v1/vagrant/create_topics.sh | 8 + .../sarama.v1/vagrant/install_cluster.sh | 49 + .../Shopify/sarama.v1/vagrant/kafka.conf | 9 + .../Shopify/sarama.v1/vagrant/provision.sh | 15 + .../sarama.v1/vagrant/run_toxiproxy.sh | 22 + .../sarama.v1/vagrant/server.properties | 127 ++ .../sarama.v1/vagrant/setup_services.sh | 29 + .../Shopify/sarama.v1/vagrant/toxiproxy.conf | 6 + .../Shopify/sarama.v1/vagrant/zookeeper.conf | 7 + .../sarama.v1/vagrant/zookeeper.properties | 36 + 876 files changed, 73718 insertions(+) create mode 100644 vendor/manifest create mode 100644 vendor/src/github.com/Shopify/sarama/CHANGELOG.md create mode 100644 vendor/src/github.com/Shopify/sarama/MIT-LICENSE create mode 100644 vendor/src/github.com/Shopify/sarama/Makefile create mode 100644 vendor/src/github.com/Shopify/sarama/README.md create mode 100644 vendor/src/github.com/Shopify/sarama/Vagrantfile create mode 100644 vendor/src/github.com/Shopify/sarama/api_versions_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/api_versions_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/api_versions_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/api_versions_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/async_producer.go create mode 100644 vendor/src/github.com/Shopify/sarama/async_producer_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/broker.go create mode 100644 vendor/src/github.com/Shopify/sarama/broker_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/client.go create mode 100644 vendor/src/github.com/Shopify/sarama/client_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/config.go create mode 100644 vendor/src/github.com/Shopify/sarama/config_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/consumer.go create mode 100644 vendor/src/github.com/Shopify/sarama/consumer_group_members.go create mode 100644 vendor/src/github.com/Shopify/sarama/consumer_group_members_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/consumer_metadata_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/consumer_metadata_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/consumer_metadata_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/consumer_metadata_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/consumer_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/crc32_field.go create mode 100644 vendor/src/github.com/Shopify/sarama/describe_groups_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/describe_groups_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/describe_groups_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/describe_groups_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/dev.yml create mode 100644 vendor/src/github.com/Shopify/sarama/encoder_decoder.go create mode 100644 vendor/src/github.com/Shopify/sarama/errors.go create mode 100644 vendor/src/github.com/Shopify/sarama/examples/README.md create mode 100644 vendor/src/github.com/Shopify/sarama/examples/http_server/README.md create mode 100644 vendor/src/github.com/Shopify/sarama/examples/http_server/http_server.go create mode 100644 vendor/src/github.com/Shopify/sarama/examples/http_server/http_server_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/fetch_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/fetch_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/fetch_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/fetch_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/functional_client_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/functional_consumer_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/functional_offset_manager_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/functional_producer_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/functional_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/heartbeat_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/heartbeat_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/heartbeat_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/heartbeat_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/join_group_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/join_group_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/join_group_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/join_group_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/leave_group_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/leave_group_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/leave_group_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/leave_group_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/length_field.go create mode 100644 vendor/src/github.com/Shopify/sarama/list_groups_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/list_groups_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/list_groups_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/list_groups_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/message.go create mode 100644 vendor/src/github.com/Shopify/sarama/message_set.go create mode 100644 vendor/src/github.com/Shopify/sarama/message_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/metadata_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/metadata_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/metadata_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/metadata_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/metrics.go create mode 100644 vendor/src/github.com/Shopify/sarama/metrics_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/mockbroker.go create mode 100644 vendor/src/github.com/Shopify/sarama/mockresponses.go create mode 100644 vendor/src/github.com/Shopify/sarama/mocks/README.md create mode 100644 vendor/src/github.com/Shopify/sarama/mocks/async_producer.go create mode 100644 vendor/src/github.com/Shopify/sarama/mocks/async_producer_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/mocks/consumer.go create mode 100644 vendor/src/github.com/Shopify/sarama/mocks/consumer_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/mocks/mocks.go create mode 100644 vendor/src/github.com/Shopify/sarama/mocks/sync_producer.go create mode 100644 vendor/src/github.com/Shopify/sarama/mocks/sync_producer_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_commit_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_commit_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_commit_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_commit_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_fetch_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_fetch_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_fetch_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_fetch_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_manager.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_manager_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/offset_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/packet_decoder.go create mode 100644 vendor/src/github.com/Shopify/sarama/packet_encoder.go create mode 100644 vendor/src/github.com/Shopify/sarama/partitioner.go create mode 100644 vendor/src/github.com/Shopify/sarama/partitioner_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/prep_encoder.go create mode 100644 vendor/src/github.com/Shopify/sarama/produce_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/produce_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/produce_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/produce_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/produce_set.go create mode 100644 vendor/src/github.com/Shopify/sarama/produce_set_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/real_decoder.go create mode 100644 vendor/src/github.com/Shopify/sarama/real_encoder.go create mode 100644 vendor/src/github.com/Shopify/sarama/request.go create mode 100644 vendor/src/github.com/Shopify/sarama/request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/response_header.go create mode 100644 vendor/src/github.com/Shopify/sarama/response_header_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/sarama.go create mode 100644 vendor/src/github.com/Shopify/sarama/sasl_handshake_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/sasl_handshake_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/sasl_handshake_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/sasl_handshake_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/sync_group_request.go create mode 100644 vendor/src/github.com/Shopify/sarama/sync_group_request_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/sync_group_response.go create mode 100644 vendor/src/github.com/Shopify/sarama/sync_group_response_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/sync_producer.go create mode 100644 vendor/src/github.com/Shopify/sarama/sync_producer_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/tools/README.md create mode 100644 vendor/src/github.com/Shopify/sarama/tools/kafka-console-consumer/README.md create mode 100644 vendor/src/github.com/Shopify/sarama/tools/kafka-console-consumer/kafka-console-consumer.go create mode 100644 vendor/src/github.com/Shopify/sarama/tools/kafka-console-partitionconsumer/README.md create mode 100644 vendor/src/github.com/Shopify/sarama/tools/kafka-console-partitionconsumer/kafka-console-partitionconsumer.go create mode 100644 vendor/src/github.com/Shopify/sarama/tools/kafka-console-producer/README.md create mode 100644 vendor/src/github.com/Shopify/sarama/tools/kafka-console-producer/kafka-console-producer.go create mode 100644 vendor/src/github.com/Shopify/sarama/utils.go create mode 100644 vendor/src/github.com/Shopify/sarama/utils_test.go create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/boot_cluster.sh create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/create_topics.sh create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/install_cluster.sh create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/kafka.conf create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/provision.sh create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/run_toxiproxy.sh create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/server.properties create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/setup_services.sh create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/toxiproxy.conf create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/zookeeper.conf create mode 100644 vendor/src/github.com/Shopify/sarama/vagrant/zookeeper.properties create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/bypass.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/bypasssafe.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/common.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/common_test.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/config.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/doc.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/dump.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/dump_test.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/example_test.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/format.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/format_test.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/internal_test.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/spew.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/spew_test.go create mode 100644 vendor/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go create mode 100644 vendor/src/github.com/eapache/go-resiliency/breaker/README.md create mode 100644 vendor/src/github.com/eapache/go-resiliency/breaker/breaker.go create mode 100644 vendor/src/github.com/eapache/go-resiliency/breaker/breaker_test.go create mode 100644 vendor/src/github.com/eapache/go-xerial-snappy/LICENSE create mode 100644 vendor/src/github.com/eapache/go-xerial-snappy/README.md create mode 100644 vendor/src/github.com/eapache/go-xerial-snappy/snappy.go create mode 100644 vendor/src/github.com/eapache/go-xerial-snappy/snappy_test.go create mode 100644 vendor/src/github.com/eapache/queue/LICENSE create mode 100644 vendor/src/github.com/eapache/queue/README.md create mode 100644 vendor/src/github.com/eapache/queue/queue.go create mode 100644 vendor/src/github.com/eapache/queue/queue_test.go create mode 100644 vendor/src/github.com/golang/snappy/AUTHORS create mode 100644 vendor/src/github.com/golang/snappy/CONTRIBUTORS create mode 100644 vendor/src/github.com/golang/snappy/LICENSE create mode 100644 vendor/src/github.com/golang/snappy/README create mode 100644 vendor/src/github.com/golang/snappy/cmd/snappytool/main.cpp create mode 100644 vendor/src/github.com/golang/snappy/decode.go create mode 100644 vendor/src/github.com/golang/snappy/decode_amd64.go create mode 100644 vendor/src/github.com/golang/snappy/decode_amd64.s create mode 100644 vendor/src/github.com/golang/snappy/decode_other.go create mode 100644 vendor/src/github.com/golang/snappy/encode.go create mode 100644 vendor/src/github.com/golang/snappy/encode_amd64.go create mode 100644 vendor/src/github.com/golang/snappy/encode_amd64.s create mode 100644 vendor/src/github.com/golang/snappy/encode_other.go create mode 100644 vendor/src/github.com/golang/snappy/golden_test.go create mode 100644 vendor/src/github.com/golang/snappy/snappy.go create mode 100644 vendor/src/github.com/golang/snappy/snappy_test.go create mode 100644 vendor/src/github.com/golang/snappy/testdata/Mark.Twain-Tom.Sawyer.txt create mode 100644 vendor/src/github.com/golang/snappy/testdata/Mark.Twain-Tom.Sawyer.txt.rawsnappy create mode 100644 vendor/src/github.com/klauspost/crc32/LICENSE create mode 100644 vendor/src/github.com/klauspost/crc32/README.md create mode 100644 vendor/src/github.com/klauspost/crc32/crc32.go create mode 100644 vendor/src/github.com/klauspost/crc32/crc32_amd64.go create mode 100644 vendor/src/github.com/klauspost/crc32/crc32_amd64.s create mode 100644 vendor/src/github.com/klauspost/crc32/crc32_amd64p32.go create mode 100644 vendor/src/github.com/klauspost/crc32/crc32_amd64p32.s create mode 100644 vendor/src/github.com/klauspost/crc32/crc32_generic.go create mode 100644 vendor/src/github.com/klauspost/crc32/crc32_otherarch.go create mode 100644 vendor/src/github.com/klauspost/crc32/crc32_s390x.go create mode 100644 vendor/src/github.com/klauspost/crc32/crc32_s390x.s create mode 100644 vendor/src/github.com/klauspost/crc32/crc32_test.go create mode 100644 vendor/src/github.com/klauspost/crc32/example_test.go create mode 100644 vendor/src/github.com/lib/pq/CONTRIBUTING.md create mode 100644 vendor/src/github.com/lib/pq/LICENSE.md create mode 100644 vendor/src/github.com/lib/pq/README.md create mode 100644 vendor/src/github.com/lib/pq/array.go create mode 100644 vendor/src/github.com/lib/pq/array_test.go create mode 100644 vendor/src/github.com/lib/pq/bench_test.go create mode 100644 vendor/src/github.com/lib/pq/buf.go create mode 100644 vendor/src/github.com/lib/pq/certs/README create mode 100644 vendor/src/github.com/lib/pq/certs/bogus_root.crt create mode 100644 vendor/src/github.com/lib/pq/certs/postgresql.crt create mode 100644 vendor/src/github.com/lib/pq/certs/postgresql.key create mode 100644 vendor/src/github.com/lib/pq/certs/root.crt create mode 100644 vendor/src/github.com/lib/pq/certs/server.crt create mode 100644 vendor/src/github.com/lib/pq/certs/server.key create mode 100644 vendor/src/github.com/lib/pq/conn.go create mode 100644 vendor/src/github.com/lib/pq/conn_go18.go create mode 100644 vendor/src/github.com/lib/pq/conn_test.go create mode 100644 vendor/src/github.com/lib/pq/copy.go create mode 100644 vendor/src/github.com/lib/pq/copy_test.go create mode 100644 vendor/src/github.com/lib/pq/doc.go create mode 100644 vendor/src/github.com/lib/pq/encode.go create mode 100644 vendor/src/github.com/lib/pq/encode_test.go create mode 100644 vendor/src/github.com/lib/pq/error.go create mode 100644 vendor/src/github.com/lib/pq/go18_test.go create mode 100644 vendor/src/github.com/lib/pq/hstore/hstore.go create mode 100644 vendor/src/github.com/lib/pq/hstore/hstore_test.go create mode 100644 vendor/src/github.com/lib/pq/issues_test.go create mode 100644 vendor/src/github.com/lib/pq/listen_example/doc.go create mode 100644 vendor/src/github.com/lib/pq/notify.go create mode 100644 vendor/src/github.com/lib/pq/notify_test.go create mode 100644 vendor/src/github.com/lib/pq/oid/doc.go create mode 100644 vendor/src/github.com/lib/pq/oid/gen.go create mode 100644 vendor/src/github.com/lib/pq/oid/types.go create mode 100644 vendor/src/github.com/lib/pq/ssl.go create mode 100644 vendor/src/github.com/lib/pq/ssl_go1.7.go create mode 100644 vendor/src/github.com/lib/pq/ssl_permissions.go create mode 100644 vendor/src/github.com/lib/pq/ssl_renegotiation.go create mode 100644 vendor/src/github.com/lib/pq/ssl_test.go create mode 100644 vendor/src/github.com/lib/pq/ssl_windows.go create mode 100644 vendor/src/github.com/lib/pq/url.go create mode 100644 vendor/src/github.com/lib/pq/url_test.go create mode 100644 vendor/src/github.com/lib/pq/user_posix.go create mode 100644 vendor/src/github.com/lib/pq/user_windows.go create mode 100644 vendor/src/github.com/lib/pq/uuid.go create mode 100644 vendor/src/github.com/lib/pq/uuid_test.go create mode 100644 vendor/src/github.com/pierrec/lz4/LICENSE create mode 100644 vendor/src/github.com/pierrec/lz4/README.md create mode 100644 vendor/src/github.com/pierrec/lz4/block.go create mode 100644 vendor/src/github.com/pierrec/lz4/export_test.go create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/01572067d493db8dc8161f05c339a5192b0b4087-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/02766f768fbfbd81b752cce427eb5242a44929cc-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/032f04032e12567057782672bb12670c20d38439-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0367b985641aca66e6e4eeea68acf5e2a02c62a8-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/03e85abc49352b2f7cc83efd7e4274da02d78b84-6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/049f82a81bb6b4d7cf69fac5e413f6ce299d48cf-8 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/04c05c7956f17e57a91a47909bd0706135cf17a6-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/050e2af2a57d8044139ba21375f0ac6fcb7ab0b1-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0547c73efb9b6a345fd9a52aa0798b48dd9aca62-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/05aae2cf8756f66066cf623618042ebaa92ec745-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/07fe3e792f0d2862dccc04db22c0e4aef4d41b49-6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0990ac54decbca1a97893e83c7feb2be89cb10ea-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/09f2eda28ecc97304659afded4d13a188baf2107-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0a4ff2ab3a01888686c5bc358b72be108bbb4721-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0a7fddf3c8aa1c781223748129c9dc0807de3a6b-28 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0b5bec228930b2cfcda3be9a39107a6bc8044f1e-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0ca5fd3841a6777873c7ef26f65a384e7b15d065-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0ce9c3bac93df0ea1f6343d223d5220f9eb2383a-8 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0cf885cd35e7124005b0ba0c3c4431ddfaeff84d-11 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0d7c02d4e91d82b0355baaca1237062639442db6-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/0e1b2b0c49dfb86fe01d3453dd24e39482e132e8-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/1.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/10.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/106b9d718c97bb7c872847d3070a570e99d9fa3e-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/10fa5d9f0fe75f73c0e92a1fe1c00f0041ec8f39-24 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/11.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/113a12cbb28b83fcee714d58c35bbf52c0740e90-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/12.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/1288161f8ce422490f63f257ce7338ef90fb8827-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/13.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/136f7224ae337a61df2e72b80af8b1aaa5933af3-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/13c3c26f7a34d01fc89c92ca8ba2ba5ae430c225-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/13db64707d1ea3070b4a37b6c1291d6125acbbd3-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/14.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/14193748a7b6cda204b11d042a35635151e90dbb-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/142d4f8cb427dd3562d72d889dfc0ea3a2b03d98-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/15.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/15663b854e9a4f193502ea6463dae38b4d8fca90-19 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/15e223354eb5378a7ee74a41dfab28ffc895ca33-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/16.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/17.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/177c1c68fead4507aa47dd2455fd17a10ceda5ea-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/18.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/180a2772b126d31abcb3ef692a14b13cf47f103e-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/19.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/191e0dd24b8c7f8babeae4839768df39acc17eb1-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/1a582381781f264f551bd6f0f2284a931147e6d9-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/1c2781a1ffae4059ce3e93a55ec8d8cbf8bdecdf-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/1d37fb332301cf7de0bd51a8c1aa9be4935e89fc-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/1d6b87b52e62cb84be834478ad88129f5e1f247b-9 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/1ec2f11a8d8b9cf188a58f673a0b4a8608a926ca-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/1fc2ba0bb981fec47badea1c80219452c9e3c76c-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/1fd8444ac43541c44a1c6ed8df2f688b1fa09681-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/20.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/202a9c8b188cae90f29bce3bf0438a035c504eb4-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/20cf0057443ecb322ff1169ecbe6cf20250f15af-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/20d1a26afe563ad77e7a95fbee6ff59ebf3e61ab-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/21.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/22.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2201e32d052c15874f0323a09c330f3666029a72-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/226780b32ba8f87ec614fdb376aa0884011c4ca9-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/22897c61698649d7570de91613afdc19b66e6965-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/23.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/234cc427d9be32470f3c2e11a6bc16567f558e55-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/24.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2486a84bf0f161f45b050d9c19ea9e35f5def864-8 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/25.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/25252b16cd4afa8ef86122448688c7095684c86b-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/26.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/263fb3d738b862ec4050e5a9fbabfbd99cb0d9a5-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/27.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/276580343a14eec04143e89a778dae3e14df472c-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/27fb5dc4016dc640e55a60719a222c38c604fa6b-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/28.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/29.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2a08d7c56ff9959698688f19ddd2e1e4d4651270-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2a33d8514fb512aa20b0a56800cd3e12f3952b6b-26 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2a52400dd3aa2d2a40657d1e51c47c1929912927-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2ab005ac79cd4dada693dd2a747c001898d45e1e-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2b39aa66ecfac58e61185c9664a968233931496a-9 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2c2a5947341d76797a7e2299f39d01e3aebb2eb8-19 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2cc2308b75a2e8f7eafcf69370767e5fce314892-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2cdafdadb156e2759c389b6b8edf6a402034886c-26 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2d7f0171116eec9984eaa9138e1312e90a7d67ee-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2de93224b5f0db491ced1ec491a9f41d71820671-11 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2e8487cf61feda70c0d74f12bfb5b692b684f82a-9 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2f0ee9cf4bb951a37efc6460d5709442bc3de54e-6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2f1ba7fe1cd90a4023706a2ea9c7c9dca8128119-30 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/2fad20024167a500cdb8df5334a614f113efae00-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/3.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/30.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/300579a548d96d64c9da8470efa15e787f1a36f1-28 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/31.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/32.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/33.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/34.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/35.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/36.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/363d4559cac10516289fe1b6029590c4c7a6d8eb-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/37.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/3771c6e8ea0f20350dae0180a9b14e36b8aef244-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/37ee7fab504f2d2039753d73dd0290c884bd57bf-8 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/38.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/39.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/396101a712463bb336a18f4096fc3eb5923600c1-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/397127b75cb59b253ed49206082b0428b6b23d02-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/39ccf446395ef707cf92a04b5508deda399372c2-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/3de3c5c394a3cf05620bb80871a1f10e9e36f25b-8 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/3dee65f1cf51dfe2e5be498150ce22d2ac5a07fd-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/3e34341fb51769fd9d948bdd20c011e335b145f4-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/3ee211efb3d5d8058cd9a8c59e40c8d0f7a3df53-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/40.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/405726718b3f54a0cfae1666f06d3cc1ee747104-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/407188676d45d6f9dd5f3c84e7df0e763c7cca57-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/408ac1a4a83e082e848c208eed903930d81e81b6-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/41.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/413e39442f005279560ddad02bbdd1a05c9f0eaf-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/41b7eaf8892043eccf381ccbc46ab024eb9c503c-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/42.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4208b7fe7ac3a530c159a1c8fd09dd3078b5650f-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/421bd1daa317c5d67fa21879de29d062c342294b-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/42b056f9dac9cc658c80092e490b3dbcd436e3f8-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/43.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/432c09281c46537c98864bc7d601780562b68410-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/44.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/446dc91ff0ddc34c3b02f741e3f6f079a4dfcae8-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/45.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/451831159c1afb87077066147630b4b6caeb54c3-11 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/46.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/47.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/48.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/49.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/49861b3d9bca3e2857d806aaecaac09af4bff1dd-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/49a3ead0ad96e8da5a4c8f89bd140e1d8af8995a-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4a625a4b4f3069707e88f16db88e993dabc41aa2-27 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4a6464c2aba2492f5122856de7ac451994eadda4-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4b0ab2fc1fdfc56066c5c1f2751b292f4ddc557e-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4b55f37e6637f4246a41caa490da4bec632379d4-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4bb422b835278e4aca92d076331d9c8cc5752345-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4bd00d26b893ce064dad6e771f30541b541d43b9-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4cde5adc216a29fff2ec39e23ccc6fca80cd4a15-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4d1b64babe1f045b8374f4d74949622591546eb5-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4d49686993529cfe29473c50b9b0fb2b6ea4f6bf-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4ea726d6736026a733707e695d9c2cdc83efc05b-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/4ef3e6d20ccec24376a526ab9ec9f6f2cc604129-25 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/50.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/50a87eb0c097a7ebf7f1bf3be2c6a7dbe6b6c5c3-23 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/50e3ac1126c605158726db6f2cca3120f99b8e73-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/51.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/512ed5fb4e92818b75bd7633f58d6ca5340ffd94-27 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/514a62216c761adf23d946f11c0d1a0410990641-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/516d84c21ac984bd1cae56910d71b62e39610c5d-29 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/52.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/53.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/54.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5431cabbc58d8dc143ece079de40300c1ce6e101-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/55700385089e16e44968ea410c6b90206b16d72a-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/55b9a902445e2bfa2f0f37d630779d329eeda20e-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5620a492eaf067734e5b8b64517b28ec3beaa97e-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5699fea659964d8ab94069d08b0b97834c0a42df-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5765fc21629571e51adf2fc2bc8b64541a1ea08d-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5768ea5d1911143f4b1c0585b9b864ebe16aa004-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/57b780437f4abf2d5cba0775bf802a4dfdb067d6-25 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/58f53d40265c9a49c0d3b4292cb637464a4e376a-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/59b254c3565c9eed2bc93385b821da897afcbb15-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5a962e3d6a128983afe9ea78a28cce0f40a790c0-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5af52ef91b6f717ffdd805585e24806407e9621b-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5b01aeb030dc1dc9568fd32f1647d92f0692a411-6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5bbd27cea704a4e6ff3f42f4792a91eb7839bc0d-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5bd895c23369df9505dd99ffcd035dc5e897264b-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5bfd84d7b2ba6b6325d5135fb0a9ae1ec5d7d3e1-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5c4f347c3567baf700dfccf49a91192c83b89da2-8 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5dd8001f8a87c24f866074c36b6b80f42b298ff0-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5ddf63d61aa38da1d409e37b301e0fe5a207a051-27 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5e54c67050ee8583c7453ff13d6eec15b2255288-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/5fbebd9edd144c4b9869ed4ab40c7cc3c46a4a8f-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/6.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/6046b14dd1f6925bcfe470a8484353f525db6a9c-19 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/608a9993a51ec7bf252ac76b163def5f7002d2e4-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/610d8dc3cf4012e4e2d070988b0720285a4c361e-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/61b196987682fb64ef9c4ff37532bf9b2ac201bc-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/626f8b6efa3ea0f254789fe6cf52f6e52538f357-25 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/6277f2e0a6df2ac61660ee1965c690b87c26b556-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/62c738f00c488f493989b2037d9cf1781f0bbd40-11 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/631ffa88df9713a124b3ba6c704c0c75727af2ff-6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/635d5de257a1910a7fd0db2e567edfa348e47270-11 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/64c500b5addcbf8c673188a1477e4159851ae04f-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/660387064a3cf4cb81046989929abe1b4fbfc815-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/66068a7e7bdfd1038a84aeb3dec6e3cb4d17ad57-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/67ab3037ff49f082a877224d68e35069cc4d45eb-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/69dcc80940a26844b0afe7898fea9cf68b698214-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/6a04b54e1511633ec895326b4e043e186fa5693b-29 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/6a3e8935204dcd3dc48a1ff7415c305f0e5863aa-9 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/6b351674a45f2d9be602fe8d3fb84229551b4ce3-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/6b7f4ac7aa8b357dee3067d7a60143c03b54bb8d-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/6bc138796e9b80572a6cb1b4a7ba30c97c22359d-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/6e14a407faae939957b80e641a836735bbdcad5a-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/6f24be0bcac848e4e5b4b85bc60f70f12388a5ed-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7102c7f297296821114661e00e5bf54d0891d105-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7151692dfebfc82876676e65ee9b807d83a3df54-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/71a24ce771fb7f1a4163e57a478c3044ad42e62d-24 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/72f032947602f1be74f01c91165c5118121f36c7-24 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/73b6bd1462a0521b4bf76abb1fd80df6e180dc80-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/73c81fef0997a4929b303e02a99f3977870f2013-29 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/73efed803abadf6167fc3f04e0674cc39c30f6af-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7603f5f266de813608c4cc1ccd1c798ef8065c5c-23 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/767d1943125a0f6e9397779cc757c9cdd1e05631-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/76d22068e2ed4a5952d4adc7ea8dada5509a784c-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7740102922cb9933980bb800c1115daf38edf654-24 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/783270b1e353ba3895b7d0c4135b8592e22f6508-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7851a406571c6b4c1aeed0af16db8c48444c3f2b-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/78981d313038119ac4f7017349e50a1cba56b382-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/78c88c4afaf5962056b1aea720509b9f6f286b91-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/79c5ac978f5aee35e123f523369aa46b1d0a995d-11 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7adf4aa021efaa953268c817467959fa3c42ca42-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7b8c99ded96973a6e8f523bc1c6ed4ef5c515aa1-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7ba80199cbce9a2eb47da15f0c62fd1fb8fa67d9-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7cdc0917ad63ce7a7c98301a366c31635f0f099d-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7ce37ad19bfe9f52eeadda03e6b8448e5bf57800-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7e3132012be223fd55e5e7a7fc2ea602361ed2b4-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7e9a88118e4c41e61f5c501e6edf9a5bd2432be3-23 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7f081c89cfb6344f4aac5f813da1fd15f8bab022-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7f970f16026c689c096a19fef1a3282a13ee69dc-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/7fa96d28faf45062eb803ea84a334b607e966f90-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/8.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/8261f0c1799ca71c411f6d3f34069b25dac8b739-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/82afa534de59025bf1e3358919286525ae7d3347-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/8496965f7aa6cea3e080dbfb911a7034e6623cb7-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/84a9bda8369d33ffe0d6f520c24331ae64e9dc88-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/86513e3435adaf7c493dd50eb5de372010185e36-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/86637b211f4fa0118ccab9ee193c66286126bb5d-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/8695984335fa005895377a8a60000a921d7efd99-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/86baa53eb98a9a342b0d5b79dfa5c58aa9c1b05e-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/88e6e46ab1ec92ce694b8d4c3d816491169d2bb6-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/89216c662a46d50f37cfa08963acad8c6f7aace7-11 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/8e533f8a1e58710d99d6b7d39af7034961aa4fbe-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/8f0d2862c49eebbcd473a38c8fa1e76288f47127-26 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/8f61ea021e02cc609baafbdf714b9577e4bcb05f-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/8f7a47710904981ffaa1fefa21fa95fd2d818487-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/90a227d3beab730ed6eecd63657f5406beccabdf-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/92197169aded0d5d0407e3925959e922257a101d-28 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/924e17974cd194fa756d23394676d37cc3641f64-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/92a785b5ea93d36e27029e281e9a34377d81ce55-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/92fda3aa2adbe37ff690c59939ca1e1b2a8a7936-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9363b81db6b35e8beebcc32d560f786472829bd8-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/948b1ce043c82d0cfbaa910b6989a1b35a19b8ae-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9505b43fcbc3139441e35bdaaec138e28af076f6-25 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/951bb02c199adb52e9e300e9fc070bf55980b910-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/955404fe3f375361f5c3be1dbcd28eb9a28f06e4-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/967e50c6c1bc99aa5e7fa07c2de14564f52b0fd3-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/96c9a1fa8b0184ad486f8f68a9ddc88434579080-30 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/96cc45abef3bc9fb6659714b9743cda92ec0abb9-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9719ea029fdf8c837f991ac3548145485cc1f06e-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/984480af27d1640fd02f40e736ffcde3a91e4abb-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/98d40a50ee58c05727777e242ecbc0d4e214f7fe-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9915e9bb007bc2c1f3d346123933923279f0dec1-27 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/992413e17d64968cb04af34c7761182f20fc97b6-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/99cfa74a1fea5d16168dd9efc720425b85e95eb7-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9a552bab72f174ede3b9bdb7a663c963fd1463d3-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9aa3050cb38a6ad276cb5e5ca0c4776d92cb7b0f-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9be44693435bc6c51980f30418bcc690d8c25fe7-6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9c0420bf00f888487d543f42fc48b407c65d4717-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9ca2a086f1f08c7dec54d52425bd72f17c11056e-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/9db70b1edad2317d94dcaafe7f5c5e3145084167-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/Mark.Twain-Tom.Sawyer.txt.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a01e13c3e401957031defb62b05434c65b01d5c4-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a059044bdb0402471dbe9aaaa555a063a6bc1e6a-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a06b1a08fcda463f1d51c485b0e7271ff9048b41-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a0f3d67e96968a267366be380147cbc7b17e5b2b-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a18d849dc2a98c4ebb6000b2cc853f21fb64d9e5-24 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a2e5916be780e35e9ecb7c42be52dd5e134f3363-25 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a33252a74974fc86df30c311d501a1f363d350cd-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a462f03ee666a20244d3331e3635b7eb796d906d-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a56e983782e49f8267a61d4375e98b1a862862ac-9 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a58a9f9caca5e73b4296b931201a5ea870974c26-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a628194a08ff63e98625b1786175026c5f02c716-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a64f2336fd4a9ec8153b95f40c383e1ecfed9e73-25 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a6a5682a6663e0c548c9e5acbad4958e2c256b32-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a6dbaac639f3b82609ec27c80fbd003684c28867-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a8c6a4509b61d8baa71f59f9e1eb95712b10626c-23 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/a9e348d9896cc740f7e910d0a70c080adb65cc77-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/aa04575587509ffc65a6b0224d24ad1125cb0f63-26 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/aa290b4dcc8198945311c8149fc1252f14555e70-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/aabb8fa4913c79f0a42494ad2215a32927adbd45-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ac7077c5220abe6cd481318c42dfe6cb2cb2c666-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/acbef0322169a93c7421902883cc8057675c953b-26 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/aec95871bc7d87cae16c36a0d30955b43076aec5-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b20e3f27f4e8d41f16124881f92546f0fb2edc16-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b27fb21ecbe6e77c91341738621ad7092c29bca5-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b38ce47b707326024fb24860c4365d58ab9f3528-29 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b3eaea244bd47b64c8de3d81c7b5e94e421d7f32-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b3fd355dc090a732d5cf3b25151f165ea901a682-24 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b58846d79a8dc960a718ef88dd3a06ad49b1fe72-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b5b5b895b4619fa039ea99520b9947de2996c38f-6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b6aca5c55295d93491e47817f46ca372c9078cec-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b6ddb90092b3087158dc32669529db2012f14c3c-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b6e7a519d013ddb67313af02a9ce966877949487-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b71a5a7c576e5cc5ba23845d352b2af16737c03c-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b7815c3b5649d9a367ba99e7e09cf1f251ab6f83-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b7a5b15c9e2d4d659d421de8e3b463200f71f1ec-23 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b83b3d04ada1403578065d7f10aa7441830dea3c-11 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/b94b7ebc6d153e0c99a97864f58b26f7192f66a5-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ba98469ede70309f18893f0ff95380f5a0486fcd-6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/bc0c31f304c1a1f8be0c8a0d9daa3b8aa1f23799-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/bc650b6a5356c1935f64f6fb755e43bc5f5187c4-26 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/be06bb3c3b604660fd36b2af8860d35e31c8bbf3-8 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/be5767f4d79c5a0b2643d8eddb74eca0598674dc-19 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c07f4e4cb1d0a34dc6899097fd27ee9f1744cb70-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c2ac55a7fb702dd9a527b576d99008fe9b4f376f-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c2c3d29bce8aae89fed326832b3e1e1077cef1da-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c321670bbcd985327045dd1468bf2ac4ae7333e5-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c34998d9a8893eca9cdeafe7b2482469ad98192b-25 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c5522d11f314fc46de58e15116b6910d52acf866-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c652c46aba3567521f912bae6dc263b668c34c9c-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c6610b87900912d462229a5259dab51ea0aeef33-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c6c37f6c89fe55768f8b3f7b28b99467c239703a-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c71abfffdcf530a6d28fd99cd2c3505c61ef0ac5-8 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c77304b250e887b39b5447d19b9c106fcebe7e66-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c78cd8530e6d8a606a28797552ce3f5494763621-25 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c790308a65efa1b895bc57abe53e4fbcdb2b7d0e-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/c7fe1fe2e3fc19fab3766f9fdb1d22c848d49aed-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ca5d375d8a66727221d3e198d4ad360782944de7-27 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/cb635ef244cb6affc005c63d0bf8b52aecb1d986-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/cd67bf90feaeb1912792508afa01a09fe1f044c6-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/cda434677d4bdd969a3bbf84086349f821e39c80-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/cfe7201e28d42484764264c231663e6372e95ef7-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/cff88dd94ee94e1901d25a74e29ad863bb78b1e4-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/cffc7573debb5af80aaddfa752538825275fd6a9-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/d0ae058f71e53a7afd648b859cd7485886be550d-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/d0e6298a63ffc2695cf7d016a124db7375f197cf-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/d24f23a23508dd6bc93ea6283ed49c8ba4b737ed-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/d295ca4c78f7fd3ff10b0520b09a0a346310e0a9-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/d3ddffcd038a5646a53d48b684eac5b721c7062a-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/d4275f1f814a5b24f7b4788d15f3fef7b2be8aef-23 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/d57eaf0fada8726afac2287cafb7720af7417b16-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/d5c9dc3b5b4e71d902fe4cf5c44b237b104a32a9-4 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/d7855c38db11bfeeb474a4782f1ea293192f786f-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/d7912c5e2a776c408e7640f10bd7d655a6a0f31b-27 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/dba53c14b92561071ccd7762550d53cf43027bdf-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/dc61bdd2fb983111d1392cd79ba9b39e0a3b869f-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/dcb49d3d45d32601fa27208cec33813e03ff6179-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/dce9966b94744440d75a845a48c806041f5a6612-3 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/dd799919262810add464dbb4ee39a38f1e4ed258-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/dd92516fbea2d0f96abc78f325d731053a451e16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ddf986569f89016184b5b6e924d5ba827c9980ca-28 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/de0acf1136a1e05cd27345ce135ea26abd32bbfe-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/de33e3ef8a5780c7d3458188a423c00f470904d0-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/de501127da94246b2d3aa947637b49fbc17d5e47-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/de702cd20caeb08a843e0c09b0ce87a74e300415-20 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/de8abda1b9bd5628ca99c8f97237fa885a857bb5-19 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/def6a9e986daf0b268ef29ef7e821a9f6840ef2c-8 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/df0768cf0c709a1ff1a93cc0dad23979501c54ff-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/dfad565009b0667ef2ee10ea9c1286ee5c3ce6b2-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/e.txt.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/e1556049ba9794a15ee21aa283876bf63e531a4f-24 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/e17af76e8c119233dbd2888ab519bd76d7aa7fe9-6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/e346c715ac3187598d8c0453d9e741fae1232c99-11 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/e3acf6f2b5a1b97f5a82ebf7d1822077561583fe-26 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/e4a2a1469de980756c607cdc2584fc94bc109382-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/e68b04a675d8d4192565a808955764c77ae510e6-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/e7ea1bfd65ca7db84f0984474658bfc3b063c63a-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ea212596f8a7aec4eb2e85fd2cdb5c2816b58495-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ea9af92f89e6889b523461ae7b2b9fecee5a7280-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ebc69b7ca13ae23b075c9b21ebc283278714e3aa-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ec8e760e79dc08a79af0d79c510cafb74e504472-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ec984b6fb8e41dbcd4299ecd1dd6fd0a77347122-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ecbd6bdea50b52d263b4e9cdb96c7ce078d2b780-25 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ecdd1df7d975c8cf8d015b2f1d0d7c6e00eb578b-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/eda1ee9cf85f3f71ec8a4eec7534ed2677b47775-15 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/edbc11de7dd074c367a69532db023cd810bb3978-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ee6afbf375619a2bd6fb0abe0e42e51ab3b0ab13-6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ee907d38c1394c4971b389a99a3be0913836212b-9 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/eebbefa1983c9e1aeb5217aabcac7ab24dfe166f-17 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/eee3d4a9a8b297f016c23f50a9792c30a621720e-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ef87432939473264357babc06257b0280ffd15ee-5 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/efdd522fe3abb88204f63b1fe7312f62b6ee593d-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/f35bdf2e8b4af93c6a73e564055aa4eacd9f0d0c-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/f3a2381d6f39defe22520aea46201e6ce6d37f80-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/f3e916907eab3412b5875e5eca05bf3eac8a8d5e-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/f493376c3eda80cbe822ac456486734b72f891fc-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/f55efbb04cd32f7828e951d067319db00627153f-28 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/f71b4776ecbbe47746fb53d7749751c5c5bbff05-22 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/f724d4c839c012c7772618e28ef68d478cc00c74-21 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/f86152e5ce510dc674fa73d20b324e2d3c4d145b-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/f931bee2e7f1fefd8bb2fabf88f8f3d2b3ea78fa-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fac6c4165067ef2d87a23a2530a59eb560d470e0-23 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fb56a1001599e07354ce3101af111554c6c9bb40-1 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fb75f3059f8835a7e8781c899af756f22d1c06b4-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fbfe35b0485040874ed564b94ba764bdd17e80fc-10 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fcb1c8b1893ca85647581cadec481754d8f35c96-12 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fcb33fb48e48acd9155fd7ed8e82e71c850ffd22-16 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fcd47a15e10a21e1eb13aeac223becc89aac4c69-2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fd4f0dc77a022a8140ffe5b2e1a5ff577e844878-27 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fdb78af507e72288b059ff902ae5e76538d1e6ea-14 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fe002e4c7731ecb4c09c09a4e1fa29c0c61874bc-7 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/fe78d4faf4ce717d84938010f92ca5e844f9980b-13 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ff3b7ea844eb197dc6bd59d9f8e4a4a5718a6771-18 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ff47856b8fa7323572c8b4a6d8028dcb2663a37a-11 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/ffa97253e1ab365b84eebb9d257f9370b7796fbf-28 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/corpus/pss-vect.txt.bz2 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.output create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.quoted create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/crashers/169b44c5a64fec4d8e969d25d3e4764c9c3b604b create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/crashers/169b44c5a64fec4d8e969d25d3e4764c9c3b604b.output create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/crashers/169b44c5a64fec4d8e969d25d3e4764c9c3b604b.quoted create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/crashers/ea0a00651ba4143c05fe7b5c85f69fe16a29a458 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/crashers/ea0a00651ba4143c05fe7b5c85f69fe16a29a458.output create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/crashers/ea0a00651ba4143c05fe7b5c85f69fe16a29a458.quoted create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/lz4-fuzz.zip create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/lz4.go create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/suppressions/a596442269a13f32d85889a173f2d36187a768c6 create mode 100644 vendor/src/github.com/pierrec/lz4/fuzz/suppressions/d159e91cdd6fcbee9e37460f96c597b70c590886 create mode 100644 vendor/src/github.com/pierrec/lz4/lz4.go create mode 100644 vendor/src/github.com/pierrec/lz4/lz4_test.go create mode 100644 vendor/src/github.com/pierrec/lz4/lz4c/main.go create mode 100644 vendor/src/github.com/pierrec/lz4/reader.go create mode 100644 vendor/src/github.com/pierrec/lz4/writer.go create mode 100644 vendor/src/github.com/pierrec/xxHash/xxHash32/example_test.go create mode 100644 vendor/src/github.com/pierrec/xxHash/xxHash32/xxHash32.go create mode 100644 vendor/src/github.com/pierrec/xxHash/xxHash32/xxHash32_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/LICENSE create mode 100644 vendor/src/github.com/rcrowley/go-metrics/README.md create mode 100644 vendor/src/github.com/rcrowley/go-metrics/cmd/metrics-bench/metrics-bench.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/cmd/metrics-example/metrics-example.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/cmd/never-read/never-read.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/counter.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/counter_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/debug.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/debug_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/ewma.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/ewma_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/exp/exp.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/gauge.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/gauge_float64.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/gauge_float64_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/gauge_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/graphite.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/graphite_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/healthcheck.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/histogram.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/histogram_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/json.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/json_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/librato/client.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/librato/librato.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/log.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/memory.md create mode 100644 vendor/src/github.com/rcrowley/go-metrics/meter.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/meter_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/metrics.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/metrics_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/opentsdb.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/opentsdb_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/registry.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/registry_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/runtime.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/runtime_cgo.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/runtime_gccpufraction.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/runtime_no_cgo.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/runtime_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/sample.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/sample_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/stathat/stathat.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/syslog.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/timer.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/timer_test.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/validate.sh create mode 100644 vendor/src/github.com/rcrowley/go-metrics/writer.go create mode 100644 vendor/src/github.com/rcrowley/go-metrics/writer_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/CHANGELOG.md create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/MIT-LICENSE create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/Makefile create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/README.md create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/Vagrantfile create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/async_producer.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/async_producer_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/broker.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/broker_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/client.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/client_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/config.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/config_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/consumer.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/consumer_group_members.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/consumer_group_members_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/consumer_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/crc32_field.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/dev.yml create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/encoder_decoder.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/errors.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/examples/README.md create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/README.md create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/http_server.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/http_server_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/fetch_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/fetch_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/fetch_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/fetch_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/functional_client_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/functional_consumer_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/functional_offset_manager_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/functional_producer_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/functional_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/join_group_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/join_group_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/join_group_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/join_group_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/length_field.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/message.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/message_set.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/message_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/metadata_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/metadata_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/metadata_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/metadata_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/metrics.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/metrics_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/mockbroker.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/mockresponses.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/mocks/README.md create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/mocks/async_producer.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/mocks/async_producer_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/mocks/consumer.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/mocks/consumer_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/mocks/mocks.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/mocks/sync_producer.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/mocks/sync_producer_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_manager.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_manager_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/offset_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/packet_decoder.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/packet_encoder.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/partitioner.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/partitioner_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/prep_encoder.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/produce_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/produce_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/produce_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/produce_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/produce_set.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/produce_set_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/real_decoder.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/real_encoder.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/response_header.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/response_header_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sarama.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_request.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_request_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_response.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_response_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sync_producer.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/sync_producer_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/tools/README.md create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-consumer/README.md create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-consumer/kafka-console-consumer.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-partitionconsumer/README.md create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-partitionconsumer/kafka-console-partitionconsumer.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-producer/README.md create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-producer/kafka-console-producer.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/utils.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/utils_test.go create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/boot_cluster.sh create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/create_topics.sh create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/install_cluster.sh create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/kafka.conf create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/provision.sh create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/run_toxiproxy.sh create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/server.properties create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/setup_services.sh create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/toxiproxy.conf create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/zookeeper.conf create mode 100644 vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/zookeeper.properties diff --git a/vendor/manifest b/vendor/manifest new file mode 100644 index 00000000..9a0a4d78 --- /dev/null +++ b/vendor/manifest @@ -0,0 +1,80 @@ +{ + "version": 0, + "dependencies": [ + { + "importpath": "github.com/Shopify/sarama", + "repository": "https://github.com/Shopify/sarama", + "revision": "574d3147eee384229bf96a5d12c207fe7b5234f3", + "branch": "master" + }, + { + "importpath": "github.com/davecgh/go-spew/spew", + "repository": "https://github.com/davecgh/go-spew", + "revision": "346938d642f2ec3594ed81d874461961cd0faa76", + "branch": "master", + "path": "/spew" + }, + { + "importpath": "github.com/eapache/go-resiliency/breaker", + "repository": "https://github.com/eapache/go-resiliency", + "revision": "b86b1ec0dd4209a588dc1285cdd471e73525c0b3", + "branch": "master", + "path": "/breaker" + }, + { + "importpath": "github.com/eapache/go-xerial-snappy", + "repository": "https://github.com/eapache/go-xerial-snappy", + "revision": "bb955e01b9346ac19dc29eb16586c90ded99a98c", + "branch": "master" + }, + { + "importpath": "github.com/eapache/queue", + "repository": "https://github.com/eapache/queue", + "revision": "44cc805cf13205b55f69e14bcb69867d1ae92f98", + "branch": "master" + }, + { + "importpath": "github.com/golang/snappy", + "repository": "https://github.com/golang/snappy", + "revision": "7db9049039a047d955fe8c19b83c8ff5abd765c7", + "branch": "master" + }, + { + "importpath": "github.com/klauspost/crc32", + "repository": "https://github.com/klauspost/crc32", + "revision": "cb6bfca970f6908083f26f39a79009d608efd5cd", + "branch": "master" + }, + { + "importpath": "github.com/lib/pq", + "repository": "https://github.com/lib/pq", + "revision": "a6657b2386e9b8be76484c08711b02c7cf867ead", + "branch": "master" + }, + { + "importpath": "github.com/pierrec/lz4", + "repository": "https://github.com/pierrec/lz4", + "revision": "5c9560bfa9ace2bf86080bf40d46b34ae44604df", + "branch": "master" + }, + { + "importpath": "github.com/pierrec/xxHash/xxHash32", + "repository": "https://github.com/pierrec/xxHash", + "revision": "5a004441f897722c627870a981d02b29924215fa", + "branch": "master", + "path": "/xxHash32" + }, + { + "importpath": "github.com/rcrowley/go-metrics", + "repository": "https://github.com/rcrowley/go-metrics", + "revision": "1f30fe9094a513ce4c700b9a54458bbb0c96996c", + "branch": "master" + }, + { + "importpath": "gopkg.in/Shopify/sarama.v1", + "repository": "https://gopkg.in/Shopify/sarama.v1", + "revision": "0fb560e5f7fbcaee2f75e3c34174320709f69944", + "branch": "master" + } + ] +} \ No newline at end of file diff --git a/vendor/src/github.com/Shopify/sarama/CHANGELOG.md b/vendor/src/github.com/Shopify/sarama/CHANGELOG.md new file mode 100644 index 00000000..5fb51203 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/CHANGELOG.md @@ -0,0 +1,355 @@ +# Changelog + +#### Version 1.11.0 (2016-12-20) + +_Important:_ As of Sarama 1.11 it is necessary to set the config value of +`Producer.Return.Successes` to true in order to use the SyncProducer. Previous +versions would silently override this value when instantiating a SyncProducer +which led to unexpected values and data races. + +New Features: + - Metrics! Thanks to Sébastien Launay for all his work on this feature + ([#701](https://github.com/Shopify/sarama/pull/701), + [#746](https://github.com/Shopify/sarama/pull/746), + [#766](https://github.com/Shopify/sarama/pull/766)). + - Add support for LZ4 compression + ([#786](https://github.com/Shopify/sarama/pull/786)). + - Add support for ListOffsetRequest v1 and Kafka 0.10.1 + ([#775](https://github.com/Shopify/sarama/pull/775)). + - Added a `HighWaterMarks` method to the Consumer which aggregates the + `HighWaterMarkOffset` values of its child topic/partitions + ([#769](https://github.com/Shopify/sarama/pull/769)). + +Bug Fixes: + - Fixed producing when using timestamps, compression and Kafka 0.10 + ([#759](https://github.com/Shopify/sarama/pull/759)). + - Added missing decoder methods to DescribeGroups response + ([#756](https://github.com/Shopify/sarama/pull/756)). + - Fix producer shutdown when `Return.Errors` is disabled + ([#787](https://github.com/Shopify/sarama/pull/787)). + - Don't mutate configuration in SyncProducer + ([#790](https://github.com/Shopify/sarama/pull/790)). + - Fix crash on SASL initialization failure + ([#795](https://github.com/Shopify/sarama/pull/795)). + +#### Version 1.10.1 (2016-08-30) + +Bug Fixes: + - Fix the documentation for `HashPartitioner` which was incorrect + ([#717](https://github.com/Shopify/sarama/pull/717)). + - Permit client creation even when it is limited by ACLs + ([#722](https://github.com/Shopify/sarama/pull/722)). + - Several fixes to the consumer timer optimization code, regressions introduced + in v1.10.0. Go's timers are finicky + ([#730](https://github.com/Shopify/sarama/pull/730), + [#733](https://github.com/Shopify/sarama/pull/733), + [#734](https://github.com/Shopify/sarama/pull/734)). + - Handle consuming compressed relative offsets with Kafka 0.10 + ([#735](https://github.com/Shopify/sarama/pull/735)). + +#### Version 1.10.0 (2016-08-02) + +_Important:_ As of Sarama 1.10 it is necessary to tell Sarama the version of +Kafka you are running against (via the `config.Version` value) in order to use +features that may not be compatible with old Kafka versions. If you don't +specify this value it will default to 0.8.2 (the minimum supported), and trying +to use more recent features (like the offset manager) will fail with an error. + +_Also:_ The offset-manager's behaviour has been changed to match the upstream +java consumer (see [#705](https://github.com/Shopify/sarama/pull/705) and +[#713](https://github.com/Shopify/sarama/pull/713)). If you use the +offset-manager, please ensure that you are committing one *greater* than the +last consumed message offset or else you may end up consuming duplicate +messages. + +New Features: + - Support for Kafka 0.10 + ([#672](https://github.com/Shopify/sarama/pull/672), + [#678](https://github.com/Shopify/sarama/pull/678), + [#681](https://github.com/Shopify/sarama/pull/681), and others). + - Support for configuring the target Kafka version + ([#676](https://github.com/Shopify/sarama/pull/676)). + - Batch producing support in the SyncProducer + ([#677](https://github.com/Shopify/sarama/pull/677)). + - Extend producer mock to allow setting expectations on message contents + ([#667](https://github.com/Shopify/sarama/pull/667)). + +Improvements: + - Support `nil` compressed messages for deleting in compacted topics + ([#634](https://github.com/Shopify/sarama/pull/634)). + - Pre-allocate decoding errors, greatly reducing heap usage and GC time against + misbehaving brokers ([#690](https://github.com/Shopify/sarama/pull/690)). + - Re-use consumer expiry timers, removing one allocation per consumed message + ([#707](https://github.com/Shopify/sarama/pull/707)). + +Bug Fixes: + - Actually default the client ID to "sarama" like we say we do + ([#664](https://github.com/Shopify/sarama/pull/664)). + - Fix a rare issue where `Client.Leader` could return the wrong error + ([#685](https://github.com/Shopify/sarama/pull/685)). + - Fix a possible tight loop in the consumer + ([#693](https://github.com/Shopify/sarama/pull/693)). + - Match upstream's offset-tracking behaviour + ([#705](https://github.com/Shopify/sarama/pull/705)). + - Report UnknownTopicOrPartition errors from the offset manager + ([#706](https://github.com/Shopify/sarama/pull/706)). + - Fix possible negative partition value from the HashPartitioner + ([#709](https://github.com/Shopify/sarama/pull/709)). + +#### Version 1.9.0 (2016-05-16) + +New Features: + - Add support for custom offset manager retention durations + ([#602](https://github.com/Shopify/sarama/pull/602)). + - Publish low-level mocks to enable testing of third-party producer/consumer + implementations ([#570](https://github.com/Shopify/sarama/pull/570)). + - Declare support for Golang 1.6 + ([#611](https://github.com/Shopify/sarama/pull/611)). + - Support for SASL plain-text auth + ([#648](https://github.com/Shopify/sarama/pull/648)). + +Improvements: + - Simplified broker locking scheme slightly + ([#604](https://github.com/Shopify/sarama/pull/604)). + - Documentation cleanup + ([#605](https://github.com/Shopify/sarama/pull/605), + [#621](https://github.com/Shopify/sarama/pull/621), + [#654](https://github.com/Shopify/sarama/pull/654)). + +Bug Fixes: + - Fix race condition shutting down the OffsetManager + ([#658](https://github.com/Shopify/sarama/pull/658)). + +#### Version 1.8.0 (2016-02-01) + +New Features: + - Full support for Kafka 0.9: + - All protocol messages and fields + ([#586](https://github.com/Shopify/sarama/pull/586), + [#588](https://github.com/Shopify/sarama/pull/588), + [#590](https://github.com/Shopify/sarama/pull/590)). + - Verified that TLS support works + ([#581](https://github.com/Shopify/sarama/pull/581)). + - Fixed the OffsetManager compatibility + ([#585](https://github.com/Shopify/sarama/pull/585)). + +Improvements: + - Optimize for fewer system calls when reading from the network + ([#584](https://github.com/Shopify/sarama/pull/584)). + - Automatically retry `InvalidMessage` errors to match upstream behaviour + ([#589](https://github.com/Shopify/sarama/pull/589)). + +#### Version 1.7.0 (2015-12-11) + +New Features: + - Preliminary support for Kafka 0.9 + ([#572](https://github.com/Shopify/sarama/pull/572)). This comes with several + caveats: + - Protocol-layer support is mostly in place + ([#577](https://github.com/Shopify/sarama/pull/577)), however Kafka 0.9 + renamed some messages and fields, which we did not in order to preserve API + compatibility. + - The producer and consumer work against 0.9, but the offset manager does + not ([#573](https://github.com/Shopify/sarama/pull/573)). + - TLS support may or may not work + ([#581](https://github.com/Shopify/sarama/pull/581)). + +Improvements: + - Don't wait for request timeouts on dead brokers, greatly speeding recovery + when the TCP connection is left hanging + ([#548](https://github.com/Shopify/sarama/pull/548)). + - Refactored part of the producer. The new version provides a much more elegant + solution to [#449](https://github.com/Shopify/sarama/pull/449). It is also + slightly more efficient, and much more precise in calculating batch sizes + when compression is used + ([#549](https://github.com/Shopify/sarama/pull/549), + [#550](https://github.com/Shopify/sarama/pull/550), + [#551](https://github.com/Shopify/sarama/pull/551)). + +Bug Fixes: + - Fix race condition in consumer test mock + ([#553](https://github.com/Shopify/sarama/pull/553)). + +#### Version 1.6.1 (2015-09-25) + +Bug Fixes: + - Fix panic that could occur if a user-supplied message value failed to encode + ([#449](https://github.com/Shopify/sarama/pull/449)). + +#### Version 1.6.0 (2015-09-04) + +New Features: + - Implementation of a consumer offset manager using the APIs introduced in + Kafka 0.8.2. The API is designed mainly for integration into a future + high-level consumer, not for direct use, although it is *possible* to use it + directly. + ([#461](https://github.com/Shopify/sarama/pull/461)). + +Improvements: + - CRC32 calculation is much faster on machines with SSE4.2 instructions, + removing a major hotspot from most profiles + ([#255](https://github.com/Shopify/sarama/pull/255)). + +Bug Fixes: + - Make protocol decoding more robust against some malformed packets generated + by go-fuzz ([#523](https://github.com/Shopify/sarama/pull/523), + [#525](https://github.com/Shopify/sarama/pull/525)) or found in other ways + ([#528](https://github.com/Shopify/sarama/pull/528)). + - Fix a potential race condition panic in the consumer on shutdown + ([#529](https://github.com/Shopify/sarama/pull/529)). + +#### Version 1.5.0 (2015-08-17) + +New Features: + - TLS-encrypted network connections are now supported. This feature is subject + to change when Kafka releases built-in TLS support, but for now this is + enough to work with TLS-terminating proxies + ([#154](https://github.com/Shopify/sarama/pull/154)). + +Improvements: + - The consumer will not block if a single partition is not drained by the user; + all other partitions will continue to consume normally + ([#485](https://github.com/Shopify/sarama/pull/485)). + - Formatting of error strings has been much improved + ([#495](https://github.com/Shopify/sarama/pull/495)). + - Internal refactoring of the producer for code cleanliness and to enable + future work ([#300](https://github.com/Shopify/sarama/pull/300)). + +Bug Fixes: + - Fix a potential deadlock in the consumer on shutdown + ([#475](https://github.com/Shopify/sarama/pull/475)). + +#### Version 1.4.3 (2015-07-21) + +Bug Fixes: + - Don't include the partitioner in the producer's "fetch partitions" + circuit-breaker ([#466](https://github.com/Shopify/sarama/pull/466)). + - Don't retry messages until the broker is closed when abandoning a broker in + the producer ([#468](https://github.com/Shopify/sarama/pull/468)). + - Update the import path for snappy-go, it has moved again and the API has + changed slightly ([#486](https://github.com/Shopify/sarama/pull/486)). + +#### Version 1.4.2 (2015-05-27) + +Bug Fixes: + - Update the import path for snappy-go, it has moved from google code to github + ([#456](https://github.com/Shopify/sarama/pull/456)). + +#### Version 1.4.1 (2015-05-25) + +Improvements: + - Optimizations when decoding snappy messages, thanks to John Potocny + ([#446](https://github.com/Shopify/sarama/pull/446)). + +Bug Fixes: + - Fix hypothetical race conditions on producer shutdown + ([#450](https://github.com/Shopify/sarama/pull/450), + [#451](https://github.com/Shopify/sarama/pull/451)). + +#### Version 1.4.0 (2015-05-01) + +New Features: + - The consumer now implements `Topics()` and `Partitions()` methods to enable + users to dynamically choose what topics/partitions to consume without + instantiating a full client + ([#431](https://github.com/Shopify/sarama/pull/431)). + - The partition-consumer now exposes the high water mark offset value returned + by the broker via the `HighWaterMarkOffset()` method ([#339](https://github.com/Shopify/sarama/pull/339)). + - Added a `kafka-console-consumer` tool capable of handling multiple + partitions, and deprecated the now-obsolete `kafka-console-partitionConsumer` + ([#439](https://github.com/Shopify/sarama/pull/439), + [#442](https://github.com/Shopify/sarama/pull/442)). + +Improvements: + - The producer's logging during retry scenarios is more consistent, more + useful, and slightly less verbose + ([#429](https://github.com/Shopify/sarama/pull/429)). + - The client now shuffles its initial list of seed brokers in order to prevent + thundering herd on the first broker in the list + ([#441](https://github.com/Shopify/sarama/pull/441)). + +Bug Fixes: + - The producer now correctly manages its state if retries occur when it is + shutting down, fixing several instances of confusing behaviour and at least + one potential deadlock ([#419](https://github.com/Shopify/sarama/pull/419)). + - The consumer now handles messages for different partitions asynchronously, + making it much more resilient to specific user code ordering + ([#325](https://github.com/Shopify/sarama/pull/325)). + +#### Version 1.3.0 (2015-04-16) + +New Features: + - The client now tracks consumer group coordinators using + ConsumerMetadataRequests similar to how it tracks partition leadership using + regular MetadataRequests ([#411](https://github.com/Shopify/sarama/pull/411)). + This adds two methods to the client API: + - `Coordinator(consumerGroup string) (*Broker, error)` + - `RefreshCoordinator(consumerGroup string) error` + +Improvements: + - ConsumerMetadataResponses now automatically create a Broker object out of the + ID/address/port combination for the Coordinator; accessing the fields + individually has been deprecated + ([#413](https://github.com/Shopify/sarama/pull/413)). + - Much improved handling of `OffsetOutOfRange` errors in the consumer. + Consumers will fail to start if the provided offset is out of range + ([#418](https://github.com/Shopify/sarama/pull/418)) + and they will automatically shut down if the offset falls out of range + ([#424](https://github.com/Shopify/sarama/pull/424)). + - Small performance improvement in encoding and decoding protocol messages + ([#427](https://github.com/Shopify/sarama/pull/427)). + +Bug Fixes: + - Fix a rare race condition in the client's background metadata refresher if + it happens to be activated while the client is being closed + ([#422](https://github.com/Shopify/sarama/pull/422)). + +#### Version 1.2.0 (2015-04-07) + +Improvements: + - The producer's behaviour when `Flush.Frequency` is set is now more intuitive + ([#389](https://github.com/Shopify/sarama/pull/389)). + - The producer is now somewhat more memory-efficient during and after retrying + messages due to an improved queue implementation + ([#396](https://github.com/Shopify/sarama/pull/396)). + - The consumer produces much more useful logging output when leadership + changes ([#385](https://github.com/Shopify/sarama/pull/385)). + - The client's `GetOffset` method will now automatically refresh metadata and + retry once in the event of stale information or similar + ([#394](https://github.com/Shopify/sarama/pull/394)). + - Broker connections now have support for using TCP keepalives + ([#407](https://github.com/Shopify/sarama/issues/407)). + +Bug Fixes: + - The OffsetCommitRequest message now correctly implements all three possible + API versions ([#390](https://github.com/Shopify/sarama/pull/390), + [#400](https://github.com/Shopify/sarama/pull/400)). + +#### Version 1.1.0 (2015-03-20) + +Improvements: + - Wrap the producer's partitioner call in a circuit-breaker so that repeatedly + broken topics don't choke throughput + ([#373](https://github.com/Shopify/sarama/pull/373)). + +Bug Fixes: + - Fix the producer's internal reference counting in certain unusual scenarios + ([#367](https://github.com/Shopify/sarama/pull/367)). + - Fix the consumer's internal reference counting in certain unusual scenarios + ([#369](https://github.com/Shopify/sarama/pull/369)). + - Fix a condition where the producer's internal control messages could have + gotten stuck ([#368](https://github.com/Shopify/sarama/pull/368)). + - Fix an issue where invalid partition lists would be cached when asking for + metadata for a non-existant topic ([#372](https://github.com/Shopify/sarama/pull/372)). + + +#### Version 1.0.0 (2015-03-17) + +Version 1.0.0 is the first tagged version, and is almost a complete rewrite. The primary differences with previous untagged versions are: + +- The producer has been rewritten; there is now a `SyncProducer` with a blocking API, and an `AsyncProducer` that is non-blocking. +- The consumer has been rewritten to only open one connection per broker instead of one connection per partition. +- The main types of Sarama are now interfaces to make depedency injection easy; mock implementations for `Consumer`, `SyncProducer` and `AsyncProducer` are provided in the `github.com/Shopify/sarama/mocks` package. +- For most uses cases, it is no longer necessary to open a `Client`; this will be done for you. +- All the configuration values have been unified in the `Config` struct. +- Much improved test suite. diff --git a/vendor/src/github.com/Shopify/sarama/MIT-LICENSE b/vendor/src/github.com/Shopify/sarama/MIT-LICENSE new file mode 100644 index 00000000..8121b63b --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2013 Evan Huus + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/src/github.com/Shopify/sarama/Makefile b/vendor/src/github.com/Shopify/sarama/Makefile new file mode 100644 index 00000000..626b09a5 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/Makefile @@ -0,0 +1,21 @@ +default: fmt vet errcheck test + +test: + go test -v -timeout 60s -race ./... + +vet: + go vet ./... + +errcheck: + errcheck github.com/Shopify/sarama/... + +fmt: + @if [ -n "$$(go fmt ./...)" ]; then echo 'Please run go fmt on your code.' && exit 1; fi + +install_dependencies: install_errcheck get + +install_errcheck: + go get github.com/kisielk/errcheck + +get: + go get -t diff --git a/vendor/src/github.com/Shopify/sarama/README.md b/vendor/src/github.com/Shopify/sarama/README.md new file mode 100644 index 00000000..c2968b92 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/README.md @@ -0,0 +1,36 @@ +sarama +====== + +[![GoDoc](https://godoc.org/github.com/Shopify/sarama?status.png)](https://godoc.org/github.com/Shopify/sarama) +[![Build Status](https://travis-ci.org/Shopify/sarama.svg?branch=master)](https://travis-ci.org/Shopify/sarama) + +Sarama is an MIT-licensed Go client library for [Apache Kafka](https://kafka.apache.org/) version 0.8 (and later). + +### Getting started + +- API documentation and examples are available via [godoc](https://godoc.org/github.com/Shopify/sarama). +- Mocks for testing are available in the [mocks](./mocks) subpackage. +- The [examples](./examples) directory contains more elaborate example applications. +- The [tools](./tools) directory contains command line tools that can be useful for testing, diagnostics, and instrumentation. + +### Compatibility and API stability + +Sarama provides a "2 releases + 2 months" compatibility guarantee: we support +the two latest stable releases of Kafka and Go, and we provide a two month +grace period for older releases. This means we currently officially support +Go 1.7 and 1.6, and Kafka 0.10.0 and 0.9.0, although older releases are +still likely to work. + +Sarama follows semantic versioning and provides API stability via the gopkg.in service. +You can import a version with a guaranteed stable API via http://gopkg.in/Shopify/sarama.v1. +A changelog is available [here](CHANGELOG.md). + +### Contributing + +* Get started by checking our [contribution guidelines](https://github.com/Shopify/sarama/blob/master/CONTRIBUTING.md). +* Read the [Sarama wiki](https://github.com/Shopify/sarama/wiki) for more + technical and design details. +* The [Kafka Protocol Specification](https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol) + contains a wealth of useful information. +* For more general issues, there is [a google group](https://groups.google.com/forum/#!forum/kafka-clients) for Kafka client developers. +* If you have any questions, just ask! diff --git a/vendor/src/github.com/Shopify/sarama/Vagrantfile b/vendor/src/github.com/Shopify/sarama/Vagrantfile new file mode 100644 index 00000000..f4b848a3 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/Vagrantfile @@ -0,0 +1,20 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +# We have 5 * 192MB ZK processes and 5 * 320MB Kafka processes => 2560MB +MEMORY = 3072 + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.box = "ubuntu/trusty64" + + config.vm.provision :shell, path: "vagrant/provision.sh" + + config.vm.network "private_network", ip: "192.168.100.67" + + config.vm.provider "virtualbox" do |v| + v.memory = MEMORY + end +end diff --git a/vendor/src/github.com/Shopify/sarama/api_versions_request.go b/vendor/src/github.com/Shopify/sarama/api_versions_request.go new file mode 100644 index 00000000..ab65f01c --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/api_versions_request.go @@ -0,0 +1,24 @@ +package sarama + +type ApiVersionsRequest struct { +} + +func (r *ApiVersionsRequest) encode(pe packetEncoder) error { + return nil +} + +func (r *ApiVersionsRequest) decode(pd packetDecoder, version int16) (err error) { + return nil +} + +func (r *ApiVersionsRequest) key() int16 { + return 18 +} + +func (r *ApiVersionsRequest) version() int16 { + return 0 +} + +func (r *ApiVersionsRequest) requiredVersion() KafkaVersion { + return V0_10_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/api_versions_request_test.go b/vendor/src/github.com/Shopify/sarama/api_versions_request_test.go new file mode 100644 index 00000000..5ab4fa71 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/api_versions_request_test.go @@ -0,0 +1,14 @@ +package sarama + +import "testing" + +var ( + apiVersionRequest = []byte{} +) + +func TestApiVersionsRequest(t *testing.T) { + var request *ApiVersionsRequest + + request = new(ApiVersionsRequest) + testRequest(t, "basic", request, apiVersionRequest) +} diff --git a/vendor/src/github.com/Shopify/sarama/api_versions_response.go b/vendor/src/github.com/Shopify/sarama/api_versions_response.go new file mode 100644 index 00000000..16d62db2 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/api_versions_response.go @@ -0,0 +1,86 @@ +package sarama + +type ApiVersionsResponseBlock struct { + ApiKey int16 + MinVersion int16 + MaxVersion int16 +} + +func (b *ApiVersionsResponseBlock) encode(pe packetEncoder) error { + pe.putInt16(b.ApiKey) + pe.putInt16(b.MinVersion) + pe.putInt16(b.MaxVersion) + return nil +} + +func (b *ApiVersionsResponseBlock) decode(pd packetDecoder) error { + var err error + + if b.ApiKey, err = pd.getInt16(); err != nil { + return err + } + + if b.MinVersion, err = pd.getInt16(); err != nil { + return err + } + + if b.MaxVersion, err = pd.getInt16(); err != nil { + return err + } + + return nil +} + +type ApiVersionsResponse struct { + Err KError + ApiVersions []*ApiVersionsResponseBlock +} + +func (r *ApiVersionsResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + if err := pe.putArrayLength(len(r.ApiVersions)); err != nil { + return err + } + for _, apiVersion := range r.ApiVersions { + if err := apiVersion.encode(pe); err != nil { + return err + } + } + return nil +} + +func (r *ApiVersionsResponse) decode(pd packetDecoder, version int16) error { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + numBlocks, err := pd.getArrayLength() + if err != nil { + return err + } + + r.ApiVersions = make([]*ApiVersionsResponseBlock, numBlocks) + for i := 0; i < numBlocks; i++ { + block := new(ApiVersionsResponseBlock) + if err := block.decode(pd); err != nil { + return err + } + r.ApiVersions[i] = block + } + + return nil +} + +func (r *ApiVersionsResponse) key() int16 { + return 18 +} + +func (r *ApiVersionsResponse) version() int16 { + return 0 +} + +func (r *ApiVersionsResponse) requiredVersion() KafkaVersion { + return V0_10_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/api_versions_response_test.go b/vendor/src/github.com/Shopify/sarama/api_versions_response_test.go new file mode 100644 index 00000000..675a65a7 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/api_versions_response_test.go @@ -0,0 +1,32 @@ +package sarama + +import "testing" + +var ( + apiVersionResponse = []byte{ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x03, + 0x00, 0x02, + 0x00, 0x01, + } +) + +func TestApiVersionsResponse(t *testing.T) { + var response *ApiVersionsResponse + + response = new(ApiVersionsResponse) + testVersionDecodable(t, "no error", response, apiVersionResponse, 0) + if response.Err != ErrNoError { + t.Error("Decoding error failed: no error expected but found", response.Err) + } + if response.ApiVersions[0].ApiKey != 0x03 { + t.Error("Decoding error: expected 0x03 but got", response.ApiVersions[0].ApiKey) + } + if response.ApiVersions[0].MinVersion != 0x02 { + t.Error("Decoding error: expected 0x02 but got", response.ApiVersions[0].MinVersion) + } + if response.ApiVersions[0].MaxVersion != 0x01 { + t.Error("Decoding error: expected 0x01 but got", response.ApiVersions[0].MaxVersion) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/async_producer.go b/vendor/src/github.com/Shopify/sarama/async_producer.go new file mode 100644 index 00000000..3af47fdd --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/async_producer.go @@ -0,0 +1,905 @@ +package sarama + +import ( + "fmt" + "sync" + "time" + + "github.com/eapache/go-resiliency/breaker" + "github.com/eapache/queue" +) + +// AsyncProducer publishes Kafka messages using a non-blocking API. It routes messages +// to the correct broker for the provided topic-partition, refreshing metadata as appropriate, +// and parses responses for errors. You must read from the Errors() channel or the +// producer will deadlock. You must call Close() or AsyncClose() on a producer to avoid +// leaks: it will not be garbage-collected automatically when it passes out of +// scope. +type AsyncProducer interface { + + // AsyncClose triggers a shutdown of the producer, flushing any messages it may + // have buffered. The shutdown has completed when both the Errors and Successes + // channels have been closed. When calling AsyncClose, you *must* continue to + // read from those channels in order to drain the results of any messages in + // flight. + AsyncClose() + + // Close shuts down the producer and flushes any messages it may have buffered. + // You must call this function before a producer object passes out of scope, as + // it may otherwise leak memory. You must call this before calling Close on the + // underlying client. + Close() error + + // Input is the input channel for the user to write messages to that they + // wish to send. + Input() chan<- *ProducerMessage + + // Successes is the success output channel back to the user when AckSuccesses is + // enabled. If Return.Successes is true, you MUST read from this channel or the + // Producer will deadlock. It is suggested that you send and read messages + // together in a single select statement. + Successes() <-chan *ProducerMessage + + // Errors is the error output channel back to the user. You MUST read from this + // channel or the Producer will deadlock when the channel is full. Alternatively, + // you can set Producer.Return.Errors in your config to false, which prevents + // errors to be returned. + Errors() <-chan *ProducerError +} + +type asyncProducer struct { + client Client + conf *Config + ownClient bool + + errors chan *ProducerError + input, successes, retries chan *ProducerMessage + inFlight sync.WaitGroup + + brokers map[*Broker]chan<- *ProducerMessage + brokerRefs map[chan<- *ProducerMessage]int + brokerLock sync.Mutex +} + +// NewAsyncProducer creates a new AsyncProducer using the given broker addresses and configuration. +func NewAsyncProducer(addrs []string, conf *Config) (AsyncProducer, error) { + client, err := NewClient(addrs, conf) + if err != nil { + return nil, err + } + + p, err := NewAsyncProducerFromClient(client) + if err != nil { + return nil, err + } + p.(*asyncProducer).ownClient = true + return p, nil +} + +// NewAsyncProducerFromClient creates a new Producer using the given client. It is still +// necessary to call Close() on the underlying client when shutting down this producer. +func NewAsyncProducerFromClient(client Client) (AsyncProducer, error) { + // Check that we are not dealing with a closed Client before processing any other arguments + if client.Closed() { + return nil, ErrClosedClient + } + + p := &asyncProducer{ + client: client, + conf: client.Config(), + errors: make(chan *ProducerError), + input: make(chan *ProducerMessage), + successes: make(chan *ProducerMessage), + retries: make(chan *ProducerMessage), + brokers: make(map[*Broker]chan<- *ProducerMessage), + brokerRefs: make(map[chan<- *ProducerMessage]int), + } + + // launch our singleton dispatchers + go withRecover(p.dispatcher) + go withRecover(p.retryHandler) + + return p, nil +} + +type flagSet int8 + +const ( + syn flagSet = 1 << iota // first message from partitionProducer to brokerProducer + fin // final message from partitionProducer to brokerProducer and back + shutdown // start the shutdown process +) + +// ProducerMessage is the collection of elements passed to the Producer in order to send a message. +type ProducerMessage struct { + Topic string // The Kafka topic for this message. + // The partitioning key for this message. Pre-existing Encoders include + // StringEncoder and ByteEncoder. + Key Encoder + // The actual message to store in Kafka. Pre-existing Encoders include + // StringEncoder and ByteEncoder. + Value Encoder + + // This field is used to hold arbitrary data you wish to include so it + // will be available when receiving on the Successes and Errors channels. + // Sarama completely ignores this field and is only to be used for + // pass-through data. + Metadata interface{} + + // Below this point are filled in by the producer as the message is processed + + // Offset is the offset of the message stored on the broker. This is only + // guaranteed to be defined if the message was successfully delivered and + // RequiredAcks is not NoResponse. + Offset int64 + // Partition is the partition that the message was sent to. This is only + // guaranteed to be defined if the message was successfully delivered. + Partition int32 + // Timestamp is the timestamp assigned to the message by the broker. This + // is only guaranteed to be defined if the message was successfully + // delivered, RequiredAcks is not NoResponse, and the Kafka broker is at + // least version 0.10.0. + Timestamp time.Time + + retries int + flags flagSet +} + +const producerMessageOverhead = 26 // the metadata overhead of CRC, flags, etc. + +func (m *ProducerMessage) byteSize() int { + size := producerMessageOverhead + if m.Key != nil { + size += m.Key.Length() + } + if m.Value != nil { + size += m.Value.Length() + } + return size +} + +func (m *ProducerMessage) clear() { + m.flags = 0 + m.retries = 0 +} + +// ProducerError is the type of error generated when the producer fails to deliver a message. +// It contains the original ProducerMessage as well as the actual error value. +type ProducerError struct { + Msg *ProducerMessage + Err error +} + +func (pe ProducerError) Error() string { + return fmt.Sprintf("kafka: Failed to produce message to topic %s: %s", pe.Msg.Topic, pe.Err) +} + +// ProducerErrors is a type that wraps a batch of "ProducerError"s and implements the Error interface. +// It can be returned from the Producer's Close method to avoid the need to manually drain the Errors channel +// when closing a producer. +type ProducerErrors []*ProducerError + +func (pe ProducerErrors) Error() string { + return fmt.Sprintf("kafka: Failed to deliver %d messages.", len(pe)) +} + +func (p *asyncProducer) Errors() <-chan *ProducerError { + return p.errors +} + +func (p *asyncProducer) Successes() <-chan *ProducerMessage { + return p.successes +} + +func (p *asyncProducer) Input() chan<- *ProducerMessage { + return p.input +} + +func (p *asyncProducer) Close() error { + p.AsyncClose() + + if p.conf.Producer.Return.Successes { + go withRecover(func() { + for _ = range p.successes { + } + }) + } + + var errors ProducerErrors + if p.conf.Producer.Return.Errors { + for event := range p.errors { + errors = append(errors, event) + } + } else { + <-p.errors + } + + if len(errors) > 0 { + return errors + } + return nil +} + +func (p *asyncProducer) AsyncClose() { + go withRecover(p.shutdown) +} + +// singleton +// dispatches messages by topic +func (p *asyncProducer) dispatcher() { + handlers := make(map[string]chan<- *ProducerMessage) + shuttingDown := false + + for msg := range p.input { + if msg == nil { + Logger.Println("Something tried to send a nil message, it was ignored.") + continue + } + + if msg.flags&shutdown != 0 { + shuttingDown = true + p.inFlight.Done() + continue + } else if msg.retries == 0 { + if shuttingDown { + // we can't just call returnError here because that decrements the wait group, + // which hasn't been incremented yet for this message, and shouldn't be + pErr := &ProducerError{Msg: msg, Err: ErrShuttingDown} + if p.conf.Producer.Return.Errors { + p.errors <- pErr + } else { + Logger.Println(pErr) + } + continue + } + p.inFlight.Add(1) + } + + if msg.byteSize() > p.conf.Producer.MaxMessageBytes { + p.returnError(msg, ErrMessageSizeTooLarge) + continue + } + + handler := handlers[msg.Topic] + if handler == nil { + handler = p.newTopicProducer(msg.Topic) + handlers[msg.Topic] = handler + } + + handler <- msg + } + + for _, handler := range handlers { + close(handler) + } +} + +// one per topic +// partitions messages, then dispatches them by partition +type topicProducer struct { + parent *asyncProducer + topic string + input <-chan *ProducerMessage + + breaker *breaker.Breaker + handlers map[int32]chan<- *ProducerMessage + partitioner Partitioner +} + +func (p *asyncProducer) newTopicProducer(topic string) chan<- *ProducerMessage { + input := make(chan *ProducerMessage, p.conf.ChannelBufferSize) + tp := &topicProducer{ + parent: p, + topic: topic, + input: input, + breaker: breaker.New(3, 1, 10*time.Second), + handlers: make(map[int32]chan<- *ProducerMessage), + partitioner: p.conf.Producer.Partitioner(topic), + } + go withRecover(tp.dispatch) + return input +} + +func (tp *topicProducer) dispatch() { + for msg := range tp.input { + if msg.retries == 0 { + if err := tp.partitionMessage(msg); err != nil { + tp.parent.returnError(msg, err) + continue + } + } + + handler := tp.handlers[msg.Partition] + if handler == nil { + handler = tp.parent.newPartitionProducer(msg.Topic, msg.Partition) + tp.handlers[msg.Partition] = handler + } + + handler <- msg + } + + for _, handler := range tp.handlers { + close(handler) + } +} + +func (tp *topicProducer) partitionMessage(msg *ProducerMessage) error { + var partitions []int32 + + err := tp.breaker.Run(func() (err error) { + if tp.partitioner.RequiresConsistency() { + partitions, err = tp.parent.client.Partitions(msg.Topic) + } else { + partitions, err = tp.parent.client.WritablePartitions(msg.Topic) + } + return + }) + + if err != nil { + return err + } + + numPartitions := int32(len(partitions)) + + if numPartitions == 0 { + return ErrLeaderNotAvailable + } + + choice, err := tp.partitioner.Partition(msg, numPartitions) + + if err != nil { + return err + } else if choice < 0 || choice >= numPartitions { + return ErrInvalidPartition + } + + msg.Partition = partitions[choice] + + return nil +} + +// one per partition per topic +// dispatches messages to the appropriate broker +// also responsible for maintaining message order during retries +type partitionProducer struct { + parent *asyncProducer + topic string + partition int32 + input <-chan *ProducerMessage + + leader *Broker + breaker *breaker.Breaker + output chan<- *ProducerMessage + + // highWatermark tracks the "current" retry level, which is the only one where we actually let messages through, + // all other messages get buffered in retryState[msg.retries].buf to preserve ordering + // retryState[msg.retries].expectChaser simply tracks whether we've seen a fin message for a given level (and + // therefore whether our buffer is complete and safe to flush) + highWatermark int + retryState []partitionRetryState +} + +type partitionRetryState struct { + buf []*ProducerMessage + expectChaser bool +} + +func (p *asyncProducer) newPartitionProducer(topic string, partition int32) chan<- *ProducerMessage { + input := make(chan *ProducerMessage, p.conf.ChannelBufferSize) + pp := &partitionProducer{ + parent: p, + topic: topic, + partition: partition, + input: input, + + breaker: breaker.New(3, 1, 10*time.Second), + retryState: make([]partitionRetryState, p.conf.Producer.Retry.Max+1), + } + go withRecover(pp.dispatch) + return input +} + +func (pp *partitionProducer) dispatch() { + // try to prefetch the leader; if this doesn't work, we'll do a proper call to `updateLeader` + // on the first message + pp.leader, _ = pp.parent.client.Leader(pp.topic, pp.partition) + if pp.leader != nil { + pp.output = pp.parent.getBrokerProducer(pp.leader) + pp.parent.inFlight.Add(1) // we're generating a syn message; track it so we don't shut down while it's still inflight + pp.output <- &ProducerMessage{Topic: pp.topic, Partition: pp.partition, flags: syn} + } + + for msg := range pp.input { + if msg.retries > pp.highWatermark { + // a new, higher, retry level; handle it and then back off + pp.newHighWatermark(msg.retries) + time.Sleep(pp.parent.conf.Producer.Retry.Backoff) + } else if pp.highWatermark > 0 { + // we are retrying something (else highWatermark would be 0) but this message is not a *new* retry level + if msg.retries < pp.highWatermark { + // in fact this message is not even the current retry level, so buffer it for now (unless it's a just a fin) + if msg.flags&fin == fin { + pp.retryState[msg.retries].expectChaser = false + pp.parent.inFlight.Done() // this fin is now handled and will be garbage collected + } else { + pp.retryState[msg.retries].buf = append(pp.retryState[msg.retries].buf, msg) + } + continue + } else if msg.flags&fin == fin { + // this message is of the current retry level (msg.retries == highWatermark) and the fin flag is set, + // meaning this retry level is done and we can go down (at least) one level and flush that + pp.retryState[pp.highWatermark].expectChaser = false + pp.flushRetryBuffers() + pp.parent.inFlight.Done() // this fin is now handled and will be garbage collected + continue + } + } + + // if we made it this far then the current msg contains real data, and can be sent to the next goroutine + // without breaking any of our ordering guarantees + + if pp.output == nil { + if err := pp.updateLeader(); err != nil { + pp.parent.returnError(msg, err) + time.Sleep(pp.parent.conf.Producer.Retry.Backoff) + continue + } + Logger.Printf("producer/leader/%s/%d selected broker %d\n", pp.topic, pp.partition, pp.leader.ID()) + } + + pp.output <- msg + } + + if pp.output != nil { + pp.parent.unrefBrokerProducer(pp.leader, pp.output) + } +} + +func (pp *partitionProducer) newHighWatermark(hwm int) { + Logger.Printf("producer/leader/%s/%d state change to [retrying-%d]\n", pp.topic, pp.partition, hwm) + pp.highWatermark = hwm + + // send off a fin so that we know when everything "in between" has made it + // back to us and we can safely flush the backlog (otherwise we risk re-ordering messages) + pp.retryState[pp.highWatermark].expectChaser = true + pp.parent.inFlight.Add(1) // we're generating a fin message; track it so we don't shut down while it's still inflight + pp.output <- &ProducerMessage{Topic: pp.topic, Partition: pp.partition, flags: fin, retries: pp.highWatermark - 1} + + // a new HWM means that our current broker selection is out of date + Logger.Printf("producer/leader/%s/%d abandoning broker %d\n", pp.topic, pp.partition, pp.leader.ID()) + pp.parent.unrefBrokerProducer(pp.leader, pp.output) + pp.output = nil +} + +func (pp *partitionProducer) flushRetryBuffers() { + Logger.Printf("producer/leader/%s/%d state change to [flushing-%d]\n", pp.topic, pp.partition, pp.highWatermark) + for { + pp.highWatermark-- + + if pp.output == nil { + if err := pp.updateLeader(); err != nil { + pp.parent.returnErrors(pp.retryState[pp.highWatermark].buf, err) + goto flushDone + } + Logger.Printf("producer/leader/%s/%d selected broker %d\n", pp.topic, pp.partition, pp.leader.ID()) + } + + for _, msg := range pp.retryState[pp.highWatermark].buf { + pp.output <- msg + } + + flushDone: + pp.retryState[pp.highWatermark].buf = nil + if pp.retryState[pp.highWatermark].expectChaser { + Logger.Printf("producer/leader/%s/%d state change to [retrying-%d]\n", pp.topic, pp.partition, pp.highWatermark) + break + } else if pp.highWatermark == 0 { + Logger.Printf("producer/leader/%s/%d state change to [normal]\n", pp.topic, pp.partition) + break + } + } +} + +func (pp *partitionProducer) updateLeader() error { + return pp.breaker.Run(func() (err error) { + if err = pp.parent.client.RefreshMetadata(pp.topic); err != nil { + return err + } + + if pp.leader, err = pp.parent.client.Leader(pp.topic, pp.partition); err != nil { + return err + } + + pp.output = pp.parent.getBrokerProducer(pp.leader) + pp.parent.inFlight.Add(1) // we're generating a syn message; track it so we don't shut down while it's still inflight + pp.output <- &ProducerMessage{Topic: pp.topic, Partition: pp.partition, flags: syn} + + return nil + }) +} + +// one per broker; also constructs an associated flusher +func (p *asyncProducer) newBrokerProducer(broker *Broker) chan<- *ProducerMessage { + var ( + input = make(chan *ProducerMessage) + bridge = make(chan *produceSet) + responses = make(chan *brokerProducerResponse) + ) + + bp := &brokerProducer{ + parent: p, + broker: broker, + input: input, + output: bridge, + responses: responses, + buffer: newProduceSet(p), + currentRetries: make(map[string]map[int32]error), + } + go withRecover(bp.run) + + // minimal bridge to make the network response `select`able + go withRecover(func() { + for set := range bridge { + request := set.buildRequest() + + response, err := broker.Produce(request) + + responses <- &brokerProducerResponse{ + set: set, + err: err, + res: response, + } + } + close(responses) + }) + + return input +} + +type brokerProducerResponse struct { + set *produceSet + err error + res *ProduceResponse +} + +// groups messages together into appropriately-sized batches for sending to the broker +// handles state related to retries etc +type brokerProducer struct { + parent *asyncProducer + broker *Broker + + input <-chan *ProducerMessage + output chan<- *produceSet + responses <-chan *brokerProducerResponse + + buffer *produceSet + timer <-chan time.Time + timerFired bool + + closing error + currentRetries map[string]map[int32]error +} + +func (bp *brokerProducer) run() { + var output chan<- *produceSet + Logger.Printf("producer/broker/%d starting up\n", bp.broker.ID()) + + for { + select { + case msg := <-bp.input: + if msg == nil { + bp.shutdown() + return + } + + if msg.flags&syn == syn { + Logger.Printf("producer/broker/%d state change to [open] on %s/%d\n", + bp.broker.ID(), msg.Topic, msg.Partition) + if bp.currentRetries[msg.Topic] == nil { + bp.currentRetries[msg.Topic] = make(map[int32]error) + } + bp.currentRetries[msg.Topic][msg.Partition] = nil + bp.parent.inFlight.Done() + continue + } + + if reason := bp.needsRetry(msg); reason != nil { + bp.parent.retryMessage(msg, reason) + + if bp.closing == nil && msg.flags&fin == fin { + // we were retrying this partition but we can start processing again + delete(bp.currentRetries[msg.Topic], msg.Partition) + Logger.Printf("producer/broker/%d state change to [closed] on %s/%d\n", + bp.broker.ID(), msg.Topic, msg.Partition) + } + + continue + } + + if bp.buffer.wouldOverflow(msg) { + if err := bp.waitForSpace(msg); err != nil { + bp.parent.retryMessage(msg, err) + continue + } + } + + if err := bp.buffer.add(msg); err != nil { + bp.parent.returnError(msg, err) + continue + } + + if bp.parent.conf.Producer.Flush.Frequency > 0 && bp.timer == nil { + bp.timer = time.After(bp.parent.conf.Producer.Flush.Frequency) + } + case <-bp.timer: + bp.timerFired = true + case output <- bp.buffer: + bp.rollOver() + case response := <-bp.responses: + bp.handleResponse(response) + } + + if bp.timerFired || bp.buffer.readyToFlush() { + output = bp.output + } else { + output = nil + } + } +} + +func (bp *brokerProducer) shutdown() { + for !bp.buffer.empty() { + select { + case response := <-bp.responses: + bp.handleResponse(response) + case bp.output <- bp.buffer: + bp.rollOver() + } + } + close(bp.output) + for response := range bp.responses { + bp.handleResponse(response) + } + + Logger.Printf("producer/broker/%d shut down\n", bp.broker.ID()) +} + +func (bp *brokerProducer) needsRetry(msg *ProducerMessage) error { + if bp.closing != nil { + return bp.closing + } + + return bp.currentRetries[msg.Topic][msg.Partition] +} + +func (bp *brokerProducer) waitForSpace(msg *ProducerMessage) error { + Logger.Printf("producer/broker/%d maximum request accumulated, waiting for space\n", bp.broker.ID()) + + for { + select { + case response := <-bp.responses: + bp.handleResponse(response) + // handling a response can change our state, so re-check some things + if reason := bp.needsRetry(msg); reason != nil { + return reason + } else if !bp.buffer.wouldOverflow(msg) { + return nil + } + case bp.output <- bp.buffer: + bp.rollOver() + return nil + } + } +} + +func (bp *brokerProducer) rollOver() { + bp.timer = nil + bp.timerFired = false + bp.buffer = newProduceSet(bp.parent) +} + +func (bp *brokerProducer) handleResponse(response *brokerProducerResponse) { + if response.err != nil { + bp.handleError(response.set, response.err) + } else { + bp.handleSuccess(response.set, response.res) + } + + if bp.buffer.empty() { + bp.rollOver() // this can happen if the response invalidated our buffer + } +} + +func (bp *brokerProducer) handleSuccess(sent *produceSet, response *ProduceResponse) { + // we iterate through the blocks in the request set, not the response, so that we notice + // if the response is missing a block completely + sent.eachPartition(func(topic string, partition int32, msgs []*ProducerMessage) { + if response == nil { + // this only happens when RequiredAcks is NoResponse, so we have to assume success + bp.parent.returnSuccesses(msgs) + return + } + + block := response.GetBlock(topic, partition) + if block == nil { + bp.parent.returnErrors(msgs, ErrIncompleteResponse) + return + } + + switch block.Err { + // Success + case ErrNoError: + if bp.parent.conf.Version.IsAtLeast(V0_10_0_0) && !block.Timestamp.IsZero() { + for _, msg := range msgs { + msg.Timestamp = block.Timestamp + } + } + for i, msg := range msgs { + msg.Offset = block.Offset + int64(i) + } + bp.parent.returnSuccesses(msgs) + // Retriable errors + case ErrInvalidMessage, ErrUnknownTopicOrPartition, ErrLeaderNotAvailable, ErrNotLeaderForPartition, + ErrRequestTimedOut, ErrNotEnoughReplicas, ErrNotEnoughReplicasAfterAppend: + Logger.Printf("producer/broker/%d state change to [retrying] on %s/%d because %v\n", + bp.broker.ID(), topic, partition, block.Err) + bp.currentRetries[topic][partition] = block.Err + bp.parent.retryMessages(msgs, block.Err) + bp.parent.retryMessages(bp.buffer.dropPartition(topic, partition), block.Err) + // Other non-retriable errors + default: + bp.parent.returnErrors(msgs, block.Err) + } + }) +} + +func (bp *brokerProducer) handleError(sent *produceSet, err error) { + switch err.(type) { + case PacketEncodingError: + sent.eachPartition(func(topic string, partition int32, msgs []*ProducerMessage) { + bp.parent.returnErrors(msgs, err) + }) + default: + Logger.Printf("producer/broker/%d state change to [closing] because %s\n", bp.broker.ID(), err) + bp.parent.abandonBrokerConnection(bp.broker) + _ = bp.broker.Close() + bp.closing = err + sent.eachPartition(func(topic string, partition int32, msgs []*ProducerMessage) { + bp.parent.retryMessages(msgs, err) + }) + bp.buffer.eachPartition(func(topic string, partition int32, msgs []*ProducerMessage) { + bp.parent.retryMessages(msgs, err) + }) + bp.rollOver() + } +} + +// singleton +// effectively a "bridge" between the flushers and the dispatcher in order to avoid deadlock +// based on https://godoc.org/github.com/eapache/channels#InfiniteChannel +func (p *asyncProducer) retryHandler() { + var msg *ProducerMessage + buf := queue.New() + + for { + if buf.Length() == 0 { + msg = <-p.retries + } else { + select { + case msg = <-p.retries: + case p.input <- buf.Peek().(*ProducerMessage): + buf.Remove() + continue + } + } + + if msg == nil { + return + } + + buf.Add(msg) + } +} + +// utility functions + +func (p *asyncProducer) shutdown() { + Logger.Println("Producer shutting down.") + p.inFlight.Add(1) + p.input <- &ProducerMessage{flags: shutdown} + + p.inFlight.Wait() + + if p.ownClient { + err := p.client.Close() + if err != nil { + Logger.Println("producer/shutdown failed to close the embedded client:", err) + } + } + + close(p.input) + close(p.retries) + close(p.errors) + close(p.successes) +} + +func (p *asyncProducer) returnError(msg *ProducerMessage, err error) { + msg.clear() + pErr := &ProducerError{Msg: msg, Err: err} + if p.conf.Producer.Return.Errors { + p.errors <- pErr + } else { + Logger.Println(pErr) + } + p.inFlight.Done() +} + +func (p *asyncProducer) returnErrors(batch []*ProducerMessage, err error) { + for _, msg := range batch { + p.returnError(msg, err) + } +} + +func (p *asyncProducer) returnSuccesses(batch []*ProducerMessage) { + for _, msg := range batch { + if p.conf.Producer.Return.Successes { + msg.clear() + p.successes <- msg + } + p.inFlight.Done() + } +} + +func (p *asyncProducer) retryMessage(msg *ProducerMessage, err error) { + if msg.retries >= p.conf.Producer.Retry.Max { + p.returnError(msg, err) + } else { + msg.retries++ + p.retries <- msg + } +} + +func (p *asyncProducer) retryMessages(batch []*ProducerMessage, err error) { + for _, msg := range batch { + p.retryMessage(msg, err) + } +} + +func (p *asyncProducer) getBrokerProducer(broker *Broker) chan<- *ProducerMessage { + p.brokerLock.Lock() + defer p.brokerLock.Unlock() + + bp := p.brokers[broker] + + if bp == nil { + bp = p.newBrokerProducer(broker) + p.brokers[broker] = bp + p.brokerRefs[bp] = 0 + } + + p.brokerRefs[bp]++ + + return bp +} + +func (p *asyncProducer) unrefBrokerProducer(broker *Broker, bp chan<- *ProducerMessage) { + p.brokerLock.Lock() + defer p.brokerLock.Unlock() + + p.brokerRefs[bp]-- + if p.brokerRefs[bp] == 0 { + close(bp) + delete(p.brokerRefs, bp) + + if p.brokers[broker] == bp { + delete(p.brokers, broker) + } + } +} + +func (p *asyncProducer) abandonBrokerConnection(broker *Broker) { + p.brokerLock.Lock() + defer p.brokerLock.Unlock() + + delete(p.brokers, broker) +} diff --git a/vendor/src/github.com/Shopify/sarama/async_producer_test.go b/vendor/src/github.com/Shopify/sarama/async_producer_test.go new file mode 100644 index 00000000..13af1202 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/async_producer_test.go @@ -0,0 +1,841 @@ +package sarama + +import ( + "errors" + "log" + "os" + "os/signal" + "sync" + "testing" + "time" +) + +const TestMessage = "ABC THE MESSAGE" + +func closeProducer(t *testing.T, p AsyncProducer) { + var wg sync.WaitGroup + p.AsyncClose() + + wg.Add(2) + go func() { + for _ = range p.Successes() { + t.Error("Unexpected message on Successes()") + } + wg.Done() + }() + go func() { + for msg := range p.Errors() { + t.Error(msg.Err) + } + wg.Done() + }() + wg.Wait() +} + +func expectResults(t *testing.T, p AsyncProducer, successes, errors int) { + expect := successes + errors + for expect > 0 { + select { + case msg := <-p.Errors(): + if msg.Msg.flags != 0 { + t.Error("Message had flags set") + } + errors-- + expect-- + if errors < 0 { + t.Error(msg.Err) + } + case msg := <-p.Successes(): + if msg.flags != 0 { + t.Error("Message had flags set") + } + successes-- + expect-- + if successes < 0 { + t.Error("Too many successes") + } + } + } + if successes != 0 || errors != 0 { + t.Error("Unexpected successes", successes, "or errors", errors) + } +} + +type testPartitioner chan *int32 + +func (p testPartitioner) Partition(msg *ProducerMessage, numPartitions int32) (int32, error) { + part := <-p + if part == nil { + return 0, errors.New("BOOM") + } + + return *part, nil +} + +func (p testPartitioner) RequiresConsistency() bool { + return true +} + +func (p testPartitioner) feed(partition int32) { + p <- &partition +} + +type flakyEncoder bool + +func (f flakyEncoder) Length() int { + return len(TestMessage) +} + +func (f flakyEncoder) Encode() ([]byte, error) { + if !bool(f) { + return nil, errors.New("flaky encoding error") + } + return []byte(TestMessage), nil +} + +func TestAsyncProducer(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage), Metadata: i} + } + for i := 0; i < 10; i++ { + select { + case msg := <-producer.Errors(): + t.Error(msg.Err) + if msg.Msg.flags != 0 { + t.Error("Message had flags set") + } + case msg := <-producer.Successes(): + if msg.flags != 0 { + t.Error("Message had flags set") + } + if msg.Metadata.(int) != i { + t.Error("Message metadata did not match") + } + } + } + + closeProducer(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestAsyncProducerMultipleFlushes(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + leader.Returns(prodSuccess) + leader.Returns(prodSuccess) + + config := NewConfig() + config.Producer.Flush.Messages = 5 + config.Producer.Return.Successes = true + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for flush := 0; flush < 3; flush++ { + for i := 0; i < 5; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + expectResults(t, producer, 5, 0) + } + + closeProducer(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestAsyncProducerMultipleBrokers(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader0 := NewMockBroker(t, 2) + leader1 := NewMockBroker(t, 3) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader0.Addr(), leader0.BrokerID()) + metadataResponse.AddBroker(leader1.Addr(), leader1.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader0.BrokerID(), nil, nil, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 1, leader1.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodResponse0 := new(ProduceResponse) + prodResponse0.AddTopicPartition("my_topic", 0, ErrNoError) + leader0.Returns(prodResponse0) + + prodResponse1 := new(ProduceResponse) + prodResponse1.AddTopicPartition("my_topic", 1, ErrNoError) + leader1.Returns(prodResponse1) + + config := NewConfig() + config.Producer.Flush.Messages = 5 + config.Producer.Return.Successes = true + config.Producer.Partitioner = NewRoundRobinPartitioner + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + expectResults(t, producer, 10, 0) + + closeProducer(t, producer) + leader1.Close() + leader0.Close() + seedBroker.Close() +} + +func TestAsyncProducerCustomPartitioner(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodResponse := new(ProduceResponse) + prodResponse.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodResponse) + + config := NewConfig() + config.Producer.Flush.Messages = 2 + config.Producer.Return.Successes = true + config.Producer.Partitioner = func(topic string) Partitioner { + p := make(testPartitioner) + go func() { + p.feed(0) + p <- nil + p <- nil + p <- nil + p.feed(0) + }() + return p + } + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 5; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + expectResults(t, producer, 2, 3) + + closeProducer(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestAsyncProducerFailureRetry(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader1 := NewMockBroker(t, 2) + leader2 := NewMockBroker(t, 3) + + metadataLeader1 := new(MetadataResponse) + metadataLeader1.AddBroker(leader1.Addr(), leader1.BrokerID()) + metadataLeader1.AddTopicPartition("my_topic", 0, leader1.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader1) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + seedBroker.Close() + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + prodNotLeader := new(ProduceResponse) + prodNotLeader.AddTopicPartition("my_topic", 0, ErrNotLeaderForPartition) + leader1.Returns(prodNotLeader) + + metadataLeader2 := new(MetadataResponse) + metadataLeader2.AddBroker(leader2.Addr(), leader2.BrokerID()) + metadataLeader2.AddTopicPartition("my_topic", 0, leader2.BrokerID(), nil, nil, ErrNoError) + leader1.Returns(metadataLeader2) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader2.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + leader1.Close() + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + leader2.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + + leader2.Close() + closeProducer(t, producer) +} + +func TestAsyncProducerEncoderFailures(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + leader.Returns(prodSuccess) + leader.Returns(prodSuccess) + + config := NewConfig() + config.Producer.Flush.Messages = 1 + config.Producer.Return.Successes = true + config.Producer.Partitioner = NewManualPartitioner + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for flush := 0; flush < 3; flush++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: flakyEncoder(true), Value: flakyEncoder(false)} + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: flakyEncoder(false), Value: flakyEncoder(true)} + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: flakyEncoder(true), Value: flakyEncoder(true)} + expectResults(t, producer, 1, 2) + } + + closeProducer(t, producer) + leader.Close() + seedBroker.Close() +} + +// If a Kafka broker becomes unavailable and then returns back in service, then +// producer reconnects to it and continues sending messages. +func TestAsyncProducerBrokerBounce(t *testing.T) { + // Given + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + leaderAddr := leader.Addr() + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leaderAddr, leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + + config := NewConfig() + config.Producer.Flush.Messages = 1 + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + leader.Returns(prodSuccess) + expectResults(t, producer, 1, 0) + + // When: a broker connection gets reset by a broker (network glitch, restart, you name it). + leader.Close() // producer should get EOF + leader = NewMockBrokerAddr(t, 2, leaderAddr) // start it up again right away for giggles + seedBroker.Returns(metadataResponse) // tell it to go to broker 2 again + + // Then: a produced message goes through the new broker connection. + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + leader.Returns(prodSuccess) + expectResults(t, producer, 1, 0) + + closeProducer(t, producer) + seedBroker.Close() + leader.Close() +} + +func TestAsyncProducerBrokerBounceWithStaleMetadata(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader1 := NewMockBroker(t, 2) + leader2 := NewMockBroker(t, 3) + + metadataLeader1 := new(MetadataResponse) + metadataLeader1.AddBroker(leader1.Addr(), leader1.BrokerID()) + metadataLeader1.AddTopicPartition("my_topic", 0, leader1.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader1) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + config.Producer.Retry.Max = 3 + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + leader1.Close() // producer should get EOF + seedBroker.Returns(metadataLeader1) // tell it to go to leader1 again even though it's still down + seedBroker.Returns(metadataLeader1) // tell it to go to leader1 again even though it's still down + + // ok fine, tell it to go to leader2 finally + metadataLeader2 := new(MetadataResponse) + metadataLeader2.AddBroker(leader2.Addr(), leader2.BrokerID()) + metadataLeader2.AddTopicPartition("my_topic", 0, leader2.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader2) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader2.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + seedBroker.Close() + leader2.Close() + + closeProducer(t, producer) +} + +func TestAsyncProducerMultipleRetries(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader1 := NewMockBroker(t, 2) + leader2 := NewMockBroker(t, 3) + + metadataLeader1 := new(MetadataResponse) + metadataLeader1.AddBroker(leader1.Addr(), leader1.BrokerID()) + metadataLeader1.AddTopicPartition("my_topic", 0, leader1.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader1) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + config.Producer.Retry.Max = 4 + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + prodNotLeader := new(ProduceResponse) + prodNotLeader.AddTopicPartition("my_topic", 0, ErrNotLeaderForPartition) + leader1.Returns(prodNotLeader) + + metadataLeader2 := new(MetadataResponse) + metadataLeader2.AddBroker(leader2.Addr(), leader2.BrokerID()) + metadataLeader2.AddTopicPartition("my_topic", 0, leader2.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader2) + leader2.Returns(prodNotLeader) + seedBroker.Returns(metadataLeader1) + leader1.Returns(prodNotLeader) + seedBroker.Returns(metadataLeader1) + leader1.Returns(prodNotLeader) + seedBroker.Returns(metadataLeader2) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader2.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + leader2.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + + seedBroker.Close() + leader1.Close() + leader2.Close() + closeProducer(t, producer) +} + +func TestAsyncProducerOutOfRetries(t *testing.T) { + t.Skip("Enable once bug #294 is fixed.") + + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + config.Producer.Retry.Max = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + + prodNotLeader := new(ProduceResponse) + prodNotLeader.AddTopicPartition("my_topic", 0, ErrNotLeaderForPartition) + leader.Returns(prodNotLeader) + + for i := 0; i < 10; i++ { + select { + case msg := <-producer.Errors(): + if msg.Err != ErrNotLeaderForPartition { + t.Error(msg.Err) + } + case <-producer.Successes(): + t.Error("Unexpected success") + } + } + + seedBroker.Returns(metadataResponse) + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + + expectResults(t, producer, 10, 0) + + leader.Close() + seedBroker.Close() + safeClose(t, producer) +} + +func TestAsyncProducerRetryWithReferenceOpen(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + leaderAddr := leader.Addr() + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leaderAddr, leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 1, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + config.Producer.Retry.Max = 1 + config.Producer.Partitioner = NewRoundRobinPartitioner + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + // prime partition 0 + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + expectResults(t, producer, 1, 0) + + // prime partition 1 + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + prodSuccess = new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 1, ErrNoError) + leader.Returns(prodSuccess) + expectResults(t, producer, 1, 0) + + // reboot the broker (the producer will get EOF on its existing connection) + leader.Close() + leader = NewMockBrokerAddr(t, 2, leaderAddr) + + // send another message on partition 0 to trigger the EOF and retry + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + + // tell partition 0 to go to that broker again + seedBroker.Returns(metadataResponse) + + // succeed this time + prodSuccess = new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + expectResults(t, producer, 1, 0) + + // shutdown + closeProducer(t, producer) + seedBroker.Close() + leader.Close() +} + +func TestAsyncProducerFlusherRetryCondition(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 1, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Producer.Flush.Messages = 5 + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + config.Producer.Retry.Max = 1 + config.Producer.Partitioner = NewManualPartitioner + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + // prime partitions + for p := int32(0); p < 2; p++ { + for i := 0; i < 5; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage), Partition: p} + } + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", p, ErrNoError) + leader.Returns(prodSuccess) + expectResults(t, producer, 5, 0) + } + + // send more messages on partition 0 + for i := 0; i < 5; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage), Partition: 0} + } + prodNotLeader := new(ProduceResponse) + prodNotLeader.AddTopicPartition("my_topic", 0, ErrNotLeaderForPartition) + leader.Returns(prodNotLeader) + + time.Sleep(50 * time.Millisecond) + + leader.SetHandlerByMap(map[string]MockResponse{ + "ProduceRequest": NewMockProduceResponse(t). + SetError("my_topic", 0, ErrNoError), + }) + + // tell partition 0 to go to that broker again + seedBroker.Returns(metadataResponse) + + // succeed this time + expectResults(t, producer, 5, 0) + + // put five more through + for i := 0; i < 5; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage), Partition: 0} + } + expectResults(t, producer, 5, 0) + + // shutdown + closeProducer(t, producer) + seedBroker.Close() + leader.Close() +} + +func TestAsyncProducerRetryShutdown(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataLeader := new(MetadataResponse) + metadataLeader.AddBroker(leader.Addr(), leader.BrokerID()) + metadataLeader.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + producer.AsyncClose() + time.Sleep(5 * time.Millisecond) // let the shutdown goroutine kick in + + producer.Input() <- &ProducerMessage{Topic: "FOO"} + if err := <-producer.Errors(); err.Err != ErrShuttingDown { + t.Error(err) + } + + prodNotLeader := new(ProduceResponse) + prodNotLeader.AddTopicPartition("my_topic", 0, ErrNotLeaderForPartition) + leader.Returns(prodNotLeader) + + seedBroker.Returns(metadataLeader) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + + seedBroker.Close() + leader.Close() + + // wait for the async-closed producer to shut down fully + for err := range producer.Errors() { + t.Error(err) + } +} + +func TestAsyncProducerNoReturns(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataLeader := new(MetadataResponse) + metadataLeader.AddBroker(leader.Addr(), leader.BrokerID()) + metadataLeader.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = false + config.Producer.Return.Errors = false + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + + wait := make(chan bool) + go func() { + if err := producer.Close(); err != nil { + t.Error(err) + } + close(wait) + }() + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + + <-wait + seedBroker.Close() + leader.Close() +} + +// This example shows how to use the producer while simultaneously +// reading the Errors channel to know about any failures. +func ExampleAsyncProducer_select() { + producer, err := NewAsyncProducer([]string{"localhost:9092"}, nil) + if err != nil { + panic(err) + } + + defer func() { + if err := producer.Close(); err != nil { + log.Fatalln(err) + } + }() + + // Trap SIGINT to trigger a shutdown. + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Interrupt) + + var enqueued, errors int +ProducerLoop: + for { + select { + case producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder("testing 123")}: + enqueued++ + case err := <-producer.Errors(): + log.Println("Failed to produce message", err) + errors++ + case <-signals: + break ProducerLoop + } + } + + log.Printf("Enqueued: %d; errors: %d\n", enqueued, errors) +} + +// This example shows how to use the producer with separate goroutines +// reading from the Successes and Errors channels. Note that in order +// for the Successes channel to be populated, you have to set +// config.Producer.Return.Successes to true. +func ExampleAsyncProducer_goroutines() { + config := NewConfig() + config.Producer.Return.Successes = true + producer, err := NewAsyncProducer([]string{"localhost:9092"}, config) + if err != nil { + panic(err) + } + + // Trap SIGINT to trigger a graceful shutdown. + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Interrupt) + + var ( + wg sync.WaitGroup + enqueued, successes, errors int + ) + + wg.Add(1) + go func() { + defer wg.Done() + for _ = range producer.Successes() { + successes++ + } + }() + + wg.Add(1) + go func() { + defer wg.Done() + for err := range producer.Errors() { + log.Println(err) + errors++ + } + }() + +ProducerLoop: + for { + message := &ProducerMessage{Topic: "my_topic", Value: StringEncoder("testing 123")} + select { + case producer.Input() <- message: + enqueued++ + + case <-signals: + producer.AsyncClose() // Trigger a shutdown of the producer. + break ProducerLoop + } + } + + wg.Wait() + + log.Printf("Successfully produced: %d; errors: %d\n", successes, errors) +} diff --git a/vendor/src/github.com/Shopify/sarama/broker.go b/vendor/src/github.com/Shopify/sarama/broker.go new file mode 100644 index 00000000..89beecc8 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/broker.go @@ -0,0 +1,674 @@ +package sarama + +import ( + "crypto/tls" + "encoding/binary" + "fmt" + "io" + "net" + "strconv" + "sync" + "sync/atomic" + "time" + + "github.com/rcrowley/go-metrics" +) + +// Broker represents a single Kafka broker connection. All operations on this object are entirely concurrency-safe. +type Broker struct { + id int32 + addr string + + conf *Config + correlationID int32 + conn net.Conn + connErr error + lock sync.Mutex + opened int32 + + responses chan responsePromise + done chan bool + + incomingByteRate metrics.Meter + requestRate metrics.Meter + requestSize metrics.Histogram + requestLatency metrics.Histogram + outgoingByteRate metrics.Meter + responseRate metrics.Meter + responseSize metrics.Histogram + brokerIncomingByteRate metrics.Meter + brokerRequestRate metrics.Meter + brokerRequestSize metrics.Histogram + brokerRequestLatency metrics.Histogram + brokerOutgoingByteRate metrics.Meter + brokerResponseRate metrics.Meter + brokerResponseSize metrics.Histogram +} + +type responsePromise struct { + requestTime time.Time + correlationID int32 + packets chan []byte + errors chan error +} + +// NewBroker creates and returns a Broker targetting the given host:port address. +// This does not attempt to actually connect, you have to call Open() for that. +func NewBroker(addr string) *Broker { + return &Broker{id: -1, addr: addr} +} + +// Open tries to connect to the Broker if it is not already connected or connecting, but does not block +// waiting for the connection to complete. This means that any subsequent operations on the broker will +// block waiting for the connection to succeed or fail. To get the effect of a fully synchronous Open call, +// follow it by a call to Connected(). The only errors Open will return directly are ConfigurationError or +// AlreadyConnected. If conf is nil, the result of NewConfig() is used. +func (b *Broker) Open(conf *Config) error { + if !atomic.CompareAndSwapInt32(&b.opened, 0, 1) { + return ErrAlreadyConnected + } + + if conf == nil { + conf = NewConfig() + } + + err := conf.Validate() + if err != nil { + return err + } + + b.lock.Lock() + + go withRecover(func() { + defer b.lock.Unlock() + + dialer := net.Dialer{ + Timeout: conf.Net.DialTimeout, + KeepAlive: conf.Net.KeepAlive, + } + + if conf.Net.TLS.Enable { + b.conn, b.connErr = tls.DialWithDialer(&dialer, "tcp", b.addr, conf.Net.TLS.Config) + } else { + b.conn, b.connErr = dialer.Dial("tcp", b.addr) + } + if b.connErr != nil { + Logger.Printf("Failed to connect to broker %s: %s\n", b.addr, b.connErr) + b.conn = nil + atomic.StoreInt32(&b.opened, 0) + return + } + b.conn = newBufConn(b.conn) + + b.conf = conf + + // Create or reuse the global metrics shared between brokers + b.incomingByteRate = metrics.GetOrRegisterMeter("incoming-byte-rate", conf.MetricRegistry) + b.requestRate = metrics.GetOrRegisterMeter("request-rate", conf.MetricRegistry) + b.requestSize = getOrRegisterHistogram("request-size", conf.MetricRegistry) + b.requestLatency = getOrRegisterHistogram("request-latency-in-ms", conf.MetricRegistry) + b.outgoingByteRate = metrics.GetOrRegisterMeter("outgoing-byte-rate", conf.MetricRegistry) + b.responseRate = metrics.GetOrRegisterMeter("response-rate", conf.MetricRegistry) + b.responseSize = getOrRegisterHistogram("response-size", conf.MetricRegistry) + // Do not gather metrics for seeded broker (only used during bootstrap) because they share + // the same id (-1) and are already exposed through the global metrics above + if b.id >= 0 { + b.brokerIncomingByteRate = getOrRegisterBrokerMeter("incoming-byte-rate", b, conf.MetricRegistry) + b.brokerRequestRate = getOrRegisterBrokerMeter("request-rate", b, conf.MetricRegistry) + b.brokerRequestSize = getOrRegisterBrokerHistogram("request-size", b, conf.MetricRegistry) + b.brokerRequestLatency = getOrRegisterBrokerHistogram("request-latency-in-ms", b, conf.MetricRegistry) + b.brokerOutgoingByteRate = getOrRegisterBrokerMeter("outgoing-byte-rate", b, conf.MetricRegistry) + b.brokerResponseRate = getOrRegisterBrokerMeter("response-rate", b, conf.MetricRegistry) + b.brokerResponseSize = getOrRegisterBrokerHistogram("response-size", b, conf.MetricRegistry) + } + + if conf.Net.SASL.Enable { + b.connErr = b.sendAndReceiveSASLPlainAuth() + if b.connErr != nil { + err = b.conn.Close() + if err == nil { + Logger.Printf("Closed connection to broker %s\n", b.addr) + } else { + Logger.Printf("Error while closing connection to broker %s: %s\n", b.addr, err) + } + b.conn = nil + atomic.StoreInt32(&b.opened, 0) + return + } + } + + b.done = make(chan bool) + b.responses = make(chan responsePromise, b.conf.Net.MaxOpenRequests-1) + + if b.id >= 0 { + Logger.Printf("Connected to broker at %s (registered as #%d)\n", b.addr, b.id) + } else { + Logger.Printf("Connected to broker at %s (unregistered)\n", b.addr) + } + go withRecover(b.responseReceiver) + }) + + return nil +} + +// Connected returns true if the broker is connected and false otherwise. If the broker is not +// connected but it had tried to connect, the error from that connection attempt is also returned. +func (b *Broker) Connected() (bool, error) { + b.lock.Lock() + defer b.lock.Unlock() + + return b.conn != nil, b.connErr +} + +func (b *Broker) Close() error { + b.lock.Lock() + defer b.lock.Unlock() + + if b.conn == nil { + return ErrNotConnected + } + + close(b.responses) + <-b.done + + err := b.conn.Close() + + b.conn = nil + b.connErr = nil + b.done = nil + b.responses = nil + + if err == nil { + Logger.Printf("Closed connection to broker %s\n", b.addr) + } else { + Logger.Printf("Error while closing connection to broker %s: %s\n", b.addr, err) + } + + atomic.StoreInt32(&b.opened, 0) + + return err +} + +// ID returns the broker ID retrieved from Kafka's metadata, or -1 if that is not known. +func (b *Broker) ID() int32 { + return b.id +} + +// Addr returns the broker address as either retrieved from Kafka's metadata or passed to NewBroker. +func (b *Broker) Addr() string { + return b.addr +} + +func (b *Broker) GetMetadata(request *MetadataRequest) (*MetadataResponse, error) { + response := new(MetadataResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) GetConsumerMetadata(request *ConsumerMetadataRequest) (*ConsumerMetadataResponse, error) { + response := new(ConsumerMetadataResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) GetAvailableOffsets(request *OffsetRequest) (*OffsetResponse, error) { + response := new(OffsetResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) Produce(request *ProduceRequest) (*ProduceResponse, error) { + var response *ProduceResponse + var err error + + if request.RequiredAcks == NoResponse { + err = b.sendAndReceive(request, nil) + } else { + response = new(ProduceResponse) + err = b.sendAndReceive(request, response) + } + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) Fetch(request *FetchRequest) (*FetchResponse, error) { + response := new(FetchResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) CommitOffset(request *OffsetCommitRequest) (*OffsetCommitResponse, error) { + response := new(OffsetCommitResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) FetchOffset(request *OffsetFetchRequest) (*OffsetFetchResponse, error) { + response := new(OffsetFetchResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) JoinGroup(request *JoinGroupRequest) (*JoinGroupResponse, error) { + response := new(JoinGroupResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) SyncGroup(request *SyncGroupRequest) (*SyncGroupResponse, error) { + response := new(SyncGroupResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) LeaveGroup(request *LeaveGroupRequest) (*LeaveGroupResponse, error) { + response := new(LeaveGroupResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) Heartbeat(request *HeartbeatRequest) (*HeartbeatResponse, error) { + response := new(HeartbeatResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) ListGroups(request *ListGroupsRequest) (*ListGroupsResponse, error) { + response := new(ListGroupsResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) DescribeGroups(request *DescribeGroupsRequest) (*DescribeGroupsResponse, error) { + response := new(DescribeGroupsResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) send(rb protocolBody, promiseResponse bool) (*responsePromise, error) { + b.lock.Lock() + defer b.lock.Unlock() + + if b.conn == nil { + if b.connErr != nil { + return nil, b.connErr + } + return nil, ErrNotConnected + } + + if !b.conf.Version.IsAtLeast(rb.requiredVersion()) { + return nil, ErrUnsupportedVersion + } + + req := &request{correlationID: b.correlationID, clientID: b.conf.ClientID, body: rb} + buf, err := encode(req, b.conf.MetricRegistry) + if err != nil { + return nil, err + } + + err = b.conn.SetWriteDeadline(time.Now().Add(b.conf.Net.WriteTimeout)) + if err != nil { + return nil, err + } + + requestTime := time.Now() + bytes, err := b.conn.Write(buf) + b.updateOutgoingCommunicationMetrics(bytes) + if err != nil { + return nil, err + } + b.correlationID++ + + if !promiseResponse { + // Record request latency without the response + b.updateRequestLatencyMetrics(time.Since(requestTime)) + return nil, nil + } + + promise := responsePromise{requestTime, req.correlationID, make(chan []byte), make(chan error)} + b.responses <- promise + + return &promise, nil +} + +func (b *Broker) sendAndReceive(req protocolBody, res versionedDecoder) error { + promise, err := b.send(req, res != nil) + + if err != nil { + return err + } + + if promise == nil { + return nil + } + + select { + case buf := <-promise.packets: + return versionedDecode(buf, res, req.version()) + case err = <-promise.errors: + return err + } +} + +func (b *Broker) decode(pd packetDecoder) (err error) { + b.id, err = pd.getInt32() + if err != nil { + return err + } + + host, err := pd.getString() + if err != nil { + return err + } + + port, err := pd.getInt32() + if err != nil { + return err + } + + b.addr = net.JoinHostPort(host, fmt.Sprint(port)) + if _, _, err := net.SplitHostPort(b.addr); err != nil { + return err + } + + return nil +} + +func (b *Broker) encode(pe packetEncoder) (err error) { + + host, portstr, err := net.SplitHostPort(b.addr) + if err != nil { + return err + } + port, err := strconv.Atoi(portstr) + if err != nil { + return err + } + + pe.putInt32(b.id) + + err = pe.putString(host) + if err != nil { + return err + } + + pe.putInt32(int32(port)) + + return nil +} + +func (b *Broker) responseReceiver() { + var dead error + header := make([]byte, 8) + for response := range b.responses { + if dead != nil { + response.errors <- dead + continue + } + + err := b.conn.SetReadDeadline(time.Now().Add(b.conf.Net.ReadTimeout)) + if err != nil { + dead = err + response.errors <- err + continue + } + + bytesReadHeader, err := io.ReadFull(b.conn, header) + requestLatency := time.Since(response.requestTime) + if err != nil { + b.updateIncomingCommunicationMetrics(bytesReadHeader, requestLatency) + dead = err + response.errors <- err + continue + } + + decodedHeader := responseHeader{} + err = decode(header, &decodedHeader) + if err != nil { + b.updateIncomingCommunicationMetrics(bytesReadHeader, requestLatency) + dead = err + response.errors <- err + continue + } + if decodedHeader.correlationID != response.correlationID { + b.updateIncomingCommunicationMetrics(bytesReadHeader, requestLatency) + // TODO if decoded ID < cur ID, discard until we catch up + // TODO if decoded ID > cur ID, save it so when cur ID catches up we have a response + dead = PacketDecodingError{fmt.Sprintf("correlation ID didn't match, wanted %d, got %d", response.correlationID, decodedHeader.correlationID)} + response.errors <- dead + continue + } + + buf := make([]byte, decodedHeader.length-4) + bytesReadBody, err := io.ReadFull(b.conn, buf) + b.updateIncomingCommunicationMetrics(bytesReadHeader+bytesReadBody, requestLatency) + if err != nil { + dead = err + response.errors <- err + continue + } + + response.packets <- buf + } + close(b.done) +} + +func (b *Broker) sendAndReceiveSASLPlainHandshake() error { + rb := &SaslHandshakeRequest{"PLAIN"} + req := &request{correlationID: b.correlationID, clientID: b.conf.ClientID, body: rb} + buf, err := encode(req, b.conf.MetricRegistry) + if err != nil { + return err + } + + err = b.conn.SetWriteDeadline(time.Now().Add(b.conf.Net.WriteTimeout)) + if err != nil { + return err + } + + requestTime := time.Now() + bytes, err := b.conn.Write(buf) + b.updateOutgoingCommunicationMetrics(bytes) + if err != nil { + Logger.Printf("Failed to send SASL handshake %s: %s\n", b.addr, err.Error()) + return err + } + b.correlationID++ + //wait for the response + header := make([]byte, 8) // response header + _, err = io.ReadFull(b.conn, header) + if err != nil { + Logger.Printf("Failed to read SASL handshake header : %s\n", err.Error()) + return err + } + length := binary.BigEndian.Uint32(header[:4]) + payload := make([]byte, length-4) + n, err := io.ReadFull(b.conn, payload) + if err != nil { + Logger.Printf("Failed to read SASL handshake payload : %s\n", err.Error()) + return err + } + b.updateIncomingCommunicationMetrics(n+8, time.Since(requestTime)) + res := &SaslHandshakeResponse{} + err = versionedDecode(payload, res, 0) + if err != nil { + Logger.Printf("Failed to parse SASL handshake : %s\n", err.Error()) + return err + } + if res.Err != ErrNoError { + Logger.Printf("Invalid SASL Mechanism : %s\n", res.Err.Error()) + return res.Err + } + Logger.Print("Successful SASL handshake") + return nil +} + +// Kafka 0.10.0 plans to support SASL Plain and Kerberos as per PR #812 (KIP-43)/(JIRA KAFKA-3149) +// Some hosted kafka services such as IBM Message Hub already offer SASL/PLAIN auth with Kafka 0.9 +// +// In SASL Plain, Kafka expects the auth header to be in the following format +// Message format (from https://tools.ietf.org/html/rfc4616): +// +// message = [authzid] UTF8NUL authcid UTF8NUL passwd +// authcid = 1*SAFE ; MUST accept up to 255 octets +// authzid = 1*SAFE ; MUST accept up to 255 octets +// passwd = 1*SAFE ; MUST accept up to 255 octets +// UTF8NUL = %x00 ; UTF-8 encoded NUL character +// +// SAFE = UTF1 / UTF2 / UTF3 / UTF4 +// ;; any UTF-8 encoded Unicode character except NUL +// +// When credentials are valid, Kafka returns a 4 byte array of null characters. +// When credentials are invalid, Kafka closes the connection. This does not seem to be the ideal way +// of responding to bad credentials but thats how its being done today. +func (b *Broker) sendAndReceiveSASLPlainAuth() error { + if b.conf.Net.SASL.Handshake { + handshakeErr := b.sendAndReceiveSASLPlainHandshake() + if handshakeErr != nil { + Logger.Printf("Error while performing SASL handshake %s\n", b.addr) + return handshakeErr + } + } + length := 1 + len(b.conf.Net.SASL.User) + 1 + len(b.conf.Net.SASL.Password) + authBytes := make([]byte, length+4) //4 byte length header + auth data + binary.BigEndian.PutUint32(authBytes, uint32(length)) + copy(authBytes[4:], []byte("\x00"+b.conf.Net.SASL.User+"\x00"+b.conf.Net.SASL.Password)) + + err := b.conn.SetWriteDeadline(time.Now().Add(b.conf.Net.WriteTimeout)) + if err != nil { + Logger.Printf("Failed to set write deadline when doing SASL auth with broker %s: %s\n", b.addr, err.Error()) + return err + } + + requestTime := time.Now() + bytesWritten, err := b.conn.Write(authBytes) + b.updateOutgoingCommunicationMetrics(bytesWritten) + if err != nil { + Logger.Printf("Failed to write SASL auth header to broker %s: %s\n", b.addr, err.Error()) + return err + } + + header := make([]byte, 4) + n, err := io.ReadFull(b.conn, header) + b.updateIncomingCommunicationMetrics(n, time.Since(requestTime)) + // If the credentials are valid, we would get a 4 byte response filled with null characters. + // Otherwise, the broker closes the connection and we get an EOF + if err != nil { + Logger.Printf("Failed to read response while authenticating with SASL to broker %s: %s\n", b.addr, err.Error()) + return err + } + + Logger.Printf("SASL authentication successful with broker %s:%v - %v\n", b.addr, n, header) + return nil +} + +func (b *Broker) updateIncomingCommunicationMetrics(bytes int, requestLatency time.Duration) { + b.updateRequestLatencyMetrics(requestLatency) + b.responseRate.Mark(1) + if b.brokerResponseRate != nil { + b.brokerResponseRate.Mark(1) + } + responseSize := int64(bytes) + b.incomingByteRate.Mark(responseSize) + if b.brokerIncomingByteRate != nil { + b.brokerIncomingByteRate.Mark(responseSize) + } + b.responseSize.Update(responseSize) + if b.brokerResponseSize != nil { + b.brokerResponseSize.Update(responseSize) + } +} + +func (b *Broker) updateRequestLatencyMetrics(requestLatency time.Duration) { + requestLatencyInMs := int64(requestLatency / time.Millisecond) + b.requestLatency.Update(requestLatencyInMs) + if b.brokerRequestLatency != nil { + b.brokerRequestLatency.Update(requestLatencyInMs) + } +} + +func (b *Broker) updateOutgoingCommunicationMetrics(bytes int) { + b.requestRate.Mark(1) + if b.brokerRequestRate != nil { + b.brokerRequestRate.Mark(1) + } + requestSize := int64(bytes) + b.outgoingByteRate.Mark(requestSize) + if b.brokerOutgoingByteRate != nil { + b.brokerOutgoingByteRate.Mark(requestSize) + } + b.requestSize.Update(requestSize) + if b.brokerRequestSize != nil { + b.brokerRequestSize.Update(requestSize) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/broker_test.go b/vendor/src/github.com/Shopify/sarama/broker_test.go new file mode 100644 index 00000000..5adb46f1 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/broker_test.go @@ -0,0 +1,315 @@ +package sarama + +import ( + "fmt" + "testing" + "time" +) + +func ExampleBroker() { + broker := NewBroker("localhost:9092") + err := broker.Open(nil) + if err != nil { + panic(err) + } + + request := MetadataRequest{Topics: []string{"myTopic"}} + response, err := broker.GetMetadata(&request) + if err != nil { + _ = broker.Close() + panic(err) + } + + fmt.Println("There are", len(response.Topics), "topics active in the cluster.") + + if err = broker.Close(); err != nil { + panic(err) + } +} + +type mockEncoder struct { + bytes []byte +} + +func (m mockEncoder) encode(pe packetEncoder) error { + return pe.putRawBytes(m.bytes) +} + +type brokerMetrics struct { + bytesRead int + bytesWritten int +} + +func TestBrokerAccessors(t *testing.T) { + broker := NewBroker("abc:123") + + if broker.ID() != -1 { + t.Error("New broker didn't have an ID of -1.") + } + + if broker.Addr() != "abc:123" { + t.Error("New broker didn't have the correct address") + } + + broker.id = 34 + if broker.ID() != 34 { + t.Error("Manually setting broker ID did not take effect.") + } +} + +func TestSimpleBrokerCommunication(t *testing.T) { + for _, tt := range brokerTestTable { + Logger.Printf("Testing broker communication for %s", tt.name) + mb := NewMockBroker(t, 0) + mb.Returns(&mockEncoder{tt.response}) + pendingNotify := make(chan brokerMetrics) + // Register a callback to be notified about successful requests + mb.SetNotifier(func(bytesRead, bytesWritten int) { + pendingNotify <- brokerMetrics{bytesRead, bytesWritten} + }) + broker := NewBroker(mb.Addr()) + // Set the broker id in order to validate local broker metrics + broker.id = 0 + conf := NewConfig() + conf.Version = V0_10_0_0 + err := broker.Open(conf) + if err != nil { + t.Fatal(err) + } + tt.runner(t, broker) + err = broker.Close() + if err != nil { + t.Error(err) + } + // Wait up to 500 ms for the remote broker to process the request and + // notify us about the metrics + timeout := 500 * time.Millisecond + select { + case mockBrokerMetrics := <-pendingNotify: + validateBrokerMetrics(t, broker, mockBrokerMetrics) + case <-time.After(timeout): + t.Errorf("No request received for: %s after waiting for %v", tt.name, timeout) + } + mb.Close() + } + +} + +// We're not testing encoding/decoding here, so most of the requests/responses will be empty for simplicity's sake +var brokerTestTable = []struct { + name string + response []byte + runner func(*testing.T, *Broker) +}{ + {"MetadataRequest", + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := MetadataRequest{} + response, err := broker.GetMetadata(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Metadata request got no response!") + } + }}, + + {"ConsumerMetadataRequest", + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 't', 0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := ConsumerMetadataRequest{} + response, err := broker.GetConsumerMetadata(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Consumer Metadata request got no response!") + } + }}, + + {"ProduceRequest (NoResponse)", + []byte{}, + func(t *testing.T, broker *Broker) { + request := ProduceRequest{} + request.RequiredAcks = NoResponse + response, err := broker.Produce(&request) + if err != nil { + t.Error(err) + } + if response != nil { + t.Error("Produce request with NoResponse got a response!") + } + }}, + + {"ProduceRequest (WaitForLocal)", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := ProduceRequest{} + request.RequiredAcks = WaitForLocal + response, err := broker.Produce(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Produce request without NoResponse got no response!") + } + }}, + + {"FetchRequest", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := FetchRequest{} + response, err := broker.Fetch(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Fetch request got no response!") + } + }}, + + {"OffsetFetchRequest", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := OffsetFetchRequest{} + response, err := broker.FetchOffset(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("OffsetFetch request got no response!") + } + }}, + + {"OffsetCommitRequest", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := OffsetCommitRequest{} + response, err := broker.CommitOffset(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("OffsetCommit request got no response!") + } + }}, + + {"OffsetRequest", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := OffsetRequest{} + response, err := broker.GetAvailableOffsets(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Offset request got no response!") + } + }}, + + {"JoinGroupRequest", + []byte{0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := JoinGroupRequest{} + response, err := broker.JoinGroup(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("JoinGroup request got no response!") + } + }}, + + {"SyncGroupRequest", + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := SyncGroupRequest{} + response, err := broker.SyncGroup(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("SyncGroup request got no response!") + } + }}, + + {"LeaveGroupRequest", + []byte{0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := LeaveGroupRequest{} + response, err := broker.LeaveGroup(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("LeaveGroup request got no response!") + } + }}, + + {"HeartbeatRequest", + []byte{0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := HeartbeatRequest{} + response, err := broker.Heartbeat(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Heartbeat request got no response!") + } + }}, + + {"ListGroupsRequest", + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := ListGroupsRequest{} + response, err := broker.ListGroups(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("ListGroups request got no response!") + } + }}, + + {"DescribeGroupsRequest", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := DescribeGroupsRequest{} + response, err := broker.DescribeGroups(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("DescribeGroups request got no response!") + } + }}, +} + +func validateBrokerMetrics(t *testing.T, broker *Broker, mockBrokerMetrics brokerMetrics) { + metricValidators := newMetricValidators() + mockBrokerBytesRead := mockBrokerMetrics.bytesRead + mockBrokerBytesWritten := mockBrokerMetrics.bytesWritten + + // Check that the number of bytes sent corresponds to what the mock broker received + metricValidators.registerForAllBrokers(broker, countMeterValidator("incoming-byte-rate", mockBrokerBytesWritten)) + if mockBrokerBytesWritten == 0 { + // This a ProduceRequest with NoResponse + metricValidators.registerForAllBrokers(broker, countMeterValidator("response-rate", 0)) + metricValidators.registerForAllBrokers(broker, countHistogramValidator("response-size", 0)) + metricValidators.registerForAllBrokers(broker, minMaxHistogramValidator("response-size", 0, 0)) + } else { + metricValidators.registerForAllBrokers(broker, countMeterValidator("response-rate", 1)) + metricValidators.registerForAllBrokers(broker, countHistogramValidator("response-size", 1)) + metricValidators.registerForAllBrokers(broker, minMaxHistogramValidator("response-size", mockBrokerBytesWritten, mockBrokerBytesWritten)) + } + + // Check that the number of bytes received corresponds to what the mock broker sent + metricValidators.registerForAllBrokers(broker, countMeterValidator("outgoing-byte-rate", mockBrokerBytesRead)) + metricValidators.registerForAllBrokers(broker, countMeterValidator("request-rate", 1)) + metricValidators.registerForAllBrokers(broker, countHistogramValidator("request-size", 1)) + metricValidators.registerForAllBrokers(broker, minMaxHistogramValidator("request-size", mockBrokerBytesRead, mockBrokerBytesRead)) + + // Run the validators + metricValidators.run(t, broker.conf.MetricRegistry) +} diff --git a/vendor/src/github.com/Shopify/sarama/client.go b/vendor/src/github.com/Shopify/sarama/client.go new file mode 100644 index 00000000..28592c75 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/client.go @@ -0,0 +1,749 @@ +package sarama + +import ( + "math/rand" + "sort" + "sync" + "time" +) + +// Client is a generic Kafka client. It manages connections to one or more Kafka brokers. +// You MUST call Close() on a client to avoid leaks, it will not be garbage-collected +// automatically when it passes out of scope. It is safe to share a client amongst many +// users, however Kafka will process requests from a single client strictly in serial, +// so it is generally more efficient to use the default one client per producer/consumer. +type Client interface { + // Config returns the Config struct of the client. This struct should not be + // altered after it has been created. + Config() *Config + + // Brokers returns the current set of active brokers as retrieved from cluster metadata. + Brokers() []*Broker + + // Topics returns the set of available topics as retrieved from cluster metadata. + Topics() ([]string, error) + + // Partitions returns the sorted list of all partition IDs for the given topic. + Partitions(topic string) ([]int32, error) + + // WritablePartitions returns the sorted list of all writable partition IDs for + // the given topic, where "writable" means "having a valid leader accepting + // writes". + WritablePartitions(topic string) ([]int32, error) + + // Leader returns the broker object that is the leader of the current + // topic/partition, as determined by querying the cluster metadata. + Leader(topic string, partitionID int32) (*Broker, error) + + // Replicas returns the set of all replica IDs for the given partition. + Replicas(topic string, partitionID int32) ([]int32, error) + + // RefreshMetadata takes a list of topics and queries the cluster to refresh the + // available metadata for those topics. If no topics are provided, it will refresh + // metadata for all topics. + RefreshMetadata(topics ...string) error + + // GetOffset queries the cluster to get the most recent available offset at the + // given time on the topic/partition combination. Time should be OffsetOldest for + // the earliest available offset, OffsetNewest for the offset of the message that + // will be produced next, or a time. + GetOffset(topic string, partitionID int32, time int64) (int64, error) + + // Coordinator returns the coordinating broker for a consumer group. It will + // return a locally cached value if it's available. You can call + // RefreshCoordinator to update the cached value. This function only works on + // Kafka 0.8.2 and higher. + Coordinator(consumerGroup string) (*Broker, error) + + // RefreshCoordinator retrieves the coordinator for a consumer group and stores it + // in local cache. This function only works on Kafka 0.8.2 and higher. + RefreshCoordinator(consumerGroup string) error + + // Close shuts down all broker connections managed by this client. It is required + // to call this function before a client object passes out of scope, as it will + // otherwise leak memory. You must close any Producers or Consumers using a client + // before you close the client. + Close() error + + // Closed returns true if the client has already had Close called on it + Closed() bool +} + +const ( + // OffsetNewest stands for the log head offset, i.e. the offset that will be + // assigned to the next message that will be produced to the partition. You + // can send this to a client's GetOffset method to get this offset, or when + // calling ConsumePartition to start consuming new messages. + OffsetNewest int64 = -1 + // OffsetOldest stands for the oldest offset available on the broker for a + // partition. You can send this to a client's GetOffset method to get this + // offset, or when calling ConsumePartition to start consuming from the + // oldest offset that is still available on the broker. + OffsetOldest int64 = -2 +) + +type client struct { + conf *Config + closer, closed chan none // for shutting down background metadata updater + + // the broker addresses given to us through the constructor are not guaranteed to be returned in + // the cluster metadata (I *think* it only returns brokers who are currently leading partitions?) + // so we store them separately + seedBrokers []*Broker + deadSeeds []*Broker + + brokers map[int32]*Broker // maps broker ids to brokers + metadata map[string]map[int32]*PartitionMetadata // maps topics to partition ids to metadata + coordinators map[string]int32 // Maps consumer group names to coordinating broker IDs + + // If the number of partitions is large, we can get some churn calling cachedPartitions, + // so the result is cached. It is important to update this value whenever metadata is changed + cachedPartitionsResults map[string][maxPartitionIndex][]int32 + + lock sync.RWMutex // protects access to the maps that hold cluster state. +} + +// NewClient creates a new Client. It connects to one of the given broker addresses +// and uses that broker to automatically fetch metadata on the rest of the kafka cluster. If metadata cannot +// be retrieved from any of the given broker addresses, the client is not created. +func NewClient(addrs []string, conf *Config) (Client, error) { + Logger.Println("Initializing new client") + + if conf == nil { + conf = NewConfig() + } + + if err := conf.Validate(); err != nil { + return nil, err + } + + if len(addrs) < 1 { + return nil, ConfigurationError("You must provide at least one broker address") + } + + client := &client{ + conf: conf, + closer: make(chan none), + closed: make(chan none), + brokers: make(map[int32]*Broker), + metadata: make(map[string]map[int32]*PartitionMetadata), + cachedPartitionsResults: make(map[string][maxPartitionIndex][]int32), + coordinators: make(map[string]int32), + } + + random := rand.New(rand.NewSource(time.Now().UnixNano())) + for _, index := range random.Perm(len(addrs)) { + client.seedBrokers = append(client.seedBrokers, NewBroker(addrs[index])) + } + + // do an initial fetch of all cluster metadata by specifing an empty list of topics + err := client.RefreshMetadata() + switch err { + case nil: + break + case ErrLeaderNotAvailable, ErrReplicaNotAvailable, ErrTopicAuthorizationFailed, ErrClusterAuthorizationFailed: + // indicates that maybe part of the cluster is down, but is not fatal to creating the client + Logger.Println(err) + default: + close(client.closed) // we haven't started the background updater yet, so we have to do this manually + _ = client.Close() + return nil, err + } + go withRecover(client.backgroundMetadataUpdater) + + Logger.Println("Successfully initialized new client") + + return client, nil +} + +func (client *client) Config() *Config { + return client.conf +} + +func (client *client) Brokers() []*Broker { + client.lock.RLock() + defer client.lock.RUnlock() + brokers := make([]*Broker, 0) + for _, broker := range client.brokers { + brokers = append(brokers, broker) + } + return brokers +} + +func (client *client) Close() error { + if client.Closed() { + // Chances are this is being called from a defer() and the error will go unobserved + // so we go ahead and log the event in this case. + Logger.Printf("Close() called on already closed client") + return ErrClosedClient + } + + // shutdown and wait for the background thread before we take the lock, to avoid races + close(client.closer) + <-client.closed + + client.lock.Lock() + defer client.lock.Unlock() + Logger.Println("Closing Client") + + for _, broker := range client.brokers { + safeAsyncClose(broker) + } + + for _, broker := range client.seedBrokers { + safeAsyncClose(broker) + } + + client.brokers = nil + client.metadata = nil + + return nil +} + +func (client *client) Closed() bool { + return client.brokers == nil +} + +func (client *client) Topics() ([]string, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + client.lock.RLock() + defer client.lock.RUnlock() + + ret := make([]string, 0, len(client.metadata)) + for topic := range client.metadata { + ret = append(ret, topic) + } + + return ret, nil +} + +func (client *client) Partitions(topic string) ([]int32, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + partitions := client.cachedPartitions(topic, allPartitions) + + if len(partitions) == 0 { + err := client.RefreshMetadata(topic) + if err != nil { + return nil, err + } + partitions = client.cachedPartitions(topic, allPartitions) + } + + if partitions == nil { + return nil, ErrUnknownTopicOrPartition + } + + return partitions, nil +} + +func (client *client) WritablePartitions(topic string) ([]int32, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + partitions := client.cachedPartitions(topic, writablePartitions) + + // len==0 catches when it's nil (no such topic) and the odd case when every single + // partition is undergoing leader election simultaneously. Callers have to be able to handle + // this function returning an empty slice (which is a valid return value) but catching it + // here the first time (note we *don't* catch it below where we return ErrUnknownTopicOrPartition) triggers + // a metadata refresh as a nicety so callers can just try again and don't have to manually + // trigger a refresh (otherwise they'd just keep getting a stale cached copy). + if len(partitions) == 0 { + err := client.RefreshMetadata(topic) + if err != nil { + return nil, err + } + partitions = client.cachedPartitions(topic, writablePartitions) + } + + if partitions == nil { + return nil, ErrUnknownTopicOrPartition + } + + return partitions, nil +} + +func (client *client) Replicas(topic string, partitionID int32) ([]int32, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + metadata := client.cachedMetadata(topic, partitionID) + + if metadata == nil { + err := client.RefreshMetadata(topic) + if err != nil { + return nil, err + } + metadata = client.cachedMetadata(topic, partitionID) + } + + if metadata == nil { + return nil, ErrUnknownTopicOrPartition + } + + if metadata.Err == ErrReplicaNotAvailable { + return nil, metadata.Err + } + return dupeAndSort(metadata.Replicas), nil +} + +func (client *client) Leader(topic string, partitionID int32) (*Broker, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + leader, err := client.cachedLeader(topic, partitionID) + + if leader == nil { + err = client.RefreshMetadata(topic) + if err != nil { + return nil, err + } + leader, err = client.cachedLeader(topic, partitionID) + } + + return leader, err +} + +func (client *client) RefreshMetadata(topics ...string) error { + if client.Closed() { + return ErrClosedClient + } + + // Prior to 0.8.2, Kafka will throw exceptions on an empty topic and not return a proper + // error. This handles the case by returning an error instead of sending it + // off to Kafka. See: https://github.com/Shopify/sarama/pull/38#issuecomment-26362310 + for _, topic := range topics { + if len(topic) == 0 { + return ErrInvalidTopic // this is the error that 0.8.2 and later correctly return + } + } + + return client.tryRefreshMetadata(topics, client.conf.Metadata.Retry.Max) +} + +func (client *client) GetOffset(topic string, partitionID int32, time int64) (int64, error) { + if client.Closed() { + return -1, ErrClosedClient + } + + offset, err := client.getOffset(topic, partitionID, time) + + if err != nil { + if err := client.RefreshMetadata(topic); err != nil { + return -1, err + } + return client.getOffset(topic, partitionID, time) + } + + return offset, err +} + +func (client *client) Coordinator(consumerGroup string) (*Broker, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + coordinator := client.cachedCoordinator(consumerGroup) + + if coordinator == nil { + if err := client.RefreshCoordinator(consumerGroup); err != nil { + return nil, err + } + coordinator = client.cachedCoordinator(consumerGroup) + } + + if coordinator == nil { + return nil, ErrConsumerCoordinatorNotAvailable + } + + _ = coordinator.Open(client.conf) + return coordinator, nil +} + +func (client *client) RefreshCoordinator(consumerGroup string) error { + if client.Closed() { + return ErrClosedClient + } + + response, err := client.getConsumerMetadata(consumerGroup, client.conf.Metadata.Retry.Max) + if err != nil { + return err + } + + client.lock.Lock() + defer client.lock.Unlock() + client.registerBroker(response.Coordinator) + client.coordinators[consumerGroup] = response.Coordinator.ID() + return nil +} + +// private broker management helpers + +// registerBroker makes sure a broker received by a Metadata or Coordinator request is registered +// in the brokers map. It returns the broker that is registered, which may be the provided broker, +// or a previously registered Broker instance. You must hold the write lock before calling this function. +func (client *client) registerBroker(broker *Broker) { + if client.brokers[broker.ID()] == nil { + client.brokers[broker.ID()] = broker + Logger.Printf("client/brokers registered new broker #%d at %s", broker.ID(), broker.Addr()) + } else if broker.Addr() != client.brokers[broker.ID()].Addr() { + safeAsyncClose(client.brokers[broker.ID()]) + client.brokers[broker.ID()] = broker + Logger.Printf("client/brokers replaced registered broker #%d with %s", broker.ID(), broker.Addr()) + } +} + +// deregisterBroker removes a broker from the seedsBroker list, and if it's +// not the seedbroker, removes it from brokers map completely. +func (client *client) deregisterBroker(broker *Broker) { + client.lock.Lock() + defer client.lock.Unlock() + + if len(client.seedBrokers) > 0 && broker == client.seedBrokers[0] { + client.deadSeeds = append(client.deadSeeds, broker) + client.seedBrokers = client.seedBrokers[1:] + } else { + // we do this so that our loop in `tryRefreshMetadata` doesn't go on forever, + // but we really shouldn't have to; once that loop is made better this case can be + // removed, and the function generally can be renamed from `deregisterBroker` to + // `nextSeedBroker` or something + Logger.Printf("client/brokers deregistered broker #%d at %s", broker.ID(), broker.Addr()) + delete(client.brokers, broker.ID()) + } +} + +func (client *client) resurrectDeadBrokers() { + client.lock.Lock() + defer client.lock.Unlock() + + Logger.Printf("client/brokers resurrecting %d dead seed brokers", len(client.deadSeeds)) + client.seedBrokers = append(client.seedBrokers, client.deadSeeds...) + client.deadSeeds = nil +} + +func (client *client) any() *Broker { + client.lock.RLock() + defer client.lock.RUnlock() + + if len(client.seedBrokers) > 0 { + _ = client.seedBrokers[0].Open(client.conf) + return client.seedBrokers[0] + } + + // not guaranteed to be random *or* deterministic + for _, broker := range client.brokers { + _ = broker.Open(client.conf) + return broker + } + + return nil +} + +// private caching/lazy metadata helpers + +type partitionType int + +const ( + allPartitions partitionType = iota + writablePartitions + // If you add any more types, update the partition cache in update() + + // Ensure this is the last partition type value + maxPartitionIndex +) + +func (client *client) cachedMetadata(topic string, partitionID int32) *PartitionMetadata { + client.lock.RLock() + defer client.lock.RUnlock() + + partitions := client.metadata[topic] + if partitions != nil { + return partitions[partitionID] + } + + return nil +} + +func (client *client) cachedPartitions(topic string, partitionSet partitionType) []int32 { + client.lock.RLock() + defer client.lock.RUnlock() + + partitions, exists := client.cachedPartitionsResults[topic] + + if !exists { + return nil + } + return partitions[partitionSet] +} + +func (client *client) setPartitionCache(topic string, partitionSet partitionType) []int32 { + partitions := client.metadata[topic] + + if partitions == nil { + return nil + } + + ret := make([]int32, 0, len(partitions)) + for _, partition := range partitions { + if partitionSet == writablePartitions && partition.Err == ErrLeaderNotAvailable { + continue + } + ret = append(ret, partition.ID) + } + + sort.Sort(int32Slice(ret)) + return ret +} + +func (client *client) cachedLeader(topic string, partitionID int32) (*Broker, error) { + client.lock.RLock() + defer client.lock.RUnlock() + + partitions := client.metadata[topic] + if partitions != nil { + metadata, ok := partitions[partitionID] + if ok { + if metadata.Err == ErrLeaderNotAvailable { + return nil, ErrLeaderNotAvailable + } + b := client.brokers[metadata.Leader] + if b == nil { + return nil, ErrLeaderNotAvailable + } + _ = b.Open(client.conf) + return b, nil + } + } + + return nil, ErrUnknownTopicOrPartition +} + +func (client *client) getOffset(topic string, partitionID int32, time int64) (int64, error) { + broker, err := client.Leader(topic, partitionID) + if err != nil { + return -1, err + } + + request := &OffsetRequest{} + if client.conf.Version.IsAtLeast(V0_10_1_0) { + request.Version = 1 + } + request.AddBlock(topic, partitionID, time, 1) + + response, err := broker.GetAvailableOffsets(request) + if err != nil { + _ = broker.Close() + return -1, err + } + + block := response.GetBlock(topic, partitionID) + if block == nil { + _ = broker.Close() + return -1, ErrIncompleteResponse + } + if block.Err != ErrNoError { + return -1, block.Err + } + if len(block.Offsets) != 1 { + return -1, ErrOffsetOutOfRange + } + + return block.Offsets[0], nil +} + +// core metadata update logic + +func (client *client) backgroundMetadataUpdater() { + defer close(client.closed) + + if client.conf.Metadata.RefreshFrequency == time.Duration(0) { + return + } + + ticker := time.NewTicker(client.conf.Metadata.RefreshFrequency) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + if err := client.RefreshMetadata(); err != nil { + Logger.Println("Client background metadata update:", err) + } + case <-client.closer: + return + } + } +} + +func (client *client) tryRefreshMetadata(topics []string, attemptsRemaining int) error { + retry := func(err error) error { + if attemptsRemaining > 0 { + Logger.Printf("client/metadata retrying after %dms... (%d attempts remaining)\n", client.conf.Metadata.Retry.Backoff/time.Millisecond, attemptsRemaining) + time.Sleep(client.conf.Metadata.Retry.Backoff) + return client.tryRefreshMetadata(topics, attemptsRemaining-1) + } + return err + } + + for broker := client.any(); broker != nil; broker = client.any() { + if len(topics) > 0 { + Logger.Printf("client/metadata fetching metadata for %v from broker %s\n", topics, broker.addr) + } else { + Logger.Printf("client/metadata fetching metadata for all topics from broker %s\n", broker.addr) + } + response, err := broker.GetMetadata(&MetadataRequest{Topics: topics}) + + switch err.(type) { + case nil: + // valid response, use it + if shouldRetry, err := client.updateMetadata(response); shouldRetry { + Logger.Println("client/metadata found some partitions to be leaderless") + return retry(err) // note: err can be nil + } else { + return err + } + + case PacketEncodingError: + // didn't even send, return the error + return err + default: + // some other error, remove that broker and try again + Logger.Println("client/metadata got error from broker while fetching metadata:", err) + _ = broker.Close() + client.deregisterBroker(broker) + } + } + + Logger.Println("client/metadata no available broker to send metadata request to") + client.resurrectDeadBrokers() + return retry(ErrOutOfBrokers) +} + +// if no fatal error, returns a list of topics that need retrying due to ErrLeaderNotAvailable +func (client *client) updateMetadata(data *MetadataResponse) (retry bool, err error) { + client.lock.Lock() + defer client.lock.Unlock() + + // For all the brokers we received: + // - if it is a new ID, save it + // - if it is an existing ID, but the address we have is stale, discard the old one and save it + // - otherwise ignore it, replacing our existing one would just bounce the connection + for _, broker := range data.Brokers { + client.registerBroker(broker) + } + + for _, topic := range data.Topics { + delete(client.metadata, topic.Name) + delete(client.cachedPartitionsResults, topic.Name) + + switch topic.Err { + case ErrNoError: + break + case ErrInvalidTopic, ErrTopicAuthorizationFailed: // don't retry, don't store partial results + err = topic.Err + continue + case ErrUnknownTopicOrPartition: // retry, do not store partial partition results + err = topic.Err + retry = true + continue + case ErrLeaderNotAvailable: // retry, but store partial partition results + retry = true + break + default: // don't retry, don't store partial results + Logger.Printf("Unexpected topic-level metadata error: %s", topic.Err) + err = topic.Err + continue + } + + client.metadata[topic.Name] = make(map[int32]*PartitionMetadata, len(topic.Partitions)) + for _, partition := range topic.Partitions { + client.metadata[topic.Name][partition.ID] = partition + if partition.Err == ErrLeaderNotAvailable { + retry = true + } + } + + var partitionCache [maxPartitionIndex][]int32 + partitionCache[allPartitions] = client.setPartitionCache(topic.Name, allPartitions) + partitionCache[writablePartitions] = client.setPartitionCache(topic.Name, writablePartitions) + client.cachedPartitionsResults[topic.Name] = partitionCache + } + + return +} + +func (client *client) cachedCoordinator(consumerGroup string) *Broker { + client.lock.RLock() + defer client.lock.RUnlock() + if coordinatorID, ok := client.coordinators[consumerGroup]; ok { + return client.brokers[coordinatorID] + } + return nil +} + +func (client *client) getConsumerMetadata(consumerGroup string, attemptsRemaining int) (*ConsumerMetadataResponse, error) { + retry := func(err error) (*ConsumerMetadataResponse, error) { + if attemptsRemaining > 0 { + Logger.Printf("client/coordinator retrying after %dms... (%d attempts remaining)\n", client.conf.Metadata.Retry.Backoff/time.Millisecond, attemptsRemaining) + time.Sleep(client.conf.Metadata.Retry.Backoff) + return client.getConsumerMetadata(consumerGroup, attemptsRemaining-1) + } + return nil, err + } + + for broker := client.any(); broker != nil; broker = client.any() { + Logger.Printf("client/coordinator requesting coordinator for consumergroup %s from %s\n", consumerGroup, broker.Addr()) + + request := new(ConsumerMetadataRequest) + request.ConsumerGroup = consumerGroup + + response, err := broker.GetConsumerMetadata(request) + + if err != nil { + Logger.Printf("client/coordinator request to broker %s failed: %s\n", broker.Addr(), err) + + switch err.(type) { + case PacketEncodingError: + return nil, err + default: + _ = broker.Close() + client.deregisterBroker(broker) + continue + } + } + + switch response.Err { + case ErrNoError: + Logger.Printf("client/coordinator coordinator for consumergroup %s is #%d (%s)\n", consumerGroup, response.Coordinator.ID(), response.Coordinator.Addr()) + return response, nil + + case ErrConsumerCoordinatorNotAvailable: + Logger.Printf("client/coordinator coordinator for consumer group %s is not available\n", consumerGroup) + + // This is very ugly, but this scenario will only happen once per cluster. + // The __consumer_offsets topic only has to be created one time. + // The number of partitions not configurable, but partition 0 should always exist. + if _, err := client.Leader("__consumer_offsets", 0); err != nil { + Logger.Printf("client/coordinator the __consumer_offsets topic is not initialized completely yet. Waiting 2 seconds...\n") + time.Sleep(2 * time.Second) + } + + return retry(ErrConsumerCoordinatorNotAvailable) + default: + return nil, response.Err + } + } + + Logger.Println("client/coordinator no available broker to send consumer metadata request to") + client.resurrectDeadBrokers() + return retry(ErrOutOfBrokers) +} diff --git a/vendor/src/github.com/Shopify/sarama/client_test.go b/vendor/src/github.com/Shopify/sarama/client_test.go new file mode 100644 index 00000000..b0559466 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/client_test.go @@ -0,0 +1,608 @@ +package sarama + +import ( + "io" + "sync" + "testing" + "time" +) + +func safeClose(t testing.TB, c io.Closer) { + err := c.Close() + if err != nil { + t.Error(err) + } +} + +func TestSimpleClient(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + seedBroker.Returns(new(MetadataResponse)) + + client, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + seedBroker.Close() + safeClose(t, client) +} + +func TestCachedPartitions(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + replicas := []int32{3, 1, 5} + isr := []int32{5, 1} + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker("localhost:12345", 2) + metadataResponse.AddTopicPartition("my_topic", 0, 2, replicas, isr, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 1, 2, replicas, isr, ErrLeaderNotAvailable) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Metadata.Retry.Max = 0 + c, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + client := c.(*client) + + // Verify they aren't cached the same + allP := client.cachedPartitionsResults["my_topic"][allPartitions] + writeP := client.cachedPartitionsResults["my_topic"][writablePartitions] + if len(allP) == len(writeP) { + t.Fatal("Invalid lengths!") + } + + tmp := client.cachedPartitionsResults["my_topic"] + // Verify we actually use the cache at all! + tmp[allPartitions] = []int32{1, 2, 3, 4} + client.cachedPartitionsResults["my_topic"] = tmp + if 4 != len(client.cachedPartitions("my_topic", allPartitions)) { + t.Fatal("Not using the cache!") + } + + seedBroker.Close() + safeClose(t, client) +} + +func TestClientDoesntCachePartitionsForTopicsWithErrors(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + replicas := []int32{seedBroker.BrokerID()} + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(seedBroker.Addr(), seedBroker.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 1, replicas[0], replicas, replicas, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 2, replicas[0], replicas, replicas, ErrNoError) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Metadata.Retry.Max = 0 + client, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + metadataResponse = new(MetadataResponse) + metadataResponse.AddTopic("unknown", ErrUnknownTopicOrPartition) + seedBroker.Returns(metadataResponse) + + partitions, err := client.Partitions("unknown") + + if err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, found", err) + } + if partitions != nil { + t.Errorf("Should return nil as partition list, found %v", partitions) + } + + // Should still use the cache of a known topic + partitions, err = client.Partitions("my_topic") + if err != nil { + t.Errorf("Expected no error, found %v", err) + } + + metadataResponse = new(MetadataResponse) + metadataResponse.AddTopic("unknown", ErrUnknownTopicOrPartition) + seedBroker.Returns(metadataResponse) + + // Should not use cache for unknown topic + partitions, err = client.Partitions("unknown") + if err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, found", err) + } + if partitions != nil { + t.Errorf("Should return nil as partition list, found %v", partitions) + } + + seedBroker.Close() + safeClose(t, client) +} + +func TestClientSeedBrokers(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker("localhost:12345", 2) + seedBroker.Returns(metadataResponse) + + client, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + seedBroker.Close() + safeClose(t, client) +} + +func TestClientMetadata(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 5) + + replicas := []int32{3, 1, 5} + isr := []int32{5, 1} + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), replicas, isr, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 1, leader.BrokerID(), replicas, isr, ErrLeaderNotAvailable) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Metadata.Retry.Max = 0 + client, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + topics, err := client.Topics() + if err != nil { + t.Error(err) + } else if len(topics) != 1 || topics[0] != "my_topic" { + t.Error("Client returned incorrect topics:", topics) + } + + parts, err := client.Partitions("my_topic") + if err != nil { + t.Error(err) + } else if len(parts) != 2 || parts[0] != 0 || parts[1] != 1 { + t.Error("Client returned incorrect partitions for my_topic:", parts) + } + + parts, err = client.WritablePartitions("my_topic") + if err != nil { + t.Error(err) + } else if len(parts) != 1 || parts[0] != 0 { + t.Error("Client returned incorrect writable partitions for my_topic:", parts) + } + + tst, err := client.Leader("my_topic", 0) + if err != nil { + t.Error(err) + } else if tst.ID() != 5 { + t.Error("Leader for my_topic had incorrect ID.") + } + + replicas, err = client.Replicas("my_topic", 0) + if err != nil { + t.Error(err) + } else if replicas[0] != 1 { + t.Error("Incorrect (or unsorted) replica") + } else if replicas[1] != 3 { + t.Error("Incorrect (or unsorted) replica") + } else if replicas[2] != 5 { + t.Error("Incorrect (or unsorted) replica") + } + + leader.Close() + seedBroker.Close() + safeClose(t, client) +} + +func TestClientGetOffset(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + leaderAddr := leader.Addr() + + metadata := new(MetadataResponse) + metadata.AddTopicPartition("foo", 0, leader.BrokerID(), nil, nil, ErrNoError) + metadata.AddBroker(leaderAddr, leader.BrokerID()) + seedBroker.Returns(metadata) + + client, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + offsetResponse := new(OffsetResponse) + offsetResponse.AddTopicPartition("foo", 0, 123) + leader.Returns(offsetResponse) + + offset, err := client.GetOffset("foo", 0, OffsetNewest) + if err != nil { + t.Error(err) + } + if offset != 123 { + t.Error("Unexpected offset, got ", offset) + } + + leader.Close() + seedBroker.Returns(metadata) + + leader = NewMockBrokerAddr(t, 2, leaderAddr) + offsetResponse = new(OffsetResponse) + offsetResponse.AddTopicPartition("foo", 0, 456) + leader.Returns(offsetResponse) + + offset, err = client.GetOffset("foo", 0, OffsetNewest) + if err != nil { + t.Error(err) + } + if offset != 456 { + t.Error("Unexpected offset, got ", offset) + } + + seedBroker.Close() + leader.Close() + safeClose(t, client) +} + +func TestClientReceivingUnknownTopic(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + metadataResponse1 := new(MetadataResponse) + seedBroker.Returns(metadataResponse1) + + config := NewConfig() + config.Metadata.Retry.Max = 1 + config.Metadata.Retry.Backoff = 0 + client, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + metadataUnknownTopic := new(MetadataResponse) + metadataUnknownTopic.AddTopic("new_topic", ErrUnknownTopicOrPartition) + seedBroker.Returns(metadataUnknownTopic) + seedBroker.Returns(metadataUnknownTopic) + + if err := client.RefreshMetadata("new_topic"); err != ErrUnknownTopicOrPartition { + t.Error("ErrUnknownTopicOrPartition expected, got", err) + } + + // If we are asking for the leader of a partition of the non-existing topic. + // we will request metadata again. + seedBroker.Returns(metadataUnknownTopic) + seedBroker.Returns(metadataUnknownTopic) + + if _, err = client.Leader("new_topic", 1); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, got", err) + } + + safeClose(t, client) + seedBroker.Close() +} + +func TestClientReceivingPartialMetadata(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 5) + + metadataResponse1 := new(MetadataResponse) + metadataResponse1.AddBroker(leader.Addr(), leader.BrokerID()) + seedBroker.Returns(metadataResponse1) + + config := NewConfig() + config.Metadata.Retry.Max = 0 + client, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + replicas := []int32{leader.BrokerID(), seedBroker.BrokerID()} + + metadataPartial := new(MetadataResponse) + metadataPartial.AddTopic("new_topic", ErrLeaderNotAvailable) + metadataPartial.AddTopicPartition("new_topic", 0, leader.BrokerID(), replicas, replicas, ErrNoError) + metadataPartial.AddTopicPartition("new_topic", 1, -1, replicas, []int32{}, ErrLeaderNotAvailable) + seedBroker.Returns(metadataPartial) + + if err := client.RefreshMetadata("new_topic"); err != nil { + t.Error("ErrLeaderNotAvailable should not make RefreshMetadata respond with an error") + } + + // Even though the metadata was incomplete, we should be able to get the leader of a partition + // for which we did get a useful response, without doing additional requests. + + partition0Leader, err := client.Leader("new_topic", 0) + if err != nil { + t.Error(err) + } else if partition0Leader.Addr() != leader.Addr() { + t.Error("Unexpected leader returned", partition0Leader.Addr()) + } + + // If we are asking for the leader of a partition that didn't have a leader before, + // we will do another metadata request. + + seedBroker.Returns(metadataPartial) + + // Still no leader for the partition, so asking for it should return an error. + _, err = client.Leader("new_topic", 1) + if err != ErrLeaderNotAvailable { + t.Error("Expected ErrLeaderNotAvailable, got", err) + } + + safeClose(t, client) + seedBroker.Close() + leader.Close() +} + +func TestClientRefreshBehaviour(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 5) + + metadataResponse1 := new(MetadataResponse) + metadataResponse1.AddBroker(leader.Addr(), leader.BrokerID()) + seedBroker.Returns(metadataResponse1) + + metadataResponse2 := new(MetadataResponse) + metadataResponse2.AddTopicPartition("my_topic", 0xb, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse2) + + client, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + parts, err := client.Partitions("my_topic") + if err != nil { + t.Error(err) + } else if len(parts) != 1 || parts[0] != 0xb { + t.Error("Client returned incorrect partitions for my_topic:", parts) + } + + tst, err := client.Leader("my_topic", 0xb) + if err != nil { + t.Error(err) + } else if tst.ID() != 5 { + t.Error("Leader for my_topic had incorrect ID.") + } + + leader.Close() + seedBroker.Close() + safeClose(t, client) +} + +func TestClientResurrectDeadSeeds(t *testing.T) { + initialSeed := NewMockBroker(t, 0) + emptyMetadata := new(MetadataResponse) + initialSeed.Returns(emptyMetadata) + + conf := NewConfig() + conf.Metadata.Retry.Backoff = 0 + conf.Metadata.RefreshFrequency = 0 + c, err := NewClient([]string{initialSeed.Addr()}, conf) + if err != nil { + t.Fatal(err) + } + initialSeed.Close() + + client := c.(*client) + + seed1 := NewMockBroker(t, 1) + seed2 := NewMockBroker(t, 2) + seed3 := NewMockBroker(t, 3) + addr1 := seed1.Addr() + addr2 := seed2.Addr() + addr3 := seed3.Addr() + + // Overwrite the seed brokers with a fixed ordering to make this test deterministic. + safeClose(t, client.seedBrokers[0]) + client.seedBrokers = []*Broker{NewBroker(addr1), NewBroker(addr2), NewBroker(addr3)} + client.deadSeeds = []*Broker{} + + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + if err := client.RefreshMetadata(); err != nil { + t.Error(err) + } + wg.Done() + }() + seed1.Close() + seed2.Close() + + seed1 = NewMockBrokerAddr(t, 1, addr1) + seed2 = NewMockBrokerAddr(t, 2, addr2) + + seed3.Close() + + seed1.Close() + seed2.Returns(emptyMetadata) + + wg.Wait() + + if len(client.seedBrokers) != 2 { + t.Error("incorrect number of live seeds") + } + if len(client.deadSeeds) != 1 { + t.Error("incorrect number of dead seeds") + } + + safeClose(t, c) +} + +func TestClientCoordinatorWithConsumerOffsetsTopic(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + staleCoordinator := NewMockBroker(t, 2) + freshCoordinator := NewMockBroker(t, 3) + + replicas := []int32{staleCoordinator.BrokerID(), freshCoordinator.BrokerID()} + metadataResponse1 := new(MetadataResponse) + metadataResponse1.AddBroker(staleCoordinator.Addr(), staleCoordinator.BrokerID()) + metadataResponse1.AddBroker(freshCoordinator.Addr(), freshCoordinator.BrokerID()) + metadataResponse1.AddTopicPartition("__consumer_offsets", 0, replicas[0], replicas, replicas, ErrNoError) + seedBroker.Returns(metadataResponse1) + + client, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + coordinatorResponse1 := new(ConsumerMetadataResponse) + coordinatorResponse1.Err = ErrConsumerCoordinatorNotAvailable + seedBroker.Returns(coordinatorResponse1) + + coordinatorResponse2 := new(ConsumerMetadataResponse) + coordinatorResponse2.CoordinatorID = staleCoordinator.BrokerID() + coordinatorResponse2.CoordinatorHost = "127.0.0.1" + coordinatorResponse2.CoordinatorPort = staleCoordinator.Port() + + seedBroker.Returns(coordinatorResponse2) + + broker, err := client.Coordinator("my_group") + if err != nil { + t.Error(err) + } + + if staleCoordinator.Addr() != broker.Addr() { + t.Errorf("Expected coordinator to have address %s, found %s", staleCoordinator.Addr(), broker.Addr()) + } + + if staleCoordinator.BrokerID() != broker.ID() { + t.Errorf("Expected coordinator to have ID %d, found %d", staleCoordinator.BrokerID(), broker.ID()) + } + + // Grab the cached value + broker2, err := client.Coordinator("my_group") + if err != nil { + t.Error(err) + } + + if broker2.Addr() != broker.Addr() { + t.Errorf("Expected the coordinator to be the same, but found %s vs. %s", broker2.Addr(), broker.Addr()) + } + + coordinatorResponse3 := new(ConsumerMetadataResponse) + coordinatorResponse3.CoordinatorID = freshCoordinator.BrokerID() + coordinatorResponse3.CoordinatorHost = "127.0.0.1" + coordinatorResponse3.CoordinatorPort = freshCoordinator.Port() + + seedBroker.Returns(coordinatorResponse3) + + // Refresh the locally cahced value because it's stale + if err := client.RefreshCoordinator("my_group"); err != nil { + t.Error(err) + } + + // Grab the fresh value + broker3, err := client.Coordinator("my_group") + if err != nil { + t.Error(err) + } + + if broker3.Addr() != freshCoordinator.Addr() { + t.Errorf("Expected the freshCoordinator to be returned, but found %s.", broker3.Addr()) + } + + freshCoordinator.Close() + staleCoordinator.Close() + seedBroker.Close() + safeClose(t, client) +} + +func TestClientCoordinatorWithoutConsumerOffsetsTopic(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + coordinator := NewMockBroker(t, 2) + + metadataResponse1 := new(MetadataResponse) + seedBroker.Returns(metadataResponse1) + + config := NewConfig() + config.Metadata.Retry.Max = 1 + config.Metadata.Retry.Backoff = 0 + client, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + coordinatorResponse1 := new(ConsumerMetadataResponse) + coordinatorResponse1.Err = ErrConsumerCoordinatorNotAvailable + seedBroker.Returns(coordinatorResponse1) + + metadataResponse2 := new(MetadataResponse) + metadataResponse2.AddTopic("__consumer_offsets", ErrUnknownTopicOrPartition) + seedBroker.Returns(metadataResponse2) + + replicas := []int32{coordinator.BrokerID()} + metadataResponse3 := new(MetadataResponse) + metadataResponse3.AddTopicPartition("__consumer_offsets", 0, replicas[0], replicas, replicas, ErrNoError) + seedBroker.Returns(metadataResponse3) + + coordinatorResponse2 := new(ConsumerMetadataResponse) + coordinatorResponse2.CoordinatorID = coordinator.BrokerID() + coordinatorResponse2.CoordinatorHost = "127.0.0.1" + coordinatorResponse2.CoordinatorPort = coordinator.Port() + + seedBroker.Returns(coordinatorResponse2) + + broker, err := client.Coordinator("my_group") + if err != nil { + t.Error(err) + } + + if coordinator.Addr() != broker.Addr() { + t.Errorf("Expected coordinator to have address %s, found %s", coordinator.Addr(), broker.Addr()) + } + + if coordinator.BrokerID() != broker.ID() { + t.Errorf("Expected coordinator to have ID %d, found %d", coordinator.BrokerID(), broker.ID()) + } + + coordinator.Close() + seedBroker.Close() + safeClose(t, client) +} + +func TestClientAutorefreshShutdownRace(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + metadataResponse := new(MetadataResponse) + seedBroker.Returns(metadataResponse) + + conf := NewConfig() + conf.Metadata.RefreshFrequency = 100 * time.Millisecond + client, err := NewClient([]string{seedBroker.Addr()}, conf) + if err != nil { + t.Fatal(err) + } + + // Wait for the background refresh to kick in + time.Sleep(110 * time.Millisecond) + + done := make(chan none) + go func() { + // Close the client + if err := client.Close(); err != nil { + t.Fatal(err) + } + close(done) + }() + + // Wait for the Close to kick in + time.Sleep(10 * time.Millisecond) + + // Then return some metadata to the still-running background thread + leader := NewMockBroker(t, 2) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("foo", 0, leader.BrokerID(), []int32{2}, []int32{2}, ErrNoError) + seedBroker.Returns(metadataResponse) + + <-done + + seedBroker.Close() + + // give the update time to happen so we get a panic if it's still running (which it shouldn't) + time.Sleep(10 * time.Millisecond) +} diff --git a/vendor/src/github.com/Shopify/sarama/config.go b/vendor/src/github.com/Shopify/sarama/config.go new file mode 100644 index 00000000..a417a38b --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/config.go @@ -0,0 +1,417 @@ +package sarama + +import ( + "crypto/tls" + "regexp" + "time" + + "github.com/rcrowley/go-metrics" +) + +const defaultClientID = "sarama" + +var validID = regexp.MustCompile(`\A[A-Za-z0-9._-]+\z`) + +// Config is used to pass multiple configuration options to Sarama's constructors. +type Config struct { + // Net is the namespace for network-level properties used by the Broker, and + // shared by the Client/Producer/Consumer. + Net struct { + // How many outstanding requests a connection is allowed to have before + // sending on it blocks (default 5). + MaxOpenRequests int + + // All three of the below configurations are similar to the + // `socket.timeout.ms` setting in JVM kafka. All of them default + // to 30 seconds. + DialTimeout time.Duration // How long to wait for the initial connection. + ReadTimeout time.Duration // How long to wait for a response. + WriteTimeout time.Duration // How long to wait for a transmit. + + TLS struct { + // Whether or not to use TLS when connecting to the broker + // (defaults to false). + Enable bool + // The TLS configuration to use for secure connections if + // enabled (defaults to nil). + Config *tls.Config + } + + // SASL based authentication with broker. While there are multiple SASL authentication methods + // the current implementation is limited to plaintext (SASL/PLAIN) authentication + SASL struct { + // Whether or not to use SASL authentication when connecting to the broker + // (defaults to false). + Enable bool + // Whether or not to send the Kafka SASL handshake first if enabled + // (defaults to true). You should only set this to false if you're using + // a non-Kafka SASL proxy. + Handshake bool + //username and password for SASL/PLAIN authentication + User string + Password string + } + + // KeepAlive specifies the keep-alive period for an active network connection. + // If zero, keep-alives are disabled. (default is 0: disabled). + KeepAlive time.Duration + } + + // Metadata is the namespace for metadata management properties used by the + // Client, and shared by the Producer/Consumer. + Metadata struct { + Retry struct { + // The total number of times to retry a metadata request when the + // cluster is in the middle of a leader election (default 3). + Max int + // How long to wait for leader election to occur before retrying + // (default 250ms). Similar to the JVM's `retry.backoff.ms`. + Backoff time.Duration + } + // How frequently to refresh the cluster metadata in the background. + // Defaults to 10 minutes. Set to 0 to disable. Similar to + // `topic.metadata.refresh.interval.ms` in the JVM version. + RefreshFrequency time.Duration + } + + // Producer is the namespace for configuration related to producing messages, + // used by the Producer. + Producer struct { + // The maximum permitted size of a message (defaults to 1000000). Should be + // set equal to or smaller than the broker's `message.max.bytes`. + MaxMessageBytes int + // The level of acknowledgement reliability needed from the broker (defaults + // to WaitForLocal). Equivalent to the `request.required.acks` setting of the + // JVM producer. + RequiredAcks RequiredAcks + // The maximum duration the broker will wait the receipt of the number of + // RequiredAcks (defaults to 10 seconds). This is only relevant when + // RequiredAcks is set to WaitForAll or a number > 1. Only supports + // millisecond resolution, nanoseconds will be truncated. Equivalent to + // the JVM producer's `request.timeout.ms` setting. + Timeout time.Duration + // The type of compression to use on messages (defaults to no compression). + // Similar to `compression.codec` setting of the JVM producer. + Compression CompressionCodec + // Generates partitioners for choosing the partition to send messages to + // (defaults to hashing the message key). Similar to the `partitioner.class` + // setting for the JVM producer. + Partitioner PartitionerConstructor + + // Return specifies what channels will be populated. If they are set to true, + // you must read from the respective channels to prevent deadlock. + Return struct { + // If enabled, successfully delivered messages will be returned on the + // Successes channel (default disabled). + Successes bool + + // If enabled, messages that failed to deliver will be returned on the + // Errors channel, including error (default enabled). + Errors bool + } + + // The following config options control how often messages are batched up and + // sent to the broker. By default, messages are sent as fast as possible, and + // all messages received while the current batch is in-flight are placed + // into the subsequent batch. + Flush struct { + // The best-effort number of bytes needed to trigger a flush. Use the + // global sarama.MaxRequestSize to set a hard upper limit. + Bytes int + // The best-effort number of messages needed to trigger a flush. Use + // `MaxMessages` to set a hard upper limit. + Messages int + // The best-effort frequency of flushes. Equivalent to + // `queue.buffering.max.ms` setting of JVM producer. + Frequency time.Duration + // The maximum number of messages the producer will send in a single + // broker request. Defaults to 0 for unlimited. Similar to + // `queue.buffering.max.messages` in the JVM producer. + MaxMessages int + } + + Retry struct { + // The total number of times to retry sending a message (default 3). + // Similar to the `message.send.max.retries` setting of the JVM producer. + Max int + // How long to wait for the cluster to settle between retries + // (default 100ms). Similar to the `retry.backoff.ms` setting of the + // JVM producer. + Backoff time.Duration + } + } + + // Consumer is the namespace for configuration related to consuming messages, + // used by the Consumer. + // + // Note that Sarama's Consumer type does not currently support automatic + // consumer-group rebalancing and offset tracking. For Zookeeper-based + // tracking (Kafka 0.8.2 and earlier), the https://github.com/wvanbergen/kafka + // library builds on Sarama to add this support. For Kafka-based tracking + // (Kafka 0.9 and later), the https://github.com/bsm/sarama-cluster library + // builds on Sarama to add this support. + Consumer struct { + Retry struct { + // How long to wait after a failing to read from a partition before + // trying again (default 2s). + Backoff time.Duration + } + + // Fetch is the namespace for controlling how many bytes are retrieved by any + // given request. + Fetch struct { + // The minimum number of message bytes to fetch in a request - the broker + // will wait until at least this many are available. The default is 1, + // as 0 causes the consumer to spin when no messages are available. + // Equivalent to the JVM's `fetch.min.bytes`. + Min int32 + // The default number of message bytes to fetch from the broker in each + // request (default 32768). This should be larger than the majority of + // your messages, or else the consumer will spend a lot of time + // negotiating sizes and not actually consuming. Similar to the JVM's + // `fetch.message.max.bytes`. + Default int32 + // The maximum number of message bytes to fetch from the broker in a + // single request. Messages larger than this will return + // ErrMessageTooLarge and will not be consumable, so you must be sure + // this is at least as large as your largest message. Defaults to 0 + // (no limit). Similar to the JVM's `fetch.message.max.bytes`. The + // global `sarama.MaxResponseSize` still applies. + Max int32 + } + // The maximum amount of time the broker will wait for Consumer.Fetch.Min + // bytes to become available before it returns fewer than that anyways. The + // default is 250ms, since 0 causes the consumer to spin when no events are + // available. 100-500ms is a reasonable range for most cases. Kafka only + // supports precision up to milliseconds; nanoseconds will be truncated. + // Equivalent to the JVM's `fetch.wait.max.ms`. + MaxWaitTime time.Duration + + // The maximum amount of time the consumer expects a message takes to process + // for the user. If writing to the Messages channel takes longer than this, + // that partition will stop fetching more messages until it can proceed again. + // Note that, since the Messages channel is buffered, the actual grace time is + // (MaxProcessingTime * ChanneBufferSize). Defaults to 100ms. + MaxProcessingTime time.Duration + + // Return specifies what channels will be populated. If they are set to true, + // you must read from them to prevent deadlock. + Return struct { + // If enabled, any errors that occurred while consuming are returned on + // the Errors channel (default disabled). + Errors bool + } + + // Offsets specifies configuration for how and when to commit consumed + // offsets. This currently requires the manual use of an OffsetManager + // but will eventually be automated. + Offsets struct { + // How frequently to commit updated offsets. Defaults to 1s. + CommitInterval time.Duration + + // The initial offset to use if no offset was previously committed. + // Should be OffsetNewest or OffsetOldest. Defaults to OffsetNewest. + Initial int64 + + // The retention duration for committed offsets. If zero, disabled + // (in which case the `offsets.retention.minutes` option on the + // broker will be used). Kafka only supports precision up to + // milliseconds; nanoseconds will be truncated. Requires Kafka + // broker version 0.9.0 or later. + // (default is 0: disabled). + Retention time.Duration + } + } + + // A user-provided string sent with every request to the brokers for logging, + // debugging, and auditing purposes. Defaults to "sarama", but you should + // probably set it to something specific to your application. + ClientID string + // The number of events to buffer in internal and external channels. This + // permits the producer and consumer to continue processing some messages + // in the background while user code is working, greatly improving throughput. + // Defaults to 256. + ChannelBufferSize int + // The version of Kafka that Sarama will assume it is running against. + // Defaults to the oldest supported stable version. Since Kafka provides + // backwards-compatibility, setting it to a version older than you have + // will not break anything, although it may prevent you from using the + // latest features. Setting it to a version greater than you are actually + // running may lead to random breakage. + Version KafkaVersion + // The registry to define metrics into. + // Defaults to a local registry. + // If you want to disable metrics gathering, set "metrics.UseNilMetrics" to "true" + // prior to starting Sarama. + // See Examples on how to use the metrics registry + MetricRegistry metrics.Registry +} + +// NewConfig returns a new configuration instance with sane defaults. +func NewConfig() *Config { + c := &Config{} + + c.Net.MaxOpenRequests = 5 + c.Net.DialTimeout = 30 * time.Second + c.Net.ReadTimeout = 30 * time.Second + c.Net.WriteTimeout = 30 * time.Second + c.Net.SASL.Handshake = true + + c.Metadata.Retry.Max = 3 + c.Metadata.Retry.Backoff = 250 * time.Millisecond + c.Metadata.RefreshFrequency = 10 * time.Minute + + c.Producer.MaxMessageBytes = 1000000 + c.Producer.RequiredAcks = WaitForLocal + c.Producer.Timeout = 10 * time.Second + c.Producer.Partitioner = NewHashPartitioner + c.Producer.Retry.Max = 3 + c.Producer.Retry.Backoff = 100 * time.Millisecond + c.Producer.Return.Errors = true + + c.Consumer.Fetch.Min = 1 + c.Consumer.Fetch.Default = 32768 + c.Consumer.Retry.Backoff = 2 * time.Second + c.Consumer.MaxWaitTime = 250 * time.Millisecond + c.Consumer.MaxProcessingTime = 100 * time.Millisecond + c.Consumer.Return.Errors = false + c.Consumer.Offsets.CommitInterval = 1 * time.Second + c.Consumer.Offsets.Initial = OffsetNewest + + c.ClientID = defaultClientID + c.ChannelBufferSize = 256 + c.Version = minVersion + c.MetricRegistry = metrics.NewRegistry() + + return c +} + +// Validate checks a Config instance. It will return a +// ConfigurationError if the specified values don't make sense. +func (c *Config) Validate() error { + // some configuration values should be warned on but not fail completely, do those first + if c.Net.TLS.Enable == false && c.Net.TLS.Config != nil { + Logger.Println("Net.TLS is disabled but a non-nil configuration was provided.") + } + if c.Net.SASL.Enable == false { + if c.Net.SASL.User != "" { + Logger.Println("Net.SASL is disabled but a non-empty username was provided.") + } + if c.Net.SASL.Password != "" { + Logger.Println("Net.SASL is disabled but a non-empty password was provided.") + } + } + if c.Producer.RequiredAcks > 1 { + Logger.Println("Producer.RequiredAcks > 1 is deprecated and will raise an exception with kafka >= 0.8.2.0.") + } + if c.Producer.MaxMessageBytes >= int(MaxRequestSize) { + Logger.Println("Producer.MaxMessageBytes is larger than MaxRequestSize; it will be ignored.") + } + if c.Producer.Flush.Bytes >= int(MaxRequestSize) { + Logger.Println("Producer.Flush.Bytes is larger than MaxRequestSize; it will be ignored.") + } + if c.Producer.Timeout%time.Millisecond != 0 { + Logger.Println("Producer.Timeout only supports millisecond resolution; nanoseconds will be truncated.") + } + if c.Consumer.MaxWaitTime < 100*time.Millisecond { + Logger.Println("Consumer.MaxWaitTime is very low, which can cause high CPU and network usage. See documentation for details.") + } + if c.Consumer.MaxWaitTime%time.Millisecond != 0 { + Logger.Println("Consumer.MaxWaitTime only supports millisecond precision; nanoseconds will be truncated.") + } + if c.Consumer.Offsets.Retention%time.Millisecond != 0 { + Logger.Println("Consumer.Offsets.Retention only supports millisecond precision; nanoseconds will be truncated.") + } + if c.ClientID == defaultClientID { + Logger.Println("ClientID is the default of 'sarama', you should consider setting it to something application-specific.") + } + + // validate Net values + switch { + case c.Net.MaxOpenRequests <= 0: + return ConfigurationError("Net.MaxOpenRequests must be > 0") + case c.Net.DialTimeout <= 0: + return ConfigurationError("Net.DialTimeout must be > 0") + case c.Net.ReadTimeout <= 0: + return ConfigurationError("Net.ReadTimeout must be > 0") + case c.Net.WriteTimeout <= 0: + return ConfigurationError("Net.WriteTimeout must be > 0") + case c.Net.KeepAlive < 0: + return ConfigurationError("Net.KeepAlive must be >= 0") + case c.Net.SASL.Enable == true && c.Net.SASL.User == "": + return ConfigurationError("Net.SASL.User must not be empty when SASL is enabled") + case c.Net.SASL.Enable == true && c.Net.SASL.Password == "": + return ConfigurationError("Net.SASL.Password must not be empty when SASL is enabled") + } + + // validate the Metadata values + switch { + case c.Metadata.Retry.Max < 0: + return ConfigurationError("Metadata.Retry.Max must be >= 0") + case c.Metadata.Retry.Backoff < 0: + return ConfigurationError("Metadata.Retry.Backoff must be >= 0") + case c.Metadata.RefreshFrequency < 0: + return ConfigurationError("Metadata.RefreshFrequency must be >= 0") + } + + // validate the Producer values + switch { + case c.Producer.MaxMessageBytes <= 0: + return ConfigurationError("Producer.MaxMessageBytes must be > 0") + case c.Producer.RequiredAcks < -1: + return ConfigurationError("Producer.RequiredAcks must be >= -1") + case c.Producer.Timeout <= 0: + return ConfigurationError("Producer.Timeout must be > 0") + case c.Producer.Partitioner == nil: + return ConfigurationError("Producer.Partitioner must not be nil") + case c.Producer.Flush.Bytes < 0: + return ConfigurationError("Producer.Flush.Bytes must be >= 0") + case c.Producer.Flush.Messages < 0: + return ConfigurationError("Producer.Flush.Messages must be >= 0") + case c.Producer.Flush.Frequency < 0: + return ConfigurationError("Producer.Flush.Frequency must be >= 0") + case c.Producer.Flush.MaxMessages < 0: + return ConfigurationError("Producer.Flush.MaxMessages must be >= 0") + case c.Producer.Flush.MaxMessages > 0 && c.Producer.Flush.MaxMessages < c.Producer.Flush.Messages: + return ConfigurationError("Producer.Flush.MaxMessages must be >= Producer.Flush.Messages when set") + case c.Producer.Retry.Max < 0: + return ConfigurationError("Producer.Retry.Max must be >= 0") + case c.Producer.Retry.Backoff < 0: + return ConfigurationError("Producer.Retry.Backoff must be >= 0") + } + + if c.Producer.Compression == CompressionLZ4 && !c.Version.IsAtLeast(V0_10_0_0) { + return ConfigurationError("lz4 compression requires Version >= V0_10_0_0") + } + + // validate the Consumer values + switch { + case c.Consumer.Fetch.Min <= 0: + return ConfigurationError("Consumer.Fetch.Min must be > 0") + case c.Consumer.Fetch.Default <= 0: + return ConfigurationError("Consumer.Fetch.Default must be > 0") + case c.Consumer.Fetch.Max < 0: + return ConfigurationError("Consumer.Fetch.Max must be >= 0") + case c.Consumer.MaxWaitTime < 1*time.Millisecond: + return ConfigurationError("Consumer.MaxWaitTime must be >= 1ms") + case c.Consumer.MaxProcessingTime <= 0: + return ConfigurationError("Consumer.MaxProcessingTime must be > 0") + case c.Consumer.Retry.Backoff < 0: + return ConfigurationError("Consumer.Retry.Backoff must be >= 0") + case c.Consumer.Offsets.CommitInterval <= 0: + return ConfigurationError("Consumer.Offsets.CommitInterval must be > 0") + case c.Consumer.Offsets.Initial != OffsetOldest && c.Consumer.Offsets.Initial != OffsetNewest: + return ConfigurationError("Consumer.Offsets.Initial must be OffsetOldest or OffsetNewest") + + } + + // validate misc shared values + switch { + case c.ChannelBufferSize < 0: + return ConfigurationError("ChannelBufferSize must be >= 0") + case !validID.MatchString(c.ClientID): + return ConfigurationError("ClientID is invalid") + } + + return nil +} diff --git a/vendor/src/github.com/Shopify/sarama/config_test.go b/vendor/src/github.com/Shopify/sarama/config_test.go new file mode 100644 index 00000000..5fef6b36 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/config_test.go @@ -0,0 +1,70 @@ +package sarama + +import ( + "os" + "testing" + + "github.com/rcrowley/go-metrics" +) + +func TestDefaultConfigValidates(t *testing.T) { + config := NewConfig() + if err := config.Validate(); err != nil { + t.Error(err) + } + if config.MetricRegistry == nil { + t.Error("Expected non nil metrics.MetricRegistry, got nil") + } +} + +func TestInvalidClientIDConfigValidates(t *testing.T) { + config := NewConfig() + config.ClientID = "foo:bar" + if err := config.Validate(); string(err.(ConfigurationError)) != "ClientID is invalid" { + t.Error("Expected invalid ClientID, got ", err) + } +} + +func TestEmptyClientIDConfigValidates(t *testing.T) { + config := NewConfig() + config.ClientID = "" + if err := config.Validate(); string(err.(ConfigurationError)) != "ClientID is invalid" { + t.Error("Expected invalid ClientID, got ", err) + } +} + +func TestLZ4ConfigValidation(t *testing.T) { + config := NewConfig() + config.Producer.Compression = CompressionLZ4 + if err := config.Validate(); string(err.(ConfigurationError)) != "lz4 compression requires Version >= V0_10_0_0" { + t.Error("Expected invalid lz4/kakfa version error, got ", err) + } + config.Version = V0_10_0_0 + if err := config.Validate(); err != nil { + t.Error("Expected lz4 to work, got ", err) + } +} + +// This example shows how to integrate with an existing registry as well as publishing metrics +// on the standard output +func ExampleConfig_metrics() { + // Our application registry + appMetricRegistry := metrics.NewRegistry() + appGauge := metrics.GetOrRegisterGauge("m1", appMetricRegistry) + appGauge.Update(1) + + config := NewConfig() + // Use a prefix registry instead of the default local one + config.MetricRegistry = metrics.NewPrefixedChildRegistry(appMetricRegistry, "sarama.") + + // Simulate a metric created by sarama without starting a broker + saramaGauge := metrics.GetOrRegisterGauge("m2", config.MetricRegistry) + saramaGauge.Update(2) + + metrics.WriteOnce(appMetricRegistry, os.Stdout) + // Output: + // gauge m1 + // value: 1 + // gauge sarama.m2 + // value: 2 +} diff --git a/vendor/src/github.com/Shopify/sarama/consumer.go b/vendor/src/github.com/Shopify/sarama/consumer.go new file mode 100644 index 00000000..ddac564f --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/consumer.go @@ -0,0 +1,735 @@ +package sarama + +import ( + "errors" + "fmt" + "sync" + "sync/atomic" + "time" +) + +// ConsumerMessage encapsulates a Kafka message returned by the consumer. +type ConsumerMessage struct { + Key, Value []byte + Topic string + Partition int32 + Offset int64 + Timestamp time.Time // only set if kafka is version 0.10+ +} + +// ConsumerError is what is provided to the user when an error occurs. +// It wraps an error and includes the topic and partition. +type ConsumerError struct { + Topic string + Partition int32 + Err error +} + +func (ce ConsumerError) Error() string { + return fmt.Sprintf("kafka: error while consuming %s/%d: %s", ce.Topic, ce.Partition, ce.Err) +} + +// ConsumerErrors is a type that wraps a batch of errors and implements the Error interface. +// It can be returned from the PartitionConsumer's Close methods to avoid the need to manually drain errors +// when stopping. +type ConsumerErrors []*ConsumerError + +func (ce ConsumerErrors) Error() string { + return fmt.Sprintf("kafka: %d errors while consuming", len(ce)) +} + +// Consumer manages PartitionConsumers which process Kafka messages from brokers. You MUST call Close() +// on a consumer to avoid leaks, it will not be garbage-collected automatically when it passes out of +// scope. +// +// Sarama's Consumer type does not currently support automatic consumer-group rebalancing and offset tracking. +// For Zookeeper-based tracking (Kafka 0.8.2 and earlier), the https://github.com/wvanbergen/kafka library +// builds on Sarama to add this support. For Kafka-based tracking (Kafka 0.9 and later), the +// https://github.com/bsm/sarama-cluster library builds on Sarama to add this support. +type Consumer interface { + + // Topics returns the set of available topics as retrieved from the cluster + // metadata. This method is the same as Client.Topics(), and is provided for + // convenience. + Topics() ([]string, error) + + // Partitions returns the sorted list of all partition IDs for the given topic. + // This method is the same as Client.Partitions(), and is provided for convenience. + Partitions(topic string) ([]int32, error) + + // ConsumePartition creates a PartitionConsumer on the given topic/partition with + // the given offset. It will return an error if this Consumer is already consuming + // on the given topic/partition. Offset can be a literal offset, or OffsetNewest + // or OffsetOldest + ConsumePartition(topic string, partition int32, offset int64) (PartitionConsumer, error) + + // HighWaterMarks returns the current high water marks for each topic and partition. + // Consistency between partitions is not guaranteed since high water marks are updated separately. + HighWaterMarks() map[string]map[int32]int64 + + // Close shuts down the consumer. It must be called after all child + // PartitionConsumers have already been closed. + Close() error +} + +type consumer struct { + client Client + conf *Config + ownClient bool + + lock sync.Mutex + children map[string]map[int32]*partitionConsumer + brokerConsumers map[*Broker]*brokerConsumer +} + +// NewConsumer creates a new consumer using the given broker addresses and configuration. +func NewConsumer(addrs []string, config *Config) (Consumer, error) { + client, err := NewClient(addrs, config) + if err != nil { + return nil, err + } + + c, err := NewConsumerFromClient(client) + if err != nil { + return nil, err + } + c.(*consumer).ownClient = true + return c, nil +} + +// NewConsumerFromClient creates a new consumer using the given client. It is still +// necessary to call Close() on the underlying client when shutting down this consumer. +func NewConsumerFromClient(client Client) (Consumer, error) { + // Check that we are not dealing with a closed Client before processing any other arguments + if client.Closed() { + return nil, ErrClosedClient + } + + c := &consumer{ + client: client, + conf: client.Config(), + children: make(map[string]map[int32]*partitionConsumer), + brokerConsumers: make(map[*Broker]*brokerConsumer), + } + + return c, nil +} + +func (c *consumer) Close() error { + if c.ownClient { + return c.client.Close() + } + return nil +} + +func (c *consumer) Topics() ([]string, error) { + return c.client.Topics() +} + +func (c *consumer) Partitions(topic string) ([]int32, error) { + return c.client.Partitions(topic) +} + +func (c *consumer) ConsumePartition(topic string, partition int32, offset int64) (PartitionConsumer, error) { + child := &partitionConsumer{ + consumer: c, + conf: c.conf, + topic: topic, + partition: partition, + messages: make(chan *ConsumerMessage, c.conf.ChannelBufferSize), + errors: make(chan *ConsumerError, c.conf.ChannelBufferSize), + feeder: make(chan *FetchResponse, 1), + trigger: make(chan none, 1), + dying: make(chan none), + fetchSize: c.conf.Consumer.Fetch.Default, + } + + if err := child.chooseStartingOffset(offset); err != nil { + return nil, err + } + + var leader *Broker + var err error + if leader, err = c.client.Leader(child.topic, child.partition); err != nil { + return nil, err + } + + if err := c.addChild(child); err != nil { + return nil, err + } + + go withRecover(child.dispatcher) + go withRecover(child.responseFeeder) + + child.broker = c.refBrokerConsumer(leader) + child.broker.input <- child + + return child, nil +} + +func (c *consumer) HighWaterMarks() map[string]map[int32]int64 { + c.lock.Lock() + defer c.lock.Unlock() + + hwms := make(map[string]map[int32]int64) + for topic, p := range c.children { + hwm := make(map[int32]int64, len(p)) + for partition, pc := range p { + hwm[partition] = pc.HighWaterMarkOffset() + } + hwms[topic] = hwm + } + + return hwms +} + +func (c *consumer) addChild(child *partitionConsumer) error { + c.lock.Lock() + defer c.lock.Unlock() + + topicChildren := c.children[child.topic] + if topicChildren == nil { + topicChildren = make(map[int32]*partitionConsumer) + c.children[child.topic] = topicChildren + } + + if topicChildren[child.partition] != nil { + return ConfigurationError("That topic/partition is already being consumed") + } + + topicChildren[child.partition] = child + return nil +} + +func (c *consumer) removeChild(child *partitionConsumer) { + c.lock.Lock() + defer c.lock.Unlock() + + delete(c.children[child.topic], child.partition) +} + +func (c *consumer) refBrokerConsumer(broker *Broker) *brokerConsumer { + c.lock.Lock() + defer c.lock.Unlock() + + bc := c.brokerConsumers[broker] + if bc == nil { + bc = c.newBrokerConsumer(broker) + c.brokerConsumers[broker] = bc + } + + bc.refs++ + + return bc +} + +func (c *consumer) unrefBrokerConsumer(brokerWorker *brokerConsumer) { + c.lock.Lock() + defer c.lock.Unlock() + + brokerWorker.refs-- + + if brokerWorker.refs == 0 { + close(brokerWorker.input) + if c.brokerConsumers[brokerWorker.broker] == brokerWorker { + delete(c.brokerConsumers, brokerWorker.broker) + } + } +} + +func (c *consumer) abandonBrokerConsumer(brokerWorker *brokerConsumer) { + c.lock.Lock() + defer c.lock.Unlock() + + delete(c.brokerConsumers, brokerWorker.broker) +} + +// PartitionConsumer + +// PartitionConsumer processes Kafka messages from a given topic and partition. You MUST call Close() +// or AsyncClose() on a PartitionConsumer to avoid leaks, it will not be garbage-collected automatically +// when it passes out of scope. +// +// The simplest way of using a PartitionConsumer is to loop over its Messages channel using a for/range +// loop. The PartitionConsumer will only stop itself in one case: when the offset being consumed is reported +// as out of range by the brokers. In this case you should decide what you want to do (try a different offset, +// notify a human, etc) and handle it appropriately. For all other error cases, it will just keep retrying. +// By default, it logs these errors to sarama.Logger; if you want to be notified directly of all errors, set +// your config's Consumer.Return.Errors to true and read from the Errors channel, using a select statement +// or a separate goroutine. Check out the Consumer examples to see implementations of these different approaches. +type PartitionConsumer interface { + + // AsyncClose initiates a shutdown of the PartitionConsumer. This method will + // return immediately, after which you should wait until the 'messages' and + // 'errors' channel are drained. It is required to call this function, or + // Close before a consumer object passes out of scope, as it will otherwise + // leak memory. You must call this before calling Close on the underlying client. + AsyncClose() + + // Close stops the PartitionConsumer from fetching messages. It is required to + // call this function (or AsyncClose) before a consumer object passes out of + // scope, as it will otherwise leak memory. You must call this before calling + // Close on the underlying client. + Close() error + + // Messages returns the read channel for the messages that are returned by + // the broker. + Messages() <-chan *ConsumerMessage + + // Errors returns a read channel of errors that occurred during consuming, if + // enabled. By default, errors are logged and not returned over this channel. + // If you want to implement any custom error handling, set your config's + // Consumer.Return.Errors setting to true, and read from this channel. + Errors() <-chan *ConsumerError + + // HighWaterMarkOffset returns the high water mark offset of the partition, + // i.e. the offset that will be used for the next message that will be produced. + // You can use this to determine how far behind the processing is. + HighWaterMarkOffset() int64 +} + +type partitionConsumer struct { + consumer *consumer + conf *Config + topic string + partition int32 + + broker *brokerConsumer + messages chan *ConsumerMessage + errors chan *ConsumerError + feeder chan *FetchResponse + + trigger, dying chan none + responseResult error + + fetchSize int32 + offset int64 + highWaterMarkOffset int64 +} + +var errTimedOut = errors.New("timed out feeding messages to the user") // not user-facing + +func (child *partitionConsumer) sendError(err error) { + cErr := &ConsumerError{ + Topic: child.topic, + Partition: child.partition, + Err: err, + } + + if child.conf.Consumer.Return.Errors { + child.errors <- cErr + } else { + Logger.Println(cErr) + } +} + +func (child *partitionConsumer) dispatcher() { + for _ = range child.trigger { + select { + case <-child.dying: + close(child.trigger) + case <-time.After(child.conf.Consumer.Retry.Backoff): + if child.broker != nil { + child.consumer.unrefBrokerConsumer(child.broker) + child.broker = nil + } + + Logger.Printf("consumer/%s/%d finding new broker\n", child.topic, child.partition) + if err := child.dispatch(); err != nil { + child.sendError(err) + child.trigger <- none{} + } + } + } + + if child.broker != nil { + child.consumer.unrefBrokerConsumer(child.broker) + } + child.consumer.removeChild(child) + close(child.feeder) +} + +func (child *partitionConsumer) dispatch() error { + if err := child.consumer.client.RefreshMetadata(child.topic); err != nil { + return err + } + + var leader *Broker + var err error + if leader, err = child.consumer.client.Leader(child.topic, child.partition); err != nil { + return err + } + + child.broker = child.consumer.refBrokerConsumer(leader) + + child.broker.input <- child + + return nil +} + +func (child *partitionConsumer) chooseStartingOffset(offset int64) error { + newestOffset, err := child.consumer.client.GetOffset(child.topic, child.partition, OffsetNewest) + if err != nil { + return err + } + oldestOffset, err := child.consumer.client.GetOffset(child.topic, child.partition, OffsetOldest) + if err != nil { + return err + } + + switch { + case offset == OffsetNewest: + child.offset = newestOffset + case offset == OffsetOldest: + child.offset = oldestOffset + case offset >= oldestOffset && offset <= newestOffset: + child.offset = offset + default: + return ErrOffsetOutOfRange + } + + return nil +} + +func (child *partitionConsumer) Messages() <-chan *ConsumerMessage { + return child.messages +} + +func (child *partitionConsumer) Errors() <-chan *ConsumerError { + return child.errors +} + +func (child *partitionConsumer) AsyncClose() { + // this triggers whatever broker owns this child to abandon it and close its trigger channel, which causes + // the dispatcher to exit its loop, which removes it from the consumer then closes its 'messages' and + // 'errors' channel (alternatively, if the child is already at the dispatcher for some reason, that will + // also just close itself) + close(child.dying) +} + +func (child *partitionConsumer) Close() error { + child.AsyncClose() + + go withRecover(func() { + for _ = range child.messages { + // drain + } + }) + + var errors ConsumerErrors + for err := range child.errors { + errors = append(errors, err) + } + + if len(errors) > 0 { + return errors + } + return nil +} + +func (child *partitionConsumer) HighWaterMarkOffset() int64 { + return atomic.LoadInt64(&child.highWaterMarkOffset) +} + +func (child *partitionConsumer) responseFeeder() { + var msgs []*ConsumerMessage + expiryTimer := time.NewTimer(child.conf.Consumer.MaxProcessingTime) + expireTimedOut := false + +feederLoop: + for response := range child.feeder { + msgs, child.responseResult = child.parseResponse(response) + + for i, msg := range msgs { + if !expiryTimer.Stop() && !expireTimedOut { + // expiryTimer was expired; clear out the waiting msg + <-expiryTimer.C + } + expiryTimer.Reset(child.conf.Consumer.MaxProcessingTime) + expireTimedOut = false + + select { + case child.messages <- msg: + case <-expiryTimer.C: + expireTimedOut = true + child.responseResult = errTimedOut + child.broker.acks.Done() + for _, msg = range msgs[i:] { + child.messages <- msg + } + child.broker.input <- child + continue feederLoop + } + } + + child.broker.acks.Done() + } + + close(child.messages) + close(child.errors) +} + +func (child *partitionConsumer) parseResponse(response *FetchResponse) ([]*ConsumerMessage, error) { + block := response.GetBlock(child.topic, child.partition) + if block == nil { + return nil, ErrIncompleteResponse + } + + if block.Err != ErrNoError { + return nil, block.Err + } + + if len(block.MsgSet.Messages) == 0 { + // We got no messages. If we got a trailing one then we need to ask for more data. + // Otherwise we just poll again and wait for one to be produced... + if block.MsgSet.PartialTrailingMessage { + if child.conf.Consumer.Fetch.Max > 0 && child.fetchSize == child.conf.Consumer.Fetch.Max { + // we can't ask for more data, we've hit the configured limit + child.sendError(ErrMessageTooLarge) + child.offset++ // skip this one so we can keep processing future messages + } else { + child.fetchSize *= 2 + if child.conf.Consumer.Fetch.Max > 0 && child.fetchSize > child.conf.Consumer.Fetch.Max { + child.fetchSize = child.conf.Consumer.Fetch.Max + } + } + } + + return nil, nil + } + + // we got messages, reset our fetch size in case it was increased for a previous request + child.fetchSize = child.conf.Consumer.Fetch.Default + atomic.StoreInt64(&child.highWaterMarkOffset, block.HighWaterMarkOffset) + + incomplete := false + prelude := true + var messages []*ConsumerMessage + for _, msgBlock := range block.MsgSet.Messages { + + for _, msg := range msgBlock.Messages() { + offset := msg.Offset + if msg.Msg.Version >= 1 { + baseOffset := msgBlock.Offset - msgBlock.Messages()[len(msgBlock.Messages())-1].Offset + offset += baseOffset + } + if prelude && offset < child.offset { + continue + } + prelude = false + + if offset >= child.offset { + messages = append(messages, &ConsumerMessage{ + Topic: child.topic, + Partition: child.partition, + Key: msg.Msg.Key, + Value: msg.Msg.Value, + Offset: offset, + Timestamp: msg.Msg.Timestamp, + }) + child.offset = offset + 1 + } else { + incomplete = true + } + } + + } + + if incomplete || len(messages) == 0 { + return nil, ErrIncompleteResponse + } + return messages, nil +} + +// brokerConsumer + +type brokerConsumer struct { + consumer *consumer + broker *Broker + input chan *partitionConsumer + newSubscriptions chan []*partitionConsumer + wait chan none + subscriptions map[*partitionConsumer]none + acks sync.WaitGroup + refs int +} + +func (c *consumer) newBrokerConsumer(broker *Broker) *brokerConsumer { + bc := &brokerConsumer{ + consumer: c, + broker: broker, + input: make(chan *partitionConsumer), + newSubscriptions: make(chan []*partitionConsumer), + wait: make(chan none), + subscriptions: make(map[*partitionConsumer]none), + refs: 0, + } + + go withRecover(bc.subscriptionManager) + go withRecover(bc.subscriptionConsumer) + + return bc +} + +func (bc *brokerConsumer) subscriptionManager() { + var buffer []*partitionConsumer + + // The subscriptionManager constantly accepts new subscriptions on `input` (even when the main subscriptionConsumer + // goroutine is in the middle of a network request) and batches it up. The main worker goroutine picks + // up a batch of new subscriptions between every network request by reading from `newSubscriptions`, so we give + // it nil if no new subscriptions are available. We also write to `wait` only when new subscriptions is available, + // so the main goroutine can block waiting for work if it has none. + for { + if len(buffer) > 0 { + select { + case event, ok := <-bc.input: + if !ok { + goto done + } + buffer = append(buffer, event) + case bc.newSubscriptions <- buffer: + buffer = nil + case bc.wait <- none{}: + } + } else { + select { + case event, ok := <-bc.input: + if !ok { + goto done + } + buffer = append(buffer, event) + case bc.newSubscriptions <- nil: + } + } + } + +done: + close(bc.wait) + if len(buffer) > 0 { + bc.newSubscriptions <- buffer + } + close(bc.newSubscriptions) +} + +func (bc *brokerConsumer) subscriptionConsumer() { + <-bc.wait // wait for our first piece of work + + // the subscriptionConsumer ensures we will get nil right away if no new subscriptions is available + for newSubscriptions := range bc.newSubscriptions { + bc.updateSubscriptions(newSubscriptions) + + if len(bc.subscriptions) == 0 { + // We're about to be shut down or we're about to receive more subscriptions. + // Either way, the signal just hasn't propagated to our goroutine yet. + <-bc.wait + continue + } + + response, err := bc.fetchNewMessages() + + if err != nil { + Logger.Printf("consumer/broker/%d disconnecting due to error processing FetchRequest: %s\n", bc.broker.ID(), err) + bc.abort(err) + return + } + + bc.acks.Add(len(bc.subscriptions)) + for child := range bc.subscriptions { + child.feeder <- response + } + bc.acks.Wait() + bc.handleResponses() + } +} + +func (bc *brokerConsumer) updateSubscriptions(newSubscriptions []*partitionConsumer) { + for _, child := range newSubscriptions { + bc.subscriptions[child] = none{} + Logger.Printf("consumer/broker/%d added subscription to %s/%d\n", bc.broker.ID(), child.topic, child.partition) + } + + for child := range bc.subscriptions { + select { + case <-child.dying: + Logger.Printf("consumer/broker/%d closed dead subscription to %s/%d\n", bc.broker.ID(), child.topic, child.partition) + close(child.trigger) + delete(bc.subscriptions, child) + default: + break + } + } +} + +func (bc *brokerConsumer) handleResponses() { + // handles the response codes left for us by our subscriptions, and abandons ones that have been closed + for child := range bc.subscriptions { + result := child.responseResult + child.responseResult = nil + + switch result { + case nil: + break + case errTimedOut: + Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because consuming was taking too long\n", + bc.broker.ID(), child.topic, child.partition) + delete(bc.subscriptions, child) + case ErrOffsetOutOfRange: + // there's no point in retrying this it will just fail the same way again + // shut it down and force the user to choose what to do + child.sendError(result) + Logger.Printf("consumer/%s/%d shutting down because %s\n", child.topic, child.partition, result) + close(child.trigger) + delete(bc.subscriptions, child) + case ErrUnknownTopicOrPartition, ErrNotLeaderForPartition, ErrLeaderNotAvailable, ErrReplicaNotAvailable: + // not an error, but does need redispatching + Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because %s\n", + bc.broker.ID(), child.topic, child.partition, result) + child.trigger <- none{} + delete(bc.subscriptions, child) + default: + // dunno, tell the user and try redispatching + child.sendError(result) + Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because %s\n", + bc.broker.ID(), child.topic, child.partition, result) + child.trigger <- none{} + delete(bc.subscriptions, child) + } + } +} + +func (bc *brokerConsumer) abort(err error) { + bc.consumer.abandonBrokerConsumer(bc) + _ = bc.broker.Close() // we don't care about the error this might return, we already have one + + for child := range bc.subscriptions { + child.sendError(err) + child.trigger <- none{} + } + + for newSubscriptions := range bc.newSubscriptions { + if len(newSubscriptions) == 0 { + <-bc.wait + continue + } + for _, child := range newSubscriptions { + child.sendError(err) + child.trigger <- none{} + } + } +} + +func (bc *brokerConsumer) fetchNewMessages() (*FetchResponse, error) { + request := &FetchRequest{ + MinBytes: bc.consumer.conf.Consumer.Fetch.Min, + MaxWaitTime: int32(bc.consumer.conf.Consumer.MaxWaitTime / time.Millisecond), + } + if bc.consumer.conf.Version.IsAtLeast(V0_10_0_0) { + request.Version = 2 + } + + for child := range bc.subscriptions { + request.AddBlock(child.topic, child.partition, child.offset, child.fetchSize) + } + + return bc.broker.Fetch(request) +} diff --git a/vendor/src/github.com/Shopify/sarama/consumer_group_members.go b/vendor/src/github.com/Shopify/sarama/consumer_group_members.go new file mode 100644 index 00000000..9d92d350 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/consumer_group_members.go @@ -0,0 +1,94 @@ +package sarama + +type ConsumerGroupMemberMetadata struct { + Version int16 + Topics []string + UserData []byte +} + +func (m *ConsumerGroupMemberMetadata) encode(pe packetEncoder) error { + pe.putInt16(m.Version) + + if err := pe.putStringArray(m.Topics); err != nil { + return err + } + + if err := pe.putBytes(m.UserData); err != nil { + return err + } + + return nil +} + +func (m *ConsumerGroupMemberMetadata) decode(pd packetDecoder) (err error) { + if m.Version, err = pd.getInt16(); err != nil { + return + } + + if m.Topics, err = pd.getStringArray(); err != nil { + return + } + + if m.UserData, err = pd.getBytes(); err != nil { + return + } + + return nil +} + +type ConsumerGroupMemberAssignment struct { + Version int16 + Topics map[string][]int32 + UserData []byte +} + +func (m *ConsumerGroupMemberAssignment) encode(pe packetEncoder) error { + pe.putInt16(m.Version) + + if err := pe.putArrayLength(len(m.Topics)); err != nil { + return err + } + + for topic, partitions := range m.Topics { + if err := pe.putString(topic); err != nil { + return err + } + if err := pe.putInt32Array(partitions); err != nil { + return err + } + } + + if err := pe.putBytes(m.UserData); err != nil { + return err + } + + return nil +} + +func (m *ConsumerGroupMemberAssignment) decode(pd packetDecoder) (err error) { + if m.Version, err = pd.getInt16(); err != nil { + return + } + + var topicLen int + if topicLen, err = pd.getArrayLength(); err != nil { + return + } + + m.Topics = make(map[string][]int32, topicLen) + for i := 0; i < topicLen; i++ { + var topic string + if topic, err = pd.getString(); err != nil { + return + } + if m.Topics[topic], err = pd.getInt32Array(); err != nil { + return + } + } + + if m.UserData, err = pd.getBytes(); err != nil { + return + } + + return nil +} diff --git a/vendor/src/github.com/Shopify/sarama/consumer_group_members_test.go b/vendor/src/github.com/Shopify/sarama/consumer_group_members_test.go new file mode 100644 index 00000000..164e07ef --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/consumer_group_members_test.go @@ -0,0 +1,73 @@ +package sarama + +import ( + "bytes" + "reflect" + "testing" +) + +var ( + groupMemberMetadata = []byte{ + 0, 1, // Version + 0, 0, 0, 2, // Topic array length + 0, 3, 'o', 'n', 'e', // Topic one + 0, 3, 't', 'w', 'o', // Topic two + 0, 0, 0, 3, 0x01, 0x02, 0x03, // Userdata + } + groupMemberAssignment = []byte{ + 0, 1, // Version + 0, 0, 0, 1, // Topic array length + 0, 3, 'o', 'n', 'e', // Topic one + 0, 0, 0, 3, // Topic one, partition array length + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 4, // 0, 2, 4 + 0, 0, 0, 3, 0x01, 0x02, 0x03, // Userdata + } +) + +func TestConsumerGroupMemberMetadata(t *testing.T) { + meta := &ConsumerGroupMemberMetadata{ + Version: 1, + Topics: []string{"one", "two"}, + UserData: []byte{0x01, 0x02, 0x03}, + } + + buf, err := encode(meta, nil) + if err != nil { + t.Error("Failed to encode data", err) + } else if !bytes.Equal(groupMemberMetadata, buf) { + t.Errorf("Encoded data does not match expectation\nexpected: %v\nactual: %v", groupMemberMetadata, buf) + } + + meta2 := new(ConsumerGroupMemberMetadata) + err = decode(buf, meta2) + if err != nil { + t.Error("Failed to decode data", err) + } else if !reflect.DeepEqual(meta, meta2) { + t.Errorf("Encoded data does not match expectation\nexpected: %v\nactual: %v", meta, meta2) + } +} + +func TestConsumerGroupMemberAssignment(t *testing.T) { + amt := &ConsumerGroupMemberAssignment{ + Version: 1, + Topics: map[string][]int32{ + "one": []int32{0, 2, 4}, + }, + UserData: []byte{0x01, 0x02, 0x03}, + } + + buf, err := encode(amt, nil) + if err != nil { + t.Error("Failed to encode data", err) + } else if !bytes.Equal(groupMemberAssignment, buf) { + t.Errorf("Encoded data does not match expectation\nexpected: %v\nactual: %v", groupMemberAssignment, buf) + } + + amt2 := new(ConsumerGroupMemberAssignment) + err = decode(buf, amt2) + if err != nil { + t.Error("Failed to decode data", err) + } else if !reflect.DeepEqual(amt, amt2) { + t.Errorf("Encoded data does not match expectation\nexpected: %v\nactual: %v", amt, amt2) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/consumer_metadata_request.go b/vendor/src/github.com/Shopify/sarama/consumer_metadata_request.go new file mode 100644 index 00000000..483be335 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/consumer_metadata_request.go @@ -0,0 +1,26 @@ +package sarama + +type ConsumerMetadataRequest struct { + ConsumerGroup string +} + +func (r *ConsumerMetadataRequest) encode(pe packetEncoder) error { + return pe.putString(r.ConsumerGroup) +} + +func (r *ConsumerMetadataRequest) decode(pd packetDecoder, version int16) (err error) { + r.ConsumerGroup, err = pd.getString() + return err +} + +func (r *ConsumerMetadataRequest) key() int16 { + return 10 +} + +func (r *ConsumerMetadataRequest) version() int16 { + return 0 +} + +func (r *ConsumerMetadataRequest) requiredVersion() KafkaVersion { + return V0_8_2_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/consumer_metadata_request_test.go b/vendor/src/github.com/Shopify/sarama/consumer_metadata_request_test.go new file mode 100644 index 00000000..4509631a --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/consumer_metadata_request_test.go @@ -0,0 +1,19 @@ +package sarama + +import "testing" + +var ( + consumerMetadataRequestEmpty = []byte{ + 0x00, 0x00} + + consumerMetadataRequestString = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r'} +) + +func TestConsumerMetadataRequest(t *testing.T) { + request := new(ConsumerMetadataRequest) + testRequest(t, "empty string", request, consumerMetadataRequestEmpty) + + request.ConsumerGroup = "foobar" + testRequest(t, "with string", request, consumerMetadataRequestString) +} diff --git a/vendor/src/github.com/Shopify/sarama/consumer_metadata_response.go b/vendor/src/github.com/Shopify/sarama/consumer_metadata_response.go new file mode 100644 index 00000000..6b9632bb --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/consumer_metadata_response.go @@ -0,0 +1,85 @@ +package sarama + +import ( + "net" + "strconv" +) + +type ConsumerMetadataResponse struct { + Err KError + Coordinator *Broker + CoordinatorID int32 // deprecated: use Coordinator.ID() + CoordinatorHost string // deprecated: use Coordinator.Addr() + CoordinatorPort int32 // deprecated: use Coordinator.Addr() +} + +func (r *ConsumerMetadataResponse) decode(pd packetDecoder, version int16) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + r.Err = KError(tmp) + + coordinator := new(Broker) + if err := coordinator.decode(pd); err != nil { + return err + } + if coordinator.addr == ":0" { + return nil + } + r.Coordinator = coordinator + + // this can all go away in 2.0, but we have to fill in deprecated fields to maintain + // backwards compatibility + host, portstr, err := net.SplitHostPort(r.Coordinator.Addr()) + if err != nil { + return err + } + port, err := strconv.ParseInt(portstr, 10, 32) + if err != nil { + return err + } + r.CoordinatorID = r.Coordinator.ID() + r.CoordinatorHost = host + r.CoordinatorPort = int32(port) + + return nil +} + +func (r *ConsumerMetadataResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + if r.Coordinator != nil { + host, portstr, err := net.SplitHostPort(r.Coordinator.Addr()) + if err != nil { + return err + } + port, err := strconv.ParseInt(portstr, 10, 32) + if err != nil { + return err + } + pe.putInt32(r.Coordinator.ID()) + if err := pe.putString(host); err != nil { + return err + } + pe.putInt32(int32(port)) + return nil + } + pe.putInt32(r.CoordinatorID) + if err := pe.putString(r.CoordinatorHost); err != nil { + return err + } + pe.putInt32(r.CoordinatorPort) + return nil +} + +func (r *ConsumerMetadataResponse) key() int16 { + return 10 +} + +func (r *ConsumerMetadataResponse) version() int16 { + return 0 +} + +func (r *ConsumerMetadataResponse) requiredVersion() KafkaVersion { + return V0_8_2_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/consumer_metadata_response_test.go b/vendor/src/github.com/Shopify/sarama/consumer_metadata_response_test.go new file mode 100644 index 00000000..b748784d --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/consumer_metadata_response_test.go @@ -0,0 +1,35 @@ +package sarama + +import "testing" + +var ( + consumerMetadataResponseError = []byte{ + 0x00, 0x0E, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} + + consumerMetadataResponseSuccess = []byte{ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0xAB, + 0x00, 0x03, 'f', 'o', 'o', + 0x00, 0x00, 0xCC, 0xDD} +) + +func TestConsumerMetadataResponseError(t *testing.T) { + response := ConsumerMetadataResponse{Err: ErrOffsetsLoadInProgress} + testResponse(t, "error", &response, consumerMetadataResponseError) +} + +func TestConsumerMetadataResponseSuccess(t *testing.T) { + broker := NewBroker("foo:52445") + broker.id = 0xAB + response := ConsumerMetadataResponse{ + Coordinator: broker, + CoordinatorID: 0xAB, + CoordinatorHost: "foo", + CoordinatorPort: 0xCCDD, + Err: ErrNoError, + } + testResponse(t, "success", &response, consumerMetadataResponseSuccess) +} diff --git a/vendor/src/github.com/Shopify/sarama/consumer_test.go b/vendor/src/github.com/Shopify/sarama/consumer_test.go new file mode 100644 index 00000000..387ede31 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/consumer_test.go @@ -0,0 +1,854 @@ +package sarama + +import ( + "log" + "os" + "os/signal" + "sync" + "testing" + "time" +) + +var testMsg = StringEncoder("Foo") + +// If a particular offset is provided then messages are consumed starting from +// that offset. +func TestConsumerOffsetManual(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + + mockFetchResponse := NewMockFetchResponse(t, 1) + for i := 0; i < 10; i++ { + mockFetchResponse.SetMessage("my_topic", 0, int64(i+1234), testMsg) + } + + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 0). + SetOffset("my_topic", 0, OffsetNewest, 2345), + "FetchRequest": mockFetchResponse, + }) + + // When + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + consumer, err := master.ConsumePartition("my_topic", 0, 1234) + if err != nil { + t.Fatal(err) + } + + // Then: messages starting from offset 1234 are consumed. + for i := 0; i < 10; i++ { + select { + case message := <-consumer.Messages(): + assertMessageOffset(t, message, int64(i+1234)) + case err := <-consumer.Errors(): + t.Error(err) + } + } + + safeClose(t, consumer) + safeClose(t, master) + broker0.Close() +} + +// If `OffsetNewest` is passed as the initial offset then the first consumed +// message is indeed corresponds to the offset that broker claims to be the +// newest in its metadata response. +func TestConsumerOffsetNewest(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetNewest, 10). + SetOffset("my_topic", 0, OffsetOldest, 7), + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 9, testMsg). + SetMessage("my_topic", 0, 10, testMsg). + SetMessage("my_topic", 0, 11, testMsg). + SetHighWaterMark("my_topic", 0, 14), + }) + + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When + consumer, err := master.ConsumePartition("my_topic", 0, OffsetNewest) + if err != nil { + t.Fatal(err) + } + + // Then + assertMessageOffset(t, <-consumer.Messages(), 10) + if hwmo := consumer.HighWaterMarkOffset(); hwmo != 14 { + t.Errorf("Expected high water mark offset 14, found %d", hwmo) + } + + safeClose(t, consumer) + safeClose(t, master) + broker0.Close() +} + +// It is possible to close a partition consumer and create the same anew. +func TestConsumerRecreate(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 0). + SetOffset("my_topic", 0, OffsetNewest, 1000), + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 10, testMsg), + }) + + c, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + pc, err := c.ConsumePartition("my_topic", 0, 10) + if err != nil { + t.Fatal(err) + } + assertMessageOffset(t, <-pc.Messages(), 10) + + // When + safeClose(t, pc) + pc, err = c.ConsumePartition("my_topic", 0, 10) + if err != nil { + t.Fatal(err) + } + + // Then + assertMessageOffset(t, <-pc.Messages(), 10) + + safeClose(t, pc) + safeClose(t, c) + broker0.Close() +} + +// An attempt to consume the same partition twice should fail. +func TestConsumerDuplicate(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 0). + SetOffset("my_topic", 0, OffsetNewest, 1000), + "FetchRequest": NewMockFetchResponse(t, 1), + }) + + config := NewConfig() + config.ChannelBufferSize = 0 + c, err := NewConsumer([]string{broker0.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + pc1, err := c.ConsumePartition("my_topic", 0, 0) + if err != nil { + t.Fatal(err) + } + + // When + pc2, err := c.ConsumePartition("my_topic", 0, 0) + + // Then + if pc2 != nil || err != ConfigurationError("That topic/partition is already being consumed") { + t.Fatal("A partition cannot be consumed twice at the same time") + } + + safeClose(t, pc1) + safeClose(t, c) + broker0.Close() +} + +// If consumer fails to refresh metadata it keeps retrying with frequency +// specified by `Config.Consumer.Retry.Backoff`. +func TestConsumerLeaderRefreshError(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 100) + + // Stage 1: my_topic/0 served by broker0 + Logger.Printf(" STAGE 1") + + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 123). + SetOffset("my_topic", 0, OffsetNewest, 1000), + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 123, testMsg), + }) + + config := NewConfig() + config.Net.ReadTimeout = 100 * time.Millisecond + config.Consumer.Retry.Backoff = 200 * time.Millisecond + config.Consumer.Return.Errors = true + config.Metadata.Retry.Max = 0 + c, err := NewConsumer([]string{broker0.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + pc, err := c.ConsumePartition("my_topic", 0, OffsetOldest) + if err != nil { + t.Fatal(err) + } + + assertMessageOffset(t, <-pc.Messages(), 123) + + // Stage 2: broker0 says that it is no longer the leader for my_topic/0, + // but the requests to retrieve metadata fail with network timeout. + Logger.Printf(" STAGE 2") + + fetchResponse2 := &FetchResponse{} + fetchResponse2.AddError("my_topic", 0, ErrNotLeaderForPartition) + + broker0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": NewMockWrapper(fetchResponse2), + }) + + if consErr := <-pc.Errors(); consErr.Err != ErrOutOfBrokers { + t.Errorf("Unexpected error: %v", consErr.Err) + } + + // Stage 3: finally the metadata returned by broker0 tells that broker1 is + // a new leader for my_topic/0. Consumption resumes. + + Logger.Printf(" STAGE 3") + + broker1 := NewMockBroker(t, 101) + + broker1.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 124, testMsg), + }) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetBroker(broker1.Addr(), broker1.BrokerID()). + SetLeader("my_topic", 0, broker1.BrokerID()), + }) + + assertMessageOffset(t, <-pc.Messages(), 124) + + safeClose(t, pc) + safeClose(t, c) + broker1.Close() + broker0.Close() +} + +func TestConsumerInvalidTopic(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 100) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()), + }) + + c, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When + pc, err := c.ConsumePartition("my_topic", 0, OffsetOldest) + + // Then + if pc != nil || err != ErrUnknownTopicOrPartition { + t.Errorf("Should fail with, err=%v", err) + } + + safeClose(t, c) + broker0.Close() +} + +// Nothing bad happens if a partition consumer that has no leader assigned at +// the moment is closed. +func TestConsumerClosePartitionWithoutLeader(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 100) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 123). + SetOffset("my_topic", 0, OffsetNewest, 1000), + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 123, testMsg), + }) + + config := NewConfig() + config.Net.ReadTimeout = 100 * time.Millisecond + config.Consumer.Retry.Backoff = 100 * time.Millisecond + config.Consumer.Return.Errors = true + config.Metadata.Retry.Max = 0 + c, err := NewConsumer([]string{broker0.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + pc, err := c.ConsumePartition("my_topic", 0, OffsetOldest) + if err != nil { + t.Fatal(err) + } + + assertMessageOffset(t, <-pc.Messages(), 123) + + // broker0 says that it is no longer the leader for my_topic/0, but the + // requests to retrieve metadata fail with network timeout. + fetchResponse2 := &FetchResponse{} + fetchResponse2.AddError("my_topic", 0, ErrNotLeaderForPartition) + + broker0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": NewMockWrapper(fetchResponse2), + }) + + // When + if consErr := <-pc.Errors(); consErr.Err != ErrOutOfBrokers { + t.Errorf("Unexpected error: %v", consErr.Err) + } + + // Then: the partition consumer can be closed without any problem. + safeClose(t, pc) + safeClose(t, c) + broker0.Close() +} + +// If the initial offset passed on partition consumer creation is out of the +// actual offset range for the partition, then the partition consumer stops +// immediately closing its output channels. +func TestConsumerShutsDownOutOfRange(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + fetchResponse := new(FetchResponse) + fetchResponse.AddError("my_topic", 0, ErrOffsetOutOfRange) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetNewest, 1234). + SetOffset("my_topic", 0, OffsetOldest, 7), + "FetchRequest": NewMockWrapper(fetchResponse), + }) + + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When + consumer, err := master.ConsumePartition("my_topic", 0, 101) + if err != nil { + t.Fatal(err) + } + + // Then: consumer should shut down closing its messages and errors channels. + if _, ok := <-consumer.Messages(); ok { + t.Error("Expected the consumer to shut down") + } + safeClose(t, consumer) + + safeClose(t, master) + broker0.Close() +} + +// If a fetch response contains messages with offsets that are smaller then +// requested, then such messages are ignored. +func TestConsumerExtraOffsets(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + fetchResponse1 := &FetchResponse{} + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 1) + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 2) + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 3) + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 4) + fetchResponse2 := &FetchResponse{} + fetchResponse2.AddError("my_topic", 0, ErrNoError) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetNewest, 1234). + SetOffset("my_topic", 0, OffsetOldest, 0), + "FetchRequest": NewMockSequence(fetchResponse1, fetchResponse2), + }) + + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When + consumer, err := master.ConsumePartition("my_topic", 0, 3) + if err != nil { + t.Fatal(err) + } + + // Then: messages with offsets 1 and 2 are not returned even though they + // are present in the response. + assertMessageOffset(t, <-consumer.Messages(), 3) + assertMessageOffset(t, <-consumer.Messages(), 4) + + safeClose(t, consumer) + safeClose(t, master) + broker0.Close() +} + +// It is fine if offsets of fetched messages are not sequential (although +// strictly increasing!). +func TestConsumerNonSequentialOffsets(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + fetchResponse1 := &FetchResponse{} + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 5) + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 7) + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 11) + fetchResponse2 := &FetchResponse{} + fetchResponse2.AddError("my_topic", 0, ErrNoError) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetNewest, 1234). + SetOffset("my_topic", 0, OffsetOldest, 0), + "FetchRequest": NewMockSequence(fetchResponse1, fetchResponse2), + }) + + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When + consumer, err := master.ConsumePartition("my_topic", 0, 3) + if err != nil { + t.Fatal(err) + } + + // Then: messages with offsets 1 and 2 are not returned even though they + // are present in the response. + assertMessageOffset(t, <-consumer.Messages(), 5) + assertMessageOffset(t, <-consumer.Messages(), 7) + assertMessageOffset(t, <-consumer.Messages(), 11) + + safeClose(t, consumer) + safeClose(t, master) + broker0.Close() +} + +// If leadership for a partition is changing then consumer resolves the new +// leader and switches to it. +func TestConsumerRebalancingMultiplePartitions(t *testing.T) { + // initial setup + seedBroker := NewMockBroker(t, 10) + leader0 := NewMockBroker(t, 0) + leader1 := NewMockBroker(t, 1) + + seedBroker.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(leader0.Addr(), leader0.BrokerID()). + SetBroker(leader1.Addr(), leader1.BrokerID()). + SetLeader("my_topic", 0, leader0.BrokerID()). + SetLeader("my_topic", 1, leader1.BrokerID()), + }) + + mockOffsetResponse1 := NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 0). + SetOffset("my_topic", 0, OffsetNewest, 1000). + SetOffset("my_topic", 1, OffsetOldest, 0). + SetOffset("my_topic", 1, OffsetNewest, 1000) + leader0.SetHandlerByMap(map[string]MockResponse{ + "OffsetRequest": mockOffsetResponse1, + "FetchRequest": NewMockFetchResponse(t, 1), + }) + leader1.SetHandlerByMap(map[string]MockResponse{ + "OffsetRequest": mockOffsetResponse1, + "FetchRequest": NewMockFetchResponse(t, 1), + }) + + // launch test goroutines + config := NewConfig() + config.Consumer.Retry.Backoff = 50 + master, err := NewConsumer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + // we expect to end up (eventually) consuming exactly ten messages on each partition + var wg sync.WaitGroup + for i := int32(0); i < 2; i++ { + consumer, err := master.ConsumePartition("my_topic", i, 0) + if err != nil { + t.Error(err) + } + + go func(c PartitionConsumer) { + for err := range c.Errors() { + t.Error(err) + } + }(consumer) + + wg.Add(1) + go func(partition int32, c PartitionConsumer) { + for i := 0; i < 10; i++ { + message := <-consumer.Messages() + if message.Offset != int64(i) { + t.Error("Incorrect message offset!", i, partition, message.Offset) + } + if message.Partition != partition { + t.Error("Incorrect message partition!") + } + } + safeClose(t, consumer) + wg.Done() + }(i, consumer) + } + + time.Sleep(50 * time.Millisecond) + Logger.Printf(" STAGE 1") + // Stage 1: + // * my_topic/0 -> leader0 serves 4 messages + // * my_topic/1 -> leader1 serves 0 messages + + mockFetchResponse := NewMockFetchResponse(t, 1) + for i := 0; i < 4; i++ { + mockFetchResponse.SetMessage("my_topic", 0, int64(i), testMsg) + } + leader0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": mockFetchResponse, + }) + + time.Sleep(50 * time.Millisecond) + Logger.Printf(" STAGE 2") + // Stage 2: + // * leader0 says that it is no longer serving my_topic/0 + // * seedBroker tells that leader1 is serving my_topic/0 now + + // seed broker tells that the new partition 0 leader is leader1 + seedBroker.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetLeader("my_topic", 0, leader1.BrokerID()). + SetLeader("my_topic", 1, leader1.BrokerID()), + }) + + // leader0 says no longer leader of partition 0 + fetchResponse := new(FetchResponse) + fetchResponse.AddError("my_topic", 0, ErrNotLeaderForPartition) + leader0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": NewMockWrapper(fetchResponse), + }) + + time.Sleep(50 * time.Millisecond) + Logger.Printf(" STAGE 3") + // Stage 3: + // * my_topic/0 -> leader1 serves 3 messages + // * my_topic/1 -> leader1 server 8 messages + + // leader1 provides 3 message on partition 0, and 8 messages on partition 1 + mockFetchResponse2 := NewMockFetchResponse(t, 2) + for i := 4; i < 7; i++ { + mockFetchResponse2.SetMessage("my_topic", 0, int64(i), testMsg) + } + for i := 0; i < 8; i++ { + mockFetchResponse2.SetMessage("my_topic", 1, int64(i), testMsg) + } + leader1.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": mockFetchResponse2, + }) + + time.Sleep(50 * time.Millisecond) + Logger.Printf(" STAGE 4") + // Stage 4: + // * my_topic/0 -> leader1 serves 3 messages + // * my_topic/1 -> leader1 tells that it is no longer the leader + // * seedBroker tells that leader0 is a new leader for my_topic/1 + + // metadata assigns 0 to leader1 and 1 to leader0 + seedBroker.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetLeader("my_topic", 0, leader1.BrokerID()). + SetLeader("my_topic", 1, leader0.BrokerID()), + }) + + // leader1 provides three more messages on partition0, says no longer leader of partition1 + mockFetchResponse3 := NewMockFetchResponse(t, 3). + SetMessage("my_topic", 0, int64(7), testMsg). + SetMessage("my_topic", 0, int64(8), testMsg). + SetMessage("my_topic", 0, int64(9), testMsg) + fetchResponse4 := new(FetchResponse) + fetchResponse4.AddError("my_topic", 1, ErrNotLeaderForPartition) + leader1.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": NewMockSequence(mockFetchResponse3, fetchResponse4), + }) + + // leader0 provides two messages on partition 1 + mockFetchResponse4 := NewMockFetchResponse(t, 2) + for i := 8; i < 10; i++ { + mockFetchResponse4.SetMessage("my_topic", 1, int64(i), testMsg) + } + leader0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": mockFetchResponse4, + }) + + wg.Wait() + safeClose(t, master) + leader1.Close() + leader0.Close() + seedBroker.Close() +} + +// When two partitions have the same broker as the leader, if one partition +// consumer channel buffer is full then that does not affect the ability to +// read messages by the other consumer. +func TestConsumerInterleavedClose(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()). + SetLeader("my_topic", 1, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 1000). + SetOffset("my_topic", 0, OffsetNewest, 1100). + SetOffset("my_topic", 1, OffsetOldest, 2000). + SetOffset("my_topic", 1, OffsetNewest, 2100), + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 1000, testMsg). + SetMessage("my_topic", 0, 1001, testMsg). + SetMessage("my_topic", 0, 1002, testMsg). + SetMessage("my_topic", 1, 2000, testMsg), + }) + + config := NewConfig() + config.ChannelBufferSize = 0 + master, err := NewConsumer([]string{broker0.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + c0, err := master.ConsumePartition("my_topic", 0, 1000) + if err != nil { + t.Fatal(err) + } + + c1, err := master.ConsumePartition("my_topic", 1, 2000) + if err != nil { + t.Fatal(err) + } + + // When/Then: we can read from partition 0 even if nobody reads from partition 1 + assertMessageOffset(t, <-c0.Messages(), 1000) + assertMessageOffset(t, <-c0.Messages(), 1001) + assertMessageOffset(t, <-c0.Messages(), 1002) + + safeClose(t, c1) + safeClose(t, c0) + safeClose(t, master) + broker0.Close() +} + +func TestConsumerBounceWithReferenceOpen(t *testing.T) { + broker0 := NewMockBroker(t, 0) + broker0Addr := broker0.Addr() + broker1 := NewMockBroker(t, 1) + + mockMetadataResponse := NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetBroker(broker1.Addr(), broker1.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()). + SetLeader("my_topic", 1, broker1.BrokerID()) + + mockOffsetResponse := NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 1000). + SetOffset("my_topic", 0, OffsetNewest, 1100). + SetOffset("my_topic", 1, OffsetOldest, 2000). + SetOffset("my_topic", 1, OffsetNewest, 2100) + + mockFetchResponse := NewMockFetchResponse(t, 1) + for i := 0; i < 10; i++ { + mockFetchResponse.SetMessage("my_topic", 0, int64(1000+i), testMsg) + mockFetchResponse.SetMessage("my_topic", 1, int64(2000+i), testMsg) + } + + broker0.SetHandlerByMap(map[string]MockResponse{ + "OffsetRequest": mockOffsetResponse, + "FetchRequest": mockFetchResponse, + }) + broker1.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": mockMetadataResponse, + "OffsetRequest": mockOffsetResponse, + "FetchRequest": mockFetchResponse, + }) + + config := NewConfig() + config.Consumer.Return.Errors = true + config.Consumer.Retry.Backoff = 100 * time.Millisecond + config.ChannelBufferSize = 1 + master, err := NewConsumer([]string{broker1.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + c0, err := master.ConsumePartition("my_topic", 0, 1000) + if err != nil { + t.Fatal(err) + } + + c1, err := master.ConsumePartition("my_topic", 1, 2000) + if err != nil { + t.Fatal(err) + } + + // read messages from both partition to make sure that both brokers operate + // normally. + assertMessageOffset(t, <-c0.Messages(), 1000) + assertMessageOffset(t, <-c1.Messages(), 2000) + + // Simulate broker shutdown. Note that metadata response does not change, + // that is the leadership does not move to another broker. So partition + // consumer will keep retrying to restore the connection with the broker. + broker0.Close() + + // Make sure that while the partition/0 leader is down, consumer/partition/1 + // is capable of pulling messages from broker1. + for i := 1; i < 7; i++ { + offset := (<-c1.Messages()).Offset + if offset != int64(2000+i) { + t.Errorf("Expected offset %d from consumer/partition/1", int64(2000+i)) + } + } + + // Bring broker0 back to service. + broker0 = NewMockBrokerAddr(t, 0, broker0Addr) + broker0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": mockFetchResponse, + }) + + // Read the rest of messages from both partitions. + for i := 7; i < 10; i++ { + assertMessageOffset(t, <-c1.Messages(), int64(2000+i)) + } + for i := 1; i < 10; i++ { + assertMessageOffset(t, <-c0.Messages(), int64(1000+i)) + } + + select { + case <-c0.Errors(): + default: + t.Errorf("Partition consumer should have detected broker restart") + } + + safeClose(t, c1) + safeClose(t, c0) + safeClose(t, master) + broker0.Close() + broker1.Close() +} + +func TestConsumerOffsetOutOfRange(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 2) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetNewest, 1234). + SetOffset("my_topic", 0, OffsetOldest, 2345), + }) + + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When/Then + if _, err := master.ConsumePartition("my_topic", 0, 0); err != ErrOffsetOutOfRange { + t.Fatal("Should return ErrOffsetOutOfRange, got:", err) + } + if _, err := master.ConsumePartition("my_topic", 0, 3456); err != ErrOffsetOutOfRange { + t.Fatal("Should return ErrOffsetOutOfRange, got:", err) + } + if _, err := master.ConsumePartition("my_topic", 0, -3); err != ErrOffsetOutOfRange { + t.Fatal("Should return ErrOffsetOutOfRange, got:", err) + } + + safeClose(t, master) + broker0.Close() +} + +func assertMessageOffset(t *testing.T, msg *ConsumerMessage, expectedOffset int64) { + if msg.Offset != expectedOffset { + t.Errorf("Incorrect message offset: expected=%d, actual=%d", expectedOffset, msg.Offset) + } +} + +// This example shows how to use the consumer to read messages +// from a single partition. +func ExampleConsumer() { + consumer, err := NewConsumer([]string{"localhost:9092"}, nil) + if err != nil { + panic(err) + } + + defer func() { + if err := consumer.Close(); err != nil { + log.Fatalln(err) + } + }() + + partitionConsumer, err := consumer.ConsumePartition("my_topic", 0, OffsetNewest) + if err != nil { + panic(err) + } + + defer func() { + if err := partitionConsumer.Close(); err != nil { + log.Fatalln(err) + } + }() + + // Trap SIGINT to trigger a shutdown. + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Interrupt) + + consumed := 0 +ConsumerLoop: + for { + select { + case msg := <-partitionConsumer.Messages(): + log.Printf("Consumed message offset %d\n", msg.Offset) + consumed++ + case <-signals: + break ConsumerLoop + } + } + + log.Printf("Consumed: %d\n", consumed) +} diff --git a/vendor/src/github.com/Shopify/sarama/crc32_field.go b/vendor/src/github.com/Shopify/sarama/crc32_field.go new file mode 100644 index 00000000..5c286079 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/crc32_field.go @@ -0,0 +1,36 @@ +package sarama + +import ( + "encoding/binary" + + "github.com/klauspost/crc32" +) + +// crc32Field implements the pushEncoder and pushDecoder interfaces for calculating CRC32s. +type crc32Field struct { + startOffset int +} + +func (c *crc32Field) saveOffset(in int) { + c.startOffset = in +} + +func (c *crc32Field) reserveLength() int { + return 4 +} + +func (c *crc32Field) run(curOffset int, buf []byte) error { + crc := crc32.ChecksumIEEE(buf[c.startOffset+4 : curOffset]) + binary.BigEndian.PutUint32(buf[c.startOffset:], crc) + return nil +} + +func (c *crc32Field) check(curOffset int, buf []byte) error { + crc := crc32.ChecksumIEEE(buf[c.startOffset+4 : curOffset]) + + if crc != binary.BigEndian.Uint32(buf[c.startOffset:]) { + return PacketDecodingError{"CRC didn't match"} + } + + return nil +} diff --git a/vendor/src/github.com/Shopify/sarama/describe_groups_request.go b/vendor/src/github.com/Shopify/sarama/describe_groups_request.go new file mode 100644 index 00000000..1fb35677 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/describe_groups_request.go @@ -0,0 +1,30 @@ +package sarama + +type DescribeGroupsRequest struct { + Groups []string +} + +func (r *DescribeGroupsRequest) encode(pe packetEncoder) error { + return pe.putStringArray(r.Groups) +} + +func (r *DescribeGroupsRequest) decode(pd packetDecoder, version int16) (err error) { + r.Groups, err = pd.getStringArray() + return +} + +func (r *DescribeGroupsRequest) key() int16 { + return 15 +} + +func (r *DescribeGroupsRequest) version() int16 { + return 0 +} + +func (r *DescribeGroupsRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} + +func (r *DescribeGroupsRequest) AddGroup(group string) { + r.Groups = append(r.Groups, group) +} diff --git a/vendor/src/github.com/Shopify/sarama/describe_groups_request_test.go b/vendor/src/github.com/Shopify/sarama/describe_groups_request_test.go new file mode 100644 index 00000000..7d45f3fe --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/describe_groups_request_test.go @@ -0,0 +1,34 @@ +package sarama + +import "testing" + +var ( + emptyDescribeGroupsRequest = []byte{0, 0, 0, 0} + + singleDescribeGroupsRequest = []byte{ + 0, 0, 0, 1, // 1 group + 0, 3, 'f', 'o', 'o', // group name: foo + } + + doubleDescribeGroupsRequest = []byte{ + 0, 0, 0, 2, // 2 groups + 0, 3, 'f', 'o', 'o', // group name: foo + 0, 3, 'b', 'a', 'r', // group name: foo + } +) + +func TestDescribeGroupsRequest(t *testing.T) { + var request *DescribeGroupsRequest + + request = new(DescribeGroupsRequest) + testRequest(t, "no groups", request, emptyDescribeGroupsRequest) + + request = new(DescribeGroupsRequest) + request.AddGroup("foo") + testRequest(t, "one group", request, singleDescribeGroupsRequest) + + request = new(DescribeGroupsRequest) + request.AddGroup("foo") + request.AddGroup("bar") + testRequest(t, "two groups", request, doubleDescribeGroupsRequest) +} diff --git a/vendor/src/github.com/Shopify/sarama/describe_groups_response.go b/vendor/src/github.com/Shopify/sarama/describe_groups_response.go new file mode 100644 index 00000000..d2c2071e --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/describe_groups_response.go @@ -0,0 +1,186 @@ +package sarama + +type DescribeGroupsResponse struct { + Groups []*GroupDescription +} + +func (r *DescribeGroupsResponse) encode(pe packetEncoder) error { + if err := pe.putArrayLength(len(r.Groups)); err != nil { + return err + } + + for _, groupDescription := range r.Groups { + if err := groupDescription.encode(pe); err != nil { + return err + } + } + + return nil +} + +func (r *DescribeGroupsResponse) decode(pd packetDecoder, version int16) (err error) { + n, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Groups = make([]*GroupDescription, n) + for i := 0; i < n; i++ { + r.Groups[i] = new(GroupDescription) + if err := r.Groups[i].decode(pd); err != nil { + return err + } + } + + return nil +} + +func (r *DescribeGroupsResponse) key() int16 { + return 15 +} + +func (r *DescribeGroupsResponse) version() int16 { + return 0 +} + +func (r *DescribeGroupsResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} + +type GroupDescription struct { + Err KError + GroupId string + State string + ProtocolType string + Protocol string + Members map[string]*GroupMemberDescription +} + +func (gd *GroupDescription) encode(pe packetEncoder) error { + pe.putInt16(int16(gd.Err)) + + if err := pe.putString(gd.GroupId); err != nil { + return err + } + if err := pe.putString(gd.State); err != nil { + return err + } + if err := pe.putString(gd.ProtocolType); err != nil { + return err + } + if err := pe.putString(gd.Protocol); err != nil { + return err + } + + if err := pe.putArrayLength(len(gd.Members)); err != nil { + return err + } + + for memberId, groupMemberDescription := range gd.Members { + if err := pe.putString(memberId); err != nil { + return err + } + if err := groupMemberDescription.encode(pe); err != nil { + return err + } + } + + return nil +} + +func (gd *GroupDescription) decode(pd packetDecoder) (err error) { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + gd.Err = KError(kerr) + } + + if gd.GroupId, err = pd.getString(); err != nil { + return + } + if gd.State, err = pd.getString(); err != nil { + return + } + if gd.ProtocolType, err = pd.getString(); err != nil { + return + } + if gd.Protocol, err = pd.getString(); err != nil { + return + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + if n == 0 { + return nil + } + + gd.Members = make(map[string]*GroupMemberDescription) + for i := 0; i < n; i++ { + memberId, err := pd.getString() + if err != nil { + return err + } + + gd.Members[memberId] = new(GroupMemberDescription) + if err := gd.Members[memberId].decode(pd); err != nil { + return err + } + } + + return nil +} + +type GroupMemberDescription struct { + ClientId string + ClientHost string + MemberMetadata []byte + MemberAssignment []byte +} + +func (gmd *GroupMemberDescription) encode(pe packetEncoder) error { + if err := pe.putString(gmd.ClientId); err != nil { + return err + } + if err := pe.putString(gmd.ClientHost); err != nil { + return err + } + if err := pe.putBytes(gmd.MemberMetadata); err != nil { + return err + } + if err := pe.putBytes(gmd.MemberAssignment); err != nil { + return err + } + + return nil +} + +func (gmd *GroupMemberDescription) decode(pd packetDecoder) (err error) { + if gmd.ClientId, err = pd.getString(); err != nil { + return + } + if gmd.ClientHost, err = pd.getString(); err != nil { + return + } + if gmd.MemberMetadata, err = pd.getBytes(); err != nil { + return + } + if gmd.MemberAssignment, err = pd.getBytes(); err != nil { + return + } + + return nil +} + +func (gmd *GroupMemberDescription) GetMemberAssignment() (*ConsumerGroupMemberAssignment, error) { + assignment := new(ConsumerGroupMemberAssignment) + err := decode(gmd.MemberAssignment, assignment) + return assignment, err +} + +func (gmd *GroupMemberDescription) GetMemberMetadata() (*ConsumerGroupMemberMetadata, error) { + metadata := new(ConsumerGroupMemberMetadata) + err := decode(gmd.MemberMetadata, metadata) + return metadata, err +} diff --git a/vendor/src/github.com/Shopify/sarama/describe_groups_response_test.go b/vendor/src/github.com/Shopify/sarama/describe_groups_response_test.go new file mode 100644 index 00000000..dd397319 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/describe_groups_response_test.go @@ -0,0 +1,91 @@ +package sarama + +import ( + "reflect" + "testing" +) + +var ( + describeGroupsResponseEmpty = []byte{ + 0, 0, 0, 0, // no groups + } + + describeGroupsResponsePopulated = []byte{ + 0, 0, 0, 2, // 2 groups + + 0, 0, // no error + 0, 3, 'f', 'o', 'o', // Group ID + 0, 3, 'b', 'a', 'r', // State + 0, 8, 'c', 'o', 'n', 's', 'u', 'm', 'e', 'r', // ConsumerProtocol type + 0, 3, 'b', 'a', 'z', // Protocol name + 0, 0, 0, 1, // 1 member + 0, 2, 'i', 'd', // Member ID + 0, 6, 's', 'a', 'r', 'a', 'm', 'a', // Client ID + 0, 9, 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', // Client Host + 0, 0, 0, 3, 0x01, 0x02, 0x03, // MemberMetadata + 0, 0, 0, 3, 0x04, 0x05, 0x06, // MemberAssignment + + 0, 30, // ErrGroupAuthorizationFailed + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, 0, 0, + } +) + +func TestDescribeGroupsResponse(t *testing.T) { + var response *DescribeGroupsResponse + + response = new(DescribeGroupsResponse) + testVersionDecodable(t, "empty", response, describeGroupsResponseEmpty, 0) + if len(response.Groups) != 0 { + t.Error("Expected no groups") + } + + response = new(DescribeGroupsResponse) + testVersionDecodable(t, "populated", response, describeGroupsResponsePopulated, 0) + if len(response.Groups) != 2 { + t.Error("Expected two groups") + } + + group0 := response.Groups[0] + if group0.Err != ErrNoError { + t.Error("Unxpected groups[0].Err, found", group0.Err) + } + if group0.GroupId != "foo" { + t.Error("Unxpected groups[0].GroupId, found", group0.GroupId) + } + if group0.State != "bar" { + t.Error("Unxpected groups[0].State, found", group0.State) + } + if group0.ProtocolType != "consumer" { + t.Error("Unxpected groups[0].ProtocolType, found", group0.ProtocolType) + } + if group0.Protocol != "baz" { + t.Error("Unxpected groups[0].Protocol, found", group0.Protocol) + } + if len(group0.Members) != 1 { + t.Error("Unxpected groups[0].Members, found", group0.Members) + } + if group0.Members["id"].ClientId != "sarama" { + t.Error("Unxpected groups[0].Members[id].ClientId, found", group0.Members["id"].ClientId) + } + if group0.Members["id"].ClientHost != "localhost" { + t.Error("Unxpected groups[0].Members[id].ClientHost, found", group0.Members["id"].ClientHost) + } + if !reflect.DeepEqual(group0.Members["id"].MemberMetadata, []byte{0x01, 0x02, 0x03}) { + t.Error("Unxpected groups[0].Members[id].MemberMetadata, found", group0.Members["id"].MemberMetadata) + } + if !reflect.DeepEqual(group0.Members["id"].MemberAssignment, []byte{0x04, 0x05, 0x06}) { + t.Error("Unxpected groups[0].Members[id].MemberAssignment, found", group0.Members["id"].MemberAssignment) + } + + group1 := response.Groups[1] + if group1.Err != ErrGroupAuthorizationFailed { + t.Error("Unxpected groups[1].Err, found", group0.Err) + } + if len(group1.Members) != 0 { + t.Error("Unxpected groups[1].Members, found", group0.Members) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/dev.yml b/vendor/src/github.com/Shopify/sarama/dev.yml new file mode 100644 index 00000000..e014316f --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/dev.yml @@ -0,0 +1,13 @@ +name: sarama + +up: + - go: 1.7.3 + +commands: + test: + run: make test + desc: 'run unit tests' + +packages: + - git@github.com:Shopify/dev-shopify.git + diff --git a/vendor/src/github.com/Shopify/sarama/encoder_decoder.go b/vendor/src/github.com/Shopify/sarama/encoder_decoder.go new file mode 100644 index 00000000..7ce3bc0f --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/encoder_decoder.go @@ -0,0 +1,89 @@ +package sarama + +import ( + "fmt" + + "github.com/rcrowley/go-metrics" +) + +// Encoder is the interface that wraps the basic Encode method. +// Anything implementing Encoder can be turned into bytes using Kafka's encoding rules. +type encoder interface { + encode(pe packetEncoder) error +} + +// Encode takes an Encoder and turns it into bytes while potentially recording metrics. +func encode(e encoder, metricRegistry metrics.Registry) ([]byte, error) { + if e == nil { + return nil, nil + } + + var prepEnc prepEncoder + var realEnc realEncoder + + err := e.encode(&prepEnc) + if err != nil { + return nil, err + } + + if prepEnc.length < 0 || prepEnc.length > int(MaxRequestSize) { + return nil, PacketEncodingError{fmt.Sprintf("invalid request size (%d)", prepEnc.length)} + } + + realEnc.raw = make([]byte, prepEnc.length) + realEnc.registry = metricRegistry + err = e.encode(&realEnc) + if err != nil { + return nil, err + } + + return realEnc.raw, nil +} + +// Decoder is the interface that wraps the basic Decode method. +// Anything implementing Decoder can be extracted from bytes using Kafka's encoding rules. +type decoder interface { + decode(pd packetDecoder) error +} + +type versionedDecoder interface { + decode(pd packetDecoder, version int16) error +} + +// Decode takes bytes and a Decoder and fills the fields of the decoder from the bytes, +// interpreted using Kafka's encoding rules. +func decode(buf []byte, in decoder) error { + if buf == nil { + return nil + } + + helper := realDecoder{raw: buf} + err := in.decode(&helper) + if err != nil { + return err + } + + if helper.off != len(buf) { + return PacketDecodingError{"invalid length"} + } + + return nil +} + +func versionedDecode(buf []byte, in versionedDecoder, version int16) error { + if buf == nil { + return nil + } + + helper := realDecoder{raw: buf} + err := in.decode(&helper, version) + if err != nil { + return err + } + + if helper.off != len(buf) { + return PacketDecodingError{"invalid length"} + } + + return nil +} diff --git a/vendor/src/github.com/Shopify/sarama/errors.go b/vendor/src/github.com/Shopify/sarama/errors.go new file mode 100644 index 00000000..cc3f623d --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/errors.go @@ -0,0 +1,197 @@ +package sarama + +import ( + "errors" + "fmt" +) + +// ErrOutOfBrokers is the error returned when the client has run out of brokers to talk to because all of them errored +// or otherwise failed to respond. +var ErrOutOfBrokers = errors.New("kafka: client has run out of available brokers to talk to (Is your cluster reachable?)") + +// ErrClosedClient is the error returned when a method is called on a client that has been closed. +var ErrClosedClient = errors.New("kafka: tried to use a client that was closed") + +// ErrIncompleteResponse is the error returned when the server returns a syntactically valid response, but it does +// not contain the expected information. +var ErrIncompleteResponse = errors.New("kafka: response did not contain all the expected topic/partition blocks") + +// ErrInvalidPartition is the error returned when a partitioner returns an invalid partition index +// (meaning one outside of the range [0...numPartitions-1]). +var ErrInvalidPartition = errors.New("kafka: partitioner returned an invalid partition index") + +// ErrAlreadyConnected is the error returned when calling Open() on a Broker that is already connected or connecting. +var ErrAlreadyConnected = errors.New("kafka: broker connection already initiated") + +// ErrNotConnected is the error returned when trying to send or call Close() on a Broker that is not connected. +var ErrNotConnected = errors.New("kafka: broker not connected") + +// ErrInsufficientData is returned when decoding and the packet is truncated. This can be expected +// when requesting messages, since as an optimization the server is allowed to return a partial message at the end +// of the message set. +var ErrInsufficientData = errors.New("kafka: insufficient data to decode packet, more bytes expected") + +// ErrShuttingDown is returned when a producer receives a message during shutdown. +var ErrShuttingDown = errors.New("kafka: message received by producer in process of shutting down") + +// ErrMessageTooLarge is returned when the next message to consume is larger than the configured Consumer.Fetch.Max +var ErrMessageTooLarge = errors.New("kafka: message is larger than Consumer.Fetch.Max") + +// PacketEncodingError is returned from a failure while encoding a Kafka packet. This can happen, for example, +// if you try to encode a string over 2^15 characters in length, since Kafka's encoding rules do not permit that. +type PacketEncodingError struct { + Info string +} + +func (err PacketEncodingError) Error() string { + return fmt.Sprintf("kafka: error encoding packet: %s", err.Info) +} + +// PacketDecodingError is returned when there was an error (other than truncated data) decoding the Kafka broker's response. +// This can be a bad CRC or length field, or any other invalid value. +type PacketDecodingError struct { + Info string +} + +func (err PacketDecodingError) Error() string { + return fmt.Sprintf("kafka: error decoding packet: %s", err.Info) +} + +// ConfigurationError is the type of error returned from a constructor (e.g. NewClient, or NewConsumer) +// when the specified configuration is invalid. +type ConfigurationError string + +func (err ConfigurationError) Error() string { + return "kafka: invalid configuration (" + string(err) + ")" +} + +// KError is the type of error that can be returned directly by the Kafka broker. +// See https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol#AGuideToTheKafkaProtocol-ErrorCodes +type KError int16 + +// Numeric error codes returned by the Kafka server. +const ( + ErrNoError KError = 0 + ErrUnknown KError = -1 + ErrOffsetOutOfRange KError = 1 + ErrInvalidMessage KError = 2 + ErrUnknownTopicOrPartition KError = 3 + ErrInvalidMessageSize KError = 4 + ErrLeaderNotAvailable KError = 5 + ErrNotLeaderForPartition KError = 6 + ErrRequestTimedOut KError = 7 + ErrBrokerNotAvailable KError = 8 + ErrReplicaNotAvailable KError = 9 + ErrMessageSizeTooLarge KError = 10 + ErrStaleControllerEpochCode KError = 11 + ErrOffsetMetadataTooLarge KError = 12 + ErrNetworkException KError = 13 + ErrOffsetsLoadInProgress KError = 14 + ErrConsumerCoordinatorNotAvailable KError = 15 + ErrNotCoordinatorForConsumer KError = 16 + ErrInvalidTopic KError = 17 + ErrMessageSetSizeTooLarge KError = 18 + ErrNotEnoughReplicas KError = 19 + ErrNotEnoughReplicasAfterAppend KError = 20 + ErrInvalidRequiredAcks KError = 21 + ErrIllegalGeneration KError = 22 + ErrInconsistentGroupProtocol KError = 23 + ErrInvalidGroupId KError = 24 + ErrUnknownMemberId KError = 25 + ErrInvalidSessionTimeout KError = 26 + ErrRebalanceInProgress KError = 27 + ErrInvalidCommitOffsetSize KError = 28 + ErrTopicAuthorizationFailed KError = 29 + ErrGroupAuthorizationFailed KError = 30 + ErrClusterAuthorizationFailed KError = 31 + ErrInvalidTimestamp KError = 32 + ErrUnsupportedSASLMechanism KError = 33 + ErrIllegalSASLState KError = 34 + ErrUnsupportedVersion KError = 35 + ErrUnsupportedForMessageFormat KError = 43 +) + +func (err KError) Error() string { + // Error messages stolen/adapted from + // https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol + switch err { + case ErrNoError: + return "kafka server: Not an error, why are you printing me?" + case ErrUnknown: + return "kafka server: Unexpected (unknown?) server error." + case ErrOffsetOutOfRange: + return "kafka server: The requested offset is outside the range of offsets maintained by the server for the given topic/partition." + case ErrInvalidMessage: + return "kafka server: Message contents does not match its CRC." + case ErrUnknownTopicOrPartition: + return "kafka server: Request was for a topic or partition that does not exist on this broker." + case ErrInvalidMessageSize: + return "kafka server: The message has a negative size." + case ErrLeaderNotAvailable: + return "kafka server: In the middle of a leadership election, there is currently no leader for this partition and hence it is unavailable for writes." + case ErrNotLeaderForPartition: + return "kafka server: Tried to send a message to a replica that is not the leader for some partition. Your metadata is out of date." + case ErrRequestTimedOut: + return "kafka server: Request exceeded the user-specified time limit in the request." + case ErrBrokerNotAvailable: + return "kafka server: Broker not available. Not a client facing error, we should never receive this!!!" + case ErrReplicaNotAvailable: + return "kafka server: Replica information not available, one or more brokers are down." + case ErrMessageSizeTooLarge: + return "kafka server: Message was too large, server rejected it to avoid allocation error." + case ErrStaleControllerEpochCode: + return "kafka server: StaleControllerEpochCode (internal error code for broker-to-broker communication)." + case ErrOffsetMetadataTooLarge: + return "kafka server: Specified a string larger than the configured maximum for offset metadata." + case ErrNetworkException: + return "kafka server: The server disconnected before a response was received." + case ErrOffsetsLoadInProgress: + return "kafka server: The broker is still loading offsets after a leader change for that offset's topic partition." + case ErrConsumerCoordinatorNotAvailable: + return "kafka server: Offset's topic has not yet been created." + case ErrNotCoordinatorForConsumer: + return "kafka server: Request was for a consumer group that is not coordinated by this broker." + case ErrInvalidTopic: + return "kafka server: The request attempted to perform an operation on an invalid topic." + case ErrMessageSetSizeTooLarge: + return "kafka server: The request included message batch larger than the configured segment size on the server." + case ErrNotEnoughReplicas: + return "kafka server: Messages are rejected since there are fewer in-sync replicas than required." + case ErrNotEnoughReplicasAfterAppend: + return "kafka server: Messages are written to the log, but to fewer in-sync replicas than required." + case ErrInvalidRequiredAcks: + return "kafka server: The number of required acks is invalid (should be either -1, 0, or 1)." + case ErrIllegalGeneration: + return "kafka server: The provided generation id is not the current generation." + case ErrInconsistentGroupProtocol: + return "kafka server: The provider group protocol type is incompatible with the other members." + case ErrInvalidGroupId: + return "kafka server: The provided group id was empty." + case ErrUnknownMemberId: + return "kafka server: The provided member is not known in the current generation." + case ErrInvalidSessionTimeout: + return "kafka server: The provided session timeout is outside the allowed range." + case ErrRebalanceInProgress: + return "kafka server: A rebalance for the group is in progress. Please re-join the group." + case ErrInvalidCommitOffsetSize: + return "kafka server: The provided commit metadata was too large." + case ErrTopicAuthorizationFailed: + return "kafka server: The client is not authorized to access this topic." + case ErrGroupAuthorizationFailed: + return "kafka server: The client is not authorized to access this group." + case ErrClusterAuthorizationFailed: + return "kafka server: The client is not authorized to send this request type." + case ErrInvalidTimestamp: + return "kafka server: The timestamp of the message is out of acceptable range." + case ErrUnsupportedSASLMechanism: + return "kafka server: The broker does not support the requested SASL mechanism." + case ErrIllegalSASLState: + return "kafka server: Request is not valid given the current SASL state." + case ErrUnsupportedVersion: + return "kafka server: The version of API is not supported." + case ErrUnsupportedForMessageFormat: + return "kafka server: The requested operation is not supported by the message format version." + } + + return fmt.Sprintf("Unknown error, how did this happen? Error code = %d", err) +} diff --git a/vendor/src/github.com/Shopify/sarama/examples/README.md b/vendor/src/github.com/Shopify/sarama/examples/README.md new file mode 100644 index 00000000..b6588051 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/examples/README.md @@ -0,0 +1,9 @@ +# Sarama examples + +This folder contains example applications to demonstrate the use of Sarama. For code snippet examples on how to use the different types in Sarama, see [Sarams's API documentation on godoc.org](https://godoc.org/github.com/Shopify/sarama) + +In these examples, we use `github.com/Shopify/sarama` as import path. We do this to ensure all the examples are up to date with the latest changes in Sarama. For your own applications, you may want to use `gopkg.in/Shopify/sarama.v1` to lock into a stable API version. + +#### HTTP server + +[http_server](./http_server) is a simple HTTP server uses both the sync producer to produce data as part of the request handling cycle, as well as the async producer to maintain an access log. It also uses the [mocks subpackage](https://godoc.org/github.com/Shopify/sarama/mocks) to test both. diff --git a/vendor/src/github.com/Shopify/sarama/examples/http_server/README.md b/vendor/src/github.com/Shopify/sarama/examples/http_server/README.md new file mode 100644 index 00000000..5ff2bc25 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/examples/http_server/README.md @@ -0,0 +1,7 @@ +# HTTP server example + +This HTTP server example shows you how to use the AsyncProducer and SyncProducer, and how to test them using mocks. The server simply sends the data of the HTTP request's query string to Kafka, and send a 200 result if that succeeds. For every request, it will send an access log entry to Kafka as well in the background. + +If you need to know whether a message was successfully sent to the Kafka cluster before you can send your HTTP response, using the `SyncProducer` is probably the simplest way to achieve this. If you don't care, e.g. for the access log, using the `AsyncProducer` will let you fire and forget. You can send the HTTP response, while the message is being produced in the background. + +One important thing to note is that both the `SyncProducer` and `AsyncProducer` are **thread-safe**. Go's `http.Server` handles requests concurrently in different goroutines, but you can use a single producer safely. This will actually achieve efficiency gains as the producer will be able to batch messages from concurrent requests together. diff --git a/vendor/src/github.com/Shopify/sarama/examples/http_server/http_server.go b/vendor/src/github.com/Shopify/sarama/examples/http_server/http_server.go new file mode 100644 index 00000000..b6d83c5d --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/examples/http_server/http_server.go @@ -0,0 +1,247 @@ +package main + +import ( + "github.com/Shopify/sarama" + + "crypto/tls" + "crypto/x509" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "strings" + "time" +) + +var ( + addr = flag.String("addr", ":8080", "The address to bind to") + brokers = flag.String("brokers", os.Getenv("KAFKA_PEERS"), "The Kafka brokers to connect to, as a comma separated list") + verbose = flag.Bool("verbose", false, "Turn on Sarama logging") + certFile = flag.String("certificate", "", "The optional certificate file for client authentication") + keyFile = flag.String("key", "", "The optional key file for client authentication") + caFile = flag.String("ca", "", "The optional certificate authority file for TLS client authentication") + verifySsl = flag.Bool("verify", false, "Optional verify ssl certificates chain") +) + +func main() { + flag.Parse() + + if *verbose { + sarama.Logger = log.New(os.Stdout, "[sarama] ", log.LstdFlags) + } + + if *brokers == "" { + flag.PrintDefaults() + os.Exit(1) + } + + brokerList := strings.Split(*brokers, ",") + log.Printf("Kafka brokers: %s", strings.Join(brokerList, ", ")) + + server := &Server{ + DataCollector: newDataCollector(brokerList), + AccessLogProducer: newAccessLogProducer(brokerList), + } + defer func() { + if err := server.Close(); err != nil { + log.Println("Failed to close server", err) + } + }() + + log.Fatal(server.Run(*addr)) +} + +func createTlsConfiguration() (t *tls.Config) { + if *certFile != "" && *keyFile != "" && *caFile != "" { + cert, err := tls.LoadX509KeyPair(*certFile, *keyFile) + if err != nil { + log.Fatal(err) + } + + caCert, err := ioutil.ReadFile(*caFile) + if err != nil { + log.Fatal(err) + } + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + t = &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caCertPool, + InsecureSkipVerify: *verifySsl, + } + } + // will be nil by default if nothing is provided + return t +} + +type Server struct { + DataCollector sarama.SyncProducer + AccessLogProducer sarama.AsyncProducer +} + +func (s *Server) Close() error { + if err := s.DataCollector.Close(); err != nil { + log.Println("Failed to shut down data collector cleanly", err) + } + + if err := s.AccessLogProducer.Close(); err != nil { + log.Println("Failed to shut down access log producer cleanly", err) + } + + return nil +} + +func (s *Server) Handler() http.Handler { + return s.withAccessLog(s.collectQueryStringData()) +} + +func (s *Server) Run(addr string) error { + httpServer := &http.Server{ + Addr: addr, + Handler: s.Handler(), + } + + log.Printf("Listening for requests on %s...\n", addr) + return httpServer.ListenAndServe() +} + +func (s *Server) collectQueryStringData() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" { + http.NotFound(w, r) + return + } + + // We are not setting a message key, which means that all messages will + // be distributed randomly over the different partitions. + partition, offset, err := s.DataCollector.SendMessage(&sarama.ProducerMessage{ + Topic: "important", + Value: sarama.StringEncoder(r.URL.RawQuery), + }) + + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Failed to store your data:, %s", err) + } else { + // The tuple (topic, partition, offset) can be used as a unique identifier + // for a message in a Kafka cluster. + fmt.Fprintf(w, "Your data is stored with unique identifier important/%d/%d", partition, offset) + } + }) +} + +type accessLogEntry struct { + Method string `json:"method"` + Host string `json:"host"` + Path string `json:"path"` + IP string `json:"ip"` + ResponseTime float64 `json:"response_time"` + + encoded []byte + err error +} + +func (ale *accessLogEntry) ensureEncoded() { + if ale.encoded == nil && ale.err == nil { + ale.encoded, ale.err = json.Marshal(ale) + } +} + +func (ale *accessLogEntry) Length() int { + ale.ensureEncoded() + return len(ale.encoded) +} + +func (ale *accessLogEntry) Encode() ([]byte, error) { + ale.ensureEncoded() + return ale.encoded, ale.err +} + +func (s *Server) withAccessLog(next http.Handler) http.Handler { + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + started := time.Now() + + next.ServeHTTP(w, r) + + entry := &accessLogEntry{ + Method: r.Method, + Host: r.Host, + Path: r.RequestURI, + IP: r.RemoteAddr, + ResponseTime: float64(time.Since(started)) / float64(time.Second), + } + + // We will use the client's IP address as key. This will cause + // all the access log entries of the same IP address to end up + // on the same partition. + s.AccessLogProducer.Input() <- &sarama.ProducerMessage{ + Topic: "access_log", + Key: sarama.StringEncoder(r.RemoteAddr), + Value: entry, + } + }) +} + +func newDataCollector(brokerList []string) sarama.SyncProducer { + + // For the data collector, we are looking for strong consistency semantics. + // Because we don't change the flush settings, sarama will try to produce messages + // as fast as possible to keep latency low. + config := sarama.NewConfig() + config.Producer.RequiredAcks = sarama.WaitForAll // Wait for all in-sync replicas to ack the message + config.Producer.Retry.Max = 10 // Retry up to 10 times to produce the message + config.Producer.Return.Successes = true + tlsConfig := createTlsConfiguration() + if tlsConfig != nil { + config.Net.TLS.Config = tlsConfig + config.Net.TLS.Enable = true + } + + // On the broker side, you may want to change the following settings to get + // stronger consistency guarantees: + // - For your broker, set `unclean.leader.election.enable` to false + // - For the topic, you could increase `min.insync.replicas`. + + producer, err := sarama.NewSyncProducer(brokerList, config) + if err != nil { + log.Fatalln("Failed to start Sarama producer:", err) + } + + return producer +} + +func newAccessLogProducer(brokerList []string) sarama.AsyncProducer { + + // For the access log, we are looking for AP semantics, with high throughput. + // By creating batches of compressed messages, we reduce network I/O at a cost of more latency. + config := sarama.NewConfig() + tlsConfig := createTlsConfiguration() + if tlsConfig != nil { + config.Net.TLS.Enable = true + config.Net.TLS.Config = tlsConfig + } + config.Producer.RequiredAcks = sarama.WaitForLocal // Only wait for the leader to ack + config.Producer.Compression = sarama.CompressionSnappy // Compress messages + config.Producer.Flush.Frequency = 500 * time.Millisecond // Flush batches every 500ms + + producer, err := sarama.NewAsyncProducer(brokerList, config) + if err != nil { + log.Fatalln("Failed to start Sarama producer:", err) + } + + // We will just log to STDOUT if we're not able to produce messages. + // Note: messages will only be returned here after all retry attempts are exhausted. + go func() { + for err := range producer.Errors() { + log.Println("Failed to write access log entry:", err) + } + }() + + return producer +} diff --git a/vendor/src/github.com/Shopify/sarama/examples/http_server/http_server_test.go b/vendor/src/github.com/Shopify/sarama/examples/http_server/http_server_test.go new file mode 100644 index 00000000..7b2451e2 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/examples/http_server/http_server_test.go @@ -0,0 +1,109 @@ +package main + +import ( + "io" + "net/http" + "net/http/httptest" + "testing" + + "github.com/Shopify/sarama" + "github.com/Shopify/sarama/mocks" +) + +// In normal operation, we expect one access log entry, +// and one data collector entry. Let's assume both will succeed. +// We should return a HTTP 200 status. +func TestCollectSuccessfully(t *testing.T) { + dataCollectorMock := mocks.NewSyncProducer(t, nil) + dataCollectorMock.ExpectSendMessageAndSucceed() + + accessLogProducerMock := mocks.NewAsyncProducer(t, nil) + accessLogProducerMock.ExpectInputAndSucceed() + + // Now, use dependency injection to use the mocks. + s := &Server{ + DataCollector: dataCollectorMock, + AccessLogProducer: accessLogProducerMock, + } + + // The Server's Close call is important; it will call Close on + // the two mock producers, which will then validate whether all + // expectations are resolved. + defer safeClose(t, s) + + req, err := http.NewRequest("GET", "http://example.com/?data", nil) + if err != nil { + t.Fatal(err) + } + res := httptest.NewRecorder() + s.Handler().ServeHTTP(res, req) + + if res.Code != 200 { + t.Errorf("Expected HTTP status 200, found %d", res.Code) + } + + if string(res.Body.Bytes()) != "Your data is stored with unique identifier important/0/1" { + t.Error("Unexpected response body", res.Body) + } +} + +// Now, let's see if we handle the case of not being able to produce +// to the data collector properly. In this case we should return a 500 status. +func TestCollectionFailure(t *testing.T) { + dataCollectorMock := mocks.NewSyncProducer(t, nil) + dataCollectorMock.ExpectSendMessageAndFail(sarama.ErrRequestTimedOut) + + accessLogProducerMock := mocks.NewAsyncProducer(t, nil) + accessLogProducerMock.ExpectInputAndSucceed() + + s := &Server{ + DataCollector: dataCollectorMock, + AccessLogProducer: accessLogProducerMock, + } + defer safeClose(t, s) + + req, err := http.NewRequest("GET", "http://example.com/?data", nil) + if err != nil { + t.Fatal(err) + } + res := httptest.NewRecorder() + s.Handler().ServeHTTP(res, req) + + if res.Code != 500 { + t.Errorf("Expected HTTP status 500, found %d", res.Code) + } +} + +// We don't expect any data collector calls because the path is wrong, +// so we are not setting any expectations on the dataCollectorMock. It +// will still generate an access log entry though. +func TestWrongPath(t *testing.T) { + dataCollectorMock := mocks.NewSyncProducer(t, nil) + + accessLogProducerMock := mocks.NewAsyncProducer(t, nil) + accessLogProducerMock.ExpectInputAndSucceed() + + s := &Server{ + DataCollector: dataCollectorMock, + AccessLogProducer: accessLogProducerMock, + } + defer safeClose(t, s) + + req, err := http.NewRequest("GET", "http://example.com/wrong?data", nil) + if err != nil { + t.Fatal(err) + } + res := httptest.NewRecorder() + + s.Handler().ServeHTTP(res, req) + + if res.Code != 404 { + t.Errorf("Expected HTTP status 404, found %d", res.Code) + } +} + +func safeClose(t *testing.T, o io.Closer) { + if err := o.Close(); err != nil { + t.Error(err) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/fetch_request.go b/vendor/src/github.com/Shopify/sarama/fetch_request.go new file mode 100644 index 00000000..ae701a3f --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/fetch_request.go @@ -0,0 +1,136 @@ +package sarama + +type fetchRequestBlock struct { + fetchOffset int64 + maxBytes int32 +} + +func (b *fetchRequestBlock) encode(pe packetEncoder) error { + pe.putInt64(b.fetchOffset) + pe.putInt32(b.maxBytes) + return nil +} + +func (b *fetchRequestBlock) decode(pd packetDecoder) (err error) { + if b.fetchOffset, err = pd.getInt64(); err != nil { + return err + } + if b.maxBytes, err = pd.getInt32(); err != nil { + return err + } + return nil +} + +type FetchRequest struct { + MaxWaitTime int32 + MinBytes int32 + Version int16 + blocks map[string]map[int32]*fetchRequestBlock +} + +func (r *FetchRequest) encode(pe packetEncoder) (err error) { + pe.putInt32(-1) // replica ID is always -1 for clients + pe.putInt32(r.MaxWaitTime) + pe.putInt32(r.MinBytes) + err = pe.putArrayLength(len(r.blocks)) + if err != nil { + return err + } + for topic, blocks := range r.blocks { + err = pe.putString(topic) + if err != nil { + return err + } + err = pe.putArrayLength(len(blocks)) + if err != nil { + return err + } + for partition, block := range blocks { + pe.putInt32(partition) + err = block.encode(pe) + if err != nil { + return err + } + } + } + return nil +} + +func (r *FetchRequest) decode(pd packetDecoder, version int16) (err error) { + r.Version = version + if _, err = pd.getInt32(); err != nil { + return err + } + if r.MaxWaitTime, err = pd.getInt32(); err != nil { + return err + } + if r.MinBytes, err = pd.getInt32(); err != nil { + return err + } + topicCount, err := pd.getArrayLength() + if err != nil { + return err + } + if topicCount == 0 { + return nil + } + r.blocks = make(map[string]map[int32]*fetchRequestBlock) + for i := 0; i < topicCount; i++ { + topic, err := pd.getString() + if err != nil { + return err + } + partitionCount, err := pd.getArrayLength() + if err != nil { + return err + } + r.blocks[topic] = make(map[int32]*fetchRequestBlock) + for j := 0; j < partitionCount; j++ { + partition, err := pd.getInt32() + if err != nil { + return err + } + fetchBlock := &fetchRequestBlock{} + if err = fetchBlock.decode(pd); err != nil { + return nil + } + r.blocks[topic][partition] = fetchBlock + } + } + return nil +} + +func (r *FetchRequest) key() int16 { + return 1 +} + +func (r *FetchRequest) version() int16 { + return r.Version +} + +func (r *FetchRequest) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_9_0_0 + case 2: + return V0_10_0_0 + default: + return minVersion + } +} + +func (r *FetchRequest) AddBlock(topic string, partitionID int32, fetchOffset int64, maxBytes int32) { + if r.blocks == nil { + r.blocks = make(map[string]map[int32]*fetchRequestBlock) + } + + if r.blocks[topic] == nil { + r.blocks[topic] = make(map[int32]*fetchRequestBlock) + } + + tmp := new(fetchRequestBlock) + tmp.maxBytes = maxBytes + tmp.fetchOffset = fetchOffset + + r.blocks[topic][partitionID] = tmp +} diff --git a/vendor/src/github.com/Shopify/sarama/fetch_request_test.go b/vendor/src/github.com/Shopify/sarama/fetch_request_test.go new file mode 100644 index 00000000..32c083c7 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/fetch_request_test.go @@ -0,0 +1,34 @@ +package sarama + +import "testing" + +var ( + fetchRequestNoBlocks = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} + + fetchRequestWithProperties = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xEF, + 0x00, 0x00, 0x00, 0x00} + + fetchRequestOneBlock = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x56} +) + +func TestFetchRequest(t *testing.T) { + request := new(FetchRequest) + testRequest(t, "no blocks", request, fetchRequestNoBlocks) + + request.MaxWaitTime = 0x20 + request.MinBytes = 0xEF + testRequest(t, "with properties", request, fetchRequestWithProperties) + + request.MaxWaitTime = 0 + request.MinBytes = 0 + request.AddBlock("topic", 0x12, 0x34, 0x56) + testRequest(t, "one block", request, fetchRequestOneBlock) +} diff --git a/vendor/src/github.com/Shopify/sarama/fetch_response.go b/vendor/src/github.com/Shopify/sarama/fetch_response.go new file mode 100644 index 00000000..b56b166c --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/fetch_response.go @@ -0,0 +1,210 @@ +package sarama + +import "time" + +type FetchResponseBlock struct { + Err KError + HighWaterMarkOffset int64 + MsgSet MessageSet +} + +func (b *FetchResponseBlock) decode(pd packetDecoder) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + b.Err = KError(tmp) + + b.HighWaterMarkOffset, err = pd.getInt64() + if err != nil { + return err + } + + msgSetSize, err := pd.getInt32() + if err != nil { + return err + } + + msgSetDecoder, err := pd.getSubset(int(msgSetSize)) + if err != nil { + return err + } + err = (&b.MsgSet).decode(msgSetDecoder) + + return err +} + +func (b *FetchResponseBlock) encode(pe packetEncoder) (err error) { + pe.putInt16(int16(b.Err)) + + pe.putInt64(b.HighWaterMarkOffset) + + pe.push(&lengthField{}) + err = b.MsgSet.encode(pe) + if err != nil { + return err + } + return pe.pop() +} + +type FetchResponse struct { + Blocks map[string]map[int32]*FetchResponseBlock + ThrottleTime time.Duration + Version int16 // v1 requires 0.9+, v2 requires 0.10+ +} + +func (r *FetchResponse) decode(pd packetDecoder, version int16) (err error) { + r.Version = version + + if r.Version >= 1 { + throttle, err := pd.getInt32() + if err != nil { + return err + } + r.ThrottleTime = time.Duration(throttle) * time.Millisecond + } + + numTopics, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks = make(map[string]map[int32]*FetchResponseBlock, numTopics) + for i := 0; i < numTopics; i++ { + name, err := pd.getString() + if err != nil { + return err + } + + numBlocks, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks[name] = make(map[int32]*FetchResponseBlock, numBlocks) + + for j := 0; j < numBlocks; j++ { + id, err := pd.getInt32() + if err != nil { + return err + } + + block := new(FetchResponseBlock) + err = block.decode(pd) + if err != nil { + return err + } + r.Blocks[name][id] = block + } + } + + return nil +} + +func (r *FetchResponse) encode(pe packetEncoder) (err error) { + if r.Version >= 1 { + pe.putInt32(int32(r.ThrottleTime / time.Millisecond)) + } + + err = pe.putArrayLength(len(r.Blocks)) + if err != nil { + return err + } + + for topic, partitions := range r.Blocks { + err = pe.putString(topic) + if err != nil { + return err + } + + err = pe.putArrayLength(len(partitions)) + if err != nil { + return err + } + + for id, block := range partitions { + pe.putInt32(id) + err = block.encode(pe) + if err != nil { + return err + } + } + + } + return nil +} + +func (r *FetchResponse) key() int16 { + return 1 +} + +func (r *FetchResponse) version() int16 { + return r.Version +} + +func (r *FetchResponse) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_9_0_0 + case 2: + return V0_10_0_0 + default: + return minVersion + } +} + +func (r *FetchResponse) GetBlock(topic string, partition int32) *FetchResponseBlock { + if r.Blocks == nil { + return nil + } + + if r.Blocks[topic] == nil { + return nil + } + + return r.Blocks[topic][partition] +} + +func (r *FetchResponse) AddError(topic string, partition int32, err KError) { + if r.Blocks == nil { + r.Blocks = make(map[string]map[int32]*FetchResponseBlock) + } + partitions, ok := r.Blocks[topic] + if !ok { + partitions = make(map[int32]*FetchResponseBlock) + r.Blocks[topic] = partitions + } + frb, ok := partitions[partition] + if !ok { + frb = new(FetchResponseBlock) + partitions[partition] = frb + } + frb.Err = err +} + +func (r *FetchResponse) AddMessage(topic string, partition int32, key, value Encoder, offset int64) { + if r.Blocks == nil { + r.Blocks = make(map[string]map[int32]*FetchResponseBlock) + } + partitions, ok := r.Blocks[topic] + if !ok { + partitions = make(map[int32]*FetchResponseBlock) + r.Blocks[topic] = partitions + } + frb, ok := partitions[partition] + if !ok { + frb = new(FetchResponseBlock) + partitions[partition] = frb + } + var kb []byte + var vb []byte + if key != nil { + kb, _ = key.Encode() + } + if value != nil { + vb, _ = value.Encode() + } + msg := &Message{Key: kb, Value: vb} + msgBlock := &MessageBlock{Msg: msg, Offset: offset} + frb.MsgSet.Messages = append(frb.MsgSet.Messages, msgBlock) +} diff --git a/vendor/src/github.com/Shopify/sarama/fetch_response_test.go b/vendor/src/github.com/Shopify/sarama/fetch_response_test.go new file mode 100644 index 00000000..52fb5a74 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/fetch_response_test.go @@ -0,0 +1,84 @@ +package sarama + +import ( + "bytes" + "testing" +) + +var ( + emptyFetchResponse = []byte{ + 0x00, 0x00, 0x00, 0x00} + + oneMessageFetchResponse = []byte{ + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x05, + 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, + 0x00, 0x00, 0x00, 0x1C, + // messageSet + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, + // message + 0x23, 0x96, 0x4a, 0xf7, // CRC + 0x00, + 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x02, 0x00, 0xEE} +) + +func TestEmptyFetchResponse(t *testing.T) { + response := FetchResponse{} + testVersionDecodable(t, "empty", &response, emptyFetchResponse, 0) + + if len(response.Blocks) != 0 { + t.Error("Decoding produced topic blocks where there were none.") + } + +} + +func TestOneMessageFetchResponse(t *testing.T) { + response := FetchResponse{} + testVersionDecodable(t, "one message", &response, oneMessageFetchResponse, 0) + + if len(response.Blocks) != 1 { + t.Fatal("Decoding produced incorrect number of topic blocks.") + } + + if len(response.Blocks["topic"]) != 1 { + t.Fatal("Decoding produced incorrect number of partition blocks for topic.") + } + + block := response.GetBlock("topic", 5) + if block == nil { + t.Fatal("GetBlock didn't return block.") + } + if block.Err != ErrOffsetOutOfRange { + t.Error("Decoding didn't produce correct error code.") + } + if block.HighWaterMarkOffset != 0x10101010 { + t.Error("Decoding didn't produce correct high water mark offset.") + } + if block.MsgSet.PartialTrailingMessage { + t.Error("Decoding detected a partial trailing message where there wasn't one.") + } + + if len(block.MsgSet.Messages) != 1 { + t.Fatal("Decoding produced incorrect number of messages.") + } + msgBlock := block.MsgSet.Messages[0] + if msgBlock.Offset != 0x550000 { + t.Error("Decoding produced incorrect message offset.") + } + msg := msgBlock.Msg + if msg.Codec != CompressionNone { + t.Error("Decoding produced incorrect message compression.") + } + if msg.Key != nil { + t.Error("Decoding produced message key where there was none.") + } + if !bytes.Equal(msg.Value, []byte{0x00, 0xEE}) { + t.Error("Decoding produced incorrect message value.") + } +} diff --git a/vendor/src/github.com/Shopify/sarama/functional_client_test.go b/vendor/src/github.com/Shopify/sarama/functional_client_test.go new file mode 100644 index 00000000..2bf99d25 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/functional_client_test.go @@ -0,0 +1,90 @@ +package sarama + +import ( + "fmt" + "testing" + "time" +) + +func TestFuncConnectionFailure(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + Proxies["kafka1"].Enabled = false + SaveProxy(t, "kafka1") + + config := NewConfig() + config.Metadata.Retry.Max = 1 + + _, err := NewClient([]string{kafkaBrokers[0]}, config) + if err != ErrOutOfBrokers { + t.Fatal("Expected returned error to be ErrOutOfBrokers, but was: ", err) + } +} + +func TestFuncClientMetadata(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + config := NewConfig() + config.Metadata.Retry.Max = 1 + config.Metadata.Retry.Backoff = 10 * time.Millisecond + client, err := NewClient(kafkaBrokers, config) + if err != nil { + t.Fatal(err) + } + + if err := client.RefreshMetadata("unknown_topic"); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, got", err) + } + + if _, err := client.Leader("unknown_topic", 0); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, got", err) + } + + if _, err := client.Replicas("invalid/topic", 0); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, got", err) + } + + partitions, err := client.Partitions("test.4") + if err != nil { + t.Error(err) + } + if len(partitions) != 4 { + t.Errorf("Expected test.4 topic to have 4 partitions, found %v", partitions) + } + + partitions, err = client.Partitions("test.1") + if err != nil { + t.Error(err) + } + if len(partitions) != 1 { + t.Errorf("Expected test.1 topic to have 1 partitions, found %v", partitions) + } + + safeClose(t, client) +} + +func TestFuncClientCoordinator(t *testing.T) { + checkKafkaVersion(t, "0.8.2") + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + client, err := NewClient(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + broker, err := client.Coordinator(fmt.Sprintf("another_new_consumer_group_%d", i)) + if err != nil { + t.Fatal(err) + } + + if connected, err := broker.Connected(); !connected || err != nil { + t.Errorf("Expected to coordinator %s broker to be properly connected.", broker.Addr()) + } + } + + safeClose(t, client) +} diff --git a/vendor/src/github.com/Shopify/sarama/functional_consumer_test.go b/vendor/src/github.com/Shopify/sarama/functional_consumer_test.go new file mode 100644 index 00000000..ab843310 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/functional_consumer_test.go @@ -0,0 +1,61 @@ +package sarama + +import ( + "math" + "testing" +) + +func TestFuncConsumerOffsetOutOfRange(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + consumer, err := NewConsumer(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + + if _, err := consumer.ConsumePartition("test.1", 0, -10); err != ErrOffsetOutOfRange { + t.Error("Expected ErrOffsetOutOfRange, got:", err) + } + + if _, err := consumer.ConsumePartition("test.1", 0, math.MaxInt64); err != ErrOffsetOutOfRange { + t.Error("Expected ErrOffsetOutOfRange, got:", err) + } + + safeClose(t, consumer) +} + +func TestConsumerHighWaterMarkOffset(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + p, err := NewSyncProducer(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + defer safeClose(t, p) + + _, offset, err := p.SendMessage(&ProducerMessage{Topic: "test.1", Value: StringEncoder("Test")}) + if err != nil { + t.Fatal(err) + } + + c, err := NewConsumer(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + defer safeClose(t, c) + + pc, err := c.ConsumePartition("test.1", 0, OffsetOldest) + if err != nil { + t.Fatal(err) + } + + <-pc.Messages() + + if hwmo := pc.HighWaterMarkOffset(); hwmo != offset+1 { + t.Logf("Last produced offset %d; high water mark should be one higher but found %d.", offset, hwmo) + } + + safeClose(t, pc) +} diff --git a/vendor/src/github.com/Shopify/sarama/functional_offset_manager_test.go b/vendor/src/github.com/Shopify/sarama/functional_offset_manager_test.go new file mode 100644 index 00000000..436f35ef --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/functional_offset_manager_test.go @@ -0,0 +1,47 @@ +package sarama + +import ( + "testing" +) + +func TestFuncOffsetManager(t *testing.T) { + checkKafkaVersion(t, "0.8.2") + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + client, err := NewClient(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + + offsetManager, err := NewOffsetManagerFromClient("sarama.TestFuncOffsetManager", client) + if err != nil { + t.Fatal(err) + } + + pom1, err := offsetManager.ManagePartition("test.1", 0) + if err != nil { + t.Fatal(err) + } + + pom1.MarkOffset(10, "test metadata") + safeClose(t, pom1) + + pom2, err := offsetManager.ManagePartition("test.1", 0) + if err != nil { + t.Fatal(err) + } + + offset, metadata := pom2.NextOffset() + + if offset != 10 { + t.Errorf("Expected the next offset to be 10, found %d.", offset) + } + if metadata != "test metadata" { + t.Errorf("Expected metadata to be 'test metadata', found %s.", metadata) + } + + safeClose(t, pom2) + safeClose(t, offsetManager) + safeClose(t, client) +} diff --git a/vendor/src/github.com/Shopify/sarama/functional_producer_test.go b/vendor/src/github.com/Shopify/sarama/functional_producer_test.go new file mode 100644 index 00000000..91bf3b5e --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/functional_producer_test.go @@ -0,0 +1,323 @@ +package sarama + +import ( + "fmt" + "os" + "sync" + "testing" + "time" + + toxiproxy "github.com/Shopify/toxiproxy/client" + "github.com/rcrowley/go-metrics" +) + +const TestBatchSize = 1000 + +func TestFuncProducing(t *testing.T) { + config := NewConfig() + testProducingMessages(t, config) +} + +func TestFuncProducingGzip(t *testing.T) { + config := NewConfig() + config.Producer.Compression = CompressionGZIP + testProducingMessages(t, config) +} + +func TestFuncProducingSnappy(t *testing.T) { + config := NewConfig() + config.Producer.Compression = CompressionSnappy + testProducingMessages(t, config) +} + +func TestFuncProducingNoResponse(t *testing.T) { + config := NewConfig() + config.Producer.RequiredAcks = NoResponse + testProducingMessages(t, config) +} + +func TestFuncProducingFlushing(t *testing.T) { + config := NewConfig() + config.Producer.Flush.Messages = TestBatchSize / 8 + config.Producer.Flush.Frequency = 250 * time.Millisecond + testProducingMessages(t, config) +} + +func TestFuncMultiPartitionProduce(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + config := NewConfig() + config.ChannelBufferSize = 20 + config.Producer.Flush.Frequency = 50 * time.Millisecond + config.Producer.Flush.Messages = 200 + config.Producer.Return.Successes = true + producer, err := NewSyncProducer(kafkaBrokers, config) + if err != nil { + t.Fatal(err) + } + + var wg sync.WaitGroup + wg.Add(TestBatchSize) + + for i := 1; i <= TestBatchSize; i++ { + go func(i int) { + defer wg.Done() + msg := &ProducerMessage{Topic: "test.64", Key: nil, Value: StringEncoder(fmt.Sprintf("hur %d", i))} + if _, _, err := producer.SendMessage(msg); err != nil { + t.Error(i, err) + } + }(i) + } + + wg.Wait() + if err := producer.Close(); err != nil { + t.Error(err) + } +} + +func TestFuncProducingToInvalidTopic(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + producer, err := NewSyncProducer(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + + if _, _, err := producer.SendMessage(&ProducerMessage{Topic: "in/valid"}); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, found", err) + } + + if _, _, err := producer.SendMessage(&ProducerMessage{Topic: "in/valid"}); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, found", err) + } + + safeClose(t, producer) +} + +func testProducingMessages(t *testing.T, config *Config) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + // Configure some latency in order to properly validate the request latency metric + for _, proxy := range Proxies { + if _, err := proxy.AddToxic("", "latency", "", 1, toxiproxy.Attributes{"latency": 10}); err != nil { + t.Fatal("Unable to configure latency toxicity", err) + } + } + + config.Producer.Return.Successes = true + config.Consumer.Return.Errors = true + + client, err := NewClient(kafkaBrokers, config) + if err != nil { + t.Fatal(err) + } + + // Keep in mind the current offset + initialOffset, err := client.GetOffset("test.1", 0, OffsetNewest) + if err != nil { + t.Fatal(err) + } + + producer, err := NewAsyncProducerFromClient(client) + if err != nil { + t.Fatal(err) + } + + expectedResponses := TestBatchSize + for i := 1; i <= TestBatchSize; { + msg := &ProducerMessage{Topic: "test.1", Key: nil, Value: StringEncoder(fmt.Sprintf("testing %d", i))} + select { + case producer.Input() <- msg: + i++ + case ret := <-producer.Errors(): + t.Fatal(ret.Err) + case <-producer.Successes(): + expectedResponses-- + } + } + for expectedResponses > 0 { + select { + case ret := <-producer.Errors(): + t.Fatal(ret.Err) + case <-producer.Successes(): + expectedResponses-- + } + } + safeClose(t, producer) + + // Validate producer metrics before using the consumer minus the offset request + validateMetrics(t, client) + + master, err := NewConsumerFromClient(client) + if err != nil { + t.Fatal(err) + } + consumer, err := master.ConsumePartition("test.1", 0, initialOffset) + if err != nil { + t.Fatal(err) + } + + for i := 1; i <= TestBatchSize; i++ { + select { + case <-time.After(10 * time.Second): + t.Fatal("Not received any more events in the last 10 seconds.") + + case err := <-consumer.Errors(): + t.Error(err) + + case message := <-consumer.Messages(): + if string(message.Value) != fmt.Sprintf("testing %d", i) { + t.Fatalf("Unexpected message with index %d: %s", i, message.Value) + } + } + + } + safeClose(t, consumer) + safeClose(t, client) +} + +func validateMetrics(t *testing.T, client Client) { + // Get the broker used by test1 topic + var broker *Broker + if partitions, err := client.Partitions("test.1"); err != nil { + t.Error(err) + } else { + for _, partition := range partitions { + if b, err := client.Leader("test.1", partition); err != nil { + t.Error(err) + } else { + if broker != nil && b != broker { + t.Fatal("Expected only one broker, got at least 2") + } + broker = b + } + } + } + + metricValidators := newMetricValidators() + noResponse := client.Config().Producer.RequiredAcks == NoResponse + compressionEnabled := client.Config().Producer.Compression != CompressionNone + + // We are adding 10ms of latency to all requests with toxiproxy + minRequestLatencyInMs := 10 + if noResponse { + // but when we do not wait for a response it can be less than 1ms + minRequestLatencyInMs = 0 + } + + // We read at least 1 byte from the broker + metricValidators.registerForAllBrokers(broker, minCountMeterValidator("incoming-byte-rate", 1)) + // in at least 3 global requests (1 for metadata request, 1 for offset request and N for produce request) + metricValidators.register(minCountMeterValidator("request-rate", 3)) + metricValidators.register(minCountHistogramValidator("request-size", 3)) + metricValidators.register(minValHistogramValidator("request-size", 1)) + metricValidators.register(minValHistogramValidator("request-latency-in-ms", minRequestLatencyInMs)) + // and at least 2 requests to the registered broker (offset + produces) + metricValidators.registerForBroker(broker, minCountMeterValidator("request-rate", 2)) + metricValidators.registerForBroker(broker, minCountHistogramValidator("request-size", 2)) + metricValidators.registerForBroker(broker, minValHistogramValidator("request-size", 1)) + metricValidators.registerForBroker(broker, minValHistogramValidator("request-latency-in-ms", minRequestLatencyInMs)) + + // We send at least 1 batch + metricValidators.registerForGlobalAndTopic("test_1", minCountHistogramValidator("batch-size", 1)) + metricValidators.registerForGlobalAndTopic("test_1", minValHistogramValidator("batch-size", 1)) + if compressionEnabled { + // We record compression ratios between [0.50,-10.00] (50-1000 with a histogram) for at least one "fake" record + metricValidators.registerForGlobalAndTopic("test_1", minCountHistogramValidator("compression-ratio", 1)) + metricValidators.registerForGlobalAndTopic("test_1", minValHistogramValidator("compression-ratio", 50)) + metricValidators.registerForGlobalAndTopic("test_1", maxValHistogramValidator("compression-ratio", 1000)) + } else { + // We record compression ratios of 1.00 (100 with a histogram) for every TestBatchSize record + metricValidators.registerForGlobalAndTopic("test_1", countHistogramValidator("compression-ratio", TestBatchSize)) + metricValidators.registerForGlobalAndTopic("test_1", minValHistogramValidator("compression-ratio", 100)) + metricValidators.registerForGlobalAndTopic("test_1", maxValHistogramValidator("compression-ratio", 100)) + } + + // We send exactly TestBatchSize messages + metricValidators.registerForGlobalAndTopic("test_1", countMeterValidator("record-send-rate", TestBatchSize)) + // We send at least one record per request + metricValidators.registerForGlobalAndTopic("test_1", minCountHistogramValidator("records-per-request", 1)) + metricValidators.registerForGlobalAndTopic("test_1", minValHistogramValidator("records-per-request", 1)) + + // We receive at least 1 byte from the broker + metricValidators.registerForAllBrokers(broker, minCountMeterValidator("outgoing-byte-rate", 1)) + if noResponse { + // in exactly 2 global responses (metadata + offset) + metricValidators.register(countMeterValidator("response-rate", 2)) + metricValidators.register(minCountHistogramValidator("response-size", 2)) + metricValidators.register(minValHistogramValidator("response-size", 1)) + // and exactly 1 offset response for the registered broker + metricValidators.registerForBroker(broker, countMeterValidator("response-rate", 1)) + metricValidators.registerForBroker(broker, minCountHistogramValidator("response-size", 1)) + metricValidators.registerForBroker(broker, minValHistogramValidator("response-size", 1)) + } else { + // in at least 3 global responses (metadata + offset + produces) + metricValidators.register(minCountMeterValidator("response-rate", 3)) + metricValidators.register(minCountHistogramValidator("response-size", 3)) + metricValidators.register(minValHistogramValidator("response-size", 1)) + // and at least 2 for the registered broker + metricValidators.registerForBroker(broker, minCountMeterValidator("response-rate", 2)) + metricValidators.registerForBroker(broker, minCountHistogramValidator("response-size", 2)) + metricValidators.registerForBroker(broker, minValHistogramValidator("response-size", 1)) + } + + // Run the validators + metricValidators.run(t, client.Config().MetricRegistry) +} + +// Benchmarks + +func BenchmarkProducerSmall(b *testing.B) { + benchmarkProducer(b, nil, "test.64", ByteEncoder(make([]byte, 128))) +} +func BenchmarkProducerMedium(b *testing.B) { + benchmarkProducer(b, nil, "test.64", ByteEncoder(make([]byte, 1024))) +} +func BenchmarkProducerLarge(b *testing.B) { + benchmarkProducer(b, nil, "test.64", ByteEncoder(make([]byte, 8192))) +} +func BenchmarkProducerSmallSinglePartition(b *testing.B) { + benchmarkProducer(b, nil, "test.1", ByteEncoder(make([]byte, 128))) +} +func BenchmarkProducerMediumSnappy(b *testing.B) { + conf := NewConfig() + conf.Producer.Compression = CompressionSnappy + benchmarkProducer(b, conf, "test.1", ByteEncoder(make([]byte, 1024))) +} + +func benchmarkProducer(b *testing.B, conf *Config, topic string, value Encoder) { + setupFunctionalTest(b) + defer teardownFunctionalTest(b) + + metricsDisable := os.Getenv("METRICS_DISABLE") + if metricsDisable != "" { + previousUseNilMetrics := metrics.UseNilMetrics + Logger.Println("Disabling metrics using no-op implementation") + metrics.UseNilMetrics = true + // Restore previous setting + defer func() { + metrics.UseNilMetrics = previousUseNilMetrics + }() + } + + producer, err := NewAsyncProducer(kafkaBrokers, conf) + if err != nil { + b.Fatal(err) + } + + b.ResetTimer() + + for i := 1; i <= b.N; { + msg := &ProducerMessage{Topic: topic, Key: StringEncoder(fmt.Sprintf("%d", i)), Value: value} + select { + case producer.Input() <- msg: + i++ + case ret := <-producer.Errors(): + b.Fatal(ret.Err) + } + } + safeClose(b, producer) +} diff --git a/vendor/src/github.com/Shopify/sarama/functional_test.go b/vendor/src/github.com/Shopify/sarama/functional_test.go new file mode 100644 index 00000000..846eb29f --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/functional_test.go @@ -0,0 +1,148 @@ +package sarama + +import ( + "log" + "math/rand" + "net" + "os" + "strconv" + "strings" + "testing" + "time" + + toxiproxy "github.com/Shopify/toxiproxy/client" +) + +const ( + VagrantToxiproxy = "http://192.168.100.67:8474" + VagrantKafkaPeers = "192.168.100.67:9091,192.168.100.67:9092,192.168.100.67:9093,192.168.100.67:9094,192.168.100.67:9095" + VagrantZookeeperPeers = "192.168.100.67:2181,192.168.100.67:2182,192.168.100.67:2183,192.168.100.67:2184,192.168.100.67:2185" +) + +var ( + kafkaAvailable, kafkaRequired bool + kafkaBrokers []string + + proxyClient *toxiproxy.Client + Proxies map[string]*toxiproxy.Proxy + ZKProxies = []string{"zk1", "zk2", "zk3", "zk4", "zk5"} + KafkaProxies = []string{"kafka1", "kafka2", "kafka3", "kafka4", "kafka5"} +) + +func init() { + if os.Getenv("DEBUG") == "true" { + Logger = log.New(os.Stdout, "[sarama] ", log.LstdFlags) + } + + seed := time.Now().UTC().UnixNano() + if tmp := os.Getenv("TEST_SEED"); tmp != "" { + seed, _ = strconv.ParseInt(tmp, 0, 64) + } + Logger.Println("Using random seed:", seed) + rand.Seed(seed) + + proxyAddr := os.Getenv("TOXIPROXY_ADDR") + if proxyAddr == "" { + proxyAddr = VagrantToxiproxy + } + proxyClient = toxiproxy.NewClient(proxyAddr) + + kafkaPeers := os.Getenv("KAFKA_PEERS") + if kafkaPeers == "" { + kafkaPeers = VagrantKafkaPeers + } + kafkaBrokers = strings.Split(kafkaPeers, ",") + + if c, err := net.DialTimeout("tcp", kafkaBrokers[0], 5*time.Second); err == nil { + if err = c.Close(); err == nil { + kafkaAvailable = true + } + } + + kafkaRequired = os.Getenv("CI") != "" +} + +func checkKafkaAvailability(t testing.TB) { + if !kafkaAvailable { + if kafkaRequired { + t.Fatalf("Kafka broker is not available on %s. Set KAFKA_PEERS to connect to Kafka on a different location.", kafkaBrokers[0]) + } else { + t.Skipf("Kafka broker is not available on %s. Set KAFKA_PEERS to connect to Kafka on a different location.", kafkaBrokers[0]) + } + } +} + +func checkKafkaVersion(t testing.TB, requiredVersion string) { + kafkaVersion := os.Getenv("KAFKA_VERSION") + if kafkaVersion == "" { + t.Logf("No KAFKA_VERSION set. This test requires Kafka version %s or higher. Continuing...", requiredVersion) + } else { + available := parseKafkaVersion(kafkaVersion) + required := parseKafkaVersion(requiredVersion) + if !available.satisfies(required) { + t.Skipf("Kafka version %s is required for this test; you have %s. Skipping...", requiredVersion, kafkaVersion) + } + } +} + +func resetProxies(t testing.TB) { + if err := proxyClient.ResetState(); err != nil { + t.Error(err) + } + Proxies = nil +} + +func fetchProxies(t testing.TB) { + var err error + Proxies, err = proxyClient.Proxies() + if err != nil { + t.Fatal(err) + } +} + +func SaveProxy(t *testing.T, px string) { + if err := Proxies[px].Save(); err != nil { + t.Fatal(err) + } +} + +func setupFunctionalTest(t testing.TB) { + checkKafkaAvailability(t) + resetProxies(t) + fetchProxies(t) +} + +func teardownFunctionalTest(t testing.TB) { + resetProxies(t) +} + +type kafkaVersion []int + +func (kv kafkaVersion) satisfies(other kafkaVersion) bool { + var ov int + for index, v := range kv { + if len(other) <= index { + ov = 0 + } else { + ov = other[index] + } + + if v < ov { + return false + } else if v > ov { + return true + } + } + return true +} + +func parseKafkaVersion(version string) kafkaVersion { + numbers := strings.Split(version, ".") + result := make(kafkaVersion, 0, len(numbers)) + for _, number := range numbers { + nr, _ := strconv.Atoi(number) + result = append(result, nr) + } + + return result +} diff --git a/vendor/src/github.com/Shopify/sarama/heartbeat_request.go b/vendor/src/github.com/Shopify/sarama/heartbeat_request.go new file mode 100644 index 00000000..ce49c473 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/heartbeat_request.go @@ -0,0 +1,47 @@ +package sarama + +type HeartbeatRequest struct { + GroupId string + GenerationId int32 + MemberId string +} + +func (r *HeartbeatRequest) encode(pe packetEncoder) error { + if err := pe.putString(r.GroupId); err != nil { + return err + } + + pe.putInt32(r.GenerationId) + + if err := pe.putString(r.MemberId); err != nil { + return err + } + + return nil +} + +func (r *HeartbeatRequest) decode(pd packetDecoder, version int16) (err error) { + if r.GroupId, err = pd.getString(); err != nil { + return + } + if r.GenerationId, err = pd.getInt32(); err != nil { + return + } + if r.MemberId, err = pd.getString(); err != nil { + return + } + + return nil +} + +func (r *HeartbeatRequest) key() int16 { + return 12 +} + +func (r *HeartbeatRequest) version() int16 { + return 0 +} + +func (r *HeartbeatRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/heartbeat_request_test.go b/vendor/src/github.com/Shopify/sarama/heartbeat_request_test.go new file mode 100644 index 00000000..da6cd18f --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/heartbeat_request_test.go @@ -0,0 +1,21 @@ +package sarama + +import "testing" + +var ( + basicHeartbeatRequest = []byte{ + 0, 3, 'f', 'o', 'o', // Group ID + 0x00, 0x01, 0x02, 0x03, // Generatiuon ID + 0, 3, 'b', 'a', 'z', // Member ID + } +) + +func TestHeartbeatRequest(t *testing.T) { + var request *HeartbeatRequest + + request = new(HeartbeatRequest) + request.GroupId = "foo" + request.GenerationId = 66051 + request.MemberId = "baz" + testRequest(t, "basic", request, basicHeartbeatRequest) +} diff --git a/vendor/src/github.com/Shopify/sarama/heartbeat_response.go b/vendor/src/github.com/Shopify/sarama/heartbeat_response.go new file mode 100644 index 00000000..3c51163a --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/heartbeat_response.go @@ -0,0 +1,32 @@ +package sarama + +type HeartbeatResponse struct { + Err KError +} + +func (r *HeartbeatResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + return nil +} + +func (r *HeartbeatResponse) decode(pd packetDecoder, version int16) error { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + return nil +} + +func (r *HeartbeatResponse) key() int16 { + return 12 +} + +func (r *HeartbeatResponse) version() int16 { + return 0 +} + +func (r *HeartbeatResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/heartbeat_response_test.go b/vendor/src/github.com/Shopify/sarama/heartbeat_response_test.go new file mode 100644 index 00000000..5bcbec98 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/heartbeat_response_test.go @@ -0,0 +1,18 @@ +package sarama + +import "testing" + +var ( + heartbeatResponseNoError = []byte{ + 0x00, 0x00} +) + +func TestHeartbeatResponse(t *testing.T) { + var response *HeartbeatResponse + + response = new(HeartbeatResponse) + testVersionDecodable(t, "no error", response, heartbeatResponseNoError, 0) + if response.Err != ErrNoError { + t.Error("Decoding error failed: no error expected but found", response.Err) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/join_group_request.go b/vendor/src/github.com/Shopify/sarama/join_group_request.go new file mode 100644 index 00000000..656db456 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/join_group_request.go @@ -0,0 +1,108 @@ +package sarama + +type JoinGroupRequest struct { + GroupId string + SessionTimeout int32 + MemberId string + ProtocolType string + GroupProtocols map[string][]byte +} + +func (r *JoinGroupRequest) encode(pe packetEncoder) error { + if err := pe.putString(r.GroupId); err != nil { + return err + } + pe.putInt32(r.SessionTimeout) + if err := pe.putString(r.MemberId); err != nil { + return err + } + if err := pe.putString(r.ProtocolType); err != nil { + return err + } + + if err := pe.putArrayLength(len(r.GroupProtocols)); err != nil { + return err + } + for name, metadata := range r.GroupProtocols { + if err := pe.putString(name); err != nil { + return err + } + if err := pe.putBytes(metadata); err != nil { + return err + } + } + + return nil +} + +func (r *JoinGroupRequest) decode(pd packetDecoder, version int16) (err error) { + if r.GroupId, err = pd.getString(); err != nil { + return + } + + if r.SessionTimeout, err = pd.getInt32(); err != nil { + return + } + + if r.MemberId, err = pd.getString(); err != nil { + return + } + + if r.ProtocolType, err = pd.getString(); err != nil { + return + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + if n == 0 { + return nil + } + + r.GroupProtocols = make(map[string][]byte) + for i := 0; i < n; i++ { + name, err := pd.getString() + if err != nil { + return err + } + metadata, err := pd.getBytes() + if err != nil { + return err + } + + r.GroupProtocols[name] = metadata + } + + return nil +} + +func (r *JoinGroupRequest) key() int16 { + return 11 +} + +func (r *JoinGroupRequest) version() int16 { + return 0 +} + +func (r *JoinGroupRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} + +func (r *JoinGroupRequest) AddGroupProtocol(name string, metadata []byte) { + if r.GroupProtocols == nil { + r.GroupProtocols = make(map[string][]byte) + } + + r.GroupProtocols[name] = metadata +} + +func (r *JoinGroupRequest) AddGroupProtocolMetadata(name string, metadata *ConsumerGroupMemberMetadata) error { + bin, err := encode(metadata, nil) + if err != nil { + return err + } + + r.AddGroupProtocol(name, bin) + return nil +} diff --git a/vendor/src/github.com/Shopify/sarama/join_group_request_test.go b/vendor/src/github.com/Shopify/sarama/join_group_request_test.go new file mode 100644 index 00000000..8a6448c0 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/join_group_request_test.go @@ -0,0 +1,41 @@ +package sarama + +import "testing" + +var ( + joinGroupRequestNoProtocols = []byte{ + 0, 9, 'T', 'e', 's', 't', 'G', 'r', 'o', 'u', 'p', // Group ID + 0, 0, 0, 100, // Session timeout + 0, 0, // Member ID + 0, 8, 'c', 'o', 'n', 's', 'u', 'm', 'e', 'r', // Protocol Type + 0, 0, 0, 0, // 0 protocol groups + } + + joinGroupRequestOneProtocol = []byte{ + 0, 9, 'T', 'e', 's', 't', 'G', 'r', 'o', 'u', 'p', // Group ID + 0, 0, 0, 100, // Session timeout + 0, 11, 'O', 'n', 'e', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', // Member ID + 0, 8, 'c', 'o', 'n', 's', 'u', 'm', 'e', 'r', // Protocol Type + 0, 0, 0, 1, // 1 group protocol + 0, 3, 'o', 'n', 'e', // Protocol name + 0, 0, 0, 3, 0x01, 0x02, 0x03, // protocol metadata + } +) + +func TestJoinGroupRequest(t *testing.T) { + var request *JoinGroupRequest + + request = new(JoinGroupRequest) + request.GroupId = "TestGroup" + request.SessionTimeout = 100 + request.ProtocolType = "consumer" + testRequest(t, "no protocols", request, joinGroupRequestNoProtocols) + + request = new(JoinGroupRequest) + request.GroupId = "TestGroup" + request.SessionTimeout = 100 + request.MemberId = "OneProtocol" + request.ProtocolType = "consumer" + request.AddGroupProtocol("one", []byte{0x01, 0x02, 0x03}) + testRequest(t, "one protocol", request, joinGroupRequestOneProtocol) +} diff --git a/vendor/src/github.com/Shopify/sarama/join_group_response.go b/vendor/src/github.com/Shopify/sarama/join_group_response.go new file mode 100644 index 00000000..94c7a7fd --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/join_group_response.go @@ -0,0 +1,114 @@ +package sarama + +type JoinGroupResponse struct { + Err KError + GenerationId int32 + GroupProtocol string + LeaderId string + MemberId string + Members map[string][]byte +} + +func (r *JoinGroupResponse) GetMembers() (map[string]ConsumerGroupMemberMetadata, error) { + members := make(map[string]ConsumerGroupMemberMetadata, len(r.Members)) + for id, bin := range r.Members { + meta := new(ConsumerGroupMemberMetadata) + if err := decode(bin, meta); err != nil { + return nil, err + } + members[id] = *meta + } + return members, nil +} + +func (r *JoinGroupResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + pe.putInt32(r.GenerationId) + + if err := pe.putString(r.GroupProtocol); err != nil { + return err + } + if err := pe.putString(r.LeaderId); err != nil { + return err + } + if err := pe.putString(r.MemberId); err != nil { + return err + } + + if err := pe.putArrayLength(len(r.Members)); err != nil { + return err + } + + for memberId, memberMetadata := range r.Members { + if err := pe.putString(memberId); err != nil { + return err + } + + if err := pe.putBytes(memberMetadata); err != nil { + return err + } + } + + return nil +} + +func (r *JoinGroupResponse) decode(pd packetDecoder, version int16) (err error) { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + if r.GenerationId, err = pd.getInt32(); err != nil { + return + } + + if r.GroupProtocol, err = pd.getString(); err != nil { + return + } + + if r.LeaderId, err = pd.getString(); err != nil { + return + } + + if r.MemberId, err = pd.getString(); err != nil { + return + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + if n == 0 { + return nil + } + + r.Members = make(map[string][]byte) + for i := 0; i < n; i++ { + memberId, err := pd.getString() + if err != nil { + return err + } + + memberMetadata, err := pd.getBytes() + if err != nil { + return err + } + + r.Members[memberId] = memberMetadata + } + + return nil +} + +func (r *JoinGroupResponse) key() int16 { + return 11 +} + +func (r *JoinGroupResponse) version() int16 { + return 0 +} + +func (r *JoinGroupResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/join_group_response_test.go b/vendor/src/github.com/Shopify/sarama/join_group_response_test.go new file mode 100644 index 00000000..ba7f71f2 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/join_group_response_test.go @@ -0,0 +1,98 @@ +package sarama + +import ( + "reflect" + "testing" +) + +var ( + joinGroupResponseNoError = []byte{ + 0x00, 0x00, // No error + 0x00, 0x01, 0x02, 0x03, // Generation ID + 0, 8, 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', // Protocol name chosen + 0, 3, 'f', 'o', 'o', // Leader ID + 0, 3, 'b', 'a', 'r', // Member ID + 0, 0, 0, 0, // No member info + } + + joinGroupResponseWithError = []byte{ + 0, 23, // Error: inconsistent group protocol + 0x00, 0x00, 0x00, 0x00, // Generation ID + 0, 0, // Protocol name chosen + 0, 0, // Leader ID + 0, 0, // Member ID + 0, 0, 0, 0, // No member info + } + + joinGroupResponseLeader = []byte{ + 0x00, 0x00, // No error + 0x00, 0x01, 0x02, 0x03, // Generation ID + 0, 8, 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', // Protocol name chosen + 0, 3, 'f', 'o', 'o', // Leader ID + 0, 3, 'f', 'o', 'o', // Member ID == Leader ID + 0, 0, 0, 1, // 1 member + 0, 3, 'f', 'o', 'o', // Member ID + 0, 0, 0, 3, 0x01, 0x02, 0x03, // Member metadata + } +) + +func TestJoinGroupResponse(t *testing.T) { + var response *JoinGroupResponse + + response = new(JoinGroupResponse) + testVersionDecodable(t, "no error", response, joinGroupResponseNoError, 0) + if response.Err != ErrNoError { + t.Error("Decoding Err failed: no error expected but found", response.Err) + } + if response.GenerationId != 66051 { + t.Error("Decoding GenerationId failed, found:", response.GenerationId) + } + if response.LeaderId != "foo" { + t.Error("Decoding LeaderId failed, found:", response.LeaderId) + } + if response.MemberId != "bar" { + t.Error("Decoding MemberId failed, found:", response.MemberId) + } + if len(response.Members) != 0 { + t.Error("Decoding Members failed, found:", response.Members) + } + + response = new(JoinGroupResponse) + testVersionDecodable(t, "with error", response, joinGroupResponseWithError, 0) + if response.Err != ErrInconsistentGroupProtocol { + t.Error("Decoding Err failed: ErrInconsistentGroupProtocol expected but found", response.Err) + } + if response.GenerationId != 0 { + t.Error("Decoding GenerationId failed, found:", response.GenerationId) + } + if response.LeaderId != "" { + t.Error("Decoding LeaderId failed, found:", response.LeaderId) + } + if response.MemberId != "" { + t.Error("Decoding MemberId failed, found:", response.MemberId) + } + if len(response.Members) != 0 { + t.Error("Decoding Members failed, found:", response.Members) + } + + response = new(JoinGroupResponse) + testVersionDecodable(t, "with error", response, joinGroupResponseLeader, 0) + if response.Err != ErrNoError { + t.Error("Decoding Err failed: ErrNoError expected but found", response.Err) + } + if response.GenerationId != 66051 { + t.Error("Decoding GenerationId failed, found:", response.GenerationId) + } + if response.LeaderId != "foo" { + t.Error("Decoding LeaderId failed, found:", response.LeaderId) + } + if response.MemberId != "foo" { + t.Error("Decoding MemberId failed, found:", response.MemberId) + } + if len(response.Members) != 1 { + t.Error("Decoding Members failed, found:", response.Members) + } + if !reflect.DeepEqual(response.Members["foo"], []byte{0x01, 0x02, 0x03}) { + t.Error("Decoding foo member failed, found:", response.Members["foo"]) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/leave_group_request.go b/vendor/src/github.com/Shopify/sarama/leave_group_request.go new file mode 100644 index 00000000..e1774274 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/leave_group_request.go @@ -0,0 +1,40 @@ +package sarama + +type LeaveGroupRequest struct { + GroupId string + MemberId string +} + +func (r *LeaveGroupRequest) encode(pe packetEncoder) error { + if err := pe.putString(r.GroupId); err != nil { + return err + } + if err := pe.putString(r.MemberId); err != nil { + return err + } + + return nil +} + +func (r *LeaveGroupRequest) decode(pd packetDecoder, version int16) (err error) { + if r.GroupId, err = pd.getString(); err != nil { + return + } + if r.MemberId, err = pd.getString(); err != nil { + return + } + + return nil +} + +func (r *LeaveGroupRequest) key() int16 { + return 13 +} + +func (r *LeaveGroupRequest) version() int16 { + return 0 +} + +func (r *LeaveGroupRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/leave_group_request_test.go b/vendor/src/github.com/Shopify/sarama/leave_group_request_test.go new file mode 100644 index 00000000..c1fed6d2 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/leave_group_request_test.go @@ -0,0 +1,19 @@ +package sarama + +import "testing" + +var ( + basicLeaveGroupRequest = []byte{ + 0, 3, 'f', 'o', 'o', + 0, 3, 'b', 'a', 'r', + } +) + +func TestLeaveGroupRequest(t *testing.T) { + var request *LeaveGroupRequest + + request = new(LeaveGroupRequest) + request.GroupId = "foo" + request.MemberId = "bar" + testRequest(t, "basic", request, basicLeaveGroupRequest) +} diff --git a/vendor/src/github.com/Shopify/sarama/leave_group_response.go b/vendor/src/github.com/Shopify/sarama/leave_group_response.go new file mode 100644 index 00000000..bd4a34f4 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/leave_group_response.go @@ -0,0 +1,32 @@ +package sarama + +type LeaveGroupResponse struct { + Err KError +} + +func (r *LeaveGroupResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + return nil +} + +func (r *LeaveGroupResponse) decode(pd packetDecoder, version int16) (err error) { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + return nil +} + +func (r *LeaveGroupResponse) key() int16 { + return 13 +} + +func (r *LeaveGroupResponse) version() int16 { + return 0 +} + +func (r *LeaveGroupResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/leave_group_response_test.go b/vendor/src/github.com/Shopify/sarama/leave_group_response_test.go new file mode 100644 index 00000000..9207c666 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/leave_group_response_test.go @@ -0,0 +1,24 @@ +package sarama + +import "testing" + +var ( + leaveGroupResponseNoError = []byte{0x00, 0x00} + leaveGroupResponseWithError = []byte{0, 25} +) + +func TestLeaveGroupResponse(t *testing.T) { + var response *LeaveGroupResponse + + response = new(LeaveGroupResponse) + testVersionDecodable(t, "no error", response, leaveGroupResponseNoError, 0) + if response.Err != ErrNoError { + t.Error("Decoding error failed: no error expected but found", response.Err) + } + + response = new(LeaveGroupResponse) + testVersionDecodable(t, "with error", response, leaveGroupResponseWithError, 0) + if response.Err != ErrUnknownMemberId { + t.Error("Decoding error failed: ErrUnknownMemberId expected but found", response.Err) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/length_field.go b/vendor/src/github.com/Shopify/sarama/length_field.go new file mode 100644 index 00000000..70078be5 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/length_field.go @@ -0,0 +1,29 @@ +package sarama + +import "encoding/binary" + +// LengthField implements the PushEncoder and PushDecoder interfaces for calculating 4-byte lengths. +type lengthField struct { + startOffset int +} + +func (l *lengthField) saveOffset(in int) { + l.startOffset = in +} + +func (l *lengthField) reserveLength() int { + return 4 +} + +func (l *lengthField) run(curOffset int, buf []byte) error { + binary.BigEndian.PutUint32(buf[l.startOffset:], uint32(curOffset-l.startOffset-4)) + return nil +} + +func (l *lengthField) check(curOffset int, buf []byte) error { + if uint32(curOffset-l.startOffset-4) != binary.BigEndian.Uint32(buf[l.startOffset:]) { + return PacketDecodingError{"length field invalid"} + } + + return nil +} diff --git a/vendor/src/github.com/Shopify/sarama/list_groups_request.go b/vendor/src/github.com/Shopify/sarama/list_groups_request.go new file mode 100644 index 00000000..3b16abf7 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/list_groups_request.go @@ -0,0 +1,24 @@ +package sarama + +type ListGroupsRequest struct { +} + +func (r *ListGroupsRequest) encode(pe packetEncoder) error { + return nil +} + +func (r *ListGroupsRequest) decode(pd packetDecoder, version int16) (err error) { + return nil +} + +func (r *ListGroupsRequest) key() int16 { + return 16 +} + +func (r *ListGroupsRequest) version() int16 { + return 0 +} + +func (r *ListGroupsRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/list_groups_request_test.go b/vendor/src/github.com/Shopify/sarama/list_groups_request_test.go new file mode 100644 index 00000000..2e977d9a --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/list_groups_request_test.go @@ -0,0 +1,7 @@ +package sarama + +import "testing" + +func TestListGroupsRequest(t *testing.T) { + testRequest(t, "ListGroupsRequest", &ListGroupsRequest{}, []byte{}) +} diff --git a/vendor/src/github.com/Shopify/sarama/list_groups_response.go b/vendor/src/github.com/Shopify/sarama/list_groups_response.go new file mode 100644 index 00000000..3a84f9b6 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/list_groups_response.go @@ -0,0 +1,68 @@ +package sarama + +type ListGroupsResponse struct { + Err KError + Groups map[string]string +} + +func (r *ListGroupsResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + + if err := pe.putArrayLength(len(r.Groups)); err != nil { + return err + } + for groupId, protocolType := range r.Groups { + if err := pe.putString(groupId); err != nil { + return err + } + if err := pe.putString(protocolType); err != nil { + return err + } + } + + return nil +} + +func (r *ListGroupsResponse) decode(pd packetDecoder, version int16) error { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + if n == 0 { + return nil + } + + r.Groups = make(map[string]string) + for i := 0; i < n; i++ { + groupId, err := pd.getString() + if err != nil { + return err + } + protocolType, err := pd.getString() + if err != nil { + return err + } + + r.Groups[groupId] = protocolType + } + + return nil +} + +func (r *ListGroupsResponse) key() int16 { + return 16 +} + +func (r *ListGroupsResponse) version() int16 { + return 0 +} + +func (r *ListGroupsResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/list_groups_response_test.go b/vendor/src/github.com/Shopify/sarama/list_groups_response_test.go new file mode 100644 index 00000000..41ab822f --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/list_groups_response_test.go @@ -0,0 +1,58 @@ +package sarama + +import ( + "testing" +) + +var ( + listGroupsResponseEmpty = []byte{ + 0, 0, // no error + 0, 0, 0, 0, // no groups + } + + listGroupsResponseError = []byte{ + 0, 31, // no error + 0, 0, 0, 0, // ErrClusterAuthorizationFailed + } + + listGroupsResponseWithConsumer = []byte{ + 0, 0, // no error + 0, 0, 0, 1, // 1 group + 0, 3, 'f', 'o', 'o', // group name + 0, 8, 'c', 'o', 'n', 's', 'u', 'm', 'e', 'r', // protocol type + } +) + +func TestListGroupsResponse(t *testing.T) { + var response *ListGroupsResponse + + response = new(ListGroupsResponse) + testVersionDecodable(t, "no error", response, listGroupsResponseEmpty, 0) + if response.Err != ErrNoError { + t.Error("Expected no gerror, found:", response.Err) + } + if len(response.Groups) != 0 { + t.Error("Expected no groups") + } + + response = new(ListGroupsResponse) + testVersionDecodable(t, "no error", response, listGroupsResponseError, 0) + if response.Err != ErrClusterAuthorizationFailed { + t.Error("Expected no gerror, found:", response.Err) + } + if len(response.Groups) != 0 { + t.Error("Expected no groups") + } + + response = new(ListGroupsResponse) + testVersionDecodable(t, "no error", response, listGroupsResponseWithConsumer, 0) + if response.Err != ErrNoError { + t.Error("Expected no gerror, found:", response.Err) + } + if len(response.Groups) != 1 { + t.Error("Expected one group") + } + if response.Groups["foo"] != "consumer" { + t.Error("Expected foo group to use consumer protocol") + } +} diff --git a/vendor/src/github.com/Shopify/sarama/message.go b/vendor/src/github.com/Shopify/sarama/message.go new file mode 100644 index 00000000..327c5fa2 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/message.go @@ -0,0 +1,196 @@ +package sarama + +import ( + "bytes" + "compress/gzip" + "fmt" + "io/ioutil" + "time" + + "github.com/eapache/go-xerial-snappy" + "github.com/pierrec/lz4" +) + +// CompressionCodec represents the various compression codecs recognized by Kafka in messages. +type CompressionCodec int8 + +// only the last two bits are really used +const compressionCodecMask int8 = 0x03 + +const ( + CompressionNone CompressionCodec = 0 + CompressionGZIP CompressionCodec = 1 + CompressionSnappy CompressionCodec = 2 + CompressionLZ4 CompressionCodec = 3 +) + +type Message struct { + Codec CompressionCodec // codec used to compress the message contents + Key []byte // the message key, may be nil + Value []byte // the message contents + Set *MessageSet // the message set a message might wrap + Version int8 // v1 requires Kafka 0.10 + Timestamp time.Time // the timestamp of the message (version 1+ only) + + compressedCache []byte + compressedSize int // used for computing the compression ratio metrics +} + +func (m *Message) encode(pe packetEncoder) error { + pe.push(&crc32Field{}) + + pe.putInt8(m.Version) + + attributes := int8(m.Codec) & compressionCodecMask + pe.putInt8(attributes) + + if m.Version >= 1 { + pe.putInt64(m.Timestamp.UnixNano() / int64(time.Millisecond)) + } + + err := pe.putBytes(m.Key) + if err != nil { + return err + } + + var payload []byte + + if m.compressedCache != nil { + payload = m.compressedCache + m.compressedCache = nil + } else if m.Value != nil { + switch m.Codec { + case CompressionNone: + payload = m.Value + case CompressionGZIP: + var buf bytes.Buffer + writer := gzip.NewWriter(&buf) + if _, err = writer.Write(m.Value); err != nil { + return err + } + if err = writer.Close(); err != nil { + return err + } + m.compressedCache = buf.Bytes() + payload = m.compressedCache + case CompressionSnappy: + tmp := snappy.Encode(m.Value) + m.compressedCache = tmp + payload = m.compressedCache + case CompressionLZ4: + var buf bytes.Buffer + writer := lz4.NewWriter(&buf) + if _, err = writer.Write(m.Value); err != nil { + return err + } + if err = writer.Close(); err != nil { + return err + } + m.compressedCache = buf.Bytes() + payload = m.compressedCache + + default: + return PacketEncodingError{fmt.Sprintf("unsupported compression codec (%d)", m.Codec)} + } + // Keep in mind the compressed payload size for metric gathering + m.compressedSize = len(payload) + } + + if err = pe.putBytes(payload); err != nil { + return err + } + + return pe.pop() +} + +func (m *Message) decode(pd packetDecoder) (err error) { + err = pd.push(&crc32Field{}) + if err != nil { + return err + } + + m.Version, err = pd.getInt8() + if err != nil { + return err + } + + attribute, err := pd.getInt8() + if err != nil { + return err + } + m.Codec = CompressionCodec(attribute & compressionCodecMask) + + if m.Version >= 1 { + millis, err := pd.getInt64() + if err != nil { + return err + } + m.Timestamp = time.Unix(millis/1000, (millis%1000)*int64(time.Millisecond)) + } + + m.Key, err = pd.getBytes() + if err != nil { + return err + } + + m.Value, err = pd.getBytes() + if err != nil { + return err + } + + // Required for deep equal assertion during tests but might be useful + // for future metrics about the compression ratio in fetch requests + m.compressedSize = len(m.Value) + + switch m.Codec { + case CompressionNone: + // nothing to do + case CompressionGZIP: + if m.Value == nil { + break + } + reader, err := gzip.NewReader(bytes.NewReader(m.Value)) + if err != nil { + return err + } + if m.Value, err = ioutil.ReadAll(reader); err != nil { + return err + } + if err := m.decodeSet(); err != nil { + return err + } + case CompressionSnappy: + if m.Value == nil { + break + } + if m.Value, err = snappy.Decode(m.Value); err != nil { + return err + } + if err := m.decodeSet(); err != nil { + return err + } + case CompressionLZ4: + if m.Value == nil { + break + } + reader := lz4.NewReader(bytes.NewReader(m.Value)) + if m.Value, err = ioutil.ReadAll(reader); err != nil { + return err + } + if err := m.decodeSet(); err != nil { + return err + } + + default: + return PacketDecodingError{fmt.Sprintf("invalid compression specified (%d)", m.Codec)} + } + + return pd.pop() +} + +// decodes a message set from a previousy encoded bulk-message +func (m *Message) decodeSet() (err error) { + pd := realDecoder{raw: m.Value} + m.Set = &MessageSet{} + return m.Set.decode(&pd) +} diff --git a/vendor/src/github.com/Shopify/sarama/message_set.go b/vendor/src/github.com/Shopify/sarama/message_set.go new file mode 100644 index 00000000..f028784e --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/message_set.go @@ -0,0 +1,89 @@ +package sarama + +type MessageBlock struct { + Offset int64 + Msg *Message +} + +// Messages convenience helper which returns either all the +// messages that are wrapped in this block +func (msb *MessageBlock) Messages() []*MessageBlock { + if msb.Msg.Set != nil { + return msb.Msg.Set.Messages + } + return []*MessageBlock{msb} +} + +func (msb *MessageBlock) encode(pe packetEncoder) error { + pe.putInt64(msb.Offset) + pe.push(&lengthField{}) + err := msb.Msg.encode(pe) + if err != nil { + return err + } + return pe.pop() +} + +func (msb *MessageBlock) decode(pd packetDecoder) (err error) { + if msb.Offset, err = pd.getInt64(); err != nil { + return err + } + + if err = pd.push(&lengthField{}); err != nil { + return err + } + + msb.Msg = new(Message) + if err = msb.Msg.decode(pd); err != nil { + return err + } + + if err = pd.pop(); err != nil { + return err + } + + return nil +} + +type MessageSet struct { + PartialTrailingMessage bool // whether the set on the wire contained an incomplete trailing MessageBlock + Messages []*MessageBlock +} + +func (ms *MessageSet) encode(pe packetEncoder) error { + for i := range ms.Messages { + err := ms.Messages[i].encode(pe) + if err != nil { + return err + } + } + return nil +} + +func (ms *MessageSet) decode(pd packetDecoder) (err error) { + ms.Messages = nil + + for pd.remaining() > 0 { + msb := new(MessageBlock) + err = msb.decode(pd) + switch err { + case nil: + ms.Messages = append(ms.Messages, msb) + case ErrInsufficientData: + // As an optimization the server is allowed to return a partial message at the + // end of the message set. Clients should handle this case. So we just ignore such things. + ms.PartialTrailingMessage = true + return nil + default: + return err + } + } + + return nil +} + +func (ms *MessageSet) addMessage(msg *Message) { + block := new(MessageBlock) + block.Msg = msg + ms.Messages = append(ms.Messages, block) +} diff --git a/vendor/src/github.com/Shopify/sarama/message_test.go b/vendor/src/github.com/Shopify/sarama/message_test.go new file mode 100644 index 00000000..af70b7b1 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/message_test.go @@ -0,0 +1,165 @@ +package sarama + +import ( + "testing" + "time" +) + +var ( + emptyMessage = []byte{ + 167, 236, 104, 3, // CRC + 0x00, // magic version byte + 0x00, // attribute flags + 0xFF, 0xFF, 0xFF, 0xFF, // key + 0xFF, 0xFF, 0xFF, 0xFF} // value + + emptyGzipMessage = []byte{ + 97, 79, 149, 90, //CRC + 0x00, // magic version byte + 0x01, // attribute flags + 0xFF, 0xFF, 0xFF, 0xFF, // key + // value + 0x00, 0x00, 0x00, 0x17, + 0x1f, 0x8b, + 0x08, + 0, 0, 9, 110, 136, 0, 255, 1, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0} + + emptyLZ4Message = []byte{ + 132, 219, 238, 101, // CRC + 0x01, // version byte + 0x03, // attribute flags: lz4 + 0, 0, 1, 88, 141, 205, 89, 56, // timestamp + 0xFF, 0xFF, 0xFF, 0xFF, // key + 0x00, 0x00, 0x00, 0x0f, // len + 0x04, 0x22, 0x4D, 0x18, // LZ4 magic number + 100, // LZ4 flags: version 01, block indepedant, content checksum + 112, 185, 0, 0, 0, 0, // LZ4 data + 5, 93, 204, 2, // LZ4 checksum + } + + emptyBulkSnappyMessage = []byte{ + 180, 47, 53, 209, //CRC + 0x00, // magic version byte + 0x02, // attribute flags + 0xFF, 0xFF, 0xFF, 0xFF, // key + 0, 0, 0, 42, + 130, 83, 78, 65, 80, 80, 89, 0, // SNAPPY magic + 0, 0, 0, 1, // min version + 0, 0, 0, 1, // default version + 0, 0, 0, 22, 52, 0, 0, 25, 1, 16, 14, 227, 138, 104, 118, 25, 15, 13, 1, 8, 1, 0, 0, 62, 26, 0} + + emptyBulkGzipMessage = []byte{ + 139, 160, 63, 141, //CRC + 0x00, // magic version byte + 0x01, // attribute flags + 0xFF, 0xFF, 0xFF, 0xFF, // key + 0x00, 0x00, 0x00, 0x27, // len + 0x1f, 0x8b, // Gzip Magic + 0x08, // deflate compressed + 0, 0, 0, 0, 0, 0, 0, 99, 96, 128, 3, 190, 202, 112, 143, 7, 12, 12, 255, 129, 0, 33, 200, 192, 136, 41, 3, 0, 199, 226, 155, 70, 52, 0, 0, 0} + + emptyBulkLZ4Message = []byte{ + 246, 12, 188, 129, // CRC + 0x01, // Version + 0x03, // attribute flags (LZ4) + 255, 255, 249, 209, 212, 181, 73, 201, // timestamp + 0xFF, 0xFF, 0xFF, 0xFF, // key + 0x00, 0x00, 0x00, 0x47, // len + 0x04, 0x22, 0x4D, 0x18, // magic number lz4 + 100, // lz4 flags 01100100 + // version: 01, block indep: 1, block checksum: 0, content size: 0, content checksum: 1, reserved: 00 + 112, 185, 52, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 121, 87, 72, 224, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 14, 121, 87, 72, 224, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, + 71, 129, 23, 111, // LZ4 checksum + } +) + +func TestMessageEncoding(t *testing.T) { + message := Message{} + testEncodable(t, "empty", &message, emptyMessage) + + message.Value = []byte{} + message.Codec = CompressionGZIP + testEncodable(t, "empty gzip", &message, emptyGzipMessage) + + message.Value = []byte{} + message.Codec = CompressionLZ4 + message.Timestamp = time.Unix(1479847795, 0) + message.Version = 1 + testEncodable(t, "empty lz4", &message, emptyLZ4Message) +} + +func TestMessageDecoding(t *testing.T) { + message := Message{} + testDecodable(t, "empty", &message, emptyMessage) + if message.Codec != CompressionNone { + t.Error("Decoding produced compression codec where there was none.") + } + if message.Key != nil { + t.Error("Decoding produced key where there was none.") + } + if message.Value != nil { + t.Error("Decoding produced value where there was none.") + } + if message.Set != nil { + t.Error("Decoding produced set where there was none.") + } + + testDecodable(t, "empty gzip", &message, emptyGzipMessage) + if message.Codec != CompressionGZIP { + t.Error("Decoding produced incorrect compression codec (was gzip).") + } + if message.Key != nil { + t.Error("Decoding produced key where there was none.") + } + if message.Value == nil || len(message.Value) != 0 { + t.Error("Decoding produced nil or content-ful value where there was an empty array.") + } +} + +func TestMessageDecodingBulkSnappy(t *testing.T) { + message := Message{} + testDecodable(t, "bulk snappy", &message, emptyBulkSnappyMessage) + if message.Codec != CompressionSnappy { + t.Errorf("Decoding produced codec %d, but expected %d.", message.Codec, CompressionSnappy) + } + if message.Key != nil { + t.Errorf("Decoding produced key %+v, but none was expected.", message.Key) + } + if message.Set == nil { + t.Error("Decoding produced no set, but one was expected.") + } else if len(message.Set.Messages) != 2 { + t.Errorf("Decoding produced a set with %d messages, but 2 were expected.", len(message.Set.Messages)) + } +} + +func TestMessageDecodingBulkGzip(t *testing.T) { + message := Message{} + testDecodable(t, "bulk gzip", &message, emptyBulkGzipMessage) + if message.Codec != CompressionGZIP { + t.Errorf("Decoding produced codec %d, but expected %d.", message.Codec, CompressionGZIP) + } + if message.Key != nil { + t.Errorf("Decoding produced key %+v, but none was expected.", message.Key) + } + if message.Set == nil { + t.Error("Decoding produced no set, but one was expected.") + } else if len(message.Set.Messages) != 2 { + t.Errorf("Decoding produced a set with %d messages, but 2 were expected.", len(message.Set.Messages)) + } +} + +func TestMessageDecodingBulkLZ4(t *testing.T) { + message := Message{} + testDecodable(t, "bulk lz4", &message, emptyBulkLZ4Message) + if message.Codec != CompressionLZ4 { + t.Errorf("Decoding produced codec %d, but expected %d.", message.Codec, CompressionLZ4) + } + if message.Key != nil { + t.Errorf("Decoding produced key %+v, but none was expected.", message.Key) + } + if message.Set == nil { + t.Error("Decoding produced no set, but one was expected.") + } else if len(message.Set.Messages) != 2 { + t.Errorf("Decoding produced a set with %d messages, but 2 were expected.", len(message.Set.Messages)) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/metadata_request.go b/vendor/src/github.com/Shopify/sarama/metadata_request.go new file mode 100644 index 00000000..9a26b55f --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/metadata_request.go @@ -0,0 +1,52 @@ +package sarama + +type MetadataRequest struct { + Topics []string +} + +func (r *MetadataRequest) encode(pe packetEncoder) error { + err := pe.putArrayLength(len(r.Topics)) + if err != nil { + return err + } + + for i := range r.Topics { + err = pe.putString(r.Topics[i]) + if err != nil { + return err + } + } + return nil +} + +func (r *MetadataRequest) decode(pd packetDecoder, version int16) error { + topicCount, err := pd.getArrayLength() + if err != nil { + return err + } + if topicCount == 0 { + return nil + } + + r.Topics = make([]string, topicCount) + for i := range r.Topics { + topic, err := pd.getString() + if err != nil { + return err + } + r.Topics[i] = topic + } + return nil +} + +func (r *MetadataRequest) key() int16 { + return 3 +} + +func (r *MetadataRequest) version() int16 { + return 0 +} + +func (r *MetadataRequest) requiredVersion() KafkaVersion { + return minVersion +} diff --git a/vendor/src/github.com/Shopify/sarama/metadata_request_test.go b/vendor/src/github.com/Shopify/sarama/metadata_request_test.go new file mode 100644 index 00000000..44f3146e --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/metadata_request_test.go @@ -0,0 +1,29 @@ +package sarama + +import "testing" + +var ( + metadataRequestNoTopics = []byte{ + 0x00, 0x00, 0x00, 0x00} + + metadataRequestOneTopic = []byte{ + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x06, 't', 'o', 'p', 'i', 'c', '1'} + + metadataRequestThreeTopics = []byte{ + 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 'f', 'o', 'o', + 0x00, 0x03, 'b', 'a', 'r', + 0x00, 0x03, 'b', 'a', 'z'} +) + +func TestMetadataRequest(t *testing.T) { + request := new(MetadataRequest) + testRequest(t, "no topics", request, metadataRequestNoTopics) + + request.Topics = []string{"topic1"} + testRequest(t, "one topic", request, metadataRequestOneTopic) + + request.Topics = []string{"foo", "bar", "baz"} + testRequest(t, "three topics", request, metadataRequestThreeTopics) +} diff --git a/vendor/src/github.com/Shopify/sarama/metadata_response.go b/vendor/src/github.com/Shopify/sarama/metadata_response.go new file mode 100644 index 00000000..f9d6a427 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/metadata_response.go @@ -0,0 +1,239 @@ +package sarama + +type PartitionMetadata struct { + Err KError + ID int32 + Leader int32 + Replicas []int32 + Isr []int32 +} + +func (pm *PartitionMetadata) decode(pd packetDecoder) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + pm.Err = KError(tmp) + + pm.ID, err = pd.getInt32() + if err != nil { + return err + } + + pm.Leader, err = pd.getInt32() + if err != nil { + return err + } + + pm.Replicas, err = pd.getInt32Array() + if err != nil { + return err + } + + pm.Isr, err = pd.getInt32Array() + if err != nil { + return err + } + + return nil +} + +func (pm *PartitionMetadata) encode(pe packetEncoder) (err error) { + pe.putInt16(int16(pm.Err)) + pe.putInt32(pm.ID) + pe.putInt32(pm.Leader) + + err = pe.putInt32Array(pm.Replicas) + if err != nil { + return err + } + + err = pe.putInt32Array(pm.Isr) + if err != nil { + return err + } + + return nil +} + +type TopicMetadata struct { + Err KError + Name string + Partitions []*PartitionMetadata +} + +func (tm *TopicMetadata) decode(pd packetDecoder) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + tm.Err = KError(tmp) + + tm.Name, err = pd.getString() + if err != nil { + return err + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + tm.Partitions = make([]*PartitionMetadata, n) + for i := 0; i < n; i++ { + tm.Partitions[i] = new(PartitionMetadata) + err = tm.Partitions[i].decode(pd) + if err != nil { + return err + } + } + + return nil +} + +func (tm *TopicMetadata) encode(pe packetEncoder) (err error) { + pe.putInt16(int16(tm.Err)) + + err = pe.putString(tm.Name) + if err != nil { + return err + } + + err = pe.putArrayLength(len(tm.Partitions)) + if err != nil { + return err + } + + for _, pm := range tm.Partitions { + err = pm.encode(pe) + if err != nil { + return err + } + } + + return nil +} + +type MetadataResponse struct { + Brokers []*Broker + Topics []*TopicMetadata +} + +func (r *MetadataResponse) decode(pd packetDecoder, version int16) (err error) { + n, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Brokers = make([]*Broker, n) + for i := 0; i < n; i++ { + r.Brokers[i] = new(Broker) + err = r.Brokers[i].decode(pd) + if err != nil { + return err + } + } + + n, err = pd.getArrayLength() + if err != nil { + return err + } + + r.Topics = make([]*TopicMetadata, n) + for i := 0; i < n; i++ { + r.Topics[i] = new(TopicMetadata) + err = r.Topics[i].decode(pd) + if err != nil { + return err + } + } + + return nil +} + +func (r *MetadataResponse) encode(pe packetEncoder) error { + err := pe.putArrayLength(len(r.Brokers)) + if err != nil { + return err + } + for _, broker := range r.Brokers { + err = broker.encode(pe) + if err != nil { + return err + } + } + + err = pe.putArrayLength(len(r.Topics)) + if err != nil { + return err + } + for _, tm := range r.Topics { + err = tm.encode(pe) + if err != nil { + return err + } + } + + return nil +} + +func (r *MetadataResponse) key() int16 { + return 3 +} + +func (r *MetadataResponse) version() int16 { + return 0 +} + +func (r *MetadataResponse) requiredVersion() KafkaVersion { + return minVersion +} + +// testing API + +func (r *MetadataResponse) AddBroker(addr string, id int32) { + r.Brokers = append(r.Brokers, &Broker{id: id, addr: addr}) +} + +func (r *MetadataResponse) AddTopic(topic string, err KError) *TopicMetadata { + var tmatch *TopicMetadata + + for _, tm := range r.Topics { + if tm.Name == topic { + tmatch = tm + goto foundTopic + } + } + + tmatch = new(TopicMetadata) + tmatch.Name = topic + r.Topics = append(r.Topics, tmatch) + +foundTopic: + + tmatch.Err = err + return tmatch +} + +func (r *MetadataResponse) AddTopicPartition(topic string, partition, brokerID int32, replicas, isr []int32, err KError) { + tmatch := r.AddTopic(topic, ErrNoError) + var pmatch *PartitionMetadata + + for _, pm := range tmatch.Partitions { + if pm.ID == partition { + pmatch = pm + goto foundPartition + } + } + + pmatch = new(PartitionMetadata) + pmatch.ID = partition + tmatch.Partitions = append(tmatch.Partitions, pmatch) + +foundPartition: + + pmatch.Leader = brokerID + pmatch.Replicas = replicas + pmatch.Isr = isr + pmatch.Err = err + +} diff --git a/vendor/src/github.com/Shopify/sarama/metadata_response_test.go b/vendor/src/github.com/Shopify/sarama/metadata_response_test.go new file mode 100644 index 00000000..ea62a4f1 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/metadata_response_test.go @@ -0,0 +1,139 @@ +package sarama + +import "testing" + +var ( + emptyMetadataResponse = []byte{ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} + + brokersNoTopicsMetadataResponse = []byte{ + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x00, 0xab, 0xff, + 0x00, 0x09, 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', + 0x00, 0x00, 0x00, 0x33, + + 0x00, 0x01, 0x02, 0x03, + 0x00, 0x0a, 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', + 0x00, 0x00, 0x01, 0x11, + + 0x00, 0x00, 0x00, 0x00} + + topicsNoBrokersMetadataResponse = []byte{ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x00, + 0x00, 0x03, 'f', 'o', 'o', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, + 0x00, 0x03, 'b', 'a', 'r', + 0x00, 0x00, 0x00, 0x00} +) + +func TestEmptyMetadataResponse(t *testing.T) { + response := MetadataResponse{} + + testVersionDecodable(t, "empty", &response, emptyMetadataResponse, 0) + if len(response.Brokers) != 0 { + t.Error("Decoding produced", len(response.Brokers), "brokers where there were none!") + } + if len(response.Topics) != 0 { + t.Error("Decoding produced", len(response.Topics), "topics where there were none!") + } +} + +func TestMetadataResponseWithBrokers(t *testing.T) { + response := MetadataResponse{} + + testVersionDecodable(t, "brokers, no topics", &response, brokersNoTopicsMetadataResponse, 0) + if len(response.Brokers) != 2 { + t.Fatal("Decoding produced", len(response.Brokers), "brokers where there were two!") + } + + if response.Brokers[0].id != 0xabff { + t.Error("Decoding produced invalid broker 0 id.") + } + if response.Brokers[0].addr != "localhost:51" { + t.Error("Decoding produced invalid broker 0 address.") + } + if response.Brokers[1].id != 0x010203 { + t.Error("Decoding produced invalid broker 1 id.") + } + if response.Brokers[1].addr != "google.com:273" { + t.Error("Decoding produced invalid broker 1 address.") + } + + if len(response.Topics) != 0 { + t.Error("Decoding produced", len(response.Topics), "topics where there were none!") + } +} + +func TestMetadataResponseWithTopics(t *testing.T) { + response := MetadataResponse{} + + testVersionDecodable(t, "topics, no brokers", &response, topicsNoBrokersMetadataResponse, 0) + if len(response.Brokers) != 0 { + t.Error("Decoding produced", len(response.Brokers), "brokers where there were none!") + } + + if len(response.Topics) != 2 { + t.Fatal("Decoding produced", len(response.Topics), "topics where there were two!") + } + + if response.Topics[0].Err != ErrNoError { + t.Error("Decoding produced invalid topic 0 error.") + } + + if response.Topics[0].Name != "foo" { + t.Error("Decoding produced invalid topic 0 name.") + } + + if len(response.Topics[0].Partitions) != 1 { + t.Fatal("Decoding produced invalid partition count for topic 0.") + } + + if response.Topics[0].Partitions[0].Err != ErrInvalidMessageSize { + t.Error("Decoding produced invalid topic 0 partition 0 error.") + } + + if response.Topics[0].Partitions[0].ID != 0x01 { + t.Error("Decoding produced invalid topic 0 partition 0 id.") + } + + if response.Topics[0].Partitions[0].Leader != 0x07 { + t.Error("Decoding produced invalid topic 0 partition 0 leader.") + } + + if len(response.Topics[0].Partitions[0].Replicas) != 3 { + t.Fatal("Decoding produced invalid topic 0 partition 0 replicas.") + } + for i := 0; i < 3; i++ { + if response.Topics[0].Partitions[0].Replicas[i] != int32(i+1) { + t.Error("Decoding produced invalid topic 0 partition 0 replica", i) + } + } + + if len(response.Topics[0].Partitions[0].Isr) != 0 { + t.Error("Decoding produced invalid topic 0 partition 0 isr length.") + } + + if response.Topics[1].Err != ErrNoError { + t.Error("Decoding produced invalid topic 1 error.") + } + + if response.Topics[1].Name != "bar" { + t.Error("Decoding produced invalid topic 0 name.") + } + + if len(response.Topics[1].Partitions) != 0 { + t.Error("Decoding produced invalid partition count for topic 1.") + } +} diff --git a/vendor/src/github.com/Shopify/sarama/metrics.go b/vendor/src/github.com/Shopify/sarama/metrics.go new file mode 100644 index 00000000..4869708e --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/metrics.go @@ -0,0 +1,51 @@ +package sarama + +import ( + "fmt" + "strings" + + "github.com/rcrowley/go-metrics" +) + +// Use exponentially decaying reservoir for sampling histograms with the same defaults as the Java library: +// 1028 elements, which offers a 99.9% confidence level with a 5% margin of error assuming a normal distribution, +// and an alpha factor of 0.015, which heavily biases the reservoir to the past 5 minutes of measurements. +// See https://github.com/dropwizard/metrics/blob/v3.1.0/metrics-core/src/main/java/com/codahale/metrics/ExponentiallyDecayingReservoir.java#L38 +const ( + metricsReservoirSize = 1028 + metricsAlphaFactor = 0.015 +) + +func getOrRegisterHistogram(name string, r metrics.Registry) metrics.Histogram { + return r.GetOrRegister(name, func() metrics.Histogram { + return metrics.NewHistogram(metrics.NewExpDecaySample(metricsReservoirSize, metricsAlphaFactor)) + }).(metrics.Histogram) +} + +func getMetricNameForBroker(name string, broker *Broker) string { + // Use broker id like the Java client as it does not contain '.' or ':' characters that + // can be interpreted as special character by monitoring tool (e.g. Graphite) + return fmt.Sprintf(name+"-for-broker-%d", broker.ID()) +} + +func getOrRegisterBrokerMeter(name string, broker *Broker, r metrics.Registry) metrics.Meter { + return metrics.GetOrRegisterMeter(getMetricNameForBroker(name, broker), r) +} + +func getOrRegisterBrokerHistogram(name string, broker *Broker, r metrics.Registry) metrics.Histogram { + return getOrRegisterHistogram(getMetricNameForBroker(name, broker), r) +} + +func getMetricNameForTopic(name string, topic string) string { + // Convert dot to _ since reporters like Graphite typically use dot to represent hierarchy + // cf. KAFKA-1902 and KAFKA-2337 + return fmt.Sprintf(name+"-for-topic-%s", strings.Replace(topic, ".", "_", -1)) +} + +func getOrRegisterTopicMeter(name string, topic string, r metrics.Registry) metrics.Meter { + return metrics.GetOrRegisterMeter(getMetricNameForTopic(name, topic), r) +} + +func getOrRegisterTopicHistogram(name string, topic string, r metrics.Registry) metrics.Histogram { + return getOrRegisterHistogram(getMetricNameForTopic(name, topic), r) +} diff --git a/vendor/src/github.com/Shopify/sarama/metrics_test.go b/vendor/src/github.com/Shopify/sarama/metrics_test.go new file mode 100644 index 00000000..789c0ff3 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/metrics_test.go @@ -0,0 +1,172 @@ +package sarama + +import ( + "testing" + + "github.com/rcrowley/go-metrics" +) + +func TestGetOrRegisterHistogram(t *testing.T) { + metricRegistry := metrics.NewRegistry() + histogram := getOrRegisterHistogram("name", metricRegistry) + + if histogram == nil { + t.Error("Unexpected nil histogram") + } + + // Fetch the metric + foundHistogram := metricRegistry.Get("name") + + if foundHistogram != histogram { + t.Error("Unexpected different histogram", foundHistogram, histogram) + } + + // Try to register the metric again + sameHistogram := getOrRegisterHistogram("name", metricRegistry) + + if sameHistogram != histogram { + t.Error("Unexpected different histogram", sameHistogram, histogram) + } +} + +func TestGetMetricNameForBroker(t *testing.T) { + metricName := getMetricNameForBroker("name", &Broker{id: 1}) + + if metricName != "name-for-broker-1" { + t.Error("Unexpected metric name", metricName) + } +} + +// Common type and functions for metric validation +type metricValidator struct { + name string + validator func(*testing.T, interface{}) +} + +type metricValidators []*metricValidator + +func newMetricValidators() metricValidators { + return make([]*metricValidator, 0, 32) +} + +func (m *metricValidators) register(validator *metricValidator) { + *m = append(*m, validator) +} + +func (m *metricValidators) registerForBroker(broker *Broker, validator *metricValidator) { + m.register(&metricValidator{getMetricNameForBroker(validator.name, broker), validator.validator}) +} + +func (m *metricValidators) registerForGlobalAndTopic(topic string, validator *metricValidator) { + m.register(&metricValidator{validator.name, validator.validator}) + m.register(&metricValidator{getMetricNameForTopic(validator.name, topic), validator.validator}) +} + +func (m *metricValidators) registerForAllBrokers(broker *Broker, validator *metricValidator) { + m.register(validator) + m.registerForBroker(broker, validator) +} + +func (m metricValidators) run(t *testing.T, r metrics.Registry) { + for _, metricValidator := range m { + metric := r.Get(metricValidator.name) + if metric == nil { + t.Error("No metric named", metricValidator.name) + } else { + metricValidator.validator(t, metric) + } + } +} + +func meterValidator(name string, extraValidator func(*testing.T, metrics.Meter)) *metricValidator { + return &metricValidator{ + name: name, + validator: func(t *testing.T, metric interface{}) { + if meter, ok := metric.(metrics.Meter); !ok { + t.Errorf("Expected meter metric for '%s', got %T", name, metric) + } else { + extraValidator(t, meter) + } + }, + } +} + +func countMeterValidator(name string, expectedCount int) *metricValidator { + return meterValidator(name, func(t *testing.T, meter metrics.Meter) { + count := meter.Count() + if count != int64(expectedCount) { + t.Errorf("Expected meter metric '%s' count = %d, got %d", name, expectedCount, count) + } + }) +} + +func minCountMeterValidator(name string, minCount int) *metricValidator { + return meterValidator(name, func(t *testing.T, meter metrics.Meter) { + count := meter.Count() + if count < int64(minCount) { + t.Errorf("Expected meter metric '%s' count >= %d, got %d", name, minCount, count) + } + }) +} + +func histogramValidator(name string, extraValidator func(*testing.T, metrics.Histogram)) *metricValidator { + return &metricValidator{ + name: name, + validator: func(t *testing.T, metric interface{}) { + if histogram, ok := metric.(metrics.Histogram); !ok { + t.Errorf("Expected histogram metric for '%s', got %T", name, metric) + } else { + extraValidator(t, histogram) + } + }, + } +} + +func countHistogramValidator(name string, expectedCount int) *metricValidator { + return histogramValidator(name, func(t *testing.T, histogram metrics.Histogram) { + count := histogram.Count() + if count != int64(expectedCount) { + t.Errorf("Expected histogram metric '%s' count = %d, got %d", name, expectedCount, count) + } + }) +} + +func minCountHistogramValidator(name string, minCount int) *metricValidator { + return histogramValidator(name, func(t *testing.T, histogram metrics.Histogram) { + count := histogram.Count() + if count < int64(minCount) { + t.Errorf("Expected histogram metric '%s' count >= %d, got %d", name, minCount, count) + } + }) +} + +func minMaxHistogramValidator(name string, expectedMin int, expectedMax int) *metricValidator { + return histogramValidator(name, func(t *testing.T, histogram metrics.Histogram) { + min := int(histogram.Min()) + if min != expectedMin { + t.Errorf("Expected histogram metric '%s' min = %d, got %d", name, expectedMin, min) + } + max := int(histogram.Max()) + if max != expectedMax { + t.Errorf("Expected histogram metric '%s' max = %d, got %d", name, expectedMax, max) + } + }) +} + +func minValHistogramValidator(name string, minMin int) *metricValidator { + return histogramValidator(name, func(t *testing.T, histogram metrics.Histogram) { + min := int(histogram.Min()) + if min < minMin { + t.Errorf("Expected histogram metric '%s' min >= %d, got %d", name, minMin, min) + } + }) +} + +func maxValHistogramValidator(name string, maxMax int) *metricValidator { + return histogramValidator(name, func(t *testing.T, histogram metrics.Histogram) { + max := int(histogram.Max()) + if max > maxMax { + t.Errorf("Expected histogram metric '%s' max <= %d, got %d", name, maxMax, max) + } + }) +} diff --git a/vendor/src/github.com/Shopify/sarama/mockbroker.go b/vendor/src/github.com/Shopify/sarama/mockbroker.go new file mode 100644 index 00000000..0734d34f --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/mockbroker.go @@ -0,0 +1,324 @@ +package sarama + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "net" + "reflect" + "strconv" + "sync" + "time" + + "github.com/davecgh/go-spew/spew" +) + +const ( + expectationTimeout = 500 * time.Millisecond +) + +type requestHandlerFunc func(req *request) (res encoder) + +// RequestNotifierFunc is invoked when a mock broker processes a request successfully +// and will provides the number of bytes read and written. +type RequestNotifierFunc func(bytesRead, bytesWritten int) + +// MockBroker is a mock Kafka broker that is used in unit tests. It is exposed +// to facilitate testing of higher level or specialized consumers and producers +// built on top of Sarama. Note that it does not 'mimic' the Kafka API protocol, +// but rather provides a facility to do that. It takes care of the TCP +// transport, request unmarshaling, response marshaling, and makes it the test +// writer responsibility to program correct according to the Kafka API protocol +// MockBroker behaviour. +// +// MockBroker is implemented as a TCP server listening on a kernel-selected +// localhost port that can accept many connections. It reads Kafka requests +// from that connection and returns responses programmed by the SetHandlerByMap +// function. If a MockBroker receives a request that it has no programmed +// response for, then it returns nothing and the request times out. +// +// A set of MockRequest builders to define mappings used by MockBroker is +// provided by Sarama. But users can develop MockRequests of their own and use +// them along with or instead of the standard ones. +// +// When running tests with MockBroker it is strongly recommended to specify +// a timeout to `go test` so that if the broker hangs waiting for a response, +// the test panics. +// +// It is not necessary to prefix message length or correlation ID to your +// response bytes, the server does that automatically as a convenience. +type MockBroker struct { + brokerID int32 + port int32 + closing chan none + stopper chan none + expectations chan encoder + listener net.Listener + t TestReporter + latency time.Duration + handler requestHandlerFunc + notifier RequestNotifierFunc + history []RequestResponse + lock sync.Mutex +} + +// RequestResponse represents a Request/Response pair processed by MockBroker. +type RequestResponse struct { + Request protocolBody + Response encoder +} + +// SetLatency makes broker pause for the specified period every time before +// replying. +func (b *MockBroker) SetLatency(latency time.Duration) { + b.latency = latency +} + +// SetHandlerByMap defines mapping of Request types to MockResponses. When a +// request is received by the broker, it looks up the request type in the map +// and uses the found MockResponse instance to generate an appropriate reply. +// If the request type is not found in the map then nothing is sent. +func (b *MockBroker) SetHandlerByMap(handlerMap map[string]MockResponse) { + b.setHandler(func(req *request) (res encoder) { + reqTypeName := reflect.TypeOf(req.body).Elem().Name() + mockResponse := handlerMap[reqTypeName] + if mockResponse == nil { + return nil + } + return mockResponse.For(req.body) + }) +} + +// SetNotifier set a function that will get invoked whenever a request has been +// processed successfully and will provide the number of bytes read and written +func (b *MockBroker) SetNotifier(notifier RequestNotifierFunc) { + b.lock.Lock() + b.notifier = notifier + b.lock.Unlock() +} + +// BrokerID returns broker ID assigned to the broker. +func (b *MockBroker) BrokerID() int32 { + return b.brokerID +} + +// History returns a slice of RequestResponse pairs in the order they were +// processed by the broker. Note that in case of multiple connections to the +// broker the order expected by a test can be different from the order recorded +// in the history, unless some synchronization is implemented in the test. +func (b *MockBroker) History() []RequestResponse { + b.lock.Lock() + history := make([]RequestResponse, len(b.history)) + copy(history, b.history) + b.lock.Unlock() + return history +} + +// Port returns the TCP port number the broker is listening for requests on. +func (b *MockBroker) Port() int32 { + return b.port +} + +// Addr returns the broker connection string in the form "
:". +func (b *MockBroker) Addr() string { + return b.listener.Addr().String() +} + +// Close terminates the broker blocking until it stops internal goroutines and +// releases all resources. +func (b *MockBroker) Close() { + close(b.expectations) + if len(b.expectations) > 0 { + buf := bytes.NewBufferString(fmt.Sprintf("mockbroker/%d: not all expectations were satisfied! Still waiting on:\n", b.BrokerID())) + for e := range b.expectations { + _, _ = buf.WriteString(spew.Sdump(e)) + } + b.t.Error(buf.String()) + } + close(b.closing) + <-b.stopper +} + +// setHandler sets the specified function as the request handler. Whenever +// a mock broker reads a request from the wire it passes the request to the +// function and sends back whatever the handler function returns. +func (b *MockBroker) setHandler(handler requestHandlerFunc) { + b.lock.Lock() + b.handler = handler + b.lock.Unlock() +} + +func (b *MockBroker) serverLoop() { + defer close(b.stopper) + var err error + var conn net.Conn + + go func() { + <-b.closing + err := b.listener.Close() + if err != nil { + b.t.Error(err) + } + }() + + wg := &sync.WaitGroup{} + i := 0 + for conn, err = b.listener.Accept(); err == nil; conn, err = b.listener.Accept() { + wg.Add(1) + go b.handleRequests(conn, i, wg) + i++ + } + wg.Wait() + Logger.Printf("*** mockbroker/%d: listener closed, err=%v", b.BrokerID(), err) +} + +func (b *MockBroker) handleRequests(conn net.Conn, idx int, wg *sync.WaitGroup) { + defer wg.Done() + defer func() { + _ = conn.Close() + }() + Logger.Printf("*** mockbroker/%d/%d: connection opened", b.BrokerID(), idx) + var err error + + abort := make(chan none) + defer close(abort) + go func() { + select { + case <-b.closing: + _ = conn.Close() + case <-abort: + } + }() + + resHeader := make([]byte, 8) + for { + req, bytesRead, err := decodeRequest(conn) + if err != nil { + Logger.Printf("*** mockbroker/%d/%d: invalid request: err=%+v, %+v", b.brokerID, idx, err, spew.Sdump(req)) + b.serverError(err) + break + } + + if b.latency > 0 { + time.Sleep(b.latency) + } + + b.lock.Lock() + res := b.handler(req) + b.history = append(b.history, RequestResponse{req.body, res}) + b.lock.Unlock() + + if res == nil { + Logger.Printf("*** mockbroker/%d/%d: ignored %v", b.brokerID, idx, spew.Sdump(req)) + continue + } + Logger.Printf("*** mockbroker/%d/%d: served %v -> %v", b.brokerID, idx, req, res) + + encodedRes, err := encode(res, nil) + if err != nil { + b.serverError(err) + break + } + if len(encodedRes) == 0 { + b.lock.Lock() + if b.notifier != nil { + b.notifier(bytesRead, 0) + } + b.lock.Unlock() + continue + } + + binary.BigEndian.PutUint32(resHeader, uint32(len(encodedRes)+4)) + binary.BigEndian.PutUint32(resHeader[4:], uint32(req.correlationID)) + if _, err = conn.Write(resHeader); err != nil { + b.serverError(err) + break + } + if _, err = conn.Write(encodedRes); err != nil { + b.serverError(err) + break + } + + b.lock.Lock() + if b.notifier != nil { + b.notifier(bytesRead, len(resHeader)+len(encodedRes)) + } + b.lock.Unlock() + } + Logger.Printf("*** mockbroker/%d/%d: connection closed, err=%v", b.BrokerID(), idx, err) +} + +func (b *MockBroker) defaultRequestHandler(req *request) (res encoder) { + select { + case res, ok := <-b.expectations: + if !ok { + return nil + } + return res + case <-time.After(expectationTimeout): + return nil + } +} + +func (b *MockBroker) serverError(err error) { + isConnectionClosedError := false + if _, ok := err.(*net.OpError); ok { + isConnectionClosedError = true + } else if err == io.EOF { + isConnectionClosedError = true + } else if err.Error() == "use of closed network connection" { + isConnectionClosedError = true + } + + if isConnectionClosedError { + return + } + + b.t.Errorf(err.Error()) +} + +// NewMockBroker launches a fake Kafka broker. It takes a TestReporter as provided by the +// test framework and a channel of responses to use. If an error occurs it is +// simply logged to the TestReporter and the broker exits. +func NewMockBroker(t TestReporter, brokerID int32) *MockBroker { + return NewMockBrokerAddr(t, brokerID, "localhost:0") +} + +// NewMockBrokerAddr behaves like newMockBroker but listens on the address you give +// it rather than just some ephemeral port. +func NewMockBrokerAddr(t TestReporter, brokerID int32, addr string) *MockBroker { + var err error + + broker := &MockBroker{ + closing: make(chan none), + stopper: make(chan none), + t: t, + brokerID: brokerID, + expectations: make(chan encoder, 512), + } + broker.handler = broker.defaultRequestHandler + + broker.listener, err = net.Listen("tcp", addr) + if err != nil { + t.Fatal(err) + } + Logger.Printf("*** mockbroker/%d listening on %s\n", brokerID, broker.listener.Addr().String()) + _, portStr, err := net.SplitHostPort(broker.listener.Addr().String()) + if err != nil { + t.Fatal(err) + } + tmp, err := strconv.ParseInt(portStr, 10, 32) + if err != nil { + t.Fatal(err) + } + broker.port = int32(tmp) + + go broker.serverLoop() + + return broker +} + +func (b *MockBroker) Returns(e encoder) { + b.expectations <- e +} diff --git a/vendor/src/github.com/Shopify/sarama/mockresponses.go b/vendor/src/github.com/Shopify/sarama/mockresponses.go new file mode 100644 index 00000000..a2031420 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/mockresponses.go @@ -0,0 +1,455 @@ +package sarama + +import ( + "fmt" +) + +// TestReporter has methods matching go's testing.T to avoid importing +// `testing` in the main part of the library. +type TestReporter interface { + Error(...interface{}) + Errorf(string, ...interface{}) + Fatal(...interface{}) + Fatalf(string, ...interface{}) +} + +// MockResponse is a response builder interface it defines one method that +// allows generating a response based on a request body. MockResponses are used +// to program behavior of MockBroker in tests. +type MockResponse interface { + For(reqBody versionedDecoder) (res encoder) +} + +// MockWrapper is a mock response builder that returns a particular concrete +// response regardless of the actual request passed to the `For` method. +type MockWrapper struct { + res encoder +} + +func (mw *MockWrapper) For(reqBody versionedDecoder) (res encoder) { + return mw.res +} + +func NewMockWrapper(res encoder) *MockWrapper { + return &MockWrapper{res: res} +} + +// MockSequence is a mock response builder that is created from a sequence of +// concrete responses. Every time when a `MockBroker` calls its `For` method +// the next response from the sequence is returned. When the end of the +// sequence is reached the last element from the sequence is returned. +type MockSequence struct { + responses []MockResponse +} + +func NewMockSequence(responses ...interface{}) *MockSequence { + ms := &MockSequence{} + ms.responses = make([]MockResponse, len(responses)) + for i, res := range responses { + switch res := res.(type) { + case MockResponse: + ms.responses[i] = res + case encoder: + ms.responses[i] = NewMockWrapper(res) + default: + panic(fmt.Sprintf("Unexpected response type: %T", res)) + } + } + return ms +} + +func (mc *MockSequence) For(reqBody versionedDecoder) (res encoder) { + res = mc.responses[0].For(reqBody) + if len(mc.responses) > 1 { + mc.responses = mc.responses[1:] + } + return res +} + +// MockMetadataResponse is a `MetadataResponse` builder. +type MockMetadataResponse struct { + leaders map[string]map[int32]int32 + brokers map[string]int32 + t TestReporter +} + +func NewMockMetadataResponse(t TestReporter) *MockMetadataResponse { + return &MockMetadataResponse{ + leaders: make(map[string]map[int32]int32), + brokers: make(map[string]int32), + t: t, + } +} + +func (mmr *MockMetadataResponse) SetLeader(topic string, partition, brokerID int32) *MockMetadataResponse { + partitions := mmr.leaders[topic] + if partitions == nil { + partitions = make(map[int32]int32) + mmr.leaders[topic] = partitions + } + partitions[partition] = brokerID + return mmr +} + +func (mmr *MockMetadataResponse) SetBroker(addr string, brokerID int32) *MockMetadataResponse { + mmr.brokers[addr] = brokerID + return mmr +} + +func (mmr *MockMetadataResponse) For(reqBody versionedDecoder) encoder { + metadataRequest := reqBody.(*MetadataRequest) + metadataResponse := &MetadataResponse{} + for addr, brokerID := range mmr.brokers { + metadataResponse.AddBroker(addr, brokerID) + } + if len(metadataRequest.Topics) == 0 { + for topic, partitions := range mmr.leaders { + for partition, brokerID := range partitions { + metadataResponse.AddTopicPartition(topic, partition, brokerID, nil, nil, ErrNoError) + } + } + return metadataResponse + } + for _, topic := range metadataRequest.Topics { + for partition, brokerID := range mmr.leaders[topic] { + metadataResponse.AddTopicPartition(topic, partition, brokerID, nil, nil, ErrNoError) + } + } + return metadataResponse +} + +// MockOffsetResponse is an `OffsetResponse` builder. +type MockOffsetResponse struct { + offsets map[string]map[int32]map[int64]int64 + t TestReporter +} + +func NewMockOffsetResponse(t TestReporter) *MockOffsetResponse { + return &MockOffsetResponse{ + offsets: make(map[string]map[int32]map[int64]int64), + t: t, + } +} + +func (mor *MockOffsetResponse) SetOffset(topic string, partition int32, time, offset int64) *MockOffsetResponse { + partitions := mor.offsets[topic] + if partitions == nil { + partitions = make(map[int32]map[int64]int64) + mor.offsets[topic] = partitions + } + times := partitions[partition] + if times == nil { + times = make(map[int64]int64) + partitions[partition] = times + } + times[time] = offset + return mor +} + +func (mor *MockOffsetResponse) For(reqBody versionedDecoder) encoder { + offsetRequest := reqBody.(*OffsetRequest) + offsetResponse := &OffsetResponse{} + for topic, partitions := range offsetRequest.blocks { + for partition, block := range partitions { + offset := mor.getOffset(topic, partition, block.time) + offsetResponse.AddTopicPartition(topic, partition, offset) + } + } + return offsetResponse +} + +func (mor *MockOffsetResponse) getOffset(topic string, partition int32, time int64) int64 { + partitions := mor.offsets[topic] + if partitions == nil { + mor.t.Errorf("missing topic: %s", topic) + } + times := partitions[partition] + if times == nil { + mor.t.Errorf("missing partition: %d", partition) + } + offset, ok := times[time] + if !ok { + mor.t.Errorf("missing time: %d", time) + } + return offset +} + +// MockFetchResponse is a `FetchResponse` builder. +type MockFetchResponse struct { + messages map[string]map[int32]map[int64]Encoder + highWaterMarks map[string]map[int32]int64 + t TestReporter + batchSize int +} + +func NewMockFetchResponse(t TestReporter, batchSize int) *MockFetchResponse { + return &MockFetchResponse{ + messages: make(map[string]map[int32]map[int64]Encoder), + highWaterMarks: make(map[string]map[int32]int64), + t: t, + batchSize: batchSize, + } +} + +func (mfr *MockFetchResponse) SetMessage(topic string, partition int32, offset int64, msg Encoder) *MockFetchResponse { + partitions := mfr.messages[topic] + if partitions == nil { + partitions = make(map[int32]map[int64]Encoder) + mfr.messages[topic] = partitions + } + messages := partitions[partition] + if messages == nil { + messages = make(map[int64]Encoder) + partitions[partition] = messages + } + messages[offset] = msg + return mfr +} + +func (mfr *MockFetchResponse) SetHighWaterMark(topic string, partition int32, offset int64) *MockFetchResponse { + partitions := mfr.highWaterMarks[topic] + if partitions == nil { + partitions = make(map[int32]int64) + mfr.highWaterMarks[topic] = partitions + } + partitions[partition] = offset + return mfr +} + +func (mfr *MockFetchResponse) For(reqBody versionedDecoder) encoder { + fetchRequest := reqBody.(*FetchRequest) + res := &FetchResponse{} + for topic, partitions := range fetchRequest.blocks { + for partition, block := range partitions { + initialOffset := block.fetchOffset + offset := initialOffset + maxOffset := initialOffset + int64(mfr.getMessageCount(topic, partition)) + for i := 0; i < mfr.batchSize && offset < maxOffset; { + msg := mfr.getMessage(topic, partition, offset) + if msg != nil { + res.AddMessage(topic, partition, nil, msg, offset) + i++ + } + offset++ + } + fb := res.GetBlock(topic, partition) + if fb == nil { + res.AddError(topic, partition, ErrNoError) + fb = res.GetBlock(topic, partition) + } + fb.HighWaterMarkOffset = mfr.getHighWaterMark(topic, partition) + } + } + return res +} + +func (mfr *MockFetchResponse) getMessage(topic string, partition int32, offset int64) Encoder { + partitions := mfr.messages[topic] + if partitions == nil { + return nil + } + messages := partitions[partition] + if messages == nil { + return nil + } + return messages[offset] +} + +func (mfr *MockFetchResponse) getMessageCount(topic string, partition int32) int { + partitions := mfr.messages[topic] + if partitions == nil { + return 0 + } + messages := partitions[partition] + if messages == nil { + return 0 + } + return len(messages) +} + +func (mfr *MockFetchResponse) getHighWaterMark(topic string, partition int32) int64 { + partitions := mfr.highWaterMarks[topic] + if partitions == nil { + return 0 + } + return partitions[partition] +} + +// MockConsumerMetadataResponse is a `ConsumerMetadataResponse` builder. +type MockConsumerMetadataResponse struct { + coordinators map[string]interface{} + t TestReporter +} + +func NewMockConsumerMetadataResponse(t TestReporter) *MockConsumerMetadataResponse { + return &MockConsumerMetadataResponse{ + coordinators: make(map[string]interface{}), + t: t, + } +} + +func (mr *MockConsumerMetadataResponse) SetCoordinator(group string, broker *MockBroker) *MockConsumerMetadataResponse { + mr.coordinators[group] = broker + return mr +} + +func (mr *MockConsumerMetadataResponse) SetError(group string, kerror KError) *MockConsumerMetadataResponse { + mr.coordinators[group] = kerror + return mr +} + +func (mr *MockConsumerMetadataResponse) For(reqBody versionedDecoder) encoder { + req := reqBody.(*ConsumerMetadataRequest) + group := req.ConsumerGroup + res := &ConsumerMetadataResponse{} + v := mr.coordinators[group] + switch v := v.(type) { + case *MockBroker: + res.Coordinator = &Broker{id: v.BrokerID(), addr: v.Addr()} + case KError: + res.Err = v + } + return res +} + +// MockOffsetCommitResponse is a `OffsetCommitResponse` builder. +type MockOffsetCommitResponse struct { + errors map[string]map[string]map[int32]KError + t TestReporter +} + +func NewMockOffsetCommitResponse(t TestReporter) *MockOffsetCommitResponse { + return &MockOffsetCommitResponse{t: t} +} + +func (mr *MockOffsetCommitResponse) SetError(group, topic string, partition int32, kerror KError) *MockOffsetCommitResponse { + if mr.errors == nil { + mr.errors = make(map[string]map[string]map[int32]KError) + } + topics := mr.errors[group] + if topics == nil { + topics = make(map[string]map[int32]KError) + mr.errors[group] = topics + } + partitions := topics[topic] + if partitions == nil { + partitions = make(map[int32]KError) + topics[topic] = partitions + } + partitions[partition] = kerror + return mr +} + +func (mr *MockOffsetCommitResponse) For(reqBody versionedDecoder) encoder { + req := reqBody.(*OffsetCommitRequest) + group := req.ConsumerGroup + res := &OffsetCommitResponse{} + for topic, partitions := range req.blocks { + for partition := range partitions { + res.AddError(topic, partition, mr.getError(group, topic, partition)) + } + } + return res +} + +func (mr *MockOffsetCommitResponse) getError(group, topic string, partition int32) KError { + topics := mr.errors[group] + if topics == nil { + return ErrNoError + } + partitions := topics[topic] + if partitions == nil { + return ErrNoError + } + kerror, ok := partitions[partition] + if !ok { + return ErrNoError + } + return kerror +} + +// MockProduceResponse is a `ProduceResponse` builder. +type MockProduceResponse struct { + errors map[string]map[int32]KError + t TestReporter +} + +func NewMockProduceResponse(t TestReporter) *MockProduceResponse { + return &MockProduceResponse{t: t} +} + +func (mr *MockProduceResponse) SetError(topic string, partition int32, kerror KError) *MockProduceResponse { + if mr.errors == nil { + mr.errors = make(map[string]map[int32]KError) + } + partitions := mr.errors[topic] + if partitions == nil { + partitions = make(map[int32]KError) + mr.errors[topic] = partitions + } + partitions[partition] = kerror + return mr +} + +func (mr *MockProduceResponse) For(reqBody versionedDecoder) encoder { + req := reqBody.(*ProduceRequest) + res := &ProduceResponse{} + for topic, partitions := range req.msgSets { + for partition := range partitions { + res.AddTopicPartition(topic, partition, mr.getError(topic, partition)) + } + } + return res +} + +func (mr *MockProduceResponse) getError(topic string, partition int32) KError { + partitions := mr.errors[topic] + if partitions == nil { + return ErrNoError + } + kerror, ok := partitions[partition] + if !ok { + return ErrNoError + } + return kerror +} + +// MockOffsetFetchResponse is a `OffsetFetchResponse` builder. +type MockOffsetFetchResponse struct { + offsets map[string]map[string]map[int32]*OffsetFetchResponseBlock + t TestReporter +} + +func NewMockOffsetFetchResponse(t TestReporter) *MockOffsetFetchResponse { + return &MockOffsetFetchResponse{t: t} +} + +func (mr *MockOffsetFetchResponse) SetOffset(group, topic string, partition int32, offset int64, metadata string, kerror KError) *MockOffsetFetchResponse { + if mr.offsets == nil { + mr.offsets = make(map[string]map[string]map[int32]*OffsetFetchResponseBlock) + } + topics := mr.offsets[group] + if topics == nil { + topics = make(map[string]map[int32]*OffsetFetchResponseBlock) + mr.offsets[group] = topics + } + partitions := topics[topic] + if partitions == nil { + partitions = make(map[int32]*OffsetFetchResponseBlock) + topics[topic] = partitions + } + partitions[partition] = &OffsetFetchResponseBlock{offset, metadata, kerror} + return mr +} + +func (mr *MockOffsetFetchResponse) For(reqBody versionedDecoder) encoder { + req := reqBody.(*OffsetFetchRequest) + group := req.ConsumerGroup + res := &OffsetFetchResponse{} + for topic, partitions := range mr.offsets[group] { + for partition, block := range partitions { + res.AddBlock(topic, partition, block) + } + } + return res +} diff --git a/vendor/src/github.com/Shopify/sarama/mocks/README.md b/vendor/src/github.com/Shopify/sarama/mocks/README.md new file mode 100644 index 00000000..55a6c2e6 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/mocks/README.md @@ -0,0 +1,13 @@ +# sarama/mocks + +The `mocks` subpackage includes mock implementations that implement the interfaces of the major sarama types. +You can use them to test your sarama applications using dependency injection. + +The following mock objects are available: + +- [Consumer](https://godoc.org/github.com/Shopify/sarama/mocks#Consumer), which will create [PartitionConsumer](https://godoc.org/github.com/Shopify/sarama/mocks#PartitionConsumer) mocks. +- [AsyncProducer](https://godoc.org/github.com/Shopify/sarama/mocks#AsyncProducer) +- [SyncProducer](https://godoc.org/github.com/Shopify/sarama/mocks#SyncProducer) + +The mocks allow you to set expectations on them. When you close the mocks, the expectations will be verified, +and the results will be reported to the `*testing.T` object you provided when creating the mock. diff --git a/vendor/src/github.com/Shopify/sarama/mocks/async_producer.go b/vendor/src/github.com/Shopify/sarama/mocks/async_producer.go new file mode 100644 index 00000000..d1d9ba41 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/mocks/async_producer.go @@ -0,0 +1,174 @@ +package mocks + +import ( + "sync" + + "github.com/Shopify/sarama" +) + +// AsyncProducer implements sarama's Producer interface for testing purposes. +// Before you can send messages to it's Input channel, you have to set expectations +// so it knows how to handle the input; it returns an error if the number of messages +// received is bigger then the number of expectations set. You can also set a +// function in each expectation so that the message value is checked by this function +// and an error is returned if the match fails. +type AsyncProducer struct { + l sync.Mutex + t ErrorReporter + expectations []*producerExpectation + closed chan struct{} + input chan *sarama.ProducerMessage + successes chan *sarama.ProducerMessage + errors chan *sarama.ProducerError + lastOffset int64 +} + +// NewAsyncProducer instantiates a new Producer mock. The t argument should +// be the *testing.T instance of your test method. An error will be written to it if +// an expectation is violated. The config argument is used to determine whether it +// should ack successes on the Successes channel. +func NewAsyncProducer(t ErrorReporter, config *sarama.Config) *AsyncProducer { + if config == nil { + config = sarama.NewConfig() + } + mp := &AsyncProducer{ + t: t, + closed: make(chan struct{}, 0), + expectations: make([]*producerExpectation, 0), + input: make(chan *sarama.ProducerMessage, config.ChannelBufferSize), + successes: make(chan *sarama.ProducerMessage, config.ChannelBufferSize), + errors: make(chan *sarama.ProducerError, config.ChannelBufferSize), + } + + go func() { + defer func() { + close(mp.successes) + close(mp.errors) + }() + + for msg := range mp.input { + mp.l.Lock() + if mp.expectations == nil || len(mp.expectations) == 0 { + mp.expectations = nil + mp.t.Errorf("No more expectation set on this mock producer to handle the input message.") + } else { + expectation := mp.expectations[0] + mp.expectations = mp.expectations[1:] + if expectation.CheckFunction != nil { + if val, err := msg.Value.Encode(); err != nil { + mp.t.Errorf("Input message encoding failed: %s", err.Error()) + mp.errors <- &sarama.ProducerError{Err: err, Msg: msg} + } else { + err = expectation.CheckFunction(val) + if err != nil { + mp.t.Errorf("Check function returned an error: %s", err.Error()) + mp.errors <- &sarama.ProducerError{Err: err, Msg: msg} + } + } + } + if expectation.Result == errProduceSuccess { + mp.lastOffset++ + if config.Producer.Return.Successes { + msg.Offset = mp.lastOffset + mp.successes <- msg + } + } else { + if config.Producer.Return.Errors { + mp.errors <- &sarama.ProducerError{Err: expectation.Result, Msg: msg} + } + } + } + mp.l.Unlock() + } + + mp.l.Lock() + if len(mp.expectations) > 0 { + mp.t.Errorf("Expected to exhaust all expectations, but %d are left.", len(mp.expectations)) + } + mp.l.Unlock() + + close(mp.closed) + }() + + return mp +} + +//////////////////////////////////////////////// +// Implement Producer interface +//////////////////////////////////////////////// + +// AsyncClose corresponds with the AsyncClose method of sarama's Producer implementation. +// By closing a mock producer, you also tell it that no more input will be provided, so it will +// write an error to the test state if there's any remaining expectations. +func (mp *AsyncProducer) AsyncClose() { + close(mp.input) +} + +// Close corresponds with the Close method of sarama's Producer implementation. +// By closing a mock producer, you also tell it that no more input will be provided, so it will +// write an error to the test state if there's any remaining expectations. +func (mp *AsyncProducer) Close() error { + mp.AsyncClose() + <-mp.closed + return nil +} + +// Input corresponds with the Input method of sarama's Producer implementation. +// You have to set expectations on the mock producer before writing messages to the Input +// channel, so it knows how to handle them. If there is no more remaining expectations and +// a messages is written to the Input channel, the mock producer will write an error to the test +// state object. +func (mp *AsyncProducer) Input() chan<- *sarama.ProducerMessage { + return mp.input +} + +// Successes corresponds with the Successes method of sarama's Producer implementation. +func (mp *AsyncProducer) Successes() <-chan *sarama.ProducerMessage { + return mp.successes +} + +// Errors corresponds with the Errors method of sarama's Producer implementation. +func (mp *AsyncProducer) Errors() <-chan *sarama.ProducerError { + return mp.errors +} + +//////////////////////////////////////////////// +// Setting expectations +//////////////////////////////////////////////// + +// ExpectInputWithCheckerFunctionAndSucceed sets an expectation on the mock producer that a message +// will be provided on the input channel. The mock producer will call the given function to check +// the message value. If an error is returned it will be made available on the Errors channel +// otherwise the mock will handle the message as if it produced successfully, i.e. it will make +// it available on the Successes channel if the Producer.Return.Successes setting is set to true. +func (mp *AsyncProducer) ExpectInputWithCheckerFunctionAndSucceed(cf ValueChecker) { + mp.l.Lock() + defer mp.l.Unlock() + mp.expectations = append(mp.expectations, &producerExpectation{Result: errProduceSuccess, CheckFunction: cf}) +} + +// ExpectInputWithCheckerFunctionAndSucceed sets an expectation on the mock producer that a message +// will be provided on the input channel. The mock producer will first call the given function to +// check the message value. If an error is returned it will be made available on the Errors channel +// otherwise the mock will handle the message as if it failed to produce successfully. This means +// it will make a ProducerError available on the Errors channel. +func (mp *AsyncProducer) ExpectInputWithCheckerFunctionAndFail(cf ValueChecker, err error) { + mp.l.Lock() + defer mp.l.Unlock() + mp.expectations = append(mp.expectations, &producerExpectation{Result: err, CheckFunction: cf}) +} + +// ExpectInputAndSucceed sets an expectation on the mock producer that a message will be provided +// on the input channel. The mock producer will handle the message as if it is produced successfully, +// i.e. it will make it available on the Successes channel if the Producer.Return.Successes setting +// is set to true. +func (mp *AsyncProducer) ExpectInputAndSucceed() { + mp.ExpectInputWithCheckerFunctionAndSucceed(nil) +} + +// ExpectInputAndFail sets an expectation on the mock producer that a message will be provided +// on the input channel. The mock producer will handle the message as if it failed to produce +// successfully. This means it will make a ProducerError available on the Errors channel. +func (mp *AsyncProducer) ExpectInputAndFail(err error) { + mp.ExpectInputWithCheckerFunctionAndFail(nil, err) +} diff --git a/vendor/src/github.com/Shopify/sarama/mocks/async_producer_test.go b/vendor/src/github.com/Shopify/sarama/mocks/async_producer_test.go new file mode 100644 index 00000000..b5d92aad --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/mocks/async_producer_test.go @@ -0,0 +1,132 @@ +package mocks + +import ( + "errors" + "fmt" + "regexp" + "strings" + "testing" + + "github.com/Shopify/sarama" +) + +func generateRegexpChecker(re string) func([]byte) error { + return func(val []byte) error { + matched, err := regexp.MatchString(re, string(val)) + if err != nil { + return errors.New("Error while trying to match the input message with the expected pattern: " + err.Error()) + } + if !matched { + return fmt.Errorf("No match between input value \"%s\" and expected pattern \"%s\"", val, re) + } + return nil + } +} + +type testReporterMock struct { + errors []string +} + +func newTestReporterMock() *testReporterMock { + return &testReporterMock{errors: make([]string, 0)} +} + +func (trm *testReporterMock) Errorf(format string, args ...interface{}) { + trm.errors = append(trm.errors, fmt.Sprintf(format, args...)) +} + +func TestMockAsyncProducerImplementsAsyncProducerInterface(t *testing.T) { + var mp interface{} = &AsyncProducer{} + if _, ok := mp.(sarama.AsyncProducer); !ok { + t.Error("The mock producer should implement the sarama.Producer interface.") + } +} + +func TestProducerReturnsExpectationsToChannels(t *testing.T) { + config := sarama.NewConfig() + config.Producer.Return.Successes = true + mp := NewAsyncProducer(t, config) + + mp.ExpectInputAndSucceed() + mp.ExpectInputAndSucceed() + mp.ExpectInputAndFail(sarama.ErrOutOfBrokers) + + mp.Input() <- &sarama.ProducerMessage{Topic: "test 1"} + mp.Input() <- &sarama.ProducerMessage{Topic: "test 2"} + mp.Input() <- &sarama.ProducerMessage{Topic: "test 3"} + + msg1 := <-mp.Successes() + msg2 := <-mp.Successes() + err1 := <-mp.Errors() + + if msg1.Topic != "test 1" { + t.Error("Expected message 1 to be returned first") + } + + if msg2.Topic != "test 2" { + t.Error("Expected message 2 to be returned second") + } + + if err1.Msg.Topic != "test 3" || err1.Err != sarama.ErrOutOfBrokers { + t.Error("Expected message 3 to be returned as error") + } + + if err := mp.Close(); err != nil { + t.Error(err) + } +} + +func TestProducerWithTooFewExpectations(t *testing.T) { + trm := newTestReporterMock() + mp := NewAsyncProducer(trm, nil) + mp.ExpectInputAndSucceed() + + mp.Input() <- &sarama.ProducerMessage{Topic: "test"} + mp.Input() <- &sarama.ProducerMessage{Topic: "test"} + + if err := mp.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Error("Expected to report an error") + } +} + +func TestProducerWithTooManyExpectations(t *testing.T) { + trm := newTestReporterMock() + mp := NewAsyncProducer(trm, nil) + mp.ExpectInputAndSucceed() + mp.ExpectInputAndFail(sarama.ErrOutOfBrokers) + + mp.Input() <- &sarama.ProducerMessage{Topic: "test"} + if err := mp.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Error("Expected to report an error") + } +} + +func TestProducerWithCheckerFunction(t *testing.T) { + trm := newTestReporterMock() + mp := NewAsyncProducer(trm, nil) + mp.ExpectInputWithCheckerFunctionAndSucceed(generateRegexpChecker("^tes")) + mp.ExpectInputWithCheckerFunctionAndSucceed(generateRegexpChecker("^tes$")) + + mp.Input() <- &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + mp.Input() <- &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + if err := mp.Close(); err != nil { + t.Error(err) + } + + if len(mp.Errors()) != 1 { + t.Error("Expected to report an error") + } + + err1 := <-mp.Errors() + if !strings.HasPrefix(err1.Err.Error(), "No match") { + t.Error("Expected to report a value check error, found: ", err1.Err) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/mocks/consumer.go b/vendor/src/github.com/Shopify/sarama/mocks/consumer.go new file mode 100644 index 00000000..a524190a --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/mocks/consumer.go @@ -0,0 +1,315 @@ +package mocks + +import ( + "sync" + "sync/atomic" + + "github.com/Shopify/sarama" +) + +// Consumer implements sarama's Consumer interface for testing purposes. +// Before you can start consuming from this consumer, you have to register +// topic/partitions using ExpectConsumePartition, and set expectations on them. +type Consumer struct { + l sync.Mutex + t ErrorReporter + config *sarama.Config + partitionConsumers map[string]map[int32]*PartitionConsumer + metadata map[string][]int32 +} + +// NewConsumer returns a new mock Consumer instance. The t argument should +// be the *testing.T instance of your test method. An error will be written to it if +// an expectation is violated. The config argument is currently unused and can be set to nil. +func NewConsumer(t ErrorReporter, config *sarama.Config) *Consumer { + if config == nil { + config = sarama.NewConfig() + } + + c := &Consumer{ + t: t, + config: config, + partitionConsumers: make(map[string]map[int32]*PartitionConsumer), + } + return c +} + +/////////////////////////////////////////////////// +// Consumer interface implementation +/////////////////////////////////////////////////// + +// ConsumePartition implements the ConsumePartition method from the sarama.Consumer interface. +// Before you can start consuming a partition, you have to set expectations on it using +// ExpectConsumePartition. You can only consume a partition once per consumer. +func (c *Consumer) ConsumePartition(topic string, partition int32, offset int64) (sarama.PartitionConsumer, error) { + c.l.Lock() + defer c.l.Unlock() + + if c.partitionConsumers[topic] == nil || c.partitionConsumers[topic][partition] == nil { + c.t.Errorf("No expectations set for %s/%d", topic, partition) + return nil, errOutOfExpectations + } + + pc := c.partitionConsumers[topic][partition] + if pc.consumed { + return nil, sarama.ConfigurationError("The topic/partition is already being consumed") + } + + if pc.offset != AnyOffset && pc.offset != offset { + c.t.Errorf("Unexpected offset when calling ConsumePartition for %s/%d. Expected %d, got %d.", topic, partition, pc.offset, offset) + } + + pc.consumed = true + return pc, nil +} + +// Topics returns a list of topics, as registered with SetMetadata +func (c *Consumer) Topics() ([]string, error) { + c.l.Lock() + defer c.l.Unlock() + + if c.metadata == nil { + c.t.Errorf("Unexpected call to Topics. Initialize the mock's topic metadata with SetMetadata.") + return nil, sarama.ErrOutOfBrokers + } + + var result []string + for topic := range c.metadata { + result = append(result, topic) + } + return result, nil +} + +// Partitions returns the list of parititons for the given topic, as registered with SetMetadata +func (c *Consumer) Partitions(topic string) ([]int32, error) { + c.l.Lock() + defer c.l.Unlock() + + if c.metadata == nil { + c.t.Errorf("Unexpected call to Partitions. Initialize the mock's topic metadata with SetMetadata.") + return nil, sarama.ErrOutOfBrokers + } + if c.metadata[topic] == nil { + return nil, sarama.ErrUnknownTopicOrPartition + } + + return c.metadata[topic], nil +} + +func (c *Consumer) HighWaterMarks() map[string]map[int32]int64 { + c.l.Lock() + defer c.l.Unlock() + + hwms := make(map[string]map[int32]int64, len(c.partitionConsumers)) + for topic, partitionConsumers := range c.partitionConsumers { + hwm := make(map[int32]int64, len(partitionConsumers)) + for partition, pc := range partitionConsumers { + hwm[partition] = pc.HighWaterMarkOffset() + } + hwms[topic] = hwm + } + + return hwms +} + +// Close implements the Close method from the sarama.Consumer interface. It will close +// all registered PartitionConsumer instances. +func (c *Consumer) Close() error { + c.l.Lock() + defer c.l.Unlock() + + for _, partitions := range c.partitionConsumers { + for _, partitionConsumer := range partitions { + _ = partitionConsumer.Close() + } + } + + return nil +} + +/////////////////////////////////////////////////// +// Expectation API +/////////////////////////////////////////////////// + +// SetTopicMetadata sets the clusters topic/partition metadata, +// which will be returned by Topics() and Partitions(). +func (c *Consumer) SetTopicMetadata(metadata map[string][]int32) { + c.l.Lock() + defer c.l.Unlock() + + c.metadata = metadata +} + +// ExpectConsumePartition will register a topic/partition, so you can set expectations on it. +// The registered PartitionConsumer will be returned, so you can set expectations +// on it using method chaining. Once a topic/partition is registered, you are +// expected to start consuming it using ConsumePartition. If that doesn't happen, +// an error will be written to the error reporter once the mock consumer is closed. It will +// also expect that the +func (c *Consumer) ExpectConsumePartition(topic string, partition int32, offset int64) *PartitionConsumer { + c.l.Lock() + defer c.l.Unlock() + + if c.partitionConsumers[topic] == nil { + c.partitionConsumers[topic] = make(map[int32]*PartitionConsumer) + } + + if c.partitionConsumers[topic][partition] == nil { + c.partitionConsumers[topic][partition] = &PartitionConsumer{ + t: c.t, + topic: topic, + partition: partition, + offset: offset, + messages: make(chan *sarama.ConsumerMessage, c.config.ChannelBufferSize), + errors: make(chan *sarama.ConsumerError, c.config.ChannelBufferSize), + } + } + + return c.partitionConsumers[topic][partition] +} + +/////////////////////////////////////////////////// +// PartitionConsumer mock type +/////////////////////////////////////////////////// + +// PartitionConsumer implements sarama's PartitionConsumer interface for testing purposes. +// It is returned by the mock Consumers ConsumePartitionMethod, but only if it is +// registered first using the Consumer's ExpectConsumePartition method. Before consuming the +// Errors and Messages channel, you should specify what values will be provided on these +// channels using YieldMessage and YieldError. +type PartitionConsumer struct { + l sync.Mutex + t ErrorReporter + topic string + partition int32 + offset int64 + messages chan *sarama.ConsumerMessage + errors chan *sarama.ConsumerError + singleClose sync.Once + consumed bool + errorsShouldBeDrained bool + messagesShouldBeDrained bool + highWaterMarkOffset int64 +} + +/////////////////////////////////////////////////// +// PartitionConsumer interface implementation +/////////////////////////////////////////////////// + +// AsyncClose implements the AsyncClose method from the sarama.PartitionConsumer interface. +func (pc *PartitionConsumer) AsyncClose() { + pc.singleClose.Do(func() { + close(pc.messages) + close(pc.errors) + }) +} + +// Close implements the Close method from the sarama.PartitionConsumer interface. It will +// verify whether the partition consumer was actually started. +func (pc *PartitionConsumer) Close() error { + if !pc.consumed { + pc.t.Errorf("Expectations set on %s/%d, but no partition consumer was started.", pc.topic, pc.partition) + return errPartitionConsumerNotStarted + } + + if pc.errorsShouldBeDrained && len(pc.errors) > 0 { + pc.t.Errorf("Expected the errors channel for %s/%d to be drained on close, but found %d errors.", pc.topic, pc.partition, len(pc.errors)) + } + + if pc.messagesShouldBeDrained && len(pc.messages) > 0 { + pc.t.Errorf("Expected the messages channel for %s/%d to be drained on close, but found %d messages.", pc.topic, pc.partition, len(pc.messages)) + } + + pc.AsyncClose() + + var ( + closeErr error + wg sync.WaitGroup + ) + + wg.Add(1) + go func() { + defer wg.Done() + + var errs = make(sarama.ConsumerErrors, 0) + for err := range pc.errors { + errs = append(errs, err) + } + + if len(errs) > 0 { + closeErr = errs + } + }() + + wg.Add(1) + go func() { + defer wg.Done() + for _ = range pc.messages { + // drain + } + }() + + wg.Wait() + return closeErr +} + +// Errors implements the Errors method from the sarama.PartitionConsumer interface. +func (pc *PartitionConsumer) Errors() <-chan *sarama.ConsumerError { + return pc.errors +} + +// Messages implements the Messages method from the sarama.PartitionConsumer interface. +func (pc *PartitionConsumer) Messages() <-chan *sarama.ConsumerMessage { + return pc.messages +} + +func (pc *PartitionConsumer) HighWaterMarkOffset() int64 { + return atomic.LoadInt64(&pc.highWaterMarkOffset) + 1 +} + +/////////////////////////////////////////////////// +// Expectation API +/////////////////////////////////////////////////// + +// YieldMessage will yield a messages Messages channel of this partition consumer +// when it is consumed. By default, the mock consumer will not verify whether this +// message was consumed from the Messages channel, because there are legitimate +// reasons forthis not to happen. ou can call ExpectMessagesDrainedOnClose so it will +// verify that the channel is empty on close. +func (pc *PartitionConsumer) YieldMessage(msg *sarama.ConsumerMessage) { + pc.l.Lock() + defer pc.l.Unlock() + + msg.Topic = pc.topic + msg.Partition = pc.partition + msg.Offset = atomic.AddInt64(&pc.highWaterMarkOffset, 1) + + pc.messages <- msg +} + +// YieldError will yield an error on the Errors channel of this partition consumer +// when it is consumed. By default, the mock consumer will not verify whether this error was +// consumed from the Errors channel, because there are legitimate reasons for this +// not to happen. You can call ExpectErrorsDrainedOnClose so it will verify that +// the channel is empty on close. +func (pc *PartitionConsumer) YieldError(err error) { + pc.errors <- &sarama.ConsumerError{ + Topic: pc.topic, + Partition: pc.partition, + Err: err, + } +} + +// ExpectMessagesDrainedOnClose sets an expectation on the partition consumer +// that the messages channel will be fully drained when Close is called. If this +// expectation is not met, an error is reported to the error reporter. +func (pc *PartitionConsumer) ExpectMessagesDrainedOnClose() { + pc.messagesShouldBeDrained = true +} + +// ExpectErrorsDrainedOnClose sets an expectation on the partition consumer +// that the errors channel will be fully drained when Close is called. If this +// expectation is not met, an error is reported to the error reporter. +func (pc *PartitionConsumer) ExpectErrorsDrainedOnClose() { + pc.errorsShouldBeDrained = true +} diff --git a/vendor/src/github.com/Shopify/sarama/mocks/consumer_test.go b/vendor/src/github.com/Shopify/sarama/mocks/consumer_test.go new file mode 100644 index 00000000..50dad3a6 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/mocks/consumer_test.go @@ -0,0 +1,249 @@ +package mocks + +import ( + "sort" + "testing" + + "github.com/Shopify/sarama" +) + +func TestMockConsumerImplementsConsumerInterface(t *testing.T) { + var c interface{} = &Consumer{} + if _, ok := c.(sarama.Consumer); !ok { + t.Error("The mock consumer should implement the sarama.Consumer interface.") + } + + var pc interface{} = &PartitionConsumer{} + if _, ok := pc.(sarama.PartitionConsumer); !ok { + t.Error("The mock partitionconsumer should implement the sarama.PartitionConsumer interface.") + } +} + +func TestConsumerHandlesExpectations(t *testing.T) { + consumer := NewConsumer(t, nil) + defer func() { + if err := consumer.Close(); err != nil { + t.Error(err) + } + }() + + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest).YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello world")}) + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest).YieldError(sarama.ErrOutOfBrokers) + consumer.ExpectConsumePartition("test", 1, sarama.OffsetOldest).YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello world again")}) + consumer.ExpectConsumePartition("other", 0, AnyOffset).YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello other")}) + + pc_test0, err := consumer.ConsumePartition("test", 0, sarama.OffsetOldest) + if err != nil { + t.Fatal(err) + } + test0_msg := <-pc_test0.Messages() + if test0_msg.Topic != "test" || test0_msg.Partition != 0 || string(test0_msg.Value) != "hello world" { + t.Error("Message was not as expected:", test0_msg) + } + test0_err := <-pc_test0.Errors() + if test0_err.Err != sarama.ErrOutOfBrokers { + t.Error("Expected sarama.ErrOutOfBrokers, found:", test0_err.Err) + } + + pc_test1, err := consumer.ConsumePartition("test", 1, sarama.OffsetOldest) + if err != nil { + t.Fatal(err) + } + test1_msg := <-pc_test1.Messages() + if test1_msg.Topic != "test" || test1_msg.Partition != 1 || string(test1_msg.Value) != "hello world again" { + t.Error("Message was not as expected:", test1_msg) + } + + pc_other0, err := consumer.ConsumePartition("other", 0, sarama.OffsetNewest) + if err != nil { + t.Fatal(err) + } + other0_msg := <-pc_other0.Messages() + if other0_msg.Topic != "other" || other0_msg.Partition != 0 || string(other0_msg.Value) != "hello other" { + t.Error("Message was not as expected:", other0_msg) + } +} + +func TestConsumerReturnsNonconsumedErrorsOnClose(t *testing.T) { + consumer := NewConsumer(t, nil) + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest).YieldError(sarama.ErrOutOfBrokers) + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest).YieldError(sarama.ErrOutOfBrokers) + + pc, err := consumer.ConsumePartition("test", 0, sarama.OffsetOldest) + if err != nil { + t.Fatal(err) + } + + select { + case <-pc.Messages(): + t.Error("Did not epxect a message on the messages channel.") + case err := <-pc.Errors(): + if err.Err != sarama.ErrOutOfBrokers { + t.Error("Expected sarama.ErrOutOfBrokers, found", err) + } + } + + errs := pc.Close().(sarama.ConsumerErrors) + if len(errs) != 1 && errs[0].Err != sarama.ErrOutOfBrokers { + t.Error("Expected Close to return the remaining sarama.ErrOutOfBrokers") + } +} + +func TestConsumerWithoutExpectationsOnPartition(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + + _, err := consumer.ConsumePartition("test", 1, sarama.OffsetOldest) + if err != errOutOfExpectations { + t.Error("Expected ConsumePartition to return errOutOfExpectations") + } + + if err := consumer.Close(); err != nil { + t.Error("No error expected on close, but found:", err) + } + + if len(trm.errors) != 1 { + t.Errorf("Expected an expectation failure to be set on the error reporter.") + } +} + +func TestConsumerWithExpectationsOnUnconsumedPartition(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest).YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello world")}) + + if err := consumer.Close(); err != nil { + t.Error("No error expected on close, but found:", err) + } + + if len(trm.errors) != 1 { + t.Errorf("Expected an expectation failure to be set on the error reporter.") + } +} + +func TestConsumerWithWrongOffsetExpectation(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest) + + _, err := consumer.ConsumePartition("test", 0, sarama.OffsetNewest) + if err != nil { + t.Error("Did not expect error, found:", err) + } + + if len(trm.errors) != 1 { + t.Errorf("Expected an expectation failure to be set on the error reporter.") + } + + if err := consumer.Close(); err != nil { + t.Error(err) + } +} + +func TestConsumerViolatesMessagesDrainedExpectation(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + pcmock := consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest) + pcmock.YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello")}) + pcmock.YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello")}) + pcmock.ExpectMessagesDrainedOnClose() + + pc, err := consumer.ConsumePartition("test", 0, sarama.OffsetOldest) + if err != nil { + t.Error(err) + } + + // consume first message, not second one + <-pc.Messages() + + if err := consumer.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Errorf("Expected an expectation failure to be set on the error reporter.") + } +} + +func TestConsumerMeetsErrorsDrainedExpectation(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + + pcmock := consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest) + pcmock.YieldError(sarama.ErrInvalidMessage) + pcmock.YieldError(sarama.ErrInvalidMessage) + pcmock.ExpectErrorsDrainedOnClose() + + pc, err := consumer.ConsumePartition("test", 0, sarama.OffsetOldest) + if err != nil { + t.Error(err) + } + + // consume first and second error, + <-pc.Errors() + <-pc.Errors() + + if err := consumer.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 0 { + t.Errorf("Expected no expectation failures to be set on the error reporter.") + } +} + +func TestConsumerTopicMetadata(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + + consumer.SetTopicMetadata(map[string][]int32{ + "test1": []int32{0, 1, 2, 3}, + "test2": []int32{0, 1, 2, 3, 4, 5, 6, 7}, + }) + + topics, err := consumer.Topics() + if err != nil { + t.Error(t) + } + + sortedTopics := sort.StringSlice(topics) + sortedTopics.Sort() + if len(sortedTopics) != 2 || sortedTopics[0] != "test1" || sortedTopics[1] != "test2" { + t.Error("Unexpected topics returned:", sortedTopics) + } + + partitions1, err := consumer.Partitions("test1") + if err != nil { + t.Error(t) + } + + if len(partitions1) != 4 { + t.Error("Unexpected partitions returned:", len(partitions1)) + } + + partitions2, err := consumer.Partitions("test2") + if err != nil { + t.Error(t) + } + + if len(partitions2) != 8 { + t.Error("Unexpected partitions returned:", len(partitions2)) + } + + if len(trm.errors) != 0 { + t.Errorf("Expected no expectation failures to be set on the error reporter.") + } +} + +func TestConsumerUnexpectedTopicMetadata(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + + if _, err := consumer.Topics(); err != sarama.ErrOutOfBrokers { + t.Error("Expected sarama.ErrOutOfBrokers, found", err) + } + + if len(trm.errors) != 1 { + t.Errorf("Expected an expectation failure to be set on the error reporter.") + } +} diff --git a/vendor/src/github.com/Shopify/sarama/mocks/mocks.go b/vendor/src/github.com/Shopify/sarama/mocks/mocks.go new file mode 100644 index 00000000..4adb838d --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/mocks/mocks.go @@ -0,0 +1,48 @@ +/* +Package mocks provides mocks that can be used for testing applications +that use Sarama. The mock types provided by this package implement the +interfaces Sarama exports, so you can use them for dependency injection +in your tests. + +All mock instances require you to set expectations on them before you +can use them. It will determine how the mock will behave. If an +expectation is not met, it will make your test fail. + +NOTE: this package currently does not fall under the API stability +guarantee of Sarama as it is still considered experimental. +*/ +package mocks + +import ( + "errors" + + "github.com/Shopify/sarama" +) + +// ErrorReporter is a simple interface that includes the testing.T methods we use to report +// expectation violations when using the mock objects. +type ErrorReporter interface { + Errorf(string, ...interface{}) +} + +// ValueChecker is a function type to be set in each expectation of the producer mocks +// to check the value passed. +type ValueChecker func(val []byte) error + +var ( + errProduceSuccess error = nil + errOutOfExpectations = errors.New("No more expectations set on mock") + errPartitionConsumerNotStarted = errors.New("The partition consumer was never started") +) + +const AnyOffset int64 = -1000 + +type producerExpectation struct { + Result error + CheckFunction ValueChecker +} + +type consumerExpectation struct { + Err error + Msg *sarama.ConsumerMessage +} diff --git a/vendor/src/github.com/Shopify/sarama/mocks/sync_producer.go b/vendor/src/github.com/Shopify/sarama/mocks/sync_producer.go new file mode 100644 index 00000000..2ac7b5c3 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/mocks/sync_producer.go @@ -0,0 +1,148 @@ +package mocks + +import ( + "sync" + + "github.com/Shopify/sarama" +) + +// SyncProducer implements sarama's SyncProducer interface for testing purposes. +// Before you can use it, you have to set expectations on the mock SyncProducer +// to tell it how to handle calls to SendMessage, so you can easily test success +// and failure scenarios. +type SyncProducer struct { + l sync.Mutex + t ErrorReporter + expectations []*producerExpectation + lastOffset int64 +} + +// NewSyncProducer instantiates a new SyncProducer mock. The t argument should +// be the *testing.T instance of your test method. An error will be written to it if +// an expectation is violated. The config argument is currently unused, but is +// maintained to be compatible with the async Producer. +func NewSyncProducer(t ErrorReporter, config *sarama.Config) *SyncProducer { + return &SyncProducer{ + t: t, + expectations: make([]*producerExpectation, 0), + } +} + +//////////////////////////////////////////////// +// Implement SyncProducer interface +//////////////////////////////////////////////// + +// SendMessage corresponds with the SendMessage method of sarama's SyncProducer implementation. +// You have to set expectations on the mock producer before calling SendMessage, so it knows +// how to handle them. You can set a function in each expectation so that the message value +// checked by this function and an error is returned if the match fails. +// If there is no more remaining expectation when SendMessage is called, +// the mock producer will write an error to the test state object. +func (sp *SyncProducer) SendMessage(msg *sarama.ProducerMessage) (partition int32, offset int64, err error) { + sp.l.Lock() + defer sp.l.Unlock() + + if len(sp.expectations) > 0 { + expectation := sp.expectations[0] + sp.expectations = sp.expectations[1:] + if expectation.CheckFunction != nil { + if val, err := msg.Value.Encode(); err != nil { + sp.t.Errorf("Input message encoding failed: %s", err.Error()) + return -1, -1, err + } else { + err := expectation.CheckFunction(val) + if err != nil { + sp.t.Errorf("Check function returned an error: %s", err.Error()) + return -1, -1, err + } + } + } + if expectation.Result == errProduceSuccess { + sp.lastOffset++ + msg.Offset = sp.lastOffset + return 0, msg.Offset, nil + } else { + return -1, -1, expectation.Result + } + } else { + sp.t.Errorf("No more expectation set on this mock producer to handle the input message.") + return -1, -1, errOutOfExpectations + } +} + +// SendMessages corresponds with the SendMessages method of sarama's SyncProducer implementation. +// You have to set expectations on the mock producer before calling SendMessages, so it knows +// how to handle them. If there is no more remaining expectations when SendMessages is called, +// the mock producer will write an error to the test state object. +func (sp *SyncProducer) SendMessages(msgs []*sarama.ProducerMessage) error { + sp.l.Lock() + defer sp.l.Unlock() + + if len(sp.expectations) >= len(msgs) { + expectations := sp.expectations[0 : len(msgs)-1] + sp.expectations = sp.expectations[len(msgs):] + + for _, expectation := range expectations { + if expectation.Result != errProduceSuccess { + return expectation.Result + } + + } + return nil + } else { + sp.t.Errorf("Insufficient expectations set on this mock producer to handle the input messages.") + return errOutOfExpectations + } +} + +// Close corresponds with the Close method of sarama's SyncProducer implementation. +// By closing a mock syncproducer, you also tell it that no more SendMessage calls will follow, +// so it will write an error to the test state if there's any remaining expectations. +func (sp *SyncProducer) Close() error { + sp.l.Lock() + defer sp.l.Unlock() + + if len(sp.expectations) > 0 { + sp.t.Errorf("Expected to exhaust all expectations, but %d are left.", len(sp.expectations)) + } + + return nil +} + +//////////////////////////////////////////////// +// Setting expectations +//////////////////////////////////////////////// + +// ExpectSendMessageWithCheckerFunctionAndSucceed sets an expectation on the mock producer that SendMessage +// will be called. The mock producer will first call the given function to check the message value. +// It will cascade the error of the function, if any, or handle the message as if it produced +// successfully, i.e. by returning a valid partition, and offset, and a nil error. +func (sp *SyncProducer) ExpectSendMessageWithCheckerFunctionAndSucceed(cf ValueChecker) { + sp.l.Lock() + defer sp.l.Unlock() + sp.expectations = append(sp.expectations, &producerExpectation{Result: errProduceSuccess, CheckFunction: cf}) +} + +// ExpectSendMessageAndFail sets an expectation on the mock producer that SendMessage will be +// called. The mock producer will first call the given function to check the message value. +// It will cascade the error of the function, if any, or handle the message as if it failed +// to produce successfully, i.e. by returning the provided error. +func (sp *SyncProducer) ExpectSendMessageWithCheckerFunctionAndFail(cf ValueChecker, err error) { + sp.l.Lock() + defer sp.l.Unlock() + sp.expectations = append(sp.expectations, &producerExpectation{Result: err, CheckFunction: cf}) +} + +// ExpectSendMessageAndSucceed sets an expectation on the mock producer that SendMessage will be +// called. The mock producer will handle the message as if it produced successfully, i.e. by +// returning a valid partition, and offset, and a nil error. +func (sp *SyncProducer) ExpectSendMessageAndSucceed() { + sp.ExpectSendMessageWithCheckerFunctionAndSucceed(nil) +} + +// ExpectSendMessageAndFail sets an expectation on the mock producer that SendMessage will be +// called. The mock producer will handle the message as if it failed to produce +// successfully, i.e. by returning the provided error. +func (sp *SyncProducer) ExpectSendMessageAndFail(err error) { + sp.ExpectSendMessageWithCheckerFunctionAndFail(nil, err) +} diff --git a/vendor/src/github.com/Shopify/sarama/mocks/sync_producer_test.go b/vendor/src/github.com/Shopify/sarama/mocks/sync_producer_test.go new file mode 100644 index 00000000..0fdc9987 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/mocks/sync_producer_test.go @@ -0,0 +1,124 @@ +package mocks + +import ( + "strings" + "testing" + + "github.com/Shopify/sarama" +) + +func TestMockSyncProducerImplementsSyncProducerInterface(t *testing.T) { + var mp interface{} = &SyncProducer{} + if _, ok := mp.(sarama.SyncProducer); !ok { + t.Error("The mock async producer should implement the sarama.SyncProducer interface.") + } +} + +func TestSyncProducerReturnsExpectationsToSendMessage(t *testing.T) { + sp := NewSyncProducer(t, nil) + defer func() { + if err := sp.Close(); err != nil { + t.Error(err) + } + }() + + sp.ExpectSendMessageAndSucceed() + sp.ExpectSendMessageAndSucceed() + sp.ExpectSendMessageAndFail(sarama.ErrOutOfBrokers) + + msg := &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + + _, offset, err := sp.SendMessage(msg) + if err != nil { + t.Errorf("The first message should have been produced successfully, but got %s", err) + } + if offset != 1 || offset != msg.Offset { + t.Errorf("The first message should have been assigned offset 1, but got %d", msg.Offset) + } + + _, offset, err = sp.SendMessage(msg) + if err != nil { + t.Errorf("The second message should have been produced successfully, but got %s", err) + } + if offset != 2 || offset != msg.Offset { + t.Errorf("The second message should have been assigned offset 2, but got %d", offset) + } + + _, _, err = sp.SendMessage(msg) + if err != sarama.ErrOutOfBrokers { + t.Errorf("The third message should not have been produced successfully") + } + + if err := sp.Close(); err != nil { + t.Error(err) + } +} + +func TestSyncProducerWithTooManyExpectations(t *testing.T) { + trm := newTestReporterMock() + + sp := NewSyncProducer(trm, nil) + sp.ExpectSendMessageAndSucceed() + sp.ExpectSendMessageAndFail(sarama.ErrOutOfBrokers) + + msg := &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + if _, _, err := sp.SendMessage(msg); err != nil { + t.Error("No error expected on first SendMessage call", err) + } + + if err := sp.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Error("Expected to report an error") + } +} + +func TestSyncProducerWithTooFewExpectations(t *testing.T) { + trm := newTestReporterMock() + + sp := NewSyncProducer(trm, nil) + sp.ExpectSendMessageAndSucceed() + + msg := &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + if _, _, err := sp.SendMessage(msg); err != nil { + t.Error("No error expected on first SendMessage call", err) + } + if _, _, err := sp.SendMessage(msg); err != errOutOfExpectations { + t.Error("errOutOfExpectations expected on second SendMessage call, found:", err) + } + + if err := sp.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Error("Expected to report an error") + } +} + +func TestSyncProducerWithCheckerFunction(t *testing.T) { + trm := newTestReporterMock() + + sp := NewSyncProducer(trm, nil) + sp.ExpectSendMessageWithCheckerFunctionAndSucceed(generateRegexpChecker("^tes")) + sp.ExpectSendMessageWithCheckerFunctionAndSucceed(generateRegexpChecker("^tes$")) + + msg := &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + if _, _, err := sp.SendMessage(msg); err != nil { + t.Error("No error expected on first SendMessage call, found: ", err) + } + msg = &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + if _, _, err := sp.SendMessage(msg); err == nil || !strings.HasPrefix(err.Error(), "No match") { + t.Error("Error during value check expected on second SendMessage call, found:", err) + } + + if err := sp.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Error("Expected to report an error") + } +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_commit_request.go b/vendor/src/github.com/Shopify/sarama/offset_commit_request.go new file mode 100644 index 00000000..b21ea634 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_commit_request.go @@ -0,0 +1,190 @@ +package sarama + +// ReceiveTime is a special value for the timestamp field of Offset Commit Requests which +// tells the broker to set the timestamp to the time at which the request was received. +// The timestamp is only used if message version 1 is used, which requires kafka 0.8.2. +const ReceiveTime int64 = -1 + +// GroupGenerationUndefined is a special value for the group generation field of +// Offset Commit Requests that should be used when a consumer group does not rely +// on Kafka for partition management. +const GroupGenerationUndefined = -1 + +type offsetCommitRequestBlock struct { + offset int64 + timestamp int64 + metadata string +} + +func (b *offsetCommitRequestBlock) encode(pe packetEncoder, version int16) error { + pe.putInt64(b.offset) + if version == 1 { + pe.putInt64(b.timestamp) + } else if b.timestamp != 0 { + Logger.Println("Non-zero timestamp specified for OffsetCommitRequest not v1, it will be ignored") + } + + return pe.putString(b.metadata) +} + +func (b *offsetCommitRequestBlock) decode(pd packetDecoder, version int16) (err error) { + if b.offset, err = pd.getInt64(); err != nil { + return err + } + if version == 1 { + if b.timestamp, err = pd.getInt64(); err != nil { + return err + } + } + b.metadata, err = pd.getString() + return err +} + +type OffsetCommitRequest struct { + ConsumerGroup string + ConsumerGroupGeneration int32 // v1 or later + ConsumerID string // v1 or later + RetentionTime int64 // v2 or later + + // Version can be: + // - 0 (kafka 0.8.1 and later) + // - 1 (kafka 0.8.2 and later) + // - 2 (kafka 0.9.0 and later) + Version int16 + blocks map[string]map[int32]*offsetCommitRequestBlock +} + +func (r *OffsetCommitRequest) encode(pe packetEncoder) error { + if r.Version < 0 || r.Version > 2 { + return PacketEncodingError{"invalid or unsupported OffsetCommitRequest version field"} + } + + if err := pe.putString(r.ConsumerGroup); err != nil { + return err + } + + if r.Version >= 1 { + pe.putInt32(r.ConsumerGroupGeneration) + if err := pe.putString(r.ConsumerID); err != nil { + return err + } + } else { + if r.ConsumerGroupGeneration != 0 { + Logger.Println("Non-zero ConsumerGroupGeneration specified for OffsetCommitRequest v0, it will be ignored") + } + if r.ConsumerID != "" { + Logger.Println("Non-empty ConsumerID specified for OffsetCommitRequest v0, it will be ignored") + } + } + + if r.Version >= 2 { + pe.putInt64(r.RetentionTime) + } else if r.RetentionTime != 0 { + Logger.Println("Non-zero RetentionTime specified for OffsetCommitRequest version <2, it will be ignored") + } + + if err := pe.putArrayLength(len(r.blocks)); err != nil { + return err + } + for topic, partitions := range r.blocks { + if err := pe.putString(topic); err != nil { + return err + } + if err := pe.putArrayLength(len(partitions)); err != nil { + return err + } + for partition, block := range partitions { + pe.putInt32(partition) + if err := block.encode(pe, r.Version); err != nil { + return err + } + } + } + return nil +} + +func (r *OffsetCommitRequest) decode(pd packetDecoder, version int16) (err error) { + r.Version = version + + if r.ConsumerGroup, err = pd.getString(); err != nil { + return err + } + + if r.Version >= 1 { + if r.ConsumerGroupGeneration, err = pd.getInt32(); err != nil { + return err + } + if r.ConsumerID, err = pd.getString(); err != nil { + return err + } + } + + if r.Version >= 2 { + if r.RetentionTime, err = pd.getInt64(); err != nil { + return err + } + } + + topicCount, err := pd.getArrayLength() + if err != nil { + return err + } + if topicCount == 0 { + return nil + } + r.blocks = make(map[string]map[int32]*offsetCommitRequestBlock) + for i := 0; i < topicCount; i++ { + topic, err := pd.getString() + if err != nil { + return err + } + partitionCount, err := pd.getArrayLength() + if err != nil { + return err + } + r.blocks[topic] = make(map[int32]*offsetCommitRequestBlock) + for j := 0; j < partitionCount; j++ { + partition, err := pd.getInt32() + if err != nil { + return err + } + block := &offsetCommitRequestBlock{} + if err := block.decode(pd, r.Version); err != nil { + return err + } + r.blocks[topic][partition] = block + } + } + return nil +} + +func (r *OffsetCommitRequest) key() int16 { + return 8 +} + +func (r *OffsetCommitRequest) version() int16 { + return r.Version +} + +func (r *OffsetCommitRequest) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_8_2_0 + case 2: + return V0_9_0_0 + default: + return minVersion + } +} + +func (r *OffsetCommitRequest) AddBlock(topic string, partitionID int32, offset int64, timestamp int64, metadata string) { + if r.blocks == nil { + r.blocks = make(map[string]map[int32]*offsetCommitRequestBlock) + } + + if r.blocks[topic] == nil { + r.blocks[topic] = make(map[int32]*offsetCommitRequestBlock) + } + + r.blocks[topic][partitionID] = &offsetCommitRequestBlock{offset, timestamp, metadata} +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_commit_request_test.go b/vendor/src/github.com/Shopify/sarama/offset_commit_request_test.go new file mode 100644 index 00000000..afc25b7b --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_commit_request_test.go @@ -0,0 +1,90 @@ +package sarama + +import "testing" + +var ( + offsetCommitRequestNoBlocksV0 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x00, 0x00} + + offsetCommitRequestNoBlocksV1 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x11, 0x22, + 0x00, 0x04, 'c', 'o', 'n', 's', + 0x00, 0x00, 0x00, 0x00} + + offsetCommitRequestNoBlocksV2 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x11, 0x22, + 0x00, 0x04, 'c', 'o', 'n', 's', + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x33, + 0x00, 0x00, 0x00, 0x00} + + offsetCommitRequestOneBlockV0 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x52, 0x21, + 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, + 0x00, 0x08, 'm', 'e', 't', 'a', 'd', 'a', 't', 'a'} + + offsetCommitRequestOneBlockV1 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x11, 0x22, + 0x00, 0x04, 'c', 'o', 'n', 's', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x52, 0x21, + 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x08, 'm', 'e', 't', 'a', 'd', 'a', 't', 'a'} + + offsetCommitRequestOneBlockV2 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x11, 0x22, + 0x00, 0x04, 'c', 'o', 'n', 's', + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x33, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x52, 0x21, + 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, + 0x00, 0x08, 'm', 'e', 't', 'a', 'd', 'a', 't', 'a'} +) + +func TestOffsetCommitRequestV0(t *testing.T) { + request := new(OffsetCommitRequest) + request.Version = 0 + request.ConsumerGroup = "foobar" + testRequest(t, "no blocks v0", request, offsetCommitRequestNoBlocksV0) + + request.AddBlock("topic", 0x5221, 0xDEADBEEF, 0, "metadata") + testRequest(t, "one block v0", request, offsetCommitRequestOneBlockV0) +} + +func TestOffsetCommitRequestV1(t *testing.T) { + request := new(OffsetCommitRequest) + request.ConsumerGroup = "foobar" + request.ConsumerID = "cons" + request.ConsumerGroupGeneration = 0x1122 + request.Version = 1 + testRequest(t, "no blocks v1", request, offsetCommitRequestNoBlocksV1) + + request.AddBlock("topic", 0x5221, 0xDEADBEEF, ReceiveTime, "metadata") + testRequest(t, "one block v1", request, offsetCommitRequestOneBlockV1) +} + +func TestOffsetCommitRequestV2(t *testing.T) { + request := new(OffsetCommitRequest) + request.ConsumerGroup = "foobar" + request.ConsumerID = "cons" + request.ConsumerGroupGeneration = 0x1122 + request.RetentionTime = 0x4433 + request.Version = 2 + testRequest(t, "no blocks v2", request, offsetCommitRequestNoBlocksV2) + + request.AddBlock("topic", 0x5221, 0xDEADBEEF, 0, "metadata") + testRequest(t, "one block v2", request, offsetCommitRequestOneBlockV2) +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_commit_response.go b/vendor/src/github.com/Shopify/sarama/offset_commit_response.go new file mode 100644 index 00000000..7f277e77 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_commit_response.go @@ -0,0 +1,85 @@ +package sarama + +type OffsetCommitResponse struct { + Errors map[string]map[int32]KError +} + +func (r *OffsetCommitResponse) AddError(topic string, partition int32, kerror KError) { + if r.Errors == nil { + r.Errors = make(map[string]map[int32]KError) + } + partitions := r.Errors[topic] + if partitions == nil { + partitions = make(map[int32]KError) + r.Errors[topic] = partitions + } + partitions[partition] = kerror +} + +func (r *OffsetCommitResponse) encode(pe packetEncoder) error { + if err := pe.putArrayLength(len(r.Errors)); err != nil { + return err + } + for topic, partitions := range r.Errors { + if err := pe.putString(topic); err != nil { + return err + } + if err := pe.putArrayLength(len(partitions)); err != nil { + return err + } + for partition, kerror := range partitions { + pe.putInt32(partition) + pe.putInt16(int16(kerror)) + } + } + return nil +} + +func (r *OffsetCommitResponse) decode(pd packetDecoder, version int16) (err error) { + numTopics, err := pd.getArrayLength() + if err != nil || numTopics == 0 { + return err + } + + r.Errors = make(map[string]map[int32]KError, numTopics) + for i := 0; i < numTopics; i++ { + name, err := pd.getString() + if err != nil { + return err + } + + numErrors, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Errors[name] = make(map[int32]KError, numErrors) + + for j := 0; j < numErrors; j++ { + id, err := pd.getInt32() + if err != nil { + return err + } + + tmp, err := pd.getInt16() + if err != nil { + return err + } + r.Errors[name][id] = KError(tmp) + } + } + + return nil +} + +func (r *OffsetCommitResponse) key() int16 { + return 8 +} + +func (r *OffsetCommitResponse) version() int16 { + return 0 +} + +func (r *OffsetCommitResponse) requiredVersion() KafkaVersion { + return minVersion +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_commit_response_test.go b/vendor/src/github.com/Shopify/sarama/offset_commit_response_test.go new file mode 100644 index 00000000..074ec923 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_commit_response_test.go @@ -0,0 +1,24 @@ +package sarama + +import ( + "testing" +) + +var ( + emptyOffsetCommitResponse = []byte{ + 0x00, 0x00, 0x00, 0x00} +) + +func TestEmptyOffsetCommitResponse(t *testing.T) { + response := OffsetCommitResponse{} + testResponse(t, "empty", &response, emptyOffsetCommitResponse) +} + +func TestNormalOffsetCommitResponse(t *testing.T) { + response := OffsetCommitResponse{} + response.AddError("t", 0, ErrNotLeaderForPartition) + response.Errors["m"] = make(map[int32]KError) + // The response encoded form cannot be checked for it varies due to + // unpredictable map traversal order. + testResponse(t, "normal", &response, nil) +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_fetch_request.go b/vendor/src/github.com/Shopify/sarama/offset_fetch_request.go new file mode 100644 index 00000000..b19fe79b --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_fetch_request.go @@ -0,0 +1,81 @@ +package sarama + +type OffsetFetchRequest struct { + ConsumerGroup string + Version int16 + partitions map[string][]int32 +} + +func (r *OffsetFetchRequest) encode(pe packetEncoder) (err error) { + if r.Version < 0 || r.Version > 1 { + return PacketEncodingError{"invalid or unsupported OffsetFetchRequest version field"} + } + + if err = pe.putString(r.ConsumerGroup); err != nil { + return err + } + if err = pe.putArrayLength(len(r.partitions)); err != nil { + return err + } + for topic, partitions := range r.partitions { + if err = pe.putString(topic); err != nil { + return err + } + if err = pe.putInt32Array(partitions); err != nil { + return err + } + } + return nil +} + +func (r *OffsetFetchRequest) decode(pd packetDecoder, version int16) (err error) { + r.Version = version + if r.ConsumerGroup, err = pd.getString(); err != nil { + return err + } + partitionCount, err := pd.getArrayLength() + if err != nil { + return err + } + if partitionCount == 0 { + return nil + } + r.partitions = make(map[string][]int32) + for i := 0; i < partitionCount; i++ { + topic, err := pd.getString() + if err != nil { + return err + } + partitions, err := pd.getInt32Array() + if err != nil { + return err + } + r.partitions[topic] = partitions + } + return nil +} + +func (r *OffsetFetchRequest) key() int16 { + return 9 +} + +func (r *OffsetFetchRequest) version() int16 { + return r.Version +} + +func (r *OffsetFetchRequest) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_8_2_0 + default: + return minVersion + } +} + +func (r *OffsetFetchRequest) AddPartition(topic string, partitionID int32) { + if r.partitions == nil { + r.partitions = make(map[string][]int32) + } + + r.partitions[topic] = append(r.partitions[topic], partitionID) +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_fetch_request_test.go b/vendor/src/github.com/Shopify/sarama/offset_fetch_request_test.go new file mode 100644 index 00000000..025d725c --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_fetch_request_test.go @@ -0,0 +1,31 @@ +package sarama + +import "testing" + +var ( + offsetFetchRequestNoGroupNoPartitions = []byte{ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} + + offsetFetchRequestNoPartitions = []byte{ + 0x00, 0x04, 'b', 'l', 'a', 'h', + 0x00, 0x00, 0x00, 0x00} + + offsetFetchRequestOnePartition = []byte{ + 0x00, 0x04, 'b', 'l', 'a', 'h', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x0D, 't', 'o', 'p', 'i', 'c', 'T', 'h', 'e', 'F', 'i', 'r', 's', 't', + 0x00, 0x00, 0x00, 0x01, + 0x4F, 0x4F, 0x4F, 0x4F} +) + +func TestOffsetFetchRequest(t *testing.T) { + request := new(OffsetFetchRequest) + testRequest(t, "no group, no partitions", request, offsetFetchRequestNoGroupNoPartitions) + + request.ConsumerGroup = "blah" + testRequest(t, "no partitions", request, offsetFetchRequestNoPartitions) + + request.AddPartition("topicTheFirst", 0x4F4F4F4F) + testRequest(t, "one partition", request, offsetFetchRequestOnePartition) +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_fetch_response.go b/vendor/src/github.com/Shopify/sarama/offset_fetch_response.go new file mode 100644 index 00000000..323220ea --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_fetch_response.go @@ -0,0 +1,143 @@ +package sarama + +type OffsetFetchResponseBlock struct { + Offset int64 + Metadata string + Err KError +} + +func (b *OffsetFetchResponseBlock) decode(pd packetDecoder) (err error) { + b.Offset, err = pd.getInt64() + if err != nil { + return err + } + + b.Metadata, err = pd.getString() + if err != nil { + return err + } + + tmp, err := pd.getInt16() + if err != nil { + return err + } + b.Err = KError(tmp) + + return nil +} + +func (b *OffsetFetchResponseBlock) encode(pe packetEncoder) (err error) { + pe.putInt64(b.Offset) + + err = pe.putString(b.Metadata) + if err != nil { + return err + } + + pe.putInt16(int16(b.Err)) + + return nil +} + +type OffsetFetchResponse struct { + Blocks map[string]map[int32]*OffsetFetchResponseBlock +} + +func (r *OffsetFetchResponse) encode(pe packetEncoder) error { + if err := pe.putArrayLength(len(r.Blocks)); err != nil { + return err + } + for topic, partitions := range r.Blocks { + if err := pe.putString(topic); err != nil { + return err + } + if err := pe.putArrayLength(len(partitions)); err != nil { + return err + } + for partition, block := range partitions { + pe.putInt32(partition) + if err := block.encode(pe); err != nil { + return err + } + } + } + return nil +} + +func (r *OffsetFetchResponse) decode(pd packetDecoder, version int16) (err error) { + numTopics, err := pd.getArrayLength() + if err != nil || numTopics == 0 { + return err + } + + r.Blocks = make(map[string]map[int32]*OffsetFetchResponseBlock, numTopics) + for i := 0; i < numTopics; i++ { + name, err := pd.getString() + if err != nil { + return err + } + + numBlocks, err := pd.getArrayLength() + if err != nil { + return err + } + + if numBlocks == 0 { + r.Blocks[name] = nil + continue + } + r.Blocks[name] = make(map[int32]*OffsetFetchResponseBlock, numBlocks) + + for j := 0; j < numBlocks; j++ { + id, err := pd.getInt32() + if err != nil { + return err + } + + block := new(OffsetFetchResponseBlock) + err = block.decode(pd) + if err != nil { + return err + } + r.Blocks[name][id] = block + } + } + + return nil +} + +func (r *OffsetFetchResponse) key() int16 { + return 9 +} + +func (r *OffsetFetchResponse) version() int16 { + return 0 +} + +func (r *OffsetFetchResponse) requiredVersion() KafkaVersion { + return minVersion +} + +func (r *OffsetFetchResponse) GetBlock(topic string, partition int32) *OffsetFetchResponseBlock { + if r.Blocks == nil { + return nil + } + + if r.Blocks[topic] == nil { + return nil + } + + return r.Blocks[topic][partition] +} + +func (r *OffsetFetchResponse) AddBlock(topic string, partition int32, block *OffsetFetchResponseBlock) { + if r.Blocks == nil { + r.Blocks = make(map[string]map[int32]*OffsetFetchResponseBlock) + } + partitions := r.Blocks[topic] + if partitions == nil { + partitions = make(map[int32]*OffsetFetchResponseBlock) + r.Blocks[topic] = partitions + } + partitions[partition] = block +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_fetch_response_test.go b/vendor/src/github.com/Shopify/sarama/offset_fetch_response_test.go new file mode 100644 index 00000000..7614ae42 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_fetch_response_test.go @@ -0,0 +1,22 @@ +package sarama + +import "testing" + +var ( + emptyOffsetFetchResponse = []byte{ + 0x00, 0x00, 0x00, 0x00} +) + +func TestEmptyOffsetFetchResponse(t *testing.T) { + response := OffsetFetchResponse{} + testResponse(t, "empty", &response, emptyOffsetFetchResponse) +} + +func TestNormalOffsetFetchResponse(t *testing.T) { + response := OffsetFetchResponse{} + response.AddBlock("t", 0, &OffsetFetchResponseBlock{0, "md", ErrRequestTimedOut}) + response.Blocks["m"] = nil + // The response encoded form cannot be checked for it varies due to + // unpredictable map traversal order. + testResponse(t, "normal", &response, nil) +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_manager.go b/vendor/src/github.com/Shopify/sarama/offset_manager.go new file mode 100644 index 00000000..5e15cdaf --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_manager.go @@ -0,0 +1,542 @@ +package sarama + +import ( + "sync" + "time" +) + +// Offset Manager + +// OffsetManager uses Kafka to store and fetch consumed partition offsets. +type OffsetManager interface { + // ManagePartition creates a PartitionOffsetManager on the given topic/partition. + // It will return an error if this OffsetManager is already managing the given + // topic/partition. + ManagePartition(topic string, partition int32) (PartitionOffsetManager, error) + + // Close stops the OffsetManager from managing offsets. It is required to call + // this function before an OffsetManager object passes out of scope, as it + // will otherwise leak memory. You must call this after all the + // PartitionOffsetManagers are closed. + Close() error +} + +type offsetManager struct { + client Client + conf *Config + group string + + lock sync.Mutex + poms map[string]map[int32]*partitionOffsetManager + boms map[*Broker]*brokerOffsetManager +} + +// NewOffsetManagerFromClient creates a new OffsetManager from the given client. +// It is still necessary to call Close() on the underlying client when finished with the partition manager. +func NewOffsetManagerFromClient(group string, client Client) (OffsetManager, error) { + // Check that we are not dealing with a closed Client before processing any other arguments + if client.Closed() { + return nil, ErrClosedClient + } + + om := &offsetManager{ + client: client, + conf: client.Config(), + group: group, + poms: make(map[string]map[int32]*partitionOffsetManager), + boms: make(map[*Broker]*brokerOffsetManager), + } + + return om, nil +} + +func (om *offsetManager) ManagePartition(topic string, partition int32) (PartitionOffsetManager, error) { + pom, err := om.newPartitionOffsetManager(topic, partition) + if err != nil { + return nil, err + } + + om.lock.Lock() + defer om.lock.Unlock() + + topicManagers := om.poms[topic] + if topicManagers == nil { + topicManagers = make(map[int32]*partitionOffsetManager) + om.poms[topic] = topicManagers + } + + if topicManagers[partition] != nil { + return nil, ConfigurationError("That topic/partition is already being managed") + } + + topicManagers[partition] = pom + return pom, nil +} + +func (om *offsetManager) Close() error { + return nil +} + +func (om *offsetManager) refBrokerOffsetManager(broker *Broker) *brokerOffsetManager { + om.lock.Lock() + defer om.lock.Unlock() + + bom := om.boms[broker] + if bom == nil { + bom = om.newBrokerOffsetManager(broker) + om.boms[broker] = bom + } + + bom.refs++ + + return bom +} + +func (om *offsetManager) unrefBrokerOffsetManager(bom *brokerOffsetManager) { + om.lock.Lock() + defer om.lock.Unlock() + + bom.refs-- + + if bom.refs == 0 { + close(bom.updateSubscriptions) + if om.boms[bom.broker] == bom { + delete(om.boms, bom.broker) + } + } +} + +func (om *offsetManager) abandonBroker(bom *brokerOffsetManager) { + om.lock.Lock() + defer om.lock.Unlock() + + delete(om.boms, bom.broker) +} + +func (om *offsetManager) abandonPartitionOffsetManager(pom *partitionOffsetManager) { + om.lock.Lock() + defer om.lock.Unlock() + + delete(om.poms[pom.topic], pom.partition) + if len(om.poms[pom.topic]) == 0 { + delete(om.poms, pom.topic) + } +} + +// Partition Offset Manager + +// PartitionOffsetManager uses Kafka to store and fetch consumed partition offsets. You MUST call Close() +// on a partition offset manager to avoid leaks, it will not be garbage-collected automatically when it passes +// out of scope. +type PartitionOffsetManager interface { + // NextOffset returns the next offset that should be consumed for the managed + // partition, accompanied by metadata which can be used to reconstruct the state + // of the partition consumer when it resumes. NextOffset() will return + // `config.Consumer.Offsets.Initial` and an empty metadata string if no offset + // was committed for this partition yet. + NextOffset() (int64, string) + + // MarkOffset marks the provided offset, alongside a metadata string + // that represents the state of the partition consumer at that point in time. The + // metadata string can be used by another consumer to restore that state, so it + // can resume consumption. + // + // To follow upstream conventions, you are expected to mark the offset of the + // next message to read, not the last message read. Thus, when calling `MarkOffset` + // you should typically add one to the offset of the last consumed message. + // + // Note: calling MarkOffset does not necessarily commit the offset to the backend + // store immediately for efficiency reasons, and it may never be committed if + // your application crashes. This means that you may end up processing the same + // message twice, and your processing should ideally be idempotent. + MarkOffset(offset int64, metadata string) + + // Errors returns a read channel of errors that occur during offset management, if + // enabled. By default, errors are logged and not returned over this channel. If + // you want to implement any custom error handling, set your config's + // Consumer.Return.Errors setting to true, and read from this channel. + Errors() <-chan *ConsumerError + + // AsyncClose initiates a shutdown of the PartitionOffsetManager. This method will + // return immediately, after which you should wait until the 'errors' channel has + // been drained and closed. It is required to call this function, or Close before + // a consumer object passes out of scope, as it will otherwise leak memory. You + // must call this before calling Close on the underlying client. + AsyncClose() + + // Close stops the PartitionOffsetManager from managing offsets. It is required to + // call this function (or AsyncClose) before a PartitionOffsetManager object + // passes out of scope, as it will otherwise leak memory. You must call this + // before calling Close on the underlying client. + Close() error +} + +type partitionOffsetManager struct { + parent *offsetManager + topic string + partition int32 + + lock sync.Mutex + offset int64 + metadata string + dirty bool + clean sync.Cond + broker *brokerOffsetManager + + errors chan *ConsumerError + rebalance chan none + dying chan none +} + +func (om *offsetManager) newPartitionOffsetManager(topic string, partition int32) (*partitionOffsetManager, error) { + pom := &partitionOffsetManager{ + parent: om, + topic: topic, + partition: partition, + errors: make(chan *ConsumerError, om.conf.ChannelBufferSize), + rebalance: make(chan none, 1), + dying: make(chan none), + } + pom.clean.L = &pom.lock + + if err := pom.selectBroker(); err != nil { + return nil, err + } + + if err := pom.fetchInitialOffset(om.conf.Metadata.Retry.Max); err != nil { + return nil, err + } + + pom.broker.updateSubscriptions <- pom + + go withRecover(pom.mainLoop) + + return pom, nil +} + +func (pom *partitionOffsetManager) mainLoop() { + for { + select { + case <-pom.rebalance: + if err := pom.selectBroker(); err != nil { + pom.handleError(err) + pom.rebalance <- none{} + } else { + pom.broker.updateSubscriptions <- pom + } + case <-pom.dying: + if pom.broker != nil { + select { + case <-pom.rebalance: + case pom.broker.updateSubscriptions <- pom: + } + pom.parent.unrefBrokerOffsetManager(pom.broker) + } + pom.parent.abandonPartitionOffsetManager(pom) + close(pom.errors) + return + } + } +} + +func (pom *partitionOffsetManager) selectBroker() error { + if pom.broker != nil { + pom.parent.unrefBrokerOffsetManager(pom.broker) + pom.broker = nil + } + + var broker *Broker + var err error + + if err = pom.parent.client.RefreshCoordinator(pom.parent.group); err != nil { + return err + } + + if broker, err = pom.parent.client.Coordinator(pom.parent.group); err != nil { + return err + } + + pom.broker = pom.parent.refBrokerOffsetManager(broker) + return nil +} + +func (pom *partitionOffsetManager) fetchInitialOffset(retries int) error { + request := new(OffsetFetchRequest) + request.Version = 1 + request.ConsumerGroup = pom.parent.group + request.AddPartition(pom.topic, pom.partition) + + response, err := pom.broker.broker.FetchOffset(request) + if err != nil { + return err + } + + block := response.GetBlock(pom.topic, pom.partition) + if block == nil { + return ErrIncompleteResponse + } + + switch block.Err { + case ErrNoError: + pom.offset = block.Offset + pom.metadata = block.Metadata + return nil + case ErrNotCoordinatorForConsumer: + if retries <= 0 { + return block.Err + } + if err := pom.selectBroker(); err != nil { + return err + } + return pom.fetchInitialOffset(retries - 1) + case ErrOffsetsLoadInProgress: + if retries <= 0 { + return block.Err + } + time.Sleep(pom.parent.conf.Metadata.Retry.Backoff) + return pom.fetchInitialOffset(retries - 1) + default: + return block.Err + } +} + +func (pom *partitionOffsetManager) handleError(err error) { + cErr := &ConsumerError{ + Topic: pom.topic, + Partition: pom.partition, + Err: err, + } + + if pom.parent.conf.Consumer.Return.Errors { + pom.errors <- cErr + } else { + Logger.Println(cErr) + } +} + +func (pom *partitionOffsetManager) Errors() <-chan *ConsumerError { + return pom.errors +} + +func (pom *partitionOffsetManager) MarkOffset(offset int64, metadata string) { + pom.lock.Lock() + defer pom.lock.Unlock() + + if offset > pom.offset { + pom.offset = offset + pom.metadata = metadata + pom.dirty = true + } +} + +func (pom *partitionOffsetManager) updateCommitted(offset int64, metadata string) { + pom.lock.Lock() + defer pom.lock.Unlock() + + if pom.offset == offset && pom.metadata == metadata { + pom.dirty = false + pom.clean.Signal() + } +} + +func (pom *partitionOffsetManager) NextOffset() (int64, string) { + pom.lock.Lock() + defer pom.lock.Unlock() + + if pom.offset >= 0 { + return pom.offset, pom.metadata + } + + return pom.parent.conf.Consumer.Offsets.Initial, "" +} + +func (pom *partitionOffsetManager) AsyncClose() { + go func() { + pom.lock.Lock() + defer pom.lock.Unlock() + + for pom.dirty { + pom.clean.Wait() + } + + close(pom.dying) + }() +} + +func (pom *partitionOffsetManager) Close() error { + pom.AsyncClose() + + var errors ConsumerErrors + for err := range pom.errors { + errors = append(errors, err) + } + + if len(errors) > 0 { + return errors + } + return nil +} + +// Broker Offset Manager + +type brokerOffsetManager struct { + parent *offsetManager + broker *Broker + timer *time.Ticker + updateSubscriptions chan *partitionOffsetManager + subscriptions map[*partitionOffsetManager]none + refs int +} + +func (om *offsetManager) newBrokerOffsetManager(broker *Broker) *brokerOffsetManager { + bom := &brokerOffsetManager{ + parent: om, + broker: broker, + timer: time.NewTicker(om.conf.Consumer.Offsets.CommitInterval), + updateSubscriptions: make(chan *partitionOffsetManager), + subscriptions: make(map[*partitionOffsetManager]none), + } + + go withRecover(bom.mainLoop) + + return bom +} + +func (bom *brokerOffsetManager) mainLoop() { + for { + select { + case <-bom.timer.C: + if len(bom.subscriptions) > 0 { + bom.flushToBroker() + } + case s, ok := <-bom.updateSubscriptions: + if !ok { + bom.timer.Stop() + return + } + if _, ok := bom.subscriptions[s]; ok { + delete(bom.subscriptions, s) + } else { + bom.subscriptions[s] = none{} + } + } + } +} + +func (bom *brokerOffsetManager) flushToBroker() { + request := bom.constructRequest() + if request == nil { + return + } + + response, err := bom.broker.CommitOffset(request) + + if err != nil { + bom.abort(err) + return + } + + for s := range bom.subscriptions { + if request.blocks[s.topic] == nil || request.blocks[s.topic][s.partition] == nil { + continue + } + + var err KError + var ok bool + + if response.Errors[s.topic] == nil { + s.handleError(ErrIncompleteResponse) + delete(bom.subscriptions, s) + s.rebalance <- none{} + continue + } + if err, ok = response.Errors[s.topic][s.partition]; !ok { + s.handleError(ErrIncompleteResponse) + delete(bom.subscriptions, s) + s.rebalance <- none{} + continue + } + + switch err { + case ErrNoError: + block := request.blocks[s.topic][s.partition] + s.updateCommitted(block.offset, block.metadata) + case ErrNotLeaderForPartition, ErrLeaderNotAvailable, + ErrConsumerCoordinatorNotAvailable, ErrNotCoordinatorForConsumer: + // not a critical error, we just need to redispatch + delete(bom.subscriptions, s) + s.rebalance <- none{} + case ErrOffsetMetadataTooLarge, ErrInvalidCommitOffsetSize: + // nothing we can do about this, just tell the user and carry on + s.handleError(err) + case ErrOffsetsLoadInProgress: + // nothing wrong but we didn't commit, we'll get it next time round + break + case ErrUnknownTopicOrPartition: + // let the user know *and* try redispatching - if topic-auto-create is + // enabled, redispatching should trigger a metadata request and create the + // topic; if not then re-dispatching won't help, but we've let the user + // know and it shouldn't hurt either (see https://github.com/Shopify/sarama/issues/706) + fallthrough + default: + // dunno, tell the user and try redispatching + s.handleError(err) + delete(bom.subscriptions, s) + s.rebalance <- none{} + } + } +} + +func (bom *brokerOffsetManager) constructRequest() *OffsetCommitRequest { + var r *OffsetCommitRequest + var perPartitionTimestamp int64 + if bom.parent.conf.Consumer.Offsets.Retention == 0 { + perPartitionTimestamp = ReceiveTime + r = &OffsetCommitRequest{ + Version: 1, + ConsumerGroup: bom.parent.group, + ConsumerGroupGeneration: GroupGenerationUndefined, + } + } else { + r = &OffsetCommitRequest{ + Version: 2, + RetentionTime: int64(bom.parent.conf.Consumer.Offsets.Retention / time.Millisecond), + ConsumerGroup: bom.parent.group, + ConsumerGroupGeneration: GroupGenerationUndefined, + } + + } + + for s := range bom.subscriptions { + s.lock.Lock() + if s.dirty { + r.AddBlock(s.topic, s.partition, s.offset, perPartitionTimestamp, s.metadata) + } + s.lock.Unlock() + } + + if len(r.blocks) > 0 { + return r + } + + return nil +} + +func (bom *brokerOffsetManager) abort(err error) { + _ = bom.broker.Close() // we don't care about the error this might return, we already have one + bom.parent.abandonBroker(bom) + + for pom := range bom.subscriptions { + pom.handleError(err) + pom.rebalance <- none{} + } + + for s := range bom.updateSubscriptions { + if _, ok := bom.subscriptions[s]; !ok { + s.handleError(err) + s.rebalance <- none{} + } + } + + bom.subscriptions = make(map[*partitionOffsetManager]none) +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_manager_test.go b/vendor/src/github.com/Shopify/sarama/offset_manager_test.go new file mode 100644 index 00000000..c111a5a6 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_manager_test.go @@ -0,0 +1,369 @@ +package sarama + +import ( + "testing" + "time" +) + +func initOffsetManager(t *testing.T) (om OffsetManager, + testClient Client, broker, coordinator *MockBroker) { + + config := NewConfig() + config.Metadata.Retry.Max = 1 + config.Consumer.Offsets.CommitInterval = 1 * time.Millisecond + config.Version = V0_9_0_0 + + broker = NewMockBroker(t, 1) + coordinator = NewMockBroker(t, 2) + + seedMeta := new(MetadataResponse) + seedMeta.AddBroker(coordinator.Addr(), coordinator.BrokerID()) + seedMeta.AddTopicPartition("my_topic", 0, 1, []int32{}, []int32{}, ErrNoError) + seedMeta.AddTopicPartition("my_topic", 1, 1, []int32{}, []int32{}, ErrNoError) + broker.Returns(seedMeta) + + var err error + testClient, err = NewClient([]string{broker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: coordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: coordinator.Port(), + }) + + om, err = NewOffsetManagerFromClient("group", testClient) + if err != nil { + t.Fatal(err) + } + + return om, testClient, broker, coordinator +} + +func initPartitionOffsetManager(t *testing.T, om OffsetManager, + coordinator *MockBroker, initialOffset int64, metadata string) PartitionOffsetManager { + + fetchResponse := new(OffsetFetchResponse) + fetchResponse.AddBlock("my_topic", 0, &OffsetFetchResponseBlock{ + Err: ErrNoError, + Offset: initialOffset, + Metadata: metadata, + }) + coordinator.Returns(fetchResponse) + + pom, err := om.ManagePartition("my_topic", 0) + if err != nil { + t.Fatal(err) + } + + return pom +} + +func TestNewOffsetManager(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + seedBroker.Returns(new(MetadataResponse)) + + testClient, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + _, err = NewOffsetManagerFromClient("group", testClient) + if err != nil { + t.Error(err) + } + + safeClose(t, testClient) + + _, err = NewOffsetManagerFromClient("group", testClient) + if err != ErrClosedClient { + t.Errorf("Error expected for closed client; actual value: %v", err) + } + + seedBroker.Close() +} + +// Test recovery from ErrNotCoordinatorForConsumer +// on first fetchInitialOffset call +func TestOffsetManagerFetchInitialFail(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + + // Error on first fetchInitialOffset call + responseBlock := OffsetFetchResponseBlock{ + Err: ErrNotCoordinatorForConsumer, + Offset: 5, + Metadata: "test_meta", + } + + fetchResponse := new(OffsetFetchResponse) + fetchResponse.AddBlock("my_topic", 0, &responseBlock) + coordinator.Returns(fetchResponse) + + // Refresh coordinator + newCoordinator := NewMockBroker(t, 3) + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + // Second fetchInitialOffset call is fine + fetchResponse2 := new(OffsetFetchResponse) + responseBlock2 := responseBlock + responseBlock2.Err = ErrNoError + fetchResponse2.AddBlock("my_topic", 0, &responseBlock2) + newCoordinator.Returns(fetchResponse2) + + pom, err := om.ManagePartition("my_topic", 0) + if err != nil { + t.Error(err) + } + + broker.Close() + coordinator.Close() + newCoordinator.Close() + safeClose(t, pom) + safeClose(t, om) + safeClose(t, testClient) +} + +// Test fetchInitialOffset retry on ErrOffsetsLoadInProgress +func TestOffsetManagerFetchInitialLoadInProgress(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + + // Error on first fetchInitialOffset call + responseBlock := OffsetFetchResponseBlock{ + Err: ErrOffsetsLoadInProgress, + Offset: 5, + Metadata: "test_meta", + } + + fetchResponse := new(OffsetFetchResponse) + fetchResponse.AddBlock("my_topic", 0, &responseBlock) + coordinator.Returns(fetchResponse) + + // Second fetchInitialOffset call is fine + fetchResponse2 := new(OffsetFetchResponse) + responseBlock2 := responseBlock + responseBlock2.Err = ErrNoError + fetchResponse2.AddBlock("my_topic", 0, &responseBlock2) + coordinator.Returns(fetchResponse2) + + pom, err := om.ManagePartition("my_topic", 0) + if err != nil { + t.Error(err) + } + + broker.Close() + coordinator.Close() + safeClose(t, pom) + safeClose(t, om) + safeClose(t, testClient) +} + +func TestPartitionOffsetManagerInitialOffset(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + testClient.Config().Consumer.Offsets.Initial = OffsetOldest + + // Kafka returns -1 if no offset has been stored for this partition yet. + pom := initPartitionOffsetManager(t, om, coordinator, -1, "") + + offset, meta := pom.NextOffset() + if offset != OffsetOldest { + t.Errorf("Expected offset 5. Actual: %v", offset) + } + if meta != "" { + t.Errorf("Expected metadata to be empty. Actual: %q", meta) + } + + safeClose(t, pom) + safeClose(t, om) + broker.Close() + coordinator.Close() + safeClose(t, testClient) +} + +func TestPartitionOffsetManagerNextOffset(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + pom := initPartitionOffsetManager(t, om, coordinator, 5, "test_meta") + + offset, meta := pom.NextOffset() + if offset != 5 { + t.Errorf("Expected offset 5. Actual: %v", offset) + } + if meta != "test_meta" { + t.Errorf("Expected metadata \"test_meta\". Actual: %q", meta) + } + + safeClose(t, pom) + safeClose(t, om) + broker.Close() + coordinator.Close() + safeClose(t, testClient) +} + +func TestPartitionOffsetManagerMarkOffset(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + pom := initPartitionOffsetManager(t, om, coordinator, 5, "original_meta") + + ocResponse := new(OffsetCommitResponse) + ocResponse.AddError("my_topic", 0, ErrNoError) + coordinator.Returns(ocResponse) + + pom.MarkOffset(100, "modified_meta") + offset, meta := pom.NextOffset() + + if offset != 100 { + t.Errorf("Expected offset 100. Actual: %v", offset) + } + if meta != "modified_meta" { + t.Errorf("Expected metadata \"modified_meta\". Actual: %q", meta) + } + + safeClose(t, pom) + safeClose(t, om) + safeClose(t, testClient) + broker.Close() + coordinator.Close() +} + +func TestPartitionOffsetManagerMarkOffsetWithRetention(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + testClient.Config().Consumer.Offsets.Retention = time.Hour + + pom := initPartitionOffsetManager(t, om, coordinator, 5, "original_meta") + + ocResponse := new(OffsetCommitResponse) + ocResponse.AddError("my_topic", 0, ErrNoError) + handler := func(req *request) (res encoder) { + if req.body.version() != 2 { + t.Errorf("Expected to be using version 2. Actual: %v", req.body.version()) + } + offsetCommitRequest := req.body.(*OffsetCommitRequest) + if offsetCommitRequest.RetentionTime != (60 * 60 * 1000) { + t.Errorf("Expected an hour retention time. Actual: %v", offsetCommitRequest.RetentionTime) + } + return ocResponse + } + coordinator.setHandler(handler) + + pom.MarkOffset(100, "modified_meta") + offset, meta := pom.NextOffset() + + if offset != 100 { + t.Errorf("Expected offset 100. Actual: %v", offset) + } + if meta != "modified_meta" { + t.Errorf("Expected metadata \"modified_meta\". Actual: %q", meta) + } + + safeClose(t, pom) + safeClose(t, om) + safeClose(t, testClient) + broker.Close() + coordinator.Close() +} + +func TestPartitionOffsetManagerCommitErr(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + pom := initPartitionOffsetManager(t, om, coordinator, 5, "meta") + + // Error on one partition + ocResponse := new(OffsetCommitResponse) + ocResponse.AddError("my_topic", 0, ErrOffsetOutOfRange) + ocResponse.AddError("my_topic", 1, ErrNoError) + coordinator.Returns(ocResponse) + + newCoordinator := NewMockBroker(t, 3) + + // For RefreshCoordinator() + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + // Nothing in response.Errors at all + ocResponse2 := new(OffsetCommitResponse) + newCoordinator.Returns(ocResponse2) + + // For RefreshCoordinator() + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + // Error on the wrong partition for this pom + ocResponse3 := new(OffsetCommitResponse) + ocResponse3.AddError("my_topic", 1, ErrNoError) + newCoordinator.Returns(ocResponse3) + + // For RefreshCoordinator() + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + // ErrUnknownTopicOrPartition/ErrNotLeaderForPartition/ErrLeaderNotAvailable block + ocResponse4 := new(OffsetCommitResponse) + ocResponse4.AddError("my_topic", 0, ErrUnknownTopicOrPartition) + newCoordinator.Returns(ocResponse4) + + // For RefreshCoordinator() + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + // Normal error response + ocResponse5 := new(OffsetCommitResponse) + ocResponse5.AddError("my_topic", 0, ErrNoError) + newCoordinator.Returns(ocResponse5) + + pom.MarkOffset(100, "modified_meta") + + err := pom.Close() + if err != nil { + t.Error(err) + } + + broker.Close() + coordinator.Close() + newCoordinator.Close() + safeClose(t, om) + safeClose(t, testClient) +} + +// Test of recovery from abort +func TestAbortPartitionOffsetManager(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + pom := initPartitionOffsetManager(t, om, coordinator, 5, "meta") + + // this triggers an error in the CommitOffset request, + // which leads to the abort call + coordinator.Close() + + // Response to refresh coordinator request + newCoordinator := NewMockBroker(t, 3) + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + ocResponse := new(OffsetCommitResponse) + ocResponse.AddError("my_topic", 0, ErrNoError) + newCoordinator.Returns(ocResponse) + + pom.MarkOffset(100, "modified_meta") + + safeClose(t, pom) + safeClose(t, om) + broker.Close() + safeClose(t, testClient) +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_request.go b/vendor/src/github.com/Shopify/sarama/offset_request.go new file mode 100644 index 00000000..6c269601 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_request.go @@ -0,0 +1,132 @@ +package sarama + +type offsetRequestBlock struct { + time int64 + maxOffsets int32 // Only used in version 0 +} + +func (b *offsetRequestBlock) encode(pe packetEncoder, version int16) error { + pe.putInt64(int64(b.time)) + if version == 0 { + pe.putInt32(b.maxOffsets) + } + + return nil +} + +func (b *offsetRequestBlock) decode(pd packetDecoder, version int16) (err error) { + if b.time, err = pd.getInt64(); err != nil { + return err + } + if version == 0 { + if b.maxOffsets, err = pd.getInt32(); err != nil { + return err + } + } + return nil +} + +type OffsetRequest struct { + Version int16 + blocks map[string]map[int32]*offsetRequestBlock +} + +func (r *OffsetRequest) encode(pe packetEncoder) error { + pe.putInt32(-1) // replica ID is always -1 for clients + err := pe.putArrayLength(len(r.blocks)) + if err != nil { + return err + } + for topic, partitions := range r.blocks { + err = pe.putString(topic) + if err != nil { + return err + } + err = pe.putArrayLength(len(partitions)) + if err != nil { + return err + } + for partition, block := range partitions { + pe.putInt32(partition) + if err = block.encode(pe, r.Version); err != nil { + return err + } + } + } + return nil +} + +func (r *OffsetRequest) decode(pd packetDecoder, version int16) error { + r.Version = version + + // Ignore replica ID + if _, err := pd.getInt32(); err != nil { + return err + } + blockCount, err := pd.getArrayLength() + if err != nil { + return err + } + if blockCount == 0 { + return nil + } + r.blocks = make(map[string]map[int32]*offsetRequestBlock) + for i := 0; i < blockCount; i++ { + topic, err := pd.getString() + if err != nil { + return err + } + partitionCount, err := pd.getArrayLength() + if err != nil { + return err + } + r.blocks[topic] = make(map[int32]*offsetRequestBlock) + for j := 0; j < partitionCount; j++ { + partition, err := pd.getInt32() + if err != nil { + return err + } + block := &offsetRequestBlock{} + if err := block.decode(pd, version); err != nil { + return err + } + r.blocks[topic][partition] = block + } + } + return nil +} + +func (r *OffsetRequest) key() int16 { + return 2 +} + +func (r *OffsetRequest) version() int16 { + return r.Version +} + +func (r *OffsetRequest) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_10_1_0 + default: + return minVersion + } +} + +func (r *OffsetRequest) AddBlock(topic string, partitionID int32, time int64, maxOffsets int32) { + if r.blocks == nil { + r.blocks = make(map[string]map[int32]*offsetRequestBlock) + } + + if r.blocks[topic] == nil { + r.blocks[topic] = make(map[int32]*offsetRequestBlock) + } + + tmp := new(offsetRequestBlock) + tmp.time = time + if r.Version == 0 { + tmp.maxOffsets = maxOffsets + } + + r.blocks[topic][partitionID] = tmp +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_request_test.go b/vendor/src/github.com/Shopify/sarama/offset_request_test.go new file mode 100644 index 00000000..9ce562c9 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_request_test.go @@ -0,0 +1,43 @@ +package sarama + +import "testing" + +var ( + offsetRequestNoBlocks = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00} + + offsetRequestOneBlock = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x03, 'f', 'o', 'o', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02} + + offsetRequestOneBlockV1 = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x03, 'b', 'a', 'r', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} +) + +func TestOffsetRequest(t *testing.T) { + request := new(OffsetRequest) + testRequest(t, "no blocks", request, offsetRequestNoBlocks) + + request.AddBlock("foo", 4, 1, 2) + testRequest(t, "one block", request, offsetRequestOneBlock) +} + +func TestOffsetRequestV1(t *testing.T) { + request := new(OffsetRequest) + request.Version = 1 + testRequest(t, "no blocks", request, offsetRequestNoBlocks) + + request.AddBlock("bar", 4, 1, 2) // Last argument is ignored for V1 + testRequest(t, "one block", request, offsetRequestOneBlockV1) +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_response.go b/vendor/src/github.com/Shopify/sarama/offset_response.go new file mode 100644 index 00000000..9a9cfe96 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_response.go @@ -0,0 +1,174 @@ +package sarama + +type OffsetResponseBlock struct { + Err KError + Offsets []int64 // Version 0 + Offset int64 // Version 1 + Timestamp int64 // Version 1 +} + +func (b *OffsetResponseBlock) decode(pd packetDecoder, version int16) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + b.Err = KError(tmp) + + if version == 0 { + b.Offsets, err = pd.getInt64Array() + + return err + } + + b.Timestamp, err = pd.getInt64() + if err != nil { + return err + } + + b.Offset, err = pd.getInt64() + if err != nil { + return err + } + + // For backwards compatibility put the offset in the offsets array too + b.Offsets = []int64{b.Offset} + + return nil +} + +func (b *OffsetResponseBlock) encode(pe packetEncoder, version int16) (err error) { + pe.putInt16(int16(b.Err)) + + if version == 0 { + return pe.putInt64Array(b.Offsets) + } + + pe.putInt64(b.Timestamp) + pe.putInt64(b.Offset) + + return nil +} + +type OffsetResponse struct { + Version int16 + Blocks map[string]map[int32]*OffsetResponseBlock +} + +func (r *OffsetResponse) decode(pd packetDecoder, version int16) (err error) { + numTopics, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks = make(map[string]map[int32]*OffsetResponseBlock, numTopics) + for i := 0; i < numTopics; i++ { + name, err := pd.getString() + if err != nil { + return err + } + + numBlocks, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks[name] = make(map[int32]*OffsetResponseBlock, numBlocks) + + for j := 0; j < numBlocks; j++ { + id, err := pd.getInt32() + if err != nil { + return err + } + + block := new(OffsetResponseBlock) + err = block.decode(pd, version) + if err != nil { + return err + } + r.Blocks[name][id] = block + } + } + + return nil +} + +func (r *OffsetResponse) GetBlock(topic string, partition int32) *OffsetResponseBlock { + if r.Blocks == nil { + return nil + } + + if r.Blocks[topic] == nil { + return nil + } + + return r.Blocks[topic][partition] +} + +/* +// [0 0 0 1 ntopics +0 8 109 121 95 116 111 112 105 99 topic +0 0 0 1 npartitions +0 0 0 0 id +0 0 + +0 0 0 1 0 0 0 0 +0 1 1 1 0 0 0 1 +0 8 109 121 95 116 111 112 +105 99 0 0 0 1 0 0 +0 0 0 0 0 0 0 1 +0 0 0 0 0 1 1 1] + +*/ +func (r *OffsetResponse) encode(pe packetEncoder) (err error) { + if err = pe.putArrayLength(len(r.Blocks)); err != nil { + return err + } + + for topic, partitions := range r.Blocks { + if err = pe.putString(topic); err != nil { + return err + } + if err = pe.putArrayLength(len(partitions)); err != nil { + return err + } + for partition, block := range partitions { + pe.putInt32(partition) + if err = block.encode(pe, r.version()); err != nil { + return err + } + } + } + + return nil +} + +func (r *OffsetResponse) key() int16 { + return 2 +} + +func (r *OffsetResponse) version() int16 { + return r.Version +} + +func (r *OffsetResponse) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_10_1_0 + default: + return minVersion + } +} + +// testing API + +func (r *OffsetResponse) AddTopicPartition(topic string, partition int32, offset int64) { + if r.Blocks == nil { + r.Blocks = make(map[string]map[int32]*OffsetResponseBlock) + } + byTopic, ok := r.Blocks[topic] + if !ok { + byTopic = make(map[int32]*OffsetResponseBlock) + r.Blocks[topic] = byTopic + } + byTopic[partition] = &OffsetResponseBlock{Offsets: []int64{offset}, Offset: offset} +} diff --git a/vendor/src/github.com/Shopify/sarama/offset_response_test.go b/vendor/src/github.com/Shopify/sarama/offset_response_test.go new file mode 100644 index 00000000..0df6c9f3 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/offset_response_test.go @@ -0,0 +1,111 @@ +package sarama + +import "testing" + +var ( + emptyOffsetResponse = []byte{ + 0x00, 0x00, 0x00, 0x00} + + normalOffsetResponse = []byte{ + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x01, 'a', + 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x01, 'z', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06} + + normalOffsetResponseV1 = []byte{ + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x01, 'a', + 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x01, 'z', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, + 0x00, 0x00, 0x01, 0x58, 0x1A, 0xE6, 0x48, 0x86, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06} +) + +func TestEmptyOffsetResponse(t *testing.T) { + response := OffsetResponse{} + + testVersionDecodable(t, "empty", &response, emptyOffsetResponse, 0) + if len(response.Blocks) != 0 { + t.Error("Decoding produced", len(response.Blocks), "topics where there were none.") + } + + response = OffsetResponse{} + + testVersionDecodable(t, "empty", &response, emptyOffsetResponse, 1) + if len(response.Blocks) != 0 { + t.Error("Decoding produced", len(response.Blocks), "topics where there were none.") + } +} + +func TestNormalOffsetResponse(t *testing.T) { + response := OffsetResponse{} + + testVersionDecodable(t, "normal", &response, normalOffsetResponse, 0) + + if len(response.Blocks) != 2 { + t.Fatal("Decoding produced", len(response.Blocks), "topics where there were two.") + } + + if len(response.Blocks["a"]) != 0 { + t.Fatal("Decoding produced", len(response.Blocks["a"]), "partitions for topic 'a' where there were none.") + } + + if len(response.Blocks["z"]) != 1 { + t.Fatal("Decoding produced", len(response.Blocks["z"]), "partitions for topic 'z' where there was one.") + } + + if response.Blocks["z"][2].Err != ErrNoError { + t.Fatal("Decoding produced invalid error for topic z partition 2.") + } + + if len(response.Blocks["z"][2].Offsets) != 2 { + t.Fatal("Decoding produced invalid number of offsets for topic z partition 2.") + } + + if response.Blocks["z"][2].Offsets[0] != 5 || response.Blocks["z"][2].Offsets[1] != 6 { + t.Fatal("Decoding produced invalid offsets for topic z partition 2.") + } +} + +func TestNormalOffsetResponseV1(t *testing.T) { + response := OffsetResponse{} + + testVersionDecodable(t, "normal", &response, normalOffsetResponseV1, 1) + + if len(response.Blocks) != 2 { + t.Fatal("Decoding produced", len(response.Blocks), "topics where there were two.") + } + + if len(response.Blocks["a"]) != 0 { + t.Fatal("Decoding produced", len(response.Blocks["a"]), "partitions for topic 'a' where there were none.") + } + + if len(response.Blocks["z"]) != 1 { + t.Fatal("Decoding produced", len(response.Blocks["z"]), "partitions for topic 'z' where there was one.") + } + + if response.Blocks["z"][2].Err != ErrNoError { + t.Fatal("Decoding produced invalid error for topic z partition 2.") + } + + if response.Blocks["z"][2].Timestamp != 1477920049286 { + t.Fatal("Decoding produced invalid timestamp for topic z partition 2.", response.Blocks["z"][2].Timestamp) + } + + if response.Blocks["z"][2].Offset != 6 { + t.Fatal("Decoding produced invalid offsets for topic z partition 2.") + } +} diff --git a/vendor/src/github.com/Shopify/sarama/packet_decoder.go b/vendor/src/github.com/Shopify/sarama/packet_decoder.go new file mode 100644 index 00000000..28670c0e --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/packet_decoder.go @@ -0,0 +1,45 @@ +package sarama + +// PacketDecoder is the interface providing helpers for reading with Kafka's encoding rules. +// Types implementing Decoder only need to worry about calling methods like GetString, +// not about how a string is represented in Kafka. +type packetDecoder interface { + // Primitives + getInt8() (int8, error) + getInt16() (int16, error) + getInt32() (int32, error) + getInt64() (int64, error) + getArrayLength() (int, error) + + // Collections + getBytes() ([]byte, error) + getString() (string, error) + getInt32Array() ([]int32, error) + getInt64Array() ([]int64, error) + getStringArray() ([]string, error) + + // Subsets + remaining() int + getSubset(length int) (packetDecoder, error) + + // Stacks, see PushDecoder + push(in pushDecoder) error + pop() error +} + +// PushDecoder is the interface for decoding fields like CRCs and lengths where the validity +// of the field depends on what is after it in the packet. Start them with PacketDecoder.Push() where +// the actual value is located in the packet, then PacketDecoder.Pop() them when all the bytes they +// depend upon have been decoded. +type pushDecoder interface { + // Saves the offset into the input buffer as the location to actually read the calculated value when able. + saveOffset(in int) + + // Returns the length of data to reserve for the input of this encoder (eg 4 bytes for a CRC32). + reserveLength() int + + // Indicates that all required data is now available to calculate and check the field. + // SaveOffset is guaranteed to have been called first. The implementation should read ReserveLength() bytes + // of data from the saved offset, and verify it based on the data between the saved offset and curOffset. + check(curOffset int, buf []byte) error +} diff --git a/vendor/src/github.com/Shopify/sarama/packet_encoder.go b/vendor/src/github.com/Shopify/sarama/packet_encoder.go new file mode 100644 index 00000000..27a10f6d --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/packet_encoder.go @@ -0,0 +1,50 @@ +package sarama + +import "github.com/rcrowley/go-metrics" + +// PacketEncoder is the interface providing helpers for writing with Kafka's encoding rules. +// Types implementing Encoder only need to worry about calling methods like PutString, +// not about how a string is represented in Kafka. +type packetEncoder interface { + // Primitives + putInt8(in int8) + putInt16(in int16) + putInt32(in int32) + putInt64(in int64) + putArrayLength(in int) error + + // Collections + putBytes(in []byte) error + putRawBytes(in []byte) error + putString(in string) error + putStringArray(in []string) error + putInt32Array(in []int32) error + putInt64Array(in []int64) error + + // Provide the current offset to record the batch size metric + offset() int + + // Stacks, see PushEncoder + push(in pushEncoder) + pop() error + + // To record metrics when provided + metricRegistry() metrics.Registry +} + +// PushEncoder is the interface for encoding fields like CRCs and lengths where the value +// of the field depends on what is encoded after it in the packet. Start them with PacketEncoder.Push() where +// the actual value is located in the packet, then PacketEncoder.Pop() them when all the bytes they +// depend upon have been written. +type pushEncoder interface { + // Saves the offset into the input buffer as the location to actually write the calculated value when able. + saveOffset(in int) + + // Returns the length of data to reserve for the output of this encoder (eg 4 bytes for a CRC32). + reserveLength() int + + // Indicates that all required data is now available to calculate and write the field. + // SaveOffset is guaranteed to have been called first. The implementation should write ReserveLength() bytes + // of data to the saved offset, based on the data between the saved offset and curOffset. + run(curOffset int, buf []byte) error +} diff --git a/vendor/src/github.com/Shopify/sarama/partitioner.go b/vendor/src/github.com/Shopify/sarama/partitioner.go new file mode 100644 index 00000000..d24199da --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/partitioner.go @@ -0,0 +1,123 @@ +package sarama + +import ( + "hash" + "hash/fnv" + "math/rand" + "time" +) + +// Partitioner is anything that, given a Kafka message and a number of partitions indexed [0...numPartitions-1], +// decides to which partition to send the message. RandomPartitioner, RoundRobinPartitioner and HashPartitioner are provided +// as simple default implementations. +type Partitioner interface { + // Partition takes a message and partition count and chooses a partition + Partition(message *ProducerMessage, numPartitions int32) (int32, error) + + // RequiresConsistency indicates to the user of the partitioner whether the + // mapping of key->partition is consistent or not. Specifically, if a + // partitioner requires consistency then it must be allowed to choose from all + // partitions (even ones known to be unavailable), and its choice must be + // respected by the caller. The obvious example is the HashPartitioner. + RequiresConsistency() bool +} + +// PartitionerConstructor is the type for a function capable of constructing new Partitioners. +type PartitionerConstructor func(topic string) Partitioner + +type manualPartitioner struct{} + +// NewManualPartitioner returns a Partitioner which uses the partition manually set in the provided +// ProducerMessage's Partition field as the partition to produce to. +func NewManualPartitioner(topic string) Partitioner { + return new(manualPartitioner) +} + +func (p *manualPartitioner) Partition(message *ProducerMessage, numPartitions int32) (int32, error) { + return message.Partition, nil +} + +func (p *manualPartitioner) RequiresConsistency() bool { + return true +} + +type randomPartitioner struct { + generator *rand.Rand +} + +// NewRandomPartitioner returns a Partitioner which chooses a random partition each time. +func NewRandomPartitioner(topic string) Partitioner { + p := new(randomPartitioner) + p.generator = rand.New(rand.NewSource(time.Now().UTC().UnixNano())) + return p +} + +func (p *randomPartitioner) Partition(message *ProducerMessage, numPartitions int32) (int32, error) { + return int32(p.generator.Intn(int(numPartitions))), nil +} + +func (p *randomPartitioner) RequiresConsistency() bool { + return false +} + +type roundRobinPartitioner struct { + partition int32 +} + +// NewRoundRobinPartitioner returns a Partitioner which walks through the available partitions one at a time. +func NewRoundRobinPartitioner(topic string) Partitioner { + return &roundRobinPartitioner{} +} + +func (p *roundRobinPartitioner) Partition(message *ProducerMessage, numPartitions int32) (int32, error) { + if p.partition >= numPartitions { + p.partition = 0 + } + ret := p.partition + p.partition++ + return ret, nil +} + +func (p *roundRobinPartitioner) RequiresConsistency() bool { + return false +} + +type hashPartitioner struct { + random Partitioner + hasher hash.Hash32 +} + +// NewHashPartitioner returns a Partitioner which behaves as follows. If the message's key is nil then a +// random partition is chosen. Otherwise the FNV-1a hash of the encoded bytes of the message key is used, +// modulus the number of partitions. This ensures that messages with the same key always end up on the +// same partition. +func NewHashPartitioner(topic string) Partitioner { + p := new(hashPartitioner) + p.random = NewRandomPartitioner(topic) + p.hasher = fnv.New32a() + return p +} + +func (p *hashPartitioner) Partition(message *ProducerMessage, numPartitions int32) (int32, error) { + if message.Key == nil { + return p.random.Partition(message, numPartitions) + } + bytes, err := message.Key.Encode() + if err != nil { + return -1, err + } + p.hasher.Reset() + _, err = p.hasher.Write(bytes) + if err != nil { + return -1, err + } + partition := int32(p.hasher.Sum32()) % numPartitions + if partition < 0 { + partition = -partition + } + return partition, nil +} + +func (p *hashPartitioner) RequiresConsistency() bool { + return true +} diff --git a/vendor/src/github.com/Shopify/sarama/partitioner_test.go b/vendor/src/github.com/Shopify/sarama/partitioner_test.go new file mode 100644 index 00000000..3d391c59 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/partitioner_test.go @@ -0,0 +1,215 @@ +package sarama + +import ( + "crypto/rand" + "log" + "testing" +) + +func assertPartitioningConsistent(t *testing.T, partitioner Partitioner, message *ProducerMessage, numPartitions int32) { + choice, err := partitioner.Partition(message, numPartitions) + if err != nil { + t.Error(partitioner, err) + } + if choice < 0 || choice >= numPartitions { + t.Error(partitioner, "returned partition", choice, "outside of range for", message) + } + for i := 1; i < 50; i++ { + newChoice, err := partitioner.Partition(message, numPartitions) + if err != nil { + t.Error(partitioner, err) + } + if newChoice != choice { + t.Error(partitioner, "returned partition", newChoice, "inconsistent with", choice, ".") + } + } +} + +func TestRandomPartitioner(t *testing.T) { + partitioner := NewRandomPartitioner("mytopic") + + choice, err := partitioner.Partition(nil, 1) + if err != nil { + t.Error(partitioner, err) + } + if choice != 0 { + t.Error("Returned non-zero partition when only one available.") + } + + for i := 1; i < 50; i++ { + choice, err := partitioner.Partition(nil, 50) + if err != nil { + t.Error(partitioner, err) + } + if choice < 0 || choice >= 50 { + t.Error("Returned partition", choice, "outside of range.") + } + } +} + +func TestRoundRobinPartitioner(t *testing.T) { + partitioner := NewRoundRobinPartitioner("mytopic") + + choice, err := partitioner.Partition(nil, 1) + if err != nil { + t.Error(partitioner, err) + } + if choice != 0 { + t.Error("Returned non-zero partition when only one available.") + } + + var i int32 + for i = 1; i < 50; i++ { + choice, err := partitioner.Partition(nil, 7) + if err != nil { + t.Error(partitioner, err) + } + if choice != i%7 { + t.Error("Returned partition", choice, "expecting", i%7) + } + } +} + +func TestHashPartitioner(t *testing.T) { + partitioner := NewHashPartitioner("mytopic") + + choice, err := partitioner.Partition(&ProducerMessage{}, 1) + if err != nil { + t.Error(partitioner, err) + } + if choice != 0 { + t.Error("Returned non-zero partition when only one available.") + } + + for i := 1; i < 50; i++ { + choice, err := partitioner.Partition(&ProducerMessage{}, 50) + if err != nil { + t.Error(partitioner, err) + } + if choice < 0 || choice >= 50 { + t.Error("Returned partition", choice, "outside of range for nil key.") + } + } + + buf := make([]byte, 256) + for i := 1; i < 50; i++ { + if _, err := rand.Read(buf); err != nil { + t.Error(err) + } + assertPartitioningConsistent(t, partitioner, &ProducerMessage{Key: ByteEncoder(buf)}, 50) + } +} + +func TestHashPartitionerMinInt32(t *testing.T) { + partitioner := NewHashPartitioner("mytopic") + + msg := ProducerMessage{} + // "1468509572224" generates 2147483648 (uint32) result from Sum32 function + // which is -2147483648 or int32's min value + msg.Key = StringEncoder("1468509572224") + + choice, err := partitioner.Partition(&msg, 50) + if err != nil { + t.Error(partitioner, err) + } + if choice < 0 || choice >= 50 { + t.Error("Returned partition", choice, "outside of range for nil key.") + } +} + +func TestManualPartitioner(t *testing.T) { + partitioner := NewManualPartitioner("mytopic") + + choice, err := partitioner.Partition(&ProducerMessage{}, 1) + if err != nil { + t.Error(partitioner, err) + } + if choice != 0 { + t.Error("Returned non-zero partition when only one available.") + } + + for i := int32(1); i < 50; i++ { + choice, err := partitioner.Partition(&ProducerMessage{Partition: i}, 50) + if err != nil { + t.Error(partitioner, err) + } + if choice != i { + t.Error("Returned partition not the same as the input partition") + } + } +} + +// By default, Sarama uses the message's key to consistently assign a partition to +// a message using hashing. If no key is set, a random partition will be chosen. +// This example shows how you can partition messages randomly, even when a key is set, +// by overriding Config.Producer.Partitioner. +func ExamplePartitioner_random() { + config := NewConfig() + config.Producer.Partitioner = NewRandomPartitioner + + producer, err := NewSyncProducer([]string{"localhost:9092"}, config) + if err != nil { + log.Fatal(err) + } + defer func() { + if err := producer.Close(); err != nil { + log.Println("Failed to close producer:", err) + } + }() + + msg := &ProducerMessage{Topic: "test", Key: StringEncoder("key is set"), Value: StringEncoder("test")} + partition, offset, err := producer.SendMessage(msg) + if err != nil { + log.Fatalln("Failed to produce message to kafka cluster.") + } + + log.Printf("Produced message to partition %d with offset %d", partition, offset) +} + +// This example shows how to assign partitions to your messages manually. +func ExamplePartitioner_manual() { + config := NewConfig() + + // First, we tell the producer that we are going to partition ourselves. + config.Producer.Partitioner = NewManualPartitioner + + producer, err := NewSyncProducer([]string{"localhost:9092"}, config) + if err != nil { + log.Fatal(err) + } + defer func() { + if err := producer.Close(); err != nil { + log.Println("Failed to close producer:", err) + } + }() + + // Now, we set the Partition field of the ProducerMessage struct. + msg := &ProducerMessage{Topic: "test", Partition: 6, Value: StringEncoder("test")} + + partition, offset, err := producer.SendMessage(msg) + if err != nil { + log.Fatalln("Failed to produce message to kafka cluster.") + } + + if partition != 6 { + log.Fatal("Message should have been produced to partition 6!") + } + + log.Printf("Produced message to partition %d with offset %d", partition, offset) +} + +// This example shows how to set a different partitioner depending on the topic. +func ExamplePartitioner_per_topic() { + config := NewConfig() + config.Producer.Partitioner = func(topic string) Partitioner { + switch topic { + case "access_log", "error_log": + return NewRandomPartitioner(topic) + + default: + return NewHashPartitioner(topic) + } + } + + // ... +} diff --git a/vendor/src/github.com/Shopify/sarama/prep_encoder.go b/vendor/src/github.com/Shopify/sarama/prep_encoder.go new file mode 100644 index 00000000..fd5ea0f9 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/prep_encoder.go @@ -0,0 +1,121 @@ +package sarama + +import ( + "fmt" + "math" + + "github.com/rcrowley/go-metrics" +) + +type prepEncoder struct { + length int +} + +// primitives + +func (pe *prepEncoder) putInt8(in int8) { + pe.length++ +} + +func (pe *prepEncoder) putInt16(in int16) { + pe.length += 2 +} + +func (pe *prepEncoder) putInt32(in int32) { + pe.length += 4 +} + +func (pe *prepEncoder) putInt64(in int64) { + pe.length += 8 +} + +func (pe *prepEncoder) putArrayLength(in int) error { + if in > math.MaxInt32 { + return PacketEncodingError{fmt.Sprintf("array too long (%d)", in)} + } + pe.length += 4 + return nil +} + +// arrays + +func (pe *prepEncoder) putBytes(in []byte) error { + pe.length += 4 + if in == nil { + return nil + } + if len(in) > math.MaxInt32 { + return PacketEncodingError{fmt.Sprintf("byteslice too long (%d)", len(in))} + } + pe.length += len(in) + return nil +} + +func (pe *prepEncoder) putRawBytes(in []byte) error { + if len(in) > math.MaxInt32 { + return PacketEncodingError{fmt.Sprintf("byteslice too long (%d)", len(in))} + } + pe.length += len(in) + return nil +} + +func (pe *prepEncoder) putString(in string) error { + pe.length += 2 + if len(in) > math.MaxInt16 { + return PacketEncodingError{fmt.Sprintf("string too long (%d)", len(in))} + } + pe.length += len(in) + return nil +} + +func (pe *prepEncoder) putStringArray(in []string) error { + err := pe.putArrayLength(len(in)) + if err != nil { + return err + } + + for _, str := range in { + if err := pe.putString(str); err != nil { + return err + } + } + + return nil +} + +func (pe *prepEncoder) putInt32Array(in []int32) error { + err := pe.putArrayLength(len(in)) + if err != nil { + return err + } + pe.length += 4 * len(in) + return nil +} + +func (pe *prepEncoder) putInt64Array(in []int64) error { + err := pe.putArrayLength(len(in)) + if err != nil { + return err + } + pe.length += 8 * len(in) + return nil +} + +func (pe *prepEncoder) offset() int { + return pe.length +} + +// stackable + +func (pe *prepEncoder) push(in pushEncoder) { + pe.length += in.reserveLength() +} + +func (pe *prepEncoder) pop() error { + return nil +} + +// we do not record metrics during the prep encoder pass +func (pe *prepEncoder) metricRegistry() metrics.Registry { + return nil +} diff --git a/vendor/src/github.com/Shopify/sarama/produce_request.go b/vendor/src/github.com/Shopify/sarama/produce_request.go new file mode 100644 index 00000000..40dc8015 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/produce_request.go @@ -0,0 +1,209 @@ +package sarama + +import "github.com/rcrowley/go-metrics" + +// RequiredAcks is used in Produce Requests to tell the broker how many replica acknowledgements +// it must see before responding. Any of the constants defined here are valid. On broker versions +// prior to 0.8.2.0 any other positive int16 is also valid (the broker will wait for that many +// acknowledgements) but in 0.8.2.0 and later this will raise an exception (it has been replaced +// by setting the `min.isr` value in the brokers configuration). +type RequiredAcks int16 + +const ( + // NoResponse doesn't send any response, the TCP ACK is all you get. + NoResponse RequiredAcks = 0 + // WaitForLocal waits for only the local commit to succeed before responding. + WaitForLocal RequiredAcks = 1 + // WaitForAll waits for all in-sync replicas to commit before responding. + // The minimum number of in-sync replicas is configured on the broker via + // the `min.insync.replicas` configuration key. + WaitForAll RequiredAcks = -1 +) + +type ProduceRequest struct { + RequiredAcks RequiredAcks + Timeout int32 + Version int16 // v1 requires Kafka 0.9, v2 requires Kafka 0.10 + msgSets map[string]map[int32]*MessageSet +} + +func (r *ProduceRequest) encode(pe packetEncoder) error { + pe.putInt16(int16(r.RequiredAcks)) + pe.putInt32(r.Timeout) + err := pe.putArrayLength(len(r.msgSets)) + if err != nil { + return err + } + metricRegistry := pe.metricRegistry() + var batchSizeMetric metrics.Histogram + var compressionRatioMetric metrics.Histogram + if metricRegistry != nil { + batchSizeMetric = getOrRegisterHistogram("batch-size", metricRegistry) + compressionRatioMetric = getOrRegisterHistogram("compression-ratio", metricRegistry) + } + + totalRecordCount := int64(0) + for topic, partitions := range r.msgSets { + err = pe.putString(topic) + if err != nil { + return err + } + err = pe.putArrayLength(len(partitions)) + if err != nil { + return err + } + topicRecordCount := int64(0) + var topicCompressionRatioMetric metrics.Histogram + if metricRegistry != nil { + topicCompressionRatioMetric = getOrRegisterTopicHistogram("compression-ratio", topic, metricRegistry) + } + for id, msgSet := range partitions { + startOffset := pe.offset() + pe.putInt32(id) + pe.push(&lengthField{}) + err = msgSet.encode(pe) + if err != nil { + return err + } + err = pe.pop() + if err != nil { + return err + } + if metricRegistry != nil { + for _, messageBlock := range msgSet.Messages { + // Is this a fake "message" wrapping real messages? + if messageBlock.Msg.Set != nil { + topicRecordCount += int64(len(messageBlock.Msg.Set.Messages)) + } else { + // A single uncompressed message + topicRecordCount++ + } + // Better be safe than sorry when computing the compression ratio + if messageBlock.Msg.compressedSize != 0 { + compressionRatio := float64(len(messageBlock.Msg.Value)) / + float64(messageBlock.Msg.compressedSize) + // Histogram do not support decimal values, let's multiple it by 100 for better precision + intCompressionRatio := int64(100 * compressionRatio) + compressionRatioMetric.Update(intCompressionRatio) + topicCompressionRatioMetric.Update(intCompressionRatio) + } + } + batchSize := int64(pe.offset() - startOffset) + batchSizeMetric.Update(batchSize) + getOrRegisterTopicHistogram("batch-size", topic, metricRegistry).Update(batchSize) + } + } + if topicRecordCount > 0 { + getOrRegisterTopicMeter("record-send-rate", topic, metricRegistry).Mark(topicRecordCount) + getOrRegisterTopicHistogram("records-per-request", topic, metricRegistry).Update(topicRecordCount) + totalRecordCount += topicRecordCount + } + } + if totalRecordCount > 0 { + metrics.GetOrRegisterMeter("record-send-rate", metricRegistry).Mark(totalRecordCount) + getOrRegisterHistogram("records-per-request", metricRegistry).Update(totalRecordCount) + } + + return nil +} + +func (r *ProduceRequest) decode(pd packetDecoder, version int16) error { + requiredAcks, err := pd.getInt16() + if err != nil { + return err + } + r.RequiredAcks = RequiredAcks(requiredAcks) + if r.Timeout, err = pd.getInt32(); err != nil { + return err + } + topicCount, err := pd.getArrayLength() + if err != nil { + return err + } + if topicCount == 0 { + return nil + } + r.msgSets = make(map[string]map[int32]*MessageSet) + for i := 0; i < topicCount; i++ { + topic, err := pd.getString() + if err != nil { + return err + } + partitionCount, err := pd.getArrayLength() + if err != nil { + return err + } + r.msgSets[topic] = make(map[int32]*MessageSet) + for j := 0; j < partitionCount; j++ { + partition, err := pd.getInt32() + if err != nil { + return err + } + messageSetSize, err := pd.getInt32() + if err != nil { + return err + } + msgSetDecoder, err := pd.getSubset(int(messageSetSize)) + if err != nil { + return err + } + msgSet := &MessageSet{} + err = msgSet.decode(msgSetDecoder) + if err != nil { + return err + } + r.msgSets[topic][partition] = msgSet + } + } + return nil +} + +func (r *ProduceRequest) key() int16 { + return 0 +} + +func (r *ProduceRequest) version() int16 { + return r.Version +} + +func (r *ProduceRequest) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_9_0_0 + case 2: + return V0_10_0_0 + default: + return minVersion + } +} + +func (r *ProduceRequest) AddMessage(topic string, partition int32, msg *Message) { + if r.msgSets == nil { + r.msgSets = make(map[string]map[int32]*MessageSet) + } + + if r.msgSets[topic] == nil { + r.msgSets[topic] = make(map[int32]*MessageSet) + } + + set := r.msgSets[topic][partition] + + if set == nil { + set = new(MessageSet) + r.msgSets[topic][partition] = set + } + + set.addMessage(msg) +} + +func (r *ProduceRequest) AddSet(topic string, partition int32, set *MessageSet) { + if r.msgSets == nil { + r.msgSets = make(map[string]map[int32]*MessageSet) + } + + if r.msgSets[topic] == nil { + r.msgSets[topic] = make(map[int32]*MessageSet) + } + + r.msgSets[topic][partition] = set +} diff --git a/vendor/src/github.com/Shopify/sarama/produce_request_test.go b/vendor/src/github.com/Shopify/sarama/produce_request_test.go new file mode 100644 index 00000000..21f4ba5b --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/produce_request_test.go @@ -0,0 +1,47 @@ +package sarama + +import ( + "testing" +) + +var ( + produceRequestEmpty = []byte{ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} + + produceRequestHeader = []byte{ + 0x01, 0x23, + 0x00, 0x00, 0x04, 0x44, + 0x00, 0x00, 0x00, 0x00} + + produceRequestOneMessage = []byte{ + 0x01, 0x23, + 0x00, 0x00, 0x04, 0x44, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0xAD, + 0x00, 0x00, 0x00, 0x1C, + // messageSet + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, + // message + 0x23, 0x96, 0x4a, 0xf7, // CRC + 0x00, + 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x02, 0x00, 0xEE} +) + +func TestProduceRequest(t *testing.T) { + request := new(ProduceRequest) + testRequest(t, "empty", request, produceRequestEmpty) + + request.RequiredAcks = 0x123 + request.Timeout = 0x444 + testRequest(t, "header", request, produceRequestHeader) + + request.AddMessage("topic", 0xAD, &Message{Codec: CompressionNone, Key: nil, Value: []byte{0x00, 0xEE}}) + testRequest(t, "one message", request, produceRequestOneMessage) +} diff --git a/vendor/src/github.com/Shopify/sarama/produce_response.go b/vendor/src/github.com/Shopify/sarama/produce_response.go new file mode 100644 index 00000000..195abcb8 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/produce_response.go @@ -0,0 +1,158 @@ +package sarama + +import "time" + +type ProduceResponseBlock struct { + Err KError + Offset int64 + // only provided if Version >= 2 and the broker is configured with `LogAppendTime` + Timestamp time.Time +} + +func (b *ProduceResponseBlock) decode(pd packetDecoder, version int16) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + b.Err = KError(tmp) + + b.Offset, err = pd.getInt64() + if err != nil { + return err + } + + if version >= 2 { + if millis, err := pd.getInt64(); err != nil { + return err + } else if millis != -1 { + b.Timestamp = time.Unix(millis/1000, (millis%1000)*int64(time.Millisecond)) + } + } + + return nil +} + +type ProduceResponse struct { + Blocks map[string]map[int32]*ProduceResponseBlock + Version int16 + ThrottleTime time.Duration // only provided if Version >= 1 +} + +func (r *ProduceResponse) decode(pd packetDecoder, version int16) (err error) { + r.Version = version + + numTopics, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks = make(map[string]map[int32]*ProduceResponseBlock, numTopics) + for i := 0; i < numTopics; i++ { + name, err := pd.getString() + if err != nil { + return err + } + + numBlocks, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks[name] = make(map[int32]*ProduceResponseBlock, numBlocks) + + for j := 0; j < numBlocks; j++ { + id, err := pd.getInt32() + if err != nil { + return err + } + + block := new(ProduceResponseBlock) + err = block.decode(pd, version) + if err != nil { + return err + } + r.Blocks[name][id] = block + } + } + + if r.Version >= 1 { + if millis, err := pd.getInt32(); err != nil { + return err + } else { + r.ThrottleTime = time.Duration(millis) * time.Millisecond + } + } + + return nil +} + +func (r *ProduceResponse) encode(pe packetEncoder) error { + err := pe.putArrayLength(len(r.Blocks)) + if err != nil { + return err + } + for topic, partitions := range r.Blocks { + err = pe.putString(topic) + if err != nil { + return err + } + err = pe.putArrayLength(len(partitions)) + if err != nil { + return err + } + for id, prb := range partitions { + pe.putInt32(id) + pe.putInt16(int16(prb.Err)) + pe.putInt64(prb.Offset) + } + } + if r.Version >= 1 { + pe.putInt32(int32(r.ThrottleTime / time.Millisecond)) + } + return nil +} + +func (r *ProduceResponse) key() int16 { + return 0 +} + +func (r *ProduceResponse) version() int16 { + return r.Version +} + +func (r *ProduceResponse) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_9_0_0 + case 2: + return V0_10_0_0 + default: + return minVersion + } +} + +func (r *ProduceResponse) GetBlock(topic string, partition int32) *ProduceResponseBlock { + if r.Blocks == nil { + return nil + } + + if r.Blocks[topic] == nil { + return nil + } + + return r.Blocks[topic][partition] +} + +// Testing API + +func (r *ProduceResponse) AddTopicPartition(topic string, partition int32, err KError) { + if r.Blocks == nil { + r.Blocks = make(map[string]map[int32]*ProduceResponseBlock) + } + byTopic, ok := r.Blocks[topic] + if !ok { + byTopic = make(map[int32]*ProduceResponseBlock) + r.Blocks[topic] = byTopic + } + byTopic[partition] = &ProduceResponseBlock{Err: err} +} diff --git a/vendor/src/github.com/Shopify/sarama/produce_response_test.go b/vendor/src/github.com/Shopify/sarama/produce_response_test.go new file mode 100644 index 00000000..f71709fe --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/produce_response_test.go @@ -0,0 +1,67 @@ +package sarama + +import "testing" + +var ( + produceResponseNoBlocks = []byte{ + 0x00, 0x00, 0x00, 0x00} + + produceResponseManyBlocks = []byte{ + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x03, 'f', 'o', 'o', + 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x03, 'b', 'a', 'r', + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +) + +func TestProduceResponse(t *testing.T) { + response := ProduceResponse{} + + testVersionDecodable(t, "no blocks", &response, produceResponseNoBlocks, 0) + if len(response.Blocks) != 0 { + t.Error("Decoding produced", len(response.Blocks), "topics where there were none") + } + + testVersionDecodable(t, "many blocks", &response, produceResponseManyBlocks, 0) + if len(response.Blocks) != 2 { + t.Error("Decoding produced", len(response.Blocks), "topics where there were 2") + } + if len(response.Blocks["foo"]) != 0 { + t.Error("Decoding produced", len(response.Blocks["foo"]), "partitions for 'foo' where there were none") + } + if len(response.Blocks["bar"]) != 2 { + t.Error("Decoding produced", len(response.Blocks["bar"]), "partitions for 'bar' where there were two") + } + block := response.GetBlock("bar", 1) + if block == nil { + t.Error("Decoding did not produce a block for bar/1") + } else { + if block.Err != ErrNoError { + t.Error("Decoding failed for bar/1/Err, got:", int16(block.Err)) + } + if block.Offset != 0xFF { + t.Error("Decoding failed for bar/1/Offset, got:", block.Offset) + } + } + block = response.GetBlock("bar", 2) + if block == nil { + t.Error("Decoding did not produce a block for bar/2") + } else { + if block.Err != ErrInvalidMessage { + t.Error("Decoding failed for bar/2/Err, got:", int16(block.Err)) + } + if block.Offset != 0 { + t.Error("Decoding failed for bar/2/Offset, got:", block.Offset) + } + } +} diff --git a/vendor/src/github.com/Shopify/sarama/produce_set.go b/vendor/src/github.com/Shopify/sarama/produce_set.go new file mode 100644 index 00000000..158d9c47 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/produce_set.go @@ -0,0 +1,176 @@ +package sarama + +import "time" + +type partitionSet struct { + msgs []*ProducerMessage + setToSend *MessageSet + bufferBytes int +} + +type produceSet struct { + parent *asyncProducer + msgs map[string]map[int32]*partitionSet + + bufferBytes int + bufferCount int +} + +func newProduceSet(parent *asyncProducer) *produceSet { + return &produceSet{ + msgs: make(map[string]map[int32]*partitionSet), + parent: parent, + } +} + +func (ps *produceSet) add(msg *ProducerMessage) error { + var err error + var key, val []byte + + if msg.Key != nil { + if key, err = msg.Key.Encode(); err != nil { + return err + } + } + + if msg.Value != nil { + if val, err = msg.Value.Encode(); err != nil { + return err + } + } + + partitions := ps.msgs[msg.Topic] + if partitions == nil { + partitions = make(map[int32]*partitionSet) + ps.msgs[msg.Topic] = partitions + } + + set := partitions[msg.Partition] + if set == nil { + set = &partitionSet{setToSend: new(MessageSet)} + partitions[msg.Partition] = set + } + + set.msgs = append(set.msgs, msg) + msgToSend := &Message{Codec: CompressionNone, Key: key, Value: val} + if ps.parent.conf.Version.IsAtLeast(V0_10_0_0) { + if msg.Timestamp.IsZero() { + msgToSend.Timestamp = time.Now() + } else { + msgToSend.Timestamp = msg.Timestamp + } + msgToSend.Version = 1 + } + set.setToSend.addMessage(msgToSend) + + size := producerMessageOverhead + len(key) + len(val) + set.bufferBytes += size + ps.bufferBytes += size + ps.bufferCount++ + + return nil +} + +func (ps *produceSet) buildRequest() *ProduceRequest { + req := &ProduceRequest{ + RequiredAcks: ps.parent.conf.Producer.RequiredAcks, + Timeout: int32(ps.parent.conf.Producer.Timeout / time.Millisecond), + } + if ps.parent.conf.Version.IsAtLeast(V0_10_0_0) { + req.Version = 2 + } + + for topic, partitionSet := range ps.msgs { + for partition, set := range partitionSet { + if ps.parent.conf.Producer.Compression == CompressionNone { + req.AddSet(topic, partition, set.setToSend) + } else { + // When compression is enabled, the entire set for each partition is compressed + // and sent as the payload of a single fake "message" with the appropriate codec + // set and no key. When the server sees a message with a compression codec, it + // decompresses the payload and treats the result as its message set. + payload, err := encode(set.setToSend, ps.parent.conf.MetricRegistry) + if err != nil { + Logger.Println(err) // if this happens, it's basically our fault. + panic(err) + } + compMsg := &Message{ + Codec: ps.parent.conf.Producer.Compression, + Key: nil, + Value: payload, + Set: set.setToSend, // Provide the underlying message set for accurate metrics + } + if ps.parent.conf.Version.IsAtLeast(V0_10_0_0) { + compMsg.Version = 1 + compMsg.Timestamp = set.setToSend.Messages[0].Msg.Timestamp + } + req.AddMessage(topic, partition, compMsg) + } + } + } + + return req +} + +func (ps *produceSet) eachPartition(cb func(topic string, partition int32, msgs []*ProducerMessage)) { + for topic, partitionSet := range ps.msgs { + for partition, set := range partitionSet { + cb(topic, partition, set.msgs) + } + } +} + +func (ps *produceSet) dropPartition(topic string, partition int32) []*ProducerMessage { + if ps.msgs[topic] == nil { + return nil + } + set := ps.msgs[topic][partition] + if set == nil { + return nil + } + ps.bufferBytes -= set.bufferBytes + ps.bufferCount -= len(set.msgs) + delete(ps.msgs[topic], partition) + return set.msgs +} + +func (ps *produceSet) wouldOverflow(msg *ProducerMessage) bool { + switch { + // Would we overflow our maximum possible size-on-the-wire? 10KiB is arbitrary overhead for safety. + case ps.bufferBytes+msg.byteSize() >= int(MaxRequestSize-(10*1024)): + return true + // Would we overflow the size-limit of a compressed message-batch for this partition? + case ps.parent.conf.Producer.Compression != CompressionNone && + ps.msgs[msg.Topic] != nil && ps.msgs[msg.Topic][msg.Partition] != nil && + ps.msgs[msg.Topic][msg.Partition].bufferBytes+msg.byteSize() >= ps.parent.conf.Producer.MaxMessageBytes: + return true + // Would we overflow simply in number of messages? + case ps.parent.conf.Producer.Flush.MaxMessages > 0 && ps.bufferCount >= ps.parent.conf.Producer.Flush.MaxMessages: + return true + default: + return false + } +} + +func (ps *produceSet) readyToFlush() bool { + switch { + // If we don't have any messages, nothing else matters + case ps.empty(): + return false + // If all three config values are 0, we always flush as-fast-as-possible + case ps.parent.conf.Producer.Flush.Frequency == 0 && ps.parent.conf.Producer.Flush.Bytes == 0 && ps.parent.conf.Producer.Flush.Messages == 0: + return true + // If we've passed the message trigger-point + case ps.parent.conf.Producer.Flush.Messages > 0 && ps.bufferCount >= ps.parent.conf.Producer.Flush.Messages: + return true + // If we've passed the byte trigger-point + case ps.parent.conf.Producer.Flush.Bytes > 0 && ps.bufferBytes >= ps.parent.conf.Producer.Flush.Bytes: + return true + default: + return false + } +} + +func (ps *produceSet) empty() bool { + return ps.bufferCount == 0 +} diff --git a/vendor/src/github.com/Shopify/sarama/produce_set_test.go b/vendor/src/github.com/Shopify/sarama/produce_set_test.go new file mode 100644 index 00000000..d016a10b --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/produce_set_test.go @@ -0,0 +1,185 @@ +package sarama + +import ( + "testing" + "time" +) + +func makeProduceSet() (*asyncProducer, *produceSet) { + parent := &asyncProducer{ + conf: NewConfig(), + } + return parent, newProduceSet(parent) +} + +func safeAddMessage(t *testing.T, ps *produceSet, msg *ProducerMessage) { + if err := ps.add(msg); err != nil { + t.Error(err) + } +} + +func TestProduceSetInitial(t *testing.T) { + _, ps := makeProduceSet() + + if !ps.empty() { + t.Error("New produceSet should be empty") + } + + if ps.readyToFlush() { + t.Error("Empty produceSet must never be ready to flush") + } +} + +func TestProduceSetAddingMessages(t *testing.T) { + parent, ps := makeProduceSet() + parent.conf.Producer.Flush.MaxMessages = 1000 + + msg := &ProducerMessage{Key: StringEncoder(TestMessage), Value: StringEncoder(TestMessage)} + safeAddMessage(t, ps, msg) + + if ps.empty() { + t.Error("set shouldn't be empty when a message is added") + } + + if !ps.readyToFlush() { + t.Error("by default set should be ready to flush when any message is in place") + } + + for i := 0; i < 999; i++ { + if ps.wouldOverflow(msg) { + t.Error("set shouldn't fill up after only", i+1, "messages") + } + safeAddMessage(t, ps, msg) + } + + if !ps.wouldOverflow(msg) { + t.Error("set should be full after 1000 messages") + } +} + +func TestProduceSetPartitionTracking(t *testing.T) { + _, ps := makeProduceSet() + + m1 := &ProducerMessage{Topic: "t1", Partition: 0} + m2 := &ProducerMessage{Topic: "t1", Partition: 1} + m3 := &ProducerMessage{Topic: "t2", Partition: 0} + safeAddMessage(t, ps, m1) + safeAddMessage(t, ps, m2) + safeAddMessage(t, ps, m3) + + seenT1P0 := false + seenT1P1 := false + seenT2P0 := false + + ps.eachPartition(func(topic string, partition int32, msgs []*ProducerMessage) { + if len(msgs) != 1 { + t.Error("Wrong message count") + } + + if topic == "t1" && partition == 0 { + seenT1P0 = true + } else if topic == "t1" && partition == 1 { + seenT1P1 = true + } else if topic == "t2" && partition == 0 { + seenT2P0 = true + } + }) + + if !seenT1P0 { + t.Error("Didn't see t1p0") + } + if !seenT1P1 { + t.Error("Didn't see t1p1") + } + if !seenT2P0 { + t.Error("Didn't see t2p0") + } + + if len(ps.dropPartition("t1", 1)) != 1 { + t.Error("Got wrong messages back from dropping partition") + } + + if ps.bufferCount != 2 { + t.Error("Incorrect buffer count after dropping partition") + } +} + +func TestProduceSetRequestBuilding(t *testing.T) { + parent, ps := makeProduceSet() + parent.conf.Producer.RequiredAcks = WaitForAll + parent.conf.Producer.Timeout = 10 * time.Second + + msg := &ProducerMessage{ + Topic: "t1", + Partition: 0, + Key: StringEncoder(TestMessage), + Value: StringEncoder(TestMessage), + } + for i := 0; i < 10; i++ { + safeAddMessage(t, ps, msg) + } + msg.Partition = 1 + for i := 0; i < 10; i++ { + safeAddMessage(t, ps, msg) + } + msg.Topic = "t2" + for i := 0; i < 10; i++ { + safeAddMessage(t, ps, msg) + } + + req := ps.buildRequest() + + if req.RequiredAcks != WaitForAll { + t.Error("RequiredAcks not set properly") + } + + if req.Timeout != 10000 { + t.Error("Timeout not set properly") + } + + if len(req.msgSets) != 2 { + t.Error("Wrong number of topics in request") + } +} + +func TestProduceSetCompressedRequestBuilding(t *testing.T) { + parent, ps := makeProduceSet() + parent.conf.Producer.RequiredAcks = WaitForAll + parent.conf.Producer.Timeout = 10 * time.Second + parent.conf.Producer.Compression = CompressionGZIP + parent.conf.Version = V0_10_0_0 + + msg := &ProducerMessage{ + Topic: "t1", + Partition: 0, + Key: StringEncoder(TestMessage), + Value: StringEncoder(TestMessage), + Timestamp: time.Now(), + } + for i := 0; i < 10; i++ { + safeAddMessage(t, ps, msg) + } + + req := ps.buildRequest() + + if req.Version != 2 { + t.Error("Wrong request version") + } + + for _, msgBlock := range req.msgSets["t1"][0].Messages { + msg := msgBlock.Msg + err := msg.decodeSet() + if err != nil { + t.Error("Failed to decode set from payload") + } + for _, compMsgBlock := range msg.Set.Messages { + compMsg := compMsgBlock.Msg + if compMsg.Version != 1 { + t.Error("Wrong compressed message version") + } + } + if msg.Version != 1 { + t.Error("Wrong compressed parent message version") + } + } +} diff --git a/vendor/src/github.com/Shopify/sarama/real_decoder.go b/vendor/src/github.com/Shopify/sarama/real_decoder.go new file mode 100644 index 00000000..a0141af0 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/real_decoder.go @@ -0,0 +1,259 @@ +package sarama + +import ( + "encoding/binary" + "math" +) + +var errInvalidArrayLength = PacketDecodingError{"invalid array length"} +var errInvalidByteSliceLength = PacketDecodingError{"invalid byteslice length"} +var errInvalidStringLength = PacketDecodingError{"invalid string length"} +var errInvalidSubsetSize = PacketDecodingError{"invalid subset size"} + +type realDecoder struct { + raw []byte + off int + stack []pushDecoder +} + +// primitives + +func (rd *realDecoder) getInt8() (int8, error) { + if rd.remaining() < 1 { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } + tmp := int8(rd.raw[rd.off]) + rd.off++ + return tmp, nil +} + +func (rd *realDecoder) getInt16() (int16, error) { + if rd.remaining() < 2 { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } + tmp := int16(binary.BigEndian.Uint16(rd.raw[rd.off:])) + rd.off += 2 + return tmp, nil +} + +func (rd *realDecoder) getInt32() (int32, error) { + if rd.remaining() < 4 { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } + tmp := int32(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + return tmp, nil +} + +func (rd *realDecoder) getInt64() (int64, error) { + if rd.remaining() < 8 { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } + tmp := int64(binary.BigEndian.Uint64(rd.raw[rd.off:])) + rd.off += 8 + return tmp, nil +} + +func (rd *realDecoder) getArrayLength() (int, error) { + if rd.remaining() < 4 { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } + tmp := int(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + if tmp > rd.remaining() { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } else if tmp > 2*math.MaxUint16 { + return -1, errInvalidArrayLength + } + return tmp, nil +} + +// collections + +func (rd *realDecoder) getBytes() ([]byte, error) { + tmp, err := rd.getInt32() + + if err != nil { + return nil, err + } + + n := int(tmp) + + switch { + case n < -1: + return nil, errInvalidByteSliceLength + case n == -1: + return nil, nil + case n == 0: + return make([]byte, 0), nil + case n > rd.remaining(): + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + + tmpStr := rd.raw[rd.off : rd.off+n] + rd.off += n + return tmpStr, nil +} + +func (rd *realDecoder) getString() (string, error) { + tmp, err := rd.getInt16() + + if err != nil { + return "", err + } + + n := int(tmp) + + switch { + case n < -1: + return "", errInvalidStringLength + case n == -1: + return "", nil + case n == 0: + return "", nil + case n > rd.remaining(): + rd.off = len(rd.raw) + return "", ErrInsufficientData + } + + tmpStr := string(rd.raw[rd.off : rd.off+n]) + rd.off += n + return tmpStr, nil +} + +func (rd *realDecoder) getInt32Array() ([]int32, error) { + if rd.remaining() < 4 { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + n := int(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + + if rd.remaining() < 4*n { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + + if n == 0 { + return nil, nil + } + + if n < 0 { + return nil, errInvalidArrayLength + } + + ret := make([]int32, n) + for i := range ret { + ret[i] = int32(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + } + return ret, nil +} + +func (rd *realDecoder) getInt64Array() ([]int64, error) { + if rd.remaining() < 4 { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + n := int(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + + if rd.remaining() < 8*n { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + + if n == 0 { + return nil, nil + } + + if n < 0 { + return nil, errInvalidArrayLength + } + + ret := make([]int64, n) + for i := range ret { + ret[i] = int64(binary.BigEndian.Uint64(rd.raw[rd.off:])) + rd.off += 8 + } + return ret, nil +} + +func (rd *realDecoder) getStringArray() ([]string, error) { + if rd.remaining() < 4 { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + n := int(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + + if n == 0 { + return nil, nil + } + + if n < 0 { + return nil, errInvalidArrayLength + } + + ret := make([]string, n) + for i := range ret { + if str, err := rd.getString(); err != nil { + return nil, err + } else { + ret[i] = str + } + } + return ret, nil +} + +// subsets + +func (rd *realDecoder) remaining() int { + return len(rd.raw) - rd.off +} + +func (rd *realDecoder) getSubset(length int) (packetDecoder, error) { + if length < 0 { + return nil, errInvalidSubsetSize + } else if length > rd.remaining() { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + + start := rd.off + rd.off += length + return &realDecoder{raw: rd.raw[start:rd.off]}, nil +} + +// stacks + +func (rd *realDecoder) push(in pushDecoder) error { + in.saveOffset(rd.off) + + reserve := in.reserveLength() + if rd.remaining() < reserve { + rd.off = len(rd.raw) + return ErrInsufficientData + } + + rd.stack = append(rd.stack, in) + + rd.off += reserve + + return nil +} + +func (rd *realDecoder) pop() error { + // this is go's ugly pop pattern (the inverse of append) + in := rd.stack[len(rd.stack)-1] + rd.stack = rd.stack[:len(rd.stack)-1] + + return in.check(rd.off, rd.raw) +} diff --git a/vendor/src/github.com/Shopify/sarama/real_encoder.go b/vendor/src/github.com/Shopify/sarama/real_encoder.go new file mode 100644 index 00000000..ced4267c --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/real_encoder.go @@ -0,0 +1,129 @@ +package sarama + +import ( + "encoding/binary" + + "github.com/rcrowley/go-metrics" +) + +type realEncoder struct { + raw []byte + off int + stack []pushEncoder + registry metrics.Registry +} + +// primitives + +func (re *realEncoder) putInt8(in int8) { + re.raw[re.off] = byte(in) + re.off++ +} + +func (re *realEncoder) putInt16(in int16) { + binary.BigEndian.PutUint16(re.raw[re.off:], uint16(in)) + re.off += 2 +} + +func (re *realEncoder) putInt32(in int32) { + binary.BigEndian.PutUint32(re.raw[re.off:], uint32(in)) + re.off += 4 +} + +func (re *realEncoder) putInt64(in int64) { + binary.BigEndian.PutUint64(re.raw[re.off:], uint64(in)) + re.off += 8 +} + +func (re *realEncoder) putArrayLength(in int) error { + re.putInt32(int32(in)) + return nil +} + +// collection + +func (re *realEncoder) putRawBytes(in []byte) error { + copy(re.raw[re.off:], in) + re.off += len(in) + return nil +} + +func (re *realEncoder) putBytes(in []byte) error { + if in == nil { + re.putInt32(-1) + return nil + } + re.putInt32(int32(len(in))) + copy(re.raw[re.off:], in) + re.off += len(in) + return nil +} + +func (re *realEncoder) putString(in string) error { + re.putInt16(int16(len(in))) + copy(re.raw[re.off:], in) + re.off += len(in) + return nil +} + +func (re *realEncoder) putStringArray(in []string) error { + err := re.putArrayLength(len(in)) + if err != nil { + return err + } + + for _, val := range in { + if err := re.putString(val); err != nil { + return err + } + } + + return nil +} + +func (re *realEncoder) putInt32Array(in []int32) error { + err := re.putArrayLength(len(in)) + if err != nil { + return err + } + for _, val := range in { + re.putInt32(val) + } + return nil +} + +func (re *realEncoder) putInt64Array(in []int64) error { + err := re.putArrayLength(len(in)) + if err != nil { + return err + } + for _, val := range in { + re.putInt64(val) + } + return nil +} + +func (re *realEncoder) offset() int { + return re.off +} + +// stacks + +func (re *realEncoder) push(in pushEncoder) { + in.saveOffset(re.off) + re.off += in.reserveLength() + re.stack = append(re.stack, in) +} + +func (re *realEncoder) pop() error { + // this is go's ugly pop pattern (the inverse of append) + in := re.stack[len(re.stack)-1] + re.stack = re.stack[:len(re.stack)-1] + + return in.run(re.off, re.raw) +} + +// we do record metrics during the real encoder pass +func (re *realEncoder) metricRegistry() metrics.Registry { + return re.registry +} diff --git a/vendor/src/github.com/Shopify/sarama/request.go b/vendor/src/github.com/Shopify/sarama/request.go new file mode 100644 index 00000000..73310ca8 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/request.go @@ -0,0 +1,119 @@ +package sarama + +import ( + "encoding/binary" + "fmt" + "io" +) + +type protocolBody interface { + encoder + versionedDecoder + key() int16 + version() int16 + requiredVersion() KafkaVersion +} + +type request struct { + correlationID int32 + clientID string + body protocolBody +} + +func (r *request) encode(pe packetEncoder) (err error) { + pe.push(&lengthField{}) + pe.putInt16(r.body.key()) + pe.putInt16(r.body.version()) + pe.putInt32(r.correlationID) + err = pe.putString(r.clientID) + if err != nil { + return err + } + err = r.body.encode(pe) + if err != nil { + return err + } + return pe.pop() +} + +func (r *request) decode(pd packetDecoder) (err error) { + var key int16 + if key, err = pd.getInt16(); err != nil { + return err + } + var version int16 + if version, err = pd.getInt16(); err != nil { + return err + } + if r.correlationID, err = pd.getInt32(); err != nil { + return err + } + r.clientID, err = pd.getString() + + r.body = allocateBody(key, version) + if r.body == nil { + return PacketDecodingError{fmt.Sprintf("unknown request key (%d)", key)} + } + return r.body.decode(pd, version) +} + +func decodeRequest(r io.Reader) (req *request, bytesRead int, err error) { + lengthBytes := make([]byte, 4) + if _, err := io.ReadFull(r, lengthBytes); err != nil { + return nil, bytesRead, err + } + bytesRead += len(lengthBytes) + + length := int32(binary.BigEndian.Uint32(lengthBytes)) + if length <= 4 || length > MaxRequestSize { + return nil, bytesRead, PacketDecodingError{fmt.Sprintf("message of length %d too large or too small", length)} + } + + encodedReq := make([]byte, length) + if _, err := io.ReadFull(r, encodedReq); err != nil { + return nil, bytesRead, err + } + bytesRead += len(encodedReq) + + req = &request{} + if err := decode(encodedReq, req); err != nil { + return nil, bytesRead, err + } + return req, bytesRead, nil +} + +func allocateBody(key, version int16) protocolBody { + switch key { + case 0: + return &ProduceRequest{} + case 1: + return &FetchRequest{} + case 2: + return &OffsetRequest{Version: version} + case 3: + return &MetadataRequest{} + case 8: + return &OffsetCommitRequest{Version: version} + case 9: + return &OffsetFetchRequest{} + case 10: + return &ConsumerMetadataRequest{} + case 11: + return &JoinGroupRequest{} + case 12: + return &HeartbeatRequest{} + case 13: + return &LeaveGroupRequest{} + case 14: + return &SyncGroupRequest{} + case 15: + return &DescribeGroupsRequest{} + case 16: + return &ListGroupsRequest{} + case 17: + return &SaslHandshakeRequest{} + case 18: + return &ApiVersionsRequest{} + } + return nil +} diff --git a/vendor/src/github.com/Shopify/sarama/request_test.go b/vendor/src/github.com/Shopify/sarama/request_test.go new file mode 100644 index 00000000..e5457543 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/request_test.go @@ -0,0 +1,91 @@ +package sarama + +import ( + "bytes" + "reflect" + "testing" + + "github.com/davecgh/go-spew/spew" +) + +type testRequestBody struct { +} + +func (s *testRequestBody) key() int16 { + return 0x666 +} + +func (s *testRequestBody) version() int16 { + return 0xD2 +} + +func (s *testRequestBody) encode(pe packetEncoder) error { + return pe.putString("abc") +} + +// not specific to request tests, just helper functions for testing structures that +// implement the encoder or decoder interfaces that needed somewhere to live + +func testEncodable(t *testing.T, name string, in encoder, expect []byte) { + packet, err := encode(in, nil) + if err != nil { + t.Error(err) + } else if !bytes.Equal(packet, expect) { + t.Error("Encoding", name, "failed\ngot ", packet, "\nwant", expect) + } +} + +func testDecodable(t *testing.T, name string, out decoder, in []byte) { + err := decode(in, out) + if err != nil { + t.Error("Decoding", name, "failed:", err) + } +} + +func testVersionDecodable(t *testing.T, name string, out versionedDecoder, in []byte, version int16) { + err := versionedDecode(in, out, version) + if err != nil { + t.Error("Decoding", name, "version", version, "failed:", err) + } +} + +func testRequest(t *testing.T, name string, rb protocolBody, expected []byte) { + // Encoder request + req := &request{correlationID: 123, clientID: "foo", body: rb} + packet, err := encode(req, nil) + headerSize := 14 + len("foo") + if err != nil { + t.Error(err) + } else if !bytes.Equal(packet[headerSize:], expected) { + t.Error("Encoding", name, "failed\ngot ", packet[headerSize:], "\nwant", expected) + } + // Decoder request + decoded, n, err := decodeRequest(bytes.NewReader(packet)) + if err != nil { + t.Error("Failed to decode request", err) + } else if decoded.correlationID != 123 || decoded.clientID != "foo" { + t.Errorf("Decoded header %q is not valid: %+v", name, decoded) + } else if !reflect.DeepEqual(rb, decoded.body) { + t.Error(spew.Sprintf("Decoded request %q does not match the encoded one\nencoded: %+v\ndecoded: %+v", name, rb, decoded.body)) + } else if n != len(packet) { + t.Errorf("Decoded request %q bytes: %d does not match the encoded one: %d\n", name, n, len(packet)) + } +} + +func testResponse(t *testing.T, name string, res protocolBody, expected []byte) { + encoded, err := encode(res, nil) + if err != nil { + t.Error(err) + } else if expected != nil && !bytes.Equal(encoded, expected) { + t.Error("Encoding", name, "failed\ngot ", encoded, "\nwant", expected) + } + + decoded := reflect.New(reflect.TypeOf(res).Elem()).Interface().(versionedDecoder) + if err := versionedDecode(encoded, decoded, res.version()); err != nil { + t.Error("Decoding", name, "failed:", err) + } + + if !reflect.DeepEqual(decoded, res) { + t.Errorf("Decoded response does not match the encoded one\nencoded: %#v\ndecoded: %#v", res, decoded) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/response_header.go b/vendor/src/github.com/Shopify/sarama/response_header.go new file mode 100644 index 00000000..f3f4d27d --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/response_header.go @@ -0,0 +1,21 @@ +package sarama + +import "fmt" + +type responseHeader struct { + length int32 + correlationID int32 +} + +func (r *responseHeader) decode(pd packetDecoder) (err error) { + r.length, err = pd.getInt32() + if err != nil { + return err + } + if r.length <= 4 || r.length > MaxResponseSize { + return PacketDecodingError{fmt.Sprintf("message of length %d too large or too small", r.length)} + } + + r.correlationID, err = pd.getInt32() + return err +} diff --git a/vendor/src/github.com/Shopify/sarama/response_header_test.go b/vendor/src/github.com/Shopify/sarama/response_header_test.go new file mode 100644 index 00000000..8f9fdb80 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/response_header_test.go @@ -0,0 +1,21 @@ +package sarama + +import "testing" + +var ( + responseHeaderBytes = []byte{ + 0x00, 0x00, 0x0f, 0x00, + 0x0a, 0xbb, 0xcc, 0xff} +) + +func TestResponseHeader(t *testing.T) { + header := responseHeader{} + + testDecodable(t, "response header", &header, responseHeaderBytes) + if header.length != 0xf00 { + t.Error("Decoding header length failed, got", header.length) + } + if header.correlationID != 0x0abbccff { + t.Error("Decoding header correlation id failed, got", header.correlationID) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/sarama.go b/vendor/src/github.com/Shopify/sarama/sarama.go new file mode 100644 index 00000000..7d5dc60d --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sarama.go @@ -0,0 +1,99 @@ +/* +Package sarama is a pure Go client library for dealing with Apache Kafka (versions 0.8 and later). It includes a high-level +API for easily producing and consuming messages, and a low-level API for controlling bytes on the wire when the high-level +API is insufficient. Usage examples for the high-level APIs are provided inline with their full documentation. + +To produce messages, use either the AsyncProducer or the SyncProducer. The AsyncProducer accepts messages on a channel +and produces them asynchronously in the background as efficiently as possible; it is preferred in most cases. +The SyncProducer provides a method which will block until Kafka acknowledges the message as produced. This can be +useful but comes with two caveats: it will generally be less efficient, and the actual durability guarantees +depend on the configured value of `Producer.RequiredAcks`. There are configurations where a message acknowledged by the +SyncProducer can still sometimes be lost. + +To consume messages, use the Consumer. Note that Sarama's Consumer implementation does not currently support automatic +consumer-group rebalancing and offset tracking. For Zookeeper-based tracking (Kafka 0.8.2 and earlier), the +https://github.com/wvanbergen/kafka library builds on Sarama to add this support. For Kafka-based tracking (Kafka 0.9 +and later), the https://github.com/bsm/sarama-cluster library builds on Sarama to add this support. + +For lower-level needs, the Broker and Request/Response objects permit precise control over each connection +and message sent on the wire; the Client provides higher-level metadata management that is shared between +the producers and the consumer. The Request/Response objects and properties are mostly undocumented, as they line up +exactly with the protocol fields documented by Kafka at +https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol + +Metrics are exposed through https://github.com/rcrowley/go-metrics library in a local registry. + +Broker related metrics: + + +----------------------------------------------+------------+---------------------------------------------------------------+ + | Name | Type | Description | + +----------------------------------------------+------------+---------------------------------------------------------------+ + | incoming-byte-rate | meter | Bytes/second read off all brokers | + | incoming-byte-rate-for-broker- | meter | Bytes/second read off a given broker | + | outgoing-byte-rate | meter | Bytes/second written off all brokers | + | outgoing-byte-rate-for-broker- | meter | Bytes/second written off a given broker | + | request-rate | meter | Requests/second sent to all brokers | + | request-rate-for-broker- | meter | Requests/second sent to a given broker | + | request-size | histogram | Distribution of the request size in bytes for all brokers | + | request-size-for-broker- | histogram | Distribution of the request size in bytes for a given broker | + | request-latency-in-ms | histogram | Distribution of the request latency in ms for all brokers | + | request-latency-in-ms-for-broker- | histogram | Distribution of the request latency in ms for a given broker | + | response-rate | meter | Responses/second received from all brokers | + | response-rate-for-broker- | meter | Responses/second received from a given broker | + | response-size | histogram | Distribution of the response size in bytes for all brokers | + | response-size-for-broker- | histogram | Distribution of the response size in bytes for a given broker | + +----------------------------------------------+------------+---------------------------------------------------------------+ + +Note that we do not gather specific metrics for seed brokers but they are part of the "all brokers" metrics. + +Producer related metrics: + + +-------------------------------------------+------------+--------------------------------------------------------------------------------------+ + | Name | Type | Description | + +-------------------------------------------+------------+--------------------------------------------------------------------------------------+ + | batch-size | histogram | Distribution of the number of bytes sent per partition per request for all topics | + | batch-size-for-topic- | histogram | Distribution of the number of bytes sent per partition per request for a given topic | + | record-send-rate | meter | Records/second sent to all topics | + | record-send-rate-for-topic- | meter | Records/second sent to a given topic | + | records-per-request | histogram | Distribution of the number of records sent per request for all topics | + | records-per-request-for-topic- | histogram | Distribution of the number of records sent per request for a given topic | + | compression-ratio | histogram | Distribution of the compression ratio times 100 of record batches for all topics | + | compression-ratio-for-topic- | histogram | Distribution of the compression ratio times 100 of record batches for a given topic | + +-------------------------------------------+------------+--------------------------------------------------------------------------------------+ + +*/ +package sarama + +import ( + "io/ioutil" + "log" +) + +// Logger is the instance of a StdLogger interface that Sarama writes connection +// management events to. By default it is set to discard all log messages via ioutil.Discard, +// but you can set it to redirect wherever you want. +var Logger StdLogger = log.New(ioutil.Discard, "[Sarama] ", log.LstdFlags) + +// StdLogger is used to log error messages. +type StdLogger interface { + Print(v ...interface{}) + Printf(format string, v ...interface{}) + Println(v ...interface{}) +} + +// PanicHandler is called for recovering from panics spawned internally to the library (and thus +// not recoverable by the caller's goroutine). Defaults to nil, which means panics are not recovered. +var PanicHandler func(interface{}) + +// MaxRequestSize is the maximum size (in bytes) of any request that Sarama will attempt to send. Trying +// to send a request larger than this will result in an PacketEncodingError. The default of 100 MiB is aligned +// with Kafka's default `socket.request.max.bytes`, which is the largest request the broker will attempt +// to process. +var MaxRequestSize int32 = 100 * 1024 * 1024 + +// MaxResponseSize is the maximum size (in bytes) of any response that Sarama will attempt to parse. If +// a broker returns a response message larger than this value, Sarama will return a PacketDecodingError to +// protect the client from running out of memory. Please note that brokers do not have any natural limit on +// the size of responses they send. In particular, they can send arbitrarily large fetch responses to consumers +// (see https://issues.apache.org/jira/browse/KAFKA-2063). +var MaxResponseSize int32 = 100 * 1024 * 1024 diff --git a/vendor/src/github.com/Shopify/sarama/sasl_handshake_request.go b/vendor/src/github.com/Shopify/sarama/sasl_handshake_request.go new file mode 100644 index 00000000..fbbc8947 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sasl_handshake_request.go @@ -0,0 +1,33 @@ +package sarama + +type SaslHandshakeRequest struct { + Mechanism string +} + +func (r *SaslHandshakeRequest) encode(pe packetEncoder) error { + if err := pe.putString(r.Mechanism); err != nil { + return err + } + + return nil +} + +func (r *SaslHandshakeRequest) decode(pd packetDecoder, version int16) (err error) { + if r.Mechanism, err = pd.getString(); err != nil { + return err + } + + return nil +} + +func (r *SaslHandshakeRequest) key() int16 { + return 17 +} + +func (r *SaslHandshakeRequest) version() int16 { + return 0 +} + +func (r *SaslHandshakeRequest) requiredVersion() KafkaVersion { + return V0_10_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/sasl_handshake_request_test.go b/vendor/src/github.com/Shopify/sarama/sasl_handshake_request_test.go new file mode 100644 index 00000000..806e628f --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sasl_handshake_request_test.go @@ -0,0 +1,17 @@ +package sarama + +import "testing" + +var ( + baseSaslRequest = []byte{ + 0, 3, 'f', 'o', 'o', // Mechanism + } +) + +func TestSaslHandshakeRequest(t *testing.T) { + var request *SaslHandshakeRequest + + request = new(SaslHandshakeRequest) + request.Mechanism = "foo" + testRequest(t, "basic", request, baseSaslRequest) +} diff --git a/vendor/src/github.com/Shopify/sarama/sasl_handshake_response.go b/vendor/src/github.com/Shopify/sarama/sasl_handshake_response.go new file mode 100644 index 00000000..8379bbb2 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sasl_handshake_response.go @@ -0,0 +1,38 @@ +package sarama + +type SaslHandshakeResponse struct { + Err KError + EnabledMechanisms []string +} + +func (r *SaslHandshakeResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + return pe.putStringArray(r.EnabledMechanisms) +} + +func (r *SaslHandshakeResponse) decode(pd packetDecoder, version int16) error { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + var err error + if r.EnabledMechanisms, err = pd.getStringArray(); err != nil { + return err + } + + return nil +} + +func (r *SaslHandshakeResponse) key() int16 { + return 17 +} + +func (r *SaslHandshakeResponse) version() int16 { + return 0 +} + +func (r *SaslHandshakeResponse) requiredVersion() KafkaVersion { + return V0_10_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/sasl_handshake_response_test.go b/vendor/src/github.com/Shopify/sarama/sasl_handshake_response_test.go new file mode 100644 index 00000000..1fd4c79e --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sasl_handshake_response_test.go @@ -0,0 +1,24 @@ +package sarama + +import "testing" + +var ( + saslHandshakeResponse = []byte{ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x03, 'f', 'o', 'o', + } +) + +func TestSaslHandshakeResponse(t *testing.T) { + var response *SaslHandshakeResponse + + response = new(SaslHandshakeResponse) + testVersionDecodable(t, "no error", response, saslHandshakeResponse, 0) + if response.Err != ErrNoError { + t.Error("Decoding error failed: no error expected but found", response.Err) + } + if response.EnabledMechanisms[0] != "foo" { + t.Error("Decoding error failed: expected 'foo' but found", response.EnabledMechanisms) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/sync_group_request.go b/vendor/src/github.com/Shopify/sarama/sync_group_request.go new file mode 100644 index 00000000..fe207080 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sync_group_request.go @@ -0,0 +1,100 @@ +package sarama + +type SyncGroupRequest struct { + GroupId string + GenerationId int32 + MemberId string + GroupAssignments map[string][]byte +} + +func (r *SyncGroupRequest) encode(pe packetEncoder) error { + if err := pe.putString(r.GroupId); err != nil { + return err + } + + pe.putInt32(r.GenerationId) + + if err := pe.putString(r.MemberId); err != nil { + return err + } + + if err := pe.putArrayLength(len(r.GroupAssignments)); err != nil { + return err + } + for memberId, memberAssignment := range r.GroupAssignments { + if err := pe.putString(memberId); err != nil { + return err + } + if err := pe.putBytes(memberAssignment); err != nil { + return err + } + } + + return nil +} + +func (r *SyncGroupRequest) decode(pd packetDecoder, version int16) (err error) { + if r.GroupId, err = pd.getString(); err != nil { + return + } + if r.GenerationId, err = pd.getInt32(); err != nil { + return + } + if r.MemberId, err = pd.getString(); err != nil { + return + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + if n == 0 { + return nil + } + + r.GroupAssignments = make(map[string][]byte) + for i := 0; i < n; i++ { + memberId, err := pd.getString() + if err != nil { + return err + } + memberAssignment, err := pd.getBytes() + if err != nil { + return err + } + + r.GroupAssignments[memberId] = memberAssignment + } + + return nil +} + +func (r *SyncGroupRequest) key() int16 { + return 14 +} + +func (r *SyncGroupRequest) version() int16 { + return 0 +} + +func (r *SyncGroupRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} + +func (r *SyncGroupRequest) AddGroupAssignment(memberId string, memberAssignment []byte) { + if r.GroupAssignments == nil { + r.GroupAssignments = make(map[string][]byte) + } + + r.GroupAssignments[memberId] = memberAssignment +} + +func (r *SyncGroupRequest) AddGroupAssignmentMember(memberId string, memberAssignment *ConsumerGroupMemberAssignment) error { + bin, err := encode(memberAssignment, nil) + if err != nil { + return err + } + + r.AddGroupAssignment(memberId, bin) + return nil +} diff --git a/vendor/src/github.com/Shopify/sarama/sync_group_request_test.go b/vendor/src/github.com/Shopify/sarama/sync_group_request_test.go new file mode 100644 index 00000000..3f537ef9 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sync_group_request_test.go @@ -0,0 +1,38 @@ +package sarama + +import "testing" + +var ( + emptySyncGroupRequest = []byte{ + 0, 3, 'f', 'o', 'o', // Group ID + 0x00, 0x01, 0x02, 0x03, // Generation ID + 0, 3, 'b', 'a', 'z', // Member ID + 0, 0, 0, 0, // no assignments + } + + populatedSyncGroupRequest = []byte{ + 0, 3, 'f', 'o', 'o', // Group ID + 0x00, 0x01, 0x02, 0x03, // Generation ID + 0, 3, 'b', 'a', 'z', // Member ID + 0, 0, 0, 1, // one assignment + 0, 3, 'b', 'a', 'z', // Member ID + 0, 0, 0, 3, 'f', 'o', 'o', // Member assignment + } +) + +func TestSyncGroupRequest(t *testing.T) { + var request *SyncGroupRequest + + request = new(SyncGroupRequest) + request.GroupId = "foo" + request.GenerationId = 66051 + request.MemberId = "baz" + testRequest(t, "empty", request, emptySyncGroupRequest) + + request = new(SyncGroupRequest) + request.GroupId = "foo" + request.GenerationId = 66051 + request.MemberId = "baz" + request.AddGroupAssignment("baz", []byte("foo")) + testRequest(t, "populated", request, populatedSyncGroupRequest) +} diff --git a/vendor/src/github.com/Shopify/sarama/sync_group_response.go b/vendor/src/github.com/Shopify/sarama/sync_group_response.go new file mode 100644 index 00000000..12aef673 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sync_group_response.go @@ -0,0 +1,40 @@ +package sarama + +type SyncGroupResponse struct { + Err KError + MemberAssignment []byte +} + +func (r *SyncGroupResponse) GetMemberAssignment() (*ConsumerGroupMemberAssignment, error) { + assignment := new(ConsumerGroupMemberAssignment) + err := decode(r.MemberAssignment, assignment) + return assignment, err +} + +func (r *SyncGroupResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + return pe.putBytes(r.MemberAssignment) +} + +func (r *SyncGroupResponse) decode(pd packetDecoder, version int16) (err error) { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + r.MemberAssignment, err = pd.getBytes() + return +} + +func (r *SyncGroupResponse) key() int16 { + return 14 +} + +func (r *SyncGroupResponse) version() int16 { + return 0 +} + +func (r *SyncGroupResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/github.com/Shopify/sarama/sync_group_response_test.go b/vendor/src/github.com/Shopify/sarama/sync_group_response_test.go new file mode 100644 index 00000000..6fb70885 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sync_group_response_test.go @@ -0,0 +1,40 @@ +package sarama + +import ( + "reflect" + "testing" +) + +var ( + syncGroupResponseNoError = []byte{ + 0x00, 0x00, // No error + 0, 0, 0, 3, 0x01, 0x02, 0x03, // Member assignment data + } + + syncGroupResponseWithError = []byte{ + 0, 27, // ErrRebalanceInProgress + 0, 0, 0, 0, // No member assignment data + } +) + +func TestSyncGroupResponse(t *testing.T) { + var response *SyncGroupResponse + + response = new(SyncGroupResponse) + testVersionDecodable(t, "no error", response, syncGroupResponseNoError, 0) + if response.Err != ErrNoError { + t.Error("Decoding Err failed: no error expected but found", response.Err) + } + if !reflect.DeepEqual(response.MemberAssignment, []byte{0x01, 0x02, 0x03}) { + t.Error("Decoding MemberAssignment failed, found:", response.MemberAssignment) + } + + response = new(SyncGroupResponse) + testVersionDecodable(t, "no error", response, syncGroupResponseWithError, 0) + if response.Err != ErrRebalanceInProgress { + t.Error("Decoding Err failed: ErrRebalanceInProgress expected but found", response.Err) + } + if !reflect.DeepEqual(response.MemberAssignment, []byte{}) { + t.Error("Decoding MemberAssignment failed, found:", response.MemberAssignment) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/sync_producer.go b/vendor/src/github.com/Shopify/sarama/sync_producer.go new file mode 100644 index 00000000..c77ae314 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sync_producer.go @@ -0,0 +1,164 @@ +package sarama + +import "sync" + +// SyncProducer publishes Kafka messages, blocking until they have been acknowledged. It routes messages to the correct +// broker, refreshing metadata as appropriate, and parses responses for errors. You must call Close() on a producer +// to avoid leaks, it may not be garbage-collected automatically when it passes out of scope. +// +// The SyncProducer comes with two caveats: it will generally be less efficient than the AsyncProducer, and the actual +// durability guarantee provided when a message is acknowledged depend on the configured value of `Producer.RequiredAcks`. +// There are configurations where a message acknowledged by the SyncProducer can still sometimes be lost. +// +// For implementation reasons, the SyncProducer requires `Producer.Return.Errors` and `Producer.Return.Successes` to +// be set to true in its configuration. +type SyncProducer interface { + + // SendMessage produces a given message, and returns only when it either has + // succeeded or failed to produce. It will return the partition and the offset + // of the produced message, or an error if the message failed to produce. + SendMessage(msg *ProducerMessage) (partition int32, offset int64, err error) + + // SendMessages produces a given set of messages, and returns only when all + // messages in the set have either succeeded or failed. Note that messages + // can succeed and fail individually; if some succeed and some fail, + // SendMessages will return an error. + SendMessages(msgs []*ProducerMessage) error + + // Close shuts down the producer and flushes any messages it may have buffered. + // You must call this function before a producer object passes out of scope, as + // it may otherwise leak memory. You must call this before calling Close on the + // underlying client. + Close() error +} + +type syncProducer struct { + producer *asyncProducer + wg sync.WaitGroup +} + +// NewSyncProducer creates a new SyncProducer using the given broker addresses and configuration. +func NewSyncProducer(addrs []string, config *Config) (SyncProducer, error) { + if config == nil { + config = NewConfig() + config.Producer.Return.Successes = true + } + + if err := verifyProducerConfig(config); err != nil { + return nil, err + } + + p, err := NewAsyncProducer(addrs, config) + if err != nil { + return nil, err + } + return newSyncProducerFromAsyncProducer(p.(*asyncProducer)), nil +} + +// NewSyncProducerFromClient creates a new SyncProducer using the given client. It is still +// necessary to call Close() on the underlying client when shutting down this producer. +func NewSyncProducerFromClient(client Client) (SyncProducer, error) { + if err := verifyProducerConfig(client.Config()); err != nil { + return nil, err + } + + p, err := NewAsyncProducerFromClient(client) + if err != nil { + return nil, err + } + return newSyncProducerFromAsyncProducer(p.(*asyncProducer)), nil +} + +func newSyncProducerFromAsyncProducer(p *asyncProducer) *syncProducer { + sp := &syncProducer{producer: p} + + sp.wg.Add(2) + go withRecover(sp.handleSuccesses) + go withRecover(sp.handleErrors) + + return sp +} + +func verifyProducerConfig(config *Config) error { + if !config.Producer.Return.Errors { + return ConfigurationError("Producer.Return.Errors must be true to be used in a SyncProducer") + } + if !config.Producer.Return.Successes { + return ConfigurationError("Producer.Return.Successes must be true to be used in a SyncProducer") + } + return nil +} + +func (sp *syncProducer) SendMessage(msg *ProducerMessage) (partition int32, offset int64, err error) { + oldMetadata := msg.Metadata + defer func() { + msg.Metadata = oldMetadata + }() + + expectation := make(chan *ProducerError, 1) + msg.Metadata = expectation + sp.producer.Input() <- msg + + if err := <-expectation; err != nil { + return -1, -1, err.Err + } + + return msg.Partition, msg.Offset, nil +} + +func (sp *syncProducer) SendMessages(msgs []*ProducerMessage) error { + savedMetadata := make([]interface{}, len(msgs)) + for i := range msgs { + savedMetadata[i] = msgs[i].Metadata + } + defer func() { + for i := range msgs { + msgs[i].Metadata = savedMetadata[i] + } + }() + + expectations := make(chan chan *ProducerError, len(msgs)) + go func() { + for _, msg := range msgs { + expectation := make(chan *ProducerError, 1) + msg.Metadata = expectation + sp.producer.Input() <- msg + expectations <- expectation + } + close(expectations) + }() + + var errors ProducerErrors + for expectation := range expectations { + if err := <-expectation; err != nil { + errors = append(errors, err) + } + } + + if len(errors) > 0 { + return errors + } + return nil +} + +func (sp *syncProducer) handleSuccesses() { + defer sp.wg.Done() + for msg := range sp.producer.Successes() { + expectation := msg.Metadata.(chan *ProducerError) + expectation <- nil + } +} + +func (sp *syncProducer) handleErrors() { + defer sp.wg.Done() + for err := range sp.producer.Errors() { + expectation := err.Msg.Metadata.(chan *ProducerError) + expectation <- err + } +} + +func (sp *syncProducer) Close() error { + sp.producer.AsyncClose() + sp.wg.Wait() + return nil +} diff --git a/vendor/src/github.com/Shopify/sarama/sync_producer_test.go b/vendor/src/github.com/Shopify/sarama/sync_producer_test.go new file mode 100644 index 00000000..c1519a14 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/sync_producer_test.go @@ -0,0 +1,199 @@ +package sarama + +import ( + "log" + "sync" + "testing" +) + +func TestSyncProducer(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + for i := 0; i < 10; i++ { + leader.Returns(prodSuccess) + } + + producer, err := NewSyncProducer([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + msg := &ProducerMessage{ + Topic: "my_topic", + Value: StringEncoder(TestMessage), + Metadata: "test", + } + + partition, offset, err := producer.SendMessage(msg) + + if partition != 0 || msg.Partition != partition { + t.Error("Unexpected partition") + } + if offset != 0 || msg.Offset != offset { + t.Error("Unexpected offset") + } + if str, ok := msg.Metadata.(string); !ok || str != "test" { + t.Error("Unexpected metadata") + } + if err != nil { + t.Error(err) + } + } + + safeClose(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestSyncProducerBatch(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + + config := NewConfig() + config.Producer.Flush.Messages = 3 + config.Producer.Return.Successes = true + producer, err := NewSyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + err = producer.SendMessages([]*ProducerMessage{ + &ProducerMessage{ + Topic: "my_topic", + Value: StringEncoder(TestMessage), + Metadata: "test", + }, + &ProducerMessage{ + Topic: "my_topic", + Value: StringEncoder(TestMessage), + Metadata: "test", + }, + &ProducerMessage{ + Topic: "my_topic", + Value: StringEncoder(TestMessage), + Metadata: "test", + }, + }) + + if err != nil { + t.Error(err) + } + + safeClose(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestConcurrentSyncProducer(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + + config := NewConfig() + config.Producer.Flush.Messages = 100 + config.Producer.Return.Successes = true + producer, err := NewSyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + wg := sync.WaitGroup{} + + for i := 0; i < 100; i++ { + wg.Add(1) + go func() { + msg := &ProducerMessage{Topic: "my_topic", Value: StringEncoder(TestMessage)} + partition, _, err := producer.SendMessage(msg) + if partition != 0 { + t.Error("Unexpected partition") + } + if err != nil { + t.Error(err) + } + wg.Done() + }() + } + wg.Wait() + + safeClose(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestSyncProducerToNonExistingTopic(t *testing.T) { + broker := NewMockBroker(t, 1) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(broker.Addr(), broker.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, broker.BrokerID(), nil, nil, ErrNoError) + broker.Returns(metadataResponse) + + config := NewConfig() + config.Metadata.Retry.Max = 0 + config.Producer.Retry.Max = 0 + config.Producer.Return.Successes = true + + producer, err := NewSyncProducer([]string{broker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + metadataResponse = new(MetadataResponse) + metadataResponse.AddTopic("unknown", ErrUnknownTopicOrPartition) + broker.Returns(metadataResponse) + + _, _, err = producer.SendMessage(&ProducerMessage{Topic: "unknown"}) + if err != ErrUnknownTopicOrPartition { + t.Error("Uxpected ErrUnknownTopicOrPartition, found:", err) + } + + safeClose(t, producer) + broker.Close() +} + +// This example shows the basic usage pattern of the SyncProducer. +func ExampleSyncProducer() { + producer, err := NewSyncProducer([]string{"localhost:9092"}, nil) + if err != nil { + log.Fatalln(err) + } + defer func() { + if err := producer.Close(); err != nil { + log.Fatalln(err) + } + }() + + msg := &ProducerMessage{Topic: "my_topic", Value: StringEncoder("testing 123")} + partition, offset, err := producer.SendMessage(msg) + if err != nil { + log.Printf("FAILED to send message: %s\n", err) + } else { + log.Printf("> message sent to partition %d at offset %d\n", partition, offset) + } +} diff --git a/vendor/src/github.com/Shopify/sarama/tools/README.md b/vendor/src/github.com/Shopify/sarama/tools/README.md new file mode 100644 index 00000000..3464c4ad --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/tools/README.md @@ -0,0 +1,10 @@ +# Sarama tools + +This folder contains applications that are useful for exploration of your Kafka cluster, or instrumentation. +Some of these tools mirror tools that ship with Kafka, but these tools won't require installing the JVM to function. + +- [kafka-console-producer](./kafka-console-producer): a command line tool to produce a single message to your Kafka custer. +- [kafka-console-partitionconsumer](./kafka-console-partitionconsumer): (deprecated) a command line tool to consume a single partition of a topic on your Kafka cluster. +- [kafka-console-consumer](./kafka-console-consumer): a command line tool to consume arbitrary partitions of a topic on your Kafka cluster. + +To install all tools, run `go get github.com/Shopify/sarama/tools/...` diff --git a/vendor/src/github.com/Shopify/sarama/tools/kafka-console-consumer/README.md b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-consumer/README.md new file mode 100644 index 00000000..4e77f0b7 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-consumer/README.md @@ -0,0 +1,29 @@ +# kafka-console-consumer + +A simple command line tool to consume partitions of a topic and print the +messages on the standard output. + +### Installation + + go get github.com/Shopify/sarama/tools/kafka-console-consumer + +### Usage + + # Minimum invocation + kafka-console-consumer -topic=test -brokers=kafka1:9092 + + # It will pick up a KAFKA_PEERS environment variable + export KAFKA_PEERS=kafka1:9092,kafka2:9092,kafka3:9092 + kafka-console-consumer -topic=test + + # You can specify the offset you want to start at. It can be either + # `oldest`, `newest`. The default is `newest`. + kafka-console-consumer -topic=test -offset=oldest + kafka-console-consumer -topic=test -offset=newest + + # You can specify the partition(s) you want to consume as a comma-separated + # list. The default is `all`. + kafka-console-consumer -topic=test -partitions=1,2,3 + + # Display all command line options + kafka-console-consumer -help diff --git a/vendor/src/github.com/Shopify/sarama/tools/kafka-console-consumer/kafka-console-consumer.go b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-consumer/kafka-console-consumer.go new file mode 100644 index 00000000..0f1eb89a --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-consumer/kafka-console-consumer.go @@ -0,0 +1,145 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "os/signal" + "strconv" + "strings" + "sync" + + "github.com/Shopify/sarama" +) + +var ( + brokerList = flag.String("brokers", os.Getenv("KAFKA_PEERS"), "The comma separated list of brokers in the Kafka cluster") + topic = flag.String("topic", "", "REQUIRED: the topic to consume") + partitions = flag.String("partitions", "all", "The partitions to consume, can be 'all' or comma-separated numbers") + offset = flag.String("offset", "newest", "The offset to start with. Can be `oldest`, `newest`") + verbose = flag.Bool("verbose", false, "Whether to turn on sarama logging") + bufferSize = flag.Int("buffer-size", 256, "The buffer size of the message channel.") + + logger = log.New(os.Stderr, "", log.LstdFlags) +) + +func main() { + flag.Parse() + + if *brokerList == "" { + printUsageErrorAndExit("You have to provide -brokers as a comma-separated list, or set the KAFKA_PEERS environment variable.") + } + + if *topic == "" { + printUsageErrorAndExit("-topic is required") + } + + if *verbose { + sarama.Logger = logger + } + + var initialOffset int64 + switch *offset { + case "oldest": + initialOffset = sarama.OffsetOldest + case "newest": + initialOffset = sarama.OffsetNewest + default: + printUsageErrorAndExit("-offset should be `oldest` or `newest`") + } + + c, err := sarama.NewConsumer(strings.Split(*brokerList, ","), nil) + if err != nil { + printErrorAndExit(69, "Failed to start consumer: %s", err) + } + + partitionList, err := getPartitions(c) + if err != nil { + printErrorAndExit(69, "Failed to get the list of partitions: %s", err) + } + + var ( + messages = make(chan *sarama.ConsumerMessage, *bufferSize) + closing = make(chan struct{}) + wg sync.WaitGroup + ) + + go func() { + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Kill, os.Interrupt) + <-signals + logger.Println("Initiating shutdown of consumer...") + close(closing) + }() + + for _, partition := range partitionList { + pc, err := c.ConsumePartition(*topic, partition, initialOffset) + if err != nil { + printErrorAndExit(69, "Failed to start consumer for partition %d: %s", partition, err) + } + + go func(pc sarama.PartitionConsumer) { + <-closing + pc.AsyncClose() + }(pc) + + wg.Add(1) + go func(pc sarama.PartitionConsumer) { + defer wg.Done() + for message := range pc.Messages() { + messages <- message + } + }(pc) + } + + go func() { + for msg := range messages { + fmt.Printf("Partition:\t%d\n", msg.Partition) + fmt.Printf("Offset:\t%d\n", msg.Offset) + fmt.Printf("Key:\t%s\n", string(msg.Key)) + fmt.Printf("Value:\t%s\n", string(msg.Value)) + fmt.Println() + } + }() + + wg.Wait() + logger.Println("Done consuming topic", *topic) + close(messages) + + if err := c.Close(); err != nil { + logger.Println("Failed to close consumer: ", err) + } +} + +func getPartitions(c sarama.Consumer) ([]int32, error) { + if *partitions == "all" { + return c.Partitions(*topic) + } + + tmp := strings.Split(*partitions, ",") + var pList []int32 + for i := range tmp { + val, err := strconv.ParseInt(tmp[i], 10, 32) + if err != nil { + return nil, err + } + pList = append(pList, int32(val)) + } + + return pList, nil +} + +func printErrorAndExit(code int, format string, values ...interface{}) { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", fmt.Sprintf(format, values...)) + fmt.Fprintln(os.Stderr) + os.Exit(code) +} + +func printUsageErrorAndExit(format string, values ...interface{}) { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", fmt.Sprintf(format, values...)) + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, "Available command line options:") + flag.PrintDefaults() + os.Exit(64) +} diff --git a/vendor/src/github.com/Shopify/sarama/tools/kafka-console-partitionconsumer/README.md b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-partitionconsumer/README.md new file mode 100644 index 00000000..646dd5f5 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-partitionconsumer/README.md @@ -0,0 +1,28 @@ +# kafka-console-partitionconsumer + +NOTE: this tool is deprecated in favour of the more general and more powerful +`kafka-console-consumer`. + +A simple command line tool to consume a partition of a topic and print the messages +on the standard output. + +### Installation + + go get github.com/Shopify/sarama/tools/kafka-console-partitionconsumer + +### Usage + + # Minimum invocation + kafka-console-partitionconsumer -topic=test -partition=4 -brokers=kafka1:9092 + + # It will pick up a KAFKA_PEERS environment variable + export KAFKA_PEERS=kafka1:9092,kafka2:9092,kafka3:9092 + kafka-console-partitionconsumer -topic=test -partition=4 + + # You can specify the offset you want to start at. It can be either + # `oldest`, `newest`, or a specific offset number + kafka-console-partitionconsumer -topic=test -partition=3 -offset=oldest + kafka-console-partitionconsumer -topic=test -partition=2 -offset=1337 + + # Display all command line options + kafka-console-partitionconsumer -help diff --git a/vendor/src/github.com/Shopify/sarama/tools/kafka-console-partitionconsumer/kafka-console-partitionconsumer.go b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-partitionconsumer/kafka-console-partitionconsumer.go new file mode 100644 index 00000000..d5e4464d --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-partitionconsumer/kafka-console-partitionconsumer.go @@ -0,0 +1,102 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "os/signal" + "strconv" + "strings" + + "github.com/Shopify/sarama" +) + +var ( + brokerList = flag.String("brokers", os.Getenv("KAFKA_PEERS"), "The comma separated list of brokers in the Kafka cluster") + topic = flag.String("topic", "", "REQUIRED: the topic to consume") + partition = flag.Int("partition", -1, "REQUIRED: the partition to consume") + offset = flag.String("offset", "newest", "The offset to start with. Can be `oldest`, `newest`, or an actual offset") + verbose = flag.Bool("verbose", false, "Whether to turn on sarama logging") + + logger = log.New(os.Stderr, "", log.LstdFlags) +) + +func main() { + flag.Parse() + + if *brokerList == "" { + printUsageErrorAndExit("You have to provide -brokers as a comma-separated list, or set the KAFKA_PEERS environment variable.") + } + + if *topic == "" { + printUsageErrorAndExit("-topic is required") + } + + if *partition == -1 { + printUsageErrorAndExit("-partition is required") + } + + if *verbose { + sarama.Logger = logger + } + + var ( + initialOffset int64 + offsetError error + ) + switch *offset { + case "oldest": + initialOffset = sarama.OffsetOldest + case "newest": + initialOffset = sarama.OffsetNewest + default: + initialOffset, offsetError = strconv.ParseInt(*offset, 10, 64) + } + + if offsetError != nil { + printUsageErrorAndExit("Invalid initial offset: %s", *offset) + } + + c, err := sarama.NewConsumer(strings.Split(*brokerList, ","), nil) + if err != nil { + printErrorAndExit(69, "Failed to start consumer: %s", err) + } + + pc, err := c.ConsumePartition(*topic, int32(*partition), initialOffset) + if err != nil { + printErrorAndExit(69, "Failed to start partition consumer: %s", err) + } + + go func() { + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Kill, os.Interrupt) + <-signals + pc.AsyncClose() + }() + + for msg := range pc.Messages() { + fmt.Printf("Offset:\t%d\n", msg.Offset) + fmt.Printf("Key:\t%s\n", string(msg.Key)) + fmt.Printf("Value:\t%s\n", string(msg.Value)) + fmt.Println() + } + + if err := c.Close(); err != nil { + logger.Println("Failed to close consumer: ", err) + } +} + +func printErrorAndExit(code int, format string, values ...interface{}) { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", fmt.Sprintf(format, values...)) + fmt.Fprintln(os.Stderr) + os.Exit(code) +} + +func printUsageErrorAndExit(format string, values ...interface{}) { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", fmt.Sprintf(format, values...)) + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, "Available command line options:") + flag.PrintDefaults() + os.Exit(64) +} diff --git a/vendor/src/github.com/Shopify/sarama/tools/kafka-console-producer/README.md b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-producer/README.md new file mode 100644 index 00000000..6b3a65f2 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-producer/README.md @@ -0,0 +1,34 @@ +# kafka-console-producer + +A simple command line tool to produce a single message to Kafka. + +### Installation + + go get github.com/Shopify/sarama/tools/kafka-console-producer + + +### Usage + + # Minimum invocation + kafka-console-producer -topic=test -value=value -brokers=kafka1:9092 + + # It will pick up a KAFKA_PEERS environment variable + export KAFKA_PEERS=kafka1:9092,kafka2:9092,kafka3:9092 + kafka-console-producer -topic=test -value=value + + # It will read the value from stdin by using pipes + echo "hello world" | kafka-console-producer -topic=test + + # Specify a key: + echo "hello world" | kafka-console-producer -topic=test -key=key + + # Partitioning: by default, kafka-console-producer will partition as follows: + # - manual partitioning if a -partition is provided + # - hash partitioning by key if a -key is provided + # - random partioning otherwise. + # + # You can override this using the -partitioner argument: + echo "hello world" | kafka-console-producer -topic=test -key=key -partitioner=random + + # Display all command line options + kafka-console-producer -help diff --git a/vendor/src/github.com/Shopify/sarama/tools/kafka-console-producer/kafka-console-producer.go b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-producer/kafka-console-producer.go new file mode 100644 index 00000000..83054ed7 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/tools/kafka-console-producer/kafka-console-producer.go @@ -0,0 +1,124 @@ +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "strings" + + "github.com/Shopify/sarama" + "github.com/rcrowley/go-metrics" +) + +var ( + brokerList = flag.String("brokers", os.Getenv("KAFKA_PEERS"), "The comma separated list of brokers in the Kafka cluster. You can also set the KAFKA_PEERS environment variable") + topic = flag.String("topic", "", "REQUIRED: the topic to produce to") + key = flag.String("key", "", "The key of the message to produce. Can be empty.") + value = flag.String("value", "", "REQUIRED: the value of the message to produce. You can also provide the value on stdin.") + partitioner = flag.String("partitioner", "", "The partitioning scheme to use. Can be `hash`, `manual`, or `random`") + partition = flag.Int("partition", -1, "The partition to produce to.") + verbose = flag.Bool("verbose", false, "Turn on sarama logging to stderr") + showMetrics = flag.Bool("metrics", false, "Output metrics on successful publish to stderr") + silent = flag.Bool("silent", false, "Turn off printing the message's topic, partition, and offset to stdout") + + logger = log.New(os.Stderr, "", log.LstdFlags) +) + +func main() { + flag.Parse() + + if *brokerList == "" { + printUsageErrorAndExit("no -brokers specified. Alternatively, set the KAFKA_PEERS environment variable") + } + + if *topic == "" { + printUsageErrorAndExit("no -topic specified") + } + + if *verbose { + sarama.Logger = logger + } + + config := sarama.NewConfig() + config.Producer.RequiredAcks = sarama.WaitForAll + config.Producer.Return.Successes = true + + switch *partitioner { + case "": + if *partition >= 0 { + config.Producer.Partitioner = sarama.NewManualPartitioner + } else { + config.Producer.Partitioner = sarama.NewHashPartitioner + } + case "hash": + config.Producer.Partitioner = sarama.NewHashPartitioner + case "random": + config.Producer.Partitioner = sarama.NewRandomPartitioner + case "manual": + config.Producer.Partitioner = sarama.NewManualPartitioner + if *partition == -1 { + printUsageErrorAndExit("-partition is required when partitioning manually") + } + default: + printUsageErrorAndExit(fmt.Sprintf("Partitioner %s not supported.", *partitioner)) + } + + message := &sarama.ProducerMessage{Topic: *topic, Partition: int32(*partition)} + + if *key != "" { + message.Key = sarama.StringEncoder(*key) + } + + if *value != "" { + message.Value = sarama.StringEncoder(*value) + } else if stdinAvailable() { + bytes, err := ioutil.ReadAll(os.Stdin) + if err != nil { + printErrorAndExit(66, "Failed to read data from the standard input: %s", err) + } + message.Value = sarama.ByteEncoder(bytes) + } else { + printUsageErrorAndExit("-value is required, or you have to provide the value on stdin") + } + + producer, err := sarama.NewSyncProducer(strings.Split(*brokerList, ","), config) + if err != nil { + printErrorAndExit(69, "Failed to open Kafka producer: %s", err) + } + defer func() { + if err := producer.Close(); err != nil { + logger.Println("Failed to close Kafka producer cleanly:", err) + } + }() + + partition, offset, err := producer.SendMessage(message) + if err != nil { + printErrorAndExit(69, "Failed to produce message: %s", err) + } else if !*silent { + fmt.Printf("topic=%s\tpartition=%d\toffset=%d\n", *topic, partition, offset) + } + if *showMetrics { + metrics.WriteOnce(config.MetricRegistry, os.Stderr) + } +} + +func printErrorAndExit(code int, format string, values ...interface{}) { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", fmt.Sprintf(format, values...)) + fmt.Fprintln(os.Stderr) + os.Exit(code) +} + +func printUsageErrorAndExit(message string) { + fmt.Fprintln(os.Stderr, "ERROR:", message) + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, "Available command line options:") + flag.PrintDefaults() + os.Exit(64) +} + +func stdinAvailable() bool { + stat, _ := os.Stdin.Stat() + return (stat.Mode() & os.ModeCharDevice) == 0 +} diff --git a/vendor/src/github.com/Shopify/sarama/utils.go b/vendor/src/github.com/Shopify/sarama/utils.go new file mode 100644 index 00000000..3cbab2d9 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/utils.go @@ -0,0 +1,152 @@ +package sarama + +import ( + "bufio" + "net" + "sort" +) + +type none struct{} + +// make []int32 sortable so we can sort partition numbers +type int32Slice []int32 + +func (slice int32Slice) Len() int { + return len(slice) +} + +func (slice int32Slice) Less(i, j int) bool { + return slice[i] < slice[j] +} + +func (slice int32Slice) Swap(i, j int) { + slice[i], slice[j] = slice[j], slice[i] +} + +func dupeAndSort(input []int32) []int32 { + ret := make([]int32, 0, len(input)) + for _, val := range input { + ret = append(ret, val) + } + + sort.Sort(int32Slice(ret)) + return ret +} + +func withRecover(fn func()) { + defer func() { + handler := PanicHandler + if handler != nil { + if err := recover(); err != nil { + handler(err) + } + } + }() + + fn() +} + +func safeAsyncClose(b *Broker) { + tmp := b // local var prevents clobbering in goroutine + go withRecover(func() { + if connected, _ := tmp.Connected(); connected { + if err := tmp.Close(); err != nil { + Logger.Println("Error closing broker", tmp.ID(), ":", err) + } + } + }) +} + +// Encoder is a simple interface for any type that can be encoded as an array of bytes +// in order to be sent as the key or value of a Kafka message. Length() is provided as an +// optimization, and must return the same as len() on the result of Encode(). +type Encoder interface { + Encode() ([]byte, error) + Length() int +} + +// make strings and byte slices encodable for convenience so they can be used as keys +// and/or values in kafka messages + +// StringEncoder implements the Encoder interface for Go strings so that they can be used +// as the Key or Value in a ProducerMessage. +type StringEncoder string + +func (s StringEncoder) Encode() ([]byte, error) { + return []byte(s), nil +} + +func (s StringEncoder) Length() int { + return len(s) +} + +// ByteEncoder implements the Encoder interface for Go byte slices so that they can be used +// as the Key or Value in a ProducerMessage. +type ByteEncoder []byte + +func (b ByteEncoder) Encode() ([]byte, error) { + return b, nil +} + +func (b ByteEncoder) Length() int { + return len(b) +} + +// bufConn wraps a net.Conn with a buffer for reads to reduce the number of +// reads that trigger syscalls. +type bufConn struct { + net.Conn + buf *bufio.Reader +} + +func newBufConn(conn net.Conn) *bufConn { + return &bufConn{ + Conn: conn, + buf: bufio.NewReader(conn), + } +} + +func (bc *bufConn) Read(b []byte) (n int, err error) { + return bc.buf.Read(b) +} + +// KafkaVersion instances represent versions of the upstream Kafka broker. +type KafkaVersion struct { + // it's a struct rather than just typing the array directly to make it opaque and stop people + // generating their own arbitrary versions + version [4]uint +} + +func newKafkaVersion(major, minor, veryMinor, patch uint) KafkaVersion { + return KafkaVersion{ + version: [4]uint{major, minor, veryMinor, patch}, + } +} + +// IsAtLeast return true if and only if the version it is called on is +// greater than or equal to the version passed in: +// V1.IsAtLeast(V2) // false +// V2.IsAtLeast(V1) // true +func (v KafkaVersion) IsAtLeast(other KafkaVersion) bool { + for i := range v.version { + if v.version[i] > other.version[i] { + return true + } else if v.version[i] < other.version[i] { + return false + } + } + return true +} + +// Effective constants defining the supported kafka versions. +var ( + V0_8_2_0 = newKafkaVersion(0, 8, 2, 0) + V0_8_2_1 = newKafkaVersion(0, 8, 2, 1) + V0_8_2_2 = newKafkaVersion(0, 8, 2, 2) + V0_9_0_0 = newKafkaVersion(0, 9, 0, 0) + V0_9_0_1 = newKafkaVersion(0, 9, 0, 1) + V0_10_0_0 = newKafkaVersion(0, 10, 0, 0) + V0_10_0_1 = newKafkaVersion(0, 10, 0, 1) + V0_10_1_0 = newKafkaVersion(0, 10, 1, 0) + minVersion = V0_8_2_0 +) diff --git a/vendor/src/github.com/Shopify/sarama/utils_test.go b/vendor/src/github.com/Shopify/sarama/utils_test.go new file mode 100644 index 00000000..a9e09502 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/utils_test.go @@ -0,0 +1,21 @@ +package sarama + +import "testing" + +func TestVersionCompare(t *testing.T) { + if V0_8_2_0.IsAtLeast(V0_8_2_1) { + t.Error("0.8.2.0 >= 0.8.2.1") + } + if !V0_8_2_1.IsAtLeast(V0_8_2_0) { + t.Error("! 0.8.2.1 >= 0.8.2.0") + } + if !V0_8_2_0.IsAtLeast(V0_8_2_0) { + t.Error("! 0.8.2.0 >= 0.8.2.0") + } + if !V0_9_0_0.IsAtLeast(V0_8_2_1) { + t.Error("! 0.9.0.0 >= 0.8.2.1") + } + if V0_8_2_1.IsAtLeast(V0_10_0_0) { + t.Error("0.8.2.1 >= 0.10.0.0") + } +} diff --git a/vendor/src/github.com/Shopify/sarama/vagrant/boot_cluster.sh b/vendor/src/github.com/Shopify/sarama/vagrant/boot_cluster.sh new file mode 100644 index 00000000..95e47dde --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/vagrant/boot_cluster.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -ex + +# Launch and wait for toxiproxy +${REPOSITORY_ROOT}/vagrant/run_toxiproxy.sh & +while ! nc -q 1 localhost 2181 ${KAFKA_INSTALL_ROOT}/zookeeper-${ZK_PORT}/myid +done diff --git a/vendor/src/github.com/Shopify/sarama/vagrant/kafka.conf b/vendor/src/github.com/Shopify/sarama/vagrant/kafka.conf new file mode 100644 index 00000000..25101df5 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/vagrant/kafka.conf @@ -0,0 +1,9 @@ +start on started zookeeper-ZK_PORT +stop on stopping zookeeper-ZK_PORT + +# Use a script instead of exec (using env stanza leaks KAFKA_HEAP_OPTS from zookeeper) +script + sleep 2 + export KAFKA_HEAP_OPTS="-Xmx320m" + exec /opt/kafka-KAFKAID/bin/kafka-server-start.sh /opt/kafka-KAFKAID/config/server.properties +end script diff --git a/vendor/src/github.com/Shopify/sarama/vagrant/provision.sh b/vendor/src/github.com/Shopify/sarama/vagrant/provision.sh new file mode 100644 index 00000000..ace768f4 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/vagrant/provision.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +set -ex + +apt-get update +yes | apt-get install default-jre + +export KAFKA_INSTALL_ROOT=/opt +export KAFKA_HOSTNAME=192.168.100.67 +export KAFKA_VERSION=0.9.0.1 +export REPOSITORY_ROOT=/vagrant + +sh /vagrant/vagrant/install_cluster.sh +sh /vagrant/vagrant/setup_services.sh +sh /vagrant/vagrant/create_topics.sh diff --git a/vendor/src/github.com/Shopify/sarama/vagrant/run_toxiproxy.sh b/vendor/src/github.com/Shopify/sarama/vagrant/run_toxiproxy.sh new file mode 100644 index 00000000..e52c00e7 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/vagrant/run_toxiproxy.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -ex + +${KAFKA_INSTALL_ROOT}/toxiproxy -port 8474 -host 0.0.0.0 & +PID=$! + +while ! nc -q 1 localhost 8474 + +# The number of threads handling network requests +num.network.threads=2 + +# The number of threads doing disk I/O +num.io.threads=8 + +# The send buffer (SO_SNDBUF) used by the socket server +socket.send.buffer.bytes=1048576 + +# The receive buffer (SO_RCVBUF) used by the socket server +socket.receive.buffer.bytes=1048576 + +# The maximum size of a request that the socket server will accept (protection against OOM) +socket.request.max.bytes=104857600 + + +############################# Log Basics ############################# + +# A comma seperated list of directories under which to store log files +log.dirs=KAFKA_DATADIR + +# The default number of log partitions per topic. More partitions allow greater +# parallelism for consumption, but this will also result in more files across +# the brokers. +num.partitions=2 + +# Create new topics with a replication factor of 2 so failover can be tested +# more easily. +default.replication.factor=2 + +auto.create.topics.enable=false +delete.topic.enable=true + +############################# Log Flush Policy ############################# + +# Messages are immediately written to the filesystem but by default we only fsync() to sync +# the OS cache lazily. The following configurations control the flush of data to disk. +# There are a few important trade-offs here: +# 1. Durability: Unflushed data may be lost if you are not using replication. +# 2. Latency: Very large flush intervals may lead to latency spikes when the flush does occur as there will be a lot of data to flush. +# 3. Throughput: The flush is generally the most expensive operation, and a small flush interval may lead to exceessive seeks. +# The settings below allow one to configure the flush policy to flush data after a period of time or +# every N messages (or both). This can be done globally and overridden on a per-topic basis. + +# The number of messages to accept before forcing a flush of data to disk +#log.flush.interval.messages=10000 + +# The maximum amount of time a message can sit in a log before we force a flush +#log.flush.interval.ms=1000 + +############################# Log Retention Policy ############################# + +# The following configurations control the disposal of log segments. The policy can +# be set to delete segments after a period of time, or after a given size has accumulated. +# A segment will be deleted whenever *either* of these criteria are met. Deletion always happens +# from the end of the log. + +# The minimum age of a log file to be eligible for deletion +log.retention.hours=168 + +# A size-based retention policy for logs. Segments are pruned from the log as long as the remaining +# segments don't drop below log.retention.bytes. +log.retention.bytes=268435456 + +# The maximum size of a log segment file. When this size is reached a new log segment will be created. +log.segment.bytes=268435456 + +# The interval at which log segments are checked to see if they can be deleted according +# to the retention policies +log.retention.check.interval.ms=60000 + +# By default the log cleaner is disabled and the log retention policy will default to just delete segments after their retention expires. +# If log.cleaner.enable=true is set the cleaner will be enabled and individual logs can then be marked for log compaction. +log.cleaner.enable=false + +############################# Zookeeper ############################# + +# Zookeeper connection string (see zookeeper docs for details). +# This is a comma separated host:port pairs, each corresponding to a zk +# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002". +# You can also append an optional chroot string to the urls to specify the +# root directory for all kafka znodes. +zookeeper.connect=localhost:ZK_PORT + +# Timeout in ms for connecting to zookeeper +zookeeper.session.timeout.ms=3000 +zookeeper.connection.timeout.ms=3000 diff --git a/vendor/src/github.com/Shopify/sarama/vagrant/setup_services.sh b/vendor/src/github.com/Shopify/sarama/vagrant/setup_services.sh new file mode 100644 index 00000000..81d8ea05 --- /dev/null +++ b/vendor/src/github.com/Shopify/sarama/vagrant/setup_services.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +set -ex + +stop toxiproxy || true +cp ${REPOSITORY_ROOT}/vagrant/toxiproxy.conf /etc/init/toxiproxy.conf +cp ${REPOSITORY_ROOT}/vagrant/run_toxiproxy.sh ${KAFKA_INSTALL_ROOT}/ +start toxiproxy + +for i in 1 2 3 4 5; do + ZK_PORT=`expr $i + 2180` + KAFKA_PORT=`expr $i + 9090` + + stop zookeeper-${ZK_PORT} || true + + # set up zk service + cp ${REPOSITORY_ROOT}/vagrant/zookeeper.conf /etc/init/zookeeper-${ZK_PORT}.conf + sed -i s/KAFKAID/${KAFKA_PORT}/g /etc/init/zookeeper-${ZK_PORT}.conf + + # set up kafka service + cp ${REPOSITORY_ROOT}/vagrant/kafka.conf /etc/init/kafka-${KAFKA_PORT}.conf + sed -i s/KAFKAID/${KAFKA_PORT}/g /etc/init/kafka-${KAFKA_PORT}.conf + sed -i s/ZK_PORT/${ZK_PORT}/g /etc/init/kafka-${KAFKA_PORT}.conf + + start zookeeper-${ZK_PORT} +done + +# Wait for the last kafka node to finish booting +while ! nc -q 1 localhost 29095 +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is not running on Google App Engine, compiled by GopherJS, and +// "-tags safe" is not added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// +build !js,!appengine,!safe,!disableunsafe + +package spew + +import ( + "reflect" + "unsafe" +) + +const ( + // UnsafeDisabled is a build-time constant which specifies whether or + // not access to the unsafe package is available. + UnsafeDisabled = false + + // ptrSize is the size of a pointer on the current arch. + ptrSize = unsafe.Sizeof((*byte)(nil)) +) + +var ( + // offsetPtr, offsetScalar, and offsetFlag are the offsets for the + // internal reflect.Value fields. These values are valid before golang + // commit ecccf07e7f9d which changed the format. The are also valid + // after commit 82f48826c6c7 which changed the format again to mirror + // the original format. Code in the init function updates these offsets + // as necessary. + offsetPtr = uintptr(ptrSize) + offsetScalar = uintptr(0) + offsetFlag = uintptr(ptrSize * 2) + + // flagKindWidth and flagKindShift indicate various bits that the + // reflect package uses internally to track kind information. + // + // flagRO indicates whether or not the value field of a reflect.Value is + // read-only. + // + // flagIndir indicates whether the value field of a reflect.Value is + // the actual data or a pointer to the data. + // + // These values are valid before golang commit 90a7c3c86944 which + // changed their positions. Code in the init function updates these + // flags as necessary. + flagKindWidth = uintptr(5) + flagKindShift = uintptr(flagKindWidth - 1) + flagRO = uintptr(1 << 0) + flagIndir = uintptr(1 << 1) +) + +func init() { + // Older versions of reflect.Value stored small integers directly in the + // ptr field (which is named val in the older versions). Versions + // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named + // scalar for this purpose which unfortunately came before the flag + // field, so the offset of the flag field is different for those + // versions. + // + // This code constructs a new reflect.Value from a known small integer + // and checks if the size of the reflect.Value struct indicates it has + // the scalar field. When it does, the offsets are updated accordingly. + vv := reflect.ValueOf(0xf00) + if unsafe.Sizeof(vv) == (ptrSize * 4) { + offsetScalar = ptrSize * 2 + offsetFlag = ptrSize * 3 + } + + // Commit 90a7c3c86944 changed the flag positions such that the low + // order bits are the kind. This code extracts the kind from the flags + // field and ensures it's the correct type. When it's not, the flag + // order has been changed to the newer format, so the flags are updated + // accordingly. + upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) + upfv := *(*uintptr)(upf) + flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { + flagKindShift = 0 + flagRO = 1 << 5 + flagIndir = 1 << 6 + + // Commit adf9b30e5594 modified the flags to separate the + // flagRO flag into two bits which specifies whether or not the + // field is embedded. This causes flagIndir to move over a bit + // and means that flagRO is the combination of either of the + // original flagRO bit and the new bit. + // + // This code detects the change by extracting what used to be + // the indirect bit to ensure it's set. When it's not, the flag + // order has been changed to the newer format, so the flags are + // updated accordingly. + if upfv&flagIndir == 0 { + flagRO = 3 << 5 + flagIndir = 1 << 7 + } + } +} + +// unsafeReflectValue converts the passed reflect.Value into a one that bypasses +// the typical safety restrictions preventing access to unaddressable and +// unexported data. It works by digging the raw pointer to the underlying +// value out of the protected value and generating a new unprotected (unsafe) +// reflect.Value to it. +// +// This allows us to check for implementations of the Stringer and error +// interfaces to be used for pretty printing ordinarily unaddressable and +// inaccessible values such as unexported struct fields. +func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { + indirects := 1 + vt := v.Type() + upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) + rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) + if rvf&flagIndir != 0 { + vt = reflect.PtrTo(v.Type()) + indirects++ + } else if offsetScalar != 0 { + // The value is in the scalar field when it's not one of the + // reference types. + switch vt.Kind() { + case reflect.Uintptr: + case reflect.Chan: + case reflect.Func: + case reflect.Map: + case reflect.Ptr: + case reflect.UnsafePointer: + default: + upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + + offsetScalar) + } + } + + pv := reflect.NewAt(vt, upv) + rv = pv + for i := 0; i < indirects; i++ { + rv = rv.Elem() + } + return rv +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/src/github.com/davecgh/go-spew/spew/bypasssafe.go new file mode 100644 index 00000000..1fe3cf3d --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/bypasssafe.go @@ -0,0 +1,38 @@ +// Copyright (c) 2015-2016 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is running on Google App Engine, compiled by GopherJS, or +// "-tags safe" is added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// +build js appengine safe disableunsafe + +package spew + +import "reflect" + +const ( + // UnsafeDisabled is a build-time constant which specifies whether or + // not access to the unsafe package is available. + UnsafeDisabled = true +) + +// unsafeReflectValue typically converts the passed reflect.Value into a one +// that bypasses the typical safety restrictions preventing access to +// unaddressable and unexported data. However, doing this relies on access to +// the unsafe package. This is a stub version which simply returns the passed +// reflect.Value when the unsafe package is not available. +func unsafeReflectValue(v reflect.Value) reflect.Value { + return v +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/common.go b/vendor/src/github.com/davecgh/go-spew/spew/common.go new file mode 100644 index 00000000..7c519ff4 --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/common.go @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "reflect" + "sort" + "strconv" +) + +// Some constants in the form of bytes to avoid string overhead. This mirrors +// the technique used in the fmt package. +var ( + panicBytes = []byte("(PANIC=") + plusBytes = []byte("+") + iBytes = []byte("i") + trueBytes = []byte("true") + falseBytes = []byte("false") + interfaceBytes = []byte("(interface {})") + commaNewlineBytes = []byte(",\n") + newlineBytes = []byte("\n") + openBraceBytes = []byte("{") + openBraceNewlineBytes = []byte("{\n") + closeBraceBytes = []byte("}") + asteriskBytes = []byte("*") + colonBytes = []byte(":") + colonSpaceBytes = []byte(": ") + openParenBytes = []byte("(") + closeParenBytes = []byte(")") + spaceBytes = []byte(" ") + pointerChainBytes = []byte("->") + nilAngleBytes = []byte("") + maxNewlineBytes = []byte("\n") + maxShortBytes = []byte("") + circularBytes = []byte("") + circularShortBytes = []byte("") + invalidAngleBytes = []byte("") + openBracketBytes = []byte("[") + closeBracketBytes = []byte("]") + percentBytes = []byte("%") + precisionBytes = []byte(".") + openAngleBytes = []byte("<") + closeAngleBytes = []byte(">") + openMapBytes = []byte("map[") + closeMapBytes = []byte("]") + lenEqualsBytes = []byte("len=") + capEqualsBytes = []byte("cap=") +) + +// hexDigits is used to map a decimal value to a hex digit. +var hexDigits = "0123456789abcdef" + +// catchPanic handles any panics that might occur during the handleMethods +// calls. +func catchPanic(w io.Writer, v reflect.Value) { + if err := recover(); err != nil { + w.Write(panicBytes) + fmt.Fprintf(w, "%v", err) + w.Write(closeParenBytes) + } +} + +// handleMethods attempts to call the Error and String methods on the underlying +// type the passed reflect.Value represents and outputes the result to Writer w. +// +// It handles panics in any called methods by catching and displaying the error +// as the formatted value. +func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { + // We need an interface to check if the type implements the error or + // Stringer interface. However, the reflect package won't give us an + // interface on certain things like unexported struct fields in order + // to enforce visibility rules. We use unsafe, when it's available, + // to bypass these restrictions since this package does not mutate the + // values. + if !v.CanInterface() { + if UnsafeDisabled { + return false + } + + v = unsafeReflectValue(v) + } + + // Choose whether or not to do error and Stringer interface lookups against + // the base type or a pointer to the base type depending on settings. + // Technically calling one of these methods with a pointer receiver can + // mutate the value, however, types which choose to satisify an error or + // Stringer interface with a pointer receiver should not be mutating their + // state inside these interface methods. + if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { + v = unsafeReflectValue(v) + } + if v.CanAddr() { + v = v.Addr() + } + + // Is it an error or Stringer? + switch iface := v.Interface().(type) { + case error: + defer catchPanic(w, v) + if cs.ContinueOnMethod { + w.Write(openParenBytes) + w.Write([]byte(iface.Error())) + w.Write(closeParenBytes) + w.Write(spaceBytes) + return false + } + + w.Write([]byte(iface.Error())) + return true + + case fmt.Stringer: + defer catchPanic(w, v) + if cs.ContinueOnMethod { + w.Write(openParenBytes) + w.Write([]byte(iface.String())) + w.Write(closeParenBytes) + w.Write(spaceBytes) + return false + } + w.Write([]byte(iface.String())) + return true + } + return false +} + +// printBool outputs a boolean value as true or false to Writer w. +func printBool(w io.Writer, val bool) { + if val { + w.Write(trueBytes) + } else { + w.Write(falseBytes) + } +} + +// printInt outputs a signed integer value to Writer w. +func printInt(w io.Writer, val int64, base int) { + w.Write([]byte(strconv.FormatInt(val, base))) +} + +// printUint outputs an unsigned integer value to Writer w. +func printUint(w io.Writer, val uint64, base int) { + w.Write([]byte(strconv.FormatUint(val, base))) +} + +// printFloat outputs a floating point value using the specified precision, +// which is expected to be 32 or 64bit, to Writer w. +func printFloat(w io.Writer, val float64, precision int) { + w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) +} + +// printComplex outputs a complex value using the specified float precision +// for the real and imaginary parts to Writer w. +func printComplex(w io.Writer, c complex128, floatPrecision int) { + r := real(c) + w.Write(openParenBytes) + w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) + i := imag(c) + if i >= 0 { + w.Write(plusBytes) + } + w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) + w.Write(iBytes) + w.Write(closeParenBytes) +} + +// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' +// prefix to Writer w. +func printHexPtr(w io.Writer, p uintptr) { + // Null pointer. + num := uint64(p) + if num == 0 { + w.Write(nilAngleBytes) + return + } + + // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix + buf := make([]byte, 18) + + // It's simpler to construct the hex string right to left. + base := uint64(16) + i := len(buf) - 1 + for num >= base { + buf[i] = hexDigits[num%base] + num /= base + i-- + } + buf[i] = hexDigits[num] + + // Add '0x' prefix. + i-- + buf[i] = 'x' + i-- + buf[i] = '0' + + // Strip unused leading bytes. + buf = buf[i:] + w.Write(buf) +} + +// valuesSorter implements sort.Interface to allow a slice of reflect.Value +// elements to be sorted. +type valuesSorter struct { + values []reflect.Value + strings []string // either nil or same len and values + cs *ConfigState +} + +// newValuesSorter initializes a valuesSorter instance, which holds a set of +// surrogate keys on which the data should be sorted. It uses flags in +// ConfigState to decide if and how to populate those surrogate keys. +func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { + vs := &valuesSorter{values: values, cs: cs} + if canSortSimply(vs.values[0].Kind()) { + return vs + } + if !cs.DisableMethods { + vs.strings = make([]string, len(values)) + for i := range vs.values { + b := bytes.Buffer{} + if !handleMethods(cs, &b, vs.values[i]) { + vs.strings = nil + break + } + vs.strings[i] = b.String() + } + } + if vs.strings == nil && cs.SpewKeys { + vs.strings = make([]string, len(values)) + for i := range vs.values { + vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) + } + } + return vs +} + +// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted +// directly, or whether it should be considered for sorting by surrogate keys +// (if the ConfigState allows it). +func canSortSimply(kind reflect.Kind) bool { + // This switch parallels valueSortLess, except for the default case. + switch kind { + case reflect.Bool: + return true + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return true + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + case reflect.Uintptr: + return true + case reflect.Array: + return true + } + return false +} + +// Len returns the number of values in the slice. It is part of the +// sort.Interface implementation. +func (s *valuesSorter) Len() int { + return len(s.values) +} + +// Swap swaps the values at the passed indices. It is part of the +// sort.Interface implementation. +func (s *valuesSorter) Swap(i, j int) { + s.values[i], s.values[j] = s.values[j], s.values[i] + if s.strings != nil { + s.strings[i], s.strings[j] = s.strings[j], s.strings[i] + } +} + +// valueSortLess returns whether the first value should sort before the second +// value. It is used by valueSorter.Less as part of the sort.Interface +// implementation. +func valueSortLess(a, b reflect.Value) bool { + switch a.Kind() { + case reflect.Bool: + return !a.Bool() && b.Bool() + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return a.Int() < b.Int() + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return a.Uint() < b.Uint() + case reflect.Float32, reflect.Float64: + return a.Float() < b.Float() + case reflect.String: + return a.String() < b.String() + case reflect.Uintptr: + return a.Uint() < b.Uint() + case reflect.Array: + // Compare the contents of both arrays. + l := a.Len() + for i := 0; i < l; i++ { + av := a.Index(i) + bv := b.Index(i) + if av.Interface() == bv.Interface() { + continue + } + return valueSortLess(av, bv) + } + } + return a.String() < b.String() +} + +// Less returns whether the value at index i should sort before the +// value at index j. It is part of the sort.Interface implementation. +func (s *valuesSorter) Less(i, j int) bool { + if s.strings == nil { + return valueSortLess(s.values[i], s.values[j]) + } + return s.strings[i] < s.strings[j] +} + +// sortValues is a sort function that handles both native types and any type that +// can be converted to error or Stringer. Other inputs are sorted according to +// their Value.String() value to ensure display stability. +func sortValues(values []reflect.Value, cs *ConfigState) { + if len(values) == 0 { + return + } + sort.Sort(newValuesSorter(values, cs)) +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/common_test.go b/vendor/src/github.com/davecgh/go-spew/spew/common_test.go new file mode 100644 index 00000000..0f5ce47d --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/common_test.go @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew_test + +import ( + "fmt" + "reflect" + "testing" + + "github.com/davecgh/go-spew/spew" +) + +// custom type to test Stinger interface on non-pointer receiver. +type stringer string + +// String implements the Stringer interface for testing invocation of custom +// stringers on types with non-pointer receivers. +func (s stringer) String() string { + return "stringer " + string(s) +} + +// custom type to test Stinger interface on pointer receiver. +type pstringer string + +// String implements the Stringer interface for testing invocation of custom +// stringers on types with only pointer receivers. +func (s *pstringer) String() string { + return "stringer " + string(*s) +} + +// xref1 and xref2 are cross referencing structs for testing circular reference +// detection. +type xref1 struct { + ps2 *xref2 +} +type xref2 struct { + ps1 *xref1 +} + +// indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular +// reference for testing detection. +type indirCir1 struct { + ps2 *indirCir2 +} +type indirCir2 struct { + ps3 *indirCir3 +} +type indirCir3 struct { + ps1 *indirCir1 +} + +// embed is used to test embedded structures. +type embed struct { + a string +} + +// embedwrap is used to test embedded structures. +type embedwrap struct { + *embed + e *embed +} + +// panicer is used to intentionally cause a panic for testing spew properly +// handles them +type panicer int + +func (p panicer) String() string { + panic("test panic") +} + +// customError is used to test custom error interface invocation. +type customError int + +func (e customError) Error() string { + return fmt.Sprintf("error: %d", int(e)) +} + +// stringizeWants converts a slice of wanted test output into a format suitable +// for a test error message. +func stringizeWants(wants []string) string { + s := "" + for i, want := range wants { + if i > 0 { + s += fmt.Sprintf("want%d: %s", i+1, want) + } else { + s += "want: " + want + } + } + return s +} + +// testFailed returns whether or not a test failed by checking if the result +// of the test is in the slice of wanted strings. +func testFailed(result string, wants []string) bool { + for _, want := range wants { + if result == want { + return false + } + } + return true +} + +type sortableStruct struct { + x int +} + +func (ss sortableStruct) String() string { + return fmt.Sprintf("ss.%d", ss.x) +} + +type unsortableStruct struct { + x int +} + +type sortTestCase struct { + input []reflect.Value + expected []reflect.Value +} + +func helpTestSortValues(tests []sortTestCase, cs *spew.ConfigState, t *testing.T) { + getInterfaces := func(values []reflect.Value) []interface{} { + interfaces := []interface{}{} + for _, v := range values { + interfaces = append(interfaces, v.Interface()) + } + return interfaces + } + + for _, test := range tests { + spew.SortValues(test.input, cs) + // reflect.DeepEqual cannot really make sense of reflect.Value, + // probably because of all the pointer tricks. For instance, + // v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{} + // instead. + input := getInterfaces(test.input) + expected := getInterfaces(test.expected) + if !reflect.DeepEqual(input, expected) { + t.Errorf("Sort mismatch:\n %v != %v", input, expected) + } + } +} + +// TestSortValues ensures the sort functionality for relect.Value based sorting +// works as intended. +func TestSortValues(t *testing.T) { + v := reflect.ValueOf + + a := v("a") + b := v("b") + c := v("c") + embedA := v(embed{"a"}) + embedB := v(embed{"b"}) + embedC := v(embed{"c"}) + tests := []sortTestCase{ + // No values. + { + []reflect.Value{}, + []reflect.Value{}, + }, + // Bools. + { + []reflect.Value{v(false), v(true), v(false)}, + []reflect.Value{v(false), v(false), v(true)}, + }, + // Ints. + { + []reflect.Value{v(2), v(1), v(3)}, + []reflect.Value{v(1), v(2), v(3)}, + }, + // Uints. + { + []reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))}, + []reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))}, + }, + // Floats. + { + []reflect.Value{v(2.0), v(1.0), v(3.0)}, + []reflect.Value{v(1.0), v(2.0), v(3.0)}, + }, + // Strings. + { + []reflect.Value{b, a, c}, + []reflect.Value{a, b, c}, + }, + // Array + { + []reflect.Value{v([3]int{3, 2, 1}), v([3]int{1, 3, 2}), v([3]int{1, 2, 3})}, + []reflect.Value{v([3]int{1, 2, 3}), v([3]int{1, 3, 2}), v([3]int{3, 2, 1})}, + }, + // Uintptrs. + { + []reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))}, + []reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))}, + }, + // SortableStructs. + { + // Note: not sorted - DisableMethods is set. + []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, + []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, + }, + // UnsortableStructs. + { + // Note: not sorted - SpewKeys is false. + []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, + []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, + }, + // Invalid. + { + []reflect.Value{embedB, embedA, embedC}, + []reflect.Value{embedB, embedA, embedC}, + }, + } + cs := spew.ConfigState{DisableMethods: true, SpewKeys: false} + helpTestSortValues(tests, &cs, t) +} + +// TestSortValuesWithMethods ensures the sort functionality for relect.Value +// based sorting works as intended when using string methods. +func TestSortValuesWithMethods(t *testing.T) { + v := reflect.ValueOf + + a := v("a") + b := v("b") + c := v("c") + tests := []sortTestCase{ + // Ints. + { + []reflect.Value{v(2), v(1), v(3)}, + []reflect.Value{v(1), v(2), v(3)}, + }, + // Strings. + { + []reflect.Value{b, a, c}, + []reflect.Value{a, b, c}, + }, + // SortableStructs. + { + []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, + []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})}, + }, + // UnsortableStructs. + { + // Note: not sorted - SpewKeys is false. + []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, + []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, + }, + } + cs := spew.ConfigState{DisableMethods: false, SpewKeys: false} + helpTestSortValues(tests, &cs, t) +} + +// TestSortValuesWithSpew ensures the sort functionality for relect.Value +// based sorting works as intended when using spew to stringify keys. +func TestSortValuesWithSpew(t *testing.T) { + v := reflect.ValueOf + + a := v("a") + b := v("b") + c := v("c") + tests := []sortTestCase{ + // Ints. + { + []reflect.Value{v(2), v(1), v(3)}, + []reflect.Value{v(1), v(2), v(3)}, + }, + // Strings. + { + []reflect.Value{b, a, c}, + []reflect.Value{a, b, c}, + }, + // SortableStructs. + { + []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, + []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})}, + }, + // UnsortableStructs. + { + []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, + []reflect.Value{v(unsortableStruct{1}), v(unsortableStruct{2}), v(unsortableStruct{3})}, + }, + } + cs := spew.ConfigState{DisableMethods: true, SpewKeys: true} + helpTestSortValues(tests, &cs, t) +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/config.go b/vendor/src/github.com/davecgh/go-spew/spew/config.go new file mode 100644 index 00000000..2e3d22f3 --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/config.go @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "os" +) + +// ConfigState houses the configuration options used by spew to format and +// display values. There is a global instance, Config, that is used to control +// all top-level Formatter and Dump functionality. Each ConfigState instance +// provides methods equivalent to the top-level functions. +// +// The zero value for ConfigState provides no indentation. You would typically +// want to set it to a space or a tab. +// +// Alternatively, you can use NewDefaultConfig to get a ConfigState instance +// with default settings. See the documentation of NewDefaultConfig for default +// values. +type ConfigState struct { + // Indent specifies the string to use for each indentation level. The + // global config instance that all top-level functions use set this to a + // single space by default. If you would like more indentation, you might + // set this to a tab with "\t" or perhaps two spaces with " ". + Indent string + + // MaxDepth controls the maximum number of levels to descend into nested + // data structures. The default, 0, means there is no limit. + // + // NOTE: Circular data structures are properly detected, so it is not + // necessary to set this value unless you specifically want to limit deeply + // nested data structures. + MaxDepth int + + // DisableMethods specifies whether or not error and Stringer interfaces are + // invoked for types that implement them. + DisableMethods bool + + // DisablePointerMethods specifies whether or not to check for and invoke + // error and Stringer interfaces on types which only accept a pointer + // receiver when the current type is not a pointer. + // + // NOTE: This might be an unsafe action since calling one of these methods + // with a pointer receiver could technically mutate the value, however, + // in practice, types which choose to satisify an error or Stringer + // interface with a pointer receiver should not be mutating their state + // inside these interface methods. As a result, this option relies on + // access to the unsafe package, so it will not have any effect when + // running in environments without access to the unsafe package such as + // Google App Engine or with the "safe" build tag specified. + DisablePointerMethods bool + + // DisablePointerAddresses specifies whether to disable the printing of + // pointer addresses. This is useful when diffing data structures in tests. + DisablePointerAddresses bool + + // DisableCapacities specifies whether to disable the printing of capacities + // for arrays, slices, maps and channels. This is useful when diffing + // data structures in tests. + DisableCapacities bool + + // ContinueOnMethod specifies whether or not recursion should continue once + // a custom error or Stringer interface is invoked. The default, false, + // means it will print the results of invoking the custom error or Stringer + // interface and return immediately instead of continuing to recurse into + // the internals of the data type. + // + // NOTE: This flag does not have any effect if method invocation is disabled + // via the DisableMethods or DisablePointerMethods options. + ContinueOnMethod bool + + // SortKeys specifies map keys should be sorted before being printed. Use + // this to have a more deterministic, diffable output. Note that only + // native types (bool, int, uint, floats, uintptr and string) and types + // that support the error or Stringer interfaces (if methods are + // enabled) are supported, with other types sorted according to the + // reflect.Value.String() output which guarantees display stability. + SortKeys bool + + // SpewKeys specifies that, as a last resort attempt, map keys should + // be spewed to strings and sorted by those strings. This is only + // considered if SortKeys is true. + SpewKeys bool +} + +// Config is the active configuration of the top-level functions. +// The configuration can be changed by modifying the contents of spew.Config. +var Config = ConfigState{Indent: " "} + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the formatted string as a value that satisfies error. See NewFormatter +// for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, c.convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, c.convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, c.convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a Formatter interface returned by c.NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, c.convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Print(a ...interface{}) (n int, err error) { + return fmt.Print(c.convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, c.convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Println(a ...interface{}) (n int, err error) { + return fmt.Println(c.convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprint(a ...interface{}) string { + return fmt.Sprint(c.convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, c.convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a Formatter interface returned by c.NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintln(a ...interface{}) string { + return fmt.Sprintln(c.convertArgs(a)...) +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +c.Printf, c.Println, or c.Printf. +*/ +func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(c, v) +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { + fdump(c, w, a...) +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by modifying the public members +of c. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func (c *ConfigState) Dump(a ...interface{}) { + fdump(c, os.Stdout, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func (c *ConfigState) Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(c, &buf, a...) + return buf.String() +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a spew Formatter interface using +// the ConfigState associated with s. +func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = newFormatter(c, arg) + } + return formatters +} + +// NewDefaultConfig returns a ConfigState with the following default settings. +// +// Indent: " " +// MaxDepth: 0 +// DisableMethods: false +// DisablePointerMethods: false +// ContinueOnMethod: false +// SortKeys: false +func NewDefaultConfig() *ConfigState { + return &ConfigState{Indent: " "} +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/doc.go b/vendor/src/github.com/davecgh/go-spew/spew/doc.go new file mode 100644 index 00000000..aacaac6f --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/doc.go @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +Package spew implements a deep pretty printer for Go data structures to aid in +debugging. + +A quick overview of the additional features spew provides over the built-in +printing facilities for Go data types are as follows: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output (only when using + Dump style) + +There are two different approaches spew allows for dumping Go data structures: + + * Dump style which prints with newlines, customizable indentation, + and additional debug information such as types and all pointer addresses + used to indirect to the final value + * A custom Formatter interface that integrates cleanly with the standard fmt + package and replaces %v, %+v, %#v, and %#+v to provide inline printing + similar to the default %v while providing the additional functionality + outlined above and passing unsupported format verbs such as %x and %q + along to fmt + +Quick Start + +This section demonstrates how to quickly get started with spew. See the +sections below for further details on formatting and configuration options. + +To dump a variable with full newlines, indentation, type, and pointer +information use Dump, Fdump, or Sdump: + spew.Dump(myVar1, myVar2, ...) + spew.Fdump(someWriter, myVar1, myVar2, ...) + str := spew.Sdump(myVar1, myVar2, ...) + +Alternatively, if you would prefer to use format strings with a compacted inline +printing style, use the convenience wrappers Printf, Fprintf, etc with +%v (most compact), %+v (adds pointer addresses), %#v (adds types), or +%#+v (adds types and pointer addresses): + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +Configuration Options + +Configuration of spew is handled by fields in the ConfigState type. For +convenience, all of the top-level functions use a global state available +via the spew.Config global. + +It is also possible to create a ConfigState instance that provides methods +equivalent to the top-level functions. This allows concurrent configuration +options. See the ConfigState documentation for more details. + +The following configuration options are available: + * Indent + String to use for each indentation level for Dump functions. + It is a single space by default. A popular alternative is "\t". + + * MaxDepth + Maximum number of levels to descend into nested data structures. + There is no limit by default. + + * DisableMethods + Disables invocation of error and Stringer interface methods. + Method invocation is enabled by default. + + * DisablePointerMethods + Disables invocation of error and Stringer interface methods on types + which only accept pointer receivers from non-pointer variables. + Pointer method invocation is enabled by default. + + * DisablePointerAddresses + DisablePointerAddresses specifies whether to disable the printing of + pointer addresses. This is useful when diffing data structures in tests. + + * DisableCapacities + DisableCapacities specifies whether to disable the printing of + capacities for arrays, slices, maps and channels. This is useful when + diffing data structures in tests. + + * ContinueOnMethod + Enables recursion into types after invoking error and Stringer interface + methods. Recursion after method invocation is disabled by default. + + * SortKeys + Specifies map keys should be sorted before being printed. Use + this to have a more deterministic, diffable output. Note that + only native types (bool, int, uint, floats, uintptr and string) + and types which implement error or Stringer interfaces are + supported with other types sorted according to the + reflect.Value.String() output which guarantees display + stability. Natural map order is used by default. + + * SpewKeys + Specifies that, as a last resort attempt, map keys should be + spewed to strings and sorted by those strings. This is only + considered if SortKeys is true. + +Dump Usage + +Simply call spew.Dump with a list of variables you want to dump: + + spew.Dump(myVar1, myVar2, ...) + +You may also call spew.Fdump if you would prefer to output to an arbitrary +io.Writer. For example, to dump to standard error: + + spew.Fdump(os.Stderr, myVar1, myVar2, ...) + +A third option is to call spew.Sdump to get the formatted output as a string: + + str := spew.Sdump(myVar1, myVar2, ...) + +Sample Dump Output + +See the Dump example for details on the setup of the types and variables being +shown here. + + (main.Foo) { + unexportedField: (*main.Bar)(0xf84002e210)({ + flag: (main.Flag) flagTwo, + data: (uintptr) + }), + ExportedField: (map[interface {}]interface {}) (len=1) { + (string) (len=3) "one": (bool) true + } + } + +Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C +command as shown. + ([]uint8) (len=32 cap=32) { + 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | + 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| + 00000020 31 32 |12| + } + +Custom Formatter + +Spew provides a custom formatter that implements the fmt.Formatter interface +so that it integrates cleanly with standard fmt package printing functions. The +formatter is useful for inline printing of smaller data types similar to the +standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Custom Formatter Usage + +The simplest way to make use of the spew custom formatter is to call one of the +convenience functions such as spew.Printf, spew.Println, or spew.Printf. The +functions have syntax you are most likely already familiar with: + + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Println(myVar, myVar2) + spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +See the Index for the full list convenience functions. + +Sample Formatter Output + +Double pointer to a uint8: + %v: <**>5 + %+v: <**>(0xf8400420d0->0xf8400420c8)5 + %#v: (**uint8)5 + %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 + +Pointer to circular struct with a uint8 field and a pointer to itself: + %v: <*>{1 <*>} + %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} + %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} + %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} + +See the Printf example for details on the setup of variables being shown +here. + +Errors + +Since it is possible for custom Stringer/error interfaces to panic, spew +detects them and handles them internally by printing the panic information +inline with the output. Since spew is intended to provide deep pretty printing +capabilities on structures, it intentionally does not return any errors. +*/ +package spew diff --git a/vendor/src/github.com/davecgh/go-spew/spew/dump.go b/vendor/src/github.com/davecgh/go-spew/spew/dump.go new file mode 100644 index 00000000..df1d582a --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/dump.go @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "encoding/hex" + "fmt" + "io" + "os" + "reflect" + "regexp" + "strconv" + "strings" +) + +var ( + // uint8Type is a reflect.Type representing a uint8. It is used to + // convert cgo types to uint8 slices for hexdumping. + uint8Type = reflect.TypeOf(uint8(0)) + + // cCharRE is a regular expression that matches a cgo char. + // It is used to detect character arrays to hexdump them. + cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") + + // cUnsignedCharRE is a regular expression that matches a cgo unsigned + // char. It is used to detect unsigned character arrays to hexdump + // them. + cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") + + // cUint8tCharRE is a regular expression that matches a cgo uint8_t. + // It is used to detect uint8_t arrays to hexdump them. + cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") +) + +// dumpState contains information about the state of a dump operation. +type dumpState struct { + w io.Writer + depth int + pointers map[uintptr]int + ignoreNextType bool + ignoreNextIndent bool + cs *ConfigState +} + +// indent performs indentation according to the depth level and cs.Indent +// option. +func (d *dumpState) indent() { + if d.ignoreNextIndent { + d.ignoreNextIndent = false + return + } + d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) +} + +// unpackValue returns values inside of non-nil interfaces when possible. +// This is useful for data types like structs, arrays, slices, and maps which +// can contain varying types packed inside an interface. +func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { + if v.Kind() == reflect.Interface && !v.IsNil() { + v = v.Elem() + } + return v +} + +// dumpPtr handles formatting of pointers by indirecting them as necessary. +func (d *dumpState) dumpPtr(v reflect.Value) { + // Remove pointers at or below the current depth from map used to detect + // circular refs. + for k, depth := range d.pointers { + if depth >= d.depth { + delete(d.pointers, k) + } + } + + // Keep list of all dereferenced pointers to show later. + pointerChain := make([]uintptr, 0) + + // Figure out how many levels of indirection there are by dereferencing + // pointers and unpacking interfaces down the chain while detecting circular + // references. + nilFound := false + cycleFound := false + indirects := 0 + ve := v + for ve.Kind() == reflect.Ptr { + if ve.IsNil() { + nilFound = true + break + } + indirects++ + addr := ve.Pointer() + pointerChain = append(pointerChain, addr) + if pd, ok := d.pointers[addr]; ok && pd < d.depth { + cycleFound = true + indirects-- + break + } + d.pointers[addr] = d.depth + + ve = ve.Elem() + if ve.Kind() == reflect.Interface { + if ve.IsNil() { + nilFound = true + break + } + ve = ve.Elem() + } + } + + // Display type information. + d.w.Write(openParenBytes) + d.w.Write(bytes.Repeat(asteriskBytes, indirects)) + d.w.Write([]byte(ve.Type().String())) + d.w.Write(closeParenBytes) + + // Display pointer information. + if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { + d.w.Write(openParenBytes) + for i, addr := range pointerChain { + if i > 0 { + d.w.Write(pointerChainBytes) + } + printHexPtr(d.w, addr) + } + d.w.Write(closeParenBytes) + } + + // Display dereferenced value. + d.w.Write(openParenBytes) + switch { + case nilFound == true: + d.w.Write(nilAngleBytes) + + case cycleFound == true: + d.w.Write(circularBytes) + + default: + d.ignoreNextType = true + d.dump(ve) + } + d.w.Write(closeParenBytes) +} + +// dumpSlice handles formatting of arrays and slices. Byte (uint8 under +// reflection) arrays and slices are dumped in hexdump -C fashion. +func (d *dumpState) dumpSlice(v reflect.Value) { + // Determine whether this type should be hex dumped or not. Also, + // for types which should be hexdumped, try to use the underlying data + // first, then fall back to trying to convert them to a uint8 slice. + var buf []uint8 + doConvert := false + doHexDump := false + numEntries := v.Len() + if numEntries > 0 { + vt := v.Index(0).Type() + vts := vt.String() + switch { + // C types that need to be converted. + case cCharRE.MatchString(vts): + fallthrough + case cUnsignedCharRE.MatchString(vts): + fallthrough + case cUint8tCharRE.MatchString(vts): + doConvert = true + + // Try to use existing uint8 slices and fall back to converting + // and copying if that fails. + case vt.Kind() == reflect.Uint8: + // We need an addressable interface to convert the type + // to a byte slice. However, the reflect package won't + // give us an interface on certain things like + // unexported struct fields in order to enforce + // visibility rules. We use unsafe, when available, to + // bypass these restrictions since this package does not + // mutate the values. + vs := v + if !vs.CanInterface() || !vs.CanAddr() { + vs = unsafeReflectValue(vs) + } + if !UnsafeDisabled { + vs = vs.Slice(0, numEntries) + + // Use the existing uint8 slice if it can be + // type asserted. + iface := vs.Interface() + if slice, ok := iface.([]uint8); ok { + buf = slice + doHexDump = true + break + } + } + + // The underlying data needs to be converted if it can't + // be type asserted to a uint8 slice. + doConvert = true + } + + // Copy and convert the underlying type if needed. + if doConvert && vt.ConvertibleTo(uint8Type) { + // Convert and copy each element into a uint8 byte + // slice. + buf = make([]uint8, numEntries) + for i := 0; i < numEntries; i++ { + vv := v.Index(i) + buf[i] = uint8(vv.Convert(uint8Type).Uint()) + } + doHexDump = true + } + } + + // Hexdump the entire slice as needed. + if doHexDump { + indent := strings.Repeat(d.cs.Indent, d.depth) + str := indent + hex.Dump(buf) + str = strings.Replace(str, "\n", "\n"+indent, -1) + str = strings.TrimRight(str, d.cs.Indent) + d.w.Write([]byte(str)) + return + } + + // Recursively call dump for each item. + for i := 0; i < numEntries; i++ { + d.dump(d.unpackValue(v.Index(i))) + if i < (numEntries - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } +} + +// dump is the main workhorse for dumping a value. It uses the passed reflect +// value to figure out what kind of object we are dealing with and formats it +// appropriately. It is a recursive function, however circular data structures +// are detected and handled properly. +func (d *dumpState) dump(v reflect.Value) { + // Handle invalid reflect values immediately. + kind := v.Kind() + if kind == reflect.Invalid { + d.w.Write(invalidAngleBytes) + return + } + + // Handle pointers specially. + if kind == reflect.Ptr { + d.indent() + d.dumpPtr(v) + return + } + + // Print type information unless already handled elsewhere. + if !d.ignoreNextType { + d.indent() + d.w.Write(openParenBytes) + d.w.Write([]byte(v.Type().String())) + d.w.Write(closeParenBytes) + d.w.Write(spaceBytes) + } + d.ignoreNextType = false + + // Display length and capacity if the built-in len and cap functions + // work with the value's kind and the len/cap itself is non-zero. + valueLen, valueCap := 0, 0 + switch v.Kind() { + case reflect.Array, reflect.Slice, reflect.Chan: + valueLen, valueCap = v.Len(), v.Cap() + case reflect.Map, reflect.String: + valueLen = v.Len() + } + if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { + d.w.Write(openParenBytes) + if valueLen != 0 { + d.w.Write(lenEqualsBytes) + printInt(d.w, int64(valueLen), 10) + } + if !d.cs.DisableCapacities && valueCap != 0 { + if valueLen != 0 { + d.w.Write(spaceBytes) + } + d.w.Write(capEqualsBytes) + printInt(d.w, int64(valueCap), 10) + } + d.w.Write(closeParenBytes) + d.w.Write(spaceBytes) + } + + // Call Stringer/error interfaces if they exist and the handle methods flag + // is enabled + if !d.cs.DisableMethods { + if (kind != reflect.Invalid) && (kind != reflect.Interface) { + if handled := handleMethods(d.cs, d.w, v); handled { + return + } + } + } + + switch kind { + case reflect.Invalid: + // Do nothing. We should never get here since invalid has already + // been handled above. + + case reflect.Bool: + printBool(d.w, v.Bool()) + + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + printInt(d.w, v.Int(), 10) + + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + printUint(d.w, v.Uint(), 10) + + case reflect.Float32: + printFloat(d.w, v.Float(), 32) + + case reflect.Float64: + printFloat(d.w, v.Float(), 64) + + case reflect.Complex64: + printComplex(d.w, v.Complex(), 32) + + case reflect.Complex128: + printComplex(d.w, v.Complex(), 64) + + case reflect.Slice: + if v.IsNil() { + d.w.Write(nilAngleBytes) + break + } + fallthrough + + case reflect.Array: + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + d.dumpSlice(v) + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.String: + d.w.Write([]byte(strconv.Quote(v.String()))) + + case reflect.Interface: + // The only time we should get here is for nil interfaces due to + // unpackValue calls. + if v.IsNil() { + d.w.Write(nilAngleBytes) + } + + case reflect.Ptr: + // Do nothing. We should never get here since pointers have already + // been handled above. + + case reflect.Map: + // nil maps should be indicated as different than empty maps + if v.IsNil() { + d.w.Write(nilAngleBytes) + break + } + + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + numEntries := v.Len() + keys := v.MapKeys() + if d.cs.SortKeys { + sortValues(keys, d.cs) + } + for i, key := range keys { + d.dump(d.unpackValue(key)) + d.w.Write(colonSpaceBytes) + d.ignoreNextIndent = true + d.dump(d.unpackValue(v.MapIndex(key))) + if i < (numEntries - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.Struct: + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + vt := v.Type() + numFields := v.NumField() + for i := 0; i < numFields; i++ { + d.indent() + vtf := vt.Field(i) + d.w.Write([]byte(vtf.Name)) + d.w.Write(colonSpaceBytes) + d.ignoreNextIndent = true + d.dump(d.unpackValue(v.Field(i))) + if i < (numFields - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.Uintptr: + printHexPtr(d.w, uintptr(v.Uint())) + + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + printHexPtr(d.w, v.Pointer()) + + // There were not any other types at the time this code was written, but + // fall back to letting the default fmt package handle it in case any new + // types are added. + default: + if v.CanInterface() { + fmt.Fprintf(d.w, "%v", v.Interface()) + } else { + fmt.Fprintf(d.w, "%v", v.String()) + } + } +} + +// fdump is a helper function to consolidate the logic from the various public +// methods which take varying writers and config states. +func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { + for _, arg := range a { + if arg == nil { + w.Write(interfaceBytes) + w.Write(spaceBytes) + w.Write(nilAngleBytes) + w.Write(newlineBytes) + continue + } + + d := dumpState{w: w, cs: cs} + d.pointers = make(map[uintptr]int) + d.dump(reflect.ValueOf(arg)) + d.w.Write(newlineBytes) + } +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func Fdump(w io.Writer, a ...interface{}) { + fdump(&Config, w, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(&Config, &buf, a...) + return buf.String() +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by an exported package global, +spew.Config. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func Dump(a ...interface{}) { + fdump(&Config, os.Stdout, a...) +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/dump_test.go b/vendor/src/github.com/davecgh/go-spew/spew/dump_test.go new file mode 100644 index 00000000..5aad9c7a --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/dump_test.go @@ -0,0 +1,1042 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +Test Summary: +NOTE: For each test, a nil pointer, a single pointer and double pointer to the +base test element are also tested to ensure proper indirection across all types. + +- Max int8, int16, int32, int64, int +- Max uint8, uint16, uint32, uint64, uint +- Boolean true and false +- Standard complex64 and complex128 +- Array containing standard ints +- Array containing type with custom formatter on pointer receiver only +- Array containing interfaces +- Array containing bytes +- Slice containing standard float32 values +- Slice containing type with custom formatter on pointer receiver only +- Slice containing interfaces +- Slice containing bytes +- Nil slice +- Standard string +- Nil interface +- Sub-interface +- Map with string keys and int vals +- Map with custom formatter type on pointer receiver only keys and vals +- Map with interface keys and values +- Map with nil interface value +- Struct with primitives +- Struct that contains another struct +- Struct that contains custom type with Stringer pointer interface via both + exported and unexported fields +- Struct that contains embedded struct and field to same struct +- Uintptr to 0 (null pointer) +- Uintptr address of real variable +- Unsafe.Pointer to 0 (null pointer) +- Unsafe.Pointer to address of real variable +- Nil channel +- Standard int channel +- Function with no params and no returns +- Function with param and no returns +- Function with multiple params and multiple returns +- Struct that is circular through self referencing +- Structs that are circular through cross referencing +- Structs that are indirectly circular +- Type that panics in its Stringer interface +*/ + +package spew_test + +import ( + "bytes" + "fmt" + "testing" + "unsafe" + + "github.com/davecgh/go-spew/spew" +) + +// dumpTest is used to describe a test to be performed against the Dump method. +type dumpTest struct { + in interface{} + wants []string +} + +// dumpTests houses all of the tests to be performed against the Dump method. +var dumpTests = make([]dumpTest, 0) + +// addDumpTest is a helper method to append the passed input and desired result +// to dumpTests +func addDumpTest(in interface{}, wants ...string) { + test := dumpTest{in, wants} + dumpTests = append(dumpTests, test) +} + +func addIntDumpTests() { + // Max int8. + v := int8(127) + nv := (*int8)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "int8" + vs := "127" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") + + // Max int16. + v2 := int16(32767) + nv2 := (*int16)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "int16" + v2s := "32767" + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") + addDumpTest(nv2, "(*"+v2t+")()\n") + + // Max int32. + v3 := int32(2147483647) + nv3 := (*int32)(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "int32" + v3s := "2147483647" + addDumpTest(v3, "("+v3t+") "+v3s+"\n") + addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") + addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") + addDumpTest(nv3, "(*"+v3t+")()\n") + + // Max int64. + v4 := int64(9223372036854775807) + nv4 := (*int64)(nil) + pv4 := &v4 + v4Addr := fmt.Sprintf("%p", pv4) + pv4Addr := fmt.Sprintf("%p", &pv4) + v4t := "int64" + v4s := "9223372036854775807" + addDumpTest(v4, "("+v4t+") "+v4s+"\n") + addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") + addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") + addDumpTest(nv4, "(*"+v4t+")()\n") + + // Max int. + v5 := int(2147483647) + nv5 := (*int)(nil) + pv5 := &v5 + v5Addr := fmt.Sprintf("%p", pv5) + pv5Addr := fmt.Sprintf("%p", &pv5) + v5t := "int" + v5s := "2147483647" + addDumpTest(v5, "("+v5t+") "+v5s+"\n") + addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") + addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") + addDumpTest(nv5, "(*"+v5t+")()\n") +} + +func addUintDumpTests() { + // Max uint8. + v := uint8(255) + nv := (*uint8)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "uint8" + vs := "255" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") + + // Max uint16. + v2 := uint16(65535) + nv2 := (*uint16)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "uint16" + v2s := "65535" + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") + addDumpTest(nv2, "(*"+v2t+")()\n") + + // Max uint32. + v3 := uint32(4294967295) + nv3 := (*uint32)(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "uint32" + v3s := "4294967295" + addDumpTest(v3, "("+v3t+") "+v3s+"\n") + addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") + addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") + addDumpTest(nv3, "(*"+v3t+")()\n") + + // Max uint64. + v4 := uint64(18446744073709551615) + nv4 := (*uint64)(nil) + pv4 := &v4 + v4Addr := fmt.Sprintf("%p", pv4) + pv4Addr := fmt.Sprintf("%p", &pv4) + v4t := "uint64" + v4s := "18446744073709551615" + addDumpTest(v4, "("+v4t+") "+v4s+"\n") + addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") + addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") + addDumpTest(nv4, "(*"+v4t+")()\n") + + // Max uint. + v5 := uint(4294967295) + nv5 := (*uint)(nil) + pv5 := &v5 + v5Addr := fmt.Sprintf("%p", pv5) + pv5Addr := fmt.Sprintf("%p", &pv5) + v5t := "uint" + v5s := "4294967295" + addDumpTest(v5, "("+v5t+") "+v5s+"\n") + addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") + addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") + addDumpTest(nv5, "(*"+v5t+")()\n") +} + +func addBoolDumpTests() { + // Boolean true. + v := bool(true) + nv := (*bool)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "bool" + vs := "true" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") + + // Boolean false. + v2 := bool(false) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "bool" + v2s := "false" + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") +} + +func addFloatDumpTests() { + // Standard float32. + v := float32(3.1415) + nv := (*float32)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "float32" + vs := "3.1415" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") + + // Standard float64. + v2 := float64(3.1415926) + nv2 := (*float64)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "float64" + v2s := "3.1415926" + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") + addDumpTest(nv2, "(*"+v2t+")()\n") +} + +func addComplexDumpTests() { + // Standard complex64. + v := complex(float32(6), -2) + nv := (*complex64)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "complex64" + vs := "(6-2i)" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") + + // Standard complex128. + v2 := complex(float64(-6), 2) + nv2 := (*complex128)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "complex128" + v2s := "(-6+2i)" + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") + addDumpTest(nv2, "(*"+v2t+")()\n") +} + +func addArrayDumpTests() { + // Array containing standard ints. + v := [3]int{1, 2, 3} + vLen := fmt.Sprintf("%d", len(v)) + vCap := fmt.Sprintf("%d", cap(v)) + nv := (*[3]int)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "int" + vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 1,\n (" + + vt + ") 2,\n (" + vt + ") 3\n}" + addDumpTest(v, "([3]"+vt+") "+vs+"\n") + addDumpTest(pv, "(*[3]"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**[3]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*[3]"+vt+")()\n") + + // Array containing type with custom formatter on pointer receiver only. + v2i0 := pstringer("1") + v2i1 := pstringer("2") + v2i2 := pstringer("3") + v2 := [3]pstringer{v2i0, v2i1, v2i2} + v2i0Len := fmt.Sprintf("%d", len(v2i0)) + v2i1Len := fmt.Sprintf("%d", len(v2i1)) + v2i2Len := fmt.Sprintf("%d", len(v2i2)) + v2Len := fmt.Sprintf("%d", len(v2)) + v2Cap := fmt.Sprintf("%d", cap(v2)) + nv2 := (*[3]pstringer)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "spew_test.pstringer" + v2sp := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + + ") (len=" + v2i0Len + ") stringer 1,\n (" + v2t + + ") (len=" + v2i1Len + ") stringer 2,\n (" + v2t + + ") (len=" + v2i2Len + ") " + "stringer 3\n}" + v2s := v2sp + if spew.UnsafeDisabled { + v2s = "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + + ") (len=" + v2i0Len + ") \"1\",\n (" + v2t + ") (len=" + + v2i1Len + ") \"2\",\n (" + v2t + ") (len=" + v2i2Len + + ") " + "\"3\"\n}" + } + addDumpTest(v2, "([3]"+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*[3]"+v2t+")("+v2Addr+")("+v2sp+")\n") + addDumpTest(&pv2, "(**[3]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2sp+")\n") + addDumpTest(nv2, "(*[3]"+v2t+")()\n") + + // Array containing interfaces. + v3i0 := "one" + v3 := [3]interface{}{v3i0, int(2), uint(3)} + v3i0Len := fmt.Sprintf("%d", len(v3i0)) + v3Len := fmt.Sprintf("%d", len(v3)) + v3Cap := fmt.Sprintf("%d", cap(v3)) + nv3 := (*[3]interface{})(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "[3]interface {}" + v3t2 := "string" + v3t3 := "int" + v3t4 := "uint" + v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " + + "(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" + + v3t4 + ") 3\n}" + addDumpTest(v3, "("+v3t+") "+v3s+"\n") + addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") + addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") + addDumpTest(nv3, "(*"+v3t+")()\n") + + // Array containing bytes. + v4 := [34]byte{ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, + } + v4Len := fmt.Sprintf("%d", len(v4)) + v4Cap := fmt.Sprintf("%d", cap(v4)) + nv4 := (*[34]byte)(nil) + pv4 := &v4 + v4Addr := fmt.Sprintf("%p", pv4) + pv4Addr := fmt.Sprintf("%p", &pv4) + v4t := "[34]uint8" + v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + + "{\n 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20" + + " |............... |\n" + + " 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30" + + " |!\"#$%&'()*+,-./0|\n" + + " 00000020 31 32 " + + " |12|\n}" + addDumpTest(v4, "("+v4t+") "+v4s+"\n") + addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") + addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") + addDumpTest(nv4, "(*"+v4t+")()\n") +} + +func addSliceDumpTests() { + // Slice containing standard float32 values. + v := []float32{3.14, 6.28, 12.56} + vLen := fmt.Sprintf("%d", len(v)) + vCap := fmt.Sprintf("%d", cap(v)) + nv := (*[]float32)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "float32" + vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 3.14,\n (" + + vt + ") 6.28,\n (" + vt + ") 12.56\n}" + addDumpTest(v, "([]"+vt+") "+vs+"\n") + addDumpTest(pv, "(*[]"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**[]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*[]"+vt+")()\n") + + // Slice containing type with custom formatter on pointer receiver only. + v2i0 := pstringer("1") + v2i1 := pstringer("2") + v2i2 := pstringer("3") + v2 := []pstringer{v2i0, v2i1, v2i2} + v2i0Len := fmt.Sprintf("%d", len(v2i0)) + v2i1Len := fmt.Sprintf("%d", len(v2i1)) + v2i2Len := fmt.Sprintf("%d", len(v2i2)) + v2Len := fmt.Sprintf("%d", len(v2)) + v2Cap := fmt.Sprintf("%d", cap(v2)) + nv2 := (*[]pstringer)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "spew_test.pstringer" + v2s := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + ") (len=" + + v2i0Len + ") stringer 1,\n (" + v2t + ") (len=" + v2i1Len + + ") stringer 2,\n (" + v2t + ") (len=" + v2i2Len + ") " + + "stringer 3\n}" + addDumpTest(v2, "([]"+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*[]"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**[]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") + addDumpTest(nv2, "(*[]"+v2t+")()\n") + + // Slice containing interfaces. + v3i0 := "one" + v3 := []interface{}{v3i0, int(2), uint(3), nil} + v3i0Len := fmt.Sprintf("%d", len(v3i0)) + v3Len := fmt.Sprintf("%d", len(v3)) + v3Cap := fmt.Sprintf("%d", cap(v3)) + nv3 := (*[]interface{})(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "[]interface {}" + v3t2 := "string" + v3t3 := "int" + v3t4 := "uint" + v3t5 := "interface {}" + v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " + + "(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" + + v3t4 + ") 3,\n (" + v3t5 + ") \n}" + addDumpTest(v3, "("+v3t+") "+v3s+"\n") + addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") + addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") + addDumpTest(nv3, "(*"+v3t+")()\n") + + // Slice containing bytes. + v4 := []byte{ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, + } + v4Len := fmt.Sprintf("%d", len(v4)) + v4Cap := fmt.Sprintf("%d", cap(v4)) + nv4 := (*[]byte)(nil) + pv4 := &v4 + v4Addr := fmt.Sprintf("%p", pv4) + pv4Addr := fmt.Sprintf("%p", &pv4) + v4t := "[]uint8" + v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + + "{\n 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20" + + " |............... |\n" + + " 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30" + + " |!\"#$%&'()*+,-./0|\n" + + " 00000020 31 32 " + + " |12|\n}" + addDumpTest(v4, "("+v4t+") "+v4s+"\n") + addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") + addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") + addDumpTest(nv4, "(*"+v4t+")()\n") + + // Nil slice. + v5 := []int(nil) + nv5 := (*[]int)(nil) + pv5 := &v5 + v5Addr := fmt.Sprintf("%p", pv5) + pv5Addr := fmt.Sprintf("%p", &pv5) + v5t := "[]int" + v5s := "" + addDumpTest(v5, "("+v5t+") "+v5s+"\n") + addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") + addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") + addDumpTest(nv5, "(*"+v5t+")()\n") +} + +func addStringDumpTests() { + // Standard string. + v := "test" + vLen := fmt.Sprintf("%d", len(v)) + nv := (*string)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "string" + vs := "(len=" + vLen + ") \"test\"" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") +} + +func addInterfaceDumpTests() { + // Nil interface. + var v interface{} + nv := (*interface{})(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "interface {}" + vs := "" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") + + // Sub-interface. + v2 := interface{}(uint16(65535)) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "uint16" + v2s := "65535" + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") +} + +func addMapDumpTests() { + // Map with string keys and int vals. + k := "one" + kk := "two" + m := map[string]int{k: 1, kk: 2} + klen := fmt.Sprintf("%d", len(k)) // not kLen to shut golint up + kkLen := fmt.Sprintf("%d", len(kk)) + mLen := fmt.Sprintf("%d", len(m)) + nilMap := map[string]int(nil) + nm := (*map[string]int)(nil) + pm := &m + mAddr := fmt.Sprintf("%p", pm) + pmAddr := fmt.Sprintf("%p", &pm) + mt := "map[string]int" + mt1 := "string" + mt2 := "int" + ms := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + klen + ") " + + "\"one\": (" + mt2 + ") 1,\n (" + mt1 + ") (len=" + kkLen + + ") \"two\": (" + mt2 + ") 2\n}" + ms2 := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + kkLen + ") " + + "\"two\": (" + mt2 + ") 2,\n (" + mt1 + ") (len=" + klen + + ") \"one\": (" + mt2 + ") 1\n}" + addDumpTest(m, "("+mt+") "+ms+"\n", "("+mt+") "+ms2+"\n") + addDumpTest(pm, "(*"+mt+")("+mAddr+")("+ms+")\n", + "(*"+mt+")("+mAddr+")("+ms2+")\n") + addDumpTest(&pm, "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms+")\n", + "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms2+")\n") + addDumpTest(nm, "(*"+mt+")()\n") + addDumpTest(nilMap, "("+mt+") \n") + + // Map with custom formatter type on pointer receiver only keys and vals. + k2 := pstringer("one") + v2 := pstringer("1") + m2 := map[pstringer]pstringer{k2: v2} + k2Len := fmt.Sprintf("%d", len(k2)) + v2Len := fmt.Sprintf("%d", len(v2)) + m2Len := fmt.Sprintf("%d", len(m2)) + nilMap2 := map[pstringer]pstringer(nil) + nm2 := (*map[pstringer]pstringer)(nil) + pm2 := &m2 + m2Addr := fmt.Sprintf("%p", pm2) + pm2Addr := fmt.Sprintf("%p", &pm2) + m2t := "map[spew_test.pstringer]spew_test.pstringer" + m2t1 := "spew_test.pstringer" + m2t2 := "spew_test.pstringer" + m2s := "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len + ") " + + "stringer one: (" + m2t2 + ") (len=" + v2Len + ") stringer 1\n}" + if spew.UnsafeDisabled { + m2s = "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len + + ") " + "\"one\": (" + m2t2 + ") (len=" + v2Len + + ") \"1\"\n}" + } + addDumpTest(m2, "("+m2t+") "+m2s+"\n") + addDumpTest(pm2, "(*"+m2t+")("+m2Addr+")("+m2s+")\n") + addDumpTest(&pm2, "(**"+m2t+")("+pm2Addr+"->"+m2Addr+")("+m2s+")\n") + addDumpTest(nm2, "(*"+m2t+")()\n") + addDumpTest(nilMap2, "("+m2t+") \n") + + // Map with interface keys and values. + k3 := "one" + k3Len := fmt.Sprintf("%d", len(k3)) + m3 := map[interface{}]interface{}{k3: 1} + m3Len := fmt.Sprintf("%d", len(m3)) + nilMap3 := map[interface{}]interface{}(nil) + nm3 := (*map[interface{}]interface{})(nil) + pm3 := &m3 + m3Addr := fmt.Sprintf("%p", pm3) + pm3Addr := fmt.Sprintf("%p", &pm3) + m3t := "map[interface {}]interface {}" + m3t1 := "string" + m3t2 := "int" + m3s := "(len=" + m3Len + ") {\n (" + m3t1 + ") (len=" + k3Len + ") " + + "\"one\": (" + m3t2 + ") 1\n}" + addDumpTest(m3, "("+m3t+") "+m3s+"\n") + addDumpTest(pm3, "(*"+m3t+")("+m3Addr+")("+m3s+")\n") + addDumpTest(&pm3, "(**"+m3t+")("+pm3Addr+"->"+m3Addr+")("+m3s+")\n") + addDumpTest(nm3, "(*"+m3t+")()\n") + addDumpTest(nilMap3, "("+m3t+") \n") + + // Map with nil interface value. + k4 := "nil" + k4Len := fmt.Sprintf("%d", len(k4)) + m4 := map[string]interface{}{k4: nil} + m4Len := fmt.Sprintf("%d", len(m4)) + nilMap4 := map[string]interface{}(nil) + nm4 := (*map[string]interface{})(nil) + pm4 := &m4 + m4Addr := fmt.Sprintf("%p", pm4) + pm4Addr := fmt.Sprintf("%p", &pm4) + m4t := "map[string]interface {}" + m4t1 := "string" + m4t2 := "interface {}" + m4s := "(len=" + m4Len + ") {\n (" + m4t1 + ") (len=" + k4Len + ")" + + " \"nil\": (" + m4t2 + ") \n}" + addDumpTest(m4, "("+m4t+") "+m4s+"\n") + addDumpTest(pm4, "(*"+m4t+")("+m4Addr+")("+m4s+")\n") + addDumpTest(&pm4, "(**"+m4t+")("+pm4Addr+"->"+m4Addr+")("+m4s+")\n") + addDumpTest(nm4, "(*"+m4t+")()\n") + addDumpTest(nilMap4, "("+m4t+") \n") +} + +func addStructDumpTests() { + // Struct with primitives. + type s1 struct { + a int8 + b uint8 + } + v := s1{127, 255} + nv := (*s1)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "spew_test.s1" + vt2 := "int8" + vt3 := "uint8" + vs := "{\n a: (" + vt2 + ") 127,\n b: (" + vt3 + ") 255\n}" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") + + // Struct that contains another struct. + type s2 struct { + s1 s1 + b bool + } + v2 := s2{s1{127, 255}, true} + nv2 := (*s2)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "spew_test.s2" + v2t2 := "spew_test.s1" + v2t3 := "int8" + v2t4 := "uint8" + v2t5 := "bool" + v2s := "{\n s1: (" + v2t2 + ") {\n a: (" + v2t3 + ") 127,\n b: (" + + v2t4 + ") 255\n },\n b: (" + v2t5 + ") true\n}" + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") + addDumpTest(nv2, "(*"+v2t+")()\n") + + // Struct that contains custom type with Stringer pointer interface via both + // exported and unexported fields. + type s3 struct { + s pstringer + S pstringer + } + v3 := s3{"test", "test2"} + nv3 := (*s3)(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "spew_test.s3" + v3t2 := "spew_test.pstringer" + v3s := "{\n s: (" + v3t2 + ") (len=4) stringer test,\n S: (" + v3t2 + + ") (len=5) stringer test2\n}" + v3sp := v3s + if spew.UnsafeDisabled { + v3s = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" + + v3t2 + ") (len=5) \"test2\"\n}" + v3sp = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" + + v3t2 + ") (len=5) stringer test2\n}" + } + addDumpTest(v3, "("+v3t+") "+v3s+"\n") + addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3sp+")\n") + addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3sp+")\n") + addDumpTest(nv3, "(*"+v3t+")()\n") + + // Struct that contains embedded struct and field to same struct. + e := embed{"embedstr"} + eLen := fmt.Sprintf("%d", len("embedstr")) + v4 := embedwrap{embed: &e, e: &e} + nv4 := (*embedwrap)(nil) + pv4 := &v4 + eAddr := fmt.Sprintf("%p", &e) + v4Addr := fmt.Sprintf("%p", pv4) + pv4Addr := fmt.Sprintf("%p", &pv4) + v4t := "spew_test.embedwrap" + v4t2 := "spew_test.embed" + v4t3 := "string" + v4s := "{\n embed: (*" + v4t2 + ")(" + eAddr + ")({\n a: (" + v4t3 + + ") (len=" + eLen + ") \"embedstr\"\n }),\n e: (*" + v4t2 + + ")(" + eAddr + ")({\n a: (" + v4t3 + ") (len=" + eLen + ")" + + " \"embedstr\"\n })\n}" + addDumpTest(v4, "("+v4t+") "+v4s+"\n") + addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") + addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") + addDumpTest(nv4, "(*"+v4t+")()\n") +} + +func addUintptrDumpTests() { + // Null pointer. + v := uintptr(0) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "uintptr" + vs := "" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + + // Address of real variable. + i := 1 + v2 := uintptr(unsafe.Pointer(&i)) + nv2 := (*uintptr)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "uintptr" + v2s := fmt.Sprintf("%p", &i) + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") + addDumpTest(nv2, "(*"+v2t+")()\n") +} + +func addUnsafePointerDumpTests() { + // Null pointer. + v := unsafe.Pointer(uintptr(0)) + nv := (*unsafe.Pointer)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "unsafe.Pointer" + vs := "" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") + + // Address of real variable. + i := 1 + v2 := unsafe.Pointer(&i) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "unsafe.Pointer" + v2s := fmt.Sprintf("%p", &i) + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") + addDumpTest(nv, "(*"+vt+")()\n") +} + +func addChanDumpTests() { + // Nil channel. + var v chan int + pv := &v + nv := (*chan int)(nil) + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "chan int" + vs := "" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") + + // Real channel. + v2 := make(chan int) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "chan int" + v2s := fmt.Sprintf("%p", v2) + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") +} + +func addFuncDumpTests() { + // Function with no params and no returns. + v := addIntDumpTests + nv := (*func())(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "func()" + vs := fmt.Sprintf("%p", v) + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") + + // Function with param and no returns. + v2 := TestDump + nv2 := (*func(*testing.T))(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "func(*testing.T)" + v2s := fmt.Sprintf("%p", v2) + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") + addDumpTest(nv2, "(*"+v2t+")()\n") + + // Function with multiple params and multiple returns. + var v3 = func(i int, s string) (b bool, err error) { + return true, nil + } + nv3 := (*func(int, string) (bool, error))(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "func(int, string) (bool, error)" + v3s := fmt.Sprintf("%p", v3) + addDumpTest(v3, "("+v3t+") "+v3s+"\n") + addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") + addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") + addDumpTest(nv3, "(*"+v3t+")()\n") +} + +func addCircularDumpTests() { + // Struct that is circular through self referencing. + type circular struct { + c *circular + } + v := circular{nil} + v.c = &v + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "spew_test.circular" + vs := "{\n c: (*" + vt + ")(" + vAddr + ")({\n c: (*" + vt + ")(" + + vAddr + ")()\n })\n}" + vs2 := "{\n c: (*" + vt + ")(" + vAddr + ")()\n}" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs2+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs2+")\n") + + // Structs that are circular through cross referencing. + v2 := xref1{nil} + ts2 := xref2{&v2} + v2.ps2 = &ts2 + pv2 := &v2 + ts2Addr := fmt.Sprintf("%p", &ts2) + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "spew_test.xref1" + v2t2 := "spew_test.xref2" + v2s := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n ps1: (*" + v2t + + ")(" + v2Addr + ")({\n ps2: (*" + v2t2 + ")(" + ts2Addr + + ")()\n })\n })\n}" + v2s2 := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n ps1: (*" + v2t + + ")(" + v2Addr + ")()\n })\n}" + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s2+")\n") + addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s2+")\n") + + // Structs that are indirectly circular. + v3 := indirCir1{nil} + tic2 := indirCir2{nil} + tic3 := indirCir3{&v3} + tic2.ps3 = &tic3 + v3.ps2 = &tic2 + pv3 := &v3 + tic2Addr := fmt.Sprintf("%p", &tic2) + tic3Addr := fmt.Sprintf("%p", &tic3) + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "spew_test.indirCir1" + v3t2 := "spew_test.indirCir2" + v3t3 := "spew_test.indirCir3" + v3s := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n ps3: (*" + v3t3 + + ")(" + tic3Addr + ")({\n ps1: (*" + v3t + ")(" + v3Addr + + ")({\n ps2: (*" + v3t2 + ")(" + tic2Addr + + ")()\n })\n })\n })\n}" + v3s2 := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n ps3: (*" + v3t3 + + ")(" + tic3Addr + ")({\n ps1: (*" + v3t + ")(" + v3Addr + + ")()\n })\n })\n}" + addDumpTest(v3, "("+v3t+") "+v3s+"\n") + addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s2+")\n") + addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s2+")\n") +} + +func addPanicDumpTests() { + // Type that panics in its Stringer interface. + v := panicer(127) + nv := (*panicer)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "spew_test.panicer" + vs := "(PANIC=test panic)127" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") +} + +func addErrorDumpTests() { + // Type that has a custom Error interface. + v := customError(127) + nv := (*customError)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "spew_test.customError" + vs := "error: 127" + addDumpTest(v, "("+vt+") "+vs+"\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") + addDumpTest(nv, "(*"+vt+")()\n") +} + +// TestDump executes all of the tests described by dumpTests. +func TestDump(t *testing.T) { + // Setup tests. + addIntDumpTests() + addUintDumpTests() + addBoolDumpTests() + addFloatDumpTests() + addComplexDumpTests() + addArrayDumpTests() + addSliceDumpTests() + addStringDumpTests() + addInterfaceDumpTests() + addMapDumpTests() + addStructDumpTests() + addUintptrDumpTests() + addUnsafePointerDumpTests() + addChanDumpTests() + addFuncDumpTests() + addCircularDumpTests() + addPanicDumpTests() + addErrorDumpTests() + addCgoDumpTests() + + t.Logf("Running %d tests", len(dumpTests)) + for i, test := range dumpTests { + buf := new(bytes.Buffer) + spew.Fdump(buf, test.in) + s := buf.String() + if testFailed(s, test.wants) { + t.Errorf("Dump #%d\n got: %s %s", i, s, stringizeWants(test.wants)) + continue + } + } +} + +func TestDumpSortedKeys(t *testing.T) { + cfg := spew.ConfigState{SortKeys: true} + s := cfg.Sdump(map[int]string{1: "1", 3: "3", 2: "2"}) + expected := "(map[int]string) (len=3) {\n(int) 1: (string) (len=1) " + + "\"1\",\n(int) 2: (string) (len=1) \"2\",\n(int) 3: (string) " + + "(len=1) \"3\"\n" + + "}\n" + if s != expected { + t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) + } + + s = cfg.Sdump(map[stringer]int{"1": 1, "3": 3, "2": 2}) + expected = "(map[spew_test.stringer]int) (len=3) {\n" + + "(spew_test.stringer) (len=1) stringer 1: (int) 1,\n" + + "(spew_test.stringer) (len=1) stringer 2: (int) 2,\n" + + "(spew_test.stringer) (len=1) stringer 3: (int) 3\n" + + "}\n" + if s != expected { + t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) + } + + s = cfg.Sdump(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2}) + expected = "(map[spew_test.pstringer]int) (len=3) {\n" + + "(spew_test.pstringer) (len=1) stringer 1: (int) 1,\n" + + "(spew_test.pstringer) (len=1) stringer 2: (int) 2,\n" + + "(spew_test.pstringer) (len=1) stringer 3: (int) 3\n" + + "}\n" + if spew.UnsafeDisabled { + expected = "(map[spew_test.pstringer]int) (len=3) {\n" + + "(spew_test.pstringer) (len=1) \"1\": (int) 1,\n" + + "(spew_test.pstringer) (len=1) \"2\": (int) 2,\n" + + "(spew_test.pstringer) (len=1) \"3\": (int) 3\n" + + "}\n" + } + if s != expected { + t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) + } + + s = cfg.Sdump(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2}) + expected = "(map[spew_test.customError]int) (len=3) {\n" + + "(spew_test.customError) error: 1: (int) 1,\n" + + "(spew_test.customError) error: 2: (int) 2,\n" + + "(spew_test.customError) error: 3: (int) 3\n" + + "}\n" + if s != expected { + t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) + } + +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go b/vendor/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go new file mode 100644 index 00000000..6ab18080 --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go @@ -0,0 +1,99 @@ +// Copyright (c) 2013-2016 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when both cgo is supported and "-tags testcgo" is added to the go test +// command line. This means the cgo tests are only added (and hence run) when +// specifially requested. This configuration is used because spew itself +// does not require cgo to run even though it does handle certain cgo types +// specially. Rather than forcing all clients to require cgo and an external +// C compiler just to run the tests, this scheme makes them optional. +// +build cgo,testcgo + +package spew_test + +import ( + "fmt" + + "github.com/davecgh/go-spew/spew/testdata" +) + +func addCgoDumpTests() { + // C char pointer. + v := testdata.GetCgoCharPointer() + nv := testdata.GetCgoNullCharPointer() + pv := &v + vcAddr := fmt.Sprintf("%p", v) + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "*testdata._Ctype_char" + vs := "116" + addDumpTest(v, "("+vt+")("+vcAddr+")("+vs+")\n") + addDumpTest(pv, "(*"+vt+")("+vAddr+"->"+vcAddr+")("+vs+")\n") + addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+"->"+vcAddr+")("+vs+")\n") + addDumpTest(nv, "("+vt+")()\n") + + // C char array. + v2, v2l, v2c := testdata.GetCgoCharArray() + v2Len := fmt.Sprintf("%d", v2l) + v2Cap := fmt.Sprintf("%d", v2c) + v2t := "[6]testdata._Ctype_char" + v2s := "(len=" + v2Len + " cap=" + v2Cap + ") " + + "{\n 00000000 74 65 73 74 32 00 " + + " |test2.|\n}" + addDumpTest(v2, "("+v2t+") "+v2s+"\n") + + // C unsigned char array. + v3, v3l, v3c := testdata.GetCgoUnsignedCharArray() + v3Len := fmt.Sprintf("%d", v3l) + v3Cap := fmt.Sprintf("%d", v3c) + v3t := "[6]testdata._Ctype_unsignedchar" + v3t2 := "[6]testdata._Ctype_uchar" + v3s := "(len=" + v3Len + " cap=" + v3Cap + ") " + + "{\n 00000000 74 65 73 74 33 00 " + + " |test3.|\n}" + addDumpTest(v3, "("+v3t+") "+v3s+"\n", "("+v3t2+") "+v3s+"\n") + + // C signed char array. + v4, v4l, v4c := testdata.GetCgoSignedCharArray() + v4Len := fmt.Sprintf("%d", v4l) + v4Cap := fmt.Sprintf("%d", v4c) + v4t := "[6]testdata._Ctype_schar" + v4t2 := "testdata._Ctype_schar" + v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + + "{\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 101,\n (" + v4t2 + + ") 115,\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 52,\n (" + v4t2 + + ") 0\n}" + addDumpTest(v4, "("+v4t+") "+v4s+"\n") + + // C uint8_t array. + v5, v5l, v5c := testdata.GetCgoUint8tArray() + v5Len := fmt.Sprintf("%d", v5l) + v5Cap := fmt.Sprintf("%d", v5c) + v5t := "[6]testdata._Ctype_uint8_t" + v5s := "(len=" + v5Len + " cap=" + v5Cap + ") " + + "{\n 00000000 74 65 73 74 35 00 " + + " |test5.|\n}" + addDumpTest(v5, "("+v5t+") "+v5s+"\n") + + // C typedefed unsigned char array. + v6, v6l, v6c := testdata.GetCgoTypdefedUnsignedCharArray() + v6Len := fmt.Sprintf("%d", v6l) + v6Cap := fmt.Sprintf("%d", v6c) + v6t := "[6]testdata._Ctype_custom_uchar_t" + v6s := "(len=" + v6Len + " cap=" + v6Cap + ") " + + "{\n 00000000 74 65 73 74 36 00 " + + " |test6.|\n}" + addDumpTest(v6, "("+v6t+") "+v6s+"\n") +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go b/vendor/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go new file mode 100644 index 00000000..52a0971f --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go @@ -0,0 +1,26 @@ +// Copyright (c) 2013 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when either cgo is not supported or "-tags testcgo" is not added to the go +// test command line. This file intentionally does not setup any cgo tests in +// this scenario. +// +build !cgo !testcgo + +package spew_test + +func addCgoDumpTests() { + // Don't add any tests for cgo since this file is only compiled when + // there should not be any cgo tests. +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/example_test.go b/vendor/src/github.com/davecgh/go-spew/spew/example_test.go new file mode 100644 index 00000000..c6ec8c6d --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/example_test.go @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew_test + +import ( + "fmt" + + "github.com/davecgh/go-spew/spew" +) + +type Flag int + +const ( + flagOne Flag = iota + flagTwo +) + +var flagStrings = map[Flag]string{ + flagOne: "flagOne", + flagTwo: "flagTwo", +} + +func (f Flag) String() string { + if s, ok := flagStrings[f]; ok { + return s + } + return fmt.Sprintf("Unknown flag (%d)", int(f)) +} + +type Bar struct { + data uintptr +} + +type Foo struct { + unexportedField Bar + ExportedField map[interface{}]interface{} +} + +// This example demonstrates how to use Dump to dump variables to stdout. +func ExampleDump() { + // The following package level declarations are assumed for this example: + /* + type Flag int + + const ( + flagOne Flag = iota + flagTwo + ) + + var flagStrings = map[Flag]string{ + flagOne: "flagOne", + flagTwo: "flagTwo", + } + + func (f Flag) String() string { + if s, ok := flagStrings[f]; ok { + return s + } + return fmt.Sprintf("Unknown flag (%d)", int(f)) + } + + type Bar struct { + data uintptr + } + + type Foo struct { + unexportedField Bar + ExportedField map[interface{}]interface{} + } + */ + + // Setup some sample data structures for the example. + bar := Bar{uintptr(0)} + s1 := Foo{bar, map[interface{}]interface{}{"one": true}} + f := Flag(5) + b := []byte{ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, + } + + // Dump! + spew.Dump(s1, f, b) + + // Output: + // (spew_test.Foo) { + // unexportedField: (spew_test.Bar) { + // data: (uintptr) + // }, + // ExportedField: (map[interface {}]interface {}) (len=1) { + // (string) (len=3) "one": (bool) true + // } + // } + // (spew_test.Flag) Unknown flag (5) + // ([]uint8) (len=34 cap=34) { + // 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | + // 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| + // 00000020 31 32 |12| + // } + // +} + +// This example demonstrates how to use Printf to display a variable with a +// format string and inline formatting. +func ExamplePrintf() { + // Create a double pointer to a uint 8. + ui8 := uint8(5) + pui8 := &ui8 + ppui8 := &pui8 + + // Create a circular data type. + type circular struct { + ui8 uint8 + c *circular + } + c := circular{ui8: 1} + c.c = &c + + // Print! + spew.Printf("ppui8: %v\n", ppui8) + spew.Printf("circular: %v\n", c) + + // Output: + // ppui8: <**>5 + // circular: {1 <*>{1 <*>}} +} + +// This example demonstrates how to use a ConfigState. +func ExampleConfigState() { + // Modify the indent level of the ConfigState only. The global + // configuration is not modified. + scs := spew.ConfigState{Indent: "\t"} + + // Output using the ConfigState instance. + v := map[string]int{"one": 1} + scs.Printf("v: %v\n", v) + scs.Dump(v) + + // Output: + // v: map[one:1] + // (map[string]int) (len=1) { + // (string) (len=3) "one": (int) 1 + // } +} + +// This example demonstrates how to use ConfigState.Dump to dump variables to +// stdout +func ExampleConfigState_Dump() { + // See the top-level Dump example for details on the types used in this + // example. + + // Create two ConfigState instances with different indentation. + scs := spew.ConfigState{Indent: "\t"} + scs2 := spew.ConfigState{Indent: " "} + + // Setup some sample data structures for the example. + bar := Bar{uintptr(0)} + s1 := Foo{bar, map[interface{}]interface{}{"one": true}} + + // Dump using the ConfigState instances. + scs.Dump(s1) + scs2.Dump(s1) + + // Output: + // (spew_test.Foo) { + // unexportedField: (spew_test.Bar) { + // data: (uintptr) + // }, + // ExportedField: (map[interface {}]interface {}) (len=1) { + // (string) (len=3) "one": (bool) true + // } + // } + // (spew_test.Foo) { + // unexportedField: (spew_test.Bar) { + // data: (uintptr) + // }, + // ExportedField: (map[interface {}]interface {}) (len=1) { + // (string) (len=3) "one": (bool) true + // } + // } + // +} + +// This example demonstrates how to use ConfigState.Printf to display a variable +// with a format string and inline formatting. +func ExampleConfigState_Printf() { + // See the top-level Dump example for details on the types used in this + // example. + + // Create two ConfigState instances and modify the method handling of the + // first ConfigState only. + scs := spew.NewDefaultConfig() + scs2 := spew.NewDefaultConfig() + scs.DisableMethods = true + + // Alternatively + // scs := spew.ConfigState{Indent: " ", DisableMethods: true} + // scs2 := spew.ConfigState{Indent: " "} + + // This is of type Flag which implements a Stringer and has raw value 1. + f := flagTwo + + // Dump using the ConfigState instances. + scs.Printf("f: %v\n", f) + scs2.Printf("f: %v\n", f) + + // Output: + // f: 1 + // f: flagTwo +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/format.go b/vendor/src/github.com/davecgh/go-spew/spew/format.go new file mode 100644 index 00000000..c49875ba --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/format.go @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" +) + +// supportedFlags is a list of all the character flags supported by fmt package. +const supportedFlags = "0-+# " + +// formatState implements the fmt.Formatter interface and contains information +// about the state of a formatting operation. The NewFormatter function can +// be used to get a new Formatter which can be used directly as arguments +// in standard fmt package printing calls. +type formatState struct { + value interface{} + fs fmt.State + depth int + pointers map[uintptr]int + ignoreNextType bool + cs *ConfigState +} + +// buildDefaultFormat recreates the original format string without precision +// and width information to pass in to fmt.Sprintf in the case of an +// unrecognized type. Unless new types are added to the language, this +// function won't ever be called. +func (f *formatState) buildDefaultFormat() (format string) { + buf := bytes.NewBuffer(percentBytes) + + for _, flag := range supportedFlags { + if f.fs.Flag(int(flag)) { + buf.WriteRune(flag) + } + } + + buf.WriteRune('v') + + format = buf.String() + return format +} + +// constructOrigFormat recreates the original format string including precision +// and width information to pass along to the standard fmt package. This allows +// automatic deferral of all format strings this package doesn't support. +func (f *formatState) constructOrigFormat(verb rune) (format string) { + buf := bytes.NewBuffer(percentBytes) + + for _, flag := range supportedFlags { + if f.fs.Flag(int(flag)) { + buf.WriteRune(flag) + } + } + + if width, ok := f.fs.Width(); ok { + buf.WriteString(strconv.Itoa(width)) + } + + if precision, ok := f.fs.Precision(); ok { + buf.Write(precisionBytes) + buf.WriteString(strconv.Itoa(precision)) + } + + buf.WriteRune(verb) + + format = buf.String() + return format +} + +// unpackValue returns values inside of non-nil interfaces when possible and +// ensures that types for values which have been unpacked from an interface +// are displayed when the show types flag is also set. +// This is useful for data types like structs, arrays, slices, and maps which +// can contain varying types packed inside an interface. +func (f *formatState) unpackValue(v reflect.Value) reflect.Value { + if v.Kind() == reflect.Interface { + f.ignoreNextType = false + if !v.IsNil() { + v = v.Elem() + } + } + return v +} + +// formatPtr handles formatting of pointers by indirecting them as necessary. +func (f *formatState) formatPtr(v reflect.Value) { + // Display nil if top level pointer is nil. + showTypes := f.fs.Flag('#') + if v.IsNil() && (!showTypes || f.ignoreNextType) { + f.fs.Write(nilAngleBytes) + return + } + + // Remove pointers at or below the current depth from map used to detect + // circular refs. + for k, depth := range f.pointers { + if depth >= f.depth { + delete(f.pointers, k) + } + } + + // Keep list of all dereferenced pointers to possibly show later. + pointerChain := make([]uintptr, 0) + + // Figure out how many levels of indirection there are by derferencing + // pointers and unpacking interfaces down the chain while detecting circular + // references. + nilFound := false + cycleFound := false + indirects := 0 + ve := v + for ve.Kind() == reflect.Ptr { + if ve.IsNil() { + nilFound = true + break + } + indirects++ + addr := ve.Pointer() + pointerChain = append(pointerChain, addr) + if pd, ok := f.pointers[addr]; ok && pd < f.depth { + cycleFound = true + indirects-- + break + } + f.pointers[addr] = f.depth + + ve = ve.Elem() + if ve.Kind() == reflect.Interface { + if ve.IsNil() { + nilFound = true + break + } + ve = ve.Elem() + } + } + + // Display type or indirection level depending on flags. + if showTypes && !f.ignoreNextType { + f.fs.Write(openParenBytes) + f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) + f.fs.Write([]byte(ve.Type().String())) + f.fs.Write(closeParenBytes) + } else { + if nilFound || cycleFound { + indirects += strings.Count(ve.Type().String(), "*") + } + f.fs.Write(openAngleBytes) + f.fs.Write([]byte(strings.Repeat("*", indirects))) + f.fs.Write(closeAngleBytes) + } + + // Display pointer information depending on flags. + if f.fs.Flag('+') && (len(pointerChain) > 0) { + f.fs.Write(openParenBytes) + for i, addr := range pointerChain { + if i > 0 { + f.fs.Write(pointerChainBytes) + } + printHexPtr(f.fs, addr) + } + f.fs.Write(closeParenBytes) + } + + // Display dereferenced value. + switch { + case nilFound == true: + f.fs.Write(nilAngleBytes) + + case cycleFound == true: + f.fs.Write(circularShortBytes) + + default: + f.ignoreNextType = true + f.format(ve) + } +} + +// format is the main workhorse for providing the Formatter interface. It +// uses the passed reflect value to figure out what kind of object we are +// dealing with and formats it appropriately. It is a recursive function, +// however circular data structures are detected and handled properly. +func (f *formatState) format(v reflect.Value) { + // Handle invalid reflect values immediately. + kind := v.Kind() + if kind == reflect.Invalid { + f.fs.Write(invalidAngleBytes) + return + } + + // Handle pointers specially. + if kind == reflect.Ptr { + f.formatPtr(v) + return + } + + // Print type information unless already handled elsewhere. + if !f.ignoreNextType && f.fs.Flag('#') { + f.fs.Write(openParenBytes) + f.fs.Write([]byte(v.Type().String())) + f.fs.Write(closeParenBytes) + } + f.ignoreNextType = false + + // Call Stringer/error interfaces if they exist and the handle methods + // flag is enabled. + if !f.cs.DisableMethods { + if (kind != reflect.Invalid) && (kind != reflect.Interface) { + if handled := handleMethods(f.cs, f.fs, v); handled { + return + } + } + } + + switch kind { + case reflect.Invalid: + // Do nothing. We should never get here since invalid has already + // been handled above. + + case reflect.Bool: + printBool(f.fs, v.Bool()) + + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + printInt(f.fs, v.Int(), 10) + + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + printUint(f.fs, v.Uint(), 10) + + case reflect.Float32: + printFloat(f.fs, v.Float(), 32) + + case reflect.Float64: + printFloat(f.fs, v.Float(), 64) + + case reflect.Complex64: + printComplex(f.fs, v.Complex(), 32) + + case reflect.Complex128: + printComplex(f.fs, v.Complex(), 64) + + case reflect.Slice: + if v.IsNil() { + f.fs.Write(nilAngleBytes) + break + } + fallthrough + + case reflect.Array: + f.fs.Write(openBracketBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + numEntries := v.Len() + for i := 0; i < numEntries; i++ { + if i > 0 { + f.fs.Write(spaceBytes) + } + f.ignoreNextType = true + f.format(f.unpackValue(v.Index(i))) + } + } + f.depth-- + f.fs.Write(closeBracketBytes) + + case reflect.String: + f.fs.Write([]byte(v.String())) + + case reflect.Interface: + // The only time we should get here is for nil interfaces due to + // unpackValue calls. + if v.IsNil() { + f.fs.Write(nilAngleBytes) + } + + case reflect.Ptr: + // Do nothing. We should never get here since pointers have already + // been handled above. + + case reflect.Map: + // nil maps should be indicated as different than empty maps + if v.IsNil() { + f.fs.Write(nilAngleBytes) + break + } + + f.fs.Write(openMapBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + keys := v.MapKeys() + if f.cs.SortKeys { + sortValues(keys, f.cs) + } + for i, key := range keys { + if i > 0 { + f.fs.Write(spaceBytes) + } + f.ignoreNextType = true + f.format(f.unpackValue(key)) + f.fs.Write(colonBytes) + f.ignoreNextType = true + f.format(f.unpackValue(v.MapIndex(key))) + } + } + f.depth-- + f.fs.Write(closeMapBytes) + + case reflect.Struct: + numFields := v.NumField() + f.fs.Write(openBraceBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + vt := v.Type() + for i := 0; i < numFields; i++ { + if i > 0 { + f.fs.Write(spaceBytes) + } + vtf := vt.Field(i) + if f.fs.Flag('+') || f.fs.Flag('#') { + f.fs.Write([]byte(vtf.Name)) + f.fs.Write(colonBytes) + } + f.format(f.unpackValue(v.Field(i))) + } + } + f.depth-- + f.fs.Write(closeBraceBytes) + + case reflect.Uintptr: + printHexPtr(f.fs, uintptr(v.Uint())) + + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + printHexPtr(f.fs, v.Pointer()) + + // There were not any other types at the time this code was written, but + // fall back to letting the default fmt package handle it if any get added. + default: + format := f.buildDefaultFormat() + if v.CanInterface() { + fmt.Fprintf(f.fs, format, v.Interface()) + } else { + fmt.Fprintf(f.fs, format, v.String()) + } + } +} + +// Format satisfies the fmt.Formatter interface. See NewFormatter for usage +// details. +func (f *formatState) Format(fs fmt.State, verb rune) { + f.fs = fs + + // Use standard formatting for verbs that are not v. + if verb != 'v' { + format := f.constructOrigFormat(verb) + fmt.Fprintf(fs, format, f.value) + return + } + + if f.value == nil { + if fs.Flag('#') { + fs.Write(interfaceBytes) + } + fs.Write(nilAngleBytes) + return + } + + f.format(reflect.ValueOf(f.value)) +} + +// newFormatter is a helper function to consolidate the logic from the various +// public methods which take varying config states. +func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { + fs := &formatState{value: v, cs: cs} + fs.pointers = make(map[uintptr]int) + return fs +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +Printf, Println, or Fprintf. +*/ +func NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(&Config, v) +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/format_test.go b/vendor/src/github.com/davecgh/go-spew/spew/format_test.go new file mode 100644 index 00000000..f9b93abe --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/format_test.go @@ -0,0 +1,1558 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +Test Summary: +NOTE: For each test, a nil pointer, a single pointer and double pointer to the +base test element are also tested to ensure proper indirection across all types. + +- Max int8, int16, int32, int64, int +- Max uint8, uint16, uint32, uint64, uint +- Boolean true and false +- Standard complex64 and complex128 +- Array containing standard ints +- Array containing type with custom formatter on pointer receiver only +- Array containing interfaces +- Slice containing standard float32 values +- Slice containing type with custom formatter on pointer receiver only +- Slice containing interfaces +- Nil slice +- Standard string +- Nil interface +- Sub-interface +- Map with string keys and int vals +- Map with custom formatter type on pointer receiver only keys and vals +- Map with interface keys and values +- Map with nil interface value +- Struct with primitives +- Struct that contains another struct +- Struct that contains custom type with Stringer pointer interface via both + exported and unexported fields +- Struct that contains embedded struct and field to same struct +- Uintptr to 0 (null pointer) +- Uintptr address of real variable +- Unsafe.Pointer to 0 (null pointer) +- Unsafe.Pointer to address of real variable +- Nil channel +- Standard int channel +- Function with no params and no returns +- Function with param and no returns +- Function with multiple params and multiple returns +- Struct that is circular through self referencing +- Structs that are circular through cross referencing +- Structs that are indirectly circular +- Type that panics in its Stringer interface +- Type that has a custom Error interface +- %x passthrough with uint +- %#x passthrough with uint +- %f passthrough with precision +- %f passthrough with width and precision +- %d passthrough with width +- %q passthrough with string +*/ + +package spew_test + +import ( + "bytes" + "fmt" + "testing" + "unsafe" + + "github.com/davecgh/go-spew/spew" +) + +// formatterTest is used to describe a test to be performed against NewFormatter. +type formatterTest struct { + format string + in interface{} + wants []string +} + +// formatterTests houses all of the tests to be performed against NewFormatter. +var formatterTests = make([]formatterTest, 0) + +// addFormatterTest is a helper method to append the passed input and desired +// result to formatterTests. +func addFormatterTest(format string, in interface{}, wants ...string) { + test := formatterTest{format, in, wants} + formatterTests = append(formatterTests, test) +} + +func addIntFormatterTests() { + // Max int8. + v := int8(127) + nv := (*int8)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "int8" + vs := "127" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Max int16. + v2 := int16(32767) + nv2 := (*int16)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "int16" + v2s := "32767" + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%v", nv2, "") + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") + + // Max int32. + v3 := int32(2147483647) + nv3 := (*int32)(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "int32" + v3s := "2147483647" + addFormatterTest("%v", v3, v3s) + addFormatterTest("%v", pv3, "<*>"+v3s) + addFormatterTest("%v", &pv3, "<**>"+v3s) + addFormatterTest("%v", nv3, "") + addFormatterTest("%+v", v3, v3s) + addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) + addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%#v", v3, "("+v3t+")"+v3s) + addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) + addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) + addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") + addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) + addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) + addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) + addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") + + // Max int64. + v4 := int64(9223372036854775807) + nv4 := (*int64)(nil) + pv4 := &v4 + v4Addr := fmt.Sprintf("%p", pv4) + pv4Addr := fmt.Sprintf("%p", &pv4) + v4t := "int64" + v4s := "9223372036854775807" + addFormatterTest("%v", v4, v4s) + addFormatterTest("%v", pv4, "<*>"+v4s) + addFormatterTest("%v", &pv4, "<**>"+v4s) + addFormatterTest("%v", nv4, "") + addFormatterTest("%+v", v4, v4s) + addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) + addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) + addFormatterTest("%+v", nv4, "") + addFormatterTest("%#v", v4, "("+v4t+")"+v4s) + addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) + addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) + addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") + addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) + addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) + addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) + addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") + + // Max int. + v5 := int(2147483647) + nv5 := (*int)(nil) + pv5 := &v5 + v5Addr := fmt.Sprintf("%p", pv5) + pv5Addr := fmt.Sprintf("%p", &pv5) + v5t := "int" + v5s := "2147483647" + addFormatterTest("%v", v5, v5s) + addFormatterTest("%v", pv5, "<*>"+v5s) + addFormatterTest("%v", &pv5, "<**>"+v5s) + addFormatterTest("%v", nv5, "") + addFormatterTest("%+v", v5, v5s) + addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s) + addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s) + addFormatterTest("%+v", nv5, "") + addFormatterTest("%#v", v5, "("+v5t+")"+v5s) + addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s) + addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s) + addFormatterTest("%#v", nv5, "(*"+v5t+")"+"") + addFormatterTest("%#+v", v5, "("+v5t+")"+v5s) + addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s) + addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s) + addFormatterTest("%#+v", nv5, "(*"+v5t+")"+"") +} + +func addUintFormatterTests() { + // Max uint8. + v := uint8(255) + nv := (*uint8)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "uint8" + vs := "255" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Max uint16. + v2 := uint16(65535) + nv2 := (*uint16)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "uint16" + v2s := "65535" + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%v", nv2, "") + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") + + // Max uint32. + v3 := uint32(4294967295) + nv3 := (*uint32)(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "uint32" + v3s := "4294967295" + addFormatterTest("%v", v3, v3s) + addFormatterTest("%v", pv3, "<*>"+v3s) + addFormatterTest("%v", &pv3, "<**>"+v3s) + addFormatterTest("%v", nv3, "") + addFormatterTest("%+v", v3, v3s) + addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) + addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%#v", v3, "("+v3t+")"+v3s) + addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) + addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) + addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") + addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) + addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) + addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) + addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") + + // Max uint64. + v4 := uint64(18446744073709551615) + nv4 := (*uint64)(nil) + pv4 := &v4 + v4Addr := fmt.Sprintf("%p", pv4) + pv4Addr := fmt.Sprintf("%p", &pv4) + v4t := "uint64" + v4s := "18446744073709551615" + addFormatterTest("%v", v4, v4s) + addFormatterTest("%v", pv4, "<*>"+v4s) + addFormatterTest("%v", &pv4, "<**>"+v4s) + addFormatterTest("%v", nv4, "") + addFormatterTest("%+v", v4, v4s) + addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) + addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) + addFormatterTest("%+v", nv4, "") + addFormatterTest("%#v", v4, "("+v4t+")"+v4s) + addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) + addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) + addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") + addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) + addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) + addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) + addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") + + // Max uint. + v5 := uint(4294967295) + nv5 := (*uint)(nil) + pv5 := &v5 + v5Addr := fmt.Sprintf("%p", pv5) + pv5Addr := fmt.Sprintf("%p", &pv5) + v5t := "uint" + v5s := "4294967295" + addFormatterTest("%v", v5, v5s) + addFormatterTest("%v", pv5, "<*>"+v5s) + addFormatterTest("%v", &pv5, "<**>"+v5s) + addFormatterTest("%v", nv5, "") + addFormatterTest("%+v", v5, v5s) + addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s) + addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s) + addFormatterTest("%+v", nv5, "") + addFormatterTest("%#v", v5, "("+v5t+")"+v5s) + addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s) + addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s) + addFormatterTest("%#v", nv5, "(*"+v5t+")"+"") + addFormatterTest("%#+v", v5, "("+v5t+")"+v5s) + addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s) + addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s) + addFormatterTest("%#v", nv5, "(*"+v5t+")"+"") +} + +func addBoolFormatterTests() { + // Boolean true. + v := bool(true) + nv := (*bool)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "bool" + vs := "true" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Boolean false. + v2 := bool(false) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "bool" + v2s := "false" + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) +} + +func addFloatFormatterTests() { + // Standard float32. + v := float32(3.1415) + nv := (*float32)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "float32" + vs := "3.1415" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Standard float64. + v2 := float64(3.1415926) + nv2 := (*float64)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "float64" + v2s := "3.1415926" + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") +} + +func addComplexFormatterTests() { + // Standard complex64. + v := complex(float32(6), -2) + nv := (*complex64)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "complex64" + vs := "(6-2i)" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Standard complex128. + v2 := complex(float64(-6), 2) + nv2 := (*complex128)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "complex128" + v2s := "(-6+2i)" + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") +} + +func addArrayFormatterTests() { + // Array containing standard ints. + v := [3]int{1, 2, 3} + nv := (*[3]int)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "[3]int" + vs := "[1 2 3]" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Array containing type with custom formatter on pointer receiver only. + v2 := [3]pstringer{"1", "2", "3"} + nv2 := (*[3]pstringer)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "[3]spew_test.pstringer" + v2sp := "[stringer 1 stringer 2 stringer 3]" + v2s := v2sp + if spew.UnsafeDisabled { + v2s = "[1 2 3]" + } + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2sp) + addFormatterTest("%v", &pv2, "<**>"+v2sp) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2sp) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2sp) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2sp) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2sp) + addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2sp) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2sp) + addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") + + // Array containing interfaces. + v3 := [3]interface{}{"one", int(2), uint(3)} + nv3 := (*[3]interface{})(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "[3]interface {}" + v3t2 := "string" + v3t3 := "int" + v3t4 := "uint" + v3s := "[one 2 3]" + v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3]" + addFormatterTest("%v", v3, v3s) + addFormatterTest("%v", pv3, "<*>"+v3s) + addFormatterTest("%v", &pv3, "<**>"+v3s) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%+v", v3, v3s) + addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) + addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) + addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) + addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) + addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") + addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) + addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) + addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) + addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") +} + +func addSliceFormatterTests() { + // Slice containing standard float32 values. + v := []float32{3.14, 6.28, 12.56} + nv := (*[]float32)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "[]float32" + vs := "[3.14 6.28 12.56]" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Slice containing type with custom formatter on pointer receiver only. + v2 := []pstringer{"1", "2", "3"} + nv2 := (*[]pstringer)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "[]spew_test.pstringer" + v2s := "[stringer 1 stringer 2 stringer 3]" + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") + + // Slice containing interfaces. + v3 := []interface{}{"one", int(2), uint(3), nil} + nv3 := (*[]interface{})(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "[]interface {}" + v3t2 := "string" + v3t3 := "int" + v3t4 := "uint" + v3t5 := "interface {}" + v3s := "[one 2 3 ]" + v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3 (" + v3t5 + + ")]" + addFormatterTest("%v", v3, v3s) + addFormatterTest("%v", pv3, "<*>"+v3s) + addFormatterTest("%v", &pv3, "<**>"+v3s) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%+v", v3, v3s) + addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) + addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) + addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) + addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) + addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") + addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) + addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) + addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) + addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") + + // Nil slice. + var v4 []int + nv4 := (*[]int)(nil) + pv4 := &v4 + v4Addr := fmt.Sprintf("%p", pv4) + pv4Addr := fmt.Sprintf("%p", &pv4) + v4t := "[]int" + v4s := "" + addFormatterTest("%v", v4, v4s) + addFormatterTest("%v", pv4, "<*>"+v4s) + addFormatterTest("%v", &pv4, "<**>"+v4s) + addFormatterTest("%+v", nv4, "") + addFormatterTest("%+v", v4, v4s) + addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) + addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) + addFormatterTest("%+v", nv4, "") + addFormatterTest("%#v", v4, "("+v4t+")"+v4s) + addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) + addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) + addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") + addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) + addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) + addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) + addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") +} + +func addStringFormatterTests() { + // Standard string. + v := "test" + nv := (*string)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "string" + vs := "test" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") +} + +func addInterfaceFormatterTests() { + // Nil interface. + var v interface{} + nv := (*interface{})(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "interface {}" + vs := "" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Sub-interface. + v2 := interface{}(uint16(65535)) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "uint16" + v2s := "65535" + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) +} + +func addMapFormatterTests() { + // Map with string keys and int vals. + v := map[string]int{"one": 1, "two": 2} + nilMap := map[string]int(nil) + nv := (*map[string]int)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "map[string]int" + vs := "map[one:1 two:2]" + vs2 := "map[two:2 one:1]" + addFormatterTest("%v", v, vs, vs2) + addFormatterTest("%v", pv, "<*>"+vs, "<*>"+vs2) + addFormatterTest("%v", &pv, "<**>"+vs, "<**>"+vs2) + addFormatterTest("%+v", nilMap, "") + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs, vs2) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs, "<*>("+vAddr+")"+vs2) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs, + "<**>("+pvAddr+"->"+vAddr+")"+vs2) + addFormatterTest("%+v", nilMap, "") + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs, "("+vt+")"+vs2) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs, "(*"+vt+")"+vs2) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs, "(**"+vt+")"+vs2) + addFormatterTest("%#v", nilMap, "("+vt+")"+"") + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs, "("+vt+")"+vs2) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs, + "(*"+vt+")("+vAddr+")"+vs2) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs, + "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs2) + addFormatterTest("%#+v", nilMap, "("+vt+")"+"") + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Map with custom formatter type on pointer receiver only keys and vals. + v2 := map[pstringer]pstringer{"one": "1"} + nv2 := (*map[pstringer]pstringer)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "map[spew_test.pstringer]spew_test.pstringer" + v2s := "map[stringer one:stringer 1]" + if spew.UnsafeDisabled { + v2s = "map[one:1]" + } + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") + + // Map with interface keys and values. + v3 := map[interface{}]interface{}{"one": 1} + nv3 := (*map[interface{}]interface{})(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "map[interface {}]interface {}" + v3t1 := "string" + v3t2 := "int" + v3s := "map[one:1]" + v3s2 := "map[(" + v3t1 + ")one:(" + v3t2 + ")1]" + addFormatterTest("%v", v3, v3s) + addFormatterTest("%v", pv3, "<*>"+v3s) + addFormatterTest("%v", &pv3, "<**>"+v3s) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%+v", v3, v3s) + addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) + addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) + addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) + addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) + addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") + addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) + addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) + addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) + addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") + + // Map with nil interface value + v4 := map[string]interface{}{"nil": nil} + nv4 := (*map[string]interface{})(nil) + pv4 := &v4 + v4Addr := fmt.Sprintf("%p", pv4) + pv4Addr := fmt.Sprintf("%p", &pv4) + v4t := "map[string]interface {}" + v4t1 := "interface {}" + v4s := "map[nil:]" + v4s2 := "map[nil:(" + v4t1 + ")]" + addFormatterTest("%v", v4, v4s) + addFormatterTest("%v", pv4, "<*>"+v4s) + addFormatterTest("%v", &pv4, "<**>"+v4s) + addFormatterTest("%+v", nv4, "") + addFormatterTest("%+v", v4, v4s) + addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) + addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) + addFormatterTest("%+v", nv4, "") + addFormatterTest("%#v", v4, "("+v4t+")"+v4s2) + addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s2) + addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s2) + addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") + addFormatterTest("%#+v", v4, "("+v4t+")"+v4s2) + addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s2) + addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s2) + addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") +} + +func addStructFormatterTests() { + // Struct with primitives. + type s1 struct { + a int8 + b uint8 + } + v := s1{127, 255} + nv := (*s1)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "spew_test.s1" + vt2 := "int8" + vt3 := "uint8" + vs := "{127 255}" + vs2 := "{a:127 b:255}" + vs3 := "{a:(" + vt2 + ")127 b:(" + vt3 + ")255}" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs2) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs2) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs2) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs3) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs3) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs3) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs3) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs3) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs3) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Struct that contains another struct. + type s2 struct { + s1 s1 + b bool + } + v2 := s2{s1{127, 255}, true} + nv2 := (*s2)(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "spew_test.s2" + v2t2 := "spew_test.s1" + v2t3 := "int8" + v2t4 := "uint8" + v2t5 := "bool" + v2s := "{{127 255} true}" + v2s2 := "{s1:{a:127 b:255} b:true}" + v2s3 := "{s1:(" + v2t2 + "){a:(" + v2t3 + ")127 b:(" + v2t4 + ")255} b:(" + + v2t5 + ")true}" + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%+v", v2, v2s2) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s2) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s2) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%#v", v2, "("+v2t+")"+v2s3) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s3) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s3) + addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s3) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s3) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s3) + addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") + + // Struct that contains custom type with Stringer pointer interface via both + // exported and unexported fields. + type s3 struct { + s pstringer + S pstringer + } + v3 := s3{"test", "test2"} + nv3 := (*s3)(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "spew_test.s3" + v3t2 := "spew_test.pstringer" + v3s := "{stringer test stringer test2}" + v3sp := v3s + v3s2 := "{s:stringer test S:stringer test2}" + v3s2p := v3s2 + v3s3 := "{s:(" + v3t2 + ")stringer test S:(" + v3t2 + ")stringer test2}" + v3s3p := v3s3 + if spew.UnsafeDisabled { + v3s = "{test test2}" + v3sp = "{test stringer test2}" + v3s2 = "{s:test S:test2}" + v3s2p = "{s:test S:stringer test2}" + v3s3 = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")test2}" + v3s3p = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")stringer test2}" + } + addFormatterTest("%v", v3, v3s) + addFormatterTest("%v", pv3, "<*>"+v3sp) + addFormatterTest("%v", &pv3, "<**>"+v3sp) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%+v", v3, v3s2) + addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s2p) + addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s2p) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%#v", v3, "("+v3t+")"+v3s3) + addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s3p) + addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s3p) + addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") + addFormatterTest("%#+v", v3, "("+v3t+")"+v3s3) + addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s3p) + addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s3p) + addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") + + // Struct that contains embedded struct and field to same struct. + e := embed{"embedstr"} + v4 := embedwrap{embed: &e, e: &e} + nv4 := (*embedwrap)(nil) + pv4 := &v4 + eAddr := fmt.Sprintf("%p", &e) + v4Addr := fmt.Sprintf("%p", pv4) + pv4Addr := fmt.Sprintf("%p", &pv4) + v4t := "spew_test.embedwrap" + v4t2 := "spew_test.embed" + v4t3 := "string" + v4s := "{<*>{embedstr} <*>{embedstr}}" + v4s2 := "{embed:<*>(" + eAddr + "){a:embedstr} e:<*>(" + eAddr + + "){a:embedstr}}" + v4s3 := "{embed:(*" + v4t2 + "){a:(" + v4t3 + ")embedstr} e:(*" + v4t2 + + "){a:(" + v4t3 + ")embedstr}}" + v4s4 := "{embed:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 + + ")embedstr} e:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 + ")embedstr}}" + addFormatterTest("%v", v4, v4s) + addFormatterTest("%v", pv4, "<*>"+v4s) + addFormatterTest("%v", &pv4, "<**>"+v4s) + addFormatterTest("%+v", nv4, "") + addFormatterTest("%+v", v4, v4s2) + addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s2) + addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s2) + addFormatterTest("%+v", nv4, "") + addFormatterTest("%#v", v4, "("+v4t+")"+v4s3) + addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s3) + addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s3) + addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") + addFormatterTest("%#+v", v4, "("+v4t+")"+v4s4) + addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s4) + addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s4) + addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") +} + +func addUintptrFormatterTests() { + // Null pointer. + v := uintptr(0) + nv := (*uintptr)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "uintptr" + vs := "" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Address of real variable. + i := 1 + v2 := uintptr(unsafe.Pointer(&i)) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "uintptr" + v2s := fmt.Sprintf("%p", &i) + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) +} + +func addUnsafePointerFormatterTests() { + // Null pointer. + v := unsafe.Pointer(uintptr(0)) + nv := (*unsafe.Pointer)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "unsafe.Pointer" + vs := "" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Address of real variable. + i := 1 + v2 := unsafe.Pointer(&i) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "unsafe.Pointer" + v2s := fmt.Sprintf("%p", &i) + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) +} + +func addChanFormatterTests() { + // Nil channel. + var v chan int + pv := &v + nv := (*chan int)(nil) + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "chan int" + vs := "" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Real channel. + v2 := make(chan int) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "chan int" + v2s := fmt.Sprintf("%p", v2) + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) +} + +func addFuncFormatterTests() { + // Function with no params and no returns. + v := addIntFormatterTests + nv := (*func())(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "func()" + vs := fmt.Sprintf("%p", v) + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") + + // Function with param and no returns. + v2 := TestFormatter + nv2 := (*func(*testing.T))(nil) + pv2 := &v2 + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "func(*testing.T)" + v2s := fmt.Sprintf("%p", v2) + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s) + addFormatterTest("%v", &pv2, "<**>"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%+v", v2, v2s) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%+v", nv2, "") + addFormatterTest("%#v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) + addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) + addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") + + // Function with multiple params and multiple returns. + var v3 = func(i int, s string) (b bool, err error) { + return true, nil + } + nv3 := (*func(int, string) (bool, error))(nil) + pv3 := &v3 + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "func(int, string) (bool, error)" + v3s := fmt.Sprintf("%p", v3) + addFormatterTest("%v", v3, v3s) + addFormatterTest("%v", pv3, "<*>"+v3s) + addFormatterTest("%v", &pv3, "<**>"+v3s) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%+v", v3, v3s) + addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) + addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) + addFormatterTest("%+v", nv3, "") + addFormatterTest("%#v", v3, "("+v3t+")"+v3s) + addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) + addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) + addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") + addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) + addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) + addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) + addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") +} + +func addCircularFormatterTests() { + // Struct that is circular through self referencing. + type circular struct { + c *circular + } + v := circular{nil} + v.c = &v + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "spew_test.circular" + vs := "{<*>{<*>}}" + vs2 := "{<*>}" + vs3 := "{c:<*>(" + vAddr + "){c:<*>(" + vAddr + ")}}" + vs4 := "{c:<*>(" + vAddr + ")}" + vs5 := "{c:(*" + vt + "){c:(*" + vt + ")}}" + vs6 := "{c:(*" + vt + ")}" + vs7 := "{c:(*" + vt + ")(" + vAddr + "){c:(*" + vt + ")(" + vAddr + + ")}}" + vs8 := "{c:(*" + vt + ")(" + vAddr + ")}" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs2) + addFormatterTest("%v", &pv, "<**>"+vs2) + addFormatterTest("%+v", v, vs3) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs4) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs4) + addFormatterTest("%#v", v, "("+vt+")"+vs5) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs6) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs6) + addFormatterTest("%#+v", v, "("+vt+")"+vs7) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs8) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs8) + + // Structs that are circular through cross referencing. + v2 := xref1{nil} + ts2 := xref2{&v2} + v2.ps2 = &ts2 + pv2 := &v2 + ts2Addr := fmt.Sprintf("%p", &ts2) + v2Addr := fmt.Sprintf("%p", pv2) + pv2Addr := fmt.Sprintf("%p", &pv2) + v2t := "spew_test.xref1" + v2t2 := "spew_test.xref2" + v2s := "{<*>{<*>{<*>}}}" + v2s2 := "{<*>{<*>}}" + v2s3 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + "){ps2:<*>(" + + ts2Addr + ")}}}" + v2s4 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + ")}}" + v2s5 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + "){ps2:(*" + v2t2 + + ")}}}" + v2s6 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + ")}}" + v2s7 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t + + ")(" + v2Addr + "){ps2:(*" + v2t2 + ")(" + ts2Addr + + ")}}}" + v2s8 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t + + ")(" + v2Addr + ")}}" + addFormatterTest("%v", v2, v2s) + addFormatterTest("%v", pv2, "<*>"+v2s2) + addFormatterTest("%v", &pv2, "<**>"+v2s2) + addFormatterTest("%+v", v2, v2s3) + addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s4) + addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s4) + addFormatterTest("%#v", v2, "("+v2t+")"+v2s5) + addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s6) + addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s6) + addFormatterTest("%#+v", v2, "("+v2t+")"+v2s7) + addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s8) + addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s8) + + // Structs that are indirectly circular. + v3 := indirCir1{nil} + tic2 := indirCir2{nil} + tic3 := indirCir3{&v3} + tic2.ps3 = &tic3 + v3.ps2 = &tic2 + pv3 := &v3 + tic2Addr := fmt.Sprintf("%p", &tic2) + tic3Addr := fmt.Sprintf("%p", &tic3) + v3Addr := fmt.Sprintf("%p", pv3) + pv3Addr := fmt.Sprintf("%p", &pv3) + v3t := "spew_test.indirCir1" + v3t2 := "spew_test.indirCir2" + v3t3 := "spew_test.indirCir3" + v3s := "{<*>{<*>{<*>{<*>}}}}" + v3s2 := "{<*>{<*>{<*>}}}" + v3s3 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" + + v3Addr + "){ps2:<*>(" + tic2Addr + ")}}}}" + v3s4 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" + + v3Addr + ")}}}" + v3s5 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t + + "){ps2:(*" + v3t2 + ")}}}}" + v3s6 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t + + ")}}}" + v3s7 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" + + tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + "){ps2:(*" + v3t2 + + ")(" + tic2Addr + ")}}}}" + v3s8 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" + + tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + ")}}}" + addFormatterTest("%v", v3, v3s) + addFormatterTest("%v", pv3, "<*>"+v3s2) + addFormatterTest("%v", &pv3, "<**>"+v3s2) + addFormatterTest("%+v", v3, v3s3) + addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s4) + addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s4) + addFormatterTest("%#v", v3, "("+v3t+")"+v3s5) + addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s6) + addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s6) + addFormatterTest("%#+v", v3, "("+v3t+")"+v3s7) + addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s8) + addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s8) +} + +func addPanicFormatterTests() { + // Type that panics in its Stringer interface. + v := panicer(127) + nv := (*panicer)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "spew_test.panicer" + vs := "(PANIC=test panic)127" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") +} + +func addErrorFormatterTests() { + // Type that has a custom Error interface. + v := customError(127) + nv := (*customError)(nil) + pv := &v + vAddr := fmt.Sprintf("%p", pv) + pvAddr := fmt.Sprintf("%p", &pv) + vt := "spew_test.customError" + vs := "error: 127" + addFormatterTest("%v", v, vs) + addFormatterTest("%v", pv, "<*>"+vs) + addFormatterTest("%v", &pv, "<**>"+vs) + addFormatterTest("%v", nv, "") + addFormatterTest("%+v", v, vs) + addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) + addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%+v", nv, "") + addFormatterTest("%#v", v, "("+vt+")"+vs) + addFormatterTest("%#v", pv, "(*"+vt+")"+vs) + addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) + addFormatterTest("%#v", nv, "(*"+vt+")"+"") + addFormatterTest("%#+v", v, "("+vt+")"+vs) + addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) + addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) + addFormatterTest("%#+v", nv, "(*"+vt+")"+"") +} + +func addPassthroughFormatterTests() { + // %x passthrough with uint. + v := uint(4294967295) + pv := &v + vAddr := fmt.Sprintf("%x", pv) + pvAddr := fmt.Sprintf("%x", &pv) + vs := "ffffffff" + addFormatterTest("%x", v, vs) + addFormatterTest("%x", pv, vAddr) + addFormatterTest("%x", &pv, pvAddr) + + // %#x passthrough with uint. + v2 := int(2147483647) + pv2 := &v2 + v2Addr := fmt.Sprintf("%#x", pv2) + pv2Addr := fmt.Sprintf("%#x", &pv2) + v2s := "0x7fffffff" + addFormatterTest("%#x", v2, v2s) + addFormatterTest("%#x", pv2, v2Addr) + addFormatterTest("%#x", &pv2, pv2Addr) + + // %f passthrough with precision. + addFormatterTest("%.2f", 3.1415, "3.14") + addFormatterTest("%.3f", 3.1415, "3.142") + addFormatterTest("%.4f", 3.1415, "3.1415") + + // %f passthrough with width and precision. + addFormatterTest("%5.2f", 3.1415, " 3.14") + addFormatterTest("%6.3f", 3.1415, " 3.142") + addFormatterTest("%7.4f", 3.1415, " 3.1415") + + // %d passthrough with width. + addFormatterTest("%3d", 127, "127") + addFormatterTest("%4d", 127, " 127") + addFormatterTest("%5d", 127, " 127") + + // %q passthrough with string. + addFormatterTest("%q", "test", "\"test\"") +} + +// TestFormatter executes all of the tests described by formatterTests. +func TestFormatter(t *testing.T) { + // Setup tests. + addIntFormatterTests() + addUintFormatterTests() + addBoolFormatterTests() + addFloatFormatterTests() + addComplexFormatterTests() + addArrayFormatterTests() + addSliceFormatterTests() + addStringFormatterTests() + addInterfaceFormatterTests() + addMapFormatterTests() + addStructFormatterTests() + addUintptrFormatterTests() + addUnsafePointerFormatterTests() + addChanFormatterTests() + addFuncFormatterTests() + addCircularFormatterTests() + addPanicFormatterTests() + addErrorFormatterTests() + addPassthroughFormatterTests() + + t.Logf("Running %d tests", len(formatterTests)) + for i, test := range formatterTests { + buf := new(bytes.Buffer) + spew.Fprintf(buf, test.format, test.in) + s := buf.String() + if testFailed(s, test.wants) { + t.Errorf("Formatter #%d format: %s got: %s %s", i, test.format, s, + stringizeWants(test.wants)) + continue + } + } +} + +type testStruct struct { + x int +} + +func (ts testStruct) String() string { + return fmt.Sprintf("ts.%d", ts.x) +} + +type testStructP struct { + x int +} + +func (ts *testStructP) String() string { + return fmt.Sprintf("ts.%d", ts.x) +} + +func TestPrintSortedKeys(t *testing.T) { + cfg := spew.ConfigState{SortKeys: true} + s := cfg.Sprint(map[int]string{1: "1", 3: "3", 2: "2"}) + expected := "map[1:1 2:2 3:3]" + if s != expected { + t.Errorf("Sorted keys mismatch 1:\n %v %v", s, expected) + } + + s = cfg.Sprint(map[stringer]int{"1": 1, "3": 3, "2": 2}) + expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]" + if s != expected { + t.Errorf("Sorted keys mismatch 2:\n %v %v", s, expected) + } + + s = cfg.Sprint(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2}) + expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]" + if spew.UnsafeDisabled { + expected = "map[1:1 2:2 3:3]" + } + if s != expected { + t.Errorf("Sorted keys mismatch 3:\n %v %v", s, expected) + } + + s = cfg.Sprint(map[testStruct]int{testStruct{1}: 1, testStruct{3}: 3, testStruct{2}: 2}) + expected = "map[ts.1:1 ts.2:2 ts.3:3]" + if s != expected { + t.Errorf("Sorted keys mismatch 4:\n %v %v", s, expected) + } + + if !spew.UnsafeDisabled { + s = cfg.Sprint(map[testStructP]int{testStructP{1}: 1, testStructP{3}: 3, testStructP{2}: 2}) + expected = "map[ts.1:1 ts.2:2 ts.3:3]" + if s != expected { + t.Errorf("Sorted keys mismatch 5:\n %v %v", s, expected) + } + } + + s = cfg.Sprint(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2}) + expected = "map[error: 1:1 error: 2:2 error: 3:3]" + if s != expected { + t.Errorf("Sorted keys mismatch 6:\n %v %v", s, expected) + } +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/internal_test.go b/vendor/src/github.com/davecgh/go-spew/spew/internal_test.go new file mode 100644 index 00000000..20a9cfef --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/internal_test.go @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +This test file is part of the spew package rather than than the spew_test +package because it needs access to internals to properly test certain cases +which are not possible via the public interface since they should never happen. +*/ + +package spew + +import ( + "bytes" + "reflect" + "testing" +) + +// dummyFmtState implements a fake fmt.State to use for testing invalid +// reflect.Value handling. This is necessary because the fmt package catches +// invalid values before invoking the formatter on them. +type dummyFmtState struct { + bytes.Buffer +} + +func (dfs *dummyFmtState) Flag(f int) bool { + if f == int('+') { + return true + } + return false +} + +func (dfs *dummyFmtState) Precision() (int, bool) { + return 0, false +} + +func (dfs *dummyFmtState) Width() (int, bool) { + return 0, false +} + +// TestInvalidReflectValue ensures the dump and formatter code handles an +// invalid reflect value properly. This needs access to internal state since it +// should never happen in real code and therefore can't be tested via the public +// API. +func TestInvalidReflectValue(t *testing.T) { + i := 1 + + // Dump invalid reflect value. + v := new(reflect.Value) + buf := new(bytes.Buffer) + d := dumpState{w: buf, cs: &Config} + d.dump(*v) + s := buf.String() + want := "" + if s != want { + t.Errorf("InvalidReflectValue #%d\n got: %s want: %s", i, s, want) + } + i++ + + // Formatter invalid reflect value. + buf2 := new(dummyFmtState) + f := formatState{value: *v, cs: &Config, fs: buf2} + f.format(*v) + s = buf2.String() + want = "" + if s != want { + t.Errorf("InvalidReflectValue #%d got: %s want: %s", i, s, want) + } +} + +// SortValues makes the internal sortValues function available to the test +// package. +func SortValues(values []reflect.Value, cs *ConfigState) { + sortValues(values, cs) +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go b/vendor/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go new file mode 100644 index 00000000..a0c612ec --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go @@ -0,0 +1,102 @@ +// Copyright (c) 2013-2016 Dave Collins + +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. + +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is not running on Google App Engine, compiled by GopherJS, and +// "-tags safe" is not added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// +build !js,!appengine,!safe,!disableunsafe + +/* +This test file is part of the spew package rather than than the spew_test +package because it needs access to internals to properly test certain cases +which are not possible via the public interface since they should never happen. +*/ + +package spew + +import ( + "bytes" + "reflect" + "testing" + "unsafe" +) + +// changeKind uses unsafe to intentionally change the kind of a reflect.Value to +// the maximum kind value which does not exist. This is needed to test the +// fallback code which punts to the standard fmt library for new types that +// might get added to the language. +func changeKind(v *reflect.Value, readOnly bool) { + rvf := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + offsetFlag)) + *rvf = *rvf | ((1< + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "fmt" + "io" +) + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the formatted string as a value that satisfies error. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a default Formatter interface returned by NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) +func Print(a ...interface{}) (n int, err error) { + return fmt.Print(convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) +func Println(a ...interface{}) (n int, err error) { + return fmt.Println(convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprint(a ...interface{}) string { + return fmt.Sprint(convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprintln(a ...interface{}) string { + return fmt.Sprintln(convertArgs(a)...) +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a default spew Formatter interface. +func convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = NewFormatter(arg) + } + return formatters +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/spew_test.go b/vendor/src/github.com/davecgh/go-spew/spew/spew_test.go new file mode 100644 index 00000000..b70466c6 --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/spew_test.go @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew_test + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "testing" + + "github.com/davecgh/go-spew/spew" +) + +// spewFunc is used to identify which public function of the spew package or +// ConfigState a test applies to. +type spewFunc int + +const ( + fCSFdump spewFunc = iota + fCSFprint + fCSFprintf + fCSFprintln + fCSPrint + fCSPrintln + fCSSdump + fCSSprint + fCSSprintf + fCSSprintln + fCSErrorf + fCSNewFormatter + fErrorf + fFprint + fFprintln + fPrint + fPrintln + fSdump + fSprint + fSprintf + fSprintln +) + +// Map of spewFunc values to names for pretty printing. +var spewFuncStrings = map[spewFunc]string{ + fCSFdump: "ConfigState.Fdump", + fCSFprint: "ConfigState.Fprint", + fCSFprintf: "ConfigState.Fprintf", + fCSFprintln: "ConfigState.Fprintln", + fCSSdump: "ConfigState.Sdump", + fCSPrint: "ConfigState.Print", + fCSPrintln: "ConfigState.Println", + fCSSprint: "ConfigState.Sprint", + fCSSprintf: "ConfigState.Sprintf", + fCSSprintln: "ConfigState.Sprintln", + fCSErrorf: "ConfigState.Errorf", + fCSNewFormatter: "ConfigState.NewFormatter", + fErrorf: "spew.Errorf", + fFprint: "spew.Fprint", + fFprintln: "spew.Fprintln", + fPrint: "spew.Print", + fPrintln: "spew.Println", + fSdump: "spew.Sdump", + fSprint: "spew.Sprint", + fSprintf: "spew.Sprintf", + fSprintln: "spew.Sprintln", +} + +func (f spewFunc) String() string { + if s, ok := spewFuncStrings[f]; ok { + return s + } + return fmt.Sprintf("Unknown spewFunc (%d)", int(f)) +} + +// spewTest is used to describe a test to be performed against the public +// functions of the spew package or ConfigState. +type spewTest struct { + cs *spew.ConfigState + f spewFunc + format string + in interface{} + want string +} + +// spewTests houses the tests to be performed against the public functions of +// the spew package and ConfigState. +// +// These tests are only intended to ensure the public functions are exercised +// and are intentionally not exhaustive of types. The exhaustive type +// tests are handled in the dump and format tests. +var spewTests []spewTest + +// redirStdout is a helper function to return the standard output from f as a +// byte slice. +func redirStdout(f func()) ([]byte, error) { + tempFile, err := ioutil.TempFile("", "ss-test") + if err != nil { + return nil, err + } + fileName := tempFile.Name() + defer os.Remove(fileName) // Ignore error + + origStdout := os.Stdout + os.Stdout = tempFile + f() + os.Stdout = origStdout + tempFile.Close() + + return ioutil.ReadFile(fileName) +} + +func initSpewTests() { + // Config states with various settings. + scsDefault := spew.NewDefaultConfig() + scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true} + scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true} + scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1} + scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true} + scsNoPtrAddr := &spew.ConfigState{DisablePointerAddresses: true} + scsNoCap := &spew.ConfigState{DisableCapacities: true} + + // Variables for tests on types which implement Stringer interface with and + // without a pointer receiver. + ts := stringer("test") + tps := pstringer("test") + + type ptrTester struct { + s *struct{} + } + tptr := &ptrTester{s: &struct{}{}} + + // depthTester is used to test max depth handling for structs, array, slices + // and maps. + type depthTester struct { + ic indirCir1 + arr [1]string + slice []string + m map[string]int + } + dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"}, + map[string]int{"one": 1}} + + // Variable for tests on types which implement error interface. + te := customError(10) + + spewTests = []spewTest{ + {scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"}, + {scsDefault, fCSFprint, "", int16(32767), "32767"}, + {scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"}, + {scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"}, + {scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"}, + {scsDefault, fCSPrintln, "", uint8(255), "255\n"}, + {scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"}, + {scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"}, + {scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"}, + {scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"}, + {scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"}, + {scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"}, + {scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"}, + {scsDefault, fFprint, "", float32(3.14), "3.14"}, + {scsDefault, fFprintln, "", float64(6.28), "6.28\n"}, + {scsDefault, fPrint, "", true, "true"}, + {scsDefault, fPrintln, "", false, "false\n"}, + {scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"}, + {scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"}, + {scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"}, + {scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"}, + {scsNoMethods, fCSFprint, "", ts, "test"}, + {scsNoMethods, fCSFprint, "", &ts, "<*>test"}, + {scsNoMethods, fCSFprint, "", tps, "test"}, + {scsNoMethods, fCSFprint, "", &tps, "<*>test"}, + {scsNoPmethods, fCSFprint, "", ts, "stringer test"}, + {scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"}, + {scsNoPmethods, fCSFprint, "", tps, "test"}, + {scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"}, + {scsMaxDepth, fCSFprint, "", dt, "{{} [] [] map[]}"}, + {scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" + + " ic: (spew_test.indirCir1) {\n \n },\n" + + " arr: ([1]string) (len=1 cap=1) {\n \n },\n" + + " slice: ([]string) (len=1 cap=1) {\n \n },\n" + + " m: (map[string]int) (len=1) {\n \n }\n}\n"}, + {scsContinue, fCSFprint, "", ts, "(stringer test) test"}, + {scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " + + "(len=4) (stringer test) \"test\"\n"}, + {scsContinue, fCSFprint, "", te, "(error: 10) 10"}, + {scsContinue, fCSFdump, "", te, "(spew_test.customError) " + + "(error: 10) 10\n"}, + {scsNoPtrAddr, fCSFprint, "", tptr, "<*>{<*>{}}"}, + {scsNoPtrAddr, fCSSdump, "", tptr, "(*spew_test.ptrTester)({\ns: (*struct {})({\n})\n})\n"}, + {scsNoCap, fCSSdump, "", make([]string, 0, 10), "([]string) {\n}\n"}, + {scsNoCap, fCSSdump, "", make([]string, 1, 10), "([]string) (len=1) {\n(string) \"\"\n}\n"}, + } +} + +// TestSpew executes all of the tests described by spewTests. +func TestSpew(t *testing.T) { + initSpewTests() + + t.Logf("Running %d tests", len(spewTests)) + for i, test := range spewTests { + buf := new(bytes.Buffer) + switch test.f { + case fCSFdump: + test.cs.Fdump(buf, test.in) + + case fCSFprint: + test.cs.Fprint(buf, test.in) + + case fCSFprintf: + test.cs.Fprintf(buf, test.format, test.in) + + case fCSFprintln: + test.cs.Fprintln(buf, test.in) + + case fCSPrint: + b, err := redirStdout(func() { test.cs.Print(test.in) }) + if err != nil { + t.Errorf("%v #%d %v", test.f, i, err) + continue + } + buf.Write(b) + + case fCSPrintln: + b, err := redirStdout(func() { test.cs.Println(test.in) }) + if err != nil { + t.Errorf("%v #%d %v", test.f, i, err) + continue + } + buf.Write(b) + + case fCSSdump: + str := test.cs.Sdump(test.in) + buf.WriteString(str) + + case fCSSprint: + str := test.cs.Sprint(test.in) + buf.WriteString(str) + + case fCSSprintf: + str := test.cs.Sprintf(test.format, test.in) + buf.WriteString(str) + + case fCSSprintln: + str := test.cs.Sprintln(test.in) + buf.WriteString(str) + + case fCSErrorf: + err := test.cs.Errorf(test.format, test.in) + buf.WriteString(err.Error()) + + case fCSNewFormatter: + fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in)) + + case fErrorf: + err := spew.Errorf(test.format, test.in) + buf.WriteString(err.Error()) + + case fFprint: + spew.Fprint(buf, test.in) + + case fFprintln: + spew.Fprintln(buf, test.in) + + case fPrint: + b, err := redirStdout(func() { spew.Print(test.in) }) + if err != nil { + t.Errorf("%v #%d %v", test.f, i, err) + continue + } + buf.Write(b) + + case fPrintln: + b, err := redirStdout(func() { spew.Println(test.in) }) + if err != nil { + t.Errorf("%v #%d %v", test.f, i, err) + continue + } + buf.Write(b) + + case fSdump: + str := spew.Sdump(test.in) + buf.WriteString(str) + + case fSprint: + str := spew.Sprint(test.in) + buf.WriteString(str) + + case fSprintf: + str := spew.Sprintf(test.format, test.in) + buf.WriteString(str) + + case fSprintln: + str := spew.Sprintln(test.in) + buf.WriteString(str) + + default: + t.Errorf("%v #%d unrecognized function", test.f, i) + continue + } + s := buf.String() + if test.want != s { + t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want) + continue + } + } +} diff --git a/vendor/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go b/vendor/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go new file mode 100644 index 00000000..5c87dd45 --- /dev/null +++ b/vendor/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go @@ -0,0 +1,82 @@ +// Copyright (c) 2013 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when both cgo is supported and "-tags testcgo" is added to the go test +// command line. This code should really only be in the dumpcgo_test.go file, +// but unfortunately Go will not allow cgo in test files, so this is a +// workaround to allow cgo types to be tested. This configuration is used +// because spew itself does not require cgo to run even though it does handle +// certain cgo types specially. Rather than forcing all clients to require cgo +// and an external C compiler just to run the tests, this scheme makes them +// optional. +// +build cgo,testcgo + +package testdata + +/* +#include +typedef unsigned char custom_uchar_t; + +char *ncp = 0; +char *cp = "test"; +char ca[6] = {'t', 'e', 's', 't', '2', '\0'}; +unsigned char uca[6] = {'t', 'e', 's', 't', '3', '\0'}; +signed char sca[6] = {'t', 'e', 's', 't', '4', '\0'}; +uint8_t ui8ta[6] = {'t', 'e', 's', 't', '5', '\0'}; +custom_uchar_t tuca[6] = {'t', 'e', 's', 't', '6', '\0'}; +*/ +import "C" + +// GetCgoNullCharPointer returns a null char pointer via cgo. This is only +// used for tests. +func GetCgoNullCharPointer() interface{} { + return C.ncp +} + +// GetCgoCharPointer returns a char pointer via cgo. This is only used for +// tests. +func GetCgoCharPointer() interface{} { + return C.cp +} + +// GetCgoCharArray returns a char array via cgo and the array's len and cap. +// This is only used for tests. +func GetCgoCharArray() (interface{}, int, int) { + return C.ca, len(C.ca), cap(C.ca) +} + +// GetCgoUnsignedCharArray returns an unsigned char array via cgo and the +// array's len and cap. This is only used for tests. +func GetCgoUnsignedCharArray() (interface{}, int, int) { + return C.uca, len(C.uca), cap(C.uca) +} + +// GetCgoSignedCharArray returns a signed char array via cgo and the array's len +// and cap. This is only used for tests. +func GetCgoSignedCharArray() (interface{}, int, int) { + return C.sca, len(C.sca), cap(C.sca) +} + +// GetCgoUint8tArray returns a uint8_t array via cgo and the array's len and +// cap. This is only used for tests. +func GetCgoUint8tArray() (interface{}, int, int) { + return C.ui8ta, len(C.ui8ta), cap(C.ui8ta) +} + +// GetCgoTypdefedUnsignedCharArray returns a typedefed unsigned char array via +// cgo and the array's len and cap. This is only used for tests. +func GetCgoTypdefedUnsignedCharArray() (interface{}, int, int) { + return C.tuca, len(C.tuca), cap(C.tuca) +} diff --git a/vendor/src/github.com/eapache/go-resiliency/breaker/README.md b/vendor/src/github.com/eapache/go-resiliency/breaker/README.md new file mode 100644 index 00000000..2d1b3d93 --- /dev/null +++ b/vendor/src/github.com/eapache/go-resiliency/breaker/README.md @@ -0,0 +1,34 @@ +circuit-breaker +=============== + +[![Build Status](https://travis-ci.org/eapache/go-resiliency.svg?branch=master)](https://travis-ci.org/eapache/go-resiliency) +[![GoDoc](https://godoc.org/github.com/eapache/go-resiliency/breaker?status.svg)](https://godoc.org/github.com/eapache/go-resiliency/breaker) +[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](https://eapache.github.io/conduct.html) + +The circuit-breaker resiliency pattern for golang. + +Creating a breaker takes three parameters: +- error threshold (for opening the breaker) +- success threshold (for closing the breaker) +- timeout (how long to keep the breaker open) + +```go +b := breaker.New(3, 1, 5*time.Second) + +for { + result := b.Run(func() error { + // communicate with some external service and + // return an error if the communication failed + return nil + }) + + switch result { + case nil: + // success! + case breaker.ErrBreakerOpen: + // our function wasn't run because the breaker was open + default: + // some other error + } +} +``` diff --git a/vendor/src/github.com/eapache/go-resiliency/breaker/breaker.go b/vendor/src/github.com/eapache/go-resiliency/breaker/breaker.go new file mode 100644 index 00000000..f88ca724 --- /dev/null +++ b/vendor/src/github.com/eapache/go-resiliency/breaker/breaker.go @@ -0,0 +1,161 @@ +// Package breaker implements the circuit-breaker resiliency pattern for Go. +package breaker + +import ( + "errors" + "sync" + "sync/atomic" + "time" +) + +// ErrBreakerOpen is the error returned from Run() when the function is not executed +// because the breaker is currently open. +var ErrBreakerOpen = errors.New("circuit breaker is open") + +const ( + closed uint32 = iota + open + halfOpen +) + +// Breaker implements the circuit-breaker resiliency pattern +type Breaker struct { + errorThreshold, successThreshold int + timeout time.Duration + + lock sync.Mutex + state uint32 + errors, successes int + lastError time.Time +} + +// New constructs a new circuit-breaker that starts closed. +// From closed, the breaker opens if "errorThreshold" errors are seen +// without an error-free period of at least "timeout". From open, the +// breaker half-closes after "timeout". From half-open, the breaker closes +// after "successThreshold" consecutive successes, or opens on a single error. +func New(errorThreshold, successThreshold int, timeout time.Duration) *Breaker { + return &Breaker{ + errorThreshold: errorThreshold, + successThreshold: successThreshold, + timeout: timeout, + } +} + +// Run will either return ErrBreakerOpen immediately if the circuit-breaker is +// already open, or it will run the given function and pass along its return +// value. It is safe to call Run concurrently on the same Breaker. +func (b *Breaker) Run(work func() error) error { + state := atomic.LoadUint32(&b.state) + + if state == open { + return ErrBreakerOpen + } + + return b.doWork(state, work) +} + +// Go will either return ErrBreakerOpen immediately if the circuit-breaker is +// already open, or it will run the given function in a separate goroutine. +// If the function is run, Go will return nil immediately, and will *not* return +// the return value of the function. It is safe to call Go concurrently on the +// same Breaker. +func (b *Breaker) Go(work func() error) error { + state := atomic.LoadUint32(&b.state) + + if state == open { + return ErrBreakerOpen + } + + // errcheck complains about ignoring the error return value, but + // that's on purpose; if you want an error from a goroutine you have to + // get it over a channel or something + go b.doWork(state, work) + + return nil +} + +func (b *Breaker) doWork(state uint32, work func() error) error { + var panicValue interface{} + + result := func() error { + defer func() { + panicValue = recover() + }() + return work() + }() + + if result == nil && panicValue == nil && state == closed { + // short-circuit the normal, success path without contending + // on the lock + return nil + } + + // oh well, I guess we have to contend on the lock + b.processResult(result, panicValue) + + if panicValue != nil { + // as close as Go lets us come to a "rethrow" although unfortunately + // we lose the original panicing location + panic(panicValue) + } + + return result +} + +func (b *Breaker) processResult(result error, panicValue interface{}) { + b.lock.Lock() + defer b.lock.Unlock() + + if result == nil && panicValue == nil { + if b.state == halfOpen { + b.successes++ + if b.successes == b.successThreshold { + b.closeBreaker() + } + } + } else { + if b.errors > 0 { + expiry := b.lastError.Add(b.timeout) + if time.Now().After(expiry) { + b.errors = 0 + } + } + + switch b.state { + case closed: + b.errors++ + if b.errors == b.errorThreshold { + b.openBreaker() + } else { + b.lastError = time.Now() + } + case halfOpen: + b.openBreaker() + } + } +} + +func (b *Breaker) openBreaker() { + b.changeState(open) + go b.timer() +} + +func (b *Breaker) closeBreaker() { + b.changeState(closed) +} + +func (b *Breaker) timer() { + time.Sleep(b.timeout) + + b.lock.Lock() + defer b.lock.Unlock() + + b.changeState(halfOpen) +} + +func (b *Breaker) changeState(newState uint32) { + b.errors = 0 + b.successes = 0 + atomic.StoreUint32(&b.state, newState) +} diff --git a/vendor/src/github.com/eapache/go-resiliency/breaker/breaker_test.go b/vendor/src/github.com/eapache/go-resiliency/breaker/breaker_test.go new file mode 100644 index 00000000..b41308db --- /dev/null +++ b/vendor/src/github.com/eapache/go-resiliency/breaker/breaker_test.go @@ -0,0 +1,196 @@ +package breaker + +import ( + "errors" + "testing" + "time" +) + +var errSomeError = errors.New("errSomeError") + +func alwaysPanics() error { + panic("foo") +} + +func returnsError() error { + return errSomeError +} + +func returnsSuccess() error { + return nil +} + +func TestBreakerErrorExpiry(t *testing.T) { + breaker := New(2, 1, 1*time.Second) + + for i := 0; i < 3; i++ { + if err := breaker.Run(returnsError); err != errSomeError { + t.Error(err) + } + time.Sleep(1 * time.Second) + } + + for i := 0; i < 3; i++ { + if err := breaker.Go(returnsError); err != nil { + t.Error(err) + } + time.Sleep(1 * time.Second) + } +} + +func TestBreakerPanicsCountAsErrors(t *testing.T) { + breaker := New(3, 2, 1*time.Second) + + // three errors opens the breaker + for i := 0; i < 3; i++ { + func() { + defer func() { + val := recover() + if val.(string) != "foo" { + t.Error("incorrect panic") + } + }() + if err := breaker.Run(alwaysPanics); err != nil { + t.Error(err) + } + t.Error("shouldn't get here") + }() + } + + // breaker is open + for i := 0; i < 5; i++ { + if err := breaker.Run(returnsError); err != ErrBreakerOpen { + t.Error(err) + } + } +} + +func TestBreakerStateTransitions(t *testing.T) { + breaker := New(3, 2, 1*time.Second) + + // three errors opens the breaker + for i := 0; i < 3; i++ { + if err := breaker.Run(returnsError); err != errSomeError { + t.Error(err) + } + } + + // breaker is open + for i := 0; i < 5; i++ { + if err := breaker.Run(returnsError); err != ErrBreakerOpen { + t.Error(err) + } + } + + // wait for it to half-close + time.Sleep(2 * time.Second) + // one success works, but is not enough to fully close + if err := breaker.Run(returnsSuccess); err != nil { + t.Error(err) + } + // error works, but re-opens immediately + if err := breaker.Run(returnsError); err != errSomeError { + t.Error(err) + } + // breaker is open + if err := breaker.Run(returnsError); err != ErrBreakerOpen { + t.Error(err) + } + + // wait for it to half-close + time.Sleep(2 * time.Second) + // two successes is enough to close it for good + for i := 0; i < 2; i++ { + if err := breaker.Run(returnsSuccess); err != nil { + t.Error(err) + } + } + // error works + if err := breaker.Run(returnsError); err != errSomeError { + t.Error(err) + } + // breaker is still closed + if err := breaker.Run(returnsSuccess); err != nil { + t.Error(err) + } +} + +func TestBreakerAsyncStateTransitions(t *testing.T) { + breaker := New(3, 2, 1*time.Second) + + // three errors opens the breaker + for i := 0; i < 3; i++ { + if err := breaker.Go(returnsError); err != nil { + t.Error(err) + } + } + + // just enough to yield the scheduler and let the goroutines work off + time.Sleep(1 * time.Millisecond) + + // breaker is open + for i := 0; i < 5; i++ { + if err := breaker.Go(returnsError); err != ErrBreakerOpen { + t.Error(err) + } + } + + // wait for it to half-close + time.Sleep(2 * time.Second) + // one success works, but is not enough to fully close + if err := breaker.Go(returnsSuccess); err != nil { + t.Error(err) + } + // error works, but re-opens immediately + if err := breaker.Go(returnsError); err != nil { + t.Error(err) + } + // just enough to yield the scheduler and let the goroutines work off + time.Sleep(1 * time.Millisecond) + // breaker is open + if err := breaker.Go(returnsError); err != ErrBreakerOpen { + t.Error(err) + } + + // wait for it to half-close + time.Sleep(2 * time.Second) + // two successes is enough to close it for good + for i := 0; i < 2; i++ { + if err := breaker.Go(returnsSuccess); err != nil { + t.Error(err) + } + } + // just enough to yield the scheduler and let the goroutines work off + time.Sleep(1 * time.Millisecond) + // error works + if err := breaker.Go(returnsError); err != nil { + t.Error(err) + } + // just enough to yield the scheduler and let the goroutines work off + time.Sleep(1 * time.Millisecond) + // breaker is still closed + if err := breaker.Go(returnsSuccess); err != nil { + t.Error(err) + } +} + +func ExampleBreaker() { + breaker := New(3, 1, 5*time.Second) + + for { + result := breaker.Run(func() error { + // communicate with some external service and + // return an error if the communication failed + return nil + }) + + switch result { + case nil: + // success! + case ErrBreakerOpen: + // our function wasn't run because the breaker was open + default: + // some other error + } + } +} diff --git a/vendor/src/github.com/eapache/go-xerial-snappy/LICENSE b/vendor/src/github.com/eapache/go-xerial-snappy/LICENSE new file mode 100644 index 00000000..5bf3688d --- /dev/null +++ b/vendor/src/github.com/eapache/go-xerial-snappy/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Evan Huus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/src/github.com/eapache/go-xerial-snappy/README.md b/vendor/src/github.com/eapache/go-xerial-snappy/README.md new file mode 100644 index 00000000..3f2695c7 --- /dev/null +++ b/vendor/src/github.com/eapache/go-xerial-snappy/README.md @@ -0,0 +1,13 @@ +# go-xerial-snappy + +[![Build Status](https://travis-ci.org/eapache/go-xerial-snappy.svg?branch=master)](https://travis-ci.org/eapache/go-xerial-snappy) + +Xerial-compatible Snappy framing support for golang. + +Packages using Xerial for snappy encoding use a framing format incompatible with +basically everything else in existence. This package wraps Go's built-in snappy +package to support it. + +Apps that use this format include Apache Kafka (see +https://github.com/dpkp/kafka-python/issues/126#issuecomment-35478921 for +details). diff --git a/vendor/src/github.com/eapache/go-xerial-snappy/snappy.go b/vendor/src/github.com/eapache/go-xerial-snappy/snappy.go new file mode 100644 index 00000000..b8f8b51f --- /dev/null +++ b/vendor/src/github.com/eapache/go-xerial-snappy/snappy.go @@ -0,0 +1,43 @@ +package snappy + +import ( + "bytes" + "encoding/binary" + + master "github.com/golang/snappy" +) + +var xerialHeader = []byte{130, 83, 78, 65, 80, 80, 89, 0} + +// Encode encodes data as snappy with no framing header. +func Encode(src []byte) []byte { + return master.Encode(nil, src) +} + +// Decode decodes snappy data whether it is traditional unframed +// or includes the xerial framing format. +func Decode(src []byte) ([]byte, error) { + if !bytes.Equal(src[:8], xerialHeader) { + return master.Decode(nil, src) + } + + var ( + pos = uint32(16) + max = uint32(len(src)) + dst = make([]byte, 0, len(src)) + chunk []byte + err error + ) + for pos < max { + size := binary.BigEndian.Uint32(src[pos : pos+4]) + pos += 4 + + chunk, err = master.Decode(chunk, src[pos:pos+size]) + if err != nil { + return nil, err + } + pos += size + dst = append(dst, chunk...) + } + return dst, nil +} diff --git a/vendor/src/github.com/eapache/go-xerial-snappy/snappy_test.go b/vendor/src/github.com/eapache/go-xerial-snappy/snappy_test.go new file mode 100644 index 00000000..e94f635d --- /dev/null +++ b/vendor/src/github.com/eapache/go-xerial-snappy/snappy_test.go @@ -0,0 +1,49 @@ +package snappy + +import ( + "bytes" + "testing" +) + +var snappyTestCases = map[string][]byte{ + "REPEATREPEATREPEATREPEATREPEATREPEAT": {36, 20, 82, 69, 80, 69, 65, 84, 118, 6, 0}, + "REALLY SHORT": {12, 44, 82, 69, 65, 76, 76, 89, 32, 83, 72, 79, 82, 84}, + "AXBXCXDXEXFX": {12, 44, 65, 88, 66, 88, 67, 88, 68, 88, 69, 88, 70, 88}, +} + +var snappyStreamTestCases = map[string][]byte{ + "PLAINDATA": {130, 83, 78, 65, 80, 80, 89, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 11, 9, 32, 80, 76, 65, 73, 78, 68, 65, 84, 65}, + `{"a":"UtaitILHMDAAAAfU","b":"日本"}`: {130, 83, 78, 65, 80, 80, 89, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 39, 37, 144, 123, 34, 97, 34, 58, 34, 85, 116, 97, 105, 116, 73, 76, 72, 77, 68, 65, 65, 65, 65, 102, 85, 34, 44, 34, 98, 34, 58, 34, 230, 151, 165, 230, 156, 172, 34, 125}, + `Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias except`: {130, 83, 78, 65, 80, 80, 89, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 3, 89, 128, 8, 240, 90, 83, 101, 100, 32, 117, 116, 32, 112, 101, 114, 115, 112, 105, 99, 105, 97, 116, 105, 115, 32, 117, 110, 100, 101, 32, 111, 109, 110, 105, 115, 32, 105, 115, 116, 101, 32, 110, 97, 116, 117, 115, 32, 101, 114, 114, 111, 114, 32, 115, 105, 116, 32, 118, 111, 108, 117, 112, 116, 97, 116, 101, 109, 32, 97, 99, 99, 117, 115, 97, 110, 116, 105, 117, 109, 32, 100, 111, 108, 111, 114, 101, 109, 113, 117, 101, 32, 108, 97, 117, 100, 97, 5, 22, 240, 60, 44, 32, 116, 111, 116, 97, 109, 32, 114, 101, 109, 32, 97, 112, 101, 114, 105, 97, 109, 44, 32, 101, 97, 113, 117, 101, 32, 105, 112, 115, 97, 32, 113, 117, 97, 101, 32, 97, 98, 32, 105, 108, 108, 111, 32, 105, 110, 118, 101, 110, 116, 111, 114, 101, 32, 118, 101, 114, 105, 116, 97, 1, 141, 4, 101, 116, 1, 36, 88, 115, 105, 32, 97, 114, 99, 104, 105, 116, 101, 99, 116, 111, 32, 98, 101, 97, 116, 97, 101, 32, 118, 105, 1, 6, 120, 100, 105, 99, 116, 97, 32, 115, 117, 110, 116, 32, 101, 120, 112, 108, 105, 99, 97, 98, 111, 46, 32, 78, 101, 109, 111, 32, 101, 110, 105, 109, 5, 103, 0, 109, 46, 180, 0, 12, 113, 117, 105, 97, 17, 16, 0, 115, 5, 209, 72, 97, 115, 112, 101, 114, 110, 97, 116, 117, 114, 32, 97, 117, 116, 32, 111, 100, 105, 116, 5, 9, 36, 102, 117, 103, 105, 116, 44, 32, 115, 101, 100, 9, 53, 32, 99, 111, 110, 115, 101, 113, 117, 117, 110, 1, 42, 20, 109, 97, 103, 110, 105, 32, 9, 245, 16, 115, 32, 101, 111, 115, 1, 36, 28, 32, 114, 97, 116, 105, 111, 110, 101, 17, 96, 33, 36, 1, 51, 36, 105, 32, 110, 101, 115, 99, 105, 117, 110, 116, 1, 155, 1, 254, 16, 112, 111, 114, 114, 111, 1, 51, 36, 115, 113, 117, 97, 109, 32, 101, 115, 116, 44, 1, 14, 13, 81, 5, 183, 4, 117, 109, 1, 18, 0, 97, 9, 19, 4, 32, 115, 1, 149, 12, 109, 101, 116, 44, 9, 135, 76, 99, 116, 101, 116, 117, 114, 44, 32, 97, 100, 105, 112, 105, 115, 99, 105, 32, 118, 101, 108, 50, 173, 0, 24, 110, 111, 110, 32, 110, 117, 109, 9, 94, 84, 105, 117, 115, 32, 109, 111, 100, 105, 32, 116, 101, 109, 112, 111, 114, 97, 32, 105, 110, 99, 105, 100, 33, 52, 20, 117, 116, 32, 108, 97, 98, 33, 116, 4, 101, 116, 9, 106, 0, 101, 5, 219, 20, 97, 109, 32, 97, 108, 105, 5, 62, 33, 164, 8, 114, 97, 116, 29, 212, 12, 46, 32, 85, 116, 41, 94, 52, 97, 100, 32, 109, 105, 110, 105, 109, 97, 32, 118, 101, 110, 105, 33, 221, 72, 113, 117, 105, 115, 32, 110, 111, 115, 116, 114, 117, 109, 32, 101, 120, 101, 114, 99, 105, 33, 202, 104, 111, 110, 101, 109, 32, 117, 108, 108, 97, 109, 32, 99, 111, 114, 112, 111, 114, 105, 115, 32, 115, 117, 115, 99, 105, 112, 105, 13, 130, 8, 105, 111, 115, 1, 64, 12, 110, 105, 115, 105, 1, 150, 5, 126, 44, 105, 100, 32, 101, 120, 32, 101, 97, 32, 99, 111, 109, 5, 192, 0, 99, 41, 131, 33, 172, 8, 63, 32, 81, 1, 107, 4, 97, 117, 33, 101, 96, 118, 101, 108, 32, 101, 117, 109, 32, 105, 117, 114, 101, 32, 114, 101, 112, 114, 101, 104, 101, 110, 100, 101, 114, 105, 65, 63, 12, 105, 32, 105, 110, 1, 69, 16, 118, 111, 108, 117, 112, 65, 185, 1, 47, 24, 105, 116, 32, 101, 115, 115, 101, 1, 222, 64, 109, 32, 110, 105, 104, 105, 108, 32, 109, 111, 108, 101, 115, 116, 105, 97, 101, 46, 103, 0, 0, 44, 1, 45, 16, 32, 105, 108, 108, 117, 37, 143, 45, 36, 0, 109, 5, 110, 65, 33, 20, 97, 116, 32, 113, 117, 111, 17, 92, 44, 115, 32, 110, 117, 108, 108, 97, 32, 112, 97, 114, 105, 9, 165, 24, 65, 116, 32, 118, 101, 114, 111, 69, 34, 44, 101, 116, 32, 97, 99, 99, 117, 115, 97, 109, 117, 115, 1, 13, 104, 105, 117, 115, 116, 111, 32, 111, 100, 105, 111, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 111, 115, 32, 100, 117, 99, 105, 1, 34, 80, 113, 117, 105, 32, 98, 108, 97, 110, 100, 105, 116, 105, 105, 115, 32, 112, 114, 97, 101, 115, 101, 101, 87, 17, 111, 56, 116, 117, 109, 32, 100, 101, 108, 101, 110, 105, 116, 105, 32, 97, 116, 65, 89, 28, 99, 111, 114, 114, 117, 112, 116, 105, 1, 150, 0, 115, 13, 174, 5, 109, 8, 113, 117, 97, 65, 5, 52, 108, 101, 115, 116, 105, 97, 115, 32, 101, 120, 99, 101, 112, 116, 0, 0, 0, 1, 0}, +} + +func TestSnappyEncode(t *testing.T) { + for src, exp := range snappyTestCases { + dst := Encode([]byte(src)) + if !bytes.Equal(dst, exp) { + t.Errorf("Expected %s to generate %v, but was %v", src, exp, dst) + } + } +} + +func TestSnappyDecode(t *testing.T) { + for exp, src := range snappyTestCases { + dst, err := Decode(src) + if err != nil { + t.Error("Encoding error: ", err) + } else if !bytes.Equal(dst, []byte(exp)) { + t.Errorf("Expected %s to be generated from %v, but was %s", exp, src, string(dst)) + } + } +} + +func TestSnappyDecodeStreams(t *testing.T) { + for exp, src := range snappyStreamTestCases { + dst, err := Decode(src) + if err != nil { + t.Error("Encoding error: ", err) + } else if !bytes.Equal(dst, []byte(exp)) { + t.Errorf("Expected %s to be generated from [%d]byte, but was %s", exp, len(src), string(dst)) + } + } +} diff --git a/vendor/src/github.com/eapache/queue/LICENSE b/vendor/src/github.com/eapache/queue/LICENSE new file mode 100644 index 00000000..d5f36dbc --- /dev/null +++ b/vendor/src/github.com/eapache/queue/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Evan Huus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/src/github.com/eapache/queue/README.md b/vendor/src/github.com/eapache/queue/README.md new file mode 100644 index 00000000..8e782335 --- /dev/null +++ b/vendor/src/github.com/eapache/queue/README.md @@ -0,0 +1,16 @@ +Queue +===== + +[![Build Status](https://travis-ci.org/eapache/queue.svg)](https://travis-ci.org/eapache/queue) +[![GoDoc](https://godoc.org/github.com/eapache/queue?status.png)](https://godoc.org/github.com/eapache/queue) +[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](https://eapache.github.io/conduct.html) + +A fast Golang queue using a ring-buffer, based on the version suggested by Dariusz Górecki. +Using this instead of other, simpler, queue implementations (slice+append or linked list) provides +substantial memory and time benefits, and fewer GC pauses. + +The queue implemented here is as fast as it is in part because it is *not* thread-safe. + +Follows semantic versioning using https://gopkg.in/ - import from +[`gopkg.in/eapache/queue.v1`](https://gopkg.in/eapache/queue.v1) +for guaranteed API stability. diff --git a/vendor/src/github.com/eapache/queue/queue.go b/vendor/src/github.com/eapache/queue/queue.go new file mode 100644 index 00000000..71d1acdf --- /dev/null +++ b/vendor/src/github.com/eapache/queue/queue.go @@ -0,0 +1,102 @@ +/* +Package queue provides a fast, ring-buffer queue based on the version suggested by Dariusz Górecki. +Using this instead of other, simpler, queue implementations (slice+append or linked list) provides +substantial memory and time benefits, and fewer GC pauses. + +The queue implemented here is as fast as it is for an additional reason: it is *not* thread-safe. +*/ +package queue + +// minQueueLen is smallest capacity that queue may have. +// Must be power of 2 for bitwise modulus: x % n == x & (n - 1). +const minQueueLen = 16 + +// Queue represents a single instance of the queue data structure. +type Queue struct { + buf []interface{} + head, tail, count int +} + +// New constructs and returns a new Queue. +func New() *Queue { + return &Queue{ + buf: make([]interface{}, minQueueLen), + } +} + +// Length returns the number of elements currently stored in the queue. +func (q *Queue) Length() int { + return q.count +} + +// resizes the queue to fit exactly twice its current contents +// this can result in shrinking if the queue is less than half-full +func (q *Queue) resize() { + newBuf := make([]interface{}, q.count<<1) + + if q.tail > q.head { + copy(newBuf, q.buf[q.head:q.tail]) + } else { + n := copy(newBuf, q.buf[q.head:]) + copy(newBuf[n:], q.buf[:q.tail]) + } + + q.head = 0 + q.tail = q.count + q.buf = newBuf +} + +// Add puts an element on the end of the queue. +func (q *Queue) Add(elem interface{}) { + if q.count == len(q.buf) { + q.resize() + } + + q.buf[q.tail] = elem + // bitwise modulus + q.tail = (q.tail + 1) & (len(q.buf) - 1) + q.count++ +} + +// Peek returns the element at the head of the queue. This call panics +// if the queue is empty. +func (q *Queue) Peek() interface{} { + if q.count <= 0 { + panic("queue: Peek() called on empty queue") + } + return q.buf[q.head] +} + +// Get returns the element at index i in the queue. If the index is +// invalid, the call will panic. This method accepts both positive and +// negative index values. Index 0 refers to the first element, and +// index -1 refers to the last. +func (q *Queue) Get(i int) interface{} { + // If indexing backwards, convert to positive index. + if i < 0 { + i += q.count + } + if i < 0 || i >= q.count { + panic("queue: Get() called with index out of range") + } + // bitwise modulus + return q.buf[(q.head+i)&(len(q.buf)-1)] +} + +// Remove removes and returns the element from the front of the queue. If the +// queue is empty, the call will panic. +func (q *Queue) Remove() interface{} { + if q.count <= 0 { + panic("queue: Remove() called on empty queue") + } + ret := q.buf[q.head] + q.buf[q.head] = nil + // bitwise modulus + q.head = (q.head + 1) & (len(q.buf) - 1) + q.count-- + // Resize down if buffer 1/4 full. + if len(q.buf) > minQueueLen && (q.count<<2) == len(q.buf) { + q.resize() + } + return ret +} diff --git a/vendor/src/github.com/eapache/queue/queue_test.go b/vendor/src/github.com/eapache/queue/queue_test.go new file mode 100644 index 00000000..a8758488 --- /dev/null +++ b/vendor/src/github.com/eapache/queue/queue_test.go @@ -0,0 +1,178 @@ +package queue + +import "testing" + +func TestQueueSimple(t *testing.T) { + q := New() + + for i := 0; i < minQueueLen; i++ { + q.Add(i) + } + for i := 0; i < minQueueLen; i++ { + if q.Peek().(int) != i { + t.Error("peek", i, "had value", q.Peek()) + } + x := q.Remove() + if x != i { + t.Error("remove", i, "had value", x) + } + } +} + +func TestQueueWrapping(t *testing.T) { + q := New() + + for i := 0; i < minQueueLen; i++ { + q.Add(i) + } + for i := 0; i < 3; i++ { + q.Remove() + q.Add(minQueueLen + i) + } + + for i := 0; i < minQueueLen; i++ { + if q.Peek().(int) != i+3 { + t.Error("peek", i, "had value", q.Peek()) + } + q.Remove() + } +} + +func TestQueueLength(t *testing.T) { + q := New() + + if q.Length() != 0 { + t.Error("empty queue length not 0") + } + + for i := 0; i < 1000; i++ { + q.Add(i) + if q.Length() != i+1 { + t.Error("adding: queue with", i, "elements has length", q.Length()) + } + } + for i := 0; i < 1000; i++ { + q.Remove() + if q.Length() != 1000-i-1 { + t.Error("removing: queue with", 1000-i-i, "elements has length", q.Length()) + } + } +} + +func TestQueueGet(t *testing.T) { + q := New() + + for i := 0; i < 1000; i++ { + q.Add(i) + for j := 0; j < q.Length(); j++ { + if q.Get(j).(int) != j { + t.Errorf("index %d doesn't contain %d", j, j) + } + } + } +} + +func TestQueueGetNegative(t *testing.T) { + q := New() + + for i := 0; i < 1000; i++ { + q.Add(i) + for j := 1; j <= q.Length(); j++ { + if q.Get(-j).(int) != q.Length()-j { + t.Errorf("index %d doesn't contain %d", -j, q.Length()-j) + } + } + } +} + +func TestQueueGetOutOfRangePanics(t *testing.T) { + q := New() + + q.Add(1) + q.Add(2) + q.Add(3) + + assertPanics(t, "should panic when negative index", func() { + q.Get(-4) + }) + + assertPanics(t, "should panic when index greater than length", func() { + q.Get(4) + }) +} + +func TestQueuePeekOutOfRangePanics(t *testing.T) { + q := New() + + assertPanics(t, "should panic when peeking empty queue", func() { + q.Peek() + }) + + q.Add(1) + q.Remove() + + assertPanics(t, "should panic when peeking emptied queue", func() { + q.Peek() + }) +} + +func TestQueueRemoveOutOfRangePanics(t *testing.T) { + q := New() + + assertPanics(t, "should panic when removing empty queue", func() { + q.Remove() + }) + + q.Add(1) + q.Remove() + + assertPanics(t, "should panic when removing emptied queue", func() { + q.Remove() + }) +} + +func assertPanics(t *testing.T, name string, f func()) { + defer func() { + if r := recover(); r == nil { + t.Errorf("%s: didn't panic as expected", name) + } + }() + + f() +} + +// General warning: Go's benchmark utility (go test -bench .) increases the number of +// iterations until the benchmarks take a reasonable amount of time to run; memory usage +// is *NOT* considered. On my machine, these benchmarks hit around ~1GB before they've had +// enough, but if you have less than that available and start swapping, then all bets are off. + +func BenchmarkQueueSerial(b *testing.B) { + q := New() + for i := 0; i < b.N; i++ { + q.Add(nil) + } + for i := 0; i < b.N; i++ { + q.Peek() + q.Remove() + } +} + +func BenchmarkQueueGet(b *testing.B) { + q := New() + for i := 0; i < b.N; i++ { + q.Add(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + q.Get(i) + } +} + +func BenchmarkQueueTickTock(b *testing.B) { + q := New() + for i := 0; i < b.N; i++ { + q.Add(nil) + q.Peek() + q.Remove() + } +} diff --git a/vendor/src/github.com/golang/snappy/AUTHORS b/vendor/src/github.com/golang/snappy/AUTHORS new file mode 100644 index 00000000..bcfa1952 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/AUTHORS @@ -0,0 +1,15 @@ +# This is the official list of Snappy-Go authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. + +# Names should be added to this file as +# Name or Organization +# The email address is not required for organizations. + +# Please keep the list sorted. + +Damian Gryski +Google Inc. +Jan Mercl <0xjnml@gmail.com> +Rodolfo Carvalho +Sebastien Binet diff --git a/vendor/src/github.com/golang/snappy/CONTRIBUTORS b/vendor/src/github.com/golang/snappy/CONTRIBUTORS new file mode 100644 index 00000000..931ae316 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/CONTRIBUTORS @@ -0,0 +1,37 @@ +# This is the official list of people who can contribute +# (and typically have contributed) code to the Snappy-Go repository. +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. +# +# The submission process automatically checks to make sure +# that people submitting code are listed in this file (by email address). +# +# Names should be added to this file only after verifying that +# the individual or the individual's organization has agreed to +# the appropriate Contributor License Agreement, found here: +# +# http://code.google.com/legal/individual-cla-v1.0.html +# http://code.google.com/legal/corporate-cla-v1.0.html +# +# The agreement for individuals can be filled out on the web. +# +# When adding J Random Contributor's name to this file, +# either J's name or J's organization's name should be +# added to the AUTHORS file, depending on whether the +# individual or corporate CLA was used. + +# Names should be added to this file like so: +# Name + +# Please keep the list sorted. + +Damian Gryski +Jan Mercl <0xjnml@gmail.com> +Kai Backman +Marc-Antoine Ruel +Nigel Tao +Rob Pike +Rodolfo Carvalho +Russ Cox +Sebastien Binet diff --git a/vendor/src/github.com/golang/snappy/LICENSE b/vendor/src/github.com/golang/snappy/LICENSE new file mode 100644 index 00000000..6050c10f --- /dev/null +++ b/vendor/src/github.com/golang/snappy/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/src/github.com/golang/snappy/README b/vendor/src/github.com/golang/snappy/README new file mode 100644 index 00000000..cea12879 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/README @@ -0,0 +1,107 @@ +The Snappy compression format in the Go programming language. + +To download and install from source: +$ go get github.com/golang/snappy + +Unless otherwise noted, the Snappy-Go source files are distributed +under the BSD-style license found in the LICENSE file. + + + +Benchmarks. + +The golang/snappy benchmarks include compressing (Z) and decompressing (U) ten +or so files, the same set used by the C++ Snappy code (github.com/google/snappy +and note the "google", not "golang"). On an "Intel(R) Core(TM) i7-3770 CPU @ +3.40GHz", Go's GOARCH=amd64 numbers as of 2016-05-29: + +"go test -test.bench=." + +_UFlat0-8 2.19GB/s ± 0% html +_UFlat1-8 1.41GB/s ± 0% urls +_UFlat2-8 23.5GB/s ± 2% jpg +_UFlat3-8 1.91GB/s ± 0% jpg_200 +_UFlat4-8 14.0GB/s ± 1% pdf +_UFlat5-8 1.97GB/s ± 0% html4 +_UFlat6-8 814MB/s ± 0% txt1 +_UFlat7-8 785MB/s ± 0% txt2 +_UFlat8-8 857MB/s ± 0% txt3 +_UFlat9-8 719MB/s ± 1% txt4 +_UFlat10-8 2.84GB/s ± 0% pb +_UFlat11-8 1.05GB/s ± 0% gaviota + +_ZFlat0-8 1.04GB/s ± 0% html +_ZFlat1-8 534MB/s ± 0% urls +_ZFlat2-8 15.7GB/s ± 1% jpg +_ZFlat3-8 740MB/s ± 3% jpg_200 +_ZFlat4-8 9.20GB/s ± 1% pdf +_ZFlat5-8 991MB/s ± 0% html4 +_ZFlat6-8 379MB/s ± 0% txt1 +_ZFlat7-8 352MB/s ± 0% txt2 +_ZFlat8-8 396MB/s ± 1% txt3 +_ZFlat9-8 327MB/s ± 1% txt4 +_ZFlat10-8 1.33GB/s ± 1% pb +_ZFlat11-8 605MB/s ± 1% gaviota + + + +"go test -test.bench=. -tags=noasm" + +_UFlat0-8 621MB/s ± 2% html +_UFlat1-8 494MB/s ± 1% urls +_UFlat2-8 23.2GB/s ± 1% jpg +_UFlat3-8 1.12GB/s ± 1% jpg_200 +_UFlat4-8 4.35GB/s ± 1% pdf +_UFlat5-8 609MB/s ± 0% html4 +_UFlat6-8 296MB/s ± 0% txt1 +_UFlat7-8 288MB/s ± 0% txt2 +_UFlat8-8 309MB/s ± 1% txt3 +_UFlat9-8 280MB/s ± 1% txt4 +_UFlat10-8 753MB/s ± 0% pb +_UFlat11-8 400MB/s ± 0% gaviota + +_ZFlat0-8 409MB/s ± 1% html +_ZFlat1-8 250MB/s ± 1% urls +_ZFlat2-8 12.3GB/s ± 1% jpg +_ZFlat3-8 132MB/s ± 0% jpg_200 +_ZFlat4-8 2.92GB/s ± 0% pdf +_ZFlat5-8 405MB/s ± 1% html4 +_ZFlat6-8 179MB/s ± 1% txt1 +_ZFlat7-8 170MB/s ± 1% txt2 +_ZFlat8-8 189MB/s ± 1% txt3 +_ZFlat9-8 164MB/s ± 1% txt4 +_ZFlat10-8 479MB/s ± 1% pb +_ZFlat11-8 270MB/s ± 1% gaviota + + + +For comparison (Go's encoded output is byte-for-byte identical to C++'s), here +are the numbers from C++ Snappy's + +make CXXFLAGS="-O2 -DNDEBUG -g" clean snappy_unittest.log && cat snappy_unittest.log + +BM_UFlat/0 2.4GB/s html +BM_UFlat/1 1.4GB/s urls +BM_UFlat/2 21.8GB/s jpg +BM_UFlat/3 1.5GB/s jpg_200 +BM_UFlat/4 13.3GB/s pdf +BM_UFlat/5 2.1GB/s html4 +BM_UFlat/6 1.0GB/s txt1 +BM_UFlat/7 959.4MB/s txt2 +BM_UFlat/8 1.0GB/s txt3 +BM_UFlat/9 864.5MB/s txt4 +BM_UFlat/10 2.9GB/s pb +BM_UFlat/11 1.2GB/s gaviota + +BM_ZFlat/0 944.3MB/s html (22.31 %) +BM_ZFlat/1 501.6MB/s urls (47.78 %) +BM_ZFlat/2 14.3GB/s jpg (99.95 %) +BM_ZFlat/3 538.3MB/s jpg_200 (73.00 %) +BM_ZFlat/4 8.3GB/s pdf (83.30 %) +BM_ZFlat/5 903.5MB/s html4 (22.52 %) +BM_ZFlat/6 336.0MB/s txt1 (57.88 %) +BM_ZFlat/7 312.3MB/s txt2 (61.91 %) +BM_ZFlat/8 353.1MB/s txt3 (54.99 %) +BM_ZFlat/9 289.9MB/s txt4 (66.26 %) +BM_ZFlat/10 1.2GB/s pb (19.68 %) +BM_ZFlat/11 527.4MB/s gaviota (37.72 %) diff --git a/vendor/src/github.com/golang/snappy/cmd/snappytool/main.cpp b/vendor/src/github.com/golang/snappy/cmd/snappytool/main.cpp new file mode 100644 index 00000000..fc31f517 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/cmd/snappytool/main.cpp @@ -0,0 +1,77 @@ +/* +To build the snappytool binary: +g++ main.cpp /usr/lib/libsnappy.a -o snappytool +or, if you have built the C++ snappy library from source: +g++ main.cpp /path/to/your/snappy/.libs/libsnappy.a -o snappytool +after running "make" from your snappy checkout directory. +*/ + +#include +#include +#include +#include + +#include "snappy.h" + +#define N 1000000 + +char dst[N]; +char src[N]; + +int main(int argc, char** argv) { + // Parse args. + if (argc != 2) { + fprintf(stderr, "exactly one of -d or -e must be given\n"); + return 1; + } + bool decode = strcmp(argv[1], "-d") == 0; + bool encode = strcmp(argv[1], "-e") == 0; + if (decode == encode) { + fprintf(stderr, "exactly one of -d or -e must be given\n"); + return 1; + } + + // Read all of stdin into src[:s]. + size_t s = 0; + while (1) { + if (s == N) { + fprintf(stderr, "input too large\n"); + return 1; + } + ssize_t n = read(0, src+s, N-s); + if (n == 0) { + break; + } + if (n < 0) { + fprintf(stderr, "read error: %s\n", strerror(errno)); + // TODO: handle EAGAIN, EINTR? + return 1; + } + s += n; + } + + // Encode or decode src[:s] to dst[:d], and write to stdout. + size_t d = 0; + if (encode) { + if (N < snappy::MaxCompressedLength(s)) { + fprintf(stderr, "input too large after encoding\n"); + return 1; + } + snappy::RawCompress(src, s, dst, &d); + } else { + if (!snappy::GetUncompressedLength(src, s, &d)) { + fprintf(stderr, "could not get uncompressed length\n"); + return 1; + } + if (N < d) { + fprintf(stderr, "input too large after decoding\n"); + return 1; + } + if (!snappy::RawUncompress(src, s, dst)) { + fprintf(stderr, "input was not valid Snappy-compressed data\n"); + return 1; + } + } + write(1, dst, d); + return 0; +} diff --git a/vendor/src/github.com/golang/snappy/decode.go b/vendor/src/github.com/golang/snappy/decode.go new file mode 100644 index 00000000..72efb035 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/decode.go @@ -0,0 +1,237 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package snappy + +import ( + "encoding/binary" + "errors" + "io" +) + +var ( + // ErrCorrupt reports that the input is invalid. + ErrCorrupt = errors.New("snappy: corrupt input") + // ErrTooLarge reports that the uncompressed length is too large. + ErrTooLarge = errors.New("snappy: decoded block is too large") + // ErrUnsupported reports that the input isn't supported. + ErrUnsupported = errors.New("snappy: unsupported input") + + errUnsupportedLiteralLength = errors.New("snappy: unsupported literal length") +) + +// DecodedLen returns the length of the decoded block. +func DecodedLen(src []byte) (int, error) { + v, _, err := decodedLen(src) + return v, err +} + +// decodedLen returns the length of the decoded block and the number of bytes +// that the length header occupied. +func decodedLen(src []byte) (blockLen, headerLen int, err error) { + v, n := binary.Uvarint(src) + if n <= 0 || v > 0xffffffff { + return 0, 0, ErrCorrupt + } + + const wordSize = 32 << (^uint(0) >> 32 & 1) + if wordSize == 32 && v > 0x7fffffff { + return 0, 0, ErrTooLarge + } + return int(v), n, nil +} + +const ( + decodeErrCodeCorrupt = 1 + decodeErrCodeUnsupportedLiteralLength = 2 +) + +// Decode returns the decoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire decoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +func Decode(dst, src []byte) ([]byte, error) { + dLen, s, err := decodedLen(src) + if err != nil { + return nil, err + } + if dLen <= len(dst) { + dst = dst[:dLen] + } else { + dst = make([]byte, dLen) + } + switch decode(dst, src[s:]) { + case 0: + return dst, nil + case decodeErrCodeUnsupportedLiteralLength: + return nil, errUnsupportedLiteralLength + } + return nil, ErrCorrupt +} + +// NewReader returns a new Reader that decompresses from r, using the framing +// format described at +// https://github.com/google/snappy/blob/master/framing_format.txt +func NewReader(r io.Reader) *Reader { + return &Reader{ + r: r, + decoded: make([]byte, maxBlockSize), + buf: make([]byte, maxEncodedLenOfMaxBlockSize+checksumSize), + } +} + +// Reader is an io.Reader that can read Snappy-compressed bytes. +type Reader struct { + r io.Reader + err error + decoded []byte + buf []byte + // decoded[i:j] contains decoded bytes that have not yet been passed on. + i, j int + readHeader bool +} + +// Reset discards any buffered data, resets all state, and switches the Snappy +// reader to read from r. This permits reusing a Reader rather than allocating +// a new one. +func (r *Reader) Reset(reader io.Reader) { + r.r = reader + r.err = nil + r.i = 0 + r.j = 0 + r.readHeader = false +} + +func (r *Reader) readFull(p []byte, allowEOF bool) (ok bool) { + if _, r.err = io.ReadFull(r.r, p); r.err != nil { + if r.err == io.ErrUnexpectedEOF || (r.err == io.EOF && !allowEOF) { + r.err = ErrCorrupt + } + return false + } + return true +} + +// Read satisfies the io.Reader interface. +func (r *Reader) Read(p []byte) (int, error) { + if r.err != nil { + return 0, r.err + } + for { + if r.i < r.j { + n := copy(p, r.decoded[r.i:r.j]) + r.i += n + return n, nil + } + if !r.readFull(r.buf[:4], true) { + return 0, r.err + } + chunkType := r.buf[0] + if !r.readHeader { + if chunkType != chunkTypeStreamIdentifier { + r.err = ErrCorrupt + return 0, r.err + } + r.readHeader = true + } + chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16 + if chunkLen > len(r.buf) { + r.err = ErrUnsupported + return 0, r.err + } + + // The chunk types are specified at + // https://github.com/google/snappy/blob/master/framing_format.txt + switch chunkType { + case chunkTypeCompressedData: + // Section 4.2. Compressed data (chunk type 0x00). + if chunkLen < checksumSize { + r.err = ErrCorrupt + return 0, r.err + } + buf := r.buf[:chunkLen] + if !r.readFull(buf, false) { + return 0, r.err + } + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + buf = buf[checksumSize:] + + n, err := DecodedLen(buf) + if err != nil { + r.err = err + return 0, r.err + } + if n > len(r.decoded) { + r.err = ErrCorrupt + return 0, r.err + } + if _, err := Decode(r.decoded, buf); err != nil { + r.err = err + return 0, r.err + } + if crc(r.decoded[:n]) != checksum { + r.err = ErrCorrupt + return 0, r.err + } + r.i, r.j = 0, n + continue + + case chunkTypeUncompressedData: + // Section 4.3. Uncompressed data (chunk type 0x01). + if chunkLen < checksumSize { + r.err = ErrCorrupt + return 0, r.err + } + buf := r.buf[:checksumSize] + if !r.readFull(buf, false) { + return 0, r.err + } + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + // Read directly into r.decoded instead of via r.buf. + n := chunkLen - checksumSize + if n > len(r.decoded) { + r.err = ErrCorrupt + return 0, r.err + } + if !r.readFull(r.decoded[:n], false) { + return 0, r.err + } + if crc(r.decoded[:n]) != checksum { + r.err = ErrCorrupt + return 0, r.err + } + r.i, r.j = 0, n + continue + + case chunkTypeStreamIdentifier: + // Section 4.1. Stream identifier (chunk type 0xff). + if chunkLen != len(magicBody) { + r.err = ErrCorrupt + return 0, r.err + } + if !r.readFull(r.buf[:len(magicBody)], false) { + return 0, r.err + } + for i := 0; i < len(magicBody); i++ { + if r.buf[i] != magicBody[i] { + r.err = ErrCorrupt + return 0, r.err + } + } + continue + } + + if chunkType <= 0x7f { + // Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f). + r.err = ErrUnsupported + return 0, r.err + } + // Section 4.4 Padding (chunk type 0xfe). + // Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). + if !r.readFull(r.buf[:chunkLen], false) { + return 0, r.err + } + } +} diff --git a/vendor/src/github.com/golang/snappy/decode_amd64.go b/vendor/src/github.com/golang/snappy/decode_amd64.go new file mode 100644 index 00000000..fcd192b8 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/decode_amd64.go @@ -0,0 +1,14 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +package snappy + +// decode has the same semantics as in decode_other.go. +// +//go:noescape +func decode(dst, src []byte) int diff --git a/vendor/src/github.com/golang/snappy/decode_amd64.s b/vendor/src/github.com/golang/snappy/decode_amd64.s new file mode 100644 index 00000000..e6179f65 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/decode_amd64.s @@ -0,0 +1,490 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" + +// The asm code generally follows the pure Go code in decode_other.go, except +// where marked with a "!!!". + +// func decode(dst, src []byte) int +// +// All local variables fit into registers. The non-zero stack size is only to +// spill registers and push args when issuing a CALL. The register allocation: +// - AX scratch +// - BX scratch +// - CX length or x +// - DX offset +// - SI &src[s] +// - DI &dst[d] +// + R8 dst_base +// + R9 dst_len +// + R10 dst_base + dst_len +// + R11 src_base +// + R12 src_len +// + R13 src_base + src_len +// - R14 used by doCopy +// - R15 used by doCopy +// +// The registers R8-R13 (marked with a "+") are set at the start of the +// function, and after a CALL returns, and are not otherwise modified. +// +// The d variable is implicitly DI - R8, and len(dst)-d is R10 - DI. +// The s variable is implicitly SI - R11, and len(src)-s is R13 - SI. +TEXT ·decode(SB), NOSPLIT, $48-56 + // Initialize SI, DI and R8-R13. + MOVQ dst_base+0(FP), R8 + MOVQ dst_len+8(FP), R9 + MOVQ R8, DI + MOVQ R8, R10 + ADDQ R9, R10 + MOVQ src_base+24(FP), R11 + MOVQ src_len+32(FP), R12 + MOVQ R11, SI + MOVQ R11, R13 + ADDQ R12, R13 + +loop: + // for s < len(src) + CMPQ SI, R13 + JEQ end + + // CX = uint32(src[s]) + // + // switch src[s] & 0x03 + MOVBLZX (SI), CX + MOVL CX, BX + ANDL $3, BX + CMPL BX, $1 + JAE tagCopy + + // ---------------------------------------- + // The code below handles literal tags. + + // case tagLiteral: + // x := uint32(src[s] >> 2) + // switch + SHRL $2, CX + CMPL CX, $60 + JAE tagLit60Plus + + // case x < 60: + // s++ + INCQ SI + +doLit: + // This is the end of the inner "switch", when we have a literal tag. + // + // We assume that CX == x and x fits in a uint32, where x is the variable + // used in the pure Go decode_other.go code. + + // length = int(x) + 1 + // + // Unlike the pure Go code, we don't need to check if length <= 0 because + // CX can hold 64 bits, so the increment cannot overflow. + INCQ CX + + // Prepare to check if copying length bytes will run past the end of dst or + // src. + // + // AX = len(dst) - d + // BX = len(src) - s + MOVQ R10, AX + SUBQ DI, AX + MOVQ R13, BX + SUBQ SI, BX + + // !!! Try a faster technique for short (16 or fewer bytes) copies. + // + // if length > 16 || len(dst)-d < 16 || len(src)-s < 16 { + // goto callMemmove // Fall back on calling runtime·memmove. + // } + // + // The C++ snappy code calls this TryFastAppend. It also checks len(src)-s + // against 21 instead of 16, because it cannot assume that all of its input + // is contiguous in memory and so it needs to leave enough source bytes to + // read the next tag without refilling buffers, but Go's Decode assumes + // contiguousness (the src argument is a []byte). + CMPQ CX, $16 + JGT callMemmove + CMPQ AX, $16 + JLT callMemmove + CMPQ BX, $16 + JLT callMemmove + + // !!! Implement the copy from src to dst as a 16-byte load and store. + // (Decode's documentation says that dst and src must not overlap.) + // + // This always copies 16 bytes, instead of only length bytes, but that's + // OK. If the input is a valid Snappy encoding then subsequent iterations + // will fix up the overrun. Otherwise, Decode returns a nil []byte (and a + // non-nil error), so the overrun will be ignored. + // + // Note that on amd64, it is legal and cheap to issue unaligned 8-byte or + // 16-byte loads and stores. This technique probably wouldn't be as + // effective on architectures that are fussier about alignment. + MOVOU 0(SI), X0 + MOVOU X0, 0(DI) + + // d += length + // s += length + ADDQ CX, DI + ADDQ CX, SI + JMP loop + +callMemmove: + // if length > len(dst)-d || length > len(src)-s { etc } + CMPQ CX, AX + JGT errCorrupt + CMPQ CX, BX + JGT errCorrupt + + // copy(dst[d:], src[s:s+length]) + // + // This means calling runtime·memmove(&dst[d], &src[s], length), so we push + // DI, SI and CX as arguments. Coincidentally, we also need to spill those + // three registers to the stack, to save local variables across the CALL. + MOVQ DI, 0(SP) + MOVQ SI, 8(SP) + MOVQ CX, 16(SP) + MOVQ DI, 24(SP) + MOVQ SI, 32(SP) + MOVQ CX, 40(SP) + CALL runtime·memmove(SB) + + // Restore local variables: unspill registers from the stack and + // re-calculate R8-R13. + MOVQ 24(SP), DI + MOVQ 32(SP), SI + MOVQ 40(SP), CX + MOVQ dst_base+0(FP), R8 + MOVQ dst_len+8(FP), R9 + MOVQ R8, R10 + ADDQ R9, R10 + MOVQ src_base+24(FP), R11 + MOVQ src_len+32(FP), R12 + MOVQ R11, R13 + ADDQ R12, R13 + + // d += length + // s += length + ADDQ CX, DI + ADDQ CX, SI + JMP loop + +tagLit60Plus: + // !!! This fragment does the + // + // s += x - 58; if uint(s) > uint(len(src)) { etc } + // + // checks. In the asm version, we code it once instead of once per switch case. + ADDQ CX, SI + SUBQ $58, SI + MOVQ SI, BX + SUBQ R11, BX + CMPQ BX, R12 + JA errCorrupt + + // case x == 60: + CMPL CX, $61 + JEQ tagLit61 + JA tagLit62Plus + + // x = uint32(src[s-1]) + MOVBLZX -1(SI), CX + JMP doLit + +tagLit61: + // case x == 61: + // x = uint32(src[s-2]) | uint32(src[s-1])<<8 + MOVWLZX -2(SI), CX + JMP doLit + +tagLit62Plus: + CMPL CX, $62 + JA tagLit63 + + // case x == 62: + // x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + MOVWLZX -3(SI), CX + MOVBLZX -1(SI), BX + SHLL $16, BX + ORL BX, CX + JMP doLit + +tagLit63: + // case x == 63: + // x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + MOVL -4(SI), CX + JMP doLit + +// The code above handles literal tags. +// ---------------------------------------- +// The code below handles copy tags. + +tagCopy4: + // case tagCopy4: + // s += 5 + ADDQ $5, SI + + // if uint(s) > uint(len(src)) { etc } + MOVQ SI, BX + SUBQ R11, BX + CMPQ BX, R12 + JA errCorrupt + + // length = 1 + int(src[s-5])>>2 + SHRQ $2, CX + INCQ CX + + // offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + MOVLQZX -4(SI), DX + JMP doCopy + +tagCopy2: + // case tagCopy2: + // s += 3 + ADDQ $3, SI + + // if uint(s) > uint(len(src)) { etc } + MOVQ SI, BX + SUBQ R11, BX + CMPQ BX, R12 + JA errCorrupt + + // length = 1 + int(src[s-3])>>2 + SHRQ $2, CX + INCQ CX + + // offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) + MOVWQZX -2(SI), DX + JMP doCopy + +tagCopy: + // We have a copy tag. We assume that: + // - BX == src[s] & 0x03 + // - CX == src[s] + CMPQ BX, $2 + JEQ tagCopy2 + JA tagCopy4 + + // case tagCopy1: + // s += 2 + ADDQ $2, SI + + // if uint(s) > uint(len(src)) { etc } + MOVQ SI, BX + SUBQ R11, BX + CMPQ BX, R12 + JA errCorrupt + + // offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + MOVQ CX, DX + ANDQ $0xe0, DX + SHLQ $3, DX + MOVBQZX -1(SI), BX + ORQ BX, DX + + // length = 4 + int(src[s-2])>>2&0x7 + SHRQ $2, CX + ANDQ $7, CX + ADDQ $4, CX + +doCopy: + // This is the end of the outer "switch", when we have a copy tag. + // + // We assume that: + // - CX == length && CX > 0 + // - DX == offset + + // if offset <= 0 { etc } + CMPQ DX, $0 + JLE errCorrupt + + // if d < offset { etc } + MOVQ DI, BX + SUBQ R8, BX + CMPQ BX, DX + JLT errCorrupt + + // if length > len(dst)-d { etc } + MOVQ R10, BX + SUBQ DI, BX + CMPQ CX, BX + JGT errCorrupt + + // forwardCopy(dst[d:d+length], dst[d-offset:]); d += length + // + // Set: + // - R14 = len(dst)-d + // - R15 = &dst[d-offset] + MOVQ R10, R14 + SUBQ DI, R14 + MOVQ DI, R15 + SUBQ DX, R15 + + // !!! Try a faster technique for short (16 or fewer bytes) forward copies. + // + // First, try using two 8-byte load/stores, similar to the doLit technique + // above. Even if dst[d:d+length] and dst[d-offset:] can overlap, this is + // still OK if offset >= 8. Note that this has to be two 8-byte load/stores + // and not one 16-byte load/store, and the first store has to be before the + // second load, due to the overlap if offset is in the range [8, 16). + // + // if length > 16 || offset < 8 || len(dst)-d < 16 { + // goto slowForwardCopy + // } + // copy 16 bytes + // d += length + CMPQ CX, $16 + JGT slowForwardCopy + CMPQ DX, $8 + JLT slowForwardCopy + CMPQ R14, $16 + JLT slowForwardCopy + MOVQ 0(R15), AX + MOVQ AX, 0(DI) + MOVQ 8(R15), BX + MOVQ BX, 8(DI) + ADDQ CX, DI + JMP loop + +slowForwardCopy: + // !!! If the forward copy is longer than 16 bytes, or if offset < 8, we + // can still try 8-byte load stores, provided we can overrun up to 10 extra + // bytes. As above, the overrun will be fixed up by subsequent iterations + // of the outermost loop. + // + // The C++ snappy code calls this technique IncrementalCopyFastPath. Its + // commentary says: + // + // ---- + // + // The main part of this loop is a simple copy of eight bytes at a time + // until we've copied (at least) the requested amount of bytes. However, + // if d and d-offset are less than eight bytes apart (indicating a + // repeating pattern of length < 8), we first need to expand the pattern in + // order to get the correct results. For instance, if the buffer looks like + // this, with the eight-byte and patterns marked as + // intervals: + // + // abxxxxxxxxxxxx + // [------] d-offset + // [------] d + // + // a single eight-byte copy from to will repeat the pattern + // once, after which we can move two bytes without moving : + // + // ababxxxxxxxxxx + // [------] d-offset + // [------] d + // + // and repeat the exercise until the two no longer overlap. + // + // This allows us to do very well in the special case of one single byte + // repeated many times, without taking a big hit for more general cases. + // + // The worst case of extra writing past the end of the match occurs when + // offset == 1 and length == 1; the last copy will read from byte positions + // [0..7] and write to [4..11], whereas it was only supposed to write to + // position 1. Thus, ten excess bytes. + // + // ---- + // + // That "10 byte overrun" worst case is confirmed by Go's + // TestSlowForwardCopyOverrun, which also tests the fixUpSlowForwardCopy + // and finishSlowForwardCopy algorithm. + // + // if length > len(dst)-d-10 { + // goto verySlowForwardCopy + // } + SUBQ $10, R14 + CMPQ CX, R14 + JGT verySlowForwardCopy + +makeOffsetAtLeast8: + // !!! As above, expand the pattern so that offset >= 8 and we can use + // 8-byte load/stores. + // + // for offset < 8 { + // copy 8 bytes from dst[d-offset:] to dst[d:] + // length -= offset + // d += offset + // offset += offset + // // The two previous lines together means that d-offset, and therefore + // // R15, is unchanged. + // } + CMPQ DX, $8 + JGE fixUpSlowForwardCopy + MOVQ (R15), BX + MOVQ BX, (DI) + SUBQ DX, CX + ADDQ DX, DI + ADDQ DX, DX + JMP makeOffsetAtLeast8 + +fixUpSlowForwardCopy: + // !!! Add length (which might be negative now) to d (implied by DI being + // &dst[d]) so that d ends up at the right place when we jump back to the + // top of the loop. Before we do that, though, we save DI to AX so that, if + // length is positive, copying the remaining length bytes will write to the + // right place. + MOVQ DI, AX + ADDQ CX, DI + +finishSlowForwardCopy: + // !!! Repeat 8-byte load/stores until length <= 0. Ending with a negative + // length means that we overrun, but as above, that will be fixed up by + // subsequent iterations of the outermost loop. + CMPQ CX, $0 + JLE loop + MOVQ (R15), BX + MOVQ BX, (AX) + ADDQ $8, R15 + ADDQ $8, AX + SUBQ $8, CX + JMP finishSlowForwardCopy + +verySlowForwardCopy: + // verySlowForwardCopy is a simple implementation of forward copy. In C + // parlance, this is a do/while loop instead of a while loop, since we know + // that length > 0. In Go syntax: + // + // for { + // dst[d] = dst[d - offset] + // d++ + // length-- + // if length == 0 { + // break + // } + // } + MOVB (R15), BX + MOVB BX, (DI) + INCQ R15 + INCQ DI + DECQ CX + JNZ verySlowForwardCopy + JMP loop + +// The code above handles copy tags. +// ---------------------------------------- + +end: + // This is the end of the "for s < len(src)". + // + // if d != len(dst) { etc } + CMPQ DI, R10 + JNE errCorrupt + + // return 0 + MOVQ $0, ret+48(FP) + RET + +errCorrupt: + // return decodeErrCodeCorrupt + MOVQ $1, ret+48(FP) + RET diff --git a/vendor/src/github.com/golang/snappy/decode_other.go b/vendor/src/github.com/golang/snappy/decode_other.go new file mode 100644 index 00000000..8c9f2049 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/decode_other.go @@ -0,0 +1,101 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64 appengine !gc noasm + +package snappy + +// decode writes the decoding of src to dst. It assumes that the varint-encoded +// length of the decompressed bytes has already been read, and that len(dst) +// equals that length. +// +// It returns 0 on success or a decodeErrCodeXxx error code on failure. +func decode(dst, src []byte) int { + var d, s, offset, length int + for s < len(src) { + switch src[s] & 0x03 { + case tagLiteral: + x := uint32(src[s] >> 2) + switch { + case x < 60: + s++ + case x == 60: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-1]) + case x == 61: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-2]) | uint32(src[s-1])<<8 + case x == 62: + s += 4 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + case x == 63: + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + } + length = int(x) + 1 + if length <= 0 { + return decodeErrCodeUnsupportedLiteralLength + } + if length > len(dst)-d || length > len(src)-s { + return decodeErrCodeCorrupt + } + copy(dst[d:], src[s:s+length]) + d += length + s += length + continue + + case tagCopy1: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = 4 + int(src[s-2])>>2&0x7 + offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + + case tagCopy2: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = 1 + int(src[s-3])>>2 + offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) + + case tagCopy4: + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = 1 + int(src[s-5])>>2 + offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + } + + if offset <= 0 || d < offset || length > len(dst)-d { + return decodeErrCodeCorrupt + } + // Copy from an earlier sub-slice of dst to a later sub-slice. Unlike + // the built-in copy function, this byte-by-byte copy always runs + // forwards, even if the slices overlap. Conceptually, this is: + // + // d += forwardCopy(dst[d:d+length], dst[d-offset:]) + for end := d + length; d != end; d++ { + dst[d] = dst[d-offset] + } + } + if d != len(dst) { + return decodeErrCodeCorrupt + } + return 0 +} diff --git a/vendor/src/github.com/golang/snappy/encode.go b/vendor/src/github.com/golang/snappy/encode.go new file mode 100644 index 00000000..87496890 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/encode.go @@ -0,0 +1,285 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package snappy + +import ( + "encoding/binary" + "errors" + "io" +) + +// Encode returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +func Encode(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if len(dst) < n { + dst = make([]byte, n) + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(dst, uint64(len(src))) + + for len(src) > 0 { + p := src + src = nil + if len(p) > maxBlockSize { + p, src = p[:maxBlockSize], p[maxBlockSize:] + } + if len(p) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], p) + } else { + d += encodeBlock(dst[d:], p) + } + } + return dst[:d] +} + +// inputMargin is the minimum number of extra input bytes to keep, inside +// encodeBlock's inner loop. On some architectures, this margin lets us +// implement a fast path for emitLiteral, where the copy of short (<= 16 byte) +// literals can be implemented as a single load to and store from a 16-byte +// register. That literal's actual length can be as short as 1 byte, so this +// can copy up to 15 bytes too much, but that's OK as subsequent iterations of +// the encoding loop will fix up the copy overrun, and this inputMargin ensures +// that we don't overrun the dst and src buffers. +const inputMargin = 16 - 1 + +// minNonLiteralBlockSize is the minimum size of the input to encodeBlock that +// could be encoded with a copy tag. This is the minimum with respect to the +// algorithm used by encodeBlock, not a minimum enforced by the file format. +// +// The encoded output must start with at least a 1 byte literal, as there are +// no previous bytes to copy. A minimal (1 byte) copy after that, generated +// from an emitCopy call in encodeBlock's main loop, would require at least +// another inputMargin bytes, for the reason above: we want any emitLiteral +// calls inside encodeBlock's main loop to use the fast path if possible, which +// requires being able to overrun by inputMargin bytes. Thus, +// minNonLiteralBlockSize equals 1 + 1 + inputMargin. +// +// The C++ code doesn't use this exact threshold, but it could, as discussed at +// https://groups.google.com/d/topic/snappy-compression/oGbhsdIJSJ8/discussion +// The difference between Go (2+inputMargin) and C++ (inputMargin) is purely an +// optimization. It should not affect the encoded form. This is tested by +// TestSameEncodingAsCppShortCopies. +const minNonLiteralBlockSize = 1 + 1 + inputMargin + +// MaxEncodedLen returns the maximum length of a snappy block, given its +// uncompressed length. +// +// It will return a negative value if srcLen is too large to encode. +func MaxEncodedLen(srcLen int) int { + n := uint64(srcLen) + if n > 0xffffffff { + return -1 + } + // Compressed data can be defined as: + // compressed := item* literal* + // item := literal* copy + // + // The trailing literal sequence has a space blowup of at most 62/60 + // since a literal of length 60 needs one tag byte + one extra byte + // for length information. + // + // Item blowup is trickier to measure. Suppose the "copy" op copies + // 4 bytes of data. Because of a special check in the encoding code, + // we produce a 4-byte copy only if the offset is < 65536. Therefore + // the copy op takes 3 bytes to encode, and this type of item leads + // to at most the 62/60 blowup for representing literals. + // + // Suppose the "copy" op copies 5 bytes of data. If the offset is big + // enough, it will take 5 bytes to encode the copy op. Therefore the + // worst case here is a one-byte literal followed by a five-byte copy. + // That is, 6 bytes of input turn into 7 bytes of "compressed" data. + // + // This last factor dominates the blowup, so the final estimate is: + n = 32 + n + n/6 + if n > 0xffffffff { + return -1 + } + return int(n) +} + +var errClosed = errors.New("snappy: Writer is closed") + +// NewWriter returns a new Writer that compresses to w. +// +// The Writer returned does not buffer writes. There is no need to Flush or +// Close such a Writer. +// +// Deprecated: the Writer returned is not suitable for many small writes, only +// for few large writes. Use NewBufferedWriter instead, which is efficient +// regardless of the frequency and shape of the writes, and remember to Close +// that Writer when done. +func NewWriter(w io.Writer) *Writer { + return &Writer{ + w: w, + obuf: make([]byte, obufLen), + } +} + +// NewBufferedWriter returns a new Writer that compresses to w, using the +// framing format described at +// https://github.com/google/snappy/blob/master/framing_format.txt +// +// The Writer returned buffers writes. Users must call Close to guarantee all +// data has been forwarded to the underlying io.Writer. They may also call +// Flush zero or more times before calling Close. +func NewBufferedWriter(w io.Writer) *Writer { + return &Writer{ + w: w, + ibuf: make([]byte, 0, maxBlockSize), + obuf: make([]byte, obufLen), + } +} + +// Writer is an io.Writer than can write Snappy-compressed bytes. +type Writer struct { + w io.Writer + err error + + // ibuf is a buffer for the incoming (uncompressed) bytes. + // + // Its use is optional. For backwards compatibility, Writers created by the + // NewWriter function have ibuf == nil, do not buffer incoming bytes, and + // therefore do not need to be Flush'ed or Close'd. + ibuf []byte + + // obuf is a buffer for the outgoing (compressed) bytes. + obuf []byte + + // wroteStreamHeader is whether we have written the stream header. + wroteStreamHeader bool +} + +// Reset discards the writer's state and switches the Snappy writer to write to +// w. This permits reusing a Writer rather than allocating a new one. +func (w *Writer) Reset(writer io.Writer) { + w.w = writer + w.err = nil + if w.ibuf != nil { + w.ibuf = w.ibuf[:0] + } + w.wroteStreamHeader = false +} + +// Write satisfies the io.Writer interface. +func (w *Writer) Write(p []byte) (nRet int, errRet error) { + if w.ibuf == nil { + // Do not buffer incoming bytes. This does not perform or compress well + // if the caller of Writer.Write writes many small slices. This + // behavior is therefore deprecated, but still supported for backwards + // compatibility with code that doesn't explicitly Flush or Close. + return w.write(p) + } + + // The remainder of this method is based on bufio.Writer.Write from the + // standard library. + + for len(p) > (cap(w.ibuf)-len(w.ibuf)) && w.err == nil { + var n int + if len(w.ibuf) == 0 { + // Large write, empty buffer. + // Write directly from p to avoid copy. + n, _ = w.write(p) + } else { + n = copy(w.ibuf[len(w.ibuf):cap(w.ibuf)], p) + w.ibuf = w.ibuf[:len(w.ibuf)+n] + w.Flush() + } + nRet += n + p = p[n:] + } + if w.err != nil { + return nRet, w.err + } + n := copy(w.ibuf[len(w.ibuf):cap(w.ibuf)], p) + w.ibuf = w.ibuf[:len(w.ibuf)+n] + nRet += n + return nRet, nil +} + +func (w *Writer) write(p []byte) (nRet int, errRet error) { + if w.err != nil { + return 0, w.err + } + for len(p) > 0 { + obufStart := len(magicChunk) + if !w.wroteStreamHeader { + w.wroteStreamHeader = true + copy(w.obuf, magicChunk) + obufStart = 0 + } + + var uncompressed []byte + if len(p) > maxBlockSize { + uncompressed, p = p[:maxBlockSize], p[maxBlockSize:] + } else { + uncompressed, p = p, nil + } + checksum := crc(uncompressed) + + // Compress the buffer, discarding the result if the improvement + // isn't at least 12.5%. + compressed := Encode(w.obuf[obufHeaderLen:], uncompressed) + chunkType := uint8(chunkTypeCompressedData) + chunkLen := 4 + len(compressed) + obufEnd := obufHeaderLen + len(compressed) + if len(compressed) >= len(uncompressed)-len(uncompressed)/8 { + chunkType = chunkTypeUncompressedData + chunkLen = 4 + len(uncompressed) + obufEnd = obufHeaderLen + } + + // Fill in the per-chunk header that comes before the body. + w.obuf[len(magicChunk)+0] = chunkType + w.obuf[len(magicChunk)+1] = uint8(chunkLen >> 0) + w.obuf[len(magicChunk)+2] = uint8(chunkLen >> 8) + w.obuf[len(magicChunk)+3] = uint8(chunkLen >> 16) + w.obuf[len(magicChunk)+4] = uint8(checksum >> 0) + w.obuf[len(magicChunk)+5] = uint8(checksum >> 8) + w.obuf[len(magicChunk)+6] = uint8(checksum >> 16) + w.obuf[len(magicChunk)+7] = uint8(checksum >> 24) + + if _, err := w.w.Write(w.obuf[obufStart:obufEnd]); err != nil { + w.err = err + return nRet, err + } + if chunkType == chunkTypeUncompressedData { + if _, err := w.w.Write(uncompressed); err != nil { + w.err = err + return nRet, err + } + } + nRet += len(uncompressed) + } + return nRet, nil +} + +// Flush flushes the Writer to its underlying io.Writer. +func (w *Writer) Flush() error { + if w.err != nil { + return w.err + } + if len(w.ibuf) == 0 { + return nil + } + w.write(w.ibuf) + w.ibuf = w.ibuf[:0] + return w.err +} + +// Close calls Flush and then closes the Writer. +func (w *Writer) Close() error { + w.Flush() + ret := w.err + if w.err == nil { + w.err = errClosed + } + return ret +} diff --git a/vendor/src/github.com/golang/snappy/encode_amd64.go b/vendor/src/github.com/golang/snappy/encode_amd64.go new file mode 100644 index 00000000..150d91bc --- /dev/null +++ b/vendor/src/github.com/golang/snappy/encode_amd64.go @@ -0,0 +1,29 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +package snappy + +// emitLiteral has the same semantics as in encode_other.go. +// +//go:noescape +func emitLiteral(dst, lit []byte) int + +// emitCopy has the same semantics as in encode_other.go. +// +//go:noescape +func emitCopy(dst []byte, offset, length int) int + +// extendMatch has the same semantics as in encode_other.go. +// +//go:noescape +func extendMatch(src []byte, i, j int) int + +// encodeBlock has the same semantics as in encode_other.go. +// +//go:noescape +func encodeBlock(dst, src []byte) (d int) diff --git a/vendor/src/github.com/golang/snappy/encode_amd64.s b/vendor/src/github.com/golang/snappy/encode_amd64.s new file mode 100644 index 00000000..adfd979f --- /dev/null +++ b/vendor/src/github.com/golang/snappy/encode_amd64.s @@ -0,0 +1,730 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" + +// The XXX lines assemble on Go 1.4, 1.5 and 1.7, but not 1.6, due to a +// Go toolchain regression. See https://github.com/golang/go/issues/15426 and +// https://github.com/golang/snappy/issues/29 +// +// As a workaround, the package was built with a known good assembler, and +// those instructions were disassembled by "objdump -d" to yield the +// 4e 0f b7 7c 5c 78 movzwq 0x78(%rsp,%r11,2),%r15 +// style comments, in AT&T asm syntax. Note that rsp here is a physical +// register, not Go/asm's SP pseudo-register (see https://golang.org/doc/asm). +// The instructions were then encoded as "BYTE $0x.." sequences, which assemble +// fine on Go 1.6. + +// The asm code generally follows the pure Go code in encode_other.go, except +// where marked with a "!!!". + +// ---------------------------------------------------------------------------- + +// func emitLiteral(dst, lit []byte) int +// +// All local variables fit into registers. The register allocation: +// - AX len(lit) +// - BX n +// - DX return value +// - DI &dst[i] +// - R10 &lit[0] +// +// The 24 bytes of stack space is to call runtime·memmove. +// +// The unusual register allocation of local variables, such as R10 for the +// source pointer, matches the allocation used at the call site in encodeBlock, +// which makes it easier to manually inline this function. +TEXT ·emitLiteral(SB), NOSPLIT, $24-56 + MOVQ dst_base+0(FP), DI + MOVQ lit_base+24(FP), R10 + MOVQ lit_len+32(FP), AX + MOVQ AX, DX + MOVL AX, BX + SUBL $1, BX + + CMPL BX, $60 + JLT oneByte + CMPL BX, $256 + JLT twoBytes + +threeBytes: + MOVB $0xf4, 0(DI) + MOVW BX, 1(DI) + ADDQ $3, DI + ADDQ $3, DX + JMP memmove + +twoBytes: + MOVB $0xf0, 0(DI) + MOVB BX, 1(DI) + ADDQ $2, DI + ADDQ $2, DX + JMP memmove + +oneByte: + SHLB $2, BX + MOVB BX, 0(DI) + ADDQ $1, DI + ADDQ $1, DX + +memmove: + MOVQ DX, ret+48(FP) + + // copy(dst[i:], lit) + // + // This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push + // DI, R10 and AX as arguments. + MOVQ DI, 0(SP) + MOVQ R10, 8(SP) + MOVQ AX, 16(SP) + CALL runtime·memmove(SB) + RET + +// ---------------------------------------------------------------------------- + +// func emitCopy(dst []byte, offset, length int) int +// +// All local variables fit into registers. The register allocation: +// - AX length +// - SI &dst[0] +// - DI &dst[i] +// - R11 offset +// +// The unusual register allocation of local variables, such as R11 for the +// offset, matches the allocation used at the call site in encodeBlock, which +// makes it easier to manually inline this function. +TEXT ·emitCopy(SB), NOSPLIT, $0-48 + MOVQ dst_base+0(FP), DI + MOVQ DI, SI + MOVQ offset+24(FP), R11 + MOVQ length+32(FP), AX + +loop0: + // for length >= 68 { etc } + CMPL AX, $68 + JLT step1 + + // Emit a length 64 copy, encoded as 3 bytes. + MOVB $0xfe, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + SUBL $64, AX + JMP loop0 + +step1: + // if length > 64 { etc } + CMPL AX, $64 + JLE step2 + + // Emit a length 60 copy, encoded as 3 bytes. + MOVB $0xee, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + SUBL $60, AX + +step2: + // if length >= 12 || offset >= 2048 { goto step3 } + CMPL AX, $12 + JGE step3 + CMPL R11, $2048 + JGE step3 + + // Emit the remaining copy, encoded as 2 bytes. + MOVB R11, 1(DI) + SHRL $8, R11 + SHLB $5, R11 + SUBB $4, AX + SHLB $2, AX + ORB AX, R11 + ORB $1, R11 + MOVB R11, 0(DI) + ADDQ $2, DI + + // Return the number of bytes written. + SUBQ SI, DI + MOVQ DI, ret+40(FP) + RET + +step3: + // Emit the remaining copy, encoded as 3 bytes. + SUBL $1, AX + SHLB $2, AX + ORB $2, AX + MOVB AX, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + + // Return the number of bytes written. + SUBQ SI, DI + MOVQ DI, ret+40(FP) + RET + +// ---------------------------------------------------------------------------- + +// func extendMatch(src []byte, i, j int) int +// +// All local variables fit into registers. The register allocation: +// - DX &src[0] +// - SI &src[j] +// - R13 &src[len(src) - 8] +// - R14 &src[len(src)] +// - R15 &src[i] +// +// The unusual register allocation of local variables, such as R15 for a source +// pointer, matches the allocation used at the call site in encodeBlock, which +// makes it easier to manually inline this function. +TEXT ·extendMatch(SB), NOSPLIT, $0-48 + MOVQ src_base+0(FP), DX + MOVQ src_len+8(FP), R14 + MOVQ i+24(FP), R15 + MOVQ j+32(FP), SI + ADDQ DX, R14 + ADDQ DX, R15 + ADDQ DX, SI + MOVQ R14, R13 + SUBQ $8, R13 + +cmp8: + // As long as we are 8 or more bytes before the end of src, we can load and + // compare 8 bytes at a time. If those 8 bytes are equal, repeat. + CMPQ SI, R13 + JA cmp1 + MOVQ (R15), AX + MOVQ (SI), BX + CMPQ AX, BX + JNE bsf + ADDQ $8, R15 + ADDQ $8, SI + JMP cmp8 + +bsf: + // If those 8 bytes were not equal, XOR the two 8 byte values, and return + // the index of the first byte that differs. The BSF instruction finds the + // least significant 1 bit, the amd64 architecture is little-endian, and + // the shift by 3 converts a bit index to a byte index. + XORQ AX, BX + BSFQ BX, BX + SHRQ $3, BX + ADDQ BX, SI + + // Convert from &src[ret] to ret. + SUBQ DX, SI + MOVQ SI, ret+40(FP) + RET + +cmp1: + // In src's tail, compare 1 byte at a time. + CMPQ SI, R14 + JAE extendMatchEnd + MOVB (R15), AX + MOVB (SI), BX + CMPB AX, BX + JNE extendMatchEnd + ADDQ $1, R15 + ADDQ $1, SI + JMP cmp1 + +extendMatchEnd: + // Convert from &src[ret] to ret. + SUBQ DX, SI + MOVQ SI, ret+40(FP) + RET + +// ---------------------------------------------------------------------------- + +// func encodeBlock(dst, src []byte) (d int) +// +// All local variables fit into registers, other than "var table". The register +// allocation: +// - AX . . +// - BX . . +// - CX 56 shift (note that amd64 shifts by non-immediates must use CX). +// - DX 64 &src[0], tableSize +// - SI 72 &src[s] +// - DI 80 &dst[d] +// - R9 88 sLimit +// - R10 . &src[nextEmit] +// - R11 96 prevHash, currHash, nextHash, offset +// - R12 104 &src[base], skip +// - R13 . &src[nextS], &src[len(src) - 8] +// - R14 . len(src), bytesBetweenHashLookups, &src[len(src)], x +// - R15 112 candidate +// +// The second column (56, 64, etc) is the stack offset to spill the registers +// when calling other functions. We could pack this slightly tighter, but it's +// simpler to have a dedicated spill map independent of the function called. +// +// "var table [maxTableSize]uint16" takes up 32768 bytes of stack space. An +// extra 56 bytes, to call other functions, and an extra 64 bytes, to spill +// local variables (registers) during calls gives 32768 + 56 + 64 = 32888. +TEXT ·encodeBlock(SB), 0, $32888-56 + MOVQ dst_base+0(FP), DI + MOVQ src_base+24(FP), SI + MOVQ src_len+32(FP), R14 + + // shift, tableSize := uint32(32-8), 1<<8 + MOVQ $24, CX + MOVQ $256, DX + +calcShift: + // for ; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 { + // shift-- + // } + CMPQ DX, $16384 + JGE varTable + CMPQ DX, R14 + JGE varTable + SUBQ $1, CX + SHLQ $1, DX + JMP calcShift + +varTable: + // var table [maxTableSize]uint16 + // + // In the asm code, unlike the Go code, we can zero-initialize only the + // first tableSize elements. Each uint16 element is 2 bytes and each MOVOU + // writes 16 bytes, so we can do only tableSize/8 writes instead of the + // 2048 writes that would zero-initialize all of table's 32768 bytes. + SHRQ $3, DX + LEAQ table-32768(SP), BX + PXOR X0, X0 + +memclr: + MOVOU X0, 0(BX) + ADDQ $16, BX + SUBQ $1, DX + JNZ memclr + + // !!! DX = &src[0] + MOVQ SI, DX + + // sLimit := len(src) - inputMargin + MOVQ R14, R9 + SUBQ $15, R9 + + // !!! Pre-emptively spill CX, DX and R9 to the stack. Their values don't + // change for the rest of the function. + MOVQ CX, 56(SP) + MOVQ DX, 64(SP) + MOVQ R9, 88(SP) + + // nextEmit := 0 + MOVQ DX, R10 + + // s := 1 + ADDQ $1, SI + + // nextHash := hash(load32(src, s), shift) + MOVL 0(SI), R11 + IMULL $0x1e35a7bd, R11 + SHRL CX, R11 + +outer: + // for { etc } + + // skip := 32 + MOVQ $32, R12 + + // nextS := s + MOVQ SI, R13 + + // candidate := 0 + MOVQ $0, R15 + +inner0: + // for { etc } + + // s := nextS + MOVQ R13, SI + + // bytesBetweenHashLookups := skip >> 5 + MOVQ R12, R14 + SHRQ $5, R14 + + // nextS = s + bytesBetweenHashLookups + ADDQ R14, R13 + + // skip += bytesBetweenHashLookups + ADDQ R14, R12 + + // if nextS > sLimit { goto emitRemainder } + MOVQ R13, AX + SUBQ DX, AX + CMPQ AX, R9 + JA emitRemainder + + // candidate = int(table[nextHash]) + // XXX: MOVWQZX table-32768(SP)(R11*2), R15 + // XXX: 4e 0f b7 7c 5c 78 movzwq 0x78(%rsp,%r11,2),%r15 + BYTE $0x4e + BYTE $0x0f + BYTE $0xb7 + BYTE $0x7c + BYTE $0x5c + BYTE $0x78 + + // table[nextHash] = uint16(s) + MOVQ SI, AX + SUBQ DX, AX + + // XXX: MOVW AX, table-32768(SP)(R11*2) + // XXX: 66 42 89 44 5c 78 mov %ax,0x78(%rsp,%r11,2) + BYTE $0x66 + BYTE $0x42 + BYTE $0x89 + BYTE $0x44 + BYTE $0x5c + BYTE $0x78 + + // nextHash = hash(load32(src, nextS), shift) + MOVL 0(R13), R11 + IMULL $0x1e35a7bd, R11 + SHRL CX, R11 + + // if load32(src, s) != load32(src, candidate) { continue } break + MOVL 0(SI), AX + MOVL (DX)(R15*1), BX + CMPL AX, BX + JNE inner0 + +fourByteMatch: + // As per the encode_other.go code: + // + // A 4-byte match has been found. We'll later see etc. + + // !!! Jump to a fast path for short (<= 16 byte) literals. See the comment + // on inputMargin in encode.go. + MOVQ SI, AX + SUBQ R10, AX + CMPQ AX, $16 + JLE emitLiteralFastPath + + // ---------------------------------------- + // Begin inline of the emitLiteral call. + // + // d += emitLiteral(dst[d:], src[nextEmit:s]) + + MOVL AX, BX + SUBL $1, BX + + CMPL BX, $60 + JLT inlineEmitLiteralOneByte + CMPL BX, $256 + JLT inlineEmitLiteralTwoBytes + +inlineEmitLiteralThreeBytes: + MOVB $0xf4, 0(DI) + MOVW BX, 1(DI) + ADDQ $3, DI + JMP inlineEmitLiteralMemmove + +inlineEmitLiteralTwoBytes: + MOVB $0xf0, 0(DI) + MOVB BX, 1(DI) + ADDQ $2, DI + JMP inlineEmitLiteralMemmove + +inlineEmitLiteralOneByte: + SHLB $2, BX + MOVB BX, 0(DI) + ADDQ $1, DI + +inlineEmitLiteralMemmove: + // Spill local variables (registers) onto the stack; call; unspill. + // + // copy(dst[i:], lit) + // + // This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push + // DI, R10 and AX as arguments. + MOVQ DI, 0(SP) + MOVQ R10, 8(SP) + MOVQ AX, 16(SP) + ADDQ AX, DI // Finish the "d +=" part of "d += emitLiteral(etc)". + MOVQ SI, 72(SP) + MOVQ DI, 80(SP) + MOVQ R15, 112(SP) + CALL runtime·memmove(SB) + MOVQ 56(SP), CX + MOVQ 64(SP), DX + MOVQ 72(SP), SI + MOVQ 80(SP), DI + MOVQ 88(SP), R9 + MOVQ 112(SP), R15 + JMP inner1 + +inlineEmitLiteralEnd: + // End inline of the emitLiteral call. + // ---------------------------------------- + +emitLiteralFastPath: + // !!! Emit the 1-byte encoding "uint8(len(lit)-1)<<2". + MOVB AX, BX + SUBB $1, BX + SHLB $2, BX + MOVB BX, (DI) + ADDQ $1, DI + + // !!! Implement the copy from lit to dst as a 16-byte load and store. + // (Encode's documentation says that dst and src must not overlap.) + // + // This always copies 16 bytes, instead of only len(lit) bytes, but that's + // OK. Subsequent iterations will fix up the overrun. + // + // Note that on amd64, it is legal and cheap to issue unaligned 8-byte or + // 16-byte loads and stores. This technique probably wouldn't be as + // effective on architectures that are fussier about alignment. + MOVOU 0(R10), X0 + MOVOU X0, 0(DI) + ADDQ AX, DI + +inner1: + // for { etc } + + // base := s + MOVQ SI, R12 + + // !!! offset := base - candidate + MOVQ R12, R11 + SUBQ R15, R11 + SUBQ DX, R11 + + // ---------------------------------------- + // Begin inline of the extendMatch call. + // + // s = extendMatch(src, candidate+4, s+4) + + // !!! R14 = &src[len(src)] + MOVQ src_len+32(FP), R14 + ADDQ DX, R14 + + // !!! R13 = &src[len(src) - 8] + MOVQ R14, R13 + SUBQ $8, R13 + + // !!! R15 = &src[candidate + 4] + ADDQ $4, R15 + ADDQ DX, R15 + + // !!! s += 4 + ADDQ $4, SI + +inlineExtendMatchCmp8: + // As long as we are 8 or more bytes before the end of src, we can load and + // compare 8 bytes at a time. If those 8 bytes are equal, repeat. + CMPQ SI, R13 + JA inlineExtendMatchCmp1 + MOVQ (R15), AX + MOVQ (SI), BX + CMPQ AX, BX + JNE inlineExtendMatchBSF + ADDQ $8, R15 + ADDQ $8, SI + JMP inlineExtendMatchCmp8 + +inlineExtendMatchBSF: + // If those 8 bytes were not equal, XOR the two 8 byte values, and return + // the index of the first byte that differs. The BSF instruction finds the + // least significant 1 bit, the amd64 architecture is little-endian, and + // the shift by 3 converts a bit index to a byte index. + XORQ AX, BX + BSFQ BX, BX + SHRQ $3, BX + ADDQ BX, SI + JMP inlineExtendMatchEnd + +inlineExtendMatchCmp1: + // In src's tail, compare 1 byte at a time. + CMPQ SI, R14 + JAE inlineExtendMatchEnd + MOVB (R15), AX + MOVB (SI), BX + CMPB AX, BX + JNE inlineExtendMatchEnd + ADDQ $1, R15 + ADDQ $1, SI + JMP inlineExtendMatchCmp1 + +inlineExtendMatchEnd: + // End inline of the extendMatch call. + // ---------------------------------------- + + // ---------------------------------------- + // Begin inline of the emitCopy call. + // + // d += emitCopy(dst[d:], base-candidate, s-base) + + // !!! length := s - base + MOVQ SI, AX + SUBQ R12, AX + +inlineEmitCopyLoop0: + // for length >= 68 { etc } + CMPL AX, $68 + JLT inlineEmitCopyStep1 + + // Emit a length 64 copy, encoded as 3 bytes. + MOVB $0xfe, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + SUBL $64, AX + JMP inlineEmitCopyLoop0 + +inlineEmitCopyStep1: + // if length > 64 { etc } + CMPL AX, $64 + JLE inlineEmitCopyStep2 + + // Emit a length 60 copy, encoded as 3 bytes. + MOVB $0xee, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + SUBL $60, AX + +inlineEmitCopyStep2: + // if length >= 12 || offset >= 2048 { goto inlineEmitCopyStep3 } + CMPL AX, $12 + JGE inlineEmitCopyStep3 + CMPL R11, $2048 + JGE inlineEmitCopyStep3 + + // Emit the remaining copy, encoded as 2 bytes. + MOVB R11, 1(DI) + SHRL $8, R11 + SHLB $5, R11 + SUBB $4, AX + SHLB $2, AX + ORB AX, R11 + ORB $1, R11 + MOVB R11, 0(DI) + ADDQ $2, DI + JMP inlineEmitCopyEnd + +inlineEmitCopyStep3: + // Emit the remaining copy, encoded as 3 bytes. + SUBL $1, AX + SHLB $2, AX + ORB $2, AX + MOVB AX, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + +inlineEmitCopyEnd: + // End inline of the emitCopy call. + // ---------------------------------------- + + // nextEmit = s + MOVQ SI, R10 + + // if s >= sLimit { goto emitRemainder } + MOVQ SI, AX + SUBQ DX, AX + CMPQ AX, R9 + JAE emitRemainder + + // As per the encode_other.go code: + // + // We could immediately etc. + + // x := load64(src, s-1) + MOVQ -1(SI), R14 + + // prevHash := hash(uint32(x>>0), shift) + MOVL R14, R11 + IMULL $0x1e35a7bd, R11 + SHRL CX, R11 + + // table[prevHash] = uint16(s-1) + MOVQ SI, AX + SUBQ DX, AX + SUBQ $1, AX + + // XXX: MOVW AX, table-32768(SP)(R11*2) + // XXX: 66 42 89 44 5c 78 mov %ax,0x78(%rsp,%r11,2) + BYTE $0x66 + BYTE $0x42 + BYTE $0x89 + BYTE $0x44 + BYTE $0x5c + BYTE $0x78 + + // currHash := hash(uint32(x>>8), shift) + SHRQ $8, R14 + MOVL R14, R11 + IMULL $0x1e35a7bd, R11 + SHRL CX, R11 + + // candidate = int(table[currHash]) + // XXX: MOVWQZX table-32768(SP)(R11*2), R15 + // XXX: 4e 0f b7 7c 5c 78 movzwq 0x78(%rsp,%r11,2),%r15 + BYTE $0x4e + BYTE $0x0f + BYTE $0xb7 + BYTE $0x7c + BYTE $0x5c + BYTE $0x78 + + // table[currHash] = uint16(s) + ADDQ $1, AX + + // XXX: MOVW AX, table-32768(SP)(R11*2) + // XXX: 66 42 89 44 5c 78 mov %ax,0x78(%rsp,%r11,2) + BYTE $0x66 + BYTE $0x42 + BYTE $0x89 + BYTE $0x44 + BYTE $0x5c + BYTE $0x78 + + // if uint32(x>>8) == load32(src, candidate) { continue } + MOVL (DX)(R15*1), BX + CMPL R14, BX + JEQ inner1 + + // nextHash = hash(uint32(x>>16), shift) + SHRQ $8, R14 + MOVL R14, R11 + IMULL $0x1e35a7bd, R11 + SHRL CX, R11 + + // s++ + ADDQ $1, SI + + // break out of the inner1 for loop, i.e. continue the outer loop. + JMP outer + +emitRemainder: + // if nextEmit < len(src) { etc } + MOVQ src_len+32(FP), AX + ADDQ DX, AX + CMPQ R10, AX + JEQ encodeBlockEnd + + // d += emitLiteral(dst[d:], src[nextEmit:]) + // + // Push args. + MOVQ DI, 0(SP) + MOVQ $0, 8(SP) // Unnecessary, as the callee ignores it, but conservative. + MOVQ $0, 16(SP) // Unnecessary, as the callee ignores it, but conservative. + MOVQ R10, 24(SP) + SUBQ R10, AX + MOVQ AX, 32(SP) + MOVQ AX, 40(SP) // Unnecessary, as the callee ignores it, but conservative. + + // Spill local variables (registers) onto the stack; call; unspill. + MOVQ DI, 80(SP) + CALL ·emitLiteral(SB) + MOVQ 80(SP), DI + + // Finish the "d +=" part of "d += emitLiteral(etc)". + ADDQ 48(SP), DI + +encodeBlockEnd: + MOVQ dst_base+0(FP), AX + SUBQ AX, DI + MOVQ DI, d+48(FP) + RET diff --git a/vendor/src/github.com/golang/snappy/encode_other.go b/vendor/src/github.com/golang/snappy/encode_other.go new file mode 100644 index 00000000..dbcae905 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/encode_other.go @@ -0,0 +1,238 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64 appengine !gc noasm + +package snappy + +func load32(b []byte, i int) uint32 { + b = b[i : i+4 : len(b)] // Help the compiler eliminate bounds checks on the next line. + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func load64(b []byte, i int) uint64 { + b = b[i : i+8 : len(b)] // Help the compiler eliminate bounds checks on the next line. + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +// emitLiteral writes a literal chunk and returns the number of bytes written. +// +// It assumes that: +// dst is long enough to hold the encoded bytes +// 1 <= len(lit) && len(lit) <= 65536 +func emitLiteral(dst, lit []byte) int { + i, n := 0, uint(len(lit)-1) + switch { + case n < 60: + dst[0] = uint8(n)<<2 | tagLiteral + i = 1 + case n < 1<<8: + dst[0] = 60<<2 | tagLiteral + dst[1] = uint8(n) + i = 2 + default: + dst[0] = 61<<2 | tagLiteral + dst[1] = uint8(n) + dst[2] = uint8(n >> 8) + i = 3 + } + return i + copy(dst[i:], lit) +} + +// emitCopy writes a copy chunk and returns the number of bytes written. +// +// It assumes that: +// dst is long enough to hold the encoded bytes +// 1 <= offset && offset <= 65535 +// 4 <= length && length <= 65535 +func emitCopy(dst []byte, offset, length int) int { + i := 0 + // The maximum length for a single tagCopy1 or tagCopy2 op is 64 bytes. The + // threshold for this loop is a little higher (at 68 = 64 + 4), and the + // length emitted down below is is a little lower (at 60 = 64 - 4), because + // it's shorter to encode a length 67 copy as a length 60 tagCopy2 followed + // by a length 7 tagCopy1 (which encodes as 3+2 bytes) than to encode it as + // a length 64 tagCopy2 followed by a length 3 tagCopy2 (which encodes as + // 3+3 bytes). The magic 4 in the 64±4 is because the minimum length for a + // tagCopy1 op is 4 bytes, which is why a length 3 copy has to be an + // encodes-as-3-bytes tagCopy2 instead of an encodes-as-2-bytes tagCopy1. + for length >= 68 { + // Emit a length 64 copy, encoded as 3 bytes. + dst[i+0] = 63<<2 | tagCopy2 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + i += 3 + length -= 64 + } + if length > 64 { + // Emit a length 60 copy, encoded as 3 bytes. + dst[i+0] = 59<<2 | tagCopy2 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + i += 3 + length -= 60 + } + if length >= 12 || offset >= 2048 { + // Emit the remaining copy, encoded as 3 bytes. + dst[i+0] = uint8(length-1)<<2 | tagCopy2 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + return i + 3 + } + // Emit the remaining copy, encoded as 2 bytes. + dst[i+0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1 + dst[i+1] = uint8(offset) + return i + 2 +} + +// extendMatch returns the largest k such that k <= len(src) and that +// src[i:i+k-j] and src[j:k] have the same contents. +// +// It assumes that: +// 0 <= i && i < j && j <= len(src) +func extendMatch(src []byte, i, j int) int { + for ; j < len(src) && src[i] == src[j]; i, j = i+1, j+1 { + } + return j +} + +func hash(u, shift uint32) uint32 { + return (u * 0x1e35a7bd) >> shift +} + +// encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlock(dst, src []byte) (d int) { + // Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive. + // The table element type is uint16, as s < sLimit and sLimit < len(src) + // and len(src) <= maxBlockSize and maxBlockSize == 65536. + const ( + maxTableSize = 1 << 14 + // tableMask is redundant, but helps the compiler eliminate bounds + // checks. + tableMask = maxTableSize - 1 + ) + shift := uint32(32 - 8) + for tableSize := 1 << 8; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 { + shift-- + } + // In Go, all array elements are zero-initialized, so there is no advantage + // to a smaller tableSize per se. However, it matches the C++ algorithm, + // and in the asm versions of this code, we can get away with zeroing only + // the first tableSize elements. + var table [maxTableSize]uint16 + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + nextHash := hash(load32(src, s), shift) + + for { + // Copied from the C++ snappy implementation: + // + // Heuristic match skipping: If 32 bytes are scanned with no matches + // found, start looking only at every other byte. If 32 more bytes are + // scanned (or skipped), look at every third byte, etc.. When a match + // is found, immediately go back to looking at every byte. This is a + // small loss (~5% performance, ~0.1% density) for compressible data + // due to more bookkeeping, but for non-compressible data (such as + // JPEG) it's a huge win since the compressor quickly "realizes" the + // data is incompressible and doesn't bother looking for matches + // everywhere. + // + // The "skip" variable keeps track of how many bytes there are since + // the last match; dividing it by 32 (ie. right-shifting by five) gives + // the number of bytes to move ahead for each iteration. + skip := 32 + + nextS := s + candidate := 0 + for { + s = nextS + bytesBetweenHashLookups := skip >> 5 + nextS = s + bytesBetweenHashLookups + skip += bytesBetweenHashLookups + if nextS > sLimit { + goto emitRemainder + } + candidate = int(table[nextHash&tableMask]) + table[nextHash&tableMask] = uint16(s) + nextHash = hash(load32(src, nextS), shift) + if load32(src, s) == load32(src, candidate) { + break + } + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + d += emitLiteral(dst[d:], src[nextEmit:s]) + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + + // Extend the 4-byte match as long as possible. + // + // This is an inlined version of: + // s = extendMatch(src, candidate+4, s+4) + s += 4 + for i := candidate + 4; s < len(src) && src[i] == src[s]; i, s = i+1, s+1 { + } + + d += emitCopy(dst[d:], base-candidate, s-base) + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-1 and at s. If + // another emitCopy is not our next move, also calculate nextHash + // at s+1. At least on GOARCH=amd64, these three hash calculations + // are faster as one load64 call (with some shifts) instead of + // three load32 calls. + x := load64(src, s-1) + prevHash := hash(uint32(x>>0), shift) + table[prevHash&tableMask] = uint16(s - 1) + currHash := hash(uint32(x>>8), shift) + candidate = int(table[currHash&tableMask]) + table[currHash&tableMask] = uint16(s) + if uint32(x>>8) != load32(src, candidate) { + nextHash = hash(uint32(x>>16), shift) + s++ + break + } + } + } + +emitRemainder: + if nextEmit < len(src) { + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} diff --git a/vendor/src/github.com/golang/snappy/golden_test.go b/vendor/src/github.com/golang/snappy/golden_test.go new file mode 100644 index 00000000..e4496f92 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/golden_test.go @@ -0,0 +1,1965 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package snappy + +// extendMatchGoldenTestCases is the i and j arguments, and the returned value, +// for every extendMatch call issued when encoding the +// testdata/Mark.Twain-Tom.Sawyer.txt file. It is used to benchmark the +// extendMatch implementation. +// +// It was generated manually by adding some print statements to the (pure Go) +// extendMatch implementation: +// +// func extendMatch(src []byte, i, j int) int { +// i0, j0 := i, j +// for ; j < len(src) && src[i] == src[j]; i, j = i+1, j+1 { +// } +// println("{", i0, ",", j0, ",", j, "},") +// return j +// } +// +// and running "go test -test.run=EncodeGoldenInput -tags=noasm". +var extendMatchGoldenTestCases = []struct { + i, j, want int +}{ + {11, 61, 62}, + {80, 81, 82}, + {86, 87, 101}, + {85, 133, 149}, + {152, 153, 162}, + {133, 168, 193}, + {168, 207, 225}, + {81, 255, 275}, + {278, 279, 283}, + {306, 417, 417}, + {373, 428, 430}, + {389, 444, 447}, + {474, 510, 512}, + {465, 533, 533}, + {47, 547, 547}, + {307, 551, 554}, + {420, 582, 587}, + {309, 604, 604}, + {604, 625, 625}, + {538, 629, 629}, + {328, 640, 640}, + {573, 645, 645}, + {319, 657, 657}, + {30, 664, 664}, + {45, 679, 680}, + {621, 684, 684}, + {376, 700, 700}, + {33, 707, 708}, + {601, 733, 733}, + {334, 744, 745}, + {625, 758, 759}, + {382, 763, 763}, + {550, 769, 771}, + {533, 789, 789}, + {804, 813, 813}, + {342, 841, 842}, + {742, 847, 847}, + {74, 852, 852}, + {810, 864, 864}, + {758, 868, 869}, + {714, 883, 883}, + {582, 889, 891}, + {61, 934, 935}, + {894, 942, 942}, + {939, 949, 949}, + {785, 956, 957}, + {886, 978, 978}, + {792, 998, 998}, + {998, 1005, 1005}, + {572, 1032, 1032}, + {698, 1051, 1053}, + {599, 1067, 1069}, + {1056, 1079, 1079}, + {942, 1089, 1090}, + {831, 1094, 1096}, + {1088, 1100, 1103}, + {732, 1113, 1114}, + {1037, 1118, 1118}, + {872, 1128, 1130}, + {1079, 1140, 1142}, + {332, 1162, 1162}, + {207, 1168, 1186}, + {1189, 1190, 1225}, + {105, 1229, 1230}, + {79, 1256, 1257}, + {1190, 1261, 1283}, + {255, 1306, 1306}, + {1319, 1339, 1358}, + {364, 1370, 1370}, + {955, 1378, 1380}, + {122, 1403, 1403}, + {1325, 1407, 1419}, + {664, 1423, 1424}, + {941, 1461, 1463}, + {867, 1477, 1478}, + {757, 1488, 1489}, + {1140, 1499, 1499}, + {31, 1506, 1506}, + {1487, 1510, 1512}, + {1089, 1520, 1521}, + {1467, 1525, 1529}, + {1394, 1537, 1537}, + {1499, 1541, 1541}, + {367, 1558, 1558}, + {1475, 1564, 1564}, + {1525, 1568, 1571}, + {1541, 1582, 1583}, + {864, 1587, 1588}, + {704, 1597, 1597}, + {336, 1602, 1602}, + {1383, 1613, 1613}, + {1498, 1617, 1618}, + {1051, 1623, 1625}, + {401, 1643, 1645}, + {1072, 1654, 1655}, + {1067, 1667, 1669}, + {699, 1673, 1674}, + {1587, 1683, 1684}, + {920, 1696, 1696}, + {1505, 1710, 1710}, + {1550, 1723, 1723}, + {996, 1727, 1727}, + {833, 1733, 1734}, + {1638, 1739, 1740}, + {1654, 1744, 1744}, + {753, 1761, 1761}, + {1548, 1773, 1773}, + {1568, 1777, 1780}, + {1683, 1793, 1794}, + {948, 1801, 1801}, + {1666, 1805, 1808}, + {1502, 1814, 1814}, + {1696, 1822, 1822}, + {502, 1836, 1837}, + {917, 1843, 1843}, + {1733, 1854, 1855}, + {970, 1859, 1859}, + {310, 1863, 1863}, + {657, 1872, 1872}, + {1005, 1876, 1876}, + {1662, 1880, 1880}, + {904, 1892, 1892}, + {1427, 1910, 1910}, + {1772, 1929, 1930}, + {1822, 1937, 1940}, + {1858, 1949, 1950}, + {1602, 1956, 1956}, + {1150, 1962, 1962}, + {1504, 1966, 1967}, + {51, 1971, 1971}, + {1605, 1979, 1979}, + {1458, 1983, 1988}, + {1536, 2001, 2006}, + {1373, 2014, 2018}, + {1494, 2025, 2025}, + {1667, 2029, 2031}, + {1592, 2035, 2035}, + {330, 2045, 2045}, + {1376, 2053, 2053}, + {1991, 2058, 2059}, + {1635, 2065, 2065}, + {1992, 2073, 2074}, + {2014, 2080, 2081}, + {1546, 2085, 2087}, + {59, 2099, 2099}, + {1996, 2106, 2106}, + {1836, 2110, 2110}, + {2068, 2114, 2114}, + {1338, 2122, 2122}, + {1562, 2128, 2130}, + {1934, 2134, 2134}, + {2114, 2141, 2142}, + {977, 2149, 2150}, + {956, 2154, 2155}, + {1407, 2162, 2162}, + {1773, 2166, 2166}, + {883, 2171, 2171}, + {623, 2175, 2178}, + {1520, 2191, 2192}, + {1162, 2200, 2200}, + {912, 2204, 2204}, + {733, 2208, 2208}, + {1777, 2212, 2215}, + {1532, 2219, 2219}, + {718, 2223, 2225}, + {2069, 2229, 2229}, + {2207, 2245, 2246}, + {1139, 2264, 2264}, + {677, 2274, 2274}, + {2099, 2279, 2279}, + {1863, 2283, 2283}, + {1966, 2305, 2306}, + {2279, 2313, 2313}, + {1628, 2319, 2319}, + {755, 2329, 2329}, + {1461, 2334, 2334}, + {2117, 2340, 2340}, + {2313, 2349, 2349}, + {1859, 2353, 2353}, + {1048, 2362, 2362}, + {895, 2366, 2366}, + {2278, 2373, 2373}, + {1884, 2377, 2377}, + {1402, 2387, 2392}, + {700, 2398, 2398}, + {1971, 2402, 2402}, + {2009, 2419, 2419}, + {1441, 2426, 2428}, + {2208, 2432, 2432}, + {2038, 2436, 2436}, + {932, 2443, 2443}, + {1759, 2447, 2448}, + {744, 2452, 2452}, + {1875, 2458, 2458}, + {2405, 2468, 2468}, + {1596, 2472, 2473}, + {1953, 2480, 2482}, + {736, 2487, 2487}, + {1913, 2493, 2493}, + {774, 2497, 2497}, + {1484, 2506, 2508}, + {2432, 2512, 2512}, + {752, 2519, 2519}, + {2497, 2523, 2523}, + {2409, 2528, 2529}, + {2122, 2533, 2533}, + {2396, 2537, 2538}, + {2410, 2547, 2548}, + {1093, 2555, 2560}, + {551, 2564, 2565}, + {2268, 2569, 2569}, + {1362, 2580, 2580}, + {1916, 2584, 2585}, + {994, 2589, 2590}, + {1979, 2596, 2596}, + {1041, 2602, 2602}, + {2104, 2614, 2616}, + {2609, 2621, 2628}, + {2329, 2638, 2638}, + {2211, 2657, 2658}, + {2638, 2662, 2667}, + {2578, 2676, 2679}, + {2153, 2685, 2686}, + {2608, 2696, 2697}, + {598, 2712, 2712}, + {2620, 2719, 2720}, + {1888, 2724, 2728}, + {2709, 2732, 2732}, + {1365, 2739, 2739}, + {784, 2747, 2748}, + {424, 2753, 2753}, + {2204, 2759, 2759}, + {812, 2768, 2769}, + {2455, 2773, 2773}, + {1722, 2781, 2781}, + {1917, 2792, 2792}, + {2705, 2799, 2799}, + {2685, 2806, 2807}, + {2742, 2811, 2811}, + {1370, 2818, 2818}, + {2641, 2830, 2830}, + {2512, 2837, 2837}, + {2457, 2841, 2841}, + {2756, 2845, 2845}, + {2719, 2855, 2855}, + {1423, 2859, 2859}, + {2849, 2863, 2865}, + {1474, 2871, 2871}, + {1161, 2875, 2876}, + {2282, 2880, 2881}, + {2746, 2888, 2888}, + {1783, 2893, 2893}, + {2401, 2899, 2900}, + {2632, 2920, 2923}, + {2422, 2928, 2930}, + {2715, 2939, 2939}, + {2162, 2943, 2943}, + {2859, 2947, 2947}, + {1910, 2951, 2951}, + {1431, 2955, 2956}, + {1439, 2964, 2964}, + {2501, 2968, 2969}, + {2029, 2973, 2976}, + {689, 2983, 2984}, + {1658, 2988, 2988}, + {1031, 2996, 2996}, + {2149, 3001, 3002}, + {25, 3009, 3013}, + {2964, 3023, 3023}, + {953, 3027, 3028}, + {2359, 3036, 3036}, + {3023, 3049, 3049}, + {2880, 3055, 3056}, + {2973, 3076, 3077}, + {2874, 3090, 3090}, + {2871, 3094, 3094}, + {2532, 3100, 3100}, + {2938, 3107, 3108}, + {350, 3115, 3115}, + {2196, 3119, 3121}, + {1133, 3127, 3129}, + {1797, 3134, 3150}, + {3032, 3158, 3158}, + {3016, 3172, 3172}, + {2533, 3179, 3179}, + {3055, 3187, 3188}, + {1384, 3192, 3193}, + {2799, 3199, 3199}, + {2126, 3203, 3207}, + {2334, 3215, 3215}, + {2105, 3220, 3221}, + {3199, 3229, 3229}, + {2891, 3233, 3233}, + {855, 3240, 3240}, + {1852, 3253, 3256}, + {2140, 3263, 3263}, + {1682, 3268, 3270}, + {3243, 3274, 3274}, + {924, 3279, 3279}, + {2212, 3283, 3283}, + {2596, 3287, 3287}, + {2999, 3291, 3291}, + {2353, 3295, 3295}, + {2480, 3302, 3304}, + {1959, 3308, 3311}, + {3000, 3318, 3318}, + {845, 3330, 3330}, + {2283, 3334, 3334}, + {2519, 3342, 3342}, + {3325, 3346, 3348}, + {2397, 3353, 3354}, + {2763, 3358, 3358}, + {3198, 3363, 3364}, + {3211, 3368, 3372}, + {2950, 3376, 3377}, + {3245, 3388, 3391}, + {2264, 3398, 3398}, + {795, 3403, 3403}, + {3287, 3407, 3407}, + {3358, 3411, 3411}, + {3317, 3415, 3415}, + {3232, 3431, 3431}, + {2128, 3435, 3437}, + {3236, 3441, 3441}, + {3398, 3445, 3446}, + {2814, 3450, 3450}, + {3394, 3466, 3466}, + {2425, 3470, 3470}, + {3330, 3476, 3476}, + {1612, 3480, 3480}, + {1004, 3485, 3486}, + {2732, 3490, 3490}, + {1117, 3494, 3495}, + {629, 3501, 3501}, + {3087, 3514, 3514}, + {684, 3518, 3518}, + {3489, 3522, 3524}, + {1760, 3529, 3529}, + {617, 3537, 3537}, + {3431, 3541, 3541}, + {997, 3547, 3547}, + {882, 3552, 3553}, + {2419, 3558, 3558}, + {610, 3562, 3563}, + {1903, 3567, 3569}, + {3005, 3575, 3575}, + {3076, 3585, 3586}, + {3541, 3590, 3590}, + {3490, 3594, 3594}, + {1899, 3599, 3599}, + {3545, 3606, 3606}, + {3290, 3614, 3615}, + {2056, 3619, 3620}, + {3556, 3625, 3625}, + {3294, 3632, 3633}, + {637, 3643, 3644}, + {3609, 3648, 3650}, + {3175, 3658, 3658}, + {3498, 3665, 3665}, + {1597, 3669, 3669}, + {1983, 3673, 3673}, + {3215, 3682, 3682}, + {3544, 3689, 3689}, + {3694, 3698, 3698}, + {3228, 3715, 3716}, + {2594, 3720, 3722}, + {3573, 3726, 3726}, + {2479, 3732, 3735}, + {3191, 3741, 3742}, + {1113, 3746, 3747}, + {2844, 3751, 3751}, + {3445, 3756, 3757}, + {3755, 3766, 3766}, + {3421, 3775, 3780}, + {3593, 3784, 3786}, + {3263, 3796, 3796}, + {3469, 3806, 3806}, + {2602, 3815, 3815}, + {723, 3819, 3821}, + {1608, 3826, 3826}, + {3334, 3830, 3830}, + {2198, 3835, 3835}, + {2635, 3840, 3840}, + {3702, 3852, 3853}, + {3406, 3858, 3859}, + {3681, 3867, 3870}, + {3407, 3880, 3880}, + {340, 3889, 3889}, + {3772, 3893, 3893}, + {593, 3897, 3897}, + {2563, 3914, 3916}, + {2981, 3929, 3929}, + {1835, 3933, 3934}, + {3906, 3951, 3951}, + {1459, 3958, 3958}, + {3889, 3974, 3974}, + {2188, 3982, 3982}, + {3220, 3986, 3987}, + {3585, 3991, 3993}, + {3712, 3997, 4001}, + {2805, 4007, 4007}, + {1879, 4012, 4013}, + {3618, 4018, 4018}, + {1145, 4031, 4032}, + {3901, 4037, 4037}, + {2772, 4046, 4047}, + {2802, 4053, 4054}, + {3299, 4058, 4058}, + {3725, 4066, 4066}, + {2271, 4070, 4070}, + {385, 4075, 4076}, + {3624, 4089, 4090}, + {3745, 4096, 4098}, + {1563, 4102, 4102}, + {4045, 4106, 4111}, + {3696, 4115, 4119}, + {3376, 4125, 4126}, + {1880, 4130, 4130}, + {2048, 4140, 4141}, + {2724, 4149, 4149}, + {1767, 4156, 4156}, + {2601, 4164, 4164}, + {2757, 4168, 4168}, + {3974, 4172, 4172}, + {3914, 4178, 4178}, + {516, 4185, 4185}, + {1032, 4189, 4190}, + {3462, 4197, 4198}, + {3805, 4202, 4203}, + {3910, 4207, 4212}, + {3075, 4221, 4221}, + {3756, 4225, 4226}, + {1872, 4236, 4237}, + {3844, 4241, 4241}, + {3991, 4245, 4249}, + {2203, 4258, 4258}, + {3903, 4267, 4268}, + {705, 4272, 4272}, + {1896, 4276, 4276}, + {1955, 4285, 4288}, + {3746, 4302, 4303}, + {2672, 4311, 4311}, + {3969, 4317, 4317}, + {3883, 4322, 4322}, + {1920, 4339, 4340}, + {3527, 4344, 4346}, + {1160, 4358, 4358}, + {3648, 4364, 4366}, + {2711, 4387, 4387}, + {3619, 4391, 4392}, + {1944, 4396, 4396}, + {4369, 4400, 4400}, + {2736, 4404, 4407}, + {2546, 4411, 4412}, + {4390, 4422, 4422}, + {3610, 4426, 4427}, + {4058, 4431, 4431}, + {4374, 4435, 4435}, + {3463, 4445, 4446}, + {1813, 4452, 4452}, + {3669, 4456, 4456}, + {3830, 4460, 4460}, + {421, 4464, 4465}, + {1719, 4471, 4471}, + {3880, 4475, 4475}, + {1834, 4485, 4487}, + {3590, 4491, 4491}, + {442, 4496, 4497}, + {4435, 4501, 4501}, + {3814, 4509, 4509}, + {987, 4513, 4513}, + {4494, 4518, 4521}, + {3218, 4526, 4529}, + {4221, 4537, 4537}, + {2778, 4543, 4545}, + {4422, 4552, 4552}, + {4031, 4558, 4559}, + {4178, 4563, 4563}, + {3726, 4567, 4574}, + {4027, 4578, 4578}, + {4339, 4585, 4587}, + {3796, 4592, 4595}, + {543, 4600, 4613}, + {2855, 4620, 4621}, + {2795, 4627, 4627}, + {3440, 4631, 4632}, + {4279, 4636, 4639}, + {4245, 4643, 4645}, + {4516, 4649, 4650}, + {3133, 4654, 4654}, + {4042, 4658, 4659}, + {3422, 4663, 4663}, + {4046, 4667, 4668}, + {4267, 4672, 4672}, + {4004, 4676, 4677}, + {2490, 4682, 4682}, + {2451, 4697, 4697}, + {3027, 4705, 4705}, + {4028, 4717, 4717}, + {4460, 4721, 4721}, + {2471, 4725, 4727}, + {3090, 4735, 4735}, + {3192, 4739, 4740}, + {3835, 4760, 4760}, + {4540, 4764, 4764}, + {4007, 4772, 4774}, + {619, 4784, 4784}, + {3561, 4789, 4791}, + {3367, 4805, 4805}, + {4490, 4810, 4811}, + {2402, 4815, 4815}, + {3352, 4819, 4822}, + {2773, 4828, 4828}, + {4552, 4832, 4832}, + {2522, 4840, 4841}, + {316, 4847, 4852}, + {4715, 4858, 4858}, + {2959, 4862, 4862}, + {4858, 4868, 4869}, + {2134, 4873, 4873}, + {578, 4878, 4878}, + {4189, 4889, 4890}, + {2229, 4894, 4894}, + {4501, 4898, 4898}, + {2297, 4903, 4903}, + {2933, 4909, 4909}, + {3008, 4913, 4913}, + {3153, 4917, 4917}, + {4819, 4921, 4921}, + {4921, 4932, 4933}, + {4920, 4944, 4945}, + {4814, 4954, 4955}, + {576, 4966, 4966}, + {1854, 4970, 4971}, + {1374, 4975, 4976}, + {3307, 4980, 4980}, + {974, 4984, 4988}, + {4721, 4992, 4992}, + {4898, 4996, 4996}, + {4475, 5006, 5006}, + {3819, 5012, 5012}, + {1948, 5019, 5021}, + {4954, 5027, 5029}, + {3740, 5038, 5040}, + {4763, 5044, 5045}, + {1936, 5051, 5051}, + {4844, 5055, 5060}, + {4215, 5069, 5072}, + {1146, 5076, 5076}, + {3845, 5082, 5082}, + {4865, 5090, 5090}, + {4624, 5094, 5094}, + {4815, 5098, 5098}, + {5006, 5105, 5105}, + {4980, 5109, 5109}, + {4795, 5113, 5115}, + {5043, 5119, 5121}, + {4782, 5129, 5129}, + {3826, 5139, 5139}, + {3876, 5156, 5156}, + {3111, 5167, 5171}, + {1470, 5177, 5177}, + {4431, 5181, 5181}, + {546, 5189, 5189}, + {4225, 5193, 5193}, + {1672, 5199, 5201}, + {4207, 5205, 5209}, + {4220, 5216, 5217}, + {4658, 5224, 5225}, + {3295, 5235, 5235}, + {2436, 5239, 5239}, + {2349, 5246, 5246}, + {2175, 5250, 5250}, + {5180, 5257, 5258}, + {3161, 5263, 5263}, + {5105, 5272, 5272}, + {3552, 5282, 5282}, + {4944, 5299, 5300}, + {4130, 5312, 5313}, + {902, 5323, 5323}, + {913, 5327, 5327}, + {2987, 5333, 5334}, + {5150, 5344, 5344}, + {5249, 5348, 5348}, + {1965, 5358, 5359}, + {5330, 5364, 5364}, + {2012, 5373, 5377}, + {712, 5384, 5386}, + {5235, 5390, 5390}, + {5044, 5398, 5399}, + {564, 5406, 5406}, + {39, 5410, 5410}, + {4642, 5422, 5425}, + {4421, 5437, 5438}, + {2347, 5449, 5449}, + {5333, 5453, 5454}, + {4136, 5458, 5459}, + {3793, 5468, 5468}, + {2243, 5480, 5480}, + {4889, 5492, 5493}, + {4295, 5504, 5504}, + {2785, 5511, 5511}, + {2377, 5518, 5518}, + {3662, 5525, 5525}, + {5097, 5529, 5530}, + {4781, 5537, 5538}, + {4697, 5547, 5548}, + {436, 5552, 5553}, + {5542, 5558, 5558}, + {3692, 5562, 5562}, + {2696, 5568, 5569}, + {4620, 5578, 5578}, + {2898, 5590, 5590}, + {5557, 5596, 5618}, + {2797, 5623, 5625}, + {2792, 5629, 5629}, + {5243, 5633, 5633}, + {5348, 5637, 5637}, + {5547, 5643, 5643}, + {4296, 5654, 5655}, + {5568, 5662, 5662}, + {3001, 5670, 5671}, + {3794, 5679, 5679}, + {4006, 5685, 5686}, + {4969, 5690, 5692}, + {687, 5704, 5704}, + {4563, 5708, 5708}, + {1723, 5738, 5738}, + {649, 5742, 5742}, + {5163, 5748, 5755}, + {3907, 5759, 5759}, + {3074, 5764, 5764}, + {5326, 5771, 5771}, + {2951, 5776, 5776}, + {5181, 5780, 5780}, + {2614, 5785, 5788}, + {4709, 5794, 5794}, + {2784, 5799, 5799}, + {5518, 5803, 5803}, + {4155, 5812, 5815}, + {921, 5819, 5819}, + {5224, 5823, 5824}, + {2853, 5830, 5836}, + {5776, 5840, 5840}, + {2955, 5844, 5845}, + {5745, 5853, 5853}, + {3291, 5857, 5857}, + {2988, 5861, 5861}, + {2647, 5865, 5865}, + {5398, 5869, 5870}, + {1085, 5874, 5875}, + {4906, 5881, 5881}, + {802, 5886, 5886}, + {5119, 5890, 5893}, + {5802, 5899, 5900}, + {3415, 5904, 5904}, + {5629, 5908, 5908}, + {3714, 5912, 5914}, + {5558, 5921, 5921}, + {2710, 5927, 5928}, + {1094, 5932, 5934}, + {2653, 5940, 5941}, + {4735, 5954, 5954}, + {5861, 5958, 5958}, + {1040, 5971, 5971}, + {5514, 5977, 5977}, + {5048, 5981, 5982}, + {5953, 5992, 5993}, + {3751, 5997, 5997}, + {4991, 6001, 6002}, + {5885, 6006, 6007}, + {5529, 6011, 6012}, + {4974, 6019, 6020}, + {5857, 6024, 6024}, + {3483, 6032, 6032}, + {3594, 6036, 6036}, + {1997, 6040, 6040}, + {5997, 6044, 6047}, + {5197, 6051, 6051}, + {1764, 6055, 6055}, + {6050, 6059, 6059}, + {5239, 6063, 6063}, + {5049, 6067, 6067}, + {5957, 6073, 6074}, + {1022, 6078, 6078}, + {3414, 6083, 6084}, + {3809, 6090, 6090}, + {4562, 6095, 6096}, + {5878, 6104, 6104}, + {594, 6108, 6109}, + {3353, 6115, 6116}, + {4992, 6120, 6121}, + {2424, 6125, 6125}, + {4484, 6130, 6130}, + {3900, 6134, 6135}, + {5793, 6139, 6141}, + {3562, 6145, 6145}, + {1438, 6152, 6153}, + {6058, 6157, 6158}, + {4411, 6162, 6163}, + {4590, 6167, 6171}, + {4748, 6175, 6175}, + {5517, 6183, 6184}, + {6095, 6191, 6192}, + {1471, 6203, 6203}, + {2643, 6209, 6210}, + {450, 6220, 6220}, + {5266, 6226, 6226}, + {2576, 6233, 6233}, + {2607, 6239, 6240}, + {5164, 6244, 6251}, + {6054, 6255, 6255}, + {1789, 6260, 6261}, + {5250, 6265, 6265}, + {6062, 6273, 6278}, + {5990, 6282, 6282}, + {3283, 6286, 6286}, + {5436, 6290, 6290}, + {6059, 6294, 6294}, + {5668, 6298, 6300}, + {3072, 6324, 6329}, + {3132, 6338, 6339}, + {3246, 6343, 6344}, + {28, 6348, 6349}, + {1503, 6353, 6355}, + {6067, 6359, 6359}, + {3384, 6364, 6364}, + {545, 6375, 6376}, + {5803, 6380, 6380}, + {5522, 6384, 6385}, + {5908, 6389, 6389}, + {2796, 6393, 6396}, + {4831, 6403, 6404}, + {6388, 6412, 6412}, + {6005, 6417, 6420}, + {4450, 6430, 6430}, + {4050, 6435, 6435}, + {5372, 6441, 6441}, + {4378, 6447, 6447}, + {6199, 6452, 6452}, + {3026, 6456, 6456}, + {2642, 6460, 6462}, + {6392, 6470, 6470}, + {6459, 6474, 6474}, + {2829, 6487, 6488}, + {2942, 6499, 6504}, + {5069, 6508, 6511}, + {5341, 6515, 6516}, + {5853, 6521, 6525}, + {6104, 6531, 6531}, + {5759, 6535, 6538}, + {4672, 6542, 6543}, + {2443, 6550, 6550}, + {5109, 6554, 6554}, + {6494, 6558, 6560}, + {6006, 6570, 6572}, + {6424, 6576, 6580}, + {4693, 6591, 6592}, + {6439, 6596, 6597}, + {3179, 6601, 6601}, + {5299, 6606, 6607}, + {4148, 6612, 6613}, + {3774, 6617, 6617}, + {3537, 6623, 6624}, + {4975, 6628, 6629}, + {3848, 6636, 6636}, + {856, 6640, 6640}, + {5724, 6645, 6645}, + {6632, 6651, 6651}, + {4630, 6656, 6658}, + {1440, 6662, 6662}, + {4281, 6666, 6667}, + {4302, 6671, 6672}, + {2589, 6676, 6677}, + {5647, 6681, 6687}, + {6082, 6691, 6693}, + {6144, 6698, 6698}, + {6103, 6709, 6710}, + {3710, 6714, 6714}, + {4253, 6718, 6721}, + {2467, 6730, 6730}, + {4778, 6734, 6734}, + {6528, 6738, 6738}, + {4358, 6747, 6747}, + {5889, 6753, 6753}, + {5193, 6757, 6757}, + {5797, 6761, 6761}, + {3858, 6765, 6766}, + {5951, 6776, 6776}, + {6487, 6781, 6782}, + {3282, 6786, 6787}, + {4667, 6797, 6799}, + {1927, 6803, 6806}, + {6583, 6810, 6810}, + {4937, 6814, 6814}, + {6099, 6824, 6824}, + {4415, 6835, 6836}, + {6332, 6840, 6841}, + {5160, 6850, 6850}, + {4764, 6854, 6854}, + {6814, 6858, 6859}, + {3018, 6864, 6864}, + {6293, 6868, 6869}, + {6359, 6877, 6877}, + {3047, 6884, 6886}, + {5262, 6890, 6891}, + {5471, 6900, 6900}, + {3268, 6910, 6912}, + {1047, 6916, 6916}, + {5904, 6923, 6923}, + {5798, 6933, 6938}, + {4149, 6942, 6942}, + {1821, 6946, 6946}, + {3599, 6952, 6952}, + {6470, 6957, 6957}, + {5562, 6961, 6961}, + {6268, 6965, 6967}, + {6389, 6971, 6971}, + {6596, 6975, 6976}, + {6553, 6980, 6981}, + {6576, 6985, 6989}, + {1375, 6993, 6993}, + {652, 6998, 6998}, + {4876, 7002, 7003}, + {5768, 7011, 7013}, + {3973, 7017, 7017}, + {6802, 7025, 7025}, + {6955, 7034, 7036}, + {6974, 7040, 7040}, + {5944, 7044, 7044}, + {6992, 7048, 7054}, + {6872, 7059, 7059}, + {2943, 7063, 7063}, + {6923, 7067, 7067}, + {5094, 7071, 7071}, + {4873, 7075, 7075}, + {5819, 7079, 7079}, + {5945, 7085, 7085}, + {1540, 7090, 7091}, + {2090, 7095, 7095}, + {5024, 7104, 7105}, + {6900, 7109, 7109}, + {6024, 7113, 7114}, + {6000, 7118, 7120}, + {2187, 7124, 7125}, + {6760, 7129, 7130}, + {5898, 7134, 7136}, + {7032, 7144, 7144}, + {4271, 7148, 7148}, + {3706, 7152, 7152}, + {6970, 7156, 7157}, + {7088, 7161, 7163}, + {2718, 7168, 7169}, + {5674, 7175, 7175}, + {4631, 7182, 7182}, + {7070, 7188, 7189}, + {6220, 7196, 7196}, + {3458, 7201, 7202}, + {2041, 7211, 7212}, + {1454, 7216, 7216}, + {5199, 7225, 7227}, + {3529, 7234, 7234}, + {6890, 7238, 7238}, + {3815, 7242, 7243}, + {5490, 7250, 7253}, + {6554, 7257, 7263}, + {5890, 7267, 7269}, + {6877, 7273, 7273}, + {4877, 7277, 7277}, + {2502, 7285, 7285}, + {1483, 7289, 7295}, + {7210, 7304, 7308}, + {6845, 7313, 7316}, + {7219, 7320, 7320}, + {7001, 7325, 7329}, + {6853, 7333, 7334}, + {6120, 7338, 7338}, + {6606, 7342, 7343}, + {7020, 7348, 7350}, + {3509, 7354, 7354}, + {7133, 7359, 7363}, + {3434, 7371, 7374}, + {2787, 7384, 7384}, + {7044, 7388, 7388}, + {6960, 7394, 7395}, + {6676, 7399, 7400}, + {7161, 7404, 7404}, + {7285, 7417, 7418}, + {4558, 7425, 7426}, + {4828, 7430, 7430}, + {6063, 7436, 7436}, + {3597, 7442, 7442}, + {914, 7446, 7446}, + {7320, 7452, 7454}, + {7267, 7458, 7460}, + {5076, 7464, 7464}, + {7430, 7468, 7469}, + {6273, 7473, 7474}, + {7440, 7478, 7487}, + {7348, 7491, 7494}, + {1021, 7510, 7510}, + {7473, 7515, 7515}, + {2823, 7519, 7519}, + {6264, 7527, 7527}, + {7302, 7531, 7531}, + {7089, 7535, 7535}, + {7342, 7540, 7541}, + {3688, 7547, 7551}, + {3054, 7558, 7560}, + {4177, 7566, 7567}, + {6691, 7574, 7575}, + {7156, 7585, 7586}, + {7147, 7590, 7592}, + {7407, 7598, 7598}, + {7403, 7602, 7603}, + {6868, 7607, 7607}, + {6636, 7611, 7611}, + {4805, 7617, 7617}, + {5779, 7623, 7623}, + {7063, 7627, 7627}, + {5079, 7632, 7632}, + {7377, 7637, 7637}, + {7337, 7641, 7642}, + {6738, 7655, 7655}, + {7338, 7659, 7659}, + {6541, 7669, 7671}, + {595, 7675, 7675}, + {7658, 7679, 7680}, + {7647, 7685, 7686}, + {2477, 7690, 7690}, + {5823, 7694, 7694}, + {4156, 7699, 7699}, + {5931, 7703, 7706}, + {6854, 7712, 7712}, + {4931, 7718, 7718}, + {6979, 7722, 7722}, + {5085, 7727, 7727}, + {6965, 7732, 7732}, + {7201, 7736, 7737}, + {3639, 7741, 7743}, + {7534, 7749, 7749}, + {4292, 7753, 7753}, + {3427, 7759, 7763}, + {7273, 7767, 7767}, + {940, 7778, 7778}, + {4838, 7782, 7785}, + {4216, 7790, 7792}, + {922, 7800, 7801}, + {7256, 7810, 7811}, + {7789, 7815, 7819}, + {7225, 7823, 7825}, + {7531, 7829, 7829}, + {6997, 7833, 7833}, + {7757, 7837, 7838}, + {4129, 7842, 7842}, + {7333, 7848, 7849}, + {6776, 7855, 7855}, + {7527, 7859, 7859}, + {4370, 7863, 7863}, + {4512, 7868, 7868}, + {5679, 7880, 7880}, + {3162, 7884, 7885}, + {3933, 7892, 7894}, + {7804, 7899, 7902}, + {6363, 7906, 7907}, + {7848, 7911, 7912}, + {5584, 7917, 7921}, + {874, 7926, 7926}, + {3342, 7930, 7930}, + {4507, 7935, 7937}, + {3672, 7943, 7944}, + {7911, 7948, 7949}, + {6402, 7956, 7956}, + {7940, 7960, 7960}, + {7113, 7964, 7964}, + {1073, 7968, 7968}, + {7740, 7974, 7974}, + {7601, 7978, 7982}, + {6797, 7987, 7988}, + {3528, 7994, 7995}, + {5483, 7999, 7999}, + {5717, 8011, 8011}, + {5480, 8017, 8017}, + {7770, 8023, 8030}, + {2452, 8034, 8034}, + {5282, 8047, 8047}, + {7967, 8051, 8051}, + {1128, 8058, 8066}, + {6348, 8070, 8070}, + {8055, 8077, 8077}, + {7925, 8081, 8086}, + {6810, 8090, 8090}, + {5051, 8101, 8101}, + {4696, 8109, 8110}, + {5129, 8119, 8119}, + {4449, 8123, 8123}, + {7222, 8127, 8127}, + {4649, 8131, 8134}, + {7994, 8138, 8138}, + {5954, 8148, 8148}, + {475, 8152, 8153}, + {7906, 8157, 8157}, + {7458, 8164, 8166}, + {7632, 8171, 8173}, + {3874, 8177, 8183}, + {4391, 8187, 8187}, + {561, 8191, 8191}, + {2417, 8195, 8195}, + {2357, 8204, 8204}, + {2269, 8216, 8218}, + {3968, 8222, 8222}, + {2200, 8226, 8227}, + {3453, 8247, 8247}, + {2439, 8251, 8252}, + {7175, 8257, 8257}, + {976, 8262, 8264}, + {4953, 8273, 8273}, + {4219, 8278, 8278}, + {6, 8285, 8291}, + {5703, 8295, 8296}, + {5272, 8300, 8300}, + {8037, 8304, 8304}, + {8186, 8314, 8314}, + {8304, 8318, 8318}, + {8051, 8326, 8326}, + {8318, 8330, 8330}, + {2671, 8334, 8335}, + {2662, 8339, 8339}, + {8081, 8349, 8350}, + {3328, 8356, 8356}, + {2879, 8360, 8362}, + {8050, 8370, 8371}, + {8330, 8375, 8376}, + {8375, 8386, 8386}, + {4961, 8390, 8390}, + {1017, 8403, 8405}, + {3533, 8416, 8416}, + {4555, 8422, 8422}, + {6445, 8426, 8426}, + {8169, 8432, 8432}, + {990, 8436, 8436}, + {4102, 8440, 8440}, + {7398, 8444, 8446}, + {3480, 8450, 8450}, + {6324, 8462, 8462}, + {7948, 8466, 8467}, + {5950, 8471, 8471}, + {5189, 8476, 8476}, + {4026, 8490, 8490}, + {8374, 8494, 8495}, + {4682, 8501, 8501}, + {7387, 8506, 8506}, + {8164, 8510, 8515}, + {4079, 8524, 8524}, + {8360, 8529, 8531}, + {7446, 8540, 8543}, + {7971, 8547, 8548}, + {4311, 8552, 8552}, + {5204, 8556, 8557}, + {7968, 8562, 8562}, + {7847, 8571, 8573}, + {8547, 8577, 8577}, + {5320, 8581, 8581}, + {8556, 8585, 8586}, + {8504, 8590, 8590}, + {7669, 8602, 8604}, + {5874, 8608, 8609}, + {5828, 8613, 8613}, + {7998, 8617, 8617}, + {8519, 8625, 8625}, + {7250, 8637, 8637}, + {426, 8641, 8641}, + {8436, 8645, 8645}, + {5986, 8649, 8656}, + {8157, 8660, 8660}, + {7182, 8665, 8665}, + {8421, 8675, 8675}, + {8509, 8681, 8681}, + {5137, 8688, 8689}, + {8625, 8694, 8695}, + {5228, 8701, 8702}, + {6661, 8714, 8714}, + {1010, 8719, 8719}, + {6648, 8723, 8723}, + {3500, 8728, 8728}, + {2442, 8735, 8735}, + {8494, 8740, 8741}, + {8171, 8753, 8755}, + {7242, 8763, 8764}, + {4739, 8768, 8769}, + {7079, 8773, 8773}, + {8386, 8777, 8777}, + {8624, 8781, 8787}, + {661, 8791, 8794}, + {8631, 8801, 8801}, + {7753, 8805, 8805}, + {4783, 8809, 8810}, + {1673, 8814, 8815}, + {6623, 8819, 8819}, + {4404, 8823, 8823}, + {8089, 8827, 8828}, + {8773, 8832, 8832}, + {5394, 8836, 8836}, + {6231, 8841, 8843}, + {1015, 8852, 8853}, + {6873, 8857, 8857}, + {6289, 8865, 8865}, + {8577, 8869, 8869}, + {8114, 8873, 8875}, + {8534, 8883, 8883}, + {3007, 8887, 8888}, + {8827, 8892, 8893}, + {4788, 8897, 8900}, + {5698, 8906, 8907}, + {7690, 8911, 8911}, + {6643, 8919, 8919}, + {7206, 8923, 8924}, + {7866, 8929, 8931}, + {8880, 8942, 8942}, + {8630, 8951, 8952}, + {6027, 8958, 8958}, + {7749, 8966, 8967}, + {4932, 8972, 8973}, + {8892, 8980, 8981}, + {634, 9003, 9003}, + {8109, 9007, 9008}, + {8777, 9012, 9012}, + {3981, 9016, 9017}, + {5723, 9025, 9025}, + {7662, 9034, 9038}, + {8955, 9042, 9042}, + {8070, 9060, 9062}, + {8910, 9066, 9066}, + {5363, 9070, 9071}, + {7699, 9075, 9076}, + {8991, 9081, 9081}, + {6850, 9085, 9085}, + {5811, 9092, 9094}, + {9079, 9098, 9102}, + {6456, 9106, 9106}, + {2259, 9111, 9111}, + {4752, 9116, 9116}, + {9060, 9120, 9123}, + {8090, 9127, 9127}, + {5305, 9131, 9132}, + {8623, 9137, 9137}, + {7417, 9141, 9141}, + {6564, 9148, 9149}, + {9126, 9157, 9158}, + {4285, 9169, 9170}, + {8698, 9174, 9174}, + {8869, 9178, 9178}, + {2572, 9182, 9183}, + {6482, 9188, 9190}, + {9181, 9201, 9201}, + {2968, 9208, 9209}, + {2506, 9213, 9215}, + {9127, 9219, 9219}, + {7910, 9225, 9227}, + {5422, 9235, 9239}, + {8813, 9244, 9246}, + {9178, 9250, 9250}, + {8748, 9255, 9255}, + {7354, 9265, 9265}, + {7767, 9269, 9269}, + {7710, 9281, 9283}, + {8826, 9288, 9290}, + {861, 9295, 9295}, + {4482, 9301, 9301}, + {9264, 9305, 9306}, + {8805, 9310, 9310}, + {4995, 9314, 9314}, + {6730, 9318, 9318}, + {7457, 9328, 9328}, + {2547, 9335, 9336}, + {6298, 9340, 9343}, + {9305, 9353, 9354}, + {9269, 9358, 9358}, + {6338, 9370, 9370}, + {7289, 9376, 9379}, + {5780, 9383, 9383}, + {7607, 9387, 9387}, + {2065, 9392, 9392}, + {7238, 9396, 9396}, + {8856, 9400, 9400}, + {8069, 9412, 9413}, + {611, 9420, 9420}, + {7071, 9424, 9424}, + {3089, 9430, 9431}, + {7117, 9435, 9438}, + {1976, 9445, 9445}, + {6640, 9449, 9449}, + {5488, 9453, 9453}, + {8739, 9457, 9459}, + {5958, 9466, 9466}, + {7985, 9470, 9470}, + {8735, 9475, 9475}, + {5009, 9479, 9479}, + {8073, 9483, 9484}, + {2328, 9490, 9491}, + {9250, 9495, 9495}, + {4043, 9502, 9502}, + {7712, 9506, 9506}, + {9012, 9510, 9510}, + {9028, 9514, 9515}, + {2190, 9521, 9524}, + {9029, 9528, 9528}, + {9519, 9532, 9532}, + {9495, 9536, 9536}, + {8527, 9540, 9540}, + {2137, 9550, 9550}, + {8419, 9557, 9557}, + {9383, 9561, 9562}, + {8970, 9575, 9578}, + {8911, 9582, 9582}, + {7828, 9595, 9596}, + {6180, 9600, 9600}, + {8738, 9604, 9607}, + {7540, 9611, 9612}, + {9599, 9616, 9618}, + {9187, 9623, 9623}, + {9294, 9628, 9629}, + {4536, 9639, 9639}, + {3867, 9643, 9643}, + {6305, 9648, 9648}, + {1617, 9654, 9657}, + {5762, 9666, 9666}, + {8314, 9670, 9670}, + {9666, 9674, 9675}, + {9506, 9679, 9679}, + {9669, 9685, 9686}, + {9683, 9690, 9690}, + {8763, 9697, 9698}, + {7468, 9702, 9702}, + {460, 9707, 9707}, + {3115, 9712, 9712}, + {9424, 9716, 9717}, + {7359, 9721, 9724}, + {7547, 9728, 9729}, + {7151, 9733, 9738}, + {7627, 9742, 9742}, + {2822, 9747, 9747}, + {8247, 9751, 9753}, + {9550, 9758, 9758}, + {7585, 9762, 9763}, + {1002, 9767, 9767}, + {7168, 9772, 9773}, + {6941, 9777, 9780}, + {9728, 9784, 9786}, + {9770, 9792, 9796}, + {6411, 9801, 9802}, + {3689, 9806, 9808}, + {9575, 9814, 9816}, + {7025, 9820, 9821}, + {2776, 9826, 9826}, + {9806, 9830, 9830}, + {9820, 9834, 9835}, + {9800, 9839, 9847}, + {9834, 9851, 9852}, + {9829, 9856, 9862}, + {1400, 9866, 9866}, + {3197, 9870, 9871}, + {9851, 9875, 9876}, + {9742, 9883, 9884}, + {3362, 9888, 9889}, + {9883, 9893, 9893}, + {5711, 9899, 9910}, + {7806, 9915, 9915}, + {9120, 9919, 9919}, + {9715, 9925, 9934}, + {2580, 9938, 9938}, + {4907, 9942, 9944}, + {6239, 9953, 9954}, + {6961, 9963, 9963}, + {5295, 9967, 9968}, + {1915, 9972, 9973}, + {3426, 9983, 9985}, + {9875, 9994, 9995}, + {6942, 9999, 9999}, + {6621, 10005, 10005}, + {7589, 10010, 10012}, + {9286, 10020, 10020}, + {838, 10024, 10024}, + {9980, 10028, 10031}, + {9994, 10035, 10041}, + {2702, 10048, 10051}, + {2621, 10059, 10059}, + {10054, 10065, 10065}, + {8612, 10073, 10074}, + {7033, 10078, 10078}, + {916, 10082, 10082}, + {10035, 10086, 10087}, + {8613, 10097, 10097}, + {9919, 10107, 10108}, + {6133, 10114, 10115}, + {10059, 10119, 10119}, + {10065, 10126, 10127}, + {7732, 10131, 10131}, + {7155, 10135, 10136}, + {6728, 10140, 10140}, + {6162, 10144, 10145}, + {4724, 10150, 10150}, + {1665, 10154, 10154}, + {10126, 10163, 10163}, + {9783, 10168, 10168}, + {1715, 10172, 10173}, + {7152, 10177, 10182}, + {8760, 10187, 10187}, + {7829, 10191, 10191}, + {9679, 10196, 10196}, + {9369, 10201, 10201}, + {2928, 10206, 10208}, + {6951, 10214, 10217}, + {5633, 10221, 10221}, + {7199, 10225, 10225}, + {10118, 10230, 10231}, + {9999, 10235, 10236}, + {10045, 10240, 10249}, + {5565, 10256, 10256}, + {9866, 10261, 10261}, + {10163, 10268, 10268}, + {9869, 10272, 10272}, + {9789, 10276, 10283}, + {10235, 10287, 10288}, + {10214, 10298, 10299}, + {6971, 10303, 10303}, + {3346, 10307, 10307}, + {10185, 10311, 10312}, + {9993, 10318, 10320}, + {2779, 10332, 10334}, + {1726, 10338, 10338}, + {741, 10354, 10360}, + {10230, 10372, 10373}, + {10260, 10384, 10385}, + {10131, 10389, 10398}, + {6946, 10406, 10409}, + {10158, 10413, 10420}, + {10123, 10424, 10424}, + {6157, 10428, 10429}, + {4518, 10434, 10434}, + {9893, 10438, 10438}, + {9865, 10442, 10446}, + {7558, 10454, 10454}, + {10434, 10460, 10460}, + {10064, 10466, 10468}, + {2703, 10472, 10474}, + {9751, 10478, 10479}, + {6714, 10485, 10485}, + {8020, 10490, 10490}, + {10303, 10494, 10494}, + {3521, 10499, 10500}, + {9281, 10513, 10515}, + {6028, 10519, 10523}, + {9387, 10527, 10527}, + {7614, 10531, 10531}, + {3611, 10536, 10536}, + {9162, 10540, 10540}, + {10081, 10546, 10547}, + {10034, 10560, 10562}, + {6726, 10567, 10571}, + {8237, 10575, 10575}, + {10438, 10579, 10583}, + {10140, 10587, 10587}, + {5784, 10592, 10592}, + {9819, 10597, 10600}, + {10567, 10604, 10608}, + {9335, 10613, 10613}, + {8300, 10617, 10617}, + {10575, 10621, 10621}, + {9678, 10625, 10626}, + {9962, 10632, 10633}, + {10535, 10637, 10638}, + {8199, 10642, 10642}, + {10372, 10647, 10648}, + {10637, 10656, 10657}, + {10579, 10667, 10668}, + {10465, 10677, 10680}, + {6702, 10684, 10685}, + {10073, 10691, 10692}, + {4505, 10696, 10697}, + {9042, 10701, 10701}, + {6460, 10705, 10706}, + {10010, 10714, 10716}, + {10656, 10720, 10722}, + {7282, 10727, 10729}, + {2327, 10733, 10733}, + {2491, 10740, 10741}, + {10704, 10748, 10750}, + {6465, 10754, 10754}, + {10647, 10758, 10759}, + {10424, 10763, 10763}, + {10748, 10776, 10776}, + {10546, 10780, 10781}, + {10758, 10785, 10786}, + {10287, 10790, 10797}, + {10785, 10801, 10807}, + {10240, 10811, 10826}, + {9509, 10830, 10830}, + {2579, 10836, 10838}, + {9801, 10843, 10845}, + {7555, 10849, 10850}, + {10776, 10860, 10865}, + {8023, 10869, 10869}, + {10046, 10876, 10884}, + {10253, 10888, 10892}, + {9941, 10897, 10897}, + {7898, 10901, 10905}, + {6725, 10909, 10913}, + {10757, 10921, 10923}, + {10160, 10931, 10931}, + {10916, 10935, 10942}, + {10261, 10946, 10946}, + {10318, 10952, 10954}, + {5911, 10959, 10961}, + {10801, 10965, 10966}, + {10946, 10970, 10977}, + {10592, 10982, 10984}, + {9913, 10988, 10990}, + {8510, 10994, 10996}, + {9419, 11000, 11001}, + {6765, 11006, 11007}, + {10725, 11011, 11011}, + {5537, 11017, 11019}, + {9208, 11024, 11025}, + {5850, 11030, 11030}, + {9610, 11034, 11036}, + {8846, 11041, 11047}, + {9697, 11051, 11051}, + {1622, 11055, 11058}, + {2370, 11062, 11062}, + {8393, 11067, 11067}, + {9756, 11071, 11071}, + {10172, 11076, 11076}, + {27, 11081, 11081}, + {7357, 11087, 11092}, + {8151, 11104, 11106}, + {6115, 11110, 11110}, + {10667, 11114, 11115}, + {11099, 11121, 11123}, + {10705, 11127, 11127}, + {8938, 11131, 11131}, + {11114, 11135, 11136}, + {1390, 11140, 11141}, + {10964, 11146, 11148}, + {11140, 11152, 11155}, + {9813, 11159, 11166}, + {624, 11171, 11172}, + {3118, 11177, 11179}, + {11029, 11184, 11186}, + {10186, 11190, 11190}, + {10306, 11196, 11196}, + {8665, 11201, 11201}, + {7382, 11205, 11205}, + {1100, 11210, 11210}, + {2337, 11216, 11217}, + {1609, 11221, 11223}, + {5763, 11228, 11229}, + {5220, 11233, 11233}, + {11061, 11241, 11241}, + {10617, 11246, 11246}, + {11190, 11250, 11251}, + {10144, 11255, 11256}, + {11232, 11260, 11260}, + {857, 11264, 11265}, + {10994, 11269, 11271}, + {3879, 11280, 11281}, + {11184, 11287, 11289}, + {9611, 11293, 11295}, + {11250, 11299, 11299}, + {4495, 11304, 11304}, + {7574, 11308, 11309}, + {9814, 11315, 11317}, + {1713, 11321, 11324}, + {1905, 11328, 11328}, + {8745, 11335, 11340}, + {8883, 11351, 11351}, + {8119, 11358, 11358}, + {1842, 11363, 11364}, + {11237, 11368, 11368}, + {8814, 11373, 11374}, + {5684, 11378, 11378}, + {11011, 11382, 11382}, + {6520, 11389, 11389}, + {11183, 11393, 11396}, + {1790, 11404, 11404}, + {9536, 11408, 11408}, + {11298, 11418, 11419}, + {3929, 11425, 11425}, + {5588, 11429, 11429}, + {8476, 11436, 11436}, + {4096, 11440, 11442}, + {11084, 11446, 11454}, + {10603, 11458, 11463}, + {7332, 11472, 11474}, + {7611, 11483, 11486}, + {4836, 11490, 11491}, + {10024, 11495, 11495}, + {4917, 11501, 11506}, + {6486, 11510, 11512}, + {11269, 11516, 11518}, + {3603, 11522, 11525}, + {11126, 11535, 11535}, + {11418, 11539, 11541}, + {11408, 11545, 11545}, + {9021, 11549, 11552}, + {6745, 11557, 11557}, + {5118, 11561, 11564}, + {7590, 11568, 11569}, + {4426, 11573, 11578}, + {9790, 11582, 11583}, + {6447, 11587, 11587}, + {10229, 11591, 11594}, + {10457, 11598, 11598}, + {10168, 11604, 11604}, + {10543, 11608, 11608}, + {7404, 11612, 11612}, + {11127, 11616, 11616}, + {3337, 11620, 11620}, + {11501, 11624, 11628}, + {4543, 11633, 11635}, + {8449, 11642, 11642}, + {4943, 11646, 11648}, + {10526, 11652, 11654}, + {11620, 11659, 11659}, + {8927, 11664, 11669}, + {532, 11673, 11673}, + {10513, 11677, 11679}, + {10428, 11683, 11683}, + {10999, 11689, 11690}, + {9469, 11695, 11695}, + {3606, 11699, 11699}, + {9560, 11708, 11709}, + {1564, 11714, 11714}, + {10527, 11718, 11718}, + {3071, 11723, 11726}, + {11590, 11731, 11732}, + {6605, 11737, 11737}, + {11624, 11741, 11745}, + {7822, 11749, 11752}, + {5269, 11757, 11758}, + {1339, 11767, 11767}, + {1363, 11771, 11773}, + {3704, 11777, 11777}, + {10952, 11781, 11783}, + {6764, 11793, 11795}, + {8675, 11800, 11800}, + {9963, 11804, 11804}, + {11573, 11808, 11809}, + {9548, 11813, 11813}, + {11591, 11817, 11818}, + {11446, 11822, 11822}, + {9224, 11828, 11828}, + {3158, 11836, 11836}, + {10830, 11840, 11840}, + {7234, 11846, 11846}, + {11299, 11850, 11850}, + {11544, 11854, 11855}, + {11498, 11859, 11859}, + {10993, 11865, 11868}, + {9720, 11872, 11878}, + {10489, 11882, 11890}, + {11712, 11898, 11904}, + {11516, 11908, 11910}, + {11568, 11914, 11915}, + {10177, 11919, 11924}, + {11363, 11928, 11929}, + {10494, 11933, 11933}, + {9870, 11937, 11938}, + {9427, 11942, 11942}, + {11481, 11949, 11949}, + {6030, 11955, 11957}, + {11718, 11961, 11961}, + {10531, 11965, 11983}, + {5126, 11987, 11987}, + {7515, 11991, 11991}, + {10646, 11996, 11997}, + {2947, 12001, 12001}, + {9582, 12009, 12010}, + {6202, 12017, 12018}, + {11714, 12022, 12022}, + {9235, 12033, 12037}, + {9721, 12041, 12044}, + {11932, 12051, 12052}, + {12040, 12056, 12056}, + {12051, 12060, 12060}, + {11601, 12066, 12066}, + {8426, 12070, 12070}, + {4053, 12077, 12077}, + {4262, 12081, 12081}, + {9761, 12086, 12088}, + {11582, 12092, 12093}, + {10965, 12097, 12098}, + {11803, 12103, 12104}, + {11933, 12108, 12109}, + {10688, 12117, 12117}, + {12107, 12125, 12126}, + {6774, 12130, 12132}, + {6286, 12137, 12137}, + {9543, 12141, 12141}, + {12097, 12145, 12146}, + {10790, 12150, 12150}, + {10125, 12154, 12156}, + {12125, 12164, 12164}, + {12064, 12168, 12172}, + {10811, 12178, 12188}, + {12092, 12192, 12193}, + {10058, 12197, 12198}, + {11611, 12211, 12212}, + {3459, 12216, 12216}, + {10291, 12225, 12228}, + {12191, 12232, 12234}, + {12145, 12238, 12238}, + {12001, 12242, 12250}, + {3840, 12255, 12255}, + {12216, 12259, 12259}, + {674, 12272, 12272}, + {12141, 12276, 12276}, + {10766, 12280, 12280}, + {11545, 12284, 12284}, + {6496, 12290, 12290}, + {11381, 12294, 12295}, + {603, 12302, 12303}, + {12276, 12308, 12308}, + {11850, 12313, 12314}, + {565, 12319, 12319}, + {9351, 12324, 12324}, + {11822, 12328, 12328}, + {2691, 12333, 12334}, + {11840, 12338, 12338}, + {11070, 12343, 12343}, + {9510, 12347, 12347}, + {11024, 12352, 12353}, + {7173, 12359, 12359}, + {517, 12363, 12363}, + {6311, 12367, 12368}, + {11367, 12372, 12373}, + {12008, 12377, 12377}, + {11372, 12382, 12384}, + {11358, 12391, 12392}, + {11382, 12396, 12396}, + {6882, 12400, 12401}, + {11246, 12405, 12405}, + {8359, 12409, 12412}, + {10154, 12418, 12418}, + {12016, 12425, 12426}, + {8972, 12434, 12435}, + {10478, 12439, 12440}, + {12395, 12449, 12449}, + {11612, 12454, 12454}, + {12347, 12458, 12458}, + {10700, 12466, 12467}, + {3637, 12471, 12476}, + {1042, 12480, 12481}, + {6747, 12488, 12488}, + {12396, 12492, 12493}, + {9420, 12497, 12497}, + {11285, 12501, 12510}, + {4470, 12515, 12515}, + {9374, 12519, 12519}, + {11293, 12528, 12528}, + {2058, 12534, 12535}, + {6521, 12539, 12539}, + {12492, 12543, 12543}, + {3043, 12547, 12547}, + {2982, 12551, 12553}, + {11030, 12557, 12563}, + {7636, 12568, 12568}, + {9639, 12572, 12572}, + {12543, 12576, 12576}, + {5989, 12580, 12583}, + {11051, 12587, 12587}, + {1061, 12592, 12594}, + {12313, 12599, 12601}, + {11846, 12605, 12605}, + {12576, 12609, 12609}, + {11040, 12618, 12625}, + {12479, 12629, 12629}, + {6903, 12633, 12633}, + {12322, 12639, 12639}, + {12253, 12643, 12645}, + {5594, 12651, 12651}, + {12522, 12655, 12655}, + {11703, 12659, 12659}, + {1377, 12665, 12665}, + {8022, 12669, 12669}, + {12280, 12674, 12674}, + {9023, 12680, 12681}, + {12328, 12685, 12685}, + {3085, 12689, 12693}, + {4700, 12698, 12698}, + {10224, 12702, 12702}, + {8781, 12706, 12706}, + {1651, 12710, 12710}, + {12458, 12714, 12714}, + {12005, 12718, 12721}, + {11908, 12725, 12726}, + {8202, 12733, 12733}, + {11708, 12739, 12740}, + {12599, 12744, 12745}, + {12284, 12749, 12749}, + {5285, 12756, 12756}, + {12055, 12775, 12777}, + {6919, 12782, 12782}, + {12242, 12786, 12786}, + {12009, 12790, 12790}, + {9628, 12794, 12796}, + {11354, 12801, 12802}, + {10225, 12806, 12807}, + {579, 12813, 12813}, + {8935, 12817, 12822}, + {8753, 12827, 12829}, + {11006, 12835, 12835}, + {858, 12841, 12845}, + {476, 12849, 12849}, + {7667, 12854, 12854}, + {12760, 12860, 12871}, + {11677, 12875, 12877}, + {12714, 12881, 12881}, + {12731, 12885, 12890}, + {7108, 12894, 12896}, + {1165, 12900, 12900}, + {4021, 12906, 12906}, + {10829, 12910, 12911}, + {12331, 12915, 12915}, + {8887, 12919, 12921}, + {11639, 12925, 12925}, + {7964, 12929, 12929}, + {12528, 12937, 12937}, + {8148, 12941, 12941}, + {12770, 12948, 12950}, + {12609, 12954, 12954}, + {12685, 12958, 12958}, + {2803, 12962, 12962}, + {9561, 12966, 12966}, + {6671, 12972, 12973}, + {12056, 12977, 12977}, + {6380, 12981, 12981}, + {12048, 12985, 12985}, + {11961, 12989, 12993}, + {3368, 12997, 12999}, + {6634, 13004, 13004}, + {6775, 13009, 13010}, + {12136, 13014, 13019}, + {10341, 13023, 13023}, + {13002, 13027, 13027}, + {10587, 13031, 13031}, + {10307, 13035, 13035}, + {12736, 13039, 13039}, + {12744, 13043, 13044}, + {6175, 13048, 13048}, + {9702, 13053, 13054}, + {662, 13059, 13061}, + {12718, 13065, 13068}, + {12893, 13072, 13075}, + {8299, 13086, 13091}, + {12604, 13095, 13096}, + {12848, 13100, 13101}, + {12749, 13105, 13105}, + {12526, 13109, 13114}, + {9173, 13122, 13122}, + {12769, 13128, 13128}, + {13038, 13132, 13132}, + {12725, 13136, 13137}, + {12639, 13146, 13146}, + {9711, 13150, 13151}, + {12137, 13155, 13155}, + {13039, 13159, 13159}, + {4681, 13163, 13164}, + {12954, 13168, 13168}, + {13158, 13175, 13176}, + {13105, 13180, 13180}, + {10754, 13184, 13184}, + {13167, 13188, 13188}, + {12658, 13192, 13192}, + {4294, 13199, 13200}, + {11682, 13204, 13205}, + {11695, 13209, 13209}, + {11076, 13214, 13214}, + {12232, 13218, 13218}, + {9399, 13223, 13224}, + {12880, 13228, 13229}, + {13048, 13234, 13234}, + {9701, 13238, 13239}, + {13209, 13243, 13243}, + {3658, 13248, 13248}, + {3698, 13252, 13254}, + {12237, 13260, 13260}, + {8872, 13266, 13266}, + {12957, 13272, 13273}, + {1393, 13281, 13281}, + {2013, 13285, 13288}, + {4244, 13296, 13299}, + {9428, 13303, 13303}, + {12702, 13307, 13307}, + {13078, 13311, 13311}, + {6071, 13315, 13315}, + {3061, 13319, 13319}, + {2051, 13324, 13324}, + {11560, 13328, 13331}, + {6584, 13336, 13336}, + {8482, 13340, 13340}, + {5331, 13344, 13344}, + {4171, 13348, 13348}, + {8501, 13352, 13352}, + {9219, 13356, 13356}, + {9473, 13360, 13363}, + {12881, 13367, 13367}, + {13065, 13371, 13375}, + {2979, 13379, 13384}, + {1518, 13388, 13388}, + {11177, 13392, 13392}, + {9457, 13398, 13398}, + {12293, 13407, 13410}, + {3697, 13414, 13417}, + {10338, 13425, 13425}, + {13367, 13429, 13429}, + {11074, 13433, 13437}, + {4201, 13441, 13443}, + {1812, 13447, 13448}, + {13360, 13452, 13456}, + {13188, 13463, 13463}, + {9732, 13470, 13470}, + {11332, 13477, 13477}, + {9918, 13487, 13487}, + {6337, 13497, 13497}, + {13429, 13501, 13501}, + {11413, 13505, 13505}, + {4685, 13512, 13513}, + {13136, 13517, 13519}, + {7416, 13528, 13530}, + {12929, 13534, 13534}, + {11110, 13539, 13539}, + {11521, 13543, 13543}, + {12825, 13553, 13553}, + {13447, 13557, 13558}, + {12299, 13562, 13563}, + {9003, 13570, 13570}, + {12500, 13577, 13577}, + {13501, 13581, 13581}, + {9392, 13586, 13586}, + {12454, 13590, 13590}, + {6189, 13595, 13595}, + {13053, 13599, 13599}, + {11881, 13604, 13604}, + {13159, 13608, 13608}, + {4894, 13612, 13612}, + {13221, 13621, 13621}, + {8950, 13625, 13625}, + {13533, 13629, 13629}, + {9633, 13633, 13633}, + {7892, 13637, 13639}, + {13581, 13643, 13643}, + {13616, 13647, 13649}, + {12794, 13653, 13654}, + {8919, 13659, 13659}, + {9674, 13663, 13663}, + {13577, 13668, 13668}, + {12966, 13672, 13672}, + {12659, 13676, 13683}, + {6124, 13688, 13688}, + {9225, 13693, 13695}, + {11833, 13702, 13702}, + {12904, 13709, 13717}, + {13647, 13721, 13722}, + {11687, 13726, 13727}, + {12434, 13731, 13732}, + {12689, 13736, 13742}, + {13168, 13746, 13746}, + {6151, 13751, 13752}, + {11821, 13756, 13757}, + {6467, 13764, 13764}, + {5730, 13769, 13769}, + {5136, 13780, 13780}, + {724, 13784, 13785}, + {13517, 13789, 13791}, + {640, 13795, 13796}, + {7721, 13800, 13802}, + {11121, 13806, 13807}, + {5791, 13811, 13815}, + {12894, 13819, 13819}, + {11100, 13824, 13824}, + {7011, 13830, 13830}, + {7129, 13834, 13837}, + {13833, 13841, 13841}, + {11276, 13847, 13847}, + {13621, 13853, 13853}, + {13589, 13862, 13863}, + {12989, 13867, 13867}, + {12789, 13871, 13871}, + {1239, 13875, 13875}, + {4675, 13879, 13881}, + {4686, 13885, 13885}, + {707, 13889, 13889}, + {5449, 13897, 13898}, + {13867, 13902, 13903}, + {10613, 13908, 13908}, + {13789, 13912, 13914}, + {4451, 13918, 13919}, + {9200, 13924, 13924}, + {2011, 13930, 13930}, + {11433, 13934, 13936}, + {4695, 13942, 13943}, + {9435, 13948, 13951}, + {13688, 13955, 13957}, + {11694, 13961, 13962}, + {5712, 13966, 13966}, + {5991, 13970, 13972}, + {13477, 13976, 13976}, + {10213, 13987, 13987}, + {11839, 13991, 13993}, + {12272, 13997, 13997}, + {6206, 14001, 14001}, + {13179, 14006, 14007}, + {2939, 14011, 14011}, + {12972, 14016, 14017}, + {13918, 14021, 14022}, + {7436, 14026, 14027}, + {7678, 14032, 14034}, + {13586, 14040, 14040}, + {13347, 14044, 14044}, + {13109, 14048, 14051}, + {9244, 14055, 14057}, + {13315, 14061, 14061}, + {13276, 14067, 14067}, + {11435, 14073, 14074}, + {13853, 14078, 14078}, + {13452, 14082, 14082}, + {14044, 14087, 14087}, + {4440, 14091, 14095}, + {4479, 14100, 14103}, + {9395, 14107, 14109}, + {6834, 14119, 14119}, + {10458, 14123, 14124}, + {1429, 14129, 14129}, + {8443, 14135, 14135}, + {10365, 14140, 14140}, + {5267, 14145, 14145}, + {11834, 14151, 14153}, +} diff --git a/vendor/src/github.com/golang/snappy/snappy.go b/vendor/src/github.com/golang/snappy/snappy.go new file mode 100644 index 00000000..0cf5e379 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/snappy.go @@ -0,0 +1,87 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package snappy implements the snappy block-based compression format. +// It aims for very high speeds and reasonable compression. +// +// The C++ snappy implementation is at https://github.com/google/snappy +package snappy // import "github.com/golang/snappy" + +import ( + "hash/crc32" +) + +/* +Each encoded block begins with the varint-encoded length of the decoded data, +followed by a sequence of chunks. Chunks begin and end on byte boundaries. The +first byte of each chunk is broken into its 2 least and 6 most significant bits +called l and m: l ranges in [0, 4) and m ranges in [0, 64). l is the chunk tag. +Zero means a literal tag. All other values mean a copy tag. + +For literal tags: + - If m < 60, the next 1 + m bytes are literal bytes. + - Otherwise, let n be the little-endian unsigned integer denoted by the next + m - 59 bytes. The next 1 + n bytes after that are literal bytes. + +For copy tags, length bytes are copied from offset bytes ago, in the style of +Lempel-Ziv compression algorithms. In particular: + - For l == 1, the offset ranges in [0, 1<<11) and the length in [4, 12). + The length is 4 + the low 3 bits of m. The high 3 bits of m form bits 8-10 + of the offset. The next byte is bits 0-7 of the offset. + - For l == 2, the offset ranges in [0, 1<<16) and the length in [1, 65). + The length is 1 + m. The offset is the little-endian unsigned integer + denoted by the next 2 bytes. + - For l == 3, this tag is a legacy format that is no longer issued by most + encoders. Nonetheless, the offset ranges in [0, 1<<32) and the length in + [1, 65). The length is 1 + m. The offset is the little-endian unsigned + integer denoted by the next 4 bytes. +*/ +const ( + tagLiteral = 0x00 + tagCopy1 = 0x01 + tagCopy2 = 0x02 + tagCopy4 = 0x03 +) + +const ( + checksumSize = 4 + chunkHeaderSize = 4 + magicChunk = "\xff\x06\x00\x00" + magicBody + magicBody = "sNaPpY" + + // maxBlockSize is the maximum size of the input to encodeBlock. It is not + // part of the wire format per se, but some parts of the encoder assume + // that an offset fits into a uint16. + // + // Also, for the framing format (Writer type instead of Encode function), + // https://github.com/google/snappy/blob/master/framing_format.txt says + // that "the uncompressed data in a chunk must be no longer than 65536 + // bytes". + maxBlockSize = 65536 + + // maxEncodedLenOfMaxBlockSize equals MaxEncodedLen(maxBlockSize), but is + // hard coded to be a const instead of a variable, so that obufLen can also + // be a const. Their equivalence is confirmed by + // TestMaxEncodedLenOfMaxBlockSize. + maxEncodedLenOfMaxBlockSize = 76490 + + obufHeaderLen = len(magicChunk) + checksumSize + chunkHeaderSize + obufLen = obufHeaderLen + maxEncodedLenOfMaxBlockSize +) + +const ( + chunkTypeCompressedData = 0x00 + chunkTypeUncompressedData = 0x01 + chunkTypePadding = 0xfe + chunkTypeStreamIdentifier = 0xff +) + +var crcTable = crc32.MakeTable(crc32.Castagnoli) + +// crc implements the checksum specified in section 3 of +// https://github.com/google/snappy/blob/master/framing_format.txt +func crc(b []byte) uint32 { + c := crc32.Update(0, crcTable, b) + return uint32(c>>15|c<<17) + 0xa282ead8 +} diff --git a/vendor/src/github.com/golang/snappy/snappy_test.go b/vendor/src/github.com/golang/snappy/snappy_test.go new file mode 100644 index 00000000..2712710d --- /dev/null +++ b/vendor/src/github.com/golang/snappy/snappy_test.go @@ -0,0 +1,1353 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package snappy + +import ( + "bytes" + "encoding/binary" + "flag" + "fmt" + "io" + "io/ioutil" + "math/rand" + "net/http" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" +) + +var ( + download = flag.Bool("download", false, "If true, download any missing files before running benchmarks") + testdataDir = flag.String("testdataDir", "testdata", "Directory containing the test data") + benchdataDir = flag.String("benchdataDir", "testdata/bench", "Directory containing the benchmark data") +) + +// goEncoderShouldMatchCppEncoder is whether to test that the algorithm used by +// Go's encoder matches byte-for-byte what the C++ snappy encoder produces, on +// this GOARCH. There is more than one valid encoding of any given input, and +// there is more than one good algorithm along the frontier of trading off +// throughput for output size. Nonetheless, we presume that the C++ encoder's +// algorithm is a good one and has been tested on a wide range of inputs, so +// matching that exactly should mean that the Go encoder's algorithm is also +// good, without needing to gather our own corpus of test data. +// +// The exact algorithm used by the C++ code is potentially endian dependent, as +// it puns a byte pointer to a uint32 pointer to load, hash and compare 4 bytes +// at a time. The Go implementation is endian agnostic, in that its output is +// the same (as little-endian C++ code), regardless of the CPU's endianness. +// +// Thus, when comparing Go's output to C++ output generated beforehand, such as +// the "testdata/pi.txt.rawsnappy" file generated by C++ code on a little- +// endian system, we can run that test regardless of the runtime.GOARCH value. +// +// When comparing Go's output to dynamically generated C++ output, i.e. the +// result of fork/exec'ing a C++ program, we can run that test only on +// little-endian systems, because the C++ output might be different on +// big-endian systems. The runtime package doesn't export endianness per se, +// but we can restrict this match-C++ test to common little-endian systems. +const goEncoderShouldMatchCppEncoder = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "arm" + +func TestMaxEncodedLenOfMaxBlockSize(t *testing.T) { + got := maxEncodedLenOfMaxBlockSize + want := MaxEncodedLen(maxBlockSize) + if got != want { + t.Fatalf("got %d, want %d", got, want) + } +} + +func cmp(a, b []byte) error { + if bytes.Equal(a, b) { + return nil + } + if len(a) != len(b) { + return fmt.Errorf("got %d bytes, want %d", len(a), len(b)) + } + for i := range a { + if a[i] != b[i] { + return fmt.Errorf("byte #%d: got 0x%02x, want 0x%02x", i, a[i], b[i]) + } + } + return nil +} + +func roundtrip(b, ebuf, dbuf []byte) error { + d, err := Decode(dbuf, Encode(ebuf, b)) + if err != nil { + return fmt.Errorf("decoding error: %v", err) + } + if err := cmp(d, b); err != nil { + return fmt.Errorf("roundtrip mismatch: %v", err) + } + return nil +} + +func TestEmpty(t *testing.T) { + if err := roundtrip(nil, nil, nil); err != nil { + t.Fatal(err) + } +} + +func TestSmallCopy(t *testing.T) { + for _, ebuf := range [][]byte{nil, make([]byte, 20), make([]byte, 64)} { + for _, dbuf := range [][]byte{nil, make([]byte, 20), make([]byte, 64)} { + for i := 0; i < 32; i++ { + s := "aaaa" + strings.Repeat("b", i) + "aaaabbbb" + if err := roundtrip([]byte(s), ebuf, dbuf); err != nil { + t.Errorf("len(ebuf)=%d, len(dbuf)=%d, i=%d: %v", len(ebuf), len(dbuf), i, err) + } + } + } + } +} + +func TestSmallRand(t *testing.T) { + rng := rand.New(rand.NewSource(1)) + for n := 1; n < 20000; n += 23 { + b := make([]byte, n) + for i := range b { + b[i] = uint8(rng.Intn(256)) + } + if err := roundtrip(b, nil, nil); err != nil { + t.Fatal(err) + } + } +} + +func TestSmallRegular(t *testing.T) { + for n := 1; n < 20000; n += 23 { + b := make([]byte, n) + for i := range b { + b[i] = uint8(i%10 + 'a') + } + if err := roundtrip(b, nil, nil); err != nil { + t.Fatal(err) + } + } +} + +func TestInvalidVarint(t *testing.T) { + testCases := []struct { + desc string + input string + }{{ + "invalid varint, final byte has continuation bit set", + "\xff", + }, { + "invalid varint, value overflows uint64", + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00", + }, { + // https://github.com/google/snappy/blob/master/format_description.txt + // says that "the stream starts with the uncompressed length [as a + // varint] (up to a maximum of 2^32 - 1)". + "valid varint (as uint64), but value overflows uint32", + "\x80\x80\x80\x80\x10", + }} + + for _, tc := range testCases { + input := []byte(tc.input) + if _, err := DecodedLen(input); err != ErrCorrupt { + t.Errorf("%s: DecodedLen: got %v, want ErrCorrupt", tc.desc, err) + } + if _, err := Decode(nil, input); err != ErrCorrupt { + t.Errorf("%s: Decode: got %v, want ErrCorrupt", tc.desc, err) + } + } +} + +func TestDecode(t *testing.T) { + lit40Bytes := make([]byte, 40) + for i := range lit40Bytes { + lit40Bytes[i] = byte(i) + } + lit40 := string(lit40Bytes) + + testCases := []struct { + desc string + input string + want string + wantErr error + }{{ + `decodedLen=0; valid input`, + "\x00", + "", + nil, + }, { + `decodedLen=3; tagLiteral, 0-byte length; length=3; valid input`, + "\x03" + "\x08\xff\xff\xff", + "\xff\xff\xff", + nil, + }, { + `decodedLen=2; tagLiteral, 0-byte length; length=3; not enough dst bytes`, + "\x02" + "\x08\xff\xff\xff", + "", + ErrCorrupt, + }, { + `decodedLen=3; tagLiteral, 0-byte length; length=3; not enough src bytes`, + "\x03" + "\x08\xff\xff", + "", + ErrCorrupt, + }, { + `decodedLen=40; tagLiteral, 0-byte length; length=40; valid input`, + "\x28" + "\x9c" + lit40, + lit40, + nil, + }, { + `decodedLen=1; tagLiteral, 1-byte length; not enough length bytes`, + "\x01" + "\xf0", + "", + ErrCorrupt, + }, { + `decodedLen=3; tagLiteral, 1-byte length; length=3; valid input`, + "\x03" + "\xf0\x02\xff\xff\xff", + "\xff\xff\xff", + nil, + }, { + `decodedLen=1; tagLiteral, 2-byte length; not enough length bytes`, + "\x01" + "\xf4\x00", + "", + ErrCorrupt, + }, { + `decodedLen=3; tagLiteral, 2-byte length; length=3; valid input`, + "\x03" + "\xf4\x02\x00\xff\xff\xff", + "\xff\xff\xff", + nil, + }, { + `decodedLen=1; tagLiteral, 3-byte length; not enough length bytes`, + "\x01" + "\xf8\x00\x00", + "", + ErrCorrupt, + }, { + `decodedLen=3; tagLiteral, 3-byte length; length=3; valid input`, + "\x03" + "\xf8\x02\x00\x00\xff\xff\xff", + "\xff\xff\xff", + nil, + }, { + `decodedLen=1; tagLiteral, 4-byte length; not enough length bytes`, + "\x01" + "\xfc\x00\x00\x00", + "", + ErrCorrupt, + }, { + `decodedLen=1; tagLiteral, 4-byte length; length=3; not enough dst bytes`, + "\x01" + "\xfc\x02\x00\x00\x00\xff\xff\xff", + "", + ErrCorrupt, + }, { + `decodedLen=4; tagLiteral, 4-byte length; length=3; not enough src bytes`, + "\x04" + "\xfc\x02\x00\x00\x00\xff", + "", + ErrCorrupt, + }, { + `decodedLen=3; tagLiteral, 4-byte length; length=3; valid input`, + "\x03" + "\xfc\x02\x00\x00\x00\xff\xff\xff", + "\xff\xff\xff", + nil, + }, { + `decodedLen=4; tagCopy1, 1 extra length|offset byte; not enough extra bytes`, + "\x04" + "\x01", + "", + ErrCorrupt, + }, { + `decodedLen=4; tagCopy2, 2 extra length|offset bytes; not enough extra bytes`, + "\x04" + "\x02\x00", + "", + ErrCorrupt, + }, { + `decodedLen=4; tagCopy4, 4 extra length|offset bytes; not enough extra bytes`, + "\x04" + "\x03\x00\x00\x00", + "", + ErrCorrupt, + }, { + `decodedLen=4; tagLiteral (4 bytes "abcd"); valid input`, + "\x04" + "\x0cabcd", + "abcd", + nil, + }, { + `decodedLen=13; tagLiteral (4 bytes "abcd"); tagCopy1; length=9 offset=4; valid input`, + "\x0d" + "\x0cabcd" + "\x15\x04", + "abcdabcdabcda", + nil, + }, { + `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=4; valid input`, + "\x08" + "\x0cabcd" + "\x01\x04", + "abcdabcd", + nil, + }, { + `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=2; valid input`, + "\x08" + "\x0cabcd" + "\x01\x02", + "abcdcdcd", + nil, + }, { + `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=1; valid input`, + "\x08" + "\x0cabcd" + "\x01\x01", + "abcddddd", + nil, + }, { + `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=0; zero offset`, + "\x08" + "\x0cabcd" + "\x01\x00", + "", + ErrCorrupt, + }, { + `decodedLen=9; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=4; inconsistent dLen`, + "\x09" + "\x0cabcd" + "\x01\x04", + "", + ErrCorrupt, + }, { + `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=5; offset too large`, + "\x08" + "\x0cabcd" + "\x01\x05", + "", + ErrCorrupt, + }, { + `decodedLen=7; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=4; length too large`, + "\x07" + "\x0cabcd" + "\x01\x04", + "", + ErrCorrupt, + }, { + `decodedLen=6; tagLiteral (4 bytes "abcd"); tagCopy2; length=2 offset=3; valid input`, + "\x06" + "\x0cabcd" + "\x06\x03\x00", + "abcdbc", + nil, + }, { + `decodedLen=6; tagLiteral (4 bytes "abcd"); tagCopy4; length=2 offset=3; valid input`, + "\x06" + "\x0cabcd" + "\x07\x03\x00\x00\x00", + "abcdbc", + nil, + }} + + const ( + // notPresentXxx defines a range of byte values [0xa0, 0xc5) that are + // not present in either the input or the output. It is written to dBuf + // to check that Decode does not write bytes past the end of + // dBuf[:dLen]. + // + // The magic number 37 was chosen because it is prime. A more 'natural' + // number like 32 might lead to a false negative if, for example, a + // byte was incorrectly copied 4*8 bytes later. + notPresentBase = 0xa0 + notPresentLen = 37 + ) + + var dBuf [100]byte +loop: + for i, tc := range testCases { + input := []byte(tc.input) + for _, x := range input { + if notPresentBase <= x && x < notPresentBase+notPresentLen { + t.Errorf("#%d (%s): input shouldn't contain %#02x\ninput: % x", i, tc.desc, x, input) + continue loop + } + } + + dLen, n := binary.Uvarint(input) + if n <= 0 { + t.Errorf("#%d (%s): invalid varint-encoded dLen", i, tc.desc) + continue + } + if dLen > uint64(len(dBuf)) { + t.Errorf("#%d (%s): dLen %d is too large", i, tc.desc, dLen) + continue + } + + for j := range dBuf { + dBuf[j] = byte(notPresentBase + j%notPresentLen) + } + g, gotErr := Decode(dBuf[:], input) + if got := string(g); got != tc.want || gotErr != tc.wantErr { + t.Errorf("#%d (%s):\ngot %q, %v\nwant %q, %v", + i, tc.desc, got, gotErr, tc.want, tc.wantErr) + continue + } + for j, x := range dBuf { + if uint64(j) < dLen { + continue + } + if w := byte(notPresentBase + j%notPresentLen); x != w { + t.Errorf("#%d (%s): Decode overrun: dBuf[%d] was modified: got %#02x, want %#02x\ndBuf: % x", + i, tc.desc, j, x, w, dBuf) + continue loop + } + } + } +} + +func TestDecodeCopy4(t *testing.T) { + dots := strings.Repeat(".", 65536) + + input := strings.Join([]string{ + "\x89\x80\x04", // decodedLen = 65545. + "\x0cpqrs", // 4-byte literal "pqrs". + "\xf4\xff\xff" + dots, // 65536-byte literal dots. + "\x13\x04\x00\x01\x00", // tagCopy4; length=5 offset=65540. + }, "") + + gotBytes, err := Decode(nil, []byte(input)) + if err != nil { + t.Fatal(err) + } + got := string(gotBytes) + want := "pqrs" + dots + "pqrs." + if len(got) != len(want) { + t.Fatalf("got %d bytes, want %d", len(got), len(want)) + } + if got != want { + for i := 0; i < len(got); i++ { + if g, w := got[i], want[i]; g != w { + t.Fatalf("byte #%d: got %#02x, want %#02x", i, g, w) + } + } + } +} + +// TestDecodeLengthOffset tests decoding an encoding of the form literal + +// copy-length-offset + literal. For example: "abcdefghijkl" + "efghij" + "AB". +func TestDecodeLengthOffset(t *testing.T) { + const ( + prefix = "abcdefghijklmnopqr" + suffix = "ABCDEFGHIJKLMNOPQR" + + // notPresentXxx defines a range of byte values [0xa0, 0xc5) that are + // not present in either the input or the output. It is written to + // gotBuf to check that Decode does not write bytes past the end of + // gotBuf[:totalLen]. + // + // The magic number 37 was chosen because it is prime. A more 'natural' + // number like 32 might lead to a false negative if, for example, a + // byte was incorrectly copied 4*8 bytes later. + notPresentBase = 0xa0 + notPresentLen = 37 + ) + var gotBuf, wantBuf, inputBuf [128]byte + for length := 1; length <= 18; length++ { + for offset := 1; offset <= 18; offset++ { + loop: + for suffixLen := 0; suffixLen <= 18; suffixLen++ { + totalLen := len(prefix) + length + suffixLen + + inputLen := binary.PutUvarint(inputBuf[:], uint64(totalLen)) + inputBuf[inputLen] = tagLiteral + 4*byte(len(prefix)-1) + inputLen++ + inputLen += copy(inputBuf[inputLen:], prefix) + inputBuf[inputLen+0] = tagCopy2 + 4*byte(length-1) + inputBuf[inputLen+1] = byte(offset) + inputBuf[inputLen+2] = 0x00 + inputLen += 3 + if suffixLen > 0 { + inputBuf[inputLen] = tagLiteral + 4*byte(suffixLen-1) + inputLen++ + inputLen += copy(inputBuf[inputLen:], suffix[:suffixLen]) + } + input := inputBuf[:inputLen] + + for i := range gotBuf { + gotBuf[i] = byte(notPresentBase + i%notPresentLen) + } + got, err := Decode(gotBuf[:], input) + if err != nil { + t.Errorf("length=%d, offset=%d; suffixLen=%d: %v", length, offset, suffixLen, err) + continue + } + + wantLen := 0 + wantLen += copy(wantBuf[wantLen:], prefix) + for i := 0; i < length; i++ { + wantBuf[wantLen] = wantBuf[wantLen-offset] + wantLen++ + } + wantLen += copy(wantBuf[wantLen:], suffix[:suffixLen]) + want := wantBuf[:wantLen] + + for _, x := range input { + if notPresentBase <= x && x < notPresentBase+notPresentLen { + t.Errorf("length=%d, offset=%d; suffixLen=%d: input shouldn't contain %#02x\ninput: % x", + length, offset, suffixLen, x, input) + continue loop + } + } + for i, x := range gotBuf { + if i < totalLen { + continue + } + if w := byte(notPresentBase + i%notPresentLen); x != w { + t.Errorf("length=%d, offset=%d; suffixLen=%d; totalLen=%d: "+ + "Decode overrun: gotBuf[%d] was modified: got %#02x, want %#02x\ngotBuf: % x", + length, offset, suffixLen, totalLen, i, x, w, gotBuf) + continue loop + } + } + for _, x := range want { + if notPresentBase <= x && x < notPresentBase+notPresentLen { + t.Errorf("length=%d, offset=%d; suffixLen=%d: want shouldn't contain %#02x\nwant: % x", + length, offset, suffixLen, x, want) + continue loop + } + } + + if !bytes.Equal(got, want) { + t.Errorf("length=%d, offset=%d; suffixLen=%d:\ninput % x\ngot % x\nwant % x", + length, offset, suffixLen, input, got, want) + continue + } + } + } + } +} + +const ( + goldenText = "Mark.Twain-Tom.Sawyer.txt" + goldenCompressed = goldenText + ".rawsnappy" +) + +func TestDecodeGoldenInput(t *testing.T) { + tDir := filepath.FromSlash(*testdataDir) + src, err := ioutil.ReadFile(filepath.Join(tDir, goldenCompressed)) + if err != nil { + t.Fatalf("ReadFile: %v", err) + } + got, err := Decode(nil, src) + if err != nil { + t.Fatalf("Decode: %v", err) + } + want, err := ioutil.ReadFile(filepath.Join(tDir, goldenText)) + if err != nil { + t.Fatalf("ReadFile: %v", err) + } + if err := cmp(got, want); err != nil { + t.Fatal(err) + } +} + +func TestEncodeGoldenInput(t *testing.T) { + tDir := filepath.FromSlash(*testdataDir) + src, err := ioutil.ReadFile(filepath.Join(tDir, goldenText)) + if err != nil { + t.Fatalf("ReadFile: %v", err) + } + got := Encode(nil, src) + want, err := ioutil.ReadFile(filepath.Join(tDir, goldenCompressed)) + if err != nil { + t.Fatalf("ReadFile: %v", err) + } + if err := cmp(got, want); err != nil { + t.Fatal(err) + } +} + +func TestExtendMatchGoldenInput(t *testing.T) { + tDir := filepath.FromSlash(*testdataDir) + src, err := ioutil.ReadFile(filepath.Join(tDir, goldenText)) + if err != nil { + t.Fatalf("ReadFile: %v", err) + } + for i, tc := range extendMatchGoldenTestCases { + got := extendMatch(src, tc.i, tc.j) + if got != tc.want { + t.Errorf("test #%d: i, j = %5d, %5d: got %5d (= j + %6d), want %5d (= j + %6d)", + i, tc.i, tc.j, got, got-tc.j, tc.want, tc.want-tc.j) + } + } +} + +func TestExtendMatch(t *testing.T) { + // ref is a simple, reference implementation of extendMatch. + ref := func(src []byte, i, j int) int { + for ; j < len(src) && src[i] == src[j]; i, j = i+1, j+1 { + } + return j + } + + nums := []int{0, 1, 2, 7, 8, 9, 29, 30, 31, 32, 33, 34, 38, 39, 40} + for yIndex := 40; yIndex > 30; yIndex-- { + xxx := bytes.Repeat([]byte("x"), 40) + if yIndex < len(xxx) { + xxx[yIndex] = 'y' + } + for _, i := range nums { + for _, j := range nums { + if i >= j { + continue + } + got := extendMatch(xxx, i, j) + want := ref(xxx, i, j) + if got != want { + t.Errorf("yIndex=%d, i=%d, j=%d: got %d, want %d", yIndex, i, j, got, want) + } + } + } + } +} + +const snappytoolCmdName = "cmd/snappytool/snappytool" + +func skipTestSameEncodingAsCpp() (msg string) { + if !goEncoderShouldMatchCppEncoder { + return fmt.Sprintf("skipping testing that the encoding is byte-for-byte identical to C++: GOARCH=%s", runtime.GOARCH) + } + if _, err := os.Stat(snappytoolCmdName); err != nil { + return fmt.Sprintf("could not find snappytool: %v", err) + } + return "" +} + +func runTestSameEncodingAsCpp(src []byte) error { + got := Encode(nil, src) + + cmd := exec.Command(snappytoolCmdName, "-e") + cmd.Stdin = bytes.NewReader(src) + want, err := cmd.Output() + if err != nil { + return fmt.Errorf("could not run snappytool: %v", err) + } + return cmp(got, want) +} + +func TestSameEncodingAsCppShortCopies(t *testing.T) { + if msg := skipTestSameEncodingAsCpp(); msg != "" { + t.Skip(msg) + } + src := bytes.Repeat([]byte{'a'}, 20) + for i := 0; i <= len(src); i++ { + if err := runTestSameEncodingAsCpp(src[:i]); err != nil { + t.Errorf("i=%d: %v", i, err) + } + } +} + +func TestSameEncodingAsCppLongFiles(t *testing.T) { + if msg := skipTestSameEncodingAsCpp(); msg != "" { + t.Skip(msg) + } + bDir := filepath.FromSlash(*benchdataDir) + failed := false + for i, tf := range testFiles { + if err := downloadBenchmarkFiles(t, tf.filename); err != nil { + t.Fatalf("failed to download testdata: %s", err) + } + data := readFile(t, filepath.Join(bDir, tf.filename)) + if n := tf.sizeLimit; 0 < n && n < len(data) { + data = data[:n] + } + if err := runTestSameEncodingAsCpp(data); err != nil { + t.Errorf("i=%d: %v", i, err) + failed = true + } + } + if failed { + t.Errorf("was the snappytool program built against the C++ snappy library version " + + "d53de187 or later, commited on 2016-04-05? See " + + "https://github.com/google/snappy/commit/d53de18799418e113e44444252a39b12a0e4e0cc") + } +} + +// TestSlowForwardCopyOverrun tests the "expand the pattern" algorithm +// described in decode_amd64.s and its claim of a 10 byte overrun worst case. +func TestSlowForwardCopyOverrun(t *testing.T) { + const base = 100 + + for length := 1; length < 18; length++ { + for offset := 1; offset < 18; offset++ { + highWaterMark := base + d := base + l := length + o := offset + + // makeOffsetAtLeast8 + for o < 8 { + if end := d + 8; highWaterMark < end { + highWaterMark = end + } + l -= o + d += o + o += o + } + + // fixUpSlowForwardCopy + a := d + d += l + + // finishSlowForwardCopy + for l > 0 { + if end := a + 8; highWaterMark < end { + highWaterMark = end + } + a += 8 + l -= 8 + } + + dWant := base + length + overrun := highWaterMark - dWant + if d != dWant || overrun < 0 || 10 < overrun { + t.Errorf("length=%d, offset=%d: d and overrun: got (%d, %d), want (%d, something in [0, 10])", + length, offset, d, overrun, dWant) + } + } + } +} + +// TestEncodeNoiseThenRepeats encodes input for which the first half is very +// incompressible and the second half is very compressible. The encoded form's +// length should be closer to 50% of the original length than 100%. +func TestEncodeNoiseThenRepeats(t *testing.T) { + for _, origLen := range []int{256 * 1024, 2048 * 1024} { + src := make([]byte, origLen) + rng := rand.New(rand.NewSource(1)) + firstHalf, secondHalf := src[:origLen/2], src[origLen/2:] + for i := range firstHalf { + firstHalf[i] = uint8(rng.Intn(256)) + } + for i := range secondHalf { + secondHalf[i] = uint8(i >> 8) + } + dst := Encode(nil, src) + if got, want := len(dst), origLen*3/4; got >= want { + t.Errorf("origLen=%d: got %d encoded bytes, want less than %d", origLen, got, want) + } + } +} + +func TestFramingFormat(t *testing.T) { + // src is comprised of alternating 1e5-sized sequences of random + // (incompressible) bytes and repeated (compressible) bytes. 1e5 was chosen + // because it is larger than maxBlockSize (64k). + src := make([]byte, 1e6) + rng := rand.New(rand.NewSource(1)) + for i := 0; i < 10; i++ { + if i%2 == 0 { + for j := 0; j < 1e5; j++ { + src[1e5*i+j] = uint8(rng.Intn(256)) + } + } else { + for j := 0; j < 1e5; j++ { + src[1e5*i+j] = uint8(i) + } + } + } + + buf := new(bytes.Buffer) + if _, err := NewWriter(buf).Write(src); err != nil { + t.Fatalf("Write: encoding: %v", err) + } + dst, err := ioutil.ReadAll(NewReader(buf)) + if err != nil { + t.Fatalf("ReadAll: decoding: %v", err) + } + if err := cmp(dst, src); err != nil { + t.Fatal(err) + } +} + +func TestWriterGoldenOutput(t *testing.T) { + buf := new(bytes.Buffer) + w := NewBufferedWriter(buf) + defer w.Close() + w.Write([]byte("abcd")) // Not compressible. + w.Flush() + w.Write(bytes.Repeat([]byte{'A'}, 150)) // Compressible. + w.Flush() + // The next chunk is also compressible, but a naive, greedy encoding of the + // overall length 67 copy as a length 64 copy (the longest expressible as a + // tagCopy1 or tagCopy2) plus a length 3 remainder would be two 3-byte + // tagCopy2 tags (6 bytes), since the minimum length for a tagCopy1 is 4 + // bytes. Instead, we could do it shorter, in 5 bytes: a 3-byte tagCopy2 + // (of length 60) and a 2-byte tagCopy1 (of length 7). + w.Write(bytes.Repeat([]byte{'B'}, 68)) + w.Write([]byte("efC")) // Not compressible. + w.Write(bytes.Repeat([]byte{'C'}, 20)) // Compressible. + w.Write(bytes.Repeat([]byte{'B'}, 20)) // Compressible. + w.Write([]byte("g")) // Not compressible. + w.Flush() + + got := buf.String() + want := strings.Join([]string{ + magicChunk, + "\x01\x08\x00\x00", // Uncompressed chunk, 8 bytes long (including 4 byte checksum). + "\x68\x10\xe6\xb6", // Checksum. + "\x61\x62\x63\x64", // Uncompressed payload: "abcd". + "\x00\x11\x00\x00", // Compressed chunk, 17 bytes long (including 4 byte checksum). + "\x5f\xeb\xf2\x10", // Checksum. + "\x96\x01", // Compressed payload: Uncompressed length (varint encoded): 150. + "\x00\x41", // Compressed payload: tagLiteral, length=1, "A". + "\xfe\x01\x00", // Compressed payload: tagCopy2, length=64, offset=1. + "\xfe\x01\x00", // Compressed payload: tagCopy2, length=64, offset=1. + "\x52\x01\x00", // Compressed payload: tagCopy2, length=21, offset=1. + "\x00\x18\x00\x00", // Compressed chunk, 24 bytes long (including 4 byte checksum). + "\x30\x85\x69\xeb", // Checksum. + "\x70", // Compressed payload: Uncompressed length (varint encoded): 112. + "\x00\x42", // Compressed payload: tagLiteral, length=1, "B". + "\xee\x01\x00", // Compressed payload: tagCopy2, length=60, offset=1. + "\x0d\x01", // Compressed payload: tagCopy1, length=7, offset=1. + "\x08\x65\x66\x43", // Compressed payload: tagLiteral, length=3, "efC". + "\x4e\x01\x00", // Compressed payload: tagCopy2, length=20, offset=1. + "\x4e\x5a\x00", // Compressed payload: tagCopy2, length=20, offset=90. + "\x00\x67", // Compressed payload: tagLiteral, length=1, "g". + }, "") + if got != want { + t.Fatalf("\ngot: % x\nwant: % x", got, want) + } +} + +func TestEmitLiteral(t *testing.T) { + testCases := []struct { + length int + want string + }{ + {1, "\x00"}, + {2, "\x04"}, + {59, "\xe8"}, + {60, "\xec"}, + {61, "\xf0\x3c"}, + {62, "\xf0\x3d"}, + {254, "\xf0\xfd"}, + {255, "\xf0\xfe"}, + {256, "\xf0\xff"}, + {257, "\xf4\x00\x01"}, + {65534, "\xf4\xfd\xff"}, + {65535, "\xf4\xfe\xff"}, + {65536, "\xf4\xff\xff"}, + } + + dst := make([]byte, 70000) + nines := bytes.Repeat([]byte{0x99}, 65536) + for _, tc := range testCases { + lit := nines[:tc.length] + n := emitLiteral(dst, lit) + if !bytes.HasSuffix(dst[:n], lit) { + t.Errorf("length=%d: did not end with that many literal bytes", tc.length) + continue + } + got := string(dst[:n-tc.length]) + if got != tc.want { + t.Errorf("length=%d:\ngot % x\nwant % x", tc.length, got, tc.want) + continue + } + } +} + +func TestEmitCopy(t *testing.T) { + testCases := []struct { + offset int + length int + want string + }{ + {8, 04, "\x01\x08"}, + {8, 11, "\x1d\x08"}, + {8, 12, "\x2e\x08\x00"}, + {8, 13, "\x32\x08\x00"}, + {8, 59, "\xea\x08\x00"}, + {8, 60, "\xee\x08\x00"}, + {8, 61, "\xf2\x08\x00"}, + {8, 62, "\xf6\x08\x00"}, + {8, 63, "\xfa\x08\x00"}, + {8, 64, "\xfe\x08\x00"}, + {8, 65, "\xee\x08\x00\x05\x08"}, + {8, 66, "\xee\x08\x00\x09\x08"}, + {8, 67, "\xee\x08\x00\x0d\x08"}, + {8, 68, "\xfe\x08\x00\x01\x08"}, + {8, 69, "\xfe\x08\x00\x05\x08"}, + {8, 80, "\xfe\x08\x00\x3e\x08\x00"}, + + {256, 04, "\x21\x00"}, + {256, 11, "\x3d\x00"}, + {256, 12, "\x2e\x00\x01"}, + {256, 13, "\x32\x00\x01"}, + {256, 59, "\xea\x00\x01"}, + {256, 60, "\xee\x00\x01"}, + {256, 61, "\xf2\x00\x01"}, + {256, 62, "\xf6\x00\x01"}, + {256, 63, "\xfa\x00\x01"}, + {256, 64, "\xfe\x00\x01"}, + {256, 65, "\xee\x00\x01\x25\x00"}, + {256, 66, "\xee\x00\x01\x29\x00"}, + {256, 67, "\xee\x00\x01\x2d\x00"}, + {256, 68, "\xfe\x00\x01\x21\x00"}, + {256, 69, "\xfe\x00\x01\x25\x00"}, + {256, 80, "\xfe\x00\x01\x3e\x00\x01"}, + + {2048, 04, "\x0e\x00\x08"}, + {2048, 11, "\x2a\x00\x08"}, + {2048, 12, "\x2e\x00\x08"}, + {2048, 13, "\x32\x00\x08"}, + {2048, 59, "\xea\x00\x08"}, + {2048, 60, "\xee\x00\x08"}, + {2048, 61, "\xf2\x00\x08"}, + {2048, 62, "\xf6\x00\x08"}, + {2048, 63, "\xfa\x00\x08"}, + {2048, 64, "\xfe\x00\x08"}, + {2048, 65, "\xee\x00\x08\x12\x00\x08"}, + {2048, 66, "\xee\x00\x08\x16\x00\x08"}, + {2048, 67, "\xee\x00\x08\x1a\x00\x08"}, + {2048, 68, "\xfe\x00\x08\x0e\x00\x08"}, + {2048, 69, "\xfe\x00\x08\x12\x00\x08"}, + {2048, 80, "\xfe\x00\x08\x3e\x00\x08"}, + } + + dst := make([]byte, 1024) + for _, tc := range testCases { + n := emitCopy(dst, tc.offset, tc.length) + got := string(dst[:n]) + if got != tc.want { + t.Errorf("offset=%d, length=%d:\ngot % x\nwant % x", tc.offset, tc.length, got, tc.want) + } + } +} + +func TestNewBufferedWriter(t *testing.T) { + // Test all 32 possible sub-sequences of these 5 input slices. + // + // Their lengths sum to 400,000, which is over 6 times the Writer ibuf + // capacity: 6 * maxBlockSize is 393,216. + inputs := [][]byte{ + bytes.Repeat([]byte{'a'}, 40000), + bytes.Repeat([]byte{'b'}, 150000), + bytes.Repeat([]byte{'c'}, 60000), + bytes.Repeat([]byte{'d'}, 120000), + bytes.Repeat([]byte{'e'}, 30000), + } +loop: + for i := 0; i < 1< 0; { + i := copy(x, src) + x = x[i:] + } + return dst +} + +func benchWords(b *testing.B, n int, decode bool) { + // Note: the file is OS-language dependent so the resulting values are not + // directly comparable for non-US-English OS installations. + data := expand(readFile(b, "/usr/share/dict/words"), n) + if decode { + benchDecode(b, data) + } else { + benchEncode(b, data) + } +} + +func BenchmarkWordsDecode1e1(b *testing.B) { benchWords(b, 1e1, true) } +func BenchmarkWordsDecode1e2(b *testing.B) { benchWords(b, 1e2, true) } +func BenchmarkWordsDecode1e3(b *testing.B) { benchWords(b, 1e3, true) } +func BenchmarkWordsDecode1e4(b *testing.B) { benchWords(b, 1e4, true) } +func BenchmarkWordsDecode1e5(b *testing.B) { benchWords(b, 1e5, true) } +func BenchmarkWordsDecode1e6(b *testing.B) { benchWords(b, 1e6, true) } +func BenchmarkWordsEncode1e1(b *testing.B) { benchWords(b, 1e1, false) } +func BenchmarkWordsEncode1e2(b *testing.B) { benchWords(b, 1e2, false) } +func BenchmarkWordsEncode1e3(b *testing.B) { benchWords(b, 1e3, false) } +func BenchmarkWordsEncode1e4(b *testing.B) { benchWords(b, 1e4, false) } +func BenchmarkWordsEncode1e5(b *testing.B) { benchWords(b, 1e5, false) } +func BenchmarkWordsEncode1e6(b *testing.B) { benchWords(b, 1e6, false) } + +func BenchmarkRandomEncode(b *testing.B) { + rng := rand.New(rand.NewSource(1)) + data := make([]byte, 1<<20) + for i := range data { + data[i] = uint8(rng.Intn(256)) + } + benchEncode(b, data) +} + +// testFiles' values are copied directly from +// https://raw.githubusercontent.com/google/snappy/master/snappy_unittest.cc +// The label field is unused in snappy-go. +var testFiles = []struct { + label string + filename string + sizeLimit int +}{ + {"html", "html", 0}, + {"urls", "urls.10K", 0}, + {"jpg", "fireworks.jpeg", 0}, + {"jpg_200", "fireworks.jpeg", 200}, + {"pdf", "paper-100k.pdf", 0}, + {"html4", "html_x_4", 0}, + {"txt1", "alice29.txt", 0}, + {"txt2", "asyoulik.txt", 0}, + {"txt3", "lcet10.txt", 0}, + {"txt4", "plrabn12.txt", 0}, + {"pb", "geo.protodata", 0}, + {"gaviota", "kppkn.gtb", 0}, +} + +const ( + // The benchmark data files are at this canonical URL. + benchURL = "https://raw.githubusercontent.com/google/snappy/master/testdata/" +) + +func downloadBenchmarkFiles(b testing.TB, basename string) (errRet error) { + bDir := filepath.FromSlash(*benchdataDir) + filename := filepath.Join(bDir, basename) + if stat, err := os.Stat(filename); err == nil && stat.Size() != 0 { + return nil + } + + if !*download { + b.Skipf("test data not found; skipping %s without the -download flag", testOrBenchmark(b)) + } + // Download the official snappy C++ implementation reference test data + // files for benchmarking. + if err := os.MkdirAll(bDir, 0777); err != nil && !os.IsExist(err) { + return fmt.Errorf("failed to create %s: %s", bDir, err) + } + + f, err := os.Create(filename) + if err != nil { + return fmt.Errorf("failed to create %s: %s", filename, err) + } + defer f.Close() + defer func() { + if errRet != nil { + os.Remove(filename) + } + }() + url := benchURL + basename + resp, err := http.Get(url) + if err != nil { + return fmt.Errorf("failed to download %s: %s", url, err) + } + defer resp.Body.Close() + if s := resp.StatusCode; s != http.StatusOK { + return fmt.Errorf("downloading %s: HTTP status code %d (%s)", url, s, http.StatusText(s)) + } + _, err = io.Copy(f, resp.Body) + if err != nil { + return fmt.Errorf("failed to download %s to %s: %s", url, filename, err) + } + return nil +} + +func benchFile(b *testing.B, i int, decode bool) { + if err := downloadBenchmarkFiles(b, testFiles[i].filename); err != nil { + b.Fatalf("failed to download testdata: %s", err) + } + bDir := filepath.FromSlash(*benchdataDir) + data := readFile(b, filepath.Join(bDir, testFiles[i].filename)) + if n := testFiles[i].sizeLimit; 0 < n && n < len(data) { + data = data[:n] + } + if decode { + benchDecode(b, data) + } else { + benchEncode(b, data) + } +} + +// Naming convention is kept similar to what snappy's C++ implementation uses. +func Benchmark_UFlat0(b *testing.B) { benchFile(b, 0, true) } +func Benchmark_UFlat1(b *testing.B) { benchFile(b, 1, true) } +func Benchmark_UFlat2(b *testing.B) { benchFile(b, 2, true) } +func Benchmark_UFlat3(b *testing.B) { benchFile(b, 3, true) } +func Benchmark_UFlat4(b *testing.B) { benchFile(b, 4, true) } +func Benchmark_UFlat5(b *testing.B) { benchFile(b, 5, true) } +func Benchmark_UFlat6(b *testing.B) { benchFile(b, 6, true) } +func Benchmark_UFlat7(b *testing.B) { benchFile(b, 7, true) } +func Benchmark_UFlat8(b *testing.B) { benchFile(b, 8, true) } +func Benchmark_UFlat9(b *testing.B) { benchFile(b, 9, true) } +func Benchmark_UFlat10(b *testing.B) { benchFile(b, 10, true) } +func Benchmark_UFlat11(b *testing.B) { benchFile(b, 11, true) } +func Benchmark_ZFlat0(b *testing.B) { benchFile(b, 0, false) } +func Benchmark_ZFlat1(b *testing.B) { benchFile(b, 1, false) } +func Benchmark_ZFlat2(b *testing.B) { benchFile(b, 2, false) } +func Benchmark_ZFlat3(b *testing.B) { benchFile(b, 3, false) } +func Benchmark_ZFlat4(b *testing.B) { benchFile(b, 4, false) } +func Benchmark_ZFlat5(b *testing.B) { benchFile(b, 5, false) } +func Benchmark_ZFlat6(b *testing.B) { benchFile(b, 6, false) } +func Benchmark_ZFlat7(b *testing.B) { benchFile(b, 7, false) } +func Benchmark_ZFlat8(b *testing.B) { benchFile(b, 8, false) } +func Benchmark_ZFlat9(b *testing.B) { benchFile(b, 9, false) } +func Benchmark_ZFlat10(b *testing.B) { benchFile(b, 10, false) } +func Benchmark_ZFlat11(b *testing.B) { benchFile(b, 11, false) } + +func BenchmarkExtendMatch(b *testing.B) { + tDir := filepath.FromSlash(*testdataDir) + src, err := ioutil.ReadFile(filepath.Join(tDir, goldenText)) + if err != nil { + b.Fatalf("ReadFile: %v", err) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + for _, tc := range extendMatchGoldenTestCases { + extendMatch(src, tc.i, tc.j) + } + } +} diff --git a/vendor/src/github.com/golang/snappy/testdata/Mark.Twain-Tom.Sawyer.txt b/vendor/src/github.com/golang/snappy/testdata/Mark.Twain-Tom.Sawyer.txt new file mode 100644 index 00000000..86a18750 --- /dev/null +++ b/vendor/src/github.com/golang/snappy/testdata/Mark.Twain-Tom.Sawyer.txt @@ -0,0 +1,396 @@ +Produced by David Widger. The previous edition was updated by Jose +Menendez. + + + + + + THE ADVENTURES OF TOM SAWYER + BY + MARK TWAIN + (Samuel Langhorne Clemens) + + + + + P R E F A C E + +MOST of the adventures recorded in this book really occurred; one or +two were experiences of my own, the rest those of boys who were +schoolmates of mine. Huck Finn is drawn from life; Tom Sawyer also, but +not from an individual--he is a combination of the characteristics of +three boys whom I knew, and therefore belongs to the composite order of +architecture. + +The odd superstitions touched upon were all prevalent among children +and slaves in the West at the period of this story--that is to say, +thirty or forty years ago. + +Although my book is intended mainly for the entertainment of boys and +girls, I hope it will not be shunned by men and women on that account, +for part of my plan has been to try to pleasantly remind adults of what +they once were themselves, and of how they felt and thought and talked, +and what queer enterprises they sometimes engaged in. + + THE AUTHOR. + +HARTFORD, 1876. + + + + T O M S A W Y E R + + + +CHAPTER I + +"TOM!" + +No answer. + +"TOM!" + +No answer. + +"What's gone with that boy, I wonder? You TOM!" + +No answer. + +The old lady pulled her spectacles down and looked over them about the +room; then she put them up and looked out under them. She seldom or +never looked THROUGH them for so small a thing as a boy; they were her +state pair, the pride of her heart, and were built for "style," not +service--she could have seen through a pair of stove-lids just as well. +She looked perplexed for a moment, and then said, not fiercely, but +still loud enough for the furniture to hear: + +"Well, I lay if I get hold of you I'll--" + +She did not finish, for by this time she was bending down and punching +under the bed with the broom, and so she needed breath to punctuate the +punches with. She resurrected nothing but the cat. + +"I never did see the beat of that boy!" + +She went to the open door and stood in it and looked out among the +tomato vines and "jimpson" weeds that constituted the garden. No Tom. +So she lifted up her voice at an angle calculated for distance and +shouted: + +"Y-o-u-u TOM!" + +There was a slight noise behind her and she turned just in time to +seize a small boy by the slack of his roundabout and arrest his flight. + +"There! I might 'a' thought of that closet. What you been doing in +there?" + +"Nothing." + +"Nothing! Look at your hands. And look at your mouth. What IS that +truck?" + +"I don't know, aunt." + +"Well, I know. It's jam--that's what it is. Forty times I've said if +you didn't let that jam alone I'd skin you. Hand me that switch." + +The switch hovered in the air--the peril was desperate-- + +"My! Look behind you, aunt!" + +The old lady whirled round, and snatched her skirts out of danger. The +lad fled on the instant, scrambled up the high board-fence, and +disappeared over it. + +His aunt Polly stood surprised a moment, and then broke into a gentle +laugh. + +"Hang the boy, can't I never learn anything? Ain't he played me tricks +enough like that for me to be looking out for him by this time? But old +fools is the biggest fools there is. Can't learn an old dog new tricks, +as the saying is. But my goodness, he never plays them alike, two days, +and how is a body to know what's coming? He 'pears to know just how +long he can torment me before I get my dander up, and he knows if he +can make out to put me off for a minute or make me laugh, it's all down +again and I can't hit him a lick. I ain't doing my duty by that boy, +and that's the Lord's truth, goodness knows. Spare the rod and spile +the child, as the Good Book says. I'm a laying up sin and suffering for +us both, I know. He's full of the Old Scratch, but laws-a-me! he's my +own dead sister's boy, poor thing, and I ain't got the heart to lash +him, somehow. Every time I let him off, my conscience does hurt me so, +and every time I hit him my old heart most breaks. Well-a-well, man +that is born of woman is of few days and full of trouble, as the +Scripture says, and I reckon it's so. He'll play hookey this evening, * +and [* Southwestern for "afternoon"] I'll just be obleeged to make him +work, to-morrow, to punish him. It's mighty hard to make him work +Saturdays, when all the boys is having holiday, but he hates work more +than he hates anything else, and I've GOT to do some of my duty by him, +or I'll be the ruination of the child." + +Tom did play hookey, and he had a very good time. He got back home +barely in season to help Jim, the small colored boy, saw next-day's +wood and split the kindlings before supper--at least he was there in +time to tell his adventures to Jim while Jim did three-fourths of the +work. Tom's younger brother (or rather half-brother) Sid was already +through with his part of the work (picking up chips), for he was a +quiet boy, and had no adventurous, troublesome ways. + +While Tom was eating his supper, and stealing sugar as opportunity +offered, Aunt Polly asked him questions that were full of guile, and +very deep--for she wanted to trap him into damaging revealments. Like +many other simple-hearted souls, it was her pet vanity to believe she +was endowed with a talent for dark and mysterious diplomacy, and she +loved to contemplate her most transparent devices as marvels of low +cunning. Said she: + +"Tom, it was middling warm in school, warn't it?" + +"Yes'm." + +"Powerful warm, warn't it?" + +"Yes'm." + +"Didn't you want to go in a-swimming, Tom?" + +A bit of a scare shot through Tom--a touch of uncomfortable suspicion. +He searched Aunt Polly's face, but it told him nothing. So he said: + +"No'm--well, not very much." + +The old lady reached out her hand and felt Tom's shirt, and said: + +"But you ain't too warm now, though." And it flattered her to reflect +that she had discovered that the shirt was dry without anybody knowing +that that was what she had in her mind. But in spite of her, Tom knew +where the wind lay, now. So he forestalled what might be the next move: + +"Some of us pumped on our heads--mine's damp yet. See?" + +Aunt Polly was vexed to think she had overlooked that bit of +circumstantial evidence, and missed a trick. Then she had a new +inspiration: + +"Tom, you didn't have to undo your shirt collar where I sewed it, to +pump on your head, did you? Unbutton your jacket!" + +The trouble vanished out of Tom's face. He opened his jacket. His +shirt collar was securely sewed. + +"Bother! Well, go 'long with you. I'd made sure you'd played hookey +and been a-swimming. But I forgive ye, Tom. I reckon you're a kind of a +singed cat, as the saying is--better'n you look. THIS time." + +She was half sorry her sagacity had miscarried, and half glad that Tom +had stumbled into obedient conduct for once. + +But Sidney said: + +"Well, now, if I didn't think you sewed his collar with white thread, +but it's black." + +"Why, I did sew it with white! Tom!" + +But Tom did not wait for the rest. As he went out at the door he said: + +"Siddy, I'll lick you for that." + +In a safe place Tom examined two large needles which were thrust into +the lapels of his jacket, and had thread bound about them--one needle +carried white thread and the other black. He said: + +"She'd never noticed if it hadn't been for Sid. Confound it! sometimes +she sews it with white, and sometimes she sews it with black. I wish to +geeminy she'd stick to one or t'other--I can't keep the run of 'em. But +I bet you I'll lam Sid for that. I'll learn him!" + +He was not the Model Boy of the village. He knew the model boy very +well though--and loathed him. + +Within two minutes, or even less, he had forgotten all his troubles. +Not because his troubles were one whit less heavy and bitter to him +than a man's are to a man, but because a new and powerful interest bore +them down and drove them out of his mind for the time--just as men's +misfortunes are forgotten in the excitement of new enterprises. This +new interest was a valued novelty in whistling, which he had just +acquired from a negro, and he was suffering to practise it undisturbed. +It consisted in a peculiar bird-like turn, a sort of liquid warble, +produced by touching the tongue to the roof of the mouth at short +intervals in the midst of the music--the reader probably remembers how +to do it, if he has ever been a boy. Diligence and attention soon gave +him the knack of it, and he strode down the street with his mouth full +of harmony and his soul full of gratitude. He felt much as an +astronomer feels who has discovered a new planet--no doubt, as far as +strong, deep, unalloyed pleasure is concerned, the advantage was with +the boy, not the astronomer. + +The summer evenings were long. It was not dark, yet. Presently Tom +checked his whistle. A stranger was before him--a boy a shade larger +than himself. A new-comer of any age or either sex was an impressive +curiosity in the poor little shabby village of St. Petersburg. This boy +was well dressed, too--well dressed on a week-day. This was simply +astounding. His cap was a dainty thing, his close-buttoned blue cloth +roundabout was new and natty, and so were his pantaloons. He had shoes +on--and it was only Friday. He even wore a necktie, a bright bit of +ribbon. He had a citified air about him that ate into Tom's vitals. The +more Tom stared at the splendid marvel, the higher he turned up his +nose at his finery and the shabbier and shabbier his own outfit seemed +to him to grow. Neither boy spoke. If one moved, the other moved--but +only sidewise, in a circle; they kept face to face and eye to eye all +the time. Finally Tom said: + +"I can lick you!" + +"I'd like to see you try it." + +"Well, I can do it." + +"No you can't, either." + +"Yes I can." + +"No you can't." + +"I can." + +"You can't." + +"Can!" + +"Can't!" + +An uncomfortable pause. Then Tom said: + +"What's your name?" + +"'Tisn't any of your business, maybe." + +"Well I 'low I'll MAKE it my business." + +"Well why don't you?" + +"If you say much, I will." + +"Much--much--MUCH. There now." + +"Oh, you think you're mighty smart, DON'T you? I could lick you with +one hand tied behind me, if I wanted to." + +"Well why don't you DO it? You SAY you can do it." + +"Well I WILL, if you fool with me." + +"Oh yes--I've seen whole families in the same fix." + +"Smarty! You think you're SOME, now, DON'T you? Oh, what a hat!" + +"You can lump that hat if you don't like it. I dare you to knock it +off--and anybody that'll take a dare will suck eggs." + +"You're a liar!" + +"You're another." + +"You're a fighting liar and dasn't take it up." + +"Aw--take a walk!" + +"Say--if you give me much more of your sass I'll take and bounce a +rock off'n your head." + +"Oh, of COURSE you will." + +"Well I WILL." + +"Well why don't you DO it then? What do you keep SAYING you will for? +Why don't you DO it? It's because you're afraid." + +"I AIN'T afraid." + +"You are." + +"I ain't." + +"You are." + +Another pause, and more eying and sidling around each other. Presently +they were shoulder to shoulder. Tom said: + +"Get away from here!" + +"Go away yourself!" + +"I won't." + +"I won't either." + +So they stood, each with a foot placed at an angle as a brace, and +both shoving with might and main, and glowering at each other with +hate. But neither could get an advantage. After struggling till both +were hot and flushed, each relaxed his strain with watchful caution, +and Tom said: + +"You're a coward and a pup. I'll tell my big brother on you, and he +can thrash you with his little finger, and I'll make him do it, too." + +"What do I care for your big brother? I've got a brother that's bigger +than he is--and what's more, he can throw him over that fence, too." +[Both brothers were imaginary.] + +"That's a lie." + +"YOUR saying so don't make it so." + +Tom drew a line in the dust with his big toe, and said: + +"I dare you to step over that, and I'll lick you till you can't stand +up. Anybody that'll take a dare will steal sheep." + +The new boy stepped over promptly, and said: + +"Now you said you'd do it, now let's see you do it." + +"Don't you crowd me now; you better look out." + +"Well, you SAID you'd do it--why don't you do it?" + +"By jingo! for two cents I WILL do it." + +The new boy took two broad coppers out of his pocket and held them out +with derision. Tom struck them to the ground. In an instant both boys +were rolling and tumbling in the dirt, gripped together like cats; and +for the space of a minute they tugged and tore at each other's hair and +clothes, punched and scratched each other's nose, and covered +themselves with dust and glory. Presently the confusion took form, and +through the fog of battle Tom appeared, seated astride the new boy, and +pounding him with his fists. "Holler 'nuff!" said he. + +The boy only struggled to free himself. He was crying--mainly from rage. + +"Holler 'nuff!"--and the pounding went on. + +At last the stranger got out a smothered "'Nuff!" and Tom let him up +and said: + +"Now that'll learn you. Better look out who you're fooling with next +time." + +The new boy went off brushing the dust from his clothes, sobbing, +snuffling, and occasionally looking back and shaking his head and +threatening what he would do to Tom the "next time he caught him out." +To which Tom responded with jeers, and started off in high feather, and +as soon as his back was turned the new boy snatched up a stone, threw +it and hit him between the shoulders and then turned tail and ran like +an antelope. Tom chased the traitor home, and thus found out where he +lived. He then held a position at the gate for some time, daring the +enemy to come outside, but the enemy only made faces at him through the +window and declined. At last the enemy's mother appeared, and called +Tom a bad, vicious, vulgar child, and ordered him away. So he went +away; but he said he "'lowed" to "lay" for that boy. + +He got home pretty late that night, and when he climbed cautiously in +at the window, he uncovered an ambuscade, in the person of his aunt; +and when she saw the state his clothes were in her resolution to turn +his Saturday holiday into captivity at hard labor became adamantine in +its firmness. diff --git a/vendor/src/github.com/golang/snappy/testdata/Mark.Twain-Tom.Sawyer.txt.rawsnappy b/vendor/src/github.com/golang/snappy/testdata/Mark.Twain-Tom.Sawyer.txt.rawsnappy new file mode 100644 index 0000000000000000000000000000000000000000..9c56d985888e48a9967e187523f0e3326330aeca GIT binary patch literal 9871 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, byte(s>>16), byte(s>>8), byte(s)) +} + +// Checksum returns the CRC-32 checksum of data +// using the polynomial represented by the Table. +func Checksum(data []byte, tab *Table) uint32 { return Update(0, tab, data) } + +// ChecksumIEEE returns the CRC-32 checksum of data +// using the IEEE polynomial. +func ChecksumIEEE(data []byte) uint32 { + ieeeOnce.Do(ieeeInit) + return updateIEEE(0, data) +} diff --git a/vendor/src/github.com/klauspost/crc32/crc32_amd64.go b/vendor/src/github.com/klauspost/crc32/crc32_amd64.go new file mode 100644 index 00000000..af2a0b84 --- /dev/null +++ b/vendor/src/github.com/klauspost/crc32/crc32_amd64.go @@ -0,0 +1,230 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine,!gccgo + +// AMD64-specific hardware-assisted CRC32 algorithms. See crc32.go for a +// description of the interface that each architecture-specific file +// implements. + +package crc32 + +import "unsafe" + +// This file contains the code to call the SSE 4.2 version of the Castagnoli +// and IEEE CRC. + +// haveSSE41/haveSSE42/haveCLMUL are defined in crc_amd64.s and use +// CPUID to test for SSE 4.1, 4.2 and CLMUL support. +func haveSSE41() bool +func haveSSE42() bool +func haveCLMUL() bool + +// castagnoliSSE42 is defined in crc32_amd64.s and uses the SSE4.2 CRC32 +// instruction. +//go:noescape +func castagnoliSSE42(crc uint32, p []byte) uint32 + +// castagnoliSSE42Triple is defined in crc32_amd64.s and uses the SSE4.2 CRC32 +// instruction. +//go:noescape +func castagnoliSSE42Triple( + crcA, crcB, crcC uint32, + a, b, c []byte, + rounds uint32, +) (retA uint32, retB uint32, retC uint32) + +// ieeeCLMUL is defined in crc_amd64.s and uses the PCLMULQDQ +// instruction as well as SSE 4.1. +//go:noescape +func ieeeCLMUL(crc uint32, p []byte) uint32 + +var sse42 = haveSSE42() +var useFastIEEE = haveCLMUL() && haveSSE41() + +const castagnoliK1 = 168 +const castagnoliK2 = 1344 + +type sse42Table [4]Table + +var castagnoliSSE42TableK1 *sse42Table +var castagnoliSSE42TableK2 *sse42Table + +func archAvailableCastagnoli() bool { + return sse42 +} + +func archInitCastagnoli() { + if !sse42 { + panic("arch-specific Castagnoli not available") + } + castagnoliSSE42TableK1 = new(sse42Table) + castagnoliSSE42TableK2 = new(sse42Table) + // See description in updateCastagnoli. + // t[0][i] = CRC(i000, O) + // t[1][i] = CRC(0i00, O) + // t[2][i] = CRC(00i0, O) + // t[3][i] = CRC(000i, O) + // where O is a sequence of K zeros. + var tmp [castagnoliK2]byte + for b := 0; b < 4; b++ { + for i := 0; i < 256; i++ { + val := uint32(i) << uint32(b*8) + castagnoliSSE42TableK1[b][i] = castagnoliSSE42(val, tmp[:castagnoliK1]) + castagnoliSSE42TableK2[b][i] = castagnoliSSE42(val, tmp[:]) + } + } +} + +// castagnoliShift computes the CRC32-C of K1 or K2 zeroes (depending on the +// table given) with the given initial crc value. This corresponds to +// CRC(crc, O) in the description in updateCastagnoli. +func castagnoliShift(table *sse42Table, crc uint32) uint32 { + return table[3][crc>>24] ^ + table[2][(crc>>16)&0xFF] ^ + table[1][(crc>>8)&0xFF] ^ + table[0][crc&0xFF] +} + +func archUpdateCastagnoli(crc uint32, p []byte) uint32 { + if !sse42 { + panic("not available") + } + + // This method is inspired from the algorithm in Intel's white paper: + // "Fast CRC Computation for iSCSI Polynomial Using CRC32 Instruction" + // The same strategy of splitting the buffer in three is used but the + // combining calculation is different; the complete derivation is explained + // below. + // + // -- The basic idea -- + // + // The CRC32 instruction (available in SSE4.2) can process 8 bytes at a + // time. In recent Intel architectures the instruction takes 3 cycles; + // however the processor can pipeline up to three instructions if they + // don't depend on each other. + // + // Roughly this means that we can process three buffers in about the same + // time we can process one buffer. + // + // The idea is then to split the buffer in three, CRC the three pieces + // separately and then combine the results. + // + // Combining the results requires precomputed tables, so we must choose a + // fixed buffer length to optimize. The longer the length, the faster; but + // only buffers longer than this length will use the optimization. We choose + // two cutoffs and compute tables for both: + // - one around 512: 168*3=504 + // - one around 4KB: 1344*3=4032 + // + // -- The nitty gritty -- + // + // Let CRC(I, X) be the non-inverted CRC32-C of the sequence X (with + // initial non-inverted CRC I). This function has the following properties: + // (a) CRC(I, AB) = CRC(CRC(I, A), B) + // (b) CRC(I, A xor B) = CRC(I, A) xor CRC(0, B) + // + // Say we want to compute CRC(I, ABC) where A, B, C are three sequences of + // K bytes each, where K is a fixed constant. Let O be the sequence of K zero + // bytes. + // + // CRC(I, ABC) = CRC(I, ABO xor C) + // = CRC(I, ABO) xor CRC(0, C) + // = CRC(CRC(I, AB), O) xor CRC(0, C) + // = CRC(CRC(I, AO xor B), O) xor CRC(0, C) + // = CRC(CRC(I, AO) xor CRC(0, B), O) xor CRC(0, C) + // = CRC(CRC(CRC(I, A), O) xor CRC(0, B), O) xor CRC(0, C) + // + // The castagnoliSSE42Triple function can compute CRC(I, A), CRC(0, B), + // and CRC(0, C) efficiently. We just need to find a way to quickly compute + // CRC(uvwx, O) given a 4-byte initial value uvwx. We can precompute these + // values; since we can't have a 32-bit table, we break it up into four + // 8-bit tables: + // + // CRC(uvwx, O) = CRC(u000, O) xor + // CRC(0v00, O) xor + // CRC(00w0, O) xor + // CRC(000x, O) + // + // We can compute tables corresponding to the four terms for all 8-bit + // values. + + crc = ^crc + + // If a buffer is long enough to use the optimization, process the first few + // bytes to align the buffer to an 8 byte boundary (if necessary). + if len(p) >= castagnoliK1*3 { + delta := int(uintptr(unsafe.Pointer(&p[0])) & 7) + if delta != 0 { + delta = 8 - delta + crc = castagnoliSSE42(crc, p[:delta]) + p = p[delta:] + } + } + + // Process 3*K2 at a time. + for len(p) >= castagnoliK2*3 { + // Compute CRC(I, A), CRC(0, B), and CRC(0, C). + crcA, crcB, crcC := castagnoliSSE42Triple( + crc, 0, 0, + p, p[castagnoliK2:], p[castagnoliK2*2:], + castagnoliK2/24) + + // CRC(I, AB) = CRC(CRC(I, A), O) xor CRC(0, B) + crcAB := castagnoliShift(castagnoliSSE42TableK2, crcA) ^ crcB + // CRC(I, ABC) = CRC(CRC(I, AB), O) xor CRC(0, C) + crc = castagnoliShift(castagnoliSSE42TableK2, crcAB) ^ crcC + p = p[castagnoliK2*3:] + } + + // Process 3*K1 at a time. + for len(p) >= castagnoliK1*3 { + // Compute CRC(I, A), CRC(0, B), and CRC(0, C). + crcA, crcB, crcC := castagnoliSSE42Triple( + crc, 0, 0, + p, p[castagnoliK1:], p[castagnoliK1*2:], + castagnoliK1/24) + + // CRC(I, AB) = CRC(CRC(I, A), O) xor CRC(0, B) + crcAB := castagnoliShift(castagnoliSSE42TableK1, crcA) ^ crcB + // CRC(I, ABC) = CRC(CRC(I, AB), O) xor CRC(0, C) + crc = castagnoliShift(castagnoliSSE42TableK1, crcAB) ^ crcC + p = p[castagnoliK1*3:] + } + + // Use the simple implementation for what's left. + crc = castagnoliSSE42(crc, p) + return ^crc +} + +func archAvailableIEEE() bool { + return useFastIEEE +} + +var archIeeeTable8 *slicing8Table + +func archInitIEEE() { + if !useFastIEEE { + panic("not available") + } + // We still use slicing-by-8 for small buffers. + archIeeeTable8 = slicingMakeTable(IEEE) +} + +func archUpdateIEEE(crc uint32, p []byte) uint32 { + if !useFastIEEE { + panic("not available") + } + + if len(p) >= 64 { + left := len(p) & 15 + do := len(p) - left + crc = ^ieeeCLMUL(^crc, p[:do]) + p = p[do:] + } + if len(p) == 0 { + return crc + } + return slicingUpdate(crc, archIeeeTable8, p) +} diff --git a/vendor/src/github.com/klauspost/crc32/crc32_amd64.s b/vendor/src/github.com/klauspost/crc32/crc32_amd64.s new file mode 100644 index 00000000..e8a7941c --- /dev/null +++ b/vendor/src/github.com/klauspost/crc32/crc32_amd64.s @@ -0,0 +1,319 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build gc + +#define NOSPLIT 4 +#define RODATA 8 + +// castagnoliSSE42 updates the (non-inverted) crc with the given buffer. +// +// func castagnoliSSE42(crc uint32, p []byte) uint32 +TEXT ·castagnoliSSE42(SB), NOSPLIT, $0 + MOVL crc+0(FP), AX // CRC value + MOVQ p+8(FP), SI // data pointer + MOVQ p_len+16(FP), CX // len(p) + + // If there are fewer than 8 bytes to process, skip alignment. + CMPQ CX, $8 + JL less_than_8 + + MOVQ SI, BX + ANDQ $7, BX + JZ aligned + + // Process the first few bytes to 8-byte align the input. + + // BX = 8 - BX. We need to process this many bytes to align. + SUBQ $1, BX + XORQ $7, BX + + BTQ $0, BX + JNC align_2 + + CRC32B (SI), AX + DECQ CX + INCQ SI + +align_2: + BTQ $1, BX + JNC align_4 + + // CRC32W (SI), AX + BYTE $0x66; BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06 + + SUBQ $2, CX + ADDQ $2, SI + +align_4: + BTQ $2, BX + JNC aligned + + // CRC32L (SI), AX + BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06 + + SUBQ $4, CX + ADDQ $4, SI + +aligned: + // The input is now 8-byte aligned and we can process 8-byte chunks. + CMPQ CX, $8 + JL less_than_8 + + CRC32Q (SI), AX + ADDQ $8, SI + SUBQ $8, CX + JMP aligned + +less_than_8: + // We may have some bytes left over; process 4 bytes, then 2, then 1. + BTQ $2, CX + JNC less_than_4 + + // CRC32L (SI), AX + BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06 + ADDQ $4, SI + +less_than_4: + BTQ $1, CX + JNC less_than_2 + + // CRC32W (SI), AX + BYTE $0x66; BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06 + ADDQ $2, SI + +less_than_2: + BTQ $0, CX + JNC done + + CRC32B (SI), AX + +done: + MOVL AX, ret+32(FP) + RET + +// castagnoliSSE42Triple updates three (non-inverted) crcs with (24*rounds) +// bytes from each buffer. +// +// func castagnoliSSE42Triple( +// crc1, crc2, crc3 uint32, +// a, b, c []byte, +// rounds uint32, +// ) (retA uint32, retB uint32, retC uint32) +TEXT ·castagnoliSSE42Triple(SB), NOSPLIT, $0 + MOVL crcA+0(FP), AX + MOVL crcB+4(FP), CX + MOVL crcC+8(FP), DX + + MOVQ a+16(FP), R8 // data pointer + MOVQ b+40(FP), R9 // data pointer + MOVQ c+64(FP), R10 // data pointer + + MOVL rounds+88(FP), R11 + +loop: + CRC32Q (R8), AX + CRC32Q (R9), CX + CRC32Q (R10), DX + + CRC32Q 8(R8), AX + CRC32Q 8(R9), CX + CRC32Q 8(R10), DX + + CRC32Q 16(R8), AX + CRC32Q 16(R9), CX + CRC32Q 16(R10), DX + + ADDQ $24, R8 + ADDQ $24, R9 + ADDQ $24, R10 + + DECQ R11 + JNZ loop + + MOVL AX, retA+96(FP) + MOVL CX, retB+100(FP) + MOVL DX, retC+104(FP) + RET + +// func haveSSE42() bool +TEXT ·haveSSE42(SB), NOSPLIT, $0 + XORQ AX, AX + INCL AX + CPUID + SHRQ $20, CX + ANDQ $1, CX + MOVB CX, ret+0(FP) + RET + +// func haveCLMUL() bool +TEXT ·haveCLMUL(SB), NOSPLIT, $0 + XORQ AX, AX + INCL AX + CPUID + SHRQ $1, CX + ANDQ $1, CX + MOVB CX, ret+0(FP) + RET + +// func haveSSE41() bool +TEXT ·haveSSE41(SB), NOSPLIT, $0 + XORQ AX, AX + INCL AX + CPUID + SHRQ $19, CX + ANDQ $1, CX + MOVB CX, ret+0(FP) + RET + +// CRC32 polynomial data +// +// These constants are lifted from the +// Linux kernel, since they avoid the costly +// PSHUFB 16 byte reversal proposed in the +// original Intel paper. +DATA r2r1kp<>+0(SB)/8, $0x154442bd4 +DATA r2r1kp<>+8(SB)/8, $0x1c6e41596 +DATA r4r3kp<>+0(SB)/8, $0x1751997d0 +DATA r4r3kp<>+8(SB)/8, $0x0ccaa009e +DATA rupolykp<>+0(SB)/8, $0x1db710641 +DATA rupolykp<>+8(SB)/8, $0x1f7011641 +DATA r5kp<>+0(SB)/8, $0x163cd6124 + +GLOBL r2r1kp<>(SB), RODATA, $16 +GLOBL r4r3kp<>(SB), RODATA, $16 +GLOBL rupolykp<>(SB), RODATA, $16 +GLOBL r5kp<>(SB), RODATA, $8 + +// Based on http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf +// len(p) must be at least 64, and must be a multiple of 16. + +// func ieeeCLMUL(crc uint32, p []byte) uint32 +TEXT ·ieeeCLMUL(SB), NOSPLIT, $0 + MOVL crc+0(FP), X0 // Initial CRC value + MOVQ p+8(FP), SI // data pointer + MOVQ p_len+16(FP), CX // len(p) + + MOVOU (SI), X1 + MOVOU 16(SI), X2 + MOVOU 32(SI), X3 + MOVOU 48(SI), X4 + PXOR X0, X1 + ADDQ $64, SI // buf+=64 + SUBQ $64, CX // len-=64 + CMPQ CX, $64 // Less than 64 bytes left + JB remain64 + + MOVOA r2r1kp<>+0(SB), X0 + +loopback64: + MOVOA X1, X5 + MOVOA X2, X6 + MOVOA X3, X7 + MOVOA X4, X8 + + PCLMULQDQ $0, X0, X1 + PCLMULQDQ $0, X0, X2 + PCLMULQDQ $0, X0, X3 + PCLMULQDQ $0, X0, X4 + + // Load next early + MOVOU (SI), X11 + MOVOU 16(SI), X12 + MOVOU 32(SI), X13 + MOVOU 48(SI), X14 + + PCLMULQDQ $0x11, X0, X5 + PCLMULQDQ $0x11, X0, X6 + PCLMULQDQ $0x11, X0, X7 + PCLMULQDQ $0x11, X0, X8 + + PXOR X5, X1 + PXOR X6, X2 + PXOR X7, X3 + PXOR X8, X4 + + PXOR X11, X1 + PXOR X12, X2 + PXOR X13, X3 + PXOR X14, X4 + + ADDQ $0x40, DI + ADDQ $64, SI // buf+=64 + SUBQ $64, CX // len-=64 + CMPQ CX, $64 // Less than 64 bytes left? + JGE loopback64 + + // Fold result into a single register (X1) +remain64: + MOVOA r4r3kp<>+0(SB), X0 + + MOVOA X1, X5 + PCLMULQDQ $0, X0, X1 + PCLMULQDQ $0x11, X0, X5 + PXOR X5, X1 + PXOR X2, X1 + + MOVOA X1, X5 + PCLMULQDQ $0, X0, X1 + PCLMULQDQ $0x11, X0, X5 + PXOR X5, X1 + PXOR X3, X1 + + MOVOA X1, X5 + PCLMULQDQ $0, X0, X1 + PCLMULQDQ $0x11, X0, X5 + PXOR X5, X1 + PXOR X4, X1 + + // If there is less than 16 bytes left we are done + CMPQ CX, $16 + JB finish + + // Encode 16 bytes +remain16: + MOVOU (SI), X10 + MOVOA X1, X5 + PCLMULQDQ $0, X0, X1 + PCLMULQDQ $0x11, X0, X5 + PXOR X5, X1 + PXOR X10, X1 + SUBQ $16, CX + ADDQ $16, SI + CMPQ CX, $16 + JGE remain16 + +finish: + // Fold final result into 32 bits and return it + PCMPEQB X3, X3 + PCLMULQDQ $1, X1, X0 + PSRLDQ $8, X1 + PXOR X0, X1 + + MOVOA X1, X2 + MOVQ r5kp<>+0(SB), X0 + + // Creates 32 bit mask. Note that we don't care about upper half. + PSRLQ $32, X3 + + PSRLDQ $4, X2 + PAND X3, X1 + PCLMULQDQ $0, X0, X1 + PXOR X2, X1 + + MOVOA rupolykp<>+0(SB), X0 + + MOVOA X1, X2 + PAND X3, X1 + PCLMULQDQ $0x10, X0, X1 + PAND X3, X1 + PCLMULQDQ $0, X0, X1 + PXOR X2, X1 + + // PEXTRD $1, X1, AX (SSE 4.1) + BYTE $0x66; BYTE $0x0f; BYTE $0x3a + BYTE $0x16; BYTE $0xc8; BYTE $0x01 + MOVL AX, ret+32(FP) + + RET diff --git a/vendor/src/github.com/klauspost/crc32/crc32_amd64p32.go b/vendor/src/github.com/klauspost/crc32/crc32_amd64p32.go new file mode 100644 index 00000000..3222b06a --- /dev/null +++ b/vendor/src/github.com/klauspost/crc32/crc32_amd64p32.go @@ -0,0 +1,43 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine,!gccgo + +package crc32 + +// This file contains the code to call the SSE 4.2 version of the Castagnoli +// CRC. + +// haveSSE42 is defined in crc32_amd64p32.s and uses CPUID to test for SSE 4.2 +// support. +func haveSSE42() bool + +// castagnoliSSE42 is defined in crc32_amd64p32.s and uses the SSE4.2 CRC32 +// instruction. +//go:noescape +func castagnoliSSE42(crc uint32, p []byte) uint32 + +var sse42 = haveSSE42() + +func archAvailableCastagnoli() bool { + return sse42 +} + +func archInitCastagnoli() { + if !sse42 { + panic("not available") + } + // No initialization necessary. +} + +func archUpdateCastagnoli(crc uint32, p []byte) uint32 { + if !sse42 { + panic("not available") + } + return castagnoliSSE42(crc, p) +} + +func archAvailableIEEE() bool { return false } +func archInitIEEE() { panic("not available") } +func archUpdateIEEE(crc uint32, p []byte) uint32 { panic("not available") } diff --git a/vendor/src/github.com/klauspost/crc32/crc32_amd64p32.s b/vendor/src/github.com/klauspost/crc32/crc32_amd64p32.s new file mode 100644 index 00000000..a578d685 --- /dev/null +++ b/vendor/src/github.com/klauspost/crc32/crc32_amd64p32.s @@ -0,0 +1,67 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build gc + +#define NOSPLIT 4 +#define RODATA 8 + +// func castagnoliSSE42(crc uint32, p []byte) uint32 +TEXT ·castagnoliSSE42(SB), NOSPLIT, $0 + MOVL crc+0(FP), AX // CRC value + MOVL p+4(FP), SI // data pointer + MOVL p_len+8(FP), CX // len(p) + + NOTL AX + + // If there's less than 8 bytes to process, we do it byte-by-byte. + CMPQ CX, $8 + JL cleanup + + // Process individual bytes until the input is 8-byte aligned. +startup: + MOVQ SI, BX + ANDQ $7, BX + JZ aligned + + CRC32B (SI), AX + DECQ CX + INCQ SI + JMP startup + +aligned: + // The input is now 8-byte aligned and we can process 8-byte chunks. + CMPQ CX, $8 + JL cleanup + + CRC32Q (SI), AX + ADDQ $8, SI + SUBQ $8, CX + JMP aligned + +cleanup: + // We may have some bytes left over that we process one at a time. + CMPQ CX, $0 + JE done + + CRC32B (SI), AX + INCQ SI + DECQ CX + JMP cleanup + +done: + NOTL AX + MOVL AX, ret+16(FP) + RET + +// func haveSSE42() bool +TEXT ·haveSSE42(SB), NOSPLIT, $0 + XORQ AX, AX + INCL AX + CPUID + SHRQ $20, CX + ANDQ $1, CX + MOVB CX, ret+0(FP) + RET + diff --git a/vendor/src/github.com/klauspost/crc32/crc32_generic.go b/vendor/src/github.com/klauspost/crc32/crc32_generic.go new file mode 100644 index 00000000..abacbb66 --- /dev/null +++ b/vendor/src/github.com/klauspost/crc32/crc32_generic.go @@ -0,0 +1,89 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains CRC32 algorithms that are not specific to any architecture +// and don't use hardware acceleration. +// +// The simple (and slow) CRC32 implementation only uses a 256*4 bytes table. +// +// The slicing-by-8 algorithm is a faster implementation that uses a bigger +// table (8*256*4 bytes). + +package crc32 + +// simpleMakeTable allocates and constructs a Table for the specified +// polynomial. The table is suitable for use with the simple algorithm +// (simpleUpdate). +func simpleMakeTable(poly uint32) *Table { + t := new(Table) + simplePopulateTable(poly, t) + return t +} + +// simplePopulateTable constructs a Table for the specified polynomial, suitable +// for use with simpleUpdate. +func simplePopulateTable(poly uint32, t *Table) { + for i := 0; i < 256; i++ { + crc := uint32(i) + for j := 0; j < 8; j++ { + if crc&1 == 1 { + crc = (crc >> 1) ^ poly + } else { + crc >>= 1 + } + } + t[i] = crc + } +} + +// simpleUpdate uses the simple algorithm to update the CRC, given a table that +// was previously computed using simpleMakeTable. +func simpleUpdate(crc uint32, tab *Table, p []byte) uint32 { + crc = ^crc + for _, v := range p { + crc = tab[byte(crc)^v] ^ (crc >> 8) + } + return ^crc +} + +// Use slicing-by-8 when payload >= this value. +const slicing8Cutoff = 16 + +// slicing8Table is array of 8 Tables, used by the slicing-by-8 algorithm. +type slicing8Table [8]Table + +// slicingMakeTable constructs a slicing8Table for the specified polynomial. The +// table is suitable for use with the slicing-by-8 algorithm (slicingUpdate). +func slicingMakeTable(poly uint32) *slicing8Table { + t := new(slicing8Table) + simplePopulateTable(poly, &t[0]) + for i := 0; i < 256; i++ { + crc := t[0][i] + for j := 1; j < 8; j++ { + crc = t[0][crc&0xFF] ^ (crc >> 8) + t[j][i] = crc + } + } + return t +} + +// slicingUpdate uses the slicing-by-8 algorithm to update the CRC, given a +// table that was previously computed using slicingMakeTable. +func slicingUpdate(crc uint32, tab *slicing8Table, p []byte) uint32 { + if len(p) >= slicing8Cutoff { + crc = ^crc + for len(p) > 8 { + crc ^= uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24 + crc = tab[0][p[7]] ^ tab[1][p[6]] ^ tab[2][p[5]] ^ tab[3][p[4]] ^ + tab[4][crc>>24] ^ tab[5][(crc>>16)&0xFF] ^ + tab[6][(crc>>8)&0xFF] ^ tab[7][crc&0xFF] + p = p[8:] + } + crc = ^crc + } + if len(p) == 0 { + return crc + } + return simpleUpdate(crc, &tab[0], p) +} diff --git a/vendor/src/github.com/klauspost/crc32/crc32_otherarch.go b/vendor/src/github.com/klauspost/crc32/crc32_otherarch.go new file mode 100644 index 00000000..cc960764 --- /dev/null +++ b/vendor/src/github.com/klauspost/crc32/crc32_otherarch.go @@ -0,0 +1,15 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64,!amd64p32,!s390x + +package crc32 + +func archAvailableIEEE() bool { return false } +func archInitIEEE() { panic("not available") } +func archUpdateIEEE(crc uint32, p []byte) uint32 { panic("not available") } + +func archAvailableCastagnoli() bool { return false } +func archInitCastagnoli() { panic("not available") } +func archUpdateCastagnoli(crc uint32, p []byte) uint32 { panic("not available") } diff --git a/vendor/src/github.com/klauspost/crc32/crc32_s390x.go b/vendor/src/github.com/klauspost/crc32/crc32_s390x.go new file mode 100644 index 00000000..ce96f032 --- /dev/null +++ b/vendor/src/github.com/klauspost/crc32/crc32_s390x.go @@ -0,0 +1,91 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build s390x + +package crc32 + +const ( + vxMinLen = 64 + vxAlignMask = 15 // align to 16 bytes +) + +// hasVectorFacility reports whether the machine has the z/Architecture +// vector facility installed and enabled. +func hasVectorFacility() bool + +var hasVX = hasVectorFacility() + +// vectorizedCastagnoli implements CRC32 using vector instructions. +// It is defined in crc32_s390x.s. +//go:noescape +func vectorizedCastagnoli(crc uint32, p []byte) uint32 + +// vectorizedIEEE implements CRC32 using vector instructions. +// It is defined in crc32_s390x.s. +//go:noescape +func vectorizedIEEE(crc uint32, p []byte) uint32 + +func archAvailableCastagnoli() bool { + return hasVX +} + +var archCastagnoliTable8 *slicing8Table + +func archInitCastagnoli() { + if !hasVX { + panic("not available") + } + // We still use slicing-by-8 for small buffers. + archCastagnoliTable8 = slicingMakeTable(Castagnoli) +} + +// archUpdateCastagnoli calculates the checksum of p using +// vectorizedCastagnoli. +func archUpdateCastagnoli(crc uint32, p []byte) uint32 { + if !hasVX { + panic("not available") + } + // Use vectorized function if data length is above threshold. + if len(p) >= vxMinLen { + aligned := len(p) & ^vxAlignMask + crc = vectorizedCastagnoli(crc, p[:aligned]) + p = p[aligned:] + } + if len(p) == 0 { + return crc + } + return slicingUpdate(crc, archCastagnoliTable8, p) +} + +func archAvailableIEEE() bool { + return hasVX +} + +var archIeeeTable8 *slicing8Table + +func archInitIEEE() { + if !hasVX { + panic("not available") + } + // We still use slicing-by-8 for small buffers. + archIeeeTable8 = slicingMakeTable(IEEE) +} + +// archUpdateIEEE calculates the checksum of p using vectorizedIEEE. +func archUpdateIEEE(crc uint32, p []byte) uint32 { + if !hasVX { + panic("not available") + } + // Use vectorized function if data length is above threshold. + if len(p) >= vxMinLen { + aligned := len(p) & ^vxAlignMask + crc = vectorizedIEEE(crc, p[:aligned]) + p = p[aligned:] + } + if len(p) == 0 { + return crc + } + return slicingUpdate(crc, archIeeeTable8, p) +} diff --git a/vendor/src/github.com/klauspost/crc32/crc32_s390x.s b/vendor/src/github.com/klauspost/crc32/crc32_s390x.s new file mode 100644 index 00000000..e980ca29 --- /dev/null +++ b/vendor/src/github.com/klauspost/crc32/crc32_s390x.s @@ -0,0 +1,249 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build s390x + +#include "textflag.h" + +// Vector register range containing CRC-32 constants + +#define CONST_PERM_LE2BE V9 +#define CONST_R2R1 V10 +#define CONST_R4R3 V11 +#define CONST_R5 V12 +#define CONST_RU_POLY V13 +#define CONST_CRC_POLY V14 + +// The CRC-32 constant block contains reduction constants to fold and +// process particular chunks of the input data stream in parallel. +// +// Note that the constant definitions below are extended in order to compute +// intermediate results with a single VECTOR GALOIS FIELD MULTIPLY instruction. +// The rightmost doubleword can be 0 to prevent contribution to the result or +// can be multiplied by 1 to perform an XOR without the need for a separate +// VECTOR EXCLUSIVE OR instruction. +// +// The polynomials used are bit-reflected: +// +// IEEE: P'(x) = 0x0edb88320 +// Castagnoli: P'(x) = 0x082f63b78 + +// IEEE polynomial constants +DATA ·crcleconskp+0(SB)/8, $0x0F0E0D0C0B0A0908 // LE-to-BE mask +DATA ·crcleconskp+8(SB)/8, $0x0706050403020100 +DATA ·crcleconskp+16(SB)/8, $0x00000001c6e41596 // R2 +DATA ·crcleconskp+24(SB)/8, $0x0000000154442bd4 // R1 +DATA ·crcleconskp+32(SB)/8, $0x00000000ccaa009e // R4 +DATA ·crcleconskp+40(SB)/8, $0x00000001751997d0 // R3 +DATA ·crcleconskp+48(SB)/8, $0x0000000000000000 +DATA ·crcleconskp+56(SB)/8, $0x0000000163cd6124 // R5 +DATA ·crcleconskp+64(SB)/8, $0x0000000000000000 +DATA ·crcleconskp+72(SB)/8, $0x00000001F7011641 // u' +DATA ·crcleconskp+80(SB)/8, $0x0000000000000000 +DATA ·crcleconskp+88(SB)/8, $0x00000001DB710641 // P'(x) << 1 + +GLOBL ·crcleconskp(SB), RODATA, $144 + +// Castagonli Polynomial constants +DATA ·crccleconskp+0(SB)/8, $0x0F0E0D0C0B0A0908 // LE-to-BE mask +DATA ·crccleconskp+8(SB)/8, $0x0706050403020100 +DATA ·crccleconskp+16(SB)/8, $0x000000009e4addf8 // R2 +DATA ·crccleconskp+24(SB)/8, $0x00000000740eef02 // R1 +DATA ·crccleconskp+32(SB)/8, $0x000000014cd00bd6 // R4 +DATA ·crccleconskp+40(SB)/8, $0x00000000f20c0dfe // R3 +DATA ·crccleconskp+48(SB)/8, $0x0000000000000000 +DATA ·crccleconskp+56(SB)/8, $0x00000000dd45aab8 // R5 +DATA ·crccleconskp+64(SB)/8, $0x0000000000000000 +DATA ·crccleconskp+72(SB)/8, $0x00000000dea713f1 // u' +DATA ·crccleconskp+80(SB)/8, $0x0000000000000000 +DATA ·crccleconskp+88(SB)/8, $0x0000000105ec76f0 // P'(x) << 1 + +GLOBL ·crccleconskp(SB), RODATA, $144 + +// func hasVectorFacility() bool +TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1 + MOVD $x-24(SP), R1 + XC $24, 0(R1), 0(R1) // clear the storage + MOVD $2, R0 // R0 is the number of double words stored -1 + WORD $0xB2B01000 // STFLE 0(R1) + XOR R0, R0 // reset the value of R0 + MOVBZ z-8(SP), R1 + AND $0x40, R1 + BEQ novector + +vectorinstalled: + // check if the vector instruction has been enabled + VLEIB $0, $0xF, V16 + VLGVB $0, V16, R1 + CMPBNE R1, $0xF, novector + MOVB $1, ret+0(FP) // have vx + RET + +novector: + MOVB $0, ret+0(FP) // no vx + RET + +// The CRC-32 function(s) use these calling conventions: +// +// Parameters: +// +// R2: Initial CRC value, typically ~0; and final CRC (return) value. +// R3: Input buffer pointer, performance might be improved if the +// buffer is on a doubleword boundary. +// R4: Length of the buffer, must be 64 bytes or greater. +// +// Register usage: +// +// R5: CRC-32 constant pool base pointer. +// V0: Initial CRC value and intermediate constants and results. +// V1..V4: Data for CRC computation. +// V5..V8: Next data chunks that are fetched from the input buffer. +// +// V9..V14: CRC-32 constants. + +// func vectorizedIEEE(crc uint32, p []byte) uint32 +TEXT ·vectorizedIEEE(SB), NOSPLIT, $0 + MOVWZ crc+0(FP), R2 // R2 stores the CRC value + MOVD p+8(FP), R3 // data pointer + MOVD p_len+16(FP), R4 // len(p) + + MOVD $·crcleconskp(SB), R5 + BR vectorizedBody<>(SB) + +// func vectorizedCastagnoli(crc uint32, p []byte) uint32 +TEXT ·vectorizedCastagnoli(SB), NOSPLIT, $0 + MOVWZ crc+0(FP), R2 // R2 stores the CRC value + MOVD p+8(FP), R3 // data pointer + MOVD p_len+16(FP), R4 // len(p) + + // R5: crc-32 constant pool base pointer, constant is used to reduce crc + MOVD $·crccleconskp(SB), R5 + BR vectorizedBody<>(SB) + +TEXT vectorizedBody<>(SB), NOSPLIT, $0 + XOR $0xffffffff, R2 // NOTW R2 + VLM 0(R5), CONST_PERM_LE2BE, CONST_CRC_POLY + + // Load the initial CRC value into the rightmost word of V0 + VZERO V0 + VLVGF $3, R2, V0 + + // Crash if the input size is less than 64-bytes. + CMP R4, $64 + BLT crash + + // Load a 64-byte data chunk and XOR with CRC + VLM 0(R3), V1, V4 // 64-bytes into V1..V4 + + // Reflect the data if the CRC operation is in the bit-reflected domain + VPERM V1, V1, CONST_PERM_LE2BE, V1 + VPERM V2, V2, CONST_PERM_LE2BE, V2 + VPERM V3, V3, CONST_PERM_LE2BE, V3 + VPERM V4, V4, CONST_PERM_LE2BE, V4 + + VX V0, V1, V1 // V1 ^= CRC + ADD $64, R3 // BUF = BUF + 64 + ADD $(-64), R4 + + // Check remaining buffer size and jump to proper folding method + CMP R4, $64 + BLT less_than_64bytes + +fold_64bytes_loop: + // Load the next 64-byte data chunk into V5 to V8 + VLM 0(R3), V5, V8 + VPERM V5, V5, CONST_PERM_LE2BE, V5 + VPERM V6, V6, CONST_PERM_LE2BE, V6 + VPERM V7, V7, CONST_PERM_LE2BE, V7 + VPERM V8, V8, CONST_PERM_LE2BE, V8 + + // Perform a GF(2) multiplication of the doublewords in V1 with + // the reduction constants in V0. The intermediate result is + // then folded (accumulated) with the next data chunk in V5 and + // stored in V1. Repeat this step for the register contents + // in V2, V3, and V4 respectively. + + VGFMAG CONST_R2R1, V1, V5, V1 + VGFMAG CONST_R2R1, V2, V6, V2 + VGFMAG CONST_R2R1, V3, V7, V3 + VGFMAG CONST_R2R1, V4, V8, V4 + + // Adjust buffer pointer and length for next loop + ADD $64, R3 // BUF = BUF + 64 + ADD $(-64), R4 // LEN = LEN - 64 + + CMP R4, $64 + BGE fold_64bytes_loop + +less_than_64bytes: + // Fold V1 to V4 into a single 128-bit value in V1 + VGFMAG CONST_R4R3, V1, V2, V1 + VGFMAG CONST_R4R3, V1, V3, V1 + VGFMAG CONST_R4R3, V1, V4, V1 + + // Check whether to continue with 64-bit folding + CMP R4, $16 + BLT final_fold + +fold_16bytes_loop: + VL 0(R3), V2 // Load next data chunk + VPERM V2, V2, CONST_PERM_LE2BE, V2 + + VGFMAG CONST_R4R3, V1, V2, V1 // Fold next data chunk + + // Adjust buffer pointer and size for folding next data chunk + ADD $16, R3 + ADD $-16, R4 + + // Process remaining data chunks + CMP R4, $16 + BGE fold_16bytes_loop + +final_fold: + VLEIB $7, $0x40, V9 + VSRLB V9, CONST_R4R3, V0 + VLEIG $0, $1, V0 + + VGFMG V0, V1, V1 + + VLEIB $7, $0x20, V9 // Shift by words + VSRLB V9, V1, V2 // Store remaining bits in V2 + VUPLLF V1, V1 // Split rightmost doubleword + VGFMAG CONST_R5, V1, V2, V1 // V1 = (V1 * R5) XOR V2 + + // The input values to the Barret reduction are the degree-63 polynomial + // in V1 (R(x)), degree-32 generator polynomial, and the reduction + // constant u. The Barret reduction result is the CRC value of R(x) mod + // P(x). + // + // The Barret reduction algorithm is defined as: + // + // 1. T1(x) = floor( R(x) / x^32 ) GF2MUL u + // 2. T2(x) = floor( T1(x) / x^32 ) GF2MUL P(x) + // 3. C(x) = R(x) XOR T2(x) mod x^32 + // + // Note: To compensate the division by x^32, use the vector unpack + // instruction to move the leftmost word into the leftmost doubleword + // of the vector register. The rightmost doubleword is multiplied + // with zero to not contribute to the intermedate results. + + // T1(x) = floor( R(x) / x^32 ) GF2MUL u + VUPLLF V1, V2 + VGFMG CONST_RU_POLY, V2, V2 + + // Compute the GF(2) product of the CRC polynomial in VO with T1(x) in + // V2 and XOR the intermediate result, T2(x), with the value in V1. + // The final result is in the rightmost word of V2. + + VUPLLF V2, V2 + VGFMAG CONST_CRC_POLY, V2, V1, V2 + +done: + VLGVF $2, V2, R2 + XOR $0xffffffff, R2 // NOTW R2 + MOVWZ R2, ret + 32(FP) + RET + +crash: + MOVD $0, (R0) // input size is less than 64-bytes diff --git a/vendor/src/github.com/klauspost/crc32/crc32_test.go b/vendor/src/github.com/klauspost/crc32/crc32_test.go new file mode 100644 index 00000000..03994363 --- /dev/null +++ b/vendor/src/github.com/klauspost/crc32/crc32_test.go @@ -0,0 +1,284 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package crc32 + +import ( + crand "crypto/rand" + "hash" + mrand "math/rand" + "testing" +) + +type test struct { + ieee, castagnoli uint32 + in string +} + +var golden = []test{ + {0x0, 0x0, ""}, + {0xe8b7be43, 0xc1d04330, "a"}, + {0x9e83486d, 0xe2a22936, "ab"}, + {0x352441c2, 0x364b3fb7, "abc"}, + {0xed82cd11, 0x92c80a31, "abcd"}, + {0x8587d865, 0xc450d697, "abcde"}, + {0x4b8e39ef, 0x53bceff1, "abcdef"}, + {0x312a6aa6, 0xe627f441, "abcdefg"}, + {0xaeef2a50, 0xa9421b7, "abcdefgh"}, + {0x8da988af, 0x2ddc99fc, "abcdefghi"}, + {0x3981703a, 0xe6599437, "abcdefghij"}, + {0x6b9cdfe7, 0xb2cc01fe, "Discard medicine more than two years old."}, + {0xc90ef73f, 0xe28207f, "He who has a shady past knows that nice guys finish last."}, + {0xb902341f, 0xbe93f964, "I wouldn't marry him with a ten foot pole."}, + {0x42080e8, 0x9e3be0c3, "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"}, + {0x154c6d11, 0xf505ef04, "The days of the digital watch are numbered. -Tom Stoppard"}, + {0x4c418325, 0x85d3dc82, "Nepal premier won't resign."}, + {0x33955150, 0xc5142380, "For every action there is an equal and opposite government program."}, + {0x26216a4b, 0x75eb77dd, "His money is twice tainted: 'taint yours and 'taint mine."}, + {0x1abbe45e, 0x91ebe9f7, "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"}, + {0xc89a94f7, 0xf0b1168e, "It's a tiny change to the code and not completely disgusting. - Bob Manchek"}, + {0xab3abe14, 0x572b74e2, "size: a.out: bad magic"}, + {0xbab102b6, 0x8a58a6d5, "The major problem is with sendmail. -Mark Horton"}, + {0x999149d7, 0x9c426c50, "Give me a rock, paper and scissors and I will move the world. CCFestoon"}, + {0x6d52a33c, 0x735400a4, "If the enemy is within range, then so are you."}, + {0x90631e8d, 0xbec49c95, "It's well we cannot hear the screams/That we create in others' dreams."}, + {0x78309130, 0xa95a2079, "You remind me of a TV show, but that's all right: I watch it anyway."}, + {0x7d0a377f, 0xde2e65c5, "C is as portable as Stonehedge!!"}, + {0x8c79fd79, 0x297a88ed, "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"}, + {0xa20b7167, 0x66ed1d8b, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"}, + {0x8e0bb443, 0xdcded527, "How can you write a big system without C++? -Paul Glick"}, +} + +// testGoldenIEEE verifies that the given function returns +// correct IEEE checksums. +func testGoldenIEEE(t *testing.T, crcFunc func(b []byte) uint32) { + for _, g := range golden { + if crc := crcFunc([]byte(g.in)); crc != g.ieee { + t.Errorf("IEEE(%s) = 0x%x want 0x%x", g.in, crc, g.ieee) + } + } +} + +// testGoldenCastagnoli verifies that the given function returns +// correct IEEE checksums. +func testGoldenCastagnoli(t *testing.T, crcFunc func(b []byte) uint32) { + for _, g := range golden { + if crc := crcFunc([]byte(g.in)); crc != g.castagnoli { + t.Errorf("Castagnoli(%s) = 0x%x want 0x%x", g.in, crc, g.castagnoli) + } + } +} + +// testCrossCheck generates random buffers of various lengths and verifies that +// the two "update" functions return the same result. +func testCrossCheck(t *testing.T, crcFunc1, crcFunc2 func(crc uint32, b []byte) uint32) { + // The AMD64 implementation has some cutoffs at lengths 168*3=504 and + // 1344*3=4032. We should make sure lengths around these values are in the + // list. + lengths := []int{0, 1, 2, 3, 4, 5, 10, 16, 50, 100, 128, + 500, 501, 502, 503, 504, 505, 512, 1000, 1024, 2000, + 4030, 4031, 4032, 4033, 4036, 4040, 4048, 4096, 5000, 10000} + for _, length := range lengths { + p := make([]byte, length) + _, _ = crand.Read(p) + crcInit := uint32(mrand.Int63()) + crc1 := crcFunc1(crcInit, p) + crc2 := crcFunc2(crcInit, p) + if crc1 != crc2 { + t.Errorf("mismatch: 0x%x vs 0x%x (buffer length %d)", crc1, crc2, length) + } + } +} + +// TestSimple tests the simple generic algorithm. +func TestSimple(t *testing.T) { + tab := simpleMakeTable(IEEE) + testGoldenIEEE(t, func(b []byte) uint32 { + return simpleUpdate(0, tab, b) + }) + + tab = simpleMakeTable(Castagnoli) + testGoldenCastagnoli(t, func(b []byte) uint32 { + return simpleUpdate(0, tab, b) + }) +} + +// TestSimple tests the slicing-by-8 algorithm. +func TestSlicing(t *testing.T) { + tab := slicingMakeTable(IEEE) + testGoldenIEEE(t, func(b []byte) uint32 { + return slicingUpdate(0, tab, b) + }) + + tab = slicingMakeTable(Castagnoli) + testGoldenCastagnoli(t, func(b []byte) uint32 { + return slicingUpdate(0, tab, b) + }) + + // Cross-check various polys against the simple algorithm. + for _, poly := range []uint32{IEEE, Castagnoli, Koopman, 0xD5828281} { + t1 := simpleMakeTable(poly) + f1 := func(crc uint32, b []byte) uint32 { + return simpleUpdate(crc, t1, b) + } + t2 := slicingMakeTable(poly) + f2 := func(crc uint32, b []byte) uint32 { + return slicingUpdate(crc, t2, b) + } + testCrossCheck(t, f1, f2) + } +} + +func TestArchIEEE(t *testing.T) { + if !archAvailableIEEE() { + t.Skip("Arch-specific IEEE not available.") + } + archInitIEEE() + slicingTable := slicingMakeTable(IEEE) + testCrossCheck(t, archUpdateIEEE, func(crc uint32, b []byte) uint32 { + return slicingUpdate(crc, slicingTable, b) + }) +} + +func TestArchCastagnoli(t *testing.T) { + if !archAvailableCastagnoli() { + t.Skip("Arch-specific Castagnoli not available.") + } + archInitCastagnoli() + slicingTable := slicingMakeTable(Castagnoli) + testCrossCheck(t, archUpdateCastagnoli, func(crc uint32, b []byte) uint32 { + return slicingUpdate(crc, slicingTable, b) + }) +} + +func TestGolden(t *testing.T) { + testGoldenIEEE(t, ChecksumIEEE) + + // Some implementations have special code to deal with misaligned + // data; test that as well. + for delta := 1; delta <= 7; delta++ { + testGoldenIEEE(t, func(b []byte) uint32 { + ieee := NewIEEE() + d := delta + if d >= len(b) { + d = len(b) + } + ieee.Write(b[:d]) + ieee.Write(b[d:]) + return ieee.Sum32() + }) + } + + castagnoliTab := MakeTable(Castagnoli) + if castagnoliTab == nil { + t.Errorf("nil Castagnoli Table") + } + + testGoldenCastagnoli(t, func(b []byte) uint32 { + castagnoli := New(castagnoliTab) + castagnoli.Write(b) + return castagnoli.Sum32() + }) + + // Some implementations have special code to deal with misaligned + // data; test that as well. + for delta := 1; delta <= 7; delta++ { + testGoldenCastagnoli(t, func(b []byte) uint32 { + castagnoli := New(castagnoliTab) + d := delta + if d >= len(b) { + d = len(b) + } + castagnoli.Write(b[:d]) + castagnoli.Write(b[d:]) + return castagnoli.Sum32() + }) + } +} + +func BenchmarkIEEECrc40B(b *testing.B) { + benchmark(b, NewIEEE(), 40, 0) +} + +func BenchmarkIEEECrc1KB(b *testing.B) { + benchmark(b, NewIEEE(), 1<<10, 0) +} + +func BenchmarkIEEECrc4KB(b *testing.B) { + benchmark(b, NewIEEE(), 4<<10, 0) +} + +func BenchmarkIEEECrc32KB(b *testing.B) { + benchmark(b, NewIEEE(), 32<<10, 0) +} + +func BenchmarkCastagnoliCrc15B(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 15, 0) +} + +func BenchmarkCastagnoliCrc15BMisaligned(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 15, 1) +} + +func BenchmarkCastagnoliCrc40B(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 40, 0) +} + +func BenchmarkCastagnoliCrc40BMisaligned(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 40, 1) +} + +func BenchmarkCastagnoliCrc512(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 512, 0) +} + +func BenchmarkCastagnoliCrc512Misaligned(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 512, 1) +} + +func BenchmarkCastagnoliCrc1KB(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 1<<10, 0) +} + +func BenchmarkCastagnoliCrc1KBMisaligned(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 1<<10, 1) +} + +func BenchmarkCastagnoliCrc4KB(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 4<<10, 0) +} + +func BenchmarkCastagnoliCrc4KBMisaligned(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 4<<10, 1) +} + +func BenchmarkCastagnoliCrc32KB(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 32<<10, 0) +} + +func BenchmarkCastagnoliCrc32KBMisaligned(b *testing.B) { + benchmark(b, New(MakeTable(Castagnoli)), 32<<10, 1) +} + +func benchmark(b *testing.B, h hash.Hash32, n, alignment int64) { + b.SetBytes(n) + data := make([]byte, n+alignment) + data = data[alignment:] + for i := range data { + data[i] = byte(i) + } + in := make([]byte, 0, h.Size()) + + // Warm up + h.Reset() + h.Write(data) + h.Sum(in) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + h.Reset() + h.Write(data) + h.Sum(in) + } +} diff --git a/vendor/src/github.com/klauspost/crc32/example_test.go b/vendor/src/github.com/klauspost/crc32/example_test.go new file mode 100644 index 00000000..621bf838 --- /dev/null +++ b/vendor/src/github.com/klauspost/crc32/example_test.go @@ -0,0 +1,28 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package crc32_test + +import ( + "fmt" + "hash/crc32" +) + +func ExampleMakeTable() { + // In this package, the CRC polynomial is represented in reversed notation, + // or LSB-first representation. + // + // LSB-first representation is a hexadecimal number with n bits, in which the + // most significant bit represents the coefficient of xâ° and the least significant + // bit represents the coefficient of xâ¿â»Â¹ (the coefficient for xâ¿ is implicit). + // + // For example, CRC32-Q, as defined by the following polynomial, + // x³²+ x³¹+ x²â´+ x²²+ x¹â¶+ x¹â´+ xâ¸+ xâ·+ xâµ+ x³+ x¹+ xâ° + // has the reversed notation 0b11010101100000101000001010000001, so the value + // that should be passed to MakeTable is 0xD5828281. + crc32q := crc32.MakeTable(0xD5828281) + fmt.Printf("%08x\n", crc32.Checksum([]byte("Hello world"), crc32q)) + // Output: + // 2964d064 +} diff --git a/vendor/src/github.com/lib/pq/CONTRIBUTING.md b/vendor/src/github.com/lib/pq/CONTRIBUTING.md new file mode 100644 index 00000000..84c937f1 --- /dev/null +++ b/vendor/src/github.com/lib/pq/CONTRIBUTING.md @@ -0,0 +1,29 @@ +## Contributing to pq + +`pq` has a backlog of pull requests, but contributions are still very +much welcome. You can help with patch review, submitting bug reports, +or adding new functionality. There is no formal style guide, but +please conform to the style of existing code and general Go formatting +conventions when submitting patches. + +### Patch review + +Help review existing open pull requests by commenting on the code or +proposed functionality. + +### Bug reports + +We appreciate any bug reports, but especially ones with self-contained +(doesn't depend on code outside of pq), minimal (can't be simplified +further) test cases. It's especially helpful if you can submit a pull +request with just the failing test case (you'll probably want to +pattern it after the tests in +[conn_test.go](https://github.com/lib/pq/blob/master/conn_test.go). + +### New functionality + +There are a number of pending patches for new functionality, so +additional feature patches will take a while to merge. Still, patches +are generally reviewed based on usefulness and complexity in addition +to time-in-queue, so if you have a knockout idea, take a shot. Feel +free to open an issue discussion your proposed patch beforehand. diff --git a/vendor/src/github.com/lib/pq/LICENSE.md b/vendor/src/github.com/lib/pq/LICENSE.md new file mode 100644 index 00000000..5773904a --- /dev/null +++ b/vendor/src/github.com/lib/pq/LICENSE.md @@ -0,0 +1,8 @@ +Copyright (c) 2011-2013, 'pq' Contributors +Portions Copyright (C) 2011 Blake Mizerany + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/src/github.com/lib/pq/README.md b/vendor/src/github.com/lib/pq/README.md new file mode 100644 index 00000000..5eb9e144 --- /dev/null +++ b/vendor/src/github.com/lib/pq/README.md @@ -0,0 +1,105 @@ +# pq - A pure Go postgres driver for Go's database/sql package + +[![Build Status](https://travis-ci.org/lib/pq.png?branch=master)](https://travis-ci.org/lib/pq) + +## Install + + go get github.com/lib/pq + +## Docs + +For detailed documentation and basic usage examples, please see the package +documentation at . + +## Tests + +`go test` is used for testing. A running PostgreSQL server is +required, with the ability to log in. The default database to connect +to test with is "pqgotest," but it can be overridden using environment +variables. + +Example: + + PGHOST=/run/postgresql go test github.com/lib/pq + +Optionally, a benchmark suite can be run as part of the tests: + + PGHOST=/run/postgresql go test -bench . + +## Features + +* SSL +* Handles bad connections for `database/sql` +* Scan `time.Time` correctly (i.e. `timestamp[tz]`, `time[tz]`, `date`) +* Scan binary blobs correctly (i.e. `bytea`) +* Package for `hstore` support +* COPY FROM support +* pq.ParseURL for converting urls to connection strings for sql.Open. +* Many libpq compatible environment variables +* Unix socket support +* Notifications: `LISTEN`/`NOTIFY` +* pgpass support + +## Future / Things you can help with + +* Better COPY FROM / COPY TO (see discussion in #181) + +## Thank you (alphabetical) + +Some of these contributors are from the original library `bmizerany/pq.go` whose +code still exists in here. + +* Andy Balholm (andybalholm) +* Ben Berkert (benburkert) +* Benjamin Heatwole (bheatwole) +* Bill Mill (llimllib) +* Bjørn Madsen (aeons) +* Blake Gentry (bgentry) +* Brad Fitzpatrick (bradfitz) +* Charlie Melbye (cmelbye) +* Chris Bandy (cbandy) +* Chris Gilling (cgilling) +* Chris Walsh (cwds) +* Dan Sosedoff (sosedoff) +* Daniel Farina (fdr) +* Eric Chlebek (echlebek) +* Eric Garrido (minusnine) +* Eric Urban (hydrogen18) +* Everyone at The Go Team +* Evan Shaw (edsrzf) +* Ewan Chou (coocood) +* Fazal Majid (fazalmajid) +* Federico Romero (federomero) +* Fumin (fumin) +* Gary Burd (garyburd) +* Heroku (heroku) +* James Pozdena (jpoz) +* Jason McVetta (jmcvetta) +* Jeremy Jay (pbnjay) +* Joakim Sernbrant (serbaut) +* John Gallagher (jgallagher) +* Jonathan Rudenberg (titanous) +* Joël Stemmer (jstemmer) +* Kamil Kisiel (kisielk) +* Kelly Dunn (kellydunn) +* Keith Rarick (kr) +* Kir Shatrov (kirs) +* Lann Martin (lann) +* Maciek Sakrejda (uhoh-itsmaciek) +* Marc Brinkmann (mbr) +* Marko Tiikkaja (johto) +* Matt Newberry (MattNewberry) +* Matt Robenolt (mattrobenolt) +* Martin Olsen (martinolsen) +* Mike Lewis (mikelikespie) +* Nicolas Patry (Narsil) +* Oliver Tonnhofer (olt) +* Patrick Hayes (phayes) +* Paul Hammond (paulhammond) +* Ryan Smith (ryandotsmith) +* Samuel Stauffer (samuel) +* Timothée Peignier (cyberdelia) +* Travis Cline (tmc) +* TruongSinh Tran-Nguyen (truongsinh) +* Yaismel Miranda (ympons) +* notedit (notedit) diff --git a/vendor/src/github.com/lib/pq/array.go b/vendor/src/github.com/lib/pq/array.go new file mode 100644 index 00000000..e7b2145d --- /dev/null +++ b/vendor/src/github.com/lib/pq/array.go @@ -0,0 +1,756 @@ +package pq + +import ( + "bytes" + "database/sql" + "database/sql/driver" + "encoding/hex" + "fmt" + "reflect" + "strconv" + "strings" +) + +var typeByteSlice = reflect.TypeOf([]byte{}) +var typeDriverValuer = reflect.TypeOf((*driver.Valuer)(nil)).Elem() +var typeSqlScanner = reflect.TypeOf((*sql.Scanner)(nil)).Elem() + +// Array returns the optimal driver.Valuer and sql.Scanner for an array or +// slice of any dimension. +// +// For example: +// db.Query(`SELECT * FROM t WHERE id = ANY($1)`, pq.Array([]int{235, 401})) +// +// var x []sql.NullInt64 +// db.QueryRow('SELECT ARRAY[235, 401]').Scan(pq.Array(&x)) +// +// Scanning multi-dimensional arrays is not supported. Arrays where the lower +// bound is not one (such as `[0:0]={1}') are not supported. +func Array(a interface{}) interface { + driver.Valuer + sql.Scanner +} { + switch a := a.(type) { + case []bool: + return (*BoolArray)(&a) + case []float64: + return (*Float64Array)(&a) + case []int64: + return (*Int64Array)(&a) + case []string: + return (*StringArray)(&a) + + case *[]bool: + return (*BoolArray)(a) + case *[]float64: + return (*Float64Array)(a) + case *[]int64: + return (*Int64Array)(a) + case *[]string: + return (*StringArray)(a) + } + + return GenericArray{a} +} + +// ArrayDelimiter may be optionally implemented by driver.Valuer or sql.Scanner +// to override the array delimiter used by GenericArray. +type ArrayDelimiter interface { + // ArrayDelimiter returns the delimiter character(s) for this element's type. + ArrayDelimiter() string +} + +// BoolArray represents a one-dimensional array of the PostgreSQL boolean type. +type BoolArray []bool + +// Scan implements the sql.Scanner interface. +func (a *BoolArray) Scan(src interface{}) error { + switch src := src.(type) { + case []byte: + return a.scanBytes(src) + case string: + return a.scanBytes([]byte(src)) + case nil: + *a = nil + return nil + } + + return fmt.Errorf("pq: cannot convert %T to BoolArray", src) +} + +func (a *BoolArray) scanBytes(src []byte) error { + elems, err := scanLinearArray(src, []byte{','}, "BoolArray") + if err != nil { + return err + } + if *a != nil && len(elems) == 0 { + *a = (*a)[:0] + } else { + b := make(BoolArray, len(elems)) + for i, v := range elems { + if len(v) != 1 { + return fmt.Errorf("pq: could not parse boolean array index %d: invalid boolean %q", i, v) + } + switch v[0] { + case 't': + b[i] = true + case 'f': + b[i] = false + default: + return fmt.Errorf("pq: could not parse boolean array index %d: invalid boolean %q", i, v) + } + } + *a = b + } + return nil +} + +// Value implements the driver.Valuer interface. +func (a BoolArray) Value() (driver.Value, error) { + if a == nil { + return nil, nil + } + + if n := len(a); n > 0 { + // There will be exactly two curly brackets, N bytes of values, + // and N-1 bytes of delimiters. + b := make([]byte, 1+2*n) + + for i := 0; i < n; i++ { + b[2*i] = ',' + if a[i] { + b[1+2*i] = 't' + } else { + b[1+2*i] = 'f' + } + } + + b[0] = '{' + b[2*n] = '}' + + return string(b), nil + } + + return "{}", nil +} + +// ByteaArray represents a one-dimensional array of the PostgreSQL bytea type. +type ByteaArray [][]byte + +// Scan implements the sql.Scanner interface. +func (a *ByteaArray) Scan(src interface{}) error { + switch src := src.(type) { + case []byte: + return a.scanBytes(src) + case string: + return a.scanBytes([]byte(src)) + case nil: + *a = nil + return nil + } + + return fmt.Errorf("pq: cannot convert %T to ByteaArray", src) +} + +func (a *ByteaArray) scanBytes(src []byte) error { + elems, err := scanLinearArray(src, []byte{','}, "ByteaArray") + if err != nil { + return err + } + if *a != nil && len(elems) == 0 { + *a = (*a)[:0] + } else { + b := make(ByteaArray, len(elems)) + for i, v := range elems { + b[i], err = parseBytea(v) + if err != nil { + return fmt.Errorf("could not parse bytea array index %d: %s", i, err.Error()) + } + } + *a = b + } + return nil +} + +// Value implements the driver.Valuer interface. It uses the "hex" format which +// is only supported on PostgreSQL 9.0 or newer. +func (a ByteaArray) Value() (driver.Value, error) { + if a == nil { + return nil, nil + } + + if n := len(a); n > 0 { + // There will be at least two curly brackets, 2*N bytes of quotes, + // 3*N bytes of hex formatting, and N-1 bytes of delimiters. + size := 1 + 6*n + for _, x := range a { + size += hex.EncodedLen(len(x)) + } + + b := make([]byte, size) + + for i, s := 0, b; i < n; i++ { + o := copy(s, `,"\\x`) + o += hex.Encode(s[o:], a[i]) + s[o] = '"' + s = s[o+1:] + } + + b[0] = '{' + b[size-1] = '}' + + return string(b), nil + } + + return "{}", nil +} + +// Float64Array represents a one-dimensional array of the PostgreSQL double +// precision type. +type Float64Array []float64 + +// Scan implements the sql.Scanner interface. +func (a *Float64Array) Scan(src interface{}) error { + switch src := src.(type) { + case []byte: + return a.scanBytes(src) + case string: + return a.scanBytes([]byte(src)) + case nil: + *a = nil + return nil + } + + return fmt.Errorf("pq: cannot convert %T to Float64Array", src) +} + +func (a *Float64Array) scanBytes(src []byte) error { + elems, err := scanLinearArray(src, []byte{','}, "Float64Array") + if err != nil { + return err + } + if *a != nil && len(elems) == 0 { + *a = (*a)[:0] + } else { + b := make(Float64Array, len(elems)) + for i, v := range elems { + if b[i], err = strconv.ParseFloat(string(v), 64); err != nil { + return fmt.Errorf("pq: parsing array element index %d: %v", i, err) + } + } + *a = b + } + return nil +} + +// Value implements the driver.Valuer interface. +func (a Float64Array) Value() (driver.Value, error) { + if a == nil { + return nil, nil + } + + if n := len(a); n > 0 { + // There will be at least two curly brackets, N bytes of values, + // and N-1 bytes of delimiters. + b := make([]byte, 1, 1+2*n) + b[0] = '{' + + b = strconv.AppendFloat(b, a[0], 'f', -1, 64) + for i := 1; i < n; i++ { + b = append(b, ',') + b = strconv.AppendFloat(b, a[i], 'f', -1, 64) + } + + return string(append(b, '}')), nil + } + + return "{}", nil +} + +// GenericArray implements the driver.Valuer and sql.Scanner interfaces for +// an array or slice of any dimension. +type GenericArray struct{ A interface{} } + +func (GenericArray) evaluateDestination(rt reflect.Type) (reflect.Type, func([]byte, reflect.Value) error, string) { + var assign func([]byte, reflect.Value) error + var del = "," + + // TODO calculate the assign function for other types + // TODO repeat this section on the element type of arrays or slices (multidimensional) + { + if reflect.PtrTo(rt).Implements(typeSqlScanner) { + // dest is always addressable because it is an element of a slice. + assign = func(src []byte, dest reflect.Value) (err error) { + ss := dest.Addr().Interface().(sql.Scanner) + if src == nil { + err = ss.Scan(nil) + } else { + err = ss.Scan(src) + } + return + } + goto FoundType + } + + assign = func([]byte, reflect.Value) error { + return fmt.Errorf("pq: scanning to %s is not implemented; only sql.Scanner", rt) + } + } + +FoundType: + + if ad, ok := reflect.Zero(rt).Interface().(ArrayDelimiter); ok { + del = ad.ArrayDelimiter() + } + + return rt, assign, del +} + +// Scan implements the sql.Scanner interface. +func (a GenericArray) Scan(src interface{}) error { + dpv := reflect.ValueOf(a.A) + switch { + case dpv.Kind() != reflect.Ptr: + return fmt.Errorf("pq: destination %T is not a pointer to array or slice", a.A) + case dpv.IsNil(): + return fmt.Errorf("pq: destination %T is nil", a.A) + } + + dv := dpv.Elem() + switch dv.Kind() { + case reflect.Slice: + case reflect.Array: + default: + return fmt.Errorf("pq: destination %T is not a pointer to array or slice", a.A) + } + + switch src := src.(type) { + case []byte: + return a.scanBytes(src, dv) + case string: + return a.scanBytes([]byte(src), dv) + case nil: + if dv.Kind() == reflect.Slice { + dv.Set(reflect.Zero(dv.Type())) + return nil + } + } + + return fmt.Errorf("pq: cannot convert %T to %s", src, dv.Type()) +} + +func (a GenericArray) scanBytes(src []byte, dv reflect.Value) error { + dtype, assign, del := a.evaluateDestination(dv.Type().Elem()) + dims, elems, err := parseArray(src, []byte(del)) + if err != nil { + return err + } + + // TODO allow multidimensional + + if len(dims) > 1 { + return fmt.Errorf("pq: scanning from multidimensional ARRAY%s is not implemented", + strings.Replace(fmt.Sprint(dims), " ", "][", -1)) + } + + // Treat a zero-dimensional array like an array with a single dimension of zero. + if len(dims) == 0 { + dims = append(dims, 0) + } + + for i, rt := 0, dv.Type(); i < len(dims); i, rt = i+1, rt.Elem() { + switch rt.Kind() { + case reflect.Slice: + case reflect.Array: + if rt.Len() != dims[i] { + return fmt.Errorf("pq: cannot convert ARRAY%s to %s", + strings.Replace(fmt.Sprint(dims), " ", "][", -1), dv.Type()) + } + default: + // TODO handle multidimensional + } + } + + values := reflect.MakeSlice(reflect.SliceOf(dtype), len(elems), len(elems)) + for i, e := range elems { + if err := assign(e, values.Index(i)); err != nil { + return fmt.Errorf("pq: parsing array element index %d: %v", i, err) + } + } + + // TODO handle multidimensional + + switch dv.Kind() { + case reflect.Slice: + dv.Set(values.Slice(0, dims[0])) + case reflect.Array: + for i := 0; i < dims[0]; i++ { + dv.Index(i).Set(values.Index(i)) + } + } + + return nil +} + +// Value implements the driver.Valuer interface. +func (a GenericArray) Value() (driver.Value, error) { + if a.A == nil { + return nil, nil + } + + rv := reflect.ValueOf(a.A) + + switch rv.Kind() { + case reflect.Slice: + if rv.IsNil() { + return nil, nil + } + case reflect.Array: + default: + return nil, fmt.Errorf("pq: Unable to convert %T to array", a.A) + } + + if n := rv.Len(); n > 0 { + // There will be at least two curly brackets, N bytes of values, + // and N-1 bytes of delimiters. + b := make([]byte, 0, 1+2*n) + + b, _, err := appendArray(b, rv, n) + return string(b), err + } + + return "{}", nil +} + +// Int64Array represents a one-dimensional array of the PostgreSQL integer types. +type Int64Array []int64 + +// Scan implements the sql.Scanner interface. +func (a *Int64Array) Scan(src interface{}) error { + switch src := src.(type) { + case []byte: + return a.scanBytes(src) + case string: + return a.scanBytes([]byte(src)) + case nil: + *a = nil + return nil + } + + return fmt.Errorf("pq: cannot convert %T to Int64Array", src) +} + +func (a *Int64Array) scanBytes(src []byte) error { + elems, err := scanLinearArray(src, []byte{','}, "Int64Array") + if err != nil { + return err + } + if *a != nil && len(elems) == 0 { + *a = (*a)[:0] + } else { + b := make(Int64Array, len(elems)) + for i, v := range elems { + if b[i], err = strconv.ParseInt(string(v), 10, 64); err != nil { + return fmt.Errorf("pq: parsing array element index %d: %v", i, err) + } + } + *a = b + } + return nil +} + +// Value implements the driver.Valuer interface. +func (a Int64Array) Value() (driver.Value, error) { + if a == nil { + return nil, nil + } + + if n := len(a); n > 0 { + // There will be at least two curly brackets, N bytes of values, + // and N-1 bytes of delimiters. + b := make([]byte, 1, 1+2*n) + b[0] = '{' + + b = strconv.AppendInt(b, a[0], 10) + for i := 1; i < n; i++ { + b = append(b, ',') + b = strconv.AppendInt(b, a[i], 10) + } + + return string(append(b, '}')), nil + } + + return "{}", nil +} + +// StringArray represents a one-dimensional array of the PostgreSQL character types. +type StringArray []string + +// Scan implements the sql.Scanner interface. +func (a *StringArray) Scan(src interface{}) error { + switch src := src.(type) { + case []byte: + return a.scanBytes(src) + case string: + return a.scanBytes([]byte(src)) + case nil: + *a = nil + return nil + } + + return fmt.Errorf("pq: cannot convert %T to StringArray", src) +} + +func (a *StringArray) scanBytes(src []byte) error { + elems, err := scanLinearArray(src, []byte{','}, "StringArray") + if err != nil { + return err + } + if *a != nil && len(elems) == 0 { + *a = (*a)[:0] + } else { + b := make(StringArray, len(elems)) + for i, v := range elems { + if b[i] = string(v); v == nil { + return fmt.Errorf("pq: parsing array element index %d: cannot convert nil to string", i) + } + } + *a = b + } + return nil +} + +// Value implements the driver.Valuer interface. +func (a StringArray) Value() (driver.Value, error) { + if a == nil { + return nil, nil + } + + if n := len(a); n > 0 { + // There will be at least two curly brackets, 2*N bytes of quotes, + // and N-1 bytes of delimiters. + b := make([]byte, 1, 1+3*n) + b[0] = '{' + + b = appendArrayQuotedBytes(b, []byte(a[0])) + for i := 1; i < n; i++ { + b = append(b, ',') + b = appendArrayQuotedBytes(b, []byte(a[i])) + } + + return string(append(b, '}')), nil + } + + return "{}", nil +} + +// appendArray appends rv to the buffer, returning the extended buffer and +// the delimiter used between elements. +// +// It panics when n <= 0 or rv's Kind is not reflect.Array nor reflect.Slice. +func appendArray(b []byte, rv reflect.Value, n int) ([]byte, string, error) { + var del string + var err error + + b = append(b, '{') + + if b, del, err = appendArrayElement(b, rv.Index(0)); err != nil { + return b, del, err + } + + for i := 1; i < n; i++ { + b = append(b, del...) + if b, del, err = appendArrayElement(b, rv.Index(i)); err != nil { + return b, del, err + } + } + + return append(b, '}'), del, nil +} + +// appendArrayElement appends rv to the buffer, returning the extended buffer +// and the delimiter to use before the next element. +// +// When rv's Kind is neither reflect.Array nor reflect.Slice, it is converted +// using driver.DefaultParameterConverter and the resulting []byte or string +// is double-quoted. +// +// See http://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-IO +func appendArrayElement(b []byte, rv reflect.Value) ([]byte, string, error) { + if k := rv.Kind(); k == reflect.Array || k == reflect.Slice { + if t := rv.Type(); t != typeByteSlice && !t.Implements(typeDriverValuer) { + if n := rv.Len(); n > 0 { + return appendArray(b, rv, n) + } + + return b, "", nil + } + } + + var del string = "," + var err error + var iv interface{} = rv.Interface() + + if ad, ok := iv.(ArrayDelimiter); ok { + del = ad.ArrayDelimiter() + } + + if iv, err = driver.DefaultParameterConverter.ConvertValue(iv); err != nil { + return b, del, err + } + + switch v := iv.(type) { + case nil: + return append(b, "NULL"...), del, nil + case []byte: + return appendArrayQuotedBytes(b, v), del, nil + case string: + return appendArrayQuotedBytes(b, []byte(v)), del, nil + } + + b, err = appendValue(b, iv) + return b, del, err +} + +func appendArrayQuotedBytes(b, v []byte) []byte { + b = append(b, '"') + for { + i := bytes.IndexAny(v, `"\`) + if i < 0 { + b = append(b, v...) + break + } + if i > 0 { + b = append(b, v[:i]...) + } + b = append(b, '\\', v[i]) + v = v[i+1:] + } + return append(b, '"') +} + +func appendValue(b []byte, v driver.Value) ([]byte, error) { + return append(b, encode(nil, v, 0)...), nil +} + +// parseArray extracts the dimensions and elements of an array represented in +// text format. Only representations emitted by the backend are supported. +// Notably, whitespace around brackets and delimiters is significant, and NULL +// is case-sensitive. +// +// See http://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-IO +func parseArray(src, del []byte) (dims []int, elems [][]byte, err error) { + var depth, i int + + if len(src) < 1 || src[0] != '{' { + return nil, nil, fmt.Errorf("pq: unable to parse array; expected %q at offset %d", '{', 0) + } + +Open: + for i < len(src) { + switch src[i] { + case '{': + depth++ + i++ + case '}': + elems = make([][]byte, 0) + goto Close + default: + break Open + } + } + dims = make([]int, i) + +Element: + for i < len(src) { + switch src[i] { + case '{': + if depth == len(dims) { + break Element + } + depth++ + dims[depth-1] = 0 + i++ + case '"': + var elem = []byte{} + var escape bool + for i++; i < len(src); i++ { + if escape { + elem = append(elem, src[i]) + escape = false + } else { + switch src[i] { + default: + elem = append(elem, src[i]) + case '\\': + escape = true + case '"': + elems = append(elems, elem) + i++ + break Element + } + } + } + default: + for start := i; i < len(src); i++ { + if bytes.HasPrefix(src[i:], del) || src[i] == '}' { + elem := src[start:i] + if len(elem) == 0 { + return nil, nil, fmt.Errorf("pq: unable to parse array; unexpected %q at offset %d", src[i], i) + } + if bytes.Equal(elem, []byte("NULL")) { + elem = nil + } + elems = append(elems, elem) + break Element + } + } + } + } + + for i < len(src) { + if bytes.HasPrefix(src[i:], del) && depth > 0 { + dims[depth-1]++ + i += len(del) + goto Element + } else if src[i] == '}' && depth > 0 { + dims[depth-1]++ + depth-- + i++ + } else { + return nil, nil, fmt.Errorf("pq: unable to parse array; unexpected %q at offset %d", src[i], i) + } + } + +Close: + for i < len(src) { + if src[i] == '}' && depth > 0 { + depth-- + i++ + } else { + return nil, nil, fmt.Errorf("pq: unable to parse array; unexpected %q at offset %d", src[i], i) + } + } + if depth > 0 { + err = fmt.Errorf("pq: unable to parse array; expected %q at offset %d", '}', i) + } + if err == nil { + for _, d := range dims { + if (len(elems) % d) != 0 { + err = fmt.Errorf("pq: multidimensional arrays must have elements with matching dimensions") + } + } + } + return +} + +func scanLinearArray(src, del []byte, typ string) (elems [][]byte, err error) { + dims, elems, err := parseArray(src, del) + if err != nil { + return nil, err + } + if len(dims) > 1 { + return nil, fmt.Errorf("pq: cannot convert ARRAY%s to %s", strings.Replace(fmt.Sprint(dims), " ", "][", -1), typ) + } + return elems, err +} diff --git a/vendor/src/github.com/lib/pq/array_test.go b/vendor/src/github.com/lib/pq/array_test.go new file mode 100644 index 00000000..10b84318 --- /dev/null +++ b/vendor/src/github.com/lib/pq/array_test.go @@ -0,0 +1,1317 @@ +package pq + +import ( + "bytes" + "database/sql" + "database/sql/driver" + "math/rand" + "reflect" + "strings" + "testing" +) + +func TestParseArray(t *testing.T) { + for _, tt := range []struct { + input string + delim string + dims []int + elems [][]byte + }{ + {`{}`, `,`, nil, [][]byte{}}, + {`{NULL}`, `,`, []int{1}, [][]byte{nil}}, + {`{a}`, `,`, []int{1}, [][]byte{{'a'}}}, + {`{a,b}`, `,`, []int{2}, [][]byte{{'a'}, {'b'}}}, + {`{{a,b}}`, `,`, []int{1, 2}, [][]byte{{'a'}, {'b'}}}, + {`{{a},{b}}`, `,`, []int{2, 1}, [][]byte{{'a'}, {'b'}}}, + {`{{{a,b},{c,d},{e,f}}}`, `,`, []int{1, 3, 2}, [][]byte{ + {'a'}, {'b'}, {'c'}, {'d'}, {'e'}, {'f'}, + }}, + {`{""}`, `,`, []int{1}, [][]byte{{}}}, + {`{","}`, `,`, []int{1}, [][]byte{{','}}}, + {`{",",","}`, `,`, []int{2}, [][]byte{{','}, {','}}}, + {`{{",",","}}`, `,`, []int{1, 2}, [][]byte{{','}, {','}}}, + {`{{","},{","}}`, `,`, []int{2, 1}, [][]byte{{','}, {','}}}, + {`{{{",",","},{",",","},{",",","}}}`, `,`, []int{1, 3, 2}, [][]byte{ + {','}, {','}, {','}, {','}, {','}, {','}, + }}, + {`{"\"}"}`, `,`, []int{1}, [][]byte{{'"', '}'}}}, + {`{"\"","\""}`, `,`, []int{2}, [][]byte{{'"'}, {'"'}}}, + {`{{"\"","\""}}`, `,`, []int{1, 2}, [][]byte{{'"'}, {'"'}}}, + {`{{"\""},{"\""}}`, `,`, []int{2, 1}, [][]byte{{'"'}, {'"'}}}, + {`{{{"\"","\""},{"\"","\""},{"\"","\""}}}`, `,`, []int{1, 3, 2}, [][]byte{ + {'"'}, {'"'}, {'"'}, {'"'}, {'"'}, {'"'}, + }}, + {`{axyzb}`, `xyz`, []int{2}, [][]byte{{'a'}, {'b'}}}, + } { + dims, elems, err := parseArray([]byte(tt.input), []byte(tt.delim)) + + if err != nil { + t.Fatalf("Expected no error for %q, got %q", tt.input, err) + } + if !reflect.DeepEqual(dims, tt.dims) { + t.Errorf("Expected %v dimensions for %q, got %v", tt.dims, tt.input, dims) + } + if !reflect.DeepEqual(elems, tt.elems) { + t.Errorf("Expected %v elements for %q, got %v", tt.elems, tt.input, elems) + } + } +} + +func TestParseArrayError(t *testing.T) { + for _, tt := range []struct { + input, err string + }{ + {``, "expected '{' at offset 0"}, + {`x`, "expected '{' at offset 0"}, + {`}`, "expected '{' at offset 0"}, + {`{`, "expected '}' at offset 1"}, + {`{{}`, "expected '}' at offset 3"}, + {`{}}`, "unexpected '}' at offset 2"}, + {`{,}`, "unexpected ',' at offset 1"}, + {`{,x}`, "unexpected ',' at offset 1"}, + {`{x,}`, "unexpected '}' at offset 3"}, + {`{x,{`, "unexpected '{' at offset 3"}, + {`{x},`, "unexpected ',' at offset 3"}, + {`{x}}`, "unexpected '}' at offset 3"}, + {`{{x}`, "expected '}' at offset 4"}, + {`{""x}`, "unexpected 'x' at offset 3"}, + {`{{a},{b,c}}`, "multidimensional arrays must have elements with matching dimensions"}, + } { + _, _, err := parseArray([]byte(tt.input), []byte{','}) + + if err == nil { + t.Fatalf("Expected error for %q, got none", tt.input) + } + if !strings.Contains(err.Error(), tt.err) { + t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) + } + } +} + +func TestArrayScanner(t *testing.T) { + var s sql.Scanner + + s = Array(&[]bool{}) + if _, ok := s.(*BoolArray); !ok { + t.Errorf("Expected *BoolArray, got %T", s) + } + + s = Array(&[]float64{}) + if _, ok := s.(*Float64Array); !ok { + t.Errorf("Expected *Float64Array, got %T", s) + } + + s = Array(&[]int64{}) + if _, ok := s.(*Int64Array); !ok { + t.Errorf("Expected *Int64Array, got %T", s) + } + + s = Array(&[]string{}) + if _, ok := s.(*StringArray); !ok { + t.Errorf("Expected *StringArray, got %T", s) + } + + for _, tt := range []interface{}{ + &[]sql.Scanner{}, + &[][]bool{}, + &[][]float64{}, + &[][]int64{}, + &[][]string{}, + } { + s = Array(tt) + if _, ok := s.(GenericArray); !ok { + t.Errorf("Expected GenericArray for %T, got %T", tt, s) + } + } +} + +func TestArrayValuer(t *testing.T) { + var v driver.Valuer + + v = Array([]bool{}) + if _, ok := v.(*BoolArray); !ok { + t.Errorf("Expected *BoolArray, got %T", v) + } + + v = Array([]float64{}) + if _, ok := v.(*Float64Array); !ok { + t.Errorf("Expected *Float64Array, got %T", v) + } + + v = Array([]int64{}) + if _, ok := v.(*Int64Array); !ok { + t.Errorf("Expected *Int64Array, got %T", v) + } + + v = Array([]string{}) + if _, ok := v.(*StringArray); !ok { + t.Errorf("Expected *StringArray, got %T", v) + } + + for _, tt := range []interface{}{ + nil, + []driver.Value{}, + [][]bool{}, + [][]float64{}, + [][]int64{}, + [][]string{}, + } { + v = Array(tt) + if _, ok := v.(GenericArray); !ok { + t.Errorf("Expected GenericArray for %T, got %T", tt, v) + } + } +} + +func TestBoolArrayScanUnsupported(t *testing.T) { + var arr BoolArray + err := arr.Scan(1) + + if err == nil { + t.Fatal("Expected error when scanning from int") + } + if !strings.Contains(err.Error(), "int to BoolArray") { + t.Errorf("Expected type to be mentioned when scanning, got %q", err) + } +} + +func TestBoolArrayScanEmpty(t *testing.T) { + var arr BoolArray + err := arr.Scan(`{}`) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if arr == nil || len(arr) != 0 { + t.Errorf("Expected empty, got %#v", arr) + } +} + +func TestBoolArrayScanNil(t *testing.T) { + arr := BoolArray{true, true, true} + err := arr.Scan(nil) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if arr != nil { + t.Errorf("Expected nil, got %+v", arr) + } +} + +var BoolArrayStringTests = []struct { + str string + arr BoolArray +}{ + {`{}`, BoolArray{}}, + {`{t}`, BoolArray{true}}, + {`{f,t}`, BoolArray{false, true}}, +} + +func TestBoolArrayScanBytes(t *testing.T) { + for _, tt := range BoolArrayStringTests { + bytes := []byte(tt.str) + arr := BoolArray{true, true, true} + err := arr.Scan(bytes) + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", bytes, err) + } + if !reflect.DeepEqual(arr, tt.arr) { + t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr) + } + } +} + +func BenchmarkBoolArrayScanBytes(b *testing.B) { + var a BoolArray + var x interface{} = []byte(`{t,f,t,f,t,f,t,f,t,f}`) + + for i := 0; i < b.N; i++ { + a = BoolArray{} + a.Scan(x) + } +} + +func TestBoolArrayScanString(t *testing.T) { + for _, tt := range BoolArrayStringTests { + arr := BoolArray{true, true, true} + err := arr.Scan(tt.str) + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", tt.str, err) + } + if !reflect.DeepEqual(arr, tt.arr) { + t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr) + } + } +} + +func TestBoolArrayScanError(t *testing.T) { + for _, tt := range []struct { + input, err string + }{ + {``, "unable to parse array"}, + {`{`, "unable to parse array"}, + {`{{t},{f}}`, "cannot convert ARRAY[2][1] to BoolArray"}, + {`{NULL}`, `could not parse boolean array index 0: invalid boolean ""`}, + {`{a}`, `could not parse boolean array index 0: invalid boolean "a"`}, + {`{t,b}`, `could not parse boolean array index 1: invalid boolean "b"`}, + {`{t,f,cd}`, `could not parse boolean array index 2: invalid boolean "cd"`}, + } { + arr := BoolArray{true, true, true} + err := arr.Scan(tt.input) + + if err == nil { + t.Fatalf("Expected error for %q, got none", tt.input) + } + if !strings.Contains(err.Error(), tt.err) { + t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) + } + if !reflect.DeepEqual(arr, BoolArray{true, true, true}) { + t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr) + } + } +} + +func TestBoolArrayValue(t *testing.T) { + result, err := BoolArray(nil).Value() + + if err != nil { + t.Fatalf("Expected no error for nil, got %v", err) + } + if result != nil { + t.Errorf("Expected nil, got %q", result) + } + + result, err = BoolArray([]bool{}).Value() + + if err != nil { + t.Fatalf("Expected no error for empty, got %v", err) + } + if expected := `{}`; !reflect.DeepEqual(result, expected) { + t.Errorf("Expected empty, got %q", result) + } + + result, err = BoolArray([]bool{false, true, false}).Value() + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if expected := `{f,t,f}`; !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %q, got %q", expected, result) + } +} + +func BenchmarkBoolArrayValue(b *testing.B) { + rand.Seed(1) + x := make([]bool, 10) + for i := 0; i < len(x); i++ { + x[i] = rand.Intn(2) == 0 + } + a := BoolArray(x) + + for i := 0; i < b.N; i++ { + a.Value() + } +} + +func TestByteaArrayScanUnsupported(t *testing.T) { + var arr ByteaArray + err := arr.Scan(1) + + if err == nil { + t.Fatal("Expected error when scanning from int") + } + if !strings.Contains(err.Error(), "int to ByteaArray") { + t.Errorf("Expected type to be mentioned when scanning, got %q", err) + } +} + +func TestByteaArrayScanEmpty(t *testing.T) { + var arr ByteaArray + err := arr.Scan(`{}`) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if arr == nil || len(arr) != 0 { + t.Errorf("Expected empty, got %#v", arr) + } +} + +func TestByteaArrayScanNil(t *testing.T) { + arr := ByteaArray{{2}, {6}, {0, 0}} + err := arr.Scan(nil) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if arr != nil { + t.Errorf("Expected nil, got %+v", arr) + } +} + +var ByteaArrayStringTests = []struct { + str string + arr ByteaArray +}{ + {`{}`, ByteaArray{}}, + {`{NULL}`, ByteaArray{nil}}, + {`{"\\xfeff"}`, ByteaArray{{'\xFE', '\xFF'}}}, + {`{"\\xdead","\\xbeef"}`, ByteaArray{{'\xDE', '\xAD'}, {'\xBE', '\xEF'}}}, +} + +func TestByteaArrayScanBytes(t *testing.T) { + for _, tt := range ByteaArrayStringTests { + bytes := []byte(tt.str) + arr := ByteaArray{{2}, {6}, {0, 0}} + err := arr.Scan(bytes) + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", bytes, err) + } + if !reflect.DeepEqual(arr, tt.arr) { + t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr) + } + } +} + +func BenchmarkByteaArrayScanBytes(b *testing.B) { + var a ByteaArray + var x interface{} = []byte(`{"\\xfe","\\xff","\\xdead","\\xbeef","\\xfe","\\xff","\\xdead","\\xbeef","\\xfe","\\xff"}`) + + for i := 0; i < b.N; i++ { + a = ByteaArray{} + a.Scan(x) + } +} + +func TestByteaArrayScanString(t *testing.T) { + for _, tt := range ByteaArrayStringTests { + arr := ByteaArray{{2}, {6}, {0, 0}} + err := arr.Scan(tt.str) + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", tt.str, err) + } + if !reflect.DeepEqual(arr, tt.arr) { + t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr) + } + } +} + +func TestByteaArrayScanError(t *testing.T) { + for _, tt := range []struct { + input, err string + }{ + {``, "unable to parse array"}, + {`{`, "unable to parse array"}, + {`{{"\\xfeff"},{"\\xbeef"}}`, "cannot convert ARRAY[2][1] to ByteaArray"}, + {`{"\\abc"}`, "could not parse bytea array index 0: could not parse bytea value"}, + } { + arr := ByteaArray{{2}, {6}, {0, 0}} + err := arr.Scan(tt.input) + + if err == nil { + t.Fatalf("Expected error for %q, got none", tt.input) + } + if !strings.Contains(err.Error(), tt.err) { + t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) + } + if !reflect.DeepEqual(arr, ByteaArray{{2}, {6}, {0, 0}}) { + t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr) + } + } +} + +func TestByteaArrayValue(t *testing.T) { + result, err := ByteaArray(nil).Value() + + if err != nil { + t.Fatalf("Expected no error for nil, got %v", err) + } + if result != nil { + t.Errorf("Expected nil, got %q", result) + } + + result, err = ByteaArray([][]byte{}).Value() + + if err != nil { + t.Fatalf("Expected no error for empty, got %v", err) + } + if expected := `{}`; !reflect.DeepEqual(result, expected) { + t.Errorf("Expected empty, got %q", result) + } + + result, err = ByteaArray([][]byte{{'\xDE', '\xAD', '\xBE', '\xEF'}, {'\xFE', '\xFF'}, {}}).Value() + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if expected := `{"\\xdeadbeef","\\xfeff","\\x"}`; !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %q, got %q", expected, result) + } +} + +func BenchmarkByteaArrayValue(b *testing.B) { + rand.Seed(1) + x := make([][]byte, 10) + for i := 0; i < len(x); i++ { + x[i] = make([]byte, len(x)) + for j := 0; j < len(x); j++ { + x[i][j] = byte(rand.Int()) + } + } + a := ByteaArray(x) + + for i := 0; i < b.N; i++ { + a.Value() + } +} + +func TestFloat64ArrayScanUnsupported(t *testing.T) { + var arr Float64Array + err := arr.Scan(true) + + if err == nil { + t.Fatal("Expected error when scanning from bool") + } + if !strings.Contains(err.Error(), "bool to Float64Array") { + t.Errorf("Expected type to be mentioned when scanning, got %q", err) + } +} + +func TestFloat64ArrayScanEmpty(t *testing.T) { + var arr Float64Array + err := arr.Scan(`{}`) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if arr == nil || len(arr) != 0 { + t.Errorf("Expected empty, got %#v", arr) + } +} + +func TestFloat64ArrayScanNil(t *testing.T) { + arr := Float64Array{5, 5, 5} + err := arr.Scan(nil) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if arr != nil { + t.Errorf("Expected nil, got %+v", arr) + } +} + +var Float64ArrayStringTests = []struct { + str string + arr Float64Array +}{ + {`{}`, Float64Array{}}, + {`{1.2}`, Float64Array{1.2}}, + {`{3.456,7.89}`, Float64Array{3.456, 7.89}}, + {`{3,1,2}`, Float64Array{3, 1, 2}}, +} + +func TestFloat64ArrayScanBytes(t *testing.T) { + for _, tt := range Float64ArrayStringTests { + bytes := []byte(tt.str) + arr := Float64Array{5, 5, 5} + err := arr.Scan(bytes) + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", bytes, err) + } + if !reflect.DeepEqual(arr, tt.arr) { + t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr) + } + } +} + +func BenchmarkFloat64ArrayScanBytes(b *testing.B) { + var a Float64Array + var x interface{} = []byte(`{1.2,3.4,5.6,7.8,9.01,2.34,5.67,8.90,1.234,5.678}`) + + for i := 0; i < b.N; i++ { + a = Float64Array{} + a.Scan(x) + } +} + +func TestFloat64ArrayScanString(t *testing.T) { + for _, tt := range Float64ArrayStringTests { + arr := Float64Array{5, 5, 5} + err := arr.Scan(tt.str) + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", tt.str, err) + } + if !reflect.DeepEqual(arr, tt.arr) { + t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr) + } + } +} + +func TestFloat64ArrayScanError(t *testing.T) { + for _, tt := range []struct { + input, err string + }{ + {``, "unable to parse array"}, + {`{`, "unable to parse array"}, + {`{{5.6},{7.8}}`, "cannot convert ARRAY[2][1] to Float64Array"}, + {`{NULL}`, "parsing array element index 0:"}, + {`{a}`, "parsing array element index 0:"}, + {`{5.6,a}`, "parsing array element index 1:"}, + {`{5.6,7.8,a}`, "parsing array element index 2:"}, + } { + arr := Float64Array{5, 5, 5} + err := arr.Scan(tt.input) + + if err == nil { + t.Fatalf("Expected error for %q, got none", tt.input) + } + if !strings.Contains(err.Error(), tt.err) { + t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) + } + if !reflect.DeepEqual(arr, Float64Array{5, 5, 5}) { + t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr) + } + } +} + +func TestFloat64ArrayValue(t *testing.T) { + result, err := Float64Array(nil).Value() + + if err != nil { + t.Fatalf("Expected no error for nil, got %v", err) + } + if result != nil { + t.Errorf("Expected nil, got %q", result) + } + + result, err = Float64Array([]float64{}).Value() + + if err != nil { + t.Fatalf("Expected no error for empty, got %v", err) + } + if expected := `{}`; !reflect.DeepEqual(result, expected) { + t.Errorf("Expected empty, got %q", result) + } + + result, err = Float64Array([]float64{1.2, 3.4, 5.6}).Value() + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if expected := `{1.2,3.4,5.6}`; !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %q, got %q", expected, result) + } +} + +func BenchmarkFloat64ArrayValue(b *testing.B) { + rand.Seed(1) + x := make([]float64, 10) + for i := 0; i < len(x); i++ { + x[i] = rand.NormFloat64() + } + a := Float64Array(x) + + for i := 0; i < b.N; i++ { + a.Value() + } +} + +func TestInt64ArrayScanUnsupported(t *testing.T) { + var arr Int64Array + err := arr.Scan(true) + + if err == nil { + t.Fatal("Expected error when scanning from bool") + } + if !strings.Contains(err.Error(), "bool to Int64Array") { + t.Errorf("Expected type to be mentioned when scanning, got %q", err) + } +} + +func TestInt64ArrayScanEmpty(t *testing.T) { + var arr Int64Array + err := arr.Scan(`{}`) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if arr == nil || len(arr) != 0 { + t.Errorf("Expected empty, got %#v", arr) + } +} + +func TestInt64ArrayScanNil(t *testing.T) { + arr := Int64Array{5, 5, 5} + err := arr.Scan(nil) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if arr != nil { + t.Errorf("Expected nil, got %+v", arr) + } +} + +var Int64ArrayStringTests = []struct { + str string + arr Int64Array +}{ + {`{}`, Int64Array{}}, + {`{12}`, Int64Array{12}}, + {`{345,678}`, Int64Array{345, 678}}, +} + +func TestInt64ArrayScanBytes(t *testing.T) { + for _, tt := range Int64ArrayStringTests { + bytes := []byte(tt.str) + arr := Int64Array{5, 5, 5} + err := arr.Scan(bytes) + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", bytes, err) + } + if !reflect.DeepEqual(arr, tt.arr) { + t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr) + } + } +} + +func BenchmarkInt64ArrayScanBytes(b *testing.B) { + var a Int64Array + var x interface{} = []byte(`{1,2,3,4,5,6,7,8,9,0}`) + + for i := 0; i < b.N; i++ { + a = Int64Array{} + a.Scan(x) + } +} + +func TestInt64ArrayScanString(t *testing.T) { + for _, tt := range Int64ArrayStringTests { + arr := Int64Array{5, 5, 5} + err := arr.Scan(tt.str) + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", tt.str, err) + } + if !reflect.DeepEqual(arr, tt.arr) { + t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr) + } + } +} + +func TestInt64ArrayScanError(t *testing.T) { + for _, tt := range []struct { + input, err string + }{ + {``, "unable to parse array"}, + {`{`, "unable to parse array"}, + {`{{5},{6}}`, "cannot convert ARRAY[2][1] to Int64Array"}, + {`{NULL}`, "parsing array element index 0:"}, + {`{a}`, "parsing array element index 0:"}, + {`{5,a}`, "parsing array element index 1:"}, + {`{5,6,a}`, "parsing array element index 2:"}, + } { + arr := Int64Array{5, 5, 5} + err := arr.Scan(tt.input) + + if err == nil { + t.Fatalf("Expected error for %q, got none", tt.input) + } + if !strings.Contains(err.Error(), tt.err) { + t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) + } + if !reflect.DeepEqual(arr, Int64Array{5, 5, 5}) { + t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr) + } + } +} + +func TestInt64ArrayValue(t *testing.T) { + result, err := Int64Array(nil).Value() + + if err != nil { + t.Fatalf("Expected no error for nil, got %v", err) + } + if result != nil { + t.Errorf("Expected nil, got %q", result) + } + + result, err = Int64Array([]int64{}).Value() + + if err != nil { + t.Fatalf("Expected no error for empty, got %v", err) + } + if expected := `{}`; !reflect.DeepEqual(result, expected) { + t.Errorf("Expected empty, got %q", result) + } + + result, err = Int64Array([]int64{1, 2, 3}).Value() + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if expected := `{1,2,3}`; !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %q, got %q", expected, result) + } +} + +func BenchmarkInt64ArrayValue(b *testing.B) { + rand.Seed(1) + x := make([]int64, 10) + for i := 0; i < len(x); i++ { + x[i] = rand.Int63() + } + a := Int64Array(x) + + for i := 0; i < b.N; i++ { + a.Value() + } +} + +func TestStringArrayScanUnsupported(t *testing.T) { + var arr StringArray + err := arr.Scan(true) + + if err == nil { + t.Fatal("Expected error when scanning from bool") + } + if !strings.Contains(err.Error(), "bool to StringArray") { + t.Errorf("Expected type to be mentioned when scanning, got %q", err) + } +} + +func TestStringArrayScanEmpty(t *testing.T) { + var arr StringArray + err := arr.Scan(`{}`) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if arr == nil || len(arr) != 0 { + t.Errorf("Expected empty, got %#v", arr) + } +} + +func TestStringArrayScanNil(t *testing.T) { + arr := StringArray{"x", "x", "x"} + err := arr.Scan(nil) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if arr != nil { + t.Errorf("Expected nil, got %+v", arr) + } +} + +var StringArrayStringTests = []struct { + str string + arr StringArray +}{ + {`{}`, StringArray{}}, + {`{t}`, StringArray{"t"}}, + {`{f,1}`, StringArray{"f", "1"}}, + {`{"a\\b","c d",","}`, StringArray{"a\\b", "c d", ","}}, +} + +func TestStringArrayScanBytes(t *testing.T) { + for _, tt := range StringArrayStringTests { + bytes := []byte(tt.str) + arr := StringArray{"x", "x", "x"} + err := arr.Scan(bytes) + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", bytes, err) + } + if !reflect.DeepEqual(arr, tt.arr) { + t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr) + } + } +} + +func BenchmarkStringArrayScanBytes(b *testing.B) { + var a StringArray + var x interface{} = []byte(`{a,b,c,d,e,f,g,h,i,j}`) + var y interface{} = []byte(`{"\a","\b","\c","\d","\e","\f","\g","\h","\i","\j"}`) + + for i := 0; i < b.N; i++ { + a = StringArray{} + a.Scan(x) + a = StringArray{} + a.Scan(y) + } +} + +func TestStringArrayScanString(t *testing.T) { + for _, tt := range StringArrayStringTests { + arr := StringArray{"x", "x", "x"} + err := arr.Scan(tt.str) + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", tt.str, err) + } + if !reflect.DeepEqual(arr, tt.arr) { + t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr) + } + } +} + +func TestStringArrayScanError(t *testing.T) { + for _, tt := range []struct { + input, err string + }{ + {``, "unable to parse array"}, + {`{`, "unable to parse array"}, + {`{{a},{b}}`, "cannot convert ARRAY[2][1] to StringArray"}, + {`{NULL}`, "parsing array element index 0: cannot convert nil to string"}, + {`{a,NULL}`, "parsing array element index 1: cannot convert nil to string"}, + {`{a,b,NULL}`, "parsing array element index 2: cannot convert nil to string"}, + } { + arr := StringArray{"x", "x", "x"} + err := arr.Scan(tt.input) + + if err == nil { + t.Fatalf("Expected error for %q, got none", tt.input) + } + if !strings.Contains(err.Error(), tt.err) { + t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) + } + if !reflect.DeepEqual(arr, StringArray{"x", "x", "x"}) { + t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr) + } + } +} + +func TestStringArrayValue(t *testing.T) { + result, err := StringArray(nil).Value() + + if err != nil { + t.Fatalf("Expected no error for nil, got %v", err) + } + if result != nil { + t.Errorf("Expected nil, got %q", result) + } + + result, err = StringArray([]string{}).Value() + + if err != nil { + t.Fatalf("Expected no error for empty, got %v", err) + } + if expected := `{}`; !reflect.DeepEqual(result, expected) { + t.Errorf("Expected empty, got %q", result) + } + + result, err = StringArray([]string{`a`, `\b`, `c"`, `d,e`}).Value() + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if expected := `{"a","\\b","c\"","d,e"}`; !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %q, got %q", expected, result) + } +} + +func BenchmarkStringArrayValue(b *testing.B) { + x := make([]string, 10) + for i := 0; i < len(x); i++ { + x[i] = strings.Repeat(`abc"def\ghi`, 5) + } + a := StringArray(x) + + for i := 0; i < b.N; i++ { + a.Value() + } +} + +func TestGenericArrayScanUnsupported(t *testing.T) { + var s string + var ss []string + var nsa [1]sql.NullString + + for _, tt := range []struct { + src, dest interface{} + err string + }{ + {nil, nil, "destination is not a pointer to array or slice"}, + {nil, true, "destination bool is not a pointer to array or slice"}, + {nil, &s, "destination *string is not a pointer to array or slice"}, + {nil, ss, "destination []string is not a pointer to array or slice"}, + {nil, &nsa, " to [1]sql.NullString"}, + {true, &ss, "bool to []string"}, + {`{{x}}`, &ss, "multidimensional ARRAY[1][1] is not implemented"}, + {`{{x},{x}}`, &ss, "multidimensional ARRAY[2][1] is not implemented"}, + {`{x}`, &ss, "scanning to string is not implemented"}, + } { + err := GenericArray{tt.dest}.Scan(tt.src) + + if err == nil { + t.Fatalf("Expected error for [%#v %#v]", tt.src, tt.dest) + } + if !strings.Contains(err.Error(), tt.err) { + t.Errorf("Expected error to contain %q for [%#v %#v], got %q", tt.err, tt.src, tt.dest, err) + } + } +} + +func TestGenericArrayScanScannerArrayBytes(t *testing.T) { + src, expected, nsa := []byte(`{NULL,abc,"\""}`), + [3]sql.NullString{{}, {String: `abc`, Valid: true}, {String: `"`, Valid: true}}, + [3]sql.NullString{{String: ``, Valid: true}, {}, {}} + + if err := (GenericArray{&nsa}).Scan(src); err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if !reflect.DeepEqual(nsa, expected) { + t.Errorf("Expected %v, got %v", expected, nsa) + } +} + +func TestGenericArrayScanScannerArrayString(t *testing.T) { + src, expected, nsa := `{NULL,"\"",xyz}`, + [3]sql.NullString{{}, {String: `"`, Valid: true}, {String: `xyz`, Valid: true}}, + [3]sql.NullString{{String: ``, Valid: true}, {}, {}} + + if err := (GenericArray{&nsa}).Scan(src); err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if !reflect.DeepEqual(nsa, expected) { + t.Errorf("Expected %v, got %v", expected, nsa) + } +} + +func TestGenericArrayScanScannerSliceEmpty(t *testing.T) { + var nss []sql.NullString + + if err := (GenericArray{&nss}).Scan(`{}`); err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if nss == nil || len(nss) != 0 { + t.Errorf("Expected empty, got %#v", nss) + } +} + +func TestGenericArrayScanScannerSliceNil(t *testing.T) { + nss := []sql.NullString{{String: ``, Valid: true}, {}} + + if err := (GenericArray{&nss}).Scan(nil); err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if nss != nil { + t.Errorf("Expected nil, got %+v", nss) + } +} + +func TestGenericArrayScanScannerSliceBytes(t *testing.T) { + src, expected, nss := []byte(`{NULL,abc,"\""}`), + []sql.NullString{{}, {String: `abc`, Valid: true}, {String: `"`, Valid: true}}, + []sql.NullString{{String: ``, Valid: true}, {}, {}, {}, {}} + + if err := (GenericArray{&nss}).Scan(src); err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if !reflect.DeepEqual(nss, expected) { + t.Errorf("Expected %v, got %v", expected, nss) + } +} + +func BenchmarkGenericArrayScanScannerSliceBytes(b *testing.B) { + var a GenericArray + var x interface{} = []byte(`{a,b,c,d,e,f,g,h,i,j}`) + var y interface{} = []byte(`{"\a","\b","\c","\d","\e","\f","\g","\h","\i","\j"}`) + + for i := 0; i < b.N; i++ { + a = GenericArray{new([]sql.NullString)} + a.Scan(x) + a = GenericArray{new([]sql.NullString)} + a.Scan(y) + } +} + +func TestGenericArrayScanScannerSliceString(t *testing.T) { + src, expected, nss := `{NULL,"\"",xyz}`, + []sql.NullString{{}, {String: `"`, Valid: true}, {String: `xyz`, Valid: true}}, + []sql.NullString{{String: ``, Valid: true}, {}, {}} + + if err := (GenericArray{&nss}).Scan(src); err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if !reflect.DeepEqual(nss, expected) { + t.Errorf("Expected %v, got %v", expected, nss) + } +} + +type TildeNullInt64 struct{ sql.NullInt64 } + +func (TildeNullInt64) ArrayDelimiter() string { return "~" } + +func TestGenericArrayScanDelimiter(t *testing.T) { + src, expected, tnis := `{12~NULL~76}`, + []TildeNullInt64{{sql.NullInt64{Int64: 12, Valid: true}}, {}, {sql.NullInt64{Int64: 76, Valid: true}}}, + []TildeNullInt64{{sql.NullInt64{Int64: 0, Valid: true}}, {}} + + if err := (GenericArray{&tnis}).Scan(src); err != nil { + t.Fatalf("Expected no error for %#v, got %v", src, err) + } + if !reflect.DeepEqual(tnis, expected) { + t.Errorf("Expected %v for %#v, got %v", expected, src, tnis) + } +} + +func TestGenericArrayScanErrors(t *testing.T) { + var sa [1]string + var nis []sql.NullInt64 + var pss *[]string + + for _, tt := range []struct { + src, dest interface{} + err string + }{ + {nil, pss, "destination *[]string is nil"}, + {`{`, &sa, "unable to parse"}, + {`{}`, &sa, "cannot convert ARRAY[0] to [1]string"}, + {`{x,x}`, &sa, "cannot convert ARRAY[2] to [1]string"}, + {`{x}`, &nis, `parsing array element index 0: converting`}, + } { + err := GenericArray{tt.dest}.Scan(tt.src) + + if err == nil { + t.Fatalf("Expected error for [%#v %#v]", tt.src, tt.dest) + } + if !strings.Contains(err.Error(), tt.err) { + t.Errorf("Expected error to contain %q for [%#v %#v], got %q", tt.err, tt.src, tt.dest, err) + } + } +} + +func TestGenericArrayValueUnsupported(t *testing.T) { + _, err := GenericArray{true}.Value() + + if err == nil { + t.Fatal("Expected error for bool") + } + if !strings.Contains(err.Error(), "bool to array") { + t.Errorf("Expected type to be mentioned, got %q", err) + } +} + +type ByteArrayValuer [1]byte +type ByteSliceValuer []byte +type FuncArrayValuer struct { + delimiter func() string + value func() (driver.Value, error) +} + +func (a ByteArrayValuer) Value() (driver.Value, error) { return a[:], nil } +func (b ByteSliceValuer) Value() (driver.Value, error) { return []byte(b), nil } +func (f FuncArrayValuer) ArrayDelimiter() string { return f.delimiter() } +func (f FuncArrayValuer) Value() (driver.Value, error) { return f.value() } + +func TestGenericArrayValue(t *testing.T) { + result, err := GenericArray{nil}.Value() + + if err != nil { + t.Fatalf("Expected no error for nil, got %v", err) + } + if result != nil { + t.Errorf("Expected nil, got %q", result) + } + + for _, tt := range []interface{}{ + []bool(nil), + [][]int(nil), + []*int(nil), + []sql.NullString(nil), + } { + result, err := GenericArray{tt}.Value() + + if err != nil { + t.Fatalf("Expected no error for %#v, got %v", tt, err) + } + if result != nil { + t.Errorf("Expected nil for %#v, got %q", tt, result) + } + } + + Tilde := func(v driver.Value) FuncArrayValuer { + return FuncArrayValuer{ + func() string { return "~" }, + func() (driver.Value, error) { return v, nil }} + } + + for _, tt := range []struct { + result string + input interface{} + }{ + {`{}`, []bool{}}, + {`{true}`, []bool{true}}, + {`{true,false}`, []bool{true, false}}, + {`{true,false}`, [2]bool{true, false}}, + + {`{}`, [][]int{{}}}, + {`{}`, [][]int{{}, {}}}, + {`{{1}}`, [][]int{{1}}}, + {`{{1},{2}}`, [][]int{{1}, {2}}}, + {`{{1,2},{3,4}}`, [][]int{{1, 2}, {3, 4}}}, + {`{{1,2},{3,4}}`, [2][2]int{{1, 2}, {3, 4}}}, + + {`{"a","\\b","c\"","d,e"}`, []string{`a`, `\b`, `c"`, `d,e`}}, + {`{"a","\\b","c\"","d,e"}`, [][]byte{{'a'}, {'\\', 'b'}, {'c', '"'}, {'d', ',', 'e'}}}, + + {`{NULL}`, []*int{nil}}, + {`{0,NULL}`, []*int{new(int), nil}}, + + {`{NULL}`, []sql.NullString{{}}}, + {`{"\"",NULL}`, []sql.NullString{{String: `"`, Valid: true}, {}}}, + + {`{"a","b"}`, []ByteArrayValuer{{'a'}, {'b'}}}, + {`{{"a","b"},{"c","d"}}`, [][]ByteArrayValuer{{{'a'}, {'b'}}, {{'c'}, {'d'}}}}, + + {`{"e","f"}`, []ByteSliceValuer{{'e'}, {'f'}}}, + {`{{"e","f"},{"g","h"}}`, [][]ByteSliceValuer{{{'e'}, {'f'}}, {{'g'}, {'h'}}}}, + + {`{1~2}`, []FuncArrayValuer{Tilde(int64(1)), Tilde(int64(2))}}, + {`{{1~2}~{3~4}}`, [][]FuncArrayValuer{{Tilde(int64(1)), Tilde(int64(2))}, {Tilde(int64(3)), Tilde(int64(4))}}}, + } { + result, err := GenericArray{tt.input}.Value() + + if err != nil { + t.Fatalf("Expected no error for %q, got %v", tt.input, err) + } + if !reflect.DeepEqual(result, tt.result) { + t.Errorf("Expected %q for %q, got %q", tt.result, tt.input, result) + } + } +} + +func TestGenericArrayValueErrors(t *testing.T) { + var v []interface{} + + v = []interface{}{func() {}} + if _, err := (GenericArray{v}).Value(); err == nil { + t.Errorf("Expected error for %q, got nil", v) + } + + v = []interface{}{nil, func() {}} + if _, err := (GenericArray{v}).Value(); err == nil { + t.Errorf("Expected error for %q, got nil", v) + } +} + +func BenchmarkGenericArrayValueBools(b *testing.B) { + rand.Seed(1) + x := make([]bool, 10) + for i := 0; i < len(x); i++ { + x[i] = rand.Intn(2) == 0 + } + a := GenericArray{x} + + for i := 0; i < b.N; i++ { + a.Value() + } +} + +func BenchmarkGenericArrayValueFloat64s(b *testing.B) { + rand.Seed(1) + x := make([]float64, 10) + for i := 0; i < len(x); i++ { + x[i] = rand.NormFloat64() + } + a := GenericArray{x} + + for i := 0; i < b.N; i++ { + a.Value() + } +} + +func BenchmarkGenericArrayValueInt64s(b *testing.B) { + rand.Seed(1) + x := make([]int64, 10) + for i := 0; i < len(x); i++ { + x[i] = rand.Int63() + } + a := GenericArray{x} + + for i := 0; i < b.N; i++ { + a.Value() + } +} + +func BenchmarkGenericArrayValueByteSlices(b *testing.B) { + x := make([][]byte, 10) + for i := 0; i < len(x); i++ { + x[i] = bytes.Repeat([]byte(`abc"def\ghi`), 5) + } + a := GenericArray{x} + + for i := 0; i < b.N; i++ { + a.Value() + } +} + +func BenchmarkGenericArrayValueStrings(b *testing.B) { + x := make([]string, 10) + for i := 0; i < len(x); i++ { + x[i] = strings.Repeat(`abc"def\ghi`, 5) + } + a := GenericArray{x} + + for i := 0; i < b.N; i++ { + a.Value() + } +} + +func TestArrayScanBackend(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + for _, tt := range []struct { + s string + d sql.Scanner + e interface{} + }{ + {`ARRAY[true, false]`, new(BoolArray), &BoolArray{true, false}}, + {`ARRAY[E'\\xdead', E'\\xbeef']`, new(ByteaArray), &ByteaArray{{'\xDE', '\xAD'}, {'\xBE', '\xEF'}}}, + {`ARRAY[1.2, 3.4]`, new(Float64Array), &Float64Array{1.2, 3.4}}, + {`ARRAY[1, 2, 3]`, new(Int64Array), &Int64Array{1, 2, 3}}, + {`ARRAY['a', E'\\b', 'c"', 'd,e']`, new(StringArray), &StringArray{`a`, `\b`, `c"`, `d,e`}}, + } { + err := db.QueryRow(`SELECT ` + tt.s).Scan(tt.d) + if err != nil { + t.Errorf("Expected no error when scanning %s into %T, got %v", tt.s, tt.d, err) + } + if !reflect.DeepEqual(tt.d, tt.e) { + t.Errorf("Expected %v when scanning %s into %T, got %v", tt.e, tt.s, tt.d, tt.d) + } + } +} + +func TestArrayValueBackend(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + for _, tt := range []struct { + s string + v driver.Valuer + }{ + {`ARRAY[true, false]`, BoolArray{true, false}}, + {`ARRAY[E'\\xdead', E'\\xbeef']`, ByteaArray{{'\xDE', '\xAD'}, {'\xBE', '\xEF'}}}, + {`ARRAY[1.2, 3.4]`, Float64Array{1.2, 3.4}}, + {`ARRAY[1, 2, 3]`, Int64Array{1, 2, 3}}, + {`ARRAY['a', E'\\b', 'c"', 'd,e']`, StringArray{`a`, `\b`, `c"`, `d,e`}}, + } { + var x int + err := db.QueryRow(`SELECT 1 WHERE `+tt.s+` <> $1`, tt.v).Scan(&x) + if err != sql.ErrNoRows { + t.Errorf("Expected %v to equal %s, got %v", tt.v, tt.s, err) + } + } +} diff --git a/vendor/src/github.com/lib/pq/bench_test.go b/vendor/src/github.com/lib/pq/bench_test.go new file mode 100644 index 00000000..e71f41d0 --- /dev/null +++ b/vendor/src/github.com/lib/pq/bench_test.go @@ -0,0 +1,435 @@ +// +build go1.1 + +package pq + +import ( + "bufio" + "bytes" + "database/sql" + "database/sql/driver" + "io" + "math/rand" + "net" + "runtime" + "strconv" + "strings" + "sync" + "testing" + "time" + + "github.com/lib/pq/oid" +) + +var ( + selectStringQuery = "SELECT '" + strings.Repeat("0123456789", 10) + "'" + selectSeriesQuery = "SELECT generate_series(1, 100)" +) + +func BenchmarkSelectString(b *testing.B) { + var result string + benchQuery(b, selectStringQuery, &result) +} + +func BenchmarkSelectSeries(b *testing.B) { + var result int + benchQuery(b, selectSeriesQuery, &result) +} + +func benchQuery(b *testing.B, query string, result interface{}) { + b.StopTimer() + db := openTestConn(b) + defer db.Close() + b.StartTimer() + + for i := 0; i < b.N; i++ { + benchQueryLoop(b, db, query, result) + } +} + +func benchQueryLoop(b *testing.B, db *sql.DB, query string, result interface{}) { + rows, err := db.Query(query) + if err != nil { + b.Fatal(err) + } + defer rows.Close() + for rows.Next() { + err = rows.Scan(result) + if err != nil { + b.Fatal("failed to scan", err) + } + } +} + +// reading from circularConn yields content[:prefixLen] once, followed by +// content[prefixLen:] over and over again. It never returns EOF. +type circularConn struct { + content string + prefixLen int + pos int + net.Conn // for all other net.Conn methods that will never be called +} + +func (r *circularConn) Read(b []byte) (n int, err error) { + n = copy(b, r.content[r.pos:]) + r.pos += n + if r.pos >= len(r.content) { + r.pos = r.prefixLen + } + return +} + +func (r *circularConn) Write(b []byte) (n int, err error) { return len(b), nil } + +func (r *circularConn) Close() error { return nil } + +func fakeConn(content string, prefixLen int) *conn { + c := &circularConn{content: content, prefixLen: prefixLen} + return &conn{buf: bufio.NewReader(c), c: c} +} + +// This benchmark is meant to be the same as BenchmarkSelectString, but takes +// out some of the factors this package can't control. The numbers are less noisy, +// but also the costs of network communication aren't accurately represented. +func BenchmarkMockSelectString(b *testing.B) { + b.StopTimer() + // taken from a recorded run of BenchmarkSelectString + // See: http://www.postgresql.org/docs/current/static/protocol-message-formats.html + const response = "1\x00\x00\x00\x04" + + "t\x00\x00\x00\x06\x00\x00" + + "T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" + + "Z\x00\x00\x00\x05I" + + "2\x00\x00\x00\x04" + + "D\x00\x00\x00n\x00\x01\x00\x00\x00d0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "C\x00\x00\x00\rSELECT 1\x00" + + "Z\x00\x00\x00\x05I" + + "3\x00\x00\x00\x04" + + "Z\x00\x00\x00\x05I" + c := fakeConn(response, 0) + b.StartTimer() + + for i := 0; i < b.N; i++ { + benchMockQuery(b, c, selectStringQuery) + } +} + +var seriesRowData = func() string { + var buf bytes.Buffer + for i := 1; i <= 100; i++ { + digits := byte(2) + if i >= 100 { + digits = 3 + } else if i < 10 { + digits = 1 + } + buf.WriteString("D\x00\x00\x00") + buf.WriteByte(10 + digits) + buf.WriteString("\x00\x01\x00\x00\x00") + buf.WriteByte(digits) + buf.WriteString(strconv.Itoa(i)) + } + return buf.String() +}() + +func BenchmarkMockSelectSeries(b *testing.B) { + b.StopTimer() + var response = "1\x00\x00\x00\x04" + + "t\x00\x00\x00\x06\x00\x00" + + "T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" + + "Z\x00\x00\x00\x05I" + + "2\x00\x00\x00\x04" + + seriesRowData + + "C\x00\x00\x00\x0fSELECT 100\x00" + + "Z\x00\x00\x00\x05I" + + "3\x00\x00\x00\x04" + + "Z\x00\x00\x00\x05I" + c := fakeConn(response, 0) + b.StartTimer() + + for i := 0; i < b.N; i++ { + benchMockQuery(b, c, selectSeriesQuery) + } +} + +func benchMockQuery(b *testing.B, c *conn, query string) { + stmt, err := c.Prepare(query) + if err != nil { + b.Fatal(err) + } + defer stmt.Close() + rows, err := stmt.Query(nil) + if err != nil { + b.Fatal(err) + } + defer rows.Close() + var dest [1]driver.Value + for { + if err := rows.Next(dest[:]); err != nil { + if err == io.EOF { + break + } + b.Fatal(err) + } + } +} + +func BenchmarkPreparedSelectString(b *testing.B) { + var result string + benchPreparedQuery(b, selectStringQuery, &result) +} + +func BenchmarkPreparedSelectSeries(b *testing.B) { + var result int + benchPreparedQuery(b, selectSeriesQuery, &result) +} + +func benchPreparedQuery(b *testing.B, query string, result interface{}) { + b.StopTimer() + db := openTestConn(b) + defer db.Close() + stmt, err := db.Prepare(query) + if err != nil { + b.Fatal(err) + } + defer stmt.Close() + b.StartTimer() + + for i := 0; i < b.N; i++ { + benchPreparedQueryLoop(b, db, stmt, result) + } +} + +func benchPreparedQueryLoop(b *testing.B, db *sql.DB, stmt *sql.Stmt, result interface{}) { + rows, err := stmt.Query() + if err != nil { + b.Fatal(err) + } + if !rows.Next() { + rows.Close() + b.Fatal("no rows") + } + defer rows.Close() + for rows.Next() { + err = rows.Scan(&result) + if err != nil { + b.Fatal("failed to scan") + } + } +} + +// See the comment for BenchmarkMockSelectString. +func BenchmarkMockPreparedSelectString(b *testing.B) { + b.StopTimer() + const parseResponse = "1\x00\x00\x00\x04" + + "t\x00\x00\x00\x06\x00\x00" + + "T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" + + "Z\x00\x00\x00\x05I" + const responses = parseResponse + + "2\x00\x00\x00\x04" + + "D\x00\x00\x00n\x00\x01\x00\x00\x00d0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + + "C\x00\x00\x00\rSELECT 1\x00" + + "Z\x00\x00\x00\x05I" + c := fakeConn(responses, len(parseResponse)) + + stmt, err := c.Prepare(selectStringQuery) + if err != nil { + b.Fatal(err) + } + b.StartTimer() + + for i := 0; i < b.N; i++ { + benchPreparedMockQuery(b, c, stmt) + } +} + +func BenchmarkMockPreparedSelectSeries(b *testing.B) { + b.StopTimer() + const parseResponse = "1\x00\x00\x00\x04" + + "t\x00\x00\x00\x06\x00\x00" + + "T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" + + "Z\x00\x00\x00\x05I" + var responses = parseResponse + + "2\x00\x00\x00\x04" + + seriesRowData + + "C\x00\x00\x00\x0fSELECT 100\x00" + + "Z\x00\x00\x00\x05I" + c := fakeConn(responses, len(parseResponse)) + + stmt, err := c.Prepare(selectSeriesQuery) + if err != nil { + b.Fatal(err) + } + b.StartTimer() + + for i := 0; i < b.N; i++ { + benchPreparedMockQuery(b, c, stmt) + } +} + +func benchPreparedMockQuery(b *testing.B, c *conn, stmt driver.Stmt) { + rows, err := stmt.Query(nil) + if err != nil { + b.Fatal(err) + } + defer rows.Close() + var dest [1]driver.Value + for { + if err := rows.Next(dest[:]); err != nil { + if err == io.EOF { + break + } + b.Fatal(err) + } + } +} + +func BenchmarkEncodeInt64(b *testing.B) { + for i := 0; i < b.N; i++ { + encode(¶meterStatus{}, int64(1234), oid.T_int8) + } +} + +func BenchmarkEncodeFloat64(b *testing.B) { + for i := 0; i < b.N; i++ { + encode(¶meterStatus{}, 3.14159, oid.T_float8) + } +} + +var testByteString = []byte("abcdefghijklmnopqrstuvwxyz") + +func BenchmarkEncodeByteaHex(b *testing.B) { + for i := 0; i < b.N; i++ { + encode(¶meterStatus{serverVersion: 90000}, testByteString, oid.T_bytea) + } +} +func BenchmarkEncodeByteaEscape(b *testing.B) { + for i := 0; i < b.N; i++ { + encode(¶meterStatus{serverVersion: 84000}, testByteString, oid.T_bytea) + } +} + +func BenchmarkEncodeBool(b *testing.B) { + for i := 0; i < b.N; i++ { + encode(¶meterStatus{}, true, oid.T_bool) + } +} + +var testTimestamptz = time.Date(2001, time.January, 1, 0, 0, 0, 0, time.Local) + +func BenchmarkEncodeTimestamptz(b *testing.B) { + for i := 0; i < b.N; i++ { + encode(¶meterStatus{}, testTimestamptz, oid.T_timestamptz) + } +} + +var testIntBytes = []byte("1234") + +func BenchmarkDecodeInt64(b *testing.B) { + for i := 0; i < b.N; i++ { + decode(¶meterStatus{}, testIntBytes, oid.T_int8, formatText) + } +} + +var testFloatBytes = []byte("3.14159") + +func BenchmarkDecodeFloat64(b *testing.B) { + for i := 0; i < b.N; i++ { + decode(¶meterStatus{}, testFloatBytes, oid.T_float8, formatText) + } +} + +var testBoolBytes = []byte{'t'} + +func BenchmarkDecodeBool(b *testing.B) { + for i := 0; i < b.N; i++ { + decode(¶meterStatus{}, testBoolBytes, oid.T_bool, formatText) + } +} + +func TestDecodeBool(t *testing.T) { + db := openTestConn(t) + rows, err := db.Query("select true") + if err != nil { + t.Fatal(err) + } + rows.Close() +} + +var testTimestamptzBytes = []byte("2013-09-17 22:15:32.360754-07") + +func BenchmarkDecodeTimestamptz(b *testing.B) { + for i := 0; i < b.N; i++ { + decode(¶meterStatus{}, testTimestamptzBytes, oid.T_timestamptz, formatText) + } +} + +func BenchmarkDecodeTimestamptzMultiThread(b *testing.B) { + oldProcs := runtime.GOMAXPROCS(0) + defer runtime.GOMAXPROCS(oldProcs) + runtime.GOMAXPROCS(runtime.NumCPU()) + globalLocationCache = newLocationCache() + + f := func(wg *sync.WaitGroup, loops int) { + defer wg.Done() + for i := 0; i < loops; i++ { + decode(¶meterStatus{}, testTimestamptzBytes, oid.T_timestamptz, formatText) + } + } + + wg := &sync.WaitGroup{} + b.ResetTimer() + for j := 0; j < 10; j++ { + wg.Add(1) + go f(wg, b.N/10) + } + wg.Wait() +} + +func BenchmarkLocationCache(b *testing.B) { + globalLocationCache = newLocationCache() + for i := 0; i < b.N; i++ { + globalLocationCache.getLocation(rand.Intn(10000)) + } +} + +func BenchmarkLocationCacheMultiThread(b *testing.B) { + oldProcs := runtime.GOMAXPROCS(0) + defer runtime.GOMAXPROCS(oldProcs) + runtime.GOMAXPROCS(runtime.NumCPU()) + globalLocationCache = newLocationCache() + + f := func(wg *sync.WaitGroup, loops int) { + defer wg.Done() + for i := 0; i < loops; i++ { + globalLocationCache.getLocation(rand.Intn(10000)) + } + } + + wg := &sync.WaitGroup{} + b.ResetTimer() + for j := 0; j < 10; j++ { + wg.Add(1) + go f(wg, b.N/10) + } + wg.Wait() +} + +// Stress test the performance of parsing results from the wire. +func BenchmarkResultParsing(b *testing.B) { + b.StopTimer() + + db := openTestConn(b) + defer db.Close() + _, err := db.Exec("BEGIN") + if err != nil { + b.Fatal(err) + } + + b.StartTimer() + for i := 0; i < b.N; i++ { + res, err := db.Query("SELECT generate_series(1, 50000)") + if err != nil { + b.Fatal(err) + } + res.Close() + } +} diff --git a/vendor/src/github.com/lib/pq/buf.go b/vendor/src/github.com/lib/pq/buf.go new file mode 100644 index 00000000..666b0012 --- /dev/null +++ b/vendor/src/github.com/lib/pq/buf.go @@ -0,0 +1,91 @@ +package pq + +import ( + "bytes" + "encoding/binary" + + "github.com/lib/pq/oid" +) + +type readBuf []byte + +func (b *readBuf) int32() (n int) { + n = int(int32(binary.BigEndian.Uint32(*b))) + *b = (*b)[4:] + return +} + +func (b *readBuf) oid() (n oid.Oid) { + n = oid.Oid(binary.BigEndian.Uint32(*b)) + *b = (*b)[4:] + return +} + +// N.B: this is actually an unsigned 16-bit integer, unlike int32 +func (b *readBuf) int16() (n int) { + n = int(binary.BigEndian.Uint16(*b)) + *b = (*b)[2:] + return +} + +func (b *readBuf) string() string { + i := bytes.IndexByte(*b, 0) + if i < 0 { + errorf("invalid message format; expected string terminator") + } + s := (*b)[:i] + *b = (*b)[i+1:] + return string(s) +} + +func (b *readBuf) next(n int) (v []byte) { + v = (*b)[:n] + *b = (*b)[n:] + return +} + +func (b *readBuf) byte() byte { + return b.next(1)[0] +} + +type writeBuf struct { + buf []byte + pos int +} + +func (b *writeBuf) int32(n int) { + x := make([]byte, 4) + binary.BigEndian.PutUint32(x, uint32(n)) + b.buf = append(b.buf, x...) +} + +func (b *writeBuf) int16(n int) { + x := make([]byte, 2) + binary.BigEndian.PutUint16(x, uint16(n)) + b.buf = append(b.buf, x...) +} + +func (b *writeBuf) string(s string) { + b.buf = append(b.buf, (s + "\000")...) +} + +func (b *writeBuf) byte(c byte) { + b.buf = append(b.buf, c) +} + +func (b *writeBuf) bytes(v []byte) { + b.buf = append(b.buf, v...) +} + +func (b *writeBuf) wrap() []byte { + p := b.buf[b.pos:] + binary.BigEndian.PutUint32(p, uint32(len(p))) + return b.buf +} + +func (b *writeBuf) next(c byte) { + p := b.buf[b.pos:] + binary.BigEndian.PutUint32(p, uint32(len(p))) + b.pos = len(b.buf) + 1 + b.buf = append(b.buf, c, 0, 0, 0, 0) +} diff --git a/vendor/src/github.com/lib/pq/certs/README b/vendor/src/github.com/lib/pq/certs/README new file mode 100644 index 00000000..24ab7b25 --- /dev/null +++ b/vendor/src/github.com/lib/pq/certs/README @@ -0,0 +1,3 @@ +This directory contains certificates and private keys for testing some +SSL-related functionality in Travis. Do NOT use these certificates for +anything other than testing. diff --git a/vendor/src/github.com/lib/pq/certs/bogus_root.crt b/vendor/src/github.com/lib/pq/certs/bogus_root.crt new file mode 100644 index 00000000..1239db3a --- /dev/null +++ b/vendor/src/github.com/lib/pq/certs/bogus_root.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBjCCAe6gAwIBAgIQSnDYp/Naet9HOZljF5PuwDANBgkqhkiG9w0BAQsFADAr +MRIwEAYDVQQKEwlDb2Nrcm9hY2gxFTATBgNVBAMTDENvY2tyb2FjaCBDQTAeFw0x +NjAyMDcxNjQ0MzdaFw0xNzAyMDYxNjQ0MzdaMCsxEjAQBgNVBAoTCUNvY2tyb2Fj +aDEVMBMGA1UEAxMMQ29ja3JvYWNoIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxdln3/UdgP7ayA/G1kT7upjLe4ERwQjYQ25q0e1+vgsB5jhiirxJ +e0+WkhhYu/mwoSAXzvlsbZ2PWFyfdanZeD/Lh6SvIeWXVVaPcWVWL1TEcoN2jr5+ +E85MMHmbbmaT2he8s6br2tM/UZxyTQ2XRprIzApbDssyw1c0Yufcpu3C6267FLEl +IfcWrzDhnluFhthhtGXv3ToD8IuMScMC5qlKBXtKmD1B5x14ngO/ecNJ+OlEi0HU +mavK4KWgI2rDXRZ2EnCpyTZdkc3kkRnzKcg653oOjMDRZdrhfIrha+Jq38ACsUmZ +Su7Sp5jkIHOCO8Zg+l6GKVSq37dKMapD8wIDAQABoyYwJDAOBgNVHQ8BAf8EBAMC +AuQwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQsFAAOCAQEAwZ2Tu0Yu +rrSVdMdoPEjT1IZd+5OhM/SLzL0ddtvTithRweLHsw2lDQYlXFqr24i3UGZJQ1sp +cqSrNwswgLUQT3vWyTjmM51HEb2vMYWKmjZ+sBQYAUP1CadrN/+OTfNGnlF1+B4w +IXOzh7EvQmJJnNybLe4a/aRvj1NE2n8Z898B76SVU9WbfKKz8VwLzuIPDqkKcZda +lMy5yzthyztV9YjcWs2zVOUGZvGdAhDrvZuUq6mSmxrBEvR2LBOggmVf3tGRT+Ls +lW7c9Lrva5zLHuqmoPP07A+vuI9a0D1X44jwGDuPWJ5RnTOQ63Uez12mKNjqleHw +DnkwNanuO8dhAA== +-----END CERTIFICATE----- diff --git a/vendor/src/github.com/lib/pq/certs/postgresql.crt b/vendor/src/github.com/lib/pq/certs/postgresql.crt new file mode 100644 index 00000000..6e6b4284 --- /dev/null +++ b/vendor/src/github.com/lib/pq/certs/postgresql.crt @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Nevada, L=Las Vegas, O=github.com/lib/pq, CN=pq CA + Validity + Not Before: Oct 11 15:10:11 2014 GMT + Not After : Oct 8 15:10:11 2024 GMT + Subject: C=US, ST=Nevada, L=Las Vegas, O=github.com/lib/pq, CN=pqgosslcert + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e3:8c:06:9a:70:54:51:d1:34:34:83:39:cd:a2: + 59:0f:05:ed:8d:d8:0e:34:d0:92:f4:09:4d:ee:8c: + 78:55:49:24:f8:3c:e0:34:58:02:b2:e7:94:58:c1: + e8:e5:bb:d1:af:f6:54:c1:40:b1:90:70:79:0d:35: + 54:9c:8f:16:e9:c2:f0:92:e6:64:49:38:c1:76:f8: + 47:66:c4:5b:4a:b6:a9:43:ce:c8:be:6c:4d:2b:94: + 97:3c:55:bc:d1:d0:6e:b7:53:ae:89:5c:4b:6b:86: + 40:be:c1:ae:1e:64:ce:9c:ae:87:0a:69:e5:c8:21: + 12:be:ae:1d:f6:45:df:16:a7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 9B:25:31:63:A2:D8:06:FF:CB:E3:E9:96:FF:0D:BA:DC:12:7D:04:CF + X509v3 Authority Key Identifier: + keyid:52:93:ED:1E:76:0A:9F:65:4F:DE:19:66:C1:D5:22:40:35:CB:A0:72 + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha256WithRSAEncryption + 3e:f5:f8:0b:4e:11:bd:00:86:1f:ce:dc:97:02:98:91:11:f5: + 65:f6:f2:8a:b2:3e:47:92:05:69:28:c9:e9:b4:f7:cf:93:d1: + 2d:81:5d:00:3c:23:be:da:70:ea:59:e1:2c:d3:25:49:ae:a6: + 95:54:c1:10:df:23:e3:fe:d6:e4:76:c7:6b:73:ad:1b:34:7c: + e2:56:cc:c0:37:ae:c5:7a:11:20:6c:3d:05:0e:99:cd:22:6c: + cf:59:a1:da:28:d4:65:ba:7d:2f:2b:3d:69:6d:a6:c1:ae:57: + bf:56:64:13:79:f8:48:46:65:eb:81:67:28:0b:7b:de:47:10: + b3:80:3c:31:d1:58:94:01:51:4a:c7:c8:1a:01:a8:af:c4:cd: + bb:84:a5:d9:8b:b4:b9:a1:64:3e:95:d9:90:1d:d5:3f:67:cc: + 3b:ba:f5:b4:d1:33:77:ee:c2:d2:3e:7e:c5:66:6e:b7:35:4c: + 60:57:b0:b8:be:36:c8:f3:d3:95:8c:28:4a:c9:f7:27:a4:0d: + e5:96:99:eb:f5:c8:bd:f3:84:6d:ef:02:f9:8a:36:7d:6b:5f: + 36:68:37:41:d9:74:ae:c6:78:2e:44:86:a1:ad:43:ca:fb:b5: + 3e:ba:10:23:09:02:ac:62:d1:d0:83:c8:95:b9:e3:5e:30:ff: + 5b:2b:38:fa +-----BEGIN CERTIFICATE----- +MIIDEzCCAfugAwIBAgIBAjANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEP +MA0GA1UECBMGTmV2YWRhMRIwEAYDVQQHEwlMYXMgVmVnYXMxGjAYBgNVBAoTEWdp +dGh1Yi5jb20vbGliL3BxMQ4wDAYDVQQDEwVwcSBDQTAeFw0xNDEwMTExNTEwMTFa +Fw0yNDEwMDgxNTEwMTFaMGQxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZOZXZhZGEx +EjAQBgNVBAcTCUxhcyBWZWdhczEaMBgGA1UEChMRZ2l0aHViLmNvbS9saWIvcHEx +FDASBgNVBAMTC3BxZ29zc2xjZXJ0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQDjjAaacFRR0TQ0gznNolkPBe2N2A400JL0CU3ujHhVSST4POA0WAKy55RYwejl +u9Gv9lTBQLGQcHkNNVScjxbpwvCS5mRJOMF2+EdmxFtKtqlDzsi+bE0rlJc8VbzR +0G63U66JXEtrhkC+wa4eZM6crocKaeXIIRK+rh32Rd8WpwIDAQABo1owWDAdBgNV +HQ4EFgQUmyUxY6LYBv/L4+mW/w263BJ9BM8wHwYDVR0jBBgwFoAUUpPtHnYKn2VP +3hlmwdUiQDXLoHIwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwDQYJKoZIhvcNAQEL +BQADggEBAD71+AtOEb0Ahh/O3JcCmJER9WX28oqyPkeSBWkoyem098+T0S2BXQA8 +I77acOpZ4SzTJUmuppVUwRDfI+P+1uR2x2tzrRs0fOJWzMA3rsV6ESBsPQUOmc0i +bM9Zodoo1GW6fS8rPWltpsGuV79WZBN5+EhGZeuBZygLe95HELOAPDHRWJQBUUrH +yBoBqK/EzbuEpdmLtLmhZD6V2ZAd1T9nzDu69bTRM3fuwtI+fsVmbrc1TGBXsLi+ +Nsjz05WMKErJ9yekDeWWmev1yL3zhG3vAvmKNn1rXzZoN0HZdK7GeC5EhqGtQ8r7 +tT66ECMJAqxi0dCDyJW5414w/1srOPo= +-----END CERTIFICATE----- diff --git a/vendor/src/github.com/lib/pq/certs/postgresql.key b/vendor/src/github.com/lib/pq/certs/postgresql.key new file mode 100644 index 00000000..eb8b20be --- /dev/null +++ b/vendor/src/github.com/lib/pq/certs/postgresql.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQDjjAaacFRR0TQ0gznNolkPBe2N2A400JL0CU3ujHhVSST4POA0 +WAKy55RYwejlu9Gv9lTBQLGQcHkNNVScjxbpwvCS5mRJOMF2+EdmxFtKtqlDzsi+ +bE0rlJc8VbzR0G63U66JXEtrhkC+wa4eZM6crocKaeXIIRK+rh32Rd8WpwIDAQAB +AoGAM5dM6/kp9P700i8qjOgRPym96Zoh5nGfz/rIE5z/r36NBkdvIg8OVZfR96nH +b0b9TOMR5lsPp0sI9yivTWvX6qyvLJRWy2vvx17hXK9NxXUNTAm0PYZUTvCtcPeX +RnJpzQKNZQPkFzF0uXBc4CtPK2Vz0+FGvAelrhYAxnw1dIkCQQD+9qaW5QhXjsjb +Nl85CmXgxPmGROcgLQCO+omfrjf9UXrituU9Dz6auym5lDGEdMFnkzfr+wpasEy9 +mf5ZZOhDAkEA5HjXfVGaCtpydOt6hDon/uZsyssCK2lQ7NSuE3vP+sUsYMzIpEoy +t3VWXqKbo+g9KNDTP4WEliqp1aiSIylzzQJANPeqzihQnlgEdD4MdD4rwhFJwVIp +Le8Lcais1KaN7StzOwxB/XhgSibd2TbnPpw+3bSg5n5lvUdo+e62/31OHwJAU1jS +I+F09KikQIr28u3UUWT2IzTT4cpVv1AHAQyV3sG3YsjSGT0IK20eyP9BEBZU2WL0 +7aNjrvR5aHxKc5FXsQJABsFtyGpgI5X4xufkJZVZ+Mklz2n7iXa+XPatMAHFxAtb +EEMt60rngwMjXAzBSC6OYuYogRRAY3UCacNC5VhLYQ== +-----END RSA PRIVATE KEY----- diff --git a/vendor/src/github.com/lib/pq/certs/root.crt b/vendor/src/github.com/lib/pq/certs/root.crt new file mode 100644 index 00000000..aecf8f62 --- /dev/null +++ b/vendor/src/github.com/lib/pq/certs/root.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIJANmheROCdW1NMA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNV +BAYTAlVTMQ8wDQYDVQQIEwZOZXZhZGExEjAQBgNVBAcTCUxhcyBWZWdhczEaMBgG +A1UEChMRZ2l0aHViLmNvbS9saWIvcHExDjAMBgNVBAMTBXBxIENBMB4XDTE0MTAx +MTE1MDQyOVoXDTI0MTAwODE1MDQyOVowXjELMAkGA1UEBhMCVVMxDzANBgNVBAgT +Bk5ldmFkYTESMBAGA1UEBxMJTGFzIFZlZ2FzMRowGAYDVQQKExFnaXRodWIuY29t +L2xpYi9wcTEOMAwGA1UEAxMFcHEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCV4PxP7ShzWBzUCThcKk3qZtOLtHmszQVtbqhvgTpm1kTRtKBdVMu0 +pLAHQ3JgJCnAYgH0iZxVGoMP16T3irdgsdC48+nNTFM2T0cCdkfDURGIhSFN47cb +Pgy306BcDUD2q7ucW33+dlFSRuGVewocoh4BWM/vMtMvvWzdi4Ag/L/jhb+5wZxZ +sWymsadOVSDePEMKOvlCa3EdVwVFV40TVyDb+iWBUivDAYsS2a3KajuJrO6MbZiE +Sp2RCIkZS2zFmzWxVRi9ZhzIZhh7EVF9JAaNC3T52jhGUdlRq3YpBTMnd89iOh74 +6jWXG7wSuPj3haFzyNhmJ0ZUh+2Ynoh1AgMBAAGjgcMwgcAwHQYDVR0OBBYEFFKT +7R52Cp9lT94ZZsHVIkA1y6ByMIGQBgNVHSMEgYgwgYWAFFKT7R52Cp9lT94ZZsHV +IkA1y6ByoWKkYDBeMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGTmV2YWRhMRIwEAYD +VQQHEwlMYXMgVmVnYXMxGjAYBgNVBAoTEWdpdGh1Yi5jb20vbGliL3BxMQ4wDAYD +VQQDEwVwcSBDQYIJANmheROCdW1NMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF +BQADggEBAAEhCLWkqJNMI8b4gkbmj5fqQ/4+oO83bZ3w2Oqf6eZ8I8BC4f2NOyE6 +tRUlq5+aU7eqC1cOAvGjO+YHN/bF/DFpwLlzvUSXt+JP/pYcUjL7v+pIvwqec9hD +ndvM4iIbkD/H/OYQ3L+N3W+G1x7AcFIX+bGCb3PzYVQAjxreV6//wgKBosMGFbZo +HPxT9RPMun61SViF04H5TNs0derVn1+5eiiYENeAhJzQNyZoOOUuX1X/Inx9bEPh +C5vFBtSMgIytPgieRJVWAiMLYsfpIAStrHztRAbBs2DU01LmMgRvHdxgFEKinC/d +UHZZQDP+6pT+zADrGhQGXe4eThaO6f0= +-----END CERTIFICATE----- diff --git a/vendor/src/github.com/lib/pq/certs/server.crt b/vendor/src/github.com/lib/pq/certs/server.crt new file mode 100644 index 00000000..ddc995a6 --- /dev/null +++ b/vendor/src/github.com/lib/pq/certs/server.crt @@ -0,0 +1,81 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Nevada, L=Las Vegas, O=github.com/lib/pq, CN=pq CA + Validity + Not Before: Oct 11 15:05:15 2014 GMT + Not After : Oct 8 15:05:15 2024 GMT + Subject: C=US, ST=Nevada, L=Las Vegas, O=github.com/lib/pq, CN=postgres + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d7:8a:4c:85:fb:17:a5:3c:8f:e0:72:11:29:ce: + 3f:b0:1f:3f:7d:c6:ee:7f:a7:fc:02:2b:35:47:08: + a6:3d:90:df:5c:56:14:94:00:c7:6d:d1:d2:e2:61: + 95:77:b8:e3:a6:66:31:f9:1f:21:7d:62:e1:27:da: + 94:37:61:4a:ea:63:53:a0:61:b8:9c:bb:a5:e2:e7: + b7:a6:d8:0f:05:04:c7:29:e2:ea:49:2b:7f:de:15: + 00:a6:18:70:50:c7:0c:de:9a:f9:5a:96:b0:e1:94: + 06:c6:6d:4a:21:3b:b4:0f:a5:6d:92:86:34:b2:4e: + d7:0e:a7:19:c0:77:0b:7b:87:c8:92:de:42:ff:86: + d2:b7:9a:a4:d4:15:23:ca:ad:a5:69:21:b8:ce:7e: + 66:cb:85:5d:b9:ed:8b:2d:09:8d:94:e4:04:1e:72: + ec:ef:d0:76:90:15:5a:a4:f7:91:4b:e9:ce:4e:9d: + 5d:9a:70:17:9c:d8:e9:73:83:ea:3d:61:99:a6:cd: + ac:91:40:5a:88:77:e5:4e:2a:8e:3d:13:f3:f9:38: + 6f:81:6b:8a:95:ca:0e:07:ab:6f:da:b4:8c:d9:ff: + aa:78:03:aa:c7:c2:cf:6f:64:92:d3:d8:83:d5:af: + f1:23:18:a7:2e:7b:17:0b:e7:7d:f1:fa:a8:41:a3: + 04:57 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EE:F0:B3:46:DC:C7:09:EB:0E:B6:2F:E5:FE:62:60:45:44:9F:59:CC + X509v3 Authority Key Identifier: + keyid:52:93:ED:1E:76:0A:9F:65:4F:DE:19:66:C1:D5:22:40:35:CB:A0:72 + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha256WithRSAEncryption + 7e:5a:6e:be:bf:d2:6c:c1:d6:fa:b6:fb:3f:06:53:36:08:87: + 9d:95:b1:39:af:9e:f6:47:38:17:39:da:25:7c:f2:ad:0c:e3: + ab:74:19:ca:fb:8c:a0:50:c0:1d:19:8a:9c:21:ed:0f:3a:d1: + 96:54:2e:10:09:4f:b8:70:f7:2b:99:43:d2:c6:15:bc:3f:24: + 7d:28:39:32:3f:8d:a4:4f:40:75:7f:3e:0d:1c:d1:69:f2:4e: + 98:83:47:97:d2:25:ac:c9:36:86:2f:04:a6:c4:86:c7:c4:00: + 5f:7f:b9:ad:fc:bf:e9:f5:78:d7:82:1a:51:0d:fc:ab:9e:92: + 1d:5f:0c:18:d1:82:e0:14:c9:ce:91:89:71:ff:49:49:ff:35: + bf:7b:44:78:42:c1:d0:66:65:bb:28:2e:60:ca:9b:20:12:a9: + 90:61:b1:96:ec:15:46:c9:37:f7:07:90:8a:89:45:2a:3f:37: + ec:dc:e3:e5:8f:c3:3a:57:80:a5:54:60:0c:e1:b2:26:99:2b: + 40:7e:36:d1:9a:70:02:ec:63:f4:3b:72:ae:81:fb:30:20:6d: + cb:48:46:c6:b5:8f:39:b1:84:05:25:55:8d:f5:62:f6:1b:46: + 2e:da:a3:4c:26:12:44:d7:56:b6:b8:a9:ca:d3:ab:71:45:7c: + 9f:48:6d:1e +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIBATANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEP +MA0GA1UECBMGTmV2YWRhMRIwEAYDVQQHEwlMYXMgVmVnYXMxGjAYBgNVBAoTEWdp +dGh1Yi5jb20vbGliL3BxMQ4wDAYDVQQDEwVwcSBDQTAeFw0xNDEwMTExNTA1MTVa +Fw0yNDEwMDgxNTA1MTVaMGExCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZOZXZhZGEx +EjAQBgNVBAcTCUxhcyBWZWdhczEaMBgGA1UEChMRZ2l0aHViLmNvbS9saWIvcHEx +ETAPBgNVBAMTCHBvc3RncmVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA14pMhfsXpTyP4HIRKc4/sB8/fcbuf6f8Ais1RwimPZDfXFYUlADHbdHS4mGV +d7jjpmYx+R8hfWLhJ9qUN2FK6mNToGG4nLul4ue3ptgPBQTHKeLqSSt/3hUAphhw +UMcM3pr5Wpaw4ZQGxm1KITu0D6VtkoY0sk7XDqcZwHcLe4fIkt5C/4bSt5qk1BUj +yq2laSG4zn5my4Vdue2LLQmNlOQEHnLs79B2kBVapPeRS+nOTp1dmnAXnNjpc4Pq +PWGZps2skUBaiHflTiqOPRPz+ThvgWuKlcoOB6tv2rSM2f+qeAOqx8LPb2SS09iD +1a/xIxinLnsXC+d98fqoQaMEVwIDAQABo1owWDAdBgNVHQ4EFgQU7vCzRtzHCesO +ti/l/mJgRUSfWcwwHwYDVR0jBBgwFoAUUpPtHnYKn2VP3hlmwdUiQDXLoHIwCQYD +VR0TBAIwADALBgNVHQ8EBAMCBeAwDQYJKoZIhvcNAQELBQADggEBAH5abr6/0mzB +1vq2+z8GUzYIh52VsTmvnvZHOBc52iV88q0M46t0Gcr7jKBQwB0Zipwh7Q860ZZU +LhAJT7hw9yuZQ9LGFbw/JH0oOTI/jaRPQHV/Pg0c0WnyTpiDR5fSJazJNoYvBKbE +hsfEAF9/ua38v+n1eNeCGlEN/Kuekh1fDBjRguAUyc6RiXH/SUn/Nb97RHhCwdBm +ZbsoLmDKmyASqZBhsZbsFUbJN/cHkIqJRSo/N+zc4+WPwzpXgKVUYAzhsiaZK0B+ +NtGacALsY/Q7cq6B+zAgbctIRsa1jzmxhAUlVY31YvYbRi7ao0wmEkTXVra4qcrT +q3FFfJ9IbR4= +-----END CERTIFICATE----- diff --git a/vendor/src/github.com/lib/pq/certs/server.key b/vendor/src/github.com/lib/pq/certs/server.key new file mode 100644 index 00000000..bd7b019b --- /dev/null +++ b/vendor/src/github.com/lib/pq/certs/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA14pMhfsXpTyP4HIRKc4/sB8/fcbuf6f8Ais1RwimPZDfXFYU +lADHbdHS4mGVd7jjpmYx+R8hfWLhJ9qUN2FK6mNToGG4nLul4ue3ptgPBQTHKeLq +SSt/3hUAphhwUMcM3pr5Wpaw4ZQGxm1KITu0D6VtkoY0sk7XDqcZwHcLe4fIkt5C +/4bSt5qk1BUjyq2laSG4zn5my4Vdue2LLQmNlOQEHnLs79B2kBVapPeRS+nOTp1d +mnAXnNjpc4PqPWGZps2skUBaiHflTiqOPRPz+ThvgWuKlcoOB6tv2rSM2f+qeAOq +x8LPb2SS09iD1a/xIxinLnsXC+d98fqoQaMEVwIDAQABAoIBAF3ZoihUhJ82F4+r +Gz4QyDpv4L1reT2sb1aiabhcU8ZK5nbWJG+tRyjSS/i2dNaEcttpdCj9HR/zhgZM +bm0OuAgG58rVwgS80CZUruq++Qs+YVojq8/gWPTiQD4SNhV2Fmx3HkwLgUk3oxuT +SsvdqzGE3okGVrutCIcgy126eA147VPMoej1Bb3fO6npqK0pFPhZfAc0YoqJuM+k +obRm5pAnGUipyLCFXjA9HYPKwYZw2RtfdA3CiImHeanSdqS+ctrC9y8BV40Th7gZ +haXdKUNdjmIxV695QQ1mkGqpKLZFqhzKioGQ2/Ly2d1iaKN9fZltTusu8unepWJ2 +tlT9qMECgYEA9uHaF1t2CqE+AJvWTihHhPIIuLxoOQXYea1qvxfcH/UMtaLKzCNm +lQ5pqCGsPvp+10f36yttO1ZehIvlVNXuJsjt0zJmPtIolNuJY76yeussfQ9jHheB +5uPEzCFlHzxYbBUyqgWaF6W74okRGzEGJXjYSP0yHPPdU4ep2q3bGiUCgYEA34Af +wBSuQSK7uLxArWHvQhyuvi43ZGXls6oRGl+Ysj54s8BP6XGkq9hEJ6G4yxgyV+BR +DUOs5X8/TLT8POuIMYvKTQthQyCk0eLv2FLdESDuuKx0kBVY3s8lK3/z5HhrdOiN +VMNZU+xDKgKc3hN9ypkk8vcZe6EtH7Y14e0rVcsCgYBTgxi8F/M5K0wG9rAqphNz +VFBA9XKn/2M33cKjO5X5tXIEKzpAjaUQvNxexG04rJGljzG8+mar0M6ONahw5yD1 +O7i/XWgazgpuOEkkVYiYbd8RutfDgR4vFVMn3hAP3eDnRtBplRWH9Ec3HTiNIys6 +F8PKBOQjyRZQQC7jyzW3hQKBgACe5HeuFwXLSOYsb6mLmhR+6+VPT4wR1F95W27N +USk9jyxAnngxfpmTkiziABdgS9N+pfr5cyN4BP77ia/Jn6kzkC5Cl9SN5KdIkA3z +vPVtN/x/ThuQU5zaymmig1ThGLtMYggYOslG4LDfLPxY5YKIhle+Y+259twdr2yf +Mf2dAoGAaGv3tWMgnIdGRk6EQL/yb9PKHo7ShN+tKNlGaK7WwzBdKs+Fe8jkgcr7 +pz4Ne887CmxejdISzOCcdT+Zm9Bx6I/uZwWOtDvWpIgIxVX9a9URj/+D1MxTE/y4 +d6H+c89yDY62I2+drMpdjCd3EtCaTlxpTbRS+s1eAHMH7aEkcCE= +-----END RSA PRIVATE KEY----- diff --git a/vendor/src/github.com/lib/pq/conn.go b/vendor/src/github.com/lib/pq/conn.go new file mode 100644 index 00000000..3c8f77cb --- /dev/null +++ b/vendor/src/github.com/lib/pq/conn.go @@ -0,0 +1,1811 @@ +package pq + +import ( + "bufio" + "crypto/md5" + "database/sql" + "database/sql/driver" + "encoding/binary" + "errors" + "fmt" + "io" + "net" + "os" + "os/user" + "path" + "path/filepath" + "strconv" + "strings" + "time" + "unicode" + + "github.com/lib/pq/oid" +) + +// Common error types +var ( + ErrNotSupported = errors.New("pq: Unsupported command") + ErrInFailedTransaction = errors.New("pq: Could not complete operation in a failed transaction") + ErrSSLNotSupported = errors.New("pq: SSL is not enabled on the server") + ErrSSLKeyHasWorldPermissions = errors.New("pq: Private key file has group or world access. Permissions should be u=rw (0600) or less.") + ErrCouldNotDetectUsername = errors.New("pq: Could not detect default username. Please provide one explicitly.") + + errUnexpectedReady = errors.New("unexpected ReadyForQuery") + errNoRowsAffected = errors.New("no RowsAffected available after the empty statement") + errNoLastInsertId = errors.New("no LastInsertId available after the empty statement") +) + +type drv struct{} + +func (d *drv) Open(name string) (driver.Conn, error) { + return Open(name) +} + +func init() { + sql.Register("postgres", &drv{}) +} + +type parameterStatus struct { + // server version in the same format as server_version_num, or 0 if + // unavailable + serverVersion int + + // the current location based on the TimeZone value of the session, if + // available + currentLocation *time.Location +} + +type transactionStatus byte + +const ( + txnStatusIdle transactionStatus = 'I' + txnStatusIdleInTransaction transactionStatus = 'T' + txnStatusInFailedTransaction transactionStatus = 'E' +) + +func (s transactionStatus) String() string { + switch s { + case txnStatusIdle: + return "idle" + case txnStatusIdleInTransaction: + return "idle in transaction" + case txnStatusInFailedTransaction: + return "in a failed transaction" + default: + errorf("unknown transactionStatus %d", s) + } + + panic("not reached") +} + +type Dialer interface { + Dial(network, address string) (net.Conn, error) + DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) +} + +type defaultDialer struct{} + +func (d defaultDialer) Dial(ntw, addr string) (net.Conn, error) { + return net.Dial(ntw, addr) +} +func (d defaultDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) { + return net.DialTimeout(ntw, addr, timeout) +} + +type conn struct { + c net.Conn + buf *bufio.Reader + namei int + scratch [512]byte + txnStatus transactionStatus + txnClosed chan<- struct{} + + // Save connection arguments to use during CancelRequest. + dialer Dialer + opts values + + // Cancellation key data for use with CancelRequest messages. + processID int + secretKey int + + parameterStatus parameterStatus + + saveMessageType byte + saveMessageBuffer []byte + + // If true, this connection is bad and all public-facing functions should + // return ErrBadConn. + bad bool + + // If set, this connection should never use the binary format when + // receiving query results from prepared statements. Only provided for + // debugging. + disablePreparedBinaryResult bool + + // Whether to always send []byte parameters over as binary. Enables single + // round-trip mode for non-prepared Query calls. + binaryParameters bool + + // If true this connection is in the middle of a COPY + inCopy bool +} + +// Handle driver-side settings in parsed connection string. +func (c *conn) handleDriverSettings(o values) (err error) { + boolSetting := func(key string, val *bool) error { + if value := o.Get(key); value != "" { + if value == "yes" { + *val = true + } else if value == "no" { + *val = false + } else { + return fmt.Errorf("unrecognized value %q for %s", value, key) + } + } + return nil + } + + err = boolSetting("disable_prepared_binary_result", &c.disablePreparedBinaryResult) + if err != nil { + return err + } + err = boolSetting("binary_parameters", &c.binaryParameters) + if err != nil { + return err + } + return nil +} + +func (c *conn) handlePgpass(o values) { + // if a password was supplied, do not process .pgpass + _, ok := o["password"] + if ok { + return + } + filename := os.Getenv("PGPASSFILE") + if filename == "" { + // XXX this code doesn't work on Windows where the default filename is + // XXX %APPDATA%\postgresql\pgpass.conf + user, err := user.Current() + if err != nil { + return + } + filename = filepath.Join(user.HomeDir, ".pgpass") + } + fileinfo, err := os.Stat(filename) + if err != nil { + return + } + mode := fileinfo.Mode() + if mode&(0x77) != 0 { + // XXX should warn about incorrect .pgpass permissions as psql does + return + } + file, err := os.Open(filename) + if err != nil { + return + } + defer file.Close() + scanner := bufio.NewScanner(io.Reader(file)) + hostname := o.Get("host") + ntw, _ := network(o) + port := o.Get("port") + db := o.Get("dbname") + username := o.Get("user") + // From: https://github.com/tg/pgpass/blob/master/reader.go + getFields := func(s string) []string { + fs := make([]string, 0, 5) + f := make([]rune, 0, len(s)) + + var esc bool + for _, c := range s { + switch { + case esc: + f = append(f, c) + esc = false + case c == '\\': + esc = true + case c == ':': + fs = append(fs, string(f)) + f = f[:0] + default: + f = append(f, c) + } + } + return append(fs, string(f)) + } + for scanner.Scan() { + line := scanner.Text() + if len(line) == 0 || line[0] == '#' { + continue + } + split := getFields(line) + if len(split) != 5 { + continue + } + if (split[0] == "*" || split[0] == hostname || (split[0] == "localhost" && (hostname == "" || ntw == "unix"))) && (split[1] == "*" || split[1] == port) && (split[2] == "*" || split[2] == db) && (split[3] == "*" || split[3] == username) { + o["password"] = split[4] + return + } + } +} + +func (c *conn) writeBuf(b byte) *writeBuf { + c.scratch[0] = b + return &writeBuf{ + buf: c.scratch[:5], + pos: 1, + } +} + +func Open(name string) (_ driver.Conn, err error) { + return DialOpen(defaultDialer{}, name) +} + +func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { + // Handle any panics during connection initialization. Note that we + // specifically do *not* want to use errRecover(), as that would turn any + // connection errors into ErrBadConns, hiding the real error message from + // the user. + defer errRecoverNoErrBadConn(&err) + + o := make(values) + + // A number of defaults are applied here, in this order: + // + // * Very low precedence defaults applied in every situation + // * Environment variables + // * Explicitly passed connection information + o.Set("host", "localhost") + o.Set("port", "5432") + // N.B.: Extra float digits should be set to 3, but that breaks + // Postgres 8.4 and older, where the max is 2. + o.Set("extra_float_digits", "2") + for k, v := range parseEnviron(os.Environ()) { + o.Set(k, v) + } + + if strings.HasPrefix(name, "postgres://") || strings.HasPrefix(name, "postgresql://") { + name, err = ParseURL(name) + if err != nil { + return nil, err + } + } + + if err := parseOpts(name, o); err != nil { + return nil, err + } + + // Use the "fallback" application name if necessary + if fallback := o.Get("fallback_application_name"); fallback != "" { + if !o.Isset("application_name") { + o.Set("application_name", fallback) + } + } + + // We can't work with any client_encoding other than UTF-8 currently. + // However, we have historically allowed the user to set it to UTF-8 + // explicitly, and there's no reason to break such programs, so allow that. + // Note that the "options" setting could also set client_encoding, but + // parsing its value is not worth it. Instead, we always explicitly send + // client_encoding as a separate run-time parameter, which should override + // anything set in options. + if enc := o.Get("client_encoding"); enc != "" && !isUTF8(enc) { + return nil, errors.New("client_encoding must be absent or 'UTF8'") + } + o.Set("client_encoding", "UTF8") + // DateStyle needs a similar treatment. + if datestyle := o.Get("datestyle"); datestyle != "" { + if datestyle != "ISO, MDY" { + panic(fmt.Sprintf("setting datestyle must be absent or %v; got %v", + "ISO, MDY", datestyle)) + } + } else { + o.Set("datestyle", "ISO, MDY") + } + + // If a user is not provided by any other means, the last + // resort is to use the current operating system provided user + // name. + if o.Get("user") == "" { + u, err := userCurrent() + if err != nil { + return nil, err + } else { + o.Set("user", u) + } + } + + cn := &conn{ + opts: o, + dialer: d, + } + err = cn.handleDriverSettings(o) + if err != nil { + return nil, err + } + cn.handlePgpass(o) + + cn.c, err = dial(d, o) + if err != nil { + return nil, err + } + cn.ssl(o) + cn.buf = bufio.NewReader(cn.c) + cn.startup(o) + + // reset the deadline, in case one was set (see dial) + if timeout := o.Get("connect_timeout"); timeout != "" && timeout != "0" { + err = cn.c.SetDeadline(time.Time{}) + } + return cn, err +} + +func dial(d Dialer, o values) (net.Conn, error) { + ntw, addr := network(o) + // SSL is not necessary or supported over UNIX domain sockets + if ntw == "unix" { + o["sslmode"] = "disable" + } + + // Zero or not specified means wait indefinitely. + if timeout := o.Get("connect_timeout"); timeout != "" && timeout != "0" { + seconds, err := strconv.ParseInt(timeout, 10, 0) + if err != nil { + return nil, fmt.Errorf("invalid value for parameter connect_timeout: %s", err) + } + duration := time.Duration(seconds) * time.Second + // connect_timeout should apply to the entire connection establishment + // procedure, so we both use a timeout for the TCP connection + // establishment and set a deadline for doing the initial handshake. + // The deadline is then reset after startup() is done. + deadline := time.Now().Add(duration) + conn, err := d.DialTimeout(ntw, addr, duration) + if err != nil { + return nil, err + } + err = conn.SetDeadline(deadline) + return conn, err + } + return d.Dial(ntw, addr) +} + +func network(o values) (string, string) { + host := o.Get("host") + + if strings.HasPrefix(host, "/") { + sockPath := path.Join(host, ".s.PGSQL."+o.Get("port")) + return "unix", sockPath + } + + return "tcp", net.JoinHostPort(host, o.Get("port")) +} + +type values map[string]string + +func (vs values) Set(k, v string) { + vs[k] = v +} + +func (vs values) Get(k string) (v string) { + return vs[k] +} + +func (vs values) Isset(k string) bool { + _, ok := vs[k] + return ok +} + +// scanner implements a tokenizer for libpq-style option strings. +type scanner struct { + s []rune + i int +} + +// newScanner returns a new scanner initialized with the option string s. +func newScanner(s string) *scanner { + return &scanner{[]rune(s), 0} +} + +// Next returns the next rune. +// It returns 0, false if the end of the text has been reached. +func (s *scanner) Next() (rune, bool) { + if s.i >= len(s.s) { + return 0, false + } + r := s.s[s.i] + s.i++ + return r, true +} + +// SkipSpaces returns the next non-whitespace rune. +// It returns 0, false if the end of the text has been reached. +func (s *scanner) SkipSpaces() (rune, bool) { + r, ok := s.Next() + for unicode.IsSpace(r) && ok { + r, ok = s.Next() + } + return r, ok +} + +// parseOpts parses the options from name and adds them to the values. +// +// The parsing code is based on conninfo_parse from libpq's fe-connect.c +func parseOpts(name string, o values) error { + s := newScanner(name) + + for { + var ( + keyRunes, valRunes []rune + r rune + ok bool + ) + + if r, ok = s.SkipSpaces(); !ok { + break + } + + // Scan the key + for !unicode.IsSpace(r) && r != '=' { + keyRunes = append(keyRunes, r) + if r, ok = s.Next(); !ok { + break + } + } + + // Skip any whitespace if we're not at the = yet + if r != '=' { + r, ok = s.SkipSpaces() + } + + // The current character should be = + if r != '=' || !ok { + return fmt.Errorf(`missing "=" after %q in connection info string"`, string(keyRunes)) + } + + // Skip any whitespace after the = + if r, ok = s.SkipSpaces(); !ok { + // If we reach the end here, the last value is just an empty string as per libpq. + o.Set(string(keyRunes), "") + break + } + + if r != '\'' { + for !unicode.IsSpace(r) { + if r == '\\' { + if r, ok = s.Next(); !ok { + return fmt.Errorf(`missing character after backslash`) + } + } + valRunes = append(valRunes, r) + + if r, ok = s.Next(); !ok { + break + } + } + } else { + quote: + for { + if r, ok = s.Next(); !ok { + return fmt.Errorf(`unterminated quoted string literal in connection string`) + } + switch r { + case '\'': + break quote + case '\\': + r, _ = s.Next() + fallthrough + default: + valRunes = append(valRunes, r) + } + } + } + + o.Set(string(keyRunes), string(valRunes)) + } + + return nil +} + +func (cn *conn) isInTransaction() bool { + return cn.txnStatus == txnStatusIdleInTransaction || + cn.txnStatus == txnStatusInFailedTransaction +} + +func (cn *conn) checkIsInTransaction(intxn bool) { + if cn.isInTransaction() != intxn { + cn.bad = true + errorf("unexpected transaction status %v", cn.txnStatus) + } +} + +func (cn *conn) Begin() (_ driver.Tx, err error) { + if cn.bad { + return nil, driver.ErrBadConn + } + defer cn.errRecover(&err) + + cn.checkIsInTransaction(false) + _, commandTag, err := cn.simpleExec("BEGIN") + if err != nil { + return nil, err + } + if commandTag != "BEGIN" { + cn.bad = true + return nil, fmt.Errorf("unexpected command tag %s", commandTag) + } + if cn.txnStatus != txnStatusIdleInTransaction { + cn.bad = true + return nil, fmt.Errorf("unexpected transaction status %v", cn.txnStatus) + } + return cn, nil +} + +func (cn *conn) closeTxn() { + if cn.txnClosed != nil { + close(cn.txnClosed) + cn.txnClosed = nil + } +} + +func (cn *conn) Commit() (err error) { + defer cn.closeTxn() + if cn.bad { + return driver.ErrBadConn + } + defer cn.errRecover(&err) + + cn.checkIsInTransaction(true) + // We don't want the client to think that everything is okay if it tries + // to commit a failed transaction. However, no matter what we return, + // database/sql will release this connection back into the free connection + // pool so we have to abort the current transaction here. Note that you + // would get the same behaviour if you issued a COMMIT in a failed + // transaction, so it's also the least surprising thing to do here. + if cn.txnStatus == txnStatusInFailedTransaction { + if err := cn.Rollback(); err != nil { + return err + } + return ErrInFailedTransaction + } + + _, commandTag, err := cn.simpleExec("COMMIT") + if err != nil { + if cn.isInTransaction() { + cn.bad = true + } + return err + } + if commandTag != "COMMIT" { + cn.bad = true + return fmt.Errorf("unexpected command tag %s", commandTag) + } + cn.checkIsInTransaction(false) + return nil +} + +func (cn *conn) Rollback() (err error) { + defer cn.closeTxn() + if cn.bad { + return driver.ErrBadConn + } + defer cn.errRecover(&err) + + cn.checkIsInTransaction(true) + _, commandTag, err := cn.simpleExec("ROLLBACK") + if err != nil { + if cn.isInTransaction() { + cn.bad = true + } + return err + } + if commandTag != "ROLLBACK" { + return fmt.Errorf("unexpected command tag %s", commandTag) + } + cn.checkIsInTransaction(false) + return nil +} + +func (cn *conn) gname() string { + cn.namei++ + return strconv.FormatInt(int64(cn.namei), 10) +} + +func (cn *conn) simpleExec(q string) (res driver.Result, commandTag string, err error) { + b := cn.writeBuf('Q') + b.string(q) + cn.send(b) + + for { + t, r := cn.recv1() + switch t { + case 'C': + res, commandTag = cn.parseComplete(r.string()) + case 'Z': + cn.processReadyForQuery(r) + if res == nil && err == nil { + err = errUnexpectedReady + } + // done + return + case 'E': + err = parseError(r) + case 'I': + res = emptyRows + case 'T', 'D': + // ignore any results + default: + cn.bad = true + errorf("unknown response for simple query: %q", t) + } + } +} + +func (cn *conn) simpleQuery(q string) (res *rows, err error) { + defer cn.errRecover(&err) + + b := cn.writeBuf('Q') + b.string(q) + cn.send(b) + + for { + t, r := cn.recv1() + switch t { + case 'C', 'I': + // We allow queries which don't return any results through Query as + // well as Exec. We still have to give database/sql a rows object + // the user can close, though, to avoid connections from being + // leaked. A "rows" with done=true works fine for that purpose. + if err != nil { + cn.bad = true + errorf("unexpected message %q in simple query execution", t) + } + if res == nil { + res = &rows{ + cn: cn, + } + } + res.done = true + case 'Z': + cn.processReadyForQuery(r) + // done + return + case 'E': + res = nil + err = parseError(r) + case 'D': + if res == nil { + cn.bad = true + errorf("unexpected DataRow in simple query execution") + } + // the query didn't fail; kick off to Next + cn.saveMessage(t, r) + return + case 'T': + // res might be non-nil here if we received a previous + // CommandComplete, but that's fine; just overwrite it + res = &rows{cn: cn} + res.colNames, res.colFmts, res.colTyps = parsePortalRowDescribe(r) + + // To work around a bug in QueryRow in Go 1.2 and earlier, wait + // until the first DataRow has been received. + default: + cn.bad = true + errorf("unknown response for simple query: %q", t) + } + } +} + +type noRows struct{} + +var emptyRows noRows + +var _ driver.Result = noRows{} + +func (noRows) LastInsertId() (int64, error) { + return 0, errNoLastInsertId +} + +func (noRows) RowsAffected() (int64, error) { + return 0, errNoRowsAffected +} + +// Decides which column formats to use for a prepared statement. The input is +// an array of type oids, one element per result column. +func decideColumnFormats(colTyps []oid.Oid, forceText bool) (colFmts []format, colFmtData []byte) { + if len(colTyps) == 0 { + return nil, colFmtDataAllText + } + + colFmts = make([]format, len(colTyps)) + if forceText { + return colFmts, colFmtDataAllText + } + + allBinary := true + allText := true + for i, o := range colTyps { + switch o { + // This is the list of types to use binary mode for when receiving them + // through a prepared statement. If a type appears in this list, it + // must also be implemented in binaryDecode in encode.go. + case oid.T_bytea: + fallthrough + case oid.T_int8: + fallthrough + case oid.T_int4: + fallthrough + case oid.T_int2: + fallthrough + case oid.T_uuid: + colFmts[i] = formatBinary + allText = false + + default: + allBinary = false + } + } + + if allBinary { + return colFmts, colFmtDataAllBinary + } else if allText { + return colFmts, colFmtDataAllText + } else { + colFmtData = make([]byte, 2+len(colFmts)*2) + binary.BigEndian.PutUint16(colFmtData, uint16(len(colFmts))) + for i, v := range colFmts { + binary.BigEndian.PutUint16(colFmtData[2+i*2:], uint16(v)) + } + return colFmts, colFmtData + } +} + +func (cn *conn) prepareTo(q, stmtName string) *stmt { + st := &stmt{cn: cn, name: stmtName} + + b := cn.writeBuf('P') + b.string(st.name) + b.string(q) + b.int16(0) + + b.next('D') + b.byte('S') + b.string(st.name) + + b.next('S') + cn.send(b) + + cn.readParseResponse() + st.paramTyps, st.colNames, st.colTyps = cn.readStatementDescribeResponse() + st.colFmts, st.colFmtData = decideColumnFormats(st.colTyps, cn.disablePreparedBinaryResult) + cn.readReadyForQuery() + return st +} + +func (cn *conn) Prepare(q string) (_ driver.Stmt, err error) { + if cn.bad { + return nil, driver.ErrBadConn + } + defer cn.errRecover(&err) + + if len(q) >= 4 && strings.EqualFold(q[:4], "COPY") { + s, err := cn.prepareCopyIn(q) + if err == nil { + cn.inCopy = true + } + return s, err + } + return cn.prepareTo(q, cn.gname()), nil +} + +func (cn *conn) Close() (err error) { + // Skip cn.bad return here because we always want to close a connection. + defer cn.errRecover(&err) + + // Ensure that cn.c.Close is always run. Since error handling is done with + // panics and cn.errRecover, the Close must be in a defer. + defer func() { + cerr := cn.c.Close() + if err == nil { + err = cerr + } + }() + + // Don't go through send(); ListenerConn relies on us not scribbling on the + // scratch buffer of this connection. + return cn.sendSimpleMessage('X') +} + +// Implement the "Queryer" interface +func (cn *conn) Query(query string, args []driver.Value) (driver.Rows, error) { + return cn.query(query, args) +} + +func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) { + if cn.bad { + return nil, driver.ErrBadConn + } + if cn.inCopy { + return nil, errCopyInProgress + } + defer cn.errRecover(&err) + + // Check to see if we can use the "simpleQuery" interface, which is + // *much* faster than going through prepare/exec + if len(args) == 0 { + return cn.simpleQuery(query) + } + + if cn.binaryParameters { + cn.sendBinaryModeQuery(query, args) + + cn.readParseResponse() + cn.readBindResponse() + rows := &rows{cn: cn} + rows.colNames, rows.colFmts, rows.colTyps = cn.readPortalDescribeResponse() + cn.postExecuteWorkaround() + return rows, nil + } else { + st := cn.prepareTo(query, "") + st.exec(args) + return &rows{ + cn: cn, + colNames: st.colNames, + colTyps: st.colTyps, + colFmts: st.colFmts, + }, nil + } +} + +// Implement the optional "Execer" interface for one-shot queries +func (cn *conn) Exec(query string, args []driver.Value) (res driver.Result, err error) { + if cn.bad { + return nil, driver.ErrBadConn + } + defer cn.errRecover(&err) + + // Check to see if we can use the "simpleExec" interface, which is + // *much* faster than going through prepare/exec + if len(args) == 0 { + // ignore commandTag, our caller doesn't care + r, _, err := cn.simpleExec(query) + return r, err + } + + if cn.binaryParameters { + cn.sendBinaryModeQuery(query, args) + + cn.readParseResponse() + cn.readBindResponse() + cn.readPortalDescribeResponse() + cn.postExecuteWorkaround() + res, _, err = cn.readExecuteResponse("Execute") + return res, err + } else { + // Use the unnamed statement to defer planning until bind + // time, or else value-based selectivity estimates cannot be + // used. + st := cn.prepareTo(query, "") + r, err := st.Exec(args) + if err != nil { + panic(err) + } + return r, err + } +} + +func (cn *conn) send(m *writeBuf) { + _, err := cn.c.Write(m.wrap()) + if err != nil { + panic(err) + } +} + +func (cn *conn) sendStartupPacket(m *writeBuf) { + // sanity check + if m.buf[0] != 0 { + panic("oops") + } + + _, err := cn.c.Write((m.wrap())[1:]) + if err != nil { + panic(err) + } +} + +// Send a message of type typ to the server on the other end of cn. The +// message should have no payload. This method does not use the scratch +// buffer. +func (cn *conn) sendSimpleMessage(typ byte) (err error) { + _, err = cn.c.Write([]byte{typ, '\x00', '\x00', '\x00', '\x04'}) + return err +} + +// saveMessage memorizes a message and its buffer in the conn struct. +// recvMessage will then return these values on the next call to it. This +// method is useful in cases where you have to see what the next message is +// going to be (e.g. to see whether it's an error or not) but you can't handle +// the message yourself. +func (cn *conn) saveMessage(typ byte, buf *readBuf) { + if cn.saveMessageType != 0 { + cn.bad = true + errorf("unexpected saveMessageType %d", cn.saveMessageType) + } + cn.saveMessageType = typ + cn.saveMessageBuffer = *buf +} + +// recvMessage receives any message from the backend, or returns an error if +// a problem occurred while reading the message. +func (cn *conn) recvMessage(r *readBuf) (byte, error) { + // workaround for a QueryRow bug, see exec + if cn.saveMessageType != 0 { + t := cn.saveMessageType + *r = cn.saveMessageBuffer + cn.saveMessageType = 0 + cn.saveMessageBuffer = nil + return t, nil + } + + x := cn.scratch[:5] + _, err := io.ReadFull(cn.buf, x) + if err != nil { + return 0, err + } + + // read the type and length of the message that follows + t := x[0] + n := int(binary.BigEndian.Uint32(x[1:])) - 4 + var y []byte + if n <= len(cn.scratch) { + y = cn.scratch[:n] + } else { + y = make([]byte, n) + } + _, err = io.ReadFull(cn.buf, y) + if err != nil { + return 0, err + } + *r = y + return t, nil +} + +// recv receives a message from the backend, but if an error happened while +// reading the message or the received message was an ErrorResponse, it panics. +// NoticeResponses are ignored. This function should generally be used only +// during the startup sequence. +func (cn *conn) recv() (t byte, r *readBuf) { + for { + var err error + r = &readBuf{} + t, err = cn.recvMessage(r) + if err != nil { + panic(err) + } + + switch t { + case 'E': + panic(parseError(r)) + case 'N': + // ignore + default: + return + } + } +} + +// recv1Buf is exactly equivalent to recv1, except it uses a buffer supplied by +// the caller to avoid an allocation. +func (cn *conn) recv1Buf(r *readBuf) byte { + for { + t, err := cn.recvMessage(r) + if err != nil { + panic(err) + } + + switch t { + case 'A', 'N': + // ignore + case 'S': + cn.processParameterStatus(r) + default: + return t + } + } +} + +// recv1 receives a message from the backend, panicking if an error occurs +// while attempting to read it. All asynchronous messages are ignored, with +// the exception of ErrorResponse. +func (cn *conn) recv1() (t byte, r *readBuf) { + r = &readBuf{} + t = cn.recv1Buf(r) + return t, r +} + +func (cn *conn) ssl(o values) { + upgrade := ssl(o) + if upgrade == nil { + // Nothing to do + return + } + + w := cn.writeBuf(0) + w.int32(80877103) + cn.sendStartupPacket(w) + + b := cn.scratch[:1] + _, err := io.ReadFull(cn.c, b) + if err != nil { + panic(err) + } + + if b[0] != 'S' { + panic(ErrSSLNotSupported) + } + + cn.c = upgrade(cn.c) +} + +// isDriverSetting returns true iff a setting is purely for configuring the +// driver's options and should not be sent to the server in the connection +// startup packet. +func isDriverSetting(key string) bool { + switch key { + case "host", "port": + return true + case "password": + return true + case "sslmode", "sslcert", "sslkey", "sslrootcert": + return true + case "fallback_application_name": + return true + case "connect_timeout": + return true + case "disable_prepared_binary_result": + return true + case "binary_parameters": + return true + + default: + return false + } +} + +func (cn *conn) startup(o values) { + w := cn.writeBuf(0) + w.int32(196608) + // Send the backend the name of the database we want to connect to, and the + // user we want to connect as. Additionally, we send over any run-time + // parameters potentially included in the connection string. If the server + // doesn't recognize any of them, it will reply with an error. + for k, v := range o { + if isDriverSetting(k) { + // skip options which can't be run-time parameters + continue + } + // The protocol requires us to supply the database name as "database" + // instead of "dbname". + if k == "dbname" { + k = "database" + } + w.string(k) + w.string(v) + } + w.string("") + cn.sendStartupPacket(w) + + for { + t, r := cn.recv() + switch t { + case 'K': + cn.processBackendKeyData(r) + case 'S': + cn.processParameterStatus(r) + case 'R': + cn.auth(r, o) + case 'Z': + cn.processReadyForQuery(r) + return + default: + errorf("unknown response for startup: %q", t) + } + } +} + +func (cn *conn) auth(r *readBuf, o values) { + switch code := r.int32(); code { + case 0: + // OK + case 3: + w := cn.writeBuf('p') + w.string(o.Get("password")) + cn.send(w) + + t, r := cn.recv() + if t != 'R' { + errorf("unexpected password response: %q", t) + } + + if r.int32() != 0 { + errorf("unexpected authentication response: %q", t) + } + case 5: + s := string(r.next(4)) + w := cn.writeBuf('p') + w.string("md5" + md5s(md5s(o.Get("password")+o.Get("user"))+s)) + cn.send(w) + + t, r := cn.recv() + if t != 'R' { + errorf("unexpected password response: %q", t) + } + + if r.int32() != 0 { + errorf("unexpected authentication response: %q", t) + } + default: + errorf("unknown authentication response: %d", code) + } +} + +type format int + +const formatText format = 0 +const formatBinary format = 1 + +// One result-column format code with the value 1 (i.e. all binary). +var colFmtDataAllBinary []byte = []byte{0, 1, 0, 1} + +// No result-column format codes (i.e. all text). +var colFmtDataAllText []byte = []byte{0, 0} + +type stmt struct { + cn *conn + name string + colNames []string + colFmts []format + colFmtData []byte + colTyps []oid.Oid + paramTyps []oid.Oid + closed bool +} + +func (st *stmt) Close() (err error) { + if st.closed { + return nil + } + if st.cn.bad { + return driver.ErrBadConn + } + defer st.cn.errRecover(&err) + + w := st.cn.writeBuf('C') + w.byte('S') + w.string(st.name) + st.cn.send(w) + + st.cn.send(st.cn.writeBuf('S')) + + t, _ := st.cn.recv1() + if t != '3' { + st.cn.bad = true + errorf("unexpected close response: %q", t) + } + st.closed = true + + t, r := st.cn.recv1() + if t != 'Z' { + st.cn.bad = true + errorf("expected ready for query, but got: %q", t) + } + st.cn.processReadyForQuery(r) + + return nil +} + +func (st *stmt) Query(v []driver.Value) (r driver.Rows, err error) { + if st.cn.bad { + return nil, driver.ErrBadConn + } + defer st.cn.errRecover(&err) + + st.exec(v) + return &rows{ + cn: st.cn, + colNames: st.colNames, + colTyps: st.colTyps, + colFmts: st.colFmts, + }, nil +} + +func (st *stmt) Exec(v []driver.Value) (res driver.Result, err error) { + if st.cn.bad { + return nil, driver.ErrBadConn + } + defer st.cn.errRecover(&err) + + st.exec(v) + res, _, err = st.cn.readExecuteResponse("simple query") + return res, err +} + +func (st *stmt) exec(v []driver.Value) { + if len(v) >= 65536 { + errorf("got %d parameters but PostgreSQL only supports 65535 parameters", len(v)) + } + if len(v) != len(st.paramTyps) { + errorf("got %d parameters but the statement requires %d", len(v), len(st.paramTyps)) + } + + cn := st.cn + w := cn.writeBuf('B') + w.byte(0) // unnamed portal + w.string(st.name) + + if cn.binaryParameters { + cn.sendBinaryParameters(w, v) + } else { + w.int16(0) + w.int16(len(v)) + for i, x := range v { + if x == nil { + w.int32(-1) + } else { + b := encode(&cn.parameterStatus, x, st.paramTyps[i]) + w.int32(len(b)) + w.bytes(b) + } + } + } + w.bytes(st.colFmtData) + + w.next('E') + w.byte(0) + w.int32(0) + + w.next('S') + cn.send(w) + + cn.readBindResponse() + cn.postExecuteWorkaround() + +} + +func (st *stmt) NumInput() int { + return len(st.paramTyps) +} + +// parseComplete parses the "command tag" from a CommandComplete message, and +// returns the number of rows affected (if applicable) and a string +// identifying only the command that was executed, e.g. "ALTER TABLE". If the +// command tag could not be parsed, parseComplete panics. +func (cn *conn) parseComplete(commandTag string) (driver.Result, string) { + commandsWithAffectedRows := []string{ + "SELECT ", + // INSERT is handled below + "UPDATE ", + "DELETE ", + "FETCH ", + "MOVE ", + "COPY ", + } + + var affectedRows *string + for _, tag := range commandsWithAffectedRows { + if strings.HasPrefix(commandTag, tag) { + t := commandTag[len(tag):] + affectedRows = &t + commandTag = tag[:len(tag)-1] + break + } + } + // INSERT also includes the oid of the inserted row in its command tag. + // Oids in user tables are deprecated, and the oid is only returned when + // exactly one row is inserted, so it's unlikely to be of value to any + // real-world application and we can ignore it. + if affectedRows == nil && strings.HasPrefix(commandTag, "INSERT ") { + parts := strings.Split(commandTag, " ") + if len(parts) != 3 { + cn.bad = true + errorf("unexpected INSERT command tag %s", commandTag) + } + affectedRows = &parts[len(parts)-1] + commandTag = "INSERT" + } + // There should be no affected rows attached to the tag, just return it + if affectedRows == nil { + return driver.RowsAffected(0), commandTag + } + n, err := strconv.ParseInt(*affectedRows, 10, 64) + if err != nil { + cn.bad = true + errorf("could not parse commandTag: %s", err) + } + return driver.RowsAffected(n), commandTag +} + +type rows struct { + cn *conn + closed chan<- struct{} + colNames []string + colTyps []oid.Oid + colFmts []format + done bool + rb readBuf +} + +func (rs *rows) Close() error { + if rs.closed != nil { + defer close(rs.closed) + } + // no need to look at cn.bad as Next() will + for { + err := rs.Next(nil) + switch err { + case nil: + case io.EOF: + return nil + default: + return err + } + } +} + +func (rs *rows) Columns() []string { + return rs.colNames +} + +func (rs *rows) Next(dest []driver.Value) (err error) { + if rs.done { + return io.EOF + } + + conn := rs.cn + if conn.bad { + return driver.ErrBadConn + } + defer conn.errRecover(&err) + + for { + t := conn.recv1Buf(&rs.rb) + switch t { + case 'E': + err = parseError(&rs.rb) + case 'C', 'I': + continue + case 'Z': + conn.processReadyForQuery(&rs.rb) + rs.done = true + if err != nil { + return err + } + return io.EOF + case 'D': + n := rs.rb.int16() + if err != nil { + conn.bad = true + errorf("unexpected DataRow after error %s", err) + } + if n < len(dest) { + dest = dest[:n] + } + for i := range dest { + l := rs.rb.int32() + if l == -1 { + dest[i] = nil + continue + } + dest[i] = decode(&conn.parameterStatus, rs.rb.next(l), rs.colTyps[i], rs.colFmts[i]) + } + return + case 'T': + rs.colNames, rs.colFmts, rs.colTyps = parsePortalRowDescribe(&rs.rb) + return io.EOF + default: + errorf("unexpected message after execute: %q", t) + } + } +} + +func (rs *rows) HasNextResultSet() bool { + return !rs.done +} + +func (rs *rows) NextResultSet() error { + return nil +} + +// QuoteIdentifier quotes an "identifier" (e.g. a table or a column name) to be +// used as part of an SQL statement. For example: +// +// tblname := "my_table" +// data := "my_data" +// err = db.Exec(fmt.Sprintf("INSERT INTO %s VALUES ($1)", pq.QuoteIdentifier(tblname)), data) +// +// Any double quotes in name will be escaped. The quoted identifier will be +// case sensitive when used in a query. If the input string contains a zero +// byte, the result will be truncated immediately before it. +func QuoteIdentifier(name string) string { + end := strings.IndexRune(name, 0) + if end > -1 { + name = name[:end] + } + return `"` + strings.Replace(name, `"`, `""`, -1) + `"` +} + +func md5s(s string) string { + h := md5.New() + h.Write([]byte(s)) + return fmt.Sprintf("%x", h.Sum(nil)) +} + +func (cn *conn) sendBinaryParameters(b *writeBuf, args []driver.Value) { + // Do one pass over the parameters to see if we're going to send any of + // them over in binary. If we are, create a paramFormats array at the + // same time. + var paramFormats []int + for i, x := range args { + _, ok := x.([]byte) + if ok { + if paramFormats == nil { + paramFormats = make([]int, len(args)) + } + paramFormats[i] = 1 + } + } + if paramFormats == nil { + b.int16(0) + } else { + b.int16(len(paramFormats)) + for _, x := range paramFormats { + b.int16(x) + } + } + + b.int16(len(args)) + for _, x := range args { + if x == nil { + b.int32(-1) + } else { + datum := binaryEncode(&cn.parameterStatus, x) + b.int32(len(datum)) + b.bytes(datum) + } + } +} + +func (cn *conn) sendBinaryModeQuery(query string, args []driver.Value) { + if len(args) >= 65536 { + errorf("got %d parameters but PostgreSQL only supports 65535 parameters", len(args)) + } + + b := cn.writeBuf('P') + b.byte(0) // unnamed statement + b.string(query) + b.int16(0) + + b.next('B') + b.int16(0) // unnamed portal and statement + cn.sendBinaryParameters(b, args) + b.bytes(colFmtDataAllText) + + b.next('D') + b.byte('P') + b.byte(0) // unnamed portal + + b.next('E') + b.byte(0) + b.int32(0) + + b.next('S') + cn.send(b) +} + +func (c *conn) processParameterStatus(r *readBuf) { + var err error + + param := r.string() + switch param { + case "server_version": + var major1 int + var major2 int + var minor int + _, err = fmt.Sscanf(r.string(), "%d.%d.%d", &major1, &major2, &minor) + if err == nil { + c.parameterStatus.serverVersion = major1*10000 + major2*100 + minor + } + + case "TimeZone": + c.parameterStatus.currentLocation, err = time.LoadLocation(r.string()) + if err != nil { + c.parameterStatus.currentLocation = nil + } + + default: + // ignore + } +} + +func (c *conn) processReadyForQuery(r *readBuf) { + c.txnStatus = transactionStatus(r.byte()) +} + +func (cn *conn) readReadyForQuery() { + t, r := cn.recv1() + switch t { + case 'Z': + cn.processReadyForQuery(r) + return + default: + cn.bad = true + errorf("unexpected message %q; expected ReadyForQuery", t) + } +} + +func (c *conn) processBackendKeyData(r *readBuf) { + c.processID = r.int32() + c.secretKey = r.int32() +} + +func (cn *conn) readParseResponse() { + t, r := cn.recv1() + switch t { + case '1': + return + case 'E': + err := parseError(r) + cn.readReadyForQuery() + panic(err) + default: + cn.bad = true + errorf("unexpected Parse response %q", t) + } +} + +func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames []string, colTyps []oid.Oid) { + for { + t, r := cn.recv1() + switch t { + case 't': + nparams := r.int16() + paramTyps = make([]oid.Oid, nparams) + for i := range paramTyps { + paramTyps[i] = r.oid() + } + case 'n': + return paramTyps, nil, nil + case 'T': + colNames, colTyps = parseStatementRowDescribe(r) + return paramTyps, colNames, colTyps + case 'E': + err := parseError(r) + cn.readReadyForQuery() + panic(err) + default: + cn.bad = true + errorf("unexpected Describe statement response %q", t) + } + } +} + +func (cn *conn) readPortalDescribeResponse() (colNames []string, colFmts []format, colTyps []oid.Oid) { + t, r := cn.recv1() + switch t { + case 'T': + return parsePortalRowDescribe(r) + case 'n': + return nil, nil, nil + case 'E': + err := parseError(r) + cn.readReadyForQuery() + panic(err) + default: + cn.bad = true + errorf("unexpected Describe response %q", t) + } + panic("not reached") +} + +func (cn *conn) readBindResponse() { + t, r := cn.recv1() + switch t { + case '2': + return + case 'E': + err := parseError(r) + cn.readReadyForQuery() + panic(err) + default: + cn.bad = true + errorf("unexpected Bind response %q", t) + } +} + +func (cn *conn) postExecuteWorkaround() { + // Work around a bug in sql.DB.QueryRow: in Go 1.2 and earlier it ignores + // any errors from rows.Next, which masks errors that happened during the + // execution of the query. To avoid the problem in common cases, we wait + // here for one more message from the database. If it's not an error the + // query will likely succeed (or perhaps has already, if it's a + // CommandComplete), so we push the message into the conn struct; recv1 + // will return it as the next message for rows.Next or rows.Close. + // However, if it's an error, we wait until ReadyForQuery and then return + // the error to our caller. + for { + t, r := cn.recv1() + switch t { + case 'E': + err := parseError(r) + cn.readReadyForQuery() + panic(err) + case 'C', 'D', 'I': + // the query didn't fail, but we can't process this message + cn.saveMessage(t, r) + return + default: + cn.bad = true + errorf("unexpected message during extended query execution: %q", t) + } + } +} + +// Only for Exec(), since we ignore the returned data +func (cn *conn) readExecuteResponse(protocolState string) (res driver.Result, commandTag string, err error) { + for { + t, r := cn.recv1() + switch t { + case 'C': + if err != nil { + cn.bad = true + errorf("unexpected CommandComplete after error %s", err) + } + res, commandTag = cn.parseComplete(r.string()) + case 'Z': + cn.processReadyForQuery(r) + if res == nil && err == nil { + err = errUnexpectedReady + } + return res, commandTag, err + case 'E': + err = parseError(r) + case 'T', 'D', 'I': + if err != nil { + cn.bad = true + errorf("unexpected %q after error %s", t, err) + } + if t == 'I' { + res = emptyRows + } + // ignore any results + default: + cn.bad = true + errorf("unknown %s response: %q", protocolState, t) + } + } +} + +func parseStatementRowDescribe(r *readBuf) (colNames []string, colTyps []oid.Oid) { + n := r.int16() + colNames = make([]string, n) + colTyps = make([]oid.Oid, n) + for i := range colNames { + colNames[i] = r.string() + r.next(6) + colTyps[i] = r.oid() + r.next(6) + // format code not known when describing a statement; always 0 + r.next(2) + } + return +} + +func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, colTyps []oid.Oid) { + n := r.int16() + colNames = make([]string, n) + colFmts = make([]format, n) + colTyps = make([]oid.Oid, n) + for i := range colNames { + colNames[i] = r.string() + r.next(6) + colTyps[i] = r.oid() + r.next(6) + colFmts[i] = format(r.int16()) + } + return +} + +// parseEnviron tries to mimic some of libpq's environment handling +// +// To ease testing, it does not directly reference os.Environ, but is +// designed to accept its output. +// +// Environment-set connection information is intended to have a higher +// precedence than a library default but lower than any explicitly +// passed information (such as in the URL or connection string). +func parseEnviron(env []string) (out map[string]string) { + out = make(map[string]string) + + for _, v := range env { + parts := strings.SplitN(v, "=", 2) + + accrue := func(keyname string) { + out[keyname] = parts[1] + } + unsupported := func() { + panic(fmt.Sprintf("setting %v not supported", parts[0])) + } + + // The order of these is the same as is seen in the + // PostgreSQL 9.1 manual. Unsupported but well-defined + // keys cause a panic; these should be unset prior to + // execution. Options which pq expects to be set to a + // certain value are allowed, but must be set to that + // value if present (they can, of course, be absent). + switch parts[0] { + case "PGHOST": + accrue("host") + case "PGHOSTADDR": + unsupported() + case "PGPORT": + accrue("port") + case "PGDATABASE": + accrue("dbname") + case "PGUSER": + accrue("user") + case "PGPASSWORD": + accrue("password") + case "PGSERVICE", "PGSERVICEFILE", "PGREALM": + unsupported() + case "PGOPTIONS": + accrue("options") + case "PGAPPNAME": + accrue("application_name") + case "PGSSLMODE": + accrue("sslmode") + case "PGSSLCERT": + accrue("sslcert") + case "PGSSLKEY": + accrue("sslkey") + case "PGSSLROOTCERT": + accrue("sslrootcert") + case "PGREQUIRESSL", "PGSSLCRL": + unsupported() + case "PGREQUIREPEER": + unsupported() + case "PGKRBSRVNAME", "PGGSSLIB": + unsupported() + case "PGCONNECT_TIMEOUT": + accrue("connect_timeout") + case "PGCLIENTENCODING": + accrue("client_encoding") + case "PGDATESTYLE": + accrue("datestyle") + case "PGTZ": + accrue("timezone") + case "PGGEQO": + accrue("geqo") + case "PGSYSCONFDIR", "PGLOCALEDIR": + unsupported() + } + } + + return out +} + +// isUTF8 returns whether name is a fuzzy variation of the string "UTF-8". +func isUTF8(name string) bool { + // Recognize all sorts of silly things as "UTF-8", like Postgres does + s := strings.Map(alnumLowerASCII, name) + return s == "utf8" || s == "unicode" +} + +func alnumLowerASCII(ch rune) rune { + if 'A' <= ch && ch <= 'Z' { + return ch + ('a' - 'A') + } + if 'a' <= ch && ch <= 'z' || '0' <= ch && ch <= '9' { + return ch + } + return -1 // discard +} diff --git a/vendor/src/github.com/lib/pq/conn_go18.go b/vendor/src/github.com/lib/pq/conn_go18.go new file mode 100644 index 00000000..0aca1d00 --- /dev/null +++ b/vendor/src/github.com/lib/pq/conn_go18.go @@ -0,0 +1,92 @@ +// +build go1.8 + +package pq + +import ( + "context" + "database/sql/driver" + "errors" +) + +// Implement the "QueryerContext" interface +func (cn *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { + list := make([]driver.Value, len(args)) + for i, nv := range args { + list[i] = nv.Value + } + var closed chan<- struct{} + if ctx.Done() != nil { + closed = watchCancel(ctx, cn.cancel) + } + r, err := cn.query(query, list) + if err != nil { + return nil, err + } + r.closed = closed + return r, nil +} + +// Implement the "ExecerContext" interface +func (cn *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { + list := make([]driver.Value, len(args)) + for i, nv := range args { + list[i] = nv.Value + } + + if ctx.Done() != nil { + closed := watchCancel(ctx, cn.cancel) + defer close(closed) + } + + return cn.Exec(query, list) +} + +// Implement the "ConnBeginTx" interface +func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { + if opts.Isolation != 0 { + return nil, errors.New("isolation levels not supported") + } + if opts.ReadOnly { + return nil, errors.New("read-only transactions not supported") + } + tx, err := cn.Begin() + if err != nil { + return nil, err + } + if ctx.Done() != nil { + cn.txnClosed = watchCancel(ctx, cn.cancel) + } + return tx, nil +} + +func watchCancel(ctx context.Context, cancel func()) chan<- struct{} { + closed := make(chan struct{}) + go func() { + select { + case <-ctx.Done(): + cancel() + case <-closed: + } + }() + return closed +} + +func (cn *conn) cancel() { + var err error + can := &conn{} + can.c, err = dial(cn.dialer, cn.opts) + if err != nil { + return + } + can.ssl(cn.opts) + + defer can.errRecover(&err) + + w := can.writeBuf(0) + w.int32(80877102) // cancel request code + w.int32(cn.processID) + w.int32(cn.secretKey) + + can.sendStartupPacket(w) + _ = can.c.Close() +} diff --git a/vendor/src/github.com/lib/pq/conn_test.go b/vendor/src/github.com/lib/pq/conn_test.go new file mode 100644 index 00000000..183e6dcd --- /dev/null +++ b/vendor/src/github.com/lib/pq/conn_test.go @@ -0,0 +1,1495 @@ +package pq + +import ( + "database/sql" + "database/sql/driver" + "fmt" + "io" + "net" + "os" + "reflect" + "strings" + "testing" + "time" +) + +type Fatalistic interface { + Fatal(args ...interface{}) +} + +func forceBinaryParameters() bool { + bp := os.Getenv("PQTEST_BINARY_PARAMETERS") + if bp == "yes" { + return true + } else if bp == "" || bp == "no" { + return false + } else { + panic("unexpected value for PQTEST_BINARY_PARAMETERS") + } +} + +func openTestConnConninfo(conninfo string) (*sql.DB, error) { + defaultTo := func(envvar string, value string) { + if os.Getenv(envvar) == "" { + os.Setenv(envvar, value) + } + } + defaultTo("PGDATABASE", "pqgotest") + defaultTo("PGSSLMODE", "disable") + defaultTo("PGCONNECT_TIMEOUT", "20") + + if forceBinaryParameters() && + !strings.HasPrefix(conninfo, "postgres://") && + !strings.HasPrefix(conninfo, "postgresql://") { + conninfo = conninfo + " binary_parameters=yes" + } + + return sql.Open("postgres", conninfo) +} + +func openTestConn(t Fatalistic) *sql.DB { + conn, err := openTestConnConninfo("") + if err != nil { + t.Fatal(err) + } + + return conn +} + +func getServerVersion(t *testing.T, db *sql.DB) int { + var version int + err := db.QueryRow("SHOW server_version_num").Scan(&version) + if err != nil { + t.Fatal(err) + } + return version +} + +func TestReconnect(t *testing.T) { + db1 := openTestConn(t) + defer db1.Close() + tx, err := db1.Begin() + if err != nil { + t.Fatal(err) + } + var pid1 int + err = tx.QueryRow("SELECT pg_backend_pid()").Scan(&pid1) + if err != nil { + t.Fatal(err) + } + db2 := openTestConn(t) + defer db2.Close() + _, err = db2.Exec("SELECT pg_terminate_backend($1)", pid1) + if err != nil { + t.Fatal(err) + } + // The rollback will probably "fail" because we just killed + // its connection above + _ = tx.Rollback() + + const expected int = 42 + var result int + err = db1.QueryRow(fmt.Sprintf("SELECT %d", expected)).Scan(&result) + if err != nil { + t.Fatal(err) + } + if result != expected { + t.Errorf("got %v; expected %v", result, expected) + } +} + +func TestCommitInFailedTransaction(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + rows, err := txn.Query("SELECT error") + if err == nil { + rows.Close() + t.Fatal("expected failure") + } + err = txn.Commit() + if err != ErrInFailedTransaction { + t.Fatalf("expected ErrInFailedTransaction; got %#v", err) + } +} + +func TestOpenURL(t *testing.T) { + testURL := func(url string) { + db, err := openTestConnConninfo(url) + if err != nil { + t.Fatal(err) + } + defer db.Close() + // database/sql might not call our Open at all unless we do something with + // the connection + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + txn.Rollback() + } + testURL("postgres://") + testURL("postgresql://") +} + +const pgpass_file = "/tmp/pqgotest_pgpass" + +func TestPgpass(t *testing.T) { + if os.Getenv("TRAVIS") != "true" { + t.Skip("not running under Travis, skipping pgpass tests") + } + + testAssert := func(conninfo string, expected string, reason string) { + conn, err := openTestConnConninfo(conninfo) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + txn, err := conn.Begin() + if err != nil { + if expected != "fail" { + t.Fatalf(reason, err) + } + return + } + rows, err := txn.Query("SELECT USER") + if err != nil { + txn.Rollback() + rows.Close() + if expected != "fail" { + t.Fatalf(reason, err) + } + } else { + if expected != "ok" { + t.Fatalf(reason, err) + } + } + txn.Rollback() + } + testAssert("", "ok", "missing .pgpass, unexpected error %#v") + os.Setenv("PGPASSFILE", pgpass_file) + testAssert("host=/tmp", "fail", ", unexpected error %#v") + os.Remove(pgpass_file) + pgpass, err := os.OpenFile(pgpass_file, os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + t.Fatalf("Unexpected error writing pgpass file %#v", err) + } + _, err = pgpass.WriteString(`# comment +server:5432:some_db:some_user:pass_A +*:5432:some_db:some_user:pass_B +localhost:*:*:*:pass_C +*:*:*:*:pass_fallback +`) + if err != nil { + t.Fatalf("Unexpected error writing pgpass file %#v", err) + } + pgpass.Close() + + assertPassword := func(extra values, expected string) { + o := &values{ + "host": "localhost", + "sslmode": "disable", + "connect_timeout": "20", + "user": "majid", + "port": "5432", + "extra_float_digits": "2", + "dbname": "pqgotest", + "client_encoding": "UTF8", + "datestyle": "ISO, MDY", + } + for k, v := range extra { + (*o)[k] = v + } + (&conn{}).handlePgpass(*o) + if o.Get("password") != expected { + t.Fatalf("For %v expected %s got %s", extra, expected, o.Get("password")) + } + } + // wrong permissions for the pgpass file means it should be ignored + assertPassword(values{"host": "example.com", "user": "foo"}, "") + // fix the permissions and check if it has taken effect + os.Chmod(pgpass_file, 0600) + assertPassword(values{"host": "server", "dbname": "some_db", "user": "some_user"}, "pass_A") + assertPassword(values{"host": "example.com", "user": "foo"}, "pass_fallback") + assertPassword(values{"host": "example.com", "dbname": "some_db", "user": "some_user"}, "pass_B") + // localhost also matches the default "" and UNIX sockets + assertPassword(values{"host": "", "user": "some_user"}, "pass_C") + assertPassword(values{"host": "/tmp", "user": "some_user"}, "pass_C") + // cleanup + os.Remove(pgpass_file) + os.Setenv("PGPASSFILE", "") +} + +func TestExec(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + _, err := db.Exec("CREATE TEMP TABLE temp (a int)") + if err != nil { + t.Fatal(err) + } + + r, err := db.Exec("INSERT INTO temp VALUES (1)") + if err != nil { + t.Fatal(err) + } + + if n, _ := r.RowsAffected(); n != 1 { + t.Fatalf("expected 1 row affected, not %d", n) + } + + r, err = db.Exec("INSERT INTO temp VALUES ($1), ($2), ($3)", 1, 2, 3) + if err != nil { + t.Fatal(err) + } + + if n, _ := r.RowsAffected(); n != 3 { + t.Fatalf("expected 3 rows affected, not %d", n) + } + + // SELECT doesn't send the number of returned rows in the command tag + // before 9.0 + if getServerVersion(t, db) >= 90000 { + r, err = db.Exec("SELECT g FROM generate_series(1, 2) g") + if err != nil { + t.Fatal(err) + } + if n, _ := r.RowsAffected(); n != 2 { + t.Fatalf("expected 2 rows affected, not %d", n) + } + + r, err = db.Exec("SELECT g FROM generate_series(1, $1) g", 3) + if err != nil { + t.Fatal(err) + } + if n, _ := r.RowsAffected(); n != 3 { + t.Fatalf("expected 3 rows affected, not %d", n) + } + } +} + +func TestStatment(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + st, err := db.Prepare("SELECT 1") + if err != nil { + t.Fatal(err) + } + + st1, err := db.Prepare("SELECT 2") + if err != nil { + t.Fatal(err) + } + + r, err := st.Query() + if err != nil { + t.Fatal(err) + } + defer r.Close() + + if !r.Next() { + t.Fatal("expected row") + } + + var i int + err = r.Scan(&i) + if err != nil { + t.Fatal(err) + } + + if i != 1 { + t.Fatalf("expected 1, got %d", i) + } + + // st1 + + r1, err := st1.Query() + if err != nil { + t.Fatal(err) + } + defer r1.Close() + + if !r1.Next() { + if r.Err() != nil { + t.Fatal(r1.Err()) + } + t.Fatal("expected row") + } + + err = r1.Scan(&i) + if err != nil { + t.Fatal(err) + } + + if i != 2 { + t.Fatalf("expected 2, got %d", i) + } +} + +func TestRowsCloseBeforeDone(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + r, err := db.Query("SELECT 1") + if err != nil { + t.Fatal(err) + } + + err = r.Close() + if err != nil { + t.Fatal(err) + } + + if r.Next() { + t.Fatal("unexpected row") + } + + if r.Err() != nil { + t.Fatal(r.Err()) + } +} + +func TestParameterCountMismatch(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + var notused int + err := db.QueryRow("SELECT false", 1).Scan(¬used) + if err == nil { + t.Fatal("expected err") + } + // make sure we clean up correctly + err = db.QueryRow("SELECT 1").Scan(¬used) + if err != nil { + t.Fatal(err) + } + + err = db.QueryRow("SELECT $1").Scan(¬used) + if err == nil { + t.Fatal("expected err") + } + // make sure we clean up correctly + err = db.QueryRow("SELECT 1").Scan(¬used) + if err != nil { + t.Fatal(err) + } +} + +// Test that EmptyQueryResponses are handled correctly. +func TestEmptyQuery(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + res, err := db.Exec("") + if err != nil { + t.Fatal(err) + } + if _, err := res.RowsAffected(); err != errNoRowsAffected { + t.Fatalf("expected %s, got %v", errNoRowsAffected, err) + } + if _, err := res.LastInsertId(); err != errNoLastInsertId { + t.Fatalf("expected %s, got %v", errNoLastInsertId, err) + } + rows, err := db.Query("") + if err != nil { + t.Fatal(err) + } + cols, err := rows.Columns() + if err != nil { + t.Fatal(err) + } + if len(cols) != 0 { + t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) + } + if rows.Next() { + t.Fatal("unexpected row") + } + if rows.Err() != nil { + t.Fatal(rows.Err()) + } + + stmt, err := db.Prepare("") + if err != nil { + t.Fatal(err) + } + res, err = stmt.Exec() + if err != nil { + t.Fatal(err) + } + if _, err := res.RowsAffected(); err != errNoRowsAffected { + t.Fatalf("expected %s, got %v", errNoRowsAffected, err) + } + if _, err := res.LastInsertId(); err != errNoLastInsertId { + t.Fatalf("expected %s, got %v", errNoLastInsertId, err) + } + rows, err = stmt.Query() + if err != nil { + t.Fatal(err) + } + cols, err = rows.Columns() + if err != nil { + t.Fatal(err) + } + if len(cols) != 0 { + t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) + } + if rows.Next() { + t.Fatal("unexpected row") + } + if rows.Err() != nil { + t.Fatal(rows.Err()) + } +} + +// Test that rows.Columns() is correct even if there are no result rows. +func TestEmptyResultSetColumns(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + rows, err := db.Query("SELECT 1 AS a, text 'bar' AS bar WHERE FALSE") + if err != nil { + t.Fatal(err) + } + cols, err := rows.Columns() + if err != nil { + t.Fatal(err) + } + if len(cols) != 2 { + t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) + } + if rows.Next() { + t.Fatal("unexpected row") + } + if rows.Err() != nil { + t.Fatal(rows.Err()) + } + if cols[0] != "a" || cols[1] != "bar" { + t.Fatalf("unexpected Columns result %v", cols) + } + + stmt, err := db.Prepare("SELECT $1::int AS a, text 'bar' AS bar WHERE FALSE") + if err != nil { + t.Fatal(err) + } + rows, err = stmt.Query(1) + if err != nil { + t.Fatal(err) + } + cols, err = rows.Columns() + if err != nil { + t.Fatal(err) + } + if len(cols) != 2 { + t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) + } + if rows.Next() { + t.Fatal("unexpected row") + } + if rows.Err() != nil { + t.Fatal(rows.Err()) + } + if cols[0] != "a" || cols[1] != "bar" { + t.Fatalf("unexpected Columns result %v", cols) + } + +} + +func TestEncodeDecode(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + q := ` + SELECT + E'\\000\\001\\002'::bytea, + 'foobar'::text, + NULL::integer, + '2000-1-1 01:02:03.04-7'::timestamptz, + 0::boolean, + 123, + -321, + 3.14::float8 + WHERE + E'\\000\\001\\002'::bytea = $1 + AND 'foobar'::text = $2 + AND $3::integer is NULL + ` + // AND '2000-1-1 12:00:00.000000-7'::timestamp = $3 + + exp1 := []byte{0, 1, 2} + exp2 := "foobar" + + r, err := db.Query(q, exp1, exp2, nil) + if err != nil { + t.Fatal(err) + } + defer r.Close() + + if !r.Next() { + if r.Err() != nil { + t.Fatal(r.Err()) + } + t.Fatal("expected row") + } + + var got1 []byte + var got2 string + var got3 = sql.NullInt64{Valid: true} + var got4 time.Time + var got5, got6, got7, got8 interface{} + + err = r.Scan(&got1, &got2, &got3, &got4, &got5, &got6, &got7, &got8) + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(exp1, got1) { + t.Errorf("expected %q byte: %q", exp1, got1) + } + + if !reflect.DeepEqual(exp2, got2) { + t.Errorf("expected %q byte: %q", exp2, got2) + } + + if got3.Valid { + t.Fatal("expected invalid") + } + + if got4.Year() != 2000 { + t.Fatal("wrong year") + } + + if got5 != false { + t.Fatalf("expected false, got %q", got5) + } + + if got6 != int64(123) { + t.Fatalf("expected 123, got %d", got6) + } + + if got7 != int64(-321) { + t.Fatalf("expected -321, got %d", got7) + } + + if got8 != float64(3.14) { + t.Fatalf("expected 3.14, got %f", got8) + } +} + +func TestNoData(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + st, err := db.Prepare("SELECT 1 WHERE true = false") + if err != nil { + t.Fatal(err) + } + defer st.Close() + + r, err := st.Query() + if err != nil { + t.Fatal(err) + } + defer r.Close() + + if r.Next() { + if r.Err() != nil { + t.Fatal(r.Err()) + } + t.Fatal("unexpected row") + } + + _, err = db.Query("SELECT * FROM nonexistenttable WHERE age=$1", 20) + if err == nil { + t.Fatal("Should have raised an error on non existent table") + } + + _, err = db.Query("SELECT * FROM nonexistenttable") + if err == nil { + t.Fatal("Should have raised an error on non existent table") + } +} + +func TestErrorDuringStartup(t *testing.T) { + // Don't use the normal connection setup, this is intended to + // blow up in the startup packet from a non-existent user. + db, err := openTestConnConninfo("user=thisuserreallydoesntexist") + if err != nil { + t.Fatal(err) + } + defer db.Close() + + _, err = db.Begin() + if err == nil { + t.Fatal("expected error") + } + + e, ok := err.(*Error) + if !ok { + t.Fatalf("expected Error, got %#v", err) + } else if e.Code.Name() != "invalid_authorization_specification" && e.Code.Name() != "invalid_password" { + t.Fatalf("expected invalid_authorization_specification or invalid_password, got %s (%+v)", e.Code.Name(), err) + } +} + +func TestBadConn(t *testing.T) { + var err error + + cn := conn{} + func() { + defer cn.errRecover(&err) + panic(io.EOF) + }() + if err != driver.ErrBadConn { + t.Fatalf("expected driver.ErrBadConn, got: %#v", err) + } + if !cn.bad { + t.Fatalf("expected cn.bad") + } + + cn = conn{} + func() { + defer cn.errRecover(&err) + e := &Error{Severity: Efatal} + panic(e) + }() + if err != driver.ErrBadConn { + t.Fatalf("expected driver.ErrBadConn, got: %#v", err) + } + if !cn.bad { + t.Fatalf("expected cn.bad") + } +} + +// TestCloseBadConn tests that the underlying connection can be closed with +// Close after an error. +func TestCloseBadConn(t *testing.T) { + nc, err := net.Dial("tcp", "localhost:5432") + if err != nil { + t.Fatal(err) + } + cn := conn{c: nc} + func() { + defer cn.errRecover(&err) + panic(io.EOF) + }() + // Verify we can write before closing. + if _, err := nc.Write(nil); err != nil { + t.Fatal(err) + } + // First close should close the connection. + if err := cn.Close(); err != nil { + t.Fatal(err) + } + // Verify write after closing fails. + if _, err := nc.Write(nil); err == nil { + t.Fatal("expected error") + } else if !strings.Contains(err.Error(), "use of closed network connection") { + t.Fatalf("expected use of closed network connection error, got %s", err) + } + // Verify second close fails. + if err := cn.Close(); err == nil { + t.Fatal("expected error") + } else if !strings.Contains(err.Error(), "use of closed network connection") { + t.Fatalf("expected use of closed network connection error, got %s", err) + } +} + +func TestErrorOnExec(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)") + if err != nil { + t.Fatal(err) + } + + _, err = txn.Exec("INSERT INTO foo VALUES (0), (0)") + if err == nil { + t.Fatal("Should have raised error") + } + + e, ok := err.(*Error) + if !ok { + t.Fatalf("expected Error, got %#v", err) + } else if e.Code.Name() != "unique_violation" { + t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err) + } +} + +func TestErrorOnQuery(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)") + if err != nil { + t.Fatal(err) + } + + _, err = txn.Query("INSERT INTO foo VALUES (0), (0)") + if err == nil { + t.Fatal("Should have raised error") + } + + e, ok := err.(*Error) + if !ok { + t.Fatalf("expected Error, got %#v", err) + } else if e.Code.Name() != "unique_violation" { + t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err) + } +} + +func TestErrorOnQueryRowSimpleQuery(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)") + if err != nil { + t.Fatal(err) + } + + var v int + err = txn.QueryRow("INSERT INTO foo VALUES (0), (0)").Scan(&v) + if err == nil { + t.Fatal("Should have raised error") + } + + e, ok := err.(*Error) + if !ok { + t.Fatalf("expected Error, got %#v", err) + } else if e.Code.Name() != "unique_violation" { + t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err) + } +} + +// Test the QueryRow bug workarounds in stmt.exec() and simpleQuery() +func TestQueryRowBugWorkaround(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + // stmt.exec() + _, err := db.Exec("CREATE TEMP TABLE notnulltemp (a varchar(10) not null)") + if err != nil { + t.Fatal(err) + } + + var a string + err = db.QueryRow("INSERT INTO notnulltemp(a) values($1) RETURNING a", nil).Scan(&a) + if err == sql.ErrNoRows { + t.Fatalf("expected constraint violation error; got: %v", err) + } + pge, ok := err.(*Error) + if !ok { + t.Fatalf("expected *Error; got: %#v", err) + } + if pge.Code.Name() != "not_null_violation" { + t.Fatalf("expected not_null_violation; got: %s (%+v)", pge.Code.Name(), err) + } + + // Test workaround in simpleQuery() + tx, err := db.Begin() + if err != nil { + t.Fatalf("unexpected error %s in Begin", err) + } + defer tx.Rollback() + + _, err = tx.Exec("SET LOCAL check_function_bodies TO FALSE") + if err != nil { + t.Fatalf("could not disable check_function_bodies: %s", err) + } + _, err = tx.Exec(` +CREATE OR REPLACE FUNCTION bad_function() +RETURNS integer +-- hack to prevent the function from being inlined +SET check_function_bodies TO TRUE +AS $$ + SELECT text 'bad' +$$ LANGUAGE sql`) + if err != nil { + t.Fatalf("could not create function: %s", err) + } + + err = tx.QueryRow("SELECT * FROM bad_function()").Scan(&a) + if err == nil { + t.Fatalf("expected error") + } + pge, ok = err.(*Error) + if !ok { + t.Fatalf("expected *Error; got: %#v", err) + } + if pge.Code.Name() != "invalid_function_definition" { + t.Fatalf("expected invalid_function_definition; got: %s (%+v)", pge.Code.Name(), err) + } + + err = tx.Rollback() + if err != nil { + t.Fatalf("unexpected error %s in Rollback", err) + } + + // Also test that simpleQuery()'s workaround works when the query fails + // after a row has been received. + rows, err := db.Query(` +select + (select generate_series(1, ss.i)) +from (select gs.i + from generate_series(1, 2) gs(i) + order by gs.i limit 2) ss`) + if err != nil { + t.Fatalf("query failed: %s", err) + } + if !rows.Next() { + t.Fatalf("expected at least one result row; got %s", rows.Err()) + } + var i int + err = rows.Scan(&i) + if err != nil { + t.Fatalf("rows.Scan() failed: %s", err) + } + if i != 1 { + t.Fatalf("unexpected value for i: %d", i) + } + if rows.Next() { + t.Fatalf("unexpected row") + } + pge, ok = rows.Err().(*Error) + if !ok { + t.Fatalf("expected *Error; got: %#v", err) + } + if pge.Code.Name() != "cardinality_violation" { + t.Fatalf("expected cardinality_violation; got: %s (%+v)", pge.Code.Name(), rows.Err()) + } +} + +func TestSimpleQuery(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + r, err := db.Query("select 1") + if err != nil { + t.Fatal(err) + } + defer r.Close() + + if !r.Next() { + t.Fatal("expected row") + } +} + +func TestBindError(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + _, err := db.Exec("create temp table test (i integer)") + if err != nil { + t.Fatal(err) + } + + _, err = db.Query("select * from test where i=$1", "hhh") + if err == nil { + t.Fatal("expected an error") + } + + // Should not get error here + r, err := db.Query("select * from test where i=$1", 1) + if err != nil { + t.Fatal(err) + } + defer r.Close() +} + +func TestParseErrorInExtendedQuery(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + rows, err := db.Query("PARSE_ERROR $1", 1) + if err == nil { + t.Fatal("expected error") + } + + rows, err = db.Query("SELECT 1") + if err != nil { + t.Fatal(err) + } + rows.Close() +} + +// TestReturning tests that an INSERT query using the RETURNING clause returns a row. +func TestReturning(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + _, err := db.Exec("CREATE TEMP TABLE distributors (did integer default 0, dname text)") + if err != nil { + t.Fatal(err) + } + + rows, err := db.Query("INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') " + + "RETURNING did;") + if err != nil { + t.Fatal(err) + } + if !rows.Next() { + t.Fatal("no rows") + } + var did int + err = rows.Scan(&did) + if err != nil { + t.Fatal(err) + } + if did != 0 { + t.Fatalf("bad value for did: got %d, want %d", did, 0) + } + + if rows.Next() { + t.Fatal("unexpected next row") + } + err = rows.Err() + if err != nil { + t.Fatal(err) + } +} + +func TestIssue186(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + // Exec() a query which returns results + _, err := db.Exec("VALUES (1), (2), (3)") + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("VALUES ($1), ($2), ($3)", 1, 2, 3) + if err != nil { + t.Fatal(err) + } + + // Query() a query which doesn't return any results + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + rows, err := txn.Query("CREATE TEMP TABLE foo(f1 int)") + if err != nil { + t.Fatal(err) + } + if err = rows.Close(); err != nil { + t.Fatal(err) + } + + // small trick to get NoData from a parameterized query + _, err = txn.Exec("CREATE RULE nodata AS ON INSERT TO foo DO INSTEAD NOTHING") + if err != nil { + t.Fatal(err) + } + rows, err = txn.Query("INSERT INTO foo VALUES ($1)", 1) + if err != nil { + t.Fatal(err) + } + if err = rows.Close(); err != nil { + t.Fatal(err) + } +} + +func TestIssue196(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + row := db.QueryRow("SELECT float4 '0.10000122' = $1, float8 '35.03554004971999' = $2", + float32(0.10000122), float64(35.03554004971999)) + + var float4match, float8match bool + err := row.Scan(&float4match, &float8match) + if err != nil { + t.Fatal(err) + } + if !float4match { + t.Errorf("Expected float4 fidelity to be maintained; got no match") + } + if !float8match { + t.Errorf("Expected float8 fidelity to be maintained; got no match") + } +} + +// Test that any CommandComplete messages sent before the query results are +// ignored. +func TestIssue282(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + var search_path string + err := db.QueryRow(` + SET LOCAL search_path TO pg_catalog; + SET LOCAL search_path TO pg_catalog; + SHOW search_path`).Scan(&search_path) + if err != nil { + t.Fatal(err) + } + if search_path != "pg_catalog" { + t.Fatalf("unexpected search_path %s", search_path) + } +} + +func TestReadFloatPrecision(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + row := db.QueryRow("SELECT float4 '0.10000122', float8 '35.03554004971999'") + var float4val float32 + var float8val float64 + err := row.Scan(&float4val, &float8val) + if err != nil { + t.Fatal(err) + } + if float4val != float32(0.10000122) { + t.Errorf("Expected float4 fidelity to be maintained; got no match") + } + if float8val != float64(35.03554004971999) { + t.Errorf("Expected float8 fidelity to be maintained; got no match") + } +} + +func TestXactMultiStmt(t *testing.T) { + // minified test case based on bug reports from + // pico303@gmail.com and rangelspam@gmail.com + t.Skip("Skipping failing test") + db := openTestConn(t) + defer db.Close() + + tx, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer tx.Commit() + + rows, err := tx.Query("select 1") + if err != nil { + t.Fatal(err) + } + + if rows.Next() { + var val int32 + if err = rows.Scan(&val); err != nil { + t.Fatal(err) + } + } else { + t.Fatal("Expected at least one row in first query in xact") + } + + rows2, err := tx.Query("select 2") + if err != nil { + t.Fatal(err) + } + + if rows2.Next() { + var val2 int32 + if err := rows2.Scan(&val2); err != nil { + t.Fatal(err) + } + } else { + t.Fatal("Expected at least one row in second query in xact") + } + + if err = rows.Err(); err != nil { + t.Fatal(err) + } + + if err = rows2.Err(); err != nil { + t.Fatal(err) + } + + if err = tx.Commit(); err != nil { + t.Fatal(err) + } +} + +var envParseTests = []struct { + Expected map[string]string + Env []string +}{ + { + Env: []string{"PGDATABASE=hello", "PGUSER=goodbye"}, + Expected: map[string]string{"dbname": "hello", "user": "goodbye"}, + }, + { + Env: []string{"PGDATESTYLE=ISO, MDY"}, + Expected: map[string]string{"datestyle": "ISO, MDY"}, + }, + { + Env: []string{"PGCONNECT_TIMEOUT=30"}, + Expected: map[string]string{"connect_timeout": "30"}, + }, +} + +func TestParseEnviron(t *testing.T) { + for i, tt := range envParseTests { + results := parseEnviron(tt.Env) + if !reflect.DeepEqual(tt.Expected, results) { + t.Errorf("%d: Expected: %#v Got: %#v", i, tt.Expected, results) + } + } +} + +func TestParseComplete(t *testing.T) { + tpc := func(commandTag string, command string, affectedRows int64, shouldFail bool) { + defer func() { + if p := recover(); p != nil { + if !shouldFail { + t.Error(p) + } + } + }() + cn := &conn{} + res, c := cn.parseComplete(commandTag) + if c != command { + t.Errorf("Expected %v, got %v", command, c) + } + n, err := res.RowsAffected() + if err != nil { + t.Fatal(err) + } + if n != affectedRows { + t.Errorf("Expected %d, got %d", affectedRows, n) + } + } + + tpc("ALTER TABLE", "ALTER TABLE", 0, false) + tpc("INSERT 0 1", "INSERT", 1, false) + tpc("UPDATE 100", "UPDATE", 100, false) + tpc("SELECT 100", "SELECT", 100, false) + tpc("FETCH 100", "FETCH", 100, false) + // allow COPY (and others) without row count + tpc("COPY", "COPY", 0, false) + // don't fail on command tags we don't recognize + tpc("UNKNOWNCOMMANDTAG", "UNKNOWNCOMMANDTAG", 0, false) + + // failure cases + tpc("INSERT 1", "", 0, true) // missing oid + tpc("UPDATE 0 1", "", 0, true) // too many numbers + tpc("SELECT foo", "", 0, true) // invalid row count +} + +func TestExecerInterface(t *testing.T) { + // Gin up a straw man private struct just for the type check + cn := &conn{c: nil} + var cni interface{} = cn + + _, ok := cni.(driver.Execer) + if !ok { + t.Fatal("Driver doesn't implement Execer") + } +} + +func TestNullAfterNonNull(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + r, err := db.Query("SELECT 9::integer UNION SELECT NULL::integer") + if err != nil { + t.Fatal(err) + } + + var n sql.NullInt64 + + if !r.Next() { + if r.Err() != nil { + t.Fatal(err) + } + t.Fatal("expected row") + } + + if err := r.Scan(&n); err != nil { + t.Fatal(err) + } + + if n.Int64 != 9 { + t.Fatalf("expected 2, not %d", n.Int64) + } + + if !r.Next() { + if r.Err() != nil { + t.Fatal(err) + } + t.Fatal("expected row") + } + + if err := r.Scan(&n); err != nil { + t.Fatal(err) + } + + if n.Valid { + t.Fatal("expected n to be invalid") + } + + if n.Int64 != 0 { + t.Fatalf("expected n to 2, not %d", n.Int64) + } +} + +func Test64BitErrorChecking(t *testing.T) { + defer func() { + if err := recover(); err != nil { + t.Fatal("panic due to 0xFFFFFFFF != -1 " + + "when int is 64 bits") + } + }() + + db := openTestConn(t) + defer db.Close() + + r, err := db.Query(`SELECT * +FROM (VALUES (0::integer, NULL::text), (1, 'test string')) AS t;`) + + if err != nil { + t.Fatal(err) + } + + defer r.Close() + + for r.Next() { + } +} + +func TestCommit(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + _, err := db.Exec("CREATE TEMP TABLE temp (a int)") + if err != nil { + t.Fatal(err) + } + sqlInsert := "INSERT INTO temp VALUES (1)" + sqlSelect := "SELECT * FROM temp" + tx, err := db.Begin() + if err != nil { + t.Fatal(err) + } + _, err = tx.Exec(sqlInsert) + if err != nil { + t.Fatal(err) + } + err = tx.Commit() + if err != nil { + t.Fatal(err) + } + var i int + err = db.QueryRow(sqlSelect).Scan(&i) + if err != nil { + t.Fatal(err) + } + if i != 1 { + t.Fatalf("expected 1, got %d", i) + } +} + +func TestErrorClass(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + _, err := db.Query("SELECT int 'notint'") + if err == nil { + t.Fatal("expected error") + } + pge, ok := err.(*Error) + if !ok { + t.Fatalf("expected *pq.Error, got %#+v", err) + } + if pge.Code.Class() != "22" { + t.Fatalf("expected class 28, got %v", pge.Code.Class()) + } + if pge.Code.Class().Name() != "data_exception" { + t.Fatalf("expected data_exception, got %v", pge.Code.Class().Name()) + } +} + +func TestParseOpts(t *testing.T) { + tests := []struct { + in string + expected values + valid bool + }{ + {"dbname=hello user=goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, + {"dbname=hello user=goodbye ", values{"dbname": "hello", "user": "goodbye"}, true}, + {"dbname = hello user=goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, + {"dbname=hello user =goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, + {"dbname=hello user= goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, + {"host=localhost password='correct horse battery staple'", values{"host": "localhost", "password": "correct horse battery staple"}, true}, + {"dbname=データベース password=パスワード", values{"dbname": "データベース", "password": "パスワード"}, true}, + {"dbname=hello user=''", values{"dbname": "hello", "user": ""}, true}, + {"user='' dbname=hello", values{"dbname": "hello", "user": ""}, true}, + // The last option value is an empty string if there's no non-whitespace after its = + {"dbname=hello user= ", values{"dbname": "hello", "user": ""}, true}, + + // The parser ignores spaces after = and interprets the next set of non-whitespace characters as the value. + {"user= password=foo", values{"user": "password=foo"}, true}, + + // Backslash escapes next char + {`user=a\ \'\\b`, values{"user": `a '\b`}, true}, + {`user='a \'b'`, values{"user": `a 'b`}, true}, + + // Incomplete escape + {`user=x\`, values{}, false}, + + // No '=' after the key + {"postgre://marko@internet", values{}, false}, + {"dbname user=goodbye", values{}, false}, + {"user=foo blah", values{}, false}, + {"user=foo blah ", values{}, false}, + + // Unterminated quoted value + {"dbname=hello user='unterminated", values{}, false}, + } + + for _, test := range tests { + o := make(values) + err := parseOpts(test.in, o) + + switch { + case err != nil && test.valid: + t.Errorf("%q got unexpected error: %s", test.in, err) + case err == nil && test.valid && !reflect.DeepEqual(test.expected, o): + t.Errorf("%q got: %#v want: %#v", test.in, o, test.expected) + case err == nil && !test.valid: + t.Errorf("%q expected an error", test.in) + } + } +} + +func TestRuntimeParameters(t *testing.T) { + type RuntimeTestResult int + const ( + ResultUnknown RuntimeTestResult = iota + ResultSuccess + ResultError // other error + ) + + tests := []struct { + conninfo string + param string + expected string + expectedOutcome RuntimeTestResult + }{ + // invalid parameter + {"DOESNOTEXIST=foo", "", "", ResultError}, + // we can only work with a specific value for these two + {"client_encoding=SQL_ASCII", "", "", ResultError}, + {"datestyle='ISO, YDM'", "", "", ResultError}, + // "options" should work exactly as it does in libpq + {"options='-c search_path=pqgotest'", "search_path", "pqgotest", ResultSuccess}, + // pq should override client_encoding in this case + {"options='-c client_encoding=SQL_ASCII'", "client_encoding", "UTF8", ResultSuccess}, + // allow client_encoding to be set explicitly + {"client_encoding=UTF8", "client_encoding", "UTF8", ResultSuccess}, + // test a runtime parameter not supported by libpq + {"work_mem='139kB'", "work_mem", "139kB", ResultSuccess}, + // test fallback_application_name + {"application_name=foo fallback_application_name=bar", "application_name", "foo", ResultSuccess}, + {"application_name='' fallback_application_name=bar", "application_name", "", ResultSuccess}, + {"fallback_application_name=bar", "application_name", "bar", ResultSuccess}, + } + + for _, test := range tests { + db, err := openTestConnConninfo(test.conninfo) + if err != nil { + t.Fatal(err) + } + + // application_name didn't exist before 9.0 + if test.param == "application_name" && getServerVersion(t, db) < 90000 { + db.Close() + continue + } + + tryGetParameterValue := func() (value string, outcome RuntimeTestResult) { + defer db.Close() + row := db.QueryRow("SELECT current_setting($1)", test.param) + err = row.Scan(&value) + if err != nil { + return "", ResultError + } + return value, ResultSuccess + } + + value, outcome := tryGetParameterValue() + if outcome != test.expectedOutcome && outcome == ResultError { + t.Fatalf("%v: unexpected error: %v", test.conninfo, err) + } + if outcome != test.expectedOutcome { + t.Fatalf("unexpected outcome %v (was expecting %v) for conninfo \"%s\"", + outcome, test.expectedOutcome, test.conninfo) + } + if value != test.expected { + t.Fatalf("bad value for %s: got %s, want %s with conninfo \"%s\"", + test.param, value, test.expected, test.conninfo) + } + } +} + +func TestIsUTF8(t *testing.T) { + var cases = []struct { + name string + want bool + }{ + {"unicode", true}, + {"utf-8", true}, + {"utf_8", true}, + {"UTF-8", true}, + {"UTF8", true}, + {"utf8", true}, + {"u n ic_ode", true}, + {"ut_f%8", true}, + {"ubf8", false}, + {"punycode", false}, + } + + for _, test := range cases { + if g := isUTF8(test.name); g != test.want { + t.Errorf("isUTF8(%q) = %v want %v", test.name, g, test.want) + } + } +} + +func TestQuoteIdentifier(t *testing.T) { + var cases = []struct { + input string + want string + }{ + {`foo`, `"foo"`}, + {`foo bar baz`, `"foo bar baz"`}, + {`foo"bar`, `"foo""bar"`}, + {"foo\x00bar", `"foo"`}, + {"\x00foo", `""`}, + } + + for _, test := range cases { + got := QuoteIdentifier(test.input) + if got != test.want { + t.Errorf("QuoteIdentifier(%q) = %v want %v", test.input, got, test.want) + } + } +} diff --git a/vendor/src/github.com/lib/pq/copy.go b/vendor/src/github.com/lib/pq/copy.go new file mode 100644 index 00000000..345c2398 --- /dev/null +++ b/vendor/src/github.com/lib/pq/copy.go @@ -0,0 +1,282 @@ +package pq + +import ( + "database/sql/driver" + "encoding/binary" + "errors" + "fmt" + "sync" +) + +var ( + errCopyInClosed = errors.New("pq: copyin statement has already been closed") + errBinaryCopyNotSupported = errors.New("pq: only text format supported for COPY") + errCopyToNotSupported = errors.New("pq: COPY TO is not supported") + errCopyNotSupportedOutsideTxn = errors.New("pq: COPY is only allowed inside a transaction") + errCopyInProgress = errors.New("pq: COPY in progress") +) + +// CopyIn creates a COPY FROM statement which can be prepared with +// Tx.Prepare(). The target table should be visible in search_path. +func CopyIn(table string, columns ...string) string { + stmt := "COPY " + QuoteIdentifier(table) + " (" + for i, col := range columns { + if i != 0 { + stmt += ", " + } + stmt += QuoteIdentifier(col) + } + stmt += ") FROM STDIN" + return stmt +} + +// CopyInSchema creates a COPY FROM statement which can be prepared with +// Tx.Prepare(). +func CopyInSchema(schema, table string, columns ...string) string { + stmt := "COPY " + QuoteIdentifier(schema) + "." + QuoteIdentifier(table) + " (" + for i, col := range columns { + if i != 0 { + stmt += ", " + } + stmt += QuoteIdentifier(col) + } + stmt += ") FROM STDIN" + return stmt +} + +type copyin struct { + cn *conn + buffer []byte + rowData chan []byte + done chan bool + + closed bool + + sync.Mutex // guards err + err error +} + +const ciBufferSize = 64 * 1024 + +// flush buffer before the buffer is filled up and needs reallocation +const ciBufferFlushSize = 63 * 1024 + +func (cn *conn) prepareCopyIn(q string) (_ driver.Stmt, err error) { + if !cn.isInTransaction() { + return nil, errCopyNotSupportedOutsideTxn + } + + ci := ©in{ + cn: cn, + buffer: make([]byte, 0, ciBufferSize), + rowData: make(chan []byte), + done: make(chan bool, 1), + } + // add CopyData identifier + 4 bytes for message length + ci.buffer = append(ci.buffer, 'd', 0, 0, 0, 0) + + b := cn.writeBuf('Q') + b.string(q) + cn.send(b) + +awaitCopyInResponse: + for { + t, r := cn.recv1() + switch t { + case 'G': + if r.byte() != 0 { + err = errBinaryCopyNotSupported + break awaitCopyInResponse + } + go ci.resploop() + return ci, nil + case 'H': + err = errCopyToNotSupported + break awaitCopyInResponse + case 'E': + err = parseError(r) + case 'Z': + if err == nil { + ci.setBad() + errorf("unexpected ReadyForQuery in response to COPY") + } + cn.processReadyForQuery(r) + return nil, err + default: + ci.setBad() + errorf("unknown response for copy query: %q", t) + } + } + + // something went wrong, abort COPY before we return + b = cn.writeBuf('f') + b.string(err.Error()) + cn.send(b) + + for { + t, r := cn.recv1() + switch t { + case 'c', 'C', 'E': + case 'Z': + // correctly aborted, we're done + cn.processReadyForQuery(r) + return nil, err + default: + ci.setBad() + errorf("unknown response for CopyFail: %q", t) + } + } +} + +func (ci *copyin) flush(buf []byte) { + // set message length (without message identifier) + binary.BigEndian.PutUint32(buf[1:], uint32(len(buf)-1)) + + _, err := ci.cn.c.Write(buf) + if err != nil { + panic(err) + } +} + +func (ci *copyin) resploop() { + for { + var r readBuf + t, err := ci.cn.recvMessage(&r) + if err != nil { + ci.setBad() + ci.setError(err) + ci.done <- true + return + } + switch t { + case 'C': + // complete + case 'N': + // NoticeResponse + case 'Z': + ci.cn.processReadyForQuery(&r) + ci.done <- true + return + case 'E': + err := parseError(&r) + ci.setError(err) + default: + ci.setBad() + ci.setError(fmt.Errorf("unknown response during CopyIn: %q", t)) + ci.done <- true + return + } + } +} + +func (ci *copyin) setBad() { + ci.Lock() + ci.cn.bad = true + ci.Unlock() +} + +func (ci *copyin) isBad() bool { + ci.Lock() + b := ci.cn.bad + ci.Unlock() + return b +} + +func (ci *copyin) isErrorSet() bool { + ci.Lock() + isSet := (ci.err != nil) + ci.Unlock() + return isSet +} + +// setError() sets ci.err if one has not been set already. Caller must not be +// holding ci.Mutex. +func (ci *copyin) setError(err error) { + ci.Lock() + if ci.err == nil { + ci.err = err + } + ci.Unlock() +} + +func (ci *copyin) NumInput() int { + return -1 +} + +func (ci *copyin) Query(v []driver.Value) (r driver.Rows, err error) { + return nil, ErrNotSupported +} + +// Exec inserts values into the COPY stream. The insert is asynchronous +// and Exec can return errors from previous Exec calls to the same +// COPY stmt. +// +// You need to call Exec(nil) to sync the COPY stream and to get any +// errors from pending data, since Stmt.Close() doesn't return errors +// to the user. +func (ci *copyin) Exec(v []driver.Value) (r driver.Result, err error) { + if ci.closed { + return nil, errCopyInClosed + } + + if ci.isBad() { + return nil, driver.ErrBadConn + } + defer ci.cn.errRecover(&err) + + if ci.isErrorSet() { + return nil, ci.err + } + + if len(v) == 0 { + return nil, ci.Close() + } + + numValues := len(v) + for i, value := range v { + ci.buffer = appendEncodedText(&ci.cn.parameterStatus, ci.buffer, value) + if i < numValues-1 { + ci.buffer = append(ci.buffer, '\t') + } + } + + ci.buffer = append(ci.buffer, '\n') + + if len(ci.buffer) > ciBufferFlushSize { + ci.flush(ci.buffer) + // reset buffer, keep bytes for message identifier and length + ci.buffer = ci.buffer[:5] + } + + return driver.RowsAffected(0), nil +} + +func (ci *copyin) Close() (err error) { + if ci.closed { // Don't do anything, we're already closed + return nil + } + ci.closed = true + + if ci.isBad() { + return driver.ErrBadConn + } + defer ci.cn.errRecover(&err) + + if len(ci.buffer) > 0 { + ci.flush(ci.buffer) + } + // Avoid touching the scratch buffer as resploop could be using it. + err = ci.cn.sendSimpleMessage('c') + if err != nil { + return err + } + + <-ci.done + ci.cn.inCopy = false + + if ci.isErrorSet() { + err = ci.err + return err + } + return nil +} diff --git a/vendor/src/github.com/lib/pq/copy_test.go b/vendor/src/github.com/lib/pq/copy_test.go new file mode 100644 index 00000000..86745b38 --- /dev/null +++ b/vendor/src/github.com/lib/pq/copy_test.go @@ -0,0 +1,465 @@ +package pq + +import ( + "bytes" + "database/sql" + "database/sql/driver" + "strings" + "testing" +) + +func TestCopyInStmt(t *testing.T) { + var stmt string + stmt = CopyIn("table name") + if stmt != `COPY "table name" () FROM STDIN` { + t.Fatal(stmt) + } + + stmt = CopyIn("table name", "column 1", "column 2") + if stmt != `COPY "table name" ("column 1", "column 2") FROM STDIN` { + t.Fatal(stmt) + } + + stmt = CopyIn(`table " name """`, `co"lumn""`) + if stmt != `COPY "table "" name """"""" ("co""lumn""""") FROM STDIN` { + t.Fatal(stmt) + } +} + +func TestCopyInSchemaStmt(t *testing.T) { + var stmt string + stmt = CopyInSchema("schema name", "table name") + if stmt != `COPY "schema name"."table name" () FROM STDIN` { + t.Fatal(stmt) + } + + stmt = CopyInSchema("schema name", "table name", "column 1", "column 2") + if stmt != `COPY "schema name"."table name" ("column 1", "column 2") FROM STDIN` { + t.Fatal(stmt) + } + + stmt = CopyInSchema(`schema " name """`, `table " name """`, `co"lumn""`) + if stmt != `COPY "schema "" name """"""".`+ + `"table "" name """"""" ("co""lumn""""") FROM STDIN` { + t.Fatal(stmt) + } +} + +func TestCopyInMultipleValues(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)") + if err != nil { + t.Fatal(err) + } + + stmt, err := txn.Prepare(CopyIn("temp", "a", "b")) + if err != nil { + t.Fatal(err) + } + + longString := strings.Repeat("#", 500) + + for i := 0; i < 500; i++ { + _, err = stmt.Exec(int64(i), longString) + if err != nil { + t.Fatal(err) + } + } + + _, err = stmt.Exec() + if err != nil { + t.Fatal(err) + } + + err = stmt.Close() + if err != nil { + t.Fatal(err) + } + + var num int + err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num) + if err != nil { + t.Fatal(err) + } + + if num != 500 { + t.Fatalf("expected 500 items, not %d", num) + } +} + +func TestCopyInRaiseStmtTrigger(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + if getServerVersion(t, db) < 90000 { + var exists int + err := db.QueryRow("SELECT 1 FROM pg_language WHERE lanname = 'plpgsql'").Scan(&exists) + if err == sql.ErrNoRows { + t.Skip("language PL/PgSQL does not exist; skipping TestCopyInRaiseStmtTrigger") + } else if err != nil { + t.Fatal(err) + } + } + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)") + if err != nil { + t.Fatal(err) + } + + _, err = txn.Exec(` + CREATE OR REPLACE FUNCTION pg_temp.temptest() + RETURNS trigger AS + $BODY$ begin + raise notice 'Hello world'; + return new; + end $BODY$ + LANGUAGE plpgsql`) + if err != nil { + t.Fatal(err) + } + + _, err = txn.Exec(` + CREATE TRIGGER temptest_trigger + BEFORE INSERT + ON temp + FOR EACH ROW + EXECUTE PROCEDURE pg_temp.temptest()`) + if err != nil { + t.Fatal(err) + } + + stmt, err := txn.Prepare(CopyIn("temp", "a", "b")) + if err != nil { + t.Fatal(err) + } + + longString := strings.Repeat("#", 500) + + _, err = stmt.Exec(int64(1), longString) + if err != nil { + t.Fatal(err) + } + + _, err = stmt.Exec() + if err != nil { + t.Fatal(err) + } + + err = stmt.Close() + if err != nil { + t.Fatal(err) + } + + var num int + err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num) + if err != nil { + t.Fatal(err) + } + + if num != 1 { + t.Fatalf("expected 1 items, not %d", num) + } +} + +func TestCopyInTypes(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER, text VARCHAR, blob BYTEA, nothing VARCHAR)") + if err != nil { + t.Fatal(err) + } + + stmt, err := txn.Prepare(CopyIn("temp", "num", "text", "blob", "nothing")) + if err != nil { + t.Fatal(err) + } + + _, err = stmt.Exec(int64(1234567890), "Héllö\n ☃!\r\t\\", []byte{0, 255, 9, 10, 13}, nil) + if err != nil { + t.Fatal(err) + } + + _, err = stmt.Exec() + if err != nil { + t.Fatal(err) + } + + err = stmt.Close() + if err != nil { + t.Fatal(err) + } + + var num int + var text string + var blob []byte + var nothing sql.NullString + + err = txn.QueryRow("SELECT * FROM temp").Scan(&num, &text, &blob, ¬hing) + if err != nil { + t.Fatal(err) + } + + if num != 1234567890 { + t.Fatal("unexpected result", num) + } + if text != "Héllö\n ☃!\r\t\\" { + t.Fatal("unexpected result", text) + } + if bytes.Compare(blob, []byte{0, 255, 9, 10, 13}) != 0 { + t.Fatal("unexpected result", blob) + } + if nothing.Valid { + t.Fatal("unexpected result", nothing.String) + } +} + +func TestCopyInWrongType(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)") + if err != nil { + t.Fatal(err) + } + + stmt, err := txn.Prepare(CopyIn("temp", "num")) + if err != nil { + t.Fatal(err) + } + defer stmt.Close() + + _, err = stmt.Exec("Héllö\n ☃!\r\t\\") + if err != nil { + t.Fatal(err) + } + + _, err = stmt.Exec() + if err == nil { + t.Fatal("expected error") + } + if pge := err.(*Error); pge.Code.Name() != "invalid_text_representation" { + t.Fatalf("expected 'invalid input syntax for integer' error, got %s (%+v)", pge.Code.Name(), pge) + } +} + +func TestCopyOutsideOfTxnError(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + _, err := db.Prepare(CopyIn("temp", "num")) + if err == nil { + t.Fatal("COPY outside of transaction did not return an error") + } + if err != errCopyNotSupportedOutsideTxn { + t.Fatalf("expected %s, got %s", err, err.Error()) + } +} + +func TestCopyInBinaryError(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)") + if err != nil { + t.Fatal(err) + } + _, err = txn.Prepare("COPY temp (num) FROM STDIN WITH binary") + if err != errBinaryCopyNotSupported { + t.Fatalf("expected %s, got %+v", errBinaryCopyNotSupported, err) + } + // check that the protocol is in a valid state + err = txn.Rollback() + if err != nil { + t.Fatal(err) + } +} + +func TestCopyFromError(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)") + if err != nil { + t.Fatal(err) + } + _, err = txn.Prepare("COPY temp (num) TO STDOUT") + if err != errCopyToNotSupported { + t.Fatalf("expected %s, got %+v", errCopyToNotSupported, err) + } + // check that the protocol is in a valid state + err = txn.Rollback() + if err != nil { + t.Fatal(err) + } +} + +func TestCopySyntaxError(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Prepare("COPY ") + if err == nil { + t.Fatal("expected error") + } + if pge := err.(*Error); pge.Code.Name() != "syntax_error" { + t.Fatalf("expected syntax error, got %s (%+v)", pge.Code.Name(), pge) + } + // check that the protocol is in a valid state + err = txn.Rollback() + if err != nil { + t.Fatal(err) + } +} + +// Tests for connection errors in copyin.resploop() +func TestCopyRespLoopConnectionError(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + var pid int + err = txn.QueryRow("SELECT pg_backend_pid()").Scan(&pid) + if err != nil { + t.Fatal(err) + } + + _, err = txn.Exec("CREATE TEMP TABLE temp (a int)") + if err != nil { + t.Fatal(err) + } + + stmt, err := txn.Prepare(CopyIn("temp", "a")) + if err != nil { + t.Fatal(err) + } + defer stmt.Close() + + _, err = db.Exec("SELECT pg_terminate_backend($1)", pid) + if err != nil { + t.Fatal(err) + } + + if getServerVersion(t, db) < 90500 { + // We have to try and send something over, since postgres before + // version 9.5 won't process SIGTERMs while it's waiting for + // CopyData/CopyEnd messages; see tcop/postgres.c. + _, err = stmt.Exec(1) + if err != nil { + t.Fatal(err) + } + } + _, err = stmt.Exec() + if err == nil { + t.Fatalf("expected error") + } + pge, ok := err.(*Error) + if !ok { + if err == driver.ErrBadConn { + // likely an EPIPE + } else { + t.Fatalf("expected *pq.Error or driver.ErrBadConn, got %+#v", err) + } + } else if pge.Code.Name() != "admin_shutdown" { + t.Fatalf("expected admin_shutdown, got %s", pge.Code.Name()) + } + + _ = stmt.Close() +} + +func BenchmarkCopyIn(b *testing.B) { + db := openTestConn(b) + defer db.Close() + + txn, err := db.Begin() + if err != nil { + b.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)") + if err != nil { + b.Fatal(err) + } + + stmt, err := txn.Prepare(CopyIn("temp", "a", "b")) + if err != nil { + b.Fatal(err) + } + + for i := 0; i < b.N; i++ { + _, err = stmt.Exec(int64(i), "hello world!") + if err != nil { + b.Fatal(err) + } + } + + _, err = stmt.Exec() + if err != nil { + b.Fatal(err) + } + + err = stmt.Close() + if err != nil { + b.Fatal(err) + } + + var num int + err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num) + if err != nil { + b.Fatal(err) + } + + if num != b.N { + b.Fatalf("expected %d items, not %d", b.N, num) + } +} diff --git a/vendor/src/github.com/lib/pq/doc.go b/vendor/src/github.com/lib/pq/doc.go new file mode 100644 index 00000000..6d252ece --- /dev/null +++ b/vendor/src/github.com/lib/pq/doc.go @@ -0,0 +1,235 @@ +/* +Package pq is a pure Go Postgres driver for the database/sql package. + +In most cases clients will use the database/sql package instead of +using this package directly. For example: + + import ( + "database/sql" + + _ "github.com/lib/pq" + ) + + func main() { + db, err := sql.Open("postgres", "user=pqgotest dbname=pqgotest sslmode=verify-full") + if err != nil { + log.Fatal(err) + } + + age := 21 + rows, err := db.Query("SELECT name FROM users WHERE age = $1", age) + … + } + +You can also connect to a database using a URL. For example: + + db, err := sql.Open("postgres", "postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full") + + +Connection String Parameters + + +Similarly to libpq, when establishing a connection using pq you are expected to +supply a connection string containing zero or more parameters. +A subset of the connection parameters supported by libpq are also supported by pq. +Additionally, pq also lets you specify run-time parameters (such as search_path or work_mem) +directly in the connection string. This is different from libpq, which does not allow +run-time parameters in the connection string, instead requiring you to supply +them in the options parameter. + +For compatibility with libpq, the following special connection parameters are +supported: + + * dbname - The name of the database to connect to + * user - The user to sign in as + * password - The user's password + * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) + * port - The port to bind to. (default is 5432) + * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) + * fallback_application_name - An application_name to fall back to if one isn't provided. + * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. + * sslcert - Cert file location. The file must contain PEM encoded data. + * sslkey - Key file location. The file must contain PEM encoded data. + * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. + +Valid values for sslmode are: + + * disable - No SSL + * require - Always SSL (skip verification) + * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) + * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) + +See http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING +for more information about connection string parameters. + +Use single quotes for values that contain whitespace: + + "user=pqgotest password='with spaces'" + +A backslash will escape the next character in values: + + "user=space\ man password='it\'s valid' + +Note that the connection parameter client_encoding (which sets the +text encoding for the connection) may be set but must be "UTF8", +matching with the same rules as Postgres. It is an error to provide +any other value. + +In addition to the parameters listed above, any run-time parameter that can be +set at backend start time can be set in the connection string. For more +information, see +http://www.postgresql.org/docs/current/static/runtime-config.html. + +Most environment variables as specified at http://www.postgresql.org/docs/current/static/libpq-envars.html +supported by libpq are also supported by pq. If any of the environment +variables not supported by pq are set, pq will panic during connection +establishment. Environment variables have a lower precedence than explicitly +provided connection parameters. + +The pgpass mechanism as described in http://www.postgresql.org/docs/current/static/libpq-pgpass.html +is supported, but on Windows PGPASSFILE must be specified explicitly. + + +Queries + + +database/sql does not dictate any specific format for parameter +markers in query strings, and pq uses the Postgres-native ordinal markers, +as shown above. The same marker can be reused for the same parameter: + + rows, err := db.Query(`SELECT name FROM users WHERE favorite_fruit = $1 + OR age BETWEEN $2 AND $2 + 3`, "orange", 64) + +pq does not support the LastInsertId() method of the Result type in database/sql. +To return the identifier of an INSERT (or UPDATE or DELETE), use the Postgres +RETURNING clause with a standard Query or QueryRow call: + + var userid int + err := db.QueryRow(`INSERT INTO users(name, favorite_fruit, age) + VALUES('beatrice', 'starfruit', 93) RETURNING id`).Scan(&userid) + +For more details on RETURNING, see the Postgres documentation: + + http://www.postgresql.org/docs/current/static/sql-insert.html + http://www.postgresql.org/docs/current/static/sql-update.html + http://www.postgresql.org/docs/current/static/sql-delete.html + +For additional instructions on querying see the documentation for the database/sql package. + + +Data Types + + +Parameters pass through driver.DefaultParameterConverter before they are handled +by this package. When the binary_parameters connection option is enabled, +[]byte values are sent directly to the backend as data in binary format. + +This package returns the following types for values from the PostgreSQL backend: + + - integer types smallint, integer, and bigint are returned as int64 + - floating-point types real and double precision are returned as float64 + - character types char, varchar, and text are returned as string + - temporal types date, time, timetz, timestamp, and timestamptz are returned as time.Time + - the boolean type is returned as bool + - the bytea type is returned as []byte + +All other types are returned directly from the backend as []byte values in text format. + + +Errors + + +pq may return errors of type *pq.Error which can be interrogated for error details: + + if err, ok := err.(*pq.Error); ok { + fmt.Println("pq error:", err.Code.Name()) + } + +See the pq.Error type for details. + + +Bulk imports + +You can perform bulk imports by preparing a statement returned by pq.CopyIn (or +pq.CopyInSchema) in an explicit transaction (sql.Tx). The returned statement +handle can then be repeatedly "executed" to copy data into the target table. +After all data has been processed you should call Exec() once with no arguments +to flush all buffered data. Any call to Exec() might return an error which +should be handled appropriately, but because of the internal buffering an error +returned by Exec() might not be related to the data passed in the call that +failed. + +CopyIn uses COPY FROM internally. It is not possible to COPY outside of an +explicit transaction in pq. + +Usage example: + + txn, err := db.Begin() + if err != nil { + log.Fatal(err) + } + + stmt, err := txn.Prepare(pq.CopyIn("users", "name", "age")) + if err != nil { + log.Fatal(err) + } + + for _, user := range users { + _, err = stmt.Exec(user.Name, int64(user.Age)) + if err != nil { + log.Fatal(err) + } + } + + _, err = stmt.Exec() + if err != nil { + log.Fatal(err) + } + + err = stmt.Close() + if err != nil { + log.Fatal(err) + } + + err = txn.Commit() + if err != nil { + log.Fatal(err) + } + + +Notifications + + +PostgreSQL supports a simple publish/subscribe model over database +connections. See http://www.postgresql.org/docs/current/static/sql-notify.html +for more information about the general mechanism. + +To start listening for notifications, you first have to open a new connection +to the database by calling NewListener. This connection can not be used for +anything other than LISTEN / NOTIFY. Calling Listen will open a "notification +channel"; once a notification channel is open, a notification generated on that +channel will effect a send on the Listener.Notify channel. A notification +channel will remain open until Unlisten is called, though connection loss might +result in some notifications being lost. To solve this problem, Listener sends +a nil pointer over the Notify channel any time the connection is re-established +following a connection loss. The application can get information about the +state of the underlying connection by setting an event callback in the call to +NewListener. + +A single Listener can safely be used from concurrent goroutines, which means +that there is often no need to create more than one Listener in your +application. However, a Listener is always connected to a single database, so +you will need to create a new Listener instance for every database you want to +receive notifications in. + +The channel name in both Listen and Unlisten is case sensitive, and can contain +any characters legal in an identifier (see +http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS +for more information). Note that the channel name will be truncated to 63 +bytes by the PostgreSQL server. + +You can find a complete, working example of Listener usage at +http://godoc.org/github.com/lib/pq/listen_example. + +*/ +package pq diff --git a/vendor/src/github.com/lib/pq/encode.go b/vendor/src/github.com/lib/pq/encode.go new file mode 100644 index 00000000..88a322cd --- /dev/null +++ b/vendor/src/github.com/lib/pq/encode.go @@ -0,0 +1,595 @@ +package pq + +import ( + "bytes" + "database/sql/driver" + "encoding/binary" + "encoding/hex" + "errors" + "fmt" + "math" + "strconv" + "strings" + "sync" + "time" + + "github.com/lib/pq/oid" +) + +func binaryEncode(parameterStatus *parameterStatus, x interface{}) []byte { + switch v := x.(type) { + case []byte: + return v + default: + return encode(parameterStatus, x, oid.T_unknown) + } +} + +func encode(parameterStatus *parameterStatus, x interface{}, pgtypOid oid.Oid) []byte { + switch v := x.(type) { + case int64: + return strconv.AppendInt(nil, v, 10) + case float64: + return strconv.AppendFloat(nil, v, 'f', -1, 64) + case []byte: + if pgtypOid == oid.T_bytea { + return encodeBytea(parameterStatus.serverVersion, v) + } + + return v + case string: + if pgtypOid == oid.T_bytea { + return encodeBytea(parameterStatus.serverVersion, []byte(v)) + } + + return []byte(v) + case bool: + return strconv.AppendBool(nil, v) + case time.Time: + return formatTs(v) + + default: + errorf("encode: unknown type for %T", v) + } + + panic("not reached") +} + +func decode(parameterStatus *parameterStatus, s []byte, typ oid.Oid, f format) interface{} { + switch f { + case formatBinary: + return binaryDecode(parameterStatus, s, typ) + case formatText: + return textDecode(parameterStatus, s, typ) + default: + panic("not reached") + } +} + +func binaryDecode(parameterStatus *parameterStatus, s []byte, typ oid.Oid) interface{} { + switch typ { + case oid.T_bytea: + return s + case oid.T_int8: + return int64(binary.BigEndian.Uint64(s)) + case oid.T_int4: + return int64(int32(binary.BigEndian.Uint32(s))) + case oid.T_int2: + return int64(int16(binary.BigEndian.Uint16(s))) + case oid.T_uuid: + b, err := decodeUUIDBinary(s) + if err != nil { + panic(err) + } + return b + + default: + errorf("don't know how to decode binary parameter of type %d", uint32(typ)) + } + + panic("not reached") +} + +func textDecode(parameterStatus *parameterStatus, s []byte, typ oid.Oid) interface{} { + switch typ { + case oid.T_char, oid.T_varchar, oid.T_text: + return string(s) + case oid.T_bytea: + b, err := parseBytea(s) + if err != nil { + errorf("%s", err) + } + return b + case oid.T_timestamptz: + return parseTs(parameterStatus.currentLocation, string(s)) + case oid.T_timestamp, oid.T_date: + return parseTs(nil, string(s)) + case oid.T_time: + return mustParse("15:04:05", typ, s) + case oid.T_timetz: + return mustParse("15:04:05-07", typ, s) + case oid.T_bool: + return s[0] == 't' + case oid.T_int8, oid.T_int4, oid.T_int2: + i, err := strconv.ParseInt(string(s), 10, 64) + if err != nil { + errorf("%s", err) + } + return i + case oid.T_float4, oid.T_float8: + bits := 64 + if typ == oid.T_float4 { + bits = 32 + } + f, err := strconv.ParseFloat(string(s), bits) + if err != nil { + errorf("%s", err) + } + return f + } + + return s +} + +// appendEncodedText encodes item in text format as required by COPY +// and appends to buf +func appendEncodedText(parameterStatus *parameterStatus, buf []byte, x interface{}) []byte { + switch v := x.(type) { + case int64: + return strconv.AppendInt(buf, v, 10) + case float64: + return strconv.AppendFloat(buf, v, 'f', -1, 64) + case []byte: + encodedBytea := encodeBytea(parameterStatus.serverVersion, v) + return appendEscapedText(buf, string(encodedBytea)) + case string: + return appendEscapedText(buf, v) + case bool: + return strconv.AppendBool(buf, v) + case time.Time: + return append(buf, formatTs(v)...) + case nil: + return append(buf, "\\N"...) + default: + errorf("encode: unknown type for %T", v) + } + + panic("not reached") +} + +func appendEscapedText(buf []byte, text string) []byte { + escapeNeeded := false + startPos := 0 + var c byte + + // check if we need to escape + for i := 0; i < len(text); i++ { + c = text[i] + if c == '\\' || c == '\n' || c == '\r' || c == '\t' { + escapeNeeded = true + startPos = i + break + } + } + if !escapeNeeded { + return append(buf, text...) + } + + // copy till first char to escape, iterate the rest + result := append(buf, text[:startPos]...) + for i := startPos; i < len(text); i++ { + c = text[i] + switch c { + case '\\': + result = append(result, '\\', '\\') + case '\n': + result = append(result, '\\', 'n') + case '\r': + result = append(result, '\\', 'r') + case '\t': + result = append(result, '\\', 't') + default: + result = append(result, c) + } + } + return result +} + +func mustParse(f string, typ oid.Oid, s []byte) time.Time { + str := string(s) + + // check for a 30-minute-offset timezone + if (typ == oid.T_timestamptz || typ == oid.T_timetz) && + str[len(str)-3] == ':' { + f += ":00" + } + t, err := time.Parse(f, str) + if err != nil { + errorf("decode: %s", err) + } + return t +} + +var errInvalidTimestamp = errors.New("invalid timestamp") + +type timestampParser struct { + err error +} + +func (p *timestampParser) expect(str string, char byte, pos int) { + if p.err != nil { + return + } + if pos+1 > len(str) { + p.err = errInvalidTimestamp + return + } + if c := str[pos]; c != char && p.err == nil { + p.err = fmt.Errorf("expected '%v' at position %v; got '%v'", char, pos, c) + } +} + +func (p *timestampParser) mustAtoi(str string, begin int, end int) int { + if p.err != nil { + return 0 + } + if begin < 0 || end < 0 || begin > end || end > len(str) { + p.err = errInvalidTimestamp + return 0 + } + result, err := strconv.Atoi(str[begin:end]) + if err != nil { + if p.err == nil { + p.err = fmt.Errorf("expected number; got '%v'", str) + } + return 0 + } + return result +} + +// The location cache caches the time zones typically used by the client. +type locationCache struct { + cache map[int]*time.Location + lock sync.Mutex +} + +// All connections share the same list of timezones. Benchmarking shows that +// about 5% speed could be gained by putting the cache in the connection and +// losing the mutex, at the cost of a small amount of memory and a somewhat +// significant increase in code complexity. +var globalLocationCache = newLocationCache() + +func newLocationCache() *locationCache { + return &locationCache{cache: make(map[int]*time.Location)} +} + +// Returns the cached timezone for the specified offset, creating and caching +// it if necessary. +func (c *locationCache) getLocation(offset int) *time.Location { + c.lock.Lock() + defer c.lock.Unlock() + + location, ok := c.cache[offset] + if !ok { + location = time.FixedZone("", offset) + c.cache[offset] = location + } + + return location +} + +var infinityTsEnabled = false +var infinityTsNegative time.Time +var infinityTsPositive time.Time + +const ( + infinityTsEnabledAlready = "pq: infinity timestamp enabled already" + infinityTsNegativeMustBeSmaller = "pq: infinity timestamp: negative value must be smaller (before) than positive" +) + +// EnableInfinityTs controls the handling of Postgres' "-infinity" and +// "infinity" "timestamp"s. +// +// If EnableInfinityTs is not called, "-infinity" and "infinity" will return +// []byte("-infinity") and []byte("infinity") respectively, and potentially +// cause error "sql: Scan error on column index 0: unsupported driver -> Scan +// pair: []uint8 -> *time.Time", when scanning into a time.Time value. +// +// Once EnableInfinityTs has been called, all connections created using this +// driver will decode Postgres' "-infinity" and "infinity" for "timestamp", +// "timestamp with time zone" and "date" types to the predefined minimum and +// maximum times, respectively. When encoding time.Time values, any time which +// equals or precedes the predefined minimum time will be encoded to +// "-infinity". Any values at or past the maximum time will similarly be +// encoded to "infinity". +// +// If EnableInfinityTs is called with negative >= positive, it will panic. +// Calling EnableInfinityTs after a connection has been established results in +// undefined behavior. If EnableInfinityTs is called more than once, it will +// panic. +func EnableInfinityTs(negative time.Time, positive time.Time) { + if infinityTsEnabled { + panic(infinityTsEnabledAlready) + } + if !negative.Before(positive) { + panic(infinityTsNegativeMustBeSmaller) + } + infinityTsEnabled = true + infinityTsNegative = negative + infinityTsPositive = positive +} + +/* + * Testing might want to toggle infinityTsEnabled + */ +func disableInfinityTs() { + infinityTsEnabled = false +} + +// This is a time function specific to the Postgres default DateStyle +// setting ("ISO, MDY"), the only one we currently support. This +// accounts for the discrepancies between the parsing available with +// time.Parse and the Postgres date formatting quirks. +func parseTs(currentLocation *time.Location, str string) interface{} { + switch str { + case "-infinity": + if infinityTsEnabled { + return infinityTsNegative + } + return []byte(str) + case "infinity": + if infinityTsEnabled { + return infinityTsPositive + } + return []byte(str) + } + t, err := ParseTimestamp(currentLocation, str) + if err != nil { + panic(err) + } + return t +} + +// ParseTimestamp parses Postgres' text format. It returns a time.Time in +// currentLocation iff that time's offset agrees with the offset sent from the +// Postgres server. Otherwise, ParseTimestamp returns a time.Time with the +// fixed offset offset provided by the Postgres server. +func ParseTimestamp(currentLocation *time.Location, str string) (time.Time, error) { + p := timestampParser{} + + monSep := strings.IndexRune(str, '-') + // this is Gregorian year, not ISO Year + // In Gregorian system, the year 1 BC is followed by AD 1 + year := p.mustAtoi(str, 0, monSep) + daySep := monSep + 3 + month := p.mustAtoi(str, monSep+1, daySep) + p.expect(str, '-', daySep) + timeSep := daySep + 3 + day := p.mustAtoi(str, daySep+1, timeSep) + + var hour, minute, second int + if len(str) > monSep+len("01-01")+1 { + p.expect(str, ' ', timeSep) + minSep := timeSep + 3 + p.expect(str, ':', minSep) + hour = p.mustAtoi(str, timeSep+1, minSep) + secSep := minSep + 3 + p.expect(str, ':', secSep) + minute = p.mustAtoi(str, minSep+1, secSep) + secEnd := secSep + 3 + second = p.mustAtoi(str, secSep+1, secEnd) + } + remainderIdx := monSep + len("01-01 00:00:00") + 1 + // Three optional (but ordered) sections follow: the + // fractional seconds, the time zone offset, and the BC + // designation. We set them up here and adjust the other + // offsets if the preceding sections exist. + + nanoSec := 0 + tzOff := 0 + + if remainderIdx < len(str) && str[remainderIdx] == '.' { + fracStart := remainderIdx + 1 + fracOff := strings.IndexAny(str[fracStart:], "-+ ") + if fracOff < 0 { + fracOff = len(str) - fracStart + } + fracSec := p.mustAtoi(str, fracStart, fracStart+fracOff) + nanoSec = fracSec * (1000000000 / int(math.Pow(10, float64(fracOff)))) + + remainderIdx += fracOff + 1 + } + if tzStart := remainderIdx; tzStart < len(str) && (str[tzStart] == '-' || str[tzStart] == '+') { + // time zone separator is always '-' or '+' (UTC is +00) + var tzSign int + switch c := str[tzStart]; c { + case '-': + tzSign = -1 + case '+': + tzSign = +1 + default: + return time.Time{}, fmt.Errorf("expected '-' or '+' at position %v; got %v", tzStart, c) + } + tzHours := p.mustAtoi(str, tzStart+1, tzStart+3) + remainderIdx += 3 + var tzMin, tzSec int + if remainderIdx < len(str) && str[remainderIdx] == ':' { + tzMin = p.mustAtoi(str, remainderIdx+1, remainderIdx+3) + remainderIdx += 3 + } + if remainderIdx < len(str) && str[remainderIdx] == ':' { + tzSec = p.mustAtoi(str, remainderIdx+1, remainderIdx+3) + remainderIdx += 3 + } + tzOff = tzSign * ((tzHours * 60 * 60) + (tzMin * 60) + tzSec) + } + var isoYear int + if remainderIdx+3 <= len(str) && str[remainderIdx:remainderIdx+3] == " BC" { + isoYear = 1 - year + remainderIdx += 3 + } else { + isoYear = year + } + if remainderIdx < len(str) { + return time.Time{}, fmt.Errorf("expected end of input, got %v", str[remainderIdx:]) + } + t := time.Date(isoYear, time.Month(month), day, + hour, minute, second, nanoSec, + globalLocationCache.getLocation(tzOff)) + + if currentLocation != nil { + // Set the location of the returned Time based on the session's + // TimeZone value, but only if the local time zone database agrees with + // the remote database on the offset. + lt := t.In(currentLocation) + _, newOff := lt.Zone() + if newOff == tzOff { + t = lt + } + } + + return t, p.err +} + +// formatTs formats t into a format postgres understands. +func formatTs(t time.Time) []byte { + if infinityTsEnabled { + // t <= -infinity : ! (t > -infinity) + if !t.After(infinityTsNegative) { + return []byte("-infinity") + } + // t >= infinity : ! (!t < infinity) + if !t.Before(infinityTsPositive) { + return []byte("infinity") + } + } + return FormatTimestamp(t) +} + +// FormatTimestamp formats t into Postgres' text format for timestamps. +func FormatTimestamp(t time.Time) []byte { + // Need to send dates before 0001 A.D. with " BC" suffix, instead of the + // minus sign preferred by Go. + // Beware, "0000" in ISO is "1 BC", "-0001" is "2 BC" and so on + bc := false + if t.Year() <= 0 { + // flip year sign, and add 1, e.g: "0" will be "1", and "-10" will be "11" + t = t.AddDate((-t.Year())*2+1, 0, 0) + bc = true + } + b := []byte(t.Format("2006-01-02 15:04:05.999999999Z07:00")) + + _, offset := t.Zone() + offset = offset % 60 + if offset != 0 { + // RFC3339Nano already printed the minus sign + if offset < 0 { + offset = -offset + } + + b = append(b, ':') + if offset < 10 { + b = append(b, '0') + } + b = strconv.AppendInt(b, int64(offset), 10) + } + + if bc { + b = append(b, " BC"...) + } + return b +} + +// Parse a bytea value received from the server. Both "hex" and the legacy +// "escape" format are supported. +func parseBytea(s []byte) (result []byte, err error) { + if len(s) >= 2 && bytes.Equal(s[:2], []byte("\\x")) { + // bytea_output = hex + s = s[2:] // trim off leading "\\x" + result = make([]byte, hex.DecodedLen(len(s))) + _, err := hex.Decode(result, s) + if err != nil { + return nil, err + } + } else { + // bytea_output = escape + for len(s) > 0 { + if s[0] == '\\' { + // escaped '\\' + if len(s) >= 2 && s[1] == '\\' { + result = append(result, '\\') + s = s[2:] + continue + } + + // '\\' followed by an octal number + if len(s) < 4 { + return nil, fmt.Errorf("invalid bytea sequence %v", s) + } + r, err := strconv.ParseInt(string(s[1:4]), 8, 9) + if err != nil { + return nil, fmt.Errorf("could not parse bytea value: %s", err.Error()) + } + result = append(result, byte(r)) + s = s[4:] + } else { + // We hit an unescaped, raw byte. Try to read in as many as + // possible in one go. + i := bytes.IndexByte(s, '\\') + if i == -1 { + result = append(result, s...) + break + } + result = append(result, s[:i]...) + s = s[i:] + } + } + } + + return result, nil +} + +func encodeBytea(serverVersion int, v []byte) (result []byte) { + if serverVersion >= 90000 { + // Use the hex format if we know that the server supports it + result = make([]byte, 2+hex.EncodedLen(len(v))) + result[0] = '\\' + result[1] = 'x' + hex.Encode(result[2:], v) + } else { + // .. or resort to "escape" + for _, b := range v { + if b == '\\' { + result = append(result, '\\', '\\') + } else if b < 0x20 || b > 0x7e { + result = append(result, []byte(fmt.Sprintf("\\%03o", b))...) + } else { + result = append(result, b) + } + } + } + + return result +} + +// NullTime represents a time.Time that may be null. NullTime implements the +// sql.Scanner interface so it can be used as a scan destination, similar to +// sql.NullString. +type NullTime struct { + Time time.Time + Valid bool // Valid is true if Time is not NULL +} + +// Scan implements the Scanner interface. +func (nt *NullTime) Scan(value interface{}) error { + nt.Time, nt.Valid = value.(time.Time) + return nil +} + +// Value implements the driver Valuer interface. +func (nt NullTime) Value() (driver.Value, error) { + if !nt.Valid { + return nil, nil + } + return nt.Time, nil +} diff --git a/vendor/src/github.com/lib/pq/encode_test.go b/vendor/src/github.com/lib/pq/encode_test.go new file mode 100644 index 00000000..b1531ec2 --- /dev/null +++ b/vendor/src/github.com/lib/pq/encode_test.go @@ -0,0 +1,758 @@ +package pq + +import ( + "bytes" + "database/sql" + "fmt" + "strings" + "testing" + "time" + + "github.com/lib/pq/oid" +) + +func TestScanTimestamp(t *testing.T) { + var nt NullTime + tn := time.Now() + nt.Scan(tn) + if !nt.Valid { + t.Errorf("Expected Valid=false") + } + if nt.Time != tn { + t.Errorf("Time value mismatch") + } +} + +func TestScanNilTimestamp(t *testing.T) { + var nt NullTime + nt.Scan(nil) + if nt.Valid { + t.Errorf("Expected Valid=false") + } +} + +var timeTests = []struct { + str string + timeval time.Time +}{ + {"22001-02-03", time.Date(22001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))}, + {"2001-02-03", time.Date(2001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06", time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.000001", time.Date(2001, time.February, 3, 4, 5, 6, 1000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.00001", time.Date(2001, time.February, 3, 4, 5, 6, 10000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.0001", time.Date(2001, time.February, 3, 4, 5, 6, 100000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.001", time.Date(2001, time.February, 3, 4, 5, 6, 1000000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.01", time.Date(2001, time.February, 3, 4, 5, 6, 10000000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.1", time.Date(2001, time.February, 3, 4, 5, 6, 100000000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.12", time.Date(2001, time.February, 3, 4, 5, 6, 120000000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.123", time.Date(2001, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.1234", time.Date(2001, time.February, 3, 4, 5, 6, 123400000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.12345", time.Date(2001, time.February, 3, 4, 5, 6, 123450000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.123456", time.Date(2001, time.February, 3, 4, 5, 6, 123456000, time.FixedZone("", 0))}, + {"2001-02-03 04:05:06.123-07", time.Date(2001, time.February, 3, 4, 5, 6, 123000000, + time.FixedZone("", -7*60*60))}, + {"2001-02-03 04:05:06-07", time.Date(2001, time.February, 3, 4, 5, 6, 0, + time.FixedZone("", -7*60*60))}, + {"2001-02-03 04:05:06-07:42", time.Date(2001, time.February, 3, 4, 5, 6, 0, + time.FixedZone("", -(7*60*60+42*60)))}, + {"2001-02-03 04:05:06-07:30:09", time.Date(2001, time.February, 3, 4, 5, 6, 0, + time.FixedZone("", -(7*60*60+30*60+9)))}, + {"2001-02-03 04:05:06+07", time.Date(2001, time.February, 3, 4, 5, 6, 0, + time.FixedZone("", 7*60*60))}, + {"0011-02-03 04:05:06 BC", time.Date(-10, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))}, + {"0011-02-03 04:05:06.123 BC", time.Date(-10, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))}, + {"0011-02-03 04:05:06.123-07 BC", time.Date(-10, time.February, 3, 4, 5, 6, 123000000, + time.FixedZone("", -7*60*60))}, + {"0001-02-03 04:05:06.123", time.Date(1, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))}, + {"0001-02-03 04:05:06.123 BC", time.Date(1, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0)).AddDate(-1, 0, 0)}, + {"0001-02-03 04:05:06.123 BC", time.Date(0, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))}, + {"0002-02-03 04:05:06.123 BC", time.Date(0, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0)).AddDate(-1, 0, 0)}, + {"0002-02-03 04:05:06.123 BC", time.Date(-1, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))}, + {"12345-02-03 04:05:06.1", time.Date(12345, time.February, 3, 4, 5, 6, 100000000, time.FixedZone("", 0))}, + {"123456-02-03 04:05:06.1", time.Date(123456, time.February, 3, 4, 5, 6, 100000000, time.FixedZone("", 0))}, +} + +// Test that parsing the string results in the expected value. +func TestParseTs(t *testing.T) { + for i, tt := range timeTests { + val, err := ParseTimestamp(nil, tt.str) + if err != nil { + t.Errorf("%d: got error: %v", i, err) + } else if val.String() != tt.timeval.String() { + t.Errorf("%d: expected to parse %q into %q; got %q", + i, tt.str, tt.timeval, val) + } + } +} + +var timeErrorTests = []string{ + "2001", + "2001-2-03", + "2001-02-3", + "2001-02-03 ", + "2001-02-03 04", + "2001-02-03 04:", + "2001-02-03 04:05", + "2001-02-03 04:05:", + "2001-02-03 04:05:6", + "2001-02-03 04:05:06.123 B", +} + +// Test that parsing the string results in an error. +func TestParseTsErrors(t *testing.T) { + for i, tt := range timeErrorTests { + _, err := ParseTimestamp(nil, tt) + if err == nil { + t.Errorf("%d: expected an error from parsing: %v", i, tt) + } + } +} + +// Now test that sending the value into the database and parsing it back +// returns the same time.Time value. +func TestEncodeAndParseTs(t *testing.T) { + db, err := openTestConnConninfo("timezone='Etc/UTC'") + if err != nil { + t.Fatal(err) + } + defer db.Close() + + for i, tt := range timeTests { + var dbstr string + err = db.QueryRow("SELECT ($1::timestamptz)::text", tt.timeval).Scan(&dbstr) + if err != nil { + t.Errorf("%d: could not send value %q to the database: %s", i, tt.timeval, err) + continue + } + + val, err := ParseTimestamp(nil, dbstr) + if err != nil { + t.Errorf("%d: could not parse value %q: %s", i, dbstr, err) + continue + } + val = val.In(tt.timeval.Location()) + if val.String() != tt.timeval.String() { + t.Errorf("%d: expected to parse %q into %q; got %q", i, dbstr, tt.timeval, val) + } + } +} + +var formatTimeTests = []struct { + time time.Time + expected string +}{ + {time.Time{}, "0001-01-01 00:00:00Z"}, + {time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "2001-02-03 04:05:06.123456789Z"}, + {time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "2001-02-03 04:05:06.123456789+02:00"}, + {time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "2001-02-03 04:05:06.123456789-06:00"}, + {time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "2001-02-03 04:05:06-07:30:09"}, + + {time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "0001-02-03 04:05:06.123456789Z"}, + {time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "0001-02-03 04:05:06.123456789+02:00"}, + {time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "0001-02-03 04:05:06.123456789-06:00"}, + + {time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "0001-02-03 04:05:06.123456789Z BC"}, + {time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "0001-02-03 04:05:06.123456789+02:00 BC"}, + {time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "0001-02-03 04:05:06.123456789-06:00 BC"}, + + {time.Date(1, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "0001-02-03 04:05:06-07:30:09"}, + {time.Date(0, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "0001-02-03 04:05:06-07:30:09 BC"}, +} + +func TestFormatTs(t *testing.T) { + for i, tt := range formatTimeTests { + val := string(formatTs(tt.time)) + if val != tt.expected { + t.Errorf("%d: incorrect time format %q, want %q", i, val, tt.expected) + } + } +} + +func TestFormatTsBackend(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + var str string + err := db.QueryRow("SELECT '2001-02-03T04:05:06.007-08:09:10'::time::text").Scan(&str) + if err == nil { + t.Fatalf("PostgreSQL is accepting an ISO timestamp input for time") + } + + for i, tt := range formatTimeTests { + for _, typ := range []string{"date", "time", "timetz", "timestamp", "timestamptz"} { + err = db.QueryRow("SELECT $1::"+typ+"::text", tt.time).Scan(&str) + if err != nil { + t.Errorf("%d: incorrect time format for %v on the backend: %v", i, typ, err) + } + } + } +} + +func TestTimestampWithTimeZone(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + tx, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer tx.Rollback() + + // try several different locations, all included in Go's zoneinfo.zip + for _, locName := range []string{ + "UTC", + "America/Chicago", + "America/New_York", + "Australia/Darwin", + "Australia/Perth", + } { + loc, err := time.LoadLocation(locName) + if err != nil { + t.Logf("Could not load time zone %s - skipping", locName) + continue + } + + // Postgres timestamps have a resolution of 1 microsecond, so don't + // use the full range of the Nanosecond argument + refTime := time.Date(2012, 11, 6, 10, 23, 42, 123456000, loc) + + for _, pgTimeZone := range []string{"US/Eastern", "Australia/Darwin"} { + // Switch Postgres's timezone to test different output timestamp formats + _, err = tx.Exec(fmt.Sprintf("set time zone '%s'", pgTimeZone)) + if err != nil { + t.Fatal(err) + } + + var gotTime time.Time + row := tx.QueryRow("select $1::timestamp with time zone", refTime) + err = row.Scan(&gotTime) + if err != nil { + t.Fatal(err) + } + + if !refTime.Equal(gotTime) { + t.Errorf("timestamps not equal: %s != %s", refTime, gotTime) + } + + // check that the time zone is set correctly based on TimeZone + pgLoc, err := time.LoadLocation(pgTimeZone) + if err != nil { + t.Logf("Could not load time zone %s - skipping", pgLoc) + continue + } + translated := refTime.In(pgLoc) + if translated.String() != gotTime.String() { + t.Errorf("timestamps not equal: %s != %s", translated, gotTime) + } + } + } +} + +func TestTimestampWithOutTimezone(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + test := func(ts, pgts string) { + r, err := db.Query("SELECT $1::timestamp", pgts) + if err != nil { + t.Fatalf("Could not run query: %v", err) + } + + n := r.Next() + + if n != true { + t.Fatal("Expected at least one row") + } + + var result time.Time + err = r.Scan(&result) + if err != nil { + t.Fatalf("Did not expect error scanning row: %v", err) + } + + expected, err := time.Parse(time.RFC3339, ts) + if err != nil { + t.Fatalf("Could not parse test time literal: %v", err) + } + + if !result.Equal(expected) { + t.Fatalf("Expected time to match %v: got mismatch %v", + expected, result) + } + + n = r.Next() + if n != false { + t.Fatal("Expected only one row") + } + } + + test("2000-01-01T00:00:00Z", "2000-01-01T00:00:00") + + // Test higher precision time + test("2013-01-04T20:14:58.80033Z", "2013-01-04 20:14:58.80033") +} + +func TestInfinityTimestamp(t *testing.T) { + db := openTestConn(t) + defer db.Close() + var err error + var resultT time.Time + + expectedErrorStrPrefix := `sql: Scan error on column index 0: unsupported` + type testCases []struct { + Query string + Param string + ExpectedErrStrPrefix string + ExpectedVal interface{} + } + tc := testCases{ + {"SELECT $1::timestamp", "-infinity", expectedErrorStrPrefix, "-infinity"}, + {"SELECT $1::timestamptz", "-infinity", expectedErrorStrPrefix, "-infinity"}, + {"SELECT $1::timestamp", "infinity", expectedErrorStrPrefix, "infinity"}, + {"SELECT $1::timestamptz", "infinity", expectedErrorStrPrefix, "infinity"}, + } + // try to assert []byte to time.Time + for _, q := range tc { + err = db.QueryRow(q.Query, q.Param).Scan(&resultT) + if !strings.HasPrefix(err.Error(), q.ExpectedErrStrPrefix) { + t.Errorf("Scanning -/+infinity, expected error to have prefix %q, got %q", q.ExpectedErrStrPrefix, err) + } + } + // yield []byte + for _, q := range tc { + var resultI interface{} + err = db.QueryRow(q.Query, q.Param).Scan(&resultI) + if err != nil { + t.Errorf("Scanning -/+infinity, expected no error, got %q", err) + } + result, ok := resultI.([]byte) + if !ok { + t.Errorf("Scanning -/+infinity, expected []byte, got %#v", resultI) + } + if string(result) != q.ExpectedVal { + t.Errorf("Scanning -/+infinity, expected %q, got %q", q.ExpectedVal, result) + } + } + + y1500 := time.Date(1500, time.January, 1, 0, 0, 0, 0, time.UTC) + y2500 := time.Date(2500, time.January, 1, 0, 0, 0, 0, time.UTC) + EnableInfinityTs(y1500, y2500) + + err = db.QueryRow("SELECT $1::timestamp", "infinity").Scan(&resultT) + if err != nil { + t.Errorf("Scanning infinity, expected no error, got %q", err) + } + if !resultT.Equal(y2500) { + t.Errorf("Scanning infinity, expected %q, got %q", y2500, resultT) + } + + err = db.QueryRow("SELECT $1::timestamptz", "infinity").Scan(&resultT) + if err != nil { + t.Errorf("Scanning infinity, expected no error, got %q", err) + } + if !resultT.Equal(y2500) { + t.Errorf("Scanning Infinity, expected time %q, got %q", y2500, resultT.String()) + } + + err = db.QueryRow("SELECT $1::timestamp", "-infinity").Scan(&resultT) + if err != nil { + t.Errorf("Scanning -infinity, expected no error, got %q", err) + } + if !resultT.Equal(y1500) { + t.Errorf("Scanning -infinity, expected time %q, got %q", y1500, resultT.String()) + } + + err = db.QueryRow("SELECT $1::timestamptz", "-infinity").Scan(&resultT) + if err != nil { + t.Errorf("Scanning -infinity, expected no error, got %q", err) + } + if !resultT.Equal(y1500) { + t.Errorf("Scanning -infinity, expected time %q, got %q", y1500, resultT.String()) + } + + y_1500 := time.Date(-1500, time.January, 1, 0, 0, 0, 0, time.UTC) + y11500 := time.Date(11500, time.January, 1, 0, 0, 0, 0, time.UTC) + var s string + err = db.QueryRow("SELECT $1::timestamp::text", y_1500).Scan(&s) + if err != nil { + t.Errorf("Encoding -infinity, expected no error, got %q", err) + } + if s != "-infinity" { + t.Errorf("Encoding -infinity, expected %q, got %q", "-infinity", s) + } + err = db.QueryRow("SELECT $1::timestamptz::text", y_1500).Scan(&s) + if err != nil { + t.Errorf("Encoding -infinity, expected no error, got %q", err) + } + if s != "-infinity" { + t.Errorf("Encoding -infinity, expected %q, got %q", "-infinity", s) + } + + err = db.QueryRow("SELECT $1::timestamp::text", y11500).Scan(&s) + if err != nil { + t.Errorf("Encoding infinity, expected no error, got %q", err) + } + if s != "infinity" { + t.Errorf("Encoding infinity, expected %q, got %q", "infinity", s) + } + err = db.QueryRow("SELECT $1::timestamptz::text", y11500).Scan(&s) + if err != nil { + t.Errorf("Encoding infinity, expected no error, got %q", err) + } + if s != "infinity" { + t.Errorf("Encoding infinity, expected %q, got %q", "infinity", s) + } + + disableInfinityTs() + + var panicErrorString string + func() { + defer func() { + panicErrorString, _ = recover().(string) + }() + EnableInfinityTs(y2500, y1500) + }() + if panicErrorString != infinityTsNegativeMustBeSmaller { + t.Errorf("Expected error, %q, got %q", infinityTsNegativeMustBeSmaller, panicErrorString) + } +} + +func TestStringWithNul(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + hello0world := string("hello\x00world") + _, err := db.Query("SELECT $1::text", &hello0world) + if err == nil { + t.Fatal("Postgres accepts a string with nul in it; " + + "injection attacks may be plausible") + } +} + +func TestByteSliceToText(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + b := []byte("hello world") + row := db.QueryRow("SELECT $1::text", b) + + var result []byte + err := row.Scan(&result) + if err != nil { + t.Fatal(err) + } + + if string(result) != string(b) { + t.Fatalf("expected %v but got %v", b, result) + } +} + +func TestStringToBytea(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + b := "hello world" + row := db.QueryRow("SELECT $1::bytea", b) + + var result []byte + err := row.Scan(&result) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(result, []byte(b)) { + t.Fatalf("expected %v but got %v", b, result) + } +} + +func TestTextByteSliceToUUID(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + b := []byte("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11") + row := db.QueryRow("SELECT $1::uuid", b) + + var result string + err := row.Scan(&result) + if forceBinaryParameters() { + pqErr := err.(*Error) + if pqErr == nil { + t.Errorf("Expected to get error") + } else if pqErr.Code != "22P03" { + t.Fatalf("Expected to get invalid binary encoding error (22P03), got %s", pqErr.Code) + } + } else { + if err != nil { + t.Fatal(err) + } + + if result != string(b) { + t.Fatalf("expected %v but got %v", b, result) + } + } +} + +func TestBinaryByteSlicetoUUID(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + b := []byte{'\xa0', '\xee', '\xbc', '\x99', + '\x9c', '\x0b', + '\x4e', '\xf8', + '\xbb', '\x00', '\x6b', + '\xb9', '\xbd', '\x38', '\x0a', '\x11'} + row := db.QueryRow("SELECT $1::uuid", b) + + var result string + err := row.Scan(&result) + if forceBinaryParameters() { + if err != nil { + t.Fatal(err) + } + + if result != string("a0eebc99-9c0b-4ef8-bb00-6bb9bd380a11") { + t.Fatalf("expected %v but got %v", b, result) + } + } else { + pqErr := err.(*Error) + if pqErr == nil { + t.Errorf("Expected to get error") + } else if pqErr.Code != "22021" { + t.Fatalf("Expected to get invalid byte sequence for encoding error (22021), got %s", pqErr.Code) + } + } +} + +func TestStringToUUID(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + s := "a0eebc99-9c0b-4ef8-bb00-6bb9bd380a11" + row := db.QueryRow("SELECT $1::uuid", s) + + var result string + err := row.Scan(&result) + if err != nil { + t.Fatal(err) + } + + if result != s { + t.Fatalf("expected %v but got %v", s, result) + } +} + +func TestTextByteSliceToInt(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + expected := 12345678 + b := []byte(fmt.Sprintf("%d", expected)) + row := db.QueryRow("SELECT $1::int", b) + + var result int + err := row.Scan(&result) + if forceBinaryParameters() { + pqErr := err.(*Error) + if pqErr == nil { + t.Errorf("Expected to get error") + } else if pqErr.Code != "22P03" { + t.Fatalf("Expected to get invalid binary encoding error (22P03), got %s", pqErr.Code) + } + } else { + if err != nil { + t.Fatal(err) + } + if result != expected { + t.Fatalf("expected %v but got %v", expected, result) + } + } +} + +func TestBinaryByteSliceToInt(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + expected := 12345678 + b := []byte{'\x00', '\xbc', '\x61', '\x4e'} + row := db.QueryRow("SELECT $1::int", b) + + var result int + err := row.Scan(&result) + if forceBinaryParameters() { + if err != nil { + t.Fatal(err) + } + if result != expected { + t.Fatalf("expected %v but got %v", expected, result) + } + } else { + pqErr := err.(*Error) + if pqErr == nil { + t.Errorf("Expected to get error") + } else if pqErr.Code != "22021" { + t.Fatalf("Expected to get invalid byte sequence for encoding error (22021), got %s", pqErr.Code) + } + } +} + +func TestTextDecodeIntoString(t *testing.T) { + input := []byte("hello world") + want := string(input) + for _, typ := range []oid.Oid{oid.T_char, oid.T_varchar, oid.T_text} { + got := decode(¶meterStatus{}, input, typ, formatText) + if got != want { + t.Errorf("invalid string decoding output for %T(%+v), got %v but expected %v", typ, typ, got, want) + } + } +} + +func TestByteaOutputFormatEncoding(t *testing.T) { + input := []byte("\\x\x00\x01\x02\xFF\xFEabcdefg0123") + want := []byte("\\x5c78000102fffe6162636465666730313233") + got := encode(¶meterStatus{serverVersion: 90000}, input, oid.T_bytea) + if !bytes.Equal(want, got) { + t.Errorf("invalid hex bytea output, got %v but expected %v", got, want) + } + + want = []byte("\\\\x\\000\\001\\002\\377\\376abcdefg0123") + got = encode(¶meterStatus{serverVersion: 84000}, input, oid.T_bytea) + if !bytes.Equal(want, got) { + t.Errorf("invalid escape bytea output, got %v but expected %v", got, want) + } +} + +func TestByteaOutputFormats(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + if getServerVersion(t, db) < 90000 { + // skip + return + } + + testByteaOutputFormat := func(f string, usePrepared bool) { + expectedData := []byte("\x5c\x78\x00\xff\x61\x62\x63\x01\x08") + sqlQuery := "SELECT decode('5c7800ff6162630108', 'hex')" + + var data []byte + + // use a txn to avoid relying on getting the same connection + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + defer txn.Rollback() + + _, err = txn.Exec("SET LOCAL bytea_output TO " + f) + if err != nil { + t.Fatal(err) + } + var rows *sql.Rows + var stmt *sql.Stmt + if usePrepared { + stmt, err = txn.Prepare(sqlQuery) + if err != nil { + t.Fatal(err) + } + rows, err = stmt.Query() + } else { + // use Query; QueryRow would hide the actual error + rows, err = txn.Query(sqlQuery) + } + if err != nil { + t.Fatal(err) + } + if !rows.Next() { + if rows.Err() != nil { + t.Fatal(rows.Err()) + } + t.Fatal("shouldn't happen") + } + err = rows.Scan(&data) + if err != nil { + t.Fatal(err) + } + err = rows.Close() + if err != nil { + t.Fatal(err) + } + if stmt != nil { + err = stmt.Close() + if err != nil { + t.Fatal(err) + } + } + if !bytes.Equal(data, expectedData) { + t.Errorf("unexpected bytea value %v for format %s; expected %v", data, f, expectedData) + } + } + + testByteaOutputFormat("hex", false) + testByteaOutputFormat("escape", false) + testByteaOutputFormat("hex", true) + testByteaOutputFormat("escape", true) +} + +func TestAppendEncodedText(t *testing.T) { + var buf []byte + + buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, int64(10)) + buf = append(buf, '\t') + buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, 42.0000000001) + buf = append(buf, '\t') + buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, "hello\tworld") + buf = append(buf, '\t') + buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, []byte{0, 128, 255}) + + if string(buf) != "10\t42.0000000001\thello\\tworld\t\\\\x0080ff" { + t.Fatal(string(buf)) + } +} + +func TestAppendEscapedText(t *testing.T) { + if esc := appendEscapedText(nil, "hallo\tescape"); string(esc) != "hallo\\tescape" { + t.Fatal(string(esc)) + } + if esc := appendEscapedText(nil, "hallo\\tescape\n"); string(esc) != "hallo\\\\tescape\\n" { + t.Fatal(string(esc)) + } + if esc := appendEscapedText(nil, "\n\r\t\f"); string(esc) != "\\n\\r\\t\f" { + t.Fatal(string(esc)) + } +} + +func TestAppendEscapedTextExistingBuffer(t *testing.T) { + var buf []byte + buf = []byte("123\t") + if esc := appendEscapedText(buf, "hallo\tescape"); string(esc) != "123\thallo\\tescape" { + t.Fatal(string(esc)) + } + buf = []byte("123\t") + if esc := appendEscapedText(buf, "hallo\\tescape\n"); string(esc) != "123\thallo\\\\tescape\\n" { + t.Fatal(string(esc)) + } + buf = []byte("123\t") + if esc := appendEscapedText(buf, "\n\r\t\f"); string(esc) != "123\t\\n\\r\\t\f" { + t.Fatal(string(esc)) + } +} + +func BenchmarkAppendEscapedText(b *testing.B) { + longString := "" + for i := 0; i < 100; i++ { + longString += "123456789\n" + } + for i := 0; i < b.N; i++ { + appendEscapedText(nil, longString) + } +} + +func BenchmarkAppendEscapedTextNoEscape(b *testing.B) { + longString := "" + for i := 0; i < 100; i++ { + longString += "1234567890" + } + for i := 0; i < b.N; i++ { + appendEscapedText(nil, longString) + } +} diff --git a/vendor/src/github.com/lib/pq/error.go b/vendor/src/github.com/lib/pq/error.go new file mode 100644 index 00000000..b4bb44ce --- /dev/null +++ b/vendor/src/github.com/lib/pq/error.go @@ -0,0 +1,508 @@ +package pq + +import ( + "database/sql/driver" + "fmt" + "io" + "net" + "runtime" +) + +// Error severities +const ( + Efatal = "FATAL" + Epanic = "PANIC" + Ewarning = "WARNING" + Enotice = "NOTICE" + Edebug = "DEBUG" + Einfo = "INFO" + Elog = "LOG" +) + +// Error represents an error communicating with the server. +// +// See http://www.postgresql.org/docs/current/static/protocol-error-fields.html for details of the fields +type Error struct { + Severity string + Code ErrorCode + Message string + Detail string + Hint string + Position string + InternalPosition string + InternalQuery string + Where string + Schema string + Table string + Column string + DataTypeName string + Constraint string + File string + Line string + Routine string +} + +// ErrorCode is a five-character error code. +type ErrorCode string + +// Name returns a more human friendly rendering of the error code, namely the +// "condition name". +// +// See http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html for +// details. +func (ec ErrorCode) Name() string { + return errorCodeNames[ec] +} + +// ErrorClass is only the class part of an error code. +type ErrorClass string + +// Name returns the condition name of an error class. It is equivalent to the +// condition name of the "standard" error code (i.e. the one having the last +// three characters "000"). +func (ec ErrorClass) Name() string { + return errorCodeNames[ErrorCode(ec+"000")] +} + +// Class returns the error class, e.g. "28". +// +// See http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html for +// details. +func (ec ErrorCode) Class() ErrorClass { + return ErrorClass(ec[0:2]) +} + +// errorCodeNames is a mapping between the five-character error codes and the +// human readable "condition names". It is derived from the list at +// http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html +var errorCodeNames = map[ErrorCode]string{ + // Class 00 - Successful Completion + "00000": "successful_completion", + // Class 01 - Warning + "01000": "warning", + "0100C": "dynamic_result_sets_returned", + "01008": "implicit_zero_bit_padding", + "01003": "null_value_eliminated_in_set_function", + "01007": "privilege_not_granted", + "01006": "privilege_not_revoked", + "01004": "string_data_right_truncation", + "01P01": "deprecated_feature", + // Class 02 - No Data (this is also a warning class per the SQL standard) + "02000": "no_data", + "02001": "no_additional_dynamic_result_sets_returned", + // Class 03 - SQL Statement Not Yet Complete + "03000": "sql_statement_not_yet_complete", + // Class 08 - Connection Exception + "08000": "connection_exception", + "08003": "connection_does_not_exist", + "08006": "connection_failure", + "08001": "sqlclient_unable_to_establish_sqlconnection", + "08004": "sqlserver_rejected_establishment_of_sqlconnection", + "08007": "transaction_resolution_unknown", + "08P01": "protocol_violation", + // Class 09 - Triggered Action Exception + "09000": "triggered_action_exception", + // Class 0A - Feature Not Supported + "0A000": "feature_not_supported", + // Class 0B - Invalid Transaction Initiation + "0B000": "invalid_transaction_initiation", + // Class 0F - Locator Exception + "0F000": "locator_exception", + "0F001": "invalid_locator_specification", + // Class 0L - Invalid Grantor + "0L000": "invalid_grantor", + "0LP01": "invalid_grant_operation", + // Class 0P - Invalid Role Specification + "0P000": "invalid_role_specification", + // Class 0Z - Diagnostics Exception + "0Z000": "diagnostics_exception", + "0Z002": "stacked_diagnostics_accessed_without_active_handler", + // Class 20 - Case Not Found + "20000": "case_not_found", + // Class 21 - Cardinality Violation + "21000": "cardinality_violation", + // Class 22 - Data Exception + "22000": "data_exception", + "2202E": "array_subscript_error", + "22021": "character_not_in_repertoire", + "22008": "datetime_field_overflow", + "22012": "division_by_zero", + "22005": "error_in_assignment", + "2200B": "escape_character_conflict", + "22022": "indicator_overflow", + "22015": "interval_field_overflow", + "2201E": "invalid_argument_for_logarithm", + "22014": "invalid_argument_for_ntile_function", + "22016": "invalid_argument_for_nth_value_function", + "2201F": "invalid_argument_for_power_function", + "2201G": "invalid_argument_for_width_bucket_function", + "22018": "invalid_character_value_for_cast", + "22007": "invalid_datetime_format", + "22019": "invalid_escape_character", + "2200D": "invalid_escape_octet", + "22025": "invalid_escape_sequence", + "22P06": "nonstandard_use_of_escape_character", + "22010": "invalid_indicator_parameter_value", + "22023": "invalid_parameter_value", + "2201B": "invalid_regular_expression", + "2201W": "invalid_row_count_in_limit_clause", + "2201X": "invalid_row_count_in_result_offset_clause", + "22009": "invalid_time_zone_displacement_value", + "2200C": "invalid_use_of_escape_character", + "2200G": "most_specific_type_mismatch", + "22004": "null_value_not_allowed", + "22002": "null_value_no_indicator_parameter", + "22003": "numeric_value_out_of_range", + "22026": "string_data_length_mismatch", + "22001": "string_data_right_truncation", + "22011": "substring_error", + "22027": "trim_error", + "22024": "unterminated_c_string", + "2200F": "zero_length_character_string", + "22P01": "floating_point_exception", + "22P02": "invalid_text_representation", + "22P03": "invalid_binary_representation", + "22P04": "bad_copy_file_format", + "22P05": "untranslatable_character", + "2200L": "not_an_xml_document", + "2200M": "invalid_xml_document", + "2200N": "invalid_xml_content", + "2200S": "invalid_xml_comment", + "2200T": "invalid_xml_processing_instruction", + // Class 23 - Integrity Constraint Violation + "23000": "integrity_constraint_violation", + "23001": "restrict_violation", + "23502": "not_null_violation", + "23503": "foreign_key_violation", + "23505": "unique_violation", + "23514": "check_violation", + "23P01": "exclusion_violation", + // Class 24 - Invalid Cursor State + "24000": "invalid_cursor_state", + // Class 25 - Invalid Transaction State + "25000": "invalid_transaction_state", + "25001": "active_sql_transaction", + "25002": "branch_transaction_already_active", + "25008": "held_cursor_requires_same_isolation_level", + "25003": "inappropriate_access_mode_for_branch_transaction", + "25004": "inappropriate_isolation_level_for_branch_transaction", + "25005": "no_active_sql_transaction_for_branch_transaction", + "25006": "read_only_sql_transaction", + "25007": "schema_and_data_statement_mixing_not_supported", + "25P01": "no_active_sql_transaction", + "25P02": "in_failed_sql_transaction", + // Class 26 - Invalid SQL Statement Name + "26000": "invalid_sql_statement_name", + // Class 27 - Triggered Data Change Violation + "27000": "triggered_data_change_violation", + // Class 28 - Invalid Authorization Specification + "28000": "invalid_authorization_specification", + "28P01": "invalid_password", + // Class 2B - Dependent Privilege Descriptors Still Exist + "2B000": "dependent_privilege_descriptors_still_exist", + "2BP01": "dependent_objects_still_exist", + // Class 2D - Invalid Transaction Termination + "2D000": "invalid_transaction_termination", + // Class 2F - SQL Routine Exception + "2F000": "sql_routine_exception", + "2F005": "function_executed_no_return_statement", + "2F002": "modifying_sql_data_not_permitted", + "2F003": "prohibited_sql_statement_attempted", + "2F004": "reading_sql_data_not_permitted", + // Class 34 - Invalid Cursor Name + "34000": "invalid_cursor_name", + // Class 38 - External Routine Exception + "38000": "external_routine_exception", + "38001": "containing_sql_not_permitted", + "38002": "modifying_sql_data_not_permitted", + "38003": "prohibited_sql_statement_attempted", + "38004": "reading_sql_data_not_permitted", + // Class 39 - External Routine Invocation Exception + "39000": "external_routine_invocation_exception", + "39001": "invalid_sqlstate_returned", + "39004": "null_value_not_allowed", + "39P01": "trigger_protocol_violated", + "39P02": "srf_protocol_violated", + // Class 3B - Savepoint Exception + "3B000": "savepoint_exception", + "3B001": "invalid_savepoint_specification", + // Class 3D - Invalid Catalog Name + "3D000": "invalid_catalog_name", + // Class 3F - Invalid Schema Name + "3F000": "invalid_schema_name", + // Class 40 - Transaction Rollback + "40000": "transaction_rollback", + "40002": "transaction_integrity_constraint_violation", + "40001": "serialization_failure", + "40003": "statement_completion_unknown", + "40P01": "deadlock_detected", + // Class 42 - Syntax Error or Access Rule Violation + "42000": "syntax_error_or_access_rule_violation", + "42601": "syntax_error", + "42501": "insufficient_privilege", + "42846": "cannot_coerce", + "42803": "grouping_error", + "42P20": "windowing_error", + "42P19": "invalid_recursion", + "42830": "invalid_foreign_key", + "42602": "invalid_name", + "42622": "name_too_long", + "42939": "reserved_name", + "42804": "datatype_mismatch", + "42P18": "indeterminate_datatype", + "42P21": "collation_mismatch", + "42P22": "indeterminate_collation", + "42809": "wrong_object_type", + "42703": "undefined_column", + "42883": "undefined_function", + "42P01": "undefined_table", + "42P02": "undefined_parameter", + "42704": "undefined_object", + "42701": "duplicate_column", + "42P03": "duplicate_cursor", + "42P04": "duplicate_database", + "42723": "duplicate_function", + "42P05": "duplicate_prepared_statement", + "42P06": "duplicate_schema", + "42P07": "duplicate_table", + "42712": "duplicate_alias", + "42710": "duplicate_object", + "42702": "ambiguous_column", + "42725": "ambiguous_function", + "42P08": "ambiguous_parameter", + "42P09": "ambiguous_alias", + "42P10": "invalid_column_reference", + "42611": "invalid_column_definition", + "42P11": "invalid_cursor_definition", + "42P12": "invalid_database_definition", + "42P13": "invalid_function_definition", + "42P14": "invalid_prepared_statement_definition", + "42P15": "invalid_schema_definition", + "42P16": "invalid_table_definition", + "42P17": "invalid_object_definition", + // Class 44 - WITH CHECK OPTION Violation + "44000": "with_check_option_violation", + // Class 53 - Insufficient Resources + "53000": "insufficient_resources", + "53100": "disk_full", + "53200": "out_of_memory", + "53300": "too_many_connections", + "53400": "configuration_limit_exceeded", + // Class 54 - Program Limit Exceeded + "54000": "program_limit_exceeded", + "54001": "statement_too_complex", + "54011": "too_many_columns", + "54023": "too_many_arguments", + // Class 55 - Object Not In Prerequisite State + "55000": "object_not_in_prerequisite_state", + "55006": "object_in_use", + "55P02": "cant_change_runtime_param", + "55P03": "lock_not_available", + // Class 57 - Operator Intervention + "57000": "operator_intervention", + "57014": "query_canceled", + "57P01": "admin_shutdown", + "57P02": "crash_shutdown", + "57P03": "cannot_connect_now", + "57P04": "database_dropped", + // Class 58 - System Error (errors external to PostgreSQL itself) + "58000": "system_error", + "58030": "io_error", + "58P01": "undefined_file", + "58P02": "duplicate_file", + // Class F0 - Configuration File Error + "F0000": "config_file_error", + "F0001": "lock_file_exists", + // Class HV - Foreign Data Wrapper Error (SQL/MED) + "HV000": "fdw_error", + "HV005": "fdw_column_name_not_found", + "HV002": "fdw_dynamic_parameter_value_needed", + "HV010": "fdw_function_sequence_error", + "HV021": "fdw_inconsistent_descriptor_information", + "HV024": "fdw_invalid_attribute_value", + "HV007": "fdw_invalid_column_name", + "HV008": "fdw_invalid_column_number", + "HV004": "fdw_invalid_data_type", + "HV006": "fdw_invalid_data_type_descriptors", + "HV091": "fdw_invalid_descriptor_field_identifier", + "HV00B": "fdw_invalid_handle", + "HV00C": "fdw_invalid_option_index", + "HV00D": "fdw_invalid_option_name", + "HV090": "fdw_invalid_string_length_or_buffer_length", + "HV00A": "fdw_invalid_string_format", + "HV009": "fdw_invalid_use_of_null_pointer", + "HV014": "fdw_too_many_handles", + "HV001": "fdw_out_of_memory", + "HV00P": "fdw_no_schemas", + "HV00J": "fdw_option_name_not_found", + "HV00K": "fdw_reply_handle", + "HV00Q": "fdw_schema_not_found", + "HV00R": "fdw_table_not_found", + "HV00L": "fdw_unable_to_create_execution", + "HV00M": "fdw_unable_to_create_reply", + "HV00N": "fdw_unable_to_establish_connection", + // Class P0 - PL/pgSQL Error + "P0000": "plpgsql_error", + "P0001": "raise_exception", + "P0002": "no_data_found", + "P0003": "too_many_rows", + // Class XX - Internal Error + "XX000": "internal_error", + "XX001": "data_corrupted", + "XX002": "index_corrupted", +} + +func parseError(r *readBuf) *Error { + err := new(Error) + for t := r.byte(); t != 0; t = r.byte() { + msg := r.string() + switch t { + case 'S': + err.Severity = msg + case 'C': + err.Code = ErrorCode(msg) + case 'M': + err.Message = msg + case 'D': + err.Detail = msg + case 'H': + err.Hint = msg + case 'P': + err.Position = msg + case 'p': + err.InternalPosition = msg + case 'q': + err.InternalQuery = msg + case 'W': + err.Where = msg + case 's': + err.Schema = msg + case 't': + err.Table = msg + case 'c': + err.Column = msg + case 'd': + err.DataTypeName = msg + case 'n': + err.Constraint = msg + case 'F': + err.File = msg + case 'L': + err.Line = msg + case 'R': + err.Routine = msg + } + } + return err +} + +// Fatal returns true if the Error Severity is fatal. +func (err *Error) Fatal() bool { + return err.Severity == Efatal +} + +// Get implements the legacy PGError interface. New code should use the fields +// of the Error struct directly. +func (err *Error) Get(k byte) (v string) { + switch k { + case 'S': + return err.Severity + case 'C': + return string(err.Code) + case 'M': + return err.Message + case 'D': + return err.Detail + case 'H': + return err.Hint + case 'P': + return err.Position + case 'p': + return err.InternalPosition + case 'q': + return err.InternalQuery + case 'W': + return err.Where + case 's': + return err.Schema + case 't': + return err.Table + case 'c': + return err.Column + case 'd': + return err.DataTypeName + case 'n': + return err.Constraint + case 'F': + return err.File + case 'L': + return err.Line + case 'R': + return err.Routine + } + return "" +} + +func (err Error) Error() string { + return "pq: " + err.Message +} + +// PGError is an interface used by previous versions of pq. It is provided +// only to support legacy code. New code should use the Error type. +type PGError interface { + Error() string + Fatal() bool + Get(k byte) (v string) +} + +func errorf(s string, args ...interface{}) { + panic(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...))) +} + +func errRecoverNoErrBadConn(err *error) { + e := recover() + if e == nil { + // Do nothing + return + } + var ok bool + *err, ok = e.(error) + if !ok { + *err = fmt.Errorf("pq: unexpected error: %#v", e) + } +} + +func (c *conn) errRecover(err *error) { + e := recover() + switch v := e.(type) { + case nil: + // Do nothing + case runtime.Error: + c.bad = true + panic(v) + case *Error: + if v.Fatal() { + *err = driver.ErrBadConn + } else { + *err = v + } + case *net.OpError: + *err = driver.ErrBadConn + case error: + if v == io.EOF || v.(error).Error() == "remote error: handshake failure" { + *err = driver.ErrBadConn + } else { + *err = v + } + + default: + c.bad = true + panic(fmt.Sprintf("unknown error: %#v", e)) + } + + // Any time we return ErrBadConn, we need to remember it since *Tx doesn't + // mark the connection bad in database/sql. + if *err == driver.ErrBadConn { + c.bad = true + } +} diff --git a/vendor/src/github.com/lib/pq/go18_test.go b/vendor/src/github.com/lib/pq/go18_test.go new file mode 100644 index 00000000..15546d86 --- /dev/null +++ b/vendor/src/github.com/lib/pq/go18_test.go @@ -0,0 +1,165 @@ +// +build go1.8 + +package pq + +import ( + "context" + "database/sql" + "testing" + "time" +) + +func TestMultipleSimpleQuery(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + rows, err := db.Query("select 1; set time zone default; select 2; select 3") + if err != nil { + t.Fatal(err) + } + defer rows.Close() + + var i int + for rows.Next() { + if err := rows.Scan(&i); err != nil { + t.Fatal(err) + } + if i != 1 { + t.Fatalf("expected 1, got %d", i) + } + } + if !rows.NextResultSet() { + t.Fatal("expected more result sets", rows.Err()) + } + for rows.Next() { + if err := rows.Scan(&i); err != nil { + t.Fatal(err) + } + if i != 2 { + t.Fatalf("expected 2, got %d", i) + } + } + + // Make sure that if we ignore a result we can still query. + + rows, err = db.Query("select 4; select 5") + if err != nil { + t.Fatal(err) + } + defer rows.Close() + + for rows.Next() { + if err := rows.Scan(&i); err != nil { + t.Fatal(err) + } + if i != 4 { + t.Fatalf("expected 4, got %d", i) + } + } + if !rows.NextResultSet() { + t.Fatal("expected more result sets", rows.Err()) + } + for rows.Next() { + if err := rows.Scan(&i); err != nil { + t.Fatal(err) + } + if i != 5 { + t.Fatalf("expected 5, got %d", i) + } + } + if rows.NextResultSet() { + t.Fatal("unexpected result set") + } +} + +func TestContextCancelExec(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + ctx, cancel := context.WithCancel(context.Background()) + + // Delay execution for just a bit until db.ExecContext has begun. + go func() { + time.Sleep(time.Millisecond * 10) + cancel() + }() + + // Not canceled until after the exec has started. + if _, err := db.ExecContext(ctx, "select pg_sleep(1)"); err == nil { + t.Fatal("expected error") + } else if err.Error() != "pq: canceling statement due to user request" { + t.Fatalf("unexpected error: %s", err) + } + + // Context is already canceled, so error should come before execution. + if _, err := db.ExecContext(ctx, "select pg_sleep(1)"); err == nil { + t.Fatal("expected error") + } else if err.Error() != "context canceled" { + t.Fatalf("unexpected error: %s", err) + } +} + +func TestContextCancelQuery(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + ctx, cancel := context.WithCancel(context.Background()) + + // Delay execution for just a bit until db.QueryContext has begun. + go func() { + time.Sleep(time.Millisecond * 10) + cancel() + }() + + // Not canceled until after the exec has started. + if _, err := db.QueryContext(ctx, "select pg_sleep(1)"); err == nil { + t.Fatal("expected error") + } else if err.Error() != "pq: canceling statement due to user request" { + t.Fatalf("unexpected error: %s", err) + } + + // Context is already canceled, so error should come before execution. + if _, err := db.QueryContext(ctx, "select pg_sleep(1)"); err == nil { + t.Fatal("expected error") + } else if err.Error() != "context canceled" { + t.Fatalf("unexpected error: %s", err) + } +} + +func TestContextCancelBegin(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + ctx, cancel := context.WithCancel(context.Background()) + tx, err := db.BeginTx(ctx, nil) + if err != nil { + t.Fatal(err) + } + + // Delay execution for just a bit until tx.Exec has begun. + go func() { + time.Sleep(time.Millisecond * 10) + cancel() + }() + + // Not canceled until after the exec has started. + if _, err := tx.Exec("select pg_sleep(1)"); err == nil { + t.Fatal("expected error") + } else if err.Error() != "pq: canceling statement due to user request" { + t.Fatalf("unexpected error: %s", err) + } + + // Transaction is canceled, so expect an error. + if _, err := tx.Query("select pg_sleep(1)"); err == nil { + t.Fatal("expected error") + } else if err != sql.ErrTxDone { + t.Fatalf("unexpected error: %s", err) + } + + // Context is canceled, so cannot begin a transaction. + if _, err := db.BeginTx(ctx, nil); err == nil { + t.Fatal("expected error") + } else if err.Error() != "context canceled" { + t.Fatalf("unexpected error: %s", err) + } +} diff --git a/vendor/src/github.com/lib/pq/hstore/hstore.go b/vendor/src/github.com/lib/pq/hstore/hstore.go new file mode 100644 index 00000000..72d5abf5 --- /dev/null +++ b/vendor/src/github.com/lib/pq/hstore/hstore.go @@ -0,0 +1,118 @@ +package hstore + +import ( + "database/sql" + "database/sql/driver" + "strings" +) + +// A wrapper for transferring Hstore values back and forth easily. +type Hstore struct { + Map map[string]sql.NullString +} + +// escapes and quotes hstore keys/values +// s should be a sql.NullString or string +func hQuote(s interface{}) string { + var str string + switch v := s.(type) { + case sql.NullString: + if !v.Valid { + return "NULL" + } + str = v.String + case string: + str = v + default: + panic("not a string or sql.NullString") + } + + str = strings.Replace(str, "\\", "\\\\", -1) + return `"` + strings.Replace(str, "\"", "\\\"", -1) + `"` +} + +// Scan implements the Scanner interface. +// +// Note h.Map is reallocated before the scan to clear existing values. If the +// hstore column's database value is NULL, then h.Map is set to nil instead. +func (h *Hstore) Scan(value interface{}) error { + if value == nil { + h.Map = nil + return nil + } + h.Map = make(map[string]sql.NullString) + var b byte + pair := [][]byte{{}, {}} + pi := 0 + inQuote := false + didQuote := false + sawSlash := false + bindex := 0 + for bindex, b = range value.([]byte) { + if sawSlash { + pair[pi] = append(pair[pi], b) + sawSlash = false + continue + } + + switch b { + case '\\': + sawSlash = true + continue + case '"': + inQuote = !inQuote + if !didQuote { + didQuote = true + } + continue + default: + if !inQuote { + switch b { + case ' ', '\t', '\n', '\r': + continue + case '=': + continue + case '>': + pi = 1 + didQuote = false + continue + case ',': + s := string(pair[1]) + if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" { + h.Map[string(pair[0])] = sql.NullString{String: "", Valid: false} + } else { + h.Map[string(pair[0])] = sql.NullString{String: string(pair[1]), Valid: true} + } + pair[0] = []byte{} + pair[1] = []byte{} + pi = 0 + continue + } + } + } + pair[pi] = append(pair[pi], b) + } + if bindex > 0 { + s := string(pair[1]) + if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" { + h.Map[string(pair[0])] = sql.NullString{String: "", Valid: false} + } else { + h.Map[string(pair[0])] = sql.NullString{String: string(pair[1]), Valid: true} + } + } + return nil +} + +// Value implements the driver Valuer interface. Note if h.Map is nil, the +// database column value will be set to NULL. +func (h Hstore) Value() (driver.Value, error) { + if h.Map == nil { + return nil, nil + } + parts := []string{} + for key, val := range h.Map { + thispart := hQuote(key) + "=>" + hQuote(val) + parts = append(parts, thispart) + } + return []byte(strings.Join(parts, ",")), nil +} diff --git a/vendor/src/github.com/lib/pq/hstore/hstore_test.go b/vendor/src/github.com/lib/pq/hstore/hstore_test.go new file mode 100644 index 00000000..1c9f2bd4 --- /dev/null +++ b/vendor/src/github.com/lib/pq/hstore/hstore_test.go @@ -0,0 +1,148 @@ +package hstore + +import ( + "database/sql" + "os" + "testing" + + _ "github.com/lib/pq" +) + +type Fatalistic interface { + Fatal(args ...interface{}) +} + +func openTestConn(t Fatalistic) *sql.DB { + datname := os.Getenv("PGDATABASE") + sslmode := os.Getenv("PGSSLMODE") + + if datname == "" { + os.Setenv("PGDATABASE", "pqgotest") + } + + if sslmode == "" { + os.Setenv("PGSSLMODE", "disable") + } + + conn, err := sql.Open("postgres", "") + if err != nil { + t.Fatal(err) + } + + return conn +} + +func TestHstore(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + // quitely create hstore if it doesn't exist + _, err := db.Exec("CREATE EXTENSION IF NOT EXISTS hstore") + if err != nil { + t.Skipf("Skipping hstore tests - hstore extension create failed: %s", err.Error()) + } + + hs := Hstore{} + + // test for null-valued hstores + err = db.QueryRow("SELECT NULL::hstore").Scan(&hs) + if err != nil { + t.Fatal(err) + } + if hs.Map != nil { + t.Fatalf("expected null map") + } + + err = db.QueryRow("SELECT $1::hstore", hs).Scan(&hs) + if err != nil { + t.Fatalf("re-query null map failed: %s", err.Error()) + } + if hs.Map != nil { + t.Fatalf("expected null map") + } + + // test for empty hstores + err = db.QueryRow("SELECT ''::hstore").Scan(&hs) + if err != nil { + t.Fatal(err) + } + if hs.Map == nil { + t.Fatalf("expected empty map, got null map") + } + if len(hs.Map) != 0 { + t.Fatalf("expected empty map, got len(map)=%d", len(hs.Map)) + } + + err = db.QueryRow("SELECT $1::hstore", hs).Scan(&hs) + if err != nil { + t.Fatalf("re-query empty map failed: %s", err.Error()) + } + if hs.Map == nil { + t.Fatalf("expected empty map, got null map") + } + if len(hs.Map) != 0 { + t.Fatalf("expected empty map, got len(map)=%d", len(hs.Map)) + } + + // a few example maps to test out + hsOnePair := Hstore{ + Map: map[string]sql.NullString{ + "key1": {String: "value1", Valid: true}, + }, + } + + hsThreePairs := Hstore{ + Map: map[string]sql.NullString{ + "key1": {String: "value1", Valid: true}, + "key2": {String: "value2", Valid: true}, + "key3": {String: "value3", Valid: true}, + }, + } + + hsSmorgasbord := Hstore{ + Map: map[string]sql.NullString{ + "nullstring": {String: "NULL", Valid: true}, + "actuallynull": {String: "", Valid: false}, + "NULL": {String: "NULL string key", Valid: true}, + "withbracket": {String: "value>42", Valid: true}, + "withequal": {String: "value=42", Valid: true}, + `"withquotes1"`: {String: `this "should" be fine`, Valid: true}, + `"withquotes"2"`: {String: `this "should\" also be fine`, Valid: true}, + "embedded1": {String: "value1=>x1", Valid: true}, + "embedded2": {String: `"value2"=>x2`, Valid: true}, + "withnewlines": {String: "\n\nvalue\t=>2", Valid: true}, + "<>": {String: `this, "should,\" also, => be fine`, Valid: true}, + }, + } + + // test encoding in query params, then decoding during Scan + testBidirectional := func(h Hstore) { + err = db.QueryRow("SELECT $1::hstore", h).Scan(&hs) + if err != nil { + t.Fatalf("re-query %d-pair map failed: %s", len(h.Map), err.Error()) + } + if hs.Map == nil { + t.Fatalf("expected %d-pair map, got null map", len(h.Map)) + } + if len(hs.Map) != len(h.Map) { + t.Fatalf("expected %d-pair map, got len(map)=%d", len(h.Map), len(hs.Map)) + } + + for key, val := range hs.Map { + otherval, found := h.Map[key] + if !found { + t.Fatalf(" key '%v' not found in %d-pair map", key, len(h.Map)) + } + if otherval.Valid != val.Valid { + t.Fatalf(" value %v <> %v in %d-pair map", otherval, val, len(h.Map)) + } + if otherval.String != val.String { + t.Fatalf(" value '%v' <> '%v' in %d-pair map", otherval.String, val.String, len(h.Map)) + } + } + } + + testBidirectional(hsOnePair) + testBidirectional(hsThreePairs) + testBidirectional(hsSmorgasbord) +} diff --git a/vendor/src/github.com/lib/pq/issues_test.go b/vendor/src/github.com/lib/pq/issues_test.go new file mode 100644 index 00000000..3a330a0a --- /dev/null +++ b/vendor/src/github.com/lib/pq/issues_test.go @@ -0,0 +1,26 @@ +package pq + +import "testing" + +func TestIssue494(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + query := `CREATE TEMP TABLE t (i INT PRIMARY KEY)` + if _, err := db.Exec(query); err != nil { + t.Fatal(err) + } + + txn, err := db.Begin() + if err != nil { + t.Fatal(err) + } + + if _, err := txn.Prepare(CopyIn("t", "i")); err != nil { + t.Fatal(err) + } + + if _, err := txn.Query("SELECT 1"); err == nil { + t.Fatal("expected error") + } +} diff --git a/vendor/src/github.com/lib/pq/listen_example/doc.go b/vendor/src/github.com/lib/pq/listen_example/doc.go new file mode 100644 index 00000000..5bc99f5c --- /dev/null +++ b/vendor/src/github.com/lib/pq/listen_example/doc.go @@ -0,0 +1,102 @@ +/* + +Below you will find a self-contained Go program which uses the LISTEN / NOTIFY +mechanism to avoid polling the database while waiting for more work to arrive. + + // + // You can see the program in action by defining a function similar to + // the following: + // + // CREATE OR REPLACE FUNCTION public.get_work() + // RETURNS bigint + // LANGUAGE sql + // AS $$ + // SELECT CASE WHEN random() >= 0.2 THEN int8 '1' END + // $$ + // ; + + package main + + import ( + "database/sql" + "fmt" + "time" + + "github.com/lib/pq" + ) + + func doWork(db *sql.DB, work int64) { + // work here + } + + func getWork(db *sql.DB) { + for { + // get work from the database here + var work sql.NullInt64 + err := db.QueryRow("SELECT get_work()").Scan(&work) + if err != nil { + fmt.Println("call to get_work() failed: ", err) + time.Sleep(10 * time.Second) + continue + } + if !work.Valid { + // no more work to do + fmt.Println("ran out of work") + return + } + + fmt.Println("starting work on ", work.Int64) + go doWork(db, work.Int64) + } + } + + func waitForNotification(l *pq.Listener) { + for { + select { + case <-l.Notify: + fmt.Println("received notification, new work available") + return + case <-time.After(90 * time.Second): + go func() { + l.Ping() + }() + // Check if there's more work available, just in case it takes + // a while for the Listener to notice connection loss and + // reconnect. + fmt.Println("received no work for 90 seconds, checking for new work") + return + } + } + } + + func main() { + var conninfo string = "" + + db, err := sql.Open("postgres", conninfo) + if err != nil { + panic(err) + } + + reportProblem := func(ev pq.ListenerEventType, err error) { + if err != nil { + fmt.Println(err.Error()) + } + } + + listener := pq.NewListener(conninfo, 10 * time.Second, time.Minute, reportProblem) + err = listener.Listen("getwork") + if err != nil { + panic(err) + } + + fmt.Println("entering main loop") + for { + // process all available work before waiting for notifications + getWork(db) + waitForNotification(listener) + } + } + + +*/ +package listen_example diff --git a/vendor/src/github.com/lib/pq/notify.go b/vendor/src/github.com/lib/pq/notify.go new file mode 100644 index 00000000..09f94244 --- /dev/null +++ b/vendor/src/github.com/lib/pq/notify.go @@ -0,0 +1,782 @@ +package pq + +// Package pq is a pure Go Postgres driver for the database/sql package. +// This module contains support for Postgres LISTEN/NOTIFY. + +import ( + "errors" + "fmt" + "sync" + "sync/atomic" + "time" +) + +// Notification represents a single notification from the database. +type Notification struct { + // Process ID (PID) of the notifying postgres backend. + BePid int + // Name of the channel the notification was sent on. + Channel string + // Payload, or the empty string if unspecified. + Extra string +} + +func recvNotification(r *readBuf) *Notification { + bePid := r.int32() + channel := r.string() + extra := r.string() + + return &Notification{bePid, channel, extra} +} + +const ( + connStateIdle int32 = iota + connStateExpectResponse + connStateExpectReadyForQuery +) + +type message struct { + typ byte + err error +} + +var errListenerConnClosed = errors.New("pq: ListenerConn has been closed") + +// ListenerConn is a low-level interface for waiting for notifications. You +// should use Listener instead. +type ListenerConn struct { + // guards cn and err + connectionLock sync.Mutex + cn *conn + err error + + connState int32 + + // the sending goroutine will be holding this lock + senderLock sync.Mutex + + notificationChan chan<- *Notification + + replyChan chan message +} + +// Creates a new ListenerConn. Use NewListener instead. +func NewListenerConn(name string, notificationChan chan<- *Notification) (*ListenerConn, error) { + return newDialListenerConn(defaultDialer{}, name, notificationChan) +} + +func newDialListenerConn(d Dialer, name string, c chan<- *Notification) (*ListenerConn, error) { + cn, err := DialOpen(d, name) + if err != nil { + return nil, err + } + + l := &ListenerConn{ + cn: cn.(*conn), + notificationChan: c, + connState: connStateIdle, + replyChan: make(chan message, 2), + } + + go l.listenerConnMain() + + return l, nil +} + +// We can only allow one goroutine at a time to be running a query on the +// connection for various reasons, so the goroutine sending on the connection +// must be holding senderLock. +// +// Returns an error if an unrecoverable error has occurred and the ListenerConn +// should be abandoned. +func (l *ListenerConn) acquireSenderLock() error { + // we must acquire senderLock first to avoid deadlocks; see ExecSimpleQuery + l.senderLock.Lock() + + l.connectionLock.Lock() + err := l.err + l.connectionLock.Unlock() + if err != nil { + l.senderLock.Unlock() + return err + } + return nil +} + +func (l *ListenerConn) releaseSenderLock() { + l.senderLock.Unlock() +} + +// setState advances the protocol state to newState. Returns false if moving +// to that state from the current state is not allowed. +func (l *ListenerConn) setState(newState int32) bool { + var expectedState int32 + + switch newState { + case connStateIdle: + expectedState = connStateExpectReadyForQuery + case connStateExpectResponse: + expectedState = connStateIdle + case connStateExpectReadyForQuery: + expectedState = connStateExpectResponse + default: + panic(fmt.Sprintf("unexpected listenerConnState %d", newState)) + } + + return atomic.CompareAndSwapInt32(&l.connState, expectedState, newState) +} + +// Main logic is here: receive messages from the postgres backend, forward +// notifications and query replies and keep the internal state in sync with the +// protocol state. Returns when the connection has been lost, is about to go +// away or should be discarded because we couldn't agree on the state with the +// server backend. +func (l *ListenerConn) listenerConnLoop() (err error) { + defer errRecoverNoErrBadConn(&err) + + r := &readBuf{} + for { + t, err := l.cn.recvMessage(r) + if err != nil { + return err + } + + switch t { + case 'A': + // recvNotification copies all the data so we don't need to worry + // about the scratch buffer being overwritten. + l.notificationChan <- recvNotification(r) + + case 'T', 'D': + // only used by tests; ignore + + case 'E': + // We might receive an ErrorResponse even when not in a query; it + // is expected that the server will close the connection after + // that, but we should make sure that the error we display is the + // one from the stray ErrorResponse, not io.ErrUnexpectedEOF. + if !l.setState(connStateExpectReadyForQuery) { + return parseError(r) + } + l.replyChan <- message{t, parseError(r)} + + case 'C', 'I': + if !l.setState(connStateExpectReadyForQuery) { + // protocol out of sync + return fmt.Errorf("unexpected CommandComplete") + } + // ExecSimpleQuery doesn't need to know about this message + + case 'Z': + if !l.setState(connStateIdle) { + // protocol out of sync + return fmt.Errorf("unexpected ReadyForQuery") + } + l.replyChan <- message{t, nil} + + case 'N', 'S': + // ignore + default: + return fmt.Errorf("unexpected message %q from server in listenerConnLoop", t) + } + } +} + +// This is the main routine for the goroutine receiving on the database +// connection. Most of the main logic is in listenerConnLoop. +func (l *ListenerConn) listenerConnMain() { + err := l.listenerConnLoop() + + // listenerConnLoop terminated; we're done, but we still have to clean up. + // Make sure nobody tries to start any new queries by making sure the err + // pointer is set. It is important that we do not overwrite its value; a + // connection could be closed by either this goroutine or one sending on + // the connection -- whoever closes the connection is assumed to have the + // more meaningful error message (as the other one will probably get + // net.errClosed), so that goroutine sets the error we expose while the + // other error is discarded. If the connection is lost while two + // goroutines are operating on the socket, it probably doesn't matter which + // error we expose so we don't try to do anything more complex. + l.connectionLock.Lock() + if l.err == nil { + l.err = err + } + l.cn.Close() + l.connectionLock.Unlock() + + // There might be a query in-flight; make sure nobody's waiting for a + // response to it, since there's not going to be one. + close(l.replyChan) + + // let the listener know we're done + close(l.notificationChan) + + // this ListenerConn is done +} + +// Send a LISTEN query to the server. See ExecSimpleQuery. +func (l *ListenerConn) Listen(channel string) (bool, error) { + return l.ExecSimpleQuery("LISTEN " + QuoteIdentifier(channel)) +} + +// Send an UNLISTEN query to the server. See ExecSimpleQuery. +func (l *ListenerConn) Unlisten(channel string) (bool, error) { + return l.ExecSimpleQuery("UNLISTEN " + QuoteIdentifier(channel)) +} + +// Send `UNLISTEN *` to the server. See ExecSimpleQuery. +func (l *ListenerConn) UnlistenAll() (bool, error) { + return l.ExecSimpleQuery("UNLISTEN *") +} + +// Ping the remote server to make sure it's alive. Non-nil error means the +// connection has failed and should be abandoned. +func (l *ListenerConn) Ping() error { + sent, err := l.ExecSimpleQuery("") + if !sent { + return err + } + if err != nil { + // shouldn't happen + panic(err) + } + return nil +} + +// Attempt to send a query on the connection. Returns an error if sending the +// query failed, and the caller should initiate closure of this connection. +// The caller must be holding senderLock (see acquireSenderLock and +// releaseSenderLock). +func (l *ListenerConn) sendSimpleQuery(q string) (err error) { + defer errRecoverNoErrBadConn(&err) + + // must set connection state before sending the query + if !l.setState(connStateExpectResponse) { + panic("two queries running at the same time") + } + + // Can't use l.cn.writeBuf here because it uses the scratch buffer which + // might get overwritten by listenerConnLoop. + b := &writeBuf{ + buf: []byte("Q\x00\x00\x00\x00"), + pos: 1, + } + b.string(q) + l.cn.send(b) + + return nil +} + +// Execute a "simple query" (i.e. one with no bindable parameters) on the +// connection. The possible return values are: +// 1) "executed" is true; the query was executed to completion on the +// database server. If the query failed, err will be set to the error +// returned by the database, otherwise err will be nil. +// 2) If "executed" is false, the query could not be executed on the remote +// server. err will be non-nil. +// +// After a call to ExecSimpleQuery has returned an executed=false value, the +// connection has either been closed or will be closed shortly thereafter, and +// all subsequently executed queries will return an error. +func (l *ListenerConn) ExecSimpleQuery(q string) (executed bool, err error) { + if err = l.acquireSenderLock(); err != nil { + return false, err + } + defer l.releaseSenderLock() + + err = l.sendSimpleQuery(q) + if err != nil { + // We can't know what state the protocol is in, so we need to abandon + // this connection. + l.connectionLock.Lock() + // Set the error pointer if it hasn't been set already; see + // listenerConnMain. + if l.err == nil { + l.err = err + } + l.connectionLock.Unlock() + l.cn.c.Close() + return false, err + } + + // now we just wait for a reply.. + for { + m, ok := <-l.replyChan + if !ok { + // We lost the connection to server, don't bother waiting for a + // a response. err should have been set already. + l.connectionLock.Lock() + err := l.err + l.connectionLock.Unlock() + return false, err + } + switch m.typ { + case 'Z': + // sanity check + if m.err != nil { + panic("m.err != nil") + } + // done; err might or might not be set + return true, err + + case 'E': + // sanity check + if m.err == nil { + panic("m.err == nil") + } + // server responded with an error; ReadyForQuery to follow + err = m.err + + default: + return false, fmt.Errorf("unknown response for simple query: %q", m.typ) + } + } +} + +func (l *ListenerConn) Close() error { + l.connectionLock.Lock() + if l.err != nil { + l.connectionLock.Unlock() + return errListenerConnClosed + } + l.err = errListenerConnClosed + l.connectionLock.Unlock() + // We can't send anything on the connection without holding senderLock. + // Simply close the net.Conn to wake up everyone operating on it. + return l.cn.c.Close() +} + +// Err() returns the reason the connection was closed. It is not safe to call +// this function until l.Notify has been closed. +func (l *ListenerConn) Err() error { + return l.err +} + +var errListenerClosed = errors.New("pq: Listener has been closed") + +var ErrChannelAlreadyOpen = errors.New("pq: channel is already open") +var ErrChannelNotOpen = errors.New("pq: channel is not open") + +type ListenerEventType int + +const ( + // Emitted only when the database connection has been initially + // initialized. err will always be nil. + ListenerEventConnected ListenerEventType = iota + + // Emitted after a database connection has been lost, either because of an + // error or because Close has been called. err will be set to the reason + // the database connection was lost. + ListenerEventDisconnected + + // Emitted after a database connection has been re-established after + // connection loss. err will always be nil. After this event has been + // emitted, a nil pq.Notification is sent on the Listener.Notify channel. + ListenerEventReconnected + + // Emitted after a connection to the database was attempted, but failed. + // err will be set to an error describing why the connection attempt did + // not succeed. + ListenerEventConnectionAttemptFailed +) + +type EventCallbackType func(event ListenerEventType, err error) + +// Listener provides an interface for listening to notifications from a +// PostgreSQL database. For general usage information, see section +// "Notifications". +// +// Listener can safely be used from concurrently running goroutines. +type Listener struct { + // Channel for receiving notifications from the database. In some cases a + // nil value will be sent. See section "Notifications" above. + Notify chan *Notification + + name string + minReconnectInterval time.Duration + maxReconnectInterval time.Duration + dialer Dialer + eventCallback EventCallbackType + + lock sync.Mutex + isClosed bool + reconnectCond *sync.Cond + cn *ListenerConn + connNotificationChan <-chan *Notification + channels map[string]struct{} +} + +// NewListener creates a new database connection dedicated to LISTEN / NOTIFY. +// +// name should be set to a connection string to be used to establish the +// database connection (see section "Connection String Parameters" above). +// +// minReconnectInterval controls the duration to wait before trying to +// re-establish the database connection after connection loss. After each +// consecutive failure this interval is doubled, until maxReconnectInterval is +// reached. Successfully completing the connection establishment procedure +// resets the interval back to minReconnectInterval. +// +// The last parameter eventCallback can be set to a function which will be +// called by the Listener when the state of the underlying database connection +// changes. This callback will be called by the goroutine which dispatches the +// notifications over the Notify channel, so you should try to avoid doing +// potentially time-consuming operations from the callback. +func NewListener(name string, + minReconnectInterval time.Duration, + maxReconnectInterval time.Duration, + eventCallback EventCallbackType) *Listener { + return NewDialListener(defaultDialer{}, name, minReconnectInterval, maxReconnectInterval, eventCallback) +} + +// NewDialListener is like NewListener but it takes a Dialer. +func NewDialListener(d Dialer, + name string, + minReconnectInterval time.Duration, + maxReconnectInterval time.Duration, + eventCallback EventCallbackType) *Listener { + + l := &Listener{ + name: name, + minReconnectInterval: minReconnectInterval, + maxReconnectInterval: maxReconnectInterval, + dialer: d, + eventCallback: eventCallback, + + channels: make(map[string]struct{}), + + Notify: make(chan *Notification, 32), + } + l.reconnectCond = sync.NewCond(&l.lock) + + go l.listenerMain() + + return l +} + +// Returns the notification channel for this listener. This is the same +// channel as Notify, and will not be recreated during the life time of the +// Listener. +func (l *Listener) NotificationChannel() <-chan *Notification { + return l.Notify +} + +// Listen starts listening for notifications on a channel. Calls to this +// function will block until an acknowledgement has been received from the +// server. Note that Listener automatically re-establishes the connection +// after connection loss, so this function may block indefinitely if the +// connection can not be re-established. +// +// Listen will only fail in three conditions: +// 1) The channel is already open. The returned error will be +// ErrChannelAlreadyOpen. +// 2) The query was executed on the remote server, but PostgreSQL returned an +// error message in response to the query. The returned error will be a +// pq.Error containing the information the server supplied. +// 3) Close is called on the Listener before the request could be completed. +// +// The channel name is case-sensitive. +func (l *Listener) Listen(channel string) error { + l.lock.Lock() + defer l.lock.Unlock() + + if l.isClosed { + return errListenerClosed + } + + // The server allows you to issue a LISTEN on a channel which is already + // open, but it seems useful to be able to detect this case to spot for + // mistakes in application logic. If the application genuinely does't + // care, it can check the exported error and ignore it. + _, exists := l.channels[channel] + if exists { + return ErrChannelAlreadyOpen + } + + if l.cn != nil { + // If gotResponse is true but error is set, the query was executed on + // the remote server, but resulted in an error. This should be + // relatively rare, so it's fine if we just pass the error to our + // caller. However, if gotResponse is false, we could not complete the + // query on the remote server and our underlying connection is about + // to go away, so we only add relname to l.channels, and wait for + // resync() to take care of the rest. + gotResponse, err := l.cn.Listen(channel) + if gotResponse && err != nil { + return err + } + } + + l.channels[channel] = struct{}{} + for l.cn == nil { + l.reconnectCond.Wait() + // we let go of the mutex for a while + if l.isClosed { + return errListenerClosed + } + } + + return nil +} + +// Unlisten removes a channel from the Listener's channel list. Returns +// ErrChannelNotOpen if the Listener is not listening on the specified channel. +// Returns immediately with no error if there is no connection. Note that you +// might still get notifications for this channel even after Unlisten has +// returned. +// +// The channel name is case-sensitive. +func (l *Listener) Unlisten(channel string) error { + l.lock.Lock() + defer l.lock.Unlock() + + if l.isClosed { + return errListenerClosed + } + + // Similarly to LISTEN, this is not an error in Postgres, but it seems + // useful to distinguish from the normal conditions. + _, exists := l.channels[channel] + if !exists { + return ErrChannelNotOpen + } + + if l.cn != nil { + // Similarly to Listen (see comment in that function), the caller + // should only be bothered with an error if it came from the backend as + // a response to our query. + gotResponse, err := l.cn.Unlisten(channel) + if gotResponse && err != nil { + return err + } + } + + // Don't bother waiting for resync if there's no connection. + delete(l.channels, channel) + return nil +} + +// UnlistenAll removes all channels from the Listener's channel list. Returns +// immediately with no error if there is no connection. Note that you might +// still get notifications for any of the deleted channels even after +// UnlistenAll has returned. +func (l *Listener) UnlistenAll() error { + l.lock.Lock() + defer l.lock.Unlock() + + if l.isClosed { + return errListenerClosed + } + + if l.cn != nil { + // Similarly to Listen (see comment in that function), the caller + // should only be bothered with an error if it came from the backend as + // a response to our query. + gotResponse, err := l.cn.UnlistenAll() + if gotResponse && err != nil { + return err + } + } + + // Don't bother waiting for resync if there's no connection. + l.channels = make(map[string]struct{}) + return nil +} + +// Ping the remote server to make sure it's alive. Non-nil return value means +// that there is no active connection. +func (l *Listener) Ping() error { + l.lock.Lock() + defer l.lock.Unlock() + + if l.isClosed { + return errListenerClosed + } + if l.cn == nil { + return errors.New("no connection") + } + + return l.cn.Ping() +} + +// Clean up after losing the server connection. Returns l.cn.Err(), which +// should have the reason the connection was lost. +func (l *Listener) disconnectCleanup() error { + l.lock.Lock() + defer l.lock.Unlock() + + // sanity check; can't look at Err() until the channel has been closed + select { + case _, ok := <-l.connNotificationChan: + if ok { + panic("connNotificationChan not closed") + } + default: + panic("connNotificationChan not closed") + } + + err := l.cn.Err() + l.cn.Close() + l.cn = nil + return err +} + +// Synchronize the list of channels we want to be listening on with the server +// after the connection has been established. +func (l *Listener) resync(cn *ListenerConn, notificationChan <-chan *Notification) error { + doneChan := make(chan error) + go func() { + for channel := range l.channels { + // If we got a response, return that error to our caller as it's + // going to be more descriptive than cn.Err(). + gotResponse, err := cn.Listen(channel) + if gotResponse && err != nil { + doneChan <- err + return + } + + // If we couldn't reach the server, wait for notificationChan to + // close and then return the error message from the connection, as + // per ListenerConn's interface. + if err != nil { + for _ = range notificationChan { + } + doneChan <- cn.Err() + return + } + } + doneChan <- nil + }() + + // Ignore notifications while synchronization is going on to avoid + // deadlocks. We have to send a nil notification over Notify anyway as + // we can't possibly know which notifications (if any) were lost while + // the connection was down, so there's no reason to try and process + // these messages at all. + for { + select { + case _, ok := <-notificationChan: + if !ok { + notificationChan = nil + } + + case err := <-doneChan: + return err + } + } +} + +// caller should NOT be holding l.lock +func (l *Listener) closed() bool { + l.lock.Lock() + defer l.lock.Unlock() + + return l.isClosed +} + +func (l *Listener) connect() error { + notificationChan := make(chan *Notification, 32) + cn, err := newDialListenerConn(l.dialer, l.name, notificationChan) + if err != nil { + return err + } + + l.lock.Lock() + defer l.lock.Unlock() + + err = l.resync(cn, notificationChan) + if err != nil { + cn.Close() + return err + } + + l.cn = cn + l.connNotificationChan = notificationChan + l.reconnectCond.Broadcast() + + return nil +} + +// Close disconnects the Listener from the database and shuts it down. +// Subsequent calls to its methods will return an error. Close returns an +// error if the connection has already been closed. +func (l *Listener) Close() error { + l.lock.Lock() + defer l.lock.Unlock() + + if l.isClosed { + return errListenerClosed + } + + if l.cn != nil { + l.cn.Close() + } + l.isClosed = true + + return nil +} + +func (l *Listener) emitEvent(event ListenerEventType, err error) { + if l.eventCallback != nil { + l.eventCallback(event, err) + } +} + +// Main logic here: maintain a connection to the server when possible, wait +// for notifications and emit events. +func (l *Listener) listenerConnLoop() { + var nextReconnect time.Time + + reconnectInterval := l.minReconnectInterval + for { + for { + err := l.connect() + if err == nil { + break + } + + if l.closed() { + return + } + l.emitEvent(ListenerEventConnectionAttemptFailed, err) + + time.Sleep(reconnectInterval) + reconnectInterval *= 2 + if reconnectInterval > l.maxReconnectInterval { + reconnectInterval = l.maxReconnectInterval + } + } + + if nextReconnect.IsZero() { + l.emitEvent(ListenerEventConnected, nil) + } else { + l.emitEvent(ListenerEventReconnected, nil) + l.Notify <- nil + } + + reconnectInterval = l.minReconnectInterval + nextReconnect = time.Now().Add(reconnectInterval) + + for { + notification, ok := <-l.connNotificationChan + if !ok { + // lost connection, loop again + break + } + l.Notify <- notification + } + + err := l.disconnectCleanup() + if l.closed() { + return + } + l.emitEvent(ListenerEventDisconnected, err) + + time.Sleep(nextReconnect.Sub(time.Now())) + } +} + +func (l *Listener) listenerMain() { + l.listenerConnLoop() + close(l.Notify) +} diff --git a/vendor/src/github.com/lib/pq/notify_test.go b/vendor/src/github.com/lib/pq/notify_test.go new file mode 100644 index 00000000..fe8941a4 --- /dev/null +++ b/vendor/src/github.com/lib/pq/notify_test.go @@ -0,0 +1,574 @@ +package pq + +import ( + "errors" + "fmt" + "io" + "os" + "runtime" + "sync" + "sync/atomic" + "testing" + "time" +) + +var errNilNotification = errors.New("nil notification") + +func expectNotification(t *testing.T, ch <-chan *Notification, relname string, extra string) error { + select { + case n := <-ch: + if n == nil { + return errNilNotification + } + if n.Channel != relname || n.Extra != extra { + return fmt.Errorf("unexpected notification %v", n) + } + return nil + case <-time.After(1500 * time.Millisecond): + return fmt.Errorf("timeout") + } +} + +func expectNoNotification(t *testing.T, ch <-chan *Notification) error { + select { + case n := <-ch: + return fmt.Errorf("unexpected notification %v", n) + case <-time.After(100 * time.Millisecond): + return nil + } +} + +func expectEvent(t *testing.T, eventch <-chan ListenerEventType, et ListenerEventType) error { + select { + case e := <-eventch: + if e != et { + return fmt.Errorf("unexpected event %v", e) + } + return nil + case <-time.After(1500 * time.Millisecond): + panic("expectEvent timeout") + } +} + +func expectNoEvent(t *testing.T, eventch <-chan ListenerEventType) error { + select { + case e := <-eventch: + return fmt.Errorf("unexpected event %v", e) + case <-time.After(100 * time.Millisecond): + return nil + } +} + +func newTestListenerConn(t *testing.T) (*ListenerConn, <-chan *Notification) { + datname := os.Getenv("PGDATABASE") + sslmode := os.Getenv("PGSSLMODE") + + if datname == "" { + os.Setenv("PGDATABASE", "pqgotest") + } + + if sslmode == "" { + os.Setenv("PGSSLMODE", "disable") + } + + notificationChan := make(chan *Notification) + l, err := NewListenerConn("", notificationChan) + if err != nil { + t.Fatal(err) + } + + return l, notificationChan +} + +func TestNewListenerConn(t *testing.T) { + l, _ := newTestListenerConn(t) + + defer l.Close() +} + +func TestConnListen(t *testing.T) { + l, channel := newTestListenerConn(t) + + defer l.Close() + + db := openTestConn(t) + defer db.Close() + + ok, err := l.Listen("notify_test") + if !ok || err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_test") + if err != nil { + t.Fatal(err) + } + + err = expectNotification(t, channel, "notify_test", "") + if err != nil { + t.Fatal(err) + } +} + +func TestConnUnlisten(t *testing.T) { + l, channel := newTestListenerConn(t) + + defer l.Close() + + db := openTestConn(t) + defer db.Close() + + ok, err := l.Listen("notify_test") + if !ok || err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_test") + + err = expectNotification(t, channel, "notify_test", "") + if err != nil { + t.Fatal(err) + } + + ok, err = l.Unlisten("notify_test") + if !ok || err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_test") + if err != nil { + t.Fatal(err) + } + + err = expectNoNotification(t, channel) + if err != nil { + t.Fatal(err) + } +} + +func TestConnUnlistenAll(t *testing.T) { + l, channel := newTestListenerConn(t) + + defer l.Close() + + db := openTestConn(t) + defer db.Close() + + ok, err := l.Listen("notify_test") + if !ok || err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_test") + + err = expectNotification(t, channel, "notify_test", "") + if err != nil { + t.Fatal(err) + } + + ok, err = l.UnlistenAll() + if !ok || err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_test") + if err != nil { + t.Fatal(err) + } + + err = expectNoNotification(t, channel) + if err != nil { + t.Fatal(err) + } +} + +func TestConnClose(t *testing.T) { + l, _ := newTestListenerConn(t) + defer l.Close() + + err := l.Close() + if err != nil { + t.Fatal(err) + } + err = l.Close() + if err != errListenerConnClosed { + t.Fatalf("expected errListenerConnClosed; got %v", err) + } +} + +func TestConnPing(t *testing.T) { + l, _ := newTestListenerConn(t) + defer l.Close() + err := l.Ping() + if err != nil { + t.Fatal(err) + } + err = l.Close() + if err != nil { + t.Fatal(err) + } + err = l.Ping() + if err != errListenerConnClosed { + t.Fatalf("expected errListenerConnClosed; got %v", err) + } +} + +// Test for deadlock where a query fails while another one is queued +func TestConnExecDeadlock(t *testing.T) { + l, _ := newTestListenerConn(t) + defer l.Close() + + var wg sync.WaitGroup + wg.Add(2) + + go func() { + l.ExecSimpleQuery("SELECT pg_sleep(60)") + wg.Done() + }() + runtime.Gosched() + go func() { + l.ExecSimpleQuery("SELECT 1") + wg.Done() + }() + // give the two goroutines some time to get into position + runtime.Gosched() + // calls Close on the net.Conn; equivalent to a network failure + l.Close() + + var done int32 = 0 + go func() { + time.Sleep(10 * time.Second) + if atomic.LoadInt32(&done) != 1 { + panic("timed out") + } + }() + wg.Wait() + atomic.StoreInt32(&done, 1) +} + +// Test for ListenerConn being closed while a slow query is executing +func TestListenerConnCloseWhileQueryIsExecuting(t *testing.T) { + l, _ := newTestListenerConn(t) + defer l.Close() + + var wg sync.WaitGroup + wg.Add(1) + + go func() { + sent, err := l.ExecSimpleQuery("SELECT pg_sleep(60)") + if sent { + panic("expected sent=false") + } + // could be any of a number of errors + if err == nil { + panic("expected error") + } + wg.Done() + }() + // give the above goroutine some time to get into position + runtime.Gosched() + err := l.Close() + if err != nil { + t.Fatal(err) + } + var done int32 = 0 + go func() { + time.Sleep(10 * time.Second) + if atomic.LoadInt32(&done) != 1 { + panic("timed out") + } + }() + wg.Wait() + atomic.StoreInt32(&done, 1) +} + +func TestNotifyExtra(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + if getServerVersion(t, db) < 90000 { + t.Skip("skipping NOTIFY payload test since the server does not appear to support it") + } + + l, channel := newTestListenerConn(t) + defer l.Close() + + ok, err := l.Listen("notify_test") + if !ok || err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_test, 'something'") + if err != nil { + t.Fatal(err) + } + + err = expectNotification(t, channel, "notify_test", "something") + if err != nil { + t.Fatal(err) + } +} + +// create a new test listener and also set the timeouts +func newTestListenerTimeout(t *testing.T, min time.Duration, max time.Duration) (*Listener, <-chan ListenerEventType) { + datname := os.Getenv("PGDATABASE") + sslmode := os.Getenv("PGSSLMODE") + + if datname == "" { + os.Setenv("PGDATABASE", "pqgotest") + } + + if sslmode == "" { + os.Setenv("PGSSLMODE", "disable") + } + + eventch := make(chan ListenerEventType, 16) + l := NewListener("", min, max, func(t ListenerEventType, err error) { eventch <- t }) + err := expectEvent(t, eventch, ListenerEventConnected) + if err != nil { + t.Fatal(err) + } + return l, eventch +} + +func newTestListener(t *testing.T) (*Listener, <-chan ListenerEventType) { + return newTestListenerTimeout(t, time.Hour, time.Hour) +} + +func TestListenerListen(t *testing.T) { + l, _ := newTestListener(t) + defer l.Close() + + db := openTestConn(t) + defer db.Close() + + err := l.Listen("notify_listen_test") + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_listen_test") + if err != nil { + t.Fatal(err) + } + + err = expectNotification(t, l.Notify, "notify_listen_test", "") + if err != nil { + t.Fatal(err) + } +} + +func TestListenerUnlisten(t *testing.T) { + l, _ := newTestListener(t) + defer l.Close() + + db := openTestConn(t) + defer db.Close() + + err := l.Listen("notify_listen_test") + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_listen_test") + if err != nil { + t.Fatal(err) + } + + err = l.Unlisten("notify_listen_test") + if err != nil { + t.Fatal(err) + } + + err = expectNotification(t, l.Notify, "notify_listen_test", "") + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_listen_test") + if err != nil { + t.Fatal(err) + } + + err = expectNoNotification(t, l.Notify) + if err != nil { + t.Fatal(err) + } +} + +func TestListenerUnlistenAll(t *testing.T) { + l, _ := newTestListener(t) + defer l.Close() + + db := openTestConn(t) + defer db.Close() + + err := l.Listen("notify_listen_test") + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_listen_test") + if err != nil { + t.Fatal(err) + } + + err = l.UnlistenAll() + if err != nil { + t.Fatal(err) + } + + err = expectNotification(t, l.Notify, "notify_listen_test", "") + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_listen_test") + if err != nil { + t.Fatal(err) + } + + err = expectNoNotification(t, l.Notify) + if err != nil { + t.Fatal(err) + } +} + +func TestListenerFailedQuery(t *testing.T) { + l, eventch := newTestListener(t) + defer l.Close() + + db := openTestConn(t) + defer db.Close() + + err := l.Listen("notify_listen_test") + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_listen_test") + if err != nil { + t.Fatal(err) + } + + err = expectNotification(t, l.Notify, "notify_listen_test", "") + if err != nil { + t.Fatal(err) + } + + // shouldn't cause a disconnect + ok, err := l.cn.ExecSimpleQuery("SELECT error") + if !ok { + t.Fatalf("could not send query to server: %v", err) + } + _, ok = err.(PGError) + if !ok { + t.Fatalf("unexpected error %v", err) + } + err = expectNoEvent(t, eventch) + if err != nil { + t.Fatal(err) + } + + // should still work + _, err = db.Exec("NOTIFY notify_listen_test") + if err != nil { + t.Fatal(err) + } + + err = expectNotification(t, l.Notify, "notify_listen_test", "") + if err != nil { + t.Fatal(err) + } +} + +func TestListenerReconnect(t *testing.T) { + l, eventch := newTestListenerTimeout(t, 20*time.Millisecond, time.Hour) + defer l.Close() + + db := openTestConn(t) + defer db.Close() + + err := l.Listen("notify_listen_test") + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("NOTIFY notify_listen_test") + if err != nil { + t.Fatal(err) + } + + err = expectNotification(t, l.Notify, "notify_listen_test", "") + if err != nil { + t.Fatal(err) + } + + // kill the connection and make sure it comes back up + ok, err := l.cn.ExecSimpleQuery("SELECT pg_terminate_backend(pg_backend_pid())") + if ok { + t.Fatalf("could not kill the connection: %v", err) + } + if err != io.EOF { + t.Fatalf("unexpected error %v", err) + } + err = expectEvent(t, eventch, ListenerEventDisconnected) + if err != nil { + t.Fatal(err) + } + err = expectEvent(t, eventch, ListenerEventReconnected) + if err != nil { + t.Fatal(err) + } + + // should still work + _, err = db.Exec("NOTIFY notify_listen_test") + if err != nil { + t.Fatal(err) + } + + // should get nil after Reconnected + err = expectNotification(t, l.Notify, "", "") + if err != errNilNotification { + t.Fatal(err) + } + + err = expectNotification(t, l.Notify, "notify_listen_test", "") + if err != nil { + t.Fatal(err) + } +} + +func TestListenerClose(t *testing.T) { + l, _ := newTestListenerTimeout(t, 20*time.Millisecond, time.Hour) + defer l.Close() + + err := l.Close() + if err != nil { + t.Fatal(err) + } + err = l.Close() + if err != errListenerClosed { + t.Fatalf("expected errListenerClosed; got %v", err) + } +} + +func TestListenerPing(t *testing.T) { + l, _ := newTestListenerTimeout(t, 20*time.Millisecond, time.Hour) + defer l.Close() + + err := l.Ping() + if err != nil { + t.Fatal(err) + } + + err = l.Close() + if err != nil { + t.Fatal(err) + } + + err = l.Ping() + if err != errListenerClosed { + t.Fatalf("expected errListenerClosed; got %v", err) + } +} diff --git a/vendor/src/github.com/lib/pq/oid/doc.go b/vendor/src/github.com/lib/pq/oid/doc.go new file mode 100644 index 00000000..caaede24 --- /dev/null +++ b/vendor/src/github.com/lib/pq/oid/doc.go @@ -0,0 +1,6 @@ +// Package oid contains OID constants +// as defined by the Postgres server. +package oid + +// Oid is a Postgres Object ID. +type Oid uint32 diff --git a/vendor/src/github.com/lib/pq/oid/gen.go b/vendor/src/github.com/lib/pq/oid/gen.go new file mode 100644 index 00000000..cd4aea80 --- /dev/null +++ b/vendor/src/github.com/lib/pq/oid/gen.go @@ -0,0 +1,74 @@ +// +build ignore + +// Generate the table of OID values +// Run with 'go run gen.go'. +package main + +import ( + "database/sql" + "fmt" + "log" + "os" + "os/exec" + + _ "github.com/lib/pq" +) + +func main() { + datname := os.Getenv("PGDATABASE") + sslmode := os.Getenv("PGSSLMODE") + + if datname == "" { + os.Setenv("PGDATABASE", "pqgotest") + } + + if sslmode == "" { + os.Setenv("PGSSLMODE", "disable") + } + + db, err := sql.Open("postgres", "") + if err != nil { + log.Fatal(err) + } + cmd := exec.Command("gofmt") + cmd.Stderr = os.Stderr + w, err := cmd.StdinPipe() + if err != nil { + log.Fatal(err) + } + f, err := os.Create("types.go") + if err != nil { + log.Fatal(err) + } + cmd.Stdout = f + err = cmd.Start() + if err != nil { + log.Fatal(err) + } + fmt.Fprintln(w, "// generated by 'go run gen.go'; do not edit") + fmt.Fprintln(w, "\npackage oid") + fmt.Fprintln(w, "const (") + rows, err := db.Query(` + SELECT typname, oid + FROM pg_type WHERE oid < 10000 + ORDER BY oid; + `) + if err != nil { + log.Fatal(err) + } + var name string + var oid int + for rows.Next() { + err = rows.Scan(&name, &oid) + if err != nil { + log.Fatal(err) + } + fmt.Fprintf(w, "T_%s Oid = %d\n", name, oid) + } + if err = rows.Err(); err != nil { + log.Fatal(err) + } + fmt.Fprintln(w, ")") + w.Close() + cmd.Wait() +} diff --git a/vendor/src/github.com/lib/pq/oid/types.go b/vendor/src/github.com/lib/pq/oid/types.go new file mode 100644 index 00000000..03df05a6 --- /dev/null +++ b/vendor/src/github.com/lib/pq/oid/types.go @@ -0,0 +1,161 @@ +// generated by 'go run gen.go'; do not edit + +package oid + +const ( + T_bool Oid = 16 + T_bytea Oid = 17 + T_char Oid = 18 + T_name Oid = 19 + T_int8 Oid = 20 + T_int2 Oid = 21 + T_int2vector Oid = 22 + T_int4 Oid = 23 + T_regproc Oid = 24 + T_text Oid = 25 + T_oid Oid = 26 + T_tid Oid = 27 + T_xid Oid = 28 + T_cid Oid = 29 + T_oidvector Oid = 30 + T_pg_type Oid = 71 + T_pg_attribute Oid = 75 + T_pg_proc Oid = 81 + T_pg_class Oid = 83 + T_json Oid = 114 + T_xml Oid = 142 + T__xml Oid = 143 + T_pg_node_tree Oid = 194 + T__json Oid = 199 + T_smgr Oid = 210 + T_point Oid = 600 + T_lseg Oid = 601 + T_path Oid = 602 + T_box Oid = 603 + T_polygon Oid = 604 + T_line Oid = 628 + T__line Oid = 629 + T_cidr Oid = 650 + T__cidr Oid = 651 + T_float4 Oid = 700 + T_float8 Oid = 701 + T_abstime Oid = 702 + T_reltime Oid = 703 + T_tinterval Oid = 704 + T_unknown Oid = 705 + T_circle Oid = 718 + T__circle Oid = 719 + T_money Oid = 790 + T__money Oid = 791 + T_macaddr Oid = 829 + T_inet Oid = 869 + T__bool Oid = 1000 + T__bytea Oid = 1001 + T__char Oid = 1002 + T__name Oid = 1003 + T__int2 Oid = 1005 + T__int2vector Oid = 1006 + T__int4 Oid = 1007 + T__regproc Oid = 1008 + T__text Oid = 1009 + T__tid Oid = 1010 + T__xid Oid = 1011 + T__cid Oid = 1012 + T__oidvector Oid = 1013 + T__bpchar Oid = 1014 + T__varchar Oid = 1015 + T__int8 Oid = 1016 + T__point Oid = 1017 + T__lseg Oid = 1018 + T__path Oid = 1019 + T__box Oid = 1020 + T__float4 Oid = 1021 + T__float8 Oid = 1022 + T__abstime Oid = 1023 + T__reltime Oid = 1024 + T__tinterval Oid = 1025 + T__polygon Oid = 1027 + T__oid Oid = 1028 + T_aclitem Oid = 1033 + T__aclitem Oid = 1034 + T__macaddr Oid = 1040 + T__inet Oid = 1041 + T_bpchar Oid = 1042 + T_varchar Oid = 1043 + T_date Oid = 1082 + T_time Oid = 1083 + T_timestamp Oid = 1114 + T__timestamp Oid = 1115 + T__date Oid = 1182 + T__time Oid = 1183 + T_timestamptz Oid = 1184 + T__timestamptz Oid = 1185 + T_interval Oid = 1186 + T__interval Oid = 1187 + T__numeric Oid = 1231 + T_pg_database Oid = 1248 + T__cstring Oid = 1263 + T_timetz Oid = 1266 + T__timetz Oid = 1270 + T_bit Oid = 1560 + T__bit Oid = 1561 + T_varbit Oid = 1562 + T__varbit Oid = 1563 + T_numeric Oid = 1700 + T_refcursor Oid = 1790 + T__refcursor Oid = 2201 + T_regprocedure Oid = 2202 + T_regoper Oid = 2203 + T_regoperator Oid = 2204 + T_regclass Oid = 2205 + T_regtype Oid = 2206 + T__regprocedure Oid = 2207 + T__regoper Oid = 2208 + T__regoperator Oid = 2209 + T__regclass Oid = 2210 + T__regtype Oid = 2211 + T_record Oid = 2249 + T_cstring Oid = 2275 + T_any Oid = 2276 + T_anyarray Oid = 2277 + T_void Oid = 2278 + T_trigger Oid = 2279 + T_language_handler Oid = 2280 + T_internal Oid = 2281 + T_opaque Oid = 2282 + T_anyelement Oid = 2283 + T__record Oid = 2287 + T_anynonarray Oid = 2776 + T_pg_authid Oid = 2842 + T_pg_auth_members Oid = 2843 + T__txid_snapshot Oid = 2949 + T_uuid Oid = 2950 + T__uuid Oid = 2951 + T_txid_snapshot Oid = 2970 + T_fdw_handler Oid = 3115 + T_anyenum Oid = 3500 + T_tsvector Oid = 3614 + T_tsquery Oid = 3615 + T_gtsvector Oid = 3642 + T__tsvector Oid = 3643 + T__gtsvector Oid = 3644 + T__tsquery Oid = 3645 + T_regconfig Oid = 3734 + T__regconfig Oid = 3735 + T_regdictionary Oid = 3769 + T__regdictionary Oid = 3770 + T_anyrange Oid = 3831 + T_event_trigger Oid = 3838 + T_int4range Oid = 3904 + T__int4range Oid = 3905 + T_numrange Oid = 3906 + T__numrange Oid = 3907 + T_tsrange Oid = 3908 + T__tsrange Oid = 3909 + T_tstzrange Oid = 3910 + T__tstzrange Oid = 3911 + T_daterange Oid = 3912 + T__daterange Oid = 3913 + T_int8range Oid = 3926 + T__int8range Oid = 3927 +) diff --git a/vendor/src/github.com/lib/pq/ssl.go b/vendor/src/github.com/lib/pq/ssl.go new file mode 100644 index 00000000..b282ebd9 --- /dev/null +++ b/vendor/src/github.com/lib/pq/ssl.go @@ -0,0 +1,175 @@ +package pq + +import ( + "crypto/tls" + "crypto/x509" + "io/ioutil" + "net" + "os" + "os/user" + "path/filepath" +) + +// ssl generates a function to upgrade a net.Conn based on the "sslmode" and +// related settings. The function is nil when no upgrade should take place. +func ssl(o values) func(net.Conn) net.Conn { + verifyCaOnly := false + tlsConf := tls.Config{} + switch mode := o.Get("sslmode"); mode { + // "require" is the default. + case "", "require": + // We must skip TLS's own verification since it requires full + // verification since Go 1.3. + tlsConf.InsecureSkipVerify = true + + // From http://www.postgresql.org/docs/current/static/libpq-ssl.html: + // Note: For backwards compatibility with earlier versions of PostgreSQL, if a + // root CA file exists, the behavior of sslmode=require will be the same as + // that of verify-ca, meaning the server certificate is validated against the + // CA. Relying on this behavior is discouraged, and applications that need + // certificate validation should always use verify-ca or verify-full. + if _, err := os.Stat(o.Get("sslrootcert")); err == nil { + verifyCaOnly = true + } else { + o.Set("sslrootcert", "") + } + case "verify-ca": + // We must skip TLS's own verification since it requires full + // verification since Go 1.3. + tlsConf.InsecureSkipVerify = true + verifyCaOnly = true + case "verify-full": + tlsConf.ServerName = o.Get("host") + case "disable": + return nil + default: + errorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode) + } + + sslClientCertificates(&tlsConf, o) + sslCertificateAuthority(&tlsConf, o) + sslRenegotiation(&tlsConf) + + return func(conn net.Conn) net.Conn { + client := tls.Client(conn, &tlsConf) + if verifyCaOnly { + sslVerifyCertificateAuthority(client, &tlsConf) + } + return client + } +} + +// sslClientCertificates adds the certificate specified in the "sslcert" and +// "sslkey" settings, or if they aren't set, from the .postgresql directory +// in the user's home directory. The configured files must exist and have +// the correct permissions. +func sslClientCertificates(tlsConf *tls.Config, o values) { + sslkey := o.Get("sslkey") + sslcert := o.Get("sslcert") + + var cinfo, kinfo os.FileInfo + var err error + + if sslcert != "" && sslkey != "" { + // Check that both files exist. Note that we don't do any more extensive + // checks than this (such as checking that the paths aren't directories); + // LoadX509KeyPair() will take care of the rest. + cinfo, err = os.Stat(sslcert) + if err != nil { + panic(err) + } + + kinfo, err = os.Stat(sslkey) + if err != nil { + panic(err) + } + } else { + // Automatically find certificates from ~/.postgresql + sslcert, sslkey, cinfo, kinfo = sslHomeCertificates() + + if cinfo == nil || kinfo == nil { + // No certificates to load + return + } + } + + // The files must also have the correct permissions + sslCertificatePermissions(cinfo, kinfo) + + cert, err := tls.LoadX509KeyPair(sslcert, sslkey) + if err != nil { + panic(err) + } + tlsConf.Certificates = []tls.Certificate{cert} +} + +// sslCertificateAuthority adds the RootCA specified in the "sslrootcert" setting. +func sslCertificateAuthority(tlsConf *tls.Config, o values) { + if sslrootcert := o.Get("sslrootcert"); sslrootcert != "" { + tlsConf.RootCAs = x509.NewCertPool() + + cert, err := ioutil.ReadFile(sslrootcert) + if err != nil { + panic(err) + } + + ok := tlsConf.RootCAs.AppendCertsFromPEM(cert) + if !ok { + errorf("couldn't parse pem in sslrootcert") + } + } +} + +// sslHomeCertificates returns the path and stats of certificates in the current +// user's home directory. +func sslHomeCertificates() (cert, key string, cinfo, kinfo os.FileInfo) { + user, err := user.Current() + + if err != nil { + // user.Current() might fail when cross-compiling. We have to ignore the + // error and continue without client certificates, since we wouldn't know + // from where to load them. + return + } + + cert = filepath.Join(user.HomeDir, ".postgresql", "postgresql.crt") + key = filepath.Join(user.HomeDir, ".postgresql", "postgresql.key") + + cinfo, err = os.Stat(cert) + if err != nil { + cinfo = nil + } + + kinfo, err = os.Stat(key) + if err != nil { + kinfo = nil + } + + return +} + +// sslVerifyCertificateAuthority carries out a TLS handshake to the server and +// verifies the presented certificate against the CA, i.e. the one specified in +// sslrootcert or the system CA if sslrootcert was not specified. +func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) { + err := client.Handshake() + if err != nil { + panic(err) + } + certs := client.ConnectionState().PeerCertificates + opts := x509.VerifyOptions{ + DNSName: client.ConnectionState().ServerName, + Intermediates: x509.NewCertPool(), + Roots: tlsConf.RootCAs, + } + for i, cert := range certs { + if i == 0 { + continue + } + opts.Intermediates.AddCert(cert) + } + _, err = certs[0].Verify(opts) + if err != nil { + panic(err) + } +} diff --git a/vendor/src/github.com/lib/pq/ssl_go1.7.go b/vendor/src/github.com/lib/pq/ssl_go1.7.go new file mode 100644 index 00000000..d7ba43b3 --- /dev/null +++ b/vendor/src/github.com/lib/pq/ssl_go1.7.go @@ -0,0 +1,14 @@ +// +build go1.7 + +package pq + +import "crypto/tls" + +// Accept renegotiation requests initiated by the backend. +// +// Renegotiation was deprecated then removed from PostgreSQL 9.5, but +// the default configuration of older versions has it enabled. Redshift +// also initiates renegotiations and cannot be reconfigured. +func sslRenegotiation(conf *tls.Config) { + conf.Renegotiation = tls.RenegotiateFreelyAsClient +} diff --git a/vendor/src/github.com/lib/pq/ssl_permissions.go b/vendor/src/github.com/lib/pq/ssl_permissions.go new file mode 100644 index 00000000..33076a8d --- /dev/null +++ b/vendor/src/github.com/lib/pq/ssl_permissions.go @@ -0,0 +1,16 @@ +// +build !windows + +package pq + +import "os" + +// sslCertificatePermissions checks the permissions on user-supplied certificate +// files. The key file should have very little access. +// +// libpq does not check key file permissions on Windows. +func sslCertificatePermissions(cert, key os.FileInfo) { + kmode := key.Mode() + if kmode != kmode&0600 { + panic(ErrSSLKeyHasWorldPermissions) + } +} diff --git a/vendor/src/github.com/lib/pq/ssl_renegotiation.go b/vendor/src/github.com/lib/pq/ssl_renegotiation.go new file mode 100644 index 00000000..85ed5e43 --- /dev/null +++ b/vendor/src/github.com/lib/pq/ssl_renegotiation.go @@ -0,0 +1,8 @@ +// +build !go1.7 + +package pq + +import "crypto/tls" + +// Renegotiation is not supported by crypto/tls until Go 1.7. +func sslRenegotiation(*tls.Config) {} diff --git a/vendor/src/github.com/lib/pq/ssl_test.go b/vendor/src/github.com/lib/pq/ssl_test.go new file mode 100644 index 00000000..f70a5fd5 --- /dev/null +++ b/vendor/src/github.com/lib/pq/ssl_test.go @@ -0,0 +1,269 @@ +package pq + +// This file contains SSL tests + +import ( + _ "crypto/sha256" + "crypto/x509" + "database/sql" + "fmt" + "os" + "path/filepath" + "testing" +) + +func maybeSkipSSLTests(t *testing.T) { + // Require some special variables for testing certificates + if os.Getenv("PQSSLCERTTEST_PATH") == "" { + t.Skip("PQSSLCERTTEST_PATH not set, skipping SSL tests") + } + + value := os.Getenv("PQGOSSLTESTS") + if value == "" || value == "0" { + t.Skip("PQGOSSLTESTS not enabled, skipping SSL tests") + } else if value != "1" { + t.Fatalf("unexpected value %q for PQGOSSLTESTS", value) + } +} + +func openSSLConn(t *testing.T, conninfo string) (*sql.DB, error) { + db, err := openTestConnConninfo(conninfo) + if err != nil { + // should never fail + t.Fatal(err) + } + // Do something with the connection to see whether it's working or not. + tx, err := db.Begin() + if err == nil { + return db, tx.Rollback() + } + _ = db.Close() + return nil, err +} + +func checkSSLSetup(t *testing.T, conninfo string) { + db, err := openSSLConn(t, conninfo) + if err == nil { + db.Close() + t.Fatalf("expected error with conninfo=%q", conninfo) + } +} + +// Connect over SSL and run a simple query to test the basics +func TestSSLConnection(t *testing.T) { + maybeSkipSSLTests(t) + // Environment sanity check: should fail without SSL + checkSSLSetup(t, "sslmode=disable user=pqgossltest") + + db, err := openSSLConn(t, "sslmode=require user=pqgossltest") + if err != nil { + t.Fatal(err) + } + rows, err := db.Query("SELECT 1") + if err != nil { + t.Fatal(err) + } + rows.Close() +} + +// Test sslmode=verify-full +func TestSSLVerifyFull(t *testing.T) { + maybeSkipSSLTests(t) + // Environment sanity check: should fail without SSL + checkSSLSetup(t, "sslmode=disable user=pqgossltest") + + // Not OK according to the system CA + _, err := openSSLConn(t, "host=postgres sslmode=verify-full user=pqgossltest") + if err == nil { + t.Fatal("expected error") + } + _, ok := err.(x509.UnknownAuthorityError) + if !ok { + t.Fatalf("expected x509.UnknownAuthorityError, got %#+v", err) + } + + rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt") + rootCert := "sslrootcert=" + rootCertPath + " " + // No match on Common Name + _, err = openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=verify-full user=pqgossltest") + if err == nil { + t.Fatal("expected error") + } + _, ok = err.(x509.HostnameError) + if !ok { + t.Fatalf("expected x509.HostnameError, got %#+v", err) + } + // OK + _, err = openSSLConn(t, rootCert+"host=postgres sslmode=verify-full user=pqgossltest") + if err != nil { + t.Fatal(err) + } +} + +// Test sslmode=require sslrootcert=rootCertPath +func TestSSLRequireWithRootCert(t *testing.T) { + maybeSkipSSLTests(t) + // Environment sanity check: should fail without SSL + checkSSLSetup(t, "sslmode=disable user=pqgossltest") + + bogusRootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "bogus_root.crt") + bogusRootCert := "sslrootcert=" + bogusRootCertPath + " " + + // Not OK according to the bogus CA + _, err := openSSLConn(t, bogusRootCert+"host=postgres sslmode=require user=pqgossltest") + if err == nil { + t.Fatal("expected error") + } + _, ok := err.(x509.UnknownAuthorityError) + if !ok { + t.Fatalf("expected x509.UnknownAuthorityError, got %s, %#+v", err, err) + } + + nonExistentCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "non_existent.crt") + nonExistentCert := "sslrootcert=" + nonExistentCertPath + " " + + // No match on Common Name, but that's OK because we're not validating anything. + _, err = openSSLConn(t, nonExistentCert+"host=127.0.0.1 sslmode=require user=pqgossltest") + if err != nil { + t.Fatal(err) + } + + rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt") + rootCert := "sslrootcert=" + rootCertPath + " " + + // No match on Common Name, but that's OK because we're not validating the CN. + _, err = openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=require user=pqgossltest") + if err != nil { + t.Fatal(err) + } + // Everything OK + _, err = openSSLConn(t, rootCert+"host=postgres sslmode=require user=pqgossltest") + if err != nil { + t.Fatal(err) + } +} + +// Test sslmode=verify-ca +func TestSSLVerifyCA(t *testing.T) { + maybeSkipSSLTests(t) + // Environment sanity check: should fail without SSL + checkSSLSetup(t, "sslmode=disable user=pqgossltest") + + // Not OK according to the system CA + _, err := openSSLConn(t, "host=postgres sslmode=verify-ca user=pqgossltest") + if err == nil { + t.Fatal("expected error") + } + _, ok := err.(x509.UnknownAuthorityError) + if !ok { + t.Fatalf("expected x509.UnknownAuthorityError, got %#+v", err) + } + + rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt") + rootCert := "sslrootcert=" + rootCertPath + " " + // No match on Common Name, but that's OK + _, err = openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=verify-ca user=pqgossltest") + if err != nil { + t.Fatal(err) + } + // Everything OK + _, err = openSSLConn(t, rootCert+"host=postgres sslmode=verify-ca user=pqgossltest") + if err != nil { + t.Fatal(err) + } +} + +func getCertConninfo(t *testing.T, source string) string { + var sslkey string + var sslcert string + + certpath := os.Getenv("PQSSLCERTTEST_PATH") + + switch source { + case "missingkey": + sslkey = "/tmp/filedoesnotexist" + sslcert = filepath.Join(certpath, "postgresql.crt") + case "missingcert": + sslkey = filepath.Join(certpath, "postgresql.key") + sslcert = "/tmp/filedoesnotexist" + case "certtwice": + sslkey = filepath.Join(certpath, "postgresql.crt") + sslcert = filepath.Join(certpath, "postgresql.crt") + case "valid": + sslkey = filepath.Join(certpath, "postgresql.key") + sslcert = filepath.Join(certpath, "postgresql.crt") + default: + t.Fatalf("invalid source %q", source) + } + return fmt.Sprintf("sslmode=require user=pqgosslcert sslkey=%s sslcert=%s", sslkey, sslcert) +} + +// Authenticate over SSL using client certificates +func TestSSLClientCertificates(t *testing.T) { + maybeSkipSSLTests(t) + // Environment sanity check: should fail without SSL + checkSSLSetup(t, "sslmode=disable user=pqgossltest") + + // Should also fail without a valid certificate + db, err := openSSLConn(t, "sslmode=require user=pqgosslcert") + if err == nil { + db.Close() + t.Fatal("expected error") + } + pge, ok := err.(*Error) + if !ok { + t.Fatal("expected pq.Error") + } + if pge.Code.Name() != "invalid_authorization_specification" { + t.Fatalf("unexpected error code %q", pge.Code.Name()) + } + + // Should work + db, err = openSSLConn(t, getCertConninfo(t, "valid")) + if err != nil { + t.Fatal(err) + } + rows, err := db.Query("SELECT 1") + if err != nil { + t.Fatal(err) + } + rows.Close() +} + +// Test errors with ssl certificates +func TestSSLClientCertificatesMissingFiles(t *testing.T) { + maybeSkipSSLTests(t) + // Environment sanity check: should fail without SSL + checkSSLSetup(t, "sslmode=disable user=pqgossltest") + + // Key missing, should fail + _, err := openSSLConn(t, getCertConninfo(t, "missingkey")) + if err == nil { + t.Fatal("expected error") + } + // should be a PathError + _, ok := err.(*os.PathError) + if !ok { + t.Fatalf("expected PathError, got %#+v", err) + } + + // Cert missing, should fail + _, err = openSSLConn(t, getCertConninfo(t, "missingcert")) + if err == nil { + t.Fatal("expected error") + } + // should be a PathError + _, ok = err.(*os.PathError) + if !ok { + t.Fatalf("expected PathError, got %#+v", err) + } + + // Key has wrong permissions, should fail + _, err = openSSLConn(t, getCertConninfo(t, "certtwice")) + if err == nil { + t.Fatal("expected error") + } + if err != ErrSSLKeyHasWorldPermissions { + t.Fatalf("expected ErrSSLKeyHasWorldPermissions, got %#+v", err) + } +} diff --git a/vendor/src/github.com/lib/pq/ssl_windows.go b/vendor/src/github.com/lib/pq/ssl_windows.go new file mode 100644 index 00000000..529daed2 --- /dev/null +++ b/vendor/src/github.com/lib/pq/ssl_windows.go @@ -0,0 +1,9 @@ +// +build windows + +package pq + +import "os" + +// sslCertificatePermissions checks the permissions on user-supplied certificate +// files. In libpq, this is a no-op on Windows. +func sslCertificatePermissions(cert, key os.FileInfo) {} diff --git a/vendor/src/github.com/lib/pq/url.go b/vendor/src/github.com/lib/pq/url.go new file mode 100644 index 00000000..f4d8a7c2 --- /dev/null +++ b/vendor/src/github.com/lib/pq/url.go @@ -0,0 +1,76 @@ +package pq + +import ( + "fmt" + "net" + nurl "net/url" + "sort" + "strings" +) + +// ParseURL no longer needs to be used by clients of this library since supplying a URL as a +// connection string to sql.Open() is now supported: +// +// sql.Open("postgres", "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full") +// +// It remains exported here for backwards-compatibility. +// +// ParseURL converts a url to a connection string for driver.Open. +// Example: +// +// "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full" +// +// converts to: +// +// "user=bob password=secret host=1.2.3.4 port=5432 dbname=mydb sslmode=verify-full" +// +// A minimal example: +// +// "postgres://" +// +// This will be blank, causing driver.Open to use all of the defaults +func ParseURL(url string) (string, error) { + u, err := nurl.Parse(url) + if err != nil { + return "", err + } + + if u.Scheme != "postgres" && u.Scheme != "postgresql" { + return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme) + } + + var kvs []string + escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`) + accrue := func(k, v string) { + if v != "" { + kvs = append(kvs, k+"="+escaper.Replace(v)) + } + } + + if u.User != nil { + v := u.User.Username() + accrue("user", v) + + v, _ = u.User.Password() + accrue("password", v) + } + + if host, port, err := net.SplitHostPort(u.Host); err != nil { + accrue("host", u.Host) + } else { + accrue("host", host) + accrue("port", port) + } + + if u.Path != "" { + accrue("dbname", u.Path[1:]) + } + + q := u.Query() + for k := range q { + accrue(k, q.Get(k)) + } + + sort.Strings(kvs) // Makes testing easier (not a performance concern) + return strings.Join(kvs, " "), nil +} diff --git a/vendor/src/github.com/lib/pq/url_test.go b/vendor/src/github.com/lib/pq/url_test.go new file mode 100644 index 00000000..4ff0ce03 --- /dev/null +++ b/vendor/src/github.com/lib/pq/url_test.go @@ -0,0 +1,66 @@ +package pq + +import ( + "testing" +) + +func TestSimpleParseURL(t *testing.T) { + expected := "host=hostname.remote" + str, err := ParseURL("postgres://hostname.remote") + if err != nil { + t.Fatal(err) + } + + if str != expected { + t.Fatalf("unexpected result from ParseURL:\n+ %v\n- %v", str, expected) + } +} + +func TestIPv6LoopbackParseURL(t *testing.T) { + expected := "host=::1 port=1234" + str, err := ParseURL("postgres://[::1]:1234") + if err != nil { + t.Fatal(err) + } + + if str != expected { + t.Fatalf("unexpected result from ParseURL:\n+ %v\n- %v", str, expected) + } +} + +func TestFullParseURL(t *testing.T) { + expected := `dbname=database host=hostname.remote password=top\ secret port=1234 user=username` + str, err := ParseURL("postgres://username:top%20secret@hostname.remote:1234/database") + if err != nil { + t.Fatal(err) + } + + if str != expected { + t.Fatalf("unexpected result from ParseURL:\n+ %s\n- %s", str, expected) + } +} + +func TestInvalidProtocolParseURL(t *testing.T) { + _, err := ParseURL("http://hostname.remote") + switch err { + case nil: + t.Fatal("Expected an error from parsing invalid protocol") + default: + msg := "invalid connection protocol: http" + if err.Error() != msg { + t.Fatalf("Unexpected error message:\n+ %s\n- %s", + err.Error(), msg) + } + } +} + +func TestMinimalURL(t *testing.T) { + cs, err := ParseURL("postgres://") + if err != nil { + t.Fatal(err) + } + + if cs != "" { + t.Fatalf("expected blank connection string, got: %q", cs) + } +} diff --git a/vendor/src/github.com/lib/pq/user_posix.go b/vendor/src/github.com/lib/pq/user_posix.go new file mode 100644 index 00000000..bf982524 --- /dev/null +++ b/vendor/src/github.com/lib/pq/user_posix.go @@ -0,0 +1,24 @@ +// Package pq is a pure Go Postgres driver for the database/sql package. + +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris rumprun + +package pq + +import ( + "os" + "os/user" +) + +func userCurrent() (string, error) { + u, err := user.Current() + if err == nil { + return u.Username, nil + } + + name := os.Getenv("USER") + if name != "" { + return name, nil + } + + return "", ErrCouldNotDetectUsername +} diff --git a/vendor/src/github.com/lib/pq/user_windows.go b/vendor/src/github.com/lib/pq/user_windows.go new file mode 100644 index 00000000..2b691267 --- /dev/null +++ b/vendor/src/github.com/lib/pq/user_windows.go @@ -0,0 +1,27 @@ +// Package pq is a pure Go Postgres driver for the database/sql package. +package pq + +import ( + "path/filepath" + "syscall" +) + +// Perform Windows user name lookup identically to libpq. +// +// The PostgreSQL code makes use of the legacy Win32 function +// GetUserName, and that function has not been imported into stock Go. +// GetUserNameEx is available though, the difference being that a +// wider range of names are available. To get the output to be the +// same as GetUserName, only the base (or last) component of the +// result is returned. +func userCurrent() (string, error) { + pw_name := make([]uint16, 128) + pwname_size := uint32(len(pw_name)) - 1 + err := syscall.GetUserNameEx(syscall.NameSamCompatible, &pw_name[0], &pwname_size) + if err != nil { + return "", ErrCouldNotDetectUsername + } + s := syscall.UTF16ToString(pw_name) + u := filepath.Base(s) + return u, nil +} diff --git a/vendor/src/github.com/lib/pq/uuid.go b/vendor/src/github.com/lib/pq/uuid.go new file mode 100644 index 00000000..9a1b9e07 --- /dev/null +++ b/vendor/src/github.com/lib/pq/uuid.go @@ -0,0 +1,23 @@ +package pq + +import ( + "encoding/hex" + "fmt" +) + +// decodeUUIDBinary interprets the binary format of a uuid, returning it in text format. +func decodeUUIDBinary(src []byte) ([]byte, error) { + if len(src) != 16 { + return nil, fmt.Errorf("pq: unable to decode uuid; bad length: %d", len(src)) + } + + dst := make([]byte, 36) + dst[8], dst[13], dst[18], dst[23] = '-', '-', '-', '-' + hex.Encode(dst[0:], src[0:4]) + hex.Encode(dst[9:], src[4:6]) + hex.Encode(dst[14:], src[6:8]) + hex.Encode(dst[19:], src[8:10]) + hex.Encode(dst[24:], src[10:16]) + + return dst, nil +} diff --git a/vendor/src/github.com/lib/pq/uuid_test.go b/vendor/src/github.com/lib/pq/uuid_test.go new file mode 100644 index 00000000..9df4a79b --- /dev/null +++ b/vendor/src/github.com/lib/pq/uuid_test.go @@ -0,0 +1,46 @@ +package pq + +import ( + "reflect" + "strings" + "testing" +) + +func TestDecodeUUIDBinaryError(t *testing.T) { + t.Parallel() + _, err := decodeUUIDBinary([]byte{0x12, 0x34}) + + if err == nil { + t.Fatal("Expected error, got none") + } + if !strings.HasPrefix(err.Error(), "pq:") { + t.Errorf("Expected error to start with %q, got %q", "pq:", err.Error()) + } + if !strings.Contains(err.Error(), "bad length: 2") { + t.Errorf("Expected error to contain length, got %q", err.Error()) + } +} + +func BenchmarkDecodeUUIDBinary(b *testing.B) { + x := []byte{0x03, 0xa3, 0x52, 0x2f, 0x89, 0x28, 0x49, 0x87, 0x84, 0xd6, 0x93, 0x7b, 0x36, 0xec, 0x27, 0x6f} + + for i := 0; i < b.N; i++ { + decodeUUIDBinary(x) + } +} + +func TestDecodeUUIDBackend(t *testing.T) { + db := openTestConn(t) + defer db.Close() + + var s string = "a0ecc91d-a13f-4fe4-9fce-7e09777cc70a" + var scanned interface{} + + err := db.QueryRow(`SELECT $1::uuid`, s).Scan(&scanned) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if !reflect.DeepEqual(scanned, []byte(s)) { + t.Errorf("Expected []byte(%q), got %T(%q)", s, scanned, scanned) + } +} diff --git a/vendor/src/github.com/pierrec/lz4/LICENSE b/vendor/src/github.com/pierrec/lz4/LICENSE new file mode 100644 index 00000000..bd899d83 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2015, Pierre Curto +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of xxHash nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/src/github.com/pierrec/lz4/README.md b/vendor/src/github.com/pierrec/lz4/README.md new file mode 100644 index 00000000..dd3c9d47 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/README.md @@ -0,0 +1,31 @@ +[![godoc](https://godoc.org/github.com/pierrec/lz4?status.png)](https://godoc.org/github.com/pierrec/lz4) +[![Build Status](https://travis-ci.org/pierrec/lz4.svg?branch=master)](https://travis-ci.org/pierrec/lz4) + +# lz4 +LZ4 compression and decompression in pure Go + +## Usage + +```go +import "github.com/pierrec/lz4" +``` + +## Description + +Package lz4 implements reading and writing lz4 compressed data (a frame), +as specified in http://fastcompression.blogspot.fr/2013/04/lz4-streaming-format-final.html, +using an io.Reader (decompression) and io.Writer (compression). +It is designed to minimize memory usage while maximizing throughput by being able to +[de]compress data concurrently. + +The Reader and the Writer support concurrent processing provided the supplied buffers are +large enough (in multiples of BlockMaxSize) and there is no block dependency. +Reader.WriteTo and Writer.ReadFrom do leverage the concurrency transparently. +The runtime.GOMAXPROCS() value is used to apply concurrency or not. + +Although the block level compression and decompression functions are exposed and are fully compatible +with the lz4 block format definition, they are low level and should not be used directly. +For a complete description of an lz4 compressed block, see: +http://fastcompression.blogspot.fr/2011/05/lz4-explained.html + +See https://github.com/Cyan4973/lz4 for the reference C implementation. diff --git a/vendor/src/github.com/pierrec/lz4/block.go b/vendor/src/github.com/pierrec/lz4/block.go new file mode 100644 index 00000000..6884bccd --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/block.go @@ -0,0 +1,474 @@ +package lz4 + +import ( + "encoding/binary" + "errors" + "unsafe" +) + +// block represents a frame data block. +// Used when compressing or decompressing frame blocks concurrently. +type block struct { + compressed bool + zdata []byte // compressed data + data []byte // decompressed data + offset int // offset within the data as with block dependency the 64Kb window is prepended to it + checksum uint32 // compressed data checksum + err error // error while [de]compressing +} + +var ( + // ErrInvalidSource is returned by UncompressBlock when a compressed block is corrupted. + ErrInvalidSource = errors.New("lz4: invalid source") + // ErrShortBuffer is returned by UncompressBlock, CompressBlock or CompressBlockHC when + // the supplied buffer for [de]compression is too small. + ErrShortBuffer = errors.New("lz4: short buffer") +) + +// CompressBlockBound returns the maximum size of a given buffer of size n, when not compressible. +func CompressBlockBound(n int) int { + return n + n/255 + 16 +} + +// UncompressBlock decompresses the source buffer into the destination one, +// starting at the di index and returning the decompressed size. +// +// The destination buffer must be sized appropriately. +// +// An error is returned if the source data is invalid or the destination buffer is too small. +func UncompressBlock(src, dst []byte, di int) (int, error) { + si, sn, di0 := 0, len(src), di + if sn == 0 { + return 0, nil + } + + for { + // literals and match lengths (token) + lLen := int(src[si] >> 4) + mLen := int(src[si] & 0xF) + if si++; si == sn { + return di, ErrInvalidSource + } + + // literals + if lLen > 0 { + if lLen == 0xF { + for src[si] == 0xFF { + lLen += 0xFF + if si++; si == sn { + return di - di0, ErrInvalidSource + } + } + lLen += int(src[si]) + if si++; si == sn { + return di - di0, ErrInvalidSource + } + } + if len(dst)-di < lLen || si+lLen > sn { + return di - di0, ErrShortBuffer + } + di += copy(dst[di:], src[si:si+lLen]) + + if si += lLen; si >= sn { + return di - di0, nil + } + } + + if si += 2; si >= sn { + return di, ErrInvalidSource + } + offset := int(src[si-2]) | int(src[si-1])<<8 + if di-offset < 0 || offset == 0 { + return di - di0, ErrInvalidSource + } + + // match + if mLen == 0xF { + for src[si] == 0xFF { + mLen += 0xFF + if si++; si == sn { + return di - di0, ErrInvalidSource + } + } + mLen += int(src[si]) + if si++; si == sn { + return di - di0, ErrInvalidSource + } + } + // minimum match length is 4 + mLen += 4 + if len(dst)-di <= mLen { + return di - di0, ErrShortBuffer + } + + // copy the match (NB. match is at least 4 bytes long) + // NB. past di, copy() would write old bytes instead of + // the ones we just copied, so split the work into the largest chunk. + for ; mLen >= offset; mLen -= offset { + di += copy(dst[di:], dst[di-offset:di]) + } + di += copy(dst[di:], dst[di-offset:di-offset+mLen]) + } +} + +type hashEntry struct { + generation uint + value int +} + +// CompressBlock compresses the source buffer starting at soffet into the destination one. +// This is the fast version of LZ4 compression and also the default one. +// +// The size of the compressed data is returned. If it is 0 and no error, then the data is incompressible. +// +// An error is returned if the destination buffer is too small. +func CompressBlock(src, dst []byte, soffset int) (int, error) { + var hashTable [hashTableSize]hashEntry + return compressGenerationalBlock(src, dst, soffset, 0, hashTable[:]) +} + +// getUint32 is a despicably evil function (well, for Go!) that takes advantage +// of the machine's byte order to save some operations. This may look +// inefficient but it is significantly faster on littleEndian machines, +// which include x84, amd64, and some ARM processors. +func getUint32(b []byte) uint32 { + _ = b[3] + if isLittleEndian { + return *(*uint32)(unsafe.Pointer(&b)) + } + + return uint32(b[0]) | + uint32(b[1])<<8 | + uint32(b[2])<<16 | + uint32(b[3])<<24 +} + +func compressGenerationalBlock(src, dst []byte, soffset int, generation uint, hashTable []hashEntry) (int, error) { + sn, dn := len(src)-mfLimit, len(dst) + if sn <= 0 || dn == 0 || soffset >= sn { + return 0, nil + } + var si, di int + + // fast scan strategy: + // we only need a hash table to store the last sequences (4 bytes) + var hashShift = uint((minMatch * 8) - hashLog) + + // Initialise the hash table with the first 64Kb of the input buffer + // (used when compressing dependent blocks) + for si < soffset { + h := getUint32(src[si:]) * hasher >> hashShift + si++ + hashTable[h] = hashEntry{generation, si} + } + + anchor := si + fma := 1 << skipStrength + for si < sn-minMatch { + // hash the next 4 bytes (sequence)... + h := getUint32(src[si:]) * hasher >> hashShift + if hashTable[h].generation != generation { + hashTable[h] = hashEntry{generation, 0} + } + // -1 to separate existing entries from new ones + ref := hashTable[h].value - 1 + // ...and store the position of the hash in the hash table (+1 to compensate the -1 upon saving) + hashTable[h].value = si + 1 + // no need to check the last 3 bytes in the first literal 4 bytes as + // this guarantees that the next match, if any, is compressed with + // a lower size, since to have some compression we must have: + // ll+ml-overlap > 1 + (ll-15)/255 + (ml-4-15)/255 + 2 (uncompressed size>compressed size) + // => ll+ml>3+2*overlap => ll+ml>= 4+2*overlap + // and by definition we do have: + // ll >= 1, ml >= 4 + // => ll+ml >= 5 + // => so overlap must be 0 + + // the sequence is new, out of bound (64kb) or not valid: try next sequence + if ref < 0 || fma&(1<>winSizeLog > 0 || + src[ref] != src[si] || + src[ref+1] != src[si+1] || + src[ref+2] != src[si+2] || + src[ref+3] != src[si+3] { + // variable step: improves performance on non-compressible data + si += fma >> skipStrength + fma++ + continue + } + // match found + fma = 1 << skipStrength + lLen := si - anchor + offset := si - ref + + // encode match length part 1 + si += minMatch + mLen := si // match length has minMatch already + for si <= sn && src[si] == src[si-offset] { + si++ + } + mLen = si - mLen + if mLen < 0xF { + dst[di] = byte(mLen) + } else { + dst[di] = 0xF + } + + // encode literals length + if lLen < 0xF { + dst[di] |= byte(lLen << 4) + } else { + dst[di] |= 0xF0 + if di++; di == dn { + return di, ErrShortBuffer + } + l := lLen - 0xF + for ; l >= 0xFF; l -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(l) + } + if di++; di == dn { + return di, ErrShortBuffer + } + + // literals + if di+lLen >= dn { + return di, ErrShortBuffer + } + di += copy(dst[di:], src[anchor:anchor+lLen]) + anchor = si + + // encode offset + if di += 2; di >= dn { + return di, ErrShortBuffer + } + dst[di-2], dst[di-1] = byte(offset), byte(offset>>8) + + // encode match length part 2 + if mLen >= 0xF { + for mLen -= 0xF; mLen >= 0xFF; mLen -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(mLen) + if di++; di == dn { + return di, ErrShortBuffer + } + } + } + + if anchor == 0 { + // incompressible + return 0, nil + } + + // last literals + lLen := len(src) - anchor + if lLen < 0xF { + dst[di] = byte(lLen << 4) + } else { + dst[di] = 0xF0 + if di++; di == dn { + return di, ErrShortBuffer + } + lLen -= 0xF + for ; lLen >= 0xFF; lLen -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(lLen) + } + if di++; di == dn { + return di, ErrShortBuffer + } + + // write literals + src = src[anchor:] + switch n := di + len(src); { + case n > dn: + return di, ErrShortBuffer + case n >= sn: + // incompressible + return 0, nil + } + di += copy(dst[di:], src) + return di, nil +} + +// CompressBlockHC compresses the source buffer starting at soffet into the destination one. +// CompressBlockHC compression ratio is better than CompressBlock but it is also slower. +// +// The size of the compressed data is returned. If it is 0 and no error, then the data is not compressible. +// +// An error is returned if the destination buffer is too small. +func CompressBlockHC(src, dst []byte, soffset int) (int, error) { + sn, dn := len(src)-mfLimit, len(dst) + if sn <= 0 || dn == 0 || soffset >= sn { + return 0, nil + } + var si, di int + + // Hash Chain strategy: + // we need a hash table and a chain table + // the chain table cannot contain more entries than the window size (64Kb entries) + var hashTable [1 << hashLog]int + var chainTable [winSize]int + var hashShift = uint((minMatch * 8) - hashLog) + + // Initialise the hash table with the first 64Kb of the input buffer + // (used when compressing dependent blocks) + for si < soffset { + h := binary.LittleEndian.Uint32(src[si:]) * hasher >> hashShift + chainTable[si&winMask] = hashTable[h] + si++ + hashTable[h] = si + } + + anchor := si + for si < sn-minMatch { + // hash the next 4 bytes (sequence)... + h := binary.LittleEndian.Uint32(src[si:]) * hasher >> hashShift + + // follow the chain until out of window and give the longest match + mLen := 0 + offset := 0 + for next := hashTable[h] - 1; next > 0 && next > si-winSize; next = chainTable[next&winMask] - 1 { + // the first (mLen==0) or next byte (mLen>=minMatch) at current match length must match to improve on the match length + if src[next+mLen] == src[si+mLen] { + for ml := 0; ; ml++ { + if src[next+ml] != src[si+ml] || si+ml > sn { + // found a longer match, keep its position and length + if mLen < ml && ml >= minMatch { + mLen = ml + offset = si - next + } + break + } + } + } + } + chainTable[si&winMask] = hashTable[h] + hashTable[h] = si + 1 + + // no match found + if mLen == 0 { + si++ + continue + } + + // match found + // update hash/chain tables with overlaping bytes: + // si already hashed, add everything from si+1 up to the match length + for si, ml := si+1, si+mLen; si < ml; { + h := binary.LittleEndian.Uint32(src[si:]) * hasher >> hashShift + chainTable[si&winMask] = hashTable[h] + si++ + hashTable[h] = si + } + + lLen := si - anchor + si += mLen + mLen -= minMatch // match length does not include minMatch + + if mLen < 0xF { + dst[di] = byte(mLen) + } else { + dst[di] = 0xF + } + + // encode literals length + if lLen < 0xF { + dst[di] |= byte(lLen << 4) + } else { + dst[di] |= 0xF0 + if di++; di == dn { + return di, ErrShortBuffer + } + l := lLen - 0xF + for ; l >= 0xFF; l -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(l) + } + if di++; di == dn { + return di, ErrShortBuffer + } + + // literals + if di+lLen >= dn { + return di, ErrShortBuffer + } + di += copy(dst[di:], src[anchor:anchor+lLen]) + anchor = si + + // encode offset + if di += 2; di >= dn { + return di, ErrShortBuffer + } + dst[di-2], dst[di-1] = byte(offset), byte(offset>>8) + + // encode match length part 2 + if mLen >= 0xF { + for mLen -= 0xF; mLen >= 0xFF; mLen -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(mLen) + if di++; di == dn { + return di, ErrShortBuffer + } + } + } + + if anchor == 0 { + // incompressible + return 0, nil + } + + // last literals + lLen := len(src) - anchor + if lLen < 0xF { + dst[di] = byte(lLen << 4) + } else { + dst[di] = 0xF0 + if di++; di == dn { + return di, ErrShortBuffer + } + lLen -= 0xF + for ; lLen >= 0xFF; lLen -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(lLen) + } + if di++; di == dn { + return di, ErrShortBuffer + } + + // write literals + src = src[anchor:] + switch n := di + len(src); { + case n > dn: + return di, ErrShortBuffer + case n >= sn: + // incompressible + return 0, nil + } + di += copy(dst[di:], src) + return di, nil +} diff --git a/vendor/src/github.com/pierrec/lz4/export_test.go b/vendor/src/github.com/pierrec/lz4/export_test.go new file mode 100644 index 00000000..3052506d --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/export_test.go @@ -0,0 +1,13 @@ +// Expose some internals for testing purposes +package lz4 + +// expose the possible block max sizes +var BlockMaxSizeItems []int + +func init() { + for s := range bsMapValue { + BlockMaxSizeItems = append(BlockMaxSizeItems, s) + } +} + +var FrameSkipMagic = frameSkipMagic diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/01572067d493db8dc8161f05c339a5192b0b4087-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/01572067d493db8dc8161f05c339a5192b0b4087-22 new file mode 100644 index 0000000000000000000000000000000000000000..4b8b629d5449a3467afe85535aa7eec4223bac59 GIT binary patch literal 105 zcmZQk@|DO-Y&o%a|NB@5Mh0F628Npd{~H(>B=VRT6c`zV85kNQ3=J)f3@nW-EKN-f e%z-KxKUFp4G@E%rU3w`^c_n8 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/02766f768fbfbd81b752cce427eb5242a44929cc-5 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/02766f768fbfbd81b752cce427eb5242a44929cc-5 new file mode 100644 index 0000000000000000000000000000000000000000..ead0ac0d319ff48ac6dc14c1db920ee00ceb917a GIT binary patch literal 19 ZcmZQk@|DO-Y&o%a|NB@5Mg|~g002Oq1@Hg> literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/032f04032e12567057782672bb12670c20d38439-10 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/032f04032e12567057782672bb12670c20d38439-10 new file mode 100644 index 0000000000000000000000000000000000000000..f1a389337beb616a2f139bf9205844ad38db9044 GIT binary patch literal 23 dcmZQk@|Ey)P+GZn|N8>%=qn6B;H2d%0RUK(2I>F+ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0367b985641aca66e6e4eeea68acf5e2a02c62a8-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0367b985641aca66e6e4eeea68acf5e2a02c62a8-16 new file mode 100644 index 0000000000000000000000000000000000000000..753a67cd3ca9f4e93e6370b727a4729ed05f2bfe GIT binary patch literal 38 scmZQk@|DO-Y&o%a|NB@5Mg}GZh6V`+ULaZX|9=AmgG3$^g957r0O39gRsaA1 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/03e85abc49352b2f7cc83efd7e4274da02d78b84-6 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/03e85abc49352b2f7cc83efd7e4274da02d78b84-6 new file mode 100644 index 0000000000000000000000000000000000000000..d2017a91adb9aca4ffd9ec8a84fd76ffc43f5083 GIT binary patch literal 13 RcmZS4@|9o!0u~@W82||00lEMH literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/049f82a81bb6b4d7cf69fac5e413f6ce299d48cf-8 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/049f82a81bb6b4d7cf69fac5e413f6ce299d48cf-8 new file mode 100644 index 0000000000000000000000000000000000000000..a69e01f280889b4a8249ce9b8cb378b796c262e0 GIT binary patch literal 19 acmZQk@|Ey)U|?|4^5tPrXJlYF#{>Wye*)G3 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/04c05c7956f17e57a91a47909bd0706135cf17a6-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/04c05c7956f17e57a91a47909bd0706135cf17a6-1 new file mode 100644 index 0000000000000000000000000000000000000000..0ea966b8f7cc3049888e796ad3ccdd9f375d71b6 GIT binary patch literal 46 zcmZ>Y$}l!`j8qGbjGmAd!oVOV-{8Qmq@d3d!eIaYj(`F~O1^kq;)OQ06z*mIMgS$D B4Kx4% literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/050e2af2a57d8044139ba21375f0ac6fcb7ab0b1-12 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/050e2af2a57d8044139ba21375f0ac6fcb7ab0b1-12 new file mode 100644 index 0000000000000000000000000000000000000000..6cb971272a19d3fa9fddcb0617ef95cb36991fbc GIT binary patch literal 84 XcmZ>Y%CHbGaY$}lu^j8qGbEVa7Mz`*dT=HS0UrPW literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0990ac54decbca1a97893e83c7feb2be89cb10ea-14 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0990ac54decbca1a97893e83c7feb2be89cb10ea-14 new file mode 100644 index 0000000000000000000000000000000000000000..37a0194e55dcdb47987d0f668a3ddc54ffaf1529 GIT binary patch literal 68 ocmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lW~Fqwx$Ld20pU~CW#0Ig98lmGw# literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/09f2eda28ecc97304659afded4d13a188baf2107-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/09f2eda28ecc97304659afded4d13a188baf2107-22 new file mode 100644 index 0000000000000000000000000000000000000000..c1b1ad50619559026aeac86cefc84eda3e3a405f GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%Y%CHbGa08$7BS^xk5 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0cf885cd35e7124005b0ba0c3c4431ddfaeff84d-11 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0cf885cd35e7124005b0ba0c3c4431ddfaeff84d-11 new file mode 100644 index 0000000000000000000000000000000000000000..b45509f6e5afba39a7f6aa400b98857af321b0f6 GIT binary patch literal 48 ScmZS4@|9o!0u~}@kQxA6pacd0 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0d7c02d4e91d82b0355baaca1237062639442db6-3 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0d7c02d4e91d82b0355baaca1237062639442db6-3 new file mode 100644 index 00000000..66665729 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0d7c02d4e91d82b0355baaca1237062639442db6-3 @@ -0,0 +1 @@ +"M@5 \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0e1b2b0c49dfb86fe01d3453dd24e39482e132e8-7 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/0e1b2b0c49dfb86fe01d3453dd24e39482e132e8-7 new file mode 100644 index 0000000000000000000000000000000000000000..8ca78705a4e4e7465e5326de594a8bccfe422481 GIT binary patch literal 21 bcmZQk@|DO-Y&o%a|NB@5Mg}GZAaDc#OG^c_ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..c21a363248ee3e69300c4f872699e14d94b64609 GIT binary patch literal 42 ycmZ>Y$}lu^j8qGbWG}V6&cMLH$Y9@~z+lM3aO6Y$}ki!aB=VRT6ih(^4M27xNDQn(7AT+u5(ddY JltL+}HURCk8Dsze literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/10fa5d9f0fe75f73c0e92a1fe1c00f0041ec8f39-24 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/10fa5d9f0fe75f73c0e92a1fe1c00f0041ec8f39-24 new file mode 100644 index 0000000000000000000000000000000000000000..62459e7280d635ee35f1980023b924ec33fd2c66 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%z8{OoL FL;wi63k(1N literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/11.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/11.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..b8539d875265721333033cef148a8ddb5b49cee6 GIT binary patch literal 14 TcmZ>Y$}kcyaY$}ko$aY$}kZxaY$}kl#aB=VRT6c`y~85kOrK*B)O0Fi-GP*nhK C#S`%W literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/142d4f8cb427dd3562d72d889dfc0ea3a2b03d98-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/142d4f8cb427dd3562d72d889dfc0ea3a2b03d98-22 new file mode 100644 index 0000000000000000000000000000000000000000..d162c38e792e97a45e2f10a9bbc70df796f7e142 GIT binary patch literal 83 bcmZQk@|DO-Y&o%a|NB@5Mg|~gpcDfDw7d=Q literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/15.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/15.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..bd2c29c27df1ef3674b1ac103ab04003f810e7c7 GIT binary patch literal 14 TcmZ>Y$}kfzaY$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42DdC He^MI&cccu4 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/16.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/16.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..5e13f64415b9b631a4303809662903f269bf3e4d GIT binary patch literal 14 TcmZ>Y$}kr%aY%CHbGaY$}lu^j8qGbRA4aVVK{Oq^<3Y%CHnKaY$}lu^j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DGh+=a literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/191e0dd24b8c7f8babeae4839768df39acc17eb1-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/191e0dd24b8c7f8babeae4839768df39acc17eb1-17 new file mode 100644 index 0000000000000000000000000000000000000000..000242c63608a1181bc2c414ded8cc81b0d4bb8e GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^&cG||4gkZR3)27q literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1a582381781f264f551bd6f0f2284a931147e6d9-4 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1a582381781f264f551bd6f0f2284a931147e6d9-4 new file mode 100644 index 0000000000000000000000000000000000000000..c02b40509a98970d9d91af2f9b6dfbf090a79955 GIT binary patch literal 9 QcmZ?L@|EzFU|?VX00=h$Hvj+t literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1c2781a1ffae4059ce3e93a55ec8d8cbf8bdecdf-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1c2781a1ffae4059ce3e93a55ec8d8cbf8bdecdf-22 new file mode 100644 index 0000000000000000000000000000000000000000..a9c4864764d15e1589fee301bc67511e661421a1 GIT binary patch literal 105 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`zV85kNQ3=J)f3@nW-EKN-f e%z-KxKUFp4K-j2Y8n8g?j1q^ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1d37fb332301cf7de0bd51a8c1aa9be4935e89fc-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1d37fb332301cf7de0bd51a8c1aa9be4935e89fc-1 new file mode 100644 index 00000000..ee12c7a5 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1d37fb332301cf7de0bd51a8c1aa9be4935e89fc-1 @@ -0,0 +1 @@ +"M \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1d6b87b52e62cb84be834478ad88129f5e1f247b-9 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1d6b87b52e62cb84be834478ad88129f5e1f247b-9 new file mode 100644 index 0000000000000000000000000000000000000000..bd5ff8ff1fa0e21cada483100c931b2c0509ea8a GIT binary patch literal 32 icmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^d2niHrNCW_vPza6y literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1ec2f11a8d8b9cf188a58f673a0b4a8608a926ca-3 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1ec2f11a8d8b9cf188a58f673a0b4a8608a926ca-3 new file mode 100644 index 00000000..7eeb2e86 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1ec2f11a8d8b9cf188a58f673a0b4a8608a926ca-3 @@ -0,0 +1 @@ +"M3 \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1fc2ba0bb981fec47badea1c80219452c9e3c76c-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1fc2ba0bb981fec47badea1c80219452c9e3c76c-22 new file mode 100644 index 0000000000000000000000000000000000000000..b53b47a542019475666d8c29698187d4d7d018c9 GIT binary patch literal 88 zcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lWRULaWm#6Wf)6N7>&NT8txS)D9UKnWxamihm` M0i*y-feDE`0G!1a#sB~S literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1fd8444ac43541c44a1c6ed8df2f688b1fa09681-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/1fd8444ac43541c44a1c6ed8df2f688b1fa09681-1 new file mode 100644 index 0000000000000000000000000000000000000000..f3fe56210bc1e92f2456695a25d79a5f01b7af13 GIT binary patch literal 29 kcmZ>Y$}lu^j8qGbWG}V6&cMLH$Y9@~z`(Y$}lo?j8qGbWG}V6&cMLH$Y9@~z+lM3aO6Y$}lo?j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DGms4| literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/202a9c8b188cae90f29bce3bf0438a035c504eb4-20 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/202a9c8b188cae90f29bce3bf0438a035c504eb4-20 new file mode 100644 index 0000000000000000000000000000000000000000..0014dc68bb5ab4a287ce9ac3fee91de7158de0d2 GIT binary patch literal 62 hcmZQk@|Ey#P+GZn|N8=^=qn6Bz(R~r1H%=dMgVf`6d(Wq literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/20cf0057443ecb322ff1169ecbe6cf20250f15af-13 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/20cf0057443ecb322ff1169ecbe6cf20250f15af-13 new file mode 100644 index 0000000000000000000000000000000000000000..f83424bf2b5731f4849848410e7298b21be08baa GIT binary patch literal 32 icmZQk@|DO-Y&o%a|NB@5Mh0F628RC-kjDgMO8@}S8w~yc literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/20d1a26afe563ad77e7a95fbee6ff59ebf3e61ab-13 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/20d1a26afe563ad77e7a95fbee6ff59ebf3e61ab-13 new file mode 100644 index 0000000000000000000000000000000000000000..ecd0320fc6c4619a9705f58e75c34e3817de2cc0 GIT binary patch literal 46 gcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^d93(>?0Qg!67ytkO literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/21.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/21.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..0701d3d648e96b370bc62da1aaa0ab9d125cb2ff GIT binary patch literal 48 zcmZ>Y$}l!`j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DGrbKh literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/22.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/22.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..25578e2dbe9903b2544519f846e4e149f2b37ca1 GIT binary patch literal 48 zcmZ>Y$}ll>j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DGwKa4 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2201e32d052c15874f0323a09c330f3666029a72-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2201e32d052c15874f0323a09c330f3666029a72-1 new file mode 100644 index 0000000000000000000000000000000000000000..c4353fe81683aeb72f1cc8ec101a86d5391353a4 GIT binary patch literal 1473 zcmV;y1wQ&hT4*^jL0KkKS(G)X0|3c~|A2H5p~Qdp|M>s^|LQ;g|L|hUKKsA`6YlAD zc`I*Yq>cap03SdA000000Pe>@o%ZE+&|9wQdZK`RbC%m4%MG;|_Z&S3uFrNr00Yvf zPytkx3ZMko01IFM1MbBD=%4@+NF%Ic3;?8kv>bPxFFi;`@6aWAeqKW_jHKKq5loTBl0MJoVC{aKaD`r6|I>_9? zM-U21B2p*-P%g%l=nSX;C@ZZ12HN{%DIf&^prud%0HT0U0)POJ0HHt>000F508@wo zs-*y+P(lKPiUD5i0011Q3ZqJiAt#e00)2o9%b#m03!C@cI|cX z^ewwOgP}kG00jU5PyhfF00000KIUddWzUy*zYj(XS zo#2k@&yew7MfZI4zGbj5%K6?ETfXnR=e?&s%=R5=*Q$L!xO%M*Oy+NSp7(1bO*@-! zeNVjg!`Ha__?%a};t#KV*Ig4ehLd#HZe5%WSj~3RyPd!h+Oykk-8A;c00%OJ&5)RG ztzZTyDyoWr1qzf8ce-*`#_b&`~O?by^sztE~1O3vuo5Rh`LsGW40~*GGGf zPkZB|RQR@KQ$s-R(QfYVxO>gByB(iRb4rwhNl&iel{AKY-g)hu*{4F9(z?@gEw^V} z*k>>R001Z(;r99-PrD}1S6tohk5Or+g!>WWuW9l?;k?@!?(**4fMbO2WQ3SjEY|`r1R~S-8op4hizH5 zZJVK|2rd%0M72}MN_ly03Lu262{qixapuq!IDEzDy6p7ni5vE zvAVms$OAwqHg4?L0noVH4FKD=8s*Sk7t5?i9^UP%z3b8Dbba^F2hWYOH{EvTcYP0f zCNbRm>+Apk0000!$C&xIS@S)4>^Ugzy;~{NwKG>SO?}u?-^ zYoHD4qPvZGO1tfYRDJWhUER|;dA-{3yPL<#rBr|b$7zpvoxMJNA5aw?>zhca6KxH7 zeeN~f01B<{6~4WFd+yyc)y>^ERz2)Q8e0majit0`DFGT1=yEP;Q&{Xck1STz7;T2u z0ZJMhd8O}XJH_ForBPGT#_v6DbiBKCLidMCgSG(i-E2rb0N1CX>GlKR@1~Ri3i+WN znwxeQcJ1!PQ?Wj}`p3q7?Fqc-TjRM6 zn5%=UyEmMpdvxS-dE2MDX7*z@x!-N?yRB{&w(fn`nmcoMZEyep9RL&n4u-0(==*Bv zZvlY_pIQgEv|#k_Ub-!sYV3F3-F){w(DUYj<|MOax&;6R<#2euGN*3La1^9T%+}iO z?G7oq_keq?2iqmq54P*O0YFdy2J_0R%t|Fb=eN7P+2?uNw>fR*#qV`Zb#{ty4$bDO zS@+O4zTdH@9gy?Rx_gJm2Ww{7>!eaL;wXwQ-&hMT*9zW5v9^Y43I zxLc>YyAMoK?X2w8RUHV{rRmw7cYOdf3(p&a*_F1J(>865RH?AlX}fjRBv5yydcX(UP7O~$LJ<%^fDqFm83fa6nWPN{i1w$Y bJxnyhAqYYtOp_=ur;|~jGynmh0006^ON7Ej literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/226780b32ba8f87ec614fdb376aa0884011c4ca9-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/226780b32ba8f87ec614fdb376aa0884011c4ca9-17 new file mode 100644 index 0000000000000000000000000000000000000000..747cfa5225ae3e20fdc337a7414292ff69eff5d4 GIT binary patch literal 32 mcmZQk@|DO-Y&o%a|NB@5Mh0F628R6qK!TBhiQ#{Q{C@zSmkDD4 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/22897c61698649d7570de91613afdc19b66e6965-20 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/22897c61698649d7570de91613afdc19b66e6965-20 new file mode 100644 index 0000000000000000000000000000000000000000..ea2cb769eb165150857c610aab5410ff18651319 GIT binary patch literal 71 zcmZQk@|DO-Y&o%a|NB@5Mh0O9h6V`+ULXlVEg%ZSkOdM-AYqV9&Hw)(SqKGYOXL9n DeYF#P literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/23.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/23.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..bc8b6be6a45bc9948999c68a8ec9070ce440a596 GIT binary patch literal 48 zcmZ>Y$}lx_j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DG#3po literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/234cc427d9be32470f3c2e11a6bc16567f558e55-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/234cc427d9be32470f3c2e11a6bc16567f558e55-22 new file mode 100644 index 0000000000000000000000000000000000000000..c69e874b3b8a83312db1400176c83fb7889b297a GIT binary patch literal 37 kcmZQk@|Ey)U|?|4^5tPrXB1*!V2C@NY}6vb%Y$}lr@j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DG(-(B literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2486a84bf0f161f45b050d9c19ea9e35f5def864-8 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2486a84bf0f161f45b050d9c19ea9e35f5def864-8 new file mode 100644 index 0000000000000000000000000000000000000000..9ed0d0e084d5b31b353699faaa49f01fedd1ec0a GIT binary patch literal 25 ecmZQk@|DO-Y&o%a|NB@5Mg}GZ1_ltH!4Uvv*#{l~ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/25.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/25.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..869a668b58382ce1b5c9d869d038e9b47a3a2840 GIT binary patch literal 48 zcmZ>Y$}l%{j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DG;s|v literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/25252b16cd4afa8ef86122448688c7095684c86b-12 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/25252b16cd4afa8ef86122448688c7095684c86b-12 new file mode 100644 index 0000000000000000000000000000000000000000..b5a986b2526123e39a24241fc9c34fda8adb9e40 GIT binary patch literal 25 bcmZQk@|B28Y&o&_G6MqxBM>t%uz-aCP=5tz literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/26.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/26.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..2d7678a7acfdaf4e7ec6cf9de1e87cc3b26dcd70 GIT binary patch literal 48 zcmZ>Y%CInWj8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DG@cDI literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/263fb3d738b862ec4050e5a9fbabfbd99cb0d9a5-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/263fb3d738b862ec4050e5a9fbabfbd99cb0d9a5-16 new file mode 100644 index 0000000000000000000000000000000000000000..72e921a6686e4a2eda634e52f94048f906a51078 GIT binary patch literal 32 lcmZQk@|EyTY&pTe$nfhwBLgo314I3P5J+cdWcdG|0RXLx408Yg literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/27.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/27.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..409a9a2d97d6f314b6e6c898648fa5a1a57ef4d0 GIT binary patch literal 48 zcmZ>Y%CIzaj8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DG|LS$ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/276580343a14eec04143e89a778dae3e14df472c-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/276580343a14eec04143e89a778dae3e14df472c-17 new file mode 100644 index 0000000000000000000000000000000000000000..ce6896874300e2ea4a8df1a3bbbbe3415fa37ea3 GIT binary patch literal 52 qcmZQk@|Ey)U|?|4^5tPrXJlhwU&j9?kU#SB{{n1Qk>VvhmV1qnj{ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/27fb5dc4016dc640e55a60719a222c38c604fa6b-2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/27fb5dc4016dc640e55a60719a222c38c604fa6b-2 new file mode 100644 index 0000000000000000000000000000000000000000..c742bacacc44aee87823184e0084d75395aa9b02 GIT binary patch literal 14 VcmZ>Y%CHbGaz1i=6R literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/28.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/28.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..112aea2e8c0e8b29c3121f2be1ec2a17b9e35f86 GIT binary patch literal 157 zcmV;O0Al|_T4*sbL0KkKSzC~1Q~&@LAAmpyA|NjWQ~*Ek+z=oDl|xkVKxoL&9*`cO zB}{~RDWlZ%n4Y1K^$n*SV}F#i(Y8Y9`#e_0kn2jrQ&<)@Eixu}cN3W|eT2obV{S=$ zAzI3A5HnhFs6ue@OfL1nJQJm4Zx?=H_0Wa}WDBNGGL(qUj^!B))kRsU*Y%CHbGad{ivR!s literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2b39aa66ecfac58e61185c9664a968233931496a-9 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2b39aa66ecfac58e61185c9664a968233931496a-9 new file mode 100644 index 00000000..27cfb62c --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2b39aa66ecfac58e61185c9664a968233931496a-9 @@ -0,0 +1 @@ +"MM@"©½¿ïp+[Ô \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2c2a5947341d76797a7e2299f39d01e3aebb2eb8-19 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2c2a5947341d76797a7e2299f39d01e3aebb2eb8-19 new file mode 100644 index 0000000000000000000000000000000000000000..e94d8da56642f42dec7b8e176ad022612050e10e GIT binary patch literal 70 ocmZQk@|Ey)U|?|4^5tPrXJlhwU&j9?jJ5kr+VY>{9F0ENyAp8x;= literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2cc2308b75a2e8f7eafcf69370767e5fce314892-13 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2cc2308b75a2e8f7eafcf69370767e5fce314892-13 new file mode 100644 index 0000000000000000000000000000000000000000..202625196ed4cd0cd6601c52e0e0557ad943d6d3 GIT binary patch literal 32 mcmZQk@|DO-Y&o%a|NB@5Mh0F628RFt|2Hr&NaQgA*%AP=Y$}lo?j8qGb6zG4f!@$5^{oTi@A>%^Ir@q-C3PxY|a9gTBdgrm6ONdGEPig}I Dnb8ta literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2de93224b5f0db491ced1ec491a9f41d71820671-11 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2de93224b5f0db491ced1ec491a9f41d71820671-11 new file mode 100644 index 0000000000000000000000000000000000000000..71c5a14eba7cd3ebbcb82906e86c2f2bd2274ede GIT binary patch literal 23 ecmZQk@|Ey)P+GZn|N8>%=qn5i3=K|Nz7hai6bEVm literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2e8487cf61feda70c0d74f12bfb5b692b684f82a-9 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2e8487cf61feda70c0d74f12bfb5b692b684f82a-9 new file mode 100644 index 0000000000000000000000000000000000000000..f1c5b7a4fefd4ada12ca7689806d3ebe6ed44dae GIT binary patch literal 25 dcmZQk@|B28Y&o&_G6MqxBLfqVl*j|}839z823Y_A literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2f0ee9cf4bb951a37efc6460d5709442bc3de54e-6 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2f0ee9cf4bb951a37efc6460d5709442bc3de54e-6 new file mode 100644 index 0000000000000000000000000000000000000000..49c3db23b6d6173fb72a79e88637ff17a29379bb GIT binary patch literal 23 ccmZQk@|DO-Y&o%a|NB@5Mg|bbNX%0J09l;|#{d8T literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2f1ba7fe1cd90a4023706a2ea9c7c9dca8128119-30 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/2f1ba7fe1cd90a4023706a2ea9c7c9dca8128119-30 new file mode 100644 index 0000000000000000000000000000000000000000..3d62f949ed5e5b9647961e404b8e3c9ab7fb29e3 GIT binary patch literal 167 hcmZQk@|Ey#P+GZn|N8=^=qn6Bz%r&j9?jJ5yK|S$Y$6A0L}>w3IG5A literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..197b557835ae0dacf12146abcfdea1713aa313aa GIT binary patch literal 42 ycmZ>Y$}l!`j8qGbWG}V6&cMLH$Y9@~z+lM3aO60|QVF$Okgy69EUm B3$XwI literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/31.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/31.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..22bbfb22c38d277892dc0bd8d87aee40bcfe6533 GIT binary patch literal 157 zcmV;O0Al|_T4*#eL0KkKSzC~1Q~&@LAAmpyA|NjWQ~*Ek+z=oDl|xkVKxoL&9*`cO zB}{~RDWlZ%n4Y1K^$n*SV}F#i(Y8Y9`#e_0kn2jrQ&<)@Eixu}cN3W|eT2obV{S=$ zAzI3A5HnhFs6ue@OfL1nJQJm4Zx?=H_0Wa}WDBNGGL(qUj^!B))kRsU*iL0KkKSzC~1Q~&@LAAmpyA|NjWQ~*Ek+z=oDl|xkVKxoL&9*`cO zB}{~RDWlZ%n4Y1K^$n*SV}F#i(Y8Y9`#e_0kn2jrQ&<)@Eixu}cN3W|eT2obV{S=$ zAzI3A5HnhFs6ue@OfL1nJQJm4Zx?=H_0Wa}WDBNGGL(qUj^!B))kRsU*Y$}lu^j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkg$`6D9 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3771c6e8ea0f20350dae0180a9b14e36b8aef244-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3771c6e8ea0f20350dae0180a9b14e36b8aef244-22 new file mode 100644 index 0000000000000000000000000000000000000000..0d255bfa1e0cf635c76827fc44bafdc32e6a7823 GIT binary patch literal 71 scmZQk@|DO-Y&o%a|NB@5Mh0O9h6V`+ULXlVEg%ZSkOdMgU|}4R06eD+pa1{> literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/37ee7fab504f2d2039753d73dd0290c884bd57bf-8 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/37ee7fab504f2d2039753d73dd0290c884bd57bf-8 new file mode 100644 index 0000000000000000000000000000000000000000..901a42d396b5128898f62b06b22b2c70753ba00e GIT binary patch literal 25 VcmZS3@|9o!0v04%!dHTY0RS7;0yh8v literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/38.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/38.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..30ca1c20ad7c03598b3103c2dbf1976e55f3a3f1 GIT binary patch literal 58 zcmZ>Y$}lo?j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkh0S|=$ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/39.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/39.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..16298f604e58d565c56b9217a7432c381fa4208b GIT binary patch literal 58 zcmZ>Y$}l!`j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkhI1h#Z literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/396101a712463bb336a18f4096fc3eb5923600c1-10 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/396101a712463bb336a18f4096fc3eb5923600c1-10 new file mode 100644 index 0000000000000000000000000000000000000000..7274cb5ed0009231db71fae8344f5c297e5eef84 GIT binary patch literal 74 WcmZ>Y%CHbGa%=qn5i3=Oz20R7MjnE(I) literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/39ccf446395ef707cf92a04b5508deda399372c2-15 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/39ccf446395ef707cf92a04b5508deda399372c2-15 new file mode 100644 index 0000000000000000000000000000000000000000..974c4236d8fd0df9d712bb0ee8d611ebe05ebaea GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$ngI^0|3Y84P*cS literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3de3c5c394a3cf05620bb80871a1f10e9e36f25b-8 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3de3c5c394a3cf05620bb80871a1f10e9e36f25b-8 new file mode 100644 index 0000000000000000000000000000000000000000..667f2f2a71501f2b69634fa6d3faf406cde73dda GIT binary patch literal 25 ecmZQk@|DO-Y&o%a|NB@5Mg}$ph6a!bgChWFvIi^x literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3dee65f1cf51dfe2e5be498150ce22d2ac5a07fd-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3dee65f1cf51dfe2e5be498150ce22d2ac5a07fd-1 new file mode 100644 index 0000000000000000000000000000000000000000..8600d6d505cd27825bbe8a69b069f3b7fdc17e16 GIT binary patch literal 22 dcmZ>Y$}ll>j8qGbObcOP5R-3kU{_Mm2LM3Y1pNR2 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3e34341fb51769fd9d948bdd20c011e335b145f4-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3e34341fb51769fd9d948bdd20c011e335b145f4-1 new file mode 100644 index 0000000000000000000000000000000000000000..194057f9beefcd15205479ab1c65f3d361d07cf6 GIT binary patch literal 64 zcmZ>Y$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x RvzUFH8ZM-K>YE*+008=i5OM$j literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3ee211efb3d5d8058cd9a8c59e40c8d0f7a3df53-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/3ee211efb3d5d8058cd9a8c59e40c8d0f7a3df53-1 new file mode 100644 index 0000000000000000000000000000000000000000..bb86190c205ae17643f402d0d6983e2f9b6ff02d GIT binary patch literal 51 zcmZ>Y$}lu^j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lU!CAaqss*m1z HEaw6MO5F`n literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..679a04b7741552f16f2107271c43c7d5cf2d24cc GIT binary patch literal 42 ycmZ>Y$}ll>j8qGbWG}V6&cMLH$Y9@~z+lM3aO6Y$}ll>j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkhZx4q6 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/405726718b3f54a0cfae1666f06d3cc1ee747104-14 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/405726718b3f54a0cfae1666f06d3cc1ee747104-14 new file mode 100644 index 0000000000000000000000000000000000000000..63f58da0e6967f29514d765df519a8db4f388194 GIT binary patch literal 27 ccmZQk@|Ey#P+GZn|N8=^=qn5i3=J?00Ch$OivR!s literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/407188676d45d6f9dd5f3c84e7df0e763c7cca57-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/407188676d45d6f9dd5f3c84e7df0e763c7cca57-22 new file mode 100644 index 0000000000000000000000000000000000000000..76680dd54f939e3ed45a4bb7932d17663e6dfbb5 GIT binary patch literal 82 zcmZQk@|DO-Y&o%a|NB@5Mh0F628Npd{~H(>B=VRT6ih(^4L~+Rg)C4&2_y`XfhdJi GP;CJBSQ)MW literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/408ac1a4a83e082e848c208eed903930d81e81b6-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/408ac1a4a83e082e848c208eed903930d81e81b6-17 new file mode 100644 index 0000000000000000000000000000000000000000..934e10f0702b38f38b1066f17363509c7ffbec7a GIT binary patch literal 67 zcmZQk@|Ey)U|?|4^5tPrXVhR|Xkf@MOD!@~F*GnTGBz+WF*7nXG&M6dF)%SQHZwLf UGqW(TG_Wu-FlGRP*KX>e0HSvd2><{9 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/41.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/41.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..d63608f3990a460aacc4e5e5f072b726fb26b767 GIT binary patch literal 58 zcmZ>Y$}lx_j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkhrVoe! literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/413e39442f005279560ddad02bbdd1a05c9f0eaf-4 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/413e39442f005279560ddad02bbdd1a05c9f0eaf-4 new file mode 100644 index 00000000..8e4e3529 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/413e39442f005279560ddad02bbdd1a05c9f0eaf-4 @@ -0,0 +1 @@ +"Mna„Ƚ¿ï½¿ï½ \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/41b7eaf8892043eccf381ccbc46ab024eb9c503c-4 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/41b7eaf8892043eccf381ccbc46ab024eb9c503c-4 new file mode 100644 index 0000000000000000000000000000000000000000..6b428d19e1d8c2a3ed5259538555cd48520856ef GIT binary patch literal 9 QcmZS4@|7?VU|?VX00nFS*Z=?k literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/42.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/42.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..f0f25c7fd78aae73103e7cc63a701c3c11e818ee GIT binary patch literal 58 zcmZ>Y$}lr@j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkh-4BTX literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4208b7fe7ac3a530c159a1c8fd09dd3078b5650f-15 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4208b7fe7ac3a530c159a1c8fd09dd3078b5650f-15 new file mode 100644 index 0000000000000000000000000000000000000000..c8c2c6aa62426046320864a69c8868615dac6e1f GIT binary patch literal 35 ccmZQk@|Ey#P+GZn|N8=^=qn5i3=QZQ0JNS6ivR!s literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/421bd1daa317c5d67fa21879de29d062c342294b-5 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/421bd1daa317c5d67fa21879de29d062c342294b-5 new file mode 100644 index 0000000000000000000000000000000000000000..6a19eb3d8ac56d593b679b31cfab290dbe9f960d GIT binary patch literal 19 ZcmZQk@|DO-Y&o%a|NB@5Mg}0Y7XU}<2$%o> literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/42b056f9dac9cc658c80092e490b3dbcd436e3f8-15 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/42b056f9dac9cc658c80092e490b3dbcd436e3f8-15 new file mode 100644 index 0000000000000000000000000000000000000000..2b38240671da6d27fa7c9648dfe5085d580c4684 GIT binary patch literal 32 mcmZQk@|DO-Y&o%a|NB@5Mh0F628IeCW?+!WV`5NXl>h*diw3#? literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/43.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/43.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..f68d3a73a41dcc6ca6420448a0efc858b52bc8df GIT binary patch literal 58 zcmZ>Y$}l%{j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggki6c363 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/432c09281c46537c98864bc7d601780562b68410-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/432c09281c46537c98864bc7d601780562b68410-1 new file mode 100644 index 0000000000000000000000000000000000000000..f462929668c6773d243d7ecbe686edd62ef035e2 GIT binary patch literal 22 dcmZ>Y$}lo?j8qGbYz<~$V7L>*z_5UU0RTmB1%vY%CInWj8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkiOAm_x literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/446dc91ff0ddc34c3b02f741e3f6f079a4dfcae8-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/446dc91ff0ddc34c3b02f741e3f6f079a4dfcae8-17 new file mode 100644 index 0000000000000000000000000000000000000000..2ae4b5acf927f24991600909fda9df2bd6913ed0 GIT binary patch literal 81 WcmZ?L@|9o!0w*-ul0-gCKLY?@_XrRG literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/45.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/45.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..855e812da10291f9a0b563932857d0324099879c GIT binary patch literal 58 zcmZ>Y%CIzaj8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkif)9)U literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/451831159c1afb87077066147630b4b6caeb54c3-11 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/451831159c1afb87077066147630b4b6caeb54c3-11 new file mode 100644 index 0000000000000000000000000000000000000000..bfd673d45aa96bdd9ee338aa4dab59c6b96156e2 GIT binary patch literal 25 ScmZ?L@|9o!0w-h|!~p;(&;vyP literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/46.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/46.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..a11978d36014479974c9b2ec30e1dc1b82b8d5e2 GIT binary patch literal 82 zcmZ>Y$}lu^j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Bg4w_5c6? literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/47.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/47.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..78995878879f418a2ff19c29f808255ee361aacf GIT binary patch literal 82 zcmZ>Y$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Bi;q_W%F@ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/48.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/48.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..d7b0df5d367f6506b92c91de2859a23911995b40 GIT binary patch literal 82 zcmZ>Y$}l!`j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Bltk_y7O^ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/49.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/49.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..0e16e69c13346cdfcbbd4306e763a01ab43af9f0 GIT binary patch literal 82 zcmZ>Y$}ll>j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Boce`2YX_ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/49861b3d9bca3e2857d806aaecaac09af4bff1dd-2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/49861b3d9bca3e2857d806aaecaac09af4bff1dd-2 new file mode 100644 index 0000000000000000000000000000000000000000..0648054b9d0bb5320f83f8cfbfc79ee18ca0b232 GIT binary patch literal 35 rcmZ>Y$}lu^j8qGbRA4aVVK{Oq^<3Y%CHbGa}ga9Lxe< literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4b0ab2fc1fdfc56066c5c1f2751b292f4ddc557e-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4b0ab2fc1fdfc56066c5c1f2751b292f4ddc557e-16 new file mode 100644 index 0000000000000000000000000000000000000000..51ffa5a1efd59285a4f3cf5df05f47a3369140ec GIT binary patch literal 71 vcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@Y6#UMhMs_O3B=(cCY$}lo?j8qGb6zG4f!@$5^{k_4dA>%^Ir@q-C3PxY|a9gTBdgrm6ONdGEPig}I DpMesE literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4bd00d26b893ce064dad6e771f30541b541d43b9-18 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4bd00d26b893ce064dad6e771f30541b541d43b9-18 new file mode 100644 index 0000000000000000000000000000000000000000..244f762135fc9bf5123f4dc774beda16f78d9593 GIT binary patch literal 114 zcmZQk@|B28lsGS_b(w*Iff0xqSinLpC-%ZcphCo`%1Z=l-2XlnXcQ9zLxU0nFOaPH QFA-UH-$u7RV}GIq0A!*YGynhq literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4cde5adc216a29fff2ec39e23ccc6fca80cd4a15-21 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4cde5adc216a29fff2ec39e23ccc6fca80cd4a15-21 new file mode 100644 index 0000000000000000000000000000000000000000..9a3f3a8f744392c70e32a58cc5caa85c4ab87872 GIT binary patch literal 83 ccmZQk@|Ey#P+GZn|N8=^=qn5i3=NcG0NBh9ivR!s literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4d1b64babe1f045b8374f4d74949622591546eb5-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/4d1b64babe1f045b8374f4d74949622591546eb5-17 new file mode 100644 index 0000000000000000000000000000000000000000..983d0a4f2365a137bdc720b79c121899402f2796 GIT binary patch literal 56 zcmZQk@|Ey)U|?|4^5tPrXB1#yXkh3qOD!@~F*GnTF$Q8YsF;zdp{bdviGhicv6-V6mBLY%CHbGaY$}lx_j8qGbWG}V6&cMLH$Y9@~z+lM3aO6Y$}lx_j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0BrLY`Tzg` literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/50a87eb0c097a7ebf7f1bf3be2c6a7dbe6b6c5c3-23 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/50a87eb0c097a7ebf7f1bf3be2c6a7dbe6b6c5c3-23 new file mode 100644 index 0000000000000000000000000000000000000000..e6a919b262580e935678fd90159ab65434172abe GIT binary patch literal 105 zcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lWRULaWm#6Wf)6N7>&NT8txSsjLeEKr3#NF7+_ Q|NjOC2D2J41tui&0C9mGo&W#< literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/50e3ac1126c605158726db6f2cca3120f99b8e73-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/50e3ac1126c605158726db6f2cca3120f99b8e73-22 new file mode 100644 index 0000000000000000000000000000000000000000..5ad9706b72da7752f765a964e2aac568f88d9411 GIT binary patch literal 105 zcmZQk@|DO-Y&o%a|NB@5Mh0F628Npd{~H>BG!ugYBZDvlLxY5&p{0?5rICfDsi}cE eP=*1duAv55qbyKB2_y`b0h$0(0H(l%L>>UBf*nNw literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/51.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/51.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..b965c7a646f1fa109fa59d67bf21668b0f70ac4c GIT binary patch literal 82 zcmZ>Y$}lr@j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Bu4S`v3p{ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/512ed5fb4e92818b75bd7633f58d6ca5340ffd94-27 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/512ed5fb4e92818b75bd7633f58d6ca5340ffd94-27 new file mode 100644 index 0000000000000000000000000000000000000000..b2dfe276d2c9e652d54bf5c586ec5a9d162bfd1b GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`zV85kNQ3=J)f3_!@#)W965 zf&rwip$4WAsEY%CHbGaY$}l%{j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Bw;M`~Uy| literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/53.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/53.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..2ab0a6de2512a19021319339370d361a190bb63f GIT binary patch literal 82 zcmZ>Y%CInWj8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0BztG{Qv*} literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/54.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/54.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..6004de354485e1710d01b2429c4db9a597e4d835 GIT binary patch literal 82 zcmZ>Y%CIzaj8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0B$cA{r~^~ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5431cabbc58d8dc143ece079de40300c1ce6e101-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5431cabbc58d8dc143ece079de40300c1ce6e101-1 new file mode 100644 index 0000000000000000000000000000000000000000..4061e90f86018fa5953c22b91b481bf3e4647abe GIT binary patch literal 144 zcmV;B0B`?7T4*#eL0KkKSzC~1Q~&@LAAmpyA|NjWQ~*Ek+z=oDl~nOSXvokWkRG5V zdMTsS^q8KZko66x9F(-twnFIpJXXe#>q^5@SQa)dGA4L;6PYf3gvGLBZb^C}TFPz^ yGg@(|LU8d+F7?1X6QyKt7k**&(1r$NPn3wxj^!B))kRsU*Y$}lu^j8qGbRA4YE=Y$}kZxaB=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKUFpMm1pS|9`N_Oh8={VDoFhCV&Y}g{f%%IGWcZ#XfDFpy!tOnr# literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/59b254c3565c9eed2bc93385b821da897afcbb15-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/59b254c3565c9eed2bc93385b821da897afcbb15-1 new file mode 100644 index 0000000000000000000000000000000000000000..a6cbaf736a7253a27ec10d0aa24f3ee5611619d3 GIT binary patch literal 44 zcmZ>Y$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)(SgCCfkTKvfT2-9fI;Da0)rs{3}gzD literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5a962e3d6a128983afe9ea78a28cce0f40a790c0-14 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5a962e3d6a128983afe9ea78a28cce0f40a790c0-14 new file mode 100644 index 0000000000000000000000000000000000000000..014f6a6f30af0debdd97a780bfb590e6e6181838 GIT binary patch literal 42 jcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@Y6#Xv#;$|48p literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5af52ef91b6f717ffdd805585e24806407e9621b-14 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5af52ef91b6f717ffdd805585e24806407e9621b-14 new file mode 100644 index 0000000000000000000000000000000000000000..8695d399b324f101638ad360c39949a7f582aa2a GIT binary patch literal 114 XcmZ>Y%CHbGa%=qn5i3=JUcq?IM%1OR}02uT0{ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5bd895c23369df9505dd99ffcd035dc5e897264b-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5bd895c23369df9505dd99ffcd035dc5e897264b-1 new file mode 100644 index 0000000000000000000000000000000000000000..affcc488964e3a17c555604546dd3bfe94d8d2d9 GIT binary patch literal 49 zcmZ>Y$}ll>j8qGbjGmAd!oVOV-{8Qmq@d3d!eIaYj(`G#bI3=Bj1w2+u6&udaKcyK FY$}l!`j8qGbjGmAd!oVQ*e*az|QU&63^Rt2ERA-*6u8}Km#wz;#n520K00b%* AQvd(} literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5c4f347c3567baf700dfccf49a91192c83b89da2-8 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5c4f347c3567baf700dfccf49a91192c83b89da2-8 new file mode 100644 index 00000000..6282cf69 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5c4f347c3567baf700dfccf49a91192c83b89da2-8 @@ -0,0 +1 @@ +"MM@"©½¿ïp+[ \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5dd8001f8a87c24f866074c36b6b80f42b298ff0-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5dd8001f8a87c24f866074c36b6b80f42b298ff0-1 new file mode 100644 index 0000000000000000000000000000000000000000..39ef02cbfe8c969084e4200339e01042b5782d19 GIT binary patch literal 38 tcmZ>Y%CInWj8qGb>{?*|jDdlbAw`6Nfnf)O0)rCQLzUoGPL5T~{{Y4_3PS(@ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5ddf63d61aa38da1d409e37b301e0fe5a207a051-27 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5ddf63d61aa38da1d409e37b301e0fe5a207a051-27 new file mode 100644 index 0000000000000000000000000000000000000000..ea34cb440c9d3528e08033b6177f44ebd54201be GIT binary patch literal 156 ecmZQk@|Ey#P+GZn|N8=^=qn6Bz%odLRssM#7BOuA literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5e54c67050ee8583c7453ff13d6eec15b2255288-20 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5e54c67050ee8583c7453ff13d6eec15b2255288-20 new file mode 100644 index 0000000000000000000000000000000000000000..0a87f43f7dc7ded006b3b5e0945ade4bd4fb5845 GIT binary patch literal 83 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=NcG0NmCNnE(I) literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5fbebd9edd144c4b9869ed4ab40c7cc3c46a4a8f-4 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5fbebd9edd144c4b9869ed4ab40c7cc3c46a4a8f-4 new file mode 100644 index 00000000..bf8e930d --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/5fbebd9edd144c4b9869ed4ab40c7cc3c46a4a8f-4 @@ -0,0 +1 @@ +"M@c¯ \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/6.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/6.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..0cfbc601e365f93232364b895863098d7a65bf63 GIT binary patch literal 42 ycmZ>Y$}lr@j8qGbWG}V6&cMLH$Y9@~z+lM3aO69u6S@ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/6046b14dd1f6925bcfe470a8484353f525db6a9c-19 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/6046b14dd1f6925bcfe470a8484353f525db6a9c-19 new file mode 100644 index 0000000000000000000000000000000000000000..1cd81c49e0b0da9db531291694f168544beb4c34 GIT binary patch literal 57 fcmZQk@|Ey#P+GZn|N8=^=qn6Bz(P<6s6_$*62=nb literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/608a9993a51ec7bf252ac76b163def5f7002d2e4-4 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/608a9993a51ec7bf252ac76b163def5f7002d2e4-4 new file mode 100644 index 00000000..79174b20 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/608a9993a51ec7bf252ac76b163def5f7002d2e4-4 @@ -0,0 +1 @@ +"M@T \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/610d8dc3cf4012e4e2d070988b0720285a4c361e-7 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/610d8dc3cf4012e4e2d070988b0720285a4c361e-7 new file mode 100644 index 0000000000000000000000000000000000000000..20c9dd137d1deb6d2a0cf22c2712cd86361c57e5 GIT binary patch literal 21 ccmZQk@|DO-Y&o%a|NB@5Mg}GZh6V;l08GmUGXMYp literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/61b196987682fb64ef9c4ff37532bf9b2ac201bc-14 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/61b196987682fb64ef9c4ff37532bf9b2ac201bc-14 new file mode 100644 index 0000000000000000000000000000000000000000..d9fd8979ef91e7678a72d9e5eed974dbd34e5346 GIT binary patch literal 30 lcmZQk@|Ey)U|?|4^5tPrXJlhwU&Y}k?__V{qN8~{!f2I&9* literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/626f8b6efa3ea0f254789fe6cf52f6e52538f357-25 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/626f8b6efa3ea0f254789fe6cf52f6e52538f357-25 new file mode 100644 index 0000000000000000000000000000000000000000..6b1a5b5844ac62b4a9fc4c350a76770f1c18031e GIT binary patch literal 219 zcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lWRULaWm#6Wf)6N7>&NT8txSsjLeEKr3#NF7+_ S|NjOC2BR7<_5c3>nG67ZGB@7< literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/6277f2e0a6df2ac61660ee1965c690b87c26b556-7 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/6277f2e0a6df2ac61660ee1965c690b87c26b556-7 new file mode 100644 index 0000000000000000000000000000000000000000..a3979ce0f5fcfeb5e57fe29c3ea562d2c34e65db GIT binary patch literal 21 ccmZQk@|DO-Y&o%a|NB@5Mg}GZ28Iug08J|fqW}N^ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/62c738f00c488f493989b2037d9cf1781f0bbd40-11 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/62c738f00c488f493989b2037d9cf1781f0bbd40-11 new file mode 100644 index 0000000000000000000000000000000000000000..f965e8c674b218d6516f5ff33a6f46637087e39d GIT binary patch literal 38 gcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^dWD+a@0K1Y0jsO4v literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/631ffa88df9713a124b3ba6c704c0c75727af2ff-6 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/631ffa88df9713a124b3ba6c704c0c75727af2ff-6 new file mode 100644 index 0000000000000000000000000000000000000000..b8f1f4a4d8a6408ee66904e79899ff314ed057b2 GIT binary patch literal 16 RcmZ?L@|9o!0w)OV1OO4z0p$Py literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/635d5de257a1910a7fd0db2e567edfa348e47270-11 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/635d5de257a1910a7fd0db2e567edfa348e47270-11 new file mode 100644 index 0000000000000000000000000000000000000000..32aa66d51fa27ed4d950f8a7adac40d1aaa9e029 GIT binary patch literal 38 icmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^dWD+RQkOu&~Vh8pB literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/64c500b5addcbf8c673188a1477e4159851ae04f-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/64c500b5addcbf8c673188a1477e4159851ae04f-1 new file mode 100644 index 0000000000000000000000000000000000000000..6c6541ba79787771828977d31a017d6585d7ff42 GIT binary patch literal 124 zcmV-?0E7QRT4*;hL0KkKSzC~1Q~&@LAAmpyA|NjWQ~*Ek+z=oDl|xkVKxoL&9*`cO zB}{~RDWlZ%n4Y1K^$n*SV}F#i(Y8Y9`#e^V>q^5@SQa)dGA4L;6PYf3gvGLBZb^C} eTFPz^Gg@(|LU8d+F7?1X6QyKt7k**&(1r$k<1+sM literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/660387064a3cf4cb81046989929abe1b4fbfc815-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/660387064a3cf4cb81046989929abe1b4fbfc815-17 new file mode 100644 index 0000000000000000000000000000000000000000..1bf5f59afb271f1bcd67fbf5bc329a415862e7f9 GIT binary patch literal 51 ccmZQk@|Ey#P+GZn|N8=^=qn5i3=M=Z083p8ivR!s literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/66068a7e7bdfd1038a84aeb3dec6e3cb4d17ad57-2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/66068a7e7bdfd1038a84aeb3dec6e3cb4d17ad57-2 new file mode 100644 index 0000000000000000000000000000000000000000..1a2cd7c6d79c283c95fbabe626d0a03b09827cc1 GIT binary patch literal 16 VcmZ>Y%CHbGa&Y=~gBNH7D%Qp6qu0F0IgmH+?% literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/6bc138796e9b80572a6cb1b4a7ba30c97c22359d-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/6bc138796e9b80572a6cb1b4a7ba30c97c22359d-1 new file mode 100644 index 0000000000000000000000000000000000000000..e1fdc112331bc4a7efc663e09681430342ec387d GIT binary patch literal 46636 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 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7102c7f297296821114661e00e5bf54d0891d105-21 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7102c7f297296821114661e00e5bf54d0891d105-21 new file mode 100644 index 0000000000000000000000000000000000000000..5aafd5aaf2007937d5767840462fa75d5ac898d3 GIT binary patch literal 76 zcmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%pJ@}( literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/71a24ce771fb7f1a4163e57a478c3044ad42e62d-24 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/71a24ce771fb7f1a4163e57a478c3044ad42e62d-24 new file mode 100644 index 0000000000000000000000000000000000000000..b80bd7ce35ccaf4f7f087a3d6505b2ccc938ba60 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%<%s|1A```SmG`Qh6V literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/72f032947602f1be74f01c91165c5118121f36c7-24 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/72f032947602f1be74f01c91165c5118121f36c7-24 new file mode 100644 index 0000000000000000000000000000000000000000..f7f621e0abe3fb320f9ed6091f8a40f237b3050d GIT binary patch literal 51 wcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%Y$}lu^j8qGbWG}V6&cMLH$Y9@~z+lM3@aUb#axNi;cL0~+2}J+^ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/78981d313038119ac4f7017349e50a1cba56b382-7 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/78981d313038119ac4f7017349e50a1cba56b382-7 new file mode 100644 index 0000000000000000000000000000000000000000..74d78e493891c9eddd04b7884d66db2198a7714b GIT binary patch literal 23 ccmZQk@|DO-Y&o%a|NB@5Mg|aIjXlEz09d02pa1{> literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/78c88c4afaf5962056b1aea720509b9f6f286b91-15 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/78c88c4afaf5962056b1aea720509b9f6f286b91-15 new file mode 100644 index 0000000000000000000000000000000000000000..33bb48d49ca59524c6865f326b38abc8e0dccb62 GIT binary patch literal 64 mcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@Y6#UMi1Q~?0N0u0>% literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/79c5ac978f5aee35e123f523369aa46b1d0a995d-11 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/79c5ac978f5aee35e123f523369aa46b1d0a995d-11 new file mode 100644 index 0000000000000000000000000000000000000000..a5d3bf48c3046dd8ff77c573984a1ca76ece939c GIT binary patch literal 26 ccmZQk@|B28Y&o&_G6MqxBM>t%uz-am09F45fB*mh literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7adf4aa021efaa953268c817467959fa3c42ca42-13 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7adf4aa021efaa953268c817467959fa3c42ca42-13 new file mode 100644 index 0000000000000000000000000000000000000000..5959a250beea437da8c5b7ba9757b329d3e28d44 GIT binary patch literal 25 ccmZQk@|Ey)U|?|4^5tPrXJlhwVE7LP06Q!Q1^@s6 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7b8c99ded96973a6e8f523bc1c6ed4ef5c515aa1-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7b8c99ded96973a6e8f523bc1c6ed4ef5c515aa1-1 new file mode 100644 index 00000000..dc224e05 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7b8c99ded96973a6e8f523bc1c6ed4ef5c515aa1-1 @@ -0,0 +1 @@ +BZh \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7ba80199cbce9a2eb47da15f0c62fd1fb8fa67d9-3 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7ba80199cbce9a2eb47da15f0c62fd1fb8fa67d9-3 new file mode 100644 index 00000000..7a425b8a --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7ba80199cbce9a2eb47da15f0c62fd1fb8fa67d9-3 @@ -0,0 +1 @@ +*M4883 \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7cdc0917ad63ce7a7c98301a366c31635f0f099d-14 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7cdc0917ad63ce7a7c98301a366c31635f0f099d-14 new file mode 100644 index 0000000000000000000000000000000000000000..ce78b27630ffd1823dd1a4a10c5fc34ad90b0080 GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$nZap0RYCu4ATGr literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7ce37ad19bfe9f52eeadda03e6b8448e5bf57800-3 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7ce37ad19bfe9f52eeadda03e6b8448e5bf57800-3 new file mode 100644 index 0000000000000000000000000000000000000000..b4ceb19f0f0e7a81ccec898d3f965f0073e78c8d GIT binary patch literal 1452 zcmV;d1ylM$T4*sbL0KkKS(G)X0|3c~|A2H5p~Qdp|M>s^|LQ;g|L|hUKKsA`6YlAD zc`I*Yq>cap03SdA000000Pe>@o%ZE+&|9wQdZK`RbC%m4%MG;|_Z&S3uFrNr00Yvf zPytkx3ZMko01IFM1MbBD=%4@+NF%Ic3;?8kv>bPxFFi;`@6aWAeqKW_jHKKq5loTBl0MJoVC{aKaD`r6|I>_9? zM-U21B2p*-P%g%l=nSX;C@ZZ12HN{%DIf&^prud%0HT0U0)POJ0HHt>000F508@wo zs-*y+P(lKPiUD5i0011Q3ZqJiAt#e00)2o9%b#m03!C@cI|cX z^ewwOgP}kG00jU5PyhfF00000KIUddWzUy*zYj(XS zo#2k@&yew7MfZI4zGbj5%K6?ETfXnR=e?&s%=R5=*Q$L!xO%M*Oy+NSp7(1bO*@-! zeNVjg!`Ha__?%a};t#KV*Ig4ehLd#HZe5%WSj~3RyPd!h+Oykk-8A;c00%OJ&5)RG ztzZTyDyoWr1qzf8ce-*`#_b&`~O?by^sztE~1O3vuo5Rh`LsGW40~*GGGf zPkZB|RQR@KQ$s-R(QfYVxO>gByB(iRb4rwhNl&iel{AKY-g)hu*{4F9(z?@gEw^V} z*k>>R001Z(;r99-PrD}1S6tohk5Or+g!>WWuW9l?;k?@!?(**4fMbO2WQ3SjEY|`r1R~S-8op4hizH5 zZJVK|2rd%0M72}MN_ly03Lu262{qixapuq!IDEzDy6p7ni5vE zvAVms$OAwqHg4?L0noVH4FKD=8s*Sk7t5?i9^UP%z3b8Dbba^F2hWYOH{EvTcYP0f zCNbRm>+Apk0000!$C&xIS@S)4>^Ugzy;~{NwKG>SO?}u?-^ zYoHD4qPvZGO1tfYRDJWhUER|;dA-{3yPL<#rBr|b$7zpvoxMJNA5aw?>zhca6KxH7 zeeN~f01B<{6~4WFd+yyc)y>^ERz2)Q8e0majit0`DFGT1=yEP;Q&{Xck1STz7;T2u z0ZJMhd8O}XJH_ForBPGT#_v6DbiBKCLidMCgSG(i-E2rb0N1CX>GlKR@1~Ri3i+WN znwxeQcJ1!PQ?Wj}`p3q7?Fqc-TjRM6 zn5%=UyEmMpdvxS-dE2MDX7*z@x!-N?yRB{&w(fn`nmcoMZEyep9RL&n4u-0(==*Bv zZvlY_pIQgEv|#k_Ub-!sYV3F3-F){w(DUYj<|MOax&;6R<#2euGN*3La1^9T%+}iO z?G7oq_keq?2iqmq54P*O0YFdy2J_0R%t|Fb=eN7P+2?uNw>fR*#qV`Zb#{ty4$bDO zS@+O4zTdH@9gy?Rx_gJm2Ww{7>!eaL;wXwQ-&hMT*9zW5v9^Y43I zxLc>YyAMoK?X2w8RUHV{rRmw7cYOdf3(p&a*_F1J(>865RH?AlX}fjRBv5yydcX(UP7O~8Ktd4^K!6a_AsGbIYMG=B28i~j Gr9DhoExbMe literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7e3132012be223fd55e5e7a7fc2ea602361ed2b4-5 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7e3132012be223fd55e5e7a7fc2ea602361ed2b4-5 new file mode 100644 index 0000000000000000000000000000000000000000..010f13fc267fad0d5cb5034505c94c2a6c84acf0 GIT binary patch literal 8 NcmZS4@|9o!0ssS)0F(d# literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7e9a88118e4c41e61f5c501e6edf9a5bd2432be3-23 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7e9a88118e4c41e61f5c501e6edf9a5bd2432be3-23 new file mode 100644 index 0000000000000000000000000000000000000000..de4f0c660699169e1b2a79be0f8c16f4dfb89dec GIT binary patch literal 135 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=IQ;0d}Sp82|tP literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7f081c89cfb6344f4aac5f813da1fd15f8bab022-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7f081c89cfb6344f4aac5f813da1fd15f8bab022-1 new file mode 100644 index 0000000000000000000000000000000000000000..16410b7f524dfc8e7a3d86f278ced1f5d0bcaa4a GIT binary patch literal 26 hcmZ>Y$}lu^j8qGbEVaDOz`(%B(4fFz$Z+IPEC5|Z2MquK literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7f970f16026c689c096a19fef1a3282a13ee69dc-20 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7f970f16026c689c096a19fef1a3282a13ee69dc-20 new file mode 100644 index 0000000000000000000000000000000000000000..42795e94d20f877ebc25af82000fe420e4319766 GIT binary patch literal 65 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`y~85kOrK*B)OPy?2MQczU@ DZ6_1x literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7fa96d28faf45062eb803ea84a334b607e966f90-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/7fa96d28faf45062eb803ea84a334b607e966f90-1 new file mode 100644 index 0000000000000000000000000000000000000000..28962b057cd816316e88dec33d065eca5d1591ae GIT binary patch literal 31 mcmZ>Y$}lu^j8qGbJf6@R%)r3F!otA8(4fFz$Y7wrdY%CInWj8qGbWG}V6&cMLH$Y9@~z+lM3aO6Yz`v; literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8261f0c1799ca71c411f6d3f34069b25dac8b739-18 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8261f0c1799ca71c411f6d3f34069b25dac8b739-18 new file mode 100644 index 0000000000000000000000000000000000000000..590b0f110e19f85a6617943649ab8c7799a14da5 GIT binary patch literal 52 scmZQk@|Ey)U|?|4^5tPrXJlhwU&j9?kU#SB{{m>C!vQp6qu0N4cy!vFvP literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/82afa534de59025bf1e3358919286525ae7d3347-2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/82afa534de59025bf1e3358919286525ae7d3347-2 new file mode 100644 index 00000000..2fc2c285 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/82afa534de59025bf1e3358919286525ae7d3347-2 @@ -0,0 +1 @@ +*M \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8496965f7aa6cea3e080dbfb911a7034e6623cb7-10 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8496965f7aa6cea3e080dbfb911a7034e6623cb7-10 new file mode 100644 index 0000000000000000000000000000000000000000..8eaecb6c949eefb4fee8d669cb654866f1b6227b GIT binary patch literal 23 dcmZQk@|B28Y&o&_G6MqxBM>t%NaQ89002kW1&#m! literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/84a9bda8369d33ffe0d6f520c24331ae64e9dc88-3 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/84a9bda8369d33ffe0d6f520c24331ae64e9dc88-3 new file mode 100644 index 0000000000000000000000000000000000000000..12276fc7a588dee0efaa7cc1c0d60fa2a0bc0367 GIT binary patch literal 10 RcmZ?L@|9p4000SA0sH^} literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/86513e3435adaf7c493dd50eb5de372010185e36-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/86513e3435adaf7c493dd50eb5de372010185e36-1 new file mode 100644 index 00000000..15e4658e --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/86513e3435adaf7c493dd50eb5de372010185e36-1 @@ -0,0 +1 @@ +BZh8rE8P \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/86637b211f4fa0118ccab9ee193c66286126bb5d-20 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/86637b211f4fa0118ccab9ee193c66286126bb5d-20 new file mode 100644 index 0000000000000000000000000000000000000000..32b0426952105e4f64cb7ccfc49a75fbd176e95b GIT binary patch literal 35 ocmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%y9Y7e-N+%0DeRZdH?_b literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8695984335fa005895377a8a60000a921d7efd99-10 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8695984335fa005895377a8a60000a921d7efd99-10 new file mode 100644 index 0000000000000000000000000000000000000000..4b074d949fbbd9fa4a3e4cdb3a5cf5f3bf7cb6d8 GIT binary patch literal 25 fcmZQk@|B28Y&o&_G6MqxBLfqVl*p4ed?5e;Qs)Kp literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/86baa53eb98a9a342b0d5b79dfa5c58aa9c1b05e-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/86baa53eb98a9a342b0d5b79dfa5c58aa9c1b05e-16 new file mode 100644 index 0000000000000000000000000000000000000000..ef5234f697fda64b2d58c1fe2ef3cc7b8093464a GIT binary patch literal 35 qcmZQk@|Ey)U|?|4^5tPrXB1#yU&Y}g{f%)r3Nz`#`LlmY-=6$OU? literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/88e6e46ab1ec92ce694b8d4c3d816491169d2bb6-10 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/88e6e46ab1ec92ce694b8d4c3d816491169d2bb6-10 new file mode 100644 index 0000000000000000000000000000000000000000..aa9c757e55180997f7984f230bae8a871988dbc1 GIT binary patch literal 25 XcmZS4@|ECV00JNlqF6vQ3y=l?8nyw( literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/89216c662a46d50f37cfa08963acad8c6f7aace7-11 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/89216c662a46d50f37cfa08963acad8c6f7aace7-11 new file mode 100644 index 0000000000000000000000000000000000000000..df697e2d3ce0dbd403fac73c5439842628e69bb5 GIT binary patch literal 20 acmZQk@|B28Y&o&_G6MqxBM>t%NB{shmjpWi literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8e533f8a1e58710d99d6b7d39af7034961aa4fbe-5 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8e533f8a1e58710d99d6b7d39af7034961aa4fbe-5 new file mode 100644 index 00000000..049f5296 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8e533f8a1e58710d99d6b7d39af7034961aa4fbe-5 @@ -0,0 +1 @@ +"M@" \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8f0d2862c49eebbcd473a38c8fa1e76288f47127-26 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8f0d2862c49eebbcd473a38c8fa1e76288f47127-26 new file mode 100644 index 0000000000000000000000000000000000000000..c7dd425011b7d2e0682ae8c1d8f1f623386d2e41 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%k-M C_6rCA literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8f61ea021e02cc609baafbdf714b9577e4bcb05f-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8f61ea021e02cc609baafbdf714b9577e4bcb05f-16 new file mode 100644 index 0000000000000000000000000000000000000000..30bb322cbc2626be942b780f730a21460ddf2272 GIT binary patch literal 74 zcmZQk@|Ey)U|?|4^5tPrXEb79Xkf@MOD!@qGz?`iGRkFOV1Ch{b8WdJ!^ZvB+zhI} e85?Mrm>HRx7?>Ctn;9FLmFA^Z6r?7Xqyhk%jufo` literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8f7a47710904981ffaa1fefa21fa95fd2d818487-7 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/8f7a47710904981ffaa1fefa21fa95fd2d818487-7 new file mode 100644 index 0000000000000000000000000000000000000000..107b0ae8668d3187ece858002aac4a35ecf8ddfd GIT binary patch literal 23 dcmZQk@|DO-Y&o%a|NB@5Mg|rJAjn9}0{~cN2CD!7 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..3ce6c4456d67abdd27062e34b6a1635fe44f4db1 GIT binary patch literal 42 ycmZ>Y%CIzaj8qGbWG}V6&cMLH$Y9@~z+lM3aO6lMW;R literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/90a227d3beab730ed6eecd63657f5406beccabdf-12 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/90a227d3beab730ed6eecd63657f5406beccabdf-12 new file mode 100644 index 0000000000000000000000000000000000000000..cea8af6ba3dc7cc2963cbeb8caf14a7ad4d20095 GIT binary patch literal 39 gcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^dbTW?t0K()4cmMzZ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/92197169aded0d5d0407e3925959e922257a101d-28 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/92197169aded0d5d0407e3925959e922257a101d-28 new file mode 100644 index 0000000000000000000000000000000000000000..82153779a3afb961baf829b5623fb323ec65810e GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~K5sB=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKX9_c0tJ*n!XTNN|L^zj1tLbEB8LC}!6q{SbxDBDuK^hVG2axTT%ss7 lEhja(L@zkC1gsy~Ng$K$5hnj{U|=w+0Xh+6GLVqS0{~>oHCq4x literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/924e17974cd194fa756d23394676d37cc3641f64-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/924e17974cd194fa756d23394676d37cc3641f64-17 new file mode 100644 index 0000000000000000000000000000000000000000..4cbe3bede9963229670a1324c9a869ffc1ec4419 GIT binary patch literal 25 dcmZQk@|Ey#P+GZn|N8=^=qn6BzycCt003lu2HpSw literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/92a785b5ea93d36e27029e281e9a34377d81ce55-5 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/92a785b5ea93d36e27029e281e9a34377d81ce55-5 new file mode 100644 index 00000000..44049efb --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/92a785b5ea93d36e27029e281e9a34377d81ce55-5 @@ -0,0 +1 @@ +"Mref \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/92fda3aa2adbe37ff690c59939ca1e1b2a8a7936-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/92fda3aa2adbe37ff690c59939ca1e1b2a8a7936-1 new file mode 100644 index 0000000000000000000000000000000000000000..c441ec798ec3c8cad69852a985bc4e39119df0cb GIT binary patch literal 40 vcmZ>Y$}lu^j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?p@9Mb(bx!F literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9363b81db6b35e8beebcc32d560f786472829bd8-21 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9363b81db6b35e8beebcc32d560f786472829bd8-21 new file mode 100644 index 0000000000000000000000000000000000000000..76c0eb4055cb2242bcf948bed5f0d35d550ac165 GIT binary patch literal 88 zcmZQk@|DO-Y&o%a|NB@5Mh0O9h6V{kLrWtAOCt+QQ&R(T3qvDQ240|W4YE2}pnwuc R7%cPue*;JXm;w_Lc>qKQ8fyRm literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/948b1ce043c82d0cfbaa910b6989a1b35a19b8ae-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/948b1ce043c82d0cfbaa910b6989a1b35a19b8ae-16 new file mode 100644 index 0000000000000000000000000000000000000000..8ee35db410ce6e2c7ad9fe71e14a57d52f2384e2 GIT binary patch literal 32 mcmZQk@|DO-Y&o%a|NB@5Mh0F628R0o|A8o-osr?3#7Y3cFAQ}6 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9505b43fcbc3139441e35bdaaec138e28af076f6-25 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9505b43fcbc3139441e35bdaaec138e28af076f6-25 new file mode 100644 index 0000000000000000000000000000000000000000..f33bdb30bb4f7b7977781e6abc11e1f6bf080944 GIT binary patch literal 91 hcmZQk@|Ey#P+GZn|N8=^=qn6Bz(To@uY^x#2>>y{9T5Nk literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/951bb02c199adb52e9e300e9fc070bf55980b910-14 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/951bb02c199adb52e9e300e9fc070bf55980b910-14 new file mode 100644 index 0000000000000000000000000000000000000000..812adc7c3481e09fb921605e4d9dace8a04b813f GIT binary patch literal 25 dcmZQk@|Ey)U|?|4^5tPrXJlhwVE7LLasWC@2PFUi literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/955404fe3f375361f5c3be1dbcd28eb9a28f06e4-13 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/955404fe3f375361f5c3be1dbcd28eb9a28f06e4-13 new file mode 100644 index 0000000000000000000000000000000000000000..6b83abdb76df271b5d57995049075336eb99c289 GIT binary patch literal 23 dcmZQk@|Ey#P+GZn|N8=^=qn6B(BP!S003CD2KN8} literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/967e50c6c1bc99aa5e7fa07c2de14564f52b0fd3-20 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/967e50c6c1bc99aa5e7fa07c2de14564f52b0fd3-20 new file mode 100644 index 0000000000000000000000000000000000000000..9bca31c7c2305554a06102f7b3e4d7440e9ba004 GIT binary patch literal 28 jcmZQk@|Ey)U|?|4^5tPrXXIpHV2D4RY}6vb%+8 KN*f?LpxOX6SsFwD literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/98d40a50ee58c05727777e242ecbc0d4e214f7fe-21 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/98d40a50ee58c05727777e242ecbc0d4e214f7fe-21 new file mode 100644 index 0000000000000000000000000000000000000000..dff3de3533976b04786a2cb40d807de90923d98d GIT binary patch literal 35 ncmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%y9Y7e=q<5e+LXb literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9915e9bb007bc2c1f3d346123933923279f0dec1-27 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9915e9bb007bc2c1f3d346123933923279f0dec1-27 new file mode 100644 index 0000000000000000000000000000000000000000..d39f6c7993c4eb5a43551aaf1d800ce3d68f07e7 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%Y$}lu^j8qGboRAj6z#t~ykZGill30?ckeOGO2mph82=xE} literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/99cfa74a1fea5d16168dd9efc720425b85e95eb7-15 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/99cfa74a1fea5d16168dd9efc720425b85e95eb7-15 new file mode 100644 index 0000000000000000000000000000000000000000..acd20c4577e786890e88501f4c7ba950926dde91 GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$iOJ<4gkYk3&8*Y literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9a552bab72f174ede3b9bdb7a663c963fd1463d3-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9a552bab72f174ede3b9bdb7a663c963fd1463d3-16 new file mode 100644 index 0000000000000000000000000000000000000000..657ce91e0d0754c21d2c31586380da1882ba1adb GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$Z$?#B>=`R4D|p2 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9aa3050cb38a6ad276cb5e5ca0c4776d92cb7b0f-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9aa3050cb38a6ad276cb5e5ca0c4776d92cb7b0f-1 new file mode 100644 index 00000000..9e58f1c4 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9aa3050cb38a6ad276cb5e5ca0c4776d92cb7b0f-1 @@ -0,0 +1 @@ +BZh31AY&SY \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9be44693435bc6c51980f30418bcc690d8c25fe7-6 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9be44693435bc6c51980f30418bcc690d8c25fe7-6 new file mode 100644 index 00000000..45ec57db --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9be44693435bc6c51980f30418bcc690d8c25fe7-6 @@ -0,0 +1 @@ +"MrSf \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9c0420bf00f888487d543f42fc48b407c65d4717-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9c0420bf00f888487d543f42fc48b407c65d4717-17 new file mode 100644 index 0000000000000000000000000000000000000000..635438d986ba0853cec981d2cad9188fda50cc7e GIT binary patch literal 95 zcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@Y6#UMf$s`5Y@_rH$?YGh(yXi#F{1(G%Y QB_iwY+vv7u>`#;c00|Bk`2YX_ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9ca2a086f1f08c7dec54d52425bd72f17c11056e-21 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/9ca2a086f1f08c7dec54d52425bd72f17c11056e-21 new file mode 100644 index 0000000000000000000000000000000000000000..b52fcb904e7846b16ef63ceb2dcd59428e1f4e72 GIT binary patch literal 37 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প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%0D<2qAto3;!NWm9J$MG_^gIkf+5mQEAOC;if40-F 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 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a01e13c3e401957031defb62b05434c65b01d5c4-10 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a01e13c3e401957031defb62b05434c65b01d5c4-10 new file mode 100644 index 0000000000000000000000000000000000000000..4582464344334bc231319855bd8997bee60de8f0 GIT binary patch literal 31 hcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^d2niHr0054{2rU2r literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a059044bdb0402471dbe9aaaa555a063a6bc1e6a-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a059044bdb0402471dbe9aaaa555a063a6bc1e6a-16 new file mode 100644 index 0000000000000000000000000000000000000000..a0735ef2b06b039a9cca862a54d1d7e5dc1c17dc GIT binary patch literal 38 tcmZQk@|DO-Y&o%a|NB@5Mg}GZh6V`+UIqq+n*aYB7#Jk-m>3jTB>>t!3Dy7r literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a06b1a08fcda463f1d51c485b0e7271ff9048b41-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a06b1a08fcda463f1d51c485b0e7271ff9048b41-16 new file mode 100644 index 0000000000000000000000000000000000000000..f400b22c08ff86d2adbf6b7a632fc9d48fef8b9e GIT binary patch literal 35 pcmZQk@|Ey)U|?|4^5tPrXB1#yU&Y}g{f3}oe&NT8txSsjLeEKr3#NF7+_ W|NjOC2BR7<_5VNZOa|H_kp}=%cs2_F literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a2e5916be780e35e9ecb7c42be52dd5e134f3363-25 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a2e5916be780e35e9ecb7c42be52dd5e134f3363-25 new file mode 100644 index 0000000000000000000000000000000000000000..67cfb1080b7f919b7688a12c3330016473cff695 GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKUFpMm1pS|9`N_Oh8={VDqcNCVpF literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a33252a74974fc86df30c311d501a1f363d350cd-12 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a33252a74974fc86df30c311d501a1f363d350cd-12 new file mode 100644 index 0000000000000000000000000000000000000000..c2a9be06f713b696a360271716baa610f261cbe1 GIT binary patch literal 33 kcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@V<-1L?O0EgZP8vpY%CHbGaY%CHbGaY%CHbGaRsSU*d literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a6dbaac639f3b82609ec27c80fbd003684c28867-21 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/a6dbaac639f3b82609ec27c80fbd003684c28867-21 new file mode 100644 index 0000000000000000000000000000000000000000..9f39c8e439181b414a21d5c19396a4389a0ae18c GIT binary patch literal 61 fcmZQk@|Ey#P+GZn|N8=^=qn6Bz(SPJ6`(!t%uz-am&I@XR#Q=^92VMXG literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/aa04575587509ffc65a6b0224d24ad1125cb0f63-26 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/aa04575587509ffc65a6b0224d24ad1125cb0f63-26 new file mode 100644 index 0000000000000000000000000000000000000000..d95281c298e1efe1b30345159672a9aaf747c23e GIT binary patch literal 91 hcmZQk@|Ey#P+GZn|N8=^=qn6Bz(To@uY^ygHvlo19OwW5 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/aa290b4dcc8198945311c8149fc1252f14555e70-15 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/aa290b4dcc8198945311c8149fc1252f14555e70-15 new file mode 100644 index 0000000000000000000000000000000000000000..3e939f9109f31dbd3354fa01b64c0e7dcadbfd78 GIT binary patch literal 63 mcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lW~Fqwx$Ld20pplkqr-w7fB literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/aabb8fa4913c79f0a42494ad2215a32927adbd45-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/aabb8fa4913c79f0a42494ad2215a32927adbd45-16 new file mode 100644 index 0000000000000000000000000000000000000000..3812c581c117632f16ca452fba409c9e6ff61ace GIT binary patch literal 63 mcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@Y6#UMghQ~?0AB@D#? literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ac7077c5220abe6cd481318c42dfe6cb2cb2c666-10 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ac7077c5220abe6cd481318c42dfe6cb2cb2c666-10 new file mode 100644 index 0000000000000000000000000000000000000000..592c47a4f1cffdc5f70790a525d2714f6f0d5732 GIT binary patch literal 40 ScmZS4@|9o!0v0?pNDcr&6a#Yr literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/acbef0322169a93c7421902883cc8057675c953b-26 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/acbef0322169a93c7421902883cc8057675c953b-26 new file mode 100644 index 0000000000000000000000000000000000000000..48bcaa723f0179276cf77cccee6203f2daf32be9 GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKbq?7-WG0N+4md4A=yt8Zh<$KiFg@pe_lp`88k@z~-C64LXeE0))vR OCxJ}1$6;~<$ejQw;5A18 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/aec95871bc7d87cae16c36a0d30955b43076aec5-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/aec95871bc7d87cae16c36a0d30955b43076aec5-17 new file mode 100644 index 0000000000000000000000000000000000000000..2bbc1c02b4b64222258094cf6e370f9204b98a0a GIT binary patch literal 35 pcmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}g{f3}oeY$}lu^j8qGbJf6@R%)r3F!otA8&=A0oVJ=?eYN0Rz0FSQ-2LJ#7 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b27fb21ecbe6e77c91341738621ad7092c29bca5-17 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b27fb21ecbe6e77c91341738621ad7092c29bca5-17 new file mode 100644 index 0000000000000000000000000000000000000000..0292f9be34d257c386d44010d47446736e5bfc6f GIT binary patch literal 89 zcmZQk@|Ey)U|?|4^5tPrXLMy?Xkf@MOD!@~F*GnTGBz+WF*7o?G&M6dF)%SQHZwMS bzke?fnVDG_SQ=Ou89-GSBB=n$F)#oChJO^s literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b38ce47b707326024fb24860c4365d58ab9f3528-29 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b38ce47b707326024fb24860c4365d58ab9f3528-29 new file mode 100644 index 0000000000000000000000000000000000000000..8374ff944848c3abe63811bf477552434247ec0a GIT binary patch literal 166 fcmZQk@|Ey#P+GZn|N8=^=qn6Bz%r|iQ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b3eaea244bd47b64c8de3d81c7b5e94e421d7f32-5 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b3eaea244bd47b64c8de3d81c7b5e94e421d7f32-5 new file mode 100644 index 0000000000000000000000000000000000000000..6c89843bc4d24eb4ffc350485113a38fbf0cc30b GIT binary patch literal 9 OcmZ?L@|9o!0w(|lm;n?3 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b3fd355dc090a732d5cf3b25151f165ea901a682-24 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b3fd355dc090a732d5cf3b25151f165ea901a682-24 new file mode 100644 index 0000000000000000000000000000000000000000..6274d9303318c5aa7b9c4afee278a9c36cd113b1 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%&Y}g{f%)r3Nz`(@7m;wM?CY$}kr%aB21Eb= literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b71a5a7c576e5cc5ba23845d352b2af16737c03c-7 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b71a5a7c576e5cc5ba23845d352b2af16737c03c-7 new file mode 100644 index 0000000000000000000000000000000000000000..1e596c355ff642c3ef131ef634f44e5566a7e519 GIT binary patch literal 17 TcmZS4@|9o!0u~?*VkrOs4(I`_ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b7815c3b5649d9a367ba99e7e09cf1f251ab6f83-18 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b7815c3b5649d9a367ba99e7e09cf1f251ab6f83-18 new file mode 100644 index 0000000000000000000000000000000000000000..4cf6940c45f769d717e6cfb2e06ccaf0a6598b2b GIT binary patch literal 44 dcmZQk@|Ey#P+GZn|N8=^=qn6Bz=A_a0suJ;4FCWD literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b7a5b15c9e2d4d659d421de8e3b463200f71f1ec-23 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b7a5b15c9e2d4d659d421de8e3b463200f71f1ec-23 new file mode 100644 index 0000000000000000000000000000000000000000..a47008c94c650f98bd7325a6d47adbf2cc51b807 GIT binary patch literal 143 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=IQ`0U~`C82|tP literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b83b3d04ada1403578065d7f10aa7441830dea3c-11 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b83b3d04ada1403578065d7f10aa7441830dea3c-11 new file mode 100644 index 0000000000000000000000000000000000000000..1288ace233d98353d9622a06742503716db48aa1 GIT binary patch literal 20 YcmZQk@|Ey)U|?|4^5tPrXJh~Y02}851^@s6 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b94b7ebc6d153e0c99a97864f58b26f7192f66a5-20 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/b94b7ebc6d153e0c99a97864f58b26f7192f66a5-20 new file mode 100644 index 0000000000000000000000000000000000000000..11053a55e2cf79c70420e5fe4b6ba643becd750b GIT binary patch literal 35 mcmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%Y%CHbGaB=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKX9_c0tJ*n!XTNN|L^zj1tLbEB8LC}!6q{SbxDBDuK^hVG2axT9L)s{ VHOK-WlkE{EgWP6R19l?RodAn$HT(bo literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/be06bb3c3b604660fd36b2af8860d35e31c8bbf3-8 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/be06bb3c3b604660fd36b2af8860d35e31c8bbf3-8 new file mode 100644 index 0000000000000000000000000000000000000000..ffe89ef6a12a8b19bf48bcb43af961fcdf876f42 GIT binary patch literal 66 WcmZ>Y%CHbGa%=qn5i3=QOB0BsHpnE(I) literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c07f4e4cb1d0a34dc6899097fd27ee9f1744cb70-12 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c07f4e4cb1d0a34dc6899097fd27ee9f1744cb70-12 new file mode 100644 index 0000000000000000000000000000000000000000..9551b7b887fc38e9eef806a4894adbc7e4ee5d44 GIT binary patch literal 19 acmZQk@|Ey#P+GZn|N8=^=qn5i3=IH1?gonh literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c2ac55a7fb702dd9a527b576d99008fe9b4f376f-14 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c2ac55a7fb702dd9a527b576d99008fe9b4f376f-14 new file mode 100644 index 0000000000000000000000000000000000000000..2cbdb3a8c8b69d9f3b2f1ecb4d3ed30842ee3135 GIT binary patch literal 36 rcmZQk@|Ey)U|?|4^5tPrXB1#yXkf@MOD#&v$uC#P&r?XwNGt*XeCG(o literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c2c3d29bce8aae89fed326832b3e1e1077cef1da-18 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c2c3d29bce8aae89fed326832b3e1e1077cef1da-18 new file mode 100644 index 0000000000000000000000000000000000000000..468e64850cdb63c1eee4d75ff6776a9e79e0b0c5 GIT binary patch literal 61 ucmZQk@|DO-Y&o%a|NB@5Mg}GZh6V`+ULaY6F02F*{{O#$fdNcNb literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c321670bbcd985327045dd1468bf2ac4ae7333e5-7 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c321670bbcd985327045dd1468bf2ac4ae7333e5-7 new file mode 100644 index 0000000000000000000000000000000000000000..eca662b7694b7094998f4deeca9a3b1b901b6264 GIT binary patch literal 32 acmZ>Y$}kZxazm)C~N?DB?!3y literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c652c46aba3567521f912bae6dc263b668c34c9c-7 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c652c46aba3567521f912bae6dc263b668c34c9c-7 new file mode 100644 index 0000000000000000000000000000000000000000..5cfdce9b9dbf45290fa1a487d46498f712f4c05c GIT binary patch literal 17 ScmZ?L@|9o!0w)N4jtKx1(E@V- literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c6610b87900912d462229a5259dab51ea0aeef33-4 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c6610b87900912d462229a5259dab51ea0aeef33-4 new file mode 100644 index 00000000..7a1dbaaf --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c6610b87900912d462229a5259dab51ea0aeef33-4 @@ -0,0 +1 @@ +B*M \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c6c37f6c89fe55768f8b3f7b28b99467c239703a-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c6c37f6c89fe55768f8b3f7b28b99467c239703a-1 new file mode 100644 index 0000000000000000000000000000000000000000..8c206a17cf90bbd82e1cbe005ebcd6b2ff77491c GIT binary patch literal 39 ucmZ>Y%CInWj8qGb>{?*|jDdkQkU@ljfnf)O0)rCQ!*Z42R!)vp%>Mw;uL`FC literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c71abfffdcf530a6d28fd99cd2c3505c61ef0ac5-8 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c71abfffdcf530a6d28fd99cd2c3505c61ef0ac5-8 new file mode 100644 index 0000000000000000000000000000000000000000..490ee245d6b8ffc19f7048a59af391cba9e1552a GIT binary patch literal 26 ecmZQk@|DO-Y&o%a|NB@5Mg}GZ1_m&n!4Uv(4hQA{ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c77304b250e887b39b5447d19b9c106fcebe7e66-20 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c77304b250e887b39b5447d19b9c106fcebe7e66-20 new file mode 100644 index 0000000000000000000000000000000000000000..7f1cf184c1e69db74b083f3983b559de0cf83c23 GIT binary patch literal 71 zcmZQk@|DO-Y&o%a|NB@5Mh0O9h6V`+ULaY6EG!EYPyz{qW&Zzf04V@dU_v4f01K`b A@c;k- literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c78cd8530e6d8a606a28797552ce3f5494763621-25 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c78cd8530e6d8a606a28797552ce3f5494763621-25 new file mode 100644 index 0000000000000000000000000000000000000000..5140f6f62cd9d09079e740107343de9fc9513167 GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lWRULaWm#6Wf)6N7>&NT8txSsjLeEJy`N9a!f7 Y{{{vIqZ%;v|3Bp>+v6}9Xp2N10B_SaNB{r; literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c790308a65efa1b895bc57abe53e4fbcdb2b7d0e-13 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/c790308a65efa1b895bc57abe53e4fbcdb2b7d0e-13 new file mode 100644 index 0000000000000000000000000000000000000000..c2479e6d87397739554a60f77c33f5f123a60a54 GIT binary patch literal 88 XcmZ>Y%CHbGaY$}ll>j8qGbjGmAd!oVQ*e*az|isy|;gRtZq9N3i<^jSg}?BCxJP+*wq9P$wW DIrtTA literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ca5d375d8a66727221d3e198d4ad360782944de7-27 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ca5d375d8a66727221d3e198d4ad360782944de7-27 new file mode 100644 index 0000000000000000000000000000000000000000..8c22c4dec7c989c754f375f9279ab19147fa6911 GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKX9_c0tJ*n!XTNN|L^zj1tLbEB8LC}!6q{SbxDBDuK^hVG2axTT%ss7 fEhja(L@zkC1gsy~Ng$K$5hjD&W>f=qBGjD#Vj4A9 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cb635ef244cb6affc005c63d0bf8b52aecb1d986-4 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cb635ef244cb6affc005c63d0bf8b52aecb1d986-4 new file mode 100644 index 00000000..9206cb93 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cb635ef244cb6affc005c63d0bf8b52aecb1d986-4 @@ -0,0 +1 @@ +"M1 \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cd67bf90feaeb1912792508afa01a09fe1f044c6-13 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cd67bf90feaeb1912792508afa01a09fe1f044c6-13 new file mode 100644 index 0000000000000000000000000000000000000000..71ebffbc207bc13b8584d97a7d8a4e9727e3bdba GIT binary patch literal 33 QcmZ?L@|9o!0w-KF06@nBhX4Qo literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cda434677d4bdd969a3bbf84086349f821e39c80-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cda434677d4bdd969a3bbf84086349f821e39c80-1 new file mode 100644 index 0000000000000000000000000000000000000000..0d66552a94f9755ba775f3a5a30d1ae566e55710 GIT binary patch literal 48 zcmZ>Y$}l!`j8qGbjGmAd!oVOV-{8Qmq@d3d!eIaYj(`HgRA-*6u8}Km#wz;#n520K E07-EVlK=n! literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cfe7201e28d42484764264c231663e6372e95ef7-14 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cfe7201e28d42484764264c231663e6372e95ef7-14 new file mode 100644 index 0000000000000000000000000000000000000000..ad5308bbad6312d84f874040858f22b93390965e GIT binary patch literal 32 jcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$N;1O$mR}X literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cff88dd94ee94e1901d25a74e29ad863bb78b1e4-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cff88dd94ee94e1901d25a74e29ad863bb78b1e4-16 new file mode 100644 index 0000000000000000000000000000000000000000..50ebc75bfb4fdb40ad07fcc99111f961cb8cdbca GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^&cG<_4gkY?3&#Ke literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cffc7573debb5af80aaddfa752538825275fd6a9-7 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cffc7573debb5af80aaddfa752538825275fd6a9-7 new file mode 100644 index 00000000..cac35b69 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/cffc7573debb5af80aaddfa752538825275fd6a9-7 @@ -0,0 +1 @@ +"MM@"©+[z_ \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d0ae058f71e53a7afd648b859cd7485886be550d-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d0ae058f71e53a7afd648b859cd7485886be550d-22 new file mode 100644 index 0000000000000000000000000000000000000000..8a7600c2c87c4e9934e84d8911c6a12cecc93589 GIT binary patch literal 127 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=QgO3 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d24f23a23508dd6bc93ea6283ed49c8ba4b737ed-15 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d24f23a23508dd6bc93ea6283ed49c8ba4b737ed-15 new file mode 100644 index 0000000000000000000000000000000000000000..3bc8f21001899a43a7937c8ed3e35f33d458be5c GIT binary patch literal 49 VcmZ?L@|9o!0w*-u5{(a+2LOjy1t0(b literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d295ca4c78f7fd3ff10b0520b09a0a346310e0a9-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d295ca4c78f7fd3ff10b0520b09a0a346310e0a9-1 new file mode 100644 index 0000000000000000000000000000000000000000..104bdc3d18f289e79d59ffef745a011a450b8113 GIT binary patch literal 58 zcmZ>Y$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x KvzUFH8ZrQ#K@ArG literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d3ddffcd038a5646a53d48b684eac5b721c7062a-18 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d3ddffcd038a5646a53d48b684eac5b721c7062a-18 new file mode 100644 index 0000000000000000000000000000000000000000..0702c4f88e08ccafe37fe70250000fd5aade110d GIT binary patch literal 59 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=PC$0HtpWnE(I) literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d4275f1f814a5b24f7b4788d15f3fef7b2be8aef-23 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d4275f1f814a5b24f7b4788d15f3fef7b2be8aef-23 new file mode 100644 index 0000000000000000000000000000000000000000..7405bc729cc0462e338851792d70ec19bf4a9605 GIT binary patch literal 72 ncmZQk@|Ey#P+GZn|N8=^=qn6Bz(TZ;Pi9F;PAUT<14AMJJZu$u literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d57eaf0fada8726afac2287cafb7720af7417b16-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d57eaf0fada8726afac2287cafb7720af7417b16-1 new file mode 100644 index 00000000..50220fca --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d57eaf0fada8726afac2287cafb7720af7417b16-1 @@ -0,0 +1 @@ +BZh11AY&SYà \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d5c9dc3b5b4e71d902fe4cf5c44b237b104a32a9-4 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d5c9dc3b5b4e71d902fe4cf5c44b237b104a32a9-4 new file mode 100644 index 0000000000000000000000000000000000000000..5a0cc7def8c4e585e04e5adcfc52b647a09c47c4 GIT binary patch literal 30 WcmZ>Y%CHbGazQ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d7855c38db11bfeeb474a4782f1ea293192f786f-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d7855c38db11bfeeb474a4782f1ea293192f786f-1 new file mode 100644 index 0000000000000000000000000000000000000000..d4bba7dfde6e5c111d70903c50390f914cfc4c27 GIT binary patch literal 42 xcmZ>Y$}lo?j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSeGXUah2w(sJ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d7912c5e2a776c408e7640f10bd7d655a6a0f31b-27 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/d7912c5e2a776c408e7640f10bd7d655a6a0f31b-27 new file mode 100644 index 0000000000000000000000000000000000000000..3df2af3fc89b18264e42538f1bf6b5eb08e2cc24 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%Y$}lu^j8qGbY*1h@>PYEOplBxOsA0!K*z-);;0ORZy A4gdfE literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/dcb49d3d45d32601fa27208cec33813e03ff6179-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/dcb49d3d45d32601fa27208cec33813e03ff6179-1 new file mode 100644 index 0000000000000000000000000000000000000000..a2dd20a4cad4ebc32b9f00cbf96b41c2936ba0da GIT binary patch literal 47 zcmZ>Y$}lx_j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{`Bxk_*=C&w!0e+d8~ Ctqe{8 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/dce9966b94744440d75a845a48c806041f5a6612-3 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/dce9966b94744440d75a845a48c806041f5a6612-3 new file mode 100644 index 0000000000000000000000000000000000000000..de247315cb6fba307228d83d2166c8108552fe24 GIT binary patch literal 31 ncmZ>Y$}lu^j8qGbRA4aVVK{Oq^<3rd^lSU058x4wEzGB literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/dd92516fbea2d0f96abc78f325d731053a451e16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/dd92516fbea2d0f96abc78f325d731053a451e16 new file mode 100644 index 00000000..5f62a794 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/dd92516fbea2d0f96abc78f325d731053a451e16 @@ -0,0 +1 @@ +ìª` \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ddf986569f89016184b5b6e924d5ba827c9980ca-28 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ddf986569f89016184b5b6e924d5ba827c9980ca-28 new file mode 100644 index 0000000000000000000000000000000000000000..c80538dd4374026fe627ee8dc69aff393be82111 GIT binary patch literal 156 ccmZQk@|Ey#P+GZn|N8=^=qn6Bz%p2b06T>++yDRo literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de0acf1136a1e05cd27345ce135ea26abd32bbfe-18 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de0acf1136a1e05cd27345ce135ea26abd32bbfe-18 new file mode 100644 index 0000000000000000000000000000000000000000..60f4c4567f35494ba04df43fda31b6cb6570f2fc GIT binary patch literal 36 rcmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%#fUsm}jG_z`y_iZ%PK2 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de33e3ef8a5780c7d3458188a423c00f470904d0-15 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de33e3ef8a5780c7d3458188a423c00f470904d0-15 new file mode 100644 index 0000000000000000000000000000000000000000..57de944141fb2c859d84250381bd99a6070db3f2 GIT binary patch literal 32 ncmZQk@|DO-Y&o%a|NB@5Mh0F628N3N{~H(>B=VRT6j&tyt#k=E literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de501127da94246b2d3aa947637b49fbc17d5e47-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de501127da94246b2d3aa947637b49fbc17d5e47-1 new file mode 100644 index 00000000..1d6eb7a2 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de501127da94246b2d3aa947637b49fbc17d5e47-1 @@ -0,0 +1 @@ +BZ \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de702cd20caeb08a843e0c09b0ce87a74e300415-20 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de702cd20caeb08a843e0c09b0ce87a74e300415-20 new file mode 100644 index 0000000000000000000000000000000000000000..bf568f6f4853bd8fddcef874115b0e9e53684961 GIT binary patch literal 71 zcmZQk@|DO-Y&o%a|NB@5Mh0O9h6V`+ULXlVEg%XcEDPi*frLRaHUIyEWFZuoEs+NR DdC3!7 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de8abda1b9bd5628ca99c8f97237fa885a857bb5-19 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/de8abda1b9bd5628ca99c8f97237fa885a857bb5-19 new file mode 100644 index 0000000000000000000000000000000000000000..064419b0cea2314dd9a997d13994314094564932 GIT binary patch literal 35 ncmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%d$0-k literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/def6a9e986daf0b268ef29ef7e821a9f6840ef2c-8 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/def6a9e986daf0b268ef29ef7e821a9f6840ef2c-8 new file mode 100644 index 0000000000000000000000000000000000000000..61307ca8277c078c79268eccd91620319bb2cd15 GIT binary patch literal 20 QcmZS4@|9o!0v04101=!4x&QzG literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/df0768cf0c709a1ff1a93cc0dad23979501c54ff-21 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/df0768cf0c709a1ff1a93cc0dad23979501c54ff-21 new file mode 100644 index 0000000000000000000000000000000000000000..07995a45638fc772cff8fd750794098f82ee7502 GIT binary patch literal 115 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=Oo#0PGYJnE(I) literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/dfad565009b0667ef2ee10ea9c1286ee5c3ce6b2-1 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/dfad565009b0667ef2ee10ea9c1286ee5c3ce6b2-1 new file mode 100644 index 00000000..dd3288dd --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/dfad565009b0667ef2ee10ea9c1286ee5c3ce6b2-1 @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/e.txt.bz2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/e.txt.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..65bf3b4c32a4742140c57c59ed46a06f859f9ca1 GIT binary patch literal 43149 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 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/e1556049ba9794a15ee21aa283876bf63e531a4f-24 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/e1556049ba9794a15ee21aa283876bf63e531a4f-24 new file mode 100644 index 0000000000000000000000000000000000000000..fe1bb6515770027f402f5e181ccc298280353d87 GIT binary patch literal 147 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=IQ~0efKB=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKUFpMm1pS|9`N_Oh8={VDoFhCVY$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C}H LkKTDK=Mn+{qihY} literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/e68b04a675d8d4192565a808955764c77ae510e6-16 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/e68b04a675d8d4192565a808955764c77ae510e6-16 new file mode 100644 index 0000000000000000000000000000000000000000..08838f05e71fa5cd6b9276bc5c69bff991d49ebc GIT binary patch literal 122 XcmZ>Y%CHbGaY%CHbGa%=qn5i3=K%wNecj+>j(t^ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ecbd6bdea50b52d263b4e9cdb96c7ce078d2b780-25 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ecbd6bdea50b52d263b4e9cdb96c7ce078d2b780-25 new file mode 100644 index 0000000000000000000000000000000000000000..41a813aa9bd54cdecf6b746f4456ea9f98934106 GIT binary patch literal 147 bcmZQk@|DO-Y&o%a|NB@5Mg|~g7-$RtDF+qs literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ecdd1df7d975c8cf8d015b2f1d0d7c6e00eb578b-15 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ecdd1df7d975c8cf8d015b2f1d0d7c6e00eb578b-15 new file mode 100644 index 0000000000000000000000000000000000000000..d02e56eff147b92a29f530274518474690eb5683 GIT binary patch literal 33 mcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$Z$?#<$nOwBMtNb literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/eda1ee9cf85f3f71ec8a4eec7534ed2677b47775-15 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/eda1ee9cf85f3f71ec8a4eec7534ed2677b47775-15 new file mode 100644 index 0000000000000000000000000000000000000000..f0d2c8cea4be83518d0e0effe712dda49cecf440 GIT binary patch literal 32 mcmZQk@|Ey)U|?|4^5tPrXJlhwU&Y}g{f3}mHY%CHbGaY$}lu^j8qGbRA4aVVK{Oq^<3Y$}ll>j8qGbjGmAd!oVOV-{8Qmq@d3d!eIaYj(`HgROgV70J~obmjD0& literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/f493376c3eda80cbe822ac456486734b72f891fc-2 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/f493376c3eda80cbe822ac456486734b72f891fc-2 new file mode 100644 index 0000000000000000000000000000000000000000..b06a853b78e23f1cb190543567fa465eee20fb90 GIT binary patch literal 44 zcmZ>Y$}l!`j8qGbjGmAd!oVOV|KEXKNkN|_gu(v(9f6d5@w&tdZEPvr%lwT1AN38B literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/f55efbb04cd32f7828e951d067319db00627153f-28 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/f55efbb04cd32f7828e951d067319db00627153f-28 new file mode 100644 index 0000000000000000000000000000000000000000..4b730fdd58a4cf87b4284c6a55189fbb41b19132 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%<%s|gS;*yh|kc#0F(prfeiUX00x!| Ap8x;= literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/f71b4776ecbbe47746fb53d7749751c5c5bbff05-22 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/f71b4776ecbbe47746fb53d7749751c5c5bbff05-22 new file mode 100644 index 0000000000000000000000000000000000000000..dd1e8e9c061c7a43cfcdc0b43973d53b709c924b GIT binary patch literal 61 ccmZQk@|Ey#P+GZn|N8=^=qn6Bz(TYT09r;8ssI20 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/f724d4c839c012c7772618e28ef68d478cc00c74-21 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/f724d4c839c012c7772618e28ef68d478cc00c74-21 new file mode 100644 index 0000000000000000000000000000000000000000..0476ee760651c63160e294c45397e7bd08f782b7 GIT binary patch literal 37 pcmZQk@|Ey)U|?|4^5tPrXB1*!V2D4RY}6vb%Y$}lu^j8qGbjGmAd!oVOV-{8Qmq@d3d!eIaYj(`G#^S=ZDu<;5Q literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/fac6c4165067ef2d87a23a2530a59eb560d470e0-23 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/fac6c4165067ef2d87a23a2530a59eb560d470e0-23 new file mode 100644 index 0000000000000000000000000000000000000000..72b39c999b57d5240281988a4d8ac16244fd3e84 GIT binary patch literal 51 xcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%Y$}lo?j8qGb6zG4f!@$5^{hgsffQh4#fx!U?85%f*7z7xAJOKd)g#!uY%CInWj8qGb>{?*|jDdlbAw`6Nfnf)O0)rCQLzUoGPL5Ta{{Y563P}I} literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/fd4f0dc77a022a8140ffe5b2e1a5ff577e844878-27 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/fd4f0dc77a022a8140ffe5b2e1a5ff577e844878-27 new file mode 100644 index 0000000000000000000000000000000000000000..fec864e0afc1805e6b39ec2914ccd6ca5b7e577f GIT binary patch literal 51 ycmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%B=VRT7+56$trQ6u literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/fe002e4c7731ecb4c09c09a4e1fa29c0c61874bc-7 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/fe002e4c7731ecb4c09c09a4e1fa29c0c61874bc-7 new file mode 100644 index 0000000000000000000000000000000000000000..9bf6f6e96fb9501712d70443440e3c3bd4863e1e GIT binary patch literal 15 WcmZQk@|DO-Y&o%a|NB@5Mg{;XUIlOf literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/fe78d4faf4ce717d84938010f92ca5e844f9980b-13 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/fe78d4faf4ce717d84938010f92ca5e844f9980b-13 new file mode 100644 index 0000000000000000000000000000000000000000..88b3ef7e5ea0c0d54f243afe1d291fcec0bfdb6d GIT binary patch literal 24 dcmZQk@|Ey#P+GZn|N8=^=qn5i3=JUc1OQ*>2TcF~ literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ff3b7ea844eb197dc6bd59d9f8e4a4a5718a6771-18 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ff3b7ea844eb197dc6bd59d9f8e4a4a5718a6771-18 new file mode 100644 index 0000000000000000000000000000000000000000..eea11f1681947a285ae2d927b29c0d62cdd53451 GIT binary patch literal 36 pcmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%Ad2 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ff47856b8fa7323572c8b4a6d8028dcb2663a37a-11 b/vendor/src/github.com/pierrec/lz4/fuzz/corpus/ff47856b8fa7323572c8b4a6d8028dcb2663a37a-11 new file mode 100644 index 0000000000000000000000000000000000000000..ed4aac7166ac3db93a890972d9bed4272f79f7ff GIT binary patch literal 84 acmZ>Y%CHbGabe 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 literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968 b/vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968 new file mode 100644 index 0000000000000000000000000000000000000000..2b0938aa3f0d3e1c9f002692db98f9cfb92cc0f2 GIT binary patch literal 27 ecmZQk@|Ey)U|?|4^5tPrXJlgl1F^>p0&)N@kpnXT literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.output b/vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.output new file mode 100644 index 00000000..62f54ca1 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.output @@ -0,0 +1,51 @@ +program hanged (timeout 10 seconds) + +SIGABRT: abort +PC=0x5e9e2 m=0 + +goroutine 1 [running]: +github.com/pierrec/lz4.UncompressBlock(0x820282830, 0x6, 0x6, 0x82032e000, 0x10000, 0x10000, 0x0, 0x6, 0x0, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/github.com/pierrec/lz4/block.go:104 +0xec2 fp=0x8202b59d8 sp=0x8202b5900 +github.com/pierrec/lz4.(*Reader).decompressBlock(0x8203085a0, 0x820290240, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/github.com/pierrec/lz4/reader.go:271 +0x189 fp=0x8202b5a48 sp=0x8202b59d8 +github.com/pierrec/lz4.(*Reader).Read(0x8203085a0, 0x82030b400, 0x200, 0x200, 0x0, 0x0, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/github.com/pierrec/lz4/reader.go:188 +0x1156 fp=0x8202b5c38 sp=0x8202b5a48 +bytes.(*Buffer).ReadFrom(0x8202b5d68, 0x882042d260, 0x8203085a0, 0x0, 0x0, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/bytes/buffer.go:173 +0x3db fp=0x8202b5ce8 sp=0x8202b5c38 +io/ioutil.readAll(0x882042d260, 0x8203085a0, 0x200, 0x0, 0x0, 0x0, 0x0, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/io/ioutil/ioutil.go:33 +0x1ed fp=0x8202b5de0 sp=0x8202b5ce8 +io/ioutil.ReadAll(0x882042d260, 0x8203085a0, 0x0, 0x0, 0x0, 0x0, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/io/ioutil/ioutil.go:42 +0x80 fp=0x8202b5e28 sp=0x8202b5de0 +github.com/pierrec/lz4/fuzz.Fuzz(0x8820479000, 0x1b, 0x200000, 0x3) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/github.com/pierrec/lz4/fuzz/lz4.go:11 +0x15f fp=0x8202b5ea0 sp=0x8202b5e28 +github.com/dvyukov/go-fuzz/go-fuzz-dep.Main(0x1a7f18) + /Users/pierrecurto/sandbox/src/github.com/dvyukov/go-fuzz/go-fuzz-dep/main.go:47 +0x14c fp=0x8202b5f40 sp=0x8202b5ea0 +main.main() + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/go-fuzz-main/main.go:10 +0x23 fp=0x8202b5f50 sp=0x8202b5f40 +runtime.main() + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/runtime/proc.go:111 +0x2b0 fp=0x8202b5fa0 sp=0x8202b5f50 +runtime.goexit() + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/runtime/asm_amd64.s:1696 +0x1 fp=0x8202b5fa8 sp=0x8202b5fa0 + +rax 0x0 +rbx 0x0 +rcx 0x0 +rdx 0x82032e000 +rdi 0x82032e000 +rsi 0x82032e000 +rbp 0x0 +rsp 0x8202b5900 +r8 0x10000 +r9 0x82032e000 +r10 0x10000 +r11 0x82032e000 +r12 0x10000 +r13 0x10000 +r14 0x1 +r15 0x8 +rip 0x5e9e2 +rflags 0x206 +cs 0x2b +fs 0x0 +gs 0x0 +exit status 2 \ No newline at end of file diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.quoted b/vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.quoted new file mode 100644 index 00000000..4b42bc15 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.quoted @@ -0,0 +1,2 @@ + "\x04\"M\x18M@\x00\x00B*M\f\x00'\x01\x06\x00\x00\x00\x00" + + "\x00\x00\x16\xe3\x00\x10\x1e" diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/crashers/169b44c5a64fec4d8e969d25d3e4764c9c3b604b b/vendor/src/github.com/pierrec/lz4/fuzz/crashers/169b44c5a64fec4d8e969d25d3e4764c9c3b604b new file mode 100644 index 0000000000000000000000000000000000000000..501c796d72a3966f73687757da2c5df5add36b1d GIT binary patch literal 66 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±z73{sw_E!VpeTfjmIiYz zUWqK;oD5$6Iqh}a5vnu~a4Em!O9%&546(gSdVruHx06>c28&1|w z!ZiYTENAP?a?;cQo9YQVdZH(}j;=?L1Elm+`T9_=R4ep|U?uAC zK}4r9HSKI_J)yD}SrD1_gO?%jN@92&7!}|_*4wla890|uu!(99Xkgs(Be=|d+2s}ziWvz^rkwE1bM5cvqxz;UKIC<*)PT~G*ekVUen2nD18xnbJ$jJQ1lv$ zn0oEkof1uamkO+5`YVLMobar9yo%K`e7;TCX?)l@mRN-`#QIlTha&EblrzGG27}|p z(G=qj^{1Irx0bcg0*}rXM5L~xC|ObzP07IHOv%DXN;<+%FtYf-En|dJHlL0ZK3F4+ zmtG>xy{W_oy(>b0?G0W73TX{^U91?8<86u(!zlqr=p6Lt9ih+op1m$~RS+MW zBGw*+3xOZ001UElJ`rV;=GZ1w1lF~&$VN?E@FG^Uw>!nMf_U_=)($0}2KA*0LxgmR zT?K_^pP*#1uT7iPdXr($OjzoFs}ch@bS^t%PWSyzu@_r~8#bET!ekxI+y-vLUAJj_rK+1CH;b7ZUA54vSl|P5-6c9H;shS}B5_OzE^$VYe0l{pBw&K-wcJ@3 z5soNmsFakT1>Yh^L_k|#awc-h=ZWAiLj2&ox3&K~mR z%WE;5Xq4Y4i50D&(r(<$b4ax-5%%j)cR%wg_!FzSix2U9`qO;G-1k=8n9}be_Rh-n zsOXYfO)2c(zvR>*mi1uYOP*i}(&^pezdV_;)m#QVeVi2n2GiP{tAS{-LPw<3BIy4Q+fp|MAY8iG?Yq3TyKK&aZ8 zVeL}zHG`J+EHdA!66|~LqoxAI`;ad2)RZyV59UN@Qc^jqsZ9x8>3<1yvy;2|lM>Yp z>svNe;_BN>sc(((a&H#BJyXLa5PlCL4)I=XJJw)HTCnYSlQ>eKk9P9VRuONviDW;c zC1%#YOv(76dr%tRn<7pn;HH`JD*tlO@kHZU`ei&x9~SMx3dIQP=K-}^0LJ!iCTih} zEy~WdQz|qZq1?vJ8!))8C<28+aVJ}_@AZor-@$3(c7>v^CcxC@IO7#1DOk*FVk!a)nwQiGTkd`S+7}ze-~#Gw`L1*yU_2L#w6T-O*Qq z^;zgpICv0Pr_~v4(I~cgB#Cq&qn-!GwwRmaG9A9bsiyriIXV<1f^P3p!&&`)?-eE3~8dKWG=fcei8yZBCQ4g$K`Rc{Q%=Ifi|mo*CU zOEzBFpy5D0Sw~_9`U$AQCS^{#M(;3DW|iQV_hc-MUoe_;v}^>>ar!8J^CZ9Y9rtpe zaCVmU=1Jxeb92F%wux7%l$e)1&78v`+DXHAXA|=wntXt!7Kd$U5}OWpUIFB|==A$5 z&E6+u>=lRZToUmq^~SkZobf)POC$5s8pKv7&JOKKW86=%^nCwv0Q+8CctVWPv&4%2f><~khL<|}Su4X^jaD#TIyMn!{)NOl za@t5o%-cMwo9fRg-)HSH-)Ak)B@~cdjBHzc8QbH;wuMa2Ck6nP9*gWRMO|=NBH<^K zZ4TPt!u>EubZ)?{^Buxkp@rk1FqJ*x+5nHZ^^Z23?t9GEx)-+YXtoA#EL~A%VYT+d zqod)6D!5uURs)A`W)EQsrP}t2RIA$1@Tu^*w-i>* zYSj@31BTK{E=5K8C6*>1Jr|#8PSl2;*liTeiR_cYw+7H1r(v2y64)>MX%zB4em;AS z*Yu`{3*pky2BVj9unKmPeuF8U$Mz~4y_?wR)yX~;P6zpekxs`{jH_;6geG{s6Sp_< z_qs*mlBKVAqH;*f-jN~J$cp-(Mv$osEIV`Vj>st zL~crqzJ%cQd2&5$@Q@6J9zjiHzL%nJg6KZ{R6q$YfVC%`%=)yKByZk!d6D zf%QJ;u)45{e|!1&tl98A8@~sB((3lLrHzunHZqK|DA_dl)W3<<9);c-_;}3Ap?H|M+}J_jFgkqh7swRrTssIkWJRwYvBw1m<-lhU8;WU0?y~TTWBEwh9Hq{!&RZJh-6$^aZwNRXj4L1NxTxaDjl^ zpY+k`z@w6oM+xVE^G`1?2)57t$%N>te1d3HXBwR`!{A{5nj-{e+?YVKgO!72Du(d3 zte0?jLQjV!SmO=PE=-|LQBM? zF3J~0;vWvh#pX#r{Xa-T^nt+0?*>NhK!mXN@NOFWr*K`NYKe)7Bri{S_M$4IUUv;m zoc2mKRePDWTD>IE6ku4g%;LJ;7-M5`Ip;^$2c$8oJt53(5cy{;=qUy(NH=v-j}c~1 zf8$>9v1@sORkU#`Mvy)6c?zqN?OPC?p=bDiCqI}KyLI%CV)xuYAL`!@6*K=$ef;I9 z{6(a2gZ>hId_K4g$)E%iP__D!kcQcy_`piVR}#fyi$Wa=W*Dm}^|*pDPG>DK5hxIJ z$9RE24!$SfB7U>zrpbNqw|cq(6YMja5ZHG%BXC$00&g}Dm}?*~(?DSF2m(7(MDgQD zCZdUipfSw|K{(0a4`AgRefd2CLF)h?g^G~`K|_y)thLj~O9VIp@4qcFQMam)Cc{LQ zR<%gv*p%|@t)C~;d3jS*j1WJx1&@oMOi+Z;94SH@?Pm;)Gge#Sb3;|o(XT+-dljab zn8I2z=L&K2;S=?iM0`?Yiix?Yjg=-v|Fg|63fe#{QFsYJx8(U_afmkZxcKo$>Q1FP z=rnirqs1kB>~8p&D7Z|~78ddz^d!S;bs_IfZeT3&Yp9Jng$Azi4K|kV-ePPlgWQpb ztFJzQ;y4K3z>-!p%@uVi6-Ex3v7r!11m*fTzzS`IHQN8Lxc})i^)hye!~H5*7v#BP zkaTNYbNmvKZaM#+JO#isc`W`?S2LD|6+DyO!@M3`d#OmeTux6>d;4%Ch-nB zwsSav0w4h3s97|dN8=@{%H>~)@PSS>=4m)~6~eq4S%+P-c#F0mpUVD4BDT|)_{~m! zQ$)i&9)m$D)q4`Kw$!hAe^`T6GU+g88$h;5L$m2Y#Qq;VG%F)Nst@t#ETczyW21v* z3b|LC=qAGmcJsJV7lx#t^el0$KU~X|t2l8|afVWNXn>Y;Ic772$5)HT?J)D3R>1j7 zkTd-lyeo`Hdqcm#{|!{Azz4={<6b*JtaRYEM%8CzsdrW2TBOI!Hnb^KxcrmW?9qdj zB-OXhx0A-vr}zt6IQ0jfB(RH)wTpm}629&!Q|1S-YXD4dCyYznxYC>SO0J`q_2Z`a z@jUog{}tZqdl}@S3i~mvV6j2JrY(xKqFzKme2KV$s*n{%tJSe$h-WfV~a1wiCC>}4ihmVWAN1AViaBn%*pc1 ztPdWd(+_!!00UOnVr}ujtz(G8?u7E9Igf2YAafw*^FsB_f67zbwC)fc2 z@o_`!i4(OkB z1>Afj+DF}?xPb?3EohD{Xtph9ZcqH|n5{pF+#hJ@){v3^fE&7t8)}v>Y(eof68>;} zX_Ga8VGIF#sk#M2k$Sg=T+4T{0P1E?sm6a=Ds8FO`1j@bxf&d_<4Smg zYxyPqeQxt1)ct`J{f{EF(CBF#X(GNRa`i zeiGI(n;>Q1LFuau16+1if5Sx-RU<#n|r ztlNVfb`zk*wM$pA|W(StzG8ZUY;LXYIo_W7$(z3<~_toQo8)2Pha zo9w+Fg)J$c(Ri;Fd^utUed=pt-{|UrZ=aok-*f3>Zm_p_&N$KH^6Xod8AcU6U3-^@ z99uHhA^BqzlbXrJd|2~3GLDaPE$;yY4isIx66Z2U{UrfQ-2f|Q8}>87SxozdXo$3t zeb2+;u%H#F309pp!u1$wn5vu-pw?^&hL&Q$7u;sW>x#zWu~aaLx*0qEeVt7!{PBI3 z(Ip%H(_@9?&wRaFcM@;!$}35DEpBhp8LBms3$$9p(iE-=9cGb&0fiz)rllWm793sg z+bNEt-bvB_eA-B~9RU6D9wIE9UjNzn(q!B51Tj)NDI zeg)mzm$jpKm}_}2uZqdiz3MvkR2UUVV{ys#*6sGG>qv!ESNoE1c~{T*)L)hABe5A< zwQY*yTe2P;0e)AH+~ixu|7)xohHgRGlU}d65w!YGBkdJ&y^OWB3(H#Tl&s&1+ff$N zjjl*5;pwCU(E^ffe0H$@G*z)UKI%(;LlRgZ+!6;Q)8;`DN_{GYc0L{Ns-%Pyq(jt- zO>u0Lf^3e~OLWnFNjxn8c}EQabtMbop`s&vt?J#5pg(5~lmah2^aA(3yZvN&OcF@N z9DKaOe9ZP6q@?S+8GE1wb7Pq+glX5JfSW`4pQv57#?2bRLh#fY^A+{qUlU6q2aOEw z2LJCEt^-UYhZfkuV=e?v44l8f3}E7;3w;o0e(>Kwub|C?I%8tFD*3?p8hlnAa?->H z;xPLibot|j!7U%CRt@ohl(Z9rF}DehcM96*!quT#7}`!Wv~2OoG~0x6;TvyLCo`04 zra?lXHzQ4SyDA3~rGp_ zXz@v{wtkHiRMJU3GV@m?pq#l`3q2g#2n~=Dt2iT(k-uXLF=wyw2BKVQb8Z z%oX%|@}G83ehx7f-moTC3O$LXe`PQIuZkw=R-~qlln+I_W{2xZCOFCaLZ8pEpPsvU z6sUMza1$t}J@CAXqBXivR{!C5*?)Kn{+xLb=ble{o!skC@HtAY5y#+=*`Vx-KsAPM z7m0LN+-o;KEF zX$O$dUI~N#cBDow9NSC-8Edt1hTbbIG(FqXpLy8evSdB|= z_>Ifd3~uTTy1*LL2|*Q`AZhZRHkD39H6mK*gf&&59dFV<(gCFV$5Ln`> zihKFgV<54EuufL$lQ}N`d~|c>RK3mWyy}lixEAFPfS$A!nuS9Tg%Wb|)Z=)~@v1*z z+X}rLVk}>A?BYrTNGtwRIa4xxXw}>3Q+LsVjJXApEcMiQ@x=z8V*?a{uP1K;g(yox zhZpaO6JE7C&$Vn5mm%^KnB{DZlPvk?ldveVyJFMfT0}#Yr*6V)en!|jkd#0aW%nZ` zon6a&dvVy%2o62QH{ROXc&Z7;Um&+qjx*5s0HE<;EXXSoC#;62LZ0Q_T9jvB6zLUF zqlAg1FLjS_?ewOu^`Z7pqv9nJdS8-^v=K05)%)ULgndbMUY3Rn z@E{M-b9FFQ$yz_9`+&Lal=$KvPY-zcduEcsb=r5!c-`+p`I zTeO!dz~r%Q&Fbb}YO+c7Lm^c4O-487uk@BZ<0Px7#exgs_2(YMVRlh$KyHk;`f!|2 zJ)`*fP+~rx?(*w#5iA`wu_O@W|Eb>iJWo9elPoTB7WqgCEKVomiw8%|w&Gl-Tp!MW z9YA+^>dNz$KGRbA8f;&1Vwloqe+KP}53M3XF6~9tT*{NpsHUy88lPh=eegH<^w;R- zZ}T2ARbTrvRL8#DI|0;)%#=@cOeirkNd!=qq2|9;z~vlv(9v(&4jxDYAT zyJMgiF~mt2)iH!>O_pBcvAq(+BwABe)9TR+sXM|>_SAPK1$ zX&y`0kVAs9p`fyn{lu^x2a%-&mz<&09+&ZD2d6+EgRaq0T)n2L z7kD|Y_Q0Q;(lrcIF+@rwZzn?Gd0KNX&NGw)_Q!ftgTxPm4$N-&VoQ)w9z1cr{hdEq zKPfc&hm(hd1VfcX%iEG}cJ=(GVaUUbPmBq0*j0I%gUeWGOhEiZA}Ent)Qyi4>C~FX z$X5AlYC@~0PMwm?~OCT1?H)%Br$*^7B9+VGE2V1nvHu_)o8 zRdY5ae4<@n|H%}WzXxxY#jc5Upx7OG(cF9?QL?ksj>#pK*FQUq*E31Muf~`MpxI{Q zuukeNAWs402Ml=;lGx0R_!`A7_@G*E%HYLYEa1}wIH-*3+UOO4wx-LTTs z|E*Hm6XZ(6)jqWfeUZ}}?@qP!Kb5RW=jl%I1OvOs25O=RKVY7}Y=rW=lQD3Cc?f%| zFmvs|^^|m$4cKzmvXzPh-N<8u(@^2)-H)8@Q}~j^myUe7m@h5(;^a$x7F|y8XgZeIF$7kuQZXvHRd#;c@U6m-s3%aK5mFp zMwhmQ!+Zo?6W^fEBt{sa!%lQQV-MkT2bPqB?+`&*H7@^39+M7hVqX=uHY>BCqyB!( z!2@Eua3!G~bQ}TNt$Up?FCwISgxI}J32)?)$l6wXCln8w$0g-wUM(329k_nGMVzBZ zWjS{{Bx7S-6B$9%)pa;WC%2?Sh=eM1a@R{T5$U0A`Z&7LNAhKOrZ`NIh@0`t_@N#T zBU8*)Xk44zxHfrwxbuW-Q+%F!I^$0ebN%7?NgciZbB@v>xpS|;q$kyf;}!prczjd* z3#{fny*Lm$ti?0%AQ0Pi*pfke6%_9PWj;*Bceun0(mrTKRB$yGT=IrOE4fQaKw%|! zZj2XHOpr?`_xCR@W#-rX{0e%Gg4B<}$HJJd3|iICr*8G7o~F>8j?;>I((qMsoWzM7_jh_p0yO|2+gLw&d{cWy^)BWN1XOm7&! zp0v{NxB}gtY$>*~BC=B*e28PqhEWWS6=Sbjb^Vxb3i({ zpA2dzrP3QRw&rqXG#cHFC|3IS!2oXo%7cFV8qt=T;acRQ@CK2Q|1u8s+o}eo?2Ibq zX|og|D$+rgNGU~es7|Z`!DctK3KYS1f;2brlp=`~hiyv**)U_{~<` zbPv4ADNYkg5C$tbW(+t&=zXoqROJlFY|4jf9H|bUMF!ApPD%i+W(8DC)BXObc zVYu_4S9$90U=N&4pp4;yR)YajNb7FH#E>&3&8My>MPP#=w-2*u_B-iJG6^K`YI2=L z<38$jEvw>>MVIV?KlX~oO0A-F0!X~@e^JJv;K+Jx9E@$X7rk}*;UuWu8%N{o-{&&M z7M?3OYB^j$>~dcq-cQZLr`p4?ONNY=N5!W7BaLN1!B3#4;vGq(n@J0ozNh zFS$Xq9`P#dN(MH5uwi3O18l6dVk3sIG0;+;@!{;~4}YNDpdTA2P=TXQ7)P;;qlu^f z?>OpvDhfw*8VoLd_(Hkh{VSUW2eGbHbVmF>$x2h}XbA?_VA@=C^S+Eto;gG8gL0Nn z`dWDWH(NrM-Uq~QJmpXTAM3f@EyX1QM2_*rKi&!($B=|P@G*>wzPUG_%S@#F!#7Mz zV-cnt>%=3b@T~Y@1=EK?VHXd_!iKY8e)5L0Iz@9{Hy}w8N06GrRK*+KI!9-}%k+ue zMES-sBuwmz$B^17&nYL)0Wqn&)D9@(f%Jj z$ak7Tb_dcP8O{y|>?(=j*`ez#!m$#&V_y$Ng{o}$J;?H+C7vL8FE$ziIg^jwyia2O zxOCLIl@a1}?BD4josP|u*ws@T!a3b3yhPiL7GaFyEq{>bAmrfCel!$MT5l+6g69av z^noV{Ib9_>b1>o%9|-P+6^uDVN5Oc5K+h0oLufnB6FEzn+Sk6tJTQ-yLTFThNHjl* zPV0_V$0xUghl%92hTebb4%F}dpsis2;d|jb*GIzu1}mID8Z^%r3RxrN6A;tz(GGZ| z*W61Q>D!$xl{d%A*Za)M1rAFJZTKrz2zTY#6XxUYb~i=6QK-qVog zLnzGSr+XJOH>HDqXvcNv?Ou>1vB#MUb7?osr7@W_k<=RX2iHeK(o=u%pX2a{Pjs@+ zkR@J+@wMO?1elv-0c?qYGfY4uKI<6D)R0dO7)I>Wq2Wjz)l{Su%u0hn_sWEuzN0)l zE`Ss5HXlti&h~npPs@!j&pt2@-?V`@l&)h8{Y?#iMca$RiK%j4hi5jhHcYge8QO{= z`aX}OeJGB8{Ty2U%b+zh@1Sw>x-s~Z8w`Fr4SrMYe1m`JiAD!s4%-L+ z*>ya+>5UKmVWaIYIT9~(E%8-w7p%*GkC z6+lE8p{LT}1}&A|VXLlRG#z;wYtUzlj0TmTX{144L=!*?5kM35d<1ZCZleS+vH<}s zsO4%?8Yh6#=+`Cz7?`;1bmYDkLtDgkr`7AFKViKpICb9j>LHfbENAeTGBA&&e)L6A zsSu-(?~eA1B)TZW4-unvr+MP{mgq*5T!FmBEzVEw;i0m; zZmzpu5zDqQIERdz)fCr8jM4x!pn)({IL9(dDaI&aj;x#JM2!+BR!X4&MA4&kc(r91 z+zm!)Q}pWwqx2R^OwIp*At|kIJf7$(-jAWZ$U@ihf;mt~>sbygG=)$M z3DO&}G?jV!L^_011UT!7ZtfF(YL3U}`Uqt4@ySKrRDJXSH7C9NbD9w_kIjL=`bz$0 zsSll$^xMt)j1{0HiMYQecfF!3`8MeHCd642&gYvWvmKjNU?DKfte`*jd^lWQmfTyy z1AE*PV@=?QmEzQVWd{*&z*@p72d_RP5EU|udGaTQE409^7I4tc$1_Abm$zU|s?enA zlAh7!m$cU31M+XQGyAOs?5f-@S(~~Reyz#9(xKGmdgx1AvoV97e%Fi4F$*bQw-Ih- z{yOxC9uNt)QutqlTgegOR+PrVt$e+WRNFZ#glcPIs@8}XGH;V)jF`jP$zTC3cGg*x zNwcV9#rbBDRMF@xI?_PWS+bI+Nnzu>PK|!uU>4y@X561SXKCdm3W7teEb(JoeAZU> z<5u3|Z?u&!pR>0zhMEBdhQ7rHR!17BR~v8siEmV+F_)9H6;v^kbMkMo96?ix{%4!- zZ!`Zb@ctS6N!L%v+^#W)4d5kb)({1c7#HPJ(SNW z3DGQy(E!DkXV$6WcIa22#-QDg)c9H3O&9nG%x#R3!7<;1R2WaO_daO zlCF*6Nks7i9`eA~k@-@%#x`G+|6;!6i}_N}*nD|;t0~ElCoc3{|MXH?Nk8C=?+A?R z)lui8(~VGi5m~2J1gwE;n;17;QE3d<3Wra#s?m*xFX(Srm#FO>n1$F z8?8TAiOOvgg&#@ar*&ia`6HQ%O{vj$9fEefd7l1_G0M-uz3&Ux)95$^l8td_WC$=t zDqBaO9d}?mX4>bk$k$2nbMlPASrHw}WeyVE}ZTL^NpcVO< zsdjg=s(z+#0!Gou(#i4v^hApfLps7OJKWGY7wK7*4& zUZ2~AqszJ~#v|j=(msYK+Hkl3%qWorOp_PmBeYS-FXVC@NLR(xY~V{&M(j`!*54T) zjN6r>IMAha5(28ahQUDOQSc+Yn$E17>3f5cU;yRWFHK9vNSzo20#jge_@g36;=hqX?%Cm2w=N?=L);RmX4+nI8#dOj2cNT>C zBxiKa`d>c_heMlHDfB7l*fgGR`YbFAXD`6ZN_c6Br})0{GDxoR=JV&x=a+{m<{k!~ z(g$=DR<@O-x5@o;4D9n33bGuxWXT2;knexSy2DPV-e3L?^RvYA><7vSIUkbtEg!nB z3l7&W*BOKKED!0k@Sr^VDuyNH01d$Mm-M(ZKhEYN#=Z3LZWc?iyLA%Ko8fP7n4%<+L-f!cTo1hjfCXrZuJR!DtVI zt~IAV45gQSaJKGnw|NRg@9f;i00AXk%d@lSrsEoCZ@gLK zOvMWf{Ko7q5__=(uk8&wSqu|;C z~c(Dqd(pUW&+aR79@Gp?-k$)9MEEctf<90yS z9}^vD|0H(6d9puruGV>|e-~nfbliq59uJ!bG|RJ7A4MX$2`Ih_0M|GZ9%Ux+yeJKB zr!;FXu!PJVO^YC1CAPs|9_m|@p$>`sB48LF>u(*#7e4}4@)neFi_y4#^RaP*xhV%+ z6*r)r=Vmu=I;H`dikmEe zsz|4piL5UjSV?haWXZG)2j`MI{+cO;n}Go}5lbi23~fy-Q{r%Ybo=go9YVj-#w1cS z9sj=04D^1PhJk2JV7&hIBD)8SqdC+X9j&+CE;kZ7P zLUW(K;nM**fYz+3f+C7Eo^J)T+4B(avR?g=mpz3gm)^`F0f*r#H;tYo0j;(G2q@!^ zDWZ&@158yp!NttwLRnTaYzqrTXp=8+gN4O8@Y%oA*wB-~gT#TX8Jd6oP@pO}mzmV~ zDE775e0^g*A74ykutd0&pJ`Xx-yF`8G#<+8QfxcaA4^d{BZ}CgW?7@CjL;_NSn}0& z^V9nog64wPB3MjtKk8vG?gQrd?U_dQrveqpbXJRw=v;+n&zT3OIxvn#*;I~rjpuRj zNezagEhj2`k!A-v`tdau&zqo&8}kkHmVIoX-G?-hTE=h`ABiSIyOI(tw~9Cqu@Pxt z2MZfXA;K$2L6S|RXr3+(=6NeJ<8Su0lh|twVAE+=GWV4jiQNwEp+EnT9%%qJcsCcV z@DxU&@yfRLy^#_0jnPjYdi_$|z|!W4hq%QCr6n5OcU2ysf`{Pl@f|>lSh@v?@`~ZG zn5#P&SVX`pm`E1Ytk9IU^rcob6IRRU_E?G_qIr#B)`&vr7feOU`5pbmQ|J2cr#(0F){eTwyWoL!ENCDqo1< z8t8N6tg~m)6Pl(cCH|IX0S@+IOM5c5avSQXZ8b&wi-Wqw`miO?0z9z1ZW?g+bl38S z+Im%8ap0LdGltblJkAe~@GN(@8eq%55ji6iwXU(`Rt5T3ePMbu5>y(H;NqSR5!w^j9HxXo1bMY0g<9DZUQh_$2tGhG8Ne1#k{wE&!M*2%mZllZ zAG?7;+{6#|CYEq6OrC+CGNn^SM~a3Rd%9C;925>ho@NhU@rF5C%#4M4Bm++O!|EfE9~NvVuj@Z zM#9xPg`S`kY}^pKY|&5rJlU7b#i@$9Q20)BW_CiihqhUG$*LBy1GBcc{I3uWH&VD3 zl_QGL>DV_q0A%%kI?s)BegIoDbqZw=Z;8-_XZ*8%n{)#WcUG{tpNJn;nxSY@Gbw%| zJh=i#u_KyRQ^|yQLUAptMbBr>XzSrZjb26iNssZ5)IdL}CdMS<$6*X$REu);yZVu{ z&x}I*vNIe+Sp8#u+iJ93%wCbg2B1uIIbx&g9nd8bu01|2C()~=lxG)>7eXPt(3Etv zhdVYZm{h(f?ly$e84XKWV%5w zkn-$b$B~f!8jYIbsm)2DB4}rdf-s9+pOWr;z6J>BVhZ&p5__bGsn;=FCn``p)Qezw zwuWWHutB*4v>a@w$a;eJ_Rgk6bygT|a7MIy%joQ<(J#)uDP9C`V&e>EoYe>J1d{Jk z-$*=;{Q7hPRUqPOIU%?pbl#H#ePk4wt&J~hO8#1|VGU+EmD z%p`=}0EC+b>U@?#eHeRX(->;YVk&GdOH@m$BDL^w{U!6Q6%5-*t{P5%^?DGym+LyBOe%jx#;R3CKp6BvBw^<1H$V+qfgW(a zK)Ks|h1BuW8=|+t8<;veu!_IzN<+6os80YY`1g9WAmv(&g|EHAqna7SBaW&g*b^6u zgWG|$-Z-y6-E!hD2XSZT`X!bKbaBWICSJ^XqMH{8O=PqzO#q0Tk<6JgF?4Wjsh7i_ z3oBPT^%UbYe~D#|7fTyO`}^!fEb*9hb6un2&|=NSX~t%OS&-g-36r;*)Z!e1(_3TD z(!v*vfA^^H&HZzHt4QA**o-zm)rW<~A+lY#ffbQx6>zriW|)ZN4~bPSH@-LKm?cBP z*x#Te_IRHwp9|2idusIJZP2`j?9H>|UuFDL{zNW&Nw7o}}qe50tL5(Jj74U-3;WC*hB@mkfRZ`PI>^_Y3%Vebu2@&}^R=jhbz2 ziAR%X&~02vTTL#Z+ZfjZ=e45=9qyVn&MV;75jtk;e~|YFa*%KpBh5^0ZoIg<#Z@eb zVh6l7mjwY$9$g0IYiakjPokJ2bC8etH0Q1G*o%B3Fe4TZjZ}NL1oPCDx&FP5yk=XD zd0jo$9di||8|_M|KIU?J3*k@Oo=F`gc)0$U>)vX3v39hpmvbOIbIr2Eg+wd0#;vA7SXcXPThpW9G z8>5CPqtRO*WR0|L2)kt$h$2nMA$3U3F;@>~XZQ?SlJKAhTQUUOx%rsSb$OLf%>}V+ zi~>#Tu@Sok|Dh+t)*f@U@)p1+xdpDfp})PVU2|^7C8c)e5@Ub^a%NT+)K_Y29VAVl zqCy7>fwZztPiqP43GLy!DvuE7yK?H&*va*r4KD4O44|h}UCGAmX*1Bz9B(KneSmid z{!q3Y@~TI3{kt8$W~-@yWW1!=}UlD zyl9U#>bb@tnHEm{*wq9!q5;^ce&(JkfNfx~Hm_K~=*;F;0p=mF*BMNH(awaIvaq(Q z*7Aa)u|3nzvV*EG$Rx0CFWbY2juT*R0-L~KS1q-J4FE9xm2@(Q=hWb^d`*Gta2!k8 zE48y}Hyx2l%IM1A9&}D<650>KeI05xOi@@?@J;wllO(tg#D1J^YlC>;NxyG1@R!q3 z2P`Q5q@pDxKZSGTdL*da-i;H~DG5|%kkXNu*8VjyQ76`gevzX7Ma9!O$;P@`w2;g^ zNJ5A>uMYHZLm`o#2PfXk_w&TNRK|&SZ?#F3qn=FW855X_g{VJJ>vq^%2avY_BsP+v zbIt?34WPGj7u*R8I}yX-+6wem&NysD88*pXl8n=OBsRi0Fper&L8g+r6JE#z;9Er5 z^i+&`i$!ms+DFLW6%y~+iO=e|s)8DLw*&syV71LU8J%=1h464Yv|$Udo0Z0cZ}35c z!?=r(fjYmtgqac)w;EcUgAa2GneD7~&Bv22!=H zKvIFH8>z8CrX)j8L=NwQ_aeyv_Hz~Vua=OX55LyHT}g7f`AlJawSpN4e?dGIln26$ zzWs8VX0Czuh=@O2#j~-9X5+Fx1h#vjWj2x<#qz5JOY$&F+TNQ0fBJ_VFmM%HRS7#- z+0tS2if`VxzniF0T)l=W9^jfh)PZiB#S} zE-%oayqYUTd5K)!zFq`4z5(F#2B4b(KV`s+8dUs#UDfFuJ@VZdAlJWy@t%qRN_z#IllWWeghcBZ=t0QDX{9cW!c?!zoAn1}om zX4L#dnkB1fHU+-}4(htQihpc8ODwiWU2xMGzS|J|2U<_gt_K#|zOnrYlDC?&yp^KK zwZnK16|ME{Z?V`3uELi6ClPUnULdsbwU(yjOYYXzRKk0PTE4<#p!$qNOeNeQwF_-` zbkO8p;+EWCa%qrX(*)IZT2k`2EBInMGKE)V+O zET4sHO)_^TyU z7pKca)wTuNeRBaa|0x}51l?jtNqoS~OF;WU%63D(v&m-D%&GG_?iNHf%J8PGGu}?7k*XpG|tkiHB(qYElXyxTcFhFuDxu z`*E*CL+s+fFBl-)7;xKO3jMB+hN?oZHz?mV`&WtQqkTMTB%TWK`eze_O~AFhAQ6c- zE8;KRjX??~vYwufe)XK(7$tVJ?^_YGb(E1LyFB~#0<>lfBxfhHxZYG8^zEbmygS2M zE-qX)|AW~eEr#Y91+Vo5a@-L^M2CNf7DrCHWT2Jn{xyK_v-KCiw`=w{jE_W9Fc$bg z$~UH}Ijh}2Mm#)R6@L6Q>a&uujGw9Fxj`Njg_wW!F;8frb<;pV8-|a6I2?u!r#KYr zVSs(63DM*kw_-js^3VFrfC}J;lJ&zN?gQu}S3~Dr4a@;dG@RVJrU5=CU&8)2amlDL zaAswU6v8ett)R%zCR=$ne0Ga5@CkD|@~)A*Te;S>T!~8723N&fj!0rFhwG^qhygC# zAsGzt2?w$ix!JU2-h+G$;pOM=VmYpI9Q_<2e$E@_u(a-f&7P&nJ%=PyGx)5a2$xLj z1fI%liOfO|ll}^*2UN93=6PvnVe2RzOD6+Tq|&Z>2V6)wZFOl|06KN40CGD?hQ@uTENDYN{lNCctFYs9zc8t)&JGr!7dEp?@lYw865~&E%bD!r{<7y(zZ+_HeZQJOFypIl~|0ZI^^9 z-q9FdLyD*gwH16+Mcf~?+;6trziYWStUl1@n7AZrK2OV$pw#O}?!_5`qqdstnOUI{ zpxiB;x=7&~RbB_z&@P~@skgHj;?#TXk0J5>WDL)#Qm1|iv{dg-Mp7t9VWE z@HA(qJCY^PdIpdqu_euNArQ@u8LTSt4!`kEM1~B=Z?+b>+7_;e#owQ}#qYWBTfZX- zd+7YQvlt&uR;f7oeVjvoJvXitC`GZUJecqRZi){qALvg-q{d$FLlfABmuXXj0=)tiL!^B4L zp3zFw<-tyjYfBGD_7TV%cZ3?0c^ey8&G|lJN368Qc|0Fx6HF<##~+{_hTo>~Fynr` ze)jiBV{m`tf;@gmI)WwgxWv4Q>c~=RY^@);x|6>*666=8ukmBvr5GI4^ca4mXiFDS z_ufwSkd2U~ZRA3@E>k;;2H~<;!2p4@W@#u*EFlrIwjAqgEir{C3{ViE5Ds?+6oP|( z^m81W7n2t;*!`W^mm$FJ8b;!7{ses)-ewv#vOm6upQG~zHGQb)4L#zfcZyOJ$SC*k zJW>?44>D%x_j`DTBGOQ%VtlDf5nr18#I5Yvg%bSxev7g%(|BD3>fO-ekpaRDa=qU( zSRyA$ryX;XjF`Qc6r_oXk!plzq_+Wi-N@u9szfVD0dEamyPf<62Waxh(qu_<-V1-b zh557FN5K97QoaA5kT4o>*1=+Aa=kFY~ikf{In}H|)@W@P| z8NG4DDPQVp#kK4ly@M~GNJq8cFo@4{;VxsV;?Uu~0-xd?a|Jq2sEpXj-~K>Bn$9Td z=OV)NhwN{J8LSqtZ;FG%+RUT4))W?T2TYAWJHmv;=kh_k)8s=Px)5Rsp`e?LNZXYs zOz&FS4tgn9(?_~#BeR+joyjGD47nZrMHb!?u7IIi6U2-j^eJ(V6X!hq`^hFTR2@>w z|9L&uHRz6 z+{DZ%1|Zq{Z=s6Po*a~nvQ;8|QB4;NrFopTODmGekAmd<11RvmriFHr_nWe$t2qL@?jGf z(hTWDRZg^4In}HZ8dgp}FeJ+OsjS9(Xui?RCrdnZ7Jlg29Y{Fa{(?OT*?_LFz+#;^ zj02Mhs;I(lv%j>fgT^CM@DIGtp?j1@q^|T?vwzt?`?U*OqUc1A9`q2{Tb1@UQ~{WN zNe9zv#X)c}$pp-O!6~Z5b*;fU#Fad`0|JhQ^bz!}tX=7(v8+fgieU!N(~@1n%4vXi zl8Xcf=9$V7lilLyME;p5;O7!NJ^}Rh#8{#Wk_)N(3)qPe#-)I8{x<*4(p`Zf@gjv@ zq~dU;(4)86R~64wbk$#HYsaWcyNzrqjD_9=%~4SVJI^UKpwt%yfp)qefeIH{Xd+n@ z*byL6|Dcm33Co8#aGj1dPW>P0?_lW#>Fc(q8d`ANi z7e@oo)IwfO1zwqF6U8jDQJCRb7$LH>u|1L`E1Ajn;{z@20leVe=SIc9+C%Ymw6r@- z;1p5b4zs-U|DGoAKR->bWtxn0Rh*8YJEyDSDBmHSo^3-2{$iG$PGdV`{NT2BI(;Wb z`ajbtHHCJzpEobzB1F!iH8fwL<912hAeFW z*+)RS4agXV^iQ|%Gc*&B@do4$USy)|{j`JdQzv*aVwebxvWE-oH{D+K#{i~Zd@+}5 zs9ivN<*n(1ti=ubk00!XxB74fxhr5N&yfhS0zp27Kef)xmR%(LSL?h&+$l3xA)TX# z?=5H^ZOujft=wKz2P~=t-UeIo0rfx5&}G7Dy39RAmv>G;8TG9Ieu!=;Y6EcPsW2m^ zOvOJFO)^n=$b*NE!IypC2bI3}(Z4$Hz7LDy^QDs#*^2=q@|x4{bE;}5u4RdM`YG@) ziDw2(A_tj|gijiV^wkPl_|L$^pM@~m!pLsNeK!A~We&sGbM7fZ(%)SXMUi@k$U+l< z{`vjkuw~{3@8_RvzwuKF0?u`gc?7qPR}0RRG;$i(1CnAS;?ci@v@$^G@(mP94Hud%zHd<}d^54uV8q+{Ls zSM4xghnwK5PTN=Uml6IGhVM`CFCzR2H_m^qWa(^sSn1$diQ5Ty?IW?n=WaS0@n#}z zW&u_!gERwM81{B_2*uH(-7YL?Gc4}GDD)L-pGj1*WB^(aM;!6&i8k|#4Zln)bw!pgAbBkS-%c6&TL8C+7q7T}5$6t$E zmPw}Pg81Z4%P0CXLufFx=C-*)-E^*wm3W%eG^c6O7lW=-yxGXGge}8@$2m3m@6E*w zs=SDZ`|xx-^~?i_OMfH5LFMqes=~^tFG!#d0w?TKXefR#If157UxFWk@FN*MuK|2d zguf}lGUZYcz5<@;4|A*5UT1ftpL~k^p8IO@H_f_8Sv94={^dvDmW;d?!;cd2!?mC~ z7z;#{u`YO)2lupPuwJp;7uE|RsTfG7C*?g(`@z8QNimgz@17+WVBG4!{m!pWqqndh zc_#1El>kLO@;Fe-AYQb4oo2uqjP>>LTd>&tje~sI)*A|@M|+|J3|H)O$u{*%ilV1| zb4plDdsevq#WQ{AxBt67Y;KvB_JCLU@e$H->sLg*r$QuSQ`IPr$vpHt&^U#ot$!0* z?hT(W9>wH`u>awyJKC{sMg)TE8U?k1JLeHZo< zVZ&HVfQy;&3AM-A1l*!;1GNOt=VN;wJ#TwlvvJK1R;h`x^GA zMb3AkpJk*oairUxFlLS_Kiag5q{rc8#r?%v=Y*z)X!oGF)4PLY4C|RH-`JFbEc}^e z*f)I}Q6-S`nlkD&xocCJa`EtR5q8dB<0P-^7HiPq85+~&6rVCm)T`>Tp~spai*`)L z@H8 zi!sA5yOT=sG~qc!IPxF2%v?Hg`r97_)!Yh|-QS*mZ^Iwh$TZOj+z(vmjF90(UAqI* z_rXxVmcU(4LzCW0r zJWNm7T*-_VV32OhGzRI!h8S3HhQXgNzCdv2VY0@iwQoWO%y_)O0tYO07O8=n{0H^{ zBcRK>0Mw^BzZqq?L=TAhYnSMRZkHsXfw67d-#bX`6+OiCiq3#%u35(&>=oUWAkO0z zy=D;k@U5Ur+Q&f;x=$3hghy}Vy(%wefR_guZj^jlO%4oVH@_UXPo?pogQ4;tBl$Tx z0Cy12Q}hR&#D@!a*nPVma`D2DLu8ZFg1}U(OBu&s7GNxbbzrc)3++pRM}P_cUuOQ} zYTMf=>QqYx6aK#pwrYl5joJ!edK$O9iEJm!zQ+jr&`xqbwpsWbnQ$nq{HbwD9O zK7j8=$Y-ufmiRD08+f-7A6D;f6FC!r84phEQPgcd$7*E@X7Fauax|NF&LgTTZmOux zi{T!K@0%-`_?qjVZUVZya&wGCGB*45Ce<5$y&K5)*ZIf@+Vz!!PYVy57*ruQ)e#pg zdL6i6?3u>a6Ut)kKj_iq>#mAyr3?&P&_NloyB$OP$B=~4>=D5{7Tp{UYx19aVCvSy zsPZAWsdfIk$KZaqg_GzGKG{A|e3F*Ot}?Jtoq?4!A4VeMPh1XRMRP8S!ReI!DqZB) z;DU*IPffc_(cB{QdZ|m%?n$JLh#y&L;j_6IItH{%=eApj(g!_|Ofxc#JeSGjoh^AJ zX<9Qy!pB?i`OY*W-3+Y~bN8it{{=set>*xkkG{f>u4 zJ-vM-IHc6GbgAFxMNbI&jbojZv1_h;3BJ_i76OKb0L#%INFh=Uof9ALy#+=%VF`}k zDo+i&Al}D<>4Qdv^@`!M=zM%PwXi7CtXuop*(x1xL&Z1g4Kk)nNI>qDZtF$!&?zAtqVMgsQROL!F@XwKK@BL7no z+y$)#B zpTjhKck-_v`PbF(t33N%`lJ&){s>o@4N~7m2m77w)M*6bdi5QMSF!= z$EIDaXbyC2TY|P8y7`$Xyu8pM31TlVGH!(-CF@uj`rN;PWf2ks@~$gHbv?Y)+4vfL z^DD6&jaxbo{Y<{n2w#_2p8ZHhG6#2(Q~pSjggBel=?^QqE}aN?`B|R=1&99ASpOez zi2iHx-rtjifu;pe%QwGcx6$J@AS-9Z+(Q*g|MW)kuK4F!aelG{_`Bk!s4s3sUCRfO z526qy&p1ot8Xxt2KZWMx@iUQ!Q}t0dqROGv*3y;`@VL7a^=p92!%zLEoG$-+_#)70 zgQCTn)#h`^8KB|KqFVT*BYjfuEPfooj~n}r%n~sW(PL2+zdevzvpSBAb!!Y$9lAB{ z#NlpE!)-leos+^1Xi1ePDz!Nt%UFljtFfUPedI@T?y?VslCckFG2ho&X@9rW= z=3{-#%~ZoAvxY>dL6hGCJi+&!aQ(BOY`iHjRR2fl(8Dk!Iw+N>Gj+0nPSg(%D z>hFLDdO|^c?~8zwL-iLtFZnq73P$0^jg~X*CA81OD3$fI{`5@iX#{w{uqC*1C%kW2 zxpA2EaR;agiKzP>dBCo|=iyuIROml?E;ev{_=5hS=OpwMpd&*f{l6z;msdUG4R4?m zs6KV4H#G$0*nHA>j2!xiH_)lM_mhoZ@jpd9%0dvOKOA?cxfdRAoH+mLbczDE&X=_l zH1w=fEyZSp@*DAEO3XxM`$%V2 z&%vuHU6s_0-qf|2^9c8q;_?D5nqihrGE!zz9NrrJD3zqEe3`|UOI`ph{bCNI4L^gJ zzvNJ?C`42~BC3F5pE9Kuv73^L2RyRN|GrR~RDjt}eY|x9NWJi`J=Uo|SkFdn%dR~x zYel%EO=QbH1$I|gdq0`-Hzn7(%%_5X3Y03g%$$&r)f$jFFFD6i={d|A9Nx^v>RFRZ-!Yv=x}PUvqv z2MB-mJnPwgjPFd-ACf~*2p=g7i`JNf)WB4SP$U9r8=B&rSW0_+wSIK;APdqe^i$JX zB-c7$J0ZkaSkK`0V@41t^Js+NME{M~X5d7=0-;f!}8+wZM@Sf{P z!KJJ`Svo8Pn*89gB%1swpg4|zdrbTNh%kz{mcN7xak&WFe)e07UgN@+KlTex=@i-% z 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≺2F^7r5H>b-$o!1-${Sz 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≈agT=NIrE=1euu6fiqiGNnlo$t{PF*2`x3Y)tMBgtMbWH5O+|Bzihhxm zVOe5H;XW!Exg@40x#E(dqEcF6fJh^1rDbL1l1rs#YVIj6shMk~Sz3~2&WIM~hU>id zobSDNo@eF(vA2Jpk6q^6=dNeD=bn4+xy}Im{096?(zR^?e&+qj@KG8*PvZw!z)upN zKxZ;307orkiPXU)e&EDXU%{T0;^!B14Y&zqJZap8YurU>R7Gi2G15|iwC~SJq=~tn zEB;M%FJ35-XLw^xwEyMz2ITz@JBbg!HzSY093jboytzPLHX(27D*|~GMAr{r>#<)< z6IHhPUQO0)tkjS7;HDnZ@JzkjBTM;%;f8|JHbb>&W(B(|Tbeu4#KcENn6E_Pv{-9I zycbh9@N#aA^j%pctAEp0gno5D4>>+cH~~t?+N(PIJt*Ox4h(-$!?QOTiqhL2UPLF9yOvrG15U7xw#At->OH7 zEIr$N`kW-b?X0@?G_3=0&S|D#4dpseR1#7?eCry|Kp1bpJr}XJ`$qg*DC)Yfnq#T+Ej|H5*9AbH~6KINJ>;0+JQbXhe=wz~}D>v#o|k?jCxfkR|Q zfoau48*$tMynNWnV%a7pxMU(YM7AsAX^XkO9|Tud)!t9E=moJnfM75MK&Vr*BMKy}S)miz78=8-Gm@4c3sG{>IY2ILIesgUp?oI2k@ z;PvM;{8jDLi7a^=hpkCnDR1jWmIi8A^6njvY>K=FBp*=8lT;kWuLqHL3!bVcN9%m? zYdo(DzDVRzPQx{hXm_1kX*%Qu2j2X{QsH}6*{QBKYV&~Dpi^d$ecXI@>fFSRix1c{ ztFd#bG9rkra#B+m?O;Pc57)~MJJdA%2G`4D^BDfPhOgJIm&h`=YqO7gSA4(@f{t>! z&=^$q*JoVWU*9QscU>7}8E2_1q9{?7?*096(+-EYO2&ICaAh;UW2v&E690PpJ0(?i zFnYV-ST76Tj?fLih=&NuH)nWv4R5C(BH%2--PW?)4QFmhz0J4SaJ8<%{BvH_BO;8f zP&9C>uBb4S8(7MlP{)<+3cfc~H9%S9e%+s}u?M%)C)9_@#<;!X#{+iUm=ZLOdz(Um@2zC*A-qTJ&w zJ5?83{vcgp6(|zN@hFVvTLnL(#VfL&ac*fI**PNc_R?})WECX!jwTHMNW1o9jmV?AiNyq6UVF9b!4!X?GSo?SMA>i+%S_XO2i*j)uCK zDLl~6Z*g+-w@Y~H7&HyAV$ucDaCSLpSSPZmdUvY*sWam$zsQ+KsMB|WaZ2P1z8yxs zaC!V=kPwlz)_J{?-3?ZpBPTeLX`9^Hv*ngHT?ocLB%X5}M~C^MbEq97YcGSuj4{31MfOh(qr!qq03ML@~~$;nR`_`?q8do zWdnSQbSy*@p7)^#EE3)80r4G&q#Tmt*zEtbRn6}sppvp}m{gq!?6Dh+(&C#ZbO$Da?k2s!W&fw)Lp0qX>lvqo zU_@jkwhldOc~^D+7FAzm6Me7KaE>MIPv6N_^gZe!BW*t`Y1_X^P2Qf`Z2xe4o>Btc z)H_ik-6UU+ZcYVjy6NRL(#@PEmUQ!kSJO>-C?6DS*xhi3+!(z9@)?NaD3rj>NSeaL zaTiP+W4=){*ajBT%LzQQy*2zkZ6TFet#wuf6nO}z81*&$gr-Ky(gKnh*SOGLXlx}O z-vrK&Y?k!*ifE!O-ml%IV0}pH@)Qrx*L0&f!-l3#QW^ z3e40HNi`(r!Bci5g|Kk$Lh=QYD7d6nxIlGJHP!9;94`t?IL|{W++dKx&t>qC4s9?? zVFG)Ooi|D0mBw-};qCBG{K^s7v(W6qIUO#XuaFDpl@FxocnrYX;2qjsRWn>vJs2Ky ztre^*ss`AC8X6Q!4GIJJI9|rt@*E+*(eGtX3TBFbIqqKgY4dyp=g`qex{({{@quES zbLSb_=J@SrU&MYkiex8k1E=OG%8myk4k+ZYyrSU`XhxJ-Jt=GJhH@B<4W>3xazjJT zZl+7}=9WuRmb(7hTYPi7{DwE5pU>uUHz}Chd;;7ukz9HB<<=P9355zxFRTymIZ54* zh!c&t8~)=vSmn*9sBg`BSzmY2#!=i~o2Otc(1rw0R$y{uNx)6mF$yLfSs0wNO+H|! z99arhfeEc-t=~N9UyQq@>((RasBZTvfd9L^RWRswJs1JGVA+wCE{c0 zy6fX((z-x=j9yoIe6;Yx$GpNoeB8G#5Fa(xS>nUCE)X9lzy6Q#@m=zb;A6zse)#C* z;_h_+IuIW+tLfJz;^VHbua6J!+CY31tSvo0`ugFc#@~VX_+V`yKC;(Z;v;2kAU?XS z{g3eRc)uIL$FVhj_?QDHm7Qw>@gcL8tYLh3X?e83$J=YJkB=d10`bvxP3iH`&krBj zrvmYD)0#khTv%<1kNnkv_}H=fKf=f7eQpFFomTtdW8UZ7o!HfZ_>ft5t}YQDWmaDw zABR^3;^VtjrN>7rKYUy$2*k(eRe|{Ex5^S939AC}(RkH=gpb>L7mp7L6wkg)yH?89 z5=9S|kL4b$RCnb!7EFYpGQ|*pFY;F2&9kCR}@blXY9`vr(ZrvE0_mgG z3QPKkUJ*ziwO9N{^l|xx8{yYE%l+{2U48CO?(#r<$gE+@OT`Mdjad}DU@zKu@ANL#!#K-4L0`c+g5=(rf zFA2oQpe6qiKH7G_5qzBc(hnaiJ9Bq_{W1_AGHc_PCE{cDm)FO~YhMQ9W8jyi$44ta ze7t)!5FfXF8HkVaUs~d$aB(0$4lVwV@Uf791TyrS#buk_2GJ_;e9gYRe=l~H6@T=hKU(mSM9v`NdkZedx`nF!6r5F_L}c)}8t#kz zLRm5#P)1QJ`=rL9^hXPORyAO6m@ab_b(Qmi{x$qJU6;&ylCrjL^exd}l{Jc>2wn0W zT@oTlITw@-}?;{kRJyzYKC|u=*p;W%Y4ZaW3WS z4(901Nr9m*TOAKKL~ov9lhK>=ZKi0K|J=>dn{UdJ&fJ#Kn=2qWfpY`%n+Tpy6;9~6 zHG!)?@)=iqHJroGFs@|Qa-EfnA`kw-@Q)-sbp$?Vu#90Sh>M*p`e+hkAzEbPlO!cg zP5$+ccB-AM$$X0FlQ<1@&P1FqBKAu`w)k@p7Uecb?nCkxPDh3#xgCiOzTwB`%WfNV zh94BntTU`tV1v#uU%^Z|!yeDJ%a%GrFLby$lG~76x#aa`6t%Qx4Pf$jbeykdxIGxC zdKHE@*6@cl1IesA=KD#4}!I}VzKy<&9BoX^s zNW`L_eG<{*L0}jaP$qR=;FKrLvz+qQ^8%;*k$Kir-p^W1y9G4xH@IL6l6lu?%3J9v z|9!6Clt;xg{M)&KQ!cX>&E+Zg>BQzKpEURSQ$BER;FNcsTbe0vWijPh2Mkj_@}g(vrA;p!dcg!`yI0a=YHj^ z(#(B7i@E>vN5kCzbj~#QJ!b{ZeY;tfbKh`Q;N0Ie>%Wn(-yCxb)aB4iV<+O1)HR{-pX^ zOeWoA^eL+?ZWGGtx9;a(mfj!VgYcFhd7BI;ueTAHd+J)r_nG|hH%&G<1Nf`{u^;|q zbp2}|1>z4`{~`WPJFkboAshZH{C)M(zrf$$zgXdKvc{ijGR^qQs>%5KD6M$>ZFH6b zf7O7$1iy!`p8rtc=akK8_h_l%coCZLhAh4wR@H|szOmbA=cqfR!6TSxk$;iwk#x_>9KGAEah5N zIP$6b-L1pVa)nO5mE`FG!Mr?2Z&50V#GTPfOy4g5=`-7-3Sp0GN9K&NC$Z(8U|_)c z5`nxsbvZ((tJ$jtd&$G_3M~9U!Ov?`1ZBz1=Ge>WgoNB$P>(n2ujMPFgR&U@nT8+L zxS=dr%lK}QttjA{tFqJ8U+(DL5=nK9NNS}$V@=&3yP3vE*m|!;3D~N=USn&J#+Gu_ z1j2YBO7KHiVtQ=;Pa0t zh8meQLTB|wktzon-d)36=^~uPrjh%D$p}*!rjemxBvz8?e@@&$p~uY|oq2VLsHd8) zM?Tb*04JKO?H6+jVou8l*e@P1)8tg=n%4#RNV^UoJ0ldbcta2-GQ$e&a)3L7ts3^(;a1Hj<%8+9N3gTgV?2o;IYJ zkUnH<@srn6A+O1IfAzZxr!N85-{E{{mWDs4am`t|jvgc;$gBALjw`%eh2o*C91^TK zbipk5fzg>21>QaOENIIc$X1jb%Kxu`yZwn$p?1V@OL<{v?OPl7Lca1{TleBKEsZ#f z9=vj9T(aR#czW!KAHwm#cT+NR9(zY>&+Y8`ZSTDb_9&{s+uoOKsdqYa2Ux%D%{TZm zHpgtr2`>0WV0?@Cw3>2r+a@(Paz*xHy)(gg8GvH6HWsY-G)im7+B!)i6WBygc%V;DbD>=eB z_Nq;+AFt92F<(vPgP7m&P~to)#osc3PE-W+Or=>xL6KqO1rcwusq%xS$kD}$TDId-bfSXYjk*Xd>RP4iT5PIIbowXpZ@mfs zs{Tq-)MS^#LbC&rrp~^t;KwzhkwuJ|QFNDm5?N-&UlAkX#P^%!_o)wxIvfa}u~@-s zpge&^Kk2niIzr-}9TWd{Qhi*@tHxT|Hsx9d_|-ySQOnxET3n7N)VE#9#IQT$sa{>>CUzK?sn<1IsvZ=1r^tbEJd zV*-mFudy2U16<2EV=Wml*ADZmg}|bg)mF7c+q14g*Jy04sU6<7iSnzd9lvn%X2e{W2o4=e?<@8vu@rD7Y)5aU`{!QC6(FVk<)o=8i`c zg@{c#W$&i?3-aBcHZJlOyc^J-&}Z|Z&+>8B*poACq{m`q#fi^!ocIX*zp1G98pPHU zD;fSj4L_`@8CjWf7fN@A*Rl}I<4YJ|A^Aibj&{_k4j!lG{g^z4*g9ENKg?tf_(H=w zn9TvaGvGGaCgl<$H%)M(lTWjtOsthR>nF(VRuMmaY<#ILo#1j`*`D;@$9((B6w7^O zjiu*(&$MA%VBBA(>EkP|nyV@1fwt}gad4F`X9kt|9%xfr%Q)lKG9^8B$`0SwQuKpj zkf~ROr$}T@0W!yKCOjLqmUVC9t!1+T^8SUiNg1ML2w*IJ)k1Qa!VI*3Oo-%#CDOBf zTy?B}&cLJgf{6-;WCRqrO}m}pKWO+4o5C$+xsUMW87$|~eA(O;7#~KS=*hSvyz7jh zzf$P0DEGDUK{n^svXM54qi70nnA+2s`+S%)m%>3&Xl*+pYdz4`lI_)Q;3M5-QCUB|oDaCD&c4#jxE)AR!S*jRVW( zI!;dwg|?Y!JL}c2roC9^}4w}+E9(a4=z3mZs5yCx>h z*qlTg(LKXMm0Iyl%}^T#kn6Zt6z3th?Yqu!!{G%hRGfuScbic3CWfPj{{;%BrwQGY z8ww1#t`+lM9?ySzFwcLo#r*rMUJ(=2e7C_`-~BMdLpA(9y{SZ&ib0`fKh!w;VaC}H zcfXvCjbDV6ijw#ewRlO=j1Z$4AV}T^fE!a}H-Ux-h1p$X_&`QTahR{(8oEg-Qmf`q3KOkx3yE zACA)1zKZ5n&*BPtXm}6ZoXl#jvtm)?Ug&=JYj_=9gtIv4ArnxeGxpqRys5rbnig`^ zGUaX&j9Cv)SK5svRS@aRMP7(Q9UQ#Fqws~dtlxtH_N zo(WruLsMyf+hz0o9>V;_Wvlr;RPy}R&<&pjQ*Wuk6?n%f_&&|lGV2eWwG>6h^mL%$55KsZn79UPB|O|8hvjN}(!S)cz-?;#vDAF9qhrG0X|E2Ikj6#GsICBH|k*4Sz& z2QtUYx*fA?Tu%-6ca5XySloD{z|BMyPuE%wd`4rA;k1ZA{Md(3VaT8+w-o&Dhru*`Am>TAsd`n>F^aV;S_3m2MyJ z){gY?tyCeCZn>qB5esG zReYZ77r14cQHRlR@-YkzQVLXjyS&k=($5Y(- zrWlWHjXvMJ<%;oqbLBKwA|7tp-HT}P{Mh3W@LocC#ur5rWwt$2dmlbOsNkG!I2=@$gF z3&K{{q2X(EKs(OTPRJE#w?P5z$Smm&p&QDA@{^?`ql`N!sIP-Fr?1 z7K)-mD>x%lb}~7NB9PcKf5okX*T<-?eFOQu8Bv%AX!u+$zd0*sgEM187|xWavK;9* z?n;hUkxXFuNTUA<_Ho>X&I+$AfI}=<=p4% zme^P$$i?y1Xst=(cEbo5^FP$^<=Ulyve>L*&-xuI*r?I0*5}{Mzxq=d{*nOozjfwp zgU&;TyhhiX2~vlkv$0I+6E@ATcEsaQ5mrmfwd2~$s(T5hwc}3>uOF~>#37?H)()p@ zv|c-$a)C&YYX_D<*1fQd$m3|}UU7bF$M#6y+7YeR4u9RN#fMlsuo%mxOlwDsaqWnc zYX{e7$Of;JL2Tpks#L&ZbhygwR~$woN?`l=CxzNa$Y-*aJ|}%$ZF2bY!XXs zGWocHO-K{qg=G?bo|_nDVE`qM-I0_{cie1L#fQm^w|XxDZ>i4+T*h{1SS1Uv$4 z?#8`TM}^})Hl}mtffdBcLXwAeSoH66A^Qe+jpBUVSs~8ZYC64x6z6WMD;4jgDS9F< z6@8mAj{EkihUeH6oyn|TGK(Wz_Xb%$tza_3HG`pig_K#YjFlCM_!B+bu!K~dQqd-j zlTkHs=1IoMAHPz@$ziLMadK;pjBqVFo`OZ}86?f%5)g^R15v*j$s8mdkTl@1ZglD@ zRd*MizAnJ?ZLS0|;pL1{gN_I>Zrz4zc#wWl1Y5T$P^Rd#e(HvF@_g9>!SRGHvIzWJ z<0!-br{R+{|8ka3h9(Hwit&H45}X__X5~sS>8b2rKw+h?D{Hi#>T{d(+vmMCQuXO< zkWtpWtl|5DY<{vvUI6=wC(op(MoWPbBV|ookk(TZq!?oL3wmmzpR9R4!Y6B-O4j)6 zsXtGHtbs(4^_gT%f>G8aN?Ako8THi3O4dM6t@;dPO`?=FF;dn{Gsv2CT;zZ>e)?pM zlVwfZ5|%aNe6nU*F>`JqYa)*Z%9_;2m==mZXdyA90gw)DAsy0EHQ|Gbrz~O0NYd~lnld;G_J&XIsBZJ^7Gh`7 zPnTo1gwjUF^31fNt~D#jXm9vuxPtf9ttoqh6C$}Kw-g=kiqrOnQqUpqNUZ5_zoQg% z_{=+II>Zj=hUpO7H%*7GcGh%=-m<-+gQP)cAPuhlf^_IRCH+NM&b4RYMdMoW++SzB z1$*7YpOVIhr67g3k;v%THINj6K8m1B|BU1bM8>_42&{u9Y^8!?^~TmiMyUGgQ@=)W8!sqWP1&bWXoL4E zJI;8$VnHrba1`eO#+Sw2PuCW+bK+VF@pFC(;`xb_zS53!DOyjJOu;WQhy2QLqWyOj zQ_QCKQvO1 zMGtnc_vdED@rL&J#dk8d(pG}5xNyRrbkcJyTE=yk!R5npD46`#&o8sN-HDT_jLT(5 z^>*f*_))``=q(dvWnAlJ zpHvV;e;OCogb3xmvPVX#Ka2C>Y0dNYA3v<$INs>rDB%|lx;$S}0Q&AHCmgUmx?aIr(H zXc$`Mz@hCD>Nvl=WihlN_NT&4c&MnKA;<|s2k5&cVnnM z3p&2z(}9XrNKF=9nSFraZ)*5nn_?l(67p-z7(Vpf@@J4uv!p)xOA>`U%EJ5v${jVi z!Z-z!PoOYZkF6%g=8~Quq3)ayMDM3x@%8?<9N!ZtX9pPQJaRqPpFhA%=L}YK-u9HJ zt=$zLoeS|31^HD$BpKI6+A|4b8Q0S6Sxa%Re9`~|g5t(SoHA8sY*lGQjiU>Tl@`xn1z_$`w-_F!;R`iVI7?SR8?5miBOe_0iF$sGVVM5{ivEOql!TBwc~+4>5^uC3cFoDHWb!^p)gMT!srN~E>Cnu5<{v$ z%PIo>L8J=!;lFY@#=lygIs)n z8#leJk6A7*-_&s5`p;Pzmu$nv(3+%bl&#Zb=Uu_>X?veJ=MUk zVM5x#4JKW~59qG+R;T(pIP-HBohRuoIo27=smi$n(( z;tY@O9&HrGZs}>Dkk!~}UV6byAq*}Rp(ZyCppd)!ibi9KQ9x>8dM;m+TG5Ai0_3F^ z44u0A4R@-KU#A#cY^RLU?T01-oti9mqMq58tUFa7#+54cR%(q(V!8PKqD4G^asyQM z6b^G2p{y!vk`xm6z#D_s`ZA^t5Bm3-I3z$hbTaK$Tnm>Gq^%2IRZ5i$FnjSIr1RwKHJQe#!A zwxXu8P`O`Ju!m6-gRRG2ccG})YY_MJ3jVj^-GOaDKA{)qa=#2+7Y z_v4Qb5HuyDdmw*M7W2msia*K*fj?-}&vZA8dIscRYK zX9~L+cxKfeZs1TiGtV&Ck7r~9H9r}eRm?yoG7!5@U~LK4 z{Bl6dzr%VHB${yAf|7i$~>rGG7!@@CROIHfN_%U z&`%7_eQmzLxZUf+I9>eYKuiL`lr6y~+LAe6RUNW&nQkI~(v@ zt1maTqq7;m3|9DU_{)EX-(H;!_`Qh7I-l-r#xH~Y@M|2Wz;8I?cip^F;Q2V5tX=(E&ju;_694S9c z?JWvFzmyC2RIqpyWU#i>)RQW3Dh_qR=sxJ9(0maPn>F9Q>0Wu6U5=Zi*kbW-n&`ra z)}oawomdL@hfmsHos<-2fNrh2Uu*8}8Ako^cTsd{C&L=|zo{61C-WM|U{Pt#7(px* z4+xy}Fs^al;Ukhnss5@IZS}sL&NX#XFuB!Zu|LzSQCF(BYwb<%qc*VZ#X6(ys zofLY`*%)oET!yY6mr*}AbTsty^MAPL!j9&CGPwADR)1aev+FhM zE$Iu!`VZhZ@hQLh8C-n*eMgG=FJHB&Ul9CV*p8JYrt^yJSVLG5PINHPqKu-kzk`_; z5kaE_T70TO04@IVis;J_Ltiv4icaLivuFd|HF@*e1+Qn!mEz9tax)`s)Km5kty9}Z z{-Jao(zPsdK6?dCh+NERX5@Hy359o1_;laKcz)s;;9tYPy-nenveY4QhOf}sxvitoEpQYiiYcArfTz%WOR6TT`UVYw6g(56H zbfyE#R3DGt&ZBp)eN|9fBZCBRi>~9IqbCt+ZqPFZiDknTe}iN#=&SY+}^{6W-t z?3zJhT^nxCg2mslG(ipb6HLQWNUjewJWEdlXXUEPw56Yk{6CbRNFI!l&4Rt=ucy-a}@{gVECnW3SOtWssdSZ zJd~I9F0LHz)E~cAjw^|PY2_;oPb#M>;Vkma$a)lVXtJ**Y=!d?q&7{%y;=$6Eb{Zp zb=*<;CL8$_kt=HJt$8=uw6hU?P0mJG&g$!GzJ!h`9Smz~_*=Sq&QcHLvwsUelx)6B zmcTe$8=1)IgvcaL*`GNs7;azWMkoE5os?_v?YeX!#HM_^Vz^{#WPm^Oh!psC!9!j) zW%BKcV~F(a;x<%$27hLCzexHse-Q=WF8*9(qt*pz1-@Nl*tbhL4Eo%=sOI$8UvtR4 z%PHNv*dh3!n91Gok_{-%>P%Ry)+m^av&vv4I%S+y!~KtKXM~3A9(<2<0(--!d(w^) z$t7$o55ha}xp;-XYfvty;+giQ8h%(Smz>2nvV1{IRw|)jeXlA#Nc&Doa#{&;I?`6v zpH{|5PTMuSOBoY6xun}A=RL|RqRC}7LDGzooTRH@oTRkzjG!Vba{Bz71v&Y<3jS{} z$O#CS^_7mCjIM&|ik#ponDjquavHD6$)5crS9L&7LI6pk-PwY@O3o2fn6b4W|h%dRZt`>k>Lfc6#UFBst9NC zO4bSi-nQtE9=wSQzlrnhMH(J#XmpDCLsBZu_F4hC{AdYvWGgZv$nbX0K|*xy3U^rcY7fEWA1 zbsBy!RAB&F3!poRzD|>Uga$Z0GA$UFx~4>?Fofc%=7_bKf1E&6o<<&fZc9G)n!-0n z?91!Y+$QmpM55i6y4`N*&jAnjr=Et#>i%#R5%0v)<@uuu`lFu_I-p7mhM#V(;H!1$ z0Ln7zlJQUjx9CqBKn*+ukF-S^UQMfkoCW%Ccp8)*3i^*e&GcViLc{g!=gHaMCh1?- zx-!H>{~G>Yh|Q1w3pM?Zq`VuZ|F9D1|F6=}e_u2Ghy6SH5A~z}I@TgQOwqkqiC<&O z6^rpgOEGRsXS#3B-!a{X6*u$0HB~cghd1yg#5Ucc;e}cUqAaoqv>Z`$x&0GPz--AJlklGD3EbJ2v= z@I0)hJ1i}f=?K|)wTXiJER^Y6%``t9bMd|YG!u%%YfmwJwTAc6iUeojQh2jhFtZ7A zW^v!bk*P~Xp*DFbe2|7$(6#AH;hFN`B#V3DPZ{rpH^aSfvHr>0SYeN@%Pmw?FsZOJ z*k57Kbv&-nXLa>@U2n_i(s@$-O^vs_eLaP5#HGi+_DZJoxI$4!!|&I#$yvZnlkUJxn8Xck5;@#Y zs#1U3jJVmO;d^WrxXCXLH#Lm7X~MYS;KX8<_jyW~<-}f=vz)JHxwYk;eKpH9$AqhE z`x(9|{&BT=ik+TbnBt{$ln1LwMI<{h#fy*_ER-UtfaHWp`AZXZdlry;?Zlc=|I2`P zNfMGKNdAEC_6>Bmm!Dv(;1HM)2Z>*p*&$^#o?1izPtg)jxU1xddqUwO*u+Co8h+FY zPkV~P(>+E!wa@`TjIDZ(Ut+vD+$G>`#tW8s+vCq2)_8m2<#6lp>or&Tqb|Y69fk<( zB6$)42O>E7p(8w2ay&&-diGhKqp}JnqbU*CQxR`csW@nBFF<)mQU{6mybpE|P;DPS$#ugTIbZco+)&-1QLSXO4!`<5a*8XW;_6KzP%x znEE(5^-dssP>eOgJI0iV@S;*7ys1XGu~pA)|1iQ^A1MLhJGz#L@FIVNJ1r5Om0AqK zW0#r{?z|qt@i>)8#v=)Gb8_T3C((a!QduPKrbjM#JzpO!HlA&6W+bg6I8U5OPved~ z$+wzaGWwI~2~U?0IzZAgR%Z3xVaLix6>hp#Vw|-sV)zUVZ>(SEr7Vi+6_jzYw|&x< zn{2j>i;4EEUa+eS)+O4)u9A|$@Mksrer;EwEUJm}AJzFGD0k>#E>}mx|I`)|%8FO^ zVIi1VX>~cyJfc2b1|y3M$a+x2r~0a(tej;kipom;$v_m9F1)jQrb$ z46J6)u1r}OMOExs>v1kRK$n_VfoqG8WO#cGA74S$Mp<}DfwobClEU1x)61|VhmOSb z%TMe$s_61fP;XItuJ=*{1;10*OIgM(P!8{*9lQ0XL$MJbFoEGKG`zjuh;x?c+Ex_| z=(AZ~ukIL&|2p)sjGvZ3Tm-JH%?lN-!^@+z1o7h}U3XOGsiHRA3+qNV63~c)gF}kM5(7QmiIf>gzd%P%|IRAX+eIFp*?&#uQ1t z@$#y7*2^q)9Zx@`u+kHHTP#+ah8o^X>usEsvju@ern4Jubc z^KB}$QyTqD2bKI(U)4_`N_+;W^%_pM=A8xu6a{Hw8s~@E%+{yyAP68Ml}KeVR1y%| z-=QoT35Ar!*#|8M#a~&h(-F!d5Gv~{9jzFZMV=#{vY1%Oid+`R-hyI2wrPq<3Z$5< z7is+)EVaV}mXkdo8k3sZOiXl*FBtZ$g58Hn2H1kIT71Ng8?=6rF=Mazx5}p#{q*@6 zZ$Xy3u%g_e^upTN3<-xQ3HJO5#b`N_cX0^0??KrCx`Q$uXYU&nOx{6Zu(~ykJ1BF% z@p|R07}D zQaufK>Wvd+xnOt7xIEIH^+Yhb>2CCSkWIe72C3`|23`yNcDSCZE*Sil{~^P-YWPu2 z_ngHf&$dG_Te(AED{R}@rKb{CC2SO2RUKE)c8Pz>MHLNH6>*~4U9-5_ z2nCBmwG39(N|s=y;_zm=5Q3{>12|=ME%aVq+v9P59 zNy`&~Ju%!z`LOlHk*S+9E~eQtPteWN=YWB)`ITGGMfv(O>niF@z&1g;cV4(x!Rzbo1!v{Lgh3qRu6XA;FJ8}ZaiA9!*-Hi^Wa+aS zj*jzmeY3D3ur*`&Bn{8d8v{vl^z`bufsk;-TwTHAp7rlVT@1+U3mCrp` zD_@jZCI!ec{jvoPK7^e$+@s|_XXR`|@E=1I^0)W- z7MFNe$b@~+?-eYah|*DU=;F1laGkeb1YG=D@k(6N#>L{ z0#3Oak&u>qfds!LCvUHB$%#`-j{jcZ@iyitQL?YsqxiBhj*)Ho1#1CaC2vbhTo;TBeR~+&JTP+jtUT@sHu5;?y{u-xQg9(3F$*=)!6U?|vWW54;H z*=&o1#sn3k+2uy6rYoC{@<(X+KYG8d*en_S`kwdOCe1EU@{*Cwq-N)o9LR?^(Cqx# ztjjJ7HuKl)eryRgOOk9BU3xY%YId*$XwB{x?*&UXi`Hyr&pznednX67+T%&Q_nxix z-Z-YRnseV0=7Mt^Q)cZqVU6KDp5JHWd7Hq-?ma*w6wlagdl`Xr*i@56E47 zr$XYjU?Xy;Y53t_f8-{i@%6#~2D#zIBX`V>QXuz2b2DHR9VRm!ug@38t{E0Re=&g;8~&2Rt>aUSGI3 zaErb*LLt-~(f$h!w~T0?aQ%q(tyDyNtQonEW!pZsG6Fms=!%VKpOPMXty{Q7 zMEg}AApCnuNfGUR%h(&@b59Z-t<1P|7Ax6fuo=`sa`_7HpXQskTpg*@Q?%_Lpi13? z{eF2Q6qHH;U&emF2a-4>HINkH{Cq!>6-XK(sfDBn2f#lg>5d)B6G(1Fat@n>kw`k9 z;}!N)9fQLD!5YTu&vncSJAvhMSo)}V8}=BVip0J5TcMo~I%_^~keah&LLEgS9|tk% zY#Yptq-r=T!rTyLiQV4@BJK36*a5;{MigkK3xuH}imD>u_i6ZPO@o}JgFn%`q#UAY z1E~3;gLh{WVSXzyRIMTGh-(H1n22PUBso zY${%adR4)0LJb6_E!Ao9?`M(!yvmOhW%?p&N*e{Mgfav!_*fJu6#otgB!q%mJ#dY= z&0)akl`dRGd50OJ1eTGeG)7;7=Jnh);8EdkM{PB|12F9a-sLKnX?Rs}0T)Bh^N<22m&a580yHY+1^Oda_Jo9*5} zT#AYcCe3yP_JuCfZ4=fu<@iF!{BWBA6+uug*WYGF1%V5;8&F|*I9Yr?`8ES8My7BT zV{S8}g1{1k8Wqw5XVNtTOPSt_osZ3K7HulWo@BFX9?8lW`d=IZ7(@O};Vt8qOxF8# zD*AD@7Gnlc{T+YSQkbdCEBSL3NGEPW_^&1V8!f)x0C$a*3Kots1fJ}!Tj3m82@c44 z{6qZPAwG81Qb^m44drJKawWqxe6ik8%B)26Z2>mdZFJuVfJG7eUum$;bsU~o9*aiq zb5`N=X*qj;wh<%rSFwyYS${&4ZU_M$tl)s5t^PpRcTHK6~!0muq~R>B83^vAl-# zcvi*OZ;h7(MUgZv$2VzIAAC)O^Pv!Q5uVAe5#ApryY1zDq#@8XIYfu(&&u_^A9}iz z3ems2iwe;{ezN=fat68z;+VOU-CrAl`cS+-L|}Nh!bdx78`m~uJlQn-LA`C1S;uOq ztea6J3zv>|YWQDzpGH~sPJ>cnz%$QSwa*$AcAWYVbelbKF zGs_xiLtd}^X0rPYBRE*ud&7}j1m*lzO-iQ{lkeSi_&z8)wQA z!hz;Id$jRonq%X*#hl6@4Lh8X%^oS@@{GbJ4tyCora@EFkXo)^w&>Be--Y}Emz+E#b+ zaggegbcR2y;kC8Ur7Rz*YUy~EDX{d?@jxX-s{0G2bev5&E)J~+a*a{s$`al8L~WSf zi03+zS1FHpwMREO#dqmcvQxYwev^1rPX6Q+Pd7~_yO#v{$ZE3tlOU6{l#gKk3i(J6 z-2zcg`d@VAj%0u-IL@ea2Qd4!{vTf6+cA%Sip#Sqe>v6D9b{o08yovDG%PH z5cR;{euzp?h;o(!QR`Qfh^WOK{yz~#ZsmgiZAL_0_MSD0qd-In;43(O>WPFNr6K;# zycZK*zp_ESY>p_Yj>=~BlE9vJmwoDG#>L_GOwqWgX{0^#F#nNe&)k0*k!(DlVOQ!x zauar!C$X*Ej^uMBt+B1FOHRPM)`%@&mvh$oYG$NOpU<=v8*z$X5yUEM?pijKxot-; zc(tFey38Z5v$~eSmy~W+aXNvGT7r5O2k~c)d&3lg{aJ$vZ|Ua@udLx)^<8<+%6U2} zJ@!OA+gwIcR!-+=q2}Za5%Oq=;P4^R3uO=_(6@F~Pe-|hoyqVoHT)4x*p!uVts~w& zqHr3i6N2#ATc$UO#ua~czI(L4}ky4SNY&k?OYeMl64 z;9D+UTfu6fIDz$CjonNWPm2#l_@a%=2jU+^A3Ao6EY@FC71Nlj+N)sCpehE_=?*W( z56d73jw)-bDXHPOMgC1j#ftLpaCc!DuNPsCHcaw z*P*+(FD*2DMKv|oGOMo6nu;PxZ5Uof!$;~Oltt*tItHEXubb63JE60cTgUMI8oo&D zY@DThjdP~(7Qymp={;R|04kNQ(2dpbwz^W^D|B2f=l+lTreC4sqnMmbgZG5lB2tl?WUeHz}PD?sUjO2)V7eigs)CBH?NNB+CocXEPMCgp8Y@q4jMBe;*G z8^~uveQ!lcu?s7X6uWHp&UHAK_{6TyV6Me(qjuN1G{!}6X>2%kL>o6>6Vl6{=*8e{ zl{8juJW(_79D@5M1?M-|c=$4Fr_4%Cwd+^ORw-CFe2Q1eAzAn1l50;Z>E2^F@t;{{WT*y6rLc^z2R+y4m zcj>HQDDoYARd3Sp4!Q_uiLQofvXw8c@qm9%6e_JC!q^|4*tpo9J+6Yy7Q41qr38ES zrV#Px<=1A_vu95f+OZf{$JlSmd8^v9=;9Gw{v)y;I!}_dOS%Cml}eo(uu9bovhi$t zZmgqEoq~em=ukoRI~~Y+e>KA&m+;hNj0IpHKB%H*^Kn(_;HII7KIqx5PWjfHwb$I8OX2eMtaj+P% z8ZE~a>mMpdL~*|!{EYk7Nx@{?FMxfc{Kp<9n&u7|1{&t>M4?`*z?>%Iim5KC2f?Q6 z>wo!}X-|1I(@TPQrWZZV@Vy#N&-$Yu$ny2WuqqRHz8bGP{v^yjGRqQ}edAbR+o=OOo=MB+el4dPEe>)(nJ;>N?T){C)c zRSi;0WsF31oJ{$AFW2!`i|Z4tDoixn?rDE6m23UN5H*j}Fuz-X*{Kqq`U>V2V8e8| zeARQqak^pGbnOdooG$F!qUe9o#;J>O@BPy2l^jmOomSS0+ zE7%44-BHewCzrX7=s^`rF*^x*cB0$)INF~126iWJmsK+}4m0!1qdYUCB|LR7W(HvM z%p@2aO*GC-lEuuJ3F)qC#Ss#}^EsU6VM6fTFWIwQK~jYGX!=B7d)6F?@TN2aixym; zKDtFV#qjGtWhRc)=fyCml##=HN(}vfI5SCCutzX-fX$+t>oke9ho%dW_9Sj<(u<{E zp!-?$4z&=%XY7?T*%ZrvP~1Gx|G~4a-+$k$xZ&=>@kR`8gVXWeVA*JH9?A z%RU#(E=`}4(dWO~SoHasAVZ&jPUk+y`t=!LbDxs~`uw-pFM6(AF!Y&Ko2hXs*!&*KXJK7wZc`XOnL^GoKGk$A%C3pXiMXy_4@U7*s zvFJ=N@WZ@d2g((((v16^J_N*ORFUe&475^~}_&E5{^~dJ3dWE~Yw)R8G zFfo*M-fBLUIQt3@?=uCHECH}dRnfg^PLX=U&?o*G<{NOhdm4qs?{wbB5*TGxjF#~_xnD-egkagh{S+?|0)z>&xx}J zj<_eU+zxxzTr2`jsK1|m^Pepj?aBknm$W&ZdywtZF~>!@Pk)m|KdfTk0J{1Rt0N- zJ_Bsff@PJa9=|+Q^f;TnxaqN&g2l1Rx_R^M*^3mH_yWYsndC66|rb|YR#Ook?vYTDQAo1cqmGqgQxYjJcvC~a)rJ$%qunPUFrKy+Ox>; z(^t@2OCEXo>DM25x5$WhXhZ-F<{+>7Qe18nT_3R$VC%bnj6UG80I z=<=nZ9WL0jT8UAR2wM@J*%maysi{7d4*gwNX~IJxYMVL%#ssev*b(( z==1Cx(trLoNc=LMxqtBe=1qN zN;LU<5^?AKAtY5r;_fv2g4Z+oxG{cxZu7`#IBcjujwNGH5_^!>r#e+A;#A$eM=U9Q z>&kKPf?~u?q0ER6!5Y3v!#|-`c*Z!3!gw;zEmN0_r|D0Jp$hrnf4YWu&{e1h|5;1n z2mkXL+w55tadO*Em-q*!(g zIF@1g3MP*p2uv7~ghrI$ZvGO}(^u+KvSvK{GZ&w!VA7gF;4Qc#N4qdWgVoW)fb(iB zHjJ?y?((f7~An({=C-gL%fl|aA2M|yP8d%=f%51vgxPGF#m)Aeo(r<8G-te){bs2_s zi|Zea!{NF-UlK8FSw`38JcdZuv-@zbuglKbG}oN zyB;a|R0Qk4)u~ATBfP%*@uR1q&k=^M@zE0Z(?5nK?kPOjy6GSD5=UTjC<>0AB8C^? zp0viQB`k5GsWjXu`lQg`7_D7LfEp*m#2#J%gG5i4y-=+m2Wz|2`Iwv_w z{EPO(OamcVm0eaSU(gPZpH{UrL+vl&G<~;*N9x*6I_M(j8k2x&Nm(I^9d z!j`)iNozP~)I}1C#Dlv6a}l*I8%ZZ5kBY=y_kE!%?K>}hG)(>(`9;b$vL|@|IQlyQ ze>>^#MEW~dd?R*Bi>Yy1J)~yqn9&LLX!nHyP!i{J_m<&Hp~0<`-Ob~YLJup4G>Wda zk#bcIX*B=!K_Lx6gLx;mB*U2Q++NcQqVblbsM5gUC2v=}$gKQF%@FLk*vx zi{hH>HW>n_l0CbKmYs~E5PNn6{tC8dpXb|H2@4<5P$Za19m;(S3F( zMER^K%ce{UQ9eVYLgbbt!Sxvwq62)PPAf!xwn8D|&q>g5x&W=nyIjAp@L}g|1pD*p zMO1rw?4&4`;|Ptyx)Bw(ocR|Eq$n6FX8j-nwsujlE|_tEr-SMV9_!2<$ehC5WaN~Q z?Iow|>_?lx>CCy~kq9|QY)x`*eGb0_R^aj}Y76=bK}JH)z405Vt3^Scg&_HpBvEv3>A$;sYa4S!}lNHhHq6cCmLq3x#61LU>iGI z7+Ynr?rS#8z4T?#Yz?wr*IeX?!$S==Bf52lH`sLl+ zlbRm$&>3tV`noY?N-^}6V?|dxUo{L}bR{*%bLkrQpyH^S;{O%wnW^YeMSCWBs(20} z`zE1YA)}H#lPJrx5gAqO*|8Bk8oNFFPRPBR?OCbVe|L2&nbQp_&ld=F-b}+|wJhQ+ z^T-;c`fJ{W%yEbp=4P&YkJJZJzU4~ck}HHutqi1CWLz#gqL*m*yW?y}d=ZyXz81gG zHUrFU7l}^&k6ldHQfeQ}cvz^imlfgibzgV4Qm*xS@{6&5Xlfb8|VxG*{UV zjZMg6Gx@TQaRlS81yg?rjND?+d>wz;?OC;XO`J44K@q3#5Z41Hg8S-~1{oaaGJR3CQ zIY(84GH8QTC37|07qkIcvYH&Z3E7H!EV8<1b+J!EjOyhR8lI)ALzb+DLa`{f7njfd z1>P#^^{2r6X)+&H$jdeCS)Cw_cOEfHUD1(Etr`B6hS$+j09k4pfl^GN+^EfvKf>Jg zrUv`yZNB972#pgLJGv;uIGnmMa%2>pIErhn(HicusZJovu&B8dzGWvCt4`35mGVcp zkK!VHR7t%skR`j_>?w~QG4AIkvfB+6lWsSpWqIy_Tl`>b9Py?#FNsp>ihig4uKK+a z_K&%6VNBBS_q6>3Sw7kfleDO4Gu)3hBSQE9^Hr)ZOxM>G?G!>mD9TsxyL3CqLV4%d zqv;?7n|*3#70)57Wr!W7*Rd0VT;N>*Oe6kIeBn)d0WGO*2u|w*H&5zX2f=mqgTrdv>%lR@u}99(@EMw8kX4%Tx$h5A^O5U_zFqB)_$DTG`xP5SMkrOc z6%&wixAZ%cfhfo=Ja+c=UYu`7%3`M=*!FlsM!L;ES zy7DaIF+KrA-i`zj4?K?{*$>mp3M5HLnjlGq>7|oZ(1vs*FW~KiSASKrwft6|#b!}F zi+wfx-CNZx%B;3JYXpjn9mDX4HT+p!gtF|*-y_pBuaZ-%@TZ~r(^sl+6$?;x;UNWo zzKW`Xv&2O6!CS^!PQ?fH>4S_+{>fNdY>=-j%NuZ;Cx3*wKTR%$3aIShK0QJ#^<_YM ziz(fT=h^5#tlo)o2c3i+^nH2|<0>0%7gaU9pZ5D!vHdYP%4^Q|UQI!LVR3+=LR%+b zyHM5u?pTmpTQ;QaqJ!Ygvspgd1*{+zwu>Rx&aoW}77C-yqDXQp+bp0u~?EP<5wJ_VLu{6#N$cB9_ZNyA^(54kD5DM9K@VN!3J?5nPhF4ov?)SJp_ zxIF*$-Jt*O|@_Y7x&;Dn2~L1Iy%}WE^@kp(20gmTW~&IfdBp_cjxYt&|AP1B-1t zpxS;r$jD-gH9S=>X^O?r7s`8v=j=vVtgv_%d-L^Duvn$bH^gFv#ju#$%wjEGdk=9yy*U#a0sbrEFw zXfaK$A8A-WUZoE+a1kJEOJ-z_fXWv@<_Dt$UK)3F)s;6xqcYZ1GYyZ_jUr1n=Bmm! z=9t7}tSNi;3v8uP@un7VyZTWGzm|XBr&~bO%q~R?|5n38bQDj{+KPa}HYFsk&+>gQ z8%&OTRMlvcJ@*366kgEn9LA>aJp=%1t>Jlk(}yfs2jxv1gi31bk2|80C@3i_DPgzwXTh2u$h8QB}iV)B+P(s&|yvhEZ=4 zPS-iR;OB2Bg>W*SUGVzpI0?#g@HIZTcUu1oDf!<>M=b#Gm z%~!wm{{Rc9AMCvTr%L07a#RUR5-6tVdl?$HQSA~v}g5j(1`QM_gu z#jCMZj+^3qBLr2m^Lc8y3+oeb!fz^hB~5d%HQX4=>)0`Qo$vUI>*x zUBTqpK7ly=YH~|za+|5iEvad&fXbIGL#5UdhGpWjUDnj})~@2I$z3XH8f&B`W2>Hx zN0^$j(@LPGivL(rliQz~qKl)ZZ54~5ru5ckYKs0h)FfsoWv3syF7M}=OWYZVE@b)8 z6(x23s9+Pi=qI5oTR`Pwm*XWH;(cPrmrInfzp9s}M zd-$AjXy;p6P-56QJ+yrY)4BYtZ)hU{YKi0?Bq2!tM9lp|c=_#XB(EV!Dm1QquZV^{ zzx_?`KhBXW-&gSWehbO)zkE$@I>n$5kc>IS#6NtyqPIz)!!7Xs@2cS`n)o?Otm;Kl zMirT5RFRZXxdJL*nTwLrA{sKP+;(fC|Lfc0iN2^*GAh?d^u|^_pPgaKI6Axp%IJH_ zk}`_?DWh1Tk1SUV(I0C5Z;3t!$p9p?3pmL{(i2HDBnyvnGVv%MMpj|h(dpaxn06pE z`HA8eW|aZt4&hR^L#gm7;~^`2%6Mqh)Z9(z_TrvH+(^~b4?LrP<3Fq0v+LbM^Hg-J zJ!@Vlw^wJICMtN|pUeaPH9SRo-gB1u81$a6gL$%WRyl^YX{n?t5`xIhpAAoIBNI7Y z7CBj_Nt{lJoQ5sfds|gwS9qCL?*C&o{MYiT6UzNRnToRe{|1WFm(`qm;Ap3d+>feG z;SK6XHT-5>6=fOUa9aZH{3iYB`|yIEGL+$GwkY^$?FG$Q^37Gg1yU+a-JRF|UmAM1 zNki`*Ws$PsKX6l;+-9U>AWe0LH$hL5R;aof{)yI;loe{cWF&j$SQZ2~y3yO?vqJfA z^lnNi#YS(O`-V1pd!!Z0f1|g}Y=z33VZG7YV=(l>E#iQlgn*6Si6GwSJ}FV7!uoHikNas&ebWY(g8HidaYNL1 zK(1l_)W@^uqrRu6TT>r;Yob29XzfpZqpupN53NoUNNyyxhTMk=b@n5nPs2c@FE z938H3Cqfcb%mcDg`w9dWVDUS@Uc%Y|c?=G`%;GA+UgX+}TNHGSfE_>T{m9DIBJuAX z(Ryuk;wn7wbC3+U;KfT}SwYpfBQLJk3Mfu@E8frWP8z;lpYBqYefh_FfuD%e-MaeI zkvQF5IG^EFG`zDu-Q_HD6vrB$&w|3F0-bGhqigvXtmSECw0o6AVF+mVcb3-sjrQ_~SbWw>7}2<22UswuWeqcgoHt zfJ}PnI$c3VGHI*fgLGT!4uXwkE!{zA&9c_?o=hpoWJd91a(~}akjcE?%w#g--;v2Q zGnxGUjy0Lg&}1^|SxF)`OId3#B3XNi&!Hyii$)iu0=u3bM&gAfN+Z`0Vbo6*DNhV4Byt+)4n zjeogHHBt^Isy&x5{5=gnu1_kFRVt2r>o|@&!b!eHkQk1l9b%Fs<77@VBU5A=ULLMo z6C%UP;|nLtjVY0#{Ch9a1%t@D>(8?ICV@GJ=D9Jy#9rU&dPel4f0)npYnePzSr(aA z4i#>bX*#D1C6;{=V;!0K>V~5gD zv2ID|wh+Zv+azD@fh2oxg>*quSp^riRp7T>#z_TFR1kY z(e@^ARTkg>_(f51sY|(`c@33}a>I`sRwO1Gl_jPXrWt7qrIjU`t)dsyE1+g(W@?sc zw5gSvmK83!mbv6oF1dTJxUb;Gf6jT&oclbNi&5X--`5KV-shP!%QiKv95wYT+UJ4h^;Tth>hb~@f)#GRwHIlyfhZcS~C&Wnu)a5Otg3P zP8crZ$D|t*vi_g0(bimC#QKz^otkW@+)E-7i}I{iF1t1+lHv1A1-=50QR_sm*n)2j zo-7_Ckc!)s54e_Hzep4}MkjOOt^P{zCuMX3l2r}bhlm;scgQ+gtoFCW!$;jmSXBX2A8`axgX9v_!0x6VZdCzm!oF8lvYYyj$FAb0{&`DKH+8ZerT_B+#+%1$26t1p zYI^mhv}@p|K1M?hT%)Z1dKbZ9tfJleO@L@dFXei>{+r^W0jUJhq&sBIELk^_6tvKl zUk4Y>oUgAcnv_zBCfzC;Yr?)Azp!XN>UkB>L~RZ#nv_7%l(>Sh_h<>CncVp5D+vE2 z8Wns5_s;N3T#i2q}jZ+WvBcUbL2DW1}GD*mFV3F$1gd8F+{90sOTM z+qM@KS_jFa6er*73i3`Ht;fj^VwT?wL3jc4_z{!+$p~IQ&uZ$P6QHIIuCNaEn^Rm( zK`KE_=_IJ$*HNIg#Q_TvIVZT9hRwOEnhq$Hnr2(o)S9r*UBKeKkbD*KzPT}|cn6f) zg4~{8f|{Pb<^N_uR4@xmxg+r;;$L6!gr*^e6u+v!P-6u6-h)irAVvfQA-*56dU`#A z(^&V*f8;9F@xq3n)iJl!)zSE{R7cm-*6P?F9i%#%o|fu3af&m!;S}fm1N`+Sg5IaB z+CEuv@=c*7-nk>S=WQU?c9Re^NANM0b=_Fjo${s8wMu0$jUUJLm?3z+s5z6gH!90D zx(CM9UW~TgJ$SU8q0s^v^F`}1Ukn7)NEmCsf!Y5jxZiJJM%$4x+Wv2TgA*l>w$D6N ziqZCq>+GZL6aQ_r?X{1#KN}Hzw0*+wqcwhm$e<(bt%t0BgA+k(+*kIbRY?XlWWT|f z%#!^EW%bo2zT@!DHpAj^c)ni6&HN&dHK)(#Mqo*JC~yEytKBPjb9pFmK=C8(ADk`Y z@ZSxhPeSE6P!$|9kNIIh*6UHJx7)2D5>IYP%NT>Ho2;O2=zUQg5e#T4*JU z)_;Wi72+RetxIPY75QHJfjh0%U9ZwC1`E2&MVh+UXT7$=k?+~>AY&&`tqCW zTkrP?=){h*70Lft*$&-{zi(Ok=>@1Ig6cdqu;@o-8OZ4JOe2fKkkKc@89yNST9FZx zls1Hwfi_U6KA5Jpf&QfN7@a-V3X!NMR!JC-jT5GQZ3;0&@PuLt!HES^h(XrDSeA7# zW=r+|jZVz|Qt8BFi&!V>ce#pA%v^Ok*$0aM|s*)^}O(ES@g|wym|3)EQ^sdXV3s@oF?tB%6thVB+3b`uK zNR>FBT(heLg&gh*u8`6HMIlwN1#`#m5WI@uQ3M}jy5YtYGX5irJ{IB9)y5y$^^ss- z{AH^?`c~meg3r$Jh%3T5l5eJR7bv}4@`J`QZ~BhY*fCx6drhTr7DtU&8LSV|VAwwT zii-}s>d^1@%Z}Q{14w;pdpG})V88$5&3ownlX;x&$?9jg%9Ls(vEiJ7yQdrdj10%z z8L!(k6Fel`=q-_~tK@U=YI~@B`W{Y(ev5mej(lkFA#yU5N&Z#xaUp04r8x4upwWL^ zJs%~DbfffOdmN@Woh5%8uEl%`%c3m>|K?hgZ?k$nPAj=HV=U3^tLNMF^k%o7-gwK) z^rk>hZ^rqTMXhHqX?j!ro*-v01E)9RmSB3bTTgGs6$X~pua6f;?)17f8Nnp)XQ_~SxV|3yozHbCC ztYRd~K-?$vXO?TGMx)Cc=@;nHltcS}J}~KwtzdO8 z%oBV-1xJ8;Ax7K__p^@L+zX{>e~}ahZ-4K0EJgbZ|HCro6g8Pvu22YmY>;@$u95vhGQKJi@yAX@%4gVc9@hjX}*y3na3eXj87HZf94US z(lkwJOx!0HRw*j_|M$$}%IO%Da+)~vNWc2N#ePi7nMV~|!f<6LhSBpTnS$OH$`$a+ zQ(OU41ivBFQ~*c;*Cey?(zOAr)-zf4iaAsbIg6uWxsWcNAcd{4T5)<#XXR$hM_sp*f31dNvS@a887Cfppjv^CkTf|=DlZF=a;ee#kqq2 zTE=1RisS-^?YqbmloRc)GC>)*D5&fIgqfK9qwBx<#u8RSeBu9gCB*N?{Yu64y{aJZ zvKO^0Hwo_ACJ3&*%&}HsMQ|1uhHZR!)GxIZo z|6%2=>IG}Qs#Cr;(~?^wldmr^HS!>M4ohw|@z)v5mo{U*6h6U7TQ9l&lEQf_c*o%W zB{z^tP&9foLoc~)({tP1m{EWAPH;tg_noUMT3)FXZM0RpY*I>8tb_F8Xci_BDfd*k2?qP7L zH=Y;nZp9e1D#hoR07?+;2#4&)n51iXIz+qi?ck#Q{_U%Zc6zBqJHjejYr?)mGg-7> z-hLI)Hk%(*w9`v1+M~afAljK#{)1>8I5xV+wtU#Lir-Db>x|xK`{`xG=lGE(-`xnJ z5e&mI(>{2w=%H~IjcCjl$h+E)vugywzMiLS8d1Ox6Z!r;&Tfs`&WvYQ78UvKnZ@Yy zA9L^kf+z&#CC24~I-tU|7?^5Mf^a0D+vw-vmN zFkn)S>s&LfHL8bK{rOsA=dMIwE!h{E7_v*h8FDSZ8S+3FzZsIFUzLsUrfxfhm!n3} zW6iwrG>e|g!EiB^v@n@`8Q!8$oPD5CblR&bOS8sk(WI(uZk&(u8!QP~WZ2XXYAeh2 z{1}UzqkrUxJ;vDO%&>cT%rc9M^-J|LL4DiAd>f_W&)mcDYZ_r4f)AA;ER);?W#88Fuang z*@0hDLs0Jns4^3&GPkIopHx(Dwn;Ax`FQm%X1QK)pNwlYX}*wFVkkUrJ>yda&y^@l zQW=O3;f6s^36aAg0%o?K#CQ>$&URqDo8U>p38enS;1{R6IpH~VZgnoWA^qZG&dfK_ zY-&ryr_gM6ongF;;GLw|Fp1qSbdx5%vE$DpH;H%4kaEyIY}GnroeMhafioS_&G>@8 zrPh|CzYp_1R0Z?PaO+!Jqq4MU=&h|O5sal7Oux0I;l~WzNqsth2V?gbtSLSPOg6u0 zHFjAR5jU5fp~xLNM7!EOb6z*HjD?nQyf0N9jg zBNjS*-$MTV8>qI;h8okK&;#@(u(H0$l<1%w;H`=b_ z43|R3)z2uh|ElGB-B0S~{}~3hqY-pP@IM6M2u@;{`x=6tD)8=ashaqWm-H(t{(k}O zy*%1`61DdMB&;DS`{^E2IlH0i8&`0#QUzZks?MagYn)^F_Npv4zjdr0_ePaMSPO>8 zsh!Nb(4uMyyIYY=4P56IB6wvQYv>A}-QPq{Sa;}Ck{gS9r z4oGb4bB?6_vYnMurY7Fu+da1Lvk{Ri^W4 zmi|UmGnMEJ);zwvSM@sYSG4$U_?b*SZG{sdU8`xBH?N|<5vKJ~#i*c*k=9ie?OX#c z+Ub!RYl~t5P9QlF--G1DDIhDfm^?+fhCc8(a#r(+su)sqTYetx4_G(IVP3Y zk&1=~8#qOM+P^bneGI0bZ2+w5x%p95#a-=rO9_%UDsr1=DYm}GsiU{{Nd{(jS3wV0iO zEyni#kb{!t_lJCK9Q6JWA8E^@f>De1Z&JiUiON%}5vIQ9w&D7AJ;At3@VDC-g$2of z%qm5m)})$!Hpwz*Bdu0doRZi!-GPT*H z0M_Fj$kI5A6U=`K%)Eje?(I~88ac;D(dFH)ZYl>cl7q3WIcLo=P>v9MKx>mTkccr1 zZn8Z`*)L!@dS`}-+7vAR{FGV#BDhmnf<#=}ZgP(K84u)5kq+2TB++21!}hoxt+c4B7hgPsL^IY?Rf^k@%| ze&2{MkheJQ);IAx?yzYiO*_^sj=TG2!EuL8YgyQm^@0&T;b|ebOqt zZmf5#3y ziXKz~nZr#@$F*Py^l8KR^McoHVI%;OO*=Dq9n;lLzV463(6M(jezV~B%VMY|RS{An zL}_`H@iW5=UPYo1$+@6M5_hIQ($XMa)kXW9F71T{4PLRi!4T&K9kFD``sRO4EW(q3%TeXg#1 z9CLJ4lyrW>IYqsMbu!)Hvt7=t+}TBZtIaf;kF*4wLV#EJ#q`T z^#nQ(sb8WJt%ut>m9_rs#jN!`_&e5miXN=yGoU6}q(n61xy)X2*Q-NKyLKajTSsNboa&MhwwkKkLzurTvYbFLdIY^Sq#b)1u zI9dLf;2v2aCX!;3Ga}}UOD000O<|FJof0D1`n0= zh}8Tj9VE-V1tXx9Z}NC(H`?tBgp7_=E5UdYWj!oL!oR6@;L zm4B}}(3uc*Z=CMw9QfD)F@5m55yu?cX->D`B zjP?Q>%41W|PzLCR!u(1%+Oswkt|@;*d9OPfN{VhMW|W8AqM=-1UFU`}DxjfYl(%F) zHtKnz_b%f6;hqd{I3cktVDBk>5mC*cNscmg~iD-Jmmec%nnUZb!`d3+{@q7?; zm1dQ;$!YiSDoy{W)I|Fdjk4XU+V7o5OEl#YJyrA5{p&O3PM_lOyO;Bu5S8jnfjjzJ zHQjEA#hD5eIDCI#X0LB`9B*6h{pr-HB42ZIS^v>hFRO-O%68 zFIZQ%R-O#3y-%?sJy+%HS*$is0iT=b0<=WGPer&`f4DYE2bd6R5v-~sGny+?3)%<&B z=>6(0T2o)Za^rmn8lUD2{fQ%t3lO|_iZkT2W+)QN02c?^GeofO7W)O=N3kTi4#AfQ za!xYO9|jsxJ{83xp5Ko7&Jes)lo7EejT*?q$9=F+uMITAM*vozjB$osYQUd%VV-%( z;Jdp4r?-3_(^^P+OB$H;n8b#17GXK5DTymPQlITu(J@T@R8&8e909(l-&m82dlK@D%yQ1+q zcUfi}G*0)ZJkd8Ux(KA|;eEIXQPJKjhbUR@sk!sxZd!dpzJT~qy`t_5sPk4gS}O1= z{=XHc{VqReMp0cZL|ZAup}JhS?lFwl6MR)&Q#g=p^<_L6NHtedwKy`ur4AyzW%ppT zH%iM|l{hz-ja&by==f2&3$;X0bmxLe1h5CC60$pbfb_^N&Tg$1jK3`SCYQ-BlQ8)E zp$>+5L*VR~M}KCy=4*76O!Ow{{(rje|Ap&dmv!(LD)=Lkni>4Gt9VbgspKF0vU=)f(nXYiM4B^OY$1s#SyYdknXL#|VC*y2&q-R;JH&;2#N8r{D^a z&zDzcHoKl+-1nTpX9^o4DO@ab|nskP1lFaRnl4`z65#7t zT?+(1BzMaa$ym*aLeImUw9RmA;w`~Hl6XXdh05%X8*P*2t2+>TE>evb+$FI=`o9^U z_+8c(T7nT$>E}IT(w~T%Z0mi=`N|di6}ib4B-_|D9`32vgMO>4tT(V9AW?5&CU{rlDwrX{aiQ+oTWFM=Z1)SBc{Yp#f53!t+; zwqBSL9<=6tv;MZuXA}0EDl%#2ul7C^uP3$ovHv#_^v3?$%J}O9Tr(T6IpemcjJ(R= zBS^XYDyUdSeHS4za4-32!}GbcksQzSdXp`i;37*7lV& zhgaR{+Tqp0mnz%2RchWXyGYyS`5j&+Enhs`hPg_w%ERk(h?FhFHxD{D5y30i*0-XM zsiuBdLS7Be#%#em%M!9Cy(6Ss5hV!+H(wXLvP2=0b3u=;Jk-#4?|19N!_?V)J*}%F z#o})nAi=XOY!wcx7Yke1G@NZ=GmR!ni(I7zvmWYj?g^8LFUneN;V!|m%Q|efkTzej zA?(j7{aZsAU$P-wTDcU4FfPMx2;={oA&j*f!dLDHzCI9d4B%Sl$U)qow-M_h#TN%Y znaX2{IR1#OV0;O6?q6$CoH|n;yrb4#DYE= zO5ar{C3r6vno@Evx9$Jf%dNV~{J&x;gqt$lF5FfBZOoV#F#o^p>b=}588b>Rw=HNd zm-m6Sms=II=6!kFti4?CzihqSi*5g@m-9z$prZP|rHzAaO{^R&KRl1%0jxr_=xqeL z7|Y>>O<2%32tHMo!$F#0U6I=4%ua-%IsBN35QAmY8%Hy~QSj?z*_26Qd=^%QGH!#4 zeqEVW^c#(OrK0c@w7zvM%k`=-{<^GHMV}CSeAz%19VaUKV%cIUnpE~57xH)eRdh&z zir!VB6bt!34z(}j?=GgI1FR}KM5}0OfQoLjtLXVQ!58v(8`V_yXNa*s<`wq9h5UN& z2b!SWCDeQn6I5=^RZLJsMMx4aC&pb@k>z{6MyE?E3w1-lsXo{HJ%gK|VLeMWL36KW zf=VIZNhQm-Pq|XacjudS`A+(8@*QWFZ_U;)L6EQC1Q|I`DsF=22ACkoIPN{G37QnN z=6!LtS7Wwswwa(KElY2Lrf)VTXn~0}8n)*d1c?Z|SkPRJ+onJ6VZ`ey%VJM}9T_e7 z6`9v*(u+dcQHG=3l+5@eg8wK{Kq_e`*ckfG>;$_#F>7EL?3`YXcNYwHX8sT6=R&e! zUK@!<;GV_3f?pK%B$9K%`-`<3DC09|_;>Q@+tBd;jbi*m!Cw{@L?SQLXM7=oEaWVO zPwIJz(H5L$9Ax|$vi2bz|4i#F2jk3 z>}4R>SM8XsCX&IWErRP2oIYYT7cXr%C4GqRD@F1SjnQV~4cv9w1Ho+wb{^*7r^B4F zeh*nP)(W?BJ`#{If_={)v1P0~xU@o0;g}L3%twPE2VdVC;R=*gJ>z@-tIc%@njxwOs=)T zqP1xt*zfiBul^7tUq7z*{6EysVimcto27PsN@s=#y4h=oU|)-TTkTwXh->HgL9U%| ztz6Dsg8d8NLa=Z4LAyd7ghGMK^HwgGnlhIj0bB_7eR|l&CF=ll>5rfzf`$kV?B`&` zeompXHHCw?(Cz$#_7n*AZQXB6p(nW9vEQodBi30|{oFpK>Jyr1RsUr#fB!K8H-d%; zD)8!#EB!%BR%&nMtn?4a3cEX@>8gv^L}fN|E@yU-!Kx#p1Y_~dHxh+E zq<(%^U*6Z%QfXCi31yqE_DUnz*Tr6G7ts;yKycmP9Guz(At7+9fOcpM>ZEw?OVT`B zsdT<+!0G&MFc;EcSb9zB(0wm5tNg#!&q@_zYLX?l{qY`>C&`{$f_;zd^5<6Np%Lfd zacdqP!y?yx0eN6p@<9E#FMp>$4~kb4=2g|otJxjQtEh{e7sJAfR*HQe+Iht|GaI6N zUe?9J?_->Ho)f^2Vd0lY{JL29c`Mv%-pby=0+>jF!`BUe#UiLhL5S}%-zn<*7QqAr z+kfR?@vqiKd2)?^r0W~3NZz7bbffIJmcOr$psWhK`#=lvja|dwO9&oZ!=>E$fJJ`y zF6C0Le!wn2f_>4y+O+NPYUZ*Qfd|2J2==VvU@3xB1ox=G`(EL>BHyW%_Ve;N2~pc{ z7%+>LsD~Zl_57@PIE19y{{yC-KUtpJ|B+YF{sr$?-n4%rtw@OKNW1jgo^<9!V+efy ze)DNnuy8-a_}_w`kv-ZVS!ZY)__}S^H~g{LoHZYtz4hj-iNa{2F!FECdY!NmH)oj* z>%UQs-HG(A?T80qmw1LHLgN?#L$n9s6__qTYvg<`G3D%pzV= ze<2eZNa<|yHw-hAU*BOoQSd%89RkVB7qw+KxwK|E$OiV5+lz{fLQx*0M^U!3s2Yow zP_1Wg!@&3V`%J=n(bX)g&l&no@MSVPA(E<)4O}4^15u(e@?lRfxON}og9X1s7=UC| zv|8E~p)~mJO4{efrP8jDELT(EbI^erYtMKM!B;vQfy){Rbh*brZFRoeY;~sAM_Zk5 zI2)?n2toGiPJ2Q2>n6y4UFuWGY;;KU{6Z1vT(f_(Zuh7G>2Xhulugbfgt<3z#i=5F za9+joJ&XCyB4suHhZ$2<>~P+VzU@Z@(=g?^;a-acYj=dJqr$y*3r4Un(msu94K6hi zyobrk5a_|mdrWoeD<#f<&3xww?!Qt3B&!%3_{G?XZ;@h8x?WSvay=(ZPTOSopx}Q5 zlVNI58Ae%U*h#NTS<>^pi??|0KYbNxuJ0dInyFlcowPKQic9moOxbt+s_j;xF3T+f zP4e|Z%`Z?Dd=ms(9s=Eh%C}r8(LB#L5nh)25j2IfrB$Lu%H1B}3agiBmomY=nHT+1 z_KvKt`^C4g*Sjx*1Z??^#$V+S9K;Ji^ANmCd%wM>RCm>_kWaD)-1ktQWqc&D`S#)h z_S|g*c@_fhg_{ar5`2pYm`ORVF^^Ya;}y&IrnGRt-=#0=iBTV1lT?A_=S}+_`?*<& zk+>YiLt4>4DmFc?Tn0(xsYFk-CYQ^|Fnh-%aj%Iv3y&o(Pqtq3U!F*f{$LX%qki4K zsk}C>Ij(jYW;^*!qs(^luM_q44q@Jur2r%IJ*w&&K*XVR`@pP|ss@)Rxdzr>jZm(? zSiaB1R3Z<~`Luo#T z+C$jPcgSF!5Cw2*46Ar*Ojc?%U0dO49OXUm)`cSdvK@OldqpK>5h=Ct%J}FaQhN9D z*kw@e{Ar4Hc1M$=y2xoS_)pRVFOoh@lX?hgC%VBJgBWiw_)ijrNX`YxvE0i(!Y(K^ z6>0aIe+uHv#J&^0qDCpq3>!^9^m{OYJLYF`z;RoG>6kUJGQp&L6!vfZ$BfSre4W@o zkSH}K%;t`;G6pQPv`wC34_~9xBNDe@$7iKQg?Z9c|B%Jwie9)ODFSz&Dg%;&o2Qg9 z9YmK+wbiNeWm9kQ`Bc|U2Gf^K0e%(|d^X1OQe*XzBf(-c-g=889_e5=8VqY023|Im z*TEEb0~&JWUzta);NM6?2B}Fol382tpeNBf$k=8zIYIeQm7(l+lOy`~2=A@OP8ON7 z<7q7w+pZm0C~G024jqh8)`~pk0+v{x3$qkg2TKvp<^tgle|IZU$=&JGoH2hs0G`|DIxMm1^`y#rAe|v2_q!fIo0M zg1Znjpc{8yKB{cSZx;jZ57F1ByBgnR>i$p2#KYTdUDX8tUStANkL1K*7pd9?H6{7C z=SsdC+YENKHqsh&GR4T7>wclI`azEfy89!PEK3T2@;!I5pLfsC3m{V;n_`}lDh=l08Yc*bt)9(JQyq+AV zsXjIM-H);Gd+r#CF+mlLl)79t5w9Z_EvtM`FLxNX%9}`i8gP)z5e8$L+z2 znqpSdFl(a{cntT+mNnRoNPuBw)zT_wr8f4YM*I5m93=mwVzpEK{NlmYkSfR^+2tQp zvg>rkG>bs_Iaq#Ve<$B=YH1j1ss3utz;KPHJ&OzwY#Y^Qk=f-xvuFsUNBa8`%n)3E z7$)74x8|ElXgR#2xiXHf(Oz%WF?wB%;c29MFMUI3=-r6(UsOW=Ux5Cp37YG#+f4o+ zgw9>Yy5Um6TZqnqTuKRCDq}d z?5$PNcSp)BX!8pHEU4`(W)^hg>v|T%r?LGLp-1KekM^~K6<7g<`jixE@_r?dK}Mkh z@>AwNRe^0VmkMOoeVv8Wja(J}5AlBfMMUqU)(cHpUhSF;r3MjXu z`85vi$h>Q+pW#V-B0B_VJdla&JY2cLFBa)k#nI7mg4dFCh(vNc?9BWXR^>VQY989l z2uv;>6#QN3KbVwL{Ta$smMcbokv34pI)|l^ItJ^B7=WKu^W63k4pyluQRYxl7#XQV z`Y+sji3foCBElpY`0)8sZgwf-yon9Z6q$=?KTZVhSs3h1n#74#7ks1) z_J}mB(BTMiywO&Da;mk?ml|Gu@%K26w##7Qh(hoRYAICYBkJc5_0gi%JY;UkH_Eua zpeX#Y1}3*QNtZ*G($B*F34Tztfk~b6)VE_)(0q00wyT{v53yyU z(I;Q7~5>L-DZEm4_Z%^Ums!DQwBsn5I-FE9>D*owKmf~MH#&P~` zWiLL##ftxZD=z-WSOxg9l_|akK4@jq-3N87_PnH4wZ9WgS9+!`BsmRYhqEyX8yg6{&%iNEH0Ms4|h#FVIjp%N1>M_y~=ap#jwl)=rO=6+9{_p4`H1 z<42{or(bSUzuaY9hKZ&hPNH8_N0O?9usoWIq-N{+GZoLg|CxNGqN$z2cC}o=?~(jz zQjU;rMwFXzU&tWA!z2nwsga4pF4Gf0Z_!}te*GOLOE4sD4Q3`wXSw#HWz?>|sV@9K zLMt4OBV?DG8+^F5LQUGMNomih&yUn&Y@NZn;8VaVi!0-~H&Hzq4N+2QI53&o97YMp zQ*rf11cnOidL=QUoO6<>PVz^tw}B+ z6~NsZ--hvWg8wOwVInE1)NvPFp~$qTcw z`9;RB6MVId0f^)-sN~FCh@sojrskXJ5b`Z?jBgfvm2E~EsQIt@;@hUU6Aw$y zGwFN&iUAU&LdOc1mf$`J+qYg3yt;7Lq+UYOt6_&=ND>71uZ9uHx!}>eNI;}#kxean z*1Q+TtJ2i2X9WA|S}rD1-*}toZ-%INzrjHLVXzd$)9{Z5rm5>jc!xeSn4Y>aOf%mc z*TelPJN)yF>s8LZ?o;fNinLB$>4xSEk9{=^E&~<(V(C@O`g)+}Zq>w8hhF$C#3;ih zxPReSlgbEbCZbgHGJd$R!AD3GBGE#^#Iw3Nn}#r`iHfnXF^hf>HU@s)*odA1YC|_F zE8shiwbQJ|7NKmo7xHgx7Ye~X&qdpicpxgFI|A#%Z&_aqMiJK`I1Xp=dIXUOLJ<6o zRl__4br4*>pbY2@Ta^J_aiN6y@VC^+RR4@=Rib5XrN+OFq{7fdzr!iZj|6{4nkbP} zn~7CmQ@HU4UoSCjBDm7a5rB@aP-Z)z3I3*g=?uMM&P>gW1`IWeJDi zL&WT8(t%qHNx!x73J$FQCb<8t6(XsABZ{5a{QOI8EM&zf^4Gww@Sw!Zx0^g8L`NnpD^Dr`LP$MbRo5OuydC zFgZHhcSJeT5)$2^QQ@lAqsUBo-_54&kFG7zI*H6bF6;hFYs+GxY((o@O99?Drc3DX zdauVeG4|NrT2a9;1bq-Z3`T7bltHi$r@ZcuW>fPRF0O4CZA=XTzB6d!;}OtZb>5Df zRI83rzXh~sK9Ar&qGaW|a5J;agdQKc*{}ql8+(lS;9}_>`UE)$Q-^ODh?Rj|xOY5X z^G7c&(sDY_RF^R;_ItXrZZ^`I1u0g-F5iKIj}$2qiLTRX>l+lOK1tG_q%~I2>hYCP zt~(4?4N(~Oq_I0Rp4x&}{j66XR=wF`cQbM0bWuaQ-6dE*?s!N=qH340X#n^tqlDJgj1T(SXg#GC04c zHZbM{fKkO#|j$W&(c*d3D`}YR-*SfsxMx73M(vH2)X|FMu_M`zWJ{T}6gpC~D%7sPpm|mjI zljfbiM&*MvsO0w51OCAwD*bzJG;)nYFH?3e=j(rh*OgudBy&=lR&y-dq6c6klR`O7 zHJKk^8Of{~f3_%V9@g*d0~%br>H4{@Nm5TCk75!0Q^EaHNFud8IVfI{M`<$e*cgH3 z*ffLb9UBC%z^+;9HilStY$VpTG_MnQ3an*ad-EcgH$i!VP9ar{GLp$d$ov@GHF(%% z@Kus|CMnJC#nsez7xaD7*t1&SbKW4|-mc4u?iFE)?v-kKPcL^lPAAU1l(;f9iUg`= z{{{OhT4w*109KsY=^C1OwPj_S1AP?efcW;iQ?fuB(KVvI%02d#^F#~uD5RlFDGXl zK+>CFFk$VR4_nHR_oj=Mzi6=S!CLCn?@%k@R4a69pQs;`7WITqs5eC!a5rR$c8fzW%9lya8;dVF}*VShRTLrHp4n|E{d;|C3^D&v9 zO&>BDfGKA0zo?kBwULLXot$IotgyQvhVwk+21}lA#!;dtZ?NZ?;Np397c^%Mt*so& zpI{F412_XK7q3_KGgdW@G+2slwR9XBe7yuKvD{#K@I`QbmSym@86C|6 z3`yTLpVLwDPqC0R%wYN`xrU#sWyy6EZoqrEmOa-52hBAfC3hEe7n#R(GF^=6fhWQ)Q^0Q&QJqP`tazYdrnxc_!Q^Fm;tF-@6f zHKr9{OmCl6%$Sa%JL740z3!UAmgAFTp3M_T=WpBv$@-R?nC{yd4%iLJE_2FShJLxOK@E$5 zSHN5EtYH^0!TF<&fZYXs2GI=8S6zQaKK;zu9CNe5v`?R5DvR!#c8;-D6@k8H7<{l# z-(Bz`vmRq*-52{oUJGE&FtNst8`sNAt*i+&jzP_Oh%@6g(!UDm*e$mMdOPJQjeGlY zaevD;=vz#HwjHZxv}!K2?F-nSErP!-+D4@GHW+s&3uja~E+N0bG3$&92zeZw% zq^Dcnx~DM=2$+1)Z;5FBz0O#yPi78`TRUN_w?m%9K8c$J_iu*;$t02Ey04~nDTY+i zTd<8a$5++Fz7AaHVSuwiaC%AvT<5j5at)U88K?ajPiv*vjIL@?%(t*QKe(!0F$vE9 z)F`I<;34zDU=?XC{59VSC3Rpx3RUlLHyvuI`_GjiFxGz=A&! zZfPiW7oq&&_J%?*y;!0f%96|Nct3UXqkLLW@k&5&6V3Nye^7dH`f{-T_bb@LXw(04 zGbZiW;WQQQhE1FOHfLnH;7^K81Ic&-a$E~XSqD)eRH45d@mqsIJr$ofG@rD4X&i#< zI8qJvKRpg1Sh0xJ{qlgt;2Te1B7rs!_8Rr`jbc+zviLm|`>yHCzM|kCh+=Efv1<+K zRYVyE-}@H9AC)M>V(g_|GqPA|KRu>qp*#?y-0S}A;~%WKXVAi>^B2Vio^R({2cDmB z1XqIONIxu|h_OOrjhlzX0sHwM`8<$6ALjA)KZLPQtR9^7KUT?-OFcOG{TiO^9S`Hb zmZ-mw2m`wI&BNmAgXz~;6gUz)^|P!#xKMT$OUZiouu5RS87Wo+J0gzJq$J&(`bD z((YGLb7yhX#RhAIXbiLO&vO3W`_=_m%5c6YkKkd;DQ{F^Hh(+esU<&xC z;I$-kn$%86=i!Rz0?+u(f^QR71d~+8;Dy-96LPaRUD>cHhwXqaI_Ex#ULcZM)Mpa) zqKrr149>mh5XHQmzt+_7xFfd1Oss4&)C7)&!%s5)mf+WlV}VJSh21zdut`B#f8JkI z_@nT=&W4A(?eN$O54tJT7p^^27Zexod_Y0_>XU54$eh;^=2g6|UB z2a-P%7GGi(AAeTWMtN#CicXija2EcMNZt)kKH?-?qDK9uIVP3ppR>f19a#O_#UdKl zMAG_ZJYr_?sgmy4>7N4ULjc+qGd73MVQqM^VB#_tlG zmq{=bAdN3X5bmzS~i&D-j?NN@OntM&30#oGFtzb=-AnNCV&>EK|_(j0@; zMs^tX%nNMsd(lbx64Bk?0&Dqln8jL-fUBT)nB7_u>|glf?tUG*`?)r=`2>O+5jZeF zz0NSBq2+0e=`UB%m>yaZ?7QARw7daU_Yzjc{zC8r_9OgQ!D13Cq%hCVD%edTV2g6) zxMr8P3Z^P)_v^o^DcneA4wI-7$%hZ&SKM*XwSp1&MJPgL>}6~#_zqD7Cc%ijJhWJk z>QtSbSgFB-=#XoF8&KXZ41#@W_HAHr>HDrgvi0CyDT81)?q*nmpcR4|bW_8fU#rgY z&jQPgAaMMLtA*0JiAaC>cR5qDBhV#zz^}+CZ!GSRbkH#PP+UZ+tjJTMgy^K8QVCxZbx7n%`Fa7w*Q+(&R(Q-DjOqRxdgV=Q{L_u#KTdBxxZq*nvUeq2&X zY1X)6V~QVk!9>OSr|RG92;MpDHq$h$5lu6+s$+}MhNB@rq4SgWlFDNTT;p-S!FnKn z44Ve*E@XFSkE^;nXFOwZcgE9i(Wn@9cZRULbB6lKQmOrY+0@7*=r5DugC)GEze}c~R-)gnw1aceP4HalcQq+iNO}W)%bJWw3hv*4 z&m`3OEuRH$$MBxp9#Em|vEO#Fn&0{^!ufs0T0j=~RCOwm2_Ct|`_jq@EsIgt9uLm{3}8u~wR%*wm6T z=!s1?oIwf^+&{4a$zN&J&-*Lwy7Q*eoZoY$<()MQ-T>nx*s+=`_+!GDNa=5=>8>*) zJj9ZQ_nncJ$!EqH=<3tLfm}L@^HW_Rf5CYNCUXYKpXEO1{8{dO&SbgQBF^$PngQQj zwdX-*T6jid`sONz#ahV?DOu(+5bK802&>;B(z~MP*&nL^0p!6j zH&@+(IgU&F|IS#f&C3TlYrW6dtqsBYk^!+cQ(*bt3^uW;Yvp+wxARpB;7PErsdZvg z-t333g5W4j*GvQ>Fuz%L+QRz7xy*XbX*+9zebX-4vikuH;2Rg|{-6j z*7Y0LBZ{x{kvy$a6<8xKU<`1_X`>N$Rxla?k`YoJyKjlw$^dFBhxvx@#k!5n)6Hvw ze&djCdn4~ac2`_u@y98XPFsv?w_`W-V!><6P?$-4^G@3n&XE_%s(Ria@5UWb`c_f# z7CbcLV$msQxJvDm^E%pB&v!iXQ7KOv=^L*SU!W!i4^d}H?@3s3Z#~9a3f@tyIFme^ z_J5GJ!6Wcw6E(0^g=+)UTej+FtMl$?9O?dwJ97eA#@~ zzYY@XcMJ-5!OhV~@VR2KL83)adWc--mY(q(QAR)GNr3$s&xEJ}o%O{Ak_jkcPVtzpiDk<-`EUEW(th8=q zDR4L=(_pu2OQB$H2Z^d3gj$XfcpFU7lyF7Kz+P~_GkA%IFJJKufGO>&g3dYZ!#m5B zQ~T*mMivQ3$t%ToBfj&&O0I#GEI4K{W#8eP{QhHhQ%10FkHtzhU)?;P4e~{`n!Yt?nZ!D#`EjEuC{~*y1W#oSP5xO;y$uTMUvuaihWkJh;knRsP1hNjHp2 zujUbDISdDQC7Ij1?Z z#zk_2i1qWy(q4Za^(I3sLHTr4d=!iB#3Hy`Vo>Vb;wM7*ZR3dY{TJ2h>gfC)I_XC67fJ6zl<=MSFi8OGJ`dLl( z&ucQ;5CurWJ!IVkui&4Ff)p#H1JJ;e=NOL^e1#}2NV?3>zzqwabIF*Gt$+(KSy{&v zcfm`}Ozl6|ct{uI6_vvOu%Y}XgFO!J43md7N6+!XWOi#74qT%TSsU;P*1 zt&(JM45W%KZ zt>@SQv1OQLjY7AwMer-KGy)P&kCoc=S`H<`UoU)udPvd7nOnLG>pL?qVt(NfX8SM? zh`}R4FA2U}<^fEiyMyTXy))xOZuWEppH9^lB=Qmbwi0hE#8w{z?RtX$DFzrMlg&1> zaAATVI+@0jjGDypWuG}JDZ0_bUD(T+ITH2kD;P%=l*-PaC9%M4PQ?E}I!F z&9r!vUYNHYiq*%k&%A}@?k`xPP;Q1s@Y5~&Isv*rX{5sXV~|isGMNN(vNfK0gbLnV z%n6ZLPzN!+*uBquvkrFUciY9#}q#Q(u`g?4)%yrSR5Cn(i&*0|$G#km2RMCST(q!&(y=KcMlnA;>FWBQeu#d8C(w zk>15wT;E@sh_@?d&op3WlML1X%mC{d4!8Aq(-kC>#rsoFZ0HKCXCcOi_F9bQYtJy- z_IvF{lVHA@+v9iS=%-_{5cEfIFM>vxu3Xq-VLf^Uvp%@T&YED~+jd9JDwvwjE{pE@ z=scMD{UOXmS|O-GC&da=oSF5pUXr=T)O#hU<-I2ve_rr>(GyL2P)OsTS|8)&^lgHV zmncl4o3|eN*cc)uEj8Y0+1BgKTn5>PNW?E7`!4q}?%QqfY_S`fv`&+Fd2loqJH9uV zULG86UF>jQ;B}5iud2=A_XfB9(1$YqFMSOYbD`F{aAtm=$*aCli(%X@w{Wj@?*#2x_uj-Ek*kJ@ zL<6%|aVo2f!Suk4;DCWyvJA{T{tLBeEQ?vv4w@zH^Qc~ST0!7=RVDDzE>nWRdfAe% zFTKXYI9*8dh%vpNF{v-zVeBq!?;Oj+CwE~>=h)M%MTO0sV^`p}m_Z#C?~a;xT1&-u z0hW848>|ir#IR>=qB}o^M<*-HgBrWl&njY?HlN!6P92Tj@R$V;{y~H3H#{`_yMgHq zkEsV3`@vxP4G)H?{#8{K@%A%Ha-YZYhKEY}e`=~oD(o(7p}JfA*3y|#U;T#Zt-G+z z&<5)NR?duT@ONuxMp;d9W)v!2;fFxfpRvx2!&msXw$6;*_^rJ&vmTnr4JLoFD$lV` zbDk?0EE0KUm}+WSB~@GP?X^Xhsx4P6I}L5B{_imKI`#iuX*22fv=8~ZO7&|(+647~ z$Fwo@VcIC)CxH77O;P_pG3XwZ==dF$jNFfv`?q%3Gs3WB67*~u}=HKcPCPL zGHts0|EaXe>i?(HCirfqh7{ua7zWyXIf#FKALj3oig|O|Bp5@vIkDX+?2mftF`jd| zP4H>{sRxtHjU#VO_TM~3YcR96^Wu0*TvIlQ;&Utp^ktaCg=>4HR&gnR{hZ+SB{faz zA|wZ*=qJ3}2);+U03y+qjRP-XJ`*i7fC!qi(L0QzdPOzotLe`FrNuzEdiBB?%6$gY zw|X&5vxx_%7Rl`@=4!eHf0+#QK;QHQ`ip6T-zFK;B)5LoK(F5SL_p81dpl+*>+HB(?EbsEW&J$JO1XEN5kW1iv1G$+ ztQY)(Oi(~Fi%naTeYZqsW|muqP80> z0WkslSD~vuVBIrXixg+>l%k>_6{}Z27pkA>)c&`cT@6p&~ok>@gemd2eIKB{xn-L}_1l>8;Oc24TY zG|LI@cTQR!(@YBbnC1gP9z?Y!Hg~gTnpyF(9uaEApD2_HXq?m}mGW#EdX;B4dlce< z4ZWCdp507hX?H5&5!K}MxX9~knrAn=&=|n*_ijtVvzy7pFj3#3%g=6Fos$l8mS!A+ zmk@M85QCry3nRN}6?@N6Wn-pXw2uJ&_9iDIDv7j$pK$inbI`hW3}!(?|1eT`t{zM0 zD6SiLM)3RU8R>vDB`TJq_KQqh*#TFsb3>y(gu=)WgACC~I!~uvRr;EzkETQ=5({p! z>W?J-hiV-r5;=A|*E@wH1N3r0mY<#1fo!DfzfU-@B6$WS`f8KO`3_jV2AI6PEBKFM z`9RVoQmoc9>vCnT(=XdNGahHA*`RnbqM|ubo_A+Q#qb}Uqrw#ndeYIOcVnF3k5N+O zwx@n;Dbh0k{}m?n@Ymo+CUE_mXANu7 zhx!q>>iYKxZ?`w;5jXv17GnF)W*kQk^t2?eU0Su{8Gk_Vh0<(6DtD1;IIH?44qP|M zhoivYD6YM^M&oG%v{v=E%77Y*DG%4Ozd+&M+7sEdt=*tG+^V>)!Mxx*gIy1<3=dmQ zT22=Ku=?4kezK`G!CbaSP#&AO#FJ=@9bt5vTe%#? zy_T*3E(H5pTezsE(KW21Lw9CRXI9WHBgggHwdOgar0dOdMlbq@7AkOIrn+dosq2X@ zuIpLQ`HuvD#bt!0Nh5^x5TcBl!1xP-x0Wa%Wuw(9g+YVOj*4Z;RAG_D8zc;!at$kxif#0@Fj9_}2u#;JbY z)PIFC*W454G&y#>tb^Yu`q1g%MwgPflAii@(ALq%RmSK4uIu>$n%rRJ<0FH$MnM?% z+!4hqvNTwTR1CZWS7R8<2TW2tzjzv1G-rkSnT=d!W*{pwj_Is~I8hI)2sc|J(wFG|X9{?G%9T688Oin?<$eU zaa3rI;16GG#K$DnkhU=^djBmuYPSQm80J0uVi`wgTG#80B;SaN?5sYZ*9bZ*x#qE4 z7e}q)zq6yfIvl0xCv-SYe^&sjcC+MTLf%x@|*eOEkqpx zALbu|KQ2+3FY|?5ot9C)Ff4R7ZJp8fNn35-fAtc zewN7?M(_5wm0pNu>IbWMKZz>Yf?rL^ZmYs2&Ok>#P4FA4m=bG}TS$eKIZ8F`IPE9+ zUzJT1A_Y`Z_L2}s0ySuE;EVOJAkDlIjAL^1qSkXk=S58q(ORg(T-|r=hSblkHHr4F zY*mGxL!zLJ zb7X(~7Bc8f#pN;0C9S{W+y$E=?=e_+aAjCEoJFNnc4p*L6;8#6Rn%1AijI=$!H8+(N>eLztX0)kRlMl_qTtm+Ol>hq zwQlTHxQPd$7NPE+833GKSyZH5eN&(^S$h9Gt4yhC#e3z!KzSrtr@QyYYkN$>^{qdzZXi{ z2&x(G%m~MCHJzDzvB@Cn7gNGD*kq7^+Xkx${)PDPm}D>c<)pxpJ1iwH;6~pg$!5NS zTe;~DSUD=1`=V-2;mBXca+8k&Oq2)UuCV@s|0xq?kV<8FI~L1#afw~c^0r$3FD&o2 zTT5wqKODu{IBuB?3DE2>Vc0xG@U7D9FX#_xUQqiplYJM&(|sAXr4ziF3wWh zRnD9}=qa+6n!@fwlWen!@qvObmnI2P>GDPU_t?a2{5_;t*(BGPf0#^%Su@S&T2Pz) zqhe`SJY~Ie+g}DYOU$X$$hn{q92jLs`0skq;( z%q4P(89ag)!!l6(d}~pW-ctE5y2}z9!xycTd1`->2auMf;<7MU`_FLjJ%SGq+=#$| zVAp95env3)6bG*(=!)Qf2xf39z6=#4uFT*`D*bDo=etNZGOCuF!hdh~J*NJSD@bcr z*O@t-8+en9-Fo`mLc0;jKv^d9bZ?9IXI*b}b-{=0xi0@On7+DzVe4c*UNP{_T4Wi0 zFlUv|#wWN^`04^U8!{JCK69GXd|zkgoe*S(&tdqFIlRpmOuCYPHu8NEc4Jy!&QrYL z9mQ@i$>b}?H9s@RuHw1(7TZ;v^Pzt$r!!+Cn(FSK4FB(;S9jwYnN@;+AWan{zrDh6 zWpGZw=%m%u03hLKXrZ>mSyoq^U)RE{x`whuQnpvDu?{Dw_D(q;%{%S9uB>mtF;b^S&~t$nVP4uxbNW8qolOIB%5bq(x_-8$mE!n9S>K2wmR5T7(VCCyeNs71zFx00 z(@|$8&z2e83bI^Z|6rPh+riCc3rxrR8c*woOl`544sX=PKr77L-R!9orSA}CT0?qV z`+^!+-l^={NN*`{Qz3(1*!onF@8^6j26^h}LFU0q@8RprOgO>{upX7e~Ln{iq; za|2|vAF`?by^+nYkWCa8<}NQX_*e8HmyStBJ{jw6@{!HVCD|tLjGJg7)xHHrWgOtlEP9ba?lDzA&3cArz8#67i8V=Yh(3>R}(Px!(jv zx%&*(6xn3hNUPHacIOxIREqeymvgv|Ry(0pnXP?XQG<;BjMh@+btQj&IelDTTfWnY z_E8zRxhH32slo0=Mi?$;YnHDqKJlY8R6n(p`Y9DIQDKKrUpZuw_6JU;np}I9!EOs;GB`(Xk1$Mj1 zu;0QrJ7X;TFLN#8Pa?bdz#)s>1?+FLtVyk|P-`Fb#zYu7=luI=+J z)m5;XbGdT9y}B5-<}#de`E0JGn<36m)0p?5rMjwq_3-!3%xsvl=S+i$(6f^PRy+1g z2&a7id}FV=gs>g^8E1%F3C_#HoGT{zhk~EK9%Lx^ReZ6b;P7{?LqUBgaPvGKI6YSe z<)3E;P5=UjeM8*=qr5xc2>|Y&{~w2a+^Bxf^AG!aMGZJb-I2fw}@6El>75N_A6=Z*8ZJaL~qDu1DH%7Itz*94>HJ5Oy;D3v!hDkY= zcc?ahe!56|$GR&C^40@=tI=?YuWvP4gp+E|3GTnuh)A}*$vLj=Kj;k|K@KC3Q-(i` z@P2afq-7t6hND?+=(m_V9BI#~M9+S$#nnS)WDRzT?=e_=WP)LK_hfyE64G(`8~Hdg z8di?$mphRwZ?C4OitzAOM+fg*{XzZAP+YUVHpT0S7X1BmPHmvzcSs8+lI?|#9M_X~ zntd$2aN%Q^w#2|_)>=ZYyd_WN{>O5x`G4hx1)VpWThgIHnSsU5HjgZ5FTy`-|U zf37Zkipt^-?Kq3;4VH-P0XEyk`V-Se6vn5=O*u+Kn2NMB$wz+i&N&^z{AahjG*;u7 zUEJdG=c%75RDQ#pwoX2Vi!&cLnBF=GmNBWb93w#f?!|V6`O^q4K5cisfKgxQPpr(Un==N*{?%&`>{@U78kC@s<86qn&nn;V0%RMY-*45SY*@~Gmo=7 z_Dj9>(_GqWeI#%r#*iLzrYY&ABzk-#y zmYG6?W(K!$Bgq$0ln_cJBx=Uk_oaoTRMMRW*|X38JkR@_=YBqS<__QA_uuPvJLdg- z&U2RMInUXj6DD{|NkWrOFXw*#ejI21b-C&12}q+y!If!yJIP<${xqjUW0x=2E$MZ| zW*jcR%`(^vV8$@*H+WrtuCT7RbDubT7>ndN6RECZv={Tx4hAa+Mg&juWz4ydW1fio z%Y$c;W_s`@tBO?7MCzg#orGum!UlU7j5PeuGF>sLxGCnB%J)JU1e@|4jDs>Zv|Y|q zSQX5=#Yrw+W-&22^O?gt%j_nG;H z;7cqT&!iwE>sb{{^G%&CHJ0@)PIAttlbjWvQf94TUjB&2)A0>@FUQR9{QpqnpQT2h zI^*=mh?b1c7rc?2{s2i{9gWF!dXsQCd$@dk3kN9BiQvjl3%ec6@G z*Tu+{4f#V3^kdW1bUd->eLDSoH3u_#-osF4LA9bf$ycj8Qy;;?;9sAZBx@imou)Cq zPw*m=6_6w=A%{3O$BW)+ZZeN@ZtBo}PV)8YiONv927F?X{3iI4c=8jw(_#DB@iia*u8YiUlg*nQQhZ!Fr_#wG&P9&9JO$CmGORg63 zRbRN|>iQSswFGY=F1bK54>s-VudmUl!7Lr~rw5=(@BUe2(Yuem%mh)dMwZVm&QalX{@DgV_H5_OXdQ4P39EVy-&`A0}Lhgqkd><`Z6X zFKl9rzl%)ltm1klZawh4hBIABf;)vLNJeJ&JRc~tqDeDV%w`gEFNPjJ!$ECT!B@!8 zgGf5AGxc9In(GVAcfWFfzHBniqWmE^kMTG@kyz=IMyoF}^cRT(Rje+!N&Bh6Iw1yN ze{F9WY_07YRNHS1%! zKcVNri5?opV^mN`is!-D=ymLwp8Ck(gJf)^Ne6`FMwHW|8UIS~S`q~$BfI-v$jQ;h zVlQevRpRK&Kb_IqUKHGa`3EF_9kv*hs}3JY;6l~^i0g1Z2BnohGIa>R+UZV7V?U*? zn;%+Q{6(BR&-&2b;u*HKc#rM!54C?Qmwi}H{wRP8!TNBOaM_Ph(@F$W5on)cZ83bQ zjo@#LVs;^zj9?&wY6wDcB3O|Mdb>%Nkg^K${c zoZ>}4&R{jb1h8T9#dA5l1x~k!bBx%2P`__f)RHDD9Vcyt#msB-HKvb~YWNQWlgqC8 zxB$4%VA^HZe0}-PJ|M`d#0Ry+WfvbORn>PFbmni!w+0R(7D4bQ4&QBsRt}hNs;UgC zFan)J2f;5&6>3srAss}6`W$1>N`ikOQHVsNj}S$_@qwZ1cjQX>INk}3n|I_0reRA+ zUIQS@K=jq-cQ)+XeZUMtwTF)Ath1`xd|gKCr3~|qoC?|?(9TXm5u8LdzVt5#9dHt) z-Uk-t_u+zI#SiStPjFTNdqec$Xx$D3PaG!F(0?mW~BqKm3<-OkW?M$=Y^05+Uyqaf>q)QG%>7e>}hhBLA zs6bc0d7U_UuDf$~QS8_T2YKm?Rwbq$MQ-{^s_l@QMi|e!1+OEyVGv&9L< zR|;NP`avdz?3ALtRUJJ>s(gC}&29;vM|@H6ebQV(@-I!1yxcLn#=fS$Z?3;j9He-x z#VSE9gLOuHg5%+F|MKBnx4aAX;|yJVkBxc*3@A^&XN)=l(|mp2EnX{$pH(h{gxrtDTMWTrwBfI?YB20QQ})L(8)(0fnRXXEN@fF^ z^oWoOBg(+v7_TAtUor(?lG2RiJqn8RRx0gWbI-&Kc)}hKhRNwDBL#oDF<{F12lW`<;m?TL+)(_nC z%b4%UIhN{P3l}Dj&aqcF!M10U@10}n;Q(eC^|3osSnyRc%h06k*@iR?Q97WMhXfxc zQJAC}SWbF8FQ?NfP@E*xE{!65&xhaQjjo~81R~v@f!%065T$n`qUoci4=ZbM0(J1B zq_P|HgYzvI?<)AGGCyF_wia}%B36CUP(DdU)Vtsvw4&h8OH?M&ygRf%HlT)LYo;0J zB0*V&1h+fQ9j*S|%^i~EPV44YEzbGYAA0|9mSMRIbB?axGQL9a$kM!bt>6VnWObtwZ6^H8%v^R{)Be1mhNY-zlNIf=jkqQca zOp2sQzL^2F@K|%k_s`5-3m_TS5zBRrUK;U=JLAtnG(t)%!&?C+*VxrH{$cfo0v)T} zm61;ulxs;pj^3Rq5tlZwW1MH8J1awt8(Vlnvd{Qd56xW*DyW3urn0oYbLNxjm|KiM z&>lfOEWVz2SDO|Z#B}-+6{iq>tveOZ^NG$tw+FsMF&U=_Wmal?GF2Lr~>{-uTBiOJHh zWz_(ohzfiqW7SA&_T^yvTd%yN##-UnndHH1q$6)=p;jKmJwr(%%pGGQ5>Vz-{xF&B7r{0!#!F{hks`5jw-TsUGRI%nKwIk=JWI%ox z_PXkC*7gSm94&M<92r}bvX5Y8E`!1Gtitc_nOE5F9~Gj?;jogd&k z(-KD_Mw8d&+g z1XJb;;0M^kZ*FjYzrAgd=L6dr+w-Tk4>}l`}qYwzvpkmZ-JFxDm>_W1NZ^Hv+{Pb@@t9h zi{=6R0N+`8L#+J5;P(FXR69Sw;Meyy{8pN{4=R2o;gfEj!R`Y;z~J{Rd6r2&8!}m| z;4$^vV&T_ss-?ZohJ%FmQ|;{)u(iE@5WM|QwUoCquB6|5%U)i_}_3`mMH< z-I*^ zO;CM*xWoB=UixG2AD^cFQL!s&*tI0X4U>CqipK8O=3ARwRipQKj#94}n|uR%E|aNK z)Eyx?G+FQa^TEqG+3(~^Z-`1y#dp1Lc+&-kqwuEpror?D2f*~=OIk_zvV9^9hmw}; zxtgQT2h!Y$dJ`qxxpbi`d2wW;1oj3q4l#_ItHjPh-%h`&vFb?doYps$IcjgF zQ->H>1V5@DW`8T+wD6mV{$pMMzlks0AwPTl#A$tc;!PfMw7QF##}ad93qaQb{UZto z!`5_y=7vx1rIp6lsEMk81p)k@Rou>dbXGg56#l%AQ~1STF-Qk+FU-lf1cSrbU*(mM zSJcQolb2L#L+HL*&+DaJD%LXJ`o=2Z$rgQ@V3?Cr)(7!u!ixsePFWxP+a$Pc3!OTR zojjNqq1Y*FfPOacSoHnw){MD4c6|qYXZ_i4lP&UGdV{e&lkM^Z93an*ZW!SJ{dn8N zeL(R$!MfJyuM~H#x!W)K`p;^~^PLD^ zdP61ow;Z=gf4DXM4)=2UeFD-495ns9I{g*>Z0X0|HvK-jeVv)8)1xE#weZ5tPX^OR z@(Gq#GYVCsl?+<;cKCKw!De^3Ha;wVK9cYIrh&@Al;G*VOuksj{+YCTsPwB~YTUzM zEs;LpJo*duk8s>xzi)8}=Olub*)YP2Hr_SYtKWydx++6iBQ0HqO6Xjw#lF|-tg#AO*{kx2 ziLm7B&r4VSr~2(t-)1DU{rLkY7QRR}oe==aL$ZJFYnR6Wt?#d!5H zS8|p2z#EqM=X!AbjRElq4i^7yYy9!(PsRqsCpcLAPH$M`-}C_F|At-ufVqELrl$H1 z>EiN|{~Ij7hFE#OFu}-=0OVnWf8~P8Kf#j!53zK;ae_Vn1S9US+~v2%uMG!EV*}z7 zjQAt%@dNfd`7Pw+Q*>zSA>LXJ=r>wAtf>neitb|SL}$#Q@`)}7X~qc||(b@IBU zs7}ej;|CPa!=AJX@nwN%ZD(C)h_{Ekeb?Xm-x0o%wf%Q39(E-4Q2aa6sFWOuYNx)0 z#~6Hx9j|Ec{kQz1*ltRno6;z@n;OOHt2fyP%|BK)NY8%PQ!wjZEbr#f@^0ta%Czsf z72uFQ@Ah|VoTdG($0PlJkF&Qw!1=Ym&*ukie_QVNx4*XyV;Z0Ri>GzQ8cdJR0NZSb zC+PamIM(0IVf{O*a6U8K?H4Y zgp*T@a5%+K{XtJ+uKI(R?$jUn4%Sjdp08Lec->Oo?&xs5uiMKD*pzo(zUA#?;?jD^ zX&lgRZZN$b0@(ChRB$t|2v`rvWBfl>v!ecSHk$V@2Gji`;M??%)pdQ;>SiDRN9Er? z54WcO`4vvTPeA&BZvw{~R*bVo!TwzHoYs-JbUJ&li@_h18(- zGgnwoS)jo7|&~ zZ6csSI=NJY{~x|;#2uFItcJovY%4mTHEX`Z>WeDEIYU2uOE)2?{G&`ZmN+Dm9=@v@+GlNflq#_(y9eN>U))~TOYep`^y$vz zieY+-*z2ml*4(?^v;G_}g+=fN)FSnJ%VT@>RRx(iO|lTd%Lv*d!28x&C$Y!5O$EOD ztEqnS-J80fr1Fo{8K?RATR5hD%wYGTFo4+})DBp_w$IP)?XjO;-+Ifii>Ef(pOYAE zu*SMg_UA*!5w?Y`-gz!;Ie1}fyZU|Z>seJbM~}nO9xEHhw7&AmI>t&EOs}s1R()hz zZ@vm(dfZ&=EB5j{hw`wWG1phGYMwM{UcHag`Pg83(oC>(O?SF9riOZS@}j4uM3JUM zkth)+&7LZ%M3baE7!n<-Y9O3TMXNmB@9#blZ1~j}^RxFeMT!2VZdQs2akV zasJD`P35w0tX%eWV*tALTl-~SH|$%Qz9>qUeQBj7Oee}KEpsPxMlL3qdPOD}#${i9 zL_zNO{#HQW@f~^oT#k7q3EnT#T+0m~y2iS70P~(@Fnx^`FdIfQ3g^|zkuL;XV?Bjd zy9ejPIvF-}ZeY(8~va1uWmOs_u!_P?Cc@>-bXObZRmeZO{sZb#^4R~`^!{dx6$vi>~5Fs`E#yNtwM zG+0?AMzComtiwL_+n=jFn)Rc4COWMjjr)pORy3GiKLYH}f7@Hu{1>47|MR5If6(=# z)At6f9|g20YPLF0b4KX&htoI+HzFq*tcM;4eP++o4<+vk%u`R3Co&&!&(G)^x#W4@ZS&*GH$TpatNrraIn0acYO4_Hjl<*vGunf5Mu664nbJ3P?ZcCwuzW9J%z)89e>6`KG`3 zB}@8+a3o>-`JzQ zFIw!;gSh^+{zbbzdT_Ko{kDJR>K~`JznwkuM&xggCc_>@(Xf!_ZcR)kXd*HgPAw`M zOix4r*L{QPD<&%`2Ad~(enw-<1fqDbs`tG9cZBc53VKjA8LL}SWO8CLQ00k;?|223 z*`B%f-xmzg>C<{=<5q$1S66Zqc+l0tdd=zH8v1HP@H9Tgnni%Yni<6B*x^z)q?Ileh7ujcqdN2~u$ zOTCukYd5NZ!&m-`YcySabXh?RhiUJv1=TjG7X8DQGUZ~9o;JCTlMJDWuAlY4BgQv( zsMH+J)bq4T;BkFH1h4DV(x5CGSXjPjVL8yx^3%o4G8HUi!7}5y;*Rmnr-Ou7TU<#* z+NK?Jsc*U#(+^;I%_x}DC8{rO`8hrX9g*vi0vj zxZNVIMt&d3<9cNf*YJR6sfMFLS`SjA7n#(nRWZLj>G-*Cbf2p^hVdhQ#^*mKPdx(_ z*Z@omWEb_vq$BFSSWC0{M^Fum!1 z;#^MlVFhou!7T}%ME>H2SmD|V&T7QVBXuX)B9tP^ty@f~Zj1BpALq2+eQ({b2U{t} zh>`$GhK-U*6n5%!cNt~I8sEtCz4#1=Ly!NAVaH49^Bj;?v|qm5W?X&rdW}6o;sAO} z*i9M~jcF{!2%{L;z4MMyhhlULh`~2$zTz1A#B)>hANrBuUFILt%yZOF(_rwy(yD}2 za`N!+aZJibZhqL2Po@-&2fOSalNZx$1)Wj+T#nz-wi(PO72Qg0&W)!|yQ@Z$Kr0c6 zR+xBk3EN8v!`#VZs)f-ToyqEtj{c(7D}F8~FW&U85L?N&n13wwX#bcY{N9zXSt(Wa z!qQ3o-{o77GSs|RKJpFAOTNW|#9;Y`2gG1UI7fQ^xAJ{DJeYhp1}Wccd-+iPuldXQ zWl_olzd;xuOuRi*zdJB2P`qh9l(iffo*PybFfbwj&Lu~@mq~c zD}frGYG7Jnz7KhL&0uoa&iqK?7zX;y+& zmP2>7cs_(86s&*IZjbttSJ^i>cReHa`>&u3I zX3R){^;}e%Ykogdz2s{{#rXp>rpbcy>p2{oNnTnGEXGWtpa|;g9`f}^HZCm%PYK|{ zBjJK{E^%WH{u}46obC2(i8DTB$H!OR;=U`}4EF!+D=NaG>4Vcr$NSnv!?5BWu5wtA z^Ct&!wP=jj|ECaCMnIR%1MN{5S1Fxe7~R*RpYMlp5zBtT8F;3zDdISV>(hNi<0^{P zr~8uHjBceqZfJ5#E8`jQ%-~*w>6LMU5tp;y(M^X7JbGnZ2-ZVw7q4rN!t8HmbrIA+ zEHB24EUKF_(`G>-mOW$gJRWX;?%6=Sv?<;tuL?MzTqrO5n zv@6swE>W!8c(!u8Lv~tB?&G)Jb8rxfOS*5w~-p=O7nDhGv(|bDvD_L{aEtymH&J-iuE*Re1QH;9w;fdNw zT+e>Ik7;xoctA?<8(bkx$ML3n1>Yq1pqbR13gLX~I3|Ao_BNkw$JN;g+y?no@J|Yg z{t?Zlf6hrKvB~kde7+ZEw&W{}&k}rvm|0C4DXM_y@{Gi4+4PiePO2N9vcRY|3*mExdoKVhgUI} zK5D|SDMXHW1oaOOZ?|Rr0K>2S_@yC$7r?Bx2x?;+W@pa;kyXJ__fV7qJxm4ZSB^V9f%11Zxc`-7O*$c@5s30LZp-Wzyo*F3k}7_=*v`e3 zWhtQ2bb4<=Wb@?nlMvZU7^b8OzD-2Nq~!F*#A;)w;`CV``D`|#$3tD(Xgu+CL}mDE z^!3j1?#jE|o+I>>`Gib1)){{^cHhNrMrf_@uI_%xKIE6|`EHtL6}x1kAz3|i66yZr z;WKW0??wfE5#UYntTK@C2Zkl>SXN)m$)p)f?^qI?RVv4}WBD#IIA;J@M|J|BGE|oS_c}bmI|FSue|N=>GNnQE1edwl~rit z^y+6v9ui)Qp(Fn^V!VprlO+u%DZR+J{wQ_owT`$CT%~g+#5(zEn-M+K5Of#Gn?9E9@-13~05#?2^Omf0bFJe*Fru0|x%=ASy-~)k` z5maoTZ=mZZusb8jfmrFmN#B1$RGqHk5w|Kpzo)cxnyEq!eU`EI2CJ%jW5WFtlUq;l z#3Tb3K9tmss2|PkDQ+n%zdgelyV*5>AK`v}TfuL8ZhrRp=Kwv|`pmGS^Q5!k(ru2x z^m)?R+MQbjf#dGAOc{JMi4S(l1?NeV9RBm9ExKAP`fzydtJ~FX(E<13(v(s35{6D^ zC|AKt=hZG6bLl!DT$TEu^W9A6oOJhHhs_b6Up=@0&lcTb`_EnQKI(0m zk3ZP}^YQ*~(|o*ZCp8~WR~B$sD1=mBtVrET1- zl5f!|5O1Ze>aSuvc?lm~l9G$rKju5yrwqyD-O5Z);q1enBK`wa?yvPf#=qcpzNA`P zczm_67o1%)*iwaOX1#abmL-4vd0SQ6?{3yYRpKe?3nrW*zgP6U-G0vYYP`&yhKI!A zA?r9HD)i~_EPvtJ-`QA{_b^Oen9le*!N(LdmWD~53+@Sj@cV;AO??M!Jo@v*af-#e zxM-JTumOn9u-8?7LNU$&TQL0?*Mklw-E&26Sa|&>8Z8U##b*RtU@!fcK4n7($48^1 zy4=Z>;0v6oJP#*^zX(1<&QxkrrjUjs$^&y5UncmI5=E1y5y^AjJ>hq*VE(8kBG2Y? z(4jAJWI8t$W+E>kl5 zdaN_&w)(1e6h)vzTv z{T=T1CPa|PQF_a%thBW_Lh1W`H@FWqPwlXln1{8n%z4F;_>$Y(ErR^(ga`W9X&0_S zUXktQPD@}PHBr7X(IM10)Wo_k*$G8SLB5iYN4k@@m!a32j%x|{bj@?KnXsAKTc*d6 z{Z_m;*768K+g&=JSrMd!Y>yNk?+qP)wg~$L3inM^TC8-{k#!CSHxD9MgkTba{s`J2 z7>ki_AKKA){F<^==kxOCy&UUs2@Zd1CTp z>H8r{x7~H>H(zmRE_tGx?<&FHdHc*&UGPN?lUGeDDx?%dS&tF_`Sv=G`n61km9%^z zC$Hz^`B?18W7eJhLM-)o97E zHx*VB`mkp!rw?AwtjlD`e2PRK4=GgG&G-)6RTWXx}LjtTg0)tAabNw*zHK>m7#j@Pcn^NA?LlmRX^GGiaKCp5RnF z&6K7INqAN8u)*{+fnZx5=|yBSO*jX+9VEGJzO3Xn^;Z7pubdM*6cCp@gJrRoRbaCq;w_Npg1zpB5Cs{fIyKJJpL`Wd?F$#%P(ZFv>34XzP{ z5O3z%#(%|Wa1>|1jLCku$$kW9-RJPPzl=DYw`j#P^mE2OHCO~V17^-_&^WVH{@wZO zLuq|}gkSC<{f{%UK8FFrACGW)%>_RwqYWZK2T~^?rxi@DUQsdU;K{dw2J3@Z40~OL zGT|Z9O*XCL-3|sxJL8Xn7&Ym`;yjmAUygfR zr0U@8-@x(U0fO^Oyv&P8ti){}w<__&kK2`aAnUI)g*PnI+N)pdFiV#eTFUBxusWNF zJi4q~pIW*sw{%%Fiu>qPa9#M% zUW;YySZg~!z~EQ@HvATtxJ^YdU0#Dlg5PX?;a>6Utu*rwrI|;itG1qBQ*k?)xU_yz z3-{@p8>}k$0XF<5{4w5v_XB6-u^tj);?nq`I_^`SZly6jeyDElQ{QI%FqQUUl1~kF zdpGcGtbuA@+s^u`Rk)lJ0F@$0_5ZDminoWG)nhX`149I_CvH|jGLsW$ikEk7EU(Pf zuWRk$UJ4*{RMu4AQ~E>f=C#J|&(+6Fl65hyeeP|>e-pfVlsYlM0fW^O)DZR2wA&L2a}>?KGclX(H)m@G3SJkQ zw>0LD0X{{OHZ+2!xlQSRv1)RXH4c~Vvgid4zBQyD`czXknw#--u#r1CJ&HyatM!}_ zFBH>6db`7_Pjj(ulDv5+&FOY1i@374T;ALIdl7A3y{_To%;mlCxFhx=0o(~IT=XZ^#`WYOHdOnw)Fzv0cayp`vhe=*Mj z0XzxLx@_@g>Pxssuh_=J1lK`O0zoz=n!B;ZvN~3CqansM-1ePsFg?Uz*y{=@Ud%GY zsN!HS{$%iOCH9SA-AbDV)**(<%`SLFT~1z68nW$n>>Q!%xhIbZKD=492?#)0Y-B{JJ%r zcPB75C?Flc10$rj;dDIu(t<<(XIt-^h4sE3Sns1TYkb-iEJr9~OtUp@j8jTo&e@t$ zjU2lNk_MJyJN@$`rnQE`I8MOE^=83Oilrk`gVS-U4x3T?*Iy*wuVQ7@;#hAPtTbXU zJYlm>*WlmkcTjycK$yP)t2XW}j^07==Oj^0YAmD{i1G}EW|ai5B2k#MO&+6<)0LY* z9cKc0zVPzXdsvim{nXrWI08GST{mnJe7)E)BE|9P$@di&m)1QzE-fxXC7{gwa$Gj{ z7(=o}ubJt`?PIn(lbeFSN43`L;#@ zzr<;Y$sF9nY+GeMRA)Z%WmTZ^xXgU+VU0bF!Vny>nlwsCH?5NxS3kjj5e35}rn?LkldqReA|-9o%wlu4 zRpI!Ro7ruShKn|{*qnK|BYF8DyUhVSuw&jfM@883kjYy!VVo)1|Kc6<8RX0Uy1Y??e|(Ftv^D?en{34)bz^XQ?lF*es? z^k+T&=K7?;9&Y8_W)q;A==w!&wh%xUc%O3H)4rZ!rDz zG2nsGxJN+w%RVorQRi<@cwqj%4!7lxpFUQ<2};l}Kr^;N2^J$rMeqWxX1(^ivNo4* z=00zr^dTMka0U86dJt@XkFs*yuLLP~K`$)Ou)A0^%s%;jdf~y9FO3Le`{} zLh51Di`frYZAEasp!Zx})Zg-ZE(4$E_}vYr-*aKuzM*w*G!<HJsUm?NSYRpZv0k zu}c7;8I~OOx=iXJIb2yX&m7JvnO6=cDIFM+W3?3@AQ+3F59vqG<4QkH=Aj?7A5Z@A zBLdvL6fotYCH0*Tb1}{|)|g&W2h5AOgSkY$&41-sH$(6$wB;Z${NwNa_0nzq^#|r> zcw&nl)>~&ieazo)tgwXjiS+PbY%yF z1&;VPn*1}xV8(NHJ(oXW=gk8(El8LS<$q2YA~=7n%LW?yJ9vk=bk zppMur*5|5tAzb}ds^4s-$iG6L(-G*`+sBc1k3FUY=)M*7K5U@;sy7UfUj|;qEYUEx z{50u&gS_SUQ-eE^Um20#(gqg!JrB1tGaK0D$FSG6_J&n{)gZr?KL(fI10#aT@8K!| z@~hgwBEQNzIUCLfcKK=eO0-3O596`R6VZ105$s$u$W0Ew{txoocr>W|RR47r{nux- zTt49xPm|JckO4;><`ZI$IHbAU(MBRkc<1*CSc_=EpOSZeHL0AC8sB9RZs^VWgwsYr zITIz1je^q7Nkw>p^GYdaDyy2Z|Md;WWT?w4jTv7i`17JJAhmGA;;}E9ZtBzV@@Ye` z(EhLz1TP~j{Qj^WR$sKKZ}o@Ol)mS$*dNvoIs&Dpm8dm+0A#{us#bDyRaCft=HOK4 zWBPZ#p24R&Osbmnqb4OLI>pUZronn?l_nT#bfK>fF>bEHae0g!bnWM*f2H6P+RA#_ z%zgg#vX(>4dfD-pjk7DdlRw{s#}Egh2W*ExKYzFl!Mg}vp$Q_1%LwV-dI3UOi6=A* z*UK#=kc^Oq>It~(Xx+Splv($7LRwJQDx`Pn{x?GEUpH?dwXYjgNDb@e7Sg?SgA3{4 zp!|gNvs;98ZjWC`^9C6qHGAoQ5mK5fxsEBx$0*^a4LQq$1)nG-)TEAexI*_7=D%9j zF%`;y*EMiaQUCJFwiI4galxjZIp9Am#$>x${q@CQX7$fXdI@v{O4KEXHLRRy*oN8x z8g>v1@C$3_)-aG-=<_zbqed5?M%B(+!}`^}orXPH+p1v=YX3JHR3?s+4m zsR{pskUWm86L8%{ zx^js`|7s0WQ(GXnqPW8FjNpqzZkp6eNGZ0_dL6<0=QCQr+nMqv=gM`Xx~}z6ipRbq zjQI@K5AhlHx;$qwS|3TB3-uzE(Yd_6%RgWr8PKz&4hYt>q?OkL_V?5;ndD#Hgk^FE~@zuwH}{F~C3@z9rA1z2A= zmr7swRH4d7lwV)ATxNZFyqc+!e<1wDuW{My3%*~3uSsQv^qEaxZd8>CDCVK8P>`ZZj^`qh|qt8(;t!gj|kr@4WL$$*8QRPu3xh4 z50N~56R)#ck*xDQ13L)1)DA%{1Vu@+2JKOr^<|#x<657h^46zFzdj{hWPSR#vZ;v#SefX>3`$Rc3X|s?%wdvDx!QZ+geHv5QqECHmGnP=svMMyi_p8&})OYzu>?&x2U@#OY9>M(xijg|q zvrDPdn!MN7Cqth~L7%uEQ~Ko4`V{Whr|RcfpBCR|s^do}#}l}1HdXL-q8yr(D5RM- zed;Cnt9PVNb?&q1(@tzKM%-uDCx*SQtF>XD#%p~d#iz{3I9n40e@pa9lU~rI#1ZQAK5oW38>}ZjWmxM{n9(KQ!iEsaG_5}2zDoaI z;-&VHq&w3bewq0S{L8vC61qcTCEcOt+C8Ky(3p4xZ$MR^L(l?26;hnvw=2cj6WGHA ztWUPadENvXy$!{p7V6c!oa`FmGPO|}2QBW4V!Wr|7i8mDlVXK*pnz3pq6A-6Ah^!> zS1hko(ltvfmd(#HcEVtK#gbvKtNMR128tzRa94u1Oxxri0L2EVN=lz#s`6%ufECMO zl}xrTq6zH8o44Hs|6ZDaCOsmgFA&9rXPasWK0~5_)V8BLtz|cN+MvGLO?`Z|jyPt) z_kHNdT@P;8m9pGv1p{X4`|dGp>xWq97i$F%m*o8Oix~CAyZ2b<7nA7w-17@)1RA27 zUS+2CFRbm8i&lc?nq1VtV!PqNpGkW#y02% z!TlR5AhmP{w4S%+(^|IHGfMEHd9Wil%tgR<5B9GP+k0&SSh_(mV-*=~lS-MrUG+Rf+d{OzV!SJQ5;b-R7L!4c1_{Rk`@Dk|uW z;1LAl(M0+ocoab-otbaBNi~>bfej|0y-W(>_Tu0FEN`mm1<2|+8p0mI9~W6^(kdZU zw~b)t2wpg!5lkun{%3hh8`%j*P*0V&w-JWDt{^_4%h-_$hT{%|IcZ&00OUoJc1Td(ZZO?Oy`hBWoa{+Su4#6q}?~s9f zJ6#E^*DbriZnNLnq+CGr9EJ1zu5!7XrzRB;l6}AP@3IEZZ@=?yk=OdN7I|I3v!08} z+U3Qt*EQ*Q9{Zi0*9VtZo2P=wD?T(pUX4tWwBNZ2+vfKfOz(GUILyGb-+2O!|6&=9 z>HSW?|L6VcJ>TTNUme)qlF9_Mw+!5n?Oi5!d()(rW%6!s_m{bo_U0e`T`O&opRXfh zCrjJq$FP#0*DAmJAiwGBg3E7WmtgXnQZPV%BT8G^Tani}8_$%sw>J&DOLKes09ODW zDs9>ufd9I^Ro?jDx3?{&0@_>XLe9*mrE<47O`2XR@Afvj)Sa|9zr5O(vdF7>ea0Rr zWtSJjUf0vdtn!M4ynbI3TwXtP4koXkLjvTL8E$EBXYd5Vig0^-)9|ctOM5E>3y~6T zZ*PDH4gEj1x87gp-`;LN|GMBbV$k!inYi_SRB-?NOOw)tWS@U65&X{PUn89siEeAn z*z-=iL>X4|uQ#ouLcO~g{$=n{VWCdJBwExFAklLrO}6#?t0*ot9TD6=|I(yygrw(R zO`c_Zk>LLM7f5ZD2wDzRk{HtnK5- z&4T9|M}DG7)^X&!2Fqg{8P_hq`PY-RWE`3BnSUHvww)PAu6pA3<4EiLYx-aR)BNkg z+B=zl6)nK+%}q!10{u&PikqrCrl%5k%XgUI-}t8zL`uFIlGI*(&{2QDZ!1lKraf#h z{k9UrUf1`jaLv$-T0-B#5GZ?F;J1|&%L2^uW-$xPi@|>myJKG#`Z8}N(z$QGR7!K?X7KZuw`9If6FKjgY6%U} z`8e|LKVQnR{(bOgUSVxr)D(OptabmBT=2Srzb|(-nM9XzrgScdYM^|xI)?eWT*TY0 zxDna_H$wlq%W%0H+&lcq_&&j}iDB2I)j~RqzMxlm#^(zDl|%uF-?k;fY$Bw!Q*Grj zRsO+x_<|duP4)9*BmlCFFVMGxPe;ggP`8&aE(KiWl)IR>LO2)YB^M{rH%(dxFcu z)UnK2scgib`no1D=w}$veSCdUslCDUef)X)F*l`|gFEJTA3v}23D4kuByDZS>+=b8 zYtHNw%D&E7U$4WL=r$YqJqjeXILroVb*Ryu0($u#2T$h;{)d10{%Hr_ll(iWrut%Z zDC_iDSo9&GMyDCj8}Ewnq%e9124)eiR5lYlQ4-LkNFjAblv6z!4->qRL?IGgg~W{4 zaut#vd(>AU_Z2b`FQDNbSj!C83jUomTq4CKUvpruD=w{vJ1(tl$2gvzEf?oyXsiCK zklbeJDkR@7(S{B#WwhI=w65ycJ}f?Fhj9|tg$9phtNBN8+`TQ=ryZ0^#8W5co3sB? zPA)N<%aM`R%aOi=pvj4>r)X1(-+|w_9tt* z97!%ZW>J?t_}F>ABv~LU7RIDHg2D*4!VD}%kc!|11mzL@ORakIr>a$t%QajK?Eepu zvL~PFmgm&0TLEq%@$mKCwt#6N0NAezNiPl6=ho&4V2d2tEPBmzd14 z!$@p>%@hi6VffxW(7Q#K|cy3LmVv@!xrsXu# z#33|R!W1*aU|sY$3Gm+z4aZOe#}m*$7_72x+#Af%e4D7Wdz+&kypg?x281g1EQcx4 zCiu6Xgo}jZ1^-C=+iOyPAx%J(l6d^Dz2MJE6ei^>`U1gaw{m{Udv-aOnXe@XD9!lrm21yd#G6c={c8%fkg zV0o%Hv%E*}vceK1?GM$Nk{ODEMVoAEgLcJQ{M31&c^ALRDeG6S2Kj1??W<0>%{%Uv z$y*HE_8)+6%>jZ}6u14F6fdMJ@Eda_uVES!DJ-7Tz8j`79wvAzVGWW^%Us8Al%ZG~d4A$L zNM0KGTL8f|@;bVr1vgAGKj`5Hj^cR)U+W)!ycSTEV`#nS8T};>E7xUk>~;pz!%Bj) zT3`1MT-7%_FF5)s|wC< z#&Kal%Kh;4uSaQBfZo!^ljb~!VefiZ$X&9s|JN*n=m4KIo37afL2%ZFt2RNrZ@!@e zsu%ikyf+P|52$K*gn=JapZDweMe&;U;1}?CX|JN%}xX@5mZI+C8jbnF(LZ+swKS{m?6J? z)t(-~S?}Jkr1$S3olprdJ40@4S|St8OeP}X;wA*aukeGPevOl@XHB-?-x8DEr{NdBDS~S_AAXe1hi~~v4gbO~ z=X(FA1@+#^r$*8}KbE3Cvc;1spYPbtOF041&Ye8Zioe25TYJBI8()RCFgeG0W09`CFzBs)}@msf~QK4X_ij1 zoT)Ql_?#%OUOowt^78V@LAU1s*_mkZi-iS1?NA~uLN6(OgYF>nvPp3fjA+Cf#+L~` zNsK5+?0F1}GJ%UquSleJVD{<_X4XgWI>HPjS>ZYgGuT+Z%!Cuf6=WklrMjEFo(DWj873fUCc5_-MD_z^UTjv z5=)=2-5SB%9?`ftUkkWfq_`>bx*9!!%^_cp1mks^toj3@f!j9mIA&W02jq-fd$tbr zXq~)yB)L4JCtWP(Yhw^p#3=OBixvZvh9Kn+}nP=!lQ=!8l;O)4*d-{Sjc@Z#3Q_v>TQnY_K zdi+Yi0UPU1n@xH|&%k!U6I^aAN+n+}?@T=ajhHU1zk&=~z_rL|!RLrZFo|tgkB;CP zre7y;wYy+Mu2}qgoLM|*uqP3nVGrek-KTJ#=A`Q!a_24#m5`@tA@iEdHflbO$?*A~ z)epVXCtBpsK-RI4b;fy%T&m&0wNKC6;+=-CM`o}KAG*~o2o_!CT1Yx)sY~ZgE>6F5 z_PS)48=)C544A8W*AK7Q{k!}9zfGa80RG=pC#sq?ta^%g2(p}9ADoFE*8+9R%D(WdCsD1JAiAA$$}q{u8m1lZEvNblkFoPy@<#i@ZM+} z!JqJNM6E|DqID@?uI8e&9{m(Tz>^60<~^z?^M*B>taP5nYC3fuC4Ry1i9M{QEI^-| ze#Yd&10#Co7si(eK1hrxNO`5+v!gtpZ6I1hl^naepTRT~W43l@jI05eOzMJ561w1O z{42Tn-od$?wT|%ug0FFyT!NIMSxwO_%@hNK0I(2xV&@9RQE22 z)y}^r_;L}0CiNB4n+~g;cbmkATkU*`_8c2}wU*g?t4ggLTMb%Tv<){y3vqwekFfb? zi-^q+_4;l8%38+ecc^Q&<33Ymds7waWmI>21oaSfz?3YS0!LP1{PhR=fX&ngtevUs zb?0jV_By57cB&#a+5eU$A)i`D0C+%$zpYxS)BXbf`Oik)Gia*ppTmR!pDfnxv9h_qTkzFmLe+6!#%etpr`3Uy87<0t`;e(PKEZ$-1^&& zn&e5TT}OTorI&iMO+@1|`u*x1LB6kpL*AqFF^T@$oq z#iFyt9iy7x{tD+3$juW7cyD=0Mu_rInIlCFw0UE<{QNOw+# zwaTXKf$2Q)mtk?l!K{B;z^r!*zTRP26KVVgG|9x5)JKc;M~S^v#LIO!;yVUwjYt|E z^Owc)x52(`!e4gF-v(ZC$tYO&>(;8@2kP^fzby87+zw_@{V%(HCYZgJTI}#Vj7q#ZQMx-Xr*FrzyTBtrF5MCr4>MiSaptFPA7F`MYZB)V8*&HZDXd z!lrR~DT3F$M#dd&uWIAyUlG3kXQ{1&kupns2*9{E*CCD33R0=$NQkQlWy!M%xpE@6 zJ*F_})So7|XG@ygf~0fHv^_+#t?ewYmcaVFi&|4R{^$4prAqAex??sulhY`wtn*-K zd{$Qj4@kGc8Ejp>FOT_e@6z>n)Hj1h9S!9lNsMCcxQTJ)?6Sgr8lT1C>T2^t;KP22?sq=tztagC zsqODH3PY~&G>86KYdiH6ulJ<;HQ`zaiqla3Jh56Bzf30Q0waB^LNDe}7MJL(Fu$}! znsxKSrM_T`ZHKu?L-T9vt+N$d9=aqD@^$lIO1SUOjTlFd*X2VZ%XOx+-7&kIlQ5b) zOyr@u_^3`@Z5~r?Q-G)GYF4VtxQd#S>5e({YJHJ_w^D}xDTdm5xD`U`$rdChJ!>8h z9qWGSq#CMI4TnxpGhL`=)bPVME0hjP#+#Z*>q0faiHW357Lc{WuVWn#w{o}()U*IfCN6YBack?U%xYE+etXIDe zRf^AGCn6Tx8hei$y)PBU?O`&yn>B);mu-1XdQV9Ev6J5y?iP~;UnxOre!oz2Or!s5W1<8O0=yz$UBY5eyA_Q05&Q>P3}TYkbeZsWO*L=eNr`lCy)bM3)=<-B#nY48rps!$7G2gX zUBqbJWsS6SSs&jx*AdwL`By%zZ9HyXZ9M;M0**Qtxt|9_uz8 zWAN5pcyD0`J8o|F^tqg@rTm^m-It5y(~EXi!V21pM(BJaKgcJq#Vf9Nhvnv)Xt>_E zNnFPeSK9LAhj~2v-8q|-4EW(q-_F&#CyqwnTMEHkbckcoA#OaP4KvNX&fG_p}tHyO3&kwNDG#)`81dk$k0=o_M z5tKl11~21ZJ#0y@?3bM0pNH+~5uA17vMoI~jsny|Py~SwX8g>15l!E^YbbbeiH2Ku-7L56$~#kc zIQaVl^8HE&^BLHZ@xOmG_;iQi!z6ktu=V1c9ILzW6uoIsh&uvoB+MoVJ8d-Anxpw8 zwp3~C#@@+9gWV7Q413HlLZ!3kLu)!&ap$?_4`N_u-q3SnA1>xcULViEf!Er^nwb)i z^%_1sjoJNP1WOQjNX?U1YBjHOj={SS{C$>#_6X`BD30LtKOEFO!$C<399fG`^IyA8 zaj^UpO}Ncd$IoD*Z+xlqJ9J4<9JhrrG zNi1F#EUEVKqSR& z5@n4Zad)QZBNZFu<1rXkd>6s^Lcx0r6CyR(5y$VUn3E7Xq{X@u4%jd(W4oRe4rRgl zJoW|J3Vuntdm`c8p(6$P-63~eT8oY~@#viLGd#rb4csLT1;Y{X-ds%7Pyl&k($YL;*=JI#pra>B=4Sd{*k#VX_Y!b5>hozPiy0S2j>pLv&B= z`|EwWvJueCwP$$$K}bDsYN)fr^QK9w8N1hDdfr5EygnO-CO~U5eUDhyX1L<%RjZ|# zEZYRJf2kOi5Q}=5dDDsmIyve|hcx3Xyk{`olM7Tgx*8&8Upfp;j21Y3Hsh!!S8c> zTUGlUov#P)GhpSywP~-Zhe5awa}Ap>O9gKyuP}h5r@Cp6HASHxQ(uqKUne$H93Fg( zIV2dYB4RUacCjXGru3=R{jPpH)#ovi;2|tZMPM7Hvf!)3Ohz=Ru#l!B%KEd6pV?#Z z5fX(-URN>dI%t{c_u|)7t%sITf8$I_iZhHOuawCDVyUTP6yvi6KP)Rdr_XPh&qAzAO+x;{TxM!$TR+7^dDo)BgYk;qkaQ4a`SMiOC?*LC6f+piP7 zyhHC8k8l1*81Fu>qH(6jRgZF%=K67$VgC+Bie(mXvfm1xD2rPlr5MR3n&i`5zmW;{ zuk&2HW*4v<0)9e$IbauCtGZYm>%PlaD+au-@dtE0{iTKK4lYy`|8B|UHVh<-N7KC?m%=k1oO@+r$g$#b_$u*PT`p$0wf% zgR_%Q>to#ssnOIejgzCbK{E{YY|tZRbIJ!tKB;@yAZN$sQy6pA>8;286-`LL+F>fC zDc0r2RN=~6Ao$%fPzR}pJ3c1UnaVuVT%+VW8YZjwMeu|~KaD4jL|lU7*-MJ23mxt3 z!tb${c~%r`{63>#UhUr?933pL-#v8bEH$#n_G#r=TJ*Ncqkbu>pBRWi`+@BypDnTS zcV!Fb^DDut%E}*;lGDRz{I6`ew)AGUsEHs9!4FtW zTZ`a02D2Hore?M*eD@Q_dZ0|l$aDmPP6!$zNW}`*3)gtjZw&PWECU+ZpKPIcG{Xlc zvFNo82W|^()s2hB$V<`tpWUJ{Jw_%t>*iJ47`Yj^R6=kKi(W?&R7Ow$%W5BPv7|5) zp5osMNP*z2Z|!$+CSnC`0D{&CY9ROwS8Jxy)tW&=)xfRmWj%1iiEdZjEn@3oOa6e% zyK;iF(c#2FQnrvTsYP)A*I-9{OvYHZb4?WWSDUFS&v1T+QD3`|S?%1c%g|l-vkD$~ z@SPAxNUU?snFfE;5yzYi#b?Yq_4VA%mRj&(NHBS`y%q>ots~0f86x{5^-CjJV;I{o zCx8EyzfeSoXI?`k%ogNIw3S=Bl9n zLQxs8>iUgzi*);shyJJArOU9_<=G4AMw9%S)`fIuyx^B^bbxdx7YHWZw^jy7H!0nS z>LNt70%M@wf`2d4)ufg}`T|i_;=bekg3pjBO!Dl)1rQ_Ot4AT3dvdB|9}BegAq+b=om9>pA{+qK`vUe&1l~`*KmP@5?6{-zoTyMU99wX@!u!L=?R> z_aDJ$N)&9(^|8JH%?m<<^|!nr6bbjHPa8}x2obzBg%2v^wICEF$weX?qj5PcT<{Rd zh9+J5+K_(5V%B_k$A36mnqII*fMRQaAAYQa?-L zX?>x?*bZygI0y+Uw*Z%w2)+6B~YB`zjw3^kSHb(W?Qc8=q}yw2WK2+pUe z#IEB`?;=#OAw}kB4CHLHY1owaadfh{HQ9AAwpZ5LlO;Hqd9nA_D)QGRGEHzYF+5&u zFg?K`Sg*_b_k1qU*iMB9XmEG)ZM_Rm*OYz#n7?Xc{8tRYDNKexLogL5P@1hZb$%L4 zb*tbqzpCJSWvNb+!i0oT?6SLYg!JqhgL@?kNG)jh<$#a}AlhLp_SNoCUk6L4|euDF{?rkNxgRl{E;To!;;9rQz(WDAOdK*!8!RqIHY4G6^ zg-BwcRQ3l)uz{Kg1GPtD#DLSB>5P9Vctzm^k{GCKx3@FeV8t3c!-nhYT!yPJ7`_LF zY8>&H8b%C`B!-{+8P4|`u4wrWBpwDHF)jY5^g`co`=IIrOU z$U+QA7}(0g|#NUHROQS|du*i;N!^yoN+!63sqpkIB*7JT!CStaX(cvajw!|5^M*D$|V5 zEoIu*p81de++HSvsZ5T5GVxVTG;>TjeNQa(d-F+Jpjb6AtX@;>PYq-Cl@0bB*lW0` zf!*rUU(sP-UZJsQdi0!?$ZTw$cM7T0{wZDag?!Dq=eUna#I zNUBfeU%{iMPq4Xo?~;pzQqu;i)WtaKDAiYA1ZV7W1rfsD#5yv9Hx>ihW)coO=`zVb1n*__0AOho6;s1 zn)I5G<|4{{P}AoGA1hIqlzcU0cwe|Rp>|m2Lt4Cu$0(hf8cKUDMjKbjf{pF?*D{(Kl7zSh$1)nbWf;DNdkcJ}4 zU$~X?q~M(-3P`QkQC(T*q|d1NBws1*oYc4=|ErWUH546xIf;Fm^SP`cI=7q448B)7 zekM`TyS-*ioX7a0)t)JM*dxd4$=>m&GxS${nvJ~c#B8FCJG@bep_1PIAF0oy`&|}C z_+p+q3-^9*&*6ua%u<8>9y29sK$ z=Zkg6WG3Y!suS~XCn_bMkq}dN1P>yJKwvoqsPf+a6J2X`^ygq}E>DcX^wA#;SNVkP z{HyRQUY0&$G68v*FdY3!zEZ}S+8Rfje_LYesji+Tj$(X=;3fUj#8JFPq`K5W?%1Z; z&eYEfLah^w3o1Uf5a!!F-{yypr|!J$fPS_cYVFK?8pbP}#`4|#-}k^&|8dDdOU%ML z;ow+(!K=zFOq0qADFjiL;qbzZ#RmUfR+fkq$Jo{abeg(d$M$JYc8g0J+_yn`e9V5Q z_YhTG8oevCQKHYlIB(v!%=Tl!lY}jia7ep5vmMqkF0GSdJFu@?F->MaLf%SS=@>)I z^+f8bpIOWzY*2)Gc3NyiNI;+n)d$g%=-+77Eo*Yb2*Gzrt7Z}$(om76)P=!5y~unz z8!XPvVHV#DK3Z513DrbrH&rzysA?Ljs%fOIreC?5N~!2GC3+pO?dWB;uM1v6*b)iV zq{hW`mOUXZZIog=aHKotiZhv4mb{fRxtb2Kd1<=HVqQAAnRB&8cJo4TJ{|X^kM-wC zibd61(0_yV1`CEQRaO~Qw*F&F>gzC{T=cO$b%KK#H}(5K{U-UYjx%R`i=gSBLenRY z6fIOZ2Y>44ANwMxhrmfkIoAn;53pdAf}sCRFldNBDHvhW^fl zIkM1R7=nXUC5>${CEI* zGYXP=OKVnVqS@68$ST44bSgO?>CgKs7QNweGTUJ7!9v5|ePl`P{KJf;e`HUM;NTUL zy+Zx|qiW`ENcY+;uAuVHNvC-;?@Bottql0cREZv~#Nrxo2f_WL6(-SW<=W&s9lieDP1Pyl2KDpqnW{R98p9?NhwOG$olYnH(PbybD;?k7;o3q|^ z5G^r$L)rOlhNku)*GF(j*Ie;4x*!3GT7?N)c}a7d*J~zoC|@^{ZnVYM?))W0vNxZ$ zpaD6}6izePq`6HMwllfU50UB<>dw=8xuwM>cm93Oyf%CNHR&!)i(NT6a=ieTf4sN> zwB=>mL2=dCBd{SvteWqA&CzuOpfb7nwaBg`_$*y_;cK>Kim>VlK+|7d@#(ry64I_$ zEh!I4yeW)tRQz5|0#bJ~YO)hzR`cL1XRqdyuR5yP5Iy?ftC7_t_$<|Ire*sStFWr@ zJyBQj*K`#oq_VH_(yAO*$494D5i)@8Yl{zykd34!&A=Q5eKF?syQ24m zR&(}?XV-sB;a1JZ24dP2+o}RQH^mlxw~MQ^>`%rYSA3nzRtco;$)-xlR3%yucSZI+ z(P?co`<|t2X-tGlgAQ!sK7|T< z+e^jrDfMN`PP1@(WnDJoiHeWbi#S9I&K*I{0BF9qOMp^b*6IaXo^*LpWRJPTmF(*F zDOt>dKJkDHV|{U-&6{DrJl>H>hDL$Ub^FVu+QXMzs<7FVzi(pL;jFCG91dx*_LwcV z6=&N!!%beYHGCN>h~|ZiS6BQgT|s~}#roKXnu9Lhk;Ak~XvwXUZMs&-?|Zx*zDjYA z<_8jG(CBloZ`U9{F6U`O8p zdj++Q^Wk38A*d&XtGl|5v2yHqw&AG#TzLkFdQWR@ZRW4SF;^%3xK%!6K z-IkIi8}lIcv^!q3sn=i;Fi!m6D?UpX0U$vW<{sM}8k!jzu?;e4>0vyecs=SBe04MW#+xnbyi=5+fA zN2AX>HCon*F14GsIk(8`+m|laF4L`>BfmUlXLgTVYQOa={tbz#Wzv!?rs6{0Mn!aT z^Ym@rfT!=Gc<{PeI%A*6j(NmFfOkz~AwZ)&IoN9<3FIYWlIV2I!(T9?pt;Gi`8>HG zYn#w7eHnMUlW&=3OZ8=IQhJn!cZ!XE>C|X*C*J{E7OnCYc`wiuBpqTW>>DW=CSZQK zC1a4L!56E*nHPV@Q3}+beEmG0Dz51kNuP4-S#u1zVip=p=Yie(^FuGUBDkr)bn_-m z{ENV5=`RRN(FuKn3%RqKTTD*q36@2K-YUsJE>|Gfjg`VW1RW8ihOd8{U?X0X`T2Rt zo6c=#%;WE^v6!6OGEA=wgg(J#89uiSHhM&A@H5sIOA$Pc;2s3$A{cW`GjQ^OE418Z<(7!=2O^xEu0&E`Ht$h|C%+IF5hMxLffSl#UAzQi1hk zyL-Hi;zm+ANBmCl{nc&KlHO&i|j zY-X*ih3tzkux`dz_)0UdZv8B^wfWkmTFy4rx%?yHo~x?j^|bs#Ix)_YTu4$ETb$n% z|E-!$LL|6uD`>{$J2xfx&GwwHHgh7Gg_qy+&^YHK zKi$XK1_bc1xR>COWPO^3ubJLAwW6clE|p5l)q0ET$oD&e&1<%>~55pPxZ`X5W`zhW_kJW{Ai;`L)NvocW zw@}=pNr*&E8TPPtTpGfKdexx`g7jZi)}JV*c*jLP**VE2>5>uu(o6J~;fV=Vq!|Ks z2~OS!o*ZxQGjmx+({a1MrPn{$NYUHOTIMFxM(vWru0$t@2U2nFN!m3I#Z}K9+Ku5( zkKc30SX)K$1iu<~8`leNJ;ATWJ)|2ZNaYr+qsq<37ya@@btfucG?mS^jl|(>af3Di z?$5}rSUgI|Zn1~2BymF%vh@USN-{s7CB!lQ3x9D5rzqZ6kMV^xTuGgfW#eVtf1l{Gl!~QIPKG3w9f2i z|A$`O>$fF*J&{ZJ3tpG}LGfo3ZI=k?6D4IK$u)2!{f6RgG|4sMNZO9c$&gqZ)|Ep= z7oMTUpD)vxsPbu{AXlELIrq8?7PFEVR_!)W^F!*97FrAP6_rHgZ;?Bu+_)y@KQZfb88Ln(&g5m{}sPb zy-N#eh>}iK;v~JQF@Cq=zf`hGm_&EW&G=XHLL`fWsBEbCWK9N=G&<9Uu*bB)X5)Ah z*@~?c$B{=I{ogP6{r*<65~@29UFmt;Aw}exzF#pZ>dD zHn}a{1jj2R%bnF2(*oSTf0QlTjkq^6tT~r?v*H(PnL$Fy{Ef}3xgU)z9&vup+nQh> zE~H$9h2wLIZ_qm|LdsFn9Jzpl6TO~_KNr4$^OJGbgU$Z! zCet*1bN?@Uc=Op0vfp6qqu_1f5W1rykV$r#!7m?E!At45=8rsnoO^ly*gX~1!cKd<^X zAq`Q|KqUDXbK%{J-=axC;>Q$I{f)du+slx5HGfTtHsU8Nx*KS^6;NCq#$~MY6n|3{ zS4=V$_1X6UZZVZ;lbG&rlSJF!ESXK%@8=mWC^KEegs{z}Yw&NOS8t{n ze+(s1Jv`A`SMgU=3B;uEYI%N^(-a+t*RrG0T(oE3b9WB5qWEM}T~~c)AtXsw{v)>DAp_#a4<> zQiT#oa)!;c9M(!fU7FXrco}Ez<;?r0%6uW7hHy>8^Jl)z_jerFgfO#wrT7XxQeslT zQ=#rZdm1V?Ts;jvfl~0zHy`E;zvmInz8yYWWjcTMcEwZlvrGzjZcPzyCQlrtyxZfX zdIOk*o^vG6gW2TwBzwB7GrDTbz-9Fd;i%AFZ4+;ed9Am6#^syHeUlwlg>WfyxtA6o zN;h<0V%V*@XU4Oi29dti(ST;pZm#xePxy$j>$S`Gx%4 zfS=3d=jJ#E7ieB#*T~D{cY^$0BfqUOZiCDYNwRw6`~sf(9$iB3Cuv$@2~9s1$&aMq zNlx)M6F=lfglofgL8ewa^T2AXVH$9l+w=#EiH3>b z(9I4FQ=~JP0hIX+sG159+=rlDgo~Gs6i*x)_Ja251{}XVkZ1Y5$i?GeF|MlLtT^u} zxG+o#OSHD#oD!{qLrRsDXmgG^B^pbqH~xZ@YEA>@ zEv~g#Lo^A&?giO3bWR(-F3$vMqq1v+?t+f)2lMx-$#o_)Z$1PMArRNjhj5YRI|Nrm z+^(5{8#H|o+=QSJf{F;f#SNMd5hNlwaF~Mv1ot9ni=YmI({L006M`l17Jb{(w&!1j zWbDpcQ%_69A6Ll;5;WAS+Nbo5Gx4fuJTKC}{xhdPIn3gXG(D00m-uU$bq`SrH;LTQ zsGr4g77s(MxJYr{nQ|6Pl82Pj{hf{Y>|^BPlS$-Ir}%Ski_`9rYniY5Bz6kaxnflr z%4mRQG!tC^RYU&3or?RE>zS1Qw<~7|vVYQK-zSL{xU^s~rN6RhZyEny^QFP*<_nG7 z3mSLw?et$lntYm%4ascM+2N{*QjeneE9U=pj(b7Bl)m1L+tVw2pEjzo|B~X*eV2rK z93=hpozPEn;EQMfvjf4^)w+iXL&IzGaECSoI2;}btPaNCN-eOtP z?&tgYj<1C#l2DANQ~6ML$j9rTiaYU?L*PAEz%9Q0sYroGaHt0-Q_e+wGSSJdPk!0vywSjT8BK2*x59 zAOVizf5xf%QUtFc7>XciCkH1&9Be|c2tfq|JA)i7L-4u@g1QAzx@nww0wi@->h|ze7;=LnBqdzx+t$O?e z4M*1}9K)t9wnu40 z^$0D;4zv1G4;4!*57psCuNzQFGpOS1U6+QJskD#UVrYstul3H4cx-unxe1~D5z7nn zk>J$BG&>EY^L2hr+T z^$k-kJY9;!-j5viJ!WH$Kn_zsVtkX}IsK(F4BMkoV#F0}?vU

+R%E^}6T&;yeX~^(@~f@8jhY*5GB#DGZUBM6nj-Ir6CEXzQ_tAqHcTX^Wt~US@g} zUED%T-2(<5ZrJZ%qZahzTKx$r$orN&WaCDftdz)$kpH83;yTKh|Tg?Iw8xeCbfm zx2@vgH^4zsR%}NL-&z{4ZUigFEAEQPigRTD{iu!lVgxIGrugF}SaDozRxCN?KBgH( zPPx4V|G%7a+eJ;ep|NB{IW(P_a7cRTQ|`L=&%%WBCV~ma{R0zbl*)vI=7gDWX9*@u z*%Qfx8TLb=Ps2?3ESRu2n6S~Hl1x}_P$^89AIXF#z;-_(aJ&I-f={t+eGNt-s|Py1 z@DfbJJ{%bN1%g9Y{T==S-z_Xi|GQYO1+9i|=&6CW>*qrAdmZNB-inV?%`Zs*EWIxt z7$v=3?BUVl9#~R(gQP>|MvC{>fYPP+*8~2w^nPC$`5fY{P|+JBMW?FN)Cy&Dhs z|3!M=7)yG$>%;@6Rj1OW_k=lT890wWkAXAoe;PQ=-#wf3-W4ik;7mKK^xpqS$$|6p zBmZyGd&(oWo0da0KLrbk0>$4@)%=vmg+vFE-aR#5PFW`_wpaZ2vawjP3{D4XYSdk2 zoU9n9_*Z43S#eZsR*WkX&5Dcq*^IWvJ6Um>;-BeovFzwBcr)I9q9jYY^PeGVG+Vm! z?-f}2vP1L+D%^e@sr~BoD}DAW+wWh`ep~vMKKm8*jXnEK{x7p%Zr{>pzpTFh_p@Ke z=-F@FVKa!I?!bfi@eZZWeqX2<|}848gkEz)hZgM(>*z@S zOYL*6FfEc>pRqj;3RV-X0ho%L|3_Uu-l9$UALehZE8>4q`o3P!_tCA*mmjo^EYC*d zrt+trRXqG`1d{@!pYlKAVhe}-lL_v^r{YkGG&E*U@xF|^nrybVCmVN+lh_XFCU8`; ze&H%`)Sl-UPf)z73T`3odBBnmf>WkL6o0SyM&%Tc_`2vHY20WXOw4yBX3o`abw)7B zVs(%ba8LLQWhp@JhE1bxGk=tB6|_A zG@E{md(r&OGk=o}qcjAEiSvQ&V6;_`s^8x)Inq_SVMq8YMHZ8*bPNYPzu)L|8{Npo z;3E}dyN$m0tyng+58du`8|{mDHX_)^ZCJYSbm{)k_myS-%VuLwX7~0+PVl8J7Rf$) zE8cUmx9!>aSYW++0poutK2aA~Ac?cVR6I_`ZJI&l=YKUPiA*L1Z)o~1$X875{EA<$ z`NGt$N0g~u0bZ^5bk`J#SigOatBh?FKcEAMNxrp~Bh~G9wcd{Yd+uGv;(AB+AHxC9 z@>HCkX7YWu3h2N062kqL8P$KUzZt9l-oDM*f98{8@3Td223gP~my7b4;z?Q+A>E~< zqZq_<;Qqax;+u33Gs#C!1(_y*nio-qLLj&`&Hc!0{2h!RyVv3!G%t{>x2s{_TZ;(` z;cAyppr#N*tF|JVkzbzanrR54Bp2SAM=SoNiV~2BdzkQ!i&g=dud;Q;2@DkqH{3+A;xm+~4?&+BU}avtpI&-36rKkqNz z^^NJcB|dqMBR$YAA#9H@+R*Jwv|SNgjzD}$iUYifkRUH)NjYf=vJA#M&sa>BAOwes zBG+a0kV_c^zd-;jN05LZ#6|_m^f~=a)+sjYyUpj`O5)EYTC4*;2iP{%rCz^js6VF2 z(yMPmXf&@!+c~T(Ui`__8Ls?xZ7_ce&EIP#=LPpj&UE=Jw2!|w-C}b23$XoKqrBF+ z_EYT=LUkiPMa|ooK84qEc5U>@584qt)CTu#xv|8AS>W*wOj&6!p-r@1G5o|Z?qPcW-^mPneM0Vba#+ZdZ^u{)6m z!}(v3PzYF3a}zxu?l+&XSTdp$Ox<^Dg4~Gf=4jKO&EHD%H^ck|OyX8Haf-=s>TJ$1 z)nex&LxRcK>#qIgZ?j>Si!earDTuSLHZ4Ff0l^Ro;zQdo!irA+!+R9%u-?nHD)LgN z+HpN?`<@4OJPc1|xr*=Ajs_`{9gDgP-#`XkHKHFKHxzE`nhBmW7>OAUTLdlhRd9vp ztn(RUYoG+S2J%{Kpfx9*)Eqhpn10fG-{0 zm1e(BQ`92!H`NE7>>;%DcP0onE^Atv&h1Mb&p~N#^YtGyZCieYHh!xumuk7hh(Y34e^>BMv&Am6+Qp)+hsHmS;n4>g)V7Lm(cwX)U=eFx z>#(6?vUD=>wv?-)rhD1tEZ4z1rInv?lu3#MyG~EXm&Aa!@>(^u<)_ogc{AI{_9M&Q z*Cx=!UZ0=;=C`cb`nFGpaxS}YObCwg@`X)ZS+v@S9Fu5E7J3rnT=r`%CJQNsg$e9JD$)^gIs!U}4<^SORyY|c;-mOs9pw8!@s#EH{0`fQvmwg; z>$xEBDIU;;Jd^khq9PU#o>3ZUmI%D2j1N?NbXedSQgGkNaF1qbk7k=j{b-W($j~nw zJ>sQy&$d01mDl>b7i9TsBwSjeNXaejoE>uV#>ftN_ZwvBCI8NRKgD9<*DA#{C}cHl-Hh%@tpu?M9^F zLO!mueoeyj!{seXn8?Ck5HI0K6GfL}O~fCraPH;lE^RP>iOz^U;dm?!yTyQK)Zg*C zNz91aBo2Ks)+X`U4r1oo4sD!*HtyZc!RB*t*RE@~NH%9Uf8{_Yn=b}qi?hUB1Y+>l z533n6Tn;uaK3p8CemaKy%P4F4y*=~$_qW+5z8t&xqD(H)QpFQ>H_s$G;;{Ta`L-y2 ze;W^H}7ZjIviE3x|b-dd91i4m~5;P)36$K?0P$71vQm=|L4`}1u}<@dq2*h;+t0WtDpuIyck7pQ;`Qks(P zLz14@$D}IWPLnXnw6Q}gQYg)QA|tAqFa3$}-!e)zGm(N>M@w(!%~$`+X0AKFf}@#h zQF~pwC}uNXaWr-_H+Vi)GdFHiYBQgk;SeiTf8~lE?;0sq7>*JvvOAjO*d3J#-GRVy zf5HSuBK)d`utBF?dvMX;M&!J3l0{CGym#$YW@6y;nD=|SceVY{AKknNmhWv8 z@2cGl619`FqeTgrXzNKzz;lN%cB+eDq6B0(;F+3PiV}C`;c!PpD{-fci`5a+Z-`O? z`nuS1j|0E;U&2KhWQ!v2T?^d9!lcO=(S)%ZEhd^Az;ZwkOnXN5MYN0N_Yvu(@SdM%&dpLTddly2 z>~3GSm^|eN*lH2!u2>v3;8TZ-c>pB47c@>A)sLT-;KLR?5;5f4$c}rsODs~24J<;2V=9^6=P$uTC>(staf3#Wwm^; zTAi+3l=8MHeNhyF_uV9LhKV`^lk`s(YmTUZ<@LCnx^jYJ#%bRK`o}mXcQ}9$tNdRHBb7A9VKd zz*_&IkIQKv7j<^@aVxyu@LuQ0K4v)Jsa&;`KJLChb|2q7CRQKc)-tM(uj?Gu#{sxX zt=BoSj|HyO+0n-t`^3uLj68u9~hJ2;Nu7IE6bkyW`j-q zG8$-GU1bGSQc09aGV8AVG)|b?{9*siP3gxd`O!Rx6Cu9KpfiN}bhdAqiDg>;%FGp! z3yI*KgQhn(#~#1`s=e|$MzvP~-d)P>ShBr9D$!mY_Bz|EE9ThJop4{D(Pd=BVWO6tmr8$RVQqnjqNTI9SXxiK|Xwp0h zN8!x0!Hu>F-*3oGo7{}?^Avx+p>0|wnYxhDADL#xBeN_CvngB+Pk1h_DJ`V=&NAoq zYy-}GUI&|bp9cKVL&F)LtoTh0>_?eoK8jC`kxv!iQ>NuJxIT3vtczqBolKuEI$43c zEcizQXH$vus%_G(thVOE3^|lMPm8iRg^M_2KNs;xdyBuEVvEQmQzTNmv0~I+_yQPr zwZzVO#^lf%FCczsv4@bF;ecmC7dSiP8_}i->DG0si%H#gTKONoFzuKEIsleHX}^z% zH3ei`BU8XcA5>-L^H*yHzOBy{`wJWNI*NZ--&RaWaY`DGBvWCn5o%}gM>PqP@{23D z3%k`Xt%CxdmWME|5~&7BG_HcFiATgOe9x3SDGm1o4b;7tQ=!F!i(mHlxp_lV?xY^5 z%f+~_9WUEfB=E0pR46VA1LSw@L}GDq*!PZf&86)eT~pAJv7~m9UBhs|)1qt1u4#;} z`80Ueu9;g9t7|^Gs$|!^)K+=!LUawFB@n~`L4O~!9fyon|ODXKZfN^?|h<7kexGZ_0jEwVWn4tVYw zP_j9iqB*ARIBRo^e>PTgOuC|Eb3B!1>(ILn*X?6?itVj<`#QF6Lh>r9o+P=1@urHG z2`6DvK}wd)C}@@`DFbD`SQC%K>m@16L;^3Ou*C^?AcJ+@WUBmLZAz3%_J7k@K9ft0 z*(o#e??m<;8xKFK)8gT17PJYBo1#s;!4|DYZ7y}0x2$c8OeDJVOgE(ad@!JvCUt%Iq@*vzo6bYmF*AQ$lNWbcW-2 z77jk-c$U3;1UyInI4i5}cqSIB?rtLLBj>F{zh_-*TdVAvT-(8)b8SCTyi-kETPEc% zOY#;M5kHNYhZ_N-HEIoHk-3qxcvSJ@Nj3{2k##E%@HXQ zZOsCt`4|9BFGsU67EHGJk5cTuKP7qNw({99HAELQg!xAzJW%aigXT@5=A9{RolHNh z|2;dsdHs&}V}b`S#O^YYkGI%IFUOxCo&v|PM=pHK6pr02`Q(Web_YW*(wGqjS21^| z7H_(TCl2XS+UcyTqGaSjh zr6z-q$)S{N2^>uZmZWUpF?-T1AxvQ=F?h}58!EYiW2zo0MiHMBK|9VwrIU5~_hkET zI5-;>kB;L}k-s95td!_C4Vk>wskv+~R)b5}m>v1>KUbKjO>I=FR9@@Tk8{*-TpBe` zqh{Es@bU94qWUGO9lbDoo5H2Vvd8?GEI*Qh!=_?jCOZdas$*dG+;-N1dGpYi`~Su` zx2PlM7G)N|@eQ?2=x!RNN(z4DAk~NHaDMoI^kXKNfSwZSR%He0C|%wOShp=JHF)$>bTu#cZ2 z-spP5YkE^hBfxoa_tL~;QnM)WxbRxWUCm00N07w*vBs}_L}?; z;<5ElXBCf49*-p+uWlGA9{-#dQ#^h#FQ#~$Gw;8N#|2kgPMQV3vLj$b|El7n)vv6O z@|Bd0BwpOW=&N`qO#+h04&kn*@viWwXzpz0nJ(MRtJ}E3f@hjj@XT}yo_Qj8ra7{o z>CAqfGy65t9lSo>AU}AZZk8XZ!T$WbrHF~*2+=d95FXC*uhJbsWv;(_FzT;(%gVO? zAWe}qoY}lcfwSdzuKc!}nmqnZmJ8A!YaWvCF z`H@RC;2-pc!Yk)N=%F}UNWcFwT!N;{{wduj4otDBBEfA|aBKKSKeXJyct^|S$`5ED zniAYFhqCdU zf2D2Nui%!r@;%(*C$6ygd+L@LB-_ILxSnI?y_}b{?X70j2>k-tV817M@dkSsZZN!L zG1*`<9PoVHGNxwihD~Q3{Y?kQ8vWPSE4jh0rPW&vPsHgo4d^;66w(w6xjI8p38`XH3y*E_J#6}r6(_!LNK~w`>#P?g4s_*Yn4ix2%tm2d%EJy_%EPKlVNHw+;bdt{ z$Y+PoO!>_>xJ^+-*V0I9wFMp}dhTKTe8oRjj}lBGe~z4$VUx0(ii@LpcCzwp!$k0Q z^g473uR*z^bIN-CcadY&mph%q;4|GXoWH$JR&Ww7msVYBoAM91T&jUb-RCI2Qe7^A_T$&dso4@@CKX!WGP-%%R!{z<>%A0L!LCH?JW781{hg)ef zYP=G%nlmh8&w*lJS3`!b(**W z=XLuo-lam=?uG^mlO_hY-%V26bBBDD?^o5prMKt!K3Dwic-sshIh#S>vtK_G7YxXRvtEx9 ztFf;;J62<9(jUp%Np>}6dkW@Z&nB8)QOMAJNiWU>5w5xDGriS9L$Jx??@}NnKXy+p-k5GzL0RcWR28pPk!GJtn<5Fp6-f9BeMc=y)~4|q zTtr_fv8g>Nc6&DH@`dLCEC20$f%!x_fE@vlOt6dn@Uv=my^ofLJAGPNQe&Hy<=|Y$ zs&bmjT3J=re@<4FPrivOBw4&|i(UNVE-gNx95c=~kFWwk&s z1)Hs52pYq(@LUAjVPLolyNb&$mO(-0jnnVv-mhsfF>fR|w3L&nd1DRaavW}+UPACB zf@=^|hwrDg4JEfsTH)TnUs!0dG+E&iY-anMORb#GYdyMmHTX(CKXg9j#BbA*u;A8k8 zeuZsSJ=GdI+NJ6fI${)2QMv=BIjh7<**++^LfP3TqNBDa) z8c5!)&G%a1R{nU4HNf{6rl;+bU((A+VBSz6XSQpT`TNXd`aJw14@Phcf-4cE!%OmI zCI~JpK0tm;5?#VYpRxnl&}#_h!3*tp1OpIcm>~EJr!&7UfUDR;a25L#yuvQo#Z~$? z#nFTTTp|B7C9(+#4vjw;(S%nam#PT1z{TvxCI}|j&))hMgI6JlL-6|!lp4W!1OvCD z2@qV2AOXRrf1)-XH4{6JKC(QVESWLF8cfyQsWRsFx)=OMW z8nfoCTh?Ls$J(;yS1Gw=eW;$T!!XQacfpfsSH*kjJSL>8mDCDJCPDbsQQV_RKyqwZ z=k7b>u%uYRHL}{42t9Q525>Wy$o(e`xcDMR12)9Km~l~L12%+jg%OvwVxER4bKVd8)nDZkC z&;7{dXp(Gudp1_BPhr(sUGadfTA9SRPSUuT{}BW>_}<~-w#X9n-M&;g#)h%f+M~>Tpaplb8&H`|KlKx{^AumL@?S_3 zl{5oMs>9xQnBpTe36l(C`ZK&{Z~n&67$0 zO2dLT;OV_Qb|2i?D^?%eeV#07?!q8x1vz)U7QO{0!9ln>-%#;dItdD?l9G;NqPXfB z#t+rD_!gZgKoUKIKS^E)k_KH~JE}qV!aC`l+9ey5N#O>aTYS#h8Z_%wr=iP5)H3Jg z$869Giefit`MYB^=(*>X+Ms)CvC&~0C|Z9tzfb`I*4MIidk=LU{5|6f6d$W~1}OL#SSSg0arEB84i$ z!&j0NROjr$_YU*YvV&{a1XH=bsAD>UWXxxA2!6#xwv6tCK7Lphq=PXpbwh9^f+`4Z z$5!cDY`B)xv^9SU1G_bb)tid<)PW6Bcpu7560m#U+FpMe;# zPZJ5IxdqS*lWjKdQ`kP6cJlQ-jwMUsby#wi*SzXs+{}fFbZ?Ty%jh?Rv{6aFVcfhm zlJQRzU#{Z@B=(F(gz3ByzA4dEkk}y^S0{XHskqs+QTI|&2hu~``2#3!-#tyO6Fn7U zE5H%yNz9;0cxm$bB+H--gh$xTr%H@4zkPdKj_&L+A&t0R+e?VBSDuME;-)Q)J>n*G zk2T_6PT-SSzsFZY7?{?JuRtmdv6!qE1@2|xbc#9){BN z;!kM0QkG3a?lW=km$*5%nDqHD5X!Jv3#4T@|BNfALAt+VLSE~OZ)Fury01Ln9i&%U z`5-p<>$v^JyLS1?vqFJ{9=l!2 zG3yi0!m6Crem7?|OS58t3V5;Ce|cW(k++Bns0q(HR6gj3Z!qNxc}Y5#-}Sx8;i0Nh zQM#j57xVLN7Lz+#3{&1Id99n+jIU>(M#y-m$#}QV`HORYJs`$GndkcTcNhE6)mMkq=4k_dH)psn&$5*l4 zzXwA1L%g&8gyQQ}=rYOF&Ry^!OYA!gUv)7p-#^uiq1;z++RoR2_{Nicl@#|x#>iTc z&9i39@l`+Sxc-UskJR9tLs0KF6{jd7+_LSpzl7kJJbTh*#a|NrD?<-y`3_K1oKg{c zH1OLGMB0kd4|~{_h&h1`$hw|FVKVJ@e4safMS>=o zr%CAQ13}u`LAl~cjp$c1tw!|Q+gT%8K6Im~s}Y<_3#XR&%n$FQ$eO7O$uXRPv;21Wi#cGLEw`CCq})C}or5>Iloe0&avr#`op zj|`YhXyKm#E9?0)i|tWRos{5Pf9{LUoSZ2SX=Ac!YfEHg@w>Hg{@TQ1N%#O@jCw8G zpXTo?6FJUpn`1wi@yI%6ehEi}}@vRL{rfNo9tb3O0me%eO3c zKPm{A7n35k>2N+ca(;2K!a?5x{7SV$xT%hNUW6tFC%xrlj#SQCrIZ(US#~EuXp4(lmno(D&SmJhi!oFV!E%24xwbx!`+PG|nST}WztT*- zlhnhR$vTmpwq0(sA*XFuW7|~QV&b%o;DheOc;smQ)ixnAOY5}l_exR2Bk(NhU#aBq z5YpUAQNv@$EsRg9RC0I-X=tUA!y~&=X~W}?(-Ya!bQvB6Plt!cO9X> zwCz%@JhxW?rp1R8KdJ^FLP}TCcjcViceUalm5b!Q<-&bc-Gw+n_atasaf><+eX+lS z#nmk;lTdUXjm>Fh4!YOlEGGl9nUWNa;f0N7w&sz8(Q)G&j89Pfb{!o|BC$tyQO!7g z1+zysBi{3XMo&UEO(1}8R{Vr=5|eyvF^8RhbL{+2%pz%_hWczy&ez#|%p9IL$tx$< zB-=bX znS58h!1o-epb5sK|A%it|118evJpr`yQjbFO*g z$bXn?+QZbO0fI6J{-npSht4%~&7>2hya&qjO%|OW@q9xPhc<1cdCqZ{wQbV~=TKrF zb*zlVE9yCvkbYKDu#9uQS*iFJs^4|a)A=WBnuQPq?c_31U3CnOwDZc8>?$EWP^M&8 z-BPBst~%uGs<+xpS3UArxT}g9Ygbi?>Z%|1JG<)mq1atzzW+_UE$-J4Zrhh}xfUxv zPlcP1URBaqBsqo0;zlSwK$C#PJ8e4k+o`91-6b-s99QFZaR-Zu%8_AH|F3Xz(v;TN z&FSRCfCt_Vs~np~sT{Yri=}ehb?`vsso%G8w#@S(T#xqPqI|6QL=~<=dQC}#k>p7{ z*FIA5ZkmKibn54Iocfua|M%V&%iZ}6pccp5GF!a<+swS=Nz-hK!B>!l}O~#FcYWunHH0^0KvqcvKDZK zYJyMyCI#MyKZ-JY2ITYz1otE8fM7JFZ(jtR5L|+wDYVGvBiM)2o(<%`@Ax}L2IWWl z?+c&D&!9!GJ&zy5mVPi;!&c)eP5cQaDscl*Tk$EHDcnH7v+c=KmOdn6g8M`9JEA7I6*9q@Wp5cG1;Wf0 zER4fxBMjXB#Hx6*X7v?jf%4cB>zXszsXV+`rQX`mbdhzt->FW@H>w4$7d+MQYE~QMk{GL zl1zq<_)*34H3>-nsx_Y4ueu@YU`%YtXUdP%u${H1oPNxWLQFcs_@2KlP76^K0;GRa z2vt=j1$!Pvagv?INp%*dX}CB%z-V;k7bVDzc^-db@^EARPAL_e|JU5bC2eOhG5-f_ zODQr}OKQDfg%97iQ5ZHGu;%}=5Z#G+;xPnrE_w}u>Il*?U0jA0{QMJA9NGtXu*#Wc zG1&(YjBB*veZU)-W(pA8jo^9&e`D_X36=)8o?!0of%CfdCoFdp5Nd=n`H`X@f*-Jc zUWi~Kg2zk{Z1Sd=$y%InoN`6XXX7xRk>eRNpAjcu9)r&exe)G?OX6n!KW>?36PW1= z?6s#UzDPM5q$%M`5-PKwe2uDUZ`FX!a9c^(EJ=PO2HiiLDW-!q7T$pz!*0#KIb7^s z0Pl4ydOii8d$b5|xwvSl^BFIvI4?4}Xdp!vz~wAJ_=-=!8gC30;oydB=$gQG4!*95 z!Jm#{8f{AK-5mbc)T4=9*SA;rhp*fZHVi!q_PY)9=RL=Sf#}_cjdHx;G6d$Yn1JV?^LWEAT{gM#8Q5Yjn7$Y%w;n#=Rv^Uqu z73Um{;)?sKFuw0dNv;4X@`Diy6D3RoIk1Iy3{4%?pCsa-Fm&PrMn=UlK{srW2S5_$e`-jKFbe~HHrChonD z(;ht}m^_$B@F8~(IV7+r1AmYP(BxB@^I3k#k3Rq)c=rkvNgG^ z&*ogR6%T8Dgmkl#>OjbJ~WFpQW==f$T>o)_PD4)ar5I=qqQ&;p_xPU^Et)BIFB zXxrx^+zFlov3dG{#pCr(u#kRN(zfzWKKoMfqVkb^_6@x)W_DBOy9?ieWP4TPJ`Y|! z05_x~6d$a-N~BKyhcnH>=TTbC-gkiKdw+RO(T!4YJO%=uPnMRV>L@=cwyNXrD`Tx@ zUBAm}cHe$mtna~H524DN6c0P3719zVO+b=Y@xJz(g69lHbb>qiJ9%j%W$I5<_uS9D zajQ7eZEjUw^yP%d$sV5)isGV8SaGp2LU94DZZ@5uI~5A9T}6iRW|_Y{pIR_D9Mbw! zG4K%Saq~~qa2KA3-OA2=wnj(LXO}f+{9DC;&^`mHe*!I5t-9(RiO1@ymtSY>MT?2L zis69g*pgEEusG z@nzcmM56vo_s4nt*P2Kl?u}xEn{ZtG%HBvu5V(L~-{+m&bA#Tvy&U1rFcUnuSD4_2 zm`p(DQN!0R`)5X2>ceY!4n}B!pcaDTV1z9Q>LVx%wn%apZp2XDxX0G-6SU{s2N?fE z@hRG#AVspp3ws=F(H9G}XZA$01;YVP@+VHVs0X%a{6cKDsC#)VwrH?5iY?C7;_g5< zJqT=l?MOHb22ZO$5hqw|27$g5_T{^Y8HECFkGmk?T3nM>}o(S7II4qBmD`s^T+L z#UrF=m6RW0rPW9A`y;KiSRJXy`DNTA`I&?K`4AgW4ZMoe?Fk7c22>2YKXoMcg$<~dg`)VU-E_`mW~e0p2q_SX;-5o* zFg_$yl7EEMBUF-qZVa83e~2GmxkUKqzMf(JseVBT11h_ITl<5PfA(zoxBO$8vn)5~ z2SG=3E=Ad24MsL6!|u;YYtH=R<%Xo0Bz!M!7M*>3*UnOw@d z3-877z9`5XQ3qEAsst@Z0EkE(nh0giV+gt-xQ3RXWnM5t;LNFic>lCLv*PYV(V2T@ z{AK&IK4yzaDd>O2%j#^wr2G@EAy1eH{Ukz8HZe0EPRX=bhOjgqPFb8PJ)GAg+{5%@ zxAZW1$TcBP5hnW1@0=Zc?q=y=da`1I`N*Li@)0`oc?epPUo9qQJ_4_?a5EG2R_vhW zTdXdkGVFN6ZbJL;i#GIH#^*jc^D*sw1XB42+DJ|qZ<_nHGiR~C=JqahaeFtt;wP;3 zGoaY@doH!*xQ_-kcDzXz>nwwsVQY=&7vpC(wDa=tS=HX`frBl0gwTV=M#!b&7{EtH z#PYD>2j=hP;2+~mfqNDI1AqKbj?0^Y(&m!#BagH9Jhk0&#Jf1~_zTlUZ^g&xfd@$9 zs)gC5^>zol%)|3&jkZU!3&R1==!U{Bw`7Ldr9ow7ml~1m^2xVOcKPM|D0W%-r!C$N zIRL?0akk>C!v`QBjaSkPB>DYf#-C7pgeDl_5$hcMoWr)bdXr z~YpE^Y$u?=tAGW~jab)r_ z9Ldd7e6Aju2x+2{0!Z>M9NG_4yuT&^iF(=j#zgfpoFH8joWZQw5DTiS75`OdO(q3A zaW6Wq3)lxgGF4%p#R_}1icby}JqL^CR2fsU-po?%em3?0@AiAyV(HW${jYeZu%#1| z+H<-wO0O3&>*pw5CUVx-~Atm$&t!+PchctVrhs9IEUIk(k*weUt`$&CyItc4t|_vU`Hyxh*y8jCo27B8;RT( zm`~pTwc4R=^697WX@P&XaF&VsUI)h3Sj>y4fX~*(y@t}a`N{%65Kqf?-G~k7dlJ%eYBYX&igxR0*HJc?ipGeM3|A9{{L0VN86%Q=otE2 zOtwXUoo~feB^lLqggsoNxYdObo7(rOn%jwXhuszhTT>yki(~3%kCSxa^?VMkU(#{^ zZL4LKZy~fc;C;z8ihrm=OGxi2X?z*y@Sdpnqh%t8_Zl_N9eFhu;`jyb!gUzv_h_n* zFwh70WxS)}FX}*Nl38$sWoAxm6Sa;+&AHShuZ9US!D3aBlwdREH+R{!WYGL=FcE+K z#eU~ve18z^E>pTq4p{J}gml9x}<@V2s-> z))h$s6Q!l4kQ({|RPbVpi5i+TmBzM4LVyYu}mR!2U^@P)Vn>@52> z^S8z%X#KNoR@s6zhBa~n#lu@LAyrh8Y{8B^%lN^cEFRv132Bp%oLjIJ7AyS@3vH>A zJhI~YwM%%#wXtkW6}tBe=aQ?>SN~xPR?S`T)hRJXE?AC#)o>R~Gz}j59^Eh!Vl5lN zjR-D2Mel!)Fv4Ni$p{H%YWUla4$e9NfA{NtjN~l9GI{F5bj(?05ekd*dB6Ouq~QIsEED@%EXlcg?4Mc6 z{Vlp%)|(QrrvHr?{}#Ir*)YtPV)?Egx!g>DRLw;UgI+kN#62_fk>%#^9h2SW z&9-jqF=A%k%b!`c**TK%DIv|+%&oW$Z;npdY+F%)5t~a6s7E)KHlQ{-FNLkHDFbTk zP2mAGJuc>@uw$P)2UN{3q6UYL~zL&qr(fzgB@P`I$itK*C4=0q`{Ymb^EG+4oJG0sWAD}5wSphCBD<2+2H$fB9 zcT{gCE_<}kmUh+=qE8OO{hp~mSQc4?J>Re~j29~YlJ5CHvNwQb zy~Dm3?ioh)EYOE3rr8*=Es+AAcZ%WD0nTu%GlecI`?J}K53U}lYQcHz4^TYda^8M< zMabGJdBe6!66%GGaoCs5|K3(87Ym;na1=U4@$S0tsUeO+ZP968l%w%3LHeDoIDJpW zD`|R={>>fg-~;`2;q8d;Yag*X-{2y4&4B}&fi&6f<(qojz7rlI>w$$hx%|pvVm&}G ztOvjWVryyLLJwa_ETYx}CIkO>wnA4yfF8JsGajsXRTZE@%2d)pEW^5Bx0I&%MqP%1 z#JkmY8Ds(qYuwq^@an!|Mz4hmHRa~cxt_8BV|diQ0V=dxj1~vt>Ml8t8SWm zL9w^OCh{&ojt@TFXiFeo=O$wr{FdTjuX98aPY=mtj547pkM4cFiE`y=3Ns2Qr<;eN z{{_#A8b1&)8o~$0yz3T0Ixnj`G)}vD@y5ek+LX zw^6j+DP}pd;ae$7M^nBAuv%PVvCC0Dg6UJ0!w$S{)=Q$Zrb+rEU!>Q$bDZ~UOwbU) zIS95xP_06+7i*ZW5lllc96Q1kTP}KBH}nOSwOk@&$L-^~GZ_xpM@yF_@YSHu0C-B_ z$8}A9S=jNlAp`JZLyc@a_;=*}+Ccl1HL!OY4Et}YHH2b>y|>RgMfQyP#`g7fuq?Rk zGsXuhURx~-KyrA`R-xEAmnu463>_zkjdNQseE*pJujaO@oP)(Z6%~J56^qecNa#J4 zLwej(D|M_r-HbU`VRQxjuHr9r- ze?GmhSZ;&JJW4y#E}HID<{6#*(il3|;Om`P8vE>o9Q8gl(%M(Jc#@VFyebiY z*@$X6vtLT{bYVeqVEwqmf%T~Hh=l{|`>qxT){8q)aXo*3CH+sXimSEYYVNR@xGDy0 zS=05mWzFK%p*U#N*i~`x+PCE%$nTKXE3iPF^p$P3*TJQgp~rbf@n>DOHHidGnHXYC13%&b`Lnr9iY1ms*@W-(y z$VBihCYlc;RF97$$Utxff)<#4Y9V+Mlg3>L>L54`2il|8O52jIax-T6$1EngN`gb@ zM!M*}6*|YO5NyR^{bzJHGV3ujE%iMSv1E^0ulFOdn7_NZKH;5F+I{?eU)uh-2I6(} zM_jy3idR?hN+gm+JNX>yBZf;N zI?kc4TIAfr-Tq0`IaDhxS`GwkKNxDHD1N&NSRqwV(p5;3gXQFbFDzbFlQ1bltLQG| zD~sXvRyXI#A(b*IIN)oFVOpABe|9?F3+OlG_~XF!j1N&feEcD#9!e6&dxK6h-d6Fj z<2@l=tfXnq)vd>^_;5{vslP|0-&TIIm8X2Em=$Rxzs`5ojvtyU5F4ktYoy1?#_5>Y ze_2dyoQ{DDT1{~JxNL~N?$|$kE|-eW>bYFYim}e++ANN;aY|idt0_ku!|vvyB-*0L z5r@DhRtubEqE1}M*mjG_5eHyiHE+u@E9WX;fTBMtc!#fL*04rsY>-;Q??LkzM;y73 zlid-V&GFuCs~v5d3wJ*^td4A3h6A2y&pX?;9@=(Szu0a2YeKBH-M;WZq~pEq5OAvy zyosO?!5@%wD`~0x)gU929zPlDzP5+BT#UDB)&rb`YB+v5CZP8ky$V;E# zkH4dM9WAnuo>S7_V9a;n((!S{e{$I*AW>gAPBchy)LA04wr3a~?7G%sqU~YWF3Ig_ zkTqMXU?V?bGU(ruGdQwRu-lP=z*{X$p0F0a&DfU~6HizSlZX2gqa2>F)YyYPVVS?T z&EIo|J1zv{7lX%tLGUSpItWga9?Cz!FwiQ!Q4q1;T891BS`yR4cQ0e%1BCj;A;VY?coZ6qja_4w9887R^84pqX zQynxy>Y=15NKzfIy|-0-m?mKo3oyq^bMzx9KN5p0M$;9cp++k6#j(^^a6c&9%ww$d z+EwJJc7+@GQ=5t+t4;8Ks`iUTwya-b;2(x&>uJT`)qyXh-b(Tz$v_y^-(<@&2+;xC zojH_&8=O_&Y^zQ`7RisK;7@WBDLL|*cVvYMqATP#!*d`;a2EuZBalY|#K5*?#CRTu ziEI#pt_YeU7>lWclrF)^ea(=sa;l_1smJccT;b`mOe#$PDQt@rd$B`#T?jcW`c(;D$5ZkF>hU-6z6x#$JbSJh?NjvC1zidjd zIxpj4Ej8p42ZjIXl$4_sU;%I5gyH2_N>70LiR%?Qq7!`kG z0BlCEnC84m*=7Jdd%6_=eOH73)ZV(oQriGkz<>Q=tACl|hn1Oxbb*q-jo`n(mstG6 z82oqMkXuZ=ZzWz%8m$GYbJ|ZWmMUw3>cW4`!GABt3IC1i8FsMuo%vhB*XW3)o?7By zsR<8pwht|dWGR9TOQpG@4K%J_62($ag9#cgDaleospmLVx%Lxi&K0$N7V zjR<$aZTMGtcR?rfuh0f?TWtiVFn4^9U;&NyZuc1$eC8j=d%q}tJhH&H+D+icOR)I< zMe$3OA3;KEE>(KDcqc#3P<%&e{8+&~@?G%bIqt$d@Z+PBBxeA99_DAgEOw`S`p194 zj~AE9k9#8c(Qx8!^Y^_EcLM{aBnj?<$It;4+y(u>ms>xI;>!kDoUi(*Bwq^Y-H)R9 z@(|v2f8nE&dS< zH$W$y2i9n(c(UrGg_NqKGi97inW*@$Wg?hTjZmw(M?O%7`SJqZ3~v2UI)FBVqoFSR z(qgh1WSE_Jcf%1~VsKx&S_5H4-88%zBtyu;y--Lz^P#d4r1{h|#vf9Ap^hFVMcTJ^ zGf`XF(zG+lpXiPHTdXmXG92)(-X!P9e0Xaz+U;nquR@kae5?fWi`!`^ol#VPu z&#%WNzRO}_@d@~n2*$N{|7y7lI-2}KFQMJ#FzzJO(pwOGOxo!tcNuB)#K}_qAF(`Q z4NCs*G<&}+E8?7N^<3NNucI>(aB47D@$h*jNcOZyUB8dH10n*qn#N}0mlqlwIcjkn z8qaA$!d1kPA57Ms`m*%hgW60lZ=uacgqpkTv zz>``X7m0%IdN3F>1@wF}$JTiO04+s&r9>JgKaz_!Q zOnI4wmUjUfDtKZ72jKTql>_hvjrJE?Z#)NQ+tT#MQci3qepI}xE&)rood{u8o23c9 z!Su01-al6S1D!s0*f)^tBtzIVhXI8teAB$vcZ8~%3<@8j=)N|F+l;`;Uzf&$$M0#Q z`Q3o;Bw_k*q{ ze8}tdZKm*|QLqnc+}5y=zF*@q z;9E~_tzZRGfgMZHMKE$K)g_S}OPS%GO)j}Fd)G0Aoq#ED&37ZGFoGkdF!6lxu?f-x zZ4%P?5g<|wzTHqdB{UpSIwD9t!_(NZcO>I$%*RsjPReYHdGIm7d~*W^c1^{b7(Yd} z+GO?)R*8NJT%pSNwGX2E3k2^V7=_?r1hXK|N0U77b-R&ljm{#^-xGOmN?7q7%N}Af zRVSNEesGqQTui0_mk`_=Gn|6^`&<7(aEsMU#0^VfFS7_+MMreOWG)=MSXh&(pud}` z(zV4U&%d}n?07SOH%&&@&0@Y;28+8(XIZ{kCf;{*Au0TKk;ILUkhsM&9TGQn5o5b% zMoL_U1Ds8k5_kMdQ4%+IrtJ}VujjTtT$C)u!|(M7 zsl!aJ^vMMN)oiA%GysP~(yMQw4zg1kjz_F{bV4{LHdDvGahi<7uQ|6}UvHGj_^?|* zYaVHw<*?!MhV2F=RFm<2X#L@D+v;rsBNkxA^RVK4TEq1MDO~hSl7AXcPKcTu<@AjN zwm8sm*Z(*jh7P$-u3ech=Ffv1lluy_q*YRFY@PS**DA{HNLe%(} z0sRKq!Pa_9n+e=?d@DCoyyAV7yFlV`YIr9oypv~{>8~!uEDyvE>oSgaW`Wtg6WsLz?@wXXD=SxO8k z=k-3uo8(H842Xz9>7PP^QgU-k<)X(n=OJEpcf?qw`-dgRo`aKJNYw$ofH)y3eFj3ZC;MiXw1-3*Td+4#cg19v16}sDOD2V8hnF3G@#$Uiv1| zKeF>$*WFqb&tX!pdRJgv^)toWREOUI5J<@}0c=xflCLbN=oLz5H zysu`9*){ykTqhH+zQp6@#sTaM-4?@ggW-ej9?K88&yP1@kqO(DwP(z{++fRx>rK+{ zrb^PwOm>&F;p~=KtQxW-_@Mjz3(Q~Vgk1|w`oGNI*CytRQ*EI|d)N9?&f#gr!`eF` z^|qNiw0B)C7Tay>n_ESD*Ecb&z5BYlo(ClH@Ccs=d^g&uy*nB>tM+azcw_(q@i|U> z68xp3;h4>*WBQl)K2G^%^b}j?#pu|Yxm>wN6@OVf79`6rncgUV!Hw+}ny^O%r(C3X z%NU$;9%~&>ydteiT1WRcoOZj#MC(Yfa7es2%Hvq&AuUXb4{eH6lS_Xv$ZHl$L@xco zAQjm)%Wm`cor(11D{x$g`{n&82}c&-u2)L(LC07Akq@T)EPT-W|KsgD;G-&@0GU8$ zzsE1sQ19qLJU9d~AVNS&=tq;I8YE!op$MS|2!aR_On{sr7zL#$5ET@pg|7%Gh(W3a zjRnMlMnQcs3K3KgB>C^|%((oeiCNs5k{*1N zrq_du>5?Ac2F;BSjE2BXYyNysQuCFIf}9sV?6Vh7t>e|Q8QkV6usL>?z%LbUGen8{ ze?VXV{J?&D@m(*28-AC-M@nw^3E!%CPo|gGO3dj%z9?LaVr@dGjE-PbzU8>8K!KsX z<+%?0N`9YFQghmp#JhOnMs{(T^9vkT83<5xTKR%Q@N#e;o@x6pV1vr2*gyX6K0gCpX@;1p&0t)%$_bFQ@ zU$Pw>^@jRld^VF&aY)5rXi|*kx?&J^J_YX_AA+3?0lgAXyV{ND`dzC1S#!a@QGI-U zHLtbdV2)aXem^Vl9fdh+iTVw$&b;nA$H(UnjpGSMc}M?_&WW@B9Gz3kBu8h@^E^vZjI!UeVq|d~o-9PP z_jz3f4?f0lbDlR=FhhG|!uin&R>5B1C9m&*1=>I@(3q~IR;Ef8NUEO=P(Re%mw%qu z!;?@yhyP+lxcnT)j}!F+QGBxRY**dXpRaxncZ6AicsL-E9vALu_o4mi=c#=0Mb1c= zPp!3{W=NW1GG5>J1m?;1l~08m1157E?kh+1AdaS!t?$B??k*gMldXVei@R(=Xo`bR zD}L`~ldWQ3dFkhLT2rlvQTt<+QEM1F!}-uF`rC+`f!3^V@BcR9XU_Q3n$=6B(t!C5^MjRKPkw|2uj+3z@%>NWkB9{?h|--w z7N@tDw}-hU9;2mq1m#Nfq?2l+`8~!k{DCKWt+jLs98CWAW0t*QC8#Bsy{U~%#3*jN zc&{TUiKVH_5g<^QJ=GndbY4fHB-vpFDS@^CQo^AQ-#q8sl1wmbpXGuX4a;0p;h@4| zfp?45F^Ga|O6VNtNRg%ne0vCNe~Zo?qV9mpqL#30Bh#ICV#1{P;aGB+2%fXLy-AfTL1* z0V~d90)MCA1*1lZsOvb*2M50%5cqF=(|jyyGU!exrd~<3TKwzG+43fxNr&m~7)fVV zv==&KK7ES{lZHS7U2mLc(3VSAQCl9URLCb#^@{Q{)Ky|8=L+u`a>EK_oWT3;8GRttwfqs_;w=PM|mgWlcvIVfVNcEjT;BAYn;BI6XL%fFw}Y`v1@Y-qo;de9{j1N znZG{?*7+6?2uj8fbSDx_d&lQDg3s!LjVuN~vEFVDDqFC$U#1NpsANVS1Awpw(J?Rq<6pC7qyvd^r4E%5pGudm=W zfzO2g(}?B$tib!8356)`-_L8W^6!UcX4V%TjHEOs35JKsN_y9PwFQ79JKc>{aB9BX*Z>oWW~fln{T8y-fzC!!{m)7z!j1-_5?#5nC# z#lGZ8umVqrw3FeEo*&=<^8|tKEAHrFQS8~?WL8->eCzmaF*)<*SHjMz1{{ap{7Tq4 zRcasf`H8fi=C!afu66H5;7Mw-MM=i&*?kpsNR6P?$!$Y zyP~7Qs3%0!dibPv2Gqa6KOsJ0Q5nu7C&R#SKgDigVNb~|pb}UvT=sBU$QT@rZin(W zKIQQygwyAw*b@f*Y+ z;1hEnd)bUj{^QW|jewv%1a)99^MO>I?O9rjW%*jF(e^NOhBNJHz3su7gh5UG+n!#> z{n?)WbEKJs2H^Xag5X2&TethRh>>6l1UumZou{uC!^YzQq`-ftV1el!NG;%?;Ex=K zcOX%8KUj5a0=HBRquA!BJ!x*EG^!te z7%HE(F}&%j@ky$(ad^pAFQyvt$(>y9Qq^wl@!DzHRX8w3r+_p`XqpGHX{H*QCY(#4 z65nTmje66(w`LZd?IT=P^n@uK0xG)ay?4*{X)` zp%N5axg^FF^|py|h5T$)>~zEZ7c&E{KkoXQ1(^^`hu}dHXd~~X>yLl=^~awtOZDxy z_%yd}bo0R3k!>Ct9RCrmv zZ@5C>^TiF1#uG@yH+%zp!?7am3*Z|zna1#a1b%_=4OtXB9F)u(7WWP7EYj)Y2QY73 zc9BsZ89Kwc1vkRPP>qXg3Hta(L!UmzNc#9%jz4|eF+=hVS3SW?{Vq6qQ~qT|Ss?IP z!qLO1F(T>-_$28(!}k{W(c%*t)jK_b`-TbJH(bE>64Vl3Gy+O%Vb!5{A;*^$lvq?s z5wXBi(f?!igQ;i|;q3FJdIRghG?_e&ZbxOfcGZyfPE%UpPu5+gPk047k1?Wj-$3V4 z-Ua*%{6W!qU{o^^wGKYn?`HU#0{^)9ghgdIXCFd;vV9>KJhy(}1T6$zN)IkT;iZCs zT*`N#qjyN)7Ylk2l|-jWW2ry+v&)n6v77vA zu?>k2lh2mnXUt7Qe{wd*H8c8?>^d>L#@LH}s&^0Arj(=cM}(VJf}Ui}p9hw5sKJ^1 z{_ji0`K=+QECd>KTDo;K63m7m7J9ND=IcuN5nKp$YQC|Q6rJ2@=RV;~eqwMYC(w)! z8lA}}pl2ElK_>|6LO(TqzRpj(T9E87&Q z^Slh6;^z>ogWz!phCgtZ!n781>VlgYUOPeGbsv}%uX+($2xE|=EX+^$3m$v>T?lw z2K3O`l;IBu{66ssM2Rz0Y)d!2F8Vdrv9TNfdcZSK@q905oF{!PJ=je5a*EBKCrUN6 zLBqazsf^9np4sTZ%Pb=$#uhrgJ=p2h*xw)_EMAqR4gb?~aFcViewE5CR0brU-wpJ% zfojMd2EmVDt8yTCiOvK6v>;bpa4<)?)hu59b^V3WZOZy!GXHr9EaOM7&^mwa1R>m zl%IXZ`s#XNtl8lu-!+53$LnpieY|wd;NP=&37>@<>G#4W)b9j-wivHq)DaOi5I$J} zOVir~zNPqtMR|`HZqZ!{GFyPjlNQljVR(|jaT75|hAv${yEK_Yc@@K_@8o+{BsG{uR-oK@=|r8924e7jKq-pNJJf-LZw+8SX=l zLwAg!Gn`GI0C&toTXD>NpmlR=`rI*(}GpFekO<``-07?;S4{S#P}bFj_LE%3*M zMZu`M6WLKF(>;y*k_d>EP;gp@Z8UJ{^qP!FBNOY_5aZ+V$Re1^NA8m8wH91p1z~ z;FI^CA!-m@m2&+Uhph!ZRd_cTb%%%=3!e;w=i5sNe0T8)i^|}>R2@%x_b8I`>~x;8 zDo{B4E2EGj@K=O7(I|Wa;$e#PvSaD63oZ(F!7ZMrAMCaOl}!?~YJ&HY#sdGA_ynTZwX`&1E#t2*={dR+{hQ*V9bf`=hrtt>3LEy~J?)M$ z6^KF=Al`cE7q%HxAUcQ&tnvyK*jm}A0)w}46}Ym~rvg`dp$f!9-Mb;E4*_18n+KZE zeVVRqR)fpgnol#fO@_{JX3kf%&2OsuZ=0X&^w%~|kCcW=WuQ>MfKRj+g4GbrfnW#( zJz>Pu2!cWwIDHDiE(kIqI00jYEf6e)U?K#EVC1lojvNwd(e>eLDu1LCoomtEmsn#e z*NHn}b?{VACb64SIR2(+1Q_+Bi2BAbD)>O)4;uHKq#NF+FK1uI_GZz|C&W%TSK?>v zl);_gJ1^omJY@iA^}FWbj7on!6&sv|ZYNQpX!~9@m2&Luv9kONdWCdt7o&1zGUD(G zX@<7%Q@?zFd@`3oAvC?`;g*`60`I%P2BTJrC>+PO1T*xw!28Cr7!}Wpq#MWf<2e8K zF200Ub7~3ae6G>ItBkIZZfnb@59@uSE5ky#z^441E~HHRCt;bIk#deYz{IIs+jC$YZoUzkO#Lus(D0bzXi zUN`+hf`4K4>>Ry}w?cK&xL*C&&;0{!U_4IuXT6=kEAS3zCnew|)RzVRhUgt2igcW8 zljfX9X#FR!(%Q?hkESK?(lSJb^9#HbQ+weXUuAarQB)>7&*bxSOApc4itmJ=#ext4a40Y2u$%(4Qvy36dNP>-(#S;)04aGpTHi1>iGN_WT zC-5o(1a=p3d~5zu7)MBNzh*=53U*FRq^Z%+4#oBQ*@O;l#rI~&Ox{rwXe-n6B zyaHbLJlNkGDe$Sn>xL+C2?863zd-5G35QiUr?gy5575J;wZvi4FCWoWVSPB$a^w+X z6*6>&b5k?@%|s2L3TIUCe>2gz*ZfuCq#;rj#yrCL!Uyzc{LYFJE%3ev^fAgQqQ=7~ z!{CMB(gNR8e8QqquG{Px$ada%9otu6H^E2ajchY?hBM<_xQ^|5!1lcI{@I@Tsz0`8 z4VKs*I-ZyHS?IghRAoi!D)6(#&K`_vB%%hwClxL;d}V=eDL!FQbjh8woj*>;_Ha0a zeR`acZHCTpKKiYK?ZxH%vpr|CKeiu_mDnCTj+b>2*wyQKtSEg1K3@1A7}Z=vb%sxN z!?Rzt1iqg5ghjRcz`g>xzA{$Fbyc`I==-rot{FPR8UKx*>pOw#^l<-NFWTgf>m`FE zuBVP=wr4yH+(wP%wg(aY$8t^vfK_gj!0@dFzPYfdFYaIR^64ac7Zjg) z)qec;QgOjnfTuPL@0U^9RiX@Ad~j%uNGoImjt{_2Z-d}#FxLklSPQ{?2u^^Humysp z5KM$%5BT=aL1279e-8NeL+F$FyDHH0<<|q8FaM0W&h&nPB)W+WAFhmt$yA(2^|GS~ z&i3)V>YqoIfW_Ur1b(hhCD^et`sA}WmTfM-IhrTx3m@aV)ISM)Q}Hp2^1|u#VxL{>fZICL2zyHsQF@KnBs(Mzev^_-n zCWm2e1j|A15Ln_B&%gf(>T?Q$oe(?;0d-Ebz2!*7S0R7N^*vGelS#xmG+l0&?u;G9 z1=|`-Te~idk&XgiQU!ojZqs#)Oh%$Gx(Ov1iq*Eghi3sj>IM3er()2QlzX7 z6fUn}6nYB$Uqa7llzp%B$1zoH>`|^)z_8yTlF}nl)VRZWj1q`XnvKStqP?xR(a$@5 zyO!FcP9ATiR|w4XgFAlVTGq`XuyXpfoLC{d9w<9vE+?>$o1!}&M~{=z3NF}5Wa=eK zF&$=H=Z?Ul&|7u-!)e5E9EZ2+P;~xmrf1?-ol>B7KY@nrf#5mQS~dyJgYh~_9ncnK zi4rcj8SuR5aF{>vP!5$(%gj9+0#z;=NzFFXtuMLi5YBv^)tSYP{PeTJLO zaoE=~bcXXn8uYc%v^RCLp=*Y-UYM`1jh6b_YU};=wYB?6eXUKD^mo%FT5BVz}soGIdqL!j9(*WG#w!xs_!Mowub z%ylQ$@}&G+&u!oPH?$KkOzpH6geC$Zytnc$f%k|a`FVqRD^yG2Q2qtp47j%*!=FVw zzZnqF#6lT;gROIzZ$M89@ujN=PT`;xb_Pd*EoBcc%P+*~?r9-i^up_HevZSZU=V#LN7EO)+JDAy;T(rAcu{nVZ>Rz6Aqtg*h4PwT@Y)Sc z>RB3;$sYy~zW7tZ(A*9~@G=B=r(-UiUD#2Qw81q0=V$CCg0#OLalEeZA*r|FCC#RB zdbI-nSd_l~m5tN2zjg5pcjaMY`(x+~XOAWN_E!bk-^QC^e%s&5wf@@QT94HJk{{+} ztpGgKdX*I=LEwKA#vP;jizs|ZYA!55wHA2aLsBft`yqS9Oekro*`TCTd`kM#2Rgr) zo$`)^+d)LrWv2;*Bg#^e@4i|F-2l3!QNmFOq}ZFTa>aiA1@t|Q4@p&m;G#jT=tEN4 zV_`&RzCgRJIv;+DE;!=(aPc7aa(JSd%_C?O6imto0wi{w{fI$}8-_F60OXT@~H@_?^)Q7_E!S{Ie7ON%T4S7AlMN(Mj0 zl#W{)fL~`5k=7sY@m{ze$BrRBJgK@~RQ6`CJB`YaY~QeT8@j>Iy5 zlD)i7>_35kBp|r-oiEae#XsiRKv+p5g{5~cj>Q(&6TXyJG|PSN@t%W$6yK^17091m z+YS}zJ9A5~T-wM-W!YSunr$`ZCiAiiJ-Z^wpO%n8w;@EN*v=PLN<4D9V)Dn0^)mGj7O1^A|E{7{{4GfSjz|C6sS zwMn%o+kF4~a&gu_oN2+5V^FXg4{^2F!NjvI4VDeh3;YV2kQEl9_|tmTk~_WmG<6e4 zun}##Gy5S>2@uT74+)hh4_g^mLD@)A7=aTxv5d|tsajJF)!Hwkd${i$M2(NhV0IO; z2vfjJ^n(tu4HlMN33&!4YVYDWyb==7dR>pzHMKkxbA&c4>r!!kGjKH7m5_winSn@) zI;iJ&G5YUu96G2JonN)c=b(}_8wPSAo&*d3I4s0375J^9m%^wiB5E0YGW`g{4-)tU z@d-qwatoL4Y&MY9zyol$+%=Hb03Z^G>v7WtFFJYB=aAoEX1kqNWAvZp#~44GfuDgU z_b0!e;bLo+uwkgK+=$VImGJxZ*XcS~OcFR3kvOKMK2e7AlT3Xl%ihKE;uWACst?Hw z)1zUG*7L2)d}omFzKVD;C!FCd^*8UD_4oXW-ubU*{PoT^+^l!*Y0HnGbx*>t3{%*% zAc%pW1q6FxQe!m)^&uz$?|i@fpiXB7!+wwz4;pobqVql1i}iz=Rj|-GhraB+^!gPt zUjD~0UiR%rx`$5P!hR&uS=5_Mp(^RVx{9E+;nF(YxLGV&Hth0v zrAO-)0@{k4--1zzH<{t<3H&-Skbx+p!3B>&c5w7%4A(wn-37mceGl&WT7};d{eoQ& zONKxvv8g}Lx-&H6GO%p0T;S`8W=x}4JDky9-wwz0SGU9OSdJrYFh7z$G90~QI!0d? zU=QW{HOuLm!`&#yIFNceI@oj%r7Z)RBP>I)mk)V!jMg_tw^sAb%f(`1AORdj=AdUd zAHVGLkrSj=IAevsRyd~ddVW^Y^H+jVM)mf5tXISxj^fg)%iq8MzUxOuS2~_Bds#?dt zi6z9o}DZlR;4=RR(s;3cWlqX)mRmluf>!+MAd2C0MZA1A8K41^!8~V24rd zL{vO{@?H|d*BAJ%;u99dS{xs_YEP~$D&}5s5@jjhqho0&Jp6pxV`Pb;Gn^B;DOpN) zZuaoJ4?!RC?R|_+hQMzWeFR3$5>X4`lY8G|_+bJ+N_+xQIR7K!+m_U;++6}6QPRK4 z)wD0!fR-?ddCjv2!5|@=4HBNjxM&vlr7kXMvJc-SR)>E`(9#KceXMWjkwi?rWQ2O}}6zKALTpHv#p@Z|*lyy$`; z%3SVaUY~N-v1BFX+Eb)d-oc6{|m=q?@rPA zRdnM75?RWgN>5XH*sbTkkiQE4NB%BrU)GP!o!%f7@F~QXowJ6}tlC{~DM(&D=CQo4 zcjNfd!h&Gb_ucfC!q;h@V0hYT9_0;P-D!TnRFQU?E8s8aG?#VL3AYuT_MP3$C|ril za3*!M&}p{qrW0XVctN8X`p=3M=fRU5(5$bcSkaBwfwun} zL>|vT43Wn&n(z()i6rLnPnMLq$x5B<=IT`h>NV#hR`LXa|6cSX7}Z}yy<^bG)^4tm z8v zU7Rj-aXkE0cFs=n^&ou-Prk?~c9BZR&>7CWXg?(^KbPKV6HZDj(-ygE6 zIJXK_Y(23C>_?B>&$wa zf1R-d|DAOFe+Zk&4tFy0&(ImpK5hN*?;!e-?o98b(~Ot8F-mhg88w5V^Y8joH<+{K zj{vu!69jc2__v6O$6-(X0sg9GU(yEVwHtKeT-OD2Kj~hEuORTnqH$qVVMiWyPT#nk zX9eE3rUrryM!`oS(J!Q-9%%(uW;%lt5FBK*{`Hp`m;TM!&0`%2)6L>3tFviq1d# zhk=T2O^pQC!O(vL4UJUdq^pej`S#4s90L1=P7??yBI0O!URCcJbY;81X9ds|qNZ%a zH5rL&@AWXL$$g+E@q$(j$fE-6p7sd*-=eLvC`#^?a<`@-SK8_7b;mN6(f93)^~%s0 z&Yb%LYRFbSr6|y~=Oju|plj3Bl+vA#v}4jA1@j#bx8u^Mi2U$ER%Io@23!DbxWAoF z8~$0!zN^>Hs0|dI|G_1LHVg$dXb-{Ii!A64!JQD?{JpqXyK(+XasKh&{hSAw0_*h= zuvG7+|FJp27*dM0(Y(5FS88L}hOk)ReY;X23R^o2NPY9Nculv1)~8mm4K@=w#3UT4 z@n)WsnsD;QeMi3Zcn)*bZXI!YaZ}yc*GH}jSt}p zp7n|Y%Xke{E7n8bEHURETK{dC#>B$n+ud!s#!$orZxw#~aK*MdHEA@ICBD|is3sJh ze?z~Lm2$HbyVCVzo|0ba8VM%nZH~h$T`Ago+S@q)Euer`y50<*lT1=C=c(y!tl2Qg zp2u-`8!JPTBF_T?{5DqIu2gN>4@4X1-SoSEq$te4K9+04>lNRpJ(S6c@keWp_q|UG zQC9SE_|{9s>`9tP+#1KWIW?i8voHAt)bMGM!zZ9odlobNT!GIPYDlB-#Tl9;RwP*p zpS}Ux zE1j0c!n=VFwK8fcMdJkx!kFpar`7s=PgLZmo9g?js~YSTs)iTd)y%)2i~1+fj}$o2 z^r^rf7y6OH4>bAa&HU&`hu4^X@P~_{WGxA|FDV2qnI!Uo4GY^!e#7ts1>SeAl}6zU zR$N=$rD*-%FR4pU7%^13->5E#{=21FU4CqN3+m#*O|(7O`5=GlqC3}0ICro!iL-eT z=$XU~pRi($<~Tf)NYO-H9OUN-&#wVG!_OqPY^l?k#&Car-Ihk3p=g|W6FPH0=uCC0 zGd0f`8o!KB()I8S^-#QDD>#eLJA4e~U|(JLDe}Yt9xJ$4H9CS&b!c61`H|U`TcGU?9Mw39Rf0i(MXK}#&@PYV!tEt3q*NKeZ zmzo;+1#}>O+vbGE@7yc5!f%T&gY)}o0Dj-Um-D*``282&HrOrjOKiN^KvW=}KW|e^ z{Q{Zk%N~2vvm&jD^M#kKa-Ia752l>AJwrIJTCA|gHv;hcRTIt^KFjjtCdTh!f%iSj z0#SkZJ>R+*{A44)6YR|@MKvgIn>Ct5)@Vfjx@;fu0hPj6o_Da0l07X7{EKArAC^SI zNEYn(8lGj*oTrIov?9Obi9q`BR%1yY&Y=D`HtWNgplx7fXH^>@rEZc#+#Y`|;pQ#r z!#!X4(}&A}^gojGg@fsRa9VV?!21T%5EY2u?gy1^o(!574)=JEc|QHUw>PJ2N?usM za>u9?j$O9L1(L)S%WBXhhi(|w52m%6pA&&l>o3dWRG|95hx45U^62yk)W5(l7V?0o zK=L@!Qf&|Xa~x)kW3SNZ=`Sfgyn%SCB9SO zGX={KHNyY(ZCXt2Vi+1lFvH-2C?Dgo4a3R*{nQt|X?LOON9s3Xi35{-yBgm3rn}5T zYy2sZK&fK+JOShX?;!l&&G|eI{J#(b{0sbRf`5n##D7+M$^qLai<|Xm00(c1I!fQ6{d&5{5RE(bxn{0K5pFUWZ) zNT2WR(mp9v$Py18c=6zY7cbyXIT}YLijSMo+laNSQ$(T%j1raPS>K90qweBzD*$T>ZcglUQ9aIMckfgdI2Uz_8#J~6_)3jxL%cJxQkwW4s!29s8#$9qP2luvWs11Jx?(t()=HlblC^2}Agj(FR4wkK4LN!URc4Sd8 zov=7U3q|5}?p%2%mtYfE z19UJux@a;~hZC z=X|0LtA~NG%$rz;*8?E@2*7yaHr|tx=VCMPDJQE_n>vrS%w%ktY0xq~NBU(vpgTtQ z@$;98^A|up4~L*5XvS}MprX;&3TJ@5I?HkRTHy?|RSDAh_cm~}_%2_`eMjtwc1CEm zCXsCE<2eusCxV|nz)u9P8I4EX*=vQQOc!Cr?-RP>_xLfQf=h4u8L!+2`WM(9JMQ2W za}^9rPBiF$ZH_-H3=2dBvd3??ha06M*p`K*ki`xp#jY$I4%-#havWY+2xxK3kI&wQ zYmdHTo<|jSnznJ-_P(gMy>MkA$?+b+kPR5U0qcx*f&W2hCPw`k!K2;)99Q{l5ad2IY2`Sv9}y^OvLmm$#u zG|;mJp*N6!+k()08E)b3#BsHO9-zTeIqa*E)Oqsz&}R5Yz75mUdmr9i{Jo};9-z79 zdodur-Td2jgkIrO47Z-+>H|GMv-yiD5kQ!*yq?%+O7|P`I|B5i_Wcsgg53|)kFDYN ztjX0f*~ZlM6FBX4AI~oV@&hz8^7pbcb2QH5Nw4Nf?@qElNuLR$>c#X@-(7o{B2zVu z(Bgl*!dkj3jbD36I+QqD!JnkKd&rNTN2Z;o_GJ#yscvjWf!2QwojjIKfcmdtln0kY|T~+C+rj~^_Ty9)phwt!lvt;)s6WB+Cu)TS^ifq8uCwj*I)ir1-eyd zedh%@QQxXM?>hkzG|%?-=UAR8EKluDn%6p?KAZXdteTGB>~<{IL)DD@0y=2kcVXUT zjr^`T6iD6=>GOXEMz)=$`~e*_|3#SpvfmB)N9gh=#DA!Y#Ji9TCv0T6Qyg~>WC&=` z-*C*Zj;HvDUW-qY-#cc0o~)|lrxBRP=~a#VH0o=KA6}RHelzgndB>kTCz8BM@VthQ z{I67D`CqJpxXzG2pjrNdiF&x7-Lt_kQmc4#9Z9+d(n_8=AwqsIzlS zoRi~l2MM4F9sAyU-Dy*yJ7YUYY{q|7|Lyo~OKM=@Wz$m}cLy5ST1d~>cmGI!AIS8c z;or_6^h!g2yO84^26}*o8?wgmxVCn&y|zEc)r0irV{)~rF0ewJ^TPSB&E%J1tgj?~ z*Ph3dF)W;QhwKKAiVA8yBH4<2b zy^))t{Z};71GKgB9j>UOw+j559TGi2TPUAeA4XNw>BCDevn={lH0lGOQ6IEbU*5!7 z0cOQWI$BwgMtx|$Po)okQ~<*ERC~fV11fPG`uBk5kpGxWw-oFlA4MoB4$(&hObTgYmof%UkC6!~a?1x1^e1 zYX8dW?B5Ttm3>E9qx}OkGe>>nxMLMZ-&lIiWKU=6>HRjC;YLdI01fmKIlV+Rz54vy z)`Xtx8EF3;=LC9yX7q@^N3WORZR~sUJ7J}M-!3E7@32&s)yrkf^$StFey^PlR=;OX z-*WvHWLvA>2D|;$?+>L>R@69u0P;Ik+Gv~sZDIaKlHW<6{N|VDa@r2^yAR%Z9xLz} zLVgg%jxpRzYbz-c?(ym$4l+aRU^ZN#*L1ZzJf|yl)uQ2w=YFuC-{836tVe|Q*r({Y z(PfB~!mzX+I>Chz!S%Eiyh{H|C$gIgBBW8eyL4uEd#*tJ3;fff{vnFh zKN&>Ps-7t+0HSYA1Ll5WQ3IYLLYoX4(3i^YyB$P!wTu0)59#Z_gjD~_U@CJ~31j^O z8tOm%|DyhP$n_tltN*dfq5i{+^$%#M|AObQDqW-t(>t8DW*HHc#+657t>pWIm1(|pYn5YEy zVTZu46O{&0>>B%$SWEYN(g%gZ%W+fbRC5w+K5~27<<1`I$++`4Ojk!Td3Y>LS10JE zt9O6s8-UYw;26sGJe;o9R(=I@L~Jj#7tZ2nbzdjEm($lD)&C;kh0RyI6bbszaX4QA zXc!0W=5f0DiuD}lcfO*!XfTHP3i9n3{%sCbU-Ko8K6e+wQ*Z~AWxYq3s_ zb3uBFX8FU~Kf41wCk+e0Zu%#`P2{)SX8dOyUrZsoKs>KL;jrEv!B(qCb~|rkcJ#^g zlQ6}zj^psjbcUuUl^f60Enw4o_dKtK*??TiQC1-KWV-gpYgb^gR$m@MxGN`|L^9j= zH^be>aU&ozK!bd$@VJgX`P}>$aSa2=2Tg&C7U?Yc<&a+%`K1}lvzybR^NaCtH`#iQ z!}&!(GkJ1hW%gynhqyL>iSb z%JmHS9nu;TxfZPUmH&?$RcK4D47XgKClC+>guG_8l9t)X{|zk2OhP3L=0nzV+)$te zXsD0HH+1sCOY5iIFv`nxVLh)5hmaTfy+VHJHp4%o{1)K+Y-LVN%2esHt+Rwie?aBlfIEoU=P;3-B0ru<*m@ju`(;QzXje?a5>5nBaM zff*e~Kz$j3`cjvZ>qWA7^cR*zd5&uiSpb@k|63i>jq@YuIDaMZ!!kTYes5}pn~379 z2qf=`B!6lTHvEHmJw);^fcv|i;<)yZKcKN+1Htpv^k`U3kGTVP8l=HZ0jwd?8~I31c|5qCIM>*RBd$W^NsEqDcGXUpqaSQ7I9kA_?LY9 z=~Z3%{%Fl`?_4#O571D)@F3+|e3jXoc-Z_i`zp6L@nw`{vKju7FS=gU@wY#U;qJR? zl4sQ+aJjOJc0Ih11C3$WHAYL+C0T^10f4Q^Xn%s91Un}=@D`9 zP8pxz)?3_d|KaJ%BG%sI||D=37HwG@BnE&Tx zq4WRq;m(de9EbD&fEM%r@0#ZSSDEMkH!A1Qkue)zwlyu&tnr~F2I0O!}2AwPTSJ{ueA zybh0By(jQ&`xPq-MDfd-BHojAC6eokOZOfSdcdrCv9(3*`@@z#6uq<;Hrs}4d%OA8 z06m1~D8h687#Qf#eK}g|^+fULDPM`-Qm`MHbd%1{npLNMZ&C#L`#Af%#GKL|dJsfg z{V^Ro9WT9;pu@Da7q1j+sWr%dqibI;*5N?;>}_*+GURh`Rf4^i_a}F1(TwgWt>*ETPWYpW?Re=b1TMkKOVSM{ zC|GBw;`wswrQ(8fATHQ^S>sv0`La$My7^M8{vr|3_wwl$fBUhBehhVamVA>`iS9Iy z_O$CTr=-W*z;NpdRR?(PwWvI~R{dkc* z=gTIG!8cuU-l!@4;Ji50z1Hgmu^&q+{~-(IkD>p?N##Gd)Lj0;t@`qp1LU}=`tp~g z<=_7Ul%J0F(w_q_Nlu@pe?5X8GoYi^b4T zjES3iQc5+fp_?P2U))c>NMT>#m^~W2=~DDEd|SbX{Ez3fO0;ANx(-ThAEh$lNoZd= zQx-G~=M(s%%wtww6dQ-)ekxPSD1mnWBiZJ z_(%RkY8vrxI`yU1ScCRam@4c{rbIE5k)KK`)F=m`WHUEFh-+258URa9e$q3w5c?IBk`9W3V+d0n)&sQRo;hB=*wG~mN)fVlT8`3l9zJg zbEK4GRrWok@@dKD@-3L7C|}!(;kxqC=Am8q##FxD&++n|SfwbRpZ3C9SzkJ6pOlZ< z)!e6XgE_92QsbCE`4jn_Qr6d_9bi5{mve+Z=LndJ23>H0E)+b?xNscN!Uz`yyKKgP zM*1xX{cr<)hn~KJ)7LhGhJ_!|wyh*o-@09TJy&sh!voN>FJ(8pTGfZMPnh-Lg26{A z4albr?Te<=zW6FYA3uQgfDY}GW~aww1v~r9?6f*-ft`A5 ziVPEOq~!l*l9KoG8N~mzekLw3Gc~S-H zD-#s_6+Ld^FXfB{{tm6N#$TJK{qXl$DEha5zL}k)6BX<%8fCH%drtfM3u@2f*h=3N zZu_U5M>|i~XbNG@awx~)8Vy6Ur@4|@sp*6`UBeP?2VbMvq&={L@LNT}@99wZJ^7fK z-!CR8_+35H6+i-YV>`x*H682FDd>T@FfPj{=u2z>CD$z;zwvrKXxQOIQW2$K!U{+z3H zj9-wkTRr5mLZ`+Diy*^2!$GvBx;hPk|<@LIoXmWLbk$KLxj>M%w#W1 z$W9qcjI}Xl#w_NXb06RPd0wyQ`QyG{zyIdU^;zGa&-J;MbIx@F1G?(or?7`S+gx)V z1$?mntP~&ZPo^rx`_~!@{%kn2g_hJBZP8)tsC!O1xkKvg<>lT&=L3xO1&K=eiTm>F zf7+VQb=sQGYNy3YFF$CA;y(11@Y(tPgEM*Xa2yM`y62;IjDQU&^BkDdX$6TVE-EJr zN6r=0PunCu(0V8=hf4=b#79p;eXTaF6zmxnxMg1}u>WUo<|41rghztHf7wB(VMT-g&(Gy)dknu@Dd>>r(KM#CtQs z)c%+5IsFgvPX-tj#p%bmgB$!FVLwjeGaTnyC|nV4%<(1K#hm?uUvY2vrc)2^v}IP3n{PG;(8;)C60`pKcwIR z?x)qH!F0EjNsIlL4yKp6SM9l}KaG3<3YUR*`iCQ0f9xVG*s!w96ZPyv*TWB`U2+~Sr-q5_VY}0(TK@bAhj-Kiszc*^ zFE;Qb6qeiqc?7ZrBeF0$JRg2btSEwUn|t9@&zvEe#p_r48T!t3%G+Ln96jmVjG?!{Sh$Cq#2hB&} zm%L|7|2@kaB697aMLw2-pKCO&J0?fMJy97l+TOD-7gEv zIt;7yH&0{r#5>b;9=2kaHBknx=ZFR$xtkn9Gb#IJr8iLA)nD>zB}&Hp2G$u-+B2aE zBO!`l)0Mwf22(??Vg%hZ2a1-PVduDBFmY#h-h+-9FTw-+7%z+77_X~TX35T)G6{_(#^b(EiQ)LoxNjNV8CP(`m2klVb#M?IF<3Y@4g#k z`G&h%R-T1Do)a`>a~g8AOFm#BcZ~HpZr6;E;LUD7i^3KAW#B);Cb|@Le&1 z$h?)k67Xu0^3LtaW}~8OMQ-o2l&32m0W|3r0GE9J>T`J<hm|WUJ0VdcxGPU{oBSfO z@;MS*{1uoS_I5Slw#t`Hvk9jL@7#NUy9s>?uct!Y(NH-lloGU6aG3P4b0mjRcx69c z^IT<)-Alb!OTEh36y}|Mf?Ij*0>O|&U1y^@OHeVJEatU|7U_sT6p6Jza-X@ZS%0=r zX;FPIanBCH(F+Xbut`!?k>YObt3@>;=GE;G(({E7_xyCyAZ80O8hz+di_wZO&EnPh zrn{&E?OSi4xIq#SA73#u-AJFPtqVHT z>SVpU@B8NOU)l!zy1(CQ_0K35vXZM?Ew6UFG(+)?%q{nLvVQ^4-c%VA_%iJZ+s&K6 z{)ipFRdq^6u{fgdU~^yI)gDm~Em@E4Sc?t)g%<+UBVY2y18*KJE0sVY4f#{&Dr<=WnRDLb@JzO*3j{sOLoWsM~D`-vlXtVYbZ+V91rf90qeJ zV^b(wwEafAn}ytx_~+a+a@VKb?fo`keLkmi&-@{b2p+y|*99* ztky$0Nr|A0o=1)_;`i*F@+!~-WC*+=Z*oq=^1Pt7nm$pWown;cc1y89G^~9J_n?H| z_Ve{}JXO|~7j*pZ6oo_4fKwvdr>H$<=bG6ED*4M)g043FLNuf`epME17d|qX z-2;bg0qLdtfbzWro{OLo^rb;F_$XHSKEBLI)sDB+s=xhPLT-0TE_Pd#6>)T)T)+=p zZx^K4GMq~CiUEO-(`ojjucGDULX)r#A?D%>iiNrv5C7`sd&*lA4fqd-u}s}1QzR&l zu!RCpFWX4N=lg(NKhxgvs`3X+_fyKTy$3|jUA8%Q!crV~I;mipwEsxY_^Fim__{u! z_O0Y!#&y@yR{}Thw{@yw_shF2&cE)Tp1&OT@z7}1B0Jn3?AY`DPPv3}gs&&f-td|-H=|5>j*TJp2Sk7uP> z%x6DCSU$|tABj(T(dGyIZxu|8r}nEU?!G+k;)-JmuGKw-OR>16v^G-j<@1n~-C2;w zb5%&aUWw4xrJO{gcu{yMiU0#bVUCim5w+{k}^!qO=!V#VJ!)E>r_=w&>m$xv4R zcy(gaRv$ZR?&oMUF5j0*3P}flY4L@<;y+EJFDOV4V!M3q>d_U9>DZy$nCh>-?%yg) z4)zS$C)J=m=SBUA#}Y+#GD$B6UZSSm9fHJbZJn2%M2!-%9@DI@yvSPVlpuckpciKo z&=PN`+2dsJqGx1hcow19&6Pj3d|#L&CjZe`&eYsvC2}4m|KNnpU)#MV&LP=T96Pmh zyUnD&J`}A)Ur@i1df?QV)B|5mpSxV?5Q=|Ok%B*Zh&<>wyY3ixxxeAmn5zIRUx7VMUc>H)!Q4auwK(Iva6|Y~c*-Hicul zraKy9bcSN?c{H5tO}ny1NLVucVSLvVN5r&KZH9bG6*rv9x-NTU&ijn}*6&+dpZ9ht zZ;{MNK6c}hsLrWY2SVZQBwhnRSyS^G2qoQxfDrSo$n(cK?kP?&AOf!4B*<-BW zr%2Fadi%A@xHG*+ncP{MgEBGs6aDF67@ys>{ zhg|BZUkk^c>c15^>F5)B0WM9lUnC1x}9EM zi;#3oJUiW^JA7Kn;%z8xL{aOAMRHgXb;c@0NLcF83ICp3-_pw7V}EVqI4;Oa{vt>h ze#+IV9`GYIImtVm1xTA79_alvl|(JDTFYdl=7oD{)6Z?R5c2sT4L5)_A(;1rT z;)xiIUY4t=6-nwk-_VRdd9-SeXYu{%4|OxuJE$8i=~-`1<5tt8^|M|`MGP159HQAv z>$bf5u{E7)N9+kG@sH4^wm~y9p109JNu|(p_49xT32UCs5VfHc1 zY)UJ)pkD>t>CBrseYB23lOo(mbl0%Oa!*cypP|%ce!F|eY}ogfsskH|dFM3P z0|l1Vvq2vrz7>h(dTZ9{%F?T=Ls@aqjUP}Hv`|0xoL~7$`xV{26>ubA?Lr~qYbAb~ zq>Kr8qb({dzjNC$aH;E;%#*ay!}VVYcMDF-#S&vDUR_(cW_fGHHUIaf%?tFMU;&os zT1d48yziMmhQ|IlTCPHau0(!VA(#*R#sP-{FMfl@(j$!dVS$w!R)n>+w$x$=-|2ne z3yhA1^EF=>yi%H#s?90*To9Rp2?+QO8mm@WiOryi*K4tt*!H(p2!hW!1zy}Mx4=3@ zESPj3GjX2z+xVBwmdTpB=*%X_f~$Bt9M@FDc9IParx+Xb#B8l~JJ9c*n&^+J?n%k= z%SKIhJSn}6)ye9({w~z$vy@xRl?CgK)vd{Rk6mWML6R1y0rTdUqIXMgpK6hK7#r?} zBKj{aj~pAV*ihb|m~ubgkTO+{y>d(`A9~m#HVr*o6q|#NV#1*hJ>Mi)23OC??0$03w;!T@h;dlajkw&sqltS6 zh)z7cziBWX66;5QH=R(LU5!T>Q{VrWCw;EO}XJ5{?pfCMZ2k&B` zZ(&J7e4&`BcO}l4)xVFSZ#q7v9N~Vf^kqVplY|LjdcXXO$1CQ(=R)(fgO7Y*MZMQ? z6+1wBwVY;<4HN6XVxRMG-vWacWO541iE2lIYdxuO1a_&hM42lj8D7(W_)j#}yCwz= zJU&P~nLbl|GVqH&d#Bumb3597Dh-k%@D)q;!L4oenLiZKuKU!!=nPG2fPRYypAg-T zU;=lgV8ahy-tkba^w{=$;aFICCFHpv^0r0?)X(Cz21?2EhnY!U)*x#n#Jz&i3Cg9TW3U(QN!joGr z5WdLYrgd)w80>FOgl%elPD2fZSvNSx_vueies&dX?~1@OQAr5;GjS4(`8rjZMWzSTu- zc}vk(Ekv#1pnc-a8V-eU!+JsFbi<3>)>K;17ud$|LME{k4UZ?~tOp}2EJC>`9BSJP z_Cf;fV({`31v;_+1Apsn!v3q{T^m2>MjJ`32hTPUpPZZ(bB|oWY93v57deUbDSrg# z^o~n_Au2fq_(z&Y;hdc7|H2`$4q#v4!HsapqBus68VxU<^eKRsX0}dVZWQ^RvXTH2 zFs4;BRg$shv2S^QvxpC$<$ey(s;`)-Xp_76yr8xxcE^pZd);+-fLd|(G)O4i;R8_h z%>GbYBD$!gXmMjeY^u@tm%(sE8uB*kY@UfVI`1?cM@`ysJFL5N>pR0CBOwk4jXJWz ziQK$@HHj0%o25H!wPkVQi=#?y+ZVe4W0t!MwTmC=^ML;taui`2;P(Zqi%rS$u04jx zZKiX)bUiFs`v=E&A@W!0!bo8&iQW2(>LtIcf>K^SD89QCTkU0ii>lqDd8UIaE?i}C9qWN8>(@Q8jFT;fKlecDdYo#s&)VV)!E~UI?PcH=J zIbP(iDsz6D1NfjOV1P=xbK@Pwt4}i@BEyr@5c$vKXDXExv&9(j)H3nFmD%)s-lA1& z(8yv$vmlm{eZuiwV5vk~QqO*G0KS5E1>pPmo4~TY3>E~RkfWi|61Ded4$GLrn_l7R z$aBI=)ft#p`BwTMlQN zUt~W3^UQC}a%yA|mt9G!tLpqp1}D6iq-A}CXw_K~1)&gIoN&~YlO87eJ`9KQOA*+U}yHti1tqFh)| z7TH5m$jRtz|MC7F-N{p|gP3X?s~}W>{i<;^2t8j2i{1{V$$jecKLug{p%YzV1DX1C z2iayn>&e*3YHcoB?t_KLsw2v++`3{ln%`{|7T9H=vNU!?uDGcu;br93DYr!O8(mr7 z=I33DOUM}-kqXb^rdt~RO!)if>nSR3YH5i4#L4X6oa+)>6kp@37W%>~Hb5YI*U&KA z_OTR4d`iI4)0i9=-Xr)ve@t21*Y3-uL!8XQc-JdS&QwRfzH8~018*|V*>HZ1>l7y@ zh@S|Ko8RW%%udct+&ep!Iu=^>=}XE4`C!BxR0+N*qa13{9eo{xa)bS@CJ$HZcXWA% zFz0JkP6t0<#;km0FJF9bGy1k%_@~!fvZ3;eac$7kBkGB6eb2&Ck{t$TMyfxyZ6CI;-c?!)J6{txtNLdS%2!)!#z@fU)n0SiuG41taajjf*-{xAuBkL>|-Cnp&DT$?*u@I`u3p z*L*p5`)cu!PF8_L$=8RzDmy<)ck28;eDx^l&*^J7i5Jl7n%^Z3Tta;1$dEX1zPd`4?222gaONxojY5 zYi)%}*r=;%TS0Pslhuv8Z-6q}0>_ymhm?qbpaT_$4j;~l7^+lmj}CtrKzZTf(tGrq zMaSbqoNe5L<%;<+6sh{Z!}iL5KG|wM^lDjh&$ko*HPst=Xk^pWcP*6nb+deqM!w&L z&0m(ze%I!yb+x?-c}Nx>lw9xqPx7(PtD*H+F&+=STqS2RVw48wNs#=vlC8>ws7(gS z*5q|l-<>wi{vK&tPt*vn(l$=xYzcR)R(hCOTwmX~TPePty8h>?XnhgoFj=I2!Cs;{ zHH1}meIM?sc=-A1^KsSBDOhD|fdmhbnX=tI&p|(~)ZT-~n(Uf9r7yDwY?Jsp8gdAd z%IB<~z?r1^$k(?MB&3O946Lib>uLEjw#{aCp=S8`pu^z)eCFY4rsOhvbF)JWec{s2 z0}@}w$Nap;{YG*W^L$Na1~=ts$kn&w-x&@h5Fb7FxV|f;^NDin{&(x9*t)Ir_!q14 zz45`lRFUi?yPfP><#0z@g@S{A>@Li@G6#lUOUCkiIa}a~H`W#R) zdSMZ)`uGp>`~1C#OY!1&NsR9lv5`Wt5qAOdT=>XM@qWCuN;`VQ{pWe^!Fln!seUGD zj}%)a8%AiyZvjJ2N)KIEKe(*6{}#=eJo*XQC-lEdIy{J}gzCAkBu-Qirc<7)j+t#EC?5~rk_jg4TWt9wK5+H919w&!3gYtc;0^NJ(I# zy!X^siFBHBHS2$f(3CTtR6OxktB(*VH|FlHcN7_!JNaePxOaG^q_0v9dR!#jN5WS* zc>DP2a39Gy6NIT7VOlW1WI7n;tz3Ut1aGP*?&4%5GASu;p|{>exIRk6Ldg*2B7;b` z*puOOM|QXG-|0lqxS6 ze~}p96<)3^A6e0{$;GgKTtr=I;iR4<;ss)}iJmOtMUOQ(7=VyhuR2kdIh$49}DNX*&3<;z@-t!s9AIe&Q`(|A{ZrtRf%hy`f$_TuL(T zq`zYQ!SE!>xKn!D#`lHmNXD7_Z>zr-UMaDnRI>^3qEa%>6cNrqgl9ZnI)m{1G(&jY zCC{1bp~jDfA47N!o;Z{ftaQX+J%uU7(!z7(^zi{0^=Vf zVdU46g&{IB>{=z^tCSI2AvSIup0{TCGwEq%wQt<15|@rHCO~eynLZg=o=4w79DvTEy27+mrDWA^m}nW<*uI-8mgr zAvAtB{K}e^2t><0B&2a`x#A!0sqoGjNvm__gAqt4IFDo-k`!_X{5}$K7J4${r`Dox zj*wc1d%iu44p&$Ux{01J5;7l2-?e1jion;Ra(6y_%49Ia`v?+LB$g&fV(G4Bxl%@$ zw;__J>U$8<{}<^n-da}vACPwcpCj$`e?$7~wf`~F6{OZR+m9o*BW|1M$++m!-6iA3 zLCt!GA#q)7Sj))W&0K1t`QXJ?kw`1=P!{3Q{w(inj|(klHBNiyZtP4Pi{5UC3ne`t zyCK> z=%#3vdI5D$lSA^D(RRV7jSfj;@}ii7b$zPbnD^#`()Yp}R0p-{Ze+VW_85+3P|tXW zZ5kfZ1)t0m@kLGDH-l-A&AD`-QaV@WZKEl#Etr6C*|B@JeEaRSnxdoHbrx&3=GNE>WJSpb>y8&wCJ=?Ldk0kuXyCi&lpSad z0@gY@K53%u$E>P#}fFs!5GUp#9An zYl_uur$+Hib!ZoE)W%9yy9axv(9L}(Sfs@IQ(2k}=ej?7QtfZeec7lycET5G=o8~swYB0>cuoL{N#A2pg)__UW zEQ7*alB_kR?QORg0P(U8@Ez+|J_X14J@uA?vRsmaHReqJU-(b@Vc4#_Q`7`IKl`%P zKOIt0IG$zS-MQ^GTz)C3v#vu`x@3m7sRtLs8d2EA{uoVkImAO(ngi_7lGYWEAj7AS z{AY8D(wkFP3P6+zmKJ`De|EJ{(RLU{tj1QD!*%8|G>t_-g71iS%!3E#{)t+yqDuu; z{WFEu2E6iLkZ_LI>hIm)(|0Om|Iz)xU&@0WNxv3ftYAez!x)zPy|*JKx8bl^nnV8# z@bv>d29aQm!8_%__kL)-O9bqS)h5+zgGO&JX6&0K3C0`JX%#Rv|`W*FXNyby23Z?KBTU08F%^W`x< zD*sqn(FfRgrW*KYjs@ElCfAhm#7et60|_PX;RnJ=6f=IL8&%itKc%4CGh&k{`^14Y zzkf*2a(v(3E&Bl1{RO&rgXF?QqWv&@ZTa(QIBA)o`=2Pd!W>Jl8u+?z5vW*p%Ey2D zW^i#$ROh?X6hSSob>)>*DF}H!BVKLH-;Y=v3sL%Kyh<*;Bdq~Qx|u*M*ZoP!M|7}g zuaEJ4?htH{3$d^d)QUSuScx{I_OCY5@)}M? z@N{17t^N;bUk_HK(J$}pHS6eQ*PlT?6v5zCglQJH&4cAv`UYeA-^E!EmdXUDgA(osB85~AcFTz`wy&Aud#%k zUSVNh+WdXX)rx&j0guneVeAquH?Va@E}SU1(*M`av*r2ca{5({8PEUH(&6j!pU#n9s_4ryVI*IVdMd;zX$qT@tq70?E+ZZ8e4uj zk6OF1+RC19S7KeUf7?y{^5ua>0W4(=MfCs0=eAh1vda<3d^A&FF&ZD8yrPvBoZ^&+ z&*S;w4uFwJO>l5b!cn`o`D)B+i(dy;F6B`t=~MXqi>4C%vcCSA_+Xt$u>yja8tIk? z3)uf<{@zVqSXaE)wGLvx9!A;fHZ`=Xv+^|M{9CwXD4@maY%qXj?Wy0hPa$m2)#Ud_ z*PDr+)_(uX_}eBB zB7%2&Xt|JDw=Q#;g{MDqS^paSd`5$`B*>u!O?ES6t(rS~ffM|Ihmg5VZuzVs==y4N z9$2nbg0%*F%Gr0~`IV=rw;FnY-EYXUp7`y64tj}I`Swa21|OF?i~TzbK(4hxw^kEp zu@kcc)+6Gz@Nydq&16v)Yz6CHd$qDiODrrLu#+!1q0|Gk_LSc#or(U0Pbb&UQ+&OK zVwQz(@{9fX7Nspk@Zb@!*AP6>uf5u}qS1qE=<)hp6dN_G(Vz;gXy7Q5c`%Du zy;9i4Giwz&6MS{5gQE5O%akXJZ^?R#_aE?U`Vo5zLTgXL$%WW^{;CfJ)EBdbv?kzN z^YSh5!(M*#K}F#DoFEL5)&048iOY@y`c1%Xa~?k?6S}$WW3zt6Bek0@V=XMX8p|xE z0{-I89*!leW2+%pO1VgipIzO{58OlNf2zr3Z5Sr+$J(3TZ4SG!81S*Ts`B$$DNO%&ZjK!Ur#eodP{rwf?@3*IHiR|a2OgYf~{D|fre1K0eyVZ zbvpr+ySn-|h^%@7?n#_=7-I}Dp#)Jj;3%kMOu&<^)-&8FtrC)sKO;aJKU7$RjZb!_ z`qpr3?A;f|dr7MNX-P%6Pl}pDM+K_#kLzF}#WReVz}ejLmB}emwcnc=fhtK8qZ1$) znO8I)pmv3j9XI_3?8mQAwLJ{YNYo}PE_)z=@dKN);{>Jmc@tJ4odx@Z()6!~N7 z0CE0q+3*%NE{c5rg&%=h>MWB9%RcWTZLQ(%(|&Wc7khJnvn!rDy3AKz%YyxFliGH7 z4_<~%-*f$uESNymc5yW(_wvsM2=pT_n6%LBqsYD)GO&=DMy5Gv*NlHALrPIUk~3L? zK~zK)Qa>B31PjhKlQIkO-<_j=;$l)~G}Hqa+OpBW3 zW3$>IA^#cw)hVi5b74;>mwV@At{3>T2g_KxaS*YIP1}LPS`|ypfMzzYNntXuWG2>v zihFmHQU0?BA5@Bgh@?^|W4fs@__qby1{PRuCutZ$U%)o$9A4omJhovH@AGaKpZMWG zw}ZhF%Lj8gc9asN%5T1ZH8^F&wTpp1D@_6o!H_?sb0 z6s3#(62h;HrKrUN;|s_)olYazHq}u4VYizPA@`HH<%2ccjlK)!1Gvh^WO2Ust77a_ zWyvEO_{Gu)A%H;%xXUo_1)8lUfVdW*rt7!>REi>Z)L`E~NY;$z$Dg7GC&-XU$uerW zi&n3Z2ZZr~HiU=4+E;VSJ13g3UL&5j;OpO6@bv6}k^Z_`ipcjeFNLeY;$9`ck<#~` zOPij>>FZ4f9Yu=}}(8CZ+EtTo! zF`t~mdS!Ev6OUn_| zM(S&IfA7f_FQY`h7x{-AT8zMuM^G&vo zXgo0b?Lt!*ji`kw*^SBus9Ohq)F$sd-@PDXMc_4^Efpjr~CQ!4hLm z=mhr?SI=Y#)9 z%h>}Cx#g6)7#w57t}F-IAA_}ny;Jc!k-QanEwkwCgCPSrS*#s4=lc)GB6uAk@6H1E zF(i$nu(k1LE#@iMi`32h<92X!MCt%y7v2_&r}cH-4N}jZWWKS+#udU>t6F9Rw&m9F zwk!w_Ts#;t{dqf~cAp}^C=Z7Q98lq;_`h4~=Bw3i5(;F=m|eZp%7=4zt*OX}L9PR3 z=i&`N@Xf68oA_=$gZwj#NLu&wzwMFe;j~Uv#unmpdzX#V$Z9b-Lv6^sz=M65KsrSl zrfi2oAPpe!6N+O=*f8L<`TMSN*2XS!4Icpxz+@;Rn=wiy|1_7lnEUZ0p58 zoDDYWg^`m`O|pnn%RrC~oI2y-fXIXI9u-^bwz3nmw97sJj?5u5gRo2Z-E*DM8YgzK zfg!ePzh49&?RW9m8vlWJWQ|_n{@q_%z3@$j%UmbucjzB{gm4|SFQUu|Dq@O|Ar)7O z-@-O^LZOi2@ETX@CCaWXXzMTr@%_YfepsC6Ncbn}$3(tqX}mC7{S$?RTEyRADEFs^ z@f|~_p5%csniy*^b+mLq3~3NF@*mg${6_8OY%nI4R80N!P5c9JVedfdWs3M*3qYva zI7~q>WzT056T;($);zPDmoWywvK)`$?Z|kMMIKcc5s$Twa8?0AE5b8Xf+7!7)r%UpmCLki%NtY;_ z=FkflznOseX2ijD?4I%;Uxe81>6mxq^}V?2uivipl5X-F`I~L9J)n=N4UmEuC3F(( z@BbZ9gl!Wf`NIlxx*i|7+j>a@XC_Q*s9V@pM|WjBMdrh#KtO7a1{DN2BK3(OMRzv_ z`KBZN=4)Wq02|pcq=SY#*g!h*OcpFtn(|s;?sh7Pr-WKziHrSC5A-m_0 zVkg0j%z;p(;nn|;VS432Nwo|oKR2rc;x35oBiUm>Su{@%Fc^d5|^}cO4Sy zrLe0)kwYf1XSh*3lnvbY?4muQZB~jYoJ|}lr%NMQk&82;M)HS%-(Tg{aAyaj=V%8% zVP*dFgoo+HLd*uCwN&bP+=4AMjY|2?E83(DHv!SZv| z?#p>#HU1(TMH{ezCmJai)}rk`hfa4MyNUc1G%`Jk@V7nHUr-YnI_ysI{c(JEiJ6j) zfX!K*eFCF{II&i!v@A{cdKW`n}TyYwR0!E6tlg)aiu!T zbwcUvW1UY1XxdW|kn5SbLLKtU%>r?@y6$L?P)~g7EG2rrp)=LT00v3WUmFJ-SjKXK zZb*O(ij~(1P;d}={6apijuBK%J6Do#d2EPdepi6ZOqO&R@}@Iyvg@-b1cMsr+l>yn z5_$x`&n}MAg=?2yHM-l(@P<a$eMgKv6gjAe)wZxPT|$T|x?{ zb{2lVEs>&QKyldE0t^BcvlZlRb3m6WrAya1SUO98=uoLwD0lE6doq(cAOvpk+Id?6 zdCMDB)k|MQP8E{JbITm9&b;z{FT=vOPFx}&&wJ5$ugOQM1p2fu2P_xVXQ_UHk-Tl+ z=#C3<_!+binhKUr&?X#v7kp*!=@{GFWhgz!3O7DkV<^m-~_JQWdWlwU_HJa?swNhq#7{b3nS52NT!s69gPCPWa$yn$|d z=c4HzP-Sf32LCaT$gI}3U*Hs{gq((R4H%tt?km*Hh!Qlxdq4LZf8$Y{MtLLgpA5QI zN1n8<2z#Py;7;>g38V`{#E<41QIv$pX{Uv~g zn}P`920bWZ2<^PB#X^|fqTM6RwwQ4jYC#9z^K?cwb0p9`H-p3PiFpUl|B!1oU&cw0 z9><~^EoNYmIAFG8e@O%5@X27!bj;KEE^MOm3U}T!{;0_O$Vu#sEfB?3kjHB;@+o^D z6cbrRWip)F81C`RYVkO_UiL%sX;@?eoyZ8|iV?)*sVBW;V?W>}(5iJ;g2N$|F)txb zaPaZ=@-RV%N{_I>DwFCHDzFKfbV>gX%E-g_iz)RyaI{v&m29Vdbq5jVtF+z5M^ENm z&Gs?@d`2l<8G@y$w?A~Hue=!SRPqXLgtfkvSN-*y*`asG`GE^lRTADfFd)qKXj(P} zB)%HC!pZL^BQgs2aPW`uem}HXO_c4Eo%D7$^ zE`qK-#{Hz+Ei*Y{u5^(qL?$F*i4s*5pSg~8>f5X&b4aiv6F2l_h zGsqMvV{t85X&p=JJKYfI)ilIR=;ZfAED08W5VO736FwgA^2@@$ zJc$-ZV_@*bQ@F%ifcGVYVC~rIs~;awuCZHEW@2c5b1Rn!&mj#}Dx~H57ZSt32&^ks zjLthc_YIoMgSE$nIRhr>--`PqU;8ac&r(hjXA))*xA{vDtMg_#u#-$)f-WS_hCx;{ zug19dcQ$uCYZRVFhUmxhuX=b!>UyI(d&k?B*xNP`&gR1HU@n(7wSF>2wMLmtj zNuwoz9Q1}3ck!EK$sbP`5@tarGUl~59j-mhH^Gk^U;>HQ| zizaj|Mf3`{TzX^6wzydOdV@U(UQl&?CS3 zwy}w4c#n_cf*n7ki%18$bVJB#Bsb6X{OquW3|`e}0*&4Ur+#Gu5i?`7j%}x!BatUk zjz&Q`ow^EtVr5+^axX5+WTCUJ+-Gf5hcL1fCiH&F5Wr2%;DlS?URQYZJ5y2ueI*w) z;-yIAEGuE~uZwrd0%9TD#x|BQoH)R%MW42L6Fd>~o5Wv7QSONZ^BNSq$x<0~3ypi> z1Gw*s59i#?3IT>G_%#~}W8ezy4^W$s?D?QBkxt23PwYWPpYkmeBxNg4twd}Xt#Uom z!6{vlldfRsO&POh;W2K!HF}BWN93%Bc8b+n{^hBSp;}q%DP3NotTyV_v*Pm}C#k;0 z_-{OgQEZALV^Ai5EcB0Vf^-VDMX9dKK}!gN=+ICuojxT9* zWsieqWpR&2ESjm0v1?m<^H_hfCTkp=^oU1KM{#vnKz4b5OkX5Vw1Bd(L>uR&Cmqv+ z9k-(y#GIU)Wn<@fwu{oEI!^b_YTka@z@dn3H{^ zZqDe{=sq+u3&LzDpooHj^MieUq*aF6VBZY~*E{pw*3=w|C_%0sk?j0N)hgvrOhaY3&*Q%<{72DZu zTwOQrvP~LRaVZiR74S0}N~l`jysMGlxmi*`(+}K>oBQWu*r|;tq~9>B*T<2%Z~2s* zUfsZM5n|5^!RtFy?eAwWgU7Rc>QaxV$q^}f)pJ}YY$URbJkcdXrw++ICg%lpMs*5i zISum$H#sNx#}o+KU7wY(OSnG$bN1J=2G-=2IhhAUG-{&9?NVmq zIRADiSMCU*iyThWIRxiBH^o+~bn1=^&_nD^pp{f)(B?79g9|0n{iqE{Lc$soeqF`~ z12~zC1O~EZ*>Hp)0sI-iD#FDgw6{Mke4a4Ai?TDlQZ?aKH9IHTc5DU1$RhRgdDLJSO)Sb zy!RJUh(neYLKE67yRa1x_h?un5y20g%JfOWyg8 ze;moM0gqQ}eR}o#fhuMsD2!~_JtnV6jtN655A9V~dI~12HofB)mw69RL`%P!)H}Ivq;{A%@G9)p$$ICd*(gDy^FG;i>*)mvybYHF% z#(-tOT$@yapyLPZc^J~3^y}~ZkkT~A@gWCkCv#DBY6PYo7cI_X-Mt}@CBv#7lxxBEGpiY1j4b2w^~Lp_<&`Z4P>Rwr zvSKxX*F&NQJy<^8{EyuUwAE~I_&s+WAoX=q9mC@y`;OEKTJ9&D+J_#)nxM((&qi&F zSqY2)Js2pcUQuO*WrMHxr_Vn)g(kyOws`MyzjHgh$>p7jRfb21Q_lFN0CKSjxcS|H zLuse0KC+DS5qClz^seu^n7{$RY=E_apfD4|_K7|FjxTf)O8>{82JB(NE|7K%>I*qJ zgBpf%jR%&mGvyQbqR46(HSc~w#*pgut7%KQwhVz>uFn`y<#)3?`VHW70`a)crN4I) zPDATJswzcId>xw^pGPOk%3_7t)aNq|0%IxR#{vOV_~%^YJVp2~jfnJaHr|Iw;T&Dz zo}myOm6nN8Pvd8gU|_uNabvI1+}^jRi6RqH&u7B~q?hXs2mf4-N#N-(f!fGoe}&x+ zdR@>>q2S2H1BamOws{SfM%bhQ>_6dl146YUi|X|P6Tclxkw3NRCGu5p#3cNlFC;LY zp`BA$y|Rz?`Y!`e$8?DfE394+_&i3s;P-gJ*nPm!R13_rUVt_uJ zcm#j~AJsEQ)SVvVh1T+a9$)O_%JvZg=8ZIan!j_g&am-zK#y!OTX+w4GqT1b>rEuG z8XI7FMz(pxcc#G@iGeJiNPQX9anK>*=WSy2ZwgXB`fy`j6YuAK`svVu1`TBD=kwf9 zCkFhAmyqG`*ao)nUy=!W89zK4xW3uzYwX&9O^Qd|`@Ve*2kd*U5G=_*R>u%NF28Dk z9AA&@*`Uh2j$*Qj7qNY6H5lFvxew(^$g)!~E_goo^ZpXg>`zj`o=JF#7ojyN%#h^U zePiI0=RayD!eKNEWh9c5K_4@yZDEs6$A+1f$h>nJF4@Z;gRE+N)%)K`a0=Z?UhlON z(I*&qH351~_gobuM)*#;&Hfm%i*jI67*bPIBOZk-HxGnr|NqBtw?*27TasnkkW^FL zvd@&1Hq9-S3QaeaRujsQG3SPoYncj3mMLzj#Jo$kFmnl$B|}8n27|H0m>JA|&i8dj z_w)Pxd(1iK`Fg&d%j5ZYK3_+lU?^HHm@S{zLT>dbuzv1|a9IMCb~a+ySojP#M0_c? z4eV@Ho>0Xkc@gh(7lb~>yF=FE$xq57kAXmcBAX{~UZ>plQ;A$e9yXvSs-Y@rq=n0_ zRTLRM;J0l7#M*55Q6Kp!(o_t)tl=bqYNA;~eh^ZJNXe;ORfA*& zU-9Yb<_8M$=T}H1Ds9fC+OY#eK1a^t^GjuJySo`0ZEcT);d1N^?mV`c@9DRzEaBOG z7=L}}nHCpY^sS{{1-<~?-lO`pYHjzYeemP4v%Jjyx@XsMvPWH-46dbaE_Ot@6|2R3xv2#kzFtrg0$E)t~wRvq$`f z-4`5X1Nm0P@2A2vF`l*9o<#_x@&(Js8Yz7-S=apZkjP~$$JjJt(pS70D{62xA&r07 zBOc*qR+{gu=F+Xa2Nr&l@yB?VxCN#wc+GFxbs^HM~zllxbo=L}_LXOyS z!UK!!kr#{YP9ds#v5WXyOT*1?!{bT=Cc_adz}z13=n)Wj(kVs__Z4hE`#5r@20Ki@ zOBXB-AKmrRXpJsVgeP9$B|6 z6+bk@jtX6ck8^~UrgB|==xO4wQ@{2~3N_$5tl9b=rLZK8#cev~5hfMPgYaVIgaERc zESZ2sx{f`{yO|g>(eKx(v(Z~MH1QKkty{mBMt{XSdibmMU%!#FeHE*2c?T}MUK~Do z;yd_w4xgpG`j18{g8{`hqqzTz7ce&JyQg)U|BViizHpArmcplE^WW?t$Vl} z2Yd|D{5|mnqK6#b0#k(&`_c8^dX!YDL|5Tep*6{B%b5&8#4PPbPq3H!5N9ac?WQu5;DTdxX7LS##9fvHFaT}0zMM1Lzsf;$6qDrO+m($HK=l`g7tcM)Ff=31~IiLI#37Ez=RdNYG*t79lVC+$@Y@AW~uV8kCXmY(Z(jj?*?ER-<+s5ysjMiVvtpMm(2)kkY$c~ z{{?$dG9Xq!`nRlPr0P%itE{WDjaMM{DR;Rtf%18;ia7K~Eia%iQ;&_Der=eJuWNAg zek<A)WY4U?mNJ*~+>$A`_GQ3H>!k7$ zp8c&`6>DQSb^UJpwW&w{E@IB^6n-5ik{48GZIvAitqV+T!WVpuQ{2rz1&Baa@Grc$yNrxf=?}s!KT;vB&=347WHzxyM)KA@M#f3 zFaVmru@^e;hkHv}JawCLjGUDnEtDlwmY4e+ri^t?VP56_ZbuU)AH=DyRUqBfvV_l4 zW?|oK*^4r(+)dSbXGG=$^AQUdDR%=|C{8EX8}jlVQ%uW!bSQne2>A|Xok59Xxist` zF2|u48qh>a2IH{efvu88C9MVsxV_wLkmrW^c{39?nz zvOfYjwkDTxfJxlG==lH1mUSRKd?#~zxTylYlyxNnx#X<$6y5yRHo6kMEupqjwn0}I z@8A+nVZfmMgK6Ey39q%M1UJbP?#(W@rRcT&H!HBObzz{l1u`AMKcB+~p@X>i9xF{;z@3t5 z?NbF;@Tj=&S4JRTSM{|u84+JBE^AT*q^Wncs_?Uy%A<2P=P&fOOw(Ryn;-6Ze2G+b z@>S4DbhBRN&quO%R}w_2Mxsq)N1v-TvN4RaMtU`gf+yxGEYQbKwu8r;_L&7A(vrP1 zWS&@|7R{)Sa`T?FxZj|2VrsT}>6$>aW)qHVHMcFCabpL%cgK?^SRYV*tBNO1&qZGe z_R@7?_+jv`_euNjgb%5Lhvw5bFCznDUb$Rn@f+ya0qA@9G>IKV8HuzZc1F%2E+os! zvNGBiP3f7^cTbq;P)?bVg&rXpAJb+)xnd+6`@{~ZzobHm>5aceI!;D%Zq5Wp9y*CW|kp%LP*%6mo316}#F7s%1m zvE7*O4!D$_18b!3o5ynn1@2I79y;{NZ7MmsK7B%Ry??q1U_upSeh+4g z&0{r@D+gQfN#cMP^q}GSBkJ8fuu9sp9lZI9#a$$98q*d;Ii*{HJn5lS?7JB(su<<+dr}FI-lcCRp_N*o_X?xuRhO5uI%a8*xVs# zI$39$!MlRSyaVf`oef%7Y;zoLg}R#3yHh7vgJ72$SR*I$^=?7AcY-MU7givrmdc{* zWUiUp!6?g$51XjCBc+L4{995jd@ofIMWfL2N_Pfv@a?0qN1#vm#4{G z7seS=ZkeJc)eWfzT#e~X4<}fU=5T|^luR?sE^$(jDZTyg3D$9E#J8b70(T~S}D-2pyO|{B{k^> z#~R_-8W8F<=g>Q3@#4S)0u6j|4CiX5B$)N_A2NK)wuLuN*Y(ec)!r9}b&IT%G%5e8 z@p%s-@!}?2dr3BgA;6OwG1yOr+&?;W;I>CYkXHlU({f^j@Dk}75T2YvTvN^uq@JBf z#PgqyNsMU(l8cmRpAlNrZ{aS6{aWbBl-jHaBy@j2b~E3MDpZgbABKuKJhj$1?Zca? zS?=4Nxg;_0SI&Gy5p$1TCyU4MZyAN+cs{@{h&tc}aDT&;m(MdalCZRs;V8l#kG zqsEaxyB9LLH$D0g%YJ9&(KIdmi#=m&c3(jZLPnYo52;Mz34*;+qRSfULy7llqAJ+F z;n`SHP1cPyN``I|^at-zgNDc}Uytt8fklI`&U{>M-03T%cGB`r?HcnmqQ)?8FRrd-ymKt3!L z2GkVhUhWOONS%88Q@RdWNv8Z@eYD&P$hKcfbWi;_rtGR*Y&wFS7f%@8BPCjg@pQ?u zozaUhnPM|wk^3f0mQo7F<4D|sT*oGur%5A>9+DEtslcqd^0CKQ5yH9YBI(sIY*bHx zJ$|}*gLk7O-tm>&X}S|7Ca41Gi<)lg^g>z#M_-1kWz(uaZUGm%Ol~6|Nw!`Na{S%@ zldj4>tHnu-53k9RtWz?~%G)?;NE$OiJB_6coV08{GP=8k!~>fuUkbNH zqMMqv?KGXd=(8Z1GNK2pW@jbGgnPRJ|5U*L{(l}yQ)LJyHV#dF2D_pFMwxVvet?u$BGI8row) z_akU4B5zZ4i6vnT+{VYF4D;})Y1bt|b#$zmnM7!4>^(iz|>tVFFh&{LbG!(P>C!fJUQ@e+xE|DY1uq6xw6l#}xUN z3gqtddiFJzBmCob19$NjF8;_}GrAyINn5Wcz#Qf@t)>fu7Q-;Od!3EWI!dS1B>^cg9z-LThY_?}hvv)tV@^coVqb5S#k{p)ugGv%i9egFBg!dQ*tSc6e@q#% zsX*?DE-LT&?f4|A7RgK+72y2I?(6IJOJDl!|CD5+vU#tnwvtUU<|AusGlgrbXRRi- zA2(=HXaRSNA>g!rK#n}2*oEifU=~4vO?8_yBrYh(S-6za>P?0_OBH{#AO}t9+h_5` zu6vVdqa6O1Qx%kQLyrwC}MpOD$ZN8Y0P)Qr+9P>5J5POFo#NE_s z;HRyN!sLY>4YB$fjRKXt`OK#=wC_;DHuh5i~?5QGNpP^1#;n^dUhEz7}piupe0W27rwFrVwv}P4?=8 zdlRCkQi^!-!>3xD*o14QblgJz(B6cFIA2vqVCnBGSxe&y$*}?F*41WG>Zem4vu4TR zM@hxFB-@k;)_184T!mdPz0(`x-T)g4stH?jvEL|{SXYqA;qcHrqxW#)uwdU#<{wlO z-CLmqp){sA0{NWiNxYy+DcHF719azezZ<`IY!z^bu<>-L|I&N>ww3rn`Sn%@2Wok6 z5M>T#%6N8vw8D{Ry@C!LgJTAqv#p^xnqKhYmk-cMhj_wPp)~lQ12v3x%12AIE%=oU zOm#rx%C9=O5yz#Ue2g|kF(LhPqDx#*%WOJ~q!vY~F86}0X;Ahf;JwOH_Jbt6^~gCP zn`qmXbRuh(D70nh$f5TLz+l{7L+^Y37=AFZcXQuDxSi7qe=3bT*fCt`&c6Ys2CA^@W#<>JS|F{vbG4 zf);p&`*d)=)URV{oJQFdoGJZn!~`BhqQe5s9n8;0RQlg&Vs=GEboa0u3qOgp7Mv{B znBwDuK&*bSzBhCF*=>q|@hyUh8TnH*%+-Zm5?pxfH&9y0=dL?(XchH50?{5A;g46d zn@PwpwuOk+pAU8E*E^lxbM7NTCfc4xKA58iCqsquG>Lci#mthuOI zUwy}wf*RH7i?Gf)H2mot_ATkphThG;6`Gjmfb(9~3xOm@r?ZGBGAuG=llTXh> z?~1vJ>b^<3Rh<2Xzg@6L3}CZdcjkqI?lMN{-EJ134%8Xr@aR%UUDnkpp)3nX^FGgPB?x_k*r<`Di^{7Yv{=pDSubqn z=H@s{81uJ+V7zu;HQSJQCEgnI0T)}*Nw4{a8nba3v(nD+KBKoTQivk@59TrlPCfKJ zg3i4Llly*L8Iqd-o7_Dy*M!ok9BEEsI<>L>_7M%I_%WrQL3|Krdt|3%j`F1dU@uSQ zXbnOXCxS#V z=ss*P7&05JBmeBBP%X~meBm$If`UG@dV19{AL%fS!dT&Lq@wI0G3^%=0ED5A^E5Q@ zmo8`nroRiHU>Sk;DY$JgMWc&e`LW;1D9%R&Y?wy2 zrcMow5gKLMAj@_{1+=WIO~j_cWMf9CXV8{O?Ga!bDLs21PJFKm=5h2G1%`2P=#CPv z$8AOJWl-Z4A?Dy6w49l8PhA_go+jF=D7>n;dLxtyYJ6?OC>>nlcc>m|dHwe^2JEO_ zL(>BgXFB0)T@~`WMpWMq@1gN{E=B^E4%DrbE5C4n&f?~1V%m@k1@?EUIUvrJsQm=4 zC}mx>Br&4oT%rRm#JZbxCy>W?53x~c#A97vF8u)Ct?sv?t_Ai{IInmVk8=#fj6tCw z$7;=3+cYM0x#y)YIR>cCMh9#soay`)ob`wk0@1Lj$s~ZZ+b^_Uj21X<)7omM_C@?G zwmN=b<o^gC%MA+A@m<`Azzz1Dlw@+H6a%oBaTnF zNh<)KwhEPeYXu;eRHLQy(ES)#`g1WP*6-3~V-Q-6Twk{rywM|;u9Yd)`W2MDTYfHv zbrVCG6-%%B>6L{5pvf#IRpYDTIW|r+;b_bn_gFU+Ukj4G%S^N=gzOV9l6J7$P$&$- zD{q>_#b1VWjEMFeUNa5Vii_&bch+~l4jV-TZgHp*uJAf#0o|`KolYtc)76T~#fL0x z*c1!&O|btj_;pTyNz8o-Lh_71PVzl91!m||tPY_8XCW>ZujdiJI1PWvO4h=i5vYwG z0(<;wL|nL4wlQq&;R^N?zt3P{#%P;2?4g!upLh;w?v=mYZ|pb1p!S|A5H2vMJ? zvVTFTZq$-cMV5MzpDOY+0AvJ&<~{#w59}f1Q^lJ;!1n7@oTJ>=;sHJ-CPlqR(4TTKhOxwnZ`KZUv>aXjyZSV|#`4lZ@CE;$ z;W8I*jpN#^9f90|X#+MLfHknRUFC4sAAp@SN7P#aM5Me!JQx2oY~cKG={b4FkirTT zDDuCZ9m%O0f*%4Z+tlXaI*KPmJ#t1sN0%N`qE5+j_9UNs<#hXP;V=-$7>yZdl=93u z_TtZ<8UoRp$(~|$m9t!15V%)3EK!@bUK{aUD`XJLYWmpkX1o-Q2(rghq?V_ZnrO00 zp5yZCVc&wlR;|(U5LSri_q#(177pa)`!k~PB!LyxfQT?g)7e?Dr%7Vst<^R4r*`!Ra$-=Kj zv4LnYUl_Zw!?=s?SlREEJ`+|_im8=T72sf+YZ)kGL4x^P5PuFgE?=HAZ`)3VHRu7j z`R`$_o+*JlTng8iP@T}i$lj1siVP-vr1kJlbL-DDcMI?U13p+lYhIDjIX>naDwvhD zCqvP}2H~p3#>Mb(?wbHUhf&a>)UM`(nEpyQYH%=?NPG_YD~nVejeLvJztDh42xq@q zd)W8QjW%5S=M8tqSMzH)Dw0flT6{HHL@Y@`B^0^AoE4ihV%bRt_+Dy2` zzgslQAdu{~0iF)vS__%nf0VAzU04QLsbl@#ge!A9V;P$^<&!kg7dfs)f7jziT8EC7PCo&Igs2J*B71;v!52Ecba+upe!A zZB-<#ZYdXhu0LZmb5so}*3{CIbeOE9n8ItCdy#zp` zWn+*^e4%`l?!jy`oqBRdzA&Csi{>p~n!m{B0wO%!0X3?yvq7Q^cAyG5xEhu7Z?r+iH5j~4UA z=Re9O>G86Ic$%Q(s!`xs%Km$7A0HG>w4Ji$VA&$6>0oyljy}Cbw&*9K$kp<3r1Ok^ zXZeU;eFqOcG|Ad5vrJoWtBsbt%ggoFNn5((@K$YP&p&cZ?5O9r$R_pfp#a4Q6blFR z#y)}%=53KB7^41oIjUcw<*QiSbva-u3IdY>ax<))x>-}m$hnh?*FP(|WE%zUwN}`` zZE+Iim_XlSPX_EC&i3I~^7Lx=O|r&19ib4PA^Y&d0K)5IQPUqK78wxhjuxA@Q_Fyt zo1ieQF!w_U^QI%=xs95uSL3u?JSNnCQ5W3}K-=PbO03>#Btz)k%1Y+o(`je{Rud}@ z_Rp$k#}dW#!{(%%6|qd@ zPf+pw8i6cZC7PW?N#-+SS(w^>tA%Ks%8mz(l%u0}%c4+5nz@B~1o=xDOoGD$X&RBytC6w!OgI$fPOv*vrF%w|74z=uh zq?&9PK2CaS^)oaT6xGo&fgdC$?GV^=Cv<-Yk7prgy6Kz~6ZTIqfZ3?EuyNS~R@2uH z)vLCd{w|j67C0d&_*# zfVzrkB$#spG6dY&`h#e?Dk_2{M}!Q(bS2hgG53H=0KrUSunivf7nk8dOacX94DBSc z`JCb^IEe@vXlu|n9L5d8`PTdMcks2UtYiso=&p=0$K|w?;mcST0Y@#_j)W9dr|{;F z$CFwp;lBxmHJ#ta9JoI6x~5|$O)A$!C>Zc04^ZOk0HYe|QIvp!!5YN~Kwr>F{1%VX zXdWF==fp5t2Xeu)4!ieSz1qAZmxQTzt@U6Ba=ju8by*@VL(;Ng%@ItN@WK_M*S|n9{AqN^L1$G3}S>Ss8wcU z{2o3gXl84Bt@4CQ#<4`mAOn!N1dE@DPIh42>3b7@A;^;I0^;hRcrB~D&*VMiEz*CE zx;?EL6epgYwv3hNp0!w_F9lV#%#v<9{fiOntmx$V33%;^c>+A}+i6mr!|gk_PzpbigLu5Hp4IZsw~=N+8_ zsw*k4YSO9iM~9RRpk@F#;-0@Bw{8r-8LupJ1aOwJCwL8FK_e2&*`Pb~PF}nJcYG0t z=VsAE>0Y3N8&omKSN^;K->>e^+ptsyjB|Qyu$s}9`GL>`x?)+ZT~e;SvvNUkG;!?D zT03;H=IRE01L)a@Z2ic&h&e@x@mhbnODMTBi_d0EguV;H>eXkvA31Ah=|}BM(LSgvmMe1b$b|h%P)#G#(2@gC+ghps$n+gSU3TEw*b<)t2 z>;7VLb8tOq3+;Z7mEc1P;&2SH&_HXgG99Xsz0N=&#otx}E9?8tlQLzq;t5UH(KKB| z(iOi4ted0pmN{ie{?Fazb{d!<+v;QxQ=V86jjr@-+?g>gVz1p+G|NuB;m8>A-Q&~w=w;Q z0gIX5E}e=6mW(`V&3meFx%87t&*=7(JtD{g9qpLq{mmmi6s8@ZR@(H|v#fLHKEYeb ze%PV*-fF~GIb2X#OcPvhK-o*e6satqE&G7G z2M7g#6*D^hYubWDW*4a#z~E5OY!h9Y-a*Z)LW(tc06WbDyg^AgZ(jOGDd+|W)iAc_ z3qvSUtYqN!aA{fq&VUX*h~xy1DqgnL_~s|Xlm9hJ_(>b7+3hFP11gJWc2xq8Wil+r z_lRek(!bmTp$M%W$0S*zE}S!Z4HUGWqzi;n9Or~~7asg?9A5LvpDd)pN>@;NYtCn_ z{{)LeVjbe|F)>dqWih5dodGWy59g&Ck}PPn43 zp<^)ta5U8FcLQ3DS6kXSO1(lng2{DK0ft8(qb|J|q{GJCfMxAZE}|_j57Ph#E0_{KE(m$iA3Tk*;E0BEt}~^_)nwckav^>X+T{7Nk}rP$XaW#z z?0iwi=mAjUfUXUwm1M`Bjwsim6mYwl4PBtSPx)AuSWr4g4!=i<66XCFS~Bq~=Tyxe zv;*DfhhuFnW*%gc5qQ<6C)}();j3$4Xd&JbW6c`*7To(M%D8U~!-AT75UYYZ?v4|D zK*}$OK=Kn?@E2f_N6qTlP1EK5ZtdD|+aW;D!J;kAvnFL8fMC#}%+kbI<1c#jDNo%1 zE&nXgp9i*U*?y9KyBKNpIEHiLlR+o}2IibF`ngjWJ61H$i@1B=XPy;KjhU~e*H=v? zEgryRz<^X}nFg&W0O|SD( zc3*20SfFhMH5~Cx^wVRNJ#WXjhyhq?N=CEi=FvFP$M)qz@EOy1g36G8Z*6Vt*YR}L z)Mv`;M2gSoWg>53Hp+cWjiCATpCqXpt}?ZuHEW|^#(jXUtxKiVz@}G zL8TkhZ9``jM$l|w3F%ofpr!8BWKEaLN<-IC>PJ&l1HXL0KYkd;_L)L;W=#yRhWtO3 zR}4vSgA5M+q_3(4a&}~+5=1@oP*k|7ZQ~+E_5N)6kQ8{7x>IxIO#oC$fraPf2bXRH)KbkEg7fd8HMSEqsYf z2Ry|=&4S)fE2eoza-#tEMtKumO~dAfzIH<`G&Wdnxl*mWAfPLD1DEvO7ZpBSQw3pNJ)`q?wx~mmK`{*!F z6dE`x+=UK`oty*uBbv}{E|~d@OVs}>7fUh*ToG?RVi2i_Q>Dk_bybG_B>}?ucF6aD z1a=l>x0LH1foJK3fUgaLzVQ{-l#_UNqBRobl7s=#HP96Kj2!BTOO4ko3 za5lzJ8nk5T=PD!YhSfCM~e_eU!1Ybk6Y_B86 z3*Uq`!O$!+3`KQAb(x^~$9Wt^K|flxl5c_BtfjQr zRo@qsoy5%rgBA_Ey!lLB9o%Ij?@#2Hf!iikL1{Hv1QR9cHNfo3kq+wqWuUf^C0qj9 zi5eU)=PINcRJ#n+RP@?dxZMjrLbf%V4SK+j}Y4%p-X`>8dfPuU>2$m zn~!<#5Q~=1(LMI7dERp3vpXjnCD@yw*B(E?N(L!d6)a|u8g`*=KFjD&$c24l>kR?I3{HN~QL zZF-&)Gl?bB429aIfB~aM1_ZG_7WYow5&v%$F{)axQQ3VCHNZcrUEa)IEc-w(^q&XV zY+UH920hkaHD<4%9PY~x3&#KvQ0r8IEboJVmG#*9+!r`kSP#iF(%l?z0jrH!|2hHG z!f`)Ps2@9y{RjBTZfCggUX58WF8&g``uNZkaFpnKN|H7;H1VmGfZ^(YdewBtGR!A( zz~SuJi%KwV8dDXdR7MM>nm9kN^St=*j)Ji}1w_yQox{K95f%Uf9-ZLR75c_*1nN{l znsKYjuWgPs!X(8qRLpPDamXv5Aj+*@8=AJx;ul>uf!k)}&;a$qjw)P?T;L3P{*Pec; z4wwdd@oQWe=AckuBkK+m=hkWGYST037$WHeS7sCf(Qp4;)I za3L_4A8s151@QDdJL*cn63!v+sBjr;o+E43<3x?)$85n6-Ekeb@Q4n6P{l5`e)M{V z!6xplaLEbRlI0$^{fh|=gL-{d1@bFsxvFGYxa^HLC?I3!u2GVff$t%(hHJH?@&fQl z<=($!D$OiIYNsft*ittXYCInoCiS)Uyf=ET30zx)tu$i}ZakmsTd)imI1@h|FK#^UG8ULQSmr-25_QZTe~R#ekR z76+zXx<~~)SSwh=Beq7{zDNpr^oCQL#$gy>+R^!lN0KEbpR=&vz%gH2PCX6asWxS2 z7-waFZs=r4c8Kq!9B^%PFdJ$PTGNV`4sX|gVBHp3(+DRCQtmBd`bKJ+DKl3+DGP>G z4&qKKE;@c#AcwAU+Olu8U?;PD!$ z14s8P+%GK}^X?048iK>^z_)VuNV(flrO5yHz@kwO`lJP*J)g!lyMl3d(c7h}Ix}Np zK-v!?>grF{;#YZ|?f{XM0?fIP-?V%yQs`_N<(LF>R>R;e`P)ZGBLe%mMI9zq{| zQ|@{>q7}qT`NCd^H6cAW=6x~w<5-grT$-6!m_GcTYj=avNseNJkN!!y3=nELUW)ZL z`9?FtJAvA8Av$WHXdK@ror|snR7qQ8=Y$<%#jzW3BE2TdLUGghPR+gz?>W-kTI|W?JfgaS*p9jxgc2=_0&)0+vx{rVfc_5Mw?(WZ-~0oBJHa`E0pJe~MM={W~e@JXSwt+^l-7Dqp3=_on2YoL~3r>GHs>sZ;v|}2m_w%nF zUBwIMw&8~Z5{=i_KB9+O#z4nD@;WX*Ru}IB%`XBD<}o?&?~{wFl4^7oeQ9~tvc0~A zEp~zT1y2+8y12F=NiNZa$&Z1Lz73}YTuCo%oc06B#CYG}UY?RA-7HA>sCBjQ-E_(e zr@$Mq?>*E}&F14&K0b(+&*_q3LNPqNke#WB584G9tzewgML2rppnn@RWxIVTP!>?~ z)(Rv}dy149;1zXq!D?<6=Flh&9R*SkHs11J6CaN@|0wDh{sra1#%y{aw%cIzpnI8{ zFJ`eK0ULE1F#dp0U8qfIJr+rm!SxmcOP+~4z%+ti*aS=0S(Rd}px%igO+HBd+ysDc zR(hpv-=V(Fb|N@~P5}z76F+)5cPc3b-2gD}UqAeIbWKfPq3@^kf+1=7CSy8m-_Rx` zhmo>**aqc^?~3qIcEJuVcL9JsZV^b@8d1`8O`ChE_1X|thDYLpA>}sY8W?;Aeg4jB zUp{!Hdo6i^7g7u6N3#5wPqN$wfyFLbHqwjEwwX#F0s=xJe&oXx>9*tG0inLne8gVe zv-rmPHP=c@7I$nPc@gRlQ(CDUg$oD)a!IYvtA)?nK%4@BQ4=FkWp)nJ8mgpVE6;^GNt7CA|a~1ZfST zNEw0(OQN~>lgFP)SfJ|lPoH3kBUtz3t#{j4uS|IGZUGjhG(onGqPn)?9xj>MDbbU3 z^Msf5uH(3KQwg0(E^MuJ68^C9(eb<0py&c^?>U7RwK^qrOxCvb7VWrk05YN@5U+Jg zPVd{-CdlRz=5t@cP6mUfkKd-r7n}A{+GXDqYro5@1O@WNUI+ngPN3L48$#B_?QY{l zfo4<^pmxB#0Qga8-{oiGwnac#eF5H|Sgp`1Y$Mn7bBVjqPOT1QG@0^lG=)?ZG9<48 zd_zf?cw0#YFW!r*#2D`23vL-tNPk!asTO*Hj^dGq8ph*MkAxZ)sN@07Bh}!q5NkCU zg$g=@H*XU2>2SUE3M0%}fD=!fCH3tF0^AefoUP-~iT} z>JS~r)c_ON+fo_4`~+Exs{``}vwP(T1SsFyo2efI(u$a8I`>zT|8(ClsoDuBFm;Cf zu4rx+A9Ci?0Ka=`KL4dYI3QN13fVj_<=JS61)ymGKCkSLkJXwx5AM)F9k+UM>PINN zh*?aO$UYF|DA6TbjMJKR4H%-J4+QE zAcakGN%rJXqL<2g*#~MG7>Gjm+}cymc@T>a#EZe%95{jP(+SSMENR$OR5VIVjLw$h z?9d@0K$w zq+ZYvkVGj3RN#J7#g{237KB1}V0C~u(?@@0Npsgg&(~x*f^%)R`{kD6W*yh0)4S0v zHI+K)fcJTF%x<**Rlq&!fa9(1g|t8%$mQg}d`Z$rr*K+aA`r)im7ulKBIW(qhq8j8 zZF>#?CcbP{1P=cNzzg2FB{sMgj(H@ekP>My>BMG$;|;ao&{O)}b}SI06#B9h5PF@mGH2d0{)AAqABfEWlP)SC@9K-=4_ zJ7_{cgzwrH_Yvhg>!jzzbZnbcX!?W>1Uzcv;<+K!puyl_7j)IYVHTK!QuB>q4$6xt zOT6o$E(IrBY>4a@b8(d9$hj#2$7M>A!2=bO$>N5jt*$_MLjJRC|AZal?Dq~J#?N2c z8Ac05{PK+KSj~Xa{$d*NFPw9-{o5@Q+(hyFA8_Hvl&(hAK9E(@meYvquhj~9-5Axa zr@M944XNSz$N_eLd?n-i5v>s{XtcZ1#KFx6q|Q`ie=Q~L$=6+N*5WK4=&87@Dc>}B z$B%EeeR{DoS8EG6z&fu2u>=F%X_yYt!1E!o7=XDNkZ|{aZKuAuoC^AnvS#!&+}a)2 z!APz0+q1bH%XWdoDb1F>6y`wy4%x_~&_+We=&c&uKAiC5(@($8joqyPLGJ;m$m;?2 z=F@NKEen~=bF-X~w(#d8A#rT86zH;p{yipfIm%e51-t35BK=XGlG6kOD#d5D5__PQ zlHv79`i^o;-wU%D9Un1M3W8HP^C*^xm|+mc#Jt|h$2^|n@>kDt%Ju+ce7X#Oq!As3 zeYEW)lB~pD`4L>DA&MdiZ&U6>d%AFG)_{FHUV*&R87q8g&rB~n?LJ=`WgDPnI~3mB~HYMtxi zO~FNy?q+(=!tv&2z@gD>j^x@#Fiz-UxH9k;o|O?(Wc%=D4B@P-#n6WScGV+7&f|K$ z^^bmNgb_Hm#XBK=Z;IG{1nUyS!CniqGS?XIm<~AvJJmOXQ^YRR=v+dkA;`S8GgRPI z`Y-+2lb{aq$QSfjMBLK|+7tFHneP}bXbIZgkRPydaR4KH zFN47VuPB}0s7eDo>i*5CA9p3VFtA%27RugJ!&%_C3ED52b54DxX5Mcn|Mv^pW_x77 zpU@t-uQe#UkL{|T_fJ7jKNXW zzfksj0vt#9lBe786h#dszl;Y+7W6Pz#A3E`R*23UNzZ7vL)RsE?7aXbe!SbEA=i8q zgIk?=ba(GcCzES751e(@No5ic|t}4>mRTWhK>{6Sdc&k~C zpX;U@yr=n3hZT?Qh6cx8=d}i3hOXq~5u)0}ib>e#mG^nB;8e(1SzC9=Sbo-Gf#&+{DifGkZzCt*@RG&DybRllQ&`9WYRDaVTOBB!-{Tn49 z{iYC(_gU$SHJeQ6pV-&Y=x`pqOiuM zqpxx)K9t}#lAu)i&kAUSU#Yh!$?s@_pj&Yx{R4?PUG|jZ;Q0e%D=c1n&T#jDJ+JNx zR0!oIJm$W6s7w5(=jF+Xfi6TbJ>sSHn{c3>z+4g27Fds-(+@C~7ga+=r84xKVn$h#KwRC*D(Qv%i*Hozw>ZP2TSMn~Iex zJv-N>D-0`u>oAW#czDtkg8q+sZ(hVewUUd`={dARHsYtps)SfG967-fHs|VNcohz_ z?~#UU%QFzqnkej%>n;9$AJI#1SYmpW(8LS}P5smD3u8iEkY9w~+a+;{gA|ioynkQ7 z-?h>#3PCvV1A~YEtle-HxhL*jxXkd_K!}`L`jD+DG_spou$7sYu1hbx+sV{zz29M7 zr7>1#qs=`su&q+{Y!zQI{WgrmoJ$WR{3bL~cG+x&yf&FJ&%BRegudSm?N7DuQ(Wjf z8+}jg(IENWwGGuvgMfY|`0`Tj*#PThT)hqb6ruwVdZYAx$ntvvZppL`FRv?As?0xU zcz(dXFK?JMX|2Uv9S7M8ZLe7H=%O^PprM1=QT8@t1>#;WV+OtKd3kDL;2PJK*l9kk z1yn;a(s$V>i<4fJdkprZRjRzK`HJSZVVSuUz9dUrK$3kK+1>~Lafnj>!7}b|kz**! z-bX>D4m+NugxuGqcf1DbCRh42a|s+4mPrRMq56ZJH|NS!{iS2}eGiQSmrf<=(pl-~ z7Bow;0ty6{CD%g!8p88|oihHry?)>4XEx0KP{h6b@G+)X!3yq>{3{W3ooXQ-qIAzw zYoAMK_|Eijl!-$7YXMI*x4CR9{61;z-@_eHb)|xioPoJoW5mxLOfIwV=DHD} z9v|=XN;hVfpl$Ff_f;7ed<1;At?1+3XPS0k9q>O88J89v`VU3T#;ze;J4 zpDJB5*X457i6F3alB%*vkGPPMf_ne+T8z^ad4 zKbk1$?bb9NOE>Nt6<5uDYr_J%Y3kTmep}(LI}}nV<{s9>ZPHrQr|A09u_%7xD~K$b z8r1~56bbpCFu{Q}yD6iwALRS}kPUoAZ26!i^N(^p{El00-O0|B!YQpPrR(!lY3HW? zKttx8&he)32(v6$zJztw1XTun=AWL&**(<~ZK2V;N^<{N-pbvo0ScajQExUC`XeN3 ziO_3^+2!HM8mQ!7H6LZ1KX4LK!mC)~B&H;*$6$(Q*QapwLjwWn(OsIKxnSKIrq*Wa zZYpF7OxB{<=l~iD3Pa8E706PBOSgnu@NnvPlEq0zyW&PW_%sh!tLXG3A)s$z!6TvT zcRMrYK2&(#ga?yCW^c28rI; zxpcSM>ZEQ?UJOKR=oUIUUP z$qLWPi;rQPH=B#0g?zld0j_hCOn=xn$?)%6NIp`HAFz+BE0BKBBA)!=;-`89eqNXd zUil^l8=;}XZGyY;FZ~YqsUGMOOY=IJV)CO7Yr~6i?CprG+#}Gz8BGgwOV$IAa#ZH} z@VNE)iqmFjU@B%M`u&!O=2i;-K8>ow)4gIV+`S;~$y{Q$G=CFW5&amctx1MDxyPyx zA7^@ZCT^l$69u&0lf-{am8NReO09Q}V;-}*wnH(Vm;L-y9w1pAo%sB&x9&US0?BfM zkkSMze12g{45`BRyHr%&W>nUY!T5VD1@*`jQhAa!(>K;@@ZP8v-UseFLk@=Llau)1 zi+oo*h+>@4+ClclfzQx~$TzH3$8)OZqx*1?2FYFc7vo#KVh}O#mFYi#dP3~R2TBq9 zYrU7_fq&IwM+D}hm%gOGJDso08iA_`yeilLSoaST-jz-Zv;RlZwa2ye|9`iH5JE`J zElFw!MYXy036&7ibx1-q-E>=L2_If{GuNQ_6(?@zc)mUM}DdLk#Oe+m)iVV$21LgY^gEk3l?{(aa z2(LOr3cGa70b0A-JDDg4A#Yd0C#Aa(f&-T3en#WfQQ{3kjq-usO5d{!cP%;35av<6ki zHGiy`3nXF)AG3-(vis4+(P z%Z2BY%(vqH+a=z8(QJ0@ayP=CyU$z?c25x_&Gt$bgwCw%`(v3fo>9o!$jJ!jNbdr( zbE+-oge%ouXE=p*kI~fXTDv~bUEDXLOBtSDf(vY3f-2TyLB0$RK&(nlSjJYZHi{z} znYPv1Q3q=6Z0F2lNC%G{tJ-j}JTXgKobt1lHt(;Bd?+@i=ALIU7apQ+RaJZ)OxrTL zR)5WGz~Oh`U~s^3j4U~D@W)~#6u-BKg0q@y{uosK(OSMis*R8V%ER{uT`2c?N*=oc zDo?4&H*m5xyWirW*DyOMU3cQu2=<_NgkV9R9Gq3WW&QzV*KBV_Gslz0h zXcVwastkFWDF(1LFL60eKClFrGB3tjmk+#y*WO)36zSX`Rwq zOOUfh%vIlRpFle#*JFA38rF5Fw;rk-&LBwnouA+n+#8wp5%4*mQTRKzQW1)GjC99m z3o`D{QnMno#7Cr^Glg}Oar4{(XQ?7YW%<-LYW2j~NiAomNs&(sJ`X~+cb*Vd&P%AllP`dv(H~H{j*{ikpIrX#?1x0?*{EK zms=4j-T2a7Y=OH})zk8hSLW`}drDkJrMyB}8`7@EnOfDOgb7?5<6L)ff3KQ@Ltf*1 zhZ9gU3M0lZ2a@KxHbArOk#f|4A+&agV!*t0;p;XyF3}lTz8rWyXQyg64?f97N>{*b zaT%&YjxN3sF-b2s+I(3r9Eq-5U1D2}bCY3Dwu1T8JJ@u0)-7N433BH`t3pLoU=)+5 zFd~J|AZIoM8H419w-|G>EBSzf&VB_MASbr#RqR|>H@pFY&L2)l$dAT3TlC$|+u0^~ zc4-X~sDgg<{uwjXN{CZL^k?j0flqOoK-zATEe`wtG0I1U8CYTrtHHdB2jOc~OyZk# zB&=DG=5N}~*veCtZCv?fLoL$rII$&mPUapbM}7Uv$W#!j&k`v=L3&QZUG!TPS;qf3 ziUN|D+lEMt?J~PLk12YB>w4sbz4CvR&3@O*v@R}&8pNTLcrLCA z^ERK+01n?Z+GP?Mb`lbibOAh#kic0u--^4 z?Xg8$$qYC!Rb5|cs>0r^25iI|T{|-mECU1qb;N{=)3_?iOXNJV1bFb3_^&@WJWW(2JD)|z|&~(m}VzhEgMs z#upVjZcg>aZjj+yL~4EQ8)R7Ldge@s@~BqW)ipqS?8jONb-qQUa>= z3RRFq9w1!Bc|na4*p;`S*Gi!N>I({q4t1eiE^Y<9$NWW%3-yTM2=PHM?tK;um@m$( zj}*ok0$+kZ z8cmTLt!a!z4DIVlk{jwBh&^9i{@+>g#}u*r$9fr7PXj@ZBBqkToMG9|^DWSu+3rX= zS-%%dV5+e){xRzBe9eb+*k_ou0cttA5lS$=svx>bovA&BP(~|oThl&9BU^|iNN#_7 z=ZayDkNlgXxtv`=o+RtBR9oV?y|XA*@btAcNIE@l*DLZLiDa(a_Et(wR)cpY@!dL9 zuPwsvbTqe_-beqaye5J?|!NB zKm}#1RXkUHnL79}SF+eIHcp~A*L;+BQ2Iaama3B38d$kXJQq1xid#a91<$e%iCfCQ zqPD>~AAxYb-F6+KD1C`Vv4CUV1i4j_$C4W(Ko`8^bTx~Jyv6_VH>Rb-eGV{PDkDKb02sgu`i(&AV(z}UJduDg9bVo^o%z9TPI8uu{D8+Z-gIvz1cu9k(#)u6af zI>vn}zr^E3}DXp{5Y(2$1a$o#BXO&!;LRlXvcdeF!AA-H$L zIplfpDgtgzR2OqZ&-t|~_7z$6Rd?}Dpev|<7#N4^Ourbty+2G^4}At;|7($pt*9r1 zF_1Yl*CEs7k`4PVHgYmxjUn<`!3*~%@?t$HbIUw)-xPK!q&Q`^!lZurH-BvzWgUFh zuz}dJR7T#;qU>A9BDDdP%*S$uI8cm*hoercgSRl5rLoiOt=|wm^_9R~CB-*?h!*HA zl#%tj55Ojm!Sf>9u>&yur(&_IoB2sR1pTxt*^44NA!!Aos`5u-RjncHYc4)z23ay6 z+&{~)fAc${X!6w|u7%Oq4^%BOSy>lS$7MdnmJqAv zWExebl}ttrC^=x4f_|j{XNf=RRl)dc`(^CFcM|c|P)iqRXDWpeKc{}AFd8v3cnh~O z8a%N2a|q{{5YE;V(|-eIKT%FfFzG31MLcnKvt7x0)M3d((7N3GDKpV5$d@KzMK733 zTmY;ThbHH9`PA?+@BsV<|B%X676C;Be*G)RYVqD@$Ym|;LeT&4U!?gUu|EFQR1;=> z50>WY)jG!##TA3zw`kJhUTNKJq_{zxnt8*?t`nTS+06nUsk}e)N@^+%hE6g2y8>Zz zslp9;8IA1mPq;2o5p+#G4*2{bs?lRVx2s$pl@V~do7mYenkqM$qg}@yo(8*~%9(pv z{&tHiU(v&u^0uvj6Qq3kHxd{;rEWLbhiqLAlj?{SNs;p75k7hJP$LDT4R(HSNPTNq zIt9;6n8KvP+%Vf42)`&r%y=WfO{>Bh({W8%I{jRPin)hg4yuUzqpYA-bTrllgCh2U zL4u48wc;n$iQcRFg$UkeWV{Fg%G*HQ7B)N0bsG#e6E72(?adKP#QEtDRe5s(&m<72 ze!+b7>WP@yJ;!5cLzyY;tXa(_(??-_1_YwihrwNgygd+VmoR5>ly5^@(Nb@+0a-n~ zs?d0~zLq-I=<5;tUuYaX0=p~a-*}W&&l|O`*O_$wcpW>AB?pV5Zo(yRTb?w5HV?&N zj}d;bJsAJ{O)}r)u88!O%wJc4V1lW~AscH6S$P-aw*?#JuPu1qRV5V}C;{csV8BPn zY!|%aJdX@L(%L_&cM?-trnnNP7@9ttJyw*^%<8pX~#(->-SW7l>I+A!7lJJg&*MYq$Hm3{6(Oc=xF3@(u%qG<82x7&frkKNxW%AJ{@LtSTdaYi`bwjChDsyHq&pk`vhs!DZ5G1yWT*ms!hD-Hc70D zJzC|vJIwkI+*!_Zenx3EKF8Tz|3*jq1wnTYGsTq@bS{>Hc|P~hg=TGy>~T8v%GEPf zo33tpuZboxhlm{%%&gn*w%Biox7O(P?UIwjt_lK7MDv2qwX{Tj10_Yf7)N-2pRBLi z$jc7gr~bq=;dIW|ZOkS2@WZOQWUFUPReQ)xxt zPVD?0X1I5V@1i3)Z~ynb(*-IY$E$^QZy!y}HckJf%F*RBcjgn|n*G!ib7SWFz~J72 zrTSPslEv)ot*&0t5#0@M@E?jr-IlQo7NkSkJ0r^6hm(DbM19PqS5!8f=Xf6cT;$>k zH&t3M9ev9CYB()hwM(*h7jEJ}ru@;HnIALX(;C^cr}#3|yOm!WY0v@g0Yy1YLqaL( zv}~6ol0@ePx+{9YGK)j+s1Ud(|F6`n&;P1(79`Wbbu^n;%G|S?WKol_Tl#DVdDvY> zop3k&1KnpFmf!!RAWAKb{NtN37)S6k$FMcr;HX=YCcCEujkwgc13aUUl@5=ED(APu z#SP@0m`_eG)JB2IsoX2fi83s43kgkn9fC<36af20G*|OikA;N&fw^&a{@)a&h5a(^R7wVY%$1Yx0ICEHdF=faPM1u{Ag4_%69DSyjZ)qD9bm9JUGsv zr`Q8w@fkZB?E;TvGoH(o2Yy6`+;mFxCb|%MYG2Ap0vz$zNV4F55utyWKZ~tog+PZe zFJ!og5k0Jhx906Uq>ufE>t<<-iS8X5#;XKvx;yz~RL{)4sS9>u^x)eZP^%_-i2KMk zy!bRWtSmzq>^Mg0sRXpk%J~cNy^Q1sONp}A6Uzviy2ZG`D;p&orH3(@YMF`TYsP@1w9aN%)sKocUh3rE}=NT$5>JafM zVKyqC;MPaGGNNai+DzlsZNtf;B-3$sk&jDJJ*~vU_pnsZA)WudO#v{}Qsy%)o5T?_ zSz>p$lB^BWIusP)_o-e>MMowiEZpaFiY!kfdQ>YxmCW}04%~8Slz)LKb^XHPF|gwX z>OnPKGQ!FipU0Z*?sm80ZMfG#e6Sy>+(%c(CYpIZ%s#xjVZ?GqP3+*&%_}`^-%_s5 z2_cQ(lzqX1^MbmE;Gx`64P1xJZ$I@8T&OBKAg$j;Jv>9N)zup&>T>GyBo

$E(liw%9Q0BG=YW$2rY&p5A5z$IFuf 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 z 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

8RTR?bJMC3 zikVY_p50z2ElXne-}@witoRidq?#BLwt;scAfDoDJrn)5U#mJgC6H#&Hp7! zi{Taz{ptW5w~F(1Vb#I~T;8DR7>!?@%wK!$H=7-&HI*d&+^e$kCnlTXD`iF26ri1& z0+g3l=0j2!)m3@Xr;WoWm-o(%-Kt2bh!)Bp7fV%Bs%J+!d+^pSQ;7`imHY*F8Rn7%e zrJI}eAQo^0zN&XH$hDuFEojpbqz1pTivh?II#lbWZQPZ+MNMw4+3+l@7YledH)sNS zYGG?SV`2AUeJANyiL-ZuCY^V|pK;up%DslxP}uEB@lnHfIBNKw=Q5{VWyaHLEHn1v zzr$0zvw)|3F5sy&bEEFW0ygs3!oB9<+ZHDpW%R(sKl%8lpnO8o4ER4YQaNeok=pZt zl3mCX3giH3Cx3uWF?2O)K6SJthR=#jCr5%MebsHTkeswP?e3xJuo!38Pd;NDbv&7l?fmqIz!Cb5&!BswGRUz7UDuait7vkk`ZK!U=U+Rdji>_6q=6!5)4LFj54#{rxhML&&T5D;yJ#NZ-b!gN;h+| za2GzV3%cn0)oPnv+J04y=2}cg!U%w`?461!Ecg=qx&?FGgv^oZsL;9%$shUK9JHu zM~^Z`;JxI%x}aVL$d`p1IR-cK=Q@Z;cfAo4#VRt$pWLpFYt8(($UqbcNEDMgG3#+? zjNQelL;y-awZBvJ&ZQ6P*{Vy)el~eVbo~>SyjE@G;tw8vPKOqwa!L}dZOIC-4)kSW9m4b zvsqQRYM2@9n+^=d8>81T*zQELk7R`aa}iiFgVpvhgFV;*5P3&vMD!{gzKTH?SIaUOlP7wa^OXQEDXvK3W2=^eB0^mzx$e;e~2 z2UEu;K^^1)xfWG;P(ex-@<&yCC$QQ%^G5TZ@nPS zdObY0KCC!9{WldUb74Eh*-|_cC;^^n zlXdtHG2CEZT}<(7K$EOlqVpbaBrRTt!+H0s%uk_GT$&V+a#x)0&D!*=*d`2Mmf#{{ z(2LVZ=4s4$<^qv9^c{MBZ&xc{1L6q%ZT!|C@6XF*wNakJkt6YX0zj2Dl9;wI{nog| zGfeF@+H{64tVt8k$?BUNY2DS`K>W(Ptuk-Bgx`CGo zI(7?!P6IV!CB~K@MS>z8MAG~RP^ox8AyULBR}(qJ)e)?3Sqo~&=F7~S`BCVv`dbTb zG@BZBpR-78I~LqMpSU~b5eI&ScI!~@_>0dW=X$f0l}IY~E%A%s!9oh+o%I%42R$oh z*6A_m>Ef(h8JU6TXQB4lM6QB%T+d|zz`9i;LzC+%!?W7^snPXe?>xX&alCq;#iAeQ zob;Wr2ZX-&or#&>Mpo{Q2p8J}w_qjrHzy42TWLOj@i2^$dbGLpZ~Hv+gy=Kv`SI}B zl+=NvdP=^ZEx0OrTvFn@!|NWEuDDRwy@LA%QFm6be&R`r_QEIC-d6SmRk-{){DBc% zyhPFrCCX}C*7gXY%$%w$7wguNNy>6flHLFrwS{BJ2xYk{(yyQqi620RC#|JFhJO!- zedl6IIk*j&EtzMez%of1(cUf z8<_)$gzriAhlXYDvn`_iWks`r*~;3J7zqPlywF|Kyjf|_kgANgxXAuKH6wAZOT+x* zTGouT^W!aTZ56;7+~xN;Zt*LN-(2yVhrj9DJj$KPp3Lv(PtR5k$+mR| zvy~$vw!%q&b+-QiCi{0{kTl!6Z=ycpw*!hQSN-ggn}x8w#r>dD(B+ZI9%W=&j(@A1 zSykj1RaiNL!hFEQ3|B#2^B!Z<;O}3OMYCyWTjYwDPWRS_P1pO{0nL7gQi5z zN!`qTH5*$q4q4qTV-;>x8#6n5rZrIlYX+-W_CI-%dC6SDP)P(em!ZaAWG?GEQ6;m+ z)?DRHUCgW|89t~!Zuj(RvxVXQli>y(mawNYUxwMUqV8|wEj`b!Cte&;C30D%@Q9y7 z)~&cCyWW(KFc7lBJ2-fzFT7nD-x3c15x5{6;0I)*$&oErw1`TWgx!VI(d zNi6GsZEeQP0EXf-su>KG?J^_AW=HwLH5F|%>kBjg3WwRMzf9aT-2+J^A6kr&a0jPX zD&yN`R?kks84hYzFEZ#VxG|@64DZvs317ktI%mIJx(RVrjUkwn9Kbd%U<=7oJXc(g zSb!uxENO;}*WC0bzm;P%=!C2=YvkgM1-UpkMQt(qFtJ#@rJ?tMy<7@YQJK`T>c<#pLlOWE0EU05RMH#2Stw*N52`PY2i2-q zsD2cwFujtq#iL)0q)f6}s+GH2qQc|1kT3V86gXcm?M{oiw5JWF836kVzzmiaN}-kK zt3u!nNRKWJzy*Q^ZfEcbje~zEz-0}bO&e-zd9bn}P71$v@#_%3F7ca8zk+nMb3u(Tfbjb6tJpd86SufRnrb)(DoB zxFi_)@Q(Dor%(8IqtPPs$gG%fC0&zVwv6mSlUyPUzDBDPfKX|v1%$fO=DQ^(icn=? zbwvH|CA70g$kB>qz8!PA<*Fkt|6czA$dD1P#$b;qjP64vxzb++lOO|EahY3-W)k5P zcY%4j!*1T{*>)V}DZptqE1C`<7=oH$pe6E;A87c-#b9`|7IYZdr-Ev3j}Tq8nr9EL z28{s_0;x%vq1i3)9BQ~K_+2CwCJB5o?V3~yuP>qPK4*ej4;LwM*ib)u}pyW#G zh;8wuxVF=XySQ`o3|RhtBx|ttygqWF1ET)ILrtLm?h)dP)bCPn`Yf#DJBX)MB7_$K zOV-YCBpx)>MUmGD(|sb1o2NI9bjEY<#YlWLH6DEfloRjp@9Rtt=Nx=}?VE~pwD|D_}kM7V6itHb>0Eq_QGhCuM7pr#fCUM;)c$eYJ%yW_F-*M-$ zBSVR#`RF(D@^c``hSWAZUoaJQr6^4>dKb@Dv6>i3c(c2lpODAfDwgB37lc4Npvclk zg_gW~1TV;}(OYe-Yg`I#2$h=ZAByIusQUF9cZwSI%0S15%Gzp`U7Axbf=+LH7D|3u z;(sRj+@HAS(HS1)_N2KUjWYq#z0|OJKKL`ETDKRZa|G|72#goCZc~~CIXopmstXjC( zjlIk&6{?)-WWCsf6qDZhexg~!Jq((XdIi9RzEH{GDP;-uS02ZzH7dF0tL0U>mm$9{1RmS}yo;yKU)*PIsiUw&iX%~5 zhPH(N2^jgNV@moq4SeyN7OZY9{Dnruw+(cL-$@(!Gf-){ML2XdouBuoZ0q$EMd;ch z`?kbzCBFJrHs8%iE`h{;7_Y>)In7<30?Y1n#(#P-l)7E+n z`f^aY^Hw7_ODvy|)Ct;_ND9;)@Fyt+t)cU+^67*4mJ0e_&buwXd~rrr^DkeN{abTR zt5}_7r(9Ln#NdqOt4@QmE+g@we79V6CWc`T$TgdHN;ogKxKI6D{)6n_R~d?h zL_BbfYbOl7X)Li@qb2T#+G7m07anSkS6B2PH^A~?N!`&((vkM42FNuV@$8~pQ$;`i zVZ8amVVil1(q&7agQ}A$4B#d=o?Wj|OSa?e!=XzJ-VGB(AM6bhja$NWrL%;zG0O={ zHcYr#p@H0k&)12MML*(OI=^k7-9-*>!!b`I(D6V?$-5E2E&%3y2XD^i@FobL9e$1B zf)8q=7Xl*O#{-I=f4raTvMt(zGlU!S+5K8$5G?pAe8GxO-yf-%`<9M!tGt#bREMVK ziT5DTvwEafAV$q+xS37NaCaiyMjbAL;qFZ^z>%%;DujDlhkN5G;9)nPzkoe3;x9>S ze9d1{Tu~C3htU?)O_jKPG4ebN@$Hx#-i9>1U>F~}^VQyN^HmafVvC&jc7DqLfM@5N z{+>wbSS%=o&2u0DZ`j%_<`T@Y=0&$-_BrE#K&j*&J3Y{%#2h57EHZL);rlDvOZ)Vl&Ex5iEH(xj?VkSwkxFq#nT_D(?y1%uXuc7(TL*v+2#qv%Xd4a9E+N5t4OB7sI}YJ zeHwi^^?XZ3zAdqHjUS2%IT0gQ7>93jW5Xx?%i$Yw+B|&gx6pu$;-3-p18dkg*)I?f z-WqI;BbUMuo1TD?`{bYGHN{s#ebi1m)Pp<{phGQwqCtEm=*}6&|1!pZxxhbx??F? zb4Su;bMWPI-nyD<6~FezY^92b7G_uLPZA!nrPY2*Xk+ApxnWb-FCdwB3|@e*_v1B6 zJO;x!mQOCXcn1ENiV2Kpa*Qa1mKVO?}Ws8^CYl{Kwo znE%+1%fpTPvr~T_;{Ld>Kgr^VkwY_nfWFH8xHH_zRP%tSew=2FE>AKyuvJt)b~9LZ zgVKIQSN$O;sM)S+HSbYq_6^+Z==qhw=WTJgwDZ|ytHWqr?P%OZw64uHVt-66+(`2` z4$2I@)u8|Pus#{>vYEm0gF4AIKH0)(lWXF;4eTjlWC(Q)nKp2_>0GcR6>WQ+mx$f{ zNe{h@;!DI){;dP-SLM?lG)WJL^LBkD8ph`@?o3Uw zsuk7YFhvwOk78!)2ee!BaCQ4gk%$!a_owT4c)eLgK5E%pv~Y8_ABh)fjijH`sSKCync9)q`q@6 zx|#P_gj}w`o7I&bZcz^}stYU5X^Uu=x;RsJjM9pQHUwyM6ek!YI?#mxcXH@0nWk2+ z7}`LlR@i|A(=uB)YC z5yT+lY?HP?pPg1`n5#7c@RBS|OqhSqvax#0o z60xSVKnQ$^E=!|@V6DBfm#SUPwQF3ljz;s$?Gw|1-spu0v{t-X?XXM?vg_>ciIW|> z!uvZ9z@Vqn{FgsoBvxi;^boqF{SanG4~?-!4^j3`&p@o4JaW)%&y}m9RsGR_b^de0 zQHUDue}w4|uXBYZCQ4Tx;JBdzX7;xesRrJGhFx}tJ?}s~HrZcCO)lwUAD1;ZavWRe z5R#{`PagDbTb?|_?lqx=i{v;(dyNswpJ}s05bB;eh{j@t9jW7B{y$3tl|V0nKtJbx zS7XSaQQ&MYa0L~Jv4DRPw~0HiXt!aiklsj9{ z+KAJxQeW^fiOVV$s{4* zNc-33G|XdnxqTO?%(V=Aj^^M>o>-yveD5y)QldFjr)Vt|b%zq%flg7)txR}2`Z6z(p)x10hD<(dosAa~YAR>2L5H04Y-_TLb{!YNzXs_u;%2(penld4U zLv!zq3GD0Z>mFl~W|slX6lsDgfls@uuE173>m!<1dsfrW*Q-V3?S$@jZm4$(iM%D9 zN=w<$9d)W^6Nq)qB-X{N3e1(i3+d@V*1qO+CmFYWNTK~wSQuB#$WZM?M%@zbbXn+H zR2Z@rG4*+~W?@DDe?no2-&m|Ayg!G+%17p1f~7RSAT_j@DgT4T4EX*IPl|mpYv0gf z_FO+6w{gr($jN~gvy|@Hb}73bz)?o#Twl)^OBU;jj~`=M><(l=zEB3l!chYm14Yb0 zs61uHpXN9xdiu_wF!FYq{y&Ic&2ci7zrHrUKT>q@@AEl4LB67l^K>R+0jW1oKjcO2 z+Hj#hBdISbJXnf8Ahs^Zp%>1u$iZw0_Y^g_zo)XkA^cu&(eE71o{i*NKEg#ccPw`r z53c>1mZK{?V)y!;jyQ^~Kfe`au*fgyr+GR4(1}hc+s&lY0aST0J{7V-zBg;x(?}yD zh{ENm_^vn$f20X_db51=vJ-su+f7)cJc5dpUmH($px4KX>JKN;=6N1!)}P#DC!08s zVFH`=?>-1!SR?WAY=9o~+9d+P-RDf|Hv_?q=yr_rmiJ_0UCqCzpZ+L6?te;#G7u2u%uW5>_ff|+Ja`ICt65C~c^2!8T&6F1U^H0$PBSIcx+18BINk%_1G<=oE zPQdY`^U-EU3ndF3*QervBJ9Clp>D%bJ~5UT3n3Nsf-0YQ-nqhRUy)5{^3RT`T z_#U$4%ERzkRpe0kL8naGR156V2TcX6zgpLTeZ)QE6{mf}v_Z3vW^EMD7I@lR}d!V1ws1^%g8a4o- z+A&nZS*OwW)L|IPz6ZF(c!KTbXnlN0>ld*Zrqfbq>z5q17c%NFfi3qtTVHh8-umL- z2yF6w&elJ0*w*@?4E5LzZ$n>6MZQzElX8}(gyRqr@?7Y!b5+xJ3t zCid-P%zgV)go$Tz zwd}kcEm0}jM5pFqk`df|917+Cc>{`K-Z98p)2s-jy*C)zE^?9&r_|z*%)dpn@7oS_ zylKE=izmzoH{CoEL4FCebXcu z0Izd?Pk2JeS8Hw(gPa2TrWX17s1%s%i{NjjKD80w7gxtmja(Z~H2Ky|M3aD+%*rXz zn*0La4@roIvPKzYEdqkpIMKE^m#iDM;@OMu=S>(P+H;*z#v4~*dm2-FE;rlL*wG$0 z*S{(0fI5cSa5!CjFN-#y^!1i`KHA3FY*QC}n#Vf?;BfqB>04<}MyjFDOak6B5RFWA>rMzCf!v+7b#D13fKD z32x@kw8&f2JB!#Vn9OrH%uK!(9%^z&_#51&%2!ikDrke5KnpuU6Q7#t-1hl;V=&0s z;QHf&1X6+e(g~v4ElMPjuTO4=EjAka1w9kV8u1A0+OD>@^CZy~OqP_R6(oAIx)vZ0 z8Lp@z?(H%PRXc>yc^m9 zWI7G`-;H99LNCx7VXmNyXNO68N->IpaS7;tdJQZXI!b!_d+?@ZF>PGYgYVxXTXAfq z@nG|Nyk5j8!SX<<-Vq!5NH8=$ocIDFuq{@Nqosc_kx%^0x>H^D9`u{AIqVP{m33w^KRb72?~ zJ_OS+WS1=`FJK#$`hNsM6Syr|3D=B(L`Fco{?@lt{+4H)LiT@tv^S%Gg`uLB&Yn&C z(cZI@KM>fh^}zCfwBzYZ1{;3ViGVZ!(`S8auler32=2O1jKTI_ zL0t`}u5PNu>j=7DN7s#sq|o?Kd@jOW>aVrc!c^U<9xb(hzCJDaKd@Zc1Kahwr(mL7 zS$i@6Gxv z@Ta14v_vFDBxdD%qh=Q40tq#nWK?QM?&>S`AlCwg91zPXjE|3>H!n9 za3f(!djr8ScJCvosMEt@&o}1@{v@>g!iC0AzK(@s$S!e4#m*VCE7{S^my-SyZKkSs zMd2u^qob+l<72pJe_vz375jO;`tfQy9VqHrlH#i)JlDZ09amiK^2pG_@@clomWrtO z=~IG_vs4H|MW%@gc!$aj%Jekt-Y*pdih?s9))=Q!N*$1z{e@Pnm=#6f;5ULLu!*ohy&i*I;~to8E;(9<@#z5eE0amA$rk?YFDI4&llKGe=&$^d2MahTu0fW~ zk1@0y+|<^H4@HzB`n zqW#U0c|}pXfv0s5ZP8uq7W2b==XB0kXMDM<7C&k#9M*+Khy!K-9ZJNs=QtIH{&TYRpOID(#^6t=?yhgAwj zWQmZ-@h$i^uoqwH2}h}OpY6AGt{rx6@LGWRsOTI@2A*|A=diV&RlHyTpMh@?w6VY> zx$i4~lU|xE3^wMOADjU|?EURZv`zMF@UxR2(`O-h0nverx4y1oC&>9&5P2}9;sd-| z&Se`iwn@ehLpM2T=<6c^sUOzW_dgjg^wY!5_&i{AWrFsvl9fio97Z z2cx1C2M>2jv>rEmP_Wk{kCSqMM^={NJ1fc5%FMc8V7J}`TjL2f@kAa!bnpI80Vu?8H$XpMFnoRmy%X%P1QsvXv(gt7lwHHyX?kEBU>f1s_UWU!wQq?;eH$F9a)wQe% zFNI$`Mp^!CP>O`Rv9mWadV5{ZTL|$A=r^Rj9>b~Ni`xYQ{nSm)&%4_j_N&X-SQ{%MSr_AXYK55x4m0)f zzC9(N*7D-X%w$H}Q+TO1kG3_i`VLU|#5AWT@qiC`l}Y5iC_FU=)2d)%ekGE(M55?S zd!BUU+-jJKnz%z+So$D4iM42Nx2Jye7@I<G;7TdT)6Zfn?UUYKawQtJFOUf zLDITlZG%Pv){84Zo06ZuFNGNGD1cQ&3VUx>&-=(@Cz^;#?sFBIr-#8a zW%z!jsD@VDnP}<+6s@}sKBQQYugT471D$4~z9-_FjBFsUidd`u36o$&S1BTj*3dB+ zz2)awn0aK%{Twu=xezo19}mNkyxvq~+$Dpt9$+UKEo?%?sYx6NpMgW2uM}5A;i@Z2 zoxDtc^^9RNzE6|G<&YIVE=~+szbM10%2^`IKY2p_*@2Hi{<+pE|6EVrs4V|< zk1nnT`KKv5^3TQYfYR?Str6moViSjsn&Oa9o2j!CCYVVDa?!eCbbB3(Llf^|aVU<& zp=Zii9O6yO+lp8mQVdCmU^Wr^#R5qZxHYh!5wRSv(I5|twJjWY^zlWfb`a|a*Z zYpHx%>wjI@nI{k6cwMZ(acUUy#OYV^^nCV8d;gk0UFWy)D;S?z(XbUzXtLL zu?@>#u?@&yu}=9b)-Hchb5uU#8N*e2r&@~jz)nDvPX?KK2bf_AD35jRB*GHZaQ~G- zN`Hznh@O6n6AhmB-mI*85<{ z5jN(Orq%lrRbRC#m9+GLDVojmP`hud@uln zzAxd5oRk1nLvSbt%|uQk@Z*?IeRw`8^Ja`VP-x4p4 z6}(alCNWZlVG-d>TSJpSc%6u4Y|xCuG;rRm9SY4jI{r}YnabmqB<6O!H){pI=P<`5 z3$aiyhV3$q5QxSgYZ!!Lbgf$OL_2R*0fH1xP}E{7$S2QfY3Wr_)?QTFlWY@-XTe@A zV%Zl~^FMY6gOrK*ZWp7M_UHja8%XdFKC0CU!d!kGOvs5m zA%~H}v)78!#QF66bwXXFXhL|sP_n-sZN5Ii(`{!R`8=muRVXG1ooW^C$3x%rmx1{F zZ#ZXUsQv9>)P?kn=R$%OI9*{3A)qf|9{a8dX6#9_dT#`_zB|rPe310lNs=&%OMzW_ zGiXLYHS1R>cwf#^gr{!TC&J80?1E*%*ZRhst9fY)e2?`Nwg&kr6;=#m{@)4nKd>Ik zIClq^Atn~-!I!=rX^SeS8Wkajw;)jhjx zISrOizRPVh(%|Q`ylxsrcI)fKOZ}bdTCp)|_)wo7O`k^_5It)g5JD=X3>SteX+aKit4Ms?yk@qG1jEo>m@s zQy-QW#$CC1`?m^uggSbNmgwuw@JJ@|B)nVC7=!&{?wrVqaVC6lx$%K=t~N+ajdp?0 zM>o_XPk{)}1yMqzdgFMm>NELsVGoCSS=hf@#7G9HZ*@|b391}S}%%ocL1W_H`|nmp4HE)Mnc zrq;_;eJ;N2MLrL4u1ZuF?f{rwO&w%{t*tV4$KM%Y^8>IvkU3RBMy(iFC}x%@Mi2iB zlUrQN&Gg(ypH%e}n-eXXFYPI{-CJxD#ZGwRW>9?nVf(OKV7kqh(t?(^a_!alm zik%dr@K#3QchxU^j#0R!6!(6dsOG0A@m1@;1y=ovjqPr$V-;{A>2A@YxE!Onv~vGw zO!!fD7m#^}+6MCZ+(W(}K6ygarHD%z?yyC~R)*%n`2M_LuDT3W1?Ec^olh^iB!~T- zlzhkLx4Wb_kqAD0pQ+^ylI8IU&b;f)*Vek;LLaB#QxpgRV_o>{59+|#J0&5XhOV`g z^wi)HJ5|?AGr8Sb8glptw-%+fJnfBl1xl@03DQ))*pK4ozGO-m!t6?mD zTxzOu(8xEp5p0_ZC#(DJbpwp;N9L-W+}rGmb5%xx+uzql9vEK>o1%(!{$^IA$6{~Qc!-RXPk@5 zudi9wiat5;U{N2e0;5&%@D$#H^Q1Sx=i8WLIQw*MP+#}Aphkn)A5_BvTlDD)+V6sw zw%;A${w9XdXFSNck<3c4mq{y~z5*RzV|>Q{lkj+1WJ7Cx*|0E4U)|dv-XXM#ABqrD z|AFH|P&B!-Cz83`m`LPuk40KsZbgKHJ5M=9-1#-5uY$~WmA*ACq#XoyA>^E7<`3s zpGg7yWb$psX;)GD*e6|*{>&H`S5WUPt3P`RKYD{Qb$!SkE|wKh$qxKi@fD<68J?cJ zqRxg*3V(+wei@kw2nCi6pjRm9L9sGWI-0WH$p0Ih-%X=vd?$sB?>J3v9?t7xjJ_Y! zqRX{mOk^i;=*QWO+B8IXXoj_Y5UC&5(Hgt!X0-Zs_GWFPi)-|IhF~LwO9+T(*m~2z zwfIYBdE*@6N&3LGZgYu(G(EOEw+6D_YYhLo8 z!Ba`2_Q{VMpT2plmL_%{*V@{sb#n>T%GK(z53!R3NhizkxCu=@ibasLGp~_wuXyTV z<`Pj{*f`#v)0XTtIy$Z~wsR^{o_gjrP}n$$~8 zu1im0v9D4x=IlKLI47osx!%7kF{>R$#{7nlLE)bExy~{J%$WV~ zj0FAxWR@NjIzjNEB>|VF;jOIjC!RbzxScTFLu`bJc>s3QiHaiyO=mRNRQ<7Tk|hb9 z8$v_;vhnTKBTUre{%N%uCcX$=t$rAUS?rYIa#|PK0Cdlu!{9HWEl6xI=I~}M&|EVd zVZXa1k@jjs6{t9;0#)I~v-xXXRNgPOqQUupz@l|%h-9vh1@N}gczfQ@-6`N{bs14m zWLJ=XZo+N5=LXv*=OQk7ruf#7*DVt0JIJtP63ISAa;BIzc3~4m7?<7V6o+45JsW3u zy;;WopLTV&145tl2`h8{(4f#3(5$C#Eezu&0p$M+j)oGiug>R2Dq`|fF#cBwU_J3L z;A{0@3t##0_7&spmpbDspYin!;p@9wnbH&>Lz5pJ3^N`!#E-7|nkLj;skRBFgifew zkDEK^4e}%Lfj$u`(!-7hgZ}B~g2BLFO0e8NAM};9t#sU--f^tR)3T$+pnvFuf516j z;XY#}5l6W?@er%mPVa-`R`HgA`yHVvh~sA?}i51aRmeluttBT zEBaFg8{E%+f#qFJ@WH0LND`HS(jQJ?N>Ag#>BRQ75E*9nqfGE1y%ys%;u7{iYg&oc z=-RKfB&em*W`!hxjtfUdZ3WLhTE#plLZ;WBc}unhMG->C-YW(R<&Nr3Lhe{W51Q|% z2j?Vl`dv{4SKxv+dGVFHPbsd*h6kFw7Va@re*Gb@_*L*~iWrO@fupvRXwoL+L!7B@F)J5l=k1b=Cktq1PX@T%`(0lwD6owiW8x5tOyR-Wg z@`1x=I|(uQqmy{QhwoWTPOK*;_YDgblfO8CJPr!H8oiEOos(H6+up0S7Ih_FG?$n z{jA%jYkR6E&i=0Mst81k-k+uZopb|&0pZ5c-8{i|?i z7{;g>A(ge)_npEAymFGOd=wV0pE@t#Kw_zu3_7`tHjFnPhqdciEnDI6ldH?nqW-~& zph(tv)2+xDq7#HLbUhjD$g?=Q{`}q|(m2G2uBK_jK)D=aw8DR+mKpbQTp{1N1?I@X z3(ouqaf--?&#^OKAEb=ObPi=yr9KWm3ha zvWPtA>~+XcAJ}9t8P%}XKMS;^w>E6JYB*VZ^^G^d06$b$&%eeoUR`*+VyrPAT^?$p z4C729{PL=giR+&I(-!|pDWV1xbGu@lV@0j*xat2Ta>*w*J|$-U)cw4I#D*?n9Z&Hh z=IIX$Sld&)fO&d`EMAo-Ll>`_le~DH#^*ly?USO4{Rco8-ppsF#Ngor>)`E-llEmM zuu>n94(P>*_t5#1i1P;q__1qwfFt!;gIxv}!}iw&#Q_ruP(WaV)4pzef1UaLf{^cT zH^2X_OGDpx65k(AFuq^^03H4N`*k8<>S&tCAFVIO63QL)@TxU`t@Sas!C6S>YWA(f zai^U<-n&!_XyiEcxb^@KBad}<*^*zx5En3Ld|Jb&gVSTyUzY3?pDbAtLcKh9Lx^aQ zlZXb{=Q?JOLEoUFLx95|63esLK5aQZgn8UbKlu_7ciTSB80hNxwhU7>a|tTqJ!h!; zw*aN5yi9K=%y*i6)4g^?Va-*=ShFPXV1vqP_OIR z<2@C7W$#NK^hLR3UxwHS%5Y4r@8n8yyx4epEJ$u>XsAXBWez%L6RV^g4Zf7KZ*gXF z71K086UQ`D0?);|O2OzLPB-QM~P7KL5|1hS!+EN_mofej&(PKa%m!DbG+- z$;E4WK&%kwcGDio(*XxPUY=$um!7@=aIXWv6wLDPAm^Vn+xv2SF72a&uQV#k`@WV} zp@3ii3%mS~b2qA9duzG9m+&X|$?J}Y@>6%?miGMtwoS}ljWC)$6_2}Qk>sEmbM6lB z%@iMNx)DqOKJ&y?_DF~)2fC~h^)!*HG1iI+{Q;VSJ5%4nuO@$Wq?5Tb)#`|a9NL*W z^gSWxf?qVg%O0`A9q=1ugh$Zm+mZoMhwE(lG{)IP4<%JwdQc+PNWWI(`R{yZhQPC2 z%2P65Ov&)DhNk2anv!Jkp^w;(U4VToh(j8jL=8T5hmAI4t>;Y@rp-i54<5xCp47>< z^9vO9DVTH5z?|zY=3Mt-_=|IHB+R*-JhqZQNX$TZ+u9v)^C#gZ8nRM~MA9fyj(IEX zQ#ld|(C~UbW!9W%XU$}|wXx7hT^h~n%INo|5dk2$F6h*-NU-Fj3 z26@RiGx0{}H_cNFV(1hD^)8m3o=(CQ6wL*qe4fd(56O{A5GruN*`EYsb^z8og^jm(=iN1eNq2%%OS&)25Xcv=yxjUdxNP5l)k8 z6PJDRsx!`UdZEw|Qmc9hj6L9FXo#C-CT{$d4u^4cW;W?nlh6IuNh$)}G&rsBx=VSK zf+{-xJ7uKEI2JCF)0f@OLuSir@RL-J z>R96YOhRXY?up*4p0VUC;KK)Mso4YZ0jir%fp!>ApQ=e0Ct*)E>i=zw^a(U`eJOk9 z2^Q3o1)R+ZqKyr#D2OT-p$arnP4T_KnF!;A4*>bo;ivw=LY%sdcpjGXim{wsY#2b7 zuKZQ#(%s0;$mz3uDX)qa`o^H$4B2Ww;FLXiWp4w`<*3D`R_m-GHP+`bPJP)uqk>5W zSNv;!6)XGPZJ>cCbjQ}Pw*v3syGve{h`i7J;t;&%bhHGorvPB@FBcKKe$FDnYwa%% z!E5H%BwH*L&-L%O3qv(k>}g4REx%sPhjqC~V8knlt^%9%fzW@-)=*C#JM_=`bhw>3 zYghljSxOEZ6kX{5B_Q$VZuO8@dYpzC#f=aX%5MjaeSnYYLGxV)jeUT(@PXZwGU;Hb zDP`qBHl-{%NT!rQMjKxIDg=$hrSI@ou4m4GVk3+BvbmcgJk*xiTK@6 zy1yw(odd1`0A)a$zY37*)AxL)Z#=_kdLI$6m~*5S^Ot4t8jV8(XrBC-x~;fU!uRVo zNfJp%Li^eJdZn3Z+GtP~QA=S@^0V9}*S-mTszCC_5S)Z~m zs&9>nkPMMMB>xVGjywgD@j8Q(nQW0bnF$~_@3Jg)HI9#JwBc4{g6I<8=_p+e*`q5ezLZVnf zaKyin4Xw#a8;R@l-{cPx4UK|)f@#5ypXGEQ_~{7~7^c?BWkEsIjoc-2I5C8;H0L+V z@SEXudT(VsTC30QRf-S7K<^cMAVZ^+q)HLggXV7QVAd#Q_yY5!mKeSKo-k`Fi*;;l946f-?ro1P#U4dPoZjBJzcC@Zm80lTD|$&_M_sA5_(F@F8jfR+fS| zvqsH0Oje)pjltwJ<5*#e{li?ulQ2oRx`a}pi{WS_*;w$iD_98PJzYhcvm_D=Te1>= zfCAAuV#0pG4$KI_82r?I3(H%^r?i(=CcdYi;$vjM2AOB!AKUE(TUrQa%FzsmN z5`n#F154L$bb|3#ps%?ZS0FpPfzkdJ?2&BgM`^(W#wYOUD%UGHL3 zJsbs^Xim55Sj8G@KZ;aFnz(J09UhkS45g?RS%bS|Ck=HJXCPIg$R(5jNbTD2F1|HC z6b|K8*-_#bDUL1UJR_F~IwuTNQB){FsugS=7>u=vWn5da1%0U0ByZNJ<|No&MFcbh zA8RXiHYa9DzuKGlx40(TJ&QKPeDX7UEwaed0~KO3R-4O!@slTNOQ{4_0gyc(YDNQ?=y&p)Te3C+MKDCl#&rSgazFC5{+x)@B4Qyj4+e8n71)MFaP;z;O@W z8P!fvQU3Yf-ZuBfS~l;&D%Fl!jY^aUW=ZdWXmwzf+9=@5^%Y?gtSH)R1MGE?$a|+8 zh&#iAK}p*sVB-B>vTfi^G+AoK0K8}nfHfBWC(*K5jT^8DZGrAys2~6CpucuZe~H2r zI~`jf1UWv2OYR9hPUG#%BRoF)_SkW7S2_1I)kKur_b>i5%K8+?L5$iaW7KZasUY$Z zev?Nns~L^j!$d6dmOVHaU+!TW-UfoEF%%&?Jb;=QT~MOxn$qXga+Qd}YSgUJypp#I zX?@=f%ydHgUJ?<+gqkQ+J}Ux3*ejMe=xfx}m$9zGk-$T#o@Ig}mvP@XuT+*H!c2G} zRR8MJ#x7RHJH@K(3`tmHI6xS)N9Fpahmz2*y4iG$oWNrMfFlhjO0rQKQsc+MEi~0X z5GkpVpVPyqJpP?Qv$&|eq%*z6Fz9r2)jj|X^>49}k%NBf2rHytZP;x`Z2ISpX)Ady zK5b*nY1_5QrKau2yF;d}yNNMv-`tIqvT!#~+c~?fX)6`tw7o8*ZTaQaw0(59ecI0c zZ1>>oB1@wC-HxdKr1yI~MUV}6J|Es7O%I`+FJY&>p|orn_llWwieZG&v%Xz*iU z4IB+_d@p%8tEj1#2~~#oLj#AL_Cn*luj}r#Nt?F=s2=fXkZu3^`PLUd@2io16uMZc z??IT~F8+SaKfHgff%m?WgmM&KDJ54l3Lr&CF}yLYT=A_>$cHO^XII3}tOOnH;&NmY z@-!-pQi?VrV5PPclT#u?p(K?cNRo%BAuM|CaAwvuWw1smSn#VGAZyY8APg zm;OP5_T+?uv~qpLt>g(h4|jxVPvv&<0GYQ?GTW0(PnIntjJ)9`l0=!SmHqk9N&GMv zW_}JD2LV$SJn>}oB=$h55}tv^_q5Sdg%%3D^HFL6lwaUcYBoNCiwsFzWE&R>Ug(2+ zyUb1^?dN$XCp-jAxmDQPhLJQeyR)l-5p|c)UcO^g^@3#FW<1W% z4Sti(w(!Bm`n+zzVBl*_{ttie8H}RHIo5Yv~3LHtNxhj6kz+`?Tc2H7COhlNpLa_aFUqQWgqd6-7Dc|rsU)laNKp?X0= z0X1`00_ErQiThBQx*d663UW2c7RO$j$BQGN^FeJMnvn6bAJnoVoN8$-YMDcyfQlz- zTPS{C6t$LJtkxk3`T1-;H|1qcO0me0~1X^4o+bLw&2hIK`z2 zBSBNcoQMksyhxcDju8@$7bz$Cspkk>PZ8HY!SyrZ`dh;m35&&cH#BQfupxQC*DIl# znR$3K37I+BKxUD8tVO=+N|DGE1q3?lv!;?nXXv?K_^>ISEdUdKDO?ntpy{O!)@>Td= zjda5g3;~)cFg-(@P~L%U`m%{$H z#X;2H?_se4bMeQiBcrOi(6YswZTg-$xw!x(_B0V3*-;r zwk!FNQgKYQ`XV1znu~{(wwFjW>Px_7ct~m5w@6TlkqF9}zmB+l#Ih*A5|!Ns!F}Z1 zltUq_k?!IPFkCqm2cvRbn|K@IP!yihTdq`9#nacvIqYv2gMW^rJ9>Yt;yQp^0K;6sP7Hr;Fy zjh4?@EZn8jdCX$SGO)EV4hDB-f55gAMQI=+2M0wpgr%qLMdWI| zjkBb@S?mxb+g~U zH8M#G=zLCXXQK0)9UHm4Z3*8h7?BaHFYIDZ{Mh3L-nvslvsbuFUXqMEv~jFA-)Uv| zx9As~yFe1<_-LPq|LBYCA!94flBLAVeex+>=3v1q-jJcFO>y1Z$}_I;a(KJjd{U*4R=Hw}t;&ZTRnFbQRlY>)u@_6k ze>|ekkqOKm(zn+{rnZDb^BRcCJ1~#wLP7uc3p^}|T;ersR5L!c{GgM%h=E|Z(o)gt$&sIVX!VeEvSj2oo(ej5e+CeI&Ceysr(nvnb+PhsY6`xYMdo?(`CKr(VdN zifd?|yiUMH#GT5W+zIBy&tec#x$K8Ywq3e}o>ua9YjHL3obLFd;!qUu9P^Y_qZj^L z!pP7Xk1SW=f|^_(APpp=&GA&<5ygiYek-}g4{-rtE{Du*7%;ae z>^5+@!Wd+zz~$aNPn~>{R{sGKTR?;5X7^@Mh68P6BAM*lM~Pz`)5s&0Oz5ATU|T#- z;kTNJ30>8boX!EbRj^#}k6Gn4wB6HHaD*pAx2@^GP3<9T+d9g&n)MESS=F1U+Z0H& zj|eij0~G7Yw*$F7wgY$+ItC3tZt|$}_yzMQL`WW&X9bAS*HbpY*K5xu6MF^02#Y0S z!tQvs-Dj9a)1r+i5L8xWQw|j;k0>KDnG+g%iDA`%v@O@*J7@y>E(K;9Y46Y(d+0`- z4;$jy?;%dn=8AMgy*8pnpwC9O9o>##FtM2IJy)S_X-iBW!g!#NBe=_Q-ce4RJz#YDzJfXtn+K z?`ngAKh*HR9(`UqADwO3aK8M`W*5u$KXn#rn2>H@sWsj{&bN~P*E5vi(83EQO;EoR zB8Y$f8EWLPGlZV*@S`WEi_p(k+B<`{R^1080L#1n+y4gGg%Kbu@Bi!K`MV~J3zgrW zWB^;@LsUEa5J0ZhGtrwBcLuQ{3l|X}njwF87M}QvuXC}GUe9G??QTHUF6e#Wzj`#b zX=3nV`w=3)9dGWyyL4g4qHTh)Asncb&odYsB5t`$v*;PDp( zC$P6}HVY(9KOwshQC0VNddh1K;D)M!f0-s}x}I1Xjvmch>`3Fw#b(Z#_;>OP+BO=>&k%zj=t> zo*(BV(!G6yL2Ib!FhSH0Iyf^Xt?Vm=Xa8ngixvf4l7CF?CFpZPZ-viWnz5ek^Lp(& zn?_l%S5?~&)tI&gwy zxBU^Q)$QP$9T8|(zVc);8muNn5>aW9S3(6^N;CMIq-!aS={L9qIMq~!Ktb7uiPbgv z@TZ+5QU>LNd=;z7Kk!v6-Sr^h>C2~_u{u!&LE#~R-Dvt4fpvM=HYjwE`!A0(7}Lw4 z5d^mWB^wy(ANnT(jE8tVgKe7V9O731Og}!9-nQvxYtmKt_V2rbWHL;Y7|Dn&DsRl& zwZXJ+L4wgf2DE2xm;wlvC*n08hLEd8j)&{q%nk11XGsL7^AHrRh#UsAlo5biGMS)& z?#;^klki^4MmcO3W+>c)uxK%eypAiGJRir|Xu{I})QSm#O9?v9ydH1c&bS%de-pG{ zm(F3G#tBa)ceXothc`K6IC^5znGDWP0z5Es_B!4%4auze%sLchpIgVG z?0BlQf-QV)tix|mHVmTg0C7h4))J}7VywfX-DYaC(}2~$w`Sre^wt6yCys43XVw}$ zBQLj@U`Rq{hi}x@skSa*ar(PCMmvzrQmBS!2KO=^&68*d6h}~oxo2*JPl~Hu?$VE# z_8vYi27cw+Jn+DGM8Y{>@cOa`sMdaCozrU7qjqk+nwQ+Kd`^z|{G-GXd2#nK)N3B+ zba@n@^e?z7{bZbj(`{BnZ~VP#xfdlp(O2(gx(j!gfZ&biYr0DlY7K7AM(0F-3wn}L ze2iyC$!Q9JPkGL`Kg9Qy#{Dk7AAMZhSMvRG@&46v|5}vwUr8dt6tS*%JP(}r)cFSd zMgJm0!%;6{^HXW%>=W$>ub7YIQ)%s^`+AGpR82mAoY>;j7TE1^-q+@k{+KGIq`CAp zA{=d;a72m|Xsi^6O3G0(Uoen79)F6POWNw)fiz+w0+~jx(U+2-+a8ZC4 z@XOS#p>dsr&ck8+7=7^IX+lv=Oh-wY5QWe13ZLP?ew2!PLbr1trroT`+t!E_Df`&c z+j0#rBkZH}-k^N|XX;PjJ!4RjVvq#^@vAOS7K-46*4$JH#JuBXEaCB$Z)`L@9dp8@0iz$fglJ>cgADjBpU^bzZro2=SSuI-1&AW8F`>b2K2n=2zykuqa4QLJ>V9mS zf%quFMQ{j){9G3_U*xlt$1^!YlYb5*^ET{YwEoIF;T8+d8@WHbhntRWvTAa_aC2?Y zDk@Kt-wP?Hx2z?WmGI3W_%gvCf!<~9f(8gTr@((R%VoE& z7HC+tfHoXEt+t2^?PL1ZYIA%FF^N}`)%KaNyxN!vzx;tSfkJu@i{aDdw?KFQ{Q_0= z&4*UOhEFq*-QLT{r+Jm}k^Uw%WRVTNT+C{PT~7|bO%T(JFV4)T`zITy0S8~7z%|@M z@AoQ^RGi_#W@8@6CH!>yW2?V`CI0yj`)TeOZ?V3Vjg}Y16o}H!Xeql612&FNNrP%L zK*Fr#yW* zkFvV#exW5j%VGPYyCkA63NJy zHLk)36-^Q5)F+%>LEi|g8=f5Qf~Wh%4|+C)d{1MgYBOF2H)ttkhp1_@KvfB5mw6JR zD$~jX`{Doh`u2G0;$tUWoGv(Ye|abGFJHs^%d|`-cN9CqFgt)f%W=Oa^Nvwt-0#I3 zpPaZtu$8x7=Y;_PQ%?VuOuQorP>^!?H#38(ma-3Tl5~(ya@OrnU-SL+pW5}zIqT0+ zcji=7w@@l-yX7S5Xjz-2$+hp3ve#de5AhZ7^<#XMtI1V-rI^op=|}G&-r4str*+`; zAp0u*_do)hTH!QdeT87d<=(#v8Tl&)+%(-O=KgyStr`6Z>OTxMt<(n91fix-apX@8 zVAB{Zf3;2Cy&S>r=fZLcY7j#`Vy_bS-t<&a7;kRe$Y9M%Y+!W0eiH%Ki@=%zn0`NC z#k-z(Jg|x1CDg6knrJL}&p=~SfksV^7Kqp9-%Zs#TI58);(S}1-?^Wlc1(9F*^~3_ zZJx?tXN#R}9*}Qu^FRiRDRCN%uFtn2J&mDmEpX}{R; zBj^)`L=X3y^Yn%&$>Dr(A8zbcXemAD!^u?!-YBd+Yq=nG50ZM(Mw}yfWJBM7cQSZS z6LJJw$yT!$7t&7|`Vm6=Q2isv*W;eX+Sn*uf@nQ89v|^UE7~$c7c0Pb!;E)+e7Dqi zH%wbnE|Gm!(UxrFt6mxePgAK)@Hib92}bd6$D*~G{3 zHSRS_Fq2kx*_ecuA=;^X&GNs+ix&EGxikvz-ESKOia?)!zkTFO`V-i{9 z%3%NUI=j?zK#+3iwk!jv&3y^#p(##&bgVx^wLqwa3^j796RN5|BYPNCx%EB*`}R@i zJX;80dd;1TqcS41Vv+s_C(>CKV^19rthDH*TJ)pSnlF4Ctx#LszO^Jp$z^zt+uXTY zWXaoT?kaZ|ZzQD!Gs?D9v^zl-nvO2GPb9f+w4p0dL33ucy6+C^`R03_6!7Z3 zj8@)Nc#Wlyd!Bb<|A~8T3)nb@S~uCr#qPM*wzS^KP^Tw5#ew$s+Nddkq29UA*|3^C zZW!mMsO8ms^K(x2u{)0n>q=1HGnDrkC)5g281wX%47P5VlXzwVnEq>@AZ|4z`ai%u z=>C0}Z{;~*2P5p7K2&=m3YH!8M21x#a>Cw#u+KAWD;yynAN_1^TjSe8tMn0~a!r12 zZ?Y8JhPf#^VmrR-O=V}<+Z={v?*ats*BfoFIco)*y=V(O%SUygtThSI?GJ+xz5cID z?Z0G*G$|>q|BX{)X*^qE&Ms!Xy0{#4%qUF`E@s0vKG)|RMvwlDzq_QshxPOi^3N_l znuv;-M)1XSx@wi-0gD^ETI5fQaf`+KeX>+s8+4a!g*S80)~c0I$zDw^hqsxPQyOWJ zYZmk7PovB&Q^V9PSzZ8~8o3sKG9F`-I+Hc7oDI*qP zcSmB($Bm1OK}^KcNqlnqMKp z1SylyVs2{mAd6CSULzCDG@sdQ!FwK0m^Vxdc>ZExJ7)=npBwui|7B}Ju{c;L)i?ra z2ybHu4!>Kntp?BjjvU^D3pEC>q8IRV96_}*XEXmJq~Vf0^r0aAFP?xN?@_(~G;QGz0sd@`+hM-wB^eRfttDsHU4n!p~g zlM~|67qFrTK0mE2*FH+<1<#ZAd~+Py7*|y1h3B4RpqqpDIkzPrydfAg%L8ChW?FgX ziShTSyIhs(H?9gsYYy$v;qmG@zNLuZURuSSzA>953d-@p*LCixujpnu$fApUohc>B)3cEqN3(@D6I(v%ugj*|b1h z22g+^xzQWM06tzI8gaa=HYhOUGBBh{fsX*@6|)FXLt+BU^lvYtRcqU2!e$9UHsc79^80dx*6{YtVi1a}Duw8j*F{g(^o z{EE`%5r3{MY-z4)n=!bFCuc=NlblFUB}QUQ@PQ_M^}=Lo-J z*?yj3?m7u{?zN*+IcS%kLjl{{h3BgQuovJw4;q+^UnFf)fBq(r^mB0#x{f+NED8OM zt$B@iijAI%6ia9kt%^u^6g&G?t1!t~;cKF0?2s<@eQXH2D_$~B?k$XWd|jGoLqF}E zQzUdRG;n|vdM%LxPNf@Q_Q8bnW)0qf+#VLoW>5p3Lx>}qQOQyUdLK4>zcv^+q=pB! z8|6NTR&@ZD4B(=m7cSj1U#Gw?b#g*NW;Lua+g!9-WvgGhHWdA8RP8RQB6?g-^!S6I z#{p6=wbE7DOWjP1F*eq2#;DEjZpStcR@9b3QQOlmha$prlS$5~+iY{y z5IMhf+GU*r*<8b|*&*b+l~L*c!ID}78@T)E!Vvvltr&8sh=v{77nrGr`!S3Jer~j3 zd>2Z)x9$g8EUaxPU!Hr$Ap3l0$;xUu5O(2#Ja}m*m^926KVB3{4^yO(y z276xLaW5nmSR#wHd16>nD?ucLAu!e>cI>C~>KweFuSDk$=o*aS|#ZK zg;mu`o`}A_2#{^7bJ^v{kL71`yyn0tTE+6{$H-fzRO-|A0{*^q;?FQ-I@1baju`wI z{zMcp@yd(Ai_9kU9&wA?>=9E&Yx31!;*PUx>M%|2^)J-Gdca>-AXurT{IxY1bdD)~ z93e=Y87}mA+^gyxkK2fJqe{vFgL=eKzNh+&k46FeC24Nq2@+wWtn5tn=;e8GIh~9{ zgvo7yT&A_a;jaZ0AswKC3PKi=(Tss%$eC}*_SSmGw}7ELpc(<029T@4kJTD{<(?6P zbpgUWDw`}h50`>V(IYq0(Fz|Z}-nsPr%($p*P zH%6LvnTcAI$t&v@T>pvwKm<+Be*BZmKfU?qr`<3?2ic`c2feKndperNY@&FC&7L@#>Ut3CiZ0rIFto00stZ~X zQXRbv!^1i%!y0G_jk?}}TN1}Vt;5;-4Cf^#@4!M^6m35dTHOdyU35d$b?53DY)m*c zCcJ^h&^YU_g;6VB;GZ)7DdL~DyI>4^*EK93i1S3o@p3fDI2Vk9)bZCRcW!hA>oTY2 zaqf>O&Op=Cg?cEiHXc}yR5~hcZ~KSdIQq}rUM>KyeX)trM0U1MeR{+JxsKCuqM#K`3YQSx5Rw3*4f#Wl1--YKqA z^$GuBT;%aCjF$2~zH$YW%+nLE=5-m$vZ3=M<5bLXm3oeg#-#`SsEzz|y0mHPV?xOjd?lPYc;E&a{v{Yo>|pye|mZ>loR?XA-hOZ^t-cq&`jVhApZj zd~3~Lo(`?5M5oGz5bs&wKzz%YCgNjenuu2}g7}S}BjVdyi05|9!c-Ry)Q@@tP`^*_ za6zDc*$g}CbK$K&9Z|pdD?q*P;`UR*f7furf4ou^ITc14w=LjuG?IZt>}*WA*u(63 z(uMa!9QV17`>u}rWN{A|xw71t6;-_`20+rU`psn;H{2!5*yTA#b@~~6e4l zw~7w0>rfAB6+%@-uJ}Uq!zX|6g<1K6FX~mk=#Z`Q(nPNOt1@S?4{+s!x$;i#(t{*( z$@lRCm%H?97k%1Y)TSryFkH0pb;)vmy?Cy3gHpPZ_S%{lt^5?5g<3TaW&7UaMta-;MpP_Ikg^BV`GV-2Y<7{sp zmp900P`1^ekOG!-0crILaB~5%W`j_alfsP#9sISS26=|UCx8FfSyp8mD(kDyL}ONe zWj4kv6+Xr-tF`q$p3x>~oQxUxg#0i49q`W%m@fX2ynDZ4hLaNV;443RT>3HVt$!3+ zf4XjkS@!OQi^a1(6-o0eAIeC_*Y1Jkr`?wWm!iMPaC-_bvgvOIRz>!lwEbnkuHb(X z{O<(+JJXZ)^!FP0-$D5_ZO6d7ZbeT-RU~uza^7udXisMbSlon6EwM#4nW@O;wnor> zdQnZLMju%HYF4+o~&x;Oe^9E9{HbMs*QXUB`M5Zve!nxc#S+hq0*7coOw# z9bZK29(#?YK8huif9~lludk@Fs0P2JN;lL4O2kS#topHzO?|j0miog;1 z#E>MSuP-kIEp8aWZ5VAY9+9MPZN8C0zi<~FHCQKLVrMDI?;=~ zv&O~d?Idr_Nq6Znao367{VeV})7>{NrkHG{Djdh}lskqdP7FwokGZekQrPZUY^+x1 zbjq09@}j_F%bczyV_M?mM|)sZcwJ~M8MY65*ZZ(b%Zmah)&p)NYDxW!D6#Wt{1A8o ze3)u|=bh>7%8nMnV8gJF&UDtXxCPgd{8^o|j%4e*uJyhf6%BR z&jL;XaeAt=F{|*iBs}B%-AZ7}Pdnnze7zFp@MiJ79E7GL$BCS|Hd$icCnu)ciX<1r zt0Z>VjxlF)EM8F@PCjo`U|V|qI<+xWQGT`JXY*!Z6WVf#` zEsNhN>X)o*=5fWQix>)guZm>l{i$>{wO;9;zl^1?7v5j9MAM8qW?_^dI;_p4m^5{> zqMo;#m)$cz!RKgVuC|+)4Tr)03FA;xWB0SOxh&FBN_@=LQ(SkMyYya?l`vw98jOZj zU&kRHUp691vc{s+!z*|G<4)4J zzm7LhV-U-+*z#dkH&6>NJ|`94R28{rcoIq-k~i!6)hLi(?#=2z7nt)C>7`PW*8oiM zHkT^D4;O(yFxekrp!i&5VNZ5_pbdnSdvCXQllkkfoVs z5|o3wO*h<2f+5Oa!^GG0@-jv11G>vt((F^QQ|$Cv!l6(}$@zg$vldWu)J7x)uWwm-*R>b0n47)=D02LFmoT=`;6?NqM|@xfliwJe zIxBXH>jK;P@Z%_zkivW4{gG4B7-#Ns&*UBu3*ClMzoU=EionPM<2;XXe3T;;@6F2i z0B3x6I+A1!TF<#%r3FD2juaC+%;YVOpKs!+c;h6YvSY@fk9}GZXuPI?59?r7kE`AVf0na`C-J zbFXuy(>|8Y{&dC>7nJjsI3oW^f9Sq|ub!ELv3apWA^C;nB?1XGb_iB zRD5G($;{=3Sd7uPG^!2awr;AeRy-vvZ7VSKs44MK^^|t-XM94AFV0og61}}EjzlTJ z3Vc8LAU2JH$;kgwSC0@sn9e`#V9NSI=?ONBFGv6TvOO$b9J5L!aDOcDW;$c&h`Zz) z$qeEvC1fDw6rYzo6Nr+$S#?oNs`m$ql zjYBl_%QPm`)W9B93T(>t^@y=@UY&eiyc9>SL3M!zYFJMd_b98L{}@FDepFq7ZS2a~6~PN)shnhQ)+#FJGDUT9qp28kP0@#&MI3}8c2X$d z=|T*ERg>_~$S5Y(`Rf4xubF1BQ2LJx$$y3ViA%qe=Wk4xmJz9vBW>%8A_009oGd8|nfM)soa$GShRDA7y@} zJ|G1l(i4zmhA9>P@SL@Gbk80?W!jaIin=A|>_K5e{bs*X5ooN8++Rb)W28s$rM!)? z2^EJLQTo9#w%B8q6sr2rjdyZF0Vbr>3cA5#$i% zPyz9HF=&RIM)$`Bz4hGsNSvNq{f{(7utlX`cYxqWU0BvrZtpOi z{CSWm9DcY(LypC(aNXV!y015LbtK)7F>xbIczc=FzoLF+S$DkCm#6fz_+znxVU|z@ z=V=xE4$En5V2k8s(uge;l*R6^O7Z=PCMfH2gi;EAr+vGbmSW6>pnd*S``np6|E=pW zWK&R2tYA`VYkkE1YL}6JK9f`e`Op79Q+wm17A>!8I9%4C%e;S_-WB7Ey zyPk_Krxv@h#jV{iC9(m)3s+wXmJdEEDoMj>7x;=Hv4@cC)4uO(A|zin>5*Keqvp?V z2uwErM`))r!K7h&Myu%=ntbcU^hm=RT{i!5-JE$t_xCK_-`B!iTKW;2ODh_pV( zMdEi|IcU9JL2->31_|CvSiS8&4FH-Z`+}R$LwwUlT`(y^(@mLy57ny}#sFM86tUiW zNT0Jo-?)&UXbxKkzIq+GY@mJ}xRkF0jP&AIoe}FG`3fYhM1VOsfVXq6>XhY>ET=bqS6X{OFh3-#fG;Aq>k0HJ1;!u@+ z%Ce5V23012xD7lVE^FTwG(Rs68t3PUS)!8GToR~5KVT$%{~z|3Uo#2%5<0uJLT0bjd)lL?u0x?t z)$IizCU+HWg9$pd3xfT3sL@3{0>J8+pobq4LEU(%4hk2y9t=u-m{7g(x-qE)?BS52 zKmC2ym7&2X`O4hH9}?Yfl7i}7MwREZ!|DaG5Bm)_!REfohTdWIpwE)K7v$YaccAYB zU}QR!3p@wm?ttPvRz)JDUjAzjD3_FxE|Ee9yh&d&d92k|jTqo|g0`5S4m30FwFv zsU3B@Ow#3&V;9B>z>F8sPmG37AqRz1FpYW0@}c}BV$*&l&&_2Io}2N%+#-7-e% z=bD<^Fa4DGB@;t}yrpbytWs~?VTMDP#RJ)R#~?|#8(w!xV&{ItHT0kl%kLe+>OgG) z7py5%_@`BnAt#7cU^RAb{`orpjO=x690HK4OpM2jG2A>>znuYFRl2jt%Nv9BUWxF05tK);Yf3vExq zBVC4zZTg7XLtOFWcR0r|>(qhQG~O=ks2v?+>lL0bQE%Ff3=&ux?k|A_8%Pno|4UnQ z5L~h$MVm5=+go$-QfU7pkDk<1|@{{D^#7JHFVnrws3uD-1a z)_|;&hAiJg*gS--A_CiEVb~gM2=+`bBen^EZH*-=wpT0~HXC8ZR)@eK+5CvOm2%DX-z0(S-Q7<=Q`=Fy9n}e`@*3*b>E@1n)Ra9&%T4~rEgw09V z?vKFc3d8oX6~RVEV7maY6-CE3IE0OJ$)*IX=GzEt+iiMm!wK7u4kNbr7?_$69ott4 z8n$%8b{k>4A;XC6?l5fMbwIEOBCurvw&xR~V!I`TEt9YvjmK&%5q&#p)nm&iY~~1T z-!L$>cXVv~<27t9!d6b$dZ!z)%?rbJme%K|dl<3Z3D{Q0N5wWNgiRuBoe104ml?5j z3&S>_uw5L1?KtbSdP8(== zGDk%yg%B>#5cVa6@jZ+P`-dTXt2KgM6M?WDAiOU+Lflp)gwJaTzc67s#M0w&x>e-@dc1iCAD7YNbGl4r1U9ob(7iCE;>+c6d&37RsvgeG2 zZv-e*19YTVQa;8jIyO?#Kk&nuIICwj{N+vTfXD0(!pW<$dY85GWq1ucr2s8!&@)2N zW%VbyCl$6-A1=P z-IxitM|s=7|0G&hQwKpX#dvWR$P0gk+f>E`{U>V zd4Ht3M`7SVg7`lJH`tL)Xk-1pi65mY03b&7Lc2!sd##l@@HSZOhcssD7gS`0C}IWq zk>KBqK}1Ll9V>Q>Css6LI94qG6$7q^WNt>Q-L_JwS1xSc8s;}Z$9ec2%h)@($cnQ4 z)AYHH%j(6Tw#3uKwkb)kc`=uDaXYoUzbVLTWmC!OxrBm;e{qGT6RJES2xJo4YX#^d zWq-_2zdB2seg!C66+GnyK}g$42@7;K3f<4x2eorOmC6ZUQeM}@+5wt6@hsg7m&^B_ z`5oTQ09%mou5W;a?a>?ppgW~8?8_M_9;hxogKa(UUY+j_!pPO-OfOQ~a`NTU0dBk@ zT!f9OQ>o}Xos11DhN4^9*V^I9m!YfWGD+U0Ee;eQ5L*izFfrY_@?}UON>PF_VejN! zK=#KoP-ZORv1*JW_xNc7=jf-CwPKs5V$hTd`}n^0G3qLyRX;x2u3r2zykRs|lFnCn zQud3n5uxq<5D~2vt;4@@VR9V7@X8=80ix%Ni!kEcQhpFGtf-ISsbX{_)?jC=?2kH1 zfQ_^je?)0q{`LhP9@14RS z{8pc+4g{9^F;lA4_NUQ{g*@4Dvl%jRaEKO=|iP3=~Ew&>8mS_#9V~ewK-5 zmG`4-S~qa>|6ssZ5zc~+Mz*;IaK6C4qE8$28PaZ2nnb2ctCALfb*jnps~J4`&zO|> zlg?DrHr4+vX+C#AAm8`3DC4%CL^KE58?~?RnMS3{v#5UGgn;{P#`b)`0M*veo@1mn zje$qIWc3-i!?zisr|phwLeF0dch?P}R_%F~DNQ?t(geX#Y}5vE+2qo~wImAHYKRY| ziz(`^Ne)=dP>Q)XqiZq6r$wM3ormFt=@856f~Z%F91aQkAXv=~_$LLkBD!U(TfWZXIqR4P@eDaoQ#$O_Ts4m^ z{C|+LydE0KbM<+XUcLZRK&-!_xAx^t_#&)QJVBwaMY&9v1w}=|IxV`NM|$%66`9JJ zVbp?(deEEq7bA6Un}KGhzGlxEb5U1N$RLyyau8590`*2_VFMUtj0+V|Pp`p+^iO=4 zTA;6W&K|Uc4@vjv@2gD5t8zd7h1BMBEfBHt9Xdz1;YFP$3`dXEOMc|A$`agqZDf`- zowHa%mULq)YvsEDnYgxz=^twa`17<=>zD>7r?%D@ui@PCLs-2Grrm(vCfrfWHCQy6 z!lH38sJB11Q%zpJx2xO3y!ztCAnk3!wkK0_aoZElpSZq7x_$N~9-qKYz@DzUff3Sw z9c=S9wxQ4yaakOyr_a#~bTgFKn{1Hr(F2%rL^l~3@GEOwiaPc%DpPMH7%!%~^AuSU z7&N8sIDuf3TN!n(s~MR33{}$9PWKg0+$`G5arzfGL2CEsnc7R11DMPHeC$PAYvrRD zW+ZySKCcYxmf2eImZ6^&3r(PEi3*D!3hPzHA#Bj*cw?`WllopY{*7SICK!8lHv?1G zQY9%7y{g?Kdi51VJe~Sd{KR|#VYHui!2e(9=`;X*d_L19Tepx;2%R{dLk=c5Qsix( z13mDlxrCPVO7`cDU*#j#l}Y`|`w|hK1a>`ZvOYS`jM@Dd>sq~V6hz)yt;S27f{oeQ)yvR809|llQJjRB< zO<2ed2A6ungz51uFcNNgBd)*M&NHR`Mmaa0YjdixIfJ7$=c{GS zH|O?dn{zid2a)rmNa^&U&y5i2H9FbGXc#(z#FpB8_+9|xJOks3)FEun`zJTG5bt80 zv!7Tj2dbI@RTZ>wxQs3AGohQgFHkpK&=ILKb@SkRp>Dbi-JE`5bKRV|nYxK*v&cTp z)9llHvQI&IkYpdkH9?Gv>I8%!DI_`*gkk*r1_ha)p_MDdIjui%Jg359{zSK?^UvA+>1diVCBz{`pw|_QQe08lq!!s^*Ab#0 z-iMjT+2oCPL-flv(C@0G=IEF8wV)qs#v`m5Jy0FHgyHjcDR>xU)k18(TRRcDf|~DH zm+!+AIh!QsajVydCyf6DwJ?IWr$M7Hiq_~OOPg=>qlwKmdfq0QYMTI?^}`=|{L%*c zxn9aLm4QxTh9+g5j)hdVxJ$u!z~gHrRR?0(!u9kcePIbLHvuS$89X^=T?5&?)2^6} z$6tn7J-5)OmrYFFHDOwyYDOjK+HnjSw646Pt5kjv1|1h28HpsWrER={;wmltR9l?R z;|zbLlUL`;|IxYOba*F8<{gseY)Rcg?&+I9F#|WzMZSW`Fl2Ed=Pxlp75V`x1qa|D z9+rFAC^}P>16A9gUa2fAwFCk~#c|xk=nZ^k1(VTbaC;3TK6a{BPXTHoqsiSpLo(L@ zicHK^F@R2iQAy<%4JUk8E~Io8f&ZyPKEXBZYJ9-plm|>WoqV(Lq=Pr@iHC8FVCgTs zENpz9nMvaVfo7qx!GvL||6{E8=a02|eI^G?IG^=VxOy+Ut_ps;%~euxLpJ+=&#|Dp zXO+Jfd@DZ#ZJ61ev$njO%~PwFsnFt6>96AQ+3LVG08(8aLy&=Q)easeDR$R4uYV=e zdX}EC5g8q`q@ZQ!^v}$rjBiXn4uj*~n`yfYEK{cX7tp!g7MMkBOJYT z<&2VRjnT&u^volB4wB&Y8rqwwT3`=(8X4UN$Asvn#FB_`?y^?4CA(@gzq1e3Ej)2? z`OOq{YXjy@0b7-B)NZ4{xC+BJQ@$a{6v_JO*z|irc?H1ihHfE1^eYFq2tZ}5gREZw z%pa($5%fg$I|0aM7)r0g|47O-n^gTU<^(*eIA; zc%$cx%j&rrpy-@ArH#SrrhUZcaw0#VIbt$d6e$$;%)O5oW=R3>*!2fKG#aRBTSPe= zHe|XgWa3nafoB9^wtaB@y)u~ixzy+4F0fNde_kLdynZXU+@rWKK`2$cu(?zn@EJl_s9`(^LrrXeqAWu zJzo3rHhh^6ffGTMg@5C?!N~WaQ}T~`-- zor{cKd|KwtLnilDkA06LT7s96jD^77@yc|Qg6XY4W0;?)HI_*)v;;qO?p&dJ-}8e zkOk?S3z;+@D|welOb`yYuB>JzdR*bq?CSk-Zu5G6TeTg=-T-0`2eDxa1vEAnyoUsn z@xfMr*V%M|WASR&QZpUXiJ;d*L@!dctt&wTzyOZ1$oNY+VsIZY&b@}c6v&k+CXz@- zp!33j&=m%=uk-;

r?k+zvQz3C`BZfPOKN^X>t-smTW5D~l_R!waPiV|G<(|Tka zg(vwar0&vHIQ>J0JUEpjzdf1wE!0&Qg0LP$AA)cY!w@+55Ty9j_V3~lB;Z3f;}C$4 zOZ|H(emK08KKNe+W}f{p8<+c=qQ_%}^RqYUYSD?^4$|0CGB%ch27-xVa0&VW`TPSt zyI4I{Cf$IH;9L2Z@eMgUsJ!#s$zA7x;=UHH?S-0wO}pZpq}|DFP=8Ueq3*)lM7?z* zOr}WOg;$2YquT~FGf1Mb8`}M-6vQZryQc7dRWr^YMy^|e#Hw0CF)x9+>i_tk{v;sg zbq_`1XYcUj(-gn<1Lc==^I9PaAfC(dv;=a1J33jEy zj0|p4mf;^g10J3qv(r)C+Km39CqwYq-#<@~rSDQ!(@WfnkokoO=~DH)qj z_Ix{LER_eze3}&#`g>XoM1-+1>>;1df=N+wzDDbLdXwUlOPkLL7H@sFeiIQ%1x{1Tm3{RwnTh?-=wcZIhrjW!;7Bb4D?o9 zft7ujqF^_~keT<8lZ*SeG@lA2y?R%}DaAgmyR&wvF)aAs3|^(~wy&(q_{w@B_|IvUj@e!T_1ip4MRLo)6>Jdsbj z`H79_0qg-6t`6pRwj&pU%&8S%7x!ok4c%yF3;0<*%0A6h^GU%?nyE(V5b<6vjvmRDo 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
    ?3 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

    $v^eG2rW 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%0A#i%J6j_WJ%9Qq5b10rre|G=`nFW`* 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

    )EshGHP{9(Kb?KD9gP2UL2$Y{zUSe_vBux- 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 N^ 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

    6@v^oFxaECK`2UKG?dWi#G#Lkd2AD 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 z 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

    $1IzPCKcq?0p(I5+cg+ro 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

    |rwwbfQ*Y_DrjuQu_K9~a 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 QE5Avk65=_J5=bon3$==k6#xJL literal 0 HcmV?d00001 diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/lz4.go b/vendor/src/github.com/pierrec/lz4/fuzz/lz4.go new file mode 100644 index 00000000..4b228a14 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/lz4.go @@ -0,0 +1,45 @@ +package lz4 + +import ( + "bytes" + "io/ioutil" + + "github.com/pierrec/lz4" +) + +// lz4.Reader fuzz function +func Fuzz(data []byte) int { + // uncompress some data + d, err := ioutil.ReadAll(lz4.NewReader(bytes.NewReader(data))) + if err != nil { + return 0 + } + + // got valid compressed data + // compress the uncompressed data + // and compare with the original input + buf := bytes.NewBuffer(nil) + zw := lz4.NewWriter(buf) + n, err := zw.Write(d) + if err != nil { + panic(err) + } + if n != len(d) { + panic("short write") + } + err = zw.Close() + if err != nil { + panic(err) + } + + // uncompress the newly compressed data + ud, err := ioutil.ReadAll(lz4.NewReader(buf)) + if err != nil { + panic(err) + } + if bytes.Compare(d, ud) != 0 { + panic("not equal") + } + + return 1 +} diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/suppressions/a596442269a13f32d85889a173f2d36187a768c6 b/vendor/src/github.com/pierrec/lz4/fuzz/suppressions/a596442269a13f32d85889a173f2d36187a768c6 new file mode 100644 index 00000000..1f191523 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/suppressions/a596442269a13f32d85889a173f2d36187a768c6 @@ -0,0 +1 @@ +SIGABRT: abort diff --git a/vendor/src/github.com/pierrec/lz4/fuzz/suppressions/d159e91cdd6fcbee9e37460f96c597b70c590886 b/vendor/src/github.com/pierrec/lz4/fuzz/suppressions/d159e91cdd6fcbee9e37460f96c597b70c590886 new file mode 100644 index 00000000..381c311e --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/fuzz/suppressions/d159e91cdd6fcbee9e37460f96c597b70c590886 @@ -0,0 +1,10 @@ +panic: runtime error: slice bounds out of range [recovered] +io/ioutil.readAll.func1 +github.com/pierrec/lz4.(*Reader).readBlock +github.com/pierrec/lz4.(*Reader).Read +bytes.(*Buffer).ReadFrom +io/ioutil.readAll +io/ioutil.ReadAll +github.com/pierrec/lz4/fuzz.Fuzz +github.com/dvyukov/go-fuzz/go-fuzz-dep.Main +main.main diff --git a/vendor/src/github.com/pierrec/lz4/lz4.go b/vendor/src/github.com/pierrec/lz4/lz4.go new file mode 100644 index 00000000..46389243 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/lz4.go @@ -0,0 +1,118 @@ +// Package lz4 implements reading and writing lz4 compressed data (a frame), +// as specified in http://fastcompression.blogspot.fr/2013/04/lz4-streaming-format-final.html, +// using an io.Reader (decompression) and io.Writer (compression). +// It is designed to minimize memory usage while maximizing throughput by being able to +// [de]compress data concurrently. +// +// The Reader and the Writer support concurrent processing provided the supplied buffers are +// large enough (in multiples of BlockMaxSize) and there is no block dependency. +// Reader.WriteTo and Writer.ReadFrom do leverage the concurrency transparently. +// The runtime.GOMAXPROCS() value is used to apply concurrency or not. +// +// Although the block level compression and decompression functions are exposed and are fully compatible +// with the lz4 block format definition, they are low level and should not be used directly. +// For a complete description of an lz4 compressed block, see: +// http://fastcompression.blogspot.fr/2011/05/lz4-explained.html +// +// See https://github.com/Cyan4973/lz4 for the reference C implementation. +package lz4 + +import ( + "hash" + "sync" + "unsafe" + + "github.com/pierrec/xxHash/xxHash32" +) + +const ( + // Extension is the LZ4 frame file name extension + Extension = ".lz4" + // Version is the LZ4 frame format version + Version = 1 + + frameMagic = uint32(0x184D2204) + frameSkipMagic = uint32(0x184D2A50) + + // The following constants are used to setup the compression algorithm. + minMatch = 4 // the minimum size of the match sequence size (4 bytes) + winSizeLog = 16 // LZ4 64Kb window size limit + winSize = 1 << winSizeLog + winMask = winSize - 1 // 64Kb window of previous data for dependent blocks + + // hashLog determines the size of the hash table used to quickly find a previous match position. + // Its value influences the compression speed and memory usage, the lower the faster, + // but at the expense of the compression ratio. + // 16 seems to be the best compromise. + hashLog = 16 + hashTableSize = 1 << hashLog + hashShift = uint((minMatch * 8) - hashLog) + + mfLimit = 8 + minMatch // The last match cannot start within the last 12 bytes. + skipStrength = 6 // variable step for fast scan + + hasher = uint32(2654435761) // prime number used to hash minMatch +) + +// map the block max size id with its value in bytes: 64Kb, 256Kb, 1Mb and 4Mb. +var bsMapID = map[byte]int{4: 64 << 10, 5: 256 << 10, 6: 1 << 20, 7: 4 << 20} +var bsMapValue = map[int]byte{} + +// Reversed. +func init() { + for i, v := range bsMapID { + bsMapValue[v] = i + } +} + +var isLittleEndian = getIsLittleEndian() + +func getIsLittleEndian() (ret bool) { + var i int = 0x1 + bs := (*[1]byte)(unsafe.Pointer(&i)) + if bs[0] == 0 { + return false + } + + return true +} + +// Header describes the various flags that can be set on a Writer or obtained from a Reader. +// The default values match those of the LZ4 frame format definition (http://fastcompression.blogspot.com/2013/04/lz4-streaming-format-final.html). +// +// NB. in a Reader, in case of concatenated frames, the Header values may change between Read() calls. +// It is the caller responsibility to check them if necessary (typically when using the Reader concurrency). +type Header struct { + BlockDependency bool // compressed blocks are dependent (one block depends on the last 64Kb of the previous one) + BlockChecksum bool // compressed blocks are checksumed + NoChecksum bool // frame checksum + BlockMaxSize int // the size of the decompressed data block (one of [64KB, 256KB, 1MB, 4MB]). Default=4MB. + Size uint64 // the frame total size. It is _not_ computed by the Writer. + HighCompression bool // use high compression (only for the Writer) + done bool // whether the descriptor was processed (Read or Write and checked) + // Removed as not supported + // Dict bool // a dictionary id is to be used + // DictID uint32 // the dictionary id read from the frame, if any. +} + +// xxhPool wraps the standard pool for xxHash items. +// Putting items back in the pool automatically resets them. +type xxhPool struct { + sync.Pool +} + +func (p *xxhPool) Get() hash.Hash32 { + return p.Pool.Get().(hash.Hash32) +} + +func (p *xxhPool) Put(h hash.Hash32) { + h.Reset() + p.Pool.Put(h) +} + +// hashPool is used by readers and writers and contains xxHash items. +var hashPool = xxhPool{ + Pool: sync.Pool{ + New: func() interface{} { return xxHash32.New(0) }, + }, +} diff --git a/vendor/src/github.com/pierrec/lz4/lz4_test.go b/vendor/src/github.com/pierrec/lz4/lz4_test.go new file mode 100644 index 00000000..2eb5b6bc --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/lz4_test.go @@ -0,0 +1,646 @@ +package lz4_test + +import ( + "bytes" + "crypto/rand" + "encoding/binary" + "fmt" + "io" + "io/ioutil" + "math/big" + "reflect" + "testing" + + "github.com/pierrec/lz4" +) + +// testBuffer wraps bytes.Buffer to remove the WriteTo() and ReadFrom() methods. +type testBuffer struct { + buf *bytes.Buffer +} + +func (b *testBuffer) Read(buf []byte) (int, error) { + return b.buf.Read(buf) +} + +func (b *testBuffer) Write(buf []byte) (int, error) { + return b.buf.Write(buf) +} + +func (b *testBuffer) Len() int { + return b.buf.Len() +} + +func (b *testBuffer) Bytes() []byte { + return b.buf.Bytes() +} + +// testData represents a test data item. It is really used to provide a human readable label to a slice of bytes. +type testData struct { + label string + data []byte +} + +// testHeader represents a test data item. It is really used to provide a human readable label to an LZ4 header. +type testHeader struct { + label string + header lz4.Header +} + +// compareHeaders... compares 2 lz4 headers. +func compareHeaders(h, hh lz4.Header, t *testing.T) { + ok := true + if h.BlockDependency != hh.BlockDependency { + t.Errorf("BlockDependency: expected %v, got %v", h.BlockDependency, hh.BlockDependency) + ok = false + } + if h.BlockChecksum != hh.BlockChecksum { + t.Errorf("BlockChecksum: expected %v, got %v", h.BlockChecksum, hh.BlockChecksum) + ok = false + } + if h.NoChecksum != hh.NoChecksum { + t.Errorf("NoChecksum: expected %v, got %v", h.NoChecksum, hh.NoChecksum) + ok = false + } + if h.BlockMaxSize != hh.BlockMaxSize { + t.Errorf("BlockMaxSize: expected %d, got %d", h.BlockMaxSize, hh.BlockMaxSize) + ok = false + } + if h.Size != hh.Size { + t.Errorf("Size: expected %d, got %d", h.Size, hh.Size) + ok = false + } + // if h.Dict != hh.Dict { + // t.Errorf("Dict: expected %d, got %d", h.Dict, hh.Dict) + // ok = false + // } + // if h.DictID != hh.DictID { + // t.Errorf("DictID: expected %d, got %d", h.DictID, hh.DictID) + // ok = false + // } + if !ok { + t.FailNow() + } +} + +var ( + lorem = []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") + // Initial data items used for testing. More are added with random and other kind of data. + testDataItems = []testData{ + {"empty", nil}, + { + "small pattern", + []byte("aaaaaaaaaaaaaaaaaaa"), + }, + { + "small pattern long", + []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + }, + { + "medium pattern", + []byte("abcdefghijklmnopqabcdefghijklmnopq"), + }, + { + "lorem", + lorem, + }, + } + testHeaderItems = []testHeader{} +) + +// Build the list of all possible headers with the default values + the ones defined in the map. +func buildHeaders(options map[string][]interface{}) []testHeader { + testHeaderItems := make([]testHeader, 1) + for fieldName, fieldData := range options { + for _, o := range fieldData { + for _, d := range testHeaderItems { + s := reflect.ValueOf(&d.header).Elem() + t := s.Type() + for i := 0; i < s.NumField(); i++ { + if t.Field(i).Name == fieldName { + switch f := s.Field(i); f.Kind() { + case reflect.Bool: + f.SetBool(o.(bool)) + case reflect.Int: + f.SetInt(int64(o.(int))) + case reflect.Int64: + switch o.(type) { + case int: + f.SetInt(int64(o.(int))) + default: + f.SetInt(o.(int64)) + } + case reflect.Uint32: + switch o.(type) { + case int: + f.SetUint(uint64(o.(int))) + default: + f.SetUint(uint64(o.(uint32))) + } + case reflect.Uint64: + switch o.(type) { + case int: + f.SetUint(uint64(o.(int))) + default: + f.SetUint(o.(uint64)) + } + default: + panic(fmt.Sprintf("unsupported type: %v", f.Kind())) + } + d.label = fmt.Sprintf("%+v", d.header) + testHeaderItems = append(testHeaderItems, d) + break + } + } + } + } + } + + for i, n := 0, len(testHeaderItems); i < n; { + testHeaderItem := testHeaderItems[i] + // remove the 0 BlockMaxSize value as it is invalid and we have provisioned all possible values already. + if testHeaderItem.header.BlockMaxSize == 0 { + n-- + testHeaderItems[i], testHeaderItems = testHeaderItems[n], testHeaderItems[:n] + } else { + testHeaderItem.label = fmt.Sprintf("%+v", testHeaderItem) + i++ + } + } + + return testHeaderItems +} + +// Generate all possible LZ4 headers. +func init() { + // Only set the relevant headers having an impact on the comrpession. + seed := map[string][]interface{}{ + "BlockDependency": {true}, + "BlockChecksum": {true}, + "NoChecksum": {true}, + // "Dict": {true}, + // Enabling this substantially increase the testing time. + // As this test is not really required it is disabled. + // "HighCompression": {true}, + } + for _, bms := range lz4.BlockMaxSizeItems { + seed["BlockMaxSize"] = append(seed["BlockMaxSize"], bms) + } + testHeaderItems = buildHeaders(seed) +} + +// Initialize the test data with various sizes of uncompressible and compressible data. +func init() { + maxSize := 10 << 20 // > max block max size of 4Mb + + // repeated data with very high compression ratio + repeat := make([]byte, maxSize) + for i := copy(repeat, lorem); i < len(repeat); { + i += copy(repeat[i:], repeat[:i]) + } + + // repeated data with small compression ratio + repeatlow := make([]byte, maxSize) + for i := 0; i < len(repeatlow); { + i += copy(repeatlow[i:], lorem) + // randomly skip some bytes to make sure the pattern does not repeat too much + n, _ := rand.Int(rand.Reader, big.NewInt(int64(10))) + i += int(n.Int64()) + } + + // random data: low to no compression + random := make([]byte, maxSize) + if _, err := rand.Read(random); err != nil { + panic(fmt.Sprintf("cannot initialize random data for size %d", maxSize)) + } + + // generate some test data with various sizes and kind of data: all valid block max sizes + others + for _, size := range lz4.BlockMaxSizeItems { + testDataItems = append( + testDataItems, + testData{fmt.Sprintf("random %d", size), random[:size]}, + testData{fmt.Sprintf("random < %d", size), random[:size/3]}, + testData{fmt.Sprintf("repeated %d", size), repeat[:size]}, + testData{fmt.Sprintf("repeated < %d", size), repeat[:size/3]}, + ) + } +} + +// Test low levels core functions: +// a. compress and compare with supplied data if any +// b. decompress the previous data and compare it with the original one +func TestBlock(t *testing.T) { + for _, compress := range []func([]byte, []byte, int) (int, error){ + lz4.CompressBlock, + lz4.CompressBlockHC, + } { + for _, item := range testDataItems { + data := item.data + z := make([]byte, lz4.CompressBlockBound(len(data))) + n, err := compress(data, z, 0) + if n == 0 { // not compressible + continue + } + if err != nil { + t.Errorf("CompressBlock: %s", err) + t.FailNow() + } + z = z[:n] + d := make([]byte, len(data)) + n, err = lz4.UncompressBlock(z, d, 0) + if err != nil { + t.Errorf("UncompressBlock: %s", err) + t.FailNow() + } + d = d[:n] + if !bytes.Equal(d, data) { + t.Errorf("invalid decompressed data: %s: %s", item.label, string(d)) + t.FailNow() + } + } + } +} + +func BenchmarkUncompressBlock(b *testing.B) { + d := make([]byte, len(lorem)) + z := make([]byte, len(lorem)) + n, err := lz4.CompressBlock(lorem, z, 0) + if err != nil { + b.Errorf("CompressBlock: %s", err) + b.FailNow() + } + z = z[:n] + for i := 0; i < b.N; i++ { + lz4.UncompressBlock(z, d, 0) + } +} + +func BenchmarkCompressBlock(b *testing.B) { + d := append([]byte{}, lorem...) + z := make([]byte, len(lorem)) + n, err := lz4.CompressBlock(d, z, 0) + if err != nil { + b.Errorf("CompressBlock: %s", err) + b.FailNow() + } + z = z[:n] + for i := 0; i < b.N; i++ { + d = append([]byte{}, lorem...) + lz4.CompressBlock(d, z, 0) + } +} + +func BenchmarkCompressBlockHC(b *testing.B) { + d := append([]byte{}, lorem...) + z := make([]byte, len(lorem)) + n, err := lz4.CompressBlockHC(d, z, 0) + if err != nil { + b.Errorf("CompressBlock: %s", err) + b.FailNow() + } + z = z[:n] + for i := 0; i < b.N; i++ { + d = append([]byte{}, lorem...) + lz4.CompressBlockHC(d, z, 0) + } +} +func BenchmarkCompressEndToEnd(b *testing.B) { + w := lz4.NewWriter(ioutil.Discard) + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := w.Write(lorem); err != nil { + b.Fatal(err) + } + } +} + +// TestNoWrite compresses without any call to Write() (empty frame). +// It does so checking all possible headers. +func TestNoWrite(t *testing.T) { + // that is 2*2*2*2*2*2^4 = 512 headers! + seed := map[string][]interface{}{ + "BlockDependency": {true}, + "BlockChecksum": {true}, + "NoChecksum": {true}, + "Size": {999}, + // "Dict": {true}, + // Enabling this substantially increase the testing time. + // As this test is not really required it is disabled. + // "HighCompression": {true}, + } + for _, bms := range lz4.BlockMaxSizeItems { + seed["BlockMaxSize"] = append(seed["BlockMaxSize"], bms) + } + testHeaderItems := buildHeaders(seed) + + for _, h := range testHeaderItems { + rw := bytes.NewBuffer(nil) + + w := lz4.NewWriter(rw) + w.Header = h.header + if err := w.Close(); err != nil { + t.Errorf("Close(): unexpected error: %v", err) + t.FailNow() + } + + r := lz4.NewReader(rw) + n, err := r.Read(nil) + if err != nil { + t.Errorf("Read(): unexpected error: %v", err) + t.FailNow() + } + if n != 0 { + t.Errorf("expected 0 bytes read, got %d", n) + t.FailNow() + } + + buf := make([]byte, 16) + n, err = r.Read(buf) + if err != nil && err != io.EOF { + t.Errorf("Read(): unexpected error: %v", err) + t.FailNow() + } + if n != 0 { + t.Errorf("expected 0 bytes read, got %d", n) + t.FailNow() + } + } +} + +// TestReset tests that the Reset() method resets the header on the Reader and Writer. +func TestReset(t *testing.T) { + h := lz4.Header{ + BlockDependency: true, + BlockChecksum: true, + NoChecksum: true, + BlockMaxSize: 123, + Size: 999, + // Dict: true, + // DictID: 555, + } + dh := lz4.Header{} + + w := lz4.NewWriter(nil) + w.Header = h + w.Reset(nil) + compareHeaders(w.Header, dh, t) + + r := lz4.NewReader(nil) + r.Header = h + r.Reset(nil) + compareHeaders(r.Header, dh, t) +} + +// TestFrame compresses and decompresses LZ4 streams with various input data and options. +func TestFrame(t *testing.T) { + for _, tdata := range testDataItems { + data := tdata.data + // test various options + for _, headerItem := range testHeaderItems { + tag := tdata.label + ": " + headerItem.label + rw := bytes.NewBuffer(nil) + + // Set all options to non default values and compress + w := lz4.NewWriter(rw) + w.Header = headerItem.header + + n, err := w.Write(data) + if err != nil { + t.Errorf("%s: Write(): unexpected error: %v", tag, err) + t.FailNow() + } + if n != len(data) { + t.Errorf("%s: Write(): expected %d bytes written, got %d", tag, len(data), n) + t.FailNow() + } + if err = w.Close(); err != nil { + t.Errorf("%s: Close(): unexpected error: %v", tag, err) + t.FailNow() + } + + // Decompress + r := lz4.NewReader(rw) + n, err = r.Read(nil) + if err != nil { + t.Errorf("%s: Read(): unexpected error: %v", tag, err) + t.FailNow() + } + if n != 0 { + t.Errorf("%s: Read(): expected 0 bytes read, got %d", tag, n) + } + + buf := make([]byte, len(data)) + n, err = r.Read(buf) + if err != nil && err != io.EOF { + t.Errorf("%s: Read(): unexpected error: %v", tag, err) + t.FailNow() + } + if n != len(data) { + t.Errorf("%s: Read(): expected %d bytes read, got %d", tag, len(data), n) + } + buf = buf[:n] + if !bytes.Equal(buf, data) { + t.Errorf("%s: decompress(compress(data)) != data (%d/%d)", tag, len(buf), len(data)) + t.FailNow() + } + + compareHeaders(w.Header, r.Header, t) + } + } +} + +// TestReadFromWriteTo tests the Reader.WriteTo() and Writer.ReadFrom() methods. +func TestReadFromWriteTo(t *testing.T) { + for _, tdata := range testDataItems { + data := tdata.data + + // test various options + for _, headerItem := range testHeaderItems { + tag := "ReadFromWriteTo: " + tdata.label + ": " + headerItem.label + dbuf := bytes.NewBuffer(data) + + zbuf := bytes.NewBuffer(nil) + w := lz4.NewWriter(zbuf) + w.Header = headerItem.header + if _, err := w.ReadFrom(dbuf); err != nil { + t.Errorf("%s: unexpected error: %s", tag, err) + t.FailNow() + } + + if err := w.Close(); err != nil { + t.Errorf("%s: unexpected error: %s", tag, err) + t.FailNow() + } + + buf := bytes.NewBuffer(nil) + r := lz4.NewReader(zbuf) + if _, err := r.WriteTo(buf); err != nil { + t.Errorf("%s: unexpected error: %s", tag, err) + t.FailNow() + } + + if !bytes.Equal(buf.Bytes(), data) { + t.Errorf("%s: decompress(compress(data)) != data (%d/%d)", tag, buf.Len(), len(data)) + t.FailNow() + } + } + } +} + +// TestCopy will use io.Copy and avoid using Reader.WriteTo() and Writer.ReadFrom(). +func TestCopy(t *testing.T) { + w := lz4.NewWriter(nil) + r := lz4.NewReader(nil) + for _, tdata := range testDataItems { + data := tdata.data + + // test various options + for _, headerItem := range testHeaderItems { + tag := "io.Copy: " + tdata.label + ": " + headerItem.label + dbuf := &testBuffer{bytes.NewBuffer(data)} + + zbuf := bytes.NewBuffer(nil) + w.Reset(zbuf) + w.Header = headerItem.header + if _, err := io.Copy(w, dbuf); err != nil { + t.Errorf("%s: unexpected error: %s", tag, err) + t.FailNow() + } + + if err := w.Close(); err != nil { + t.Errorf("%s: unexpected error: %s", tag, err) + t.FailNow() + } + + buf := &testBuffer{bytes.NewBuffer(nil)} + r.Reset(zbuf) + if _, err := io.Copy(buf, r); err != nil { + t.Errorf("%s: unexpected error: %s", tag, err) + t.FailNow() + } + + if !bytes.Equal(buf.Bytes(), data) { + t.Errorf("%s: decompress(compress(data)) != data (%d/%d)", tag, buf.Len(), len(data)) + t.FailNow() + } + } + } +} + +func TestSkippable(t *testing.T) { + w := lz4.NewWriter(nil) + r := lz4.NewReader(nil) + + skippable := make([]byte, 1<<20) + binary.LittleEndian.PutUint32(skippable, lz4.FrameSkipMagic) + binary.LittleEndian.PutUint32(skippable[4:], uint32(len(skippable)-8)) + + buf := make([]byte, len(lorem)) + + tag := "skippable first" + zbuf := bytes.NewBuffer(skippable) + w.Reset(zbuf) + w.Write(lorem) + w.Close() + + r.Reset(zbuf) + if _, err := r.Read(buf); err != nil { + t.Errorf("%s: unexpected error: %s", tag, err) + t.FailNow() + } + + tag = "skippable last" + zbuf = bytes.NewBuffer(nil) + w.Reset(zbuf) + w.Write(lorem) + w.Close() + zbuf.Write(skippable) + + r.Reset(zbuf) + if _, err := r.Read(buf); err != nil { + t.Errorf("%s: unexpected error: %s", tag, err) + t.FailNow() + } + + tag = "skippable middle" + zbuf = bytes.NewBuffer(nil) + w.Reset(zbuf) + w.Write(lorem) + zbuf.Write(skippable) + w.Write(lorem) + w.Close() + + r.Reset(zbuf) + if _, err := r.Read(buf); err != nil { + t.Errorf("%s: unexpected error: %s", tag, err) + t.FailNow() + } + +} + +func TestWrittenCountAfterBufferedWrite(t *testing.T) { + w := lz4.NewWriter(bytes.NewBuffer(nil)) + w.Header.BlockDependency = true + + if n, _ := w.Write([]byte{1}); n != 1 { + t.Errorf("expected to write 1 byte, wrote %d", n) + t.FailNow() + } + + forcesWrite := make([]byte, 1<<16) + + if n, _ := w.Write(forcesWrite); n != len(forcesWrite) { + t.Errorf("expected to write %d bytes, wrote %d", len(forcesWrite), n) + t.FailNow() + } +} + +func TestWrittenBlocksExactlyWindowSize(t *testing.T) { + input := make([]byte, 128*1024) + + copy(input[64*1024-1:], []byte{1, 2, 3, 4, 1, 2, 3, 4}) + + output := writeReadChunked(t, input, 64*1024) + + if !bytes.Equal(input, output) { + t.Errorf("output is not equal to source input") + t.FailNow() + } +} + +func TestWrittenBlocksLessThanWindowSize(t *testing.T) { + input := make([]byte, 80*1024) + + copy(input[64*1024-1:], []byte{1, 2, 3, 4, 1, 2, 3, 4}) + copy(input[72*1024-1:], []byte{5, 6, 7, 8, 5, 6, 7, 8}) + + output := writeReadChunked(t, input, 8*1024) + if !bytes.Equal(input, output) { + t.Errorf("output is not equal to source input") + t.FailNow() + } +} + +func writeReadChunked(t *testing.T, in []byte, chunkSize int) []byte { + compressed := bytes.NewBuffer(nil) + w := lz4.NewWriter(compressed) + w.Header.BlockDependency = true + + buf := bytes.NewBuffer(in) + for buf.Len() > 0 { + _, err := w.Write(buf.Next(chunkSize)) + if err != nil { + t.Errorf("unexpected error: %v", err) + t.FailNow() + } + } + + r := lz4.NewReader(compressed) + out := make([]byte, len(in)) + _, err := io.ReadFull(r, out) + if err != nil { + t.Errorf("unexpected error: %v", err) + t.FailNow() + } + return out +} diff --git a/vendor/src/github.com/pierrec/lz4/lz4c/main.go b/vendor/src/github.com/pierrec/lz4/lz4c/main.go new file mode 100644 index 00000000..048ab500 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/lz4c/main.go @@ -0,0 +1,108 @@ +// Command line utility for the lz4 package. +package main + +import ( + // "bytes" + + "flag" + "fmt" + "io" + "log" + "os" + "path" + "runtime" + "strings" + + "github.com/pierrec/lz4" +) + +func main() { + // Process command line arguments + var ( + blockMaxSizeDefault = 4 << 20 + flagStdout = flag.Bool("c", false, "output to stdout") + flagDecompress = flag.Bool("d", false, "decompress flag") + flagBlockMaxSize = flag.Int("B", blockMaxSizeDefault, "block max size [64Kb,256Kb,1Mb,4Mb]") + flagBlockDependency = flag.Bool("BD", false, "enable block dependency") + flagBlockChecksum = flag.Bool("BX", false, "enable block checksum") + flagStreamChecksum = flag.Bool("Sx", false, "disable stream checksum") + flagHighCompression = flag.Bool("9", false, "enabled high compression") + ) + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "Usage:\n\t%s [arg] [input]...\n\tNo input means [de]compress stdin to stdout\n\n", os.Args[0]) + flag.PrintDefaults() + } + flag.Parse() + + // Use all CPUs + runtime.GOMAXPROCS(runtime.NumCPU()) + + zr := lz4.NewReader(nil) + zw := lz4.NewWriter(nil) + zh := lz4.Header{ + BlockDependency: *flagBlockDependency, + BlockChecksum: *flagBlockChecksum, + BlockMaxSize: *flagBlockMaxSize, + NoChecksum: *flagStreamChecksum, + HighCompression: *flagHighCompression, + } + + worker := func(in io.Reader, out io.Writer) { + if *flagDecompress { + zr.Reset(in) + if _, err := io.Copy(out, zr); err != nil { + log.Fatalf("Error while decompressing input: %v", err) + } + } else { + zw.Reset(out) + zw.Header = zh + if _, err := io.Copy(zw, in); err != nil { + log.Fatalf("Error while compressing input: %v", err) + } + if err := zw.Close(); err != nil { + log.Fatalf("Error while closing stream: %v", err) + } + } + } + + // No input means [de]compress stdin to stdout + if len(flag.Args()) == 0 { + worker(os.Stdin, os.Stdout) + os.Exit(0) + } + + // Compress or decompress all input files + for _, inputFileName := range flag.Args() { + outputFileName := path.Clean(inputFileName) + + if !*flagStdout { + if *flagDecompress { + outputFileName = strings.TrimSuffix(outputFileName, lz4.Extension) + if outputFileName == inputFileName { + log.Fatalf("Invalid output file name: same as input: %s", inputFileName) + } + } else { + outputFileName += lz4.Extension + } + } + + inputFile, err := os.Open(inputFileName) + if err != nil { + log.Fatalf("Error while opening input: %v", err) + } + + outputFile := os.Stdout + if !*flagStdout { + outputFile, err = os.Create(outputFileName) + if err != nil { + log.Fatalf("Error while opening output: %v", err) + } + } + worker(inputFile, outputFile) + + inputFile.Close() + if !*flagStdout { + outputFile.Close() + } + } +} diff --git a/vendor/src/github.com/pierrec/lz4/reader.go b/vendor/src/github.com/pierrec/lz4/reader.go new file mode 100644 index 00000000..9f7fd604 --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/reader.go @@ -0,0 +1,364 @@ +package lz4 + +import ( + "encoding/binary" + "errors" + "fmt" + "hash" + "io" + "io/ioutil" + "runtime" + "sync" + "sync/atomic" +) + +// ErrInvalid is returned when the data being read is not an LZ4 archive +// (LZ4 magic number detection failed). +var ErrInvalid = errors.New("invalid lz4 data") + +// errEndOfBlock is returned by readBlock when it has reached the last block of the frame. +// It is not an error. +var errEndOfBlock = errors.New("end of block") + +// Reader implements the LZ4 frame decoder. +// The Header is set after the first call to Read(). +// The Header may change between Read() calls in case of concatenated frames. +type Reader struct { + Pos int64 // position within the source + Header + src io.Reader + checksum hash.Hash32 // frame hash + wg sync.WaitGroup // decompressing go routine wait group + data []byte // buffered decompressed data + window []byte // 64Kb decompressed data window +} + +// NewReader returns a new LZ4 frame decoder. +// No access to the underlying io.Reader is performed. +func NewReader(src io.Reader) *Reader { + return &Reader{ + src: src, + checksum: hashPool.Get(), + } +} + +// readHeader checks the frame magic number and parses the frame descriptoz. +// Skippable frames are supported even as a first frame although the LZ4 +// specifications recommends skippable frames not to be used as first frames. +func (z *Reader) readHeader(first bool) error { + defer z.checksum.Reset() + + for { + var magic uint32 + if err := binary.Read(z.src, binary.LittleEndian, &magic); err != nil { + if !first && err == io.ErrUnexpectedEOF { + return io.EOF + } + return err + } + z.Pos += 4 + if magic>>8 == frameSkipMagic>>8 { + var skipSize uint32 + if err := binary.Read(z.src, binary.LittleEndian, &skipSize); err != nil { + return err + } + z.Pos += 4 + m, err := io.CopyN(ioutil.Discard, z.src, int64(skipSize)) + z.Pos += m + if err != nil { + return err + } + continue + } + if magic != frameMagic { + return ErrInvalid + } + break + } + + // header + var buf [8]byte + if _, err := io.ReadFull(z.src, buf[:2]); err != nil { + return err + } + z.Pos += 2 + + b := buf[0] + if b>>6 != Version { + return fmt.Errorf("lz4.Read: invalid version: got %d expected %d", b>>6, Version) + } + z.BlockDependency = b>>5&1 == 0 + z.BlockChecksum = b>>4&1 > 0 + frameSize := b>>3&1 > 0 + z.NoChecksum = b>>2&1 == 0 + // z.Dict = b&1 > 0 + + bmsID := buf[1] >> 4 & 0x7 + bSize, ok := bsMapID[bmsID] + if !ok { + return fmt.Errorf("lz4.Read: invalid block max size: %d", bmsID) + } + z.BlockMaxSize = bSize + + z.checksum.Write(buf[0:2]) + + if frameSize { + if err := binary.Read(z.src, binary.LittleEndian, &z.Size); err != nil { + return err + } + z.Pos += 8 + binary.LittleEndian.PutUint64(buf[:], z.Size) + z.checksum.Write(buf[0:8]) + } + + // if z.Dict { + // if err := binary.Read(z.src, binary.LittleEndian, &z.DictID); err != nil { + // return err + // } + // z.Pos += 4 + // binary.LittleEndian.PutUint32(buf[:], z.DictID) + // z.checksum.Write(buf[0:4]) + // } + + // header checksum + if _, err := io.ReadFull(z.src, buf[:1]); err != nil { + return err + } + z.Pos++ + if h := byte(z.checksum.Sum32() >> 8 & 0xFF); h != buf[0] { + return fmt.Errorf("lz4.Read: invalid header checksum: got %v expected %v", buf[0], h) + } + + z.Header.done = true + + return nil +} + +// Read decompresses data from the underlying source into the supplied buffer. +// +// Since there can be multiple streams concatenated, Header values may +// change between calls to Read(). If that is the case, no data is actually read from +// the underlying io.Reader, to allow for potential input buffer resizing. +// +// Data is buffered if the input buffer is too small, and exhausted upon successive calls. +// +// If the buffer is large enough (typically in multiples of BlockMaxSize) and there is +// no block dependency, then the data will be decompressed concurrently based on the GOMAXPROCS value. +func (z *Reader) Read(buf []byte) (n int, err error) { + if !z.Header.done { + if err = z.readHeader(true); err != nil { + return + } + } + + if len(buf) == 0 { + return + } + + // exhaust remaining data from previous Read() + if len(z.data) > 0 { + n = copy(buf, z.data) + z.data = z.data[n:] + if len(z.data) == 0 { + z.data = nil + } + return + } + + // Break up the input buffer into BlockMaxSize blocks with at least one block. + // Then decompress into each of them concurrently if possible (no dependency). + // In case of dependency, the first block will be missing the window (except on the + // very first call), the rest will have it already since it comes from the previous block. + wbuf := buf + zn := (len(wbuf) + z.BlockMaxSize - 1) / z.BlockMaxSize + zblocks := make([]block, zn) + for zi, abort := 0, uint32(0); zi < zn && atomic.LoadUint32(&abort) == 0; zi++ { + zb := &zblocks[zi] + // last block may be too small + if len(wbuf) < z.BlockMaxSize+len(z.window) { + wbuf = make([]byte, z.BlockMaxSize+len(z.window)) + } + copy(wbuf, z.window) + if zb.err = z.readBlock(wbuf, zb); zb.err != nil { + break + } + wbuf = wbuf[z.BlockMaxSize:] + if !z.BlockDependency { + z.wg.Add(1) + go z.decompressBlock(zb, &abort) + continue + } + // cannot decompress concurrently when dealing with block dependency + z.decompressBlock(zb, nil) + // the last block may not contain enough data + if len(z.window) == 0 { + z.window = make([]byte, winSize) + } + if len(zb.data) >= winSize { + copy(z.window, zb.data[len(zb.data)-winSize:]) + } else { + copy(z.window, z.window[len(zb.data):]) + copy(z.window[len(zb.data)+1:], zb.data) + } + } + z.wg.Wait() + + // since a block size may be less then BlockMaxSize, trim the decompressed buffers + for _, zb := range zblocks { + if zb.err != nil { + if zb.err == errEndOfBlock { + return n, z.close() + } + return n, zb.err + } + bLen := len(zb.data) + if !z.NoChecksum { + z.checksum.Write(zb.data) + } + m := copy(buf[n:], zb.data) + // buffer the remaining data (this is necessarily the last block) + if m < bLen { + z.data = zb.data[m:] + } + n += m + } + + return +} + +// readBlock reads an entire frame block from the frame. +// The input buffer is the one that will receive the decompressed data. +// If the end of the frame is detected, it returns the errEndOfBlock error. +func (z *Reader) readBlock(buf []byte, b *block) error { + var bLen uint32 + if err := binary.Read(z.src, binary.LittleEndian, &bLen); err != nil { + return err + } + atomic.AddInt64(&z.Pos, 4) + + switch { + case bLen == 0: + return errEndOfBlock + case bLen&(1<<31) == 0: + b.compressed = true + b.data = buf + b.zdata = make([]byte, bLen) + default: + bLen = bLen & (1<<31 - 1) + if int(bLen) > len(buf) { + return fmt.Errorf("lz4.Read: invalid block size: %d", bLen) + } + b.data = buf[:bLen] + b.zdata = buf[:bLen] + } + if _, err := io.ReadFull(z.src, b.zdata); err != nil { + return err + } + + if z.BlockChecksum { + if err := binary.Read(z.src, binary.LittleEndian, &b.checksum); err != nil { + return err + } + xxh := hashPool.Get() + defer hashPool.Put(xxh) + xxh.Write(b.zdata) + if h := xxh.Sum32(); h != b.checksum { + return fmt.Errorf("lz4.Read: invalid block checksum: got %x expected %x", h, b.checksum) + } + } + + return nil +} + +// decompressBlock decompresses a frame block. +// In case of an error, the block err is set with it and abort is set to 1. +func (z *Reader) decompressBlock(b *block, abort *uint32) { + if abort != nil { + defer z.wg.Done() + } + if b.compressed { + n := len(z.window) + m, err := UncompressBlock(b.zdata, b.data, n) + if err != nil { + if abort != nil { + atomic.StoreUint32(abort, 1) + } + b.err = err + return + } + b.data = b.data[n : n+m] + } + atomic.AddInt64(&z.Pos, int64(len(b.data))) +} + +// close validates the frame checksum (if any) and checks the next frame (if any). +func (z *Reader) close() error { + if !z.NoChecksum { + var checksum uint32 + if err := binary.Read(z.src, binary.LittleEndian, &checksum); err != nil { + return err + } + if checksum != z.checksum.Sum32() { + return fmt.Errorf("lz4.Read: invalid frame checksum: got %x expected %x", z.checksum.Sum32(), checksum) + } + } + + // get ready for the next concatenated frame, but do not change the position + pos := z.Pos + z.Reset(z.src) + z.Pos = pos + + // since multiple frames can be concatenated, check for another one + return z.readHeader(false) +} + +// Reset discards the Reader's state and makes it equivalent to the +// result of its original state from NewReader, but reading from r instead. +// This permits reusing a Reader rather than allocating a new one. +func (z *Reader) Reset(r io.Reader) { + z.Header = Header{} + z.Pos = 0 + z.src = r + z.checksum.Reset() + z.data = nil + z.window = nil +} + +// WriteTo decompresses the data from the underlying io.Reader and writes it to the io.Writer. +// Returns the number of bytes written. +func (z *Reader) WriteTo(w io.Writer) (n int64, err error) { + cpus := runtime.GOMAXPROCS(0) + var buf []byte + + // The initial buffer being nil, the first Read will be only read the compressed frame options. + // The buffer can then be sized appropriately to support maximum concurrency decompression. + // If multiple frames are concatenated, Read() will return with no data decompressed but with + // potentially changed options. The buffer will be resized accordingly, always trying to + // maximize concurrency. + for { + nsize := 0 + // the block max size can change if multiple streams are concatenated. + // Check it after every Read(). + if z.BlockDependency { + // in case of dependency, we cannot decompress concurrently, + // so allocate the minimum buffer + window size + nsize = len(z.window) + z.BlockMaxSize + } else { + // if no dependency, allocate a buffer large enough for concurrent decompression + nsize = cpus * z.BlockMaxSize + } + if nsize != len(buf) { + buf = make([]byte, nsize) + } + + m, er := z.Read(buf) + if er != nil && er != io.EOF { + return n, er + } + m, err = w.Write(buf[:m]) + n += int64(m) + if err != nil || er == io.EOF { + return + } + } +} diff --git a/vendor/src/github.com/pierrec/lz4/writer.go b/vendor/src/github.com/pierrec/lz4/writer.go new file mode 100644 index 00000000..11082f5a --- /dev/null +++ b/vendor/src/github.com/pierrec/lz4/writer.go @@ -0,0 +1,383 @@ +package lz4 + +import ( + "encoding/binary" + "fmt" + "hash" + "io" + "runtime" +) + +// Writer implements the LZ4 frame encoder. +type Writer struct { + Header + dst io.Writer + checksum hash.Hash32 // frame checksum + data []byte // data to be compressed, only used when dealing with block dependency as we need 64Kb to work with + window []byte // last 64KB of decompressed data (block dependency) + blockMaxSize buffer + + zbCompressBuf []byte // buffer for compressing lz4 blocks + writeSizeBuf []byte // four-byte slice for writing checksums and sizes in writeblock + hashTable []hashEntry + currentGeneration uint +} + +// NewWriter returns a new LZ4 frame encoder. +// No access to the underlying io.Writer is performed. +// The supplied Header is checked at the first Write. +// It is ok to change it before the first Write but then not until a Reset() is performed. +func NewWriter(dst io.Writer) *Writer { + return &Writer{ + dst: dst, + checksum: hashPool.Get(), + Header: Header{ + BlockMaxSize: 4 << 20, + }, + hashTable: make([]hashEntry, hashTableSize), + writeSizeBuf: make([]byte, 4), + } +} + +// writeHeader builds and writes the header (magic+header) to the underlying io.Writer. +func (z *Writer) writeHeader() error { + // Default to 4Mb if BlockMaxSize is not set + if z.Header.BlockMaxSize == 0 { + z.Header.BlockMaxSize = 4 << 20 + } + // the only option that need to be validated + bSize, ok := bsMapValue[z.Header.BlockMaxSize] + if !ok { + return fmt.Errorf("lz4: invalid block max size: %d", z.Header.BlockMaxSize) + } + + // magic number(4) + header(flags(2)+[Size(8)+DictID(4)]+checksum(1)) does not exceed 19 bytes + // Size and DictID are optional + var buf [19]byte + + // set the fixed size data: magic number, block max size and flags + binary.LittleEndian.PutUint32(buf[0:], frameMagic) + flg := byte(Version << 6) + if !z.Header.BlockDependency { + flg |= 1 << 5 + } + if z.Header.BlockChecksum { + flg |= 1 << 4 + } + if z.Header.Size > 0 { + flg |= 1 << 3 + } + if !z.Header.NoChecksum { + flg |= 1 << 2 + } + // if z.Header.Dict { + // flg |= 1 + // } + buf[4] = flg + buf[5] = bSize << 4 + + // current buffer size: magic(4) + flags(1) + block max size (1) + n := 6 + // optional items + if z.Header.Size > 0 { + binary.LittleEndian.PutUint64(buf[n:], z.Header.Size) + n += 8 + } + // if z.Header.Dict { + // binary.LittleEndian.PutUint32(buf[n:], z.Header.DictID) + // n += 4 + // } + + // header checksum includes the flags, block max size and optional Size and DictID + z.checksum.Write(buf[4:n]) + buf[n] = byte(z.checksum.Sum32() >> 8 & 0xFF) + z.checksum.Reset() + + // header ready, write it out + if _, err := z.dst.Write(buf[0 : n+1]); err != nil { + return err + } + z.Header.done = true + + // initialize buffers dependent on header info + z.zbCompressBuf = make([]byte, winSize+z.BlockMaxSize) + + return nil +} + +// Write compresses data from the supplied buffer into the underlying io.Writer. +// Write does not return until the data has been written. +// +// If the input buffer is large enough (typically in multiples of BlockMaxSize) +// the data will be compressed concurrently. +// +// Write never buffers any data unless in BlockDependency mode where it may +// do so until it has 64Kb of data, after which it never buffers any. +func (z *Writer) Write(buf []byte) (n int, err error) { + if !z.Header.done { + if err = z.writeHeader(); err != nil { + return + } + } + + if len(buf) == 0 { + return + } + + if !z.NoChecksum { + z.checksum.Write(buf) + } + + // with block dependency, require at least 64Kb of data to work with + // not having 64Kb only matters initially to setup the first window + bl := 0 + if z.BlockDependency && len(z.window) == 0 { + bl = len(z.data) + z.data = append(z.data, buf...) + if len(z.data) < winSize { + return len(buf), nil + } + buf = z.data + z.data = nil + } + + // Break up the input buffer into BlockMaxSize blocks, provisioning the left over block. + // Then compress into each of them concurrently if possible (no dependency). + var ( + zb block + wbuf = buf + zn = len(wbuf) / z.BlockMaxSize + zi = 0 + leftover = len(buf) % z.BlockMaxSize + ) + +loop: + for zi < zn { + if z.BlockDependency { + if zi == 0 { + // first block does not have the window + zb.data = append(z.window, wbuf[:z.BlockMaxSize]...) + zb.offset = len(z.window) + wbuf = wbuf[z.BlockMaxSize-winSize:] + } else { + // set the uncompressed data including the window from previous block + zb.data = wbuf[:z.BlockMaxSize+winSize] + zb.offset = winSize + wbuf = wbuf[z.BlockMaxSize:] + } + } else { + zb.data = wbuf[:z.BlockMaxSize] + wbuf = wbuf[z.BlockMaxSize:] + } + + goto write + } + + // left over + if leftover > 0 { + zb = block{data: wbuf} + if z.BlockDependency { + if zn == 0 { + zb.data = append(z.window, zb.data...) + zb.offset = len(z.window) + } else { + zb.offset = winSize + } + } + + leftover = 0 + goto write + } + + if z.BlockDependency { + if len(z.window) == 0 { + z.window = make([]byte, winSize) + } + // last buffer may be shorter than the window + if len(buf) >= winSize { + copy(z.window, buf[len(buf)-winSize:]) + } else { + copy(z.window, z.window[len(buf):]) + copy(z.window[len(buf)+1:], buf) + } + } + + return + +write: + zb = z.compressBlock(zb) + _, err = z.writeBlock(zb) + + written := len(zb.data) + if bl > 0 { + if written >= bl { + written -= bl + bl = 0 + } else { + bl -= written + written = 0 + } + } + + n += written + // remove the window in zb.data + if z.BlockDependency { + if zi == 0 { + n -= len(z.window) + } else { + n -= winSize + } + } + if err != nil { + return + } + zi++ + goto loop +} + +// compressBlock compresses a block. +func (z *Writer) compressBlock(zb block) block { + // compressed block size cannot exceed the input's + var ( + n int + err error + zbuf = z.zbCompressBuf + ) + if z.HighCompression { + n, err = CompressBlockHC(zb.data, zbuf, zb.offset) + } else { + n, err = compressGenerationalBlock(zb.data, zbuf, zb.offset, z.currentGeneration, z.hashTable) + z.currentGeneration++ + if z.currentGeneration == 0 { // wrapped around, reset table + z.hashTable = make([]hashEntry, hashTableSize) + } + } + + // compressible and compressed size smaller than decompressed: ok! + if err == nil && n > 0 && len(zb.zdata) < len(zb.data) { + zb.compressed = true + zb.zdata = zbuf[:n] + } else { + zb.zdata = zb.data[zb.offset:] + } + + if z.BlockChecksum { + xxh := hashPool.Get() + xxh.Write(zb.zdata) + zb.checksum = xxh.Sum32() + hashPool.Put(xxh) + } + + return zb +} + +// writeBlock writes a frame block to the underlying io.Writer (size, data). +func (z *Writer) writeBlock(zb block) (int, error) { + bLen := uint32(len(zb.zdata)) + if !zb.compressed { + bLen |= 1 << 31 + } + + n := 0 + + binary.LittleEndian.PutUint32(z.writeSizeBuf, bLen) + n, err := z.dst.Write(z.writeSizeBuf) + if err != nil { + return n, err + } + + m, err := z.dst.Write(zb.zdata) + n += m + if err != nil { + return n, err + } + + if z.BlockChecksum { + binary.LittleEndian.PutUint32(z.writeSizeBuf, zb.checksum) + m, err := z.dst.Write(z.writeSizeBuf) + n += m + + if err != nil { + return n, err + } + } + + return n, nil +} + +// Flush flushes any pending compressed data to the underlying writer. +// Flush does not return until the data has been written. +// If the underlying writer returns an error, Flush returns that error. +// +// Flush is only required when in BlockDependency mode and the total of +// data written is less than 64Kb. +func (z *Writer) Flush() error { + if len(z.data) == 0 { + return nil + } + + zb := z.compressBlock(block{data: z.data}) + if _, err := z.writeBlock(zb); err != nil { + return err + } + return nil +} + +// Close closes the Writer, flushing any unwritten data to the underlying io.Writer, but does not close the underlying io.Writer. +func (z *Writer) Close() error { + if !z.Header.done { + if err := z.writeHeader(); err != nil { + return err + } + } + + // buffered data for the block dependency window + if z.BlockDependency && len(z.data) > 0 { + zb := block{data: z.data} + if _, err := z.writeBlock(z.compressBlock(zb)); err != nil { + return err + } + } + + if err := binary.Write(z.dst, binary.LittleEndian, uint32(0)); err != nil { + return err + } + if !z.NoChecksum { + if err := binary.Write(z.dst, binary.LittleEndian, z.checksum.Sum32()); err != nil { + return err + } + } + return nil +} + +// Reset clears the state of the Writer z such that it is equivalent to its +// initial state from NewWriter, but instead writing to w. +// No access to the underlying io.Writer is performed. +func (z *Writer) Reset(w io.Writer) { + z.Header = Header{} + z.dst = w + z.checksum.Reset() + z.data = nil + z.window = nil +} + +// ReadFrom compresses the data read from the io.Reader and writes it to the underlying io.Writer. +// Returns the number of bytes read. +// It does not close the Writer. +func (z *Writer) ReadFrom(r io.Reader) (n int64, err error) { + cpus := runtime.GOMAXPROCS(0) + buf := make([]byte, cpus*z.BlockMaxSize) + for { + m, er := io.ReadFull(r, buf) + n += int64(m) + if er == nil || er == io.ErrUnexpectedEOF || er == io.EOF { + if _, err = z.Write(buf[:m]); err != nil { + return + } + if er == nil { + continue + } + return + } + return n, er + } +} diff --git a/vendor/src/github.com/pierrec/xxHash/xxHash32/example_test.go b/vendor/src/github.com/pierrec/xxHash/xxHash32/example_test.go new file mode 100644 index 00000000..bd912b04 --- /dev/null +++ b/vendor/src/github.com/pierrec/xxHash/xxHash32/example_test.go @@ -0,0 +1,21 @@ +package xxHash32_test + +import ( + "bytes" + "fmt" + "github.com/pierrec/xxHash/xxHash32" +) + +func ExampleNew() { + buf := bytes.NewBufferString("this is a test") + x := xxHash32.New(0xCAFE) + x.Write(buf.Bytes()) + fmt.Printf("%x\n", x.Sum32()) + // Output: bb4f02bc +} + +func ExampleChecksum() { + buf := bytes.NewBufferString("this is a test") + fmt.Printf("%x\n", xxHash32.Checksum(buf.Bytes(), 0xCAFE)) + // Output: bb4f02bc +} diff --git a/vendor/src/github.com/pierrec/xxHash/xxHash32/xxHash32.go b/vendor/src/github.com/pierrec/xxHash/xxHash32/xxHash32.go new file mode 100644 index 00000000..411504e4 --- /dev/null +++ b/vendor/src/github.com/pierrec/xxHash/xxHash32/xxHash32.go @@ -0,0 +1,205 @@ +// Package xxHash32 implements the very fast xxHash hashing algorithm (32 bits version). +// (https://github.com/Cyan4973/xxHash/) +package xxHash32 + +import "hash" + +const ( + prime32_1 = 2654435761 + prime32_2 = 2246822519 + prime32_3 = 3266489917 + prime32_4 = 668265263 + prime32_5 = 374761393 +) + +type xxHash struct { + seed uint32 + v1 uint32 + v2 uint32 + v3 uint32 + v4 uint32 + totalLen uint64 + buf [16]byte + bufused int +} + +// New returns a new Hash32 instance. +func New(seed uint32) hash.Hash32 { + xxh := &xxHash{seed: seed} + xxh.Reset() + return xxh +} + +// Sum appends the current hash to b and returns the resulting slice. +// It does not change the underlying hash state. +func (xxh xxHash) Sum(b []byte) []byte { + h32 := xxh.Sum32() + return append(b, byte(h32), byte(h32>>8), byte(h32>>16), byte(h32>>24)) +} + +// Reset resets the Hash to its initial state. +func (xxh *xxHash) Reset() { + xxh.v1 = xxh.seed + prime32_1 + prime32_2 + xxh.v2 = xxh.seed + prime32_2 + xxh.v3 = xxh.seed + xxh.v4 = xxh.seed - prime32_1 + xxh.totalLen = 0 + xxh.bufused = 0 +} + +// Size returns the number of bytes returned by Sum(). +func (xxh *xxHash) Size() int { + return 4 +} + +// BlockSize gives the minimum number of bytes accepted by Write(). +func (xxh *xxHash) BlockSize() int { + return 1 +} + +// Write adds input bytes to the Hash. +// It never returns an error. +func (xxh *xxHash) Write(input []byte) (int, error) { + n := len(input) + m := xxh.bufused + + xxh.totalLen += uint64(n) + + r := len(xxh.buf) - m + if n < r { + copy(xxh.buf[m:], input) + xxh.bufused += len(input) + return n, nil + } + + p := 0 + if m > 0 { + // some data left from previous update + copy(xxh.buf[xxh.bufused:], input[:r]) + xxh.bufused += len(input) - r + + // fast rotl(13) + p32 := xxh.v1 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2 + xxh.v1 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v2 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2 + xxh.v2 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v3 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2 + xxh.v3 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v4 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2 + xxh.v4 = (p32<<13 | p32>>19) * prime32_1 + + p = r + xxh.bufused = 0 + } + + for n := n - 16; p <= n; { + p32 := xxh.v1 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2 + xxh.v1 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v2 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2 + xxh.v2 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v3 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2 + xxh.v3 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v4 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2 + xxh.v4 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + } + + copy(xxh.buf[xxh.bufused:], input[p:]) + xxh.bufused += len(input) - p + + return n, nil +} + +// Sum32 returns the 32 bits Hash value. +func (xxh *xxHash) Sum32() uint32 { + h32 := uint32(xxh.totalLen) + if xxh.totalLen >= 16 { + h32 += ((xxh.v1 << 1) | (xxh.v1 >> 31)) + + ((xxh.v2 << 7) | (xxh.v2 >> 25)) + + ((xxh.v3 << 12) | (xxh.v3 >> 20)) + + ((xxh.v4 << 18) | (xxh.v4 >> 14)) + } else { + h32 += xxh.seed + prime32_5 + } + + p := 0 + n := xxh.bufused + for n := n - 4; p <= n; p += 4 { + h32 += (uint32(xxh.buf[p+3])<<24 | uint32(xxh.buf[p+2])<<16 | uint32(xxh.buf[p+1])<<8 | uint32(xxh.buf[p])) * prime32_3 + h32 = ((h32 << 17) | (h32 >> 15)) * prime32_4 + } + for ; p < n; p++ { + h32 += uint32(xxh.buf[p]) * prime32_5 + h32 = ((h32 << 11) | (h32 >> 21)) * prime32_1 + } + + h32 ^= h32 >> 15 + h32 *= prime32_2 + h32 ^= h32 >> 13 + h32 *= prime32_3 + h32 ^= h32 >> 16 + + return h32 +} + +// Checksum returns the 32bits Hash value. +func Checksum(input []byte, seed uint32) uint32 { + n := len(input) + h32 := uint32(n) + + if n < 16 { + h32 += seed + prime32_5 + } else { + v1 := seed + prime32_1 + prime32_2 + v2 := seed + prime32_2 + v3 := seed + v4 := seed - prime32_1 + p := 0 + for p <= n-16 { + v1 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2 + v1 = (v1<<13 | v1>>19) * prime32_1 + p += 4 + v2 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2 + v2 = (v2<<13 | v2>>19) * prime32_1 + p += 4 + v3 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2 + v3 = (v3<<13 | v3>>19) * prime32_1 + p += 4 + v4 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2 + v4 = (v4<<13 | v4>>19) * prime32_1 + p += 4 + } + input = input[p:] + n -= p + h32 += ((v1 << 1) | (v1 >> 31)) + + ((v2 << 7) | (v2 >> 25)) + + ((v3 << 12) | (v3 >> 20)) + + ((v4 << 18) | (v4 >> 14)) + } + + p := 0 + for p <= n-4 { + h32 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_3 + h32 = ((h32 << 17) | (h32 >> 15)) * prime32_4 + p += 4 + } + for p < n { + h32 += uint32(input[p]) * prime32_5 + h32 = ((h32 << 11) | (h32 >> 21)) * prime32_1 + p++ + } + + h32 ^= h32 >> 15 + h32 *= prime32_2 + h32 ^= h32 >> 13 + h32 *= prime32_3 + h32 ^= h32 >> 16 + + return h32 +} diff --git a/vendor/src/github.com/pierrec/xxHash/xxHash32/xxHash32_test.go b/vendor/src/github.com/pierrec/xxHash/xxHash32/xxHash32_test.go new file mode 100644 index 00000000..63e05486 --- /dev/null +++ b/vendor/src/github.com/pierrec/xxHash/xxHash32/xxHash32_test.go @@ -0,0 +1,150 @@ +package xxHash32_test + +import ( + "encoding/binary" + "hash/crc32" + "hash/fnv" + "testing" + + "github.com/pierrec/xxHash/xxHash32" +) + +type test struct { + sum uint32 + data, printable string +} + +var testdata = []test{ + {0x02cc5d05, "", ""}, + {0x550d7456, "a", ""}, + {0x4999fc53, "ab", ""}, + {0x32d153ff, "abc", ""}, + {0xa3643705, "abcd", ""}, + {0x9738f19b, "abcde", ""}, + {0x8b7cd587, "abcdef", ""}, + {0x9dd093b3, "abcdefg", ""}, + {0x0bb3c6bb, "abcdefgh", ""}, + {0xd03c13fd, "abcdefghi", ""}, + {0x8b988cfe, "abcdefghij", ""}, + {0x9d2d8b62, "abcdefghijklmnop", ""}, + {0x42ae804d, "abcdefghijklmnopqrstuvwxyz0123456789", ""}, + {0x62b4ed00, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", ""}, +} + +func init() { + for i := range testdata { + d := &testdata[i] + if len(d.data) > 20 { + d.printable = d.data[:20] + } else { + d.printable = d.data + } + } +} + +func TestBlockSize(t *testing.T) { + xxh := xxHash32.New(0) + if s := xxh.BlockSize(); s <= 0 { + t.Errorf("invalid BlockSize: %d", s) + } +} + +func TestSize(t *testing.T) { + xxh := xxHash32.New(0) + if s := xxh.Size(); s != 4 { + t.Errorf("invalid Size: got %d expected 4", s) + } +} + +func TestData(t *testing.T) { + for i, td := range testdata { + xxh := xxHash32.New(0) + data := []byte(td.data) + xxh.Write(data) + if h := xxh.Sum32(); h != td.sum { + t.Errorf("test %d: xxh32(%s)=0x%x expected 0x%x", i, td.printable, h, td.sum) + t.FailNow() + } + if h := xxHash32.Checksum(data, 0); h != td.sum { + t.Errorf("test %d: xxh32(%s)=0x%x expected 0x%x", i, td.printable, h, td.sum) + t.FailNow() + } + } +} + +func TestSplitData(t *testing.T) { + for i, td := range testdata { + xxh := xxHash32.New(0) + data := []byte(td.data) + l := len(data) / 2 + xxh.Write(data[0:l]) + xxh.Write(data[l:]) + h := xxh.Sum32() + if h != td.sum { + t.Errorf("test %d: xxh32(%s)=0x%x expected 0x%x", i, td.printable, h, td.sum) + t.FailNow() + } + } +} + +func TestSum(t *testing.T) { + for i, td := range testdata { + xxh := xxHash32.New(0) + data := []byte(td.data) + xxh.Write(data) + b := xxh.Sum(data) + if h := binary.LittleEndian.Uint32(b[len(data):]); h != td.sum { + t.Errorf("test %d: xxh32(%s)=0x%x expected 0x%x", i, td.printable, h, td.sum) + t.FailNow() + } + } +} + +func TestReset(t *testing.T) { + xxh := xxHash32.New(0) + for i, td := range testdata { + xxh.Write([]byte(td.data)) + h := xxh.Sum32() + if h != td.sum { + t.Errorf("test %d: xxh32(%s)=0x%x expected 0x%x", i, td.data[:40], h, td.sum) + t.FailNow() + } + xxh.Reset() + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Benchmarks +// +var testdata1 = []byte(testdata[len(testdata)-1].data) + +func Benchmark_XXH32(b *testing.B) { + h := xxHash32.New(0) + for n := 0; n < b.N; n++ { + h.Write(testdata1) + h.Sum32() + h.Reset() + } +} + +func Benchmark_XXH32_Checksum(b *testing.B) { + for n := 0; n < b.N; n++ { + xxHash32.Checksum(testdata1, 0) + } +} + +func Benchmark_CRC32(b *testing.B) { + t := crc32.MakeTable(0) + for i := 0; i < b.N; i++ { + crc32.Checksum(testdata1, t) + } +} + +func Benchmark_Fnv32(b *testing.B) { + h := fnv.New32() + for i := 0; i < b.N; i++ { + h.Write(testdata1) + h.Sum32() + h.Reset() + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/LICENSE b/vendor/src/github.com/rcrowley/go-metrics/LICENSE new file mode 100644 index 00000000..363fa9ee --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/LICENSE @@ -0,0 +1,29 @@ +Copyright 2012 Richard Crowley. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +THIS SOFTWARE IS PROVIDED BY RICHARD CROWLEY ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL RICHARD CROWLEY OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation +are those of the authors and should not be interpreted as representing +official policies, either expressed or implied, of Richard Crowley. diff --git a/vendor/src/github.com/rcrowley/go-metrics/README.md b/vendor/src/github.com/rcrowley/go-metrics/README.md new file mode 100644 index 00000000..2d1a6dcf --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/README.md @@ -0,0 +1,153 @@ +go-metrics +========== + +![travis build status](https://travis-ci.org/rcrowley/go-metrics.svg?branch=master) + +Go port of Coda Hale's Metrics library: . + +Documentation: . + +Usage +----- + +Create and update metrics: + +```go +c := metrics.NewCounter() +metrics.Register("foo", c) +c.Inc(47) + +g := metrics.NewGauge() +metrics.Register("bar", g) +g.Update(47) + +r := NewRegistry() +g := metrics.NewRegisteredFunctionalGauge("cache-evictions", r, func() int64 { return cache.getEvictionsCount() }) + +s := metrics.NewExpDecaySample(1028, 0.015) // or metrics.NewUniformSample(1028) +h := metrics.NewHistogram(s) +metrics.Register("baz", h) +h.Update(47) + +m := metrics.NewMeter() +metrics.Register("quux", m) +m.Mark(47) + +t := metrics.NewTimer() +metrics.Register("bang", t) +t.Time(func() {}) +t.Update(47) +``` + +Register() is not threadsafe. For threadsafe metric registration use +GetOrRegister: + +``` +t := metrics.GetOrRegisterTimer("account.create.latency", nil) +t.Time(func() {}) +t.Update(47) +``` + +Periodically log every metric in human-readable form to standard error: + +```go +go metrics.Log(metrics.DefaultRegistry, 5 * time.Second, log.New(os.Stderr, "metrics: ", log.Lmicroseconds)) +``` + +Periodically log every metric in slightly-more-parseable form to syslog: + +```go +w, _ := syslog.Dial("unixgram", "/dev/log", syslog.LOG_INFO, "metrics") +go metrics.Syslog(metrics.DefaultRegistry, 60e9, w) +``` + +Periodically emit every metric to Graphite using the [Graphite client](https://github.com/cyberdelia/go-metrics-graphite): + +```go + +import "github.com/cyberdelia/go-metrics-graphite" + +addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003") +go graphite.Graphite(metrics.DefaultRegistry, 10e9, "metrics", addr) +``` + +Periodically emit every metric into InfluxDB: + +**NOTE:** this has been pulled out of the library due to constant fluctuations +in the InfluxDB API. In fact, all client libraries are on their way out. see +issues [#121](https://github.com/rcrowley/go-metrics/issues/121) and +[#124](https://github.com/rcrowley/go-metrics/issues/124) for progress and details. + +```go +import "github.com/vrischmann/go-metrics-influxdb" + +go influxdb.Influxdb(metrics.DefaultRegistry, 10e9, &influxdb.Config{ + Host: "127.0.0.1:8086", + Database: "metrics", + Username: "test", + Password: "test", +}) +``` + +Periodically upload every metric to Librato using the [Librato client](https://github.com/mihasya/go-metrics-librato): + +**Note**: the client included with this repository under the `librato` package +has been deprecated and moved to the repository linked above. + +```go +import "github.com/mihasya/go-metrics-librato" + +go librato.Librato(metrics.DefaultRegistry, + 10e9, // interval + "example@example.com", // account owner email address + "token", // Librato API token + "hostname", // source + []float64{0.95}, // percentiles to send + time.Millisecond, // time unit +) +``` + +Periodically emit every metric to StatHat: + +```go +import "github.com/rcrowley/go-metrics/stathat" + +go stathat.Stathat(metrics.DefaultRegistry, 10e9, "example@example.com") +``` + +Maintain all metrics along with expvars at `/debug/metrics`: + +This uses the same mechanism as [the official expvar](http://golang.org/pkg/expvar/) +but exposed under `/debug/metrics`, which shows a json representation of all your usual expvars +as well as all your go-metrics. + + +```go +import "github.com/rcrowley/go-metrics/exp" + +exp.Exp(metrics.DefaultRegistry) +``` + +Installation +------------ + +```sh +go get github.com/rcrowley/go-metrics +``` + +StatHat support additionally requires their Go client: + +```sh +go get github.com/stathat/go +``` + +Publishing Metrics +------------------ + +Clients are available for the following destinations: + +* Librato - [https://github.com/mihasya/go-metrics-librato](https://github.com/mihasya/go-metrics-librato) +* Graphite - [https://github.com/cyberdelia/go-metrics-graphite](https://github.com/cyberdelia/go-metrics-graphite) +* InfluxDB - [https://github.com/vrischmann/go-metrics-influxdb](https://github.com/vrischmann/go-metrics-influxdb) +* Ganglia - [https://github.com/appscode/metlia](https://github.com/appscode/metlia) +* Prometheus - [https://github.com/deathowl/go-metrics-prometheus](https://github.com/deathowl/go-metrics-prometheus) diff --git a/vendor/src/github.com/rcrowley/go-metrics/cmd/metrics-bench/metrics-bench.go b/vendor/src/github.com/rcrowley/go-metrics/cmd/metrics-bench/metrics-bench.go new file mode 100644 index 00000000..dddaf4b1 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/cmd/metrics-bench/metrics-bench.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + "github.com/rcrowley/go-metrics" + "time" +) + +func main() { + r := metrics.NewRegistry() + for i := 0; i < 10000; i++ { + r.Register(fmt.Sprintf("counter-%d", i), metrics.NewCounter()) + r.Register(fmt.Sprintf("gauge-%d", i), metrics.NewGauge()) + r.Register(fmt.Sprintf("gaugefloat64-%d", i), metrics.NewGaugeFloat64()) + r.Register(fmt.Sprintf("histogram-uniform-%d", i), metrics.NewHistogram(metrics.NewUniformSample(1028))) + r.Register(fmt.Sprintf("histogram-exp-%d", i), metrics.NewHistogram(metrics.NewExpDecaySample(1028, 0.015))) + r.Register(fmt.Sprintf("meter-%d", i), metrics.NewMeter()) + } + time.Sleep(600e9) +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/cmd/metrics-example/metrics-example.go b/vendor/src/github.com/rcrowley/go-metrics/cmd/metrics-example/metrics-example.go new file mode 100644 index 00000000..66f42c04 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/cmd/metrics-example/metrics-example.go @@ -0,0 +1,154 @@ +package main + +import ( + "errors" + "github.com/rcrowley/go-metrics" + // "github.com/rcrowley/go-metrics/stathat" + "log" + "math/rand" + "os" + // "syslog" + "time" +) + +const fanout = 10 + +func main() { + + r := metrics.NewRegistry() + + c := metrics.NewCounter() + r.Register("foo", c) + for i := 0; i < fanout; i++ { + go func() { + for { + c.Dec(19) + time.Sleep(300e6) + } + }() + go func() { + for { + c.Inc(47) + time.Sleep(400e6) + } + }() + } + + g := metrics.NewGauge() + r.Register("bar", g) + for i := 0; i < fanout; i++ { + go func() { + for { + g.Update(19) + time.Sleep(300e6) + } + }() + go func() { + for { + g.Update(47) + time.Sleep(400e6) + } + }() + } + + gf := metrics.NewGaugeFloat64() + r.Register("barfloat64", gf) + for i := 0; i < fanout; i++ { + go func() { + for { + g.Update(19.0) + time.Sleep(300e6) + } + }() + go func() { + for { + g.Update(47.0) + time.Sleep(400e6) + } + }() + } + + hc := metrics.NewHealthcheck(func(h metrics.Healthcheck) { + if 0 < rand.Intn(2) { + h.Healthy() + } else { + h.Unhealthy(errors.New("baz")) + } + }) + r.Register("baz", hc) + + s := metrics.NewExpDecaySample(1028, 0.015) + //s := metrics.NewUniformSample(1028) + h := metrics.NewHistogram(s) + r.Register("bang", h) + for i := 0; i < fanout; i++ { + go func() { + for { + h.Update(19) + time.Sleep(300e6) + } + }() + go func() { + for { + h.Update(47) + time.Sleep(400e6) + } + }() + } + + m := metrics.NewMeter() + r.Register("quux", m) + for i := 0; i < fanout; i++ { + go func() { + for { + m.Mark(19) + time.Sleep(300e6) + } + }() + go func() { + for { + m.Mark(47) + time.Sleep(400e6) + } + }() + } + + t := metrics.NewTimer() + r.Register("hooah", t) + for i := 0; i < fanout; i++ { + go func() { + for { + t.Time(func() { time.Sleep(300e6) }) + } + }() + go func() { + for { + t.Time(func() { time.Sleep(400e6) }) + } + }() + } + + metrics.RegisterDebugGCStats(r) + go metrics.CaptureDebugGCStats(r, 5e9) + + metrics.RegisterRuntimeMemStats(r) + go metrics.CaptureRuntimeMemStats(r, 5e9) + + metrics.Log(r, 60e9, log.New(os.Stderr, "metrics: ", log.Lmicroseconds)) + + /* + w, err := syslog.Dial("unixgram", "/dev/log", syslog.LOG_INFO, "metrics") + if nil != err { log.Fatalln(err) } + metrics.Syslog(r, 60e9, w) + */ + + /* + addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003") + metrics.Graphite(r, 10e9, "metrics", addr) + */ + + /* + stathat.Stathat(r, 10e9, "example@example.com") + */ + +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/cmd/never-read/never-read.go b/vendor/src/github.com/rcrowley/go-metrics/cmd/never-read/never-read.go new file mode 100644 index 00000000..dc175b77 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/cmd/never-read/never-read.go @@ -0,0 +1,22 @@ +package main + +import ( + "log" + "net" +) + +func main() { + addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003") + l, err := net.ListenTCP("tcp", addr) + if nil != err { + log.Fatalln(err) + } + log.Println("listening", l.Addr()) + for { + c, err := l.AcceptTCP() + if nil != err { + log.Fatalln(err) + } + log.Println("accepted", c.RemoteAddr()) + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/counter.go b/vendor/src/github.com/rcrowley/go-metrics/counter.go new file mode 100644 index 00000000..bb7b039c --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/counter.go @@ -0,0 +1,112 @@ +package metrics + +import "sync/atomic" + +// Counters hold an int64 value that can be incremented and decremented. +type Counter interface { + Clear() + Count() int64 + Dec(int64) + Inc(int64) + Snapshot() Counter +} + +// GetOrRegisterCounter returns an existing Counter or constructs and registers +// a new StandardCounter. +func GetOrRegisterCounter(name string, r Registry) Counter { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewCounter).(Counter) +} + +// NewCounter constructs a new StandardCounter. +func NewCounter() Counter { + if UseNilMetrics { + return NilCounter{} + } + return &StandardCounter{0} +} + +// NewRegisteredCounter constructs and registers a new StandardCounter. +func NewRegisteredCounter(name string, r Registry) Counter { + c := NewCounter() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// CounterSnapshot is a read-only copy of another Counter. +type CounterSnapshot int64 + +// Clear panics. +func (CounterSnapshot) Clear() { + panic("Clear called on a CounterSnapshot") +} + +// Count returns the count at the time the snapshot was taken. +func (c CounterSnapshot) Count() int64 { return int64(c) } + +// Dec panics. +func (CounterSnapshot) Dec(int64) { + panic("Dec called on a CounterSnapshot") +} + +// Inc panics. +func (CounterSnapshot) Inc(int64) { + panic("Inc called on a CounterSnapshot") +} + +// Snapshot returns the snapshot. +func (c CounterSnapshot) Snapshot() Counter { return c } + +// NilCounter is a no-op Counter. +type NilCounter struct{} + +// Clear is a no-op. +func (NilCounter) Clear() {} + +// Count is a no-op. +func (NilCounter) Count() int64 { return 0 } + +// Dec is a no-op. +func (NilCounter) Dec(i int64) {} + +// Inc is a no-op. +func (NilCounter) Inc(i int64) {} + +// Snapshot is a no-op. +func (NilCounter) Snapshot() Counter { return NilCounter{} } + +// StandardCounter is the standard implementation of a Counter and uses the +// sync/atomic package to manage a single int64 value. +type StandardCounter struct { + count int64 +} + +// Clear sets the counter to zero. +func (c *StandardCounter) Clear() { + atomic.StoreInt64(&c.count, 0) +} + +// Count returns the current count. +func (c *StandardCounter) Count() int64 { + return atomic.LoadInt64(&c.count) +} + +// Dec decrements the counter by the given amount. +func (c *StandardCounter) Dec(i int64) { + atomic.AddInt64(&c.count, -i) +} + +// Inc increments the counter by the given amount. +func (c *StandardCounter) Inc(i int64) { + atomic.AddInt64(&c.count, i) +} + +// Snapshot returns a read-only copy of the counter. +func (c *StandardCounter) Snapshot() Counter { + return CounterSnapshot(c.Count()) +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/counter_test.go b/vendor/src/github.com/rcrowley/go-metrics/counter_test.go new file mode 100644 index 00000000..dfb03b4e --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/counter_test.go @@ -0,0 +1,77 @@ +package metrics + +import "testing" + +func BenchmarkCounter(b *testing.B) { + c := NewCounter() + b.ResetTimer() + for i := 0; i < b.N; i++ { + c.Inc(1) + } +} + +func TestCounterClear(t *testing.T) { + c := NewCounter() + c.Inc(1) + c.Clear() + if count := c.Count(); 0 != count { + t.Errorf("c.Count(): 0 != %v\n", count) + } +} + +func TestCounterDec1(t *testing.T) { + c := NewCounter() + c.Dec(1) + if count := c.Count(); -1 != count { + t.Errorf("c.Count(): -1 != %v\n", count) + } +} + +func TestCounterDec2(t *testing.T) { + c := NewCounter() + c.Dec(2) + if count := c.Count(); -2 != count { + t.Errorf("c.Count(): -2 != %v\n", count) + } +} + +func TestCounterInc1(t *testing.T) { + c := NewCounter() + c.Inc(1) + if count := c.Count(); 1 != count { + t.Errorf("c.Count(): 1 != %v\n", count) + } +} + +func TestCounterInc2(t *testing.T) { + c := NewCounter() + c.Inc(2) + if count := c.Count(); 2 != count { + t.Errorf("c.Count(): 2 != %v\n", count) + } +} + +func TestCounterSnapshot(t *testing.T) { + c := NewCounter() + c.Inc(1) + snapshot := c.Snapshot() + c.Inc(1) + if count := snapshot.Count(); 1 != count { + t.Errorf("c.Count(): 1 != %v\n", count) + } +} + +func TestCounterZero(t *testing.T) { + c := NewCounter() + if count := c.Count(); 0 != count { + t.Errorf("c.Count(): 0 != %v\n", count) + } +} + +func TestGetOrRegisterCounter(t *testing.T) { + r := NewRegistry() + NewRegisteredCounter("foo", r).Inc(47) + if c := GetOrRegisterCounter("foo", r); 47 != c.Count() { + t.Fatal(c) + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/debug.go b/vendor/src/github.com/rcrowley/go-metrics/debug.go new file mode 100644 index 00000000..043ccefa --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/debug.go @@ -0,0 +1,76 @@ +package metrics + +import ( + "runtime/debug" + "time" +) + +var ( + debugMetrics struct { + GCStats struct { + LastGC Gauge + NumGC Gauge + Pause Histogram + //PauseQuantiles Histogram + PauseTotal Gauge + } + ReadGCStats Timer + } + gcStats debug.GCStats +) + +// Capture new values for the Go garbage collector statistics exported in +// debug.GCStats. This is designed to be called as a goroutine. +func CaptureDebugGCStats(r Registry, d time.Duration) { + for _ = range time.Tick(d) { + CaptureDebugGCStatsOnce(r) + } +} + +// Capture new values for the Go garbage collector statistics exported in +// debug.GCStats. This is designed to be called in a background goroutine. +// Giving a registry which has not been given to RegisterDebugGCStats will +// panic. +// +// Be careful (but much less so) with this because debug.ReadGCStats calls +// the C function runtime·lock(runtime·mheap) which, while not a stop-the-world +// operation, isn't something you want to be doing all the time. +func CaptureDebugGCStatsOnce(r Registry) { + lastGC := gcStats.LastGC + t := time.Now() + debug.ReadGCStats(&gcStats) + debugMetrics.ReadGCStats.UpdateSince(t) + + debugMetrics.GCStats.LastGC.Update(int64(gcStats.LastGC.UnixNano())) + debugMetrics.GCStats.NumGC.Update(int64(gcStats.NumGC)) + if lastGC != gcStats.LastGC && 0 < len(gcStats.Pause) { + debugMetrics.GCStats.Pause.Update(int64(gcStats.Pause[0])) + } + //debugMetrics.GCStats.PauseQuantiles.Update(gcStats.PauseQuantiles) + debugMetrics.GCStats.PauseTotal.Update(int64(gcStats.PauseTotal)) +} + +// Register metrics for the Go garbage collector statistics exported in +// debug.GCStats. The metrics are named by their fully-qualified Go symbols, +// i.e. debug.GCStats.PauseTotal. +func RegisterDebugGCStats(r Registry) { + debugMetrics.GCStats.LastGC = NewGauge() + debugMetrics.GCStats.NumGC = NewGauge() + debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015)) + //debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015)) + debugMetrics.GCStats.PauseTotal = NewGauge() + debugMetrics.ReadGCStats = NewTimer() + + r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC) + r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC) + r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause) + //r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles) + r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal) + r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats) +} + +// Allocate an initial slice for gcStats.Pause to avoid allocations during +// normal operation. +func init() { + gcStats.Pause = make([]time.Duration, 11) +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/debug_test.go b/vendor/src/github.com/rcrowley/go-metrics/debug_test.go new file mode 100644 index 00000000..07eb8678 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/debug_test.go @@ -0,0 +1,48 @@ +package metrics + +import ( + "runtime" + "runtime/debug" + "testing" + "time" +) + +func BenchmarkDebugGCStats(b *testing.B) { + r := NewRegistry() + RegisterDebugGCStats(r) + b.ResetTimer() + for i := 0; i < b.N; i++ { + CaptureDebugGCStatsOnce(r) + } +} + +func TestDebugGCStatsBlocking(t *testing.T) { + if g := runtime.GOMAXPROCS(0); g < 2 { + t.Skipf("skipping TestDebugGCMemStatsBlocking with GOMAXPROCS=%d\n", g) + return + } + ch := make(chan int) + go testDebugGCStatsBlocking(ch) + var gcStats debug.GCStats + t0 := time.Now() + debug.ReadGCStats(&gcStats) + t1 := time.Now() + t.Log("i++ during debug.ReadGCStats:", <-ch) + go testDebugGCStatsBlocking(ch) + d := t1.Sub(t0) + t.Log(d) + time.Sleep(d) + t.Log("i++ during time.Sleep:", <-ch) +} + +func testDebugGCStatsBlocking(ch chan int) { + i := 0 + for { + select { + case ch <- i: + return + default: + i++ + } + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/ewma.go b/vendor/src/github.com/rcrowley/go-metrics/ewma.go new file mode 100644 index 00000000..694a1d03 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/ewma.go @@ -0,0 +1,118 @@ +package metrics + +import ( + "math" + "sync" + "sync/atomic" +) + +// EWMAs continuously calculate an exponentially-weighted moving average +// based on an outside source of clock ticks. +type EWMA interface { + Rate() float64 + Snapshot() EWMA + Tick() + Update(int64) +} + +// NewEWMA constructs a new EWMA with the given alpha. +func NewEWMA(alpha float64) EWMA { + if UseNilMetrics { + return NilEWMA{} + } + return &StandardEWMA{alpha: alpha} +} + +// NewEWMA1 constructs a new EWMA for a one-minute moving average. +func NewEWMA1() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/1)) +} + +// NewEWMA5 constructs a new EWMA for a five-minute moving average. +func NewEWMA5() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/5)) +} + +// NewEWMA15 constructs a new EWMA for a fifteen-minute moving average. +func NewEWMA15() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/15)) +} + +// EWMASnapshot is a read-only copy of another EWMA. +type EWMASnapshot float64 + +// Rate returns the rate of events per second at the time the snapshot was +// taken. +func (a EWMASnapshot) Rate() float64 { return float64(a) } + +// Snapshot returns the snapshot. +func (a EWMASnapshot) Snapshot() EWMA { return a } + +// Tick panics. +func (EWMASnapshot) Tick() { + panic("Tick called on an EWMASnapshot") +} + +// Update panics. +func (EWMASnapshot) Update(int64) { + panic("Update called on an EWMASnapshot") +} + +// NilEWMA is a no-op EWMA. +type NilEWMA struct{} + +// Rate is a no-op. +func (NilEWMA) Rate() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilEWMA) Snapshot() EWMA { return NilEWMA{} } + +// Tick is a no-op. +func (NilEWMA) Tick() {} + +// Update is a no-op. +func (NilEWMA) Update(n int64) {} + +// StandardEWMA is the standard implementation of an EWMA and tracks the number +// of uncounted events and processes them on each tick. It uses the +// sync/atomic package to manage uncounted events. +type StandardEWMA struct { + uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment + alpha float64 + rate float64 + init bool + mutex sync.Mutex +} + +// Rate returns the moving average rate of events per second. +func (a *StandardEWMA) Rate() float64 { + a.mutex.Lock() + defer a.mutex.Unlock() + return a.rate * float64(1e9) +} + +// Snapshot returns a read-only copy of the EWMA. +func (a *StandardEWMA) Snapshot() EWMA { + return EWMASnapshot(a.Rate()) +} + +// Tick ticks the clock to update the moving average. It assumes it is called +// every five seconds. +func (a *StandardEWMA) Tick() { + count := atomic.LoadInt64(&a.uncounted) + atomic.AddInt64(&a.uncounted, -count) + instantRate := float64(count) / float64(5e9) + a.mutex.Lock() + defer a.mutex.Unlock() + if a.init { + a.rate += a.alpha * (instantRate - a.rate) + } else { + a.init = true + a.rate = instantRate + } +} + +// Update adds n uncounted events. +func (a *StandardEWMA) Update(n int64) { + atomic.AddInt64(&a.uncounted, n) +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/ewma_test.go b/vendor/src/github.com/rcrowley/go-metrics/ewma_test.go new file mode 100644 index 00000000..0430fbd2 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/ewma_test.go @@ -0,0 +1,225 @@ +package metrics + +import "testing" + +func BenchmarkEWMA(b *testing.B) { + a := NewEWMA1() + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Update(1) + a.Tick() + } +} + +func TestEWMA1(t *testing.T) { + a := NewEWMA1() + a.Update(3) + a.Tick() + if rate := a.Rate(); 0.6 != rate { + t.Errorf("initial a.Rate(): 0.6 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.22072766470286553 != rate { + t.Errorf("1 minute a.Rate(): 0.22072766470286553 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.08120116994196772 != rate { + t.Errorf("2 minute a.Rate(): 0.08120116994196772 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.029872241020718428 != rate { + t.Errorf("3 minute a.Rate(): 0.029872241020718428 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.01098938333324054 != rate { + t.Errorf("4 minute a.Rate(): 0.01098938333324054 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.004042768199451294 != rate { + t.Errorf("5 minute a.Rate(): 0.004042768199451294 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.0014872513059998212 != rate { + t.Errorf("6 minute a.Rate(): 0.0014872513059998212 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.0005471291793327122 != rate { + t.Errorf("7 minute a.Rate(): 0.0005471291793327122 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.00020127757674150815 != rate { + t.Errorf("8 minute a.Rate(): 0.00020127757674150815 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 7.404588245200814e-05 != rate { + t.Errorf("9 minute a.Rate(): 7.404588245200814e-05 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 2.7239957857491083e-05 != rate { + t.Errorf("10 minute a.Rate(): 2.7239957857491083e-05 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 1.0021020474147462e-05 != rate { + t.Errorf("11 minute a.Rate(): 1.0021020474147462e-05 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 3.6865274119969525e-06 != rate { + t.Errorf("12 minute a.Rate(): 3.6865274119969525e-06 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 1.3561976441886433e-06 != rate { + t.Errorf("13 minute a.Rate(): 1.3561976441886433e-06 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 4.989172314621449e-07 != rate { + t.Errorf("14 minute a.Rate(): 4.989172314621449e-07 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 1.8354139230109722e-07 != rate { + t.Errorf("15 minute a.Rate(): 1.8354139230109722e-07 != %v\n", rate) + } +} + +func TestEWMA5(t *testing.T) { + a := NewEWMA5() + a.Update(3) + a.Tick() + if rate := a.Rate(); 0.6 != rate { + t.Errorf("initial a.Rate(): 0.6 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.49123845184678905 != rate { + t.Errorf("1 minute a.Rate(): 0.49123845184678905 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.4021920276213837 != rate { + t.Errorf("2 minute a.Rate(): 0.4021920276213837 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.32928698165641596 != rate { + t.Errorf("3 minute a.Rate(): 0.32928698165641596 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.269597378470333 != rate { + t.Errorf("4 minute a.Rate(): 0.269597378470333 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.2207276647028654 != rate { + t.Errorf("5 minute a.Rate(): 0.2207276647028654 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.18071652714732128 != rate { + t.Errorf("6 minute a.Rate(): 0.18071652714732128 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.14795817836496392 != rate { + t.Errorf("7 minute a.Rate(): 0.14795817836496392 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.12113791079679326 != rate { + t.Errorf("8 minute a.Rate(): 0.12113791079679326 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.09917933293295193 != rate { + t.Errorf("9 minute a.Rate(): 0.09917933293295193 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.08120116994196763 != rate { + t.Errorf("10 minute a.Rate(): 0.08120116994196763 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.06648189501740036 != rate { + t.Errorf("11 minute a.Rate(): 0.06648189501740036 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.05443077197364752 != rate { + t.Errorf("12 minute a.Rate(): 0.05443077197364752 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.04456414692860035 != rate { + t.Errorf("13 minute a.Rate(): 0.04456414692860035 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.03648603757513079 != rate { + t.Errorf("14 minute a.Rate(): 0.03648603757513079 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.0298722410207183831020718428 != rate { + t.Errorf("15 minute a.Rate(): 0.0298722410207183831020718428 != %v\n", rate) + } +} + +func TestEWMA15(t *testing.T) { + a := NewEWMA15() + a.Update(3) + a.Tick() + if rate := a.Rate(); 0.6 != rate { + t.Errorf("initial a.Rate(): 0.6 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.5613041910189706 != rate { + t.Errorf("1 minute a.Rate(): 0.5613041910189706 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.5251039914257684 != rate { + t.Errorf("2 minute a.Rate(): 0.5251039914257684 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.4912384518467888184678905 != rate { + t.Errorf("3 minute a.Rate(): 0.4912384518467888184678905 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.459557003018789 != rate { + t.Errorf("4 minute a.Rate(): 0.459557003018789 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.4299187863442732 != rate { + t.Errorf("5 minute a.Rate(): 0.4299187863442732 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.4021920276213831 != rate { + t.Errorf("6 minute a.Rate(): 0.4021920276213831 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.37625345116383313 != rate { + t.Errorf("7 minute a.Rate(): 0.37625345116383313 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.3519877317060185 != rate { + t.Errorf("8 minute a.Rate(): 0.3519877317060185 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.3292869816564153165641596 != rate { + t.Errorf("9 minute a.Rate(): 0.3292869816564153165641596 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.3080502714195546 != rate { + t.Errorf("10 minute a.Rate(): 0.3080502714195546 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.2881831806538789 != rate { + t.Errorf("11 minute a.Rate(): 0.2881831806538789 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.26959737847033216 != rate { + t.Errorf("12 minute a.Rate(): 0.26959737847033216 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.2522102307052083 != rate { + t.Errorf("13 minute a.Rate(): 0.2522102307052083 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.23594443252115815 != rate { + t.Errorf("14 minute a.Rate(): 0.23594443252115815 != %v\n", rate) + } + elapseMinute(a) + if rate := a.Rate(); 0.2207276647028646247028654470286553 != rate { + t.Errorf("15 minute a.Rate(): 0.2207276647028646247028654470286553 != %v\n", rate) + } +} + +func elapseMinute(a EWMA) { + for i := 0; i < 12; i++ { + a.Tick() + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/exp/exp.go b/vendor/src/github.com/rcrowley/go-metrics/exp/exp.go new file mode 100644 index 00000000..11dd3f89 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/exp/exp.go @@ -0,0 +1,156 @@ +// Hook go-metrics into expvar +// on any /debug/metrics request, load all vars from the registry into expvar, and execute regular expvar handler +package exp + +import ( + "expvar" + "fmt" + "net/http" + "sync" + + "github.com/rcrowley/go-metrics" +) + +type exp struct { + expvarLock sync.Mutex // expvar panics if you try to register the same var twice, so we must probe it safely + registry metrics.Registry +} + +func (exp *exp) expHandler(w http.ResponseWriter, r *http.Request) { + // load our variables into expvar + exp.syncToExpvar() + + // now just run the official expvar handler code (which is not publicly callable, so pasted inline) + w.Header().Set("Content-Type", "application/json; charset=utf-8") + fmt.Fprintf(w, "{\n") + first := true + expvar.Do(func(kv expvar.KeyValue) { + if !first { + fmt.Fprintf(w, ",\n") + } + first = false + fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value) + }) + fmt.Fprintf(w, "\n}\n") +} + +// Exp will register an expvar powered metrics handler with http.DefaultServeMux on "/debug/vars" +func Exp(r metrics.Registry) { + h := ExpHandler(r) + // this would cause a panic: + // panic: http: multiple registrations for /debug/vars + // http.HandleFunc("/debug/vars", e.expHandler) + // haven't found an elegant way, so just use a different endpoint + http.Handle("/debug/metrics", h) +} + +// ExpHandler will return an expvar powered metrics handler. +func ExpHandler(r metrics.Registry) http.Handler { + e := exp{sync.Mutex{}, r} + return http.HandlerFunc(e.expHandler) +} + +func (exp *exp) getInt(name string) *expvar.Int { + var v *expvar.Int + exp.expvarLock.Lock() + p := expvar.Get(name) + if p != nil { + v = p.(*expvar.Int) + } else { + v = new(expvar.Int) + expvar.Publish(name, v) + } + exp.expvarLock.Unlock() + return v +} + +func (exp *exp) getFloat(name string) *expvar.Float { + var v *expvar.Float + exp.expvarLock.Lock() + p := expvar.Get(name) + if p != nil { + v = p.(*expvar.Float) + } else { + v = new(expvar.Float) + expvar.Publish(name, v) + } + exp.expvarLock.Unlock() + return v +} + +func (exp *exp) publishCounter(name string, metric metrics.Counter) { + v := exp.getInt(name) + v.Set(metric.Count()) +} + +func (exp *exp) publishGauge(name string, metric metrics.Gauge) { + v := exp.getInt(name) + v.Set(metric.Value()) +} +func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64) { + exp.getFloat(name).Set(metric.Value()) +} + +func (exp *exp) publishHistogram(name string, metric metrics.Histogram) { + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + exp.getInt(name + ".count").Set(h.Count()) + exp.getFloat(name + ".min").Set(float64(h.Min())) + exp.getFloat(name + ".max").Set(float64(h.Max())) + exp.getFloat(name + ".mean").Set(float64(h.Mean())) + exp.getFloat(name + ".std-dev").Set(float64(h.StdDev())) + exp.getFloat(name + ".50-percentile").Set(float64(ps[0])) + exp.getFloat(name + ".75-percentile").Set(float64(ps[1])) + exp.getFloat(name + ".95-percentile").Set(float64(ps[2])) + exp.getFloat(name + ".99-percentile").Set(float64(ps[3])) + exp.getFloat(name + ".999-percentile").Set(float64(ps[4])) +} + +func (exp *exp) publishMeter(name string, metric metrics.Meter) { + m := metric.Snapshot() + exp.getInt(name + ".count").Set(m.Count()) + exp.getFloat(name + ".one-minute").Set(float64(m.Rate1())) + exp.getFloat(name + ".five-minute").Set(float64(m.Rate5())) + exp.getFloat(name + ".fifteen-minute").Set(float64((m.Rate15()))) + exp.getFloat(name + ".mean").Set(float64(m.RateMean())) +} + +func (exp *exp) publishTimer(name string, metric metrics.Timer) { + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + exp.getInt(name + ".count").Set(t.Count()) + exp.getFloat(name + ".min").Set(float64(t.Min())) + exp.getFloat(name + ".max").Set(float64(t.Max())) + exp.getFloat(name + ".mean").Set(float64(t.Mean())) + exp.getFloat(name + ".std-dev").Set(float64(t.StdDev())) + exp.getFloat(name + ".50-percentile").Set(float64(ps[0])) + exp.getFloat(name + ".75-percentile").Set(float64(ps[1])) + exp.getFloat(name + ".95-percentile").Set(float64(ps[2])) + exp.getFloat(name + ".99-percentile").Set(float64(ps[3])) + exp.getFloat(name + ".999-percentile").Set(float64(ps[4])) + exp.getFloat(name + ".one-minute").Set(float64(t.Rate1())) + exp.getFloat(name + ".five-minute").Set(float64(t.Rate5())) + exp.getFloat(name + ".fifteen-minute").Set(float64((t.Rate15()))) + exp.getFloat(name + ".mean-rate").Set(float64(t.RateMean())) +} + +func (exp *exp) syncToExpvar() { + exp.registry.Each(func(name string, i interface{}) { + switch i.(type) { + case metrics.Counter: + exp.publishCounter(name, i.(metrics.Counter)) + case metrics.Gauge: + exp.publishGauge(name, i.(metrics.Gauge)) + case metrics.GaugeFloat64: + exp.publishGaugeFloat64(name, i.(metrics.GaugeFloat64)) + case metrics.Histogram: + exp.publishHistogram(name, i.(metrics.Histogram)) + case metrics.Meter: + exp.publishMeter(name, i.(metrics.Meter)) + case metrics.Timer: + exp.publishTimer(name, i.(metrics.Timer)) + default: + panic(fmt.Sprintf("unsupported type for '%s': %T", name, i)) + } + }) +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/gauge.go b/vendor/src/github.com/rcrowley/go-metrics/gauge.go new file mode 100644 index 00000000..cb57a938 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/gauge.go @@ -0,0 +1,120 @@ +package metrics + +import "sync/atomic" + +// Gauges hold an int64 value that can be set arbitrarily. +type Gauge interface { + Snapshot() Gauge + Update(int64) + Value() int64 +} + +// GetOrRegisterGauge returns an existing Gauge or constructs and registers a +// new StandardGauge. +func GetOrRegisterGauge(name string, r Registry) Gauge { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewGauge).(Gauge) +} + +// NewGauge constructs a new StandardGauge. +func NewGauge() Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &StandardGauge{0} +} + +// NewRegisteredGauge constructs and registers a new StandardGauge. +func NewRegisteredGauge(name string, r Registry) Gauge { + c := NewGauge() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGauge(f func() int64) Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &FunctionalGauge{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGauge(name string, r Registry, f func() int64) Gauge { + c := NewFunctionalGauge(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// GaugeSnapshot is a read-only copy of another Gauge. +type GaugeSnapshot int64 + +// Snapshot returns the snapshot. +func (g GaugeSnapshot) Snapshot() Gauge { return g } + +// Update panics. +func (GaugeSnapshot) Update(int64) { + panic("Update called on a GaugeSnapshot") +} + +// Value returns the value at the time the snapshot was taken. +func (g GaugeSnapshot) Value() int64 { return int64(g) } + +// NilGauge is a no-op Gauge. +type NilGauge struct{} + +// Snapshot is a no-op. +func (NilGauge) Snapshot() Gauge { return NilGauge{} } + +// Update is a no-op. +func (NilGauge) Update(v int64) {} + +// Value is a no-op. +func (NilGauge) Value() int64 { return 0 } + +// StandardGauge is the standard implementation of a Gauge and uses the +// sync/atomic package to manage a single int64 value. +type StandardGauge struct { + value int64 +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardGauge) Snapshot() Gauge { + return GaugeSnapshot(g.Value()) +} + +// Update updates the gauge's value. +func (g *StandardGauge) Update(v int64) { + atomic.StoreInt64(&g.value, v) +} + +// Value returns the gauge's current value. +func (g *StandardGauge) Value() int64 { + return atomic.LoadInt64(&g.value) +} + +// FunctionalGauge returns value from given function +type FunctionalGauge struct { + value func() int64 +} + +// Value returns the gauge's current value. +func (g FunctionalGauge) Value() int64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) } + +// Update panics. +func (FunctionalGauge) Update(int64) { + panic("Update called on a FunctionalGauge") +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/gauge_float64.go b/vendor/src/github.com/rcrowley/go-metrics/gauge_float64.go new file mode 100644 index 00000000..6f93920b --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/gauge_float64.go @@ -0,0 +1,127 @@ +package metrics + +import "sync" + +// GaugeFloat64s hold a float64 value that can be set arbitrarily. +type GaugeFloat64 interface { + Snapshot() GaugeFloat64 + Update(float64) + Value() float64 +} + +// GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a +// new StandardGaugeFloat64. +func GetOrRegisterGaugeFloat64(name string, r Registry) GaugeFloat64 { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewGaugeFloat64()).(GaugeFloat64) +} + +// NewGaugeFloat64 constructs a new StandardGaugeFloat64. +func NewGaugeFloat64() GaugeFloat64 { + if UseNilMetrics { + return NilGaugeFloat64{} + } + return &StandardGaugeFloat64{ + value: 0.0, + } +} + +// NewRegisteredGaugeFloat64 constructs and registers a new StandardGaugeFloat64. +func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 { + c := NewGaugeFloat64() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGaugeFloat64(f func() float64) GaugeFloat64 { + if UseNilMetrics { + return NilGaugeFloat64{} + } + return &FunctionalGaugeFloat64{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGaugeFloat64(name string, r Registry, f func() float64) GaugeFloat64 { + c := NewFunctionalGaugeFloat64(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// GaugeFloat64Snapshot is a read-only copy of another GaugeFloat64. +type GaugeFloat64Snapshot float64 + +// Snapshot returns the snapshot. +func (g GaugeFloat64Snapshot) Snapshot() GaugeFloat64 { return g } + +// Update panics. +func (GaugeFloat64Snapshot) Update(float64) { + panic("Update called on a GaugeFloat64Snapshot") +} + +// Value returns the value at the time the snapshot was taken. +func (g GaugeFloat64Snapshot) Value() float64 { return float64(g) } + +// NilGauge is a no-op Gauge. +type NilGaugeFloat64 struct{} + +// Snapshot is a no-op. +func (NilGaugeFloat64) Snapshot() GaugeFloat64 { return NilGaugeFloat64{} } + +// Update is a no-op. +func (NilGaugeFloat64) Update(v float64) {} + +// Value is a no-op. +func (NilGaugeFloat64) Value() float64 { return 0.0 } + +// StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses +// sync.Mutex to manage a single float64 value. +type StandardGaugeFloat64 struct { + mutex sync.Mutex + value float64 +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 { + return GaugeFloat64Snapshot(g.Value()) +} + +// Update updates the gauge's value. +func (g *StandardGaugeFloat64) Update(v float64) { + g.mutex.Lock() + defer g.mutex.Unlock() + g.value = v +} + +// Value returns the gauge's current value. +func (g *StandardGaugeFloat64) Value() float64 { + g.mutex.Lock() + defer g.mutex.Unlock() + return g.value +} + +// FunctionalGaugeFloat64 returns value from given function +type FunctionalGaugeFloat64 struct { + value func() float64 +} + +// Value returns the gauge's current value. +func (g FunctionalGaugeFloat64) Value() float64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGaugeFloat64) Snapshot() GaugeFloat64 { return GaugeFloat64Snapshot(g.Value()) } + +// Update panics. +func (FunctionalGaugeFloat64) Update(float64) { + panic("Update called on a FunctionalGaugeFloat64") +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/gauge_float64_test.go b/vendor/src/github.com/rcrowley/go-metrics/gauge_float64_test.go new file mode 100644 index 00000000..99e62a40 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/gauge_float64_test.go @@ -0,0 +1,59 @@ +package metrics + +import "testing" + +func BenchmarkGuageFloat64(b *testing.B) { + g := NewGaugeFloat64() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g.Update(float64(i)) + } +} + +func TestGaugeFloat64(t *testing.T) { + g := NewGaugeFloat64() + g.Update(float64(47.0)) + if v := g.Value(); float64(47.0) != v { + t.Errorf("g.Value(): 47.0 != %v\n", v) + } +} + +func TestGaugeFloat64Snapshot(t *testing.T) { + g := NewGaugeFloat64() + g.Update(float64(47.0)) + snapshot := g.Snapshot() + g.Update(float64(0)) + if v := snapshot.Value(); float64(47.0) != v { + t.Errorf("g.Value(): 47.0 != %v\n", v) + } +} + +func TestGetOrRegisterGaugeFloat64(t *testing.T) { + r := NewRegistry() + NewRegisteredGaugeFloat64("foo", r).Update(float64(47.0)) + t.Logf("registry: %v", r) + if g := GetOrRegisterGaugeFloat64("foo", r); float64(47.0) != g.Value() { + t.Fatal(g) + } +} + +func TestFunctionalGaugeFloat64(t *testing.T) { + var counter float64 + fg := NewFunctionalGaugeFloat64(func() float64 { + counter++ + return counter + }) + fg.Value() + fg.Value() + if counter != 2 { + t.Error("counter != 2") + } +} + +func TestGetOrRegisterFunctionalGaugeFloat64(t *testing.T) { + r := NewRegistry() + NewRegisteredFunctionalGaugeFloat64("foo", r, func() float64 { return 47 }) + if g := GetOrRegisterGaugeFloat64("foo", r); 47 != g.Value() { + t.Fatal(g) + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/gauge_test.go b/vendor/src/github.com/rcrowley/go-metrics/gauge_test.go new file mode 100644 index 00000000..1f2603d3 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/gauge_test.go @@ -0,0 +1,68 @@ +package metrics + +import ( + "fmt" + "testing" +) + +func BenchmarkGuage(b *testing.B) { + g := NewGauge() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g.Update(int64(i)) + } +} + +func TestGauge(t *testing.T) { + g := NewGauge() + g.Update(int64(47)) + if v := g.Value(); 47 != v { + t.Errorf("g.Value(): 47 != %v\n", v) + } +} + +func TestGaugeSnapshot(t *testing.T) { + g := NewGauge() + g.Update(int64(47)) + snapshot := g.Snapshot() + g.Update(int64(0)) + if v := snapshot.Value(); 47 != v { + t.Errorf("g.Value(): 47 != %v\n", v) + } +} + +func TestGetOrRegisterGauge(t *testing.T) { + r := NewRegistry() + NewRegisteredGauge("foo", r).Update(47) + if g := GetOrRegisterGauge("foo", r); 47 != g.Value() { + t.Fatal(g) + } +} + +func TestFunctionalGauge(t *testing.T) { + var counter int64 + fg := NewFunctionalGauge(func() int64 { + counter++ + return counter + }) + fg.Value() + fg.Value() + if counter != 2 { + t.Error("counter != 2") + } +} + +func TestGetOrRegisterFunctionalGauge(t *testing.T) { + r := NewRegistry() + NewRegisteredFunctionalGauge("foo", r, func() int64 { return 47 }) + if g := GetOrRegisterGauge("foo", r); 47 != g.Value() { + t.Fatal(g) + } +} + +func ExampleGetOrRegisterGauge() { + m := "server.bytes_sent" + g := GetOrRegisterGauge(m, nil) + g.Update(47) + fmt.Println(g.Value()) // Output: 47 +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/graphite.go b/vendor/src/github.com/rcrowley/go-metrics/graphite.go new file mode 100644 index 00000000..abd0a7d2 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/graphite.go @@ -0,0 +1,113 @@ +package metrics + +import ( + "bufio" + "fmt" + "log" + "net" + "strconv" + "strings" + "time" +) + +// GraphiteConfig provides a container with configuration parameters for +// the Graphite exporter +type GraphiteConfig struct { + Addr *net.TCPAddr // Network address to connect to + Registry Registry // Registry to be exported + FlushInterval time.Duration // Flush interval + DurationUnit time.Duration // Time conversion unit for durations + Prefix string // Prefix to be prepended to metric names + Percentiles []float64 // Percentiles to export from timers and histograms +} + +// Graphite is a blocking exporter function which reports metrics in r +// to a graphite server located at addr, flushing them every d duration +// and prepending metric names with prefix. +func Graphite(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { + GraphiteWithConfig(GraphiteConfig{ + Addr: addr, + Registry: r, + FlushInterval: d, + DurationUnit: time.Nanosecond, + Prefix: prefix, + Percentiles: []float64{0.5, 0.75, 0.95, 0.99, 0.999}, + }) +} + +// GraphiteWithConfig is a blocking exporter function just like Graphite, +// but it takes a GraphiteConfig instead. +func GraphiteWithConfig(c GraphiteConfig) { + log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015") + for _ = range time.Tick(c.FlushInterval) { + if err := graphite(&c); nil != err { + log.Println(err) + } + } +} + +// GraphiteOnce performs a single submission to Graphite, returning a +// non-nil error on failed connections. This can be used in a loop +// similar to GraphiteWithConfig for custom error handling. +func GraphiteOnce(c GraphiteConfig) error { + log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015") + return graphite(&c) +} + +func graphite(c *GraphiteConfig) error { + now := time.Now().Unix() + du := float64(c.DurationUnit) + conn, err := net.DialTCP("tcp", nil, c.Addr) + if nil != err { + return err + } + defer conn.Close() + w := bufio.NewWriter(conn) + c.Registry.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now) + case Gauge: + fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now) + case GaugeFloat64: + fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles(c.Percentiles) + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now) + fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now) + fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now) + fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now) + for psIdx, psKey := range c.Percentiles { + key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) + fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) + } + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now) + fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now) + fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now) + fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles(c.Percentiles) + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now) + fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now) + fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now) + fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now) + for psIdx, psKey := range c.Percentiles { + key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) + fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) + } + fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now) + fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now) + fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now) + fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now) + } + w.Flush() + }) + return nil +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/graphite_test.go b/vendor/src/github.com/rcrowley/go-metrics/graphite_test.go new file mode 100644 index 00000000..c797c781 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/graphite_test.go @@ -0,0 +1,22 @@ +package metrics + +import ( + "net" + "time" +) + +func ExampleGraphite() { + addr, _ := net.ResolveTCPAddr("net", ":2003") + go Graphite(DefaultRegistry, 1*time.Second, "some.prefix", addr) +} + +func ExampleGraphiteWithConfig() { + addr, _ := net.ResolveTCPAddr("net", ":2003") + go GraphiteWithConfig(GraphiteConfig{ + Addr: addr, + Registry: DefaultRegistry, + FlushInterval: 1 * time.Second, + DurationUnit: time.Millisecond, + Percentiles: []float64{0.5, 0.75, 0.99, 0.999}, + }) +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/healthcheck.go b/vendor/src/github.com/rcrowley/go-metrics/healthcheck.go new file mode 100644 index 00000000..445131ca --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/healthcheck.go @@ -0,0 +1,61 @@ +package metrics + +// Healthchecks hold an error value describing an arbitrary up/down status. +type Healthcheck interface { + Check() + Error() error + Healthy() + Unhealthy(error) +} + +// NewHealthcheck constructs a new Healthcheck which will use the given +// function to update its status. +func NewHealthcheck(f func(Healthcheck)) Healthcheck { + if UseNilMetrics { + return NilHealthcheck{} + } + return &StandardHealthcheck{nil, f} +} + +// NilHealthcheck is a no-op. +type NilHealthcheck struct{} + +// Check is a no-op. +func (NilHealthcheck) Check() {} + +// Error is a no-op. +func (NilHealthcheck) Error() error { return nil } + +// Healthy is a no-op. +func (NilHealthcheck) Healthy() {} + +// Unhealthy is a no-op. +func (NilHealthcheck) Unhealthy(error) {} + +// StandardHealthcheck is the standard implementation of a Healthcheck and +// stores the status and a function to call to update the status. +type StandardHealthcheck struct { + err error + f func(Healthcheck) +} + +// Check runs the healthcheck function to update the healthcheck's status. +func (h *StandardHealthcheck) Check() { + h.f(h) +} + +// Error returns the healthcheck's status, which will be nil if it is healthy. +func (h *StandardHealthcheck) Error() error { + return h.err +} + +// Healthy marks the healthcheck as healthy. +func (h *StandardHealthcheck) Healthy() { + h.err = nil +} + +// Unhealthy marks the healthcheck as unhealthy. The error is stored and +// may be retrieved by the Error method. +func (h *StandardHealthcheck) Unhealthy(err error) { + h.err = err +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/histogram.go b/vendor/src/github.com/rcrowley/go-metrics/histogram.go new file mode 100644 index 00000000..dbc837fe --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/histogram.go @@ -0,0 +1,202 @@ +package metrics + +// Histograms calculate distribution statistics from a series of int64 values. +type Histogram interface { + Clear() + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Sample() Sample + Snapshot() Histogram + StdDev() float64 + Sum() int64 + Update(int64) + Variance() float64 +} + +// GetOrRegisterHistogram returns an existing Histogram or constructs and +// registers a new StandardHistogram. +func GetOrRegisterHistogram(name string, r Registry, s Sample) Histogram { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, func() Histogram { return NewHistogram(s) }).(Histogram) +} + +// NewHistogram constructs a new StandardHistogram from a Sample. +func NewHistogram(s Sample) Histogram { + if UseNilMetrics { + return NilHistogram{} + } + return &StandardHistogram{sample: s} +} + +// NewRegisteredHistogram constructs and registers a new StandardHistogram from +// a Sample. +func NewRegisteredHistogram(name string, r Registry, s Sample) Histogram { + c := NewHistogram(s) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// HistogramSnapshot is a read-only copy of another Histogram. +type HistogramSnapshot struct { + sample *SampleSnapshot +} + +// Clear panics. +func (*HistogramSnapshot) Clear() { + panic("Clear called on a HistogramSnapshot") +} + +// Count returns the number of samples recorded at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Count() int64 { return h.sample.Count() } + +// Max returns the maximum value in the sample at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Max() int64 { return h.sample.Max() } + +// Mean returns the mean of the values in the sample at the time the snapshot +// was taken. +func (h *HistogramSnapshot) Mean() float64 { return h.sample.Mean() } + +// Min returns the minimum value in the sample at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Min() int64 { return h.sample.Min() } + +// Percentile returns an arbitrary percentile of values in the sample at the +// time the snapshot was taken. +func (h *HistogramSnapshot) Percentile(p float64) float64 { + return h.sample.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the sample +// at the time the snapshot was taken. +func (h *HistogramSnapshot) Percentiles(ps []float64) []float64 { + return h.sample.Percentiles(ps) +} + +// Sample returns the Sample underlying the histogram. +func (h *HistogramSnapshot) Sample() Sample { return h.sample } + +// Snapshot returns the snapshot. +func (h *HistogramSnapshot) Snapshot() Histogram { return h } + +// StdDev returns the standard deviation of the values in the sample at the +// time the snapshot was taken. +func (h *HistogramSnapshot) StdDev() float64 { return h.sample.StdDev() } + +// Sum returns the sum in the sample at the time the snapshot was taken. +func (h *HistogramSnapshot) Sum() int64 { return h.sample.Sum() } + +// Update panics. +func (*HistogramSnapshot) Update(int64) { + panic("Update called on a HistogramSnapshot") +} + +// Variance returns the variance of inputs at the time the snapshot was taken. +func (h *HistogramSnapshot) Variance() float64 { return h.sample.Variance() } + +// NilHistogram is a no-op Histogram. +type NilHistogram struct{} + +// Clear is a no-op. +func (NilHistogram) Clear() {} + +// Count is a no-op. +func (NilHistogram) Count() int64 { return 0 } + +// Max is a no-op. +func (NilHistogram) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilHistogram) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilHistogram) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilHistogram) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilHistogram) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Sample is a no-op. +func (NilHistogram) Sample() Sample { return NilSample{} } + +// Snapshot is a no-op. +func (NilHistogram) Snapshot() Histogram { return NilHistogram{} } + +// StdDev is a no-op. +func (NilHistogram) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilHistogram) Sum() int64 { return 0 } + +// Update is a no-op. +func (NilHistogram) Update(v int64) {} + +// Variance is a no-op. +func (NilHistogram) Variance() float64 { return 0.0 } + +// StandardHistogram is the standard implementation of a Histogram and uses a +// Sample to bound its memory use. +type StandardHistogram struct { + sample Sample +} + +// Clear clears the histogram and its sample. +func (h *StandardHistogram) Clear() { h.sample.Clear() } + +// Count returns the number of samples recorded since the histogram was last +// cleared. +func (h *StandardHistogram) Count() int64 { return h.sample.Count() } + +// Max returns the maximum value in the sample. +func (h *StandardHistogram) Max() int64 { return h.sample.Max() } + +// Mean returns the mean of the values in the sample. +func (h *StandardHistogram) Mean() float64 { return h.sample.Mean() } + +// Min returns the minimum value in the sample. +func (h *StandardHistogram) Min() int64 { return h.sample.Min() } + +// Percentile returns an arbitrary percentile of the values in the sample. +func (h *StandardHistogram) Percentile(p float64) float64 { + return h.sample.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of the values in the +// sample. +func (h *StandardHistogram) Percentiles(ps []float64) []float64 { + return h.sample.Percentiles(ps) +} + +// Sample returns the Sample underlying the histogram. +func (h *StandardHistogram) Sample() Sample { return h.sample } + +// Snapshot returns a read-only copy of the histogram. +func (h *StandardHistogram) Snapshot() Histogram { + return &HistogramSnapshot{sample: h.sample.Snapshot().(*SampleSnapshot)} +} + +// StdDev returns the standard deviation of the values in the sample. +func (h *StandardHistogram) StdDev() float64 { return h.sample.StdDev() } + +// Sum returns the sum in the sample. +func (h *StandardHistogram) Sum() int64 { return h.sample.Sum() } + +// Update samples a new value. +func (h *StandardHistogram) Update(v int64) { h.sample.Update(v) } + +// Variance returns the variance of the values in the sample. +func (h *StandardHistogram) Variance() float64 { return h.sample.Variance() } diff --git a/vendor/src/github.com/rcrowley/go-metrics/histogram_test.go b/vendor/src/github.com/rcrowley/go-metrics/histogram_test.go new file mode 100644 index 00000000..d7f4f017 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/histogram_test.go @@ -0,0 +1,95 @@ +package metrics + +import "testing" + +func BenchmarkHistogram(b *testing.B) { + h := NewHistogram(NewUniformSample(100)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + h.Update(int64(i)) + } +} + +func TestGetOrRegisterHistogram(t *testing.T) { + r := NewRegistry() + s := NewUniformSample(100) + NewRegisteredHistogram("foo", r, s).Update(47) + if h := GetOrRegisterHistogram("foo", r, s); 1 != h.Count() { + t.Fatal(h) + } +} + +func TestHistogram10000(t *testing.T) { + h := NewHistogram(NewUniformSample(100000)) + for i := 1; i <= 10000; i++ { + h.Update(int64(i)) + } + testHistogram10000(t, h) +} + +func TestHistogramEmpty(t *testing.T) { + h := NewHistogram(NewUniformSample(100)) + if count := h.Count(); 0 != count { + t.Errorf("h.Count(): 0 != %v\n", count) + } + if min := h.Min(); 0 != min { + t.Errorf("h.Min(): 0 != %v\n", min) + } + if max := h.Max(); 0 != max { + t.Errorf("h.Max(): 0 != %v\n", max) + } + if mean := h.Mean(); 0.0 != mean { + t.Errorf("h.Mean(): 0.0 != %v\n", mean) + } + if stdDev := h.StdDev(); 0.0 != stdDev { + t.Errorf("h.StdDev(): 0.0 != %v\n", stdDev) + } + ps := h.Percentiles([]float64{0.5, 0.75, 0.99}) + if 0.0 != ps[0] { + t.Errorf("median: 0.0 != %v\n", ps[0]) + } + if 0.0 != ps[1] { + t.Errorf("75th percentile: 0.0 != %v\n", ps[1]) + } + if 0.0 != ps[2] { + t.Errorf("99th percentile: 0.0 != %v\n", ps[2]) + } +} + +func TestHistogramSnapshot(t *testing.T) { + h := NewHistogram(NewUniformSample(100000)) + for i := 1; i <= 10000; i++ { + h.Update(int64(i)) + } + snapshot := h.Snapshot() + h.Update(0) + testHistogram10000(t, snapshot) +} + +func testHistogram10000(t *testing.T, h Histogram) { + if count := h.Count(); 10000 != count { + t.Errorf("h.Count(): 10000 != %v\n", count) + } + if min := h.Min(); 1 != min { + t.Errorf("h.Min(): 1 != %v\n", min) + } + if max := h.Max(); 10000 != max { + t.Errorf("h.Max(): 10000 != %v\n", max) + } + if mean := h.Mean(); 5000.5 != mean { + t.Errorf("h.Mean(): 5000.5 != %v\n", mean) + } + if stdDev := h.StdDev(); 2886.751331514372 != stdDev { + t.Errorf("h.StdDev(): 2886.751331514372 != %v\n", stdDev) + } + ps := h.Percentiles([]float64{0.5, 0.75, 0.99}) + if 5000.5 != ps[0] { + t.Errorf("median: 5000.5 != %v\n", ps[0]) + } + if 7500.75 != ps[1] { + t.Errorf("75th percentile: 7500.75 != %v\n", ps[1]) + } + if 9900.99 != ps[2] { + t.Errorf("99th percentile: 9900.99 != %v\n", ps[2]) + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/json.go b/vendor/src/github.com/rcrowley/go-metrics/json.go new file mode 100644 index 00000000..2fdcbcfb --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/json.go @@ -0,0 +1,87 @@ +package metrics + +import ( + "encoding/json" + "io" + "time" +) + +// MarshalJSON returns a byte slice containing a JSON representation of all +// the metrics in the Registry. +func (r *StandardRegistry) MarshalJSON() ([]byte, error) { + data := make(map[string]map[string]interface{}) + r.Each(func(name string, i interface{}) { + values := make(map[string]interface{}) + switch metric := i.(type) { + case Counter: + values["count"] = metric.Count() + case Gauge: + values["value"] = metric.Value() + case GaugeFloat64: + values["value"] = metric.Value() + case Healthcheck: + values["error"] = nil + metric.Check() + if err := metric.Error(); nil != err { + values["error"] = metric.Error().Error() + } + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = h.Count() + values["min"] = h.Min() + values["max"] = h.Max() + values["mean"] = h.Mean() + values["stddev"] = h.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + case Meter: + m := metric.Snapshot() + values["count"] = m.Count() + values["1m.rate"] = m.Rate1() + values["5m.rate"] = m.Rate5() + values["15m.rate"] = m.Rate15() + values["mean.rate"] = m.RateMean() + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = t.Count() + values["min"] = t.Min() + values["max"] = t.Max() + values["mean"] = t.Mean() + values["stddev"] = t.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + values["1m.rate"] = t.Rate1() + values["5m.rate"] = t.Rate5() + values["15m.rate"] = t.Rate15() + values["mean.rate"] = t.RateMean() + } + data[name] = values + }) + return json.Marshal(data) +} + +// WriteJSON writes metrics from the given registry periodically to the +// specified io.Writer as JSON. +func WriteJSON(r Registry, d time.Duration, w io.Writer) { + for _ = range time.Tick(d) { + WriteJSONOnce(r, w) + } +} + +// WriteJSONOnce writes metrics from the given registry to the specified +// io.Writer as JSON. +func WriteJSONOnce(r Registry, w io.Writer) { + json.NewEncoder(w).Encode(r) +} + +func (p *PrefixedRegistry) MarshalJSON() ([]byte, error) { + return json.Marshal(p.underlying) +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/json_test.go b/vendor/src/github.com/rcrowley/go-metrics/json_test.go new file mode 100644 index 00000000..cf70051f --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/json_test.go @@ -0,0 +1,28 @@ +package metrics + +import ( + "bytes" + "encoding/json" + "testing" +) + +func TestRegistryMarshallJSON(t *testing.T) { + b := &bytes.Buffer{} + enc := json.NewEncoder(b) + r := NewRegistry() + r.Register("counter", NewCounter()) + enc.Encode(r) + if s := b.String(); "{\"counter\":{\"count\":0}}\n" != s { + t.Fatalf(s) + } +} + +func TestRegistryWriteJSONOnce(t *testing.T) { + r := NewRegistry() + r.Register("counter", NewCounter()) + b := &bytes.Buffer{} + WriteJSONOnce(r, b) + if s := b.String(); s != "{\"counter\":{\"count\":0}}\n" { + t.Fail() + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/librato/client.go b/vendor/src/github.com/rcrowley/go-metrics/librato/client.go new file mode 100644 index 00000000..8c0c850e --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/librato/client.go @@ -0,0 +1,102 @@ +package librato + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" +) + +const Operations = "operations" +const OperationsShort = "ops" + +type LibratoClient struct { + Email, Token string +} + +// property strings +const ( + // display attributes + Color = "color" + DisplayMax = "display_max" + DisplayMin = "display_min" + DisplayUnitsLong = "display_units_long" + DisplayUnitsShort = "display_units_short" + DisplayStacked = "display_stacked" + DisplayTransform = "display_transform" + // special gauge display attributes + SummarizeFunction = "summarize_function" + Aggregate = "aggregate" + + // metric keys + Name = "name" + Period = "period" + Description = "description" + DisplayName = "display_name" + Attributes = "attributes" + + // measurement keys + MeasureTime = "measure_time" + Source = "source" + Value = "value" + + // special gauge keys + Count = "count" + Sum = "sum" + Max = "max" + Min = "min" + SumSquares = "sum_squares" + + // batch keys + Counters = "counters" + Gauges = "gauges" + + MetricsPostUrl = "https://metrics-api.librato.com/v1/metrics" +) + +type Measurement map[string]interface{} +type Metric map[string]interface{} + +type Batch struct { + Gauges []Measurement `json:"gauges,omitempty"` + Counters []Measurement `json:"counters,omitempty"` + MeasureTime int64 `json:"measure_time"` + Source string `json:"source"` +} + +func (self *LibratoClient) PostMetrics(batch Batch) (err error) { + var ( + js []byte + req *http.Request + resp *http.Response + ) + + if len(batch.Counters) == 0 && len(batch.Gauges) == 0 { + return nil + } + + if js, err = json.Marshal(batch); err != nil { + return + } + + if req, err = http.NewRequest("POST", MetricsPostUrl, bytes.NewBuffer(js)); err != nil { + return + } + + req.Header.Set("Content-Type", "application/json") + req.SetBasicAuth(self.Email, self.Token) + + if resp, err = http.DefaultClient.Do(req); err != nil { + return + } + + if resp.StatusCode != http.StatusOK { + var body []byte + if body, err = ioutil.ReadAll(resp.Body); err != nil { + body = []byte(fmt.Sprintf("(could not fetch response body for error: %s)", err)) + } + err = fmt.Errorf("Unable to post to Librato: %d %s %s", resp.StatusCode, resp.Status, string(body)) + } + return +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/librato/librato.go b/vendor/src/github.com/rcrowley/go-metrics/librato/librato.go new file mode 100644 index 00000000..d7c05746 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/librato/librato.go @@ -0,0 +1,235 @@ +package librato + +import ( + "fmt" + "log" + "math" + "regexp" + "time" + + "github.com/rcrowley/go-metrics" +) + +// a regexp for extracting the unit from time.Duration.String +var unitRegexp = regexp.MustCompile("[^\\d]+$") + +// a helper that turns a time.Duration into librato display attributes for timer metrics +func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) { + attrs = make(map[string]interface{}) + attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d)) + attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String()))) + return +} + +type Reporter struct { + Email, Token string + Namespace string + Source string + Interval time.Duration + Registry metrics.Registry + Percentiles []float64 // percentiles to report on histogram metrics + TimerAttributes map[string]interface{} // units in which timers will be displayed + intervalSec int64 +} + +func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter { + return &Reporter{e, t, "", s, d, r, p, translateTimerAttributes(u), int64(d / time.Second)} +} + +func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) { + NewReporter(r, d, e, t, s, p, u).Run() +} + +func (self *Reporter) Run() { + log.Printf("WARNING: This client has been DEPRECATED! It has been moved to https://github.com/mihasya/go-metrics-librato and will be removed from rcrowley/go-metrics on August 5th 2015") + ticker := time.Tick(self.Interval) + metricsApi := &LibratoClient{self.Email, self.Token} + for now := range ticker { + var metrics Batch + var err error + if metrics, err = self.BuildRequest(now, self.Registry); err != nil { + log.Printf("ERROR constructing librato request body %s", err) + continue + } + if err := metricsApi.PostMetrics(metrics); err != nil { + log.Printf("ERROR sending metrics to librato %s", err) + continue + } + } +} + +// calculate sum of squares from data provided by metrics.Histogram +// see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods +func sumSquares(s metrics.Sample) float64 { + count := float64(s.Count()) + sumSquared := math.Pow(count*s.Mean(), 2) + sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count + if math.IsNaN(sumSquares) { + return 0.0 + } + return sumSquares +} +func sumSquaresTimer(t metrics.Timer) float64 { + count := float64(t.Count()) + sumSquared := math.Pow(count*t.Mean(), 2) + sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count + if math.IsNaN(sumSquares) { + return 0.0 + } + return sumSquares +} + +func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) { + snapshot = Batch{ + // coerce timestamps to a stepping fn so that they line up in Librato graphs + MeasureTime: (now.Unix() / self.intervalSec) * self.intervalSec, + Source: self.Source, + } + snapshot.Gauges = make([]Measurement, 0) + snapshot.Counters = make([]Measurement, 0) + histogramGaugeCount := 1 + len(self.Percentiles) + r.Each(func(name string, metric interface{}) { + if self.Namespace != "" { + name = fmt.Sprintf("%s.%s", self.Namespace, name) + } + measurement := Measurement{} + measurement[Period] = self.Interval.Seconds() + switch m := metric.(type) { + case metrics.Counter: + if m.Count() > 0 { + measurement[Name] = fmt.Sprintf("%s.%s", name, "count") + measurement[Value] = float64(m.Count()) + measurement[Attributes] = map[string]interface{}{ + DisplayUnitsLong: Operations, + DisplayUnitsShort: OperationsShort, + DisplayMin: "0", + } + snapshot.Counters = append(snapshot.Counters, measurement) + } + case metrics.Gauge: + measurement[Name] = name + measurement[Value] = float64(m.Value()) + snapshot.Gauges = append(snapshot.Gauges, measurement) + case metrics.GaugeFloat64: + measurement[Name] = name + measurement[Value] = float64(m.Value()) + snapshot.Gauges = append(snapshot.Gauges, measurement) + case metrics.Histogram: + if m.Count() > 0 { + gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount) + s := m.Sample() + measurement[Name] = fmt.Sprintf("%s.%s", name, "hist") + measurement[Count] = uint64(s.Count()) + measurement[Max] = float64(s.Max()) + measurement[Min] = float64(s.Min()) + measurement[Sum] = float64(s.Sum()) + measurement[SumSquares] = sumSquares(s) + gauges[0] = measurement + for i, p := range self.Percentiles { + gauges[i+1] = Measurement{ + Name: fmt.Sprintf("%s.%.2f", measurement[Name], p), + Value: s.Percentile(p), + Period: measurement[Period], + } + } + snapshot.Gauges = append(snapshot.Gauges, gauges...) + } + case metrics.Meter: + measurement[Name] = name + measurement[Value] = float64(m.Count()) + snapshot.Counters = append(snapshot.Counters, measurement) + snapshot.Gauges = append(snapshot.Gauges, + Measurement{ + Name: fmt.Sprintf("%s.%s", name, "1min"), + Value: m.Rate1(), + Period: int64(self.Interval.Seconds()), + Attributes: map[string]interface{}{ + DisplayUnitsLong: Operations, + DisplayUnitsShort: OperationsShort, + DisplayMin: "0", + }, + }, + Measurement{ + Name: fmt.Sprintf("%s.%s", name, "5min"), + Value: m.Rate5(), + Period: int64(self.Interval.Seconds()), + Attributes: map[string]interface{}{ + DisplayUnitsLong: Operations, + DisplayUnitsShort: OperationsShort, + DisplayMin: "0", + }, + }, + Measurement{ + Name: fmt.Sprintf("%s.%s", name, "15min"), + Value: m.Rate15(), + Period: int64(self.Interval.Seconds()), + Attributes: map[string]interface{}{ + DisplayUnitsLong: Operations, + DisplayUnitsShort: OperationsShort, + DisplayMin: "0", + }, + }, + ) + case metrics.Timer: + measurement[Name] = name + measurement[Value] = float64(m.Count()) + snapshot.Counters = append(snapshot.Counters, measurement) + if m.Count() > 0 { + libratoName := fmt.Sprintf("%s.%s", name, "timer.mean") + gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount) + gauges[0] = Measurement{ + Name: libratoName, + Count: uint64(m.Count()), + Sum: m.Mean() * float64(m.Count()), + Max: float64(m.Max()), + Min: float64(m.Min()), + SumSquares: sumSquaresTimer(m), + Period: int64(self.Interval.Seconds()), + Attributes: self.TimerAttributes, + } + for i, p := range self.Percentiles { + gauges[i+1] = Measurement{ + Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100), + Value: m.Percentile(p), + Period: int64(self.Interval.Seconds()), + Attributes: self.TimerAttributes, + } + } + snapshot.Gauges = append(snapshot.Gauges, gauges...) + snapshot.Gauges = append(snapshot.Gauges, + Measurement{ + Name: fmt.Sprintf("%s.%s", name, "rate.1min"), + Value: m.Rate1(), + Period: int64(self.Interval.Seconds()), + Attributes: map[string]interface{}{ + DisplayUnitsLong: Operations, + DisplayUnitsShort: OperationsShort, + DisplayMin: "0", + }, + }, + Measurement{ + Name: fmt.Sprintf("%s.%s", name, "rate.5min"), + Value: m.Rate5(), + Period: int64(self.Interval.Seconds()), + Attributes: map[string]interface{}{ + DisplayUnitsLong: Operations, + DisplayUnitsShort: OperationsShort, + DisplayMin: "0", + }, + }, + Measurement{ + Name: fmt.Sprintf("%s.%s", name, "rate.15min"), + Value: m.Rate15(), + Period: int64(self.Interval.Seconds()), + Attributes: map[string]interface{}{ + DisplayUnitsLong: Operations, + DisplayUnitsShort: OperationsShort, + DisplayMin: "0", + }, + }, + ) + } + } + }) + return +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/log.go b/vendor/src/github.com/rcrowley/go-metrics/log.go new file mode 100644 index 00000000..f8074c04 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/log.go @@ -0,0 +1,80 @@ +package metrics + +import ( + "time" +) + +type Logger interface { + Printf(format string, v ...interface{}) +} + +func Log(r Registry, freq time.Duration, l Logger) { + LogScaled(r, freq, time.Nanosecond, l) +} + +// Output each metric in the given registry periodically using the given +// logger. Print timings in `scale` units (eg time.Millisecond) rather than nanos. +func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) { + du := float64(scale) + duSuffix := scale.String()[1:] + + for _ = range time.Tick(freq) { + r.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + l.Printf("counter %s\n", name) + l.Printf(" count: %9d\n", metric.Count()) + case Gauge: + l.Printf("gauge %s\n", name) + l.Printf(" value: %9d\n", metric.Value()) + case GaugeFloat64: + l.Printf("gauge %s\n", name) + l.Printf(" value: %f\n", metric.Value()) + case Healthcheck: + metric.Check() + l.Printf("healthcheck %s\n", name) + l.Printf(" error: %v\n", metric.Error()) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + l.Printf("histogram %s\n", name) + l.Printf(" count: %9d\n", h.Count()) + l.Printf(" min: %9d\n", h.Min()) + l.Printf(" max: %9d\n", h.Max()) + l.Printf(" mean: %12.2f\n", h.Mean()) + l.Printf(" stddev: %12.2f\n", h.StdDev()) + l.Printf(" median: %12.2f\n", ps[0]) + l.Printf(" 75%%: %12.2f\n", ps[1]) + l.Printf(" 95%%: %12.2f\n", ps[2]) + l.Printf(" 99%%: %12.2f\n", ps[3]) + l.Printf(" 99.9%%: %12.2f\n", ps[4]) + case Meter: + m := metric.Snapshot() + l.Printf("meter %s\n", name) + l.Printf(" count: %9d\n", m.Count()) + l.Printf(" 1-min rate: %12.2f\n", m.Rate1()) + l.Printf(" 5-min rate: %12.2f\n", m.Rate5()) + l.Printf(" 15-min rate: %12.2f\n", m.Rate15()) + l.Printf(" mean rate: %12.2f\n", m.RateMean()) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + l.Printf("timer %s\n", name) + l.Printf(" count: %9d\n", t.Count()) + l.Printf(" min: %12.2f%s\n", float64(t.Min())/du, duSuffix) + l.Printf(" max: %12.2f%s\n", float64(t.Max())/du, duSuffix) + l.Printf(" mean: %12.2f%s\n", t.Mean()/du, duSuffix) + l.Printf(" stddev: %12.2f%s\n", t.StdDev()/du, duSuffix) + l.Printf(" median: %12.2f%s\n", ps[0]/du, duSuffix) + l.Printf(" 75%%: %12.2f%s\n", ps[1]/du, duSuffix) + l.Printf(" 95%%: %12.2f%s\n", ps[2]/du, duSuffix) + l.Printf(" 99%%: %12.2f%s\n", ps[3]/du, duSuffix) + l.Printf(" 99.9%%: %12.2f%s\n", ps[4]/du, duSuffix) + l.Printf(" 1-min rate: %12.2f\n", t.Rate1()) + l.Printf(" 5-min rate: %12.2f\n", t.Rate5()) + l.Printf(" 15-min rate: %12.2f\n", t.Rate15()) + l.Printf(" mean rate: %12.2f\n", t.RateMean()) + } + }) + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/memory.md b/vendor/src/github.com/rcrowley/go-metrics/memory.md new file mode 100644 index 00000000..47454f54 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/memory.md @@ -0,0 +1,285 @@ +Memory usage +============ + +(Highly unscientific.) + +Command used to gather static memory usage: + +```sh +grep ^Vm "/proc/$(ps fax | grep [m]etrics-bench | awk '{print $1}')/status" +``` + +Program used to gather baseline memory usage: + +```go +package main + +import "time" + +func main() { + time.Sleep(600e9) +} +``` + +Baseline +-------- + +``` +VmPeak: 42604 kB +VmSize: 42604 kB +VmLck: 0 kB +VmHWM: 1120 kB +VmRSS: 1120 kB +VmData: 35460 kB +VmStk: 136 kB +VmExe: 1020 kB +VmLib: 1848 kB +VmPTE: 36 kB +VmSwap: 0 kB +``` + +Program used to gather metric memory usage (with other metrics being similar): + +```go +package main + +import ( + "fmt" + "metrics" + "time" +) + +func main() { + fmt.Sprintf("foo") + metrics.NewRegistry() + time.Sleep(600e9) +} +``` + +1000 counters registered +------------------------ + +``` +VmPeak: 44016 kB +VmSize: 44016 kB +VmLck: 0 kB +VmHWM: 1928 kB +VmRSS: 1928 kB +VmData: 36868 kB +VmStk: 136 kB +VmExe: 1024 kB +VmLib: 1848 kB +VmPTE: 40 kB +VmSwap: 0 kB +``` + +**1.412 kB virtual, TODO 0.808 kB resident per counter.** + +100000 counters registered +-------------------------- + +``` +VmPeak: 55024 kB +VmSize: 55024 kB +VmLck: 0 kB +VmHWM: 12440 kB +VmRSS: 12440 kB +VmData: 47876 kB +VmStk: 136 kB +VmExe: 1024 kB +VmLib: 1848 kB +VmPTE: 64 kB +VmSwap: 0 kB +``` + +**0.1242 kB virtual, 0.1132 kB resident per counter.** + +1000 gauges registered +---------------------- + +``` +VmPeak: 44012 kB +VmSize: 44012 kB +VmLck: 0 kB +VmHWM: 1928 kB +VmRSS: 1928 kB +VmData: 36868 kB +VmStk: 136 kB +VmExe: 1020 kB +VmLib: 1848 kB +VmPTE: 40 kB +VmSwap: 0 kB +``` + +**1.408 kB virtual, 0.808 kB resident per counter.** + +100000 gauges registered +------------------------ + +``` +VmPeak: 55020 kB +VmSize: 55020 kB +VmLck: 0 kB +VmHWM: 12432 kB +VmRSS: 12432 kB +VmData: 47876 kB +VmStk: 136 kB +VmExe: 1020 kB +VmLib: 1848 kB +VmPTE: 60 kB +VmSwap: 0 kB +``` + +**0.12416 kB virtual, 0.11312 resident per gauge.** + +1000 histograms with a uniform sample size of 1028 +-------------------------------------------------- + +``` +VmPeak: 72272 kB +VmSize: 72272 kB +VmLck: 0 kB +VmHWM: 16204 kB +VmRSS: 16204 kB +VmData: 65100 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 80 kB +VmSwap: 0 kB +``` + +**29.668 kB virtual, TODO 15.084 resident per histogram.** + +10000 histograms with a uniform sample size of 1028 +--------------------------------------------------- + +``` +VmPeak: 256912 kB +VmSize: 256912 kB +VmLck: 0 kB +VmHWM: 146204 kB +VmRSS: 146204 kB +VmData: 249740 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 448 kB +VmSwap: 0 kB +``` + +**21.4308 kB virtual, 14.5084 kB resident per histogram.** + +50000 histograms with a uniform sample size of 1028 +--------------------------------------------------- + +``` +VmPeak: 908112 kB +VmSize: 908112 kB +VmLck: 0 kB +VmHWM: 645832 kB +VmRSS: 645588 kB +VmData: 900940 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 1716 kB +VmSwap: 1544 kB +``` + +**17.31016 kB virtual, 12.88936 kB resident per histogram.** + +1000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015 +------------------------------------------------------------------------------------- + +``` +VmPeak: 62480 kB +VmSize: 62480 kB +VmLck: 0 kB +VmHWM: 11572 kB +VmRSS: 11572 kB +VmData: 55308 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 64 kB +VmSwap: 0 kB +``` + +**19.876 kB virtual, 10.452 kB resident per histogram.** + +10000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015 +-------------------------------------------------------------------------------------- + +``` +VmPeak: 153296 kB +VmSize: 153296 kB +VmLck: 0 kB +VmHWM: 101176 kB +VmRSS: 101176 kB +VmData: 146124 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 240 kB +VmSwap: 0 kB +``` + +**11.0692 kB virtual, 10.0056 kB resident per histogram.** + +50000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015 +-------------------------------------------------------------------------------------- + +``` +VmPeak: 557264 kB +VmSize: 557264 kB +VmLck: 0 kB +VmHWM: 501056 kB +VmRSS: 501056 kB +VmData: 550092 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 1032 kB +VmSwap: 0 kB +``` + +**10.2932 kB virtual, 9.99872 kB resident per histogram.** + +1000 meters +----------- + +``` +VmPeak: 74504 kB +VmSize: 74504 kB +VmLck: 0 kB +VmHWM: 24124 kB +VmRSS: 24124 kB +VmData: 67340 kB +VmStk: 136 kB +VmExe: 1040 kB +VmLib: 1848 kB +VmPTE: 92 kB +VmSwap: 0 kB +``` + +**31.9 kB virtual, 23.004 kB resident per meter.** + +10000 meters +------------ + +``` +VmPeak: 278920 kB +VmSize: 278920 kB +VmLck: 0 kB +VmHWM: 227300 kB +VmRSS: 227300 kB +VmData: 271756 kB +VmStk: 136 kB +VmExe: 1040 kB +VmLib: 1848 kB +VmPTE: 488 kB +VmSwap: 0 kB +``` + +**23.6316 kB virtual, 22.618 kB resident per meter.** diff --git a/vendor/src/github.com/rcrowley/go-metrics/meter.go b/vendor/src/github.com/rcrowley/go-metrics/meter.go new file mode 100644 index 00000000..0389ab0b --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/meter.go @@ -0,0 +1,233 @@ +package metrics + +import ( + "sync" + "time" +) + +// Meters count events to produce exponentially-weighted moving average rates +// at one-, five-, and fifteen-minutes and a mean rate. +type Meter interface { + Count() int64 + Mark(int64) + Rate1() float64 + Rate5() float64 + Rate15() float64 + RateMean() float64 + Snapshot() Meter +} + +// GetOrRegisterMeter returns an existing Meter or constructs and registers a +// new StandardMeter. +func GetOrRegisterMeter(name string, r Registry) Meter { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewMeter).(Meter) +} + +// NewMeter constructs a new StandardMeter and launches a goroutine. +func NewMeter() Meter { + if UseNilMetrics { + return NilMeter{} + } + m := newStandardMeter() + arbiter.Lock() + defer arbiter.Unlock() + arbiter.meters = append(arbiter.meters, m) + if !arbiter.started { + arbiter.started = true + go arbiter.tick() + } + return m +} + +// NewMeter constructs and registers a new StandardMeter and launches a +// goroutine. +func NewRegisteredMeter(name string, r Registry) Meter { + c := NewMeter() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// MeterSnapshot is a read-only copy of another Meter. +type MeterSnapshot struct { + count int64 + rate1, rate5, rate15, rateMean float64 +} + +// Count returns the count of events at the time the snapshot was taken. +func (m *MeterSnapshot) Count() int64 { return m.count } + +// Mark panics. +func (*MeterSnapshot) Mark(n int64) { + panic("Mark called on a MeterSnapshot") +} + +// Rate1 returns the one-minute moving average rate of events per second at the +// time the snapshot was taken. +func (m *MeterSnapshot) Rate1() float64 { return m.rate1 } + +// Rate5 returns the five-minute moving average rate of events per second at +// the time the snapshot was taken. +func (m *MeterSnapshot) Rate5() float64 { return m.rate5 } + +// Rate15 returns the fifteen-minute moving average rate of events per second +// at the time the snapshot was taken. +func (m *MeterSnapshot) Rate15() float64 { return m.rate15 } + +// RateMean returns the meter's mean rate of events per second at the time the +// snapshot was taken. +func (m *MeterSnapshot) RateMean() float64 { return m.rateMean } + +// Snapshot returns the snapshot. +func (m *MeterSnapshot) Snapshot() Meter { return m } + +// NilMeter is a no-op Meter. +type NilMeter struct{} + +// Count is a no-op. +func (NilMeter) Count() int64 { return 0 } + +// Mark is a no-op. +func (NilMeter) Mark(n int64) {} + +// Rate1 is a no-op. +func (NilMeter) Rate1() float64 { return 0.0 } + +// Rate5 is a no-op. +func (NilMeter) Rate5() float64 { return 0.0 } + +// Rate15is a no-op. +func (NilMeter) Rate15() float64 { return 0.0 } + +// RateMean is a no-op. +func (NilMeter) RateMean() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilMeter) Snapshot() Meter { return NilMeter{} } + +// StandardMeter is the standard implementation of a Meter. +type StandardMeter struct { + lock sync.RWMutex + snapshot *MeterSnapshot + a1, a5, a15 EWMA + startTime time.Time +} + +func newStandardMeter() *StandardMeter { + return &StandardMeter{ + snapshot: &MeterSnapshot{}, + a1: NewEWMA1(), + a5: NewEWMA5(), + a15: NewEWMA15(), + startTime: time.Now(), + } +} + +// Count returns the number of events recorded. +func (m *StandardMeter) Count() int64 { + m.lock.RLock() + count := m.snapshot.count + m.lock.RUnlock() + return count +} + +// Mark records the occurance of n events. +func (m *StandardMeter) Mark(n int64) { + m.lock.Lock() + defer m.lock.Unlock() + m.snapshot.count += n + m.a1.Update(n) + m.a5.Update(n) + m.a15.Update(n) + m.updateSnapshot() +} + +// Rate1 returns the one-minute moving average rate of events per second. +func (m *StandardMeter) Rate1() float64 { + m.lock.RLock() + rate1 := m.snapshot.rate1 + m.lock.RUnlock() + return rate1 +} + +// Rate5 returns the five-minute moving average rate of events per second. +func (m *StandardMeter) Rate5() float64 { + m.lock.RLock() + rate5 := m.snapshot.rate5 + m.lock.RUnlock() + return rate5 +} + +// Rate15 returns the fifteen-minute moving average rate of events per second. +func (m *StandardMeter) Rate15() float64 { + m.lock.RLock() + rate15 := m.snapshot.rate15 + m.lock.RUnlock() + return rate15 +} + +// RateMean returns the meter's mean rate of events per second. +func (m *StandardMeter) RateMean() float64 { + m.lock.RLock() + rateMean := m.snapshot.rateMean + m.lock.RUnlock() + return rateMean +} + +// Snapshot returns a read-only copy of the meter. +func (m *StandardMeter) Snapshot() Meter { + m.lock.RLock() + snapshot := *m.snapshot + m.lock.RUnlock() + return &snapshot +} + +func (m *StandardMeter) updateSnapshot() { + // should run with write lock held on m.lock + snapshot := m.snapshot + snapshot.rate1 = m.a1.Rate() + snapshot.rate5 = m.a5.Rate() + snapshot.rate15 = m.a15.Rate() + snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds() +} + +func (m *StandardMeter) tick() { + m.lock.Lock() + defer m.lock.Unlock() + m.a1.Tick() + m.a5.Tick() + m.a15.Tick() + m.updateSnapshot() +} + +type meterArbiter struct { + sync.RWMutex + started bool + meters []*StandardMeter + ticker *time.Ticker +} + +var arbiter = meterArbiter{ticker: time.NewTicker(5e9)} + +// Ticks meters on the scheduled interval +func (ma *meterArbiter) tick() { + for { + select { + case <-ma.ticker.C: + ma.tickMeters() + } + } +} + +func (ma *meterArbiter) tickMeters() { + ma.RLock() + defer ma.RUnlock() + for _, meter := range ma.meters { + meter.tick() + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/meter_test.go b/vendor/src/github.com/rcrowley/go-metrics/meter_test.go new file mode 100644 index 00000000..1727612a --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/meter_test.go @@ -0,0 +1,60 @@ +package metrics + +import ( + "testing" + "time" +) + +func BenchmarkMeter(b *testing.B) { + m := NewMeter() + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.Mark(1) + } +} + +func TestGetOrRegisterMeter(t *testing.T) { + r := NewRegistry() + NewRegisteredMeter("foo", r).Mark(47) + if m := GetOrRegisterMeter("foo", r); 47 != m.Count() { + t.Fatal(m) + } +} + +func TestMeterDecay(t *testing.T) { + ma := meterArbiter{ + ticker: time.NewTicker(time.Millisecond), + } + m := newStandardMeter() + ma.meters = append(ma.meters, m) + go ma.tick() + m.Mark(1) + rateMean := m.RateMean() + time.Sleep(100 * time.Millisecond) + if m.RateMean() >= rateMean { + t.Error("m.RateMean() didn't decrease") + } +} + +func TestMeterNonzero(t *testing.T) { + m := NewMeter() + m.Mark(3) + if count := m.Count(); 3 != count { + t.Errorf("m.Count(): 3 != %v\n", count) + } +} + +func TestMeterSnapshot(t *testing.T) { + m := NewMeter() + m.Mark(1) + if snapshot := m.Snapshot(); m.RateMean() != snapshot.RateMean() { + t.Fatal(snapshot) + } +} + +func TestMeterZero(t *testing.T) { + m := NewMeter() + if count := m.Count(); 0 != count { + t.Errorf("m.Count(): 0 != %v\n", count) + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/metrics.go b/vendor/src/github.com/rcrowley/go-metrics/metrics.go new file mode 100644 index 00000000..b97a49ed --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/metrics.go @@ -0,0 +1,13 @@ +// Go port of Coda Hale's Metrics library +// +// +// +// Coda Hale's original work: +package metrics + +// UseNilMetrics is checked by the constructor functions for all of the +// standard metrics. If it is true, the metric returned is a stub. +// +// This global kill-switch helps quantify the observer effect and makes +// for less cluttered pprof profiles. +var UseNilMetrics bool = false diff --git a/vendor/src/github.com/rcrowley/go-metrics/metrics_test.go b/vendor/src/github.com/rcrowley/go-metrics/metrics_test.go new file mode 100644 index 00000000..726fba34 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/metrics_test.go @@ -0,0 +1,124 @@ +package metrics + +import ( + "fmt" + "io/ioutil" + "log" + "sync" + "testing" +) + +const FANOUT = 128 + +// Stop the compiler from complaining during debugging. +var ( + _ = ioutil.Discard + _ = log.LstdFlags +) + +func BenchmarkMetrics(b *testing.B) { + r := NewRegistry() + c := NewRegisteredCounter("counter", r) + g := NewRegisteredGauge("gauge", r) + gf := NewRegisteredGaugeFloat64("gaugefloat64", r) + h := NewRegisteredHistogram("histogram", r, NewUniformSample(100)) + m := NewRegisteredMeter("meter", r) + t := NewRegisteredTimer("timer", r) + RegisterDebugGCStats(r) + RegisterRuntimeMemStats(r) + b.ResetTimer() + ch := make(chan bool) + + wgD := &sync.WaitGroup{} + /* + wgD.Add(1) + go func() { + defer wgD.Done() + //log.Println("go CaptureDebugGCStats") + for { + select { + case <-ch: + //log.Println("done CaptureDebugGCStats") + return + default: + CaptureDebugGCStatsOnce(r) + } + } + }() + //*/ + + wgR := &sync.WaitGroup{} + //* + wgR.Add(1) + go func() { + defer wgR.Done() + //log.Println("go CaptureRuntimeMemStats") + for { + select { + case <-ch: + //log.Println("done CaptureRuntimeMemStats") + return + default: + CaptureRuntimeMemStatsOnce(r) + } + } + }() + //*/ + + wgW := &sync.WaitGroup{} + /* + wgW.Add(1) + go func() { + defer wgW.Done() + //log.Println("go Write") + for { + select { + case <-ch: + //log.Println("done Write") + return + default: + WriteOnce(r, ioutil.Discard) + } + } + }() + //*/ + + wg := &sync.WaitGroup{} + wg.Add(FANOUT) + for i := 0; i < FANOUT; i++ { + go func(i int) { + defer wg.Done() + //log.Println("go", i) + for i := 0; i < b.N; i++ { + c.Inc(1) + g.Update(int64(i)) + gf.Update(float64(i)) + h.Update(int64(i)) + m.Mark(1) + t.Update(1) + } + //log.Println("done", i) + }(i) + } + wg.Wait() + close(ch) + wgD.Wait() + wgR.Wait() + wgW.Wait() +} + +func Example() { + c := NewCounter() + Register("money", c) + c.Inc(17) + + // Threadsafe registration + t := GetOrRegisterTimer("db.get.latency", nil) + t.Time(func() {}) + t.Update(1) + + fmt.Println(c.Count()) + fmt.Println(t.Min()) + // Output: 17 + // 1 +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/opentsdb.go b/vendor/src/github.com/rcrowley/go-metrics/opentsdb.go new file mode 100644 index 00000000..266b6c93 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/opentsdb.go @@ -0,0 +1,119 @@ +package metrics + +import ( + "bufio" + "fmt" + "log" + "net" + "os" + "strings" + "time" +) + +var shortHostName string = "" + +// OpenTSDBConfig provides a container with configuration parameters for +// the OpenTSDB exporter +type OpenTSDBConfig struct { + Addr *net.TCPAddr // Network address to connect to + Registry Registry // Registry to be exported + FlushInterval time.Duration // Flush interval + DurationUnit time.Duration // Time conversion unit for durations + Prefix string // Prefix to be prepended to metric names +} + +// OpenTSDB is a blocking exporter function which reports metrics in r +// to a TSDB server located at addr, flushing them every d duration +// and prepending metric names with prefix. +func OpenTSDB(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { + OpenTSDBWithConfig(OpenTSDBConfig{ + Addr: addr, + Registry: r, + FlushInterval: d, + DurationUnit: time.Nanosecond, + Prefix: prefix, + }) +} + +// OpenTSDBWithConfig is a blocking exporter function just like OpenTSDB, +// but it takes a OpenTSDBConfig instead. +func OpenTSDBWithConfig(c OpenTSDBConfig) { + for _ = range time.Tick(c.FlushInterval) { + if err := openTSDB(&c); nil != err { + log.Println(err) + } + } +} + +func getShortHostname() string { + if shortHostName == "" { + host, _ := os.Hostname() + if index := strings.Index(host, "."); index > 0 { + shortHostName = host[:index] + } else { + shortHostName = host + } + } + return shortHostName +} + +func openTSDB(c *OpenTSDBConfig) error { + shortHostname := getShortHostname() + now := time.Now().Unix() + du := float64(c.DurationUnit) + conn, err := net.DialTCP("tcp", nil, c.Addr) + if nil != err { + return err + } + defer conn.Close() + w := bufio.NewWriter(conn) + c.Registry.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname) + case Gauge: + fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) + case GaugeFloat64: + fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, h.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, h.Min(), shortHostname) + fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, h.Max(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, h.Mean(), shortHostname) + fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, h.StdDev(), shortHostname) + fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0], shortHostname) + fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1], shortHostname) + fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2], shortHostname) + fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3], shortHostname) + fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4], shortHostname) + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, m.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate1(), shortHostname) + fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate5(), shortHostname) + fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate15(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, m.RateMean(), shortHostname) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, t.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, t.Min()/int64(du), shortHostname) + fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, t.Max()/int64(du), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, t.Mean()/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, t.StdDev()/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate1(), shortHostname) + fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate5(), shortHostname) + fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate15(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean-rate %d %.2f host=%s\n", c.Prefix, name, now, t.RateMean(), shortHostname) + } + w.Flush() + }) + return nil +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/opentsdb_test.go b/vendor/src/github.com/rcrowley/go-metrics/opentsdb_test.go new file mode 100644 index 00000000..c4372896 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/opentsdb_test.go @@ -0,0 +1,21 @@ +package metrics + +import ( + "net" + "time" +) + +func ExampleOpenTSDB() { + addr, _ := net.ResolveTCPAddr("net", ":2003") + go OpenTSDB(DefaultRegistry, 1*time.Second, "some.prefix", addr) +} + +func ExampleOpenTSDBWithConfig() { + addr, _ := net.ResolveTCPAddr("net", ":2003") + go OpenTSDBWithConfig(OpenTSDBConfig{ + Addr: addr, + Registry: DefaultRegistry, + FlushInterval: 1 * time.Second, + DurationUnit: time.Millisecond, + }) +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/registry.go b/vendor/src/github.com/rcrowley/go-metrics/registry.go new file mode 100644 index 00000000..2bb7a1e7 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/registry.go @@ -0,0 +1,270 @@ +package metrics + +import ( + "fmt" + "reflect" + "strings" + "sync" +) + +// DuplicateMetric is the error returned by Registry.Register when a metric +// already exists. If you mean to Register that metric you must first +// Unregister the existing metric. +type DuplicateMetric string + +func (err DuplicateMetric) Error() string { + return fmt.Sprintf("duplicate metric: %s", string(err)) +} + +// A Registry holds references to a set of metrics by name and can iterate +// over them, calling callback functions provided by the user. +// +// This is an interface so as to encourage other structs to implement +// the Registry API as appropriate. +type Registry interface { + + // Call the given function for each registered metric. + Each(func(string, interface{})) + + // Get the metric by the given name or nil if none is registered. + Get(string) interface{} + + // Gets an existing metric or registers the given one. + // The interface can be the metric to register if not found in registry, + // or a function returning the metric for lazy instantiation. + GetOrRegister(string, interface{}) interface{} + + // Register the given metric under the given name. + Register(string, interface{}) error + + // Run all registered healthchecks. + RunHealthchecks() + + // Unregister the metric with the given name. + Unregister(string) + + // Unregister all metrics. (Mostly for testing.) + UnregisterAll() +} + +// The standard implementation of a Registry is a mutex-protected map +// of names to metrics. +type StandardRegistry struct { + metrics map[string]interface{} + mutex sync.Mutex +} + +// Create a new registry. +func NewRegistry() Registry { + return &StandardRegistry{metrics: make(map[string]interface{})} +} + +// Call the given function for each registered metric. +func (r *StandardRegistry) Each(f func(string, interface{})) { + for name, i := range r.registered() { + f(name, i) + } +} + +// Get the metric by the given name or nil if none is registered. +func (r *StandardRegistry) Get(name string) interface{} { + r.mutex.Lock() + defer r.mutex.Unlock() + return r.metrics[name] +} + +// Gets an existing metric or creates and registers a new one. Threadsafe +// alternative to calling Get and Register on failure. +// The interface can be the metric to register if not found in registry, +// or a function returning the metric for lazy instantiation. +func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} { + r.mutex.Lock() + defer r.mutex.Unlock() + if metric, ok := r.metrics[name]; ok { + return metric + } + if v := reflect.ValueOf(i); v.Kind() == reflect.Func { + i = v.Call(nil)[0].Interface() + } + r.register(name, i) + return i +} + +// Register the given metric under the given name. Returns a DuplicateMetric +// if a metric by the given name is already registered. +func (r *StandardRegistry) Register(name string, i interface{}) error { + r.mutex.Lock() + defer r.mutex.Unlock() + return r.register(name, i) +} + +// Run all registered healthchecks. +func (r *StandardRegistry) RunHealthchecks() { + r.mutex.Lock() + defer r.mutex.Unlock() + for _, i := range r.metrics { + if h, ok := i.(Healthcheck); ok { + h.Check() + } + } +} + +// Unregister the metric with the given name. +func (r *StandardRegistry) Unregister(name string) { + r.mutex.Lock() + defer r.mutex.Unlock() + delete(r.metrics, name) +} + +// Unregister all metrics. (Mostly for testing.) +func (r *StandardRegistry) UnregisterAll() { + r.mutex.Lock() + defer r.mutex.Unlock() + for name, _ := range r.metrics { + delete(r.metrics, name) + } +} + +func (r *StandardRegistry) register(name string, i interface{}) error { + if _, ok := r.metrics[name]; ok { + return DuplicateMetric(name) + } + switch i.(type) { + case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer: + r.metrics[name] = i + } + return nil +} + +func (r *StandardRegistry) registered() map[string]interface{} { + r.mutex.Lock() + defer r.mutex.Unlock() + metrics := make(map[string]interface{}, len(r.metrics)) + for name, i := range r.metrics { + metrics[name] = i + } + return metrics +} + +type PrefixedRegistry struct { + underlying Registry + prefix string +} + +func NewPrefixedRegistry(prefix string) Registry { + return &PrefixedRegistry{ + underlying: NewRegistry(), + prefix: prefix, + } +} + +func NewPrefixedChildRegistry(parent Registry, prefix string) Registry { + return &PrefixedRegistry{ + underlying: parent, + prefix: prefix, + } +} + +// Call the given function for each registered metric. +func (r *PrefixedRegistry) Each(fn func(string, interface{})) { + wrappedFn := func(prefix string) func(string, interface{}) { + return func(name string, iface interface{}) { + if strings.HasPrefix(name, prefix) { + fn(name, iface) + } else { + return + } + } + } + + baseRegistry, prefix := findPrefix(r, "") + baseRegistry.Each(wrappedFn(prefix)) +} + +func findPrefix(registry Registry, prefix string) (Registry, string) { + switch r := registry.(type) { + case *PrefixedRegistry: + return findPrefix(r.underlying, r.prefix+prefix) + case *StandardRegistry: + return r, prefix + } + return nil, "" +} + +// Get the metric by the given name or nil if none is registered. +func (r *PrefixedRegistry) Get(name string) interface{} { + realName := r.prefix + name + return r.underlying.Get(realName) +} + +// Gets an existing metric or registers the given one. +// The interface can be the metric to register if not found in registry, +// or a function returning the metric for lazy instantiation. +func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} { + realName := r.prefix + name + return r.underlying.GetOrRegister(realName, metric) +} + +// Register the given metric under the given name. The name will be prefixed. +func (r *PrefixedRegistry) Register(name string, metric interface{}) error { + realName := r.prefix + name + return r.underlying.Register(realName, metric) +} + +// Run all registered healthchecks. +func (r *PrefixedRegistry) RunHealthchecks() { + r.underlying.RunHealthchecks() +} + +// Unregister the metric with the given name. The name will be prefixed. +func (r *PrefixedRegistry) Unregister(name string) { + realName := r.prefix + name + r.underlying.Unregister(realName) +} + +// Unregister all metrics. (Mostly for testing.) +func (r *PrefixedRegistry) UnregisterAll() { + r.underlying.UnregisterAll() +} + +var DefaultRegistry Registry = NewRegistry() + +// Call the given function for each registered metric. +func Each(f func(string, interface{})) { + DefaultRegistry.Each(f) +} + +// Get the metric by the given name or nil if none is registered. +func Get(name string) interface{} { + return DefaultRegistry.Get(name) +} + +// Gets an existing metric or creates and registers a new one. Threadsafe +// alternative to calling Get and Register on failure. +func GetOrRegister(name string, i interface{}) interface{} { + return DefaultRegistry.GetOrRegister(name, i) +} + +// Register the given metric under the given name. Returns a DuplicateMetric +// if a metric by the given name is already registered. +func Register(name string, i interface{}) error { + return DefaultRegistry.Register(name, i) +} + +// Register the given metric under the given name. Panics if a metric by the +// given name is already registered. +func MustRegister(name string, i interface{}) { + if err := Register(name, i); err != nil { + panic(err) + } +} + +// Run all registered healthchecks. +func RunHealthchecks() { + DefaultRegistry.RunHealthchecks() +} + +// Unregister the metric with the given name. +func Unregister(name string) { + DefaultRegistry.Unregister(name) +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/registry_test.go b/vendor/src/github.com/rcrowley/go-metrics/registry_test.go new file mode 100644 index 00000000..b42d4eec --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/registry_test.go @@ -0,0 +1,288 @@ +package metrics + +import ( + "testing" +) + +func BenchmarkRegistry(b *testing.B) { + r := NewRegistry() + r.Register("foo", NewCounter()) + b.ResetTimer() + for i := 0; i < b.N; i++ { + r.Each(func(string, interface{}) {}) + } +} + +func TestRegistry(t *testing.T) { + r := NewRegistry() + r.Register("foo", NewCounter()) + i := 0 + r.Each(func(name string, iface interface{}) { + i++ + if "foo" != name { + t.Fatal(name) + } + if _, ok := iface.(Counter); !ok { + t.Fatal(iface) + } + }) + if 1 != i { + t.Fatal(i) + } + r.Unregister("foo") + i = 0 + r.Each(func(string, interface{}) { i++ }) + if 0 != i { + t.Fatal(i) + } +} + +func TestRegistryDuplicate(t *testing.T) { + r := NewRegistry() + if err := r.Register("foo", NewCounter()); nil != err { + t.Fatal(err) + } + if err := r.Register("foo", NewGauge()); nil == err { + t.Fatal(err) + } + i := 0 + r.Each(func(name string, iface interface{}) { + i++ + if _, ok := iface.(Counter); !ok { + t.Fatal(iface) + } + }) + if 1 != i { + t.Fatal(i) + } +} + +func TestRegistryGet(t *testing.T) { + r := NewRegistry() + r.Register("foo", NewCounter()) + if count := r.Get("foo").(Counter).Count(); 0 != count { + t.Fatal(count) + } + r.Get("foo").(Counter).Inc(1) + if count := r.Get("foo").(Counter).Count(); 1 != count { + t.Fatal(count) + } +} + +func TestRegistryGetOrRegister(t *testing.T) { + r := NewRegistry() + + // First metric wins with GetOrRegister + _ = r.GetOrRegister("foo", NewCounter()) + m := r.GetOrRegister("foo", NewGauge()) + if _, ok := m.(Counter); !ok { + t.Fatal(m) + } + + i := 0 + r.Each(func(name string, iface interface{}) { + i++ + if name != "foo" { + t.Fatal(name) + } + if _, ok := iface.(Counter); !ok { + t.Fatal(iface) + } + }) + if i != 1 { + t.Fatal(i) + } +} + +func TestRegistryGetOrRegisterWithLazyInstantiation(t *testing.T) { + r := NewRegistry() + + // First metric wins with GetOrRegister + _ = r.GetOrRegister("foo", NewCounter) + m := r.GetOrRegister("foo", NewGauge) + if _, ok := m.(Counter); !ok { + t.Fatal(m) + } + + i := 0 + r.Each(func(name string, iface interface{}) { + i++ + if name != "foo" { + t.Fatal(name) + } + if _, ok := iface.(Counter); !ok { + t.Fatal(iface) + } + }) + if i != 1 { + t.Fatal(i) + } +} + +func TestPrefixedChildRegistryGetOrRegister(t *testing.T) { + r := NewRegistry() + pr := NewPrefixedChildRegistry(r, "prefix.") + + _ = pr.GetOrRegister("foo", NewCounter()) + + i := 0 + r.Each(func(name string, m interface{}) { + i++ + if name != "prefix.foo" { + t.Fatal(name) + } + }) + if i != 1 { + t.Fatal(i) + } +} + +func TestPrefixedRegistryGetOrRegister(t *testing.T) { + r := NewPrefixedRegistry("prefix.") + + _ = r.GetOrRegister("foo", NewCounter()) + + i := 0 + r.Each(func(name string, m interface{}) { + i++ + if name != "prefix.foo" { + t.Fatal(name) + } + }) + if i != 1 { + t.Fatal(i) + } +} + +func TestPrefixedRegistryRegister(t *testing.T) { + r := NewPrefixedRegistry("prefix.") + err := r.Register("foo", NewCounter()) + c := NewCounter() + Register("bar", c) + if err != nil { + t.Fatal(err.Error()) + } + + i := 0 + r.Each(func(name string, m interface{}) { + i++ + if name != "prefix.foo" { + t.Fatal(name) + } + }) + if i != 1 { + t.Fatal(i) + } +} + +func TestPrefixedRegistryUnregister(t *testing.T) { + r := NewPrefixedRegistry("prefix.") + + _ = r.Register("foo", NewCounter()) + + i := 0 + r.Each(func(name string, m interface{}) { + i++ + if name != "prefix.foo" { + t.Fatal(name) + } + }) + if i != 1 { + t.Fatal(i) + } + + r.Unregister("foo") + + i = 0 + r.Each(func(name string, m interface{}) { + i++ + }) + + if i != 0 { + t.Fatal(i) + } +} + +func TestPrefixedRegistryGet(t *testing.T) { + pr := NewPrefixedRegistry("prefix.") + name := "foo" + pr.Register(name, NewCounter()) + + fooCounter := pr.Get(name) + if fooCounter == nil { + t.Fatal(name) + } +} + +func TestPrefixedChildRegistryGet(t *testing.T) { + r := NewRegistry() + pr := NewPrefixedChildRegistry(r, "prefix.") + name := "foo" + pr.Register(name, NewCounter()) + fooCounter := pr.Get(name) + if fooCounter == nil { + t.Fatal(name) + } +} + +func TestChildPrefixedRegistryRegister(t *testing.T) { + r := NewPrefixedChildRegistry(DefaultRegistry, "prefix.") + err := r.Register("foo", NewCounter()) + c := NewCounter() + Register("bar", c) + if err != nil { + t.Fatal(err.Error()) + } + + i := 0 + r.Each(func(name string, m interface{}) { + i++ + if name != "prefix.foo" { + t.Fatal(name) + } + }) + if i != 1 { + t.Fatal(i) + } +} + +func TestChildPrefixedRegistryOfChildRegister(t *testing.T) { + r := NewPrefixedChildRegistry(NewRegistry(), "prefix.") + r2 := NewPrefixedChildRegistry(r, "prefix2.") + err := r.Register("foo2", NewCounter()) + if err != nil { + t.Fatal(err.Error()) + } + err = r2.Register("baz", NewCounter()) + c := NewCounter() + Register("bars", c) + + i := 0 + r2.Each(func(name string, m interface{}) { + i++ + if name != "prefix.prefix2.baz" { + //t.Fatal(name) + } + }) + if i != 1 { + t.Fatal(i) + } +} + +func TestWalkRegistries(t *testing.T) { + r := NewPrefixedChildRegistry(NewRegistry(), "prefix.") + r2 := NewPrefixedChildRegistry(r, "prefix2.") + err := r.Register("foo2", NewCounter()) + if err != nil { + t.Fatal(err.Error()) + } + err = r2.Register("baz", NewCounter()) + c := NewCounter() + Register("bars", c) + + _, prefix := findPrefix(r2, "") + if "prefix.prefix2." != prefix { + t.Fatal(prefix) + } + +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/runtime.go b/vendor/src/github.com/rcrowley/go-metrics/runtime.go new file mode 100644 index 00000000..11c6b785 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/runtime.go @@ -0,0 +1,212 @@ +package metrics + +import ( + "runtime" + "runtime/pprof" + "time" +) + +var ( + memStats runtime.MemStats + runtimeMetrics struct { + MemStats struct { + Alloc Gauge + BuckHashSys Gauge + DebugGC Gauge + EnableGC Gauge + Frees Gauge + HeapAlloc Gauge + HeapIdle Gauge + HeapInuse Gauge + HeapObjects Gauge + HeapReleased Gauge + HeapSys Gauge + LastGC Gauge + Lookups Gauge + Mallocs Gauge + MCacheInuse Gauge + MCacheSys Gauge + MSpanInuse Gauge + MSpanSys Gauge + NextGC Gauge + NumGC Gauge + GCCPUFraction GaugeFloat64 + PauseNs Histogram + PauseTotalNs Gauge + StackInuse Gauge + StackSys Gauge + Sys Gauge + TotalAlloc Gauge + } + NumCgoCall Gauge + NumGoroutine Gauge + NumThread Gauge + ReadMemStats Timer + } + frees uint64 + lookups uint64 + mallocs uint64 + numGC uint32 + numCgoCalls int64 + + threadCreateProfile = pprof.Lookup("threadcreate") +) + +// Capture new values for the Go runtime statistics exported in +// runtime.MemStats. This is designed to be called as a goroutine. +func CaptureRuntimeMemStats(r Registry, d time.Duration) { + for _ = range time.Tick(d) { + CaptureRuntimeMemStatsOnce(r) + } +} + +// Capture new values for the Go runtime statistics exported in +// runtime.MemStats. This is designed to be called in a background +// goroutine. Giving a registry which has not been given to +// RegisterRuntimeMemStats will panic. +// +// Be very careful with this because runtime.ReadMemStats calls the C +// functions runtime·semacquire(&runtime·worldsema) and runtime·stoptheworld() +// and that last one does what it says on the tin. +func CaptureRuntimeMemStatsOnce(r Registry) { + t := time.Now() + runtime.ReadMemStats(&memStats) // This takes 50-200us. + runtimeMetrics.ReadMemStats.UpdateSince(t) + + runtimeMetrics.MemStats.Alloc.Update(int64(memStats.Alloc)) + runtimeMetrics.MemStats.BuckHashSys.Update(int64(memStats.BuckHashSys)) + if memStats.DebugGC { + runtimeMetrics.MemStats.DebugGC.Update(1) + } else { + runtimeMetrics.MemStats.DebugGC.Update(0) + } + if memStats.EnableGC { + runtimeMetrics.MemStats.EnableGC.Update(1) + } else { + runtimeMetrics.MemStats.EnableGC.Update(0) + } + + runtimeMetrics.MemStats.Frees.Update(int64(memStats.Frees - frees)) + runtimeMetrics.MemStats.HeapAlloc.Update(int64(memStats.HeapAlloc)) + runtimeMetrics.MemStats.HeapIdle.Update(int64(memStats.HeapIdle)) + runtimeMetrics.MemStats.HeapInuse.Update(int64(memStats.HeapInuse)) + runtimeMetrics.MemStats.HeapObjects.Update(int64(memStats.HeapObjects)) + runtimeMetrics.MemStats.HeapReleased.Update(int64(memStats.HeapReleased)) + runtimeMetrics.MemStats.HeapSys.Update(int64(memStats.HeapSys)) + runtimeMetrics.MemStats.LastGC.Update(int64(memStats.LastGC)) + runtimeMetrics.MemStats.Lookups.Update(int64(memStats.Lookups - lookups)) + runtimeMetrics.MemStats.Mallocs.Update(int64(memStats.Mallocs - mallocs)) + runtimeMetrics.MemStats.MCacheInuse.Update(int64(memStats.MCacheInuse)) + runtimeMetrics.MemStats.MCacheSys.Update(int64(memStats.MCacheSys)) + runtimeMetrics.MemStats.MSpanInuse.Update(int64(memStats.MSpanInuse)) + runtimeMetrics.MemStats.MSpanSys.Update(int64(memStats.MSpanSys)) + runtimeMetrics.MemStats.NextGC.Update(int64(memStats.NextGC)) + runtimeMetrics.MemStats.NumGC.Update(int64(memStats.NumGC - numGC)) + runtimeMetrics.MemStats.GCCPUFraction.Update(gcCPUFraction(&memStats)) + + // + i := numGC % uint32(len(memStats.PauseNs)) + ii := memStats.NumGC % uint32(len(memStats.PauseNs)) + if memStats.NumGC-numGC >= uint32(len(memStats.PauseNs)) { + for i = 0; i < uint32(len(memStats.PauseNs)); i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + } else { + if i > ii { + for ; i < uint32(len(memStats.PauseNs)); i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + i = 0 + } + for ; i < ii; i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + } + frees = memStats.Frees + lookups = memStats.Lookups + mallocs = memStats.Mallocs + numGC = memStats.NumGC + + runtimeMetrics.MemStats.PauseTotalNs.Update(int64(memStats.PauseTotalNs)) + runtimeMetrics.MemStats.StackInuse.Update(int64(memStats.StackInuse)) + runtimeMetrics.MemStats.StackSys.Update(int64(memStats.StackSys)) + runtimeMetrics.MemStats.Sys.Update(int64(memStats.Sys)) + runtimeMetrics.MemStats.TotalAlloc.Update(int64(memStats.TotalAlloc)) + + currentNumCgoCalls := numCgoCall() + runtimeMetrics.NumCgoCall.Update(currentNumCgoCalls - numCgoCalls) + numCgoCalls = currentNumCgoCalls + + runtimeMetrics.NumGoroutine.Update(int64(runtime.NumGoroutine())) + + runtimeMetrics.NumThread.Update(int64(threadCreateProfile.Count())) +} + +// Register runtimeMetrics for the Go runtime statistics exported in runtime and +// specifically runtime.MemStats. The runtimeMetrics are named by their +// fully-qualified Go symbols, i.e. runtime.MemStats.Alloc. +func RegisterRuntimeMemStats(r Registry) { + runtimeMetrics.MemStats.Alloc = NewGauge() + runtimeMetrics.MemStats.BuckHashSys = NewGauge() + runtimeMetrics.MemStats.DebugGC = NewGauge() + runtimeMetrics.MemStats.EnableGC = NewGauge() + runtimeMetrics.MemStats.Frees = NewGauge() + runtimeMetrics.MemStats.HeapAlloc = NewGauge() + runtimeMetrics.MemStats.HeapIdle = NewGauge() + runtimeMetrics.MemStats.HeapInuse = NewGauge() + runtimeMetrics.MemStats.HeapObjects = NewGauge() + runtimeMetrics.MemStats.HeapReleased = NewGauge() + runtimeMetrics.MemStats.HeapSys = NewGauge() + runtimeMetrics.MemStats.LastGC = NewGauge() + runtimeMetrics.MemStats.Lookups = NewGauge() + runtimeMetrics.MemStats.Mallocs = NewGauge() + runtimeMetrics.MemStats.MCacheInuse = NewGauge() + runtimeMetrics.MemStats.MCacheSys = NewGauge() + runtimeMetrics.MemStats.MSpanInuse = NewGauge() + runtimeMetrics.MemStats.MSpanSys = NewGauge() + runtimeMetrics.MemStats.NextGC = NewGauge() + runtimeMetrics.MemStats.NumGC = NewGauge() + runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64() + runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015)) + runtimeMetrics.MemStats.PauseTotalNs = NewGauge() + runtimeMetrics.MemStats.StackInuse = NewGauge() + runtimeMetrics.MemStats.StackSys = NewGauge() + runtimeMetrics.MemStats.Sys = NewGauge() + runtimeMetrics.MemStats.TotalAlloc = NewGauge() + runtimeMetrics.NumCgoCall = NewGauge() + runtimeMetrics.NumGoroutine = NewGauge() + runtimeMetrics.NumThread = NewGauge() + runtimeMetrics.ReadMemStats = NewTimer() + + r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc) + r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys) + r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC) + r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC) + r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees) + r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc) + r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle) + r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse) + r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects) + r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased) + r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys) + r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC) + r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups) + r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs) + r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse) + r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys) + r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse) + r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys) + r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC) + r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC) + r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction) + r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs) + r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs) + r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse) + r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys) + r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys) + r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc) + r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall) + r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine) + r.Register("runtime.NumThread", runtimeMetrics.NumThread) + r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats) +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/runtime_cgo.go b/vendor/src/github.com/rcrowley/go-metrics/runtime_cgo.go new file mode 100644 index 00000000..e3391f4e --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/runtime_cgo.go @@ -0,0 +1,10 @@ +// +build cgo +// +build !appengine + +package metrics + +import "runtime" + +func numCgoCall() int64 { + return runtime.NumCgoCall() +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/runtime_gccpufraction.go b/vendor/src/github.com/rcrowley/go-metrics/runtime_gccpufraction.go new file mode 100644 index 00000000..ca12c05b --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/runtime_gccpufraction.go @@ -0,0 +1,9 @@ +// +build go1.5 + +package metrics + +import "runtime" + +func gcCPUFraction(memStats *runtime.MemStats) float64 { + return memStats.GCCPUFraction +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/runtime_no_cgo.go b/vendor/src/github.com/rcrowley/go-metrics/runtime_no_cgo.go new file mode 100644 index 00000000..616a3b47 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/runtime_no_cgo.go @@ -0,0 +1,7 @@ +// +build !cgo appengine + +package metrics + +func numCgoCall() int64 { + return 0 +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go b/vendor/src/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go new file mode 100644 index 00000000..be96aa6f --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go @@ -0,0 +1,9 @@ +// +build !go1.5 + +package metrics + +import "runtime" + +func gcCPUFraction(memStats *runtime.MemStats) float64 { + return 0 +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/runtime_test.go b/vendor/src/github.com/rcrowley/go-metrics/runtime_test.go new file mode 100644 index 00000000..ebbfd501 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/runtime_test.go @@ -0,0 +1,88 @@ +package metrics + +import ( + "runtime" + "testing" + "time" +) + +func BenchmarkRuntimeMemStats(b *testing.B) { + r := NewRegistry() + RegisterRuntimeMemStats(r) + b.ResetTimer() + for i := 0; i < b.N; i++ { + CaptureRuntimeMemStatsOnce(r) + } +} + +func TestRuntimeMemStats(t *testing.T) { + r := NewRegistry() + RegisterRuntimeMemStats(r) + CaptureRuntimeMemStatsOnce(r) + zero := runtimeMetrics.MemStats.PauseNs.Count() // Get a "zero" since GC may have run before these tests. + runtime.GC() + CaptureRuntimeMemStatsOnce(r) + if count := runtimeMetrics.MemStats.PauseNs.Count(); 1 != count-zero { + t.Fatal(count - zero) + } + runtime.GC() + runtime.GC() + CaptureRuntimeMemStatsOnce(r) + if count := runtimeMetrics.MemStats.PauseNs.Count(); 3 != count-zero { + t.Fatal(count - zero) + } + for i := 0; i < 256; i++ { + runtime.GC() + } + CaptureRuntimeMemStatsOnce(r) + if count := runtimeMetrics.MemStats.PauseNs.Count(); 259 != count-zero { + t.Fatal(count - zero) + } + for i := 0; i < 257; i++ { + runtime.GC() + } + CaptureRuntimeMemStatsOnce(r) + if count := runtimeMetrics.MemStats.PauseNs.Count(); 515 != count-zero { // We lost one because there were too many GCs between captures. + t.Fatal(count - zero) + } +} + +func TestRuntimeMemStatsNumThread(t *testing.T) { + r := NewRegistry() + RegisterRuntimeMemStats(r) + CaptureRuntimeMemStatsOnce(r) + + if value := runtimeMetrics.NumThread.Value(); value < 1 { + t.Fatalf("got NumThread: %d, wanted at least 1", value) + } +} + +func TestRuntimeMemStatsBlocking(t *testing.T) { + if g := runtime.GOMAXPROCS(0); g < 2 { + t.Skipf("skipping TestRuntimeMemStatsBlocking with GOMAXPROCS=%d\n", g) + } + ch := make(chan int) + go testRuntimeMemStatsBlocking(ch) + var memStats runtime.MemStats + t0 := time.Now() + runtime.ReadMemStats(&memStats) + t1 := time.Now() + t.Log("i++ during runtime.ReadMemStats:", <-ch) + go testRuntimeMemStatsBlocking(ch) + d := t1.Sub(t0) + t.Log(d) + time.Sleep(d) + t.Log("i++ during time.Sleep:", <-ch) +} + +func testRuntimeMemStatsBlocking(ch chan int) { + i := 0 + for { + select { + case ch <- i: + return + default: + i++ + } + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/sample.go b/vendor/src/github.com/rcrowley/go-metrics/sample.go new file mode 100644 index 00000000..fecee5ef --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/sample.go @@ -0,0 +1,616 @@ +package metrics + +import ( + "math" + "math/rand" + "sort" + "sync" + "time" +) + +const rescaleThreshold = time.Hour + +// Samples maintain a statistically-significant selection of values from +// a stream. +type Sample interface { + Clear() + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Size() int + Snapshot() Sample + StdDev() float64 + Sum() int64 + Update(int64) + Values() []int64 + Variance() float64 +} + +// ExpDecaySample is an exponentially-decaying sample using a forward-decaying +// priority reservoir. See Cormode et al's "Forward Decay: A Practical Time +// Decay Model for Streaming Systems". +// +// +type ExpDecaySample struct { + alpha float64 + count int64 + mutex sync.Mutex + reservoirSize int + t0, t1 time.Time + values *expDecaySampleHeap +} + +// NewExpDecaySample constructs a new exponentially-decaying sample with the +// given reservoir size and alpha. +func NewExpDecaySample(reservoirSize int, alpha float64) Sample { + if UseNilMetrics { + return NilSample{} + } + s := &ExpDecaySample{ + alpha: alpha, + reservoirSize: reservoirSize, + t0: time.Now(), + values: newExpDecaySampleHeap(reservoirSize), + } + s.t1 = s.t0.Add(rescaleThreshold) + return s +} + +// Clear clears all samples. +func (s *ExpDecaySample) Clear() { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count = 0 + s.t0 = time.Now() + s.t1 = s.t0.Add(rescaleThreshold) + s.values.Clear() +} + +// Count returns the number of samples recorded, which may exceed the +// reservoir size. +func (s *ExpDecaySample) Count() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.count +} + +// Max returns the maximum value in the sample, which may not be the maximum +// value ever to be part of the sample. +func (s *ExpDecaySample) Max() int64 { + return SampleMax(s.Values()) +} + +// Mean returns the mean of the values in the sample. +func (s *ExpDecaySample) Mean() float64 { + return SampleMean(s.Values()) +} + +// Min returns the minimum value in the sample, which may not be the minimum +// value ever to be part of the sample. +func (s *ExpDecaySample) Min() int64 { + return SampleMin(s.Values()) +} + +// Percentile returns an arbitrary percentile of values in the sample. +func (s *ExpDecaySample) Percentile(p float64) float64 { + return SamplePercentile(s.Values(), p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the +// sample. +func (s *ExpDecaySample) Percentiles(ps []float64) []float64 { + return SamplePercentiles(s.Values(), ps) +} + +// Size returns the size of the sample, which is at most the reservoir size. +func (s *ExpDecaySample) Size() int { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.values.Size() +} + +// Snapshot returns a read-only copy of the sample. +func (s *ExpDecaySample) Snapshot() Sample { + s.mutex.Lock() + defer s.mutex.Unlock() + vals := s.values.Values() + values := make([]int64, len(vals)) + for i, v := range vals { + values[i] = v.v + } + return &SampleSnapshot{ + count: s.count, + values: values, + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (s *ExpDecaySample) StdDev() float64 { + return SampleStdDev(s.Values()) +} + +// Sum returns the sum of the values in the sample. +func (s *ExpDecaySample) Sum() int64 { + return SampleSum(s.Values()) +} + +// Update samples a new value. +func (s *ExpDecaySample) Update(v int64) { + s.update(time.Now(), v) +} + +// Values returns a copy of the values in the sample. +func (s *ExpDecaySample) Values() []int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + vals := s.values.Values() + values := make([]int64, len(vals)) + for i, v := range vals { + values[i] = v.v + } + return values +} + +// Variance returns the variance of the values in the sample. +func (s *ExpDecaySample) Variance() float64 { + return SampleVariance(s.Values()) +} + +// update samples a new value at a particular timestamp. This is a method all +// its own to facilitate testing. +func (s *ExpDecaySample) update(t time.Time, v int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count++ + if s.values.Size() == s.reservoirSize { + s.values.Pop() + } + s.values.Push(expDecaySample{ + k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / rand.Float64(), + v: v, + }) + if t.After(s.t1) { + values := s.values.Values() + t0 := s.t0 + s.values.Clear() + s.t0 = t + s.t1 = s.t0.Add(rescaleThreshold) + for _, v := range values { + v.k = v.k * math.Exp(-s.alpha*s.t0.Sub(t0).Seconds()) + s.values.Push(v) + } + } +} + +// NilSample is a no-op Sample. +type NilSample struct{} + +// Clear is a no-op. +func (NilSample) Clear() {} + +// Count is a no-op. +func (NilSample) Count() int64 { return 0 } + +// Max is a no-op. +func (NilSample) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilSample) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilSample) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilSample) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilSample) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Size is a no-op. +func (NilSample) Size() int { return 0 } + +// Sample is a no-op. +func (NilSample) Snapshot() Sample { return NilSample{} } + +// StdDev is a no-op. +func (NilSample) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilSample) Sum() int64 { return 0 } + +// Update is a no-op. +func (NilSample) Update(v int64) {} + +// Values is a no-op. +func (NilSample) Values() []int64 { return []int64{} } + +// Variance is a no-op. +func (NilSample) Variance() float64 { return 0.0 } + +// SampleMax returns the maximum value of the slice of int64. +func SampleMax(values []int64) int64 { + if 0 == len(values) { + return 0 + } + var max int64 = math.MinInt64 + for _, v := range values { + if max < v { + max = v + } + } + return max +} + +// SampleMean returns the mean value of the slice of int64. +func SampleMean(values []int64) float64 { + if 0 == len(values) { + return 0.0 + } + return float64(SampleSum(values)) / float64(len(values)) +} + +// SampleMin returns the minimum value of the slice of int64. +func SampleMin(values []int64) int64 { + if 0 == len(values) { + return 0 + } + var min int64 = math.MaxInt64 + for _, v := range values { + if min > v { + min = v + } + } + return min +} + +// SamplePercentiles returns an arbitrary percentile of the slice of int64. +func SamplePercentile(values int64Slice, p float64) float64 { + return SamplePercentiles(values, []float64{p})[0] +} + +// SamplePercentiles returns a slice of arbitrary percentiles of the slice of +// int64. +func SamplePercentiles(values int64Slice, ps []float64) []float64 { + scores := make([]float64, len(ps)) + size := len(values) + if size > 0 { + sort.Sort(values) + for i, p := range ps { + pos := p * float64(size+1) + if pos < 1.0 { + scores[i] = float64(values[0]) + } else if pos >= float64(size) { + scores[i] = float64(values[size-1]) + } else { + lower := float64(values[int(pos)-1]) + upper := float64(values[int(pos)]) + scores[i] = lower + (pos-math.Floor(pos))*(upper-lower) + } + } + } + return scores +} + +// SampleSnapshot is a read-only copy of another Sample. +type SampleSnapshot struct { + count int64 + values []int64 +} + +func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot { + return &SampleSnapshot{ + count: count, + values: values, + } +} + +// Clear panics. +func (*SampleSnapshot) Clear() { + panic("Clear called on a SampleSnapshot") +} + +// Count returns the count of inputs at the time the snapshot was taken. +func (s *SampleSnapshot) Count() int64 { return s.count } + +// Max returns the maximal value at the time the snapshot was taken. +func (s *SampleSnapshot) Max() int64 { return SampleMax(s.values) } + +// Mean returns the mean value at the time the snapshot was taken. +func (s *SampleSnapshot) Mean() float64 { return SampleMean(s.values) } + +// Min returns the minimal value at the time the snapshot was taken. +func (s *SampleSnapshot) Min() int64 { return SampleMin(s.values) } + +// Percentile returns an arbitrary percentile of values at the time the +// snapshot was taken. +func (s *SampleSnapshot) Percentile(p float64) float64 { + return SamplePercentile(s.values, p) +} + +// Percentiles returns a slice of arbitrary percentiles of values at the time +// the snapshot was taken. +func (s *SampleSnapshot) Percentiles(ps []float64) []float64 { + return SamplePercentiles(s.values, ps) +} + +// Size returns the size of the sample at the time the snapshot was taken. +func (s *SampleSnapshot) Size() int { return len(s.values) } + +// Snapshot returns the snapshot. +func (s *SampleSnapshot) Snapshot() Sample { return s } + +// StdDev returns the standard deviation of values at the time the snapshot was +// taken. +func (s *SampleSnapshot) StdDev() float64 { return SampleStdDev(s.values) } + +// Sum returns the sum of values at the time the snapshot was taken. +func (s *SampleSnapshot) Sum() int64 { return SampleSum(s.values) } + +// Update panics. +func (*SampleSnapshot) Update(int64) { + panic("Update called on a SampleSnapshot") +} + +// Values returns a copy of the values in the sample. +func (s *SampleSnapshot) Values() []int64 { + values := make([]int64, len(s.values)) + copy(values, s.values) + return values +} + +// Variance returns the variance of values at the time the snapshot was taken. +func (s *SampleSnapshot) Variance() float64 { return SampleVariance(s.values) } + +// SampleStdDev returns the standard deviation of the slice of int64. +func SampleStdDev(values []int64) float64 { + return math.Sqrt(SampleVariance(values)) +} + +// SampleSum returns the sum of the slice of int64. +func SampleSum(values []int64) int64 { + var sum int64 + for _, v := range values { + sum += v + } + return sum +} + +// SampleVariance returns the variance of the slice of int64. +func SampleVariance(values []int64) float64 { + if 0 == len(values) { + return 0.0 + } + m := SampleMean(values) + var sum float64 + for _, v := range values { + d := float64(v) - m + sum += d * d + } + return sum / float64(len(values)) +} + +// A uniform sample using Vitter's Algorithm R. +// +// +type UniformSample struct { + count int64 + mutex sync.Mutex + reservoirSize int + values []int64 +} + +// NewUniformSample constructs a new uniform sample with the given reservoir +// size. +func NewUniformSample(reservoirSize int) Sample { + if UseNilMetrics { + return NilSample{} + } + return &UniformSample{ + reservoirSize: reservoirSize, + values: make([]int64, 0, reservoirSize), + } +} + +// Clear clears all samples. +func (s *UniformSample) Clear() { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count = 0 + s.values = make([]int64, 0, s.reservoirSize) +} + +// Count returns the number of samples recorded, which may exceed the +// reservoir size. +func (s *UniformSample) Count() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.count +} + +// Max returns the maximum value in the sample, which may not be the maximum +// value ever to be part of the sample. +func (s *UniformSample) Max() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMax(s.values) +} + +// Mean returns the mean of the values in the sample. +func (s *UniformSample) Mean() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMean(s.values) +} + +// Min returns the minimum value in the sample, which may not be the minimum +// value ever to be part of the sample. +func (s *UniformSample) Min() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMin(s.values) +} + +// Percentile returns an arbitrary percentile of values in the sample. +func (s *UniformSample) Percentile(p float64) float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SamplePercentile(s.values, p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the +// sample. +func (s *UniformSample) Percentiles(ps []float64) []float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SamplePercentiles(s.values, ps) +} + +// Size returns the size of the sample, which is at most the reservoir size. +func (s *UniformSample) Size() int { + s.mutex.Lock() + defer s.mutex.Unlock() + return len(s.values) +} + +// Snapshot returns a read-only copy of the sample. +func (s *UniformSample) Snapshot() Sample { + s.mutex.Lock() + defer s.mutex.Unlock() + values := make([]int64, len(s.values)) + copy(values, s.values) + return &SampleSnapshot{ + count: s.count, + values: values, + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (s *UniformSample) StdDev() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleStdDev(s.values) +} + +// Sum returns the sum of the values in the sample. +func (s *UniformSample) Sum() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleSum(s.values) +} + +// Update samples a new value. +func (s *UniformSample) Update(v int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count++ + if len(s.values) < s.reservoirSize { + s.values = append(s.values, v) + } else { + r := rand.Int63n(s.count) + if r < int64(len(s.values)) { + s.values[int(r)] = v + } + } +} + +// Values returns a copy of the values in the sample. +func (s *UniformSample) Values() []int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + values := make([]int64, len(s.values)) + copy(values, s.values) + return values +} + +// Variance returns the variance of the values in the sample. +func (s *UniformSample) Variance() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleVariance(s.values) +} + +// expDecaySample represents an individual sample in a heap. +type expDecaySample struct { + k float64 + v int64 +} + +func newExpDecaySampleHeap(reservoirSize int) *expDecaySampleHeap { + return &expDecaySampleHeap{make([]expDecaySample, 0, reservoirSize)} +} + +// expDecaySampleHeap is a min-heap of expDecaySamples. +// The internal implementation is copied from the standard library's container/heap +type expDecaySampleHeap struct { + s []expDecaySample +} + +func (h *expDecaySampleHeap) Clear() { + h.s = h.s[:0] +} + +func (h *expDecaySampleHeap) Push(s expDecaySample) { + n := len(h.s) + h.s = h.s[0 : n+1] + h.s[n] = s + h.up(n) +} + +func (h *expDecaySampleHeap) Pop() expDecaySample { + n := len(h.s) - 1 + h.s[0], h.s[n] = h.s[n], h.s[0] + h.down(0, n) + + n = len(h.s) + s := h.s[n-1] + h.s = h.s[0 : n-1] + return s +} + +func (h *expDecaySampleHeap) Size() int { + return len(h.s) +} + +func (h *expDecaySampleHeap) Values() []expDecaySample { + return h.s +} + +func (h *expDecaySampleHeap) up(j int) { + for { + i := (j - 1) / 2 // parent + if i == j || !(h.s[j].k < h.s[i].k) { + break + } + h.s[i], h.s[j] = h.s[j], h.s[i] + j = i + } +} + +func (h *expDecaySampleHeap) down(i, n int) { + for { + j1 := 2*i + 1 + if j1 >= n || j1 < 0 { // j1 < 0 after int overflow + break + } + j := j1 // left child + if j2 := j1 + 1; j2 < n && !(h.s[j1].k < h.s[j2].k) { + j = j2 // = 2*i + 2 // right child + } + if !(h.s[j].k < h.s[i].k) { + break + } + h.s[i], h.s[j] = h.s[j], h.s[i] + i = j + } +} + +type int64Slice []int64 + +func (p int64Slice) Len() int { return len(p) } +func (p int64Slice) Less(i, j int) bool { return p[i] < p[j] } +func (p int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } diff --git a/vendor/src/github.com/rcrowley/go-metrics/sample_test.go b/vendor/src/github.com/rcrowley/go-metrics/sample_test.go new file mode 100644 index 00000000..d60e99c5 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/sample_test.go @@ -0,0 +1,363 @@ +package metrics + +import ( + "math/rand" + "runtime" + "testing" + "time" +) + +// Benchmark{Compute,Copy}{1000,1000000} demonstrate that, even for relatively +// expensive computations like Variance, the cost of copying the Sample, as +// approximated by a make and copy, is much greater than the cost of the +// computation for small samples and only slightly less for large samples. +func BenchmarkCompute1000(b *testing.B) { + s := make([]int64, 1000) + for i := 0; i < len(s); i++ { + s[i] = int64(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + SampleVariance(s) + } +} +func BenchmarkCompute1000000(b *testing.B) { + s := make([]int64, 1000000) + for i := 0; i < len(s); i++ { + s[i] = int64(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + SampleVariance(s) + } +} +func BenchmarkCopy1000(b *testing.B) { + s := make([]int64, 1000) + for i := 0; i < len(s); i++ { + s[i] = int64(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + sCopy := make([]int64, len(s)) + copy(sCopy, s) + } +} +func BenchmarkCopy1000000(b *testing.B) { + s := make([]int64, 1000000) + for i := 0; i < len(s); i++ { + s[i] = int64(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + sCopy := make([]int64, len(s)) + copy(sCopy, s) + } +} + +func BenchmarkExpDecaySample257(b *testing.B) { + benchmarkSample(b, NewExpDecaySample(257, 0.015)) +} + +func BenchmarkExpDecaySample514(b *testing.B) { + benchmarkSample(b, NewExpDecaySample(514, 0.015)) +} + +func BenchmarkExpDecaySample1028(b *testing.B) { + benchmarkSample(b, NewExpDecaySample(1028, 0.015)) +} + +func BenchmarkUniformSample257(b *testing.B) { + benchmarkSample(b, NewUniformSample(257)) +} + +func BenchmarkUniformSample514(b *testing.B) { + benchmarkSample(b, NewUniformSample(514)) +} + +func BenchmarkUniformSample1028(b *testing.B) { + benchmarkSample(b, NewUniformSample(1028)) +} + +func TestExpDecaySample10(t *testing.T) { + rand.Seed(1) + s := NewExpDecaySample(100, 0.99) + for i := 0; i < 10; i++ { + s.Update(int64(i)) + } + if size := s.Count(); 10 != size { + t.Errorf("s.Count(): 10 != %v\n", size) + } + if size := s.Size(); 10 != size { + t.Errorf("s.Size(): 10 != %v\n", size) + } + if l := len(s.Values()); 10 != l { + t.Errorf("len(s.Values()): 10 != %v\n", l) + } + for _, v := range s.Values() { + if v > 10 || v < 0 { + t.Errorf("out of range [0, 10): %v\n", v) + } + } +} + +func TestExpDecaySample100(t *testing.T) { + rand.Seed(1) + s := NewExpDecaySample(1000, 0.01) + for i := 0; i < 100; i++ { + s.Update(int64(i)) + } + if size := s.Count(); 100 != size { + t.Errorf("s.Count(): 100 != %v\n", size) + } + if size := s.Size(); 100 != size { + t.Errorf("s.Size(): 100 != %v\n", size) + } + if l := len(s.Values()); 100 != l { + t.Errorf("len(s.Values()): 100 != %v\n", l) + } + for _, v := range s.Values() { + if v > 100 || v < 0 { + t.Errorf("out of range [0, 100): %v\n", v) + } + } +} + +func TestExpDecaySample1000(t *testing.T) { + rand.Seed(1) + s := NewExpDecaySample(100, 0.99) + for i := 0; i < 1000; i++ { + s.Update(int64(i)) + } + if size := s.Count(); 1000 != size { + t.Errorf("s.Count(): 1000 != %v\n", size) + } + if size := s.Size(); 100 != size { + t.Errorf("s.Size(): 100 != %v\n", size) + } + if l := len(s.Values()); 100 != l { + t.Errorf("len(s.Values()): 100 != %v\n", l) + } + for _, v := range s.Values() { + if v > 1000 || v < 0 { + t.Errorf("out of range [0, 1000): %v\n", v) + } + } +} + +// This test makes sure that the sample's priority is not amplified by using +// nanosecond duration since start rather than second duration since start. +// The priority becomes +Inf quickly after starting if this is done, +// effectively freezing the set of samples until a rescale step happens. +func TestExpDecaySampleNanosecondRegression(t *testing.T) { + rand.Seed(1) + s := NewExpDecaySample(100, 0.99) + for i := 0; i < 100; i++ { + s.Update(10) + } + time.Sleep(1 * time.Millisecond) + for i := 0; i < 100; i++ { + s.Update(20) + } + v := s.Values() + avg := float64(0) + for i := 0; i < len(v); i++ { + avg += float64(v[i]) + } + avg /= float64(len(v)) + if avg > 16 || avg < 14 { + t.Errorf("out of range [14, 16]: %v\n", avg) + } +} + +func TestExpDecaySampleRescale(t *testing.T) { + s := NewExpDecaySample(2, 0.001).(*ExpDecaySample) + s.update(time.Now(), 1) + s.update(time.Now().Add(time.Hour+time.Microsecond), 1) + for _, v := range s.values.Values() { + if v.k == 0.0 { + t.Fatal("v.k == 0.0") + } + } +} + +func TestExpDecaySampleSnapshot(t *testing.T) { + now := time.Now() + rand.Seed(1) + s := NewExpDecaySample(100, 0.99) + for i := 1; i <= 10000; i++ { + s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) + } + snapshot := s.Snapshot() + s.Update(1) + testExpDecaySampleStatistics(t, snapshot) +} + +func TestExpDecaySampleStatistics(t *testing.T) { + now := time.Now() + rand.Seed(1) + s := NewExpDecaySample(100, 0.99) + for i := 1; i <= 10000; i++ { + s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) + } + testExpDecaySampleStatistics(t, s) +} + +func TestUniformSample(t *testing.T) { + rand.Seed(1) + s := NewUniformSample(100) + for i := 0; i < 1000; i++ { + s.Update(int64(i)) + } + if size := s.Count(); 1000 != size { + t.Errorf("s.Count(): 1000 != %v\n", size) + } + if size := s.Size(); 100 != size { + t.Errorf("s.Size(): 100 != %v\n", size) + } + if l := len(s.Values()); 100 != l { + t.Errorf("len(s.Values()): 100 != %v\n", l) + } + for _, v := range s.Values() { + if v > 1000 || v < 0 { + t.Errorf("out of range [0, 100): %v\n", v) + } + } +} + +func TestUniformSampleIncludesTail(t *testing.T) { + rand.Seed(1) + s := NewUniformSample(100) + max := 100 + for i := 0; i < max; i++ { + s.Update(int64(i)) + } + v := s.Values() + sum := 0 + exp := (max - 1) * max / 2 + for i := 0; i < len(v); i++ { + sum += int(v[i]) + } + if exp != sum { + t.Errorf("sum: %v != %v\n", exp, sum) + } +} + +func TestUniformSampleSnapshot(t *testing.T) { + s := NewUniformSample(100) + for i := 1; i <= 10000; i++ { + s.Update(int64(i)) + } + snapshot := s.Snapshot() + s.Update(1) + testUniformSampleStatistics(t, snapshot) +} + +func TestUniformSampleStatistics(t *testing.T) { + rand.Seed(1) + s := NewUniformSample(100) + for i := 1; i <= 10000; i++ { + s.Update(int64(i)) + } + testUniformSampleStatistics(t, s) +} + +func benchmarkSample(b *testing.B, s Sample) { + var memStats runtime.MemStats + runtime.ReadMemStats(&memStats) + pauseTotalNs := memStats.PauseTotalNs + b.ResetTimer() + for i := 0; i < b.N; i++ { + s.Update(1) + } + b.StopTimer() + runtime.GC() + runtime.ReadMemStats(&memStats) + b.Logf("GC cost: %d ns/op", int(memStats.PauseTotalNs-pauseTotalNs)/b.N) +} + +func testExpDecaySampleStatistics(t *testing.T, s Sample) { + if count := s.Count(); 10000 != count { + t.Errorf("s.Count(): 10000 != %v\n", count) + } + if min := s.Min(); 107 != min { + t.Errorf("s.Min(): 107 != %v\n", min) + } + if max := s.Max(); 10000 != max { + t.Errorf("s.Max(): 10000 != %v\n", max) + } + if mean := s.Mean(); 4965.98 != mean { + t.Errorf("s.Mean(): 4965.98 != %v\n", mean) + } + if stdDev := s.StdDev(); 2959.825156930727 != stdDev { + t.Errorf("s.StdDev(): 2959.825156930727 != %v\n", stdDev) + } + ps := s.Percentiles([]float64{0.5, 0.75, 0.99}) + if 4615 != ps[0] { + t.Errorf("median: 4615 != %v\n", ps[0]) + } + if 7672 != ps[1] { + t.Errorf("75th percentile: 7672 != %v\n", ps[1]) + } + if 9998.99 != ps[2] { + t.Errorf("99th percentile: 9998.99 != %v\n", ps[2]) + } +} + +func testUniformSampleStatistics(t *testing.T, s Sample) { + if count := s.Count(); 10000 != count { + t.Errorf("s.Count(): 10000 != %v\n", count) + } + if min := s.Min(); 37 != min { + t.Errorf("s.Min(): 37 != %v\n", min) + } + if max := s.Max(); 9989 != max { + t.Errorf("s.Max(): 9989 != %v\n", max) + } + if mean := s.Mean(); 4748.14 != mean { + t.Errorf("s.Mean(): 4748.14 != %v\n", mean) + } + if stdDev := s.StdDev(); 2826.684117548333 != stdDev { + t.Errorf("s.StdDev(): 2826.684117548333 != %v\n", stdDev) + } + ps := s.Percentiles([]float64{0.5, 0.75, 0.99}) + if 4599 != ps[0] { + t.Errorf("median: 4599 != %v\n", ps[0]) + } + if 7380.5 != ps[1] { + t.Errorf("75th percentile: 7380.5 != %v\n", ps[1]) + } + if 9986.429999999998 != ps[2] { + t.Errorf("99th percentile: 9986.429999999998 != %v\n", ps[2]) + } +} + +// TestUniformSampleConcurrentUpdateCount would expose data race problems with +// concurrent Update and Count calls on Sample when test is called with -race +// argument +func TestUniformSampleConcurrentUpdateCount(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + s := NewUniformSample(100) + for i := 0; i < 100; i++ { + s.Update(int64(i)) + } + quit := make(chan struct{}) + go func() { + t := time.NewTicker(10 * time.Millisecond) + for { + select { + case <-t.C: + s.Update(rand.Int63()) + case <-quit: + t.Stop() + return + } + } + }() + for i := 0; i < 1000; i++ { + s.Count() + time.Sleep(5 * time.Millisecond) + } + quit <- struct{}{} +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/stathat/stathat.go b/vendor/src/github.com/rcrowley/go-metrics/stathat/stathat.go new file mode 100644 index 00000000..0afcb484 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/stathat/stathat.go @@ -0,0 +1,69 @@ +// Metrics output to StatHat. +package stathat + +import ( + "github.com/rcrowley/go-metrics" + "github.com/stathat/go" + "log" + "time" +) + +func Stathat(r metrics.Registry, d time.Duration, userkey string) { + for { + if err := sh(r, userkey); nil != err { + log.Println(err) + } + time.Sleep(d) + } +} + +func sh(r metrics.Registry, userkey string) error { + r.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case metrics.Counter: + stathat.PostEZCount(name, userkey, int(metric.Count())) + case metrics.Gauge: + stathat.PostEZValue(name, userkey, float64(metric.Value())) + case metrics.GaugeFloat64: + stathat.PostEZValue(name, userkey, float64(metric.Value())) + case metrics.Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + stathat.PostEZCount(name+".count", userkey, int(h.Count())) + stathat.PostEZValue(name+".min", userkey, float64(h.Min())) + stathat.PostEZValue(name+".max", userkey, float64(h.Max())) + stathat.PostEZValue(name+".mean", userkey, float64(h.Mean())) + stathat.PostEZValue(name+".std-dev", userkey, float64(h.StdDev())) + stathat.PostEZValue(name+".50-percentile", userkey, float64(ps[0])) + stathat.PostEZValue(name+".75-percentile", userkey, float64(ps[1])) + stathat.PostEZValue(name+".95-percentile", userkey, float64(ps[2])) + stathat.PostEZValue(name+".99-percentile", userkey, float64(ps[3])) + stathat.PostEZValue(name+".999-percentile", userkey, float64(ps[4])) + case metrics.Meter: + m := metric.Snapshot() + stathat.PostEZCount(name+".count", userkey, int(m.Count())) + stathat.PostEZValue(name+".one-minute", userkey, float64(m.Rate1())) + stathat.PostEZValue(name+".five-minute", userkey, float64(m.Rate5())) + stathat.PostEZValue(name+".fifteen-minute", userkey, float64(m.Rate15())) + stathat.PostEZValue(name+".mean", userkey, float64(m.RateMean())) + case metrics.Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + stathat.PostEZCount(name+".count", userkey, int(t.Count())) + stathat.PostEZValue(name+".min", userkey, float64(t.Min())) + stathat.PostEZValue(name+".max", userkey, float64(t.Max())) + stathat.PostEZValue(name+".mean", userkey, float64(t.Mean())) + stathat.PostEZValue(name+".std-dev", userkey, float64(t.StdDev())) + stathat.PostEZValue(name+".50-percentile", userkey, float64(ps[0])) + stathat.PostEZValue(name+".75-percentile", userkey, float64(ps[1])) + stathat.PostEZValue(name+".95-percentile", userkey, float64(ps[2])) + stathat.PostEZValue(name+".99-percentile", userkey, float64(ps[3])) + stathat.PostEZValue(name+".999-percentile", userkey, float64(ps[4])) + stathat.PostEZValue(name+".one-minute", userkey, float64(t.Rate1())) + stathat.PostEZValue(name+".five-minute", userkey, float64(t.Rate5())) + stathat.PostEZValue(name+".fifteen-minute", userkey, float64(t.Rate15())) + stathat.PostEZValue(name+".mean-rate", userkey, float64(t.RateMean())) + } + }) + return nil +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/syslog.go b/vendor/src/github.com/rcrowley/go-metrics/syslog.go new file mode 100644 index 00000000..693f1908 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/syslog.go @@ -0,0 +1,78 @@ +// +build !windows + +package metrics + +import ( + "fmt" + "log/syslog" + "time" +) + +// Output each metric in the given registry to syslog periodically using +// the given syslogger. +func Syslog(r Registry, d time.Duration, w *syslog.Writer) { + for _ = range time.Tick(d) { + r.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Count())) + case Gauge: + w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Value())) + case GaugeFloat64: + w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Value())) + case Healthcheck: + metric.Check() + w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, metric.Error())) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + w.Info(fmt.Sprintf( + "histogram %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f", + name, + h.Count(), + h.Min(), + h.Max(), + h.Mean(), + h.StdDev(), + ps[0], + ps[1], + ps[2], + ps[3], + ps[4], + )) + case Meter: + m := metric.Snapshot() + w.Info(fmt.Sprintf( + "meter %s: count: %d 1-min: %.2f 5-min: %.2f 15-min: %.2f mean: %.2f", + name, + m.Count(), + m.Rate1(), + m.Rate5(), + m.Rate15(), + m.RateMean(), + )) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + w.Info(fmt.Sprintf( + "timer %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f 1-min: %.2f 5-min: %.2f 15-min: %.2f mean-rate: %.2f", + name, + t.Count(), + t.Min(), + t.Max(), + t.Mean(), + t.StdDev(), + ps[0], + ps[1], + ps[2], + ps[3], + ps[4], + t.Rate1(), + t.Rate5(), + t.Rate15(), + t.RateMean(), + )) + } + }) + } +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/timer.go b/vendor/src/github.com/rcrowley/go-metrics/timer.go new file mode 100644 index 00000000..17db8f8d --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/timer.go @@ -0,0 +1,311 @@ +package metrics + +import ( + "sync" + "time" +) + +// Timers capture the duration and rate of events. +type Timer interface { + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Rate1() float64 + Rate5() float64 + Rate15() float64 + RateMean() float64 + Snapshot() Timer + StdDev() float64 + Sum() int64 + Time(func()) + Update(time.Duration) + UpdateSince(time.Time) + Variance() float64 +} + +// GetOrRegisterTimer returns an existing Timer or constructs and registers a +// new StandardTimer. +func GetOrRegisterTimer(name string, r Registry) Timer { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewTimer).(Timer) +} + +// NewCustomTimer constructs a new StandardTimer from a Histogram and a Meter. +func NewCustomTimer(h Histogram, m Meter) Timer { + if UseNilMetrics { + return NilTimer{} + } + return &StandardTimer{ + histogram: h, + meter: m, + } +} + +// NewRegisteredTimer constructs and registers a new StandardTimer. +func NewRegisteredTimer(name string, r Registry) Timer { + c := NewTimer() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewTimer constructs a new StandardTimer using an exponentially-decaying +// sample with the same reservoir size and alpha as UNIX load averages. +func NewTimer() Timer { + if UseNilMetrics { + return NilTimer{} + } + return &StandardTimer{ + histogram: NewHistogram(NewExpDecaySample(1028, 0.015)), + meter: NewMeter(), + } +} + +// NilTimer is a no-op Timer. +type NilTimer struct { + h Histogram + m Meter +} + +// Count is a no-op. +func (NilTimer) Count() int64 { return 0 } + +// Max is a no-op. +func (NilTimer) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilTimer) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilTimer) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilTimer) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilTimer) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Rate1 is a no-op. +func (NilTimer) Rate1() float64 { return 0.0 } + +// Rate5 is a no-op. +func (NilTimer) Rate5() float64 { return 0.0 } + +// Rate15 is a no-op. +func (NilTimer) Rate15() float64 { return 0.0 } + +// RateMean is a no-op. +func (NilTimer) RateMean() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilTimer) Snapshot() Timer { return NilTimer{} } + +// StdDev is a no-op. +func (NilTimer) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilTimer) Sum() int64 { return 0 } + +// Time is a no-op. +func (NilTimer) Time(func()) {} + +// Update is a no-op. +func (NilTimer) Update(time.Duration) {} + +// UpdateSince is a no-op. +func (NilTimer) UpdateSince(time.Time) {} + +// Variance is a no-op. +func (NilTimer) Variance() float64 { return 0.0 } + +// StandardTimer is the standard implementation of a Timer and uses a Histogram +// and Meter. +type StandardTimer struct { + histogram Histogram + meter Meter + mutex sync.Mutex +} + +// Count returns the number of events recorded. +func (t *StandardTimer) Count() int64 { + return t.histogram.Count() +} + +// Max returns the maximum value in the sample. +func (t *StandardTimer) Max() int64 { + return t.histogram.Max() +} + +// Mean returns the mean of the values in the sample. +func (t *StandardTimer) Mean() float64 { + return t.histogram.Mean() +} + +// Min returns the minimum value in the sample. +func (t *StandardTimer) Min() int64 { + return t.histogram.Min() +} + +// Percentile returns an arbitrary percentile of the values in the sample. +func (t *StandardTimer) Percentile(p float64) float64 { + return t.histogram.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of the values in the +// sample. +func (t *StandardTimer) Percentiles(ps []float64) []float64 { + return t.histogram.Percentiles(ps) +} + +// Rate1 returns the one-minute moving average rate of events per second. +func (t *StandardTimer) Rate1() float64 { + return t.meter.Rate1() +} + +// Rate5 returns the five-minute moving average rate of events per second. +func (t *StandardTimer) Rate5() float64 { + return t.meter.Rate5() +} + +// Rate15 returns the fifteen-minute moving average rate of events per second. +func (t *StandardTimer) Rate15() float64 { + return t.meter.Rate15() +} + +// RateMean returns the meter's mean rate of events per second. +func (t *StandardTimer) RateMean() float64 { + return t.meter.RateMean() +} + +// Snapshot returns a read-only copy of the timer. +func (t *StandardTimer) Snapshot() Timer { + t.mutex.Lock() + defer t.mutex.Unlock() + return &TimerSnapshot{ + histogram: t.histogram.Snapshot().(*HistogramSnapshot), + meter: t.meter.Snapshot().(*MeterSnapshot), + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (t *StandardTimer) StdDev() float64 { + return t.histogram.StdDev() +} + +// Sum returns the sum in the sample. +func (t *StandardTimer) Sum() int64 { + return t.histogram.Sum() +} + +// Record the duration of the execution of the given function. +func (t *StandardTimer) Time(f func()) { + ts := time.Now() + f() + t.Update(time.Since(ts)) +} + +// Record the duration of an event. +func (t *StandardTimer) Update(d time.Duration) { + t.mutex.Lock() + defer t.mutex.Unlock() + t.histogram.Update(int64(d)) + t.meter.Mark(1) +} + +// Record the duration of an event that started at a time and ends now. +func (t *StandardTimer) UpdateSince(ts time.Time) { + t.mutex.Lock() + defer t.mutex.Unlock() + t.histogram.Update(int64(time.Since(ts))) + t.meter.Mark(1) +} + +// Variance returns the variance of the values in the sample. +func (t *StandardTimer) Variance() float64 { + return t.histogram.Variance() +} + +// TimerSnapshot is a read-only copy of another Timer. +type TimerSnapshot struct { + histogram *HistogramSnapshot + meter *MeterSnapshot +} + +// Count returns the number of events recorded at the time the snapshot was +// taken. +func (t *TimerSnapshot) Count() int64 { return t.histogram.Count() } + +// Max returns the maximum value at the time the snapshot was taken. +func (t *TimerSnapshot) Max() int64 { return t.histogram.Max() } + +// Mean returns the mean value at the time the snapshot was taken. +func (t *TimerSnapshot) Mean() float64 { return t.histogram.Mean() } + +// Min returns the minimum value at the time the snapshot was taken. +func (t *TimerSnapshot) Min() int64 { return t.histogram.Min() } + +// Percentile returns an arbitrary percentile of sampled values at the time the +// snapshot was taken. +func (t *TimerSnapshot) Percentile(p float64) float64 { + return t.histogram.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of sampled values at +// the time the snapshot was taken. +func (t *TimerSnapshot) Percentiles(ps []float64) []float64 { + return t.histogram.Percentiles(ps) +} + +// Rate1 returns the one-minute moving average rate of events per second at the +// time the snapshot was taken. +func (t *TimerSnapshot) Rate1() float64 { return t.meter.Rate1() } + +// Rate5 returns the five-minute moving average rate of events per second at +// the time the snapshot was taken. +func (t *TimerSnapshot) Rate5() float64 { return t.meter.Rate5() } + +// Rate15 returns the fifteen-minute moving average rate of events per second +// at the time the snapshot was taken. +func (t *TimerSnapshot) Rate15() float64 { return t.meter.Rate15() } + +// RateMean returns the meter's mean rate of events per second at the time the +// snapshot was taken. +func (t *TimerSnapshot) RateMean() float64 { return t.meter.RateMean() } + +// Snapshot returns the snapshot. +func (t *TimerSnapshot) Snapshot() Timer { return t } + +// StdDev returns the standard deviation of the values at the time the snapshot +// was taken. +func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() } + +// Sum returns the sum at the time the snapshot was taken. +func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() } + +// Time panics. +func (*TimerSnapshot) Time(func()) { + panic("Time called on a TimerSnapshot") +} + +// Update panics. +func (*TimerSnapshot) Update(time.Duration) { + panic("Update called on a TimerSnapshot") +} + +// UpdateSince panics. +func (*TimerSnapshot) UpdateSince(time.Time) { + panic("UpdateSince called on a TimerSnapshot") +} + +// Variance returns the variance of the values at the time the snapshot was +// taken. +func (t *TimerSnapshot) Variance() float64 { return t.histogram.Variance() } diff --git a/vendor/src/github.com/rcrowley/go-metrics/timer_test.go b/vendor/src/github.com/rcrowley/go-metrics/timer_test.go new file mode 100644 index 00000000..313d6915 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/timer_test.go @@ -0,0 +1,89 @@ +package metrics + +import ( + "fmt" + "math" + "testing" + "time" +) + +func BenchmarkTimer(b *testing.B) { + tm := NewTimer() + b.ResetTimer() + for i := 0; i < b.N; i++ { + tm.Update(1) + } +} + +func TestGetOrRegisterTimer(t *testing.T) { + r := NewRegistry() + NewRegisteredTimer("foo", r).Update(47) + if tm := GetOrRegisterTimer("foo", r); 1 != tm.Count() { + t.Fatal(tm) + } +} + +func TestTimerExtremes(t *testing.T) { + tm := NewTimer() + tm.Update(math.MaxInt64) + tm.Update(0) + if stdDev := tm.StdDev(); 4.611686018427388e+18 != stdDev { + t.Errorf("tm.StdDev(): 4.611686018427388e+18 != %v\n", stdDev) + } +} + +func TestTimerFunc(t *testing.T) { + tm := NewTimer() + tm.Time(func() { time.Sleep(50e6) }) + if max := tm.Max(); 45e6 > max || max > 55e6 { + t.Errorf("tm.Max(): 45e6 > %v || %v > 55e6\n", max, max) + } +} + +func TestTimerZero(t *testing.T) { + tm := NewTimer() + if count := tm.Count(); 0 != count { + t.Errorf("tm.Count(): 0 != %v\n", count) + } + if min := tm.Min(); 0 != min { + t.Errorf("tm.Min(): 0 != %v\n", min) + } + if max := tm.Max(); 0 != max { + t.Errorf("tm.Max(): 0 != %v\n", max) + } + if mean := tm.Mean(); 0.0 != mean { + t.Errorf("tm.Mean(): 0.0 != %v\n", mean) + } + if stdDev := tm.StdDev(); 0.0 != stdDev { + t.Errorf("tm.StdDev(): 0.0 != %v\n", stdDev) + } + ps := tm.Percentiles([]float64{0.5, 0.75, 0.99}) + if 0.0 != ps[0] { + t.Errorf("median: 0.0 != %v\n", ps[0]) + } + if 0.0 != ps[1] { + t.Errorf("75th percentile: 0.0 != %v\n", ps[1]) + } + if 0.0 != ps[2] { + t.Errorf("99th percentile: 0.0 != %v\n", ps[2]) + } + if rate1 := tm.Rate1(); 0.0 != rate1 { + t.Errorf("tm.Rate1(): 0.0 != %v\n", rate1) + } + if rate5 := tm.Rate5(); 0.0 != rate5 { + t.Errorf("tm.Rate5(): 0.0 != %v\n", rate5) + } + if rate15 := tm.Rate15(); 0.0 != rate15 { + t.Errorf("tm.Rate15(): 0.0 != %v\n", rate15) + } + if rateMean := tm.RateMean(); 0.0 != rateMean { + t.Errorf("tm.RateMean(): 0.0 != %v\n", rateMean) + } +} + +func ExampleGetOrRegisterTimer() { + m := "account.create.latency" + t := GetOrRegisterTimer(m, nil) + t.Update(47) + fmt.Println(t.Max()) // Output: 47 +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/validate.sh b/vendor/src/github.com/rcrowley/go-metrics/validate.sh new file mode 100644 index 00000000..f6499982 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/validate.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e + +# check there are no formatting issues +GOFMT_LINES=`gofmt -l . | wc -l | xargs` +test $GOFMT_LINES -eq 0 || echo "gofmt needs to be run, ${GOFMT_LINES} files have issues" + +# run the tests for the root package +go test . diff --git a/vendor/src/github.com/rcrowley/go-metrics/writer.go b/vendor/src/github.com/rcrowley/go-metrics/writer.go new file mode 100644 index 00000000..091e971d --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/writer.go @@ -0,0 +1,100 @@ +package metrics + +import ( + "fmt" + "io" + "sort" + "time" +) + +// Write sorts writes each metric in the given registry periodically to the +// given io.Writer. +func Write(r Registry, d time.Duration, w io.Writer) { + for _ = range time.Tick(d) { + WriteOnce(r, w) + } +} + +// WriteOnce sorts and writes metrics in the given registry to the given +// io.Writer. +func WriteOnce(r Registry, w io.Writer) { + var namedMetrics namedMetricSlice + r.Each(func(name string, i interface{}) { + namedMetrics = append(namedMetrics, namedMetric{name, i}) + }) + + sort.Sort(namedMetrics) + for _, namedMetric := range namedMetrics { + switch metric := namedMetric.m.(type) { + case Counter: + fmt.Fprintf(w, "counter %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", metric.Count()) + case Gauge: + fmt.Fprintf(w, "gauge %s\n", namedMetric.name) + fmt.Fprintf(w, " value: %9d\n", metric.Value()) + case GaugeFloat64: + fmt.Fprintf(w, "gauge %s\n", namedMetric.name) + fmt.Fprintf(w, " value: %f\n", metric.Value()) + case Healthcheck: + metric.Check() + fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name) + fmt.Fprintf(w, " error: %v\n", metric.Error()) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "histogram %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", h.Count()) + fmt.Fprintf(w, " min: %9d\n", h.Min()) + fmt.Fprintf(w, " max: %9d\n", h.Max()) + fmt.Fprintf(w, " mean: %12.2f\n", h.Mean()) + fmt.Fprintf(w, " stddev: %12.2f\n", h.StdDev()) + fmt.Fprintf(w, " median: %12.2f\n", ps[0]) + fmt.Fprintf(w, " 75%%: %12.2f\n", ps[1]) + fmt.Fprintf(w, " 95%%: %12.2f\n", ps[2]) + fmt.Fprintf(w, " 99%%: %12.2f\n", ps[3]) + fmt.Fprintf(w, " 99.9%%: %12.2f\n", ps[4]) + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "meter %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", m.Count()) + fmt.Fprintf(w, " 1-min rate: %12.2f\n", m.Rate1()) + fmt.Fprintf(w, " 5-min rate: %12.2f\n", m.Rate5()) + fmt.Fprintf(w, " 15-min rate: %12.2f\n", m.Rate15()) + fmt.Fprintf(w, " mean rate: %12.2f\n", m.RateMean()) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "timer %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", t.Count()) + fmt.Fprintf(w, " min: %9d\n", t.Min()) + fmt.Fprintf(w, " max: %9d\n", t.Max()) + fmt.Fprintf(w, " mean: %12.2f\n", t.Mean()) + fmt.Fprintf(w, " stddev: %12.2f\n", t.StdDev()) + fmt.Fprintf(w, " median: %12.2f\n", ps[0]) + fmt.Fprintf(w, " 75%%: %12.2f\n", ps[1]) + fmt.Fprintf(w, " 95%%: %12.2f\n", ps[2]) + fmt.Fprintf(w, " 99%%: %12.2f\n", ps[3]) + fmt.Fprintf(w, " 99.9%%: %12.2f\n", ps[4]) + fmt.Fprintf(w, " 1-min rate: %12.2f\n", t.Rate1()) + fmt.Fprintf(w, " 5-min rate: %12.2f\n", t.Rate5()) + fmt.Fprintf(w, " 15-min rate: %12.2f\n", t.Rate15()) + fmt.Fprintf(w, " mean rate: %12.2f\n", t.RateMean()) + } + } +} + +type namedMetric struct { + name string + m interface{} +} + +// namedMetricSlice is a slice of namedMetrics that implements sort.Interface. +type namedMetricSlice []namedMetric + +func (nms namedMetricSlice) Len() int { return len(nms) } + +func (nms namedMetricSlice) Swap(i, j int) { nms[i], nms[j] = nms[j], nms[i] } + +func (nms namedMetricSlice) Less(i, j int) bool { + return nms[i].name < nms[j].name +} diff --git a/vendor/src/github.com/rcrowley/go-metrics/writer_test.go b/vendor/src/github.com/rcrowley/go-metrics/writer_test.go new file mode 100644 index 00000000..1aacc287 --- /dev/null +++ b/vendor/src/github.com/rcrowley/go-metrics/writer_test.go @@ -0,0 +1,22 @@ +package metrics + +import ( + "sort" + "testing" +) + +func TestMetricsSorting(t *testing.T) { + var namedMetrics = namedMetricSlice{ + {name: "zzz"}, + {name: "bbb"}, + {name: "fff"}, + {name: "ggg"}, + } + + sort.Sort(namedMetrics) + for i, name := range []string{"bbb", "fff", "ggg", "zzz"} { + if namedMetrics[i].name != name { + t.Fail() + } + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/CHANGELOG.md b/vendor/src/gopkg.in/Shopify/sarama.v1/CHANGELOG.md new file mode 100644 index 00000000..aad986fe --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/CHANGELOG.md @@ -0,0 +1,350 @@ +# Changelog + +#### Version 1.11.0 (2016-12-20) + +New Features: + - Metrics! Thanks to Sébastien Launay for all his work on this feature + ([#701](https://github.com/Shopify/sarama/pull/701), + [#746](https://github.com/Shopify/sarama/pull/746), + [#766](https://github.com/Shopify/sarama/pull/766)). + - Add support for LZ4 compression + ([#786](https://github.com/Shopify/sarama/pull/786)). + - Add support for ListOffsetRequest v1 and Kafka 0.10.1 + ([#775](https://github.com/Shopify/sarama/pull/775)). + - Added a `HighWaterMarks` method to the Consumer which aggregates the + `HighWaterMarkOffset` values of its child topic/partitions + ([#769](https://github.com/Shopify/sarama/pull/769)). + +Bug Fixes: + - Fixed producing when using timestamps, compression and Kafka 0.10 + ([#759](https://github.com/Shopify/sarama/pull/759)). + - Added missing decoder methods to DescribeGroups response + ([#756](https://github.com/Shopify/sarama/pull/756)). + - Fix producer shutdown when `Return.Errors` is disabled + ([#787](https://github.com/Shopify/sarama/pull/787)). + - Don't mutate configuration in SyncProducer + ([#790](https://github.com/Shopify/sarama/pull/790)). + - Fix crash on SASL initialization failure + ([#795](https://github.com/Shopify/sarama/pull/795)). + +#### Version 1.10.1 (2016-08-30) + +Bug Fixes: + - Fix the documentation for `HashPartitioner` which was incorrect + ([#717](https://github.com/Shopify/sarama/pull/717)). + - Permit client creation even when it is limited by ACLs + ([#722](https://github.com/Shopify/sarama/pull/722)). + - Several fixes to the consumer timer optimization code, regressions introduced + in v1.10.0. Go's timers are finicky + ([#730](https://github.com/Shopify/sarama/pull/730), + [#733](https://github.com/Shopify/sarama/pull/733), + [#734](https://github.com/Shopify/sarama/pull/734)). + - Handle consuming compressed relative offsets with Kafka 0.10 + ([#735](https://github.com/Shopify/sarama/pull/735)). + +#### Version 1.10.0 (2016-08-02) + +_Important:_ As of Sarama 1.10 it is necessary to tell Sarama the version of +Kafka you are running against (via the `config.Version` value) in order to use +features that may not be compatible with old Kafka versions. If you don't +specify this value it will default to 0.8.2 (the minimum supported), and trying +to use more recent features (like the offset manager) will fail with an error. + +_Also:_ The offset-manager's behaviour has been changed to match the upstream +java consumer (see [#705](https://github.com/Shopify/sarama/pull/705) and +[#713](https://github.com/Shopify/sarama/pull/713)). If you use the +offset-manager, please ensure that you are committing one *greater* than the +last consumed message offset or else you may end up consuming duplicate +messages. + +New Features: + - Support for Kafka 0.10 + ([#672](https://github.com/Shopify/sarama/pull/672), + [#678](https://github.com/Shopify/sarama/pull/678), + [#681](https://github.com/Shopify/sarama/pull/681), and others). + - Support for configuring the target Kafka version + ([#676](https://github.com/Shopify/sarama/pull/676)). + - Batch producing support in the SyncProducer + ([#677](https://github.com/Shopify/sarama/pull/677)). + - Extend producer mock to allow setting expectations on message contents + ([#667](https://github.com/Shopify/sarama/pull/667)). + +Improvements: + - Support `nil` compressed messages for deleting in compacted topics + ([#634](https://github.com/Shopify/sarama/pull/634)). + - Pre-allocate decoding errors, greatly reducing heap usage and GC time against + misbehaving brokers ([#690](https://github.com/Shopify/sarama/pull/690)). + - Re-use consumer expiry timers, removing one allocation per consumed message + ([#707](https://github.com/Shopify/sarama/pull/707)). + +Bug Fixes: + - Actually default the client ID to "sarama" like we say we do + ([#664](https://github.com/Shopify/sarama/pull/664)). + - Fix a rare issue where `Client.Leader` could return the wrong error + ([#685](https://github.com/Shopify/sarama/pull/685)). + - Fix a possible tight loop in the consumer + ([#693](https://github.com/Shopify/sarama/pull/693)). + - Match upstream's offset-tracking behaviour + ([#705](https://github.com/Shopify/sarama/pull/705)). + - Report UnknownTopicOrPartition errors from the offset manager + ([#706](https://github.com/Shopify/sarama/pull/706)). + - Fix possible negative partition value from the HashPartitioner + ([#709](https://github.com/Shopify/sarama/pull/709)). + +#### Version 1.9.0 (2016-05-16) + +New Features: + - Add support for custom offset manager retention durations + ([#602](https://github.com/Shopify/sarama/pull/602)). + - Publish low-level mocks to enable testing of third-party producer/consumer + implementations ([#570](https://github.com/Shopify/sarama/pull/570)). + - Declare support for Golang 1.6 + ([#611](https://github.com/Shopify/sarama/pull/611)). + - Support for SASL plain-text auth + ([#648](https://github.com/Shopify/sarama/pull/648)). + +Improvements: + - Simplified broker locking scheme slightly + ([#604](https://github.com/Shopify/sarama/pull/604)). + - Documentation cleanup + ([#605](https://github.com/Shopify/sarama/pull/605), + [#621](https://github.com/Shopify/sarama/pull/621), + [#654](https://github.com/Shopify/sarama/pull/654)). + +Bug Fixes: + - Fix race condition shutting down the OffsetManager + ([#658](https://github.com/Shopify/sarama/pull/658)). + +#### Version 1.8.0 (2016-02-01) + +New Features: + - Full support for Kafka 0.9: + - All protocol messages and fields + ([#586](https://github.com/Shopify/sarama/pull/586), + [#588](https://github.com/Shopify/sarama/pull/588), + [#590](https://github.com/Shopify/sarama/pull/590)). + - Verified that TLS support works + ([#581](https://github.com/Shopify/sarama/pull/581)). + - Fixed the OffsetManager compatibility + ([#585](https://github.com/Shopify/sarama/pull/585)). + +Improvements: + - Optimize for fewer system calls when reading from the network + ([#584](https://github.com/Shopify/sarama/pull/584)). + - Automatically retry `InvalidMessage` errors to match upstream behaviour + ([#589](https://github.com/Shopify/sarama/pull/589)). + +#### Version 1.7.0 (2015-12-11) + +New Features: + - Preliminary support for Kafka 0.9 + ([#572](https://github.com/Shopify/sarama/pull/572)). This comes with several + caveats: + - Protocol-layer support is mostly in place + ([#577](https://github.com/Shopify/sarama/pull/577)), however Kafka 0.9 + renamed some messages and fields, which we did not in order to preserve API + compatibility. + - The producer and consumer work against 0.9, but the offset manager does + not ([#573](https://github.com/Shopify/sarama/pull/573)). + - TLS support may or may not work + ([#581](https://github.com/Shopify/sarama/pull/581)). + +Improvements: + - Don't wait for request timeouts on dead brokers, greatly speeding recovery + when the TCP connection is left hanging + ([#548](https://github.com/Shopify/sarama/pull/548)). + - Refactored part of the producer. The new version provides a much more elegant + solution to [#449](https://github.com/Shopify/sarama/pull/449). It is also + slightly more efficient, and much more precise in calculating batch sizes + when compression is used + ([#549](https://github.com/Shopify/sarama/pull/549), + [#550](https://github.com/Shopify/sarama/pull/550), + [#551](https://github.com/Shopify/sarama/pull/551)). + +Bug Fixes: + - Fix race condition in consumer test mock + ([#553](https://github.com/Shopify/sarama/pull/553)). + +#### Version 1.6.1 (2015-09-25) + +Bug Fixes: + - Fix panic that could occur if a user-supplied message value failed to encode + ([#449](https://github.com/Shopify/sarama/pull/449)). + +#### Version 1.6.0 (2015-09-04) + +New Features: + - Implementation of a consumer offset manager using the APIs introduced in + Kafka 0.8.2. The API is designed mainly for integration into a future + high-level consumer, not for direct use, although it is *possible* to use it + directly. + ([#461](https://github.com/Shopify/sarama/pull/461)). + +Improvements: + - CRC32 calculation is much faster on machines with SSE4.2 instructions, + removing a major hotspot from most profiles + ([#255](https://github.com/Shopify/sarama/pull/255)). + +Bug Fixes: + - Make protocol decoding more robust against some malformed packets generated + by go-fuzz ([#523](https://github.com/Shopify/sarama/pull/523), + [#525](https://github.com/Shopify/sarama/pull/525)) or found in other ways + ([#528](https://github.com/Shopify/sarama/pull/528)). + - Fix a potential race condition panic in the consumer on shutdown + ([#529](https://github.com/Shopify/sarama/pull/529)). + +#### Version 1.5.0 (2015-08-17) + +New Features: + - TLS-encrypted network connections are now supported. This feature is subject + to change when Kafka releases built-in TLS support, but for now this is + enough to work with TLS-terminating proxies + ([#154](https://github.com/Shopify/sarama/pull/154)). + +Improvements: + - The consumer will not block if a single partition is not drained by the user; + all other partitions will continue to consume normally + ([#485](https://github.com/Shopify/sarama/pull/485)). + - Formatting of error strings has been much improved + ([#495](https://github.com/Shopify/sarama/pull/495)). + - Internal refactoring of the producer for code cleanliness and to enable + future work ([#300](https://github.com/Shopify/sarama/pull/300)). + +Bug Fixes: + - Fix a potential deadlock in the consumer on shutdown + ([#475](https://github.com/Shopify/sarama/pull/475)). + +#### Version 1.4.3 (2015-07-21) + +Bug Fixes: + - Don't include the partitioner in the producer's "fetch partitions" + circuit-breaker ([#466](https://github.com/Shopify/sarama/pull/466)). + - Don't retry messages until the broker is closed when abandoning a broker in + the producer ([#468](https://github.com/Shopify/sarama/pull/468)). + - Update the import path for snappy-go, it has moved again and the API has + changed slightly ([#486](https://github.com/Shopify/sarama/pull/486)). + +#### Version 1.4.2 (2015-05-27) + +Bug Fixes: + - Update the import path for snappy-go, it has moved from google code to github + ([#456](https://github.com/Shopify/sarama/pull/456)). + +#### Version 1.4.1 (2015-05-25) + +Improvements: + - Optimizations when decoding snappy messages, thanks to John Potocny + ([#446](https://github.com/Shopify/sarama/pull/446)). + +Bug Fixes: + - Fix hypothetical race conditions on producer shutdown + ([#450](https://github.com/Shopify/sarama/pull/450), + [#451](https://github.com/Shopify/sarama/pull/451)). + +#### Version 1.4.0 (2015-05-01) + +New Features: + - The consumer now implements `Topics()` and `Partitions()` methods to enable + users to dynamically choose what topics/partitions to consume without + instantiating a full client + ([#431](https://github.com/Shopify/sarama/pull/431)). + - The partition-consumer now exposes the high water mark offset value returned + by the broker via the `HighWaterMarkOffset()` method ([#339](https://github.com/Shopify/sarama/pull/339)). + - Added a `kafka-console-consumer` tool capable of handling multiple + partitions, and deprecated the now-obsolete `kafka-console-partitionConsumer` + ([#439](https://github.com/Shopify/sarama/pull/439), + [#442](https://github.com/Shopify/sarama/pull/442)). + +Improvements: + - The producer's logging during retry scenarios is more consistent, more + useful, and slightly less verbose + ([#429](https://github.com/Shopify/sarama/pull/429)). + - The client now shuffles its initial list of seed brokers in order to prevent + thundering herd on the first broker in the list + ([#441](https://github.com/Shopify/sarama/pull/441)). + +Bug Fixes: + - The producer now correctly manages its state if retries occur when it is + shutting down, fixing several instances of confusing behaviour and at least + one potential deadlock ([#419](https://github.com/Shopify/sarama/pull/419)). + - The consumer now handles messages for different partitions asynchronously, + making it much more resilient to specific user code ordering + ([#325](https://github.com/Shopify/sarama/pull/325)). + +#### Version 1.3.0 (2015-04-16) + +New Features: + - The client now tracks consumer group coordinators using + ConsumerMetadataRequests similar to how it tracks partition leadership using + regular MetadataRequests ([#411](https://github.com/Shopify/sarama/pull/411)). + This adds two methods to the client API: + - `Coordinator(consumerGroup string) (*Broker, error)` + - `RefreshCoordinator(consumerGroup string) error` + +Improvements: + - ConsumerMetadataResponses now automatically create a Broker object out of the + ID/address/port combination for the Coordinator; accessing the fields + individually has been deprecated + ([#413](https://github.com/Shopify/sarama/pull/413)). + - Much improved handling of `OffsetOutOfRange` errors in the consumer. + Consumers will fail to start if the provided offset is out of range + ([#418](https://github.com/Shopify/sarama/pull/418)) + and they will automatically shut down if the offset falls out of range + ([#424](https://github.com/Shopify/sarama/pull/424)). + - Small performance improvement in encoding and decoding protocol messages + ([#427](https://github.com/Shopify/sarama/pull/427)). + +Bug Fixes: + - Fix a rare race condition in the client's background metadata refresher if + it happens to be activated while the client is being closed + ([#422](https://github.com/Shopify/sarama/pull/422)). + +#### Version 1.2.0 (2015-04-07) + +Improvements: + - The producer's behaviour when `Flush.Frequency` is set is now more intuitive + ([#389](https://github.com/Shopify/sarama/pull/389)). + - The producer is now somewhat more memory-efficient during and after retrying + messages due to an improved queue implementation + ([#396](https://github.com/Shopify/sarama/pull/396)). + - The consumer produces much more useful logging output when leadership + changes ([#385](https://github.com/Shopify/sarama/pull/385)). + - The client's `GetOffset` method will now automatically refresh metadata and + retry once in the event of stale information or similar + ([#394](https://github.com/Shopify/sarama/pull/394)). + - Broker connections now have support for using TCP keepalives + ([#407](https://github.com/Shopify/sarama/issues/407)). + +Bug Fixes: + - The OffsetCommitRequest message now correctly implements all three possible + API versions ([#390](https://github.com/Shopify/sarama/pull/390), + [#400](https://github.com/Shopify/sarama/pull/400)). + +#### Version 1.1.0 (2015-03-20) + +Improvements: + - Wrap the producer's partitioner call in a circuit-breaker so that repeatedly + broken topics don't choke throughput + ([#373](https://github.com/Shopify/sarama/pull/373)). + +Bug Fixes: + - Fix the producer's internal reference counting in certain unusual scenarios + ([#367](https://github.com/Shopify/sarama/pull/367)). + - Fix the consumer's internal reference counting in certain unusual scenarios + ([#369](https://github.com/Shopify/sarama/pull/369)). + - Fix a condition where the producer's internal control messages could have + gotten stuck ([#368](https://github.com/Shopify/sarama/pull/368)). + - Fix an issue where invalid partition lists would be cached when asking for + metadata for a non-existant topic ([#372](https://github.com/Shopify/sarama/pull/372)). + + +#### Version 1.0.0 (2015-03-17) + +Version 1.0.0 is the first tagged version, and is almost a complete rewrite. The primary differences with previous untagged versions are: + +- The producer has been rewritten; there is now a `SyncProducer` with a blocking API, and an `AsyncProducer` that is non-blocking. +- The consumer has been rewritten to only open one connection per broker instead of one connection per partition. +- The main types of Sarama are now interfaces to make depedency injection easy; mock implementations for `Consumer`, `SyncProducer` and `AsyncProducer` are provided in the `github.com/Shopify/sarama/mocks` package. +- For most uses cases, it is no longer necessary to open a `Client`; this will be done for you. +- All the configuration values have been unified in the `Config` struct. +- Much improved test suite. diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/MIT-LICENSE b/vendor/src/gopkg.in/Shopify/sarama.v1/MIT-LICENSE new file mode 100644 index 00000000..8121b63b --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2013 Evan Huus + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/Makefile b/vendor/src/gopkg.in/Shopify/sarama.v1/Makefile new file mode 100644 index 00000000..626b09a5 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/Makefile @@ -0,0 +1,21 @@ +default: fmt vet errcheck test + +test: + go test -v -timeout 60s -race ./... + +vet: + go vet ./... + +errcheck: + errcheck github.com/Shopify/sarama/... + +fmt: + @if [ -n "$$(go fmt ./...)" ]; then echo 'Please run go fmt on your code.' && exit 1; fi + +install_dependencies: install_errcheck get + +install_errcheck: + go get github.com/kisielk/errcheck + +get: + go get -t diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/README.md b/vendor/src/gopkg.in/Shopify/sarama.v1/README.md new file mode 100644 index 00000000..c2968b92 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/README.md @@ -0,0 +1,36 @@ +sarama +====== + +[![GoDoc](https://godoc.org/github.com/Shopify/sarama?status.png)](https://godoc.org/github.com/Shopify/sarama) +[![Build Status](https://travis-ci.org/Shopify/sarama.svg?branch=master)](https://travis-ci.org/Shopify/sarama) + +Sarama is an MIT-licensed Go client library for [Apache Kafka](https://kafka.apache.org/) version 0.8 (and later). + +### Getting started + +- API documentation and examples are available via [godoc](https://godoc.org/github.com/Shopify/sarama). +- Mocks for testing are available in the [mocks](./mocks) subpackage. +- The [examples](./examples) directory contains more elaborate example applications. +- The [tools](./tools) directory contains command line tools that can be useful for testing, diagnostics, and instrumentation. + +### Compatibility and API stability + +Sarama provides a "2 releases + 2 months" compatibility guarantee: we support +the two latest stable releases of Kafka and Go, and we provide a two month +grace period for older releases. This means we currently officially support +Go 1.7 and 1.6, and Kafka 0.10.0 and 0.9.0, although older releases are +still likely to work. + +Sarama follows semantic versioning and provides API stability via the gopkg.in service. +You can import a version with a guaranteed stable API via http://gopkg.in/Shopify/sarama.v1. +A changelog is available [here](CHANGELOG.md). + +### Contributing + +* Get started by checking our [contribution guidelines](https://github.com/Shopify/sarama/blob/master/CONTRIBUTING.md). +* Read the [Sarama wiki](https://github.com/Shopify/sarama/wiki) for more + technical and design details. +* The [Kafka Protocol Specification](https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol) + contains a wealth of useful information. +* For more general issues, there is [a google group](https://groups.google.com/forum/#!forum/kafka-clients) for Kafka client developers. +* If you have any questions, just ask! diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/Vagrantfile b/vendor/src/gopkg.in/Shopify/sarama.v1/Vagrantfile new file mode 100644 index 00000000..f4b848a3 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/Vagrantfile @@ -0,0 +1,20 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +# We have 5 * 192MB ZK processes and 5 * 320MB Kafka processes => 2560MB +MEMORY = 3072 + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.box = "ubuntu/trusty64" + + config.vm.provision :shell, path: "vagrant/provision.sh" + + config.vm.network "private_network", ip: "192.168.100.67" + + config.vm.provider "virtualbox" do |v| + v.memory = MEMORY + end +end diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_request.go new file mode 100644 index 00000000..ab65f01c --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_request.go @@ -0,0 +1,24 @@ +package sarama + +type ApiVersionsRequest struct { +} + +func (r *ApiVersionsRequest) encode(pe packetEncoder) error { + return nil +} + +func (r *ApiVersionsRequest) decode(pd packetDecoder, version int16) (err error) { + return nil +} + +func (r *ApiVersionsRequest) key() int16 { + return 18 +} + +func (r *ApiVersionsRequest) version() int16 { + return 0 +} + +func (r *ApiVersionsRequest) requiredVersion() KafkaVersion { + return V0_10_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_request_test.go new file mode 100644 index 00000000..5ab4fa71 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_request_test.go @@ -0,0 +1,14 @@ +package sarama + +import "testing" + +var ( + apiVersionRequest = []byte{} +) + +func TestApiVersionsRequest(t *testing.T) { + var request *ApiVersionsRequest + + request = new(ApiVersionsRequest) + testRequest(t, "basic", request, apiVersionRequest) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_response.go new file mode 100644 index 00000000..16d62db2 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_response.go @@ -0,0 +1,86 @@ +package sarama + +type ApiVersionsResponseBlock struct { + ApiKey int16 + MinVersion int16 + MaxVersion int16 +} + +func (b *ApiVersionsResponseBlock) encode(pe packetEncoder) error { + pe.putInt16(b.ApiKey) + pe.putInt16(b.MinVersion) + pe.putInt16(b.MaxVersion) + return nil +} + +func (b *ApiVersionsResponseBlock) decode(pd packetDecoder) error { + var err error + + if b.ApiKey, err = pd.getInt16(); err != nil { + return err + } + + if b.MinVersion, err = pd.getInt16(); err != nil { + return err + } + + if b.MaxVersion, err = pd.getInt16(); err != nil { + return err + } + + return nil +} + +type ApiVersionsResponse struct { + Err KError + ApiVersions []*ApiVersionsResponseBlock +} + +func (r *ApiVersionsResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + if err := pe.putArrayLength(len(r.ApiVersions)); err != nil { + return err + } + for _, apiVersion := range r.ApiVersions { + if err := apiVersion.encode(pe); err != nil { + return err + } + } + return nil +} + +func (r *ApiVersionsResponse) decode(pd packetDecoder, version int16) error { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + numBlocks, err := pd.getArrayLength() + if err != nil { + return err + } + + r.ApiVersions = make([]*ApiVersionsResponseBlock, numBlocks) + for i := 0; i < numBlocks; i++ { + block := new(ApiVersionsResponseBlock) + if err := block.decode(pd); err != nil { + return err + } + r.ApiVersions[i] = block + } + + return nil +} + +func (r *ApiVersionsResponse) key() int16 { + return 18 +} + +func (r *ApiVersionsResponse) version() int16 { + return 0 +} + +func (r *ApiVersionsResponse) requiredVersion() KafkaVersion { + return V0_10_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_response_test.go new file mode 100644 index 00000000..675a65a7 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/api_versions_response_test.go @@ -0,0 +1,32 @@ +package sarama + +import "testing" + +var ( + apiVersionResponse = []byte{ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x03, + 0x00, 0x02, + 0x00, 0x01, + } +) + +func TestApiVersionsResponse(t *testing.T) { + var response *ApiVersionsResponse + + response = new(ApiVersionsResponse) + testVersionDecodable(t, "no error", response, apiVersionResponse, 0) + if response.Err != ErrNoError { + t.Error("Decoding error failed: no error expected but found", response.Err) + } + if response.ApiVersions[0].ApiKey != 0x03 { + t.Error("Decoding error: expected 0x03 but got", response.ApiVersions[0].ApiKey) + } + if response.ApiVersions[0].MinVersion != 0x02 { + t.Error("Decoding error: expected 0x02 but got", response.ApiVersions[0].MinVersion) + } + if response.ApiVersions[0].MaxVersion != 0x01 { + t.Error("Decoding error: expected 0x01 but got", response.ApiVersions[0].MaxVersion) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/async_producer.go b/vendor/src/gopkg.in/Shopify/sarama.v1/async_producer.go new file mode 100644 index 00000000..3af47fdd --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/async_producer.go @@ -0,0 +1,905 @@ +package sarama + +import ( + "fmt" + "sync" + "time" + + "github.com/eapache/go-resiliency/breaker" + "github.com/eapache/queue" +) + +// AsyncProducer publishes Kafka messages using a non-blocking API. It routes messages +// to the correct broker for the provided topic-partition, refreshing metadata as appropriate, +// and parses responses for errors. You must read from the Errors() channel or the +// producer will deadlock. You must call Close() or AsyncClose() on a producer to avoid +// leaks: it will not be garbage-collected automatically when it passes out of +// scope. +type AsyncProducer interface { + + // AsyncClose triggers a shutdown of the producer, flushing any messages it may + // have buffered. The shutdown has completed when both the Errors and Successes + // channels have been closed. When calling AsyncClose, you *must* continue to + // read from those channels in order to drain the results of any messages in + // flight. + AsyncClose() + + // Close shuts down the producer and flushes any messages it may have buffered. + // You must call this function before a producer object passes out of scope, as + // it may otherwise leak memory. You must call this before calling Close on the + // underlying client. + Close() error + + // Input is the input channel for the user to write messages to that they + // wish to send. + Input() chan<- *ProducerMessage + + // Successes is the success output channel back to the user when AckSuccesses is + // enabled. If Return.Successes is true, you MUST read from this channel or the + // Producer will deadlock. It is suggested that you send and read messages + // together in a single select statement. + Successes() <-chan *ProducerMessage + + // Errors is the error output channel back to the user. You MUST read from this + // channel or the Producer will deadlock when the channel is full. Alternatively, + // you can set Producer.Return.Errors in your config to false, which prevents + // errors to be returned. + Errors() <-chan *ProducerError +} + +type asyncProducer struct { + client Client + conf *Config + ownClient bool + + errors chan *ProducerError + input, successes, retries chan *ProducerMessage + inFlight sync.WaitGroup + + brokers map[*Broker]chan<- *ProducerMessage + brokerRefs map[chan<- *ProducerMessage]int + brokerLock sync.Mutex +} + +// NewAsyncProducer creates a new AsyncProducer using the given broker addresses and configuration. +func NewAsyncProducer(addrs []string, conf *Config) (AsyncProducer, error) { + client, err := NewClient(addrs, conf) + if err != nil { + return nil, err + } + + p, err := NewAsyncProducerFromClient(client) + if err != nil { + return nil, err + } + p.(*asyncProducer).ownClient = true + return p, nil +} + +// NewAsyncProducerFromClient creates a new Producer using the given client. It is still +// necessary to call Close() on the underlying client when shutting down this producer. +func NewAsyncProducerFromClient(client Client) (AsyncProducer, error) { + // Check that we are not dealing with a closed Client before processing any other arguments + if client.Closed() { + return nil, ErrClosedClient + } + + p := &asyncProducer{ + client: client, + conf: client.Config(), + errors: make(chan *ProducerError), + input: make(chan *ProducerMessage), + successes: make(chan *ProducerMessage), + retries: make(chan *ProducerMessage), + brokers: make(map[*Broker]chan<- *ProducerMessage), + brokerRefs: make(map[chan<- *ProducerMessage]int), + } + + // launch our singleton dispatchers + go withRecover(p.dispatcher) + go withRecover(p.retryHandler) + + return p, nil +} + +type flagSet int8 + +const ( + syn flagSet = 1 << iota // first message from partitionProducer to brokerProducer + fin // final message from partitionProducer to brokerProducer and back + shutdown // start the shutdown process +) + +// ProducerMessage is the collection of elements passed to the Producer in order to send a message. +type ProducerMessage struct { + Topic string // The Kafka topic for this message. + // The partitioning key for this message. Pre-existing Encoders include + // StringEncoder and ByteEncoder. + Key Encoder + // The actual message to store in Kafka. Pre-existing Encoders include + // StringEncoder and ByteEncoder. + Value Encoder + + // This field is used to hold arbitrary data you wish to include so it + // will be available when receiving on the Successes and Errors channels. + // Sarama completely ignores this field and is only to be used for + // pass-through data. + Metadata interface{} + + // Below this point are filled in by the producer as the message is processed + + // Offset is the offset of the message stored on the broker. This is only + // guaranteed to be defined if the message was successfully delivered and + // RequiredAcks is not NoResponse. + Offset int64 + // Partition is the partition that the message was sent to. This is only + // guaranteed to be defined if the message was successfully delivered. + Partition int32 + // Timestamp is the timestamp assigned to the message by the broker. This + // is only guaranteed to be defined if the message was successfully + // delivered, RequiredAcks is not NoResponse, and the Kafka broker is at + // least version 0.10.0. + Timestamp time.Time + + retries int + flags flagSet +} + +const producerMessageOverhead = 26 // the metadata overhead of CRC, flags, etc. + +func (m *ProducerMessage) byteSize() int { + size := producerMessageOverhead + if m.Key != nil { + size += m.Key.Length() + } + if m.Value != nil { + size += m.Value.Length() + } + return size +} + +func (m *ProducerMessage) clear() { + m.flags = 0 + m.retries = 0 +} + +// ProducerError is the type of error generated when the producer fails to deliver a message. +// It contains the original ProducerMessage as well as the actual error value. +type ProducerError struct { + Msg *ProducerMessage + Err error +} + +func (pe ProducerError) Error() string { + return fmt.Sprintf("kafka: Failed to produce message to topic %s: %s", pe.Msg.Topic, pe.Err) +} + +// ProducerErrors is a type that wraps a batch of "ProducerError"s and implements the Error interface. +// It can be returned from the Producer's Close method to avoid the need to manually drain the Errors channel +// when closing a producer. +type ProducerErrors []*ProducerError + +func (pe ProducerErrors) Error() string { + return fmt.Sprintf("kafka: Failed to deliver %d messages.", len(pe)) +} + +func (p *asyncProducer) Errors() <-chan *ProducerError { + return p.errors +} + +func (p *asyncProducer) Successes() <-chan *ProducerMessage { + return p.successes +} + +func (p *asyncProducer) Input() chan<- *ProducerMessage { + return p.input +} + +func (p *asyncProducer) Close() error { + p.AsyncClose() + + if p.conf.Producer.Return.Successes { + go withRecover(func() { + for _ = range p.successes { + } + }) + } + + var errors ProducerErrors + if p.conf.Producer.Return.Errors { + for event := range p.errors { + errors = append(errors, event) + } + } else { + <-p.errors + } + + if len(errors) > 0 { + return errors + } + return nil +} + +func (p *asyncProducer) AsyncClose() { + go withRecover(p.shutdown) +} + +// singleton +// dispatches messages by topic +func (p *asyncProducer) dispatcher() { + handlers := make(map[string]chan<- *ProducerMessage) + shuttingDown := false + + for msg := range p.input { + if msg == nil { + Logger.Println("Something tried to send a nil message, it was ignored.") + continue + } + + if msg.flags&shutdown != 0 { + shuttingDown = true + p.inFlight.Done() + continue + } else if msg.retries == 0 { + if shuttingDown { + // we can't just call returnError here because that decrements the wait group, + // which hasn't been incremented yet for this message, and shouldn't be + pErr := &ProducerError{Msg: msg, Err: ErrShuttingDown} + if p.conf.Producer.Return.Errors { + p.errors <- pErr + } else { + Logger.Println(pErr) + } + continue + } + p.inFlight.Add(1) + } + + if msg.byteSize() > p.conf.Producer.MaxMessageBytes { + p.returnError(msg, ErrMessageSizeTooLarge) + continue + } + + handler := handlers[msg.Topic] + if handler == nil { + handler = p.newTopicProducer(msg.Topic) + handlers[msg.Topic] = handler + } + + handler <- msg + } + + for _, handler := range handlers { + close(handler) + } +} + +// one per topic +// partitions messages, then dispatches them by partition +type topicProducer struct { + parent *asyncProducer + topic string + input <-chan *ProducerMessage + + breaker *breaker.Breaker + handlers map[int32]chan<- *ProducerMessage + partitioner Partitioner +} + +func (p *asyncProducer) newTopicProducer(topic string) chan<- *ProducerMessage { + input := make(chan *ProducerMessage, p.conf.ChannelBufferSize) + tp := &topicProducer{ + parent: p, + topic: topic, + input: input, + breaker: breaker.New(3, 1, 10*time.Second), + handlers: make(map[int32]chan<- *ProducerMessage), + partitioner: p.conf.Producer.Partitioner(topic), + } + go withRecover(tp.dispatch) + return input +} + +func (tp *topicProducer) dispatch() { + for msg := range tp.input { + if msg.retries == 0 { + if err := tp.partitionMessage(msg); err != nil { + tp.parent.returnError(msg, err) + continue + } + } + + handler := tp.handlers[msg.Partition] + if handler == nil { + handler = tp.parent.newPartitionProducer(msg.Topic, msg.Partition) + tp.handlers[msg.Partition] = handler + } + + handler <- msg + } + + for _, handler := range tp.handlers { + close(handler) + } +} + +func (tp *topicProducer) partitionMessage(msg *ProducerMessage) error { + var partitions []int32 + + err := tp.breaker.Run(func() (err error) { + if tp.partitioner.RequiresConsistency() { + partitions, err = tp.parent.client.Partitions(msg.Topic) + } else { + partitions, err = tp.parent.client.WritablePartitions(msg.Topic) + } + return + }) + + if err != nil { + return err + } + + numPartitions := int32(len(partitions)) + + if numPartitions == 0 { + return ErrLeaderNotAvailable + } + + choice, err := tp.partitioner.Partition(msg, numPartitions) + + if err != nil { + return err + } else if choice < 0 || choice >= numPartitions { + return ErrInvalidPartition + } + + msg.Partition = partitions[choice] + + return nil +} + +// one per partition per topic +// dispatches messages to the appropriate broker +// also responsible for maintaining message order during retries +type partitionProducer struct { + parent *asyncProducer + topic string + partition int32 + input <-chan *ProducerMessage + + leader *Broker + breaker *breaker.Breaker + output chan<- *ProducerMessage + + // highWatermark tracks the "current" retry level, which is the only one where we actually let messages through, + // all other messages get buffered in retryState[msg.retries].buf to preserve ordering + // retryState[msg.retries].expectChaser simply tracks whether we've seen a fin message for a given level (and + // therefore whether our buffer is complete and safe to flush) + highWatermark int + retryState []partitionRetryState +} + +type partitionRetryState struct { + buf []*ProducerMessage + expectChaser bool +} + +func (p *asyncProducer) newPartitionProducer(topic string, partition int32) chan<- *ProducerMessage { + input := make(chan *ProducerMessage, p.conf.ChannelBufferSize) + pp := &partitionProducer{ + parent: p, + topic: topic, + partition: partition, + input: input, + + breaker: breaker.New(3, 1, 10*time.Second), + retryState: make([]partitionRetryState, p.conf.Producer.Retry.Max+1), + } + go withRecover(pp.dispatch) + return input +} + +func (pp *partitionProducer) dispatch() { + // try to prefetch the leader; if this doesn't work, we'll do a proper call to `updateLeader` + // on the first message + pp.leader, _ = pp.parent.client.Leader(pp.topic, pp.partition) + if pp.leader != nil { + pp.output = pp.parent.getBrokerProducer(pp.leader) + pp.parent.inFlight.Add(1) // we're generating a syn message; track it so we don't shut down while it's still inflight + pp.output <- &ProducerMessage{Topic: pp.topic, Partition: pp.partition, flags: syn} + } + + for msg := range pp.input { + if msg.retries > pp.highWatermark { + // a new, higher, retry level; handle it and then back off + pp.newHighWatermark(msg.retries) + time.Sleep(pp.parent.conf.Producer.Retry.Backoff) + } else if pp.highWatermark > 0 { + // we are retrying something (else highWatermark would be 0) but this message is not a *new* retry level + if msg.retries < pp.highWatermark { + // in fact this message is not even the current retry level, so buffer it for now (unless it's a just a fin) + if msg.flags&fin == fin { + pp.retryState[msg.retries].expectChaser = false + pp.parent.inFlight.Done() // this fin is now handled and will be garbage collected + } else { + pp.retryState[msg.retries].buf = append(pp.retryState[msg.retries].buf, msg) + } + continue + } else if msg.flags&fin == fin { + // this message is of the current retry level (msg.retries == highWatermark) and the fin flag is set, + // meaning this retry level is done and we can go down (at least) one level and flush that + pp.retryState[pp.highWatermark].expectChaser = false + pp.flushRetryBuffers() + pp.parent.inFlight.Done() // this fin is now handled and will be garbage collected + continue + } + } + + // if we made it this far then the current msg contains real data, and can be sent to the next goroutine + // without breaking any of our ordering guarantees + + if pp.output == nil { + if err := pp.updateLeader(); err != nil { + pp.parent.returnError(msg, err) + time.Sleep(pp.parent.conf.Producer.Retry.Backoff) + continue + } + Logger.Printf("producer/leader/%s/%d selected broker %d\n", pp.topic, pp.partition, pp.leader.ID()) + } + + pp.output <- msg + } + + if pp.output != nil { + pp.parent.unrefBrokerProducer(pp.leader, pp.output) + } +} + +func (pp *partitionProducer) newHighWatermark(hwm int) { + Logger.Printf("producer/leader/%s/%d state change to [retrying-%d]\n", pp.topic, pp.partition, hwm) + pp.highWatermark = hwm + + // send off a fin so that we know when everything "in between" has made it + // back to us and we can safely flush the backlog (otherwise we risk re-ordering messages) + pp.retryState[pp.highWatermark].expectChaser = true + pp.parent.inFlight.Add(1) // we're generating a fin message; track it so we don't shut down while it's still inflight + pp.output <- &ProducerMessage{Topic: pp.topic, Partition: pp.partition, flags: fin, retries: pp.highWatermark - 1} + + // a new HWM means that our current broker selection is out of date + Logger.Printf("producer/leader/%s/%d abandoning broker %d\n", pp.topic, pp.partition, pp.leader.ID()) + pp.parent.unrefBrokerProducer(pp.leader, pp.output) + pp.output = nil +} + +func (pp *partitionProducer) flushRetryBuffers() { + Logger.Printf("producer/leader/%s/%d state change to [flushing-%d]\n", pp.topic, pp.partition, pp.highWatermark) + for { + pp.highWatermark-- + + if pp.output == nil { + if err := pp.updateLeader(); err != nil { + pp.parent.returnErrors(pp.retryState[pp.highWatermark].buf, err) + goto flushDone + } + Logger.Printf("producer/leader/%s/%d selected broker %d\n", pp.topic, pp.partition, pp.leader.ID()) + } + + for _, msg := range pp.retryState[pp.highWatermark].buf { + pp.output <- msg + } + + flushDone: + pp.retryState[pp.highWatermark].buf = nil + if pp.retryState[pp.highWatermark].expectChaser { + Logger.Printf("producer/leader/%s/%d state change to [retrying-%d]\n", pp.topic, pp.partition, pp.highWatermark) + break + } else if pp.highWatermark == 0 { + Logger.Printf("producer/leader/%s/%d state change to [normal]\n", pp.topic, pp.partition) + break + } + } +} + +func (pp *partitionProducer) updateLeader() error { + return pp.breaker.Run(func() (err error) { + if err = pp.parent.client.RefreshMetadata(pp.topic); err != nil { + return err + } + + if pp.leader, err = pp.parent.client.Leader(pp.topic, pp.partition); err != nil { + return err + } + + pp.output = pp.parent.getBrokerProducer(pp.leader) + pp.parent.inFlight.Add(1) // we're generating a syn message; track it so we don't shut down while it's still inflight + pp.output <- &ProducerMessage{Topic: pp.topic, Partition: pp.partition, flags: syn} + + return nil + }) +} + +// one per broker; also constructs an associated flusher +func (p *asyncProducer) newBrokerProducer(broker *Broker) chan<- *ProducerMessage { + var ( + input = make(chan *ProducerMessage) + bridge = make(chan *produceSet) + responses = make(chan *brokerProducerResponse) + ) + + bp := &brokerProducer{ + parent: p, + broker: broker, + input: input, + output: bridge, + responses: responses, + buffer: newProduceSet(p), + currentRetries: make(map[string]map[int32]error), + } + go withRecover(bp.run) + + // minimal bridge to make the network response `select`able + go withRecover(func() { + for set := range bridge { + request := set.buildRequest() + + response, err := broker.Produce(request) + + responses <- &brokerProducerResponse{ + set: set, + err: err, + res: response, + } + } + close(responses) + }) + + return input +} + +type brokerProducerResponse struct { + set *produceSet + err error + res *ProduceResponse +} + +// groups messages together into appropriately-sized batches for sending to the broker +// handles state related to retries etc +type brokerProducer struct { + parent *asyncProducer + broker *Broker + + input <-chan *ProducerMessage + output chan<- *produceSet + responses <-chan *brokerProducerResponse + + buffer *produceSet + timer <-chan time.Time + timerFired bool + + closing error + currentRetries map[string]map[int32]error +} + +func (bp *brokerProducer) run() { + var output chan<- *produceSet + Logger.Printf("producer/broker/%d starting up\n", bp.broker.ID()) + + for { + select { + case msg := <-bp.input: + if msg == nil { + bp.shutdown() + return + } + + if msg.flags&syn == syn { + Logger.Printf("producer/broker/%d state change to [open] on %s/%d\n", + bp.broker.ID(), msg.Topic, msg.Partition) + if bp.currentRetries[msg.Topic] == nil { + bp.currentRetries[msg.Topic] = make(map[int32]error) + } + bp.currentRetries[msg.Topic][msg.Partition] = nil + bp.parent.inFlight.Done() + continue + } + + if reason := bp.needsRetry(msg); reason != nil { + bp.parent.retryMessage(msg, reason) + + if bp.closing == nil && msg.flags&fin == fin { + // we were retrying this partition but we can start processing again + delete(bp.currentRetries[msg.Topic], msg.Partition) + Logger.Printf("producer/broker/%d state change to [closed] on %s/%d\n", + bp.broker.ID(), msg.Topic, msg.Partition) + } + + continue + } + + if bp.buffer.wouldOverflow(msg) { + if err := bp.waitForSpace(msg); err != nil { + bp.parent.retryMessage(msg, err) + continue + } + } + + if err := bp.buffer.add(msg); err != nil { + bp.parent.returnError(msg, err) + continue + } + + if bp.parent.conf.Producer.Flush.Frequency > 0 && bp.timer == nil { + bp.timer = time.After(bp.parent.conf.Producer.Flush.Frequency) + } + case <-bp.timer: + bp.timerFired = true + case output <- bp.buffer: + bp.rollOver() + case response := <-bp.responses: + bp.handleResponse(response) + } + + if bp.timerFired || bp.buffer.readyToFlush() { + output = bp.output + } else { + output = nil + } + } +} + +func (bp *brokerProducer) shutdown() { + for !bp.buffer.empty() { + select { + case response := <-bp.responses: + bp.handleResponse(response) + case bp.output <- bp.buffer: + bp.rollOver() + } + } + close(bp.output) + for response := range bp.responses { + bp.handleResponse(response) + } + + Logger.Printf("producer/broker/%d shut down\n", bp.broker.ID()) +} + +func (bp *brokerProducer) needsRetry(msg *ProducerMessage) error { + if bp.closing != nil { + return bp.closing + } + + return bp.currentRetries[msg.Topic][msg.Partition] +} + +func (bp *brokerProducer) waitForSpace(msg *ProducerMessage) error { + Logger.Printf("producer/broker/%d maximum request accumulated, waiting for space\n", bp.broker.ID()) + + for { + select { + case response := <-bp.responses: + bp.handleResponse(response) + // handling a response can change our state, so re-check some things + if reason := bp.needsRetry(msg); reason != nil { + return reason + } else if !bp.buffer.wouldOverflow(msg) { + return nil + } + case bp.output <- bp.buffer: + bp.rollOver() + return nil + } + } +} + +func (bp *brokerProducer) rollOver() { + bp.timer = nil + bp.timerFired = false + bp.buffer = newProduceSet(bp.parent) +} + +func (bp *brokerProducer) handleResponse(response *brokerProducerResponse) { + if response.err != nil { + bp.handleError(response.set, response.err) + } else { + bp.handleSuccess(response.set, response.res) + } + + if bp.buffer.empty() { + bp.rollOver() // this can happen if the response invalidated our buffer + } +} + +func (bp *brokerProducer) handleSuccess(sent *produceSet, response *ProduceResponse) { + // we iterate through the blocks in the request set, not the response, so that we notice + // if the response is missing a block completely + sent.eachPartition(func(topic string, partition int32, msgs []*ProducerMessage) { + if response == nil { + // this only happens when RequiredAcks is NoResponse, so we have to assume success + bp.parent.returnSuccesses(msgs) + return + } + + block := response.GetBlock(topic, partition) + if block == nil { + bp.parent.returnErrors(msgs, ErrIncompleteResponse) + return + } + + switch block.Err { + // Success + case ErrNoError: + if bp.parent.conf.Version.IsAtLeast(V0_10_0_0) && !block.Timestamp.IsZero() { + for _, msg := range msgs { + msg.Timestamp = block.Timestamp + } + } + for i, msg := range msgs { + msg.Offset = block.Offset + int64(i) + } + bp.parent.returnSuccesses(msgs) + // Retriable errors + case ErrInvalidMessage, ErrUnknownTopicOrPartition, ErrLeaderNotAvailable, ErrNotLeaderForPartition, + ErrRequestTimedOut, ErrNotEnoughReplicas, ErrNotEnoughReplicasAfterAppend: + Logger.Printf("producer/broker/%d state change to [retrying] on %s/%d because %v\n", + bp.broker.ID(), topic, partition, block.Err) + bp.currentRetries[topic][partition] = block.Err + bp.parent.retryMessages(msgs, block.Err) + bp.parent.retryMessages(bp.buffer.dropPartition(topic, partition), block.Err) + // Other non-retriable errors + default: + bp.parent.returnErrors(msgs, block.Err) + } + }) +} + +func (bp *brokerProducer) handleError(sent *produceSet, err error) { + switch err.(type) { + case PacketEncodingError: + sent.eachPartition(func(topic string, partition int32, msgs []*ProducerMessage) { + bp.parent.returnErrors(msgs, err) + }) + default: + Logger.Printf("producer/broker/%d state change to [closing] because %s\n", bp.broker.ID(), err) + bp.parent.abandonBrokerConnection(bp.broker) + _ = bp.broker.Close() + bp.closing = err + sent.eachPartition(func(topic string, partition int32, msgs []*ProducerMessage) { + bp.parent.retryMessages(msgs, err) + }) + bp.buffer.eachPartition(func(topic string, partition int32, msgs []*ProducerMessage) { + bp.parent.retryMessages(msgs, err) + }) + bp.rollOver() + } +} + +// singleton +// effectively a "bridge" between the flushers and the dispatcher in order to avoid deadlock +// based on https://godoc.org/github.com/eapache/channels#InfiniteChannel +func (p *asyncProducer) retryHandler() { + var msg *ProducerMessage + buf := queue.New() + + for { + if buf.Length() == 0 { + msg = <-p.retries + } else { + select { + case msg = <-p.retries: + case p.input <- buf.Peek().(*ProducerMessage): + buf.Remove() + continue + } + } + + if msg == nil { + return + } + + buf.Add(msg) + } +} + +// utility functions + +func (p *asyncProducer) shutdown() { + Logger.Println("Producer shutting down.") + p.inFlight.Add(1) + p.input <- &ProducerMessage{flags: shutdown} + + p.inFlight.Wait() + + if p.ownClient { + err := p.client.Close() + if err != nil { + Logger.Println("producer/shutdown failed to close the embedded client:", err) + } + } + + close(p.input) + close(p.retries) + close(p.errors) + close(p.successes) +} + +func (p *asyncProducer) returnError(msg *ProducerMessage, err error) { + msg.clear() + pErr := &ProducerError{Msg: msg, Err: err} + if p.conf.Producer.Return.Errors { + p.errors <- pErr + } else { + Logger.Println(pErr) + } + p.inFlight.Done() +} + +func (p *asyncProducer) returnErrors(batch []*ProducerMessage, err error) { + for _, msg := range batch { + p.returnError(msg, err) + } +} + +func (p *asyncProducer) returnSuccesses(batch []*ProducerMessage) { + for _, msg := range batch { + if p.conf.Producer.Return.Successes { + msg.clear() + p.successes <- msg + } + p.inFlight.Done() + } +} + +func (p *asyncProducer) retryMessage(msg *ProducerMessage, err error) { + if msg.retries >= p.conf.Producer.Retry.Max { + p.returnError(msg, err) + } else { + msg.retries++ + p.retries <- msg + } +} + +func (p *asyncProducer) retryMessages(batch []*ProducerMessage, err error) { + for _, msg := range batch { + p.retryMessage(msg, err) + } +} + +func (p *asyncProducer) getBrokerProducer(broker *Broker) chan<- *ProducerMessage { + p.brokerLock.Lock() + defer p.brokerLock.Unlock() + + bp := p.brokers[broker] + + if bp == nil { + bp = p.newBrokerProducer(broker) + p.brokers[broker] = bp + p.brokerRefs[bp] = 0 + } + + p.brokerRefs[bp]++ + + return bp +} + +func (p *asyncProducer) unrefBrokerProducer(broker *Broker, bp chan<- *ProducerMessage) { + p.brokerLock.Lock() + defer p.brokerLock.Unlock() + + p.brokerRefs[bp]-- + if p.brokerRefs[bp] == 0 { + close(bp) + delete(p.brokerRefs, bp) + + if p.brokers[broker] == bp { + delete(p.brokers, broker) + } + } +} + +func (p *asyncProducer) abandonBrokerConnection(broker *Broker) { + p.brokerLock.Lock() + defer p.brokerLock.Unlock() + + delete(p.brokers, broker) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/async_producer_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/async_producer_test.go new file mode 100644 index 00000000..13af1202 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/async_producer_test.go @@ -0,0 +1,841 @@ +package sarama + +import ( + "errors" + "log" + "os" + "os/signal" + "sync" + "testing" + "time" +) + +const TestMessage = "ABC THE MESSAGE" + +func closeProducer(t *testing.T, p AsyncProducer) { + var wg sync.WaitGroup + p.AsyncClose() + + wg.Add(2) + go func() { + for _ = range p.Successes() { + t.Error("Unexpected message on Successes()") + } + wg.Done() + }() + go func() { + for msg := range p.Errors() { + t.Error(msg.Err) + } + wg.Done() + }() + wg.Wait() +} + +func expectResults(t *testing.T, p AsyncProducer, successes, errors int) { + expect := successes + errors + for expect > 0 { + select { + case msg := <-p.Errors(): + if msg.Msg.flags != 0 { + t.Error("Message had flags set") + } + errors-- + expect-- + if errors < 0 { + t.Error(msg.Err) + } + case msg := <-p.Successes(): + if msg.flags != 0 { + t.Error("Message had flags set") + } + successes-- + expect-- + if successes < 0 { + t.Error("Too many successes") + } + } + } + if successes != 0 || errors != 0 { + t.Error("Unexpected successes", successes, "or errors", errors) + } +} + +type testPartitioner chan *int32 + +func (p testPartitioner) Partition(msg *ProducerMessage, numPartitions int32) (int32, error) { + part := <-p + if part == nil { + return 0, errors.New("BOOM") + } + + return *part, nil +} + +func (p testPartitioner) RequiresConsistency() bool { + return true +} + +func (p testPartitioner) feed(partition int32) { + p <- &partition +} + +type flakyEncoder bool + +func (f flakyEncoder) Length() int { + return len(TestMessage) +} + +func (f flakyEncoder) Encode() ([]byte, error) { + if !bool(f) { + return nil, errors.New("flaky encoding error") + } + return []byte(TestMessage), nil +} + +func TestAsyncProducer(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage), Metadata: i} + } + for i := 0; i < 10; i++ { + select { + case msg := <-producer.Errors(): + t.Error(msg.Err) + if msg.Msg.flags != 0 { + t.Error("Message had flags set") + } + case msg := <-producer.Successes(): + if msg.flags != 0 { + t.Error("Message had flags set") + } + if msg.Metadata.(int) != i { + t.Error("Message metadata did not match") + } + } + } + + closeProducer(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestAsyncProducerMultipleFlushes(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + leader.Returns(prodSuccess) + leader.Returns(prodSuccess) + + config := NewConfig() + config.Producer.Flush.Messages = 5 + config.Producer.Return.Successes = true + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for flush := 0; flush < 3; flush++ { + for i := 0; i < 5; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + expectResults(t, producer, 5, 0) + } + + closeProducer(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestAsyncProducerMultipleBrokers(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader0 := NewMockBroker(t, 2) + leader1 := NewMockBroker(t, 3) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader0.Addr(), leader0.BrokerID()) + metadataResponse.AddBroker(leader1.Addr(), leader1.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader0.BrokerID(), nil, nil, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 1, leader1.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodResponse0 := new(ProduceResponse) + prodResponse0.AddTopicPartition("my_topic", 0, ErrNoError) + leader0.Returns(prodResponse0) + + prodResponse1 := new(ProduceResponse) + prodResponse1.AddTopicPartition("my_topic", 1, ErrNoError) + leader1.Returns(prodResponse1) + + config := NewConfig() + config.Producer.Flush.Messages = 5 + config.Producer.Return.Successes = true + config.Producer.Partitioner = NewRoundRobinPartitioner + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + expectResults(t, producer, 10, 0) + + closeProducer(t, producer) + leader1.Close() + leader0.Close() + seedBroker.Close() +} + +func TestAsyncProducerCustomPartitioner(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodResponse := new(ProduceResponse) + prodResponse.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodResponse) + + config := NewConfig() + config.Producer.Flush.Messages = 2 + config.Producer.Return.Successes = true + config.Producer.Partitioner = func(topic string) Partitioner { + p := make(testPartitioner) + go func() { + p.feed(0) + p <- nil + p <- nil + p <- nil + p.feed(0) + }() + return p + } + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 5; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + expectResults(t, producer, 2, 3) + + closeProducer(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestAsyncProducerFailureRetry(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader1 := NewMockBroker(t, 2) + leader2 := NewMockBroker(t, 3) + + metadataLeader1 := new(MetadataResponse) + metadataLeader1.AddBroker(leader1.Addr(), leader1.BrokerID()) + metadataLeader1.AddTopicPartition("my_topic", 0, leader1.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader1) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + seedBroker.Close() + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + prodNotLeader := new(ProduceResponse) + prodNotLeader.AddTopicPartition("my_topic", 0, ErrNotLeaderForPartition) + leader1.Returns(prodNotLeader) + + metadataLeader2 := new(MetadataResponse) + metadataLeader2.AddBroker(leader2.Addr(), leader2.BrokerID()) + metadataLeader2.AddTopicPartition("my_topic", 0, leader2.BrokerID(), nil, nil, ErrNoError) + leader1.Returns(metadataLeader2) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader2.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + leader1.Close() + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + leader2.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + + leader2.Close() + closeProducer(t, producer) +} + +func TestAsyncProducerEncoderFailures(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + leader.Returns(prodSuccess) + leader.Returns(prodSuccess) + + config := NewConfig() + config.Producer.Flush.Messages = 1 + config.Producer.Return.Successes = true + config.Producer.Partitioner = NewManualPartitioner + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for flush := 0; flush < 3; flush++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: flakyEncoder(true), Value: flakyEncoder(false)} + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: flakyEncoder(false), Value: flakyEncoder(true)} + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: flakyEncoder(true), Value: flakyEncoder(true)} + expectResults(t, producer, 1, 2) + } + + closeProducer(t, producer) + leader.Close() + seedBroker.Close() +} + +// If a Kafka broker becomes unavailable and then returns back in service, then +// producer reconnects to it and continues sending messages. +func TestAsyncProducerBrokerBounce(t *testing.T) { + // Given + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + leaderAddr := leader.Addr() + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leaderAddr, leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + + config := NewConfig() + config.Producer.Flush.Messages = 1 + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + leader.Returns(prodSuccess) + expectResults(t, producer, 1, 0) + + // When: a broker connection gets reset by a broker (network glitch, restart, you name it). + leader.Close() // producer should get EOF + leader = NewMockBrokerAddr(t, 2, leaderAddr) // start it up again right away for giggles + seedBroker.Returns(metadataResponse) // tell it to go to broker 2 again + + // Then: a produced message goes through the new broker connection. + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + leader.Returns(prodSuccess) + expectResults(t, producer, 1, 0) + + closeProducer(t, producer) + seedBroker.Close() + leader.Close() +} + +func TestAsyncProducerBrokerBounceWithStaleMetadata(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader1 := NewMockBroker(t, 2) + leader2 := NewMockBroker(t, 3) + + metadataLeader1 := new(MetadataResponse) + metadataLeader1.AddBroker(leader1.Addr(), leader1.BrokerID()) + metadataLeader1.AddTopicPartition("my_topic", 0, leader1.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader1) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + config.Producer.Retry.Max = 3 + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + leader1.Close() // producer should get EOF + seedBroker.Returns(metadataLeader1) // tell it to go to leader1 again even though it's still down + seedBroker.Returns(metadataLeader1) // tell it to go to leader1 again even though it's still down + + // ok fine, tell it to go to leader2 finally + metadataLeader2 := new(MetadataResponse) + metadataLeader2.AddBroker(leader2.Addr(), leader2.BrokerID()) + metadataLeader2.AddTopicPartition("my_topic", 0, leader2.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader2) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader2.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + seedBroker.Close() + leader2.Close() + + closeProducer(t, producer) +} + +func TestAsyncProducerMultipleRetries(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader1 := NewMockBroker(t, 2) + leader2 := NewMockBroker(t, 3) + + metadataLeader1 := new(MetadataResponse) + metadataLeader1.AddBroker(leader1.Addr(), leader1.BrokerID()) + metadataLeader1.AddTopicPartition("my_topic", 0, leader1.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader1) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + config.Producer.Retry.Max = 4 + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + prodNotLeader := new(ProduceResponse) + prodNotLeader.AddTopicPartition("my_topic", 0, ErrNotLeaderForPartition) + leader1.Returns(prodNotLeader) + + metadataLeader2 := new(MetadataResponse) + metadataLeader2.AddBroker(leader2.Addr(), leader2.BrokerID()) + metadataLeader2.AddTopicPartition("my_topic", 0, leader2.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader2) + leader2.Returns(prodNotLeader) + seedBroker.Returns(metadataLeader1) + leader1.Returns(prodNotLeader) + seedBroker.Returns(metadataLeader1) + leader1.Returns(prodNotLeader) + seedBroker.Returns(metadataLeader2) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader2.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + leader2.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + + seedBroker.Close() + leader1.Close() + leader2.Close() + closeProducer(t, producer) +} + +func TestAsyncProducerOutOfRetries(t *testing.T) { + t.Skip("Enable once bug #294 is fixed.") + + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + config.Producer.Retry.Max = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + + prodNotLeader := new(ProduceResponse) + prodNotLeader.AddTopicPartition("my_topic", 0, ErrNotLeaderForPartition) + leader.Returns(prodNotLeader) + + for i := 0; i < 10; i++ { + select { + case msg := <-producer.Errors(): + if msg.Err != ErrNotLeaderForPartition { + t.Error(msg.Err) + } + case <-producer.Successes(): + t.Error("Unexpected success") + } + } + + seedBroker.Returns(metadataResponse) + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + + expectResults(t, producer, 10, 0) + + leader.Close() + seedBroker.Close() + safeClose(t, producer) +} + +func TestAsyncProducerRetryWithReferenceOpen(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + leaderAddr := leader.Addr() + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leaderAddr, leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 1, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + config.Producer.Retry.Max = 1 + config.Producer.Partitioner = NewRoundRobinPartitioner + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + // prime partition 0 + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + expectResults(t, producer, 1, 0) + + // prime partition 1 + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + prodSuccess = new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 1, ErrNoError) + leader.Returns(prodSuccess) + expectResults(t, producer, 1, 0) + + // reboot the broker (the producer will get EOF on its existing connection) + leader.Close() + leader = NewMockBrokerAddr(t, 2, leaderAddr) + + // send another message on partition 0 to trigger the EOF and retry + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + + // tell partition 0 to go to that broker again + seedBroker.Returns(metadataResponse) + + // succeed this time + prodSuccess = new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + expectResults(t, producer, 1, 0) + + // shutdown + closeProducer(t, producer) + seedBroker.Close() + leader.Close() +} + +func TestAsyncProducerFlusherRetryCondition(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 1, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Producer.Flush.Messages = 5 + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + config.Producer.Retry.Max = 1 + config.Producer.Partitioner = NewManualPartitioner + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + // prime partitions + for p := int32(0); p < 2; p++ { + for i := 0; i < 5; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage), Partition: p} + } + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", p, ErrNoError) + leader.Returns(prodSuccess) + expectResults(t, producer, 5, 0) + } + + // send more messages on partition 0 + for i := 0; i < 5; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage), Partition: 0} + } + prodNotLeader := new(ProduceResponse) + prodNotLeader.AddTopicPartition("my_topic", 0, ErrNotLeaderForPartition) + leader.Returns(prodNotLeader) + + time.Sleep(50 * time.Millisecond) + + leader.SetHandlerByMap(map[string]MockResponse{ + "ProduceRequest": NewMockProduceResponse(t). + SetError("my_topic", 0, ErrNoError), + }) + + // tell partition 0 to go to that broker again + seedBroker.Returns(metadataResponse) + + // succeed this time + expectResults(t, producer, 5, 0) + + // put five more through + for i := 0; i < 5; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage), Partition: 0} + } + expectResults(t, producer, 5, 0) + + // shutdown + closeProducer(t, producer) + seedBroker.Close() + leader.Close() +} + +func TestAsyncProducerRetryShutdown(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataLeader := new(MetadataResponse) + metadataLeader.AddBroker(leader.Addr(), leader.BrokerID()) + metadataLeader.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = true + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + producer.AsyncClose() + time.Sleep(5 * time.Millisecond) // let the shutdown goroutine kick in + + producer.Input() <- &ProducerMessage{Topic: "FOO"} + if err := <-producer.Errors(); err.Err != ErrShuttingDown { + t.Error(err) + } + + prodNotLeader := new(ProduceResponse) + prodNotLeader.AddTopicPartition("my_topic", 0, ErrNotLeaderForPartition) + leader.Returns(prodNotLeader) + + seedBroker.Returns(metadataLeader) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + expectResults(t, producer, 10, 0) + + seedBroker.Close() + leader.Close() + + // wait for the async-closed producer to shut down fully + for err := range producer.Errors() { + t.Error(err) + } +} + +func TestAsyncProducerNoReturns(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataLeader := new(MetadataResponse) + metadataLeader.AddBroker(leader.Addr(), leader.BrokerID()) + metadataLeader.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataLeader) + + config := NewConfig() + config.Producer.Flush.Messages = 10 + config.Producer.Return.Successes = false + config.Producer.Return.Errors = false + config.Producer.Retry.Backoff = 0 + producer, err := NewAsyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder(TestMessage)} + } + + wait := make(chan bool) + go func() { + if err := producer.Close(); err != nil { + t.Error(err) + } + close(wait) + }() + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + + <-wait + seedBroker.Close() + leader.Close() +} + +// This example shows how to use the producer while simultaneously +// reading the Errors channel to know about any failures. +func ExampleAsyncProducer_select() { + producer, err := NewAsyncProducer([]string{"localhost:9092"}, nil) + if err != nil { + panic(err) + } + + defer func() { + if err := producer.Close(); err != nil { + log.Fatalln(err) + } + }() + + // Trap SIGINT to trigger a shutdown. + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Interrupt) + + var enqueued, errors int +ProducerLoop: + for { + select { + case producer.Input() <- &ProducerMessage{Topic: "my_topic", Key: nil, Value: StringEncoder("testing 123")}: + enqueued++ + case err := <-producer.Errors(): + log.Println("Failed to produce message", err) + errors++ + case <-signals: + break ProducerLoop + } + } + + log.Printf("Enqueued: %d; errors: %d\n", enqueued, errors) +} + +// This example shows how to use the producer with separate goroutines +// reading from the Successes and Errors channels. Note that in order +// for the Successes channel to be populated, you have to set +// config.Producer.Return.Successes to true. +func ExampleAsyncProducer_goroutines() { + config := NewConfig() + config.Producer.Return.Successes = true + producer, err := NewAsyncProducer([]string{"localhost:9092"}, config) + if err != nil { + panic(err) + } + + // Trap SIGINT to trigger a graceful shutdown. + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Interrupt) + + var ( + wg sync.WaitGroup + enqueued, successes, errors int + ) + + wg.Add(1) + go func() { + defer wg.Done() + for _ = range producer.Successes() { + successes++ + } + }() + + wg.Add(1) + go func() { + defer wg.Done() + for err := range producer.Errors() { + log.Println(err) + errors++ + } + }() + +ProducerLoop: + for { + message := &ProducerMessage{Topic: "my_topic", Value: StringEncoder("testing 123")} + select { + case producer.Input() <- message: + enqueued++ + + case <-signals: + producer.AsyncClose() // Trigger a shutdown of the producer. + break ProducerLoop + } + } + + wg.Wait() + + log.Printf("Successfully produced: %d; errors: %d\n", successes, errors) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/broker.go b/vendor/src/gopkg.in/Shopify/sarama.v1/broker.go new file mode 100644 index 00000000..89beecc8 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/broker.go @@ -0,0 +1,674 @@ +package sarama + +import ( + "crypto/tls" + "encoding/binary" + "fmt" + "io" + "net" + "strconv" + "sync" + "sync/atomic" + "time" + + "github.com/rcrowley/go-metrics" +) + +// Broker represents a single Kafka broker connection. All operations on this object are entirely concurrency-safe. +type Broker struct { + id int32 + addr string + + conf *Config + correlationID int32 + conn net.Conn + connErr error + lock sync.Mutex + opened int32 + + responses chan responsePromise + done chan bool + + incomingByteRate metrics.Meter + requestRate metrics.Meter + requestSize metrics.Histogram + requestLatency metrics.Histogram + outgoingByteRate metrics.Meter + responseRate metrics.Meter + responseSize metrics.Histogram + brokerIncomingByteRate metrics.Meter + brokerRequestRate metrics.Meter + brokerRequestSize metrics.Histogram + brokerRequestLatency metrics.Histogram + brokerOutgoingByteRate metrics.Meter + brokerResponseRate metrics.Meter + brokerResponseSize metrics.Histogram +} + +type responsePromise struct { + requestTime time.Time + correlationID int32 + packets chan []byte + errors chan error +} + +// NewBroker creates and returns a Broker targetting the given host:port address. +// This does not attempt to actually connect, you have to call Open() for that. +func NewBroker(addr string) *Broker { + return &Broker{id: -1, addr: addr} +} + +// Open tries to connect to the Broker if it is not already connected or connecting, but does not block +// waiting for the connection to complete. This means that any subsequent operations on the broker will +// block waiting for the connection to succeed or fail. To get the effect of a fully synchronous Open call, +// follow it by a call to Connected(). The only errors Open will return directly are ConfigurationError or +// AlreadyConnected. If conf is nil, the result of NewConfig() is used. +func (b *Broker) Open(conf *Config) error { + if !atomic.CompareAndSwapInt32(&b.opened, 0, 1) { + return ErrAlreadyConnected + } + + if conf == nil { + conf = NewConfig() + } + + err := conf.Validate() + if err != nil { + return err + } + + b.lock.Lock() + + go withRecover(func() { + defer b.lock.Unlock() + + dialer := net.Dialer{ + Timeout: conf.Net.DialTimeout, + KeepAlive: conf.Net.KeepAlive, + } + + if conf.Net.TLS.Enable { + b.conn, b.connErr = tls.DialWithDialer(&dialer, "tcp", b.addr, conf.Net.TLS.Config) + } else { + b.conn, b.connErr = dialer.Dial("tcp", b.addr) + } + if b.connErr != nil { + Logger.Printf("Failed to connect to broker %s: %s\n", b.addr, b.connErr) + b.conn = nil + atomic.StoreInt32(&b.opened, 0) + return + } + b.conn = newBufConn(b.conn) + + b.conf = conf + + // Create or reuse the global metrics shared between brokers + b.incomingByteRate = metrics.GetOrRegisterMeter("incoming-byte-rate", conf.MetricRegistry) + b.requestRate = metrics.GetOrRegisterMeter("request-rate", conf.MetricRegistry) + b.requestSize = getOrRegisterHistogram("request-size", conf.MetricRegistry) + b.requestLatency = getOrRegisterHistogram("request-latency-in-ms", conf.MetricRegistry) + b.outgoingByteRate = metrics.GetOrRegisterMeter("outgoing-byte-rate", conf.MetricRegistry) + b.responseRate = metrics.GetOrRegisterMeter("response-rate", conf.MetricRegistry) + b.responseSize = getOrRegisterHistogram("response-size", conf.MetricRegistry) + // Do not gather metrics for seeded broker (only used during bootstrap) because they share + // the same id (-1) and are already exposed through the global metrics above + if b.id >= 0 { + b.brokerIncomingByteRate = getOrRegisterBrokerMeter("incoming-byte-rate", b, conf.MetricRegistry) + b.brokerRequestRate = getOrRegisterBrokerMeter("request-rate", b, conf.MetricRegistry) + b.brokerRequestSize = getOrRegisterBrokerHistogram("request-size", b, conf.MetricRegistry) + b.brokerRequestLatency = getOrRegisterBrokerHistogram("request-latency-in-ms", b, conf.MetricRegistry) + b.brokerOutgoingByteRate = getOrRegisterBrokerMeter("outgoing-byte-rate", b, conf.MetricRegistry) + b.brokerResponseRate = getOrRegisterBrokerMeter("response-rate", b, conf.MetricRegistry) + b.brokerResponseSize = getOrRegisterBrokerHistogram("response-size", b, conf.MetricRegistry) + } + + if conf.Net.SASL.Enable { + b.connErr = b.sendAndReceiveSASLPlainAuth() + if b.connErr != nil { + err = b.conn.Close() + if err == nil { + Logger.Printf("Closed connection to broker %s\n", b.addr) + } else { + Logger.Printf("Error while closing connection to broker %s: %s\n", b.addr, err) + } + b.conn = nil + atomic.StoreInt32(&b.opened, 0) + return + } + } + + b.done = make(chan bool) + b.responses = make(chan responsePromise, b.conf.Net.MaxOpenRequests-1) + + if b.id >= 0 { + Logger.Printf("Connected to broker at %s (registered as #%d)\n", b.addr, b.id) + } else { + Logger.Printf("Connected to broker at %s (unregistered)\n", b.addr) + } + go withRecover(b.responseReceiver) + }) + + return nil +} + +// Connected returns true if the broker is connected and false otherwise. If the broker is not +// connected but it had tried to connect, the error from that connection attempt is also returned. +func (b *Broker) Connected() (bool, error) { + b.lock.Lock() + defer b.lock.Unlock() + + return b.conn != nil, b.connErr +} + +func (b *Broker) Close() error { + b.lock.Lock() + defer b.lock.Unlock() + + if b.conn == nil { + return ErrNotConnected + } + + close(b.responses) + <-b.done + + err := b.conn.Close() + + b.conn = nil + b.connErr = nil + b.done = nil + b.responses = nil + + if err == nil { + Logger.Printf("Closed connection to broker %s\n", b.addr) + } else { + Logger.Printf("Error while closing connection to broker %s: %s\n", b.addr, err) + } + + atomic.StoreInt32(&b.opened, 0) + + return err +} + +// ID returns the broker ID retrieved from Kafka's metadata, or -1 if that is not known. +func (b *Broker) ID() int32 { + return b.id +} + +// Addr returns the broker address as either retrieved from Kafka's metadata or passed to NewBroker. +func (b *Broker) Addr() string { + return b.addr +} + +func (b *Broker) GetMetadata(request *MetadataRequest) (*MetadataResponse, error) { + response := new(MetadataResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) GetConsumerMetadata(request *ConsumerMetadataRequest) (*ConsumerMetadataResponse, error) { + response := new(ConsumerMetadataResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) GetAvailableOffsets(request *OffsetRequest) (*OffsetResponse, error) { + response := new(OffsetResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) Produce(request *ProduceRequest) (*ProduceResponse, error) { + var response *ProduceResponse + var err error + + if request.RequiredAcks == NoResponse { + err = b.sendAndReceive(request, nil) + } else { + response = new(ProduceResponse) + err = b.sendAndReceive(request, response) + } + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) Fetch(request *FetchRequest) (*FetchResponse, error) { + response := new(FetchResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) CommitOffset(request *OffsetCommitRequest) (*OffsetCommitResponse, error) { + response := new(OffsetCommitResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) FetchOffset(request *OffsetFetchRequest) (*OffsetFetchResponse, error) { + response := new(OffsetFetchResponse) + + err := b.sendAndReceive(request, response) + + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) JoinGroup(request *JoinGroupRequest) (*JoinGroupResponse, error) { + response := new(JoinGroupResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) SyncGroup(request *SyncGroupRequest) (*SyncGroupResponse, error) { + response := new(SyncGroupResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) LeaveGroup(request *LeaveGroupRequest) (*LeaveGroupResponse, error) { + response := new(LeaveGroupResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) Heartbeat(request *HeartbeatRequest) (*HeartbeatResponse, error) { + response := new(HeartbeatResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) ListGroups(request *ListGroupsRequest) (*ListGroupsResponse, error) { + response := new(ListGroupsResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) DescribeGroups(request *DescribeGroupsRequest) (*DescribeGroupsResponse, error) { + response := new(DescribeGroupsResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + +func (b *Broker) send(rb protocolBody, promiseResponse bool) (*responsePromise, error) { + b.lock.Lock() + defer b.lock.Unlock() + + if b.conn == nil { + if b.connErr != nil { + return nil, b.connErr + } + return nil, ErrNotConnected + } + + if !b.conf.Version.IsAtLeast(rb.requiredVersion()) { + return nil, ErrUnsupportedVersion + } + + req := &request{correlationID: b.correlationID, clientID: b.conf.ClientID, body: rb} + buf, err := encode(req, b.conf.MetricRegistry) + if err != nil { + return nil, err + } + + err = b.conn.SetWriteDeadline(time.Now().Add(b.conf.Net.WriteTimeout)) + if err != nil { + return nil, err + } + + requestTime := time.Now() + bytes, err := b.conn.Write(buf) + b.updateOutgoingCommunicationMetrics(bytes) + if err != nil { + return nil, err + } + b.correlationID++ + + if !promiseResponse { + // Record request latency without the response + b.updateRequestLatencyMetrics(time.Since(requestTime)) + return nil, nil + } + + promise := responsePromise{requestTime, req.correlationID, make(chan []byte), make(chan error)} + b.responses <- promise + + return &promise, nil +} + +func (b *Broker) sendAndReceive(req protocolBody, res versionedDecoder) error { + promise, err := b.send(req, res != nil) + + if err != nil { + return err + } + + if promise == nil { + return nil + } + + select { + case buf := <-promise.packets: + return versionedDecode(buf, res, req.version()) + case err = <-promise.errors: + return err + } +} + +func (b *Broker) decode(pd packetDecoder) (err error) { + b.id, err = pd.getInt32() + if err != nil { + return err + } + + host, err := pd.getString() + if err != nil { + return err + } + + port, err := pd.getInt32() + if err != nil { + return err + } + + b.addr = net.JoinHostPort(host, fmt.Sprint(port)) + if _, _, err := net.SplitHostPort(b.addr); err != nil { + return err + } + + return nil +} + +func (b *Broker) encode(pe packetEncoder) (err error) { + + host, portstr, err := net.SplitHostPort(b.addr) + if err != nil { + return err + } + port, err := strconv.Atoi(portstr) + if err != nil { + return err + } + + pe.putInt32(b.id) + + err = pe.putString(host) + if err != nil { + return err + } + + pe.putInt32(int32(port)) + + return nil +} + +func (b *Broker) responseReceiver() { + var dead error + header := make([]byte, 8) + for response := range b.responses { + if dead != nil { + response.errors <- dead + continue + } + + err := b.conn.SetReadDeadline(time.Now().Add(b.conf.Net.ReadTimeout)) + if err != nil { + dead = err + response.errors <- err + continue + } + + bytesReadHeader, err := io.ReadFull(b.conn, header) + requestLatency := time.Since(response.requestTime) + if err != nil { + b.updateIncomingCommunicationMetrics(bytesReadHeader, requestLatency) + dead = err + response.errors <- err + continue + } + + decodedHeader := responseHeader{} + err = decode(header, &decodedHeader) + if err != nil { + b.updateIncomingCommunicationMetrics(bytesReadHeader, requestLatency) + dead = err + response.errors <- err + continue + } + if decodedHeader.correlationID != response.correlationID { + b.updateIncomingCommunicationMetrics(bytesReadHeader, requestLatency) + // TODO if decoded ID < cur ID, discard until we catch up + // TODO if decoded ID > cur ID, save it so when cur ID catches up we have a response + dead = PacketDecodingError{fmt.Sprintf("correlation ID didn't match, wanted %d, got %d", response.correlationID, decodedHeader.correlationID)} + response.errors <- dead + continue + } + + buf := make([]byte, decodedHeader.length-4) + bytesReadBody, err := io.ReadFull(b.conn, buf) + b.updateIncomingCommunicationMetrics(bytesReadHeader+bytesReadBody, requestLatency) + if err != nil { + dead = err + response.errors <- err + continue + } + + response.packets <- buf + } + close(b.done) +} + +func (b *Broker) sendAndReceiveSASLPlainHandshake() error { + rb := &SaslHandshakeRequest{"PLAIN"} + req := &request{correlationID: b.correlationID, clientID: b.conf.ClientID, body: rb} + buf, err := encode(req, b.conf.MetricRegistry) + if err != nil { + return err + } + + err = b.conn.SetWriteDeadline(time.Now().Add(b.conf.Net.WriteTimeout)) + if err != nil { + return err + } + + requestTime := time.Now() + bytes, err := b.conn.Write(buf) + b.updateOutgoingCommunicationMetrics(bytes) + if err != nil { + Logger.Printf("Failed to send SASL handshake %s: %s\n", b.addr, err.Error()) + return err + } + b.correlationID++ + //wait for the response + header := make([]byte, 8) // response header + _, err = io.ReadFull(b.conn, header) + if err != nil { + Logger.Printf("Failed to read SASL handshake header : %s\n", err.Error()) + return err + } + length := binary.BigEndian.Uint32(header[:4]) + payload := make([]byte, length-4) + n, err := io.ReadFull(b.conn, payload) + if err != nil { + Logger.Printf("Failed to read SASL handshake payload : %s\n", err.Error()) + return err + } + b.updateIncomingCommunicationMetrics(n+8, time.Since(requestTime)) + res := &SaslHandshakeResponse{} + err = versionedDecode(payload, res, 0) + if err != nil { + Logger.Printf("Failed to parse SASL handshake : %s\n", err.Error()) + return err + } + if res.Err != ErrNoError { + Logger.Printf("Invalid SASL Mechanism : %s\n", res.Err.Error()) + return res.Err + } + Logger.Print("Successful SASL handshake") + return nil +} + +// Kafka 0.10.0 plans to support SASL Plain and Kerberos as per PR #812 (KIP-43)/(JIRA KAFKA-3149) +// Some hosted kafka services such as IBM Message Hub already offer SASL/PLAIN auth with Kafka 0.9 +// +// In SASL Plain, Kafka expects the auth header to be in the following format +// Message format (from https://tools.ietf.org/html/rfc4616): +// +// message = [authzid] UTF8NUL authcid UTF8NUL passwd +// authcid = 1*SAFE ; MUST accept up to 255 octets +// authzid = 1*SAFE ; MUST accept up to 255 octets +// passwd = 1*SAFE ; MUST accept up to 255 octets +// UTF8NUL = %x00 ; UTF-8 encoded NUL character +// +// SAFE = UTF1 / UTF2 / UTF3 / UTF4 +// ;; any UTF-8 encoded Unicode character except NUL +// +// When credentials are valid, Kafka returns a 4 byte array of null characters. +// When credentials are invalid, Kafka closes the connection. This does not seem to be the ideal way +// of responding to bad credentials but thats how its being done today. +func (b *Broker) sendAndReceiveSASLPlainAuth() error { + if b.conf.Net.SASL.Handshake { + handshakeErr := b.sendAndReceiveSASLPlainHandshake() + if handshakeErr != nil { + Logger.Printf("Error while performing SASL handshake %s\n", b.addr) + return handshakeErr + } + } + length := 1 + len(b.conf.Net.SASL.User) + 1 + len(b.conf.Net.SASL.Password) + authBytes := make([]byte, length+4) //4 byte length header + auth data + binary.BigEndian.PutUint32(authBytes, uint32(length)) + copy(authBytes[4:], []byte("\x00"+b.conf.Net.SASL.User+"\x00"+b.conf.Net.SASL.Password)) + + err := b.conn.SetWriteDeadline(time.Now().Add(b.conf.Net.WriteTimeout)) + if err != nil { + Logger.Printf("Failed to set write deadline when doing SASL auth with broker %s: %s\n", b.addr, err.Error()) + return err + } + + requestTime := time.Now() + bytesWritten, err := b.conn.Write(authBytes) + b.updateOutgoingCommunicationMetrics(bytesWritten) + if err != nil { + Logger.Printf("Failed to write SASL auth header to broker %s: %s\n", b.addr, err.Error()) + return err + } + + header := make([]byte, 4) + n, err := io.ReadFull(b.conn, header) + b.updateIncomingCommunicationMetrics(n, time.Since(requestTime)) + // If the credentials are valid, we would get a 4 byte response filled with null characters. + // Otherwise, the broker closes the connection and we get an EOF + if err != nil { + Logger.Printf("Failed to read response while authenticating with SASL to broker %s: %s\n", b.addr, err.Error()) + return err + } + + Logger.Printf("SASL authentication successful with broker %s:%v - %v\n", b.addr, n, header) + return nil +} + +func (b *Broker) updateIncomingCommunicationMetrics(bytes int, requestLatency time.Duration) { + b.updateRequestLatencyMetrics(requestLatency) + b.responseRate.Mark(1) + if b.brokerResponseRate != nil { + b.brokerResponseRate.Mark(1) + } + responseSize := int64(bytes) + b.incomingByteRate.Mark(responseSize) + if b.brokerIncomingByteRate != nil { + b.brokerIncomingByteRate.Mark(responseSize) + } + b.responseSize.Update(responseSize) + if b.brokerResponseSize != nil { + b.brokerResponseSize.Update(responseSize) + } +} + +func (b *Broker) updateRequestLatencyMetrics(requestLatency time.Duration) { + requestLatencyInMs := int64(requestLatency / time.Millisecond) + b.requestLatency.Update(requestLatencyInMs) + if b.brokerRequestLatency != nil { + b.brokerRequestLatency.Update(requestLatencyInMs) + } +} + +func (b *Broker) updateOutgoingCommunicationMetrics(bytes int) { + b.requestRate.Mark(1) + if b.brokerRequestRate != nil { + b.brokerRequestRate.Mark(1) + } + requestSize := int64(bytes) + b.outgoingByteRate.Mark(requestSize) + if b.brokerOutgoingByteRate != nil { + b.brokerOutgoingByteRate.Mark(requestSize) + } + b.requestSize.Update(requestSize) + if b.brokerRequestSize != nil { + b.brokerRequestSize.Update(requestSize) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/broker_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/broker_test.go new file mode 100644 index 00000000..5adb46f1 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/broker_test.go @@ -0,0 +1,315 @@ +package sarama + +import ( + "fmt" + "testing" + "time" +) + +func ExampleBroker() { + broker := NewBroker("localhost:9092") + err := broker.Open(nil) + if err != nil { + panic(err) + } + + request := MetadataRequest{Topics: []string{"myTopic"}} + response, err := broker.GetMetadata(&request) + if err != nil { + _ = broker.Close() + panic(err) + } + + fmt.Println("There are", len(response.Topics), "topics active in the cluster.") + + if err = broker.Close(); err != nil { + panic(err) + } +} + +type mockEncoder struct { + bytes []byte +} + +func (m mockEncoder) encode(pe packetEncoder) error { + return pe.putRawBytes(m.bytes) +} + +type brokerMetrics struct { + bytesRead int + bytesWritten int +} + +func TestBrokerAccessors(t *testing.T) { + broker := NewBroker("abc:123") + + if broker.ID() != -1 { + t.Error("New broker didn't have an ID of -1.") + } + + if broker.Addr() != "abc:123" { + t.Error("New broker didn't have the correct address") + } + + broker.id = 34 + if broker.ID() != 34 { + t.Error("Manually setting broker ID did not take effect.") + } +} + +func TestSimpleBrokerCommunication(t *testing.T) { + for _, tt := range brokerTestTable { + Logger.Printf("Testing broker communication for %s", tt.name) + mb := NewMockBroker(t, 0) + mb.Returns(&mockEncoder{tt.response}) + pendingNotify := make(chan brokerMetrics) + // Register a callback to be notified about successful requests + mb.SetNotifier(func(bytesRead, bytesWritten int) { + pendingNotify <- brokerMetrics{bytesRead, bytesWritten} + }) + broker := NewBroker(mb.Addr()) + // Set the broker id in order to validate local broker metrics + broker.id = 0 + conf := NewConfig() + conf.Version = V0_10_0_0 + err := broker.Open(conf) + if err != nil { + t.Fatal(err) + } + tt.runner(t, broker) + err = broker.Close() + if err != nil { + t.Error(err) + } + // Wait up to 500 ms for the remote broker to process the request and + // notify us about the metrics + timeout := 500 * time.Millisecond + select { + case mockBrokerMetrics := <-pendingNotify: + validateBrokerMetrics(t, broker, mockBrokerMetrics) + case <-time.After(timeout): + t.Errorf("No request received for: %s after waiting for %v", tt.name, timeout) + } + mb.Close() + } + +} + +// We're not testing encoding/decoding here, so most of the requests/responses will be empty for simplicity's sake +var brokerTestTable = []struct { + name string + response []byte + runner func(*testing.T, *Broker) +}{ + {"MetadataRequest", + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := MetadataRequest{} + response, err := broker.GetMetadata(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Metadata request got no response!") + } + }}, + + {"ConsumerMetadataRequest", + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 't', 0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := ConsumerMetadataRequest{} + response, err := broker.GetConsumerMetadata(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Consumer Metadata request got no response!") + } + }}, + + {"ProduceRequest (NoResponse)", + []byte{}, + func(t *testing.T, broker *Broker) { + request := ProduceRequest{} + request.RequiredAcks = NoResponse + response, err := broker.Produce(&request) + if err != nil { + t.Error(err) + } + if response != nil { + t.Error("Produce request with NoResponse got a response!") + } + }}, + + {"ProduceRequest (WaitForLocal)", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := ProduceRequest{} + request.RequiredAcks = WaitForLocal + response, err := broker.Produce(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Produce request without NoResponse got no response!") + } + }}, + + {"FetchRequest", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := FetchRequest{} + response, err := broker.Fetch(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Fetch request got no response!") + } + }}, + + {"OffsetFetchRequest", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := OffsetFetchRequest{} + response, err := broker.FetchOffset(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("OffsetFetch request got no response!") + } + }}, + + {"OffsetCommitRequest", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := OffsetCommitRequest{} + response, err := broker.CommitOffset(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("OffsetCommit request got no response!") + } + }}, + + {"OffsetRequest", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := OffsetRequest{} + response, err := broker.GetAvailableOffsets(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Offset request got no response!") + } + }}, + + {"JoinGroupRequest", + []byte{0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := JoinGroupRequest{} + response, err := broker.JoinGroup(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("JoinGroup request got no response!") + } + }}, + + {"SyncGroupRequest", + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := SyncGroupRequest{} + response, err := broker.SyncGroup(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("SyncGroup request got no response!") + } + }}, + + {"LeaveGroupRequest", + []byte{0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := LeaveGroupRequest{} + response, err := broker.LeaveGroup(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("LeaveGroup request got no response!") + } + }}, + + {"HeartbeatRequest", + []byte{0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := HeartbeatRequest{} + response, err := broker.Heartbeat(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("Heartbeat request got no response!") + } + }}, + + {"ListGroupsRequest", + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := ListGroupsRequest{} + response, err := broker.ListGroups(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("ListGroups request got no response!") + } + }}, + + {"DescribeGroupsRequest", + []byte{0x00, 0x00, 0x00, 0x00}, + func(t *testing.T, broker *Broker) { + request := DescribeGroupsRequest{} + response, err := broker.DescribeGroups(&request) + if err != nil { + t.Error(err) + } + if response == nil { + t.Error("DescribeGroups request got no response!") + } + }}, +} + +func validateBrokerMetrics(t *testing.T, broker *Broker, mockBrokerMetrics brokerMetrics) { + metricValidators := newMetricValidators() + mockBrokerBytesRead := mockBrokerMetrics.bytesRead + mockBrokerBytesWritten := mockBrokerMetrics.bytesWritten + + // Check that the number of bytes sent corresponds to what the mock broker received + metricValidators.registerForAllBrokers(broker, countMeterValidator("incoming-byte-rate", mockBrokerBytesWritten)) + if mockBrokerBytesWritten == 0 { + // This a ProduceRequest with NoResponse + metricValidators.registerForAllBrokers(broker, countMeterValidator("response-rate", 0)) + metricValidators.registerForAllBrokers(broker, countHistogramValidator("response-size", 0)) + metricValidators.registerForAllBrokers(broker, minMaxHistogramValidator("response-size", 0, 0)) + } else { + metricValidators.registerForAllBrokers(broker, countMeterValidator("response-rate", 1)) + metricValidators.registerForAllBrokers(broker, countHistogramValidator("response-size", 1)) + metricValidators.registerForAllBrokers(broker, minMaxHistogramValidator("response-size", mockBrokerBytesWritten, mockBrokerBytesWritten)) + } + + // Check that the number of bytes received corresponds to what the mock broker sent + metricValidators.registerForAllBrokers(broker, countMeterValidator("outgoing-byte-rate", mockBrokerBytesRead)) + metricValidators.registerForAllBrokers(broker, countMeterValidator("request-rate", 1)) + metricValidators.registerForAllBrokers(broker, countHistogramValidator("request-size", 1)) + metricValidators.registerForAllBrokers(broker, minMaxHistogramValidator("request-size", mockBrokerBytesRead, mockBrokerBytesRead)) + + // Run the validators + metricValidators.run(t, broker.conf.MetricRegistry) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/client.go b/vendor/src/gopkg.in/Shopify/sarama.v1/client.go new file mode 100644 index 00000000..f869a143 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/client.go @@ -0,0 +1,736 @@ +package sarama + +import ( + "math/rand" + "sort" + "sync" + "time" +) + +// Client is a generic Kafka client. It manages connections to one or more Kafka brokers. +// You MUST call Close() on a client to avoid leaks, it will not be garbage-collected +// automatically when it passes out of scope. It is safe to share a client amongst many +// users, however Kafka will process requests from a single client strictly in serial, +// so it is generally more efficient to use the default one client per producer/consumer. +type Client interface { + // Config returns the Config struct of the client. This struct should not be + // altered after it has been created. + Config() *Config + + // Topics returns the set of available topics as retrieved from cluster metadata. + Topics() ([]string, error) + + // Partitions returns the sorted list of all partition IDs for the given topic. + Partitions(topic string) ([]int32, error) + + // WritablePartitions returns the sorted list of all writable partition IDs for + // the given topic, where "writable" means "having a valid leader accepting + // writes". + WritablePartitions(topic string) ([]int32, error) + + // Leader returns the broker object that is the leader of the current + // topic/partition, as determined by querying the cluster metadata. + Leader(topic string, partitionID int32) (*Broker, error) + + // Replicas returns the set of all replica IDs for the given partition. + Replicas(topic string, partitionID int32) ([]int32, error) + + // RefreshMetadata takes a list of topics and queries the cluster to refresh the + // available metadata for those topics. If no topics are provided, it will refresh + // metadata for all topics. + RefreshMetadata(topics ...string) error + + // GetOffset queries the cluster to get the most recent available offset at the + // given time on the topic/partition combination. Time should be OffsetOldest for + // the earliest available offset, OffsetNewest for the offset of the message that + // will be produced next, or a time. + GetOffset(topic string, partitionID int32, time int64) (int64, error) + + // Coordinator returns the coordinating broker for a consumer group. It will + // return a locally cached value if it's available. You can call + // RefreshCoordinator to update the cached value. This function only works on + // Kafka 0.8.2 and higher. + Coordinator(consumerGroup string) (*Broker, error) + + // RefreshCoordinator retrieves the coordinator for a consumer group and stores it + // in local cache. This function only works on Kafka 0.8.2 and higher. + RefreshCoordinator(consumerGroup string) error + + // Close shuts down all broker connections managed by this client. It is required + // to call this function before a client object passes out of scope, as it will + // otherwise leak memory. You must close any Producers or Consumers using a client + // before you close the client. + Close() error + + // Closed returns true if the client has already had Close called on it + Closed() bool +} + +const ( + // OffsetNewest stands for the log head offset, i.e. the offset that will be + // assigned to the next message that will be produced to the partition. You + // can send this to a client's GetOffset method to get this offset, or when + // calling ConsumePartition to start consuming new messages. + OffsetNewest int64 = -1 + // OffsetOldest stands for the oldest offset available on the broker for a + // partition. You can send this to a client's GetOffset method to get this + // offset, or when calling ConsumePartition to start consuming from the + // oldest offset that is still available on the broker. + OffsetOldest int64 = -2 +) + +type client struct { + conf *Config + closer, closed chan none // for shutting down background metadata updater + + // the broker addresses given to us through the constructor are not guaranteed to be returned in + // the cluster metadata (I *think* it only returns brokers who are currently leading partitions?) + // so we store them separately + seedBrokers []*Broker + deadSeeds []*Broker + + brokers map[int32]*Broker // maps broker ids to brokers + metadata map[string]map[int32]*PartitionMetadata // maps topics to partition ids to metadata + coordinators map[string]int32 // Maps consumer group names to coordinating broker IDs + + // If the number of partitions is large, we can get some churn calling cachedPartitions, + // so the result is cached. It is important to update this value whenever metadata is changed + cachedPartitionsResults map[string][maxPartitionIndex][]int32 + + lock sync.RWMutex // protects access to the maps that hold cluster state. +} + +// NewClient creates a new Client. It connects to one of the given broker addresses +// and uses that broker to automatically fetch metadata on the rest of the kafka cluster. If metadata cannot +// be retrieved from any of the given broker addresses, the client is not created. +func NewClient(addrs []string, conf *Config) (Client, error) { + Logger.Println("Initializing new client") + + if conf == nil { + conf = NewConfig() + } + + if err := conf.Validate(); err != nil { + return nil, err + } + + if len(addrs) < 1 { + return nil, ConfigurationError("You must provide at least one broker address") + } + + client := &client{ + conf: conf, + closer: make(chan none), + closed: make(chan none), + brokers: make(map[int32]*Broker), + metadata: make(map[string]map[int32]*PartitionMetadata), + cachedPartitionsResults: make(map[string][maxPartitionIndex][]int32), + coordinators: make(map[string]int32), + } + + random := rand.New(rand.NewSource(time.Now().UnixNano())) + for _, index := range random.Perm(len(addrs)) { + client.seedBrokers = append(client.seedBrokers, NewBroker(addrs[index])) + } + + // do an initial fetch of all cluster metadata by specifing an empty list of topics + err := client.RefreshMetadata() + switch err { + case nil: + break + case ErrLeaderNotAvailable, ErrReplicaNotAvailable, ErrTopicAuthorizationFailed, ErrClusterAuthorizationFailed: + // indicates that maybe part of the cluster is down, but is not fatal to creating the client + Logger.Println(err) + default: + close(client.closed) // we haven't started the background updater yet, so we have to do this manually + _ = client.Close() + return nil, err + } + go withRecover(client.backgroundMetadataUpdater) + + Logger.Println("Successfully initialized new client") + + return client, nil +} + +func (client *client) Config() *Config { + return client.conf +} + +func (client *client) Close() error { + if client.Closed() { + // Chances are this is being called from a defer() and the error will go unobserved + // so we go ahead and log the event in this case. + Logger.Printf("Close() called on already closed client") + return ErrClosedClient + } + + // shutdown and wait for the background thread before we take the lock, to avoid races + close(client.closer) + <-client.closed + + client.lock.Lock() + defer client.lock.Unlock() + Logger.Println("Closing Client") + + for _, broker := range client.brokers { + safeAsyncClose(broker) + } + + for _, broker := range client.seedBrokers { + safeAsyncClose(broker) + } + + client.brokers = nil + client.metadata = nil + + return nil +} + +func (client *client) Closed() bool { + return client.brokers == nil +} + +func (client *client) Topics() ([]string, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + client.lock.RLock() + defer client.lock.RUnlock() + + ret := make([]string, 0, len(client.metadata)) + for topic := range client.metadata { + ret = append(ret, topic) + } + + return ret, nil +} + +func (client *client) Partitions(topic string) ([]int32, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + partitions := client.cachedPartitions(topic, allPartitions) + + if len(partitions) == 0 { + err := client.RefreshMetadata(topic) + if err != nil { + return nil, err + } + partitions = client.cachedPartitions(topic, allPartitions) + } + + if partitions == nil { + return nil, ErrUnknownTopicOrPartition + } + + return partitions, nil +} + +func (client *client) WritablePartitions(topic string) ([]int32, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + partitions := client.cachedPartitions(topic, writablePartitions) + + // len==0 catches when it's nil (no such topic) and the odd case when every single + // partition is undergoing leader election simultaneously. Callers have to be able to handle + // this function returning an empty slice (which is a valid return value) but catching it + // here the first time (note we *don't* catch it below where we return ErrUnknownTopicOrPartition) triggers + // a metadata refresh as a nicety so callers can just try again and don't have to manually + // trigger a refresh (otherwise they'd just keep getting a stale cached copy). + if len(partitions) == 0 { + err := client.RefreshMetadata(topic) + if err != nil { + return nil, err + } + partitions = client.cachedPartitions(topic, writablePartitions) + } + + if partitions == nil { + return nil, ErrUnknownTopicOrPartition + } + + return partitions, nil +} + +func (client *client) Replicas(topic string, partitionID int32) ([]int32, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + metadata := client.cachedMetadata(topic, partitionID) + + if metadata == nil { + err := client.RefreshMetadata(topic) + if err != nil { + return nil, err + } + metadata = client.cachedMetadata(topic, partitionID) + } + + if metadata == nil { + return nil, ErrUnknownTopicOrPartition + } + + if metadata.Err == ErrReplicaNotAvailable { + return nil, metadata.Err + } + return dupeAndSort(metadata.Replicas), nil +} + +func (client *client) Leader(topic string, partitionID int32) (*Broker, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + leader, err := client.cachedLeader(topic, partitionID) + + if leader == nil { + err = client.RefreshMetadata(topic) + if err != nil { + return nil, err + } + leader, err = client.cachedLeader(topic, partitionID) + } + + return leader, err +} + +func (client *client) RefreshMetadata(topics ...string) error { + if client.Closed() { + return ErrClosedClient + } + + // Prior to 0.8.2, Kafka will throw exceptions on an empty topic and not return a proper + // error. This handles the case by returning an error instead of sending it + // off to Kafka. See: https://github.com/Shopify/sarama/pull/38#issuecomment-26362310 + for _, topic := range topics { + if len(topic) == 0 { + return ErrInvalidTopic // this is the error that 0.8.2 and later correctly return + } + } + + return client.tryRefreshMetadata(topics, client.conf.Metadata.Retry.Max) +} + +func (client *client) GetOffset(topic string, partitionID int32, time int64) (int64, error) { + if client.Closed() { + return -1, ErrClosedClient + } + + offset, err := client.getOffset(topic, partitionID, time) + + if err != nil { + if err := client.RefreshMetadata(topic); err != nil { + return -1, err + } + return client.getOffset(topic, partitionID, time) + } + + return offset, err +} + +func (client *client) Coordinator(consumerGroup string) (*Broker, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + coordinator := client.cachedCoordinator(consumerGroup) + + if coordinator == nil { + if err := client.RefreshCoordinator(consumerGroup); err != nil { + return nil, err + } + coordinator = client.cachedCoordinator(consumerGroup) + } + + if coordinator == nil { + return nil, ErrConsumerCoordinatorNotAvailable + } + + _ = coordinator.Open(client.conf) + return coordinator, nil +} + +func (client *client) RefreshCoordinator(consumerGroup string) error { + if client.Closed() { + return ErrClosedClient + } + + response, err := client.getConsumerMetadata(consumerGroup, client.conf.Metadata.Retry.Max) + if err != nil { + return err + } + + client.lock.Lock() + defer client.lock.Unlock() + client.registerBroker(response.Coordinator) + client.coordinators[consumerGroup] = response.Coordinator.ID() + return nil +} + +// private broker management helpers + +// registerBroker makes sure a broker received by a Metadata or Coordinator request is registered +// in the brokers map. It returns the broker that is registered, which may be the provided broker, +// or a previously registered Broker instance. You must hold the write lock before calling this function. +func (client *client) registerBroker(broker *Broker) { + if client.brokers[broker.ID()] == nil { + client.brokers[broker.ID()] = broker + Logger.Printf("client/brokers registered new broker #%d at %s", broker.ID(), broker.Addr()) + } else if broker.Addr() != client.brokers[broker.ID()].Addr() { + safeAsyncClose(client.brokers[broker.ID()]) + client.brokers[broker.ID()] = broker + Logger.Printf("client/brokers replaced registered broker #%d with %s", broker.ID(), broker.Addr()) + } +} + +// deregisterBroker removes a broker from the seedsBroker list, and if it's +// not the seedbroker, removes it from brokers map completely. +func (client *client) deregisterBroker(broker *Broker) { + client.lock.Lock() + defer client.lock.Unlock() + + if len(client.seedBrokers) > 0 && broker == client.seedBrokers[0] { + client.deadSeeds = append(client.deadSeeds, broker) + client.seedBrokers = client.seedBrokers[1:] + } else { + // we do this so that our loop in `tryRefreshMetadata` doesn't go on forever, + // but we really shouldn't have to; once that loop is made better this case can be + // removed, and the function generally can be renamed from `deregisterBroker` to + // `nextSeedBroker` or something + Logger.Printf("client/brokers deregistered broker #%d at %s", broker.ID(), broker.Addr()) + delete(client.brokers, broker.ID()) + } +} + +func (client *client) resurrectDeadBrokers() { + client.lock.Lock() + defer client.lock.Unlock() + + Logger.Printf("client/brokers resurrecting %d dead seed brokers", len(client.deadSeeds)) + client.seedBrokers = append(client.seedBrokers, client.deadSeeds...) + client.deadSeeds = nil +} + +func (client *client) any() *Broker { + client.lock.RLock() + defer client.lock.RUnlock() + + if len(client.seedBrokers) > 0 { + _ = client.seedBrokers[0].Open(client.conf) + return client.seedBrokers[0] + } + + // not guaranteed to be random *or* deterministic + for _, broker := range client.brokers { + _ = broker.Open(client.conf) + return broker + } + + return nil +} + +// private caching/lazy metadata helpers + +type partitionType int + +const ( + allPartitions partitionType = iota + writablePartitions + // If you add any more types, update the partition cache in update() + + // Ensure this is the last partition type value + maxPartitionIndex +) + +func (client *client) cachedMetadata(topic string, partitionID int32) *PartitionMetadata { + client.lock.RLock() + defer client.lock.RUnlock() + + partitions := client.metadata[topic] + if partitions != nil { + return partitions[partitionID] + } + + return nil +} + +func (client *client) cachedPartitions(topic string, partitionSet partitionType) []int32 { + client.lock.RLock() + defer client.lock.RUnlock() + + partitions, exists := client.cachedPartitionsResults[topic] + + if !exists { + return nil + } + return partitions[partitionSet] +} + +func (client *client) setPartitionCache(topic string, partitionSet partitionType) []int32 { + partitions := client.metadata[topic] + + if partitions == nil { + return nil + } + + ret := make([]int32, 0, len(partitions)) + for _, partition := range partitions { + if partitionSet == writablePartitions && partition.Err == ErrLeaderNotAvailable { + continue + } + ret = append(ret, partition.ID) + } + + sort.Sort(int32Slice(ret)) + return ret +} + +func (client *client) cachedLeader(topic string, partitionID int32) (*Broker, error) { + client.lock.RLock() + defer client.lock.RUnlock() + + partitions := client.metadata[topic] + if partitions != nil { + metadata, ok := partitions[partitionID] + if ok { + if metadata.Err == ErrLeaderNotAvailable { + return nil, ErrLeaderNotAvailable + } + b := client.brokers[metadata.Leader] + if b == nil { + return nil, ErrLeaderNotAvailable + } + _ = b.Open(client.conf) + return b, nil + } + } + + return nil, ErrUnknownTopicOrPartition +} + +func (client *client) getOffset(topic string, partitionID int32, time int64) (int64, error) { + broker, err := client.Leader(topic, partitionID) + if err != nil { + return -1, err + } + + request := &OffsetRequest{} + if client.conf.Version.IsAtLeast(V0_10_1_0) { + request.Version = 1 + } + request.AddBlock(topic, partitionID, time, 1) + + response, err := broker.GetAvailableOffsets(request) + if err != nil { + _ = broker.Close() + return -1, err + } + + block := response.GetBlock(topic, partitionID) + if block == nil { + _ = broker.Close() + return -1, ErrIncompleteResponse + } + if block.Err != ErrNoError { + return -1, block.Err + } + if len(block.Offsets) != 1 { + return -1, ErrOffsetOutOfRange + } + + return block.Offsets[0], nil +} + +// core metadata update logic + +func (client *client) backgroundMetadataUpdater() { + defer close(client.closed) + + if client.conf.Metadata.RefreshFrequency == time.Duration(0) { + return + } + + ticker := time.NewTicker(client.conf.Metadata.RefreshFrequency) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + if err := client.RefreshMetadata(); err != nil { + Logger.Println("Client background metadata update:", err) + } + case <-client.closer: + return + } + } +} + +func (client *client) tryRefreshMetadata(topics []string, attemptsRemaining int) error { + retry := func(err error) error { + if attemptsRemaining > 0 { + Logger.Printf("client/metadata retrying after %dms... (%d attempts remaining)\n", client.conf.Metadata.Retry.Backoff/time.Millisecond, attemptsRemaining) + time.Sleep(client.conf.Metadata.Retry.Backoff) + return client.tryRefreshMetadata(topics, attemptsRemaining-1) + } + return err + } + + for broker := client.any(); broker != nil; broker = client.any() { + if len(topics) > 0 { + Logger.Printf("client/metadata fetching metadata for %v from broker %s\n", topics, broker.addr) + } else { + Logger.Printf("client/metadata fetching metadata for all topics from broker %s\n", broker.addr) + } + response, err := broker.GetMetadata(&MetadataRequest{Topics: topics}) + + switch err.(type) { + case nil: + // valid response, use it + if shouldRetry, err := client.updateMetadata(response); shouldRetry { + Logger.Println("client/metadata found some partitions to be leaderless") + return retry(err) // note: err can be nil + } else { + return err + } + + case PacketEncodingError: + // didn't even send, return the error + return err + default: + // some other error, remove that broker and try again + Logger.Println("client/metadata got error from broker while fetching metadata:", err) + _ = broker.Close() + client.deregisterBroker(broker) + } + } + + Logger.Println("client/metadata no available broker to send metadata request to") + client.resurrectDeadBrokers() + return retry(ErrOutOfBrokers) +} + +// if no fatal error, returns a list of topics that need retrying due to ErrLeaderNotAvailable +func (client *client) updateMetadata(data *MetadataResponse) (retry bool, err error) { + client.lock.Lock() + defer client.lock.Unlock() + + // For all the brokers we received: + // - if it is a new ID, save it + // - if it is an existing ID, but the address we have is stale, discard the old one and save it + // - otherwise ignore it, replacing our existing one would just bounce the connection + for _, broker := range data.Brokers { + client.registerBroker(broker) + } + + for _, topic := range data.Topics { + delete(client.metadata, topic.Name) + delete(client.cachedPartitionsResults, topic.Name) + + switch topic.Err { + case ErrNoError: + break + case ErrInvalidTopic, ErrTopicAuthorizationFailed: // don't retry, don't store partial results + err = topic.Err + continue + case ErrUnknownTopicOrPartition: // retry, do not store partial partition results + err = topic.Err + retry = true + continue + case ErrLeaderNotAvailable: // retry, but store partial partition results + retry = true + break + default: // don't retry, don't store partial results + Logger.Printf("Unexpected topic-level metadata error: %s", topic.Err) + err = topic.Err + continue + } + + client.metadata[topic.Name] = make(map[int32]*PartitionMetadata, len(topic.Partitions)) + for _, partition := range topic.Partitions { + client.metadata[topic.Name][partition.ID] = partition + if partition.Err == ErrLeaderNotAvailable { + retry = true + } + } + + var partitionCache [maxPartitionIndex][]int32 + partitionCache[allPartitions] = client.setPartitionCache(topic.Name, allPartitions) + partitionCache[writablePartitions] = client.setPartitionCache(topic.Name, writablePartitions) + client.cachedPartitionsResults[topic.Name] = partitionCache + } + + return +} + +func (client *client) cachedCoordinator(consumerGroup string) *Broker { + client.lock.RLock() + defer client.lock.RUnlock() + if coordinatorID, ok := client.coordinators[consumerGroup]; ok { + return client.brokers[coordinatorID] + } + return nil +} + +func (client *client) getConsumerMetadata(consumerGroup string, attemptsRemaining int) (*ConsumerMetadataResponse, error) { + retry := func(err error) (*ConsumerMetadataResponse, error) { + if attemptsRemaining > 0 { + Logger.Printf("client/coordinator retrying after %dms... (%d attempts remaining)\n", client.conf.Metadata.Retry.Backoff/time.Millisecond, attemptsRemaining) + time.Sleep(client.conf.Metadata.Retry.Backoff) + return client.getConsumerMetadata(consumerGroup, attemptsRemaining-1) + } + return nil, err + } + + for broker := client.any(); broker != nil; broker = client.any() { + Logger.Printf("client/coordinator requesting coordinator for consumergroup %s from %s\n", consumerGroup, broker.Addr()) + + request := new(ConsumerMetadataRequest) + request.ConsumerGroup = consumerGroup + + response, err := broker.GetConsumerMetadata(request) + + if err != nil { + Logger.Printf("client/coordinator request to broker %s failed: %s\n", broker.Addr(), err) + + switch err.(type) { + case PacketEncodingError: + return nil, err + default: + _ = broker.Close() + client.deregisterBroker(broker) + continue + } + } + + switch response.Err { + case ErrNoError: + Logger.Printf("client/coordinator coordinator for consumergroup %s is #%d (%s)\n", consumerGroup, response.Coordinator.ID(), response.Coordinator.Addr()) + return response, nil + + case ErrConsumerCoordinatorNotAvailable: + Logger.Printf("client/coordinator coordinator for consumer group %s is not available\n", consumerGroup) + + // This is very ugly, but this scenario will only happen once per cluster. + // The __consumer_offsets topic only has to be created one time. + // The number of partitions not configurable, but partition 0 should always exist. + if _, err := client.Leader("__consumer_offsets", 0); err != nil { + Logger.Printf("client/coordinator the __consumer_offsets topic is not initialized completely yet. Waiting 2 seconds...\n") + time.Sleep(2 * time.Second) + } + + return retry(ErrConsumerCoordinatorNotAvailable) + default: + return nil, response.Err + } + } + + Logger.Println("client/coordinator no available broker to send consumer metadata request to") + client.resurrectDeadBrokers() + return retry(ErrOutOfBrokers) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/client_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/client_test.go new file mode 100644 index 00000000..b0559466 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/client_test.go @@ -0,0 +1,608 @@ +package sarama + +import ( + "io" + "sync" + "testing" + "time" +) + +func safeClose(t testing.TB, c io.Closer) { + err := c.Close() + if err != nil { + t.Error(err) + } +} + +func TestSimpleClient(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + seedBroker.Returns(new(MetadataResponse)) + + client, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + seedBroker.Close() + safeClose(t, client) +} + +func TestCachedPartitions(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + replicas := []int32{3, 1, 5} + isr := []int32{5, 1} + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker("localhost:12345", 2) + metadataResponse.AddTopicPartition("my_topic", 0, 2, replicas, isr, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 1, 2, replicas, isr, ErrLeaderNotAvailable) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Metadata.Retry.Max = 0 + c, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + client := c.(*client) + + // Verify they aren't cached the same + allP := client.cachedPartitionsResults["my_topic"][allPartitions] + writeP := client.cachedPartitionsResults["my_topic"][writablePartitions] + if len(allP) == len(writeP) { + t.Fatal("Invalid lengths!") + } + + tmp := client.cachedPartitionsResults["my_topic"] + // Verify we actually use the cache at all! + tmp[allPartitions] = []int32{1, 2, 3, 4} + client.cachedPartitionsResults["my_topic"] = tmp + if 4 != len(client.cachedPartitions("my_topic", allPartitions)) { + t.Fatal("Not using the cache!") + } + + seedBroker.Close() + safeClose(t, client) +} + +func TestClientDoesntCachePartitionsForTopicsWithErrors(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + replicas := []int32{seedBroker.BrokerID()} + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(seedBroker.Addr(), seedBroker.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 1, replicas[0], replicas, replicas, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 2, replicas[0], replicas, replicas, ErrNoError) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Metadata.Retry.Max = 0 + client, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + metadataResponse = new(MetadataResponse) + metadataResponse.AddTopic("unknown", ErrUnknownTopicOrPartition) + seedBroker.Returns(metadataResponse) + + partitions, err := client.Partitions("unknown") + + if err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, found", err) + } + if partitions != nil { + t.Errorf("Should return nil as partition list, found %v", partitions) + } + + // Should still use the cache of a known topic + partitions, err = client.Partitions("my_topic") + if err != nil { + t.Errorf("Expected no error, found %v", err) + } + + metadataResponse = new(MetadataResponse) + metadataResponse.AddTopic("unknown", ErrUnknownTopicOrPartition) + seedBroker.Returns(metadataResponse) + + // Should not use cache for unknown topic + partitions, err = client.Partitions("unknown") + if err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, found", err) + } + if partitions != nil { + t.Errorf("Should return nil as partition list, found %v", partitions) + } + + seedBroker.Close() + safeClose(t, client) +} + +func TestClientSeedBrokers(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker("localhost:12345", 2) + seedBroker.Returns(metadataResponse) + + client, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + seedBroker.Close() + safeClose(t, client) +} + +func TestClientMetadata(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 5) + + replicas := []int32{3, 1, 5} + isr := []int32{5, 1} + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), replicas, isr, ErrNoError) + metadataResponse.AddTopicPartition("my_topic", 1, leader.BrokerID(), replicas, isr, ErrLeaderNotAvailable) + seedBroker.Returns(metadataResponse) + + config := NewConfig() + config.Metadata.Retry.Max = 0 + client, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + topics, err := client.Topics() + if err != nil { + t.Error(err) + } else if len(topics) != 1 || topics[0] != "my_topic" { + t.Error("Client returned incorrect topics:", topics) + } + + parts, err := client.Partitions("my_topic") + if err != nil { + t.Error(err) + } else if len(parts) != 2 || parts[0] != 0 || parts[1] != 1 { + t.Error("Client returned incorrect partitions for my_topic:", parts) + } + + parts, err = client.WritablePartitions("my_topic") + if err != nil { + t.Error(err) + } else if len(parts) != 1 || parts[0] != 0 { + t.Error("Client returned incorrect writable partitions for my_topic:", parts) + } + + tst, err := client.Leader("my_topic", 0) + if err != nil { + t.Error(err) + } else if tst.ID() != 5 { + t.Error("Leader for my_topic had incorrect ID.") + } + + replicas, err = client.Replicas("my_topic", 0) + if err != nil { + t.Error(err) + } else if replicas[0] != 1 { + t.Error("Incorrect (or unsorted) replica") + } else if replicas[1] != 3 { + t.Error("Incorrect (or unsorted) replica") + } else if replicas[2] != 5 { + t.Error("Incorrect (or unsorted) replica") + } + + leader.Close() + seedBroker.Close() + safeClose(t, client) +} + +func TestClientGetOffset(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + leaderAddr := leader.Addr() + + metadata := new(MetadataResponse) + metadata.AddTopicPartition("foo", 0, leader.BrokerID(), nil, nil, ErrNoError) + metadata.AddBroker(leaderAddr, leader.BrokerID()) + seedBroker.Returns(metadata) + + client, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + offsetResponse := new(OffsetResponse) + offsetResponse.AddTopicPartition("foo", 0, 123) + leader.Returns(offsetResponse) + + offset, err := client.GetOffset("foo", 0, OffsetNewest) + if err != nil { + t.Error(err) + } + if offset != 123 { + t.Error("Unexpected offset, got ", offset) + } + + leader.Close() + seedBroker.Returns(metadata) + + leader = NewMockBrokerAddr(t, 2, leaderAddr) + offsetResponse = new(OffsetResponse) + offsetResponse.AddTopicPartition("foo", 0, 456) + leader.Returns(offsetResponse) + + offset, err = client.GetOffset("foo", 0, OffsetNewest) + if err != nil { + t.Error(err) + } + if offset != 456 { + t.Error("Unexpected offset, got ", offset) + } + + seedBroker.Close() + leader.Close() + safeClose(t, client) +} + +func TestClientReceivingUnknownTopic(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + metadataResponse1 := new(MetadataResponse) + seedBroker.Returns(metadataResponse1) + + config := NewConfig() + config.Metadata.Retry.Max = 1 + config.Metadata.Retry.Backoff = 0 + client, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + metadataUnknownTopic := new(MetadataResponse) + metadataUnknownTopic.AddTopic("new_topic", ErrUnknownTopicOrPartition) + seedBroker.Returns(metadataUnknownTopic) + seedBroker.Returns(metadataUnknownTopic) + + if err := client.RefreshMetadata("new_topic"); err != ErrUnknownTopicOrPartition { + t.Error("ErrUnknownTopicOrPartition expected, got", err) + } + + // If we are asking for the leader of a partition of the non-existing topic. + // we will request metadata again. + seedBroker.Returns(metadataUnknownTopic) + seedBroker.Returns(metadataUnknownTopic) + + if _, err = client.Leader("new_topic", 1); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, got", err) + } + + safeClose(t, client) + seedBroker.Close() +} + +func TestClientReceivingPartialMetadata(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 5) + + metadataResponse1 := new(MetadataResponse) + metadataResponse1.AddBroker(leader.Addr(), leader.BrokerID()) + seedBroker.Returns(metadataResponse1) + + config := NewConfig() + config.Metadata.Retry.Max = 0 + client, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + replicas := []int32{leader.BrokerID(), seedBroker.BrokerID()} + + metadataPartial := new(MetadataResponse) + metadataPartial.AddTopic("new_topic", ErrLeaderNotAvailable) + metadataPartial.AddTopicPartition("new_topic", 0, leader.BrokerID(), replicas, replicas, ErrNoError) + metadataPartial.AddTopicPartition("new_topic", 1, -1, replicas, []int32{}, ErrLeaderNotAvailable) + seedBroker.Returns(metadataPartial) + + if err := client.RefreshMetadata("new_topic"); err != nil { + t.Error("ErrLeaderNotAvailable should not make RefreshMetadata respond with an error") + } + + // Even though the metadata was incomplete, we should be able to get the leader of a partition + // for which we did get a useful response, without doing additional requests. + + partition0Leader, err := client.Leader("new_topic", 0) + if err != nil { + t.Error(err) + } else if partition0Leader.Addr() != leader.Addr() { + t.Error("Unexpected leader returned", partition0Leader.Addr()) + } + + // If we are asking for the leader of a partition that didn't have a leader before, + // we will do another metadata request. + + seedBroker.Returns(metadataPartial) + + // Still no leader for the partition, so asking for it should return an error. + _, err = client.Leader("new_topic", 1) + if err != ErrLeaderNotAvailable { + t.Error("Expected ErrLeaderNotAvailable, got", err) + } + + safeClose(t, client) + seedBroker.Close() + leader.Close() +} + +func TestClientRefreshBehaviour(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 5) + + metadataResponse1 := new(MetadataResponse) + metadataResponse1.AddBroker(leader.Addr(), leader.BrokerID()) + seedBroker.Returns(metadataResponse1) + + metadataResponse2 := new(MetadataResponse) + metadataResponse2.AddTopicPartition("my_topic", 0xb, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse2) + + client, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + parts, err := client.Partitions("my_topic") + if err != nil { + t.Error(err) + } else if len(parts) != 1 || parts[0] != 0xb { + t.Error("Client returned incorrect partitions for my_topic:", parts) + } + + tst, err := client.Leader("my_topic", 0xb) + if err != nil { + t.Error(err) + } else if tst.ID() != 5 { + t.Error("Leader for my_topic had incorrect ID.") + } + + leader.Close() + seedBroker.Close() + safeClose(t, client) +} + +func TestClientResurrectDeadSeeds(t *testing.T) { + initialSeed := NewMockBroker(t, 0) + emptyMetadata := new(MetadataResponse) + initialSeed.Returns(emptyMetadata) + + conf := NewConfig() + conf.Metadata.Retry.Backoff = 0 + conf.Metadata.RefreshFrequency = 0 + c, err := NewClient([]string{initialSeed.Addr()}, conf) + if err != nil { + t.Fatal(err) + } + initialSeed.Close() + + client := c.(*client) + + seed1 := NewMockBroker(t, 1) + seed2 := NewMockBroker(t, 2) + seed3 := NewMockBroker(t, 3) + addr1 := seed1.Addr() + addr2 := seed2.Addr() + addr3 := seed3.Addr() + + // Overwrite the seed brokers with a fixed ordering to make this test deterministic. + safeClose(t, client.seedBrokers[0]) + client.seedBrokers = []*Broker{NewBroker(addr1), NewBroker(addr2), NewBroker(addr3)} + client.deadSeeds = []*Broker{} + + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + if err := client.RefreshMetadata(); err != nil { + t.Error(err) + } + wg.Done() + }() + seed1.Close() + seed2.Close() + + seed1 = NewMockBrokerAddr(t, 1, addr1) + seed2 = NewMockBrokerAddr(t, 2, addr2) + + seed3.Close() + + seed1.Close() + seed2.Returns(emptyMetadata) + + wg.Wait() + + if len(client.seedBrokers) != 2 { + t.Error("incorrect number of live seeds") + } + if len(client.deadSeeds) != 1 { + t.Error("incorrect number of dead seeds") + } + + safeClose(t, c) +} + +func TestClientCoordinatorWithConsumerOffsetsTopic(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + staleCoordinator := NewMockBroker(t, 2) + freshCoordinator := NewMockBroker(t, 3) + + replicas := []int32{staleCoordinator.BrokerID(), freshCoordinator.BrokerID()} + metadataResponse1 := new(MetadataResponse) + metadataResponse1.AddBroker(staleCoordinator.Addr(), staleCoordinator.BrokerID()) + metadataResponse1.AddBroker(freshCoordinator.Addr(), freshCoordinator.BrokerID()) + metadataResponse1.AddTopicPartition("__consumer_offsets", 0, replicas[0], replicas, replicas, ErrNoError) + seedBroker.Returns(metadataResponse1) + + client, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + coordinatorResponse1 := new(ConsumerMetadataResponse) + coordinatorResponse1.Err = ErrConsumerCoordinatorNotAvailable + seedBroker.Returns(coordinatorResponse1) + + coordinatorResponse2 := new(ConsumerMetadataResponse) + coordinatorResponse2.CoordinatorID = staleCoordinator.BrokerID() + coordinatorResponse2.CoordinatorHost = "127.0.0.1" + coordinatorResponse2.CoordinatorPort = staleCoordinator.Port() + + seedBroker.Returns(coordinatorResponse2) + + broker, err := client.Coordinator("my_group") + if err != nil { + t.Error(err) + } + + if staleCoordinator.Addr() != broker.Addr() { + t.Errorf("Expected coordinator to have address %s, found %s", staleCoordinator.Addr(), broker.Addr()) + } + + if staleCoordinator.BrokerID() != broker.ID() { + t.Errorf("Expected coordinator to have ID %d, found %d", staleCoordinator.BrokerID(), broker.ID()) + } + + // Grab the cached value + broker2, err := client.Coordinator("my_group") + if err != nil { + t.Error(err) + } + + if broker2.Addr() != broker.Addr() { + t.Errorf("Expected the coordinator to be the same, but found %s vs. %s", broker2.Addr(), broker.Addr()) + } + + coordinatorResponse3 := new(ConsumerMetadataResponse) + coordinatorResponse3.CoordinatorID = freshCoordinator.BrokerID() + coordinatorResponse3.CoordinatorHost = "127.0.0.1" + coordinatorResponse3.CoordinatorPort = freshCoordinator.Port() + + seedBroker.Returns(coordinatorResponse3) + + // Refresh the locally cahced value because it's stale + if err := client.RefreshCoordinator("my_group"); err != nil { + t.Error(err) + } + + // Grab the fresh value + broker3, err := client.Coordinator("my_group") + if err != nil { + t.Error(err) + } + + if broker3.Addr() != freshCoordinator.Addr() { + t.Errorf("Expected the freshCoordinator to be returned, but found %s.", broker3.Addr()) + } + + freshCoordinator.Close() + staleCoordinator.Close() + seedBroker.Close() + safeClose(t, client) +} + +func TestClientCoordinatorWithoutConsumerOffsetsTopic(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + coordinator := NewMockBroker(t, 2) + + metadataResponse1 := new(MetadataResponse) + seedBroker.Returns(metadataResponse1) + + config := NewConfig() + config.Metadata.Retry.Max = 1 + config.Metadata.Retry.Backoff = 0 + client, err := NewClient([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + coordinatorResponse1 := new(ConsumerMetadataResponse) + coordinatorResponse1.Err = ErrConsumerCoordinatorNotAvailable + seedBroker.Returns(coordinatorResponse1) + + metadataResponse2 := new(MetadataResponse) + metadataResponse2.AddTopic("__consumer_offsets", ErrUnknownTopicOrPartition) + seedBroker.Returns(metadataResponse2) + + replicas := []int32{coordinator.BrokerID()} + metadataResponse3 := new(MetadataResponse) + metadataResponse3.AddTopicPartition("__consumer_offsets", 0, replicas[0], replicas, replicas, ErrNoError) + seedBroker.Returns(metadataResponse3) + + coordinatorResponse2 := new(ConsumerMetadataResponse) + coordinatorResponse2.CoordinatorID = coordinator.BrokerID() + coordinatorResponse2.CoordinatorHost = "127.0.0.1" + coordinatorResponse2.CoordinatorPort = coordinator.Port() + + seedBroker.Returns(coordinatorResponse2) + + broker, err := client.Coordinator("my_group") + if err != nil { + t.Error(err) + } + + if coordinator.Addr() != broker.Addr() { + t.Errorf("Expected coordinator to have address %s, found %s", coordinator.Addr(), broker.Addr()) + } + + if coordinator.BrokerID() != broker.ID() { + t.Errorf("Expected coordinator to have ID %d, found %d", coordinator.BrokerID(), broker.ID()) + } + + coordinator.Close() + seedBroker.Close() + safeClose(t, client) +} + +func TestClientAutorefreshShutdownRace(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + + metadataResponse := new(MetadataResponse) + seedBroker.Returns(metadataResponse) + + conf := NewConfig() + conf.Metadata.RefreshFrequency = 100 * time.Millisecond + client, err := NewClient([]string{seedBroker.Addr()}, conf) + if err != nil { + t.Fatal(err) + } + + // Wait for the background refresh to kick in + time.Sleep(110 * time.Millisecond) + + done := make(chan none) + go func() { + // Close the client + if err := client.Close(); err != nil { + t.Fatal(err) + } + close(done) + }() + + // Wait for the Close to kick in + time.Sleep(10 * time.Millisecond) + + // Then return some metadata to the still-running background thread + leader := NewMockBroker(t, 2) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("foo", 0, leader.BrokerID(), []int32{2}, []int32{2}, ErrNoError) + seedBroker.Returns(metadataResponse) + + <-done + + seedBroker.Close() + + // give the update time to happen so we get a panic if it's still running (which it shouldn't) + time.Sleep(10 * time.Millisecond) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/config.go b/vendor/src/gopkg.in/Shopify/sarama.v1/config.go new file mode 100644 index 00000000..a417a38b --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/config.go @@ -0,0 +1,417 @@ +package sarama + +import ( + "crypto/tls" + "regexp" + "time" + + "github.com/rcrowley/go-metrics" +) + +const defaultClientID = "sarama" + +var validID = regexp.MustCompile(`\A[A-Za-z0-9._-]+\z`) + +// Config is used to pass multiple configuration options to Sarama's constructors. +type Config struct { + // Net is the namespace for network-level properties used by the Broker, and + // shared by the Client/Producer/Consumer. + Net struct { + // How many outstanding requests a connection is allowed to have before + // sending on it blocks (default 5). + MaxOpenRequests int + + // All three of the below configurations are similar to the + // `socket.timeout.ms` setting in JVM kafka. All of them default + // to 30 seconds. + DialTimeout time.Duration // How long to wait for the initial connection. + ReadTimeout time.Duration // How long to wait for a response. + WriteTimeout time.Duration // How long to wait for a transmit. + + TLS struct { + // Whether or not to use TLS when connecting to the broker + // (defaults to false). + Enable bool + // The TLS configuration to use for secure connections if + // enabled (defaults to nil). + Config *tls.Config + } + + // SASL based authentication with broker. While there are multiple SASL authentication methods + // the current implementation is limited to plaintext (SASL/PLAIN) authentication + SASL struct { + // Whether or not to use SASL authentication when connecting to the broker + // (defaults to false). + Enable bool + // Whether or not to send the Kafka SASL handshake first if enabled + // (defaults to true). You should only set this to false if you're using + // a non-Kafka SASL proxy. + Handshake bool + //username and password for SASL/PLAIN authentication + User string + Password string + } + + // KeepAlive specifies the keep-alive period for an active network connection. + // If zero, keep-alives are disabled. (default is 0: disabled). + KeepAlive time.Duration + } + + // Metadata is the namespace for metadata management properties used by the + // Client, and shared by the Producer/Consumer. + Metadata struct { + Retry struct { + // The total number of times to retry a metadata request when the + // cluster is in the middle of a leader election (default 3). + Max int + // How long to wait for leader election to occur before retrying + // (default 250ms). Similar to the JVM's `retry.backoff.ms`. + Backoff time.Duration + } + // How frequently to refresh the cluster metadata in the background. + // Defaults to 10 minutes. Set to 0 to disable. Similar to + // `topic.metadata.refresh.interval.ms` in the JVM version. + RefreshFrequency time.Duration + } + + // Producer is the namespace for configuration related to producing messages, + // used by the Producer. + Producer struct { + // The maximum permitted size of a message (defaults to 1000000). Should be + // set equal to or smaller than the broker's `message.max.bytes`. + MaxMessageBytes int + // The level of acknowledgement reliability needed from the broker (defaults + // to WaitForLocal). Equivalent to the `request.required.acks` setting of the + // JVM producer. + RequiredAcks RequiredAcks + // The maximum duration the broker will wait the receipt of the number of + // RequiredAcks (defaults to 10 seconds). This is only relevant when + // RequiredAcks is set to WaitForAll or a number > 1. Only supports + // millisecond resolution, nanoseconds will be truncated. Equivalent to + // the JVM producer's `request.timeout.ms` setting. + Timeout time.Duration + // The type of compression to use on messages (defaults to no compression). + // Similar to `compression.codec` setting of the JVM producer. + Compression CompressionCodec + // Generates partitioners for choosing the partition to send messages to + // (defaults to hashing the message key). Similar to the `partitioner.class` + // setting for the JVM producer. + Partitioner PartitionerConstructor + + // Return specifies what channels will be populated. If they are set to true, + // you must read from the respective channels to prevent deadlock. + Return struct { + // If enabled, successfully delivered messages will be returned on the + // Successes channel (default disabled). + Successes bool + + // If enabled, messages that failed to deliver will be returned on the + // Errors channel, including error (default enabled). + Errors bool + } + + // The following config options control how often messages are batched up and + // sent to the broker. By default, messages are sent as fast as possible, and + // all messages received while the current batch is in-flight are placed + // into the subsequent batch. + Flush struct { + // The best-effort number of bytes needed to trigger a flush. Use the + // global sarama.MaxRequestSize to set a hard upper limit. + Bytes int + // The best-effort number of messages needed to trigger a flush. Use + // `MaxMessages` to set a hard upper limit. + Messages int + // The best-effort frequency of flushes. Equivalent to + // `queue.buffering.max.ms` setting of JVM producer. + Frequency time.Duration + // The maximum number of messages the producer will send in a single + // broker request. Defaults to 0 for unlimited. Similar to + // `queue.buffering.max.messages` in the JVM producer. + MaxMessages int + } + + Retry struct { + // The total number of times to retry sending a message (default 3). + // Similar to the `message.send.max.retries` setting of the JVM producer. + Max int + // How long to wait for the cluster to settle between retries + // (default 100ms). Similar to the `retry.backoff.ms` setting of the + // JVM producer. + Backoff time.Duration + } + } + + // Consumer is the namespace for configuration related to consuming messages, + // used by the Consumer. + // + // Note that Sarama's Consumer type does not currently support automatic + // consumer-group rebalancing and offset tracking. For Zookeeper-based + // tracking (Kafka 0.8.2 and earlier), the https://github.com/wvanbergen/kafka + // library builds on Sarama to add this support. For Kafka-based tracking + // (Kafka 0.9 and later), the https://github.com/bsm/sarama-cluster library + // builds on Sarama to add this support. + Consumer struct { + Retry struct { + // How long to wait after a failing to read from a partition before + // trying again (default 2s). + Backoff time.Duration + } + + // Fetch is the namespace for controlling how many bytes are retrieved by any + // given request. + Fetch struct { + // The minimum number of message bytes to fetch in a request - the broker + // will wait until at least this many are available. The default is 1, + // as 0 causes the consumer to spin when no messages are available. + // Equivalent to the JVM's `fetch.min.bytes`. + Min int32 + // The default number of message bytes to fetch from the broker in each + // request (default 32768). This should be larger than the majority of + // your messages, or else the consumer will spend a lot of time + // negotiating sizes and not actually consuming. Similar to the JVM's + // `fetch.message.max.bytes`. + Default int32 + // The maximum number of message bytes to fetch from the broker in a + // single request. Messages larger than this will return + // ErrMessageTooLarge and will not be consumable, so you must be sure + // this is at least as large as your largest message. Defaults to 0 + // (no limit). Similar to the JVM's `fetch.message.max.bytes`. The + // global `sarama.MaxResponseSize` still applies. + Max int32 + } + // The maximum amount of time the broker will wait for Consumer.Fetch.Min + // bytes to become available before it returns fewer than that anyways. The + // default is 250ms, since 0 causes the consumer to spin when no events are + // available. 100-500ms is a reasonable range for most cases. Kafka only + // supports precision up to milliseconds; nanoseconds will be truncated. + // Equivalent to the JVM's `fetch.wait.max.ms`. + MaxWaitTime time.Duration + + // The maximum amount of time the consumer expects a message takes to process + // for the user. If writing to the Messages channel takes longer than this, + // that partition will stop fetching more messages until it can proceed again. + // Note that, since the Messages channel is buffered, the actual grace time is + // (MaxProcessingTime * ChanneBufferSize). Defaults to 100ms. + MaxProcessingTime time.Duration + + // Return specifies what channels will be populated. If they are set to true, + // you must read from them to prevent deadlock. + Return struct { + // If enabled, any errors that occurred while consuming are returned on + // the Errors channel (default disabled). + Errors bool + } + + // Offsets specifies configuration for how and when to commit consumed + // offsets. This currently requires the manual use of an OffsetManager + // but will eventually be automated. + Offsets struct { + // How frequently to commit updated offsets. Defaults to 1s. + CommitInterval time.Duration + + // The initial offset to use if no offset was previously committed. + // Should be OffsetNewest or OffsetOldest. Defaults to OffsetNewest. + Initial int64 + + // The retention duration for committed offsets. If zero, disabled + // (in which case the `offsets.retention.minutes` option on the + // broker will be used). Kafka only supports precision up to + // milliseconds; nanoseconds will be truncated. Requires Kafka + // broker version 0.9.0 or later. + // (default is 0: disabled). + Retention time.Duration + } + } + + // A user-provided string sent with every request to the brokers for logging, + // debugging, and auditing purposes. Defaults to "sarama", but you should + // probably set it to something specific to your application. + ClientID string + // The number of events to buffer in internal and external channels. This + // permits the producer and consumer to continue processing some messages + // in the background while user code is working, greatly improving throughput. + // Defaults to 256. + ChannelBufferSize int + // The version of Kafka that Sarama will assume it is running against. + // Defaults to the oldest supported stable version. Since Kafka provides + // backwards-compatibility, setting it to a version older than you have + // will not break anything, although it may prevent you from using the + // latest features. Setting it to a version greater than you are actually + // running may lead to random breakage. + Version KafkaVersion + // The registry to define metrics into. + // Defaults to a local registry. + // If you want to disable metrics gathering, set "metrics.UseNilMetrics" to "true" + // prior to starting Sarama. + // See Examples on how to use the metrics registry + MetricRegistry metrics.Registry +} + +// NewConfig returns a new configuration instance with sane defaults. +func NewConfig() *Config { + c := &Config{} + + c.Net.MaxOpenRequests = 5 + c.Net.DialTimeout = 30 * time.Second + c.Net.ReadTimeout = 30 * time.Second + c.Net.WriteTimeout = 30 * time.Second + c.Net.SASL.Handshake = true + + c.Metadata.Retry.Max = 3 + c.Metadata.Retry.Backoff = 250 * time.Millisecond + c.Metadata.RefreshFrequency = 10 * time.Minute + + c.Producer.MaxMessageBytes = 1000000 + c.Producer.RequiredAcks = WaitForLocal + c.Producer.Timeout = 10 * time.Second + c.Producer.Partitioner = NewHashPartitioner + c.Producer.Retry.Max = 3 + c.Producer.Retry.Backoff = 100 * time.Millisecond + c.Producer.Return.Errors = true + + c.Consumer.Fetch.Min = 1 + c.Consumer.Fetch.Default = 32768 + c.Consumer.Retry.Backoff = 2 * time.Second + c.Consumer.MaxWaitTime = 250 * time.Millisecond + c.Consumer.MaxProcessingTime = 100 * time.Millisecond + c.Consumer.Return.Errors = false + c.Consumer.Offsets.CommitInterval = 1 * time.Second + c.Consumer.Offsets.Initial = OffsetNewest + + c.ClientID = defaultClientID + c.ChannelBufferSize = 256 + c.Version = minVersion + c.MetricRegistry = metrics.NewRegistry() + + return c +} + +// Validate checks a Config instance. It will return a +// ConfigurationError if the specified values don't make sense. +func (c *Config) Validate() error { + // some configuration values should be warned on but not fail completely, do those first + if c.Net.TLS.Enable == false && c.Net.TLS.Config != nil { + Logger.Println("Net.TLS is disabled but a non-nil configuration was provided.") + } + if c.Net.SASL.Enable == false { + if c.Net.SASL.User != "" { + Logger.Println("Net.SASL is disabled but a non-empty username was provided.") + } + if c.Net.SASL.Password != "" { + Logger.Println("Net.SASL is disabled but a non-empty password was provided.") + } + } + if c.Producer.RequiredAcks > 1 { + Logger.Println("Producer.RequiredAcks > 1 is deprecated and will raise an exception with kafka >= 0.8.2.0.") + } + if c.Producer.MaxMessageBytes >= int(MaxRequestSize) { + Logger.Println("Producer.MaxMessageBytes is larger than MaxRequestSize; it will be ignored.") + } + if c.Producer.Flush.Bytes >= int(MaxRequestSize) { + Logger.Println("Producer.Flush.Bytes is larger than MaxRequestSize; it will be ignored.") + } + if c.Producer.Timeout%time.Millisecond != 0 { + Logger.Println("Producer.Timeout only supports millisecond resolution; nanoseconds will be truncated.") + } + if c.Consumer.MaxWaitTime < 100*time.Millisecond { + Logger.Println("Consumer.MaxWaitTime is very low, which can cause high CPU and network usage. See documentation for details.") + } + if c.Consumer.MaxWaitTime%time.Millisecond != 0 { + Logger.Println("Consumer.MaxWaitTime only supports millisecond precision; nanoseconds will be truncated.") + } + if c.Consumer.Offsets.Retention%time.Millisecond != 0 { + Logger.Println("Consumer.Offsets.Retention only supports millisecond precision; nanoseconds will be truncated.") + } + if c.ClientID == defaultClientID { + Logger.Println("ClientID is the default of 'sarama', you should consider setting it to something application-specific.") + } + + // validate Net values + switch { + case c.Net.MaxOpenRequests <= 0: + return ConfigurationError("Net.MaxOpenRequests must be > 0") + case c.Net.DialTimeout <= 0: + return ConfigurationError("Net.DialTimeout must be > 0") + case c.Net.ReadTimeout <= 0: + return ConfigurationError("Net.ReadTimeout must be > 0") + case c.Net.WriteTimeout <= 0: + return ConfigurationError("Net.WriteTimeout must be > 0") + case c.Net.KeepAlive < 0: + return ConfigurationError("Net.KeepAlive must be >= 0") + case c.Net.SASL.Enable == true && c.Net.SASL.User == "": + return ConfigurationError("Net.SASL.User must not be empty when SASL is enabled") + case c.Net.SASL.Enable == true && c.Net.SASL.Password == "": + return ConfigurationError("Net.SASL.Password must not be empty when SASL is enabled") + } + + // validate the Metadata values + switch { + case c.Metadata.Retry.Max < 0: + return ConfigurationError("Metadata.Retry.Max must be >= 0") + case c.Metadata.Retry.Backoff < 0: + return ConfigurationError("Metadata.Retry.Backoff must be >= 0") + case c.Metadata.RefreshFrequency < 0: + return ConfigurationError("Metadata.RefreshFrequency must be >= 0") + } + + // validate the Producer values + switch { + case c.Producer.MaxMessageBytes <= 0: + return ConfigurationError("Producer.MaxMessageBytes must be > 0") + case c.Producer.RequiredAcks < -1: + return ConfigurationError("Producer.RequiredAcks must be >= -1") + case c.Producer.Timeout <= 0: + return ConfigurationError("Producer.Timeout must be > 0") + case c.Producer.Partitioner == nil: + return ConfigurationError("Producer.Partitioner must not be nil") + case c.Producer.Flush.Bytes < 0: + return ConfigurationError("Producer.Flush.Bytes must be >= 0") + case c.Producer.Flush.Messages < 0: + return ConfigurationError("Producer.Flush.Messages must be >= 0") + case c.Producer.Flush.Frequency < 0: + return ConfigurationError("Producer.Flush.Frequency must be >= 0") + case c.Producer.Flush.MaxMessages < 0: + return ConfigurationError("Producer.Flush.MaxMessages must be >= 0") + case c.Producer.Flush.MaxMessages > 0 && c.Producer.Flush.MaxMessages < c.Producer.Flush.Messages: + return ConfigurationError("Producer.Flush.MaxMessages must be >= Producer.Flush.Messages when set") + case c.Producer.Retry.Max < 0: + return ConfigurationError("Producer.Retry.Max must be >= 0") + case c.Producer.Retry.Backoff < 0: + return ConfigurationError("Producer.Retry.Backoff must be >= 0") + } + + if c.Producer.Compression == CompressionLZ4 && !c.Version.IsAtLeast(V0_10_0_0) { + return ConfigurationError("lz4 compression requires Version >= V0_10_0_0") + } + + // validate the Consumer values + switch { + case c.Consumer.Fetch.Min <= 0: + return ConfigurationError("Consumer.Fetch.Min must be > 0") + case c.Consumer.Fetch.Default <= 0: + return ConfigurationError("Consumer.Fetch.Default must be > 0") + case c.Consumer.Fetch.Max < 0: + return ConfigurationError("Consumer.Fetch.Max must be >= 0") + case c.Consumer.MaxWaitTime < 1*time.Millisecond: + return ConfigurationError("Consumer.MaxWaitTime must be >= 1ms") + case c.Consumer.MaxProcessingTime <= 0: + return ConfigurationError("Consumer.MaxProcessingTime must be > 0") + case c.Consumer.Retry.Backoff < 0: + return ConfigurationError("Consumer.Retry.Backoff must be >= 0") + case c.Consumer.Offsets.CommitInterval <= 0: + return ConfigurationError("Consumer.Offsets.CommitInterval must be > 0") + case c.Consumer.Offsets.Initial != OffsetOldest && c.Consumer.Offsets.Initial != OffsetNewest: + return ConfigurationError("Consumer.Offsets.Initial must be OffsetOldest or OffsetNewest") + + } + + // validate misc shared values + switch { + case c.ChannelBufferSize < 0: + return ConfigurationError("ChannelBufferSize must be >= 0") + case !validID.MatchString(c.ClientID): + return ConfigurationError("ClientID is invalid") + } + + return nil +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/config_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/config_test.go new file mode 100644 index 00000000..5fef6b36 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/config_test.go @@ -0,0 +1,70 @@ +package sarama + +import ( + "os" + "testing" + + "github.com/rcrowley/go-metrics" +) + +func TestDefaultConfigValidates(t *testing.T) { + config := NewConfig() + if err := config.Validate(); err != nil { + t.Error(err) + } + if config.MetricRegistry == nil { + t.Error("Expected non nil metrics.MetricRegistry, got nil") + } +} + +func TestInvalidClientIDConfigValidates(t *testing.T) { + config := NewConfig() + config.ClientID = "foo:bar" + if err := config.Validate(); string(err.(ConfigurationError)) != "ClientID is invalid" { + t.Error("Expected invalid ClientID, got ", err) + } +} + +func TestEmptyClientIDConfigValidates(t *testing.T) { + config := NewConfig() + config.ClientID = "" + if err := config.Validate(); string(err.(ConfigurationError)) != "ClientID is invalid" { + t.Error("Expected invalid ClientID, got ", err) + } +} + +func TestLZ4ConfigValidation(t *testing.T) { + config := NewConfig() + config.Producer.Compression = CompressionLZ4 + if err := config.Validate(); string(err.(ConfigurationError)) != "lz4 compression requires Version >= V0_10_0_0" { + t.Error("Expected invalid lz4/kakfa version error, got ", err) + } + config.Version = V0_10_0_0 + if err := config.Validate(); err != nil { + t.Error("Expected lz4 to work, got ", err) + } +} + +// This example shows how to integrate with an existing registry as well as publishing metrics +// on the standard output +func ExampleConfig_metrics() { + // Our application registry + appMetricRegistry := metrics.NewRegistry() + appGauge := metrics.GetOrRegisterGauge("m1", appMetricRegistry) + appGauge.Update(1) + + config := NewConfig() + // Use a prefix registry instead of the default local one + config.MetricRegistry = metrics.NewPrefixedChildRegistry(appMetricRegistry, "sarama.") + + // Simulate a metric created by sarama without starting a broker + saramaGauge := metrics.GetOrRegisterGauge("m2", config.MetricRegistry) + saramaGauge.Update(2) + + metrics.WriteOnce(appMetricRegistry, os.Stdout) + // Output: + // gauge m1 + // value: 1 + // gauge sarama.m2 + // value: 2 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/consumer.go b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer.go new file mode 100644 index 00000000..ddac564f --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer.go @@ -0,0 +1,735 @@ +package sarama + +import ( + "errors" + "fmt" + "sync" + "sync/atomic" + "time" +) + +// ConsumerMessage encapsulates a Kafka message returned by the consumer. +type ConsumerMessage struct { + Key, Value []byte + Topic string + Partition int32 + Offset int64 + Timestamp time.Time // only set if kafka is version 0.10+ +} + +// ConsumerError is what is provided to the user when an error occurs. +// It wraps an error and includes the topic and partition. +type ConsumerError struct { + Topic string + Partition int32 + Err error +} + +func (ce ConsumerError) Error() string { + return fmt.Sprintf("kafka: error while consuming %s/%d: %s", ce.Topic, ce.Partition, ce.Err) +} + +// ConsumerErrors is a type that wraps a batch of errors and implements the Error interface. +// It can be returned from the PartitionConsumer's Close methods to avoid the need to manually drain errors +// when stopping. +type ConsumerErrors []*ConsumerError + +func (ce ConsumerErrors) Error() string { + return fmt.Sprintf("kafka: %d errors while consuming", len(ce)) +} + +// Consumer manages PartitionConsumers which process Kafka messages from brokers. You MUST call Close() +// on a consumer to avoid leaks, it will not be garbage-collected automatically when it passes out of +// scope. +// +// Sarama's Consumer type does not currently support automatic consumer-group rebalancing and offset tracking. +// For Zookeeper-based tracking (Kafka 0.8.2 and earlier), the https://github.com/wvanbergen/kafka library +// builds on Sarama to add this support. For Kafka-based tracking (Kafka 0.9 and later), the +// https://github.com/bsm/sarama-cluster library builds on Sarama to add this support. +type Consumer interface { + + // Topics returns the set of available topics as retrieved from the cluster + // metadata. This method is the same as Client.Topics(), and is provided for + // convenience. + Topics() ([]string, error) + + // Partitions returns the sorted list of all partition IDs for the given topic. + // This method is the same as Client.Partitions(), and is provided for convenience. + Partitions(topic string) ([]int32, error) + + // ConsumePartition creates a PartitionConsumer on the given topic/partition with + // the given offset. It will return an error if this Consumer is already consuming + // on the given topic/partition. Offset can be a literal offset, or OffsetNewest + // or OffsetOldest + ConsumePartition(topic string, partition int32, offset int64) (PartitionConsumer, error) + + // HighWaterMarks returns the current high water marks for each topic and partition. + // Consistency between partitions is not guaranteed since high water marks are updated separately. + HighWaterMarks() map[string]map[int32]int64 + + // Close shuts down the consumer. It must be called after all child + // PartitionConsumers have already been closed. + Close() error +} + +type consumer struct { + client Client + conf *Config + ownClient bool + + lock sync.Mutex + children map[string]map[int32]*partitionConsumer + brokerConsumers map[*Broker]*brokerConsumer +} + +// NewConsumer creates a new consumer using the given broker addresses and configuration. +func NewConsumer(addrs []string, config *Config) (Consumer, error) { + client, err := NewClient(addrs, config) + if err != nil { + return nil, err + } + + c, err := NewConsumerFromClient(client) + if err != nil { + return nil, err + } + c.(*consumer).ownClient = true + return c, nil +} + +// NewConsumerFromClient creates a new consumer using the given client. It is still +// necessary to call Close() on the underlying client when shutting down this consumer. +func NewConsumerFromClient(client Client) (Consumer, error) { + // Check that we are not dealing with a closed Client before processing any other arguments + if client.Closed() { + return nil, ErrClosedClient + } + + c := &consumer{ + client: client, + conf: client.Config(), + children: make(map[string]map[int32]*partitionConsumer), + brokerConsumers: make(map[*Broker]*brokerConsumer), + } + + return c, nil +} + +func (c *consumer) Close() error { + if c.ownClient { + return c.client.Close() + } + return nil +} + +func (c *consumer) Topics() ([]string, error) { + return c.client.Topics() +} + +func (c *consumer) Partitions(topic string) ([]int32, error) { + return c.client.Partitions(topic) +} + +func (c *consumer) ConsumePartition(topic string, partition int32, offset int64) (PartitionConsumer, error) { + child := &partitionConsumer{ + consumer: c, + conf: c.conf, + topic: topic, + partition: partition, + messages: make(chan *ConsumerMessage, c.conf.ChannelBufferSize), + errors: make(chan *ConsumerError, c.conf.ChannelBufferSize), + feeder: make(chan *FetchResponse, 1), + trigger: make(chan none, 1), + dying: make(chan none), + fetchSize: c.conf.Consumer.Fetch.Default, + } + + if err := child.chooseStartingOffset(offset); err != nil { + return nil, err + } + + var leader *Broker + var err error + if leader, err = c.client.Leader(child.topic, child.partition); err != nil { + return nil, err + } + + if err := c.addChild(child); err != nil { + return nil, err + } + + go withRecover(child.dispatcher) + go withRecover(child.responseFeeder) + + child.broker = c.refBrokerConsumer(leader) + child.broker.input <- child + + return child, nil +} + +func (c *consumer) HighWaterMarks() map[string]map[int32]int64 { + c.lock.Lock() + defer c.lock.Unlock() + + hwms := make(map[string]map[int32]int64) + for topic, p := range c.children { + hwm := make(map[int32]int64, len(p)) + for partition, pc := range p { + hwm[partition] = pc.HighWaterMarkOffset() + } + hwms[topic] = hwm + } + + return hwms +} + +func (c *consumer) addChild(child *partitionConsumer) error { + c.lock.Lock() + defer c.lock.Unlock() + + topicChildren := c.children[child.topic] + if topicChildren == nil { + topicChildren = make(map[int32]*partitionConsumer) + c.children[child.topic] = topicChildren + } + + if topicChildren[child.partition] != nil { + return ConfigurationError("That topic/partition is already being consumed") + } + + topicChildren[child.partition] = child + return nil +} + +func (c *consumer) removeChild(child *partitionConsumer) { + c.lock.Lock() + defer c.lock.Unlock() + + delete(c.children[child.topic], child.partition) +} + +func (c *consumer) refBrokerConsumer(broker *Broker) *brokerConsumer { + c.lock.Lock() + defer c.lock.Unlock() + + bc := c.brokerConsumers[broker] + if bc == nil { + bc = c.newBrokerConsumer(broker) + c.brokerConsumers[broker] = bc + } + + bc.refs++ + + return bc +} + +func (c *consumer) unrefBrokerConsumer(brokerWorker *brokerConsumer) { + c.lock.Lock() + defer c.lock.Unlock() + + brokerWorker.refs-- + + if brokerWorker.refs == 0 { + close(brokerWorker.input) + if c.brokerConsumers[brokerWorker.broker] == brokerWorker { + delete(c.brokerConsumers, brokerWorker.broker) + } + } +} + +func (c *consumer) abandonBrokerConsumer(brokerWorker *brokerConsumer) { + c.lock.Lock() + defer c.lock.Unlock() + + delete(c.brokerConsumers, brokerWorker.broker) +} + +// PartitionConsumer + +// PartitionConsumer processes Kafka messages from a given topic and partition. You MUST call Close() +// or AsyncClose() on a PartitionConsumer to avoid leaks, it will not be garbage-collected automatically +// when it passes out of scope. +// +// The simplest way of using a PartitionConsumer is to loop over its Messages channel using a for/range +// loop. The PartitionConsumer will only stop itself in one case: when the offset being consumed is reported +// as out of range by the brokers. In this case you should decide what you want to do (try a different offset, +// notify a human, etc) and handle it appropriately. For all other error cases, it will just keep retrying. +// By default, it logs these errors to sarama.Logger; if you want to be notified directly of all errors, set +// your config's Consumer.Return.Errors to true and read from the Errors channel, using a select statement +// or a separate goroutine. Check out the Consumer examples to see implementations of these different approaches. +type PartitionConsumer interface { + + // AsyncClose initiates a shutdown of the PartitionConsumer. This method will + // return immediately, after which you should wait until the 'messages' and + // 'errors' channel are drained. It is required to call this function, or + // Close before a consumer object passes out of scope, as it will otherwise + // leak memory. You must call this before calling Close on the underlying client. + AsyncClose() + + // Close stops the PartitionConsumer from fetching messages. It is required to + // call this function (or AsyncClose) before a consumer object passes out of + // scope, as it will otherwise leak memory. You must call this before calling + // Close on the underlying client. + Close() error + + // Messages returns the read channel for the messages that are returned by + // the broker. + Messages() <-chan *ConsumerMessage + + // Errors returns a read channel of errors that occurred during consuming, if + // enabled. By default, errors are logged and not returned over this channel. + // If you want to implement any custom error handling, set your config's + // Consumer.Return.Errors setting to true, and read from this channel. + Errors() <-chan *ConsumerError + + // HighWaterMarkOffset returns the high water mark offset of the partition, + // i.e. the offset that will be used for the next message that will be produced. + // You can use this to determine how far behind the processing is. + HighWaterMarkOffset() int64 +} + +type partitionConsumer struct { + consumer *consumer + conf *Config + topic string + partition int32 + + broker *brokerConsumer + messages chan *ConsumerMessage + errors chan *ConsumerError + feeder chan *FetchResponse + + trigger, dying chan none + responseResult error + + fetchSize int32 + offset int64 + highWaterMarkOffset int64 +} + +var errTimedOut = errors.New("timed out feeding messages to the user") // not user-facing + +func (child *partitionConsumer) sendError(err error) { + cErr := &ConsumerError{ + Topic: child.topic, + Partition: child.partition, + Err: err, + } + + if child.conf.Consumer.Return.Errors { + child.errors <- cErr + } else { + Logger.Println(cErr) + } +} + +func (child *partitionConsumer) dispatcher() { + for _ = range child.trigger { + select { + case <-child.dying: + close(child.trigger) + case <-time.After(child.conf.Consumer.Retry.Backoff): + if child.broker != nil { + child.consumer.unrefBrokerConsumer(child.broker) + child.broker = nil + } + + Logger.Printf("consumer/%s/%d finding new broker\n", child.topic, child.partition) + if err := child.dispatch(); err != nil { + child.sendError(err) + child.trigger <- none{} + } + } + } + + if child.broker != nil { + child.consumer.unrefBrokerConsumer(child.broker) + } + child.consumer.removeChild(child) + close(child.feeder) +} + +func (child *partitionConsumer) dispatch() error { + if err := child.consumer.client.RefreshMetadata(child.topic); err != nil { + return err + } + + var leader *Broker + var err error + if leader, err = child.consumer.client.Leader(child.topic, child.partition); err != nil { + return err + } + + child.broker = child.consumer.refBrokerConsumer(leader) + + child.broker.input <- child + + return nil +} + +func (child *partitionConsumer) chooseStartingOffset(offset int64) error { + newestOffset, err := child.consumer.client.GetOffset(child.topic, child.partition, OffsetNewest) + if err != nil { + return err + } + oldestOffset, err := child.consumer.client.GetOffset(child.topic, child.partition, OffsetOldest) + if err != nil { + return err + } + + switch { + case offset == OffsetNewest: + child.offset = newestOffset + case offset == OffsetOldest: + child.offset = oldestOffset + case offset >= oldestOffset && offset <= newestOffset: + child.offset = offset + default: + return ErrOffsetOutOfRange + } + + return nil +} + +func (child *partitionConsumer) Messages() <-chan *ConsumerMessage { + return child.messages +} + +func (child *partitionConsumer) Errors() <-chan *ConsumerError { + return child.errors +} + +func (child *partitionConsumer) AsyncClose() { + // this triggers whatever broker owns this child to abandon it and close its trigger channel, which causes + // the dispatcher to exit its loop, which removes it from the consumer then closes its 'messages' and + // 'errors' channel (alternatively, if the child is already at the dispatcher for some reason, that will + // also just close itself) + close(child.dying) +} + +func (child *partitionConsumer) Close() error { + child.AsyncClose() + + go withRecover(func() { + for _ = range child.messages { + // drain + } + }) + + var errors ConsumerErrors + for err := range child.errors { + errors = append(errors, err) + } + + if len(errors) > 0 { + return errors + } + return nil +} + +func (child *partitionConsumer) HighWaterMarkOffset() int64 { + return atomic.LoadInt64(&child.highWaterMarkOffset) +} + +func (child *partitionConsumer) responseFeeder() { + var msgs []*ConsumerMessage + expiryTimer := time.NewTimer(child.conf.Consumer.MaxProcessingTime) + expireTimedOut := false + +feederLoop: + for response := range child.feeder { + msgs, child.responseResult = child.parseResponse(response) + + for i, msg := range msgs { + if !expiryTimer.Stop() && !expireTimedOut { + // expiryTimer was expired; clear out the waiting msg + <-expiryTimer.C + } + expiryTimer.Reset(child.conf.Consumer.MaxProcessingTime) + expireTimedOut = false + + select { + case child.messages <- msg: + case <-expiryTimer.C: + expireTimedOut = true + child.responseResult = errTimedOut + child.broker.acks.Done() + for _, msg = range msgs[i:] { + child.messages <- msg + } + child.broker.input <- child + continue feederLoop + } + } + + child.broker.acks.Done() + } + + close(child.messages) + close(child.errors) +} + +func (child *partitionConsumer) parseResponse(response *FetchResponse) ([]*ConsumerMessage, error) { + block := response.GetBlock(child.topic, child.partition) + if block == nil { + return nil, ErrIncompleteResponse + } + + if block.Err != ErrNoError { + return nil, block.Err + } + + if len(block.MsgSet.Messages) == 0 { + // We got no messages. If we got a trailing one then we need to ask for more data. + // Otherwise we just poll again and wait for one to be produced... + if block.MsgSet.PartialTrailingMessage { + if child.conf.Consumer.Fetch.Max > 0 && child.fetchSize == child.conf.Consumer.Fetch.Max { + // we can't ask for more data, we've hit the configured limit + child.sendError(ErrMessageTooLarge) + child.offset++ // skip this one so we can keep processing future messages + } else { + child.fetchSize *= 2 + if child.conf.Consumer.Fetch.Max > 0 && child.fetchSize > child.conf.Consumer.Fetch.Max { + child.fetchSize = child.conf.Consumer.Fetch.Max + } + } + } + + return nil, nil + } + + // we got messages, reset our fetch size in case it was increased for a previous request + child.fetchSize = child.conf.Consumer.Fetch.Default + atomic.StoreInt64(&child.highWaterMarkOffset, block.HighWaterMarkOffset) + + incomplete := false + prelude := true + var messages []*ConsumerMessage + for _, msgBlock := range block.MsgSet.Messages { + + for _, msg := range msgBlock.Messages() { + offset := msg.Offset + if msg.Msg.Version >= 1 { + baseOffset := msgBlock.Offset - msgBlock.Messages()[len(msgBlock.Messages())-1].Offset + offset += baseOffset + } + if prelude && offset < child.offset { + continue + } + prelude = false + + if offset >= child.offset { + messages = append(messages, &ConsumerMessage{ + Topic: child.topic, + Partition: child.partition, + Key: msg.Msg.Key, + Value: msg.Msg.Value, + Offset: offset, + Timestamp: msg.Msg.Timestamp, + }) + child.offset = offset + 1 + } else { + incomplete = true + } + } + + } + + if incomplete || len(messages) == 0 { + return nil, ErrIncompleteResponse + } + return messages, nil +} + +// brokerConsumer + +type brokerConsumer struct { + consumer *consumer + broker *Broker + input chan *partitionConsumer + newSubscriptions chan []*partitionConsumer + wait chan none + subscriptions map[*partitionConsumer]none + acks sync.WaitGroup + refs int +} + +func (c *consumer) newBrokerConsumer(broker *Broker) *brokerConsumer { + bc := &brokerConsumer{ + consumer: c, + broker: broker, + input: make(chan *partitionConsumer), + newSubscriptions: make(chan []*partitionConsumer), + wait: make(chan none), + subscriptions: make(map[*partitionConsumer]none), + refs: 0, + } + + go withRecover(bc.subscriptionManager) + go withRecover(bc.subscriptionConsumer) + + return bc +} + +func (bc *brokerConsumer) subscriptionManager() { + var buffer []*partitionConsumer + + // The subscriptionManager constantly accepts new subscriptions on `input` (even when the main subscriptionConsumer + // goroutine is in the middle of a network request) and batches it up. The main worker goroutine picks + // up a batch of new subscriptions between every network request by reading from `newSubscriptions`, so we give + // it nil if no new subscriptions are available. We also write to `wait` only when new subscriptions is available, + // so the main goroutine can block waiting for work if it has none. + for { + if len(buffer) > 0 { + select { + case event, ok := <-bc.input: + if !ok { + goto done + } + buffer = append(buffer, event) + case bc.newSubscriptions <- buffer: + buffer = nil + case bc.wait <- none{}: + } + } else { + select { + case event, ok := <-bc.input: + if !ok { + goto done + } + buffer = append(buffer, event) + case bc.newSubscriptions <- nil: + } + } + } + +done: + close(bc.wait) + if len(buffer) > 0 { + bc.newSubscriptions <- buffer + } + close(bc.newSubscriptions) +} + +func (bc *brokerConsumer) subscriptionConsumer() { + <-bc.wait // wait for our first piece of work + + // the subscriptionConsumer ensures we will get nil right away if no new subscriptions is available + for newSubscriptions := range bc.newSubscriptions { + bc.updateSubscriptions(newSubscriptions) + + if len(bc.subscriptions) == 0 { + // We're about to be shut down or we're about to receive more subscriptions. + // Either way, the signal just hasn't propagated to our goroutine yet. + <-bc.wait + continue + } + + response, err := bc.fetchNewMessages() + + if err != nil { + Logger.Printf("consumer/broker/%d disconnecting due to error processing FetchRequest: %s\n", bc.broker.ID(), err) + bc.abort(err) + return + } + + bc.acks.Add(len(bc.subscriptions)) + for child := range bc.subscriptions { + child.feeder <- response + } + bc.acks.Wait() + bc.handleResponses() + } +} + +func (bc *brokerConsumer) updateSubscriptions(newSubscriptions []*partitionConsumer) { + for _, child := range newSubscriptions { + bc.subscriptions[child] = none{} + Logger.Printf("consumer/broker/%d added subscription to %s/%d\n", bc.broker.ID(), child.topic, child.partition) + } + + for child := range bc.subscriptions { + select { + case <-child.dying: + Logger.Printf("consumer/broker/%d closed dead subscription to %s/%d\n", bc.broker.ID(), child.topic, child.partition) + close(child.trigger) + delete(bc.subscriptions, child) + default: + break + } + } +} + +func (bc *brokerConsumer) handleResponses() { + // handles the response codes left for us by our subscriptions, and abandons ones that have been closed + for child := range bc.subscriptions { + result := child.responseResult + child.responseResult = nil + + switch result { + case nil: + break + case errTimedOut: + Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because consuming was taking too long\n", + bc.broker.ID(), child.topic, child.partition) + delete(bc.subscriptions, child) + case ErrOffsetOutOfRange: + // there's no point in retrying this it will just fail the same way again + // shut it down and force the user to choose what to do + child.sendError(result) + Logger.Printf("consumer/%s/%d shutting down because %s\n", child.topic, child.partition, result) + close(child.trigger) + delete(bc.subscriptions, child) + case ErrUnknownTopicOrPartition, ErrNotLeaderForPartition, ErrLeaderNotAvailable, ErrReplicaNotAvailable: + // not an error, but does need redispatching + Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because %s\n", + bc.broker.ID(), child.topic, child.partition, result) + child.trigger <- none{} + delete(bc.subscriptions, child) + default: + // dunno, tell the user and try redispatching + child.sendError(result) + Logger.Printf("consumer/broker/%d abandoned subscription to %s/%d because %s\n", + bc.broker.ID(), child.topic, child.partition, result) + child.trigger <- none{} + delete(bc.subscriptions, child) + } + } +} + +func (bc *brokerConsumer) abort(err error) { + bc.consumer.abandonBrokerConsumer(bc) + _ = bc.broker.Close() // we don't care about the error this might return, we already have one + + for child := range bc.subscriptions { + child.sendError(err) + child.trigger <- none{} + } + + for newSubscriptions := range bc.newSubscriptions { + if len(newSubscriptions) == 0 { + <-bc.wait + continue + } + for _, child := range newSubscriptions { + child.sendError(err) + child.trigger <- none{} + } + } +} + +func (bc *brokerConsumer) fetchNewMessages() (*FetchResponse, error) { + request := &FetchRequest{ + MinBytes: bc.consumer.conf.Consumer.Fetch.Min, + MaxWaitTime: int32(bc.consumer.conf.Consumer.MaxWaitTime / time.Millisecond), + } + if bc.consumer.conf.Version.IsAtLeast(V0_10_0_0) { + request.Version = 2 + } + + for child := range bc.subscriptions { + request.AddBlock(child.topic, child.partition, child.offset, child.fetchSize) + } + + return bc.broker.Fetch(request) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_group_members.go b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_group_members.go new file mode 100644 index 00000000..9d92d350 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_group_members.go @@ -0,0 +1,94 @@ +package sarama + +type ConsumerGroupMemberMetadata struct { + Version int16 + Topics []string + UserData []byte +} + +func (m *ConsumerGroupMemberMetadata) encode(pe packetEncoder) error { + pe.putInt16(m.Version) + + if err := pe.putStringArray(m.Topics); err != nil { + return err + } + + if err := pe.putBytes(m.UserData); err != nil { + return err + } + + return nil +} + +func (m *ConsumerGroupMemberMetadata) decode(pd packetDecoder) (err error) { + if m.Version, err = pd.getInt16(); err != nil { + return + } + + if m.Topics, err = pd.getStringArray(); err != nil { + return + } + + if m.UserData, err = pd.getBytes(); err != nil { + return + } + + return nil +} + +type ConsumerGroupMemberAssignment struct { + Version int16 + Topics map[string][]int32 + UserData []byte +} + +func (m *ConsumerGroupMemberAssignment) encode(pe packetEncoder) error { + pe.putInt16(m.Version) + + if err := pe.putArrayLength(len(m.Topics)); err != nil { + return err + } + + for topic, partitions := range m.Topics { + if err := pe.putString(topic); err != nil { + return err + } + if err := pe.putInt32Array(partitions); err != nil { + return err + } + } + + if err := pe.putBytes(m.UserData); err != nil { + return err + } + + return nil +} + +func (m *ConsumerGroupMemberAssignment) decode(pd packetDecoder) (err error) { + if m.Version, err = pd.getInt16(); err != nil { + return + } + + var topicLen int + if topicLen, err = pd.getArrayLength(); err != nil { + return + } + + m.Topics = make(map[string][]int32, topicLen) + for i := 0; i < topicLen; i++ { + var topic string + if topic, err = pd.getString(); err != nil { + return + } + if m.Topics[topic], err = pd.getInt32Array(); err != nil { + return + } + } + + if m.UserData, err = pd.getBytes(); err != nil { + return + } + + return nil +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_group_members_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_group_members_test.go new file mode 100644 index 00000000..164e07ef --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_group_members_test.go @@ -0,0 +1,73 @@ +package sarama + +import ( + "bytes" + "reflect" + "testing" +) + +var ( + groupMemberMetadata = []byte{ + 0, 1, // Version + 0, 0, 0, 2, // Topic array length + 0, 3, 'o', 'n', 'e', // Topic one + 0, 3, 't', 'w', 'o', // Topic two + 0, 0, 0, 3, 0x01, 0x02, 0x03, // Userdata + } + groupMemberAssignment = []byte{ + 0, 1, // Version + 0, 0, 0, 1, // Topic array length + 0, 3, 'o', 'n', 'e', // Topic one + 0, 0, 0, 3, // Topic one, partition array length + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 4, // 0, 2, 4 + 0, 0, 0, 3, 0x01, 0x02, 0x03, // Userdata + } +) + +func TestConsumerGroupMemberMetadata(t *testing.T) { + meta := &ConsumerGroupMemberMetadata{ + Version: 1, + Topics: []string{"one", "two"}, + UserData: []byte{0x01, 0x02, 0x03}, + } + + buf, err := encode(meta, nil) + if err != nil { + t.Error("Failed to encode data", err) + } else if !bytes.Equal(groupMemberMetadata, buf) { + t.Errorf("Encoded data does not match expectation\nexpected: %v\nactual: %v", groupMemberMetadata, buf) + } + + meta2 := new(ConsumerGroupMemberMetadata) + err = decode(buf, meta2) + if err != nil { + t.Error("Failed to decode data", err) + } else if !reflect.DeepEqual(meta, meta2) { + t.Errorf("Encoded data does not match expectation\nexpected: %v\nactual: %v", meta, meta2) + } +} + +func TestConsumerGroupMemberAssignment(t *testing.T) { + amt := &ConsumerGroupMemberAssignment{ + Version: 1, + Topics: map[string][]int32{ + "one": []int32{0, 2, 4}, + }, + UserData: []byte{0x01, 0x02, 0x03}, + } + + buf, err := encode(amt, nil) + if err != nil { + t.Error("Failed to encode data", err) + } else if !bytes.Equal(groupMemberAssignment, buf) { + t.Errorf("Encoded data does not match expectation\nexpected: %v\nactual: %v", groupMemberAssignment, buf) + } + + amt2 := new(ConsumerGroupMemberAssignment) + err = decode(buf, amt2) + if err != nil { + t.Error("Failed to decode data", err) + } else if !reflect.DeepEqual(amt, amt2) { + t.Errorf("Encoded data does not match expectation\nexpected: %v\nactual: %v", amt, amt2) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_request.go new file mode 100644 index 00000000..483be335 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_request.go @@ -0,0 +1,26 @@ +package sarama + +type ConsumerMetadataRequest struct { + ConsumerGroup string +} + +func (r *ConsumerMetadataRequest) encode(pe packetEncoder) error { + return pe.putString(r.ConsumerGroup) +} + +func (r *ConsumerMetadataRequest) decode(pd packetDecoder, version int16) (err error) { + r.ConsumerGroup, err = pd.getString() + return err +} + +func (r *ConsumerMetadataRequest) key() int16 { + return 10 +} + +func (r *ConsumerMetadataRequest) version() int16 { + return 0 +} + +func (r *ConsumerMetadataRequest) requiredVersion() KafkaVersion { + return V0_8_2_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_request_test.go new file mode 100644 index 00000000..4509631a --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_request_test.go @@ -0,0 +1,19 @@ +package sarama + +import "testing" + +var ( + consumerMetadataRequestEmpty = []byte{ + 0x00, 0x00} + + consumerMetadataRequestString = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r'} +) + +func TestConsumerMetadataRequest(t *testing.T) { + request := new(ConsumerMetadataRequest) + testRequest(t, "empty string", request, consumerMetadataRequestEmpty) + + request.ConsumerGroup = "foobar" + testRequest(t, "with string", request, consumerMetadataRequestString) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_response.go new file mode 100644 index 00000000..6b9632bb --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_response.go @@ -0,0 +1,85 @@ +package sarama + +import ( + "net" + "strconv" +) + +type ConsumerMetadataResponse struct { + Err KError + Coordinator *Broker + CoordinatorID int32 // deprecated: use Coordinator.ID() + CoordinatorHost string // deprecated: use Coordinator.Addr() + CoordinatorPort int32 // deprecated: use Coordinator.Addr() +} + +func (r *ConsumerMetadataResponse) decode(pd packetDecoder, version int16) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + r.Err = KError(tmp) + + coordinator := new(Broker) + if err := coordinator.decode(pd); err != nil { + return err + } + if coordinator.addr == ":0" { + return nil + } + r.Coordinator = coordinator + + // this can all go away in 2.0, but we have to fill in deprecated fields to maintain + // backwards compatibility + host, portstr, err := net.SplitHostPort(r.Coordinator.Addr()) + if err != nil { + return err + } + port, err := strconv.ParseInt(portstr, 10, 32) + if err != nil { + return err + } + r.CoordinatorID = r.Coordinator.ID() + r.CoordinatorHost = host + r.CoordinatorPort = int32(port) + + return nil +} + +func (r *ConsumerMetadataResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + if r.Coordinator != nil { + host, portstr, err := net.SplitHostPort(r.Coordinator.Addr()) + if err != nil { + return err + } + port, err := strconv.ParseInt(portstr, 10, 32) + if err != nil { + return err + } + pe.putInt32(r.Coordinator.ID()) + if err := pe.putString(host); err != nil { + return err + } + pe.putInt32(int32(port)) + return nil + } + pe.putInt32(r.CoordinatorID) + if err := pe.putString(r.CoordinatorHost); err != nil { + return err + } + pe.putInt32(r.CoordinatorPort) + return nil +} + +func (r *ConsumerMetadataResponse) key() int16 { + return 10 +} + +func (r *ConsumerMetadataResponse) version() int16 { + return 0 +} + +func (r *ConsumerMetadataResponse) requiredVersion() KafkaVersion { + return V0_8_2_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_response_test.go new file mode 100644 index 00000000..b748784d --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_metadata_response_test.go @@ -0,0 +1,35 @@ +package sarama + +import "testing" + +var ( + consumerMetadataResponseError = []byte{ + 0x00, 0x0E, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} + + consumerMetadataResponseSuccess = []byte{ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0xAB, + 0x00, 0x03, 'f', 'o', 'o', + 0x00, 0x00, 0xCC, 0xDD} +) + +func TestConsumerMetadataResponseError(t *testing.T) { + response := ConsumerMetadataResponse{Err: ErrOffsetsLoadInProgress} + testResponse(t, "error", &response, consumerMetadataResponseError) +} + +func TestConsumerMetadataResponseSuccess(t *testing.T) { + broker := NewBroker("foo:52445") + broker.id = 0xAB + response := ConsumerMetadataResponse{ + Coordinator: broker, + CoordinatorID: 0xAB, + CoordinatorHost: "foo", + CoordinatorPort: 0xCCDD, + Err: ErrNoError, + } + testResponse(t, "success", &response, consumerMetadataResponseSuccess) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_test.go new file mode 100644 index 00000000..387ede31 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/consumer_test.go @@ -0,0 +1,854 @@ +package sarama + +import ( + "log" + "os" + "os/signal" + "sync" + "testing" + "time" +) + +var testMsg = StringEncoder("Foo") + +// If a particular offset is provided then messages are consumed starting from +// that offset. +func TestConsumerOffsetManual(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + + mockFetchResponse := NewMockFetchResponse(t, 1) + for i := 0; i < 10; i++ { + mockFetchResponse.SetMessage("my_topic", 0, int64(i+1234), testMsg) + } + + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 0). + SetOffset("my_topic", 0, OffsetNewest, 2345), + "FetchRequest": mockFetchResponse, + }) + + // When + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + consumer, err := master.ConsumePartition("my_topic", 0, 1234) + if err != nil { + t.Fatal(err) + } + + // Then: messages starting from offset 1234 are consumed. + for i := 0; i < 10; i++ { + select { + case message := <-consumer.Messages(): + assertMessageOffset(t, message, int64(i+1234)) + case err := <-consumer.Errors(): + t.Error(err) + } + } + + safeClose(t, consumer) + safeClose(t, master) + broker0.Close() +} + +// If `OffsetNewest` is passed as the initial offset then the first consumed +// message is indeed corresponds to the offset that broker claims to be the +// newest in its metadata response. +func TestConsumerOffsetNewest(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetNewest, 10). + SetOffset("my_topic", 0, OffsetOldest, 7), + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 9, testMsg). + SetMessage("my_topic", 0, 10, testMsg). + SetMessage("my_topic", 0, 11, testMsg). + SetHighWaterMark("my_topic", 0, 14), + }) + + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When + consumer, err := master.ConsumePartition("my_topic", 0, OffsetNewest) + if err != nil { + t.Fatal(err) + } + + // Then + assertMessageOffset(t, <-consumer.Messages(), 10) + if hwmo := consumer.HighWaterMarkOffset(); hwmo != 14 { + t.Errorf("Expected high water mark offset 14, found %d", hwmo) + } + + safeClose(t, consumer) + safeClose(t, master) + broker0.Close() +} + +// It is possible to close a partition consumer and create the same anew. +func TestConsumerRecreate(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 0). + SetOffset("my_topic", 0, OffsetNewest, 1000), + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 10, testMsg), + }) + + c, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + pc, err := c.ConsumePartition("my_topic", 0, 10) + if err != nil { + t.Fatal(err) + } + assertMessageOffset(t, <-pc.Messages(), 10) + + // When + safeClose(t, pc) + pc, err = c.ConsumePartition("my_topic", 0, 10) + if err != nil { + t.Fatal(err) + } + + // Then + assertMessageOffset(t, <-pc.Messages(), 10) + + safeClose(t, pc) + safeClose(t, c) + broker0.Close() +} + +// An attempt to consume the same partition twice should fail. +func TestConsumerDuplicate(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 0). + SetOffset("my_topic", 0, OffsetNewest, 1000), + "FetchRequest": NewMockFetchResponse(t, 1), + }) + + config := NewConfig() + config.ChannelBufferSize = 0 + c, err := NewConsumer([]string{broker0.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + pc1, err := c.ConsumePartition("my_topic", 0, 0) + if err != nil { + t.Fatal(err) + } + + // When + pc2, err := c.ConsumePartition("my_topic", 0, 0) + + // Then + if pc2 != nil || err != ConfigurationError("That topic/partition is already being consumed") { + t.Fatal("A partition cannot be consumed twice at the same time") + } + + safeClose(t, pc1) + safeClose(t, c) + broker0.Close() +} + +// If consumer fails to refresh metadata it keeps retrying with frequency +// specified by `Config.Consumer.Retry.Backoff`. +func TestConsumerLeaderRefreshError(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 100) + + // Stage 1: my_topic/0 served by broker0 + Logger.Printf(" STAGE 1") + + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 123). + SetOffset("my_topic", 0, OffsetNewest, 1000), + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 123, testMsg), + }) + + config := NewConfig() + config.Net.ReadTimeout = 100 * time.Millisecond + config.Consumer.Retry.Backoff = 200 * time.Millisecond + config.Consumer.Return.Errors = true + config.Metadata.Retry.Max = 0 + c, err := NewConsumer([]string{broker0.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + pc, err := c.ConsumePartition("my_topic", 0, OffsetOldest) + if err != nil { + t.Fatal(err) + } + + assertMessageOffset(t, <-pc.Messages(), 123) + + // Stage 2: broker0 says that it is no longer the leader for my_topic/0, + // but the requests to retrieve metadata fail with network timeout. + Logger.Printf(" STAGE 2") + + fetchResponse2 := &FetchResponse{} + fetchResponse2.AddError("my_topic", 0, ErrNotLeaderForPartition) + + broker0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": NewMockWrapper(fetchResponse2), + }) + + if consErr := <-pc.Errors(); consErr.Err != ErrOutOfBrokers { + t.Errorf("Unexpected error: %v", consErr.Err) + } + + // Stage 3: finally the metadata returned by broker0 tells that broker1 is + // a new leader for my_topic/0. Consumption resumes. + + Logger.Printf(" STAGE 3") + + broker1 := NewMockBroker(t, 101) + + broker1.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 124, testMsg), + }) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetBroker(broker1.Addr(), broker1.BrokerID()). + SetLeader("my_topic", 0, broker1.BrokerID()), + }) + + assertMessageOffset(t, <-pc.Messages(), 124) + + safeClose(t, pc) + safeClose(t, c) + broker1.Close() + broker0.Close() +} + +func TestConsumerInvalidTopic(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 100) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()), + }) + + c, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When + pc, err := c.ConsumePartition("my_topic", 0, OffsetOldest) + + // Then + if pc != nil || err != ErrUnknownTopicOrPartition { + t.Errorf("Should fail with, err=%v", err) + } + + safeClose(t, c) + broker0.Close() +} + +// Nothing bad happens if a partition consumer that has no leader assigned at +// the moment is closed. +func TestConsumerClosePartitionWithoutLeader(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 100) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 123). + SetOffset("my_topic", 0, OffsetNewest, 1000), + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 123, testMsg), + }) + + config := NewConfig() + config.Net.ReadTimeout = 100 * time.Millisecond + config.Consumer.Retry.Backoff = 100 * time.Millisecond + config.Consumer.Return.Errors = true + config.Metadata.Retry.Max = 0 + c, err := NewConsumer([]string{broker0.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + pc, err := c.ConsumePartition("my_topic", 0, OffsetOldest) + if err != nil { + t.Fatal(err) + } + + assertMessageOffset(t, <-pc.Messages(), 123) + + // broker0 says that it is no longer the leader for my_topic/0, but the + // requests to retrieve metadata fail with network timeout. + fetchResponse2 := &FetchResponse{} + fetchResponse2.AddError("my_topic", 0, ErrNotLeaderForPartition) + + broker0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": NewMockWrapper(fetchResponse2), + }) + + // When + if consErr := <-pc.Errors(); consErr.Err != ErrOutOfBrokers { + t.Errorf("Unexpected error: %v", consErr.Err) + } + + // Then: the partition consumer can be closed without any problem. + safeClose(t, pc) + safeClose(t, c) + broker0.Close() +} + +// If the initial offset passed on partition consumer creation is out of the +// actual offset range for the partition, then the partition consumer stops +// immediately closing its output channels. +func TestConsumerShutsDownOutOfRange(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + fetchResponse := new(FetchResponse) + fetchResponse.AddError("my_topic", 0, ErrOffsetOutOfRange) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetNewest, 1234). + SetOffset("my_topic", 0, OffsetOldest, 7), + "FetchRequest": NewMockWrapper(fetchResponse), + }) + + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When + consumer, err := master.ConsumePartition("my_topic", 0, 101) + if err != nil { + t.Fatal(err) + } + + // Then: consumer should shut down closing its messages and errors channels. + if _, ok := <-consumer.Messages(); ok { + t.Error("Expected the consumer to shut down") + } + safeClose(t, consumer) + + safeClose(t, master) + broker0.Close() +} + +// If a fetch response contains messages with offsets that are smaller then +// requested, then such messages are ignored. +func TestConsumerExtraOffsets(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + fetchResponse1 := &FetchResponse{} + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 1) + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 2) + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 3) + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 4) + fetchResponse2 := &FetchResponse{} + fetchResponse2.AddError("my_topic", 0, ErrNoError) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetNewest, 1234). + SetOffset("my_topic", 0, OffsetOldest, 0), + "FetchRequest": NewMockSequence(fetchResponse1, fetchResponse2), + }) + + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When + consumer, err := master.ConsumePartition("my_topic", 0, 3) + if err != nil { + t.Fatal(err) + } + + // Then: messages with offsets 1 and 2 are not returned even though they + // are present in the response. + assertMessageOffset(t, <-consumer.Messages(), 3) + assertMessageOffset(t, <-consumer.Messages(), 4) + + safeClose(t, consumer) + safeClose(t, master) + broker0.Close() +} + +// It is fine if offsets of fetched messages are not sequential (although +// strictly increasing!). +func TestConsumerNonSequentialOffsets(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + fetchResponse1 := &FetchResponse{} + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 5) + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 7) + fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 11) + fetchResponse2 := &FetchResponse{} + fetchResponse2.AddError("my_topic", 0, ErrNoError) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetNewest, 1234). + SetOffset("my_topic", 0, OffsetOldest, 0), + "FetchRequest": NewMockSequence(fetchResponse1, fetchResponse2), + }) + + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When + consumer, err := master.ConsumePartition("my_topic", 0, 3) + if err != nil { + t.Fatal(err) + } + + // Then: messages with offsets 1 and 2 are not returned even though they + // are present in the response. + assertMessageOffset(t, <-consumer.Messages(), 5) + assertMessageOffset(t, <-consumer.Messages(), 7) + assertMessageOffset(t, <-consumer.Messages(), 11) + + safeClose(t, consumer) + safeClose(t, master) + broker0.Close() +} + +// If leadership for a partition is changing then consumer resolves the new +// leader and switches to it. +func TestConsumerRebalancingMultiplePartitions(t *testing.T) { + // initial setup + seedBroker := NewMockBroker(t, 10) + leader0 := NewMockBroker(t, 0) + leader1 := NewMockBroker(t, 1) + + seedBroker.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(leader0.Addr(), leader0.BrokerID()). + SetBroker(leader1.Addr(), leader1.BrokerID()). + SetLeader("my_topic", 0, leader0.BrokerID()). + SetLeader("my_topic", 1, leader1.BrokerID()), + }) + + mockOffsetResponse1 := NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 0). + SetOffset("my_topic", 0, OffsetNewest, 1000). + SetOffset("my_topic", 1, OffsetOldest, 0). + SetOffset("my_topic", 1, OffsetNewest, 1000) + leader0.SetHandlerByMap(map[string]MockResponse{ + "OffsetRequest": mockOffsetResponse1, + "FetchRequest": NewMockFetchResponse(t, 1), + }) + leader1.SetHandlerByMap(map[string]MockResponse{ + "OffsetRequest": mockOffsetResponse1, + "FetchRequest": NewMockFetchResponse(t, 1), + }) + + // launch test goroutines + config := NewConfig() + config.Consumer.Retry.Backoff = 50 + master, err := NewConsumer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + // we expect to end up (eventually) consuming exactly ten messages on each partition + var wg sync.WaitGroup + for i := int32(0); i < 2; i++ { + consumer, err := master.ConsumePartition("my_topic", i, 0) + if err != nil { + t.Error(err) + } + + go func(c PartitionConsumer) { + for err := range c.Errors() { + t.Error(err) + } + }(consumer) + + wg.Add(1) + go func(partition int32, c PartitionConsumer) { + for i := 0; i < 10; i++ { + message := <-consumer.Messages() + if message.Offset != int64(i) { + t.Error("Incorrect message offset!", i, partition, message.Offset) + } + if message.Partition != partition { + t.Error("Incorrect message partition!") + } + } + safeClose(t, consumer) + wg.Done() + }(i, consumer) + } + + time.Sleep(50 * time.Millisecond) + Logger.Printf(" STAGE 1") + // Stage 1: + // * my_topic/0 -> leader0 serves 4 messages + // * my_topic/1 -> leader1 serves 0 messages + + mockFetchResponse := NewMockFetchResponse(t, 1) + for i := 0; i < 4; i++ { + mockFetchResponse.SetMessage("my_topic", 0, int64(i), testMsg) + } + leader0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": mockFetchResponse, + }) + + time.Sleep(50 * time.Millisecond) + Logger.Printf(" STAGE 2") + // Stage 2: + // * leader0 says that it is no longer serving my_topic/0 + // * seedBroker tells that leader1 is serving my_topic/0 now + + // seed broker tells that the new partition 0 leader is leader1 + seedBroker.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetLeader("my_topic", 0, leader1.BrokerID()). + SetLeader("my_topic", 1, leader1.BrokerID()), + }) + + // leader0 says no longer leader of partition 0 + fetchResponse := new(FetchResponse) + fetchResponse.AddError("my_topic", 0, ErrNotLeaderForPartition) + leader0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": NewMockWrapper(fetchResponse), + }) + + time.Sleep(50 * time.Millisecond) + Logger.Printf(" STAGE 3") + // Stage 3: + // * my_topic/0 -> leader1 serves 3 messages + // * my_topic/1 -> leader1 server 8 messages + + // leader1 provides 3 message on partition 0, and 8 messages on partition 1 + mockFetchResponse2 := NewMockFetchResponse(t, 2) + for i := 4; i < 7; i++ { + mockFetchResponse2.SetMessage("my_topic", 0, int64(i), testMsg) + } + for i := 0; i < 8; i++ { + mockFetchResponse2.SetMessage("my_topic", 1, int64(i), testMsg) + } + leader1.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": mockFetchResponse2, + }) + + time.Sleep(50 * time.Millisecond) + Logger.Printf(" STAGE 4") + // Stage 4: + // * my_topic/0 -> leader1 serves 3 messages + // * my_topic/1 -> leader1 tells that it is no longer the leader + // * seedBroker tells that leader0 is a new leader for my_topic/1 + + // metadata assigns 0 to leader1 and 1 to leader0 + seedBroker.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetLeader("my_topic", 0, leader1.BrokerID()). + SetLeader("my_topic", 1, leader0.BrokerID()), + }) + + // leader1 provides three more messages on partition0, says no longer leader of partition1 + mockFetchResponse3 := NewMockFetchResponse(t, 3). + SetMessage("my_topic", 0, int64(7), testMsg). + SetMessage("my_topic", 0, int64(8), testMsg). + SetMessage("my_topic", 0, int64(9), testMsg) + fetchResponse4 := new(FetchResponse) + fetchResponse4.AddError("my_topic", 1, ErrNotLeaderForPartition) + leader1.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": NewMockSequence(mockFetchResponse3, fetchResponse4), + }) + + // leader0 provides two messages on partition 1 + mockFetchResponse4 := NewMockFetchResponse(t, 2) + for i := 8; i < 10; i++ { + mockFetchResponse4.SetMessage("my_topic", 1, int64(i), testMsg) + } + leader0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": mockFetchResponse4, + }) + + wg.Wait() + safeClose(t, master) + leader1.Close() + leader0.Close() + seedBroker.Close() +} + +// When two partitions have the same broker as the leader, if one partition +// consumer channel buffer is full then that does not affect the ability to +// read messages by the other consumer. +func TestConsumerInterleavedClose(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 0) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()). + SetLeader("my_topic", 1, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 1000). + SetOffset("my_topic", 0, OffsetNewest, 1100). + SetOffset("my_topic", 1, OffsetOldest, 2000). + SetOffset("my_topic", 1, OffsetNewest, 2100), + "FetchRequest": NewMockFetchResponse(t, 1). + SetMessage("my_topic", 0, 1000, testMsg). + SetMessage("my_topic", 0, 1001, testMsg). + SetMessage("my_topic", 0, 1002, testMsg). + SetMessage("my_topic", 1, 2000, testMsg), + }) + + config := NewConfig() + config.ChannelBufferSize = 0 + master, err := NewConsumer([]string{broker0.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + c0, err := master.ConsumePartition("my_topic", 0, 1000) + if err != nil { + t.Fatal(err) + } + + c1, err := master.ConsumePartition("my_topic", 1, 2000) + if err != nil { + t.Fatal(err) + } + + // When/Then: we can read from partition 0 even if nobody reads from partition 1 + assertMessageOffset(t, <-c0.Messages(), 1000) + assertMessageOffset(t, <-c0.Messages(), 1001) + assertMessageOffset(t, <-c0.Messages(), 1002) + + safeClose(t, c1) + safeClose(t, c0) + safeClose(t, master) + broker0.Close() +} + +func TestConsumerBounceWithReferenceOpen(t *testing.T) { + broker0 := NewMockBroker(t, 0) + broker0Addr := broker0.Addr() + broker1 := NewMockBroker(t, 1) + + mockMetadataResponse := NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetBroker(broker1.Addr(), broker1.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()). + SetLeader("my_topic", 1, broker1.BrokerID()) + + mockOffsetResponse := NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetOldest, 1000). + SetOffset("my_topic", 0, OffsetNewest, 1100). + SetOffset("my_topic", 1, OffsetOldest, 2000). + SetOffset("my_topic", 1, OffsetNewest, 2100) + + mockFetchResponse := NewMockFetchResponse(t, 1) + for i := 0; i < 10; i++ { + mockFetchResponse.SetMessage("my_topic", 0, int64(1000+i), testMsg) + mockFetchResponse.SetMessage("my_topic", 1, int64(2000+i), testMsg) + } + + broker0.SetHandlerByMap(map[string]MockResponse{ + "OffsetRequest": mockOffsetResponse, + "FetchRequest": mockFetchResponse, + }) + broker1.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": mockMetadataResponse, + "OffsetRequest": mockOffsetResponse, + "FetchRequest": mockFetchResponse, + }) + + config := NewConfig() + config.Consumer.Return.Errors = true + config.Consumer.Retry.Backoff = 100 * time.Millisecond + config.ChannelBufferSize = 1 + master, err := NewConsumer([]string{broker1.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + c0, err := master.ConsumePartition("my_topic", 0, 1000) + if err != nil { + t.Fatal(err) + } + + c1, err := master.ConsumePartition("my_topic", 1, 2000) + if err != nil { + t.Fatal(err) + } + + // read messages from both partition to make sure that both brokers operate + // normally. + assertMessageOffset(t, <-c0.Messages(), 1000) + assertMessageOffset(t, <-c1.Messages(), 2000) + + // Simulate broker shutdown. Note that metadata response does not change, + // that is the leadership does not move to another broker. So partition + // consumer will keep retrying to restore the connection with the broker. + broker0.Close() + + // Make sure that while the partition/0 leader is down, consumer/partition/1 + // is capable of pulling messages from broker1. + for i := 1; i < 7; i++ { + offset := (<-c1.Messages()).Offset + if offset != int64(2000+i) { + t.Errorf("Expected offset %d from consumer/partition/1", int64(2000+i)) + } + } + + // Bring broker0 back to service. + broker0 = NewMockBrokerAddr(t, 0, broker0Addr) + broker0.SetHandlerByMap(map[string]MockResponse{ + "FetchRequest": mockFetchResponse, + }) + + // Read the rest of messages from both partitions. + for i := 7; i < 10; i++ { + assertMessageOffset(t, <-c1.Messages(), int64(2000+i)) + } + for i := 1; i < 10; i++ { + assertMessageOffset(t, <-c0.Messages(), int64(1000+i)) + } + + select { + case <-c0.Errors(): + default: + t.Errorf("Partition consumer should have detected broker restart") + } + + safeClose(t, c1) + safeClose(t, c0) + safeClose(t, master) + broker0.Close() + broker1.Close() +} + +func TestConsumerOffsetOutOfRange(t *testing.T) { + // Given + broker0 := NewMockBroker(t, 2) + broker0.SetHandlerByMap(map[string]MockResponse{ + "MetadataRequest": NewMockMetadataResponse(t). + SetBroker(broker0.Addr(), broker0.BrokerID()). + SetLeader("my_topic", 0, broker0.BrokerID()), + "OffsetRequest": NewMockOffsetResponse(t). + SetOffset("my_topic", 0, OffsetNewest, 1234). + SetOffset("my_topic", 0, OffsetOldest, 2345), + }) + + master, err := NewConsumer([]string{broker0.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + // When/Then + if _, err := master.ConsumePartition("my_topic", 0, 0); err != ErrOffsetOutOfRange { + t.Fatal("Should return ErrOffsetOutOfRange, got:", err) + } + if _, err := master.ConsumePartition("my_topic", 0, 3456); err != ErrOffsetOutOfRange { + t.Fatal("Should return ErrOffsetOutOfRange, got:", err) + } + if _, err := master.ConsumePartition("my_topic", 0, -3); err != ErrOffsetOutOfRange { + t.Fatal("Should return ErrOffsetOutOfRange, got:", err) + } + + safeClose(t, master) + broker0.Close() +} + +func assertMessageOffset(t *testing.T, msg *ConsumerMessage, expectedOffset int64) { + if msg.Offset != expectedOffset { + t.Errorf("Incorrect message offset: expected=%d, actual=%d", expectedOffset, msg.Offset) + } +} + +// This example shows how to use the consumer to read messages +// from a single partition. +func ExampleConsumer() { + consumer, err := NewConsumer([]string{"localhost:9092"}, nil) + if err != nil { + panic(err) + } + + defer func() { + if err := consumer.Close(); err != nil { + log.Fatalln(err) + } + }() + + partitionConsumer, err := consumer.ConsumePartition("my_topic", 0, OffsetNewest) + if err != nil { + panic(err) + } + + defer func() { + if err := partitionConsumer.Close(); err != nil { + log.Fatalln(err) + } + }() + + // Trap SIGINT to trigger a shutdown. + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Interrupt) + + consumed := 0 +ConsumerLoop: + for { + select { + case msg := <-partitionConsumer.Messages(): + log.Printf("Consumed message offset %d\n", msg.Offset) + consumed++ + case <-signals: + break ConsumerLoop + } + } + + log.Printf("Consumed: %d\n", consumed) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/crc32_field.go b/vendor/src/gopkg.in/Shopify/sarama.v1/crc32_field.go new file mode 100644 index 00000000..5c286079 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/crc32_field.go @@ -0,0 +1,36 @@ +package sarama + +import ( + "encoding/binary" + + "github.com/klauspost/crc32" +) + +// crc32Field implements the pushEncoder and pushDecoder interfaces for calculating CRC32s. +type crc32Field struct { + startOffset int +} + +func (c *crc32Field) saveOffset(in int) { + c.startOffset = in +} + +func (c *crc32Field) reserveLength() int { + return 4 +} + +func (c *crc32Field) run(curOffset int, buf []byte) error { + crc := crc32.ChecksumIEEE(buf[c.startOffset+4 : curOffset]) + binary.BigEndian.PutUint32(buf[c.startOffset:], crc) + return nil +} + +func (c *crc32Field) check(curOffset int, buf []byte) error { + crc := crc32.ChecksumIEEE(buf[c.startOffset+4 : curOffset]) + + if crc != binary.BigEndian.Uint32(buf[c.startOffset:]) { + return PacketDecodingError{"CRC didn't match"} + } + + return nil +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_request.go new file mode 100644 index 00000000..1fb35677 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_request.go @@ -0,0 +1,30 @@ +package sarama + +type DescribeGroupsRequest struct { + Groups []string +} + +func (r *DescribeGroupsRequest) encode(pe packetEncoder) error { + return pe.putStringArray(r.Groups) +} + +func (r *DescribeGroupsRequest) decode(pd packetDecoder, version int16) (err error) { + r.Groups, err = pd.getStringArray() + return +} + +func (r *DescribeGroupsRequest) key() int16 { + return 15 +} + +func (r *DescribeGroupsRequest) version() int16 { + return 0 +} + +func (r *DescribeGroupsRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} + +func (r *DescribeGroupsRequest) AddGroup(group string) { + r.Groups = append(r.Groups, group) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_request_test.go new file mode 100644 index 00000000..7d45f3fe --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_request_test.go @@ -0,0 +1,34 @@ +package sarama + +import "testing" + +var ( + emptyDescribeGroupsRequest = []byte{0, 0, 0, 0} + + singleDescribeGroupsRequest = []byte{ + 0, 0, 0, 1, // 1 group + 0, 3, 'f', 'o', 'o', // group name: foo + } + + doubleDescribeGroupsRequest = []byte{ + 0, 0, 0, 2, // 2 groups + 0, 3, 'f', 'o', 'o', // group name: foo + 0, 3, 'b', 'a', 'r', // group name: foo + } +) + +func TestDescribeGroupsRequest(t *testing.T) { + var request *DescribeGroupsRequest + + request = new(DescribeGroupsRequest) + testRequest(t, "no groups", request, emptyDescribeGroupsRequest) + + request = new(DescribeGroupsRequest) + request.AddGroup("foo") + testRequest(t, "one group", request, singleDescribeGroupsRequest) + + request = new(DescribeGroupsRequest) + request.AddGroup("foo") + request.AddGroup("bar") + testRequest(t, "two groups", request, doubleDescribeGroupsRequest) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_response.go new file mode 100644 index 00000000..d2c2071e --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_response.go @@ -0,0 +1,186 @@ +package sarama + +type DescribeGroupsResponse struct { + Groups []*GroupDescription +} + +func (r *DescribeGroupsResponse) encode(pe packetEncoder) error { + if err := pe.putArrayLength(len(r.Groups)); err != nil { + return err + } + + for _, groupDescription := range r.Groups { + if err := groupDescription.encode(pe); err != nil { + return err + } + } + + return nil +} + +func (r *DescribeGroupsResponse) decode(pd packetDecoder, version int16) (err error) { + n, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Groups = make([]*GroupDescription, n) + for i := 0; i < n; i++ { + r.Groups[i] = new(GroupDescription) + if err := r.Groups[i].decode(pd); err != nil { + return err + } + } + + return nil +} + +func (r *DescribeGroupsResponse) key() int16 { + return 15 +} + +func (r *DescribeGroupsResponse) version() int16 { + return 0 +} + +func (r *DescribeGroupsResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} + +type GroupDescription struct { + Err KError + GroupId string + State string + ProtocolType string + Protocol string + Members map[string]*GroupMemberDescription +} + +func (gd *GroupDescription) encode(pe packetEncoder) error { + pe.putInt16(int16(gd.Err)) + + if err := pe.putString(gd.GroupId); err != nil { + return err + } + if err := pe.putString(gd.State); err != nil { + return err + } + if err := pe.putString(gd.ProtocolType); err != nil { + return err + } + if err := pe.putString(gd.Protocol); err != nil { + return err + } + + if err := pe.putArrayLength(len(gd.Members)); err != nil { + return err + } + + for memberId, groupMemberDescription := range gd.Members { + if err := pe.putString(memberId); err != nil { + return err + } + if err := groupMemberDescription.encode(pe); err != nil { + return err + } + } + + return nil +} + +func (gd *GroupDescription) decode(pd packetDecoder) (err error) { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + gd.Err = KError(kerr) + } + + if gd.GroupId, err = pd.getString(); err != nil { + return + } + if gd.State, err = pd.getString(); err != nil { + return + } + if gd.ProtocolType, err = pd.getString(); err != nil { + return + } + if gd.Protocol, err = pd.getString(); err != nil { + return + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + if n == 0 { + return nil + } + + gd.Members = make(map[string]*GroupMemberDescription) + for i := 0; i < n; i++ { + memberId, err := pd.getString() + if err != nil { + return err + } + + gd.Members[memberId] = new(GroupMemberDescription) + if err := gd.Members[memberId].decode(pd); err != nil { + return err + } + } + + return nil +} + +type GroupMemberDescription struct { + ClientId string + ClientHost string + MemberMetadata []byte + MemberAssignment []byte +} + +func (gmd *GroupMemberDescription) encode(pe packetEncoder) error { + if err := pe.putString(gmd.ClientId); err != nil { + return err + } + if err := pe.putString(gmd.ClientHost); err != nil { + return err + } + if err := pe.putBytes(gmd.MemberMetadata); err != nil { + return err + } + if err := pe.putBytes(gmd.MemberAssignment); err != nil { + return err + } + + return nil +} + +func (gmd *GroupMemberDescription) decode(pd packetDecoder) (err error) { + if gmd.ClientId, err = pd.getString(); err != nil { + return + } + if gmd.ClientHost, err = pd.getString(); err != nil { + return + } + if gmd.MemberMetadata, err = pd.getBytes(); err != nil { + return + } + if gmd.MemberAssignment, err = pd.getBytes(); err != nil { + return + } + + return nil +} + +func (gmd *GroupMemberDescription) GetMemberAssignment() (*ConsumerGroupMemberAssignment, error) { + assignment := new(ConsumerGroupMemberAssignment) + err := decode(gmd.MemberAssignment, assignment) + return assignment, err +} + +func (gmd *GroupMemberDescription) GetMemberMetadata() (*ConsumerGroupMemberMetadata, error) { + metadata := new(ConsumerGroupMemberMetadata) + err := decode(gmd.MemberMetadata, metadata) + return metadata, err +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_response_test.go new file mode 100644 index 00000000..dd397319 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/describe_groups_response_test.go @@ -0,0 +1,91 @@ +package sarama + +import ( + "reflect" + "testing" +) + +var ( + describeGroupsResponseEmpty = []byte{ + 0, 0, 0, 0, // no groups + } + + describeGroupsResponsePopulated = []byte{ + 0, 0, 0, 2, // 2 groups + + 0, 0, // no error + 0, 3, 'f', 'o', 'o', // Group ID + 0, 3, 'b', 'a', 'r', // State + 0, 8, 'c', 'o', 'n', 's', 'u', 'm', 'e', 'r', // ConsumerProtocol type + 0, 3, 'b', 'a', 'z', // Protocol name + 0, 0, 0, 1, // 1 member + 0, 2, 'i', 'd', // Member ID + 0, 6, 's', 'a', 'r', 'a', 'm', 'a', // Client ID + 0, 9, 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', // Client Host + 0, 0, 0, 3, 0x01, 0x02, 0x03, // MemberMetadata + 0, 0, 0, 3, 0x04, 0x05, 0x06, // MemberAssignment + + 0, 30, // ErrGroupAuthorizationFailed + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, 0, 0, + } +) + +func TestDescribeGroupsResponse(t *testing.T) { + var response *DescribeGroupsResponse + + response = new(DescribeGroupsResponse) + testVersionDecodable(t, "empty", response, describeGroupsResponseEmpty, 0) + if len(response.Groups) != 0 { + t.Error("Expected no groups") + } + + response = new(DescribeGroupsResponse) + testVersionDecodable(t, "populated", response, describeGroupsResponsePopulated, 0) + if len(response.Groups) != 2 { + t.Error("Expected two groups") + } + + group0 := response.Groups[0] + if group0.Err != ErrNoError { + t.Error("Unxpected groups[0].Err, found", group0.Err) + } + if group0.GroupId != "foo" { + t.Error("Unxpected groups[0].GroupId, found", group0.GroupId) + } + if group0.State != "bar" { + t.Error("Unxpected groups[0].State, found", group0.State) + } + if group0.ProtocolType != "consumer" { + t.Error("Unxpected groups[0].ProtocolType, found", group0.ProtocolType) + } + if group0.Protocol != "baz" { + t.Error("Unxpected groups[0].Protocol, found", group0.Protocol) + } + if len(group0.Members) != 1 { + t.Error("Unxpected groups[0].Members, found", group0.Members) + } + if group0.Members["id"].ClientId != "sarama" { + t.Error("Unxpected groups[0].Members[id].ClientId, found", group0.Members["id"].ClientId) + } + if group0.Members["id"].ClientHost != "localhost" { + t.Error("Unxpected groups[0].Members[id].ClientHost, found", group0.Members["id"].ClientHost) + } + if !reflect.DeepEqual(group0.Members["id"].MemberMetadata, []byte{0x01, 0x02, 0x03}) { + t.Error("Unxpected groups[0].Members[id].MemberMetadata, found", group0.Members["id"].MemberMetadata) + } + if !reflect.DeepEqual(group0.Members["id"].MemberAssignment, []byte{0x04, 0x05, 0x06}) { + t.Error("Unxpected groups[0].Members[id].MemberAssignment, found", group0.Members["id"].MemberAssignment) + } + + group1 := response.Groups[1] + if group1.Err != ErrGroupAuthorizationFailed { + t.Error("Unxpected groups[1].Err, found", group0.Err) + } + if len(group1.Members) != 0 { + t.Error("Unxpected groups[1].Members, found", group0.Members) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/dev.yml b/vendor/src/gopkg.in/Shopify/sarama.v1/dev.yml new file mode 100644 index 00000000..e014316f --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/dev.yml @@ -0,0 +1,13 @@ +name: sarama + +up: + - go: 1.7.3 + +commands: + test: + run: make test + desc: 'run unit tests' + +packages: + - git@github.com:Shopify/dev-shopify.git + diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/encoder_decoder.go b/vendor/src/gopkg.in/Shopify/sarama.v1/encoder_decoder.go new file mode 100644 index 00000000..7ce3bc0f --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/encoder_decoder.go @@ -0,0 +1,89 @@ +package sarama + +import ( + "fmt" + + "github.com/rcrowley/go-metrics" +) + +// Encoder is the interface that wraps the basic Encode method. +// Anything implementing Encoder can be turned into bytes using Kafka's encoding rules. +type encoder interface { + encode(pe packetEncoder) error +} + +// Encode takes an Encoder and turns it into bytes while potentially recording metrics. +func encode(e encoder, metricRegistry metrics.Registry) ([]byte, error) { + if e == nil { + return nil, nil + } + + var prepEnc prepEncoder + var realEnc realEncoder + + err := e.encode(&prepEnc) + if err != nil { + return nil, err + } + + if prepEnc.length < 0 || prepEnc.length > int(MaxRequestSize) { + return nil, PacketEncodingError{fmt.Sprintf("invalid request size (%d)", prepEnc.length)} + } + + realEnc.raw = make([]byte, prepEnc.length) + realEnc.registry = metricRegistry + err = e.encode(&realEnc) + if err != nil { + return nil, err + } + + return realEnc.raw, nil +} + +// Decoder is the interface that wraps the basic Decode method. +// Anything implementing Decoder can be extracted from bytes using Kafka's encoding rules. +type decoder interface { + decode(pd packetDecoder) error +} + +type versionedDecoder interface { + decode(pd packetDecoder, version int16) error +} + +// Decode takes bytes and a Decoder and fills the fields of the decoder from the bytes, +// interpreted using Kafka's encoding rules. +func decode(buf []byte, in decoder) error { + if buf == nil { + return nil + } + + helper := realDecoder{raw: buf} + err := in.decode(&helper) + if err != nil { + return err + } + + if helper.off != len(buf) { + return PacketDecodingError{"invalid length"} + } + + return nil +} + +func versionedDecode(buf []byte, in versionedDecoder, version int16) error { + if buf == nil { + return nil + } + + helper := realDecoder{raw: buf} + err := in.decode(&helper, version) + if err != nil { + return err + } + + if helper.off != len(buf) { + return PacketDecodingError{"invalid length"} + } + + return nil +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/errors.go b/vendor/src/gopkg.in/Shopify/sarama.v1/errors.go new file mode 100644 index 00000000..cc3f623d --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/errors.go @@ -0,0 +1,197 @@ +package sarama + +import ( + "errors" + "fmt" +) + +// ErrOutOfBrokers is the error returned when the client has run out of brokers to talk to because all of them errored +// or otherwise failed to respond. +var ErrOutOfBrokers = errors.New("kafka: client has run out of available brokers to talk to (Is your cluster reachable?)") + +// ErrClosedClient is the error returned when a method is called on a client that has been closed. +var ErrClosedClient = errors.New("kafka: tried to use a client that was closed") + +// ErrIncompleteResponse is the error returned when the server returns a syntactically valid response, but it does +// not contain the expected information. +var ErrIncompleteResponse = errors.New("kafka: response did not contain all the expected topic/partition blocks") + +// ErrInvalidPartition is the error returned when a partitioner returns an invalid partition index +// (meaning one outside of the range [0...numPartitions-1]). +var ErrInvalidPartition = errors.New("kafka: partitioner returned an invalid partition index") + +// ErrAlreadyConnected is the error returned when calling Open() on a Broker that is already connected or connecting. +var ErrAlreadyConnected = errors.New("kafka: broker connection already initiated") + +// ErrNotConnected is the error returned when trying to send or call Close() on a Broker that is not connected. +var ErrNotConnected = errors.New("kafka: broker not connected") + +// ErrInsufficientData is returned when decoding and the packet is truncated. This can be expected +// when requesting messages, since as an optimization the server is allowed to return a partial message at the end +// of the message set. +var ErrInsufficientData = errors.New("kafka: insufficient data to decode packet, more bytes expected") + +// ErrShuttingDown is returned when a producer receives a message during shutdown. +var ErrShuttingDown = errors.New("kafka: message received by producer in process of shutting down") + +// ErrMessageTooLarge is returned when the next message to consume is larger than the configured Consumer.Fetch.Max +var ErrMessageTooLarge = errors.New("kafka: message is larger than Consumer.Fetch.Max") + +// PacketEncodingError is returned from a failure while encoding a Kafka packet. This can happen, for example, +// if you try to encode a string over 2^15 characters in length, since Kafka's encoding rules do not permit that. +type PacketEncodingError struct { + Info string +} + +func (err PacketEncodingError) Error() string { + return fmt.Sprintf("kafka: error encoding packet: %s", err.Info) +} + +// PacketDecodingError is returned when there was an error (other than truncated data) decoding the Kafka broker's response. +// This can be a bad CRC or length field, or any other invalid value. +type PacketDecodingError struct { + Info string +} + +func (err PacketDecodingError) Error() string { + return fmt.Sprintf("kafka: error decoding packet: %s", err.Info) +} + +// ConfigurationError is the type of error returned from a constructor (e.g. NewClient, or NewConsumer) +// when the specified configuration is invalid. +type ConfigurationError string + +func (err ConfigurationError) Error() string { + return "kafka: invalid configuration (" + string(err) + ")" +} + +// KError is the type of error that can be returned directly by the Kafka broker. +// See https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol#AGuideToTheKafkaProtocol-ErrorCodes +type KError int16 + +// Numeric error codes returned by the Kafka server. +const ( + ErrNoError KError = 0 + ErrUnknown KError = -1 + ErrOffsetOutOfRange KError = 1 + ErrInvalidMessage KError = 2 + ErrUnknownTopicOrPartition KError = 3 + ErrInvalidMessageSize KError = 4 + ErrLeaderNotAvailable KError = 5 + ErrNotLeaderForPartition KError = 6 + ErrRequestTimedOut KError = 7 + ErrBrokerNotAvailable KError = 8 + ErrReplicaNotAvailable KError = 9 + ErrMessageSizeTooLarge KError = 10 + ErrStaleControllerEpochCode KError = 11 + ErrOffsetMetadataTooLarge KError = 12 + ErrNetworkException KError = 13 + ErrOffsetsLoadInProgress KError = 14 + ErrConsumerCoordinatorNotAvailable KError = 15 + ErrNotCoordinatorForConsumer KError = 16 + ErrInvalidTopic KError = 17 + ErrMessageSetSizeTooLarge KError = 18 + ErrNotEnoughReplicas KError = 19 + ErrNotEnoughReplicasAfterAppend KError = 20 + ErrInvalidRequiredAcks KError = 21 + ErrIllegalGeneration KError = 22 + ErrInconsistentGroupProtocol KError = 23 + ErrInvalidGroupId KError = 24 + ErrUnknownMemberId KError = 25 + ErrInvalidSessionTimeout KError = 26 + ErrRebalanceInProgress KError = 27 + ErrInvalidCommitOffsetSize KError = 28 + ErrTopicAuthorizationFailed KError = 29 + ErrGroupAuthorizationFailed KError = 30 + ErrClusterAuthorizationFailed KError = 31 + ErrInvalidTimestamp KError = 32 + ErrUnsupportedSASLMechanism KError = 33 + ErrIllegalSASLState KError = 34 + ErrUnsupportedVersion KError = 35 + ErrUnsupportedForMessageFormat KError = 43 +) + +func (err KError) Error() string { + // Error messages stolen/adapted from + // https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol + switch err { + case ErrNoError: + return "kafka server: Not an error, why are you printing me?" + case ErrUnknown: + return "kafka server: Unexpected (unknown?) server error." + case ErrOffsetOutOfRange: + return "kafka server: The requested offset is outside the range of offsets maintained by the server for the given topic/partition." + case ErrInvalidMessage: + return "kafka server: Message contents does not match its CRC." + case ErrUnknownTopicOrPartition: + return "kafka server: Request was for a topic or partition that does not exist on this broker." + case ErrInvalidMessageSize: + return "kafka server: The message has a negative size." + case ErrLeaderNotAvailable: + return "kafka server: In the middle of a leadership election, there is currently no leader for this partition and hence it is unavailable for writes." + case ErrNotLeaderForPartition: + return "kafka server: Tried to send a message to a replica that is not the leader for some partition. Your metadata is out of date." + case ErrRequestTimedOut: + return "kafka server: Request exceeded the user-specified time limit in the request." + case ErrBrokerNotAvailable: + return "kafka server: Broker not available. Not a client facing error, we should never receive this!!!" + case ErrReplicaNotAvailable: + return "kafka server: Replica information not available, one or more brokers are down." + case ErrMessageSizeTooLarge: + return "kafka server: Message was too large, server rejected it to avoid allocation error." + case ErrStaleControllerEpochCode: + return "kafka server: StaleControllerEpochCode (internal error code for broker-to-broker communication)." + case ErrOffsetMetadataTooLarge: + return "kafka server: Specified a string larger than the configured maximum for offset metadata." + case ErrNetworkException: + return "kafka server: The server disconnected before a response was received." + case ErrOffsetsLoadInProgress: + return "kafka server: The broker is still loading offsets after a leader change for that offset's topic partition." + case ErrConsumerCoordinatorNotAvailable: + return "kafka server: Offset's topic has not yet been created." + case ErrNotCoordinatorForConsumer: + return "kafka server: Request was for a consumer group that is not coordinated by this broker." + case ErrInvalidTopic: + return "kafka server: The request attempted to perform an operation on an invalid topic." + case ErrMessageSetSizeTooLarge: + return "kafka server: The request included message batch larger than the configured segment size on the server." + case ErrNotEnoughReplicas: + return "kafka server: Messages are rejected since there are fewer in-sync replicas than required." + case ErrNotEnoughReplicasAfterAppend: + return "kafka server: Messages are written to the log, but to fewer in-sync replicas than required." + case ErrInvalidRequiredAcks: + return "kafka server: The number of required acks is invalid (should be either -1, 0, or 1)." + case ErrIllegalGeneration: + return "kafka server: The provided generation id is not the current generation." + case ErrInconsistentGroupProtocol: + return "kafka server: The provider group protocol type is incompatible with the other members." + case ErrInvalidGroupId: + return "kafka server: The provided group id was empty." + case ErrUnknownMemberId: + return "kafka server: The provided member is not known in the current generation." + case ErrInvalidSessionTimeout: + return "kafka server: The provided session timeout is outside the allowed range." + case ErrRebalanceInProgress: + return "kafka server: A rebalance for the group is in progress. Please re-join the group." + case ErrInvalidCommitOffsetSize: + return "kafka server: The provided commit metadata was too large." + case ErrTopicAuthorizationFailed: + return "kafka server: The client is not authorized to access this topic." + case ErrGroupAuthorizationFailed: + return "kafka server: The client is not authorized to access this group." + case ErrClusterAuthorizationFailed: + return "kafka server: The client is not authorized to send this request type." + case ErrInvalidTimestamp: + return "kafka server: The timestamp of the message is out of acceptable range." + case ErrUnsupportedSASLMechanism: + return "kafka server: The broker does not support the requested SASL mechanism." + case ErrIllegalSASLState: + return "kafka server: Request is not valid given the current SASL state." + case ErrUnsupportedVersion: + return "kafka server: The version of API is not supported." + case ErrUnsupportedForMessageFormat: + return "kafka server: The requested operation is not supported by the message format version." + } + + return fmt.Sprintf("Unknown error, how did this happen? Error code = %d", err) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/examples/README.md b/vendor/src/gopkg.in/Shopify/sarama.v1/examples/README.md new file mode 100644 index 00000000..b6588051 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/examples/README.md @@ -0,0 +1,9 @@ +# Sarama examples + +This folder contains example applications to demonstrate the use of Sarama. For code snippet examples on how to use the different types in Sarama, see [Sarams's API documentation on godoc.org](https://godoc.org/github.com/Shopify/sarama) + +In these examples, we use `github.com/Shopify/sarama` as import path. We do this to ensure all the examples are up to date with the latest changes in Sarama. For your own applications, you may want to use `gopkg.in/Shopify/sarama.v1` to lock into a stable API version. + +#### HTTP server + +[http_server](./http_server) is a simple HTTP server uses both the sync producer to produce data as part of the request handling cycle, as well as the async producer to maintain an access log. It also uses the [mocks subpackage](https://godoc.org/github.com/Shopify/sarama/mocks) to test both. diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/README.md b/vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/README.md new file mode 100644 index 00000000..5ff2bc25 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/README.md @@ -0,0 +1,7 @@ +# HTTP server example + +This HTTP server example shows you how to use the AsyncProducer and SyncProducer, and how to test them using mocks. The server simply sends the data of the HTTP request's query string to Kafka, and send a 200 result if that succeeds. For every request, it will send an access log entry to Kafka as well in the background. + +If you need to know whether a message was successfully sent to the Kafka cluster before you can send your HTTP response, using the `SyncProducer` is probably the simplest way to achieve this. If you don't care, e.g. for the access log, using the `AsyncProducer` will let you fire and forget. You can send the HTTP response, while the message is being produced in the background. + +One important thing to note is that both the `SyncProducer` and `AsyncProducer` are **thread-safe**. Go's `http.Server` handles requests concurrently in different goroutines, but you can use a single producer safely. This will actually achieve efficiency gains as the producer will be able to batch messages from concurrent requests together. diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/http_server.go b/vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/http_server.go new file mode 100644 index 00000000..b6d83c5d --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/http_server.go @@ -0,0 +1,247 @@ +package main + +import ( + "github.com/Shopify/sarama" + + "crypto/tls" + "crypto/x509" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "strings" + "time" +) + +var ( + addr = flag.String("addr", ":8080", "The address to bind to") + brokers = flag.String("brokers", os.Getenv("KAFKA_PEERS"), "The Kafka brokers to connect to, as a comma separated list") + verbose = flag.Bool("verbose", false, "Turn on Sarama logging") + certFile = flag.String("certificate", "", "The optional certificate file for client authentication") + keyFile = flag.String("key", "", "The optional key file for client authentication") + caFile = flag.String("ca", "", "The optional certificate authority file for TLS client authentication") + verifySsl = flag.Bool("verify", false, "Optional verify ssl certificates chain") +) + +func main() { + flag.Parse() + + if *verbose { + sarama.Logger = log.New(os.Stdout, "[sarama] ", log.LstdFlags) + } + + if *brokers == "" { + flag.PrintDefaults() + os.Exit(1) + } + + brokerList := strings.Split(*brokers, ",") + log.Printf("Kafka brokers: %s", strings.Join(brokerList, ", ")) + + server := &Server{ + DataCollector: newDataCollector(brokerList), + AccessLogProducer: newAccessLogProducer(brokerList), + } + defer func() { + if err := server.Close(); err != nil { + log.Println("Failed to close server", err) + } + }() + + log.Fatal(server.Run(*addr)) +} + +func createTlsConfiguration() (t *tls.Config) { + if *certFile != "" && *keyFile != "" && *caFile != "" { + cert, err := tls.LoadX509KeyPair(*certFile, *keyFile) + if err != nil { + log.Fatal(err) + } + + caCert, err := ioutil.ReadFile(*caFile) + if err != nil { + log.Fatal(err) + } + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + t = &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caCertPool, + InsecureSkipVerify: *verifySsl, + } + } + // will be nil by default if nothing is provided + return t +} + +type Server struct { + DataCollector sarama.SyncProducer + AccessLogProducer sarama.AsyncProducer +} + +func (s *Server) Close() error { + if err := s.DataCollector.Close(); err != nil { + log.Println("Failed to shut down data collector cleanly", err) + } + + if err := s.AccessLogProducer.Close(); err != nil { + log.Println("Failed to shut down access log producer cleanly", err) + } + + return nil +} + +func (s *Server) Handler() http.Handler { + return s.withAccessLog(s.collectQueryStringData()) +} + +func (s *Server) Run(addr string) error { + httpServer := &http.Server{ + Addr: addr, + Handler: s.Handler(), + } + + log.Printf("Listening for requests on %s...\n", addr) + return httpServer.ListenAndServe() +} + +func (s *Server) collectQueryStringData() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" { + http.NotFound(w, r) + return + } + + // We are not setting a message key, which means that all messages will + // be distributed randomly over the different partitions. + partition, offset, err := s.DataCollector.SendMessage(&sarama.ProducerMessage{ + Topic: "important", + Value: sarama.StringEncoder(r.URL.RawQuery), + }) + + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Failed to store your data:, %s", err) + } else { + // The tuple (topic, partition, offset) can be used as a unique identifier + // for a message in a Kafka cluster. + fmt.Fprintf(w, "Your data is stored with unique identifier important/%d/%d", partition, offset) + } + }) +} + +type accessLogEntry struct { + Method string `json:"method"` + Host string `json:"host"` + Path string `json:"path"` + IP string `json:"ip"` + ResponseTime float64 `json:"response_time"` + + encoded []byte + err error +} + +func (ale *accessLogEntry) ensureEncoded() { + if ale.encoded == nil && ale.err == nil { + ale.encoded, ale.err = json.Marshal(ale) + } +} + +func (ale *accessLogEntry) Length() int { + ale.ensureEncoded() + return len(ale.encoded) +} + +func (ale *accessLogEntry) Encode() ([]byte, error) { + ale.ensureEncoded() + return ale.encoded, ale.err +} + +func (s *Server) withAccessLog(next http.Handler) http.Handler { + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + started := time.Now() + + next.ServeHTTP(w, r) + + entry := &accessLogEntry{ + Method: r.Method, + Host: r.Host, + Path: r.RequestURI, + IP: r.RemoteAddr, + ResponseTime: float64(time.Since(started)) / float64(time.Second), + } + + // We will use the client's IP address as key. This will cause + // all the access log entries of the same IP address to end up + // on the same partition. + s.AccessLogProducer.Input() <- &sarama.ProducerMessage{ + Topic: "access_log", + Key: sarama.StringEncoder(r.RemoteAddr), + Value: entry, + } + }) +} + +func newDataCollector(brokerList []string) sarama.SyncProducer { + + // For the data collector, we are looking for strong consistency semantics. + // Because we don't change the flush settings, sarama will try to produce messages + // as fast as possible to keep latency low. + config := sarama.NewConfig() + config.Producer.RequiredAcks = sarama.WaitForAll // Wait for all in-sync replicas to ack the message + config.Producer.Retry.Max = 10 // Retry up to 10 times to produce the message + config.Producer.Return.Successes = true + tlsConfig := createTlsConfiguration() + if tlsConfig != nil { + config.Net.TLS.Config = tlsConfig + config.Net.TLS.Enable = true + } + + // On the broker side, you may want to change the following settings to get + // stronger consistency guarantees: + // - For your broker, set `unclean.leader.election.enable` to false + // - For the topic, you could increase `min.insync.replicas`. + + producer, err := sarama.NewSyncProducer(brokerList, config) + if err != nil { + log.Fatalln("Failed to start Sarama producer:", err) + } + + return producer +} + +func newAccessLogProducer(brokerList []string) sarama.AsyncProducer { + + // For the access log, we are looking for AP semantics, with high throughput. + // By creating batches of compressed messages, we reduce network I/O at a cost of more latency. + config := sarama.NewConfig() + tlsConfig := createTlsConfiguration() + if tlsConfig != nil { + config.Net.TLS.Enable = true + config.Net.TLS.Config = tlsConfig + } + config.Producer.RequiredAcks = sarama.WaitForLocal // Only wait for the leader to ack + config.Producer.Compression = sarama.CompressionSnappy // Compress messages + config.Producer.Flush.Frequency = 500 * time.Millisecond // Flush batches every 500ms + + producer, err := sarama.NewAsyncProducer(brokerList, config) + if err != nil { + log.Fatalln("Failed to start Sarama producer:", err) + } + + // We will just log to STDOUT if we're not able to produce messages. + // Note: messages will only be returned here after all retry attempts are exhausted. + go func() { + for err := range producer.Errors() { + log.Println("Failed to write access log entry:", err) + } + }() + + return producer +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/http_server_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/http_server_test.go new file mode 100644 index 00000000..7b2451e2 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/examples/http_server/http_server_test.go @@ -0,0 +1,109 @@ +package main + +import ( + "io" + "net/http" + "net/http/httptest" + "testing" + + "github.com/Shopify/sarama" + "github.com/Shopify/sarama/mocks" +) + +// In normal operation, we expect one access log entry, +// and one data collector entry. Let's assume both will succeed. +// We should return a HTTP 200 status. +func TestCollectSuccessfully(t *testing.T) { + dataCollectorMock := mocks.NewSyncProducer(t, nil) + dataCollectorMock.ExpectSendMessageAndSucceed() + + accessLogProducerMock := mocks.NewAsyncProducer(t, nil) + accessLogProducerMock.ExpectInputAndSucceed() + + // Now, use dependency injection to use the mocks. + s := &Server{ + DataCollector: dataCollectorMock, + AccessLogProducer: accessLogProducerMock, + } + + // The Server's Close call is important; it will call Close on + // the two mock producers, which will then validate whether all + // expectations are resolved. + defer safeClose(t, s) + + req, err := http.NewRequest("GET", "http://example.com/?data", nil) + if err != nil { + t.Fatal(err) + } + res := httptest.NewRecorder() + s.Handler().ServeHTTP(res, req) + + if res.Code != 200 { + t.Errorf("Expected HTTP status 200, found %d", res.Code) + } + + if string(res.Body.Bytes()) != "Your data is stored with unique identifier important/0/1" { + t.Error("Unexpected response body", res.Body) + } +} + +// Now, let's see if we handle the case of not being able to produce +// to the data collector properly. In this case we should return a 500 status. +func TestCollectionFailure(t *testing.T) { + dataCollectorMock := mocks.NewSyncProducer(t, nil) + dataCollectorMock.ExpectSendMessageAndFail(sarama.ErrRequestTimedOut) + + accessLogProducerMock := mocks.NewAsyncProducer(t, nil) + accessLogProducerMock.ExpectInputAndSucceed() + + s := &Server{ + DataCollector: dataCollectorMock, + AccessLogProducer: accessLogProducerMock, + } + defer safeClose(t, s) + + req, err := http.NewRequest("GET", "http://example.com/?data", nil) + if err != nil { + t.Fatal(err) + } + res := httptest.NewRecorder() + s.Handler().ServeHTTP(res, req) + + if res.Code != 500 { + t.Errorf("Expected HTTP status 500, found %d", res.Code) + } +} + +// We don't expect any data collector calls because the path is wrong, +// so we are not setting any expectations on the dataCollectorMock. It +// will still generate an access log entry though. +func TestWrongPath(t *testing.T) { + dataCollectorMock := mocks.NewSyncProducer(t, nil) + + accessLogProducerMock := mocks.NewAsyncProducer(t, nil) + accessLogProducerMock.ExpectInputAndSucceed() + + s := &Server{ + DataCollector: dataCollectorMock, + AccessLogProducer: accessLogProducerMock, + } + defer safeClose(t, s) + + req, err := http.NewRequest("GET", "http://example.com/wrong?data", nil) + if err != nil { + t.Fatal(err) + } + res := httptest.NewRecorder() + + s.Handler().ServeHTTP(res, req) + + if res.Code != 404 { + t.Errorf("Expected HTTP status 404, found %d", res.Code) + } +} + +func safeClose(t *testing.T, o io.Closer) { + if err := o.Close(); err != nil { + t.Error(err) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_request.go new file mode 100644 index 00000000..ae701a3f --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_request.go @@ -0,0 +1,136 @@ +package sarama + +type fetchRequestBlock struct { + fetchOffset int64 + maxBytes int32 +} + +func (b *fetchRequestBlock) encode(pe packetEncoder) error { + pe.putInt64(b.fetchOffset) + pe.putInt32(b.maxBytes) + return nil +} + +func (b *fetchRequestBlock) decode(pd packetDecoder) (err error) { + if b.fetchOffset, err = pd.getInt64(); err != nil { + return err + } + if b.maxBytes, err = pd.getInt32(); err != nil { + return err + } + return nil +} + +type FetchRequest struct { + MaxWaitTime int32 + MinBytes int32 + Version int16 + blocks map[string]map[int32]*fetchRequestBlock +} + +func (r *FetchRequest) encode(pe packetEncoder) (err error) { + pe.putInt32(-1) // replica ID is always -1 for clients + pe.putInt32(r.MaxWaitTime) + pe.putInt32(r.MinBytes) + err = pe.putArrayLength(len(r.blocks)) + if err != nil { + return err + } + for topic, blocks := range r.blocks { + err = pe.putString(topic) + if err != nil { + return err + } + err = pe.putArrayLength(len(blocks)) + if err != nil { + return err + } + for partition, block := range blocks { + pe.putInt32(partition) + err = block.encode(pe) + if err != nil { + return err + } + } + } + return nil +} + +func (r *FetchRequest) decode(pd packetDecoder, version int16) (err error) { + r.Version = version + if _, err = pd.getInt32(); err != nil { + return err + } + if r.MaxWaitTime, err = pd.getInt32(); err != nil { + return err + } + if r.MinBytes, err = pd.getInt32(); err != nil { + return err + } + topicCount, err := pd.getArrayLength() + if err != nil { + return err + } + if topicCount == 0 { + return nil + } + r.blocks = make(map[string]map[int32]*fetchRequestBlock) + for i := 0; i < topicCount; i++ { + topic, err := pd.getString() + if err != nil { + return err + } + partitionCount, err := pd.getArrayLength() + if err != nil { + return err + } + r.blocks[topic] = make(map[int32]*fetchRequestBlock) + for j := 0; j < partitionCount; j++ { + partition, err := pd.getInt32() + if err != nil { + return err + } + fetchBlock := &fetchRequestBlock{} + if err = fetchBlock.decode(pd); err != nil { + return nil + } + r.blocks[topic][partition] = fetchBlock + } + } + return nil +} + +func (r *FetchRequest) key() int16 { + return 1 +} + +func (r *FetchRequest) version() int16 { + return r.Version +} + +func (r *FetchRequest) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_9_0_0 + case 2: + return V0_10_0_0 + default: + return minVersion + } +} + +func (r *FetchRequest) AddBlock(topic string, partitionID int32, fetchOffset int64, maxBytes int32) { + if r.blocks == nil { + r.blocks = make(map[string]map[int32]*fetchRequestBlock) + } + + if r.blocks[topic] == nil { + r.blocks[topic] = make(map[int32]*fetchRequestBlock) + } + + tmp := new(fetchRequestBlock) + tmp.maxBytes = maxBytes + tmp.fetchOffset = fetchOffset + + r.blocks[topic][partitionID] = tmp +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_request_test.go new file mode 100644 index 00000000..32c083c7 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_request_test.go @@ -0,0 +1,34 @@ +package sarama + +import "testing" + +var ( + fetchRequestNoBlocks = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} + + fetchRequestWithProperties = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xEF, + 0x00, 0x00, 0x00, 0x00} + + fetchRequestOneBlock = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x56} +) + +func TestFetchRequest(t *testing.T) { + request := new(FetchRequest) + testRequest(t, "no blocks", request, fetchRequestNoBlocks) + + request.MaxWaitTime = 0x20 + request.MinBytes = 0xEF + testRequest(t, "with properties", request, fetchRequestWithProperties) + + request.MaxWaitTime = 0 + request.MinBytes = 0 + request.AddBlock("topic", 0x12, 0x34, 0x56) + testRequest(t, "one block", request, fetchRequestOneBlock) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_response.go new file mode 100644 index 00000000..b56b166c --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_response.go @@ -0,0 +1,210 @@ +package sarama + +import "time" + +type FetchResponseBlock struct { + Err KError + HighWaterMarkOffset int64 + MsgSet MessageSet +} + +func (b *FetchResponseBlock) decode(pd packetDecoder) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + b.Err = KError(tmp) + + b.HighWaterMarkOffset, err = pd.getInt64() + if err != nil { + return err + } + + msgSetSize, err := pd.getInt32() + if err != nil { + return err + } + + msgSetDecoder, err := pd.getSubset(int(msgSetSize)) + if err != nil { + return err + } + err = (&b.MsgSet).decode(msgSetDecoder) + + return err +} + +func (b *FetchResponseBlock) encode(pe packetEncoder) (err error) { + pe.putInt16(int16(b.Err)) + + pe.putInt64(b.HighWaterMarkOffset) + + pe.push(&lengthField{}) + err = b.MsgSet.encode(pe) + if err != nil { + return err + } + return pe.pop() +} + +type FetchResponse struct { + Blocks map[string]map[int32]*FetchResponseBlock + ThrottleTime time.Duration + Version int16 // v1 requires 0.9+, v2 requires 0.10+ +} + +func (r *FetchResponse) decode(pd packetDecoder, version int16) (err error) { + r.Version = version + + if r.Version >= 1 { + throttle, err := pd.getInt32() + if err != nil { + return err + } + r.ThrottleTime = time.Duration(throttle) * time.Millisecond + } + + numTopics, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks = make(map[string]map[int32]*FetchResponseBlock, numTopics) + for i := 0; i < numTopics; i++ { + name, err := pd.getString() + if err != nil { + return err + } + + numBlocks, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks[name] = make(map[int32]*FetchResponseBlock, numBlocks) + + for j := 0; j < numBlocks; j++ { + id, err := pd.getInt32() + if err != nil { + return err + } + + block := new(FetchResponseBlock) + err = block.decode(pd) + if err != nil { + return err + } + r.Blocks[name][id] = block + } + } + + return nil +} + +func (r *FetchResponse) encode(pe packetEncoder) (err error) { + if r.Version >= 1 { + pe.putInt32(int32(r.ThrottleTime / time.Millisecond)) + } + + err = pe.putArrayLength(len(r.Blocks)) + if err != nil { + return err + } + + for topic, partitions := range r.Blocks { + err = pe.putString(topic) + if err != nil { + return err + } + + err = pe.putArrayLength(len(partitions)) + if err != nil { + return err + } + + for id, block := range partitions { + pe.putInt32(id) + err = block.encode(pe) + if err != nil { + return err + } + } + + } + return nil +} + +func (r *FetchResponse) key() int16 { + return 1 +} + +func (r *FetchResponse) version() int16 { + return r.Version +} + +func (r *FetchResponse) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_9_0_0 + case 2: + return V0_10_0_0 + default: + return minVersion + } +} + +func (r *FetchResponse) GetBlock(topic string, partition int32) *FetchResponseBlock { + if r.Blocks == nil { + return nil + } + + if r.Blocks[topic] == nil { + return nil + } + + return r.Blocks[topic][partition] +} + +func (r *FetchResponse) AddError(topic string, partition int32, err KError) { + if r.Blocks == nil { + r.Blocks = make(map[string]map[int32]*FetchResponseBlock) + } + partitions, ok := r.Blocks[topic] + if !ok { + partitions = make(map[int32]*FetchResponseBlock) + r.Blocks[topic] = partitions + } + frb, ok := partitions[partition] + if !ok { + frb = new(FetchResponseBlock) + partitions[partition] = frb + } + frb.Err = err +} + +func (r *FetchResponse) AddMessage(topic string, partition int32, key, value Encoder, offset int64) { + if r.Blocks == nil { + r.Blocks = make(map[string]map[int32]*FetchResponseBlock) + } + partitions, ok := r.Blocks[topic] + if !ok { + partitions = make(map[int32]*FetchResponseBlock) + r.Blocks[topic] = partitions + } + frb, ok := partitions[partition] + if !ok { + frb = new(FetchResponseBlock) + partitions[partition] = frb + } + var kb []byte + var vb []byte + if key != nil { + kb, _ = key.Encode() + } + if value != nil { + vb, _ = value.Encode() + } + msg := &Message{Key: kb, Value: vb} + msgBlock := &MessageBlock{Msg: msg, Offset: offset} + frb.MsgSet.Messages = append(frb.MsgSet.Messages, msgBlock) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_response_test.go new file mode 100644 index 00000000..52fb5a74 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/fetch_response_test.go @@ -0,0 +1,84 @@ +package sarama + +import ( + "bytes" + "testing" +) + +var ( + emptyFetchResponse = []byte{ + 0x00, 0x00, 0x00, 0x00} + + oneMessageFetchResponse = []byte{ + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x05, + 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, + 0x00, 0x00, 0x00, 0x1C, + // messageSet + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, + // message + 0x23, 0x96, 0x4a, 0xf7, // CRC + 0x00, + 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x02, 0x00, 0xEE} +) + +func TestEmptyFetchResponse(t *testing.T) { + response := FetchResponse{} + testVersionDecodable(t, "empty", &response, emptyFetchResponse, 0) + + if len(response.Blocks) != 0 { + t.Error("Decoding produced topic blocks where there were none.") + } + +} + +func TestOneMessageFetchResponse(t *testing.T) { + response := FetchResponse{} + testVersionDecodable(t, "one message", &response, oneMessageFetchResponse, 0) + + if len(response.Blocks) != 1 { + t.Fatal("Decoding produced incorrect number of topic blocks.") + } + + if len(response.Blocks["topic"]) != 1 { + t.Fatal("Decoding produced incorrect number of partition blocks for topic.") + } + + block := response.GetBlock("topic", 5) + if block == nil { + t.Fatal("GetBlock didn't return block.") + } + if block.Err != ErrOffsetOutOfRange { + t.Error("Decoding didn't produce correct error code.") + } + if block.HighWaterMarkOffset != 0x10101010 { + t.Error("Decoding didn't produce correct high water mark offset.") + } + if block.MsgSet.PartialTrailingMessage { + t.Error("Decoding detected a partial trailing message where there wasn't one.") + } + + if len(block.MsgSet.Messages) != 1 { + t.Fatal("Decoding produced incorrect number of messages.") + } + msgBlock := block.MsgSet.Messages[0] + if msgBlock.Offset != 0x550000 { + t.Error("Decoding produced incorrect message offset.") + } + msg := msgBlock.Msg + if msg.Codec != CompressionNone { + t.Error("Decoding produced incorrect message compression.") + } + if msg.Key != nil { + t.Error("Decoding produced message key where there was none.") + } + if !bytes.Equal(msg.Value, []byte{0x00, 0xEE}) { + t.Error("Decoding produced incorrect message value.") + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/functional_client_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/functional_client_test.go new file mode 100644 index 00000000..2bf99d25 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/functional_client_test.go @@ -0,0 +1,90 @@ +package sarama + +import ( + "fmt" + "testing" + "time" +) + +func TestFuncConnectionFailure(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + Proxies["kafka1"].Enabled = false + SaveProxy(t, "kafka1") + + config := NewConfig() + config.Metadata.Retry.Max = 1 + + _, err := NewClient([]string{kafkaBrokers[0]}, config) + if err != ErrOutOfBrokers { + t.Fatal("Expected returned error to be ErrOutOfBrokers, but was: ", err) + } +} + +func TestFuncClientMetadata(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + config := NewConfig() + config.Metadata.Retry.Max = 1 + config.Metadata.Retry.Backoff = 10 * time.Millisecond + client, err := NewClient(kafkaBrokers, config) + if err != nil { + t.Fatal(err) + } + + if err := client.RefreshMetadata("unknown_topic"); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, got", err) + } + + if _, err := client.Leader("unknown_topic", 0); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, got", err) + } + + if _, err := client.Replicas("invalid/topic", 0); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, got", err) + } + + partitions, err := client.Partitions("test.4") + if err != nil { + t.Error(err) + } + if len(partitions) != 4 { + t.Errorf("Expected test.4 topic to have 4 partitions, found %v", partitions) + } + + partitions, err = client.Partitions("test.1") + if err != nil { + t.Error(err) + } + if len(partitions) != 1 { + t.Errorf("Expected test.1 topic to have 1 partitions, found %v", partitions) + } + + safeClose(t, client) +} + +func TestFuncClientCoordinator(t *testing.T) { + checkKafkaVersion(t, "0.8.2") + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + client, err := NewClient(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + broker, err := client.Coordinator(fmt.Sprintf("another_new_consumer_group_%d", i)) + if err != nil { + t.Fatal(err) + } + + if connected, err := broker.Connected(); !connected || err != nil { + t.Errorf("Expected to coordinator %s broker to be properly connected.", broker.Addr()) + } + } + + safeClose(t, client) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/functional_consumer_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/functional_consumer_test.go new file mode 100644 index 00000000..ab843310 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/functional_consumer_test.go @@ -0,0 +1,61 @@ +package sarama + +import ( + "math" + "testing" +) + +func TestFuncConsumerOffsetOutOfRange(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + consumer, err := NewConsumer(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + + if _, err := consumer.ConsumePartition("test.1", 0, -10); err != ErrOffsetOutOfRange { + t.Error("Expected ErrOffsetOutOfRange, got:", err) + } + + if _, err := consumer.ConsumePartition("test.1", 0, math.MaxInt64); err != ErrOffsetOutOfRange { + t.Error("Expected ErrOffsetOutOfRange, got:", err) + } + + safeClose(t, consumer) +} + +func TestConsumerHighWaterMarkOffset(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + p, err := NewSyncProducer(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + defer safeClose(t, p) + + _, offset, err := p.SendMessage(&ProducerMessage{Topic: "test.1", Value: StringEncoder("Test")}) + if err != nil { + t.Fatal(err) + } + + c, err := NewConsumer(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + defer safeClose(t, c) + + pc, err := c.ConsumePartition("test.1", 0, OffsetOldest) + if err != nil { + t.Fatal(err) + } + + <-pc.Messages() + + if hwmo := pc.HighWaterMarkOffset(); hwmo != offset+1 { + t.Logf("Last produced offset %d; high water mark should be one higher but found %d.", offset, hwmo) + } + + safeClose(t, pc) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/functional_offset_manager_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/functional_offset_manager_test.go new file mode 100644 index 00000000..436f35ef --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/functional_offset_manager_test.go @@ -0,0 +1,47 @@ +package sarama + +import ( + "testing" +) + +func TestFuncOffsetManager(t *testing.T) { + checkKafkaVersion(t, "0.8.2") + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + client, err := NewClient(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + + offsetManager, err := NewOffsetManagerFromClient("sarama.TestFuncOffsetManager", client) + if err != nil { + t.Fatal(err) + } + + pom1, err := offsetManager.ManagePartition("test.1", 0) + if err != nil { + t.Fatal(err) + } + + pom1.MarkOffset(10, "test metadata") + safeClose(t, pom1) + + pom2, err := offsetManager.ManagePartition("test.1", 0) + if err != nil { + t.Fatal(err) + } + + offset, metadata := pom2.NextOffset() + + if offset != 10 { + t.Errorf("Expected the next offset to be 10, found %d.", offset) + } + if metadata != "test metadata" { + t.Errorf("Expected metadata to be 'test metadata', found %s.", metadata) + } + + safeClose(t, pom2) + safeClose(t, offsetManager) + safeClose(t, client) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/functional_producer_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/functional_producer_test.go new file mode 100644 index 00000000..91bf3b5e --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/functional_producer_test.go @@ -0,0 +1,323 @@ +package sarama + +import ( + "fmt" + "os" + "sync" + "testing" + "time" + + toxiproxy "github.com/Shopify/toxiproxy/client" + "github.com/rcrowley/go-metrics" +) + +const TestBatchSize = 1000 + +func TestFuncProducing(t *testing.T) { + config := NewConfig() + testProducingMessages(t, config) +} + +func TestFuncProducingGzip(t *testing.T) { + config := NewConfig() + config.Producer.Compression = CompressionGZIP + testProducingMessages(t, config) +} + +func TestFuncProducingSnappy(t *testing.T) { + config := NewConfig() + config.Producer.Compression = CompressionSnappy + testProducingMessages(t, config) +} + +func TestFuncProducingNoResponse(t *testing.T) { + config := NewConfig() + config.Producer.RequiredAcks = NoResponse + testProducingMessages(t, config) +} + +func TestFuncProducingFlushing(t *testing.T) { + config := NewConfig() + config.Producer.Flush.Messages = TestBatchSize / 8 + config.Producer.Flush.Frequency = 250 * time.Millisecond + testProducingMessages(t, config) +} + +func TestFuncMultiPartitionProduce(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + config := NewConfig() + config.ChannelBufferSize = 20 + config.Producer.Flush.Frequency = 50 * time.Millisecond + config.Producer.Flush.Messages = 200 + config.Producer.Return.Successes = true + producer, err := NewSyncProducer(kafkaBrokers, config) + if err != nil { + t.Fatal(err) + } + + var wg sync.WaitGroup + wg.Add(TestBatchSize) + + for i := 1; i <= TestBatchSize; i++ { + go func(i int) { + defer wg.Done() + msg := &ProducerMessage{Topic: "test.64", Key: nil, Value: StringEncoder(fmt.Sprintf("hur %d", i))} + if _, _, err := producer.SendMessage(msg); err != nil { + t.Error(i, err) + } + }(i) + } + + wg.Wait() + if err := producer.Close(); err != nil { + t.Error(err) + } +} + +func TestFuncProducingToInvalidTopic(t *testing.T) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + producer, err := NewSyncProducer(kafkaBrokers, nil) + if err != nil { + t.Fatal(err) + } + + if _, _, err := producer.SendMessage(&ProducerMessage{Topic: "in/valid"}); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, found", err) + } + + if _, _, err := producer.SendMessage(&ProducerMessage{Topic: "in/valid"}); err != ErrUnknownTopicOrPartition { + t.Error("Expected ErrUnknownTopicOrPartition, found", err) + } + + safeClose(t, producer) +} + +func testProducingMessages(t *testing.T, config *Config) { + setupFunctionalTest(t) + defer teardownFunctionalTest(t) + + // Configure some latency in order to properly validate the request latency metric + for _, proxy := range Proxies { + if _, err := proxy.AddToxic("", "latency", "", 1, toxiproxy.Attributes{"latency": 10}); err != nil { + t.Fatal("Unable to configure latency toxicity", err) + } + } + + config.Producer.Return.Successes = true + config.Consumer.Return.Errors = true + + client, err := NewClient(kafkaBrokers, config) + if err != nil { + t.Fatal(err) + } + + // Keep in mind the current offset + initialOffset, err := client.GetOffset("test.1", 0, OffsetNewest) + if err != nil { + t.Fatal(err) + } + + producer, err := NewAsyncProducerFromClient(client) + if err != nil { + t.Fatal(err) + } + + expectedResponses := TestBatchSize + for i := 1; i <= TestBatchSize; { + msg := &ProducerMessage{Topic: "test.1", Key: nil, Value: StringEncoder(fmt.Sprintf("testing %d", i))} + select { + case producer.Input() <- msg: + i++ + case ret := <-producer.Errors(): + t.Fatal(ret.Err) + case <-producer.Successes(): + expectedResponses-- + } + } + for expectedResponses > 0 { + select { + case ret := <-producer.Errors(): + t.Fatal(ret.Err) + case <-producer.Successes(): + expectedResponses-- + } + } + safeClose(t, producer) + + // Validate producer metrics before using the consumer minus the offset request + validateMetrics(t, client) + + master, err := NewConsumerFromClient(client) + if err != nil { + t.Fatal(err) + } + consumer, err := master.ConsumePartition("test.1", 0, initialOffset) + if err != nil { + t.Fatal(err) + } + + for i := 1; i <= TestBatchSize; i++ { + select { + case <-time.After(10 * time.Second): + t.Fatal("Not received any more events in the last 10 seconds.") + + case err := <-consumer.Errors(): + t.Error(err) + + case message := <-consumer.Messages(): + if string(message.Value) != fmt.Sprintf("testing %d", i) { + t.Fatalf("Unexpected message with index %d: %s", i, message.Value) + } + } + + } + safeClose(t, consumer) + safeClose(t, client) +} + +func validateMetrics(t *testing.T, client Client) { + // Get the broker used by test1 topic + var broker *Broker + if partitions, err := client.Partitions("test.1"); err != nil { + t.Error(err) + } else { + for _, partition := range partitions { + if b, err := client.Leader("test.1", partition); err != nil { + t.Error(err) + } else { + if broker != nil && b != broker { + t.Fatal("Expected only one broker, got at least 2") + } + broker = b + } + } + } + + metricValidators := newMetricValidators() + noResponse := client.Config().Producer.RequiredAcks == NoResponse + compressionEnabled := client.Config().Producer.Compression != CompressionNone + + // We are adding 10ms of latency to all requests with toxiproxy + minRequestLatencyInMs := 10 + if noResponse { + // but when we do not wait for a response it can be less than 1ms + minRequestLatencyInMs = 0 + } + + // We read at least 1 byte from the broker + metricValidators.registerForAllBrokers(broker, minCountMeterValidator("incoming-byte-rate", 1)) + // in at least 3 global requests (1 for metadata request, 1 for offset request and N for produce request) + metricValidators.register(minCountMeterValidator("request-rate", 3)) + metricValidators.register(minCountHistogramValidator("request-size", 3)) + metricValidators.register(minValHistogramValidator("request-size", 1)) + metricValidators.register(minValHistogramValidator("request-latency-in-ms", minRequestLatencyInMs)) + // and at least 2 requests to the registered broker (offset + produces) + metricValidators.registerForBroker(broker, minCountMeterValidator("request-rate", 2)) + metricValidators.registerForBroker(broker, minCountHistogramValidator("request-size", 2)) + metricValidators.registerForBroker(broker, minValHistogramValidator("request-size", 1)) + metricValidators.registerForBroker(broker, minValHistogramValidator("request-latency-in-ms", minRequestLatencyInMs)) + + // We send at least 1 batch + metricValidators.registerForGlobalAndTopic("test_1", minCountHistogramValidator("batch-size", 1)) + metricValidators.registerForGlobalAndTopic("test_1", minValHistogramValidator("batch-size", 1)) + if compressionEnabled { + // We record compression ratios between [0.50,-10.00] (50-1000 with a histogram) for at least one "fake" record + metricValidators.registerForGlobalAndTopic("test_1", minCountHistogramValidator("compression-ratio", 1)) + metricValidators.registerForGlobalAndTopic("test_1", minValHistogramValidator("compression-ratio", 50)) + metricValidators.registerForGlobalAndTopic("test_1", maxValHistogramValidator("compression-ratio", 1000)) + } else { + // We record compression ratios of 1.00 (100 with a histogram) for every TestBatchSize record + metricValidators.registerForGlobalAndTopic("test_1", countHistogramValidator("compression-ratio", TestBatchSize)) + metricValidators.registerForGlobalAndTopic("test_1", minValHistogramValidator("compression-ratio", 100)) + metricValidators.registerForGlobalAndTopic("test_1", maxValHistogramValidator("compression-ratio", 100)) + } + + // We send exactly TestBatchSize messages + metricValidators.registerForGlobalAndTopic("test_1", countMeterValidator("record-send-rate", TestBatchSize)) + // We send at least one record per request + metricValidators.registerForGlobalAndTopic("test_1", minCountHistogramValidator("records-per-request", 1)) + metricValidators.registerForGlobalAndTopic("test_1", minValHistogramValidator("records-per-request", 1)) + + // We receive at least 1 byte from the broker + metricValidators.registerForAllBrokers(broker, minCountMeterValidator("outgoing-byte-rate", 1)) + if noResponse { + // in exactly 2 global responses (metadata + offset) + metricValidators.register(countMeterValidator("response-rate", 2)) + metricValidators.register(minCountHistogramValidator("response-size", 2)) + metricValidators.register(minValHistogramValidator("response-size", 1)) + // and exactly 1 offset response for the registered broker + metricValidators.registerForBroker(broker, countMeterValidator("response-rate", 1)) + metricValidators.registerForBroker(broker, minCountHistogramValidator("response-size", 1)) + metricValidators.registerForBroker(broker, minValHistogramValidator("response-size", 1)) + } else { + // in at least 3 global responses (metadata + offset + produces) + metricValidators.register(minCountMeterValidator("response-rate", 3)) + metricValidators.register(minCountHistogramValidator("response-size", 3)) + metricValidators.register(minValHistogramValidator("response-size", 1)) + // and at least 2 for the registered broker + metricValidators.registerForBroker(broker, minCountMeterValidator("response-rate", 2)) + metricValidators.registerForBroker(broker, minCountHistogramValidator("response-size", 2)) + metricValidators.registerForBroker(broker, minValHistogramValidator("response-size", 1)) + } + + // Run the validators + metricValidators.run(t, client.Config().MetricRegistry) +} + +// Benchmarks + +func BenchmarkProducerSmall(b *testing.B) { + benchmarkProducer(b, nil, "test.64", ByteEncoder(make([]byte, 128))) +} +func BenchmarkProducerMedium(b *testing.B) { + benchmarkProducer(b, nil, "test.64", ByteEncoder(make([]byte, 1024))) +} +func BenchmarkProducerLarge(b *testing.B) { + benchmarkProducer(b, nil, "test.64", ByteEncoder(make([]byte, 8192))) +} +func BenchmarkProducerSmallSinglePartition(b *testing.B) { + benchmarkProducer(b, nil, "test.1", ByteEncoder(make([]byte, 128))) +} +func BenchmarkProducerMediumSnappy(b *testing.B) { + conf := NewConfig() + conf.Producer.Compression = CompressionSnappy + benchmarkProducer(b, conf, "test.1", ByteEncoder(make([]byte, 1024))) +} + +func benchmarkProducer(b *testing.B, conf *Config, topic string, value Encoder) { + setupFunctionalTest(b) + defer teardownFunctionalTest(b) + + metricsDisable := os.Getenv("METRICS_DISABLE") + if metricsDisable != "" { + previousUseNilMetrics := metrics.UseNilMetrics + Logger.Println("Disabling metrics using no-op implementation") + metrics.UseNilMetrics = true + // Restore previous setting + defer func() { + metrics.UseNilMetrics = previousUseNilMetrics + }() + } + + producer, err := NewAsyncProducer(kafkaBrokers, conf) + if err != nil { + b.Fatal(err) + } + + b.ResetTimer() + + for i := 1; i <= b.N; { + msg := &ProducerMessage{Topic: topic, Key: StringEncoder(fmt.Sprintf("%d", i)), Value: value} + select { + case producer.Input() <- msg: + i++ + case ret := <-producer.Errors(): + b.Fatal(ret.Err) + } + } + safeClose(b, producer) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/functional_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/functional_test.go new file mode 100644 index 00000000..846eb29f --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/functional_test.go @@ -0,0 +1,148 @@ +package sarama + +import ( + "log" + "math/rand" + "net" + "os" + "strconv" + "strings" + "testing" + "time" + + toxiproxy "github.com/Shopify/toxiproxy/client" +) + +const ( + VagrantToxiproxy = "http://192.168.100.67:8474" + VagrantKafkaPeers = "192.168.100.67:9091,192.168.100.67:9092,192.168.100.67:9093,192.168.100.67:9094,192.168.100.67:9095" + VagrantZookeeperPeers = "192.168.100.67:2181,192.168.100.67:2182,192.168.100.67:2183,192.168.100.67:2184,192.168.100.67:2185" +) + +var ( + kafkaAvailable, kafkaRequired bool + kafkaBrokers []string + + proxyClient *toxiproxy.Client + Proxies map[string]*toxiproxy.Proxy + ZKProxies = []string{"zk1", "zk2", "zk3", "zk4", "zk5"} + KafkaProxies = []string{"kafka1", "kafka2", "kafka3", "kafka4", "kafka5"} +) + +func init() { + if os.Getenv("DEBUG") == "true" { + Logger = log.New(os.Stdout, "[sarama] ", log.LstdFlags) + } + + seed := time.Now().UTC().UnixNano() + if tmp := os.Getenv("TEST_SEED"); tmp != "" { + seed, _ = strconv.ParseInt(tmp, 0, 64) + } + Logger.Println("Using random seed:", seed) + rand.Seed(seed) + + proxyAddr := os.Getenv("TOXIPROXY_ADDR") + if proxyAddr == "" { + proxyAddr = VagrantToxiproxy + } + proxyClient = toxiproxy.NewClient(proxyAddr) + + kafkaPeers := os.Getenv("KAFKA_PEERS") + if kafkaPeers == "" { + kafkaPeers = VagrantKafkaPeers + } + kafkaBrokers = strings.Split(kafkaPeers, ",") + + if c, err := net.DialTimeout("tcp", kafkaBrokers[0], 5*time.Second); err == nil { + if err = c.Close(); err == nil { + kafkaAvailable = true + } + } + + kafkaRequired = os.Getenv("CI") != "" +} + +func checkKafkaAvailability(t testing.TB) { + if !kafkaAvailable { + if kafkaRequired { + t.Fatalf("Kafka broker is not available on %s. Set KAFKA_PEERS to connect to Kafka on a different location.", kafkaBrokers[0]) + } else { + t.Skipf("Kafka broker is not available on %s. Set KAFKA_PEERS to connect to Kafka on a different location.", kafkaBrokers[0]) + } + } +} + +func checkKafkaVersion(t testing.TB, requiredVersion string) { + kafkaVersion := os.Getenv("KAFKA_VERSION") + if kafkaVersion == "" { + t.Logf("No KAFKA_VERSION set. This test requires Kafka version %s or higher. Continuing...", requiredVersion) + } else { + available := parseKafkaVersion(kafkaVersion) + required := parseKafkaVersion(requiredVersion) + if !available.satisfies(required) { + t.Skipf("Kafka version %s is required for this test; you have %s. Skipping...", requiredVersion, kafkaVersion) + } + } +} + +func resetProxies(t testing.TB) { + if err := proxyClient.ResetState(); err != nil { + t.Error(err) + } + Proxies = nil +} + +func fetchProxies(t testing.TB) { + var err error + Proxies, err = proxyClient.Proxies() + if err != nil { + t.Fatal(err) + } +} + +func SaveProxy(t *testing.T, px string) { + if err := Proxies[px].Save(); err != nil { + t.Fatal(err) + } +} + +func setupFunctionalTest(t testing.TB) { + checkKafkaAvailability(t) + resetProxies(t) + fetchProxies(t) +} + +func teardownFunctionalTest(t testing.TB) { + resetProxies(t) +} + +type kafkaVersion []int + +func (kv kafkaVersion) satisfies(other kafkaVersion) bool { + var ov int + for index, v := range kv { + if len(other) <= index { + ov = 0 + } else { + ov = other[index] + } + + if v < ov { + return false + } else if v > ov { + return true + } + } + return true +} + +func parseKafkaVersion(version string) kafkaVersion { + numbers := strings.Split(version, ".") + result := make(kafkaVersion, 0, len(numbers)) + for _, number := range numbers { + nr, _ := strconv.Atoi(number) + result = append(result, nr) + } + + return result +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_request.go new file mode 100644 index 00000000..ce49c473 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_request.go @@ -0,0 +1,47 @@ +package sarama + +type HeartbeatRequest struct { + GroupId string + GenerationId int32 + MemberId string +} + +func (r *HeartbeatRequest) encode(pe packetEncoder) error { + if err := pe.putString(r.GroupId); err != nil { + return err + } + + pe.putInt32(r.GenerationId) + + if err := pe.putString(r.MemberId); err != nil { + return err + } + + return nil +} + +func (r *HeartbeatRequest) decode(pd packetDecoder, version int16) (err error) { + if r.GroupId, err = pd.getString(); err != nil { + return + } + if r.GenerationId, err = pd.getInt32(); err != nil { + return + } + if r.MemberId, err = pd.getString(); err != nil { + return + } + + return nil +} + +func (r *HeartbeatRequest) key() int16 { + return 12 +} + +func (r *HeartbeatRequest) version() int16 { + return 0 +} + +func (r *HeartbeatRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_request_test.go new file mode 100644 index 00000000..da6cd18f --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_request_test.go @@ -0,0 +1,21 @@ +package sarama + +import "testing" + +var ( + basicHeartbeatRequest = []byte{ + 0, 3, 'f', 'o', 'o', // Group ID + 0x00, 0x01, 0x02, 0x03, // Generatiuon ID + 0, 3, 'b', 'a', 'z', // Member ID + } +) + +func TestHeartbeatRequest(t *testing.T) { + var request *HeartbeatRequest + + request = new(HeartbeatRequest) + request.GroupId = "foo" + request.GenerationId = 66051 + request.MemberId = "baz" + testRequest(t, "basic", request, basicHeartbeatRequest) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_response.go new file mode 100644 index 00000000..3c51163a --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_response.go @@ -0,0 +1,32 @@ +package sarama + +type HeartbeatResponse struct { + Err KError +} + +func (r *HeartbeatResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + return nil +} + +func (r *HeartbeatResponse) decode(pd packetDecoder, version int16) error { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + return nil +} + +func (r *HeartbeatResponse) key() int16 { + return 12 +} + +func (r *HeartbeatResponse) version() int16 { + return 0 +} + +func (r *HeartbeatResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_response_test.go new file mode 100644 index 00000000..5bcbec98 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/heartbeat_response_test.go @@ -0,0 +1,18 @@ +package sarama + +import "testing" + +var ( + heartbeatResponseNoError = []byte{ + 0x00, 0x00} +) + +func TestHeartbeatResponse(t *testing.T) { + var response *HeartbeatResponse + + response = new(HeartbeatResponse) + testVersionDecodable(t, "no error", response, heartbeatResponseNoError, 0) + if response.Err != ErrNoError { + t.Error("Decoding error failed: no error expected but found", response.Err) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_request.go new file mode 100644 index 00000000..656db456 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_request.go @@ -0,0 +1,108 @@ +package sarama + +type JoinGroupRequest struct { + GroupId string + SessionTimeout int32 + MemberId string + ProtocolType string + GroupProtocols map[string][]byte +} + +func (r *JoinGroupRequest) encode(pe packetEncoder) error { + if err := pe.putString(r.GroupId); err != nil { + return err + } + pe.putInt32(r.SessionTimeout) + if err := pe.putString(r.MemberId); err != nil { + return err + } + if err := pe.putString(r.ProtocolType); err != nil { + return err + } + + if err := pe.putArrayLength(len(r.GroupProtocols)); err != nil { + return err + } + for name, metadata := range r.GroupProtocols { + if err := pe.putString(name); err != nil { + return err + } + if err := pe.putBytes(metadata); err != nil { + return err + } + } + + return nil +} + +func (r *JoinGroupRequest) decode(pd packetDecoder, version int16) (err error) { + if r.GroupId, err = pd.getString(); err != nil { + return + } + + if r.SessionTimeout, err = pd.getInt32(); err != nil { + return + } + + if r.MemberId, err = pd.getString(); err != nil { + return + } + + if r.ProtocolType, err = pd.getString(); err != nil { + return + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + if n == 0 { + return nil + } + + r.GroupProtocols = make(map[string][]byte) + for i := 0; i < n; i++ { + name, err := pd.getString() + if err != nil { + return err + } + metadata, err := pd.getBytes() + if err != nil { + return err + } + + r.GroupProtocols[name] = metadata + } + + return nil +} + +func (r *JoinGroupRequest) key() int16 { + return 11 +} + +func (r *JoinGroupRequest) version() int16 { + return 0 +} + +func (r *JoinGroupRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} + +func (r *JoinGroupRequest) AddGroupProtocol(name string, metadata []byte) { + if r.GroupProtocols == nil { + r.GroupProtocols = make(map[string][]byte) + } + + r.GroupProtocols[name] = metadata +} + +func (r *JoinGroupRequest) AddGroupProtocolMetadata(name string, metadata *ConsumerGroupMemberMetadata) error { + bin, err := encode(metadata, nil) + if err != nil { + return err + } + + r.AddGroupProtocol(name, bin) + return nil +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_request_test.go new file mode 100644 index 00000000..8a6448c0 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_request_test.go @@ -0,0 +1,41 @@ +package sarama + +import "testing" + +var ( + joinGroupRequestNoProtocols = []byte{ + 0, 9, 'T', 'e', 's', 't', 'G', 'r', 'o', 'u', 'p', // Group ID + 0, 0, 0, 100, // Session timeout + 0, 0, // Member ID + 0, 8, 'c', 'o', 'n', 's', 'u', 'm', 'e', 'r', // Protocol Type + 0, 0, 0, 0, // 0 protocol groups + } + + joinGroupRequestOneProtocol = []byte{ + 0, 9, 'T', 'e', 's', 't', 'G', 'r', 'o', 'u', 'p', // Group ID + 0, 0, 0, 100, // Session timeout + 0, 11, 'O', 'n', 'e', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', // Member ID + 0, 8, 'c', 'o', 'n', 's', 'u', 'm', 'e', 'r', // Protocol Type + 0, 0, 0, 1, // 1 group protocol + 0, 3, 'o', 'n', 'e', // Protocol name + 0, 0, 0, 3, 0x01, 0x02, 0x03, // protocol metadata + } +) + +func TestJoinGroupRequest(t *testing.T) { + var request *JoinGroupRequest + + request = new(JoinGroupRequest) + request.GroupId = "TestGroup" + request.SessionTimeout = 100 + request.ProtocolType = "consumer" + testRequest(t, "no protocols", request, joinGroupRequestNoProtocols) + + request = new(JoinGroupRequest) + request.GroupId = "TestGroup" + request.SessionTimeout = 100 + request.MemberId = "OneProtocol" + request.ProtocolType = "consumer" + request.AddGroupProtocol("one", []byte{0x01, 0x02, 0x03}) + testRequest(t, "one protocol", request, joinGroupRequestOneProtocol) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_response.go new file mode 100644 index 00000000..94c7a7fd --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_response.go @@ -0,0 +1,114 @@ +package sarama + +type JoinGroupResponse struct { + Err KError + GenerationId int32 + GroupProtocol string + LeaderId string + MemberId string + Members map[string][]byte +} + +func (r *JoinGroupResponse) GetMembers() (map[string]ConsumerGroupMemberMetadata, error) { + members := make(map[string]ConsumerGroupMemberMetadata, len(r.Members)) + for id, bin := range r.Members { + meta := new(ConsumerGroupMemberMetadata) + if err := decode(bin, meta); err != nil { + return nil, err + } + members[id] = *meta + } + return members, nil +} + +func (r *JoinGroupResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + pe.putInt32(r.GenerationId) + + if err := pe.putString(r.GroupProtocol); err != nil { + return err + } + if err := pe.putString(r.LeaderId); err != nil { + return err + } + if err := pe.putString(r.MemberId); err != nil { + return err + } + + if err := pe.putArrayLength(len(r.Members)); err != nil { + return err + } + + for memberId, memberMetadata := range r.Members { + if err := pe.putString(memberId); err != nil { + return err + } + + if err := pe.putBytes(memberMetadata); err != nil { + return err + } + } + + return nil +} + +func (r *JoinGroupResponse) decode(pd packetDecoder, version int16) (err error) { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + if r.GenerationId, err = pd.getInt32(); err != nil { + return + } + + if r.GroupProtocol, err = pd.getString(); err != nil { + return + } + + if r.LeaderId, err = pd.getString(); err != nil { + return + } + + if r.MemberId, err = pd.getString(); err != nil { + return + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + if n == 0 { + return nil + } + + r.Members = make(map[string][]byte) + for i := 0; i < n; i++ { + memberId, err := pd.getString() + if err != nil { + return err + } + + memberMetadata, err := pd.getBytes() + if err != nil { + return err + } + + r.Members[memberId] = memberMetadata + } + + return nil +} + +func (r *JoinGroupResponse) key() int16 { + return 11 +} + +func (r *JoinGroupResponse) version() int16 { + return 0 +} + +func (r *JoinGroupResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_response_test.go new file mode 100644 index 00000000..ba7f71f2 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/join_group_response_test.go @@ -0,0 +1,98 @@ +package sarama + +import ( + "reflect" + "testing" +) + +var ( + joinGroupResponseNoError = []byte{ + 0x00, 0x00, // No error + 0x00, 0x01, 0x02, 0x03, // Generation ID + 0, 8, 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', // Protocol name chosen + 0, 3, 'f', 'o', 'o', // Leader ID + 0, 3, 'b', 'a', 'r', // Member ID + 0, 0, 0, 0, // No member info + } + + joinGroupResponseWithError = []byte{ + 0, 23, // Error: inconsistent group protocol + 0x00, 0x00, 0x00, 0x00, // Generation ID + 0, 0, // Protocol name chosen + 0, 0, // Leader ID + 0, 0, // Member ID + 0, 0, 0, 0, // No member info + } + + joinGroupResponseLeader = []byte{ + 0x00, 0x00, // No error + 0x00, 0x01, 0x02, 0x03, // Generation ID + 0, 8, 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', // Protocol name chosen + 0, 3, 'f', 'o', 'o', // Leader ID + 0, 3, 'f', 'o', 'o', // Member ID == Leader ID + 0, 0, 0, 1, // 1 member + 0, 3, 'f', 'o', 'o', // Member ID + 0, 0, 0, 3, 0x01, 0x02, 0x03, // Member metadata + } +) + +func TestJoinGroupResponse(t *testing.T) { + var response *JoinGroupResponse + + response = new(JoinGroupResponse) + testVersionDecodable(t, "no error", response, joinGroupResponseNoError, 0) + if response.Err != ErrNoError { + t.Error("Decoding Err failed: no error expected but found", response.Err) + } + if response.GenerationId != 66051 { + t.Error("Decoding GenerationId failed, found:", response.GenerationId) + } + if response.LeaderId != "foo" { + t.Error("Decoding LeaderId failed, found:", response.LeaderId) + } + if response.MemberId != "bar" { + t.Error("Decoding MemberId failed, found:", response.MemberId) + } + if len(response.Members) != 0 { + t.Error("Decoding Members failed, found:", response.Members) + } + + response = new(JoinGroupResponse) + testVersionDecodable(t, "with error", response, joinGroupResponseWithError, 0) + if response.Err != ErrInconsistentGroupProtocol { + t.Error("Decoding Err failed: ErrInconsistentGroupProtocol expected but found", response.Err) + } + if response.GenerationId != 0 { + t.Error("Decoding GenerationId failed, found:", response.GenerationId) + } + if response.LeaderId != "" { + t.Error("Decoding LeaderId failed, found:", response.LeaderId) + } + if response.MemberId != "" { + t.Error("Decoding MemberId failed, found:", response.MemberId) + } + if len(response.Members) != 0 { + t.Error("Decoding Members failed, found:", response.Members) + } + + response = new(JoinGroupResponse) + testVersionDecodable(t, "with error", response, joinGroupResponseLeader, 0) + if response.Err != ErrNoError { + t.Error("Decoding Err failed: ErrNoError expected but found", response.Err) + } + if response.GenerationId != 66051 { + t.Error("Decoding GenerationId failed, found:", response.GenerationId) + } + if response.LeaderId != "foo" { + t.Error("Decoding LeaderId failed, found:", response.LeaderId) + } + if response.MemberId != "foo" { + t.Error("Decoding MemberId failed, found:", response.MemberId) + } + if len(response.Members) != 1 { + t.Error("Decoding Members failed, found:", response.Members) + } + if !reflect.DeepEqual(response.Members["foo"], []byte{0x01, 0x02, 0x03}) { + t.Error("Decoding foo member failed, found:", response.Members["foo"]) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_request.go new file mode 100644 index 00000000..e1774274 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_request.go @@ -0,0 +1,40 @@ +package sarama + +type LeaveGroupRequest struct { + GroupId string + MemberId string +} + +func (r *LeaveGroupRequest) encode(pe packetEncoder) error { + if err := pe.putString(r.GroupId); err != nil { + return err + } + if err := pe.putString(r.MemberId); err != nil { + return err + } + + return nil +} + +func (r *LeaveGroupRequest) decode(pd packetDecoder, version int16) (err error) { + if r.GroupId, err = pd.getString(); err != nil { + return + } + if r.MemberId, err = pd.getString(); err != nil { + return + } + + return nil +} + +func (r *LeaveGroupRequest) key() int16 { + return 13 +} + +func (r *LeaveGroupRequest) version() int16 { + return 0 +} + +func (r *LeaveGroupRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_request_test.go new file mode 100644 index 00000000..c1fed6d2 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_request_test.go @@ -0,0 +1,19 @@ +package sarama + +import "testing" + +var ( + basicLeaveGroupRequest = []byte{ + 0, 3, 'f', 'o', 'o', + 0, 3, 'b', 'a', 'r', + } +) + +func TestLeaveGroupRequest(t *testing.T) { + var request *LeaveGroupRequest + + request = new(LeaveGroupRequest) + request.GroupId = "foo" + request.MemberId = "bar" + testRequest(t, "basic", request, basicLeaveGroupRequest) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_response.go new file mode 100644 index 00000000..bd4a34f4 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_response.go @@ -0,0 +1,32 @@ +package sarama + +type LeaveGroupResponse struct { + Err KError +} + +func (r *LeaveGroupResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + return nil +} + +func (r *LeaveGroupResponse) decode(pd packetDecoder, version int16) (err error) { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + return nil +} + +func (r *LeaveGroupResponse) key() int16 { + return 13 +} + +func (r *LeaveGroupResponse) version() int16 { + return 0 +} + +func (r *LeaveGroupResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_response_test.go new file mode 100644 index 00000000..9207c666 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/leave_group_response_test.go @@ -0,0 +1,24 @@ +package sarama + +import "testing" + +var ( + leaveGroupResponseNoError = []byte{0x00, 0x00} + leaveGroupResponseWithError = []byte{0, 25} +) + +func TestLeaveGroupResponse(t *testing.T) { + var response *LeaveGroupResponse + + response = new(LeaveGroupResponse) + testVersionDecodable(t, "no error", response, leaveGroupResponseNoError, 0) + if response.Err != ErrNoError { + t.Error("Decoding error failed: no error expected but found", response.Err) + } + + response = new(LeaveGroupResponse) + testVersionDecodable(t, "with error", response, leaveGroupResponseWithError, 0) + if response.Err != ErrUnknownMemberId { + t.Error("Decoding error failed: ErrUnknownMemberId expected but found", response.Err) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/length_field.go b/vendor/src/gopkg.in/Shopify/sarama.v1/length_field.go new file mode 100644 index 00000000..70078be5 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/length_field.go @@ -0,0 +1,29 @@ +package sarama + +import "encoding/binary" + +// LengthField implements the PushEncoder and PushDecoder interfaces for calculating 4-byte lengths. +type lengthField struct { + startOffset int +} + +func (l *lengthField) saveOffset(in int) { + l.startOffset = in +} + +func (l *lengthField) reserveLength() int { + return 4 +} + +func (l *lengthField) run(curOffset int, buf []byte) error { + binary.BigEndian.PutUint32(buf[l.startOffset:], uint32(curOffset-l.startOffset-4)) + return nil +} + +func (l *lengthField) check(curOffset int, buf []byte) error { + if uint32(curOffset-l.startOffset-4) != binary.BigEndian.Uint32(buf[l.startOffset:]) { + return PacketDecodingError{"length field invalid"} + } + + return nil +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_request.go new file mode 100644 index 00000000..3b16abf7 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_request.go @@ -0,0 +1,24 @@ +package sarama + +type ListGroupsRequest struct { +} + +func (r *ListGroupsRequest) encode(pe packetEncoder) error { + return nil +} + +func (r *ListGroupsRequest) decode(pd packetDecoder, version int16) (err error) { + return nil +} + +func (r *ListGroupsRequest) key() int16 { + return 16 +} + +func (r *ListGroupsRequest) version() int16 { + return 0 +} + +func (r *ListGroupsRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_request_test.go new file mode 100644 index 00000000..2e977d9a --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_request_test.go @@ -0,0 +1,7 @@ +package sarama + +import "testing" + +func TestListGroupsRequest(t *testing.T) { + testRequest(t, "ListGroupsRequest", &ListGroupsRequest{}, []byte{}) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_response.go new file mode 100644 index 00000000..3a84f9b6 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_response.go @@ -0,0 +1,68 @@ +package sarama + +type ListGroupsResponse struct { + Err KError + Groups map[string]string +} + +func (r *ListGroupsResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + + if err := pe.putArrayLength(len(r.Groups)); err != nil { + return err + } + for groupId, protocolType := range r.Groups { + if err := pe.putString(groupId); err != nil { + return err + } + if err := pe.putString(protocolType); err != nil { + return err + } + } + + return nil +} + +func (r *ListGroupsResponse) decode(pd packetDecoder, version int16) error { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + if n == 0 { + return nil + } + + r.Groups = make(map[string]string) + for i := 0; i < n; i++ { + groupId, err := pd.getString() + if err != nil { + return err + } + protocolType, err := pd.getString() + if err != nil { + return err + } + + r.Groups[groupId] = protocolType + } + + return nil +} + +func (r *ListGroupsResponse) key() int16 { + return 16 +} + +func (r *ListGroupsResponse) version() int16 { + return 0 +} + +func (r *ListGroupsResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_response_test.go new file mode 100644 index 00000000..41ab822f --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/list_groups_response_test.go @@ -0,0 +1,58 @@ +package sarama + +import ( + "testing" +) + +var ( + listGroupsResponseEmpty = []byte{ + 0, 0, // no error + 0, 0, 0, 0, // no groups + } + + listGroupsResponseError = []byte{ + 0, 31, // no error + 0, 0, 0, 0, // ErrClusterAuthorizationFailed + } + + listGroupsResponseWithConsumer = []byte{ + 0, 0, // no error + 0, 0, 0, 1, // 1 group + 0, 3, 'f', 'o', 'o', // group name + 0, 8, 'c', 'o', 'n', 's', 'u', 'm', 'e', 'r', // protocol type + } +) + +func TestListGroupsResponse(t *testing.T) { + var response *ListGroupsResponse + + response = new(ListGroupsResponse) + testVersionDecodable(t, "no error", response, listGroupsResponseEmpty, 0) + if response.Err != ErrNoError { + t.Error("Expected no gerror, found:", response.Err) + } + if len(response.Groups) != 0 { + t.Error("Expected no groups") + } + + response = new(ListGroupsResponse) + testVersionDecodable(t, "no error", response, listGroupsResponseError, 0) + if response.Err != ErrClusterAuthorizationFailed { + t.Error("Expected no gerror, found:", response.Err) + } + if len(response.Groups) != 0 { + t.Error("Expected no groups") + } + + response = new(ListGroupsResponse) + testVersionDecodable(t, "no error", response, listGroupsResponseWithConsumer, 0) + if response.Err != ErrNoError { + t.Error("Expected no gerror, found:", response.Err) + } + if len(response.Groups) != 1 { + t.Error("Expected one group") + } + if response.Groups["foo"] != "consumer" { + t.Error("Expected foo group to use consumer protocol") + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/message.go b/vendor/src/gopkg.in/Shopify/sarama.v1/message.go new file mode 100644 index 00000000..327c5fa2 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/message.go @@ -0,0 +1,196 @@ +package sarama + +import ( + "bytes" + "compress/gzip" + "fmt" + "io/ioutil" + "time" + + "github.com/eapache/go-xerial-snappy" + "github.com/pierrec/lz4" +) + +// CompressionCodec represents the various compression codecs recognized by Kafka in messages. +type CompressionCodec int8 + +// only the last two bits are really used +const compressionCodecMask int8 = 0x03 + +const ( + CompressionNone CompressionCodec = 0 + CompressionGZIP CompressionCodec = 1 + CompressionSnappy CompressionCodec = 2 + CompressionLZ4 CompressionCodec = 3 +) + +type Message struct { + Codec CompressionCodec // codec used to compress the message contents + Key []byte // the message key, may be nil + Value []byte // the message contents + Set *MessageSet // the message set a message might wrap + Version int8 // v1 requires Kafka 0.10 + Timestamp time.Time // the timestamp of the message (version 1+ only) + + compressedCache []byte + compressedSize int // used for computing the compression ratio metrics +} + +func (m *Message) encode(pe packetEncoder) error { + pe.push(&crc32Field{}) + + pe.putInt8(m.Version) + + attributes := int8(m.Codec) & compressionCodecMask + pe.putInt8(attributes) + + if m.Version >= 1 { + pe.putInt64(m.Timestamp.UnixNano() / int64(time.Millisecond)) + } + + err := pe.putBytes(m.Key) + if err != nil { + return err + } + + var payload []byte + + if m.compressedCache != nil { + payload = m.compressedCache + m.compressedCache = nil + } else if m.Value != nil { + switch m.Codec { + case CompressionNone: + payload = m.Value + case CompressionGZIP: + var buf bytes.Buffer + writer := gzip.NewWriter(&buf) + if _, err = writer.Write(m.Value); err != nil { + return err + } + if err = writer.Close(); err != nil { + return err + } + m.compressedCache = buf.Bytes() + payload = m.compressedCache + case CompressionSnappy: + tmp := snappy.Encode(m.Value) + m.compressedCache = tmp + payload = m.compressedCache + case CompressionLZ4: + var buf bytes.Buffer + writer := lz4.NewWriter(&buf) + if _, err = writer.Write(m.Value); err != nil { + return err + } + if err = writer.Close(); err != nil { + return err + } + m.compressedCache = buf.Bytes() + payload = m.compressedCache + + default: + return PacketEncodingError{fmt.Sprintf("unsupported compression codec (%d)", m.Codec)} + } + // Keep in mind the compressed payload size for metric gathering + m.compressedSize = len(payload) + } + + if err = pe.putBytes(payload); err != nil { + return err + } + + return pe.pop() +} + +func (m *Message) decode(pd packetDecoder) (err error) { + err = pd.push(&crc32Field{}) + if err != nil { + return err + } + + m.Version, err = pd.getInt8() + if err != nil { + return err + } + + attribute, err := pd.getInt8() + if err != nil { + return err + } + m.Codec = CompressionCodec(attribute & compressionCodecMask) + + if m.Version >= 1 { + millis, err := pd.getInt64() + if err != nil { + return err + } + m.Timestamp = time.Unix(millis/1000, (millis%1000)*int64(time.Millisecond)) + } + + m.Key, err = pd.getBytes() + if err != nil { + return err + } + + m.Value, err = pd.getBytes() + if err != nil { + return err + } + + // Required for deep equal assertion during tests but might be useful + // for future metrics about the compression ratio in fetch requests + m.compressedSize = len(m.Value) + + switch m.Codec { + case CompressionNone: + // nothing to do + case CompressionGZIP: + if m.Value == nil { + break + } + reader, err := gzip.NewReader(bytes.NewReader(m.Value)) + if err != nil { + return err + } + if m.Value, err = ioutil.ReadAll(reader); err != nil { + return err + } + if err := m.decodeSet(); err != nil { + return err + } + case CompressionSnappy: + if m.Value == nil { + break + } + if m.Value, err = snappy.Decode(m.Value); err != nil { + return err + } + if err := m.decodeSet(); err != nil { + return err + } + case CompressionLZ4: + if m.Value == nil { + break + } + reader := lz4.NewReader(bytes.NewReader(m.Value)) + if m.Value, err = ioutil.ReadAll(reader); err != nil { + return err + } + if err := m.decodeSet(); err != nil { + return err + } + + default: + return PacketDecodingError{fmt.Sprintf("invalid compression specified (%d)", m.Codec)} + } + + return pd.pop() +} + +// decodes a message set from a previousy encoded bulk-message +func (m *Message) decodeSet() (err error) { + pd := realDecoder{raw: m.Value} + m.Set = &MessageSet{} + return m.Set.decode(&pd) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/message_set.go b/vendor/src/gopkg.in/Shopify/sarama.v1/message_set.go new file mode 100644 index 00000000..f028784e --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/message_set.go @@ -0,0 +1,89 @@ +package sarama + +type MessageBlock struct { + Offset int64 + Msg *Message +} + +// Messages convenience helper which returns either all the +// messages that are wrapped in this block +func (msb *MessageBlock) Messages() []*MessageBlock { + if msb.Msg.Set != nil { + return msb.Msg.Set.Messages + } + return []*MessageBlock{msb} +} + +func (msb *MessageBlock) encode(pe packetEncoder) error { + pe.putInt64(msb.Offset) + pe.push(&lengthField{}) + err := msb.Msg.encode(pe) + if err != nil { + return err + } + return pe.pop() +} + +func (msb *MessageBlock) decode(pd packetDecoder) (err error) { + if msb.Offset, err = pd.getInt64(); err != nil { + return err + } + + if err = pd.push(&lengthField{}); err != nil { + return err + } + + msb.Msg = new(Message) + if err = msb.Msg.decode(pd); err != nil { + return err + } + + if err = pd.pop(); err != nil { + return err + } + + return nil +} + +type MessageSet struct { + PartialTrailingMessage bool // whether the set on the wire contained an incomplete trailing MessageBlock + Messages []*MessageBlock +} + +func (ms *MessageSet) encode(pe packetEncoder) error { + for i := range ms.Messages { + err := ms.Messages[i].encode(pe) + if err != nil { + return err + } + } + return nil +} + +func (ms *MessageSet) decode(pd packetDecoder) (err error) { + ms.Messages = nil + + for pd.remaining() > 0 { + msb := new(MessageBlock) + err = msb.decode(pd) + switch err { + case nil: + ms.Messages = append(ms.Messages, msb) + case ErrInsufficientData: + // As an optimization the server is allowed to return a partial message at the + // end of the message set. Clients should handle this case. So we just ignore such things. + ms.PartialTrailingMessage = true + return nil + default: + return err + } + } + + return nil +} + +func (ms *MessageSet) addMessage(msg *Message) { + block := new(MessageBlock) + block.Msg = msg + ms.Messages = append(ms.Messages, block) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/message_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/message_test.go new file mode 100644 index 00000000..af70b7b1 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/message_test.go @@ -0,0 +1,165 @@ +package sarama + +import ( + "testing" + "time" +) + +var ( + emptyMessage = []byte{ + 167, 236, 104, 3, // CRC + 0x00, // magic version byte + 0x00, // attribute flags + 0xFF, 0xFF, 0xFF, 0xFF, // key + 0xFF, 0xFF, 0xFF, 0xFF} // value + + emptyGzipMessage = []byte{ + 97, 79, 149, 90, //CRC + 0x00, // magic version byte + 0x01, // attribute flags + 0xFF, 0xFF, 0xFF, 0xFF, // key + // value + 0x00, 0x00, 0x00, 0x17, + 0x1f, 0x8b, + 0x08, + 0, 0, 9, 110, 136, 0, 255, 1, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0} + + emptyLZ4Message = []byte{ + 132, 219, 238, 101, // CRC + 0x01, // version byte + 0x03, // attribute flags: lz4 + 0, 0, 1, 88, 141, 205, 89, 56, // timestamp + 0xFF, 0xFF, 0xFF, 0xFF, // key + 0x00, 0x00, 0x00, 0x0f, // len + 0x04, 0x22, 0x4D, 0x18, // LZ4 magic number + 100, // LZ4 flags: version 01, block indepedant, content checksum + 112, 185, 0, 0, 0, 0, // LZ4 data + 5, 93, 204, 2, // LZ4 checksum + } + + emptyBulkSnappyMessage = []byte{ + 180, 47, 53, 209, //CRC + 0x00, // magic version byte + 0x02, // attribute flags + 0xFF, 0xFF, 0xFF, 0xFF, // key + 0, 0, 0, 42, + 130, 83, 78, 65, 80, 80, 89, 0, // SNAPPY magic + 0, 0, 0, 1, // min version + 0, 0, 0, 1, // default version + 0, 0, 0, 22, 52, 0, 0, 25, 1, 16, 14, 227, 138, 104, 118, 25, 15, 13, 1, 8, 1, 0, 0, 62, 26, 0} + + emptyBulkGzipMessage = []byte{ + 139, 160, 63, 141, //CRC + 0x00, // magic version byte + 0x01, // attribute flags + 0xFF, 0xFF, 0xFF, 0xFF, // key + 0x00, 0x00, 0x00, 0x27, // len + 0x1f, 0x8b, // Gzip Magic + 0x08, // deflate compressed + 0, 0, 0, 0, 0, 0, 0, 99, 96, 128, 3, 190, 202, 112, 143, 7, 12, 12, 255, 129, 0, 33, 200, 192, 136, 41, 3, 0, 199, 226, 155, 70, 52, 0, 0, 0} + + emptyBulkLZ4Message = []byte{ + 246, 12, 188, 129, // CRC + 0x01, // Version + 0x03, // attribute flags (LZ4) + 255, 255, 249, 209, 212, 181, 73, 201, // timestamp + 0xFF, 0xFF, 0xFF, 0xFF, // key + 0x00, 0x00, 0x00, 0x47, // len + 0x04, 0x22, 0x4D, 0x18, // magic number lz4 + 100, // lz4 flags 01100100 + // version: 01, block indep: 1, block checksum: 0, content size: 0, content checksum: 1, reserved: 00 + 112, 185, 52, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 121, 87, 72, 224, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 14, 121, 87, 72, 224, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, + 71, 129, 23, 111, // LZ4 checksum + } +) + +func TestMessageEncoding(t *testing.T) { + message := Message{} + testEncodable(t, "empty", &message, emptyMessage) + + message.Value = []byte{} + message.Codec = CompressionGZIP + testEncodable(t, "empty gzip", &message, emptyGzipMessage) + + message.Value = []byte{} + message.Codec = CompressionLZ4 + message.Timestamp = time.Unix(1479847795, 0) + message.Version = 1 + testEncodable(t, "empty lz4", &message, emptyLZ4Message) +} + +func TestMessageDecoding(t *testing.T) { + message := Message{} + testDecodable(t, "empty", &message, emptyMessage) + if message.Codec != CompressionNone { + t.Error("Decoding produced compression codec where there was none.") + } + if message.Key != nil { + t.Error("Decoding produced key where there was none.") + } + if message.Value != nil { + t.Error("Decoding produced value where there was none.") + } + if message.Set != nil { + t.Error("Decoding produced set where there was none.") + } + + testDecodable(t, "empty gzip", &message, emptyGzipMessage) + if message.Codec != CompressionGZIP { + t.Error("Decoding produced incorrect compression codec (was gzip).") + } + if message.Key != nil { + t.Error("Decoding produced key where there was none.") + } + if message.Value == nil || len(message.Value) != 0 { + t.Error("Decoding produced nil or content-ful value where there was an empty array.") + } +} + +func TestMessageDecodingBulkSnappy(t *testing.T) { + message := Message{} + testDecodable(t, "bulk snappy", &message, emptyBulkSnappyMessage) + if message.Codec != CompressionSnappy { + t.Errorf("Decoding produced codec %d, but expected %d.", message.Codec, CompressionSnappy) + } + if message.Key != nil { + t.Errorf("Decoding produced key %+v, but none was expected.", message.Key) + } + if message.Set == nil { + t.Error("Decoding produced no set, but one was expected.") + } else if len(message.Set.Messages) != 2 { + t.Errorf("Decoding produced a set with %d messages, but 2 were expected.", len(message.Set.Messages)) + } +} + +func TestMessageDecodingBulkGzip(t *testing.T) { + message := Message{} + testDecodable(t, "bulk gzip", &message, emptyBulkGzipMessage) + if message.Codec != CompressionGZIP { + t.Errorf("Decoding produced codec %d, but expected %d.", message.Codec, CompressionGZIP) + } + if message.Key != nil { + t.Errorf("Decoding produced key %+v, but none was expected.", message.Key) + } + if message.Set == nil { + t.Error("Decoding produced no set, but one was expected.") + } else if len(message.Set.Messages) != 2 { + t.Errorf("Decoding produced a set with %d messages, but 2 were expected.", len(message.Set.Messages)) + } +} + +func TestMessageDecodingBulkLZ4(t *testing.T) { + message := Message{} + testDecodable(t, "bulk lz4", &message, emptyBulkLZ4Message) + if message.Codec != CompressionLZ4 { + t.Errorf("Decoding produced codec %d, but expected %d.", message.Codec, CompressionLZ4) + } + if message.Key != nil { + t.Errorf("Decoding produced key %+v, but none was expected.", message.Key) + } + if message.Set == nil { + t.Error("Decoding produced no set, but one was expected.") + } else if len(message.Set.Messages) != 2 { + t.Errorf("Decoding produced a set with %d messages, but 2 were expected.", len(message.Set.Messages)) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_request.go new file mode 100644 index 00000000..9a26b55f --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_request.go @@ -0,0 +1,52 @@ +package sarama + +type MetadataRequest struct { + Topics []string +} + +func (r *MetadataRequest) encode(pe packetEncoder) error { + err := pe.putArrayLength(len(r.Topics)) + if err != nil { + return err + } + + for i := range r.Topics { + err = pe.putString(r.Topics[i]) + if err != nil { + return err + } + } + return nil +} + +func (r *MetadataRequest) decode(pd packetDecoder, version int16) error { + topicCount, err := pd.getArrayLength() + if err != nil { + return err + } + if topicCount == 0 { + return nil + } + + r.Topics = make([]string, topicCount) + for i := range r.Topics { + topic, err := pd.getString() + if err != nil { + return err + } + r.Topics[i] = topic + } + return nil +} + +func (r *MetadataRequest) key() int16 { + return 3 +} + +func (r *MetadataRequest) version() int16 { + return 0 +} + +func (r *MetadataRequest) requiredVersion() KafkaVersion { + return minVersion +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_request_test.go new file mode 100644 index 00000000..44f3146e --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_request_test.go @@ -0,0 +1,29 @@ +package sarama + +import "testing" + +var ( + metadataRequestNoTopics = []byte{ + 0x00, 0x00, 0x00, 0x00} + + metadataRequestOneTopic = []byte{ + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x06, 't', 'o', 'p', 'i', 'c', '1'} + + metadataRequestThreeTopics = []byte{ + 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 'f', 'o', 'o', + 0x00, 0x03, 'b', 'a', 'r', + 0x00, 0x03, 'b', 'a', 'z'} +) + +func TestMetadataRequest(t *testing.T) { + request := new(MetadataRequest) + testRequest(t, "no topics", request, metadataRequestNoTopics) + + request.Topics = []string{"topic1"} + testRequest(t, "one topic", request, metadataRequestOneTopic) + + request.Topics = []string{"foo", "bar", "baz"} + testRequest(t, "three topics", request, metadataRequestThreeTopics) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_response.go new file mode 100644 index 00000000..f9d6a427 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_response.go @@ -0,0 +1,239 @@ +package sarama + +type PartitionMetadata struct { + Err KError + ID int32 + Leader int32 + Replicas []int32 + Isr []int32 +} + +func (pm *PartitionMetadata) decode(pd packetDecoder) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + pm.Err = KError(tmp) + + pm.ID, err = pd.getInt32() + if err != nil { + return err + } + + pm.Leader, err = pd.getInt32() + if err != nil { + return err + } + + pm.Replicas, err = pd.getInt32Array() + if err != nil { + return err + } + + pm.Isr, err = pd.getInt32Array() + if err != nil { + return err + } + + return nil +} + +func (pm *PartitionMetadata) encode(pe packetEncoder) (err error) { + pe.putInt16(int16(pm.Err)) + pe.putInt32(pm.ID) + pe.putInt32(pm.Leader) + + err = pe.putInt32Array(pm.Replicas) + if err != nil { + return err + } + + err = pe.putInt32Array(pm.Isr) + if err != nil { + return err + } + + return nil +} + +type TopicMetadata struct { + Err KError + Name string + Partitions []*PartitionMetadata +} + +func (tm *TopicMetadata) decode(pd packetDecoder) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + tm.Err = KError(tmp) + + tm.Name, err = pd.getString() + if err != nil { + return err + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + tm.Partitions = make([]*PartitionMetadata, n) + for i := 0; i < n; i++ { + tm.Partitions[i] = new(PartitionMetadata) + err = tm.Partitions[i].decode(pd) + if err != nil { + return err + } + } + + return nil +} + +func (tm *TopicMetadata) encode(pe packetEncoder) (err error) { + pe.putInt16(int16(tm.Err)) + + err = pe.putString(tm.Name) + if err != nil { + return err + } + + err = pe.putArrayLength(len(tm.Partitions)) + if err != nil { + return err + } + + for _, pm := range tm.Partitions { + err = pm.encode(pe) + if err != nil { + return err + } + } + + return nil +} + +type MetadataResponse struct { + Brokers []*Broker + Topics []*TopicMetadata +} + +func (r *MetadataResponse) decode(pd packetDecoder, version int16) (err error) { + n, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Brokers = make([]*Broker, n) + for i := 0; i < n; i++ { + r.Brokers[i] = new(Broker) + err = r.Brokers[i].decode(pd) + if err != nil { + return err + } + } + + n, err = pd.getArrayLength() + if err != nil { + return err + } + + r.Topics = make([]*TopicMetadata, n) + for i := 0; i < n; i++ { + r.Topics[i] = new(TopicMetadata) + err = r.Topics[i].decode(pd) + if err != nil { + return err + } + } + + return nil +} + +func (r *MetadataResponse) encode(pe packetEncoder) error { + err := pe.putArrayLength(len(r.Brokers)) + if err != nil { + return err + } + for _, broker := range r.Brokers { + err = broker.encode(pe) + if err != nil { + return err + } + } + + err = pe.putArrayLength(len(r.Topics)) + if err != nil { + return err + } + for _, tm := range r.Topics { + err = tm.encode(pe) + if err != nil { + return err + } + } + + return nil +} + +func (r *MetadataResponse) key() int16 { + return 3 +} + +func (r *MetadataResponse) version() int16 { + return 0 +} + +func (r *MetadataResponse) requiredVersion() KafkaVersion { + return minVersion +} + +// testing API + +func (r *MetadataResponse) AddBroker(addr string, id int32) { + r.Brokers = append(r.Brokers, &Broker{id: id, addr: addr}) +} + +func (r *MetadataResponse) AddTopic(topic string, err KError) *TopicMetadata { + var tmatch *TopicMetadata + + for _, tm := range r.Topics { + if tm.Name == topic { + tmatch = tm + goto foundTopic + } + } + + tmatch = new(TopicMetadata) + tmatch.Name = topic + r.Topics = append(r.Topics, tmatch) + +foundTopic: + + tmatch.Err = err + return tmatch +} + +func (r *MetadataResponse) AddTopicPartition(topic string, partition, brokerID int32, replicas, isr []int32, err KError) { + tmatch := r.AddTopic(topic, ErrNoError) + var pmatch *PartitionMetadata + + for _, pm := range tmatch.Partitions { + if pm.ID == partition { + pmatch = pm + goto foundPartition + } + } + + pmatch = new(PartitionMetadata) + pmatch.ID = partition + tmatch.Partitions = append(tmatch.Partitions, pmatch) + +foundPartition: + + pmatch.Leader = brokerID + pmatch.Replicas = replicas + pmatch.Isr = isr + pmatch.Err = err + +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_response_test.go new file mode 100644 index 00000000..ea62a4f1 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/metadata_response_test.go @@ -0,0 +1,139 @@ +package sarama + +import "testing" + +var ( + emptyMetadataResponse = []byte{ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} + + brokersNoTopicsMetadataResponse = []byte{ + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x00, 0xab, 0xff, + 0x00, 0x09, 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', + 0x00, 0x00, 0x00, 0x33, + + 0x00, 0x01, 0x02, 0x03, + 0x00, 0x0a, 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', + 0x00, 0x00, 0x01, 0x11, + + 0x00, 0x00, 0x00, 0x00} + + topicsNoBrokersMetadataResponse = []byte{ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x00, + 0x00, 0x03, 'f', 'o', 'o', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, + 0x00, 0x03, 'b', 'a', 'r', + 0x00, 0x00, 0x00, 0x00} +) + +func TestEmptyMetadataResponse(t *testing.T) { + response := MetadataResponse{} + + testVersionDecodable(t, "empty", &response, emptyMetadataResponse, 0) + if len(response.Brokers) != 0 { + t.Error("Decoding produced", len(response.Brokers), "brokers where there were none!") + } + if len(response.Topics) != 0 { + t.Error("Decoding produced", len(response.Topics), "topics where there were none!") + } +} + +func TestMetadataResponseWithBrokers(t *testing.T) { + response := MetadataResponse{} + + testVersionDecodable(t, "brokers, no topics", &response, brokersNoTopicsMetadataResponse, 0) + if len(response.Brokers) != 2 { + t.Fatal("Decoding produced", len(response.Brokers), "brokers where there were two!") + } + + if response.Brokers[0].id != 0xabff { + t.Error("Decoding produced invalid broker 0 id.") + } + if response.Brokers[0].addr != "localhost:51" { + t.Error("Decoding produced invalid broker 0 address.") + } + if response.Brokers[1].id != 0x010203 { + t.Error("Decoding produced invalid broker 1 id.") + } + if response.Brokers[1].addr != "google.com:273" { + t.Error("Decoding produced invalid broker 1 address.") + } + + if len(response.Topics) != 0 { + t.Error("Decoding produced", len(response.Topics), "topics where there were none!") + } +} + +func TestMetadataResponseWithTopics(t *testing.T) { + response := MetadataResponse{} + + testVersionDecodable(t, "topics, no brokers", &response, topicsNoBrokersMetadataResponse, 0) + if len(response.Brokers) != 0 { + t.Error("Decoding produced", len(response.Brokers), "brokers where there were none!") + } + + if len(response.Topics) != 2 { + t.Fatal("Decoding produced", len(response.Topics), "topics where there were two!") + } + + if response.Topics[0].Err != ErrNoError { + t.Error("Decoding produced invalid topic 0 error.") + } + + if response.Topics[0].Name != "foo" { + t.Error("Decoding produced invalid topic 0 name.") + } + + if len(response.Topics[0].Partitions) != 1 { + t.Fatal("Decoding produced invalid partition count for topic 0.") + } + + if response.Topics[0].Partitions[0].Err != ErrInvalidMessageSize { + t.Error("Decoding produced invalid topic 0 partition 0 error.") + } + + if response.Topics[0].Partitions[0].ID != 0x01 { + t.Error("Decoding produced invalid topic 0 partition 0 id.") + } + + if response.Topics[0].Partitions[0].Leader != 0x07 { + t.Error("Decoding produced invalid topic 0 partition 0 leader.") + } + + if len(response.Topics[0].Partitions[0].Replicas) != 3 { + t.Fatal("Decoding produced invalid topic 0 partition 0 replicas.") + } + for i := 0; i < 3; i++ { + if response.Topics[0].Partitions[0].Replicas[i] != int32(i+1) { + t.Error("Decoding produced invalid topic 0 partition 0 replica", i) + } + } + + if len(response.Topics[0].Partitions[0].Isr) != 0 { + t.Error("Decoding produced invalid topic 0 partition 0 isr length.") + } + + if response.Topics[1].Err != ErrNoError { + t.Error("Decoding produced invalid topic 1 error.") + } + + if response.Topics[1].Name != "bar" { + t.Error("Decoding produced invalid topic 0 name.") + } + + if len(response.Topics[1].Partitions) != 0 { + t.Error("Decoding produced invalid partition count for topic 1.") + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/metrics.go b/vendor/src/gopkg.in/Shopify/sarama.v1/metrics.go new file mode 100644 index 00000000..4869708e --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/metrics.go @@ -0,0 +1,51 @@ +package sarama + +import ( + "fmt" + "strings" + + "github.com/rcrowley/go-metrics" +) + +// Use exponentially decaying reservoir for sampling histograms with the same defaults as the Java library: +// 1028 elements, which offers a 99.9% confidence level with a 5% margin of error assuming a normal distribution, +// and an alpha factor of 0.015, which heavily biases the reservoir to the past 5 minutes of measurements. +// See https://github.com/dropwizard/metrics/blob/v3.1.0/metrics-core/src/main/java/com/codahale/metrics/ExponentiallyDecayingReservoir.java#L38 +const ( + metricsReservoirSize = 1028 + metricsAlphaFactor = 0.015 +) + +func getOrRegisterHistogram(name string, r metrics.Registry) metrics.Histogram { + return r.GetOrRegister(name, func() metrics.Histogram { + return metrics.NewHistogram(metrics.NewExpDecaySample(metricsReservoirSize, metricsAlphaFactor)) + }).(metrics.Histogram) +} + +func getMetricNameForBroker(name string, broker *Broker) string { + // Use broker id like the Java client as it does not contain '.' or ':' characters that + // can be interpreted as special character by monitoring tool (e.g. Graphite) + return fmt.Sprintf(name+"-for-broker-%d", broker.ID()) +} + +func getOrRegisterBrokerMeter(name string, broker *Broker, r metrics.Registry) metrics.Meter { + return metrics.GetOrRegisterMeter(getMetricNameForBroker(name, broker), r) +} + +func getOrRegisterBrokerHistogram(name string, broker *Broker, r metrics.Registry) metrics.Histogram { + return getOrRegisterHistogram(getMetricNameForBroker(name, broker), r) +} + +func getMetricNameForTopic(name string, topic string) string { + // Convert dot to _ since reporters like Graphite typically use dot to represent hierarchy + // cf. KAFKA-1902 and KAFKA-2337 + return fmt.Sprintf(name+"-for-topic-%s", strings.Replace(topic, ".", "_", -1)) +} + +func getOrRegisterTopicMeter(name string, topic string, r metrics.Registry) metrics.Meter { + return metrics.GetOrRegisterMeter(getMetricNameForTopic(name, topic), r) +} + +func getOrRegisterTopicHistogram(name string, topic string, r metrics.Registry) metrics.Histogram { + return getOrRegisterHistogram(getMetricNameForTopic(name, topic), r) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/metrics_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/metrics_test.go new file mode 100644 index 00000000..789c0ff3 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/metrics_test.go @@ -0,0 +1,172 @@ +package sarama + +import ( + "testing" + + "github.com/rcrowley/go-metrics" +) + +func TestGetOrRegisterHistogram(t *testing.T) { + metricRegistry := metrics.NewRegistry() + histogram := getOrRegisterHistogram("name", metricRegistry) + + if histogram == nil { + t.Error("Unexpected nil histogram") + } + + // Fetch the metric + foundHistogram := metricRegistry.Get("name") + + if foundHistogram != histogram { + t.Error("Unexpected different histogram", foundHistogram, histogram) + } + + // Try to register the metric again + sameHistogram := getOrRegisterHistogram("name", metricRegistry) + + if sameHistogram != histogram { + t.Error("Unexpected different histogram", sameHistogram, histogram) + } +} + +func TestGetMetricNameForBroker(t *testing.T) { + metricName := getMetricNameForBroker("name", &Broker{id: 1}) + + if metricName != "name-for-broker-1" { + t.Error("Unexpected metric name", metricName) + } +} + +// Common type and functions for metric validation +type metricValidator struct { + name string + validator func(*testing.T, interface{}) +} + +type metricValidators []*metricValidator + +func newMetricValidators() metricValidators { + return make([]*metricValidator, 0, 32) +} + +func (m *metricValidators) register(validator *metricValidator) { + *m = append(*m, validator) +} + +func (m *metricValidators) registerForBroker(broker *Broker, validator *metricValidator) { + m.register(&metricValidator{getMetricNameForBroker(validator.name, broker), validator.validator}) +} + +func (m *metricValidators) registerForGlobalAndTopic(topic string, validator *metricValidator) { + m.register(&metricValidator{validator.name, validator.validator}) + m.register(&metricValidator{getMetricNameForTopic(validator.name, topic), validator.validator}) +} + +func (m *metricValidators) registerForAllBrokers(broker *Broker, validator *metricValidator) { + m.register(validator) + m.registerForBroker(broker, validator) +} + +func (m metricValidators) run(t *testing.T, r metrics.Registry) { + for _, metricValidator := range m { + metric := r.Get(metricValidator.name) + if metric == nil { + t.Error("No metric named", metricValidator.name) + } else { + metricValidator.validator(t, metric) + } + } +} + +func meterValidator(name string, extraValidator func(*testing.T, metrics.Meter)) *metricValidator { + return &metricValidator{ + name: name, + validator: func(t *testing.T, metric interface{}) { + if meter, ok := metric.(metrics.Meter); !ok { + t.Errorf("Expected meter metric for '%s', got %T", name, metric) + } else { + extraValidator(t, meter) + } + }, + } +} + +func countMeterValidator(name string, expectedCount int) *metricValidator { + return meterValidator(name, func(t *testing.T, meter metrics.Meter) { + count := meter.Count() + if count != int64(expectedCount) { + t.Errorf("Expected meter metric '%s' count = %d, got %d", name, expectedCount, count) + } + }) +} + +func minCountMeterValidator(name string, minCount int) *metricValidator { + return meterValidator(name, func(t *testing.T, meter metrics.Meter) { + count := meter.Count() + if count < int64(minCount) { + t.Errorf("Expected meter metric '%s' count >= %d, got %d", name, minCount, count) + } + }) +} + +func histogramValidator(name string, extraValidator func(*testing.T, metrics.Histogram)) *metricValidator { + return &metricValidator{ + name: name, + validator: func(t *testing.T, metric interface{}) { + if histogram, ok := metric.(metrics.Histogram); !ok { + t.Errorf("Expected histogram metric for '%s', got %T", name, metric) + } else { + extraValidator(t, histogram) + } + }, + } +} + +func countHistogramValidator(name string, expectedCount int) *metricValidator { + return histogramValidator(name, func(t *testing.T, histogram metrics.Histogram) { + count := histogram.Count() + if count != int64(expectedCount) { + t.Errorf("Expected histogram metric '%s' count = %d, got %d", name, expectedCount, count) + } + }) +} + +func minCountHistogramValidator(name string, minCount int) *metricValidator { + return histogramValidator(name, func(t *testing.T, histogram metrics.Histogram) { + count := histogram.Count() + if count < int64(minCount) { + t.Errorf("Expected histogram metric '%s' count >= %d, got %d", name, minCount, count) + } + }) +} + +func minMaxHistogramValidator(name string, expectedMin int, expectedMax int) *metricValidator { + return histogramValidator(name, func(t *testing.T, histogram metrics.Histogram) { + min := int(histogram.Min()) + if min != expectedMin { + t.Errorf("Expected histogram metric '%s' min = %d, got %d", name, expectedMin, min) + } + max := int(histogram.Max()) + if max != expectedMax { + t.Errorf("Expected histogram metric '%s' max = %d, got %d", name, expectedMax, max) + } + }) +} + +func minValHistogramValidator(name string, minMin int) *metricValidator { + return histogramValidator(name, func(t *testing.T, histogram metrics.Histogram) { + min := int(histogram.Min()) + if min < minMin { + t.Errorf("Expected histogram metric '%s' min >= %d, got %d", name, minMin, min) + } + }) +} + +func maxValHistogramValidator(name string, maxMax int) *metricValidator { + return histogramValidator(name, func(t *testing.T, histogram metrics.Histogram) { + max := int(histogram.Max()) + if max > maxMax { + t.Errorf("Expected histogram metric '%s' max <= %d, got %d", name, maxMax, max) + } + }) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/mockbroker.go b/vendor/src/gopkg.in/Shopify/sarama.v1/mockbroker.go new file mode 100644 index 00000000..0734d34f --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/mockbroker.go @@ -0,0 +1,324 @@ +package sarama + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "net" + "reflect" + "strconv" + "sync" + "time" + + "github.com/davecgh/go-spew/spew" +) + +const ( + expectationTimeout = 500 * time.Millisecond +) + +type requestHandlerFunc func(req *request) (res encoder) + +// RequestNotifierFunc is invoked when a mock broker processes a request successfully +// and will provides the number of bytes read and written. +type RequestNotifierFunc func(bytesRead, bytesWritten int) + +// MockBroker is a mock Kafka broker that is used in unit tests. It is exposed +// to facilitate testing of higher level or specialized consumers and producers +// built on top of Sarama. Note that it does not 'mimic' the Kafka API protocol, +// but rather provides a facility to do that. It takes care of the TCP +// transport, request unmarshaling, response marshaling, and makes it the test +// writer responsibility to program correct according to the Kafka API protocol +// MockBroker behaviour. +// +// MockBroker is implemented as a TCP server listening on a kernel-selected +// localhost port that can accept many connections. It reads Kafka requests +// from that connection and returns responses programmed by the SetHandlerByMap +// function. If a MockBroker receives a request that it has no programmed +// response for, then it returns nothing and the request times out. +// +// A set of MockRequest builders to define mappings used by MockBroker is +// provided by Sarama. But users can develop MockRequests of their own and use +// them along with or instead of the standard ones. +// +// When running tests with MockBroker it is strongly recommended to specify +// a timeout to `go test` so that if the broker hangs waiting for a response, +// the test panics. +// +// It is not necessary to prefix message length or correlation ID to your +// response bytes, the server does that automatically as a convenience. +type MockBroker struct { + brokerID int32 + port int32 + closing chan none + stopper chan none + expectations chan encoder + listener net.Listener + t TestReporter + latency time.Duration + handler requestHandlerFunc + notifier RequestNotifierFunc + history []RequestResponse + lock sync.Mutex +} + +// RequestResponse represents a Request/Response pair processed by MockBroker. +type RequestResponse struct { + Request protocolBody + Response encoder +} + +// SetLatency makes broker pause for the specified period every time before +// replying. +func (b *MockBroker) SetLatency(latency time.Duration) { + b.latency = latency +} + +// SetHandlerByMap defines mapping of Request types to MockResponses. When a +// request is received by the broker, it looks up the request type in the map +// and uses the found MockResponse instance to generate an appropriate reply. +// If the request type is not found in the map then nothing is sent. +func (b *MockBroker) SetHandlerByMap(handlerMap map[string]MockResponse) { + b.setHandler(func(req *request) (res encoder) { + reqTypeName := reflect.TypeOf(req.body).Elem().Name() + mockResponse := handlerMap[reqTypeName] + if mockResponse == nil { + return nil + } + return mockResponse.For(req.body) + }) +} + +// SetNotifier set a function that will get invoked whenever a request has been +// processed successfully and will provide the number of bytes read and written +func (b *MockBroker) SetNotifier(notifier RequestNotifierFunc) { + b.lock.Lock() + b.notifier = notifier + b.lock.Unlock() +} + +// BrokerID returns broker ID assigned to the broker. +func (b *MockBroker) BrokerID() int32 { + return b.brokerID +} + +// History returns a slice of RequestResponse pairs in the order they were +// processed by the broker. Note that in case of multiple connections to the +// broker the order expected by a test can be different from the order recorded +// in the history, unless some synchronization is implemented in the test. +func (b *MockBroker) History() []RequestResponse { + b.lock.Lock() + history := make([]RequestResponse, len(b.history)) + copy(history, b.history) + b.lock.Unlock() + return history +} + +// Port returns the TCP port number the broker is listening for requests on. +func (b *MockBroker) Port() int32 { + return b.port +} + +// Addr returns the broker connection string in the form "

    :". +func (b *MockBroker) Addr() string { + return b.listener.Addr().String() +} + +// Close terminates the broker blocking until it stops internal goroutines and +// releases all resources. +func (b *MockBroker) Close() { + close(b.expectations) + if len(b.expectations) > 0 { + buf := bytes.NewBufferString(fmt.Sprintf("mockbroker/%d: not all expectations were satisfied! Still waiting on:\n", b.BrokerID())) + for e := range b.expectations { + _, _ = buf.WriteString(spew.Sdump(e)) + } + b.t.Error(buf.String()) + } + close(b.closing) + <-b.stopper +} + +// setHandler sets the specified function as the request handler. Whenever +// a mock broker reads a request from the wire it passes the request to the +// function and sends back whatever the handler function returns. +func (b *MockBroker) setHandler(handler requestHandlerFunc) { + b.lock.Lock() + b.handler = handler + b.lock.Unlock() +} + +func (b *MockBroker) serverLoop() { + defer close(b.stopper) + var err error + var conn net.Conn + + go func() { + <-b.closing + err := b.listener.Close() + if err != nil { + b.t.Error(err) + } + }() + + wg := &sync.WaitGroup{} + i := 0 + for conn, err = b.listener.Accept(); err == nil; conn, err = b.listener.Accept() { + wg.Add(1) + go b.handleRequests(conn, i, wg) + i++ + } + wg.Wait() + Logger.Printf("*** mockbroker/%d: listener closed, err=%v", b.BrokerID(), err) +} + +func (b *MockBroker) handleRequests(conn net.Conn, idx int, wg *sync.WaitGroup) { + defer wg.Done() + defer func() { + _ = conn.Close() + }() + Logger.Printf("*** mockbroker/%d/%d: connection opened", b.BrokerID(), idx) + var err error + + abort := make(chan none) + defer close(abort) + go func() { + select { + case <-b.closing: + _ = conn.Close() + case <-abort: + } + }() + + resHeader := make([]byte, 8) + for { + req, bytesRead, err := decodeRequest(conn) + if err != nil { + Logger.Printf("*** mockbroker/%d/%d: invalid request: err=%+v, %+v", b.brokerID, idx, err, spew.Sdump(req)) + b.serverError(err) + break + } + + if b.latency > 0 { + time.Sleep(b.latency) + } + + b.lock.Lock() + res := b.handler(req) + b.history = append(b.history, RequestResponse{req.body, res}) + b.lock.Unlock() + + if res == nil { + Logger.Printf("*** mockbroker/%d/%d: ignored %v", b.brokerID, idx, spew.Sdump(req)) + continue + } + Logger.Printf("*** mockbroker/%d/%d: served %v -> %v", b.brokerID, idx, req, res) + + encodedRes, err := encode(res, nil) + if err != nil { + b.serverError(err) + break + } + if len(encodedRes) == 0 { + b.lock.Lock() + if b.notifier != nil { + b.notifier(bytesRead, 0) + } + b.lock.Unlock() + continue + } + + binary.BigEndian.PutUint32(resHeader, uint32(len(encodedRes)+4)) + binary.BigEndian.PutUint32(resHeader[4:], uint32(req.correlationID)) + if _, err = conn.Write(resHeader); err != nil { + b.serverError(err) + break + } + if _, err = conn.Write(encodedRes); err != nil { + b.serverError(err) + break + } + + b.lock.Lock() + if b.notifier != nil { + b.notifier(bytesRead, len(resHeader)+len(encodedRes)) + } + b.lock.Unlock() + } + Logger.Printf("*** mockbroker/%d/%d: connection closed, err=%v", b.BrokerID(), idx, err) +} + +func (b *MockBroker) defaultRequestHandler(req *request) (res encoder) { + select { + case res, ok := <-b.expectations: + if !ok { + return nil + } + return res + case <-time.After(expectationTimeout): + return nil + } +} + +func (b *MockBroker) serverError(err error) { + isConnectionClosedError := false + if _, ok := err.(*net.OpError); ok { + isConnectionClosedError = true + } else if err == io.EOF { + isConnectionClosedError = true + } else if err.Error() == "use of closed network connection" { + isConnectionClosedError = true + } + + if isConnectionClosedError { + return + } + + b.t.Errorf(err.Error()) +} + +// NewMockBroker launches a fake Kafka broker. It takes a TestReporter as provided by the +// test framework and a channel of responses to use. If an error occurs it is +// simply logged to the TestReporter and the broker exits. +func NewMockBroker(t TestReporter, brokerID int32) *MockBroker { + return NewMockBrokerAddr(t, brokerID, "localhost:0") +} + +// NewMockBrokerAddr behaves like newMockBroker but listens on the address you give +// it rather than just some ephemeral port. +func NewMockBrokerAddr(t TestReporter, brokerID int32, addr string) *MockBroker { + var err error + + broker := &MockBroker{ + closing: make(chan none), + stopper: make(chan none), + t: t, + brokerID: brokerID, + expectations: make(chan encoder, 512), + } + broker.handler = broker.defaultRequestHandler + + broker.listener, err = net.Listen("tcp", addr) + if err != nil { + t.Fatal(err) + } + Logger.Printf("*** mockbroker/%d listening on %s\n", brokerID, broker.listener.Addr().String()) + _, portStr, err := net.SplitHostPort(broker.listener.Addr().String()) + if err != nil { + t.Fatal(err) + } + tmp, err := strconv.ParseInt(portStr, 10, 32) + if err != nil { + t.Fatal(err) + } + broker.port = int32(tmp) + + go broker.serverLoop() + + return broker +} + +func (b *MockBroker) Returns(e encoder) { + b.expectations <- e +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/mockresponses.go b/vendor/src/gopkg.in/Shopify/sarama.v1/mockresponses.go new file mode 100644 index 00000000..a2031420 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/mockresponses.go @@ -0,0 +1,455 @@ +package sarama + +import ( + "fmt" +) + +// TestReporter has methods matching go's testing.T to avoid importing +// `testing` in the main part of the library. +type TestReporter interface { + Error(...interface{}) + Errorf(string, ...interface{}) + Fatal(...interface{}) + Fatalf(string, ...interface{}) +} + +// MockResponse is a response builder interface it defines one method that +// allows generating a response based on a request body. MockResponses are used +// to program behavior of MockBroker in tests. +type MockResponse interface { + For(reqBody versionedDecoder) (res encoder) +} + +// MockWrapper is a mock response builder that returns a particular concrete +// response regardless of the actual request passed to the `For` method. +type MockWrapper struct { + res encoder +} + +func (mw *MockWrapper) For(reqBody versionedDecoder) (res encoder) { + return mw.res +} + +func NewMockWrapper(res encoder) *MockWrapper { + return &MockWrapper{res: res} +} + +// MockSequence is a mock response builder that is created from a sequence of +// concrete responses. Every time when a `MockBroker` calls its `For` method +// the next response from the sequence is returned. When the end of the +// sequence is reached the last element from the sequence is returned. +type MockSequence struct { + responses []MockResponse +} + +func NewMockSequence(responses ...interface{}) *MockSequence { + ms := &MockSequence{} + ms.responses = make([]MockResponse, len(responses)) + for i, res := range responses { + switch res := res.(type) { + case MockResponse: + ms.responses[i] = res + case encoder: + ms.responses[i] = NewMockWrapper(res) + default: + panic(fmt.Sprintf("Unexpected response type: %T", res)) + } + } + return ms +} + +func (mc *MockSequence) For(reqBody versionedDecoder) (res encoder) { + res = mc.responses[0].For(reqBody) + if len(mc.responses) > 1 { + mc.responses = mc.responses[1:] + } + return res +} + +// MockMetadataResponse is a `MetadataResponse` builder. +type MockMetadataResponse struct { + leaders map[string]map[int32]int32 + brokers map[string]int32 + t TestReporter +} + +func NewMockMetadataResponse(t TestReporter) *MockMetadataResponse { + return &MockMetadataResponse{ + leaders: make(map[string]map[int32]int32), + brokers: make(map[string]int32), + t: t, + } +} + +func (mmr *MockMetadataResponse) SetLeader(topic string, partition, brokerID int32) *MockMetadataResponse { + partitions := mmr.leaders[topic] + if partitions == nil { + partitions = make(map[int32]int32) + mmr.leaders[topic] = partitions + } + partitions[partition] = brokerID + return mmr +} + +func (mmr *MockMetadataResponse) SetBroker(addr string, brokerID int32) *MockMetadataResponse { + mmr.brokers[addr] = brokerID + return mmr +} + +func (mmr *MockMetadataResponse) For(reqBody versionedDecoder) encoder { + metadataRequest := reqBody.(*MetadataRequest) + metadataResponse := &MetadataResponse{} + for addr, brokerID := range mmr.brokers { + metadataResponse.AddBroker(addr, brokerID) + } + if len(metadataRequest.Topics) == 0 { + for topic, partitions := range mmr.leaders { + for partition, brokerID := range partitions { + metadataResponse.AddTopicPartition(topic, partition, brokerID, nil, nil, ErrNoError) + } + } + return metadataResponse + } + for _, topic := range metadataRequest.Topics { + for partition, brokerID := range mmr.leaders[topic] { + metadataResponse.AddTopicPartition(topic, partition, brokerID, nil, nil, ErrNoError) + } + } + return metadataResponse +} + +// MockOffsetResponse is an `OffsetResponse` builder. +type MockOffsetResponse struct { + offsets map[string]map[int32]map[int64]int64 + t TestReporter +} + +func NewMockOffsetResponse(t TestReporter) *MockOffsetResponse { + return &MockOffsetResponse{ + offsets: make(map[string]map[int32]map[int64]int64), + t: t, + } +} + +func (mor *MockOffsetResponse) SetOffset(topic string, partition int32, time, offset int64) *MockOffsetResponse { + partitions := mor.offsets[topic] + if partitions == nil { + partitions = make(map[int32]map[int64]int64) + mor.offsets[topic] = partitions + } + times := partitions[partition] + if times == nil { + times = make(map[int64]int64) + partitions[partition] = times + } + times[time] = offset + return mor +} + +func (mor *MockOffsetResponse) For(reqBody versionedDecoder) encoder { + offsetRequest := reqBody.(*OffsetRequest) + offsetResponse := &OffsetResponse{} + for topic, partitions := range offsetRequest.blocks { + for partition, block := range partitions { + offset := mor.getOffset(topic, partition, block.time) + offsetResponse.AddTopicPartition(topic, partition, offset) + } + } + return offsetResponse +} + +func (mor *MockOffsetResponse) getOffset(topic string, partition int32, time int64) int64 { + partitions := mor.offsets[topic] + if partitions == nil { + mor.t.Errorf("missing topic: %s", topic) + } + times := partitions[partition] + if times == nil { + mor.t.Errorf("missing partition: %d", partition) + } + offset, ok := times[time] + if !ok { + mor.t.Errorf("missing time: %d", time) + } + return offset +} + +// MockFetchResponse is a `FetchResponse` builder. +type MockFetchResponse struct { + messages map[string]map[int32]map[int64]Encoder + highWaterMarks map[string]map[int32]int64 + t TestReporter + batchSize int +} + +func NewMockFetchResponse(t TestReporter, batchSize int) *MockFetchResponse { + return &MockFetchResponse{ + messages: make(map[string]map[int32]map[int64]Encoder), + highWaterMarks: make(map[string]map[int32]int64), + t: t, + batchSize: batchSize, + } +} + +func (mfr *MockFetchResponse) SetMessage(topic string, partition int32, offset int64, msg Encoder) *MockFetchResponse { + partitions := mfr.messages[topic] + if partitions == nil { + partitions = make(map[int32]map[int64]Encoder) + mfr.messages[topic] = partitions + } + messages := partitions[partition] + if messages == nil { + messages = make(map[int64]Encoder) + partitions[partition] = messages + } + messages[offset] = msg + return mfr +} + +func (mfr *MockFetchResponse) SetHighWaterMark(topic string, partition int32, offset int64) *MockFetchResponse { + partitions := mfr.highWaterMarks[topic] + if partitions == nil { + partitions = make(map[int32]int64) + mfr.highWaterMarks[topic] = partitions + } + partitions[partition] = offset + return mfr +} + +func (mfr *MockFetchResponse) For(reqBody versionedDecoder) encoder { + fetchRequest := reqBody.(*FetchRequest) + res := &FetchResponse{} + for topic, partitions := range fetchRequest.blocks { + for partition, block := range partitions { + initialOffset := block.fetchOffset + offset := initialOffset + maxOffset := initialOffset + int64(mfr.getMessageCount(topic, partition)) + for i := 0; i < mfr.batchSize && offset < maxOffset; { + msg := mfr.getMessage(topic, partition, offset) + if msg != nil { + res.AddMessage(topic, partition, nil, msg, offset) + i++ + } + offset++ + } + fb := res.GetBlock(topic, partition) + if fb == nil { + res.AddError(topic, partition, ErrNoError) + fb = res.GetBlock(topic, partition) + } + fb.HighWaterMarkOffset = mfr.getHighWaterMark(topic, partition) + } + } + return res +} + +func (mfr *MockFetchResponse) getMessage(topic string, partition int32, offset int64) Encoder { + partitions := mfr.messages[topic] + if partitions == nil { + return nil + } + messages := partitions[partition] + if messages == nil { + return nil + } + return messages[offset] +} + +func (mfr *MockFetchResponse) getMessageCount(topic string, partition int32) int { + partitions := mfr.messages[topic] + if partitions == nil { + return 0 + } + messages := partitions[partition] + if messages == nil { + return 0 + } + return len(messages) +} + +func (mfr *MockFetchResponse) getHighWaterMark(topic string, partition int32) int64 { + partitions := mfr.highWaterMarks[topic] + if partitions == nil { + return 0 + } + return partitions[partition] +} + +// MockConsumerMetadataResponse is a `ConsumerMetadataResponse` builder. +type MockConsumerMetadataResponse struct { + coordinators map[string]interface{} + t TestReporter +} + +func NewMockConsumerMetadataResponse(t TestReporter) *MockConsumerMetadataResponse { + return &MockConsumerMetadataResponse{ + coordinators: make(map[string]interface{}), + t: t, + } +} + +func (mr *MockConsumerMetadataResponse) SetCoordinator(group string, broker *MockBroker) *MockConsumerMetadataResponse { + mr.coordinators[group] = broker + return mr +} + +func (mr *MockConsumerMetadataResponse) SetError(group string, kerror KError) *MockConsumerMetadataResponse { + mr.coordinators[group] = kerror + return mr +} + +func (mr *MockConsumerMetadataResponse) For(reqBody versionedDecoder) encoder { + req := reqBody.(*ConsumerMetadataRequest) + group := req.ConsumerGroup + res := &ConsumerMetadataResponse{} + v := mr.coordinators[group] + switch v := v.(type) { + case *MockBroker: + res.Coordinator = &Broker{id: v.BrokerID(), addr: v.Addr()} + case KError: + res.Err = v + } + return res +} + +// MockOffsetCommitResponse is a `OffsetCommitResponse` builder. +type MockOffsetCommitResponse struct { + errors map[string]map[string]map[int32]KError + t TestReporter +} + +func NewMockOffsetCommitResponse(t TestReporter) *MockOffsetCommitResponse { + return &MockOffsetCommitResponse{t: t} +} + +func (mr *MockOffsetCommitResponse) SetError(group, topic string, partition int32, kerror KError) *MockOffsetCommitResponse { + if mr.errors == nil { + mr.errors = make(map[string]map[string]map[int32]KError) + } + topics := mr.errors[group] + if topics == nil { + topics = make(map[string]map[int32]KError) + mr.errors[group] = topics + } + partitions := topics[topic] + if partitions == nil { + partitions = make(map[int32]KError) + topics[topic] = partitions + } + partitions[partition] = kerror + return mr +} + +func (mr *MockOffsetCommitResponse) For(reqBody versionedDecoder) encoder { + req := reqBody.(*OffsetCommitRequest) + group := req.ConsumerGroup + res := &OffsetCommitResponse{} + for topic, partitions := range req.blocks { + for partition := range partitions { + res.AddError(topic, partition, mr.getError(group, topic, partition)) + } + } + return res +} + +func (mr *MockOffsetCommitResponse) getError(group, topic string, partition int32) KError { + topics := mr.errors[group] + if topics == nil { + return ErrNoError + } + partitions := topics[topic] + if partitions == nil { + return ErrNoError + } + kerror, ok := partitions[partition] + if !ok { + return ErrNoError + } + return kerror +} + +// MockProduceResponse is a `ProduceResponse` builder. +type MockProduceResponse struct { + errors map[string]map[int32]KError + t TestReporter +} + +func NewMockProduceResponse(t TestReporter) *MockProduceResponse { + return &MockProduceResponse{t: t} +} + +func (mr *MockProduceResponse) SetError(topic string, partition int32, kerror KError) *MockProduceResponse { + if mr.errors == nil { + mr.errors = make(map[string]map[int32]KError) + } + partitions := mr.errors[topic] + if partitions == nil { + partitions = make(map[int32]KError) + mr.errors[topic] = partitions + } + partitions[partition] = kerror + return mr +} + +func (mr *MockProduceResponse) For(reqBody versionedDecoder) encoder { + req := reqBody.(*ProduceRequest) + res := &ProduceResponse{} + for topic, partitions := range req.msgSets { + for partition := range partitions { + res.AddTopicPartition(topic, partition, mr.getError(topic, partition)) + } + } + return res +} + +func (mr *MockProduceResponse) getError(topic string, partition int32) KError { + partitions := mr.errors[topic] + if partitions == nil { + return ErrNoError + } + kerror, ok := partitions[partition] + if !ok { + return ErrNoError + } + return kerror +} + +// MockOffsetFetchResponse is a `OffsetFetchResponse` builder. +type MockOffsetFetchResponse struct { + offsets map[string]map[string]map[int32]*OffsetFetchResponseBlock + t TestReporter +} + +func NewMockOffsetFetchResponse(t TestReporter) *MockOffsetFetchResponse { + return &MockOffsetFetchResponse{t: t} +} + +func (mr *MockOffsetFetchResponse) SetOffset(group, topic string, partition int32, offset int64, metadata string, kerror KError) *MockOffsetFetchResponse { + if mr.offsets == nil { + mr.offsets = make(map[string]map[string]map[int32]*OffsetFetchResponseBlock) + } + topics := mr.offsets[group] + if topics == nil { + topics = make(map[string]map[int32]*OffsetFetchResponseBlock) + mr.offsets[group] = topics + } + partitions := topics[topic] + if partitions == nil { + partitions = make(map[int32]*OffsetFetchResponseBlock) + topics[topic] = partitions + } + partitions[partition] = &OffsetFetchResponseBlock{offset, metadata, kerror} + return mr +} + +func (mr *MockOffsetFetchResponse) For(reqBody versionedDecoder) encoder { + req := reqBody.(*OffsetFetchRequest) + group := req.ConsumerGroup + res := &OffsetFetchResponse{} + for topic, partitions := range mr.offsets[group] { + for partition, block := range partitions { + res.AddBlock(topic, partition, block) + } + } + return res +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/README.md b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/README.md new file mode 100644 index 00000000..55a6c2e6 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/README.md @@ -0,0 +1,13 @@ +# sarama/mocks + +The `mocks` subpackage includes mock implementations that implement the interfaces of the major sarama types. +You can use them to test your sarama applications using dependency injection. + +The following mock objects are available: + +- [Consumer](https://godoc.org/github.com/Shopify/sarama/mocks#Consumer), which will create [PartitionConsumer](https://godoc.org/github.com/Shopify/sarama/mocks#PartitionConsumer) mocks. +- [AsyncProducer](https://godoc.org/github.com/Shopify/sarama/mocks#AsyncProducer) +- [SyncProducer](https://godoc.org/github.com/Shopify/sarama/mocks#SyncProducer) + +The mocks allow you to set expectations on them. When you close the mocks, the expectations will be verified, +and the results will be reported to the `*testing.T` object you provided when creating the mock. diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/async_producer.go b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/async_producer.go new file mode 100644 index 00000000..d1d9ba41 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/async_producer.go @@ -0,0 +1,174 @@ +package mocks + +import ( + "sync" + + "github.com/Shopify/sarama" +) + +// AsyncProducer implements sarama's Producer interface for testing purposes. +// Before you can send messages to it's Input channel, you have to set expectations +// so it knows how to handle the input; it returns an error if the number of messages +// received is bigger then the number of expectations set. You can also set a +// function in each expectation so that the message value is checked by this function +// and an error is returned if the match fails. +type AsyncProducer struct { + l sync.Mutex + t ErrorReporter + expectations []*producerExpectation + closed chan struct{} + input chan *sarama.ProducerMessage + successes chan *sarama.ProducerMessage + errors chan *sarama.ProducerError + lastOffset int64 +} + +// NewAsyncProducer instantiates a new Producer mock. The t argument should +// be the *testing.T instance of your test method. An error will be written to it if +// an expectation is violated. The config argument is used to determine whether it +// should ack successes on the Successes channel. +func NewAsyncProducer(t ErrorReporter, config *sarama.Config) *AsyncProducer { + if config == nil { + config = sarama.NewConfig() + } + mp := &AsyncProducer{ + t: t, + closed: make(chan struct{}, 0), + expectations: make([]*producerExpectation, 0), + input: make(chan *sarama.ProducerMessage, config.ChannelBufferSize), + successes: make(chan *sarama.ProducerMessage, config.ChannelBufferSize), + errors: make(chan *sarama.ProducerError, config.ChannelBufferSize), + } + + go func() { + defer func() { + close(mp.successes) + close(mp.errors) + }() + + for msg := range mp.input { + mp.l.Lock() + if mp.expectations == nil || len(mp.expectations) == 0 { + mp.expectations = nil + mp.t.Errorf("No more expectation set on this mock producer to handle the input message.") + } else { + expectation := mp.expectations[0] + mp.expectations = mp.expectations[1:] + if expectation.CheckFunction != nil { + if val, err := msg.Value.Encode(); err != nil { + mp.t.Errorf("Input message encoding failed: %s", err.Error()) + mp.errors <- &sarama.ProducerError{Err: err, Msg: msg} + } else { + err = expectation.CheckFunction(val) + if err != nil { + mp.t.Errorf("Check function returned an error: %s", err.Error()) + mp.errors <- &sarama.ProducerError{Err: err, Msg: msg} + } + } + } + if expectation.Result == errProduceSuccess { + mp.lastOffset++ + if config.Producer.Return.Successes { + msg.Offset = mp.lastOffset + mp.successes <- msg + } + } else { + if config.Producer.Return.Errors { + mp.errors <- &sarama.ProducerError{Err: expectation.Result, Msg: msg} + } + } + } + mp.l.Unlock() + } + + mp.l.Lock() + if len(mp.expectations) > 0 { + mp.t.Errorf("Expected to exhaust all expectations, but %d are left.", len(mp.expectations)) + } + mp.l.Unlock() + + close(mp.closed) + }() + + return mp +} + +//////////////////////////////////////////////// +// Implement Producer interface +//////////////////////////////////////////////// + +// AsyncClose corresponds with the AsyncClose method of sarama's Producer implementation. +// By closing a mock producer, you also tell it that no more input will be provided, so it will +// write an error to the test state if there's any remaining expectations. +func (mp *AsyncProducer) AsyncClose() { + close(mp.input) +} + +// Close corresponds with the Close method of sarama's Producer implementation. +// By closing a mock producer, you also tell it that no more input will be provided, so it will +// write an error to the test state if there's any remaining expectations. +func (mp *AsyncProducer) Close() error { + mp.AsyncClose() + <-mp.closed + return nil +} + +// Input corresponds with the Input method of sarama's Producer implementation. +// You have to set expectations on the mock producer before writing messages to the Input +// channel, so it knows how to handle them. If there is no more remaining expectations and +// a messages is written to the Input channel, the mock producer will write an error to the test +// state object. +func (mp *AsyncProducer) Input() chan<- *sarama.ProducerMessage { + return mp.input +} + +// Successes corresponds with the Successes method of sarama's Producer implementation. +func (mp *AsyncProducer) Successes() <-chan *sarama.ProducerMessage { + return mp.successes +} + +// Errors corresponds with the Errors method of sarama's Producer implementation. +func (mp *AsyncProducer) Errors() <-chan *sarama.ProducerError { + return mp.errors +} + +//////////////////////////////////////////////// +// Setting expectations +//////////////////////////////////////////////// + +// ExpectInputWithCheckerFunctionAndSucceed sets an expectation on the mock producer that a message +// will be provided on the input channel. The mock producer will call the given function to check +// the message value. If an error is returned it will be made available on the Errors channel +// otherwise the mock will handle the message as if it produced successfully, i.e. it will make +// it available on the Successes channel if the Producer.Return.Successes setting is set to true. +func (mp *AsyncProducer) ExpectInputWithCheckerFunctionAndSucceed(cf ValueChecker) { + mp.l.Lock() + defer mp.l.Unlock() + mp.expectations = append(mp.expectations, &producerExpectation{Result: errProduceSuccess, CheckFunction: cf}) +} + +// ExpectInputWithCheckerFunctionAndSucceed sets an expectation on the mock producer that a message +// will be provided on the input channel. The mock producer will first call the given function to +// check the message value. If an error is returned it will be made available on the Errors channel +// otherwise the mock will handle the message as if it failed to produce successfully. This means +// it will make a ProducerError available on the Errors channel. +func (mp *AsyncProducer) ExpectInputWithCheckerFunctionAndFail(cf ValueChecker, err error) { + mp.l.Lock() + defer mp.l.Unlock() + mp.expectations = append(mp.expectations, &producerExpectation{Result: err, CheckFunction: cf}) +} + +// ExpectInputAndSucceed sets an expectation on the mock producer that a message will be provided +// on the input channel. The mock producer will handle the message as if it is produced successfully, +// i.e. it will make it available on the Successes channel if the Producer.Return.Successes setting +// is set to true. +func (mp *AsyncProducer) ExpectInputAndSucceed() { + mp.ExpectInputWithCheckerFunctionAndSucceed(nil) +} + +// ExpectInputAndFail sets an expectation on the mock producer that a message will be provided +// on the input channel. The mock producer will handle the message as if it failed to produce +// successfully. This means it will make a ProducerError available on the Errors channel. +func (mp *AsyncProducer) ExpectInputAndFail(err error) { + mp.ExpectInputWithCheckerFunctionAndFail(nil, err) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/async_producer_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/async_producer_test.go new file mode 100644 index 00000000..b5d92aad --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/async_producer_test.go @@ -0,0 +1,132 @@ +package mocks + +import ( + "errors" + "fmt" + "regexp" + "strings" + "testing" + + "github.com/Shopify/sarama" +) + +func generateRegexpChecker(re string) func([]byte) error { + return func(val []byte) error { + matched, err := regexp.MatchString(re, string(val)) + if err != nil { + return errors.New("Error while trying to match the input message with the expected pattern: " + err.Error()) + } + if !matched { + return fmt.Errorf("No match between input value \"%s\" and expected pattern \"%s\"", val, re) + } + return nil + } +} + +type testReporterMock struct { + errors []string +} + +func newTestReporterMock() *testReporterMock { + return &testReporterMock{errors: make([]string, 0)} +} + +func (trm *testReporterMock) Errorf(format string, args ...interface{}) { + trm.errors = append(trm.errors, fmt.Sprintf(format, args...)) +} + +func TestMockAsyncProducerImplementsAsyncProducerInterface(t *testing.T) { + var mp interface{} = &AsyncProducer{} + if _, ok := mp.(sarama.AsyncProducer); !ok { + t.Error("The mock producer should implement the sarama.Producer interface.") + } +} + +func TestProducerReturnsExpectationsToChannels(t *testing.T) { + config := sarama.NewConfig() + config.Producer.Return.Successes = true + mp := NewAsyncProducer(t, config) + + mp.ExpectInputAndSucceed() + mp.ExpectInputAndSucceed() + mp.ExpectInputAndFail(sarama.ErrOutOfBrokers) + + mp.Input() <- &sarama.ProducerMessage{Topic: "test 1"} + mp.Input() <- &sarama.ProducerMessage{Topic: "test 2"} + mp.Input() <- &sarama.ProducerMessage{Topic: "test 3"} + + msg1 := <-mp.Successes() + msg2 := <-mp.Successes() + err1 := <-mp.Errors() + + if msg1.Topic != "test 1" { + t.Error("Expected message 1 to be returned first") + } + + if msg2.Topic != "test 2" { + t.Error("Expected message 2 to be returned second") + } + + if err1.Msg.Topic != "test 3" || err1.Err != sarama.ErrOutOfBrokers { + t.Error("Expected message 3 to be returned as error") + } + + if err := mp.Close(); err != nil { + t.Error(err) + } +} + +func TestProducerWithTooFewExpectations(t *testing.T) { + trm := newTestReporterMock() + mp := NewAsyncProducer(trm, nil) + mp.ExpectInputAndSucceed() + + mp.Input() <- &sarama.ProducerMessage{Topic: "test"} + mp.Input() <- &sarama.ProducerMessage{Topic: "test"} + + if err := mp.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Error("Expected to report an error") + } +} + +func TestProducerWithTooManyExpectations(t *testing.T) { + trm := newTestReporterMock() + mp := NewAsyncProducer(trm, nil) + mp.ExpectInputAndSucceed() + mp.ExpectInputAndFail(sarama.ErrOutOfBrokers) + + mp.Input() <- &sarama.ProducerMessage{Topic: "test"} + if err := mp.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Error("Expected to report an error") + } +} + +func TestProducerWithCheckerFunction(t *testing.T) { + trm := newTestReporterMock() + mp := NewAsyncProducer(trm, nil) + mp.ExpectInputWithCheckerFunctionAndSucceed(generateRegexpChecker("^tes")) + mp.ExpectInputWithCheckerFunctionAndSucceed(generateRegexpChecker("^tes$")) + + mp.Input() <- &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + mp.Input() <- &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + if err := mp.Close(); err != nil { + t.Error(err) + } + + if len(mp.Errors()) != 1 { + t.Error("Expected to report an error") + } + + err1 := <-mp.Errors() + if !strings.HasPrefix(err1.Err.Error(), "No match") { + t.Error("Expected to report a value check error, found: ", err1.Err) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/consumer.go b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/consumer.go new file mode 100644 index 00000000..a524190a --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/consumer.go @@ -0,0 +1,315 @@ +package mocks + +import ( + "sync" + "sync/atomic" + + "github.com/Shopify/sarama" +) + +// Consumer implements sarama's Consumer interface for testing purposes. +// Before you can start consuming from this consumer, you have to register +// topic/partitions using ExpectConsumePartition, and set expectations on them. +type Consumer struct { + l sync.Mutex + t ErrorReporter + config *sarama.Config + partitionConsumers map[string]map[int32]*PartitionConsumer + metadata map[string][]int32 +} + +// NewConsumer returns a new mock Consumer instance. The t argument should +// be the *testing.T instance of your test method. An error will be written to it if +// an expectation is violated. The config argument is currently unused and can be set to nil. +func NewConsumer(t ErrorReporter, config *sarama.Config) *Consumer { + if config == nil { + config = sarama.NewConfig() + } + + c := &Consumer{ + t: t, + config: config, + partitionConsumers: make(map[string]map[int32]*PartitionConsumer), + } + return c +} + +/////////////////////////////////////////////////// +// Consumer interface implementation +/////////////////////////////////////////////////// + +// ConsumePartition implements the ConsumePartition method from the sarama.Consumer interface. +// Before you can start consuming a partition, you have to set expectations on it using +// ExpectConsumePartition. You can only consume a partition once per consumer. +func (c *Consumer) ConsumePartition(topic string, partition int32, offset int64) (sarama.PartitionConsumer, error) { + c.l.Lock() + defer c.l.Unlock() + + if c.partitionConsumers[topic] == nil || c.partitionConsumers[topic][partition] == nil { + c.t.Errorf("No expectations set for %s/%d", topic, partition) + return nil, errOutOfExpectations + } + + pc := c.partitionConsumers[topic][partition] + if pc.consumed { + return nil, sarama.ConfigurationError("The topic/partition is already being consumed") + } + + if pc.offset != AnyOffset && pc.offset != offset { + c.t.Errorf("Unexpected offset when calling ConsumePartition for %s/%d. Expected %d, got %d.", topic, partition, pc.offset, offset) + } + + pc.consumed = true + return pc, nil +} + +// Topics returns a list of topics, as registered with SetMetadata +func (c *Consumer) Topics() ([]string, error) { + c.l.Lock() + defer c.l.Unlock() + + if c.metadata == nil { + c.t.Errorf("Unexpected call to Topics. Initialize the mock's topic metadata with SetMetadata.") + return nil, sarama.ErrOutOfBrokers + } + + var result []string + for topic := range c.metadata { + result = append(result, topic) + } + return result, nil +} + +// Partitions returns the list of parititons for the given topic, as registered with SetMetadata +func (c *Consumer) Partitions(topic string) ([]int32, error) { + c.l.Lock() + defer c.l.Unlock() + + if c.metadata == nil { + c.t.Errorf("Unexpected call to Partitions. Initialize the mock's topic metadata with SetMetadata.") + return nil, sarama.ErrOutOfBrokers + } + if c.metadata[topic] == nil { + return nil, sarama.ErrUnknownTopicOrPartition + } + + return c.metadata[topic], nil +} + +func (c *Consumer) HighWaterMarks() map[string]map[int32]int64 { + c.l.Lock() + defer c.l.Unlock() + + hwms := make(map[string]map[int32]int64, len(c.partitionConsumers)) + for topic, partitionConsumers := range c.partitionConsumers { + hwm := make(map[int32]int64, len(partitionConsumers)) + for partition, pc := range partitionConsumers { + hwm[partition] = pc.HighWaterMarkOffset() + } + hwms[topic] = hwm + } + + return hwms +} + +// Close implements the Close method from the sarama.Consumer interface. It will close +// all registered PartitionConsumer instances. +func (c *Consumer) Close() error { + c.l.Lock() + defer c.l.Unlock() + + for _, partitions := range c.partitionConsumers { + for _, partitionConsumer := range partitions { + _ = partitionConsumer.Close() + } + } + + return nil +} + +/////////////////////////////////////////////////// +// Expectation API +/////////////////////////////////////////////////// + +// SetTopicMetadata sets the clusters topic/partition metadata, +// which will be returned by Topics() and Partitions(). +func (c *Consumer) SetTopicMetadata(metadata map[string][]int32) { + c.l.Lock() + defer c.l.Unlock() + + c.metadata = metadata +} + +// ExpectConsumePartition will register a topic/partition, so you can set expectations on it. +// The registered PartitionConsumer will be returned, so you can set expectations +// on it using method chaining. Once a topic/partition is registered, you are +// expected to start consuming it using ConsumePartition. If that doesn't happen, +// an error will be written to the error reporter once the mock consumer is closed. It will +// also expect that the +func (c *Consumer) ExpectConsumePartition(topic string, partition int32, offset int64) *PartitionConsumer { + c.l.Lock() + defer c.l.Unlock() + + if c.partitionConsumers[topic] == nil { + c.partitionConsumers[topic] = make(map[int32]*PartitionConsumer) + } + + if c.partitionConsumers[topic][partition] == nil { + c.partitionConsumers[topic][partition] = &PartitionConsumer{ + t: c.t, + topic: topic, + partition: partition, + offset: offset, + messages: make(chan *sarama.ConsumerMessage, c.config.ChannelBufferSize), + errors: make(chan *sarama.ConsumerError, c.config.ChannelBufferSize), + } + } + + return c.partitionConsumers[topic][partition] +} + +/////////////////////////////////////////////////// +// PartitionConsumer mock type +/////////////////////////////////////////////////// + +// PartitionConsumer implements sarama's PartitionConsumer interface for testing purposes. +// It is returned by the mock Consumers ConsumePartitionMethod, but only if it is +// registered first using the Consumer's ExpectConsumePartition method. Before consuming the +// Errors and Messages channel, you should specify what values will be provided on these +// channels using YieldMessage and YieldError. +type PartitionConsumer struct { + l sync.Mutex + t ErrorReporter + topic string + partition int32 + offset int64 + messages chan *sarama.ConsumerMessage + errors chan *sarama.ConsumerError + singleClose sync.Once + consumed bool + errorsShouldBeDrained bool + messagesShouldBeDrained bool + highWaterMarkOffset int64 +} + +/////////////////////////////////////////////////// +// PartitionConsumer interface implementation +/////////////////////////////////////////////////// + +// AsyncClose implements the AsyncClose method from the sarama.PartitionConsumer interface. +func (pc *PartitionConsumer) AsyncClose() { + pc.singleClose.Do(func() { + close(pc.messages) + close(pc.errors) + }) +} + +// Close implements the Close method from the sarama.PartitionConsumer interface. It will +// verify whether the partition consumer was actually started. +func (pc *PartitionConsumer) Close() error { + if !pc.consumed { + pc.t.Errorf("Expectations set on %s/%d, but no partition consumer was started.", pc.topic, pc.partition) + return errPartitionConsumerNotStarted + } + + if pc.errorsShouldBeDrained && len(pc.errors) > 0 { + pc.t.Errorf("Expected the errors channel for %s/%d to be drained on close, but found %d errors.", pc.topic, pc.partition, len(pc.errors)) + } + + if pc.messagesShouldBeDrained && len(pc.messages) > 0 { + pc.t.Errorf("Expected the messages channel for %s/%d to be drained on close, but found %d messages.", pc.topic, pc.partition, len(pc.messages)) + } + + pc.AsyncClose() + + var ( + closeErr error + wg sync.WaitGroup + ) + + wg.Add(1) + go func() { + defer wg.Done() + + var errs = make(sarama.ConsumerErrors, 0) + for err := range pc.errors { + errs = append(errs, err) + } + + if len(errs) > 0 { + closeErr = errs + } + }() + + wg.Add(1) + go func() { + defer wg.Done() + for _ = range pc.messages { + // drain + } + }() + + wg.Wait() + return closeErr +} + +// Errors implements the Errors method from the sarama.PartitionConsumer interface. +func (pc *PartitionConsumer) Errors() <-chan *sarama.ConsumerError { + return pc.errors +} + +// Messages implements the Messages method from the sarama.PartitionConsumer interface. +func (pc *PartitionConsumer) Messages() <-chan *sarama.ConsumerMessage { + return pc.messages +} + +func (pc *PartitionConsumer) HighWaterMarkOffset() int64 { + return atomic.LoadInt64(&pc.highWaterMarkOffset) + 1 +} + +/////////////////////////////////////////////////// +// Expectation API +/////////////////////////////////////////////////// + +// YieldMessage will yield a messages Messages channel of this partition consumer +// when it is consumed. By default, the mock consumer will not verify whether this +// message was consumed from the Messages channel, because there are legitimate +// reasons forthis not to happen. ou can call ExpectMessagesDrainedOnClose so it will +// verify that the channel is empty on close. +func (pc *PartitionConsumer) YieldMessage(msg *sarama.ConsumerMessage) { + pc.l.Lock() + defer pc.l.Unlock() + + msg.Topic = pc.topic + msg.Partition = pc.partition + msg.Offset = atomic.AddInt64(&pc.highWaterMarkOffset, 1) + + pc.messages <- msg +} + +// YieldError will yield an error on the Errors channel of this partition consumer +// when it is consumed. By default, the mock consumer will not verify whether this error was +// consumed from the Errors channel, because there are legitimate reasons for this +// not to happen. You can call ExpectErrorsDrainedOnClose so it will verify that +// the channel is empty on close. +func (pc *PartitionConsumer) YieldError(err error) { + pc.errors <- &sarama.ConsumerError{ + Topic: pc.topic, + Partition: pc.partition, + Err: err, + } +} + +// ExpectMessagesDrainedOnClose sets an expectation on the partition consumer +// that the messages channel will be fully drained when Close is called. If this +// expectation is not met, an error is reported to the error reporter. +func (pc *PartitionConsumer) ExpectMessagesDrainedOnClose() { + pc.messagesShouldBeDrained = true +} + +// ExpectErrorsDrainedOnClose sets an expectation on the partition consumer +// that the errors channel will be fully drained when Close is called. If this +// expectation is not met, an error is reported to the error reporter. +func (pc *PartitionConsumer) ExpectErrorsDrainedOnClose() { + pc.errorsShouldBeDrained = true +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/consumer_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/consumer_test.go new file mode 100644 index 00000000..50dad3a6 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/consumer_test.go @@ -0,0 +1,249 @@ +package mocks + +import ( + "sort" + "testing" + + "github.com/Shopify/sarama" +) + +func TestMockConsumerImplementsConsumerInterface(t *testing.T) { + var c interface{} = &Consumer{} + if _, ok := c.(sarama.Consumer); !ok { + t.Error("The mock consumer should implement the sarama.Consumer interface.") + } + + var pc interface{} = &PartitionConsumer{} + if _, ok := pc.(sarama.PartitionConsumer); !ok { + t.Error("The mock partitionconsumer should implement the sarama.PartitionConsumer interface.") + } +} + +func TestConsumerHandlesExpectations(t *testing.T) { + consumer := NewConsumer(t, nil) + defer func() { + if err := consumer.Close(); err != nil { + t.Error(err) + } + }() + + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest).YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello world")}) + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest).YieldError(sarama.ErrOutOfBrokers) + consumer.ExpectConsumePartition("test", 1, sarama.OffsetOldest).YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello world again")}) + consumer.ExpectConsumePartition("other", 0, AnyOffset).YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello other")}) + + pc_test0, err := consumer.ConsumePartition("test", 0, sarama.OffsetOldest) + if err != nil { + t.Fatal(err) + } + test0_msg := <-pc_test0.Messages() + if test0_msg.Topic != "test" || test0_msg.Partition != 0 || string(test0_msg.Value) != "hello world" { + t.Error("Message was not as expected:", test0_msg) + } + test0_err := <-pc_test0.Errors() + if test0_err.Err != sarama.ErrOutOfBrokers { + t.Error("Expected sarama.ErrOutOfBrokers, found:", test0_err.Err) + } + + pc_test1, err := consumer.ConsumePartition("test", 1, sarama.OffsetOldest) + if err != nil { + t.Fatal(err) + } + test1_msg := <-pc_test1.Messages() + if test1_msg.Topic != "test" || test1_msg.Partition != 1 || string(test1_msg.Value) != "hello world again" { + t.Error("Message was not as expected:", test1_msg) + } + + pc_other0, err := consumer.ConsumePartition("other", 0, sarama.OffsetNewest) + if err != nil { + t.Fatal(err) + } + other0_msg := <-pc_other0.Messages() + if other0_msg.Topic != "other" || other0_msg.Partition != 0 || string(other0_msg.Value) != "hello other" { + t.Error("Message was not as expected:", other0_msg) + } +} + +func TestConsumerReturnsNonconsumedErrorsOnClose(t *testing.T) { + consumer := NewConsumer(t, nil) + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest).YieldError(sarama.ErrOutOfBrokers) + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest).YieldError(sarama.ErrOutOfBrokers) + + pc, err := consumer.ConsumePartition("test", 0, sarama.OffsetOldest) + if err != nil { + t.Fatal(err) + } + + select { + case <-pc.Messages(): + t.Error("Did not epxect a message on the messages channel.") + case err := <-pc.Errors(): + if err.Err != sarama.ErrOutOfBrokers { + t.Error("Expected sarama.ErrOutOfBrokers, found", err) + } + } + + errs := pc.Close().(sarama.ConsumerErrors) + if len(errs) != 1 && errs[0].Err != sarama.ErrOutOfBrokers { + t.Error("Expected Close to return the remaining sarama.ErrOutOfBrokers") + } +} + +func TestConsumerWithoutExpectationsOnPartition(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + + _, err := consumer.ConsumePartition("test", 1, sarama.OffsetOldest) + if err != errOutOfExpectations { + t.Error("Expected ConsumePartition to return errOutOfExpectations") + } + + if err := consumer.Close(); err != nil { + t.Error("No error expected on close, but found:", err) + } + + if len(trm.errors) != 1 { + t.Errorf("Expected an expectation failure to be set on the error reporter.") + } +} + +func TestConsumerWithExpectationsOnUnconsumedPartition(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest).YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello world")}) + + if err := consumer.Close(); err != nil { + t.Error("No error expected on close, but found:", err) + } + + if len(trm.errors) != 1 { + t.Errorf("Expected an expectation failure to be set on the error reporter.") + } +} + +func TestConsumerWithWrongOffsetExpectation(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest) + + _, err := consumer.ConsumePartition("test", 0, sarama.OffsetNewest) + if err != nil { + t.Error("Did not expect error, found:", err) + } + + if len(trm.errors) != 1 { + t.Errorf("Expected an expectation failure to be set on the error reporter.") + } + + if err := consumer.Close(); err != nil { + t.Error(err) + } +} + +func TestConsumerViolatesMessagesDrainedExpectation(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + pcmock := consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest) + pcmock.YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello")}) + pcmock.YieldMessage(&sarama.ConsumerMessage{Value: []byte("hello")}) + pcmock.ExpectMessagesDrainedOnClose() + + pc, err := consumer.ConsumePartition("test", 0, sarama.OffsetOldest) + if err != nil { + t.Error(err) + } + + // consume first message, not second one + <-pc.Messages() + + if err := consumer.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Errorf("Expected an expectation failure to be set on the error reporter.") + } +} + +func TestConsumerMeetsErrorsDrainedExpectation(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + + pcmock := consumer.ExpectConsumePartition("test", 0, sarama.OffsetOldest) + pcmock.YieldError(sarama.ErrInvalidMessage) + pcmock.YieldError(sarama.ErrInvalidMessage) + pcmock.ExpectErrorsDrainedOnClose() + + pc, err := consumer.ConsumePartition("test", 0, sarama.OffsetOldest) + if err != nil { + t.Error(err) + } + + // consume first and second error, + <-pc.Errors() + <-pc.Errors() + + if err := consumer.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 0 { + t.Errorf("Expected no expectation failures to be set on the error reporter.") + } +} + +func TestConsumerTopicMetadata(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + + consumer.SetTopicMetadata(map[string][]int32{ + "test1": []int32{0, 1, 2, 3}, + "test2": []int32{0, 1, 2, 3, 4, 5, 6, 7}, + }) + + topics, err := consumer.Topics() + if err != nil { + t.Error(t) + } + + sortedTopics := sort.StringSlice(topics) + sortedTopics.Sort() + if len(sortedTopics) != 2 || sortedTopics[0] != "test1" || sortedTopics[1] != "test2" { + t.Error("Unexpected topics returned:", sortedTopics) + } + + partitions1, err := consumer.Partitions("test1") + if err != nil { + t.Error(t) + } + + if len(partitions1) != 4 { + t.Error("Unexpected partitions returned:", len(partitions1)) + } + + partitions2, err := consumer.Partitions("test2") + if err != nil { + t.Error(t) + } + + if len(partitions2) != 8 { + t.Error("Unexpected partitions returned:", len(partitions2)) + } + + if len(trm.errors) != 0 { + t.Errorf("Expected no expectation failures to be set on the error reporter.") + } +} + +func TestConsumerUnexpectedTopicMetadata(t *testing.T) { + trm := newTestReporterMock() + consumer := NewConsumer(trm, nil) + + if _, err := consumer.Topics(); err != sarama.ErrOutOfBrokers { + t.Error("Expected sarama.ErrOutOfBrokers, found", err) + } + + if len(trm.errors) != 1 { + t.Errorf("Expected an expectation failure to be set on the error reporter.") + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/mocks.go b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/mocks.go new file mode 100644 index 00000000..4adb838d --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/mocks.go @@ -0,0 +1,48 @@ +/* +Package mocks provides mocks that can be used for testing applications +that use Sarama. The mock types provided by this package implement the +interfaces Sarama exports, so you can use them for dependency injection +in your tests. + +All mock instances require you to set expectations on them before you +can use them. It will determine how the mock will behave. If an +expectation is not met, it will make your test fail. + +NOTE: this package currently does not fall under the API stability +guarantee of Sarama as it is still considered experimental. +*/ +package mocks + +import ( + "errors" + + "github.com/Shopify/sarama" +) + +// ErrorReporter is a simple interface that includes the testing.T methods we use to report +// expectation violations when using the mock objects. +type ErrorReporter interface { + Errorf(string, ...interface{}) +} + +// ValueChecker is a function type to be set in each expectation of the producer mocks +// to check the value passed. +type ValueChecker func(val []byte) error + +var ( + errProduceSuccess error = nil + errOutOfExpectations = errors.New("No more expectations set on mock") + errPartitionConsumerNotStarted = errors.New("The partition consumer was never started") +) + +const AnyOffset int64 = -1000 + +type producerExpectation struct { + Result error + CheckFunction ValueChecker +} + +type consumerExpectation struct { + Err error + Msg *sarama.ConsumerMessage +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/sync_producer.go b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/sync_producer.go new file mode 100644 index 00000000..2ac7b5c3 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/sync_producer.go @@ -0,0 +1,148 @@ +package mocks + +import ( + "sync" + + "github.com/Shopify/sarama" +) + +// SyncProducer implements sarama's SyncProducer interface for testing purposes. +// Before you can use it, you have to set expectations on the mock SyncProducer +// to tell it how to handle calls to SendMessage, so you can easily test success +// and failure scenarios. +type SyncProducer struct { + l sync.Mutex + t ErrorReporter + expectations []*producerExpectation + lastOffset int64 +} + +// NewSyncProducer instantiates a new SyncProducer mock. The t argument should +// be the *testing.T instance of your test method. An error will be written to it if +// an expectation is violated. The config argument is currently unused, but is +// maintained to be compatible with the async Producer. +func NewSyncProducer(t ErrorReporter, config *sarama.Config) *SyncProducer { + return &SyncProducer{ + t: t, + expectations: make([]*producerExpectation, 0), + } +} + +//////////////////////////////////////////////// +// Implement SyncProducer interface +//////////////////////////////////////////////// + +// SendMessage corresponds with the SendMessage method of sarama's SyncProducer implementation. +// You have to set expectations on the mock producer before calling SendMessage, so it knows +// how to handle them. You can set a function in each expectation so that the message value +// checked by this function and an error is returned if the match fails. +// If there is no more remaining expectation when SendMessage is called, +// the mock producer will write an error to the test state object. +func (sp *SyncProducer) SendMessage(msg *sarama.ProducerMessage) (partition int32, offset int64, err error) { + sp.l.Lock() + defer sp.l.Unlock() + + if len(sp.expectations) > 0 { + expectation := sp.expectations[0] + sp.expectations = sp.expectations[1:] + if expectation.CheckFunction != nil { + if val, err := msg.Value.Encode(); err != nil { + sp.t.Errorf("Input message encoding failed: %s", err.Error()) + return -1, -1, err + } else { + err := expectation.CheckFunction(val) + if err != nil { + sp.t.Errorf("Check function returned an error: %s", err.Error()) + return -1, -1, err + } + } + } + if expectation.Result == errProduceSuccess { + sp.lastOffset++ + msg.Offset = sp.lastOffset + return 0, msg.Offset, nil + } else { + return -1, -1, expectation.Result + } + } else { + sp.t.Errorf("No more expectation set on this mock producer to handle the input message.") + return -1, -1, errOutOfExpectations + } +} + +// SendMessages corresponds with the SendMessages method of sarama's SyncProducer implementation. +// You have to set expectations on the mock producer before calling SendMessages, so it knows +// how to handle them. If there is no more remaining expectations when SendMessages is called, +// the mock producer will write an error to the test state object. +func (sp *SyncProducer) SendMessages(msgs []*sarama.ProducerMessage) error { + sp.l.Lock() + defer sp.l.Unlock() + + if len(sp.expectations) >= len(msgs) { + expectations := sp.expectations[0 : len(msgs)-1] + sp.expectations = sp.expectations[len(msgs):] + + for _, expectation := range expectations { + if expectation.Result != errProduceSuccess { + return expectation.Result + } + + } + return nil + } else { + sp.t.Errorf("Insufficient expectations set on this mock producer to handle the input messages.") + return errOutOfExpectations + } +} + +// Close corresponds with the Close method of sarama's SyncProducer implementation. +// By closing a mock syncproducer, you also tell it that no more SendMessage calls will follow, +// so it will write an error to the test state if there's any remaining expectations. +func (sp *SyncProducer) Close() error { + sp.l.Lock() + defer sp.l.Unlock() + + if len(sp.expectations) > 0 { + sp.t.Errorf("Expected to exhaust all expectations, but %d are left.", len(sp.expectations)) + } + + return nil +} + +//////////////////////////////////////////////// +// Setting expectations +//////////////////////////////////////////////// + +// ExpectSendMessageWithCheckerFunctionAndSucceed sets an expectation on the mock producer that SendMessage +// will be called. The mock producer will first call the given function to check the message value. +// It will cascade the error of the function, if any, or handle the message as if it produced +// successfully, i.e. by returning a valid partition, and offset, and a nil error. +func (sp *SyncProducer) ExpectSendMessageWithCheckerFunctionAndSucceed(cf ValueChecker) { + sp.l.Lock() + defer sp.l.Unlock() + sp.expectations = append(sp.expectations, &producerExpectation{Result: errProduceSuccess, CheckFunction: cf}) +} + +// ExpectSendMessageAndFail sets an expectation on the mock producer that SendMessage will be +// called. The mock producer will first call the given function to check the message value. +// It will cascade the error of the function, if any, or handle the message as if it failed +// to produce successfully, i.e. by returning the provided error. +func (sp *SyncProducer) ExpectSendMessageWithCheckerFunctionAndFail(cf ValueChecker, err error) { + sp.l.Lock() + defer sp.l.Unlock() + sp.expectations = append(sp.expectations, &producerExpectation{Result: err, CheckFunction: cf}) +} + +// ExpectSendMessageAndSucceed sets an expectation on the mock producer that SendMessage will be +// called. The mock producer will handle the message as if it produced successfully, i.e. by +// returning a valid partition, and offset, and a nil error. +func (sp *SyncProducer) ExpectSendMessageAndSucceed() { + sp.ExpectSendMessageWithCheckerFunctionAndSucceed(nil) +} + +// ExpectSendMessageAndFail sets an expectation on the mock producer that SendMessage will be +// called. The mock producer will handle the message as if it failed to produce +// successfully, i.e. by returning the provided error. +func (sp *SyncProducer) ExpectSendMessageAndFail(err error) { + sp.ExpectSendMessageWithCheckerFunctionAndFail(nil, err) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/sync_producer_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/sync_producer_test.go new file mode 100644 index 00000000..0fdc9987 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/mocks/sync_producer_test.go @@ -0,0 +1,124 @@ +package mocks + +import ( + "strings" + "testing" + + "github.com/Shopify/sarama" +) + +func TestMockSyncProducerImplementsSyncProducerInterface(t *testing.T) { + var mp interface{} = &SyncProducer{} + if _, ok := mp.(sarama.SyncProducer); !ok { + t.Error("The mock async producer should implement the sarama.SyncProducer interface.") + } +} + +func TestSyncProducerReturnsExpectationsToSendMessage(t *testing.T) { + sp := NewSyncProducer(t, nil) + defer func() { + if err := sp.Close(); err != nil { + t.Error(err) + } + }() + + sp.ExpectSendMessageAndSucceed() + sp.ExpectSendMessageAndSucceed() + sp.ExpectSendMessageAndFail(sarama.ErrOutOfBrokers) + + msg := &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + + _, offset, err := sp.SendMessage(msg) + if err != nil { + t.Errorf("The first message should have been produced successfully, but got %s", err) + } + if offset != 1 || offset != msg.Offset { + t.Errorf("The first message should have been assigned offset 1, but got %d", msg.Offset) + } + + _, offset, err = sp.SendMessage(msg) + if err != nil { + t.Errorf("The second message should have been produced successfully, but got %s", err) + } + if offset != 2 || offset != msg.Offset { + t.Errorf("The second message should have been assigned offset 2, but got %d", offset) + } + + _, _, err = sp.SendMessage(msg) + if err != sarama.ErrOutOfBrokers { + t.Errorf("The third message should not have been produced successfully") + } + + if err := sp.Close(); err != nil { + t.Error(err) + } +} + +func TestSyncProducerWithTooManyExpectations(t *testing.T) { + trm := newTestReporterMock() + + sp := NewSyncProducer(trm, nil) + sp.ExpectSendMessageAndSucceed() + sp.ExpectSendMessageAndFail(sarama.ErrOutOfBrokers) + + msg := &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + if _, _, err := sp.SendMessage(msg); err != nil { + t.Error("No error expected on first SendMessage call", err) + } + + if err := sp.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Error("Expected to report an error") + } +} + +func TestSyncProducerWithTooFewExpectations(t *testing.T) { + trm := newTestReporterMock() + + sp := NewSyncProducer(trm, nil) + sp.ExpectSendMessageAndSucceed() + + msg := &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + if _, _, err := sp.SendMessage(msg); err != nil { + t.Error("No error expected on first SendMessage call", err) + } + if _, _, err := sp.SendMessage(msg); err != errOutOfExpectations { + t.Error("errOutOfExpectations expected on second SendMessage call, found:", err) + } + + if err := sp.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Error("Expected to report an error") + } +} + +func TestSyncProducerWithCheckerFunction(t *testing.T) { + trm := newTestReporterMock() + + sp := NewSyncProducer(trm, nil) + sp.ExpectSendMessageWithCheckerFunctionAndSucceed(generateRegexpChecker("^tes")) + sp.ExpectSendMessageWithCheckerFunctionAndSucceed(generateRegexpChecker("^tes$")) + + msg := &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + if _, _, err := sp.SendMessage(msg); err != nil { + t.Error("No error expected on first SendMessage call, found: ", err) + } + msg = &sarama.ProducerMessage{Topic: "test", Value: sarama.StringEncoder("test")} + if _, _, err := sp.SendMessage(msg); err == nil || !strings.HasPrefix(err.Error(), "No match") { + t.Error("Error during value check expected on second SendMessage call, found:", err) + } + + if err := sp.Close(); err != nil { + t.Error(err) + } + + if len(trm.errors) != 1 { + t.Error("Expected to report an error") + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_request.go new file mode 100644 index 00000000..b21ea634 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_request.go @@ -0,0 +1,190 @@ +package sarama + +// ReceiveTime is a special value for the timestamp field of Offset Commit Requests which +// tells the broker to set the timestamp to the time at which the request was received. +// The timestamp is only used if message version 1 is used, which requires kafka 0.8.2. +const ReceiveTime int64 = -1 + +// GroupGenerationUndefined is a special value for the group generation field of +// Offset Commit Requests that should be used when a consumer group does not rely +// on Kafka for partition management. +const GroupGenerationUndefined = -1 + +type offsetCommitRequestBlock struct { + offset int64 + timestamp int64 + metadata string +} + +func (b *offsetCommitRequestBlock) encode(pe packetEncoder, version int16) error { + pe.putInt64(b.offset) + if version == 1 { + pe.putInt64(b.timestamp) + } else if b.timestamp != 0 { + Logger.Println("Non-zero timestamp specified for OffsetCommitRequest not v1, it will be ignored") + } + + return pe.putString(b.metadata) +} + +func (b *offsetCommitRequestBlock) decode(pd packetDecoder, version int16) (err error) { + if b.offset, err = pd.getInt64(); err != nil { + return err + } + if version == 1 { + if b.timestamp, err = pd.getInt64(); err != nil { + return err + } + } + b.metadata, err = pd.getString() + return err +} + +type OffsetCommitRequest struct { + ConsumerGroup string + ConsumerGroupGeneration int32 // v1 or later + ConsumerID string // v1 or later + RetentionTime int64 // v2 or later + + // Version can be: + // - 0 (kafka 0.8.1 and later) + // - 1 (kafka 0.8.2 and later) + // - 2 (kafka 0.9.0 and later) + Version int16 + blocks map[string]map[int32]*offsetCommitRequestBlock +} + +func (r *OffsetCommitRequest) encode(pe packetEncoder) error { + if r.Version < 0 || r.Version > 2 { + return PacketEncodingError{"invalid or unsupported OffsetCommitRequest version field"} + } + + if err := pe.putString(r.ConsumerGroup); err != nil { + return err + } + + if r.Version >= 1 { + pe.putInt32(r.ConsumerGroupGeneration) + if err := pe.putString(r.ConsumerID); err != nil { + return err + } + } else { + if r.ConsumerGroupGeneration != 0 { + Logger.Println("Non-zero ConsumerGroupGeneration specified for OffsetCommitRequest v0, it will be ignored") + } + if r.ConsumerID != "" { + Logger.Println("Non-empty ConsumerID specified for OffsetCommitRequest v0, it will be ignored") + } + } + + if r.Version >= 2 { + pe.putInt64(r.RetentionTime) + } else if r.RetentionTime != 0 { + Logger.Println("Non-zero RetentionTime specified for OffsetCommitRequest version <2, it will be ignored") + } + + if err := pe.putArrayLength(len(r.blocks)); err != nil { + return err + } + for topic, partitions := range r.blocks { + if err := pe.putString(topic); err != nil { + return err + } + if err := pe.putArrayLength(len(partitions)); err != nil { + return err + } + for partition, block := range partitions { + pe.putInt32(partition) + if err := block.encode(pe, r.Version); err != nil { + return err + } + } + } + return nil +} + +func (r *OffsetCommitRequest) decode(pd packetDecoder, version int16) (err error) { + r.Version = version + + if r.ConsumerGroup, err = pd.getString(); err != nil { + return err + } + + if r.Version >= 1 { + if r.ConsumerGroupGeneration, err = pd.getInt32(); err != nil { + return err + } + if r.ConsumerID, err = pd.getString(); err != nil { + return err + } + } + + if r.Version >= 2 { + if r.RetentionTime, err = pd.getInt64(); err != nil { + return err + } + } + + topicCount, err := pd.getArrayLength() + if err != nil { + return err + } + if topicCount == 0 { + return nil + } + r.blocks = make(map[string]map[int32]*offsetCommitRequestBlock) + for i := 0; i < topicCount; i++ { + topic, err := pd.getString() + if err != nil { + return err + } + partitionCount, err := pd.getArrayLength() + if err != nil { + return err + } + r.blocks[topic] = make(map[int32]*offsetCommitRequestBlock) + for j := 0; j < partitionCount; j++ { + partition, err := pd.getInt32() + if err != nil { + return err + } + block := &offsetCommitRequestBlock{} + if err := block.decode(pd, r.Version); err != nil { + return err + } + r.blocks[topic][partition] = block + } + } + return nil +} + +func (r *OffsetCommitRequest) key() int16 { + return 8 +} + +func (r *OffsetCommitRequest) version() int16 { + return r.Version +} + +func (r *OffsetCommitRequest) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_8_2_0 + case 2: + return V0_9_0_0 + default: + return minVersion + } +} + +func (r *OffsetCommitRequest) AddBlock(topic string, partitionID int32, offset int64, timestamp int64, metadata string) { + if r.blocks == nil { + r.blocks = make(map[string]map[int32]*offsetCommitRequestBlock) + } + + if r.blocks[topic] == nil { + r.blocks[topic] = make(map[int32]*offsetCommitRequestBlock) + } + + r.blocks[topic][partitionID] = &offsetCommitRequestBlock{offset, timestamp, metadata} +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_request_test.go new file mode 100644 index 00000000..afc25b7b --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_request_test.go @@ -0,0 +1,90 @@ +package sarama + +import "testing" + +var ( + offsetCommitRequestNoBlocksV0 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x00, 0x00} + + offsetCommitRequestNoBlocksV1 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x11, 0x22, + 0x00, 0x04, 'c', 'o', 'n', 's', + 0x00, 0x00, 0x00, 0x00} + + offsetCommitRequestNoBlocksV2 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x11, 0x22, + 0x00, 0x04, 'c', 'o', 'n', 's', + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x33, + 0x00, 0x00, 0x00, 0x00} + + offsetCommitRequestOneBlockV0 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x52, 0x21, + 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, + 0x00, 0x08, 'm', 'e', 't', 'a', 'd', 'a', 't', 'a'} + + offsetCommitRequestOneBlockV1 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x11, 0x22, + 0x00, 0x04, 'c', 'o', 'n', 's', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x52, 0x21, + 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x08, 'm', 'e', 't', 'a', 'd', 'a', 't', 'a'} + + offsetCommitRequestOneBlockV2 = []byte{ + 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', + 0x00, 0x00, 0x11, 0x22, + 0x00, 0x04, 'c', 'o', 'n', 's', + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x33, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x52, 0x21, + 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, + 0x00, 0x08, 'm', 'e', 't', 'a', 'd', 'a', 't', 'a'} +) + +func TestOffsetCommitRequestV0(t *testing.T) { + request := new(OffsetCommitRequest) + request.Version = 0 + request.ConsumerGroup = "foobar" + testRequest(t, "no blocks v0", request, offsetCommitRequestNoBlocksV0) + + request.AddBlock("topic", 0x5221, 0xDEADBEEF, 0, "metadata") + testRequest(t, "one block v0", request, offsetCommitRequestOneBlockV0) +} + +func TestOffsetCommitRequestV1(t *testing.T) { + request := new(OffsetCommitRequest) + request.ConsumerGroup = "foobar" + request.ConsumerID = "cons" + request.ConsumerGroupGeneration = 0x1122 + request.Version = 1 + testRequest(t, "no blocks v1", request, offsetCommitRequestNoBlocksV1) + + request.AddBlock("topic", 0x5221, 0xDEADBEEF, ReceiveTime, "metadata") + testRequest(t, "one block v1", request, offsetCommitRequestOneBlockV1) +} + +func TestOffsetCommitRequestV2(t *testing.T) { + request := new(OffsetCommitRequest) + request.ConsumerGroup = "foobar" + request.ConsumerID = "cons" + request.ConsumerGroupGeneration = 0x1122 + request.RetentionTime = 0x4433 + request.Version = 2 + testRequest(t, "no blocks v2", request, offsetCommitRequestNoBlocksV2) + + request.AddBlock("topic", 0x5221, 0xDEADBEEF, 0, "metadata") + testRequest(t, "one block v2", request, offsetCommitRequestOneBlockV2) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_response.go new file mode 100644 index 00000000..7f277e77 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_response.go @@ -0,0 +1,85 @@ +package sarama + +type OffsetCommitResponse struct { + Errors map[string]map[int32]KError +} + +func (r *OffsetCommitResponse) AddError(topic string, partition int32, kerror KError) { + if r.Errors == nil { + r.Errors = make(map[string]map[int32]KError) + } + partitions := r.Errors[topic] + if partitions == nil { + partitions = make(map[int32]KError) + r.Errors[topic] = partitions + } + partitions[partition] = kerror +} + +func (r *OffsetCommitResponse) encode(pe packetEncoder) error { + if err := pe.putArrayLength(len(r.Errors)); err != nil { + return err + } + for topic, partitions := range r.Errors { + if err := pe.putString(topic); err != nil { + return err + } + if err := pe.putArrayLength(len(partitions)); err != nil { + return err + } + for partition, kerror := range partitions { + pe.putInt32(partition) + pe.putInt16(int16(kerror)) + } + } + return nil +} + +func (r *OffsetCommitResponse) decode(pd packetDecoder, version int16) (err error) { + numTopics, err := pd.getArrayLength() + if err != nil || numTopics == 0 { + return err + } + + r.Errors = make(map[string]map[int32]KError, numTopics) + for i := 0; i < numTopics; i++ { + name, err := pd.getString() + if err != nil { + return err + } + + numErrors, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Errors[name] = make(map[int32]KError, numErrors) + + for j := 0; j < numErrors; j++ { + id, err := pd.getInt32() + if err != nil { + return err + } + + tmp, err := pd.getInt16() + if err != nil { + return err + } + r.Errors[name][id] = KError(tmp) + } + } + + return nil +} + +func (r *OffsetCommitResponse) key() int16 { + return 8 +} + +func (r *OffsetCommitResponse) version() int16 { + return 0 +} + +func (r *OffsetCommitResponse) requiredVersion() KafkaVersion { + return minVersion +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_response_test.go new file mode 100644 index 00000000..074ec923 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_commit_response_test.go @@ -0,0 +1,24 @@ +package sarama + +import ( + "testing" +) + +var ( + emptyOffsetCommitResponse = []byte{ + 0x00, 0x00, 0x00, 0x00} +) + +func TestEmptyOffsetCommitResponse(t *testing.T) { + response := OffsetCommitResponse{} + testResponse(t, "empty", &response, emptyOffsetCommitResponse) +} + +func TestNormalOffsetCommitResponse(t *testing.T) { + response := OffsetCommitResponse{} + response.AddError("t", 0, ErrNotLeaderForPartition) + response.Errors["m"] = make(map[int32]KError) + // The response encoded form cannot be checked for it varies due to + // unpredictable map traversal order. + testResponse(t, "normal", &response, nil) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_request.go new file mode 100644 index 00000000..b19fe79b --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_request.go @@ -0,0 +1,81 @@ +package sarama + +type OffsetFetchRequest struct { + ConsumerGroup string + Version int16 + partitions map[string][]int32 +} + +func (r *OffsetFetchRequest) encode(pe packetEncoder) (err error) { + if r.Version < 0 || r.Version > 1 { + return PacketEncodingError{"invalid or unsupported OffsetFetchRequest version field"} + } + + if err = pe.putString(r.ConsumerGroup); err != nil { + return err + } + if err = pe.putArrayLength(len(r.partitions)); err != nil { + return err + } + for topic, partitions := range r.partitions { + if err = pe.putString(topic); err != nil { + return err + } + if err = pe.putInt32Array(partitions); err != nil { + return err + } + } + return nil +} + +func (r *OffsetFetchRequest) decode(pd packetDecoder, version int16) (err error) { + r.Version = version + if r.ConsumerGroup, err = pd.getString(); err != nil { + return err + } + partitionCount, err := pd.getArrayLength() + if err != nil { + return err + } + if partitionCount == 0 { + return nil + } + r.partitions = make(map[string][]int32) + for i := 0; i < partitionCount; i++ { + topic, err := pd.getString() + if err != nil { + return err + } + partitions, err := pd.getInt32Array() + if err != nil { + return err + } + r.partitions[topic] = partitions + } + return nil +} + +func (r *OffsetFetchRequest) key() int16 { + return 9 +} + +func (r *OffsetFetchRequest) version() int16 { + return r.Version +} + +func (r *OffsetFetchRequest) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_8_2_0 + default: + return minVersion + } +} + +func (r *OffsetFetchRequest) AddPartition(topic string, partitionID int32) { + if r.partitions == nil { + r.partitions = make(map[string][]int32) + } + + r.partitions[topic] = append(r.partitions[topic], partitionID) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_request_test.go new file mode 100644 index 00000000..025d725c --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_request_test.go @@ -0,0 +1,31 @@ +package sarama + +import "testing" + +var ( + offsetFetchRequestNoGroupNoPartitions = []byte{ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} + + offsetFetchRequestNoPartitions = []byte{ + 0x00, 0x04, 'b', 'l', 'a', 'h', + 0x00, 0x00, 0x00, 0x00} + + offsetFetchRequestOnePartition = []byte{ + 0x00, 0x04, 'b', 'l', 'a', 'h', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x0D, 't', 'o', 'p', 'i', 'c', 'T', 'h', 'e', 'F', 'i', 'r', 's', 't', + 0x00, 0x00, 0x00, 0x01, + 0x4F, 0x4F, 0x4F, 0x4F} +) + +func TestOffsetFetchRequest(t *testing.T) { + request := new(OffsetFetchRequest) + testRequest(t, "no group, no partitions", request, offsetFetchRequestNoGroupNoPartitions) + + request.ConsumerGroup = "blah" + testRequest(t, "no partitions", request, offsetFetchRequestNoPartitions) + + request.AddPartition("topicTheFirst", 0x4F4F4F4F) + testRequest(t, "one partition", request, offsetFetchRequestOnePartition) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_response.go new file mode 100644 index 00000000..323220ea --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_response.go @@ -0,0 +1,143 @@ +package sarama + +type OffsetFetchResponseBlock struct { + Offset int64 + Metadata string + Err KError +} + +func (b *OffsetFetchResponseBlock) decode(pd packetDecoder) (err error) { + b.Offset, err = pd.getInt64() + if err != nil { + return err + } + + b.Metadata, err = pd.getString() + if err != nil { + return err + } + + tmp, err := pd.getInt16() + if err != nil { + return err + } + b.Err = KError(tmp) + + return nil +} + +func (b *OffsetFetchResponseBlock) encode(pe packetEncoder) (err error) { + pe.putInt64(b.Offset) + + err = pe.putString(b.Metadata) + if err != nil { + return err + } + + pe.putInt16(int16(b.Err)) + + return nil +} + +type OffsetFetchResponse struct { + Blocks map[string]map[int32]*OffsetFetchResponseBlock +} + +func (r *OffsetFetchResponse) encode(pe packetEncoder) error { + if err := pe.putArrayLength(len(r.Blocks)); err != nil { + return err + } + for topic, partitions := range r.Blocks { + if err := pe.putString(topic); err != nil { + return err + } + if err := pe.putArrayLength(len(partitions)); err != nil { + return err + } + for partition, block := range partitions { + pe.putInt32(partition) + if err := block.encode(pe); err != nil { + return err + } + } + } + return nil +} + +func (r *OffsetFetchResponse) decode(pd packetDecoder, version int16) (err error) { + numTopics, err := pd.getArrayLength() + if err != nil || numTopics == 0 { + return err + } + + r.Blocks = make(map[string]map[int32]*OffsetFetchResponseBlock, numTopics) + for i := 0; i < numTopics; i++ { + name, err := pd.getString() + if err != nil { + return err + } + + numBlocks, err := pd.getArrayLength() + if err != nil { + return err + } + + if numBlocks == 0 { + r.Blocks[name] = nil + continue + } + r.Blocks[name] = make(map[int32]*OffsetFetchResponseBlock, numBlocks) + + for j := 0; j < numBlocks; j++ { + id, err := pd.getInt32() + if err != nil { + return err + } + + block := new(OffsetFetchResponseBlock) + err = block.decode(pd) + if err != nil { + return err + } + r.Blocks[name][id] = block + } + } + + return nil +} + +func (r *OffsetFetchResponse) key() int16 { + return 9 +} + +func (r *OffsetFetchResponse) version() int16 { + return 0 +} + +func (r *OffsetFetchResponse) requiredVersion() KafkaVersion { + return minVersion +} + +func (r *OffsetFetchResponse) GetBlock(topic string, partition int32) *OffsetFetchResponseBlock { + if r.Blocks == nil { + return nil + } + + if r.Blocks[topic] == nil { + return nil + } + + return r.Blocks[topic][partition] +} + +func (r *OffsetFetchResponse) AddBlock(topic string, partition int32, block *OffsetFetchResponseBlock) { + if r.Blocks == nil { + r.Blocks = make(map[string]map[int32]*OffsetFetchResponseBlock) + } + partitions := r.Blocks[topic] + if partitions == nil { + partitions = make(map[int32]*OffsetFetchResponseBlock) + r.Blocks[topic] = partitions + } + partitions[partition] = block +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_response_test.go new file mode 100644 index 00000000..7614ae42 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_fetch_response_test.go @@ -0,0 +1,22 @@ +package sarama + +import "testing" + +var ( + emptyOffsetFetchResponse = []byte{ + 0x00, 0x00, 0x00, 0x00} +) + +func TestEmptyOffsetFetchResponse(t *testing.T) { + response := OffsetFetchResponse{} + testResponse(t, "empty", &response, emptyOffsetFetchResponse) +} + +func TestNormalOffsetFetchResponse(t *testing.T) { + response := OffsetFetchResponse{} + response.AddBlock("t", 0, &OffsetFetchResponseBlock{0, "md", ErrRequestTimedOut}) + response.Blocks["m"] = nil + // The response encoded form cannot be checked for it varies due to + // unpredictable map traversal order. + testResponse(t, "normal", &response, nil) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_manager.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_manager.go new file mode 100644 index 00000000..5e15cdaf --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_manager.go @@ -0,0 +1,542 @@ +package sarama + +import ( + "sync" + "time" +) + +// Offset Manager + +// OffsetManager uses Kafka to store and fetch consumed partition offsets. +type OffsetManager interface { + // ManagePartition creates a PartitionOffsetManager on the given topic/partition. + // It will return an error if this OffsetManager is already managing the given + // topic/partition. + ManagePartition(topic string, partition int32) (PartitionOffsetManager, error) + + // Close stops the OffsetManager from managing offsets. It is required to call + // this function before an OffsetManager object passes out of scope, as it + // will otherwise leak memory. You must call this after all the + // PartitionOffsetManagers are closed. + Close() error +} + +type offsetManager struct { + client Client + conf *Config + group string + + lock sync.Mutex + poms map[string]map[int32]*partitionOffsetManager + boms map[*Broker]*brokerOffsetManager +} + +// NewOffsetManagerFromClient creates a new OffsetManager from the given client. +// It is still necessary to call Close() on the underlying client when finished with the partition manager. +func NewOffsetManagerFromClient(group string, client Client) (OffsetManager, error) { + // Check that we are not dealing with a closed Client before processing any other arguments + if client.Closed() { + return nil, ErrClosedClient + } + + om := &offsetManager{ + client: client, + conf: client.Config(), + group: group, + poms: make(map[string]map[int32]*partitionOffsetManager), + boms: make(map[*Broker]*brokerOffsetManager), + } + + return om, nil +} + +func (om *offsetManager) ManagePartition(topic string, partition int32) (PartitionOffsetManager, error) { + pom, err := om.newPartitionOffsetManager(topic, partition) + if err != nil { + return nil, err + } + + om.lock.Lock() + defer om.lock.Unlock() + + topicManagers := om.poms[topic] + if topicManagers == nil { + topicManagers = make(map[int32]*partitionOffsetManager) + om.poms[topic] = topicManagers + } + + if topicManagers[partition] != nil { + return nil, ConfigurationError("That topic/partition is already being managed") + } + + topicManagers[partition] = pom + return pom, nil +} + +func (om *offsetManager) Close() error { + return nil +} + +func (om *offsetManager) refBrokerOffsetManager(broker *Broker) *brokerOffsetManager { + om.lock.Lock() + defer om.lock.Unlock() + + bom := om.boms[broker] + if bom == nil { + bom = om.newBrokerOffsetManager(broker) + om.boms[broker] = bom + } + + bom.refs++ + + return bom +} + +func (om *offsetManager) unrefBrokerOffsetManager(bom *brokerOffsetManager) { + om.lock.Lock() + defer om.lock.Unlock() + + bom.refs-- + + if bom.refs == 0 { + close(bom.updateSubscriptions) + if om.boms[bom.broker] == bom { + delete(om.boms, bom.broker) + } + } +} + +func (om *offsetManager) abandonBroker(bom *brokerOffsetManager) { + om.lock.Lock() + defer om.lock.Unlock() + + delete(om.boms, bom.broker) +} + +func (om *offsetManager) abandonPartitionOffsetManager(pom *partitionOffsetManager) { + om.lock.Lock() + defer om.lock.Unlock() + + delete(om.poms[pom.topic], pom.partition) + if len(om.poms[pom.topic]) == 0 { + delete(om.poms, pom.topic) + } +} + +// Partition Offset Manager + +// PartitionOffsetManager uses Kafka to store and fetch consumed partition offsets. You MUST call Close() +// on a partition offset manager to avoid leaks, it will not be garbage-collected automatically when it passes +// out of scope. +type PartitionOffsetManager interface { + // NextOffset returns the next offset that should be consumed for the managed + // partition, accompanied by metadata which can be used to reconstruct the state + // of the partition consumer when it resumes. NextOffset() will return + // `config.Consumer.Offsets.Initial` and an empty metadata string if no offset + // was committed for this partition yet. + NextOffset() (int64, string) + + // MarkOffset marks the provided offset, alongside a metadata string + // that represents the state of the partition consumer at that point in time. The + // metadata string can be used by another consumer to restore that state, so it + // can resume consumption. + // + // To follow upstream conventions, you are expected to mark the offset of the + // next message to read, not the last message read. Thus, when calling `MarkOffset` + // you should typically add one to the offset of the last consumed message. + // + // Note: calling MarkOffset does not necessarily commit the offset to the backend + // store immediately for efficiency reasons, and it may never be committed if + // your application crashes. This means that you may end up processing the same + // message twice, and your processing should ideally be idempotent. + MarkOffset(offset int64, metadata string) + + // Errors returns a read channel of errors that occur during offset management, if + // enabled. By default, errors are logged and not returned over this channel. If + // you want to implement any custom error handling, set your config's + // Consumer.Return.Errors setting to true, and read from this channel. + Errors() <-chan *ConsumerError + + // AsyncClose initiates a shutdown of the PartitionOffsetManager. This method will + // return immediately, after which you should wait until the 'errors' channel has + // been drained and closed. It is required to call this function, or Close before + // a consumer object passes out of scope, as it will otherwise leak memory. You + // must call this before calling Close on the underlying client. + AsyncClose() + + // Close stops the PartitionOffsetManager from managing offsets. It is required to + // call this function (or AsyncClose) before a PartitionOffsetManager object + // passes out of scope, as it will otherwise leak memory. You must call this + // before calling Close on the underlying client. + Close() error +} + +type partitionOffsetManager struct { + parent *offsetManager + topic string + partition int32 + + lock sync.Mutex + offset int64 + metadata string + dirty bool + clean sync.Cond + broker *brokerOffsetManager + + errors chan *ConsumerError + rebalance chan none + dying chan none +} + +func (om *offsetManager) newPartitionOffsetManager(topic string, partition int32) (*partitionOffsetManager, error) { + pom := &partitionOffsetManager{ + parent: om, + topic: topic, + partition: partition, + errors: make(chan *ConsumerError, om.conf.ChannelBufferSize), + rebalance: make(chan none, 1), + dying: make(chan none), + } + pom.clean.L = &pom.lock + + if err := pom.selectBroker(); err != nil { + return nil, err + } + + if err := pom.fetchInitialOffset(om.conf.Metadata.Retry.Max); err != nil { + return nil, err + } + + pom.broker.updateSubscriptions <- pom + + go withRecover(pom.mainLoop) + + return pom, nil +} + +func (pom *partitionOffsetManager) mainLoop() { + for { + select { + case <-pom.rebalance: + if err := pom.selectBroker(); err != nil { + pom.handleError(err) + pom.rebalance <- none{} + } else { + pom.broker.updateSubscriptions <- pom + } + case <-pom.dying: + if pom.broker != nil { + select { + case <-pom.rebalance: + case pom.broker.updateSubscriptions <- pom: + } + pom.parent.unrefBrokerOffsetManager(pom.broker) + } + pom.parent.abandonPartitionOffsetManager(pom) + close(pom.errors) + return + } + } +} + +func (pom *partitionOffsetManager) selectBroker() error { + if pom.broker != nil { + pom.parent.unrefBrokerOffsetManager(pom.broker) + pom.broker = nil + } + + var broker *Broker + var err error + + if err = pom.parent.client.RefreshCoordinator(pom.parent.group); err != nil { + return err + } + + if broker, err = pom.parent.client.Coordinator(pom.parent.group); err != nil { + return err + } + + pom.broker = pom.parent.refBrokerOffsetManager(broker) + return nil +} + +func (pom *partitionOffsetManager) fetchInitialOffset(retries int) error { + request := new(OffsetFetchRequest) + request.Version = 1 + request.ConsumerGroup = pom.parent.group + request.AddPartition(pom.topic, pom.partition) + + response, err := pom.broker.broker.FetchOffset(request) + if err != nil { + return err + } + + block := response.GetBlock(pom.topic, pom.partition) + if block == nil { + return ErrIncompleteResponse + } + + switch block.Err { + case ErrNoError: + pom.offset = block.Offset + pom.metadata = block.Metadata + return nil + case ErrNotCoordinatorForConsumer: + if retries <= 0 { + return block.Err + } + if err := pom.selectBroker(); err != nil { + return err + } + return pom.fetchInitialOffset(retries - 1) + case ErrOffsetsLoadInProgress: + if retries <= 0 { + return block.Err + } + time.Sleep(pom.parent.conf.Metadata.Retry.Backoff) + return pom.fetchInitialOffset(retries - 1) + default: + return block.Err + } +} + +func (pom *partitionOffsetManager) handleError(err error) { + cErr := &ConsumerError{ + Topic: pom.topic, + Partition: pom.partition, + Err: err, + } + + if pom.parent.conf.Consumer.Return.Errors { + pom.errors <- cErr + } else { + Logger.Println(cErr) + } +} + +func (pom *partitionOffsetManager) Errors() <-chan *ConsumerError { + return pom.errors +} + +func (pom *partitionOffsetManager) MarkOffset(offset int64, metadata string) { + pom.lock.Lock() + defer pom.lock.Unlock() + + if offset > pom.offset { + pom.offset = offset + pom.metadata = metadata + pom.dirty = true + } +} + +func (pom *partitionOffsetManager) updateCommitted(offset int64, metadata string) { + pom.lock.Lock() + defer pom.lock.Unlock() + + if pom.offset == offset && pom.metadata == metadata { + pom.dirty = false + pom.clean.Signal() + } +} + +func (pom *partitionOffsetManager) NextOffset() (int64, string) { + pom.lock.Lock() + defer pom.lock.Unlock() + + if pom.offset >= 0 { + return pom.offset, pom.metadata + } + + return pom.parent.conf.Consumer.Offsets.Initial, "" +} + +func (pom *partitionOffsetManager) AsyncClose() { + go func() { + pom.lock.Lock() + defer pom.lock.Unlock() + + for pom.dirty { + pom.clean.Wait() + } + + close(pom.dying) + }() +} + +func (pom *partitionOffsetManager) Close() error { + pom.AsyncClose() + + var errors ConsumerErrors + for err := range pom.errors { + errors = append(errors, err) + } + + if len(errors) > 0 { + return errors + } + return nil +} + +// Broker Offset Manager + +type brokerOffsetManager struct { + parent *offsetManager + broker *Broker + timer *time.Ticker + updateSubscriptions chan *partitionOffsetManager + subscriptions map[*partitionOffsetManager]none + refs int +} + +func (om *offsetManager) newBrokerOffsetManager(broker *Broker) *brokerOffsetManager { + bom := &brokerOffsetManager{ + parent: om, + broker: broker, + timer: time.NewTicker(om.conf.Consumer.Offsets.CommitInterval), + updateSubscriptions: make(chan *partitionOffsetManager), + subscriptions: make(map[*partitionOffsetManager]none), + } + + go withRecover(bom.mainLoop) + + return bom +} + +func (bom *brokerOffsetManager) mainLoop() { + for { + select { + case <-bom.timer.C: + if len(bom.subscriptions) > 0 { + bom.flushToBroker() + } + case s, ok := <-bom.updateSubscriptions: + if !ok { + bom.timer.Stop() + return + } + if _, ok := bom.subscriptions[s]; ok { + delete(bom.subscriptions, s) + } else { + bom.subscriptions[s] = none{} + } + } + } +} + +func (bom *brokerOffsetManager) flushToBroker() { + request := bom.constructRequest() + if request == nil { + return + } + + response, err := bom.broker.CommitOffset(request) + + if err != nil { + bom.abort(err) + return + } + + for s := range bom.subscriptions { + if request.blocks[s.topic] == nil || request.blocks[s.topic][s.partition] == nil { + continue + } + + var err KError + var ok bool + + if response.Errors[s.topic] == nil { + s.handleError(ErrIncompleteResponse) + delete(bom.subscriptions, s) + s.rebalance <- none{} + continue + } + if err, ok = response.Errors[s.topic][s.partition]; !ok { + s.handleError(ErrIncompleteResponse) + delete(bom.subscriptions, s) + s.rebalance <- none{} + continue + } + + switch err { + case ErrNoError: + block := request.blocks[s.topic][s.partition] + s.updateCommitted(block.offset, block.metadata) + case ErrNotLeaderForPartition, ErrLeaderNotAvailable, + ErrConsumerCoordinatorNotAvailable, ErrNotCoordinatorForConsumer: + // not a critical error, we just need to redispatch + delete(bom.subscriptions, s) + s.rebalance <- none{} + case ErrOffsetMetadataTooLarge, ErrInvalidCommitOffsetSize: + // nothing we can do about this, just tell the user and carry on + s.handleError(err) + case ErrOffsetsLoadInProgress: + // nothing wrong but we didn't commit, we'll get it next time round + break + case ErrUnknownTopicOrPartition: + // let the user know *and* try redispatching - if topic-auto-create is + // enabled, redispatching should trigger a metadata request and create the + // topic; if not then re-dispatching won't help, but we've let the user + // know and it shouldn't hurt either (see https://github.com/Shopify/sarama/issues/706) + fallthrough + default: + // dunno, tell the user and try redispatching + s.handleError(err) + delete(bom.subscriptions, s) + s.rebalance <- none{} + } + } +} + +func (bom *brokerOffsetManager) constructRequest() *OffsetCommitRequest { + var r *OffsetCommitRequest + var perPartitionTimestamp int64 + if bom.parent.conf.Consumer.Offsets.Retention == 0 { + perPartitionTimestamp = ReceiveTime + r = &OffsetCommitRequest{ + Version: 1, + ConsumerGroup: bom.parent.group, + ConsumerGroupGeneration: GroupGenerationUndefined, + } + } else { + r = &OffsetCommitRequest{ + Version: 2, + RetentionTime: int64(bom.parent.conf.Consumer.Offsets.Retention / time.Millisecond), + ConsumerGroup: bom.parent.group, + ConsumerGroupGeneration: GroupGenerationUndefined, + } + + } + + for s := range bom.subscriptions { + s.lock.Lock() + if s.dirty { + r.AddBlock(s.topic, s.partition, s.offset, perPartitionTimestamp, s.metadata) + } + s.lock.Unlock() + } + + if len(r.blocks) > 0 { + return r + } + + return nil +} + +func (bom *brokerOffsetManager) abort(err error) { + _ = bom.broker.Close() // we don't care about the error this might return, we already have one + bom.parent.abandonBroker(bom) + + for pom := range bom.subscriptions { + pom.handleError(err) + pom.rebalance <- none{} + } + + for s := range bom.updateSubscriptions { + if _, ok := bom.subscriptions[s]; !ok { + s.handleError(err) + s.rebalance <- none{} + } + } + + bom.subscriptions = make(map[*partitionOffsetManager]none) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_manager_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_manager_test.go new file mode 100644 index 00000000..c111a5a6 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_manager_test.go @@ -0,0 +1,369 @@ +package sarama + +import ( + "testing" + "time" +) + +func initOffsetManager(t *testing.T) (om OffsetManager, + testClient Client, broker, coordinator *MockBroker) { + + config := NewConfig() + config.Metadata.Retry.Max = 1 + config.Consumer.Offsets.CommitInterval = 1 * time.Millisecond + config.Version = V0_9_0_0 + + broker = NewMockBroker(t, 1) + coordinator = NewMockBroker(t, 2) + + seedMeta := new(MetadataResponse) + seedMeta.AddBroker(coordinator.Addr(), coordinator.BrokerID()) + seedMeta.AddTopicPartition("my_topic", 0, 1, []int32{}, []int32{}, ErrNoError) + seedMeta.AddTopicPartition("my_topic", 1, 1, []int32{}, []int32{}, ErrNoError) + broker.Returns(seedMeta) + + var err error + testClient, err = NewClient([]string{broker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: coordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: coordinator.Port(), + }) + + om, err = NewOffsetManagerFromClient("group", testClient) + if err != nil { + t.Fatal(err) + } + + return om, testClient, broker, coordinator +} + +func initPartitionOffsetManager(t *testing.T, om OffsetManager, + coordinator *MockBroker, initialOffset int64, metadata string) PartitionOffsetManager { + + fetchResponse := new(OffsetFetchResponse) + fetchResponse.AddBlock("my_topic", 0, &OffsetFetchResponseBlock{ + Err: ErrNoError, + Offset: initialOffset, + Metadata: metadata, + }) + coordinator.Returns(fetchResponse) + + pom, err := om.ManagePartition("my_topic", 0) + if err != nil { + t.Fatal(err) + } + + return pom +} + +func TestNewOffsetManager(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + seedBroker.Returns(new(MetadataResponse)) + + testClient, err := NewClient([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + _, err = NewOffsetManagerFromClient("group", testClient) + if err != nil { + t.Error(err) + } + + safeClose(t, testClient) + + _, err = NewOffsetManagerFromClient("group", testClient) + if err != ErrClosedClient { + t.Errorf("Error expected for closed client; actual value: %v", err) + } + + seedBroker.Close() +} + +// Test recovery from ErrNotCoordinatorForConsumer +// on first fetchInitialOffset call +func TestOffsetManagerFetchInitialFail(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + + // Error on first fetchInitialOffset call + responseBlock := OffsetFetchResponseBlock{ + Err: ErrNotCoordinatorForConsumer, + Offset: 5, + Metadata: "test_meta", + } + + fetchResponse := new(OffsetFetchResponse) + fetchResponse.AddBlock("my_topic", 0, &responseBlock) + coordinator.Returns(fetchResponse) + + // Refresh coordinator + newCoordinator := NewMockBroker(t, 3) + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + // Second fetchInitialOffset call is fine + fetchResponse2 := new(OffsetFetchResponse) + responseBlock2 := responseBlock + responseBlock2.Err = ErrNoError + fetchResponse2.AddBlock("my_topic", 0, &responseBlock2) + newCoordinator.Returns(fetchResponse2) + + pom, err := om.ManagePartition("my_topic", 0) + if err != nil { + t.Error(err) + } + + broker.Close() + coordinator.Close() + newCoordinator.Close() + safeClose(t, pom) + safeClose(t, om) + safeClose(t, testClient) +} + +// Test fetchInitialOffset retry on ErrOffsetsLoadInProgress +func TestOffsetManagerFetchInitialLoadInProgress(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + + // Error on first fetchInitialOffset call + responseBlock := OffsetFetchResponseBlock{ + Err: ErrOffsetsLoadInProgress, + Offset: 5, + Metadata: "test_meta", + } + + fetchResponse := new(OffsetFetchResponse) + fetchResponse.AddBlock("my_topic", 0, &responseBlock) + coordinator.Returns(fetchResponse) + + // Second fetchInitialOffset call is fine + fetchResponse2 := new(OffsetFetchResponse) + responseBlock2 := responseBlock + responseBlock2.Err = ErrNoError + fetchResponse2.AddBlock("my_topic", 0, &responseBlock2) + coordinator.Returns(fetchResponse2) + + pom, err := om.ManagePartition("my_topic", 0) + if err != nil { + t.Error(err) + } + + broker.Close() + coordinator.Close() + safeClose(t, pom) + safeClose(t, om) + safeClose(t, testClient) +} + +func TestPartitionOffsetManagerInitialOffset(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + testClient.Config().Consumer.Offsets.Initial = OffsetOldest + + // Kafka returns -1 if no offset has been stored for this partition yet. + pom := initPartitionOffsetManager(t, om, coordinator, -1, "") + + offset, meta := pom.NextOffset() + if offset != OffsetOldest { + t.Errorf("Expected offset 5. Actual: %v", offset) + } + if meta != "" { + t.Errorf("Expected metadata to be empty. Actual: %q", meta) + } + + safeClose(t, pom) + safeClose(t, om) + broker.Close() + coordinator.Close() + safeClose(t, testClient) +} + +func TestPartitionOffsetManagerNextOffset(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + pom := initPartitionOffsetManager(t, om, coordinator, 5, "test_meta") + + offset, meta := pom.NextOffset() + if offset != 5 { + t.Errorf("Expected offset 5. Actual: %v", offset) + } + if meta != "test_meta" { + t.Errorf("Expected metadata \"test_meta\". Actual: %q", meta) + } + + safeClose(t, pom) + safeClose(t, om) + broker.Close() + coordinator.Close() + safeClose(t, testClient) +} + +func TestPartitionOffsetManagerMarkOffset(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + pom := initPartitionOffsetManager(t, om, coordinator, 5, "original_meta") + + ocResponse := new(OffsetCommitResponse) + ocResponse.AddError("my_topic", 0, ErrNoError) + coordinator.Returns(ocResponse) + + pom.MarkOffset(100, "modified_meta") + offset, meta := pom.NextOffset() + + if offset != 100 { + t.Errorf("Expected offset 100. Actual: %v", offset) + } + if meta != "modified_meta" { + t.Errorf("Expected metadata \"modified_meta\". Actual: %q", meta) + } + + safeClose(t, pom) + safeClose(t, om) + safeClose(t, testClient) + broker.Close() + coordinator.Close() +} + +func TestPartitionOffsetManagerMarkOffsetWithRetention(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + testClient.Config().Consumer.Offsets.Retention = time.Hour + + pom := initPartitionOffsetManager(t, om, coordinator, 5, "original_meta") + + ocResponse := new(OffsetCommitResponse) + ocResponse.AddError("my_topic", 0, ErrNoError) + handler := func(req *request) (res encoder) { + if req.body.version() != 2 { + t.Errorf("Expected to be using version 2. Actual: %v", req.body.version()) + } + offsetCommitRequest := req.body.(*OffsetCommitRequest) + if offsetCommitRequest.RetentionTime != (60 * 60 * 1000) { + t.Errorf("Expected an hour retention time. Actual: %v", offsetCommitRequest.RetentionTime) + } + return ocResponse + } + coordinator.setHandler(handler) + + pom.MarkOffset(100, "modified_meta") + offset, meta := pom.NextOffset() + + if offset != 100 { + t.Errorf("Expected offset 100. Actual: %v", offset) + } + if meta != "modified_meta" { + t.Errorf("Expected metadata \"modified_meta\". Actual: %q", meta) + } + + safeClose(t, pom) + safeClose(t, om) + safeClose(t, testClient) + broker.Close() + coordinator.Close() +} + +func TestPartitionOffsetManagerCommitErr(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + pom := initPartitionOffsetManager(t, om, coordinator, 5, "meta") + + // Error on one partition + ocResponse := new(OffsetCommitResponse) + ocResponse.AddError("my_topic", 0, ErrOffsetOutOfRange) + ocResponse.AddError("my_topic", 1, ErrNoError) + coordinator.Returns(ocResponse) + + newCoordinator := NewMockBroker(t, 3) + + // For RefreshCoordinator() + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + // Nothing in response.Errors at all + ocResponse2 := new(OffsetCommitResponse) + newCoordinator.Returns(ocResponse2) + + // For RefreshCoordinator() + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + // Error on the wrong partition for this pom + ocResponse3 := new(OffsetCommitResponse) + ocResponse3.AddError("my_topic", 1, ErrNoError) + newCoordinator.Returns(ocResponse3) + + // For RefreshCoordinator() + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + // ErrUnknownTopicOrPartition/ErrNotLeaderForPartition/ErrLeaderNotAvailable block + ocResponse4 := new(OffsetCommitResponse) + ocResponse4.AddError("my_topic", 0, ErrUnknownTopicOrPartition) + newCoordinator.Returns(ocResponse4) + + // For RefreshCoordinator() + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + // Normal error response + ocResponse5 := new(OffsetCommitResponse) + ocResponse5.AddError("my_topic", 0, ErrNoError) + newCoordinator.Returns(ocResponse5) + + pom.MarkOffset(100, "modified_meta") + + err := pom.Close() + if err != nil { + t.Error(err) + } + + broker.Close() + coordinator.Close() + newCoordinator.Close() + safeClose(t, om) + safeClose(t, testClient) +} + +// Test of recovery from abort +func TestAbortPartitionOffsetManager(t *testing.T) { + om, testClient, broker, coordinator := initOffsetManager(t) + pom := initPartitionOffsetManager(t, om, coordinator, 5, "meta") + + // this triggers an error in the CommitOffset request, + // which leads to the abort call + coordinator.Close() + + // Response to refresh coordinator request + newCoordinator := NewMockBroker(t, 3) + broker.Returns(&ConsumerMetadataResponse{ + CoordinatorID: newCoordinator.BrokerID(), + CoordinatorHost: "127.0.0.1", + CoordinatorPort: newCoordinator.Port(), + }) + + ocResponse := new(OffsetCommitResponse) + ocResponse.AddError("my_topic", 0, ErrNoError) + newCoordinator.Returns(ocResponse) + + pom.MarkOffset(100, "modified_meta") + + safeClose(t, pom) + safeClose(t, om) + broker.Close() + safeClose(t, testClient) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_request.go new file mode 100644 index 00000000..6c269601 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_request.go @@ -0,0 +1,132 @@ +package sarama + +type offsetRequestBlock struct { + time int64 + maxOffsets int32 // Only used in version 0 +} + +func (b *offsetRequestBlock) encode(pe packetEncoder, version int16) error { + pe.putInt64(int64(b.time)) + if version == 0 { + pe.putInt32(b.maxOffsets) + } + + return nil +} + +func (b *offsetRequestBlock) decode(pd packetDecoder, version int16) (err error) { + if b.time, err = pd.getInt64(); err != nil { + return err + } + if version == 0 { + if b.maxOffsets, err = pd.getInt32(); err != nil { + return err + } + } + return nil +} + +type OffsetRequest struct { + Version int16 + blocks map[string]map[int32]*offsetRequestBlock +} + +func (r *OffsetRequest) encode(pe packetEncoder) error { + pe.putInt32(-1) // replica ID is always -1 for clients + err := pe.putArrayLength(len(r.blocks)) + if err != nil { + return err + } + for topic, partitions := range r.blocks { + err = pe.putString(topic) + if err != nil { + return err + } + err = pe.putArrayLength(len(partitions)) + if err != nil { + return err + } + for partition, block := range partitions { + pe.putInt32(partition) + if err = block.encode(pe, r.Version); err != nil { + return err + } + } + } + return nil +} + +func (r *OffsetRequest) decode(pd packetDecoder, version int16) error { + r.Version = version + + // Ignore replica ID + if _, err := pd.getInt32(); err != nil { + return err + } + blockCount, err := pd.getArrayLength() + if err != nil { + return err + } + if blockCount == 0 { + return nil + } + r.blocks = make(map[string]map[int32]*offsetRequestBlock) + for i := 0; i < blockCount; i++ { + topic, err := pd.getString() + if err != nil { + return err + } + partitionCount, err := pd.getArrayLength() + if err != nil { + return err + } + r.blocks[topic] = make(map[int32]*offsetRequestBlock) + for j := 0; j < partitionCount; j++ { + partition, err := pd.getInt32() + if err != nil { + return err + } + block := &offsetRequestBlock{} + if err := block.decode(pd, version); err != nil { + return err + } + r.blocks[topic][partition] = block + } + } + return nil +} + +func (r *OffsetRequest) key() int16 { + return 2 +} + +func (r *OffsetRequest) version() int16 { + return r.Version +} + +func (r *OffsetRequest) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_10_1_0 + default: + return minVersion + } +} + +func (r *OffsetRequest) AddBlock(topic string, partitionID int32, time int64, maxOffsets int32) { + if r.blocks == nil { + r.blocks = make(map[string]map[int32]*offsetRequestBlock) + } + + if r.blocks[topic] == nil { + r.blocks[topic] = make(map[int32]*offsetRequestBlock) + } + + tmp := new(offsetRequestBlock) + tmp.time = time + if r.Version == 0 { + tmp.maxOffsets = maxOffsets + } + + r.blocks[topic][partitionID] = tmp +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_request_test.go new file mode 100644 index 00000000..9ce562c9 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_request_test.go @@ -0,0 +1,43 @@ +package sarama + +import "testing" + +var ( + offsetRequestNoBlocks = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00} + + offsetRequestOneBlock = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x03, 'f', 'o', 'o', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02} + + offsetRequestOneBlockV1 = []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x03, 'b', 'a', 'r', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} +) + +func TestOffsetRequest(t *testing.T) { + request := new(OffsetRequest) + testRequest(t, "no blocks", request, offsetRequestNoBlocks) + + request.AddBlock("foo", 4, 1, 2) + testRequest(t, "one block", request, offsetRequestOneBlock) +} + +func TestOffsetRequestV1(t *testing.T) { + request := new(OffsetRequest) + request.Version = 1 + testRequest(t, "no blocks", request, offsetRequestNoBlocks) + + request.AddBlock("bar", 4, 1, 2) // Last argument is ignored for V1 + testRequest(t, "one block", request, offsetRequestOneBlockV1) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_response.go new file mode 100644 index 00000000..9a9cfe96 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_response.go @@ -0,0 +1,174 @@ +package sarama + +type OffsetResponseBlock struct { + Err KError + Offsets []int64 // Version 0 + Offset int64 // Version 1 + Timestamp int64 // Version 1 +} + +func (b *OffsetResponseBlock) decode(pd packetDecoder, version int16) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + b.Err = KError(tmp) + + if version == 0 { + b.Offsets, err = pd.getInt64Array() + + return err + } + + b.Timestamp, err = pd.getInt64() + if err != nil { + return err + } + + b.Offset, err = pd.getInt64() + if err != nil { + return err + } + + // For backwards compatibility put the offset in the offsets array too + b.Offsets = []int64{b.Offset} + + return nil +} + +func (b *OffsetResponseBlock) encode(pe packetEncoder, version int16) (err error) { + pe.putInt16(int16(b.Err)) + + if version == 0 { + return pe.putInt64Array(b.Offsets) + } + + pe.putInt64(b.Timestamp) + pe.putInt64(b.Offset) + + return nil +} + +type OffsetResponse struct { + Version int16 + Blocks map[string]map[int32]*OffsetResponseBlock +} + +func (r *OffsetResponse) decode(pd packetDecoder, version int16) (err error) { + numTopics, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks = make(map[string]map[int32]*OffsetResponseBlock, numTopics) + for i := 0; i < numTopics; i++ { + name, err := pd.getString() + if err != nil { + return err + } + + numBlocks, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks[name] = make(map[int32]*OffsetResponseBlock, numBlocks) + + for j := 0; j < numBlocks; j++ { + id, err := pd.getInt32() + if err != nil { + return err + } + + block := new(OffsetResponseBlock) + err = block.decode(pd, version) + if err != nil { + return err + } + r.Blocks[name][id] = block + } + } + + return nil +} + +func (r *OffsetResponse) GetBlock(topic string, partition int32) *OffsetResponseBlock { + if r.Blocks == nil { + return nil + } + + if r.Blocks[topic] == nil { + return nil + } + + return r.Blocks[topic][partition] +} + +/* +// [0 0 0 1 ntopics +0 8 109 121 95 116 111 112 105 99 topic +0 0 0 1 npartitions +0 0 0 0 id +0 0 + +0 0 0 1 0 0 0 0 +0 1 1 1 0 0 0 1 +0 8 109 121 95 116 111 112 +105 99 0 0 0 1 0 0 +0 0 0 0 0 0 0 1 +0 0 0 0 0 1 1 1] + +*/ +func (r *OffsetResponse) encode(pe packetEncoder) (err error) { + if err = pe.putArrayLength(len(r.Blocks)); err != nil { + return err + } + + for topic, partitions := range r.Blocks { + if err = pe.putString(topic); err != nil { + return err + } + if err = pe.putArrayLength(len(partitions)); err != nil { + return err + } + for partition, block := range partitions { + pe.putInt32(partition) + if err = block.encode(pe, r.version()); err != nil { + return err + } + } + } + + return nil +} + +func (r *OffsetResponse) key() int16 { + return 2 +} + +func (r *OffsetResponse) version() int16 { + return r.Version +} + +func (r *OffsetResponse) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_10_1_0 + default: + return minVersion + } +} + +// testing API + +func (r *OffsetResponse) AddTopicPartition(topic string, partition int32, offset int64) { + if r.Blocks == nil { + r.Blocks = make(map[string]map[int32]*OffsetResponseBlock) + } + byTopic, ok := r.Blocks[topic] + if !ok { + byTopic = make(map[int32]*OffsetResponseBlock) + r.Blocks[topic] = byTopic + } + byTopic[partition] = &OffsetResponseBlock{Offsets: []int64{offset}, Offset: offset} +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/offset_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_response_test.go new file mode 100644 index 00000000..0df6c9f3 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/offset_response_test.go @@ -0,0 +1,111 @@ +package sarama + +import "testing" + +var ( + emptyOffsetResponse = []byte{ + 0x00, 0x00, 0x00, 0x00} + + normalOffsetResponse = []byte{ + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x01, 'a', + 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x01, 'z', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06} + + normalOffsetResponseV1 = []byte{ + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x01, 'a', + 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x01, 'z', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, + 0x00, 0x00, 0x01, 0x58, 0x1A, 0xE6, 0x48, 0x86, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06} +) + +func TestEmptyOffsetResponse(t *testing.T) { + response := OffsetResponse{} + + testVersionDecodable(t, "empty", &response, emptyOffsetResponse, 0) + if len(response.Blocks) != 0 { + t.Error("Decoding produced", len(response.Blocks), "topics where there were none.") + } + + response = OffsetResponse{} + + testVersionDecodable(t, "empty", &response, emptyOffsetResponse, 1) + if len(response.Blocks) != 0 { + t.Error("Decoding produced", len(response.Blocks), "topics where there were none.") + } +} + +func TestNormalOffsetResponse(t *testing.T) { + response := OffsetResponse{} + + testVersionDecodable(t, "normal", &response, normalOffsetResponse, 0) + + if len(response.Blocks) != 2 { + t.Fatal("Decoding produced", len(response.Blocks), "topics where there were two.") + } + + if len(response.Blocks["a"]) != 0 { + t.Fatal("Decoding produced", len(response.Blocks["a"]), "partitions for topic 'a' where there were none.") + } + + if len(response.Blocks["z"]) != 1 { + t.Fatal("Decoding produced", len(response.Blocks["z"]), "partitions for topic 'z' where there was one.") + } + + if response.Blocks["z"][2].Err != ErrNoError { + t.Fatal("Decoding produced invalid error for topic z partition 2.") + } + + if len(response.Blocks["z"][2].Offsets) != 2 { + t.Fatal("Decoding produced invalid number of offsets for topic z partition 2.") + } + + if response.Blocks["z"][2].Offsets[0] != 5 || response.Blocks["z"][2].Offsets[1] != 6 { + t.Fatal("Decoding produced invalid offsets for topic z partition 2.") + } +} + +func TestNormalOffsetResponseV1(t *testing.T) { + response := OffsetResponse{} + + testVersionDecodable(t, "normal", &response, normalOffsetResponseV1, 1) + + if len(response.Blocks) != 2 { + t.Fatal("Decoding produced", len(response.Blocks), "topics where there were two.") + } + + if len(response.Blocks["a"]) != 0 { + t.Fatal("Decoding produced", len(response.Blocks["a"]), "partitions for topic 'a' where there were none.") + } + + if len(response.Blocks["z"]) != 1 { + t.Fatal("Decoding produced", len(response.Blocks["z"]), "partitions for topic 'z' where there was one.") + } + + if response.Blocks["z"][2].Err != ErrNoError { + t.Fatal("Decoding produced invalid error for topic z partition 2.") + } + + if response.Blocks["z"][2].Timestamp != 1477920049286 { + t.Fatal("Decoding produced invalid timestamp for topic z partition 2.", response.Blocks["z"][2].Timestamp) + } + + if response.Blocks["z"][2].Offset != 6 { + t.Fatal("Decoding produced invalid offsets for topic z partition 2.") + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/packet_decoder.go b/vendor/src/gopkg.in/Shopify/sarama.v1/packet_decoder.go new file mode 100644 index 00000000..28670c0e --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/packet_decoder.go @@ -0,0 +1,45 @@ +package sarama + +// PacketDecoder is the interface providing helpers for reading with Kafka's encoding rules. +// Types implementing Decoder only need to worry about calling methods like GetString, +// not about how a string is represented in Kafka. +type packetDecoder interface { + // Primitives + getInt8() (int8, error) + getInt16() (int16, error) + getInt32() (int32, error) + getInt64() (int64, error) + getArrayLength() (int, error) + + // Collections + getBytes() ([]byte, error) + getString() (string, error) + getInt32Array() ([]int32, error) + getInt64Array() ([]int64, error) + getStringArray() ([]string, error) + + // Subsets + remaining() int + getSubset(length int) (packetDecoder, error) + + // Stacks, see PushDecoder + push(in pushDecoder) error + pop() error +} + +// PushDecoder is the interface for decoding fields like CRCs and lengths where the validity +// of the field depends on what is after it in the packet. Start them with PacketDecoder.Push() where +// the actual value is located in the packet, then PacketDecoder.Pop() them when all the bytes they +// depend upon have been decoded. +type pushDecoder interface { + // Saves the offset into the input buffer as the location to actually read the calculated value when able. + saveOffset(in int) + + // Returns the length of data to reserve for the input of this encoder (eg 4 bytes for a CRC32). + reserveLength() int + + // Indicates that all required data is now available to calculate and check the field. + // SaveOffset is guaranteed to have been called first. The implementation should read ReserveLength() bytes + // of data from the saved offset, and verify it based on the data between the saved offset and curOffset. + check(curOffset int, buf []byte) error +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/packet_encoder.go b/vendor/src/gopkg.in/Shopify/sarama.v1/packet_encoder.go new file mode 100644 index 00000000..27a10f6d --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/packet_encoder.go @@ -0,0 +1,50 @@ +package sarama + +import "github.com/rcrowley/go-metrics" + +// PacketEncoder is the interface providing helpers for writing with Kafka's encoding rules. +// Types implementing Encoder only need to worry about calling methods like PutString, +// not about how a string is represented in Kafka. +type packetEncoder interface { + // Primitives + putInt8(in int8) + putInt16(in int16) + putInt32(in int32) + putInt64(in int64) + putArrayLength(in int) error + + // Collections + putBytes(in []byte) error + putRawBytes(in []byte) error + putString(in string) error + putStringArray(in []string) error + putInt32Array(in []int32) error + putInt64Array(in []int64) error + + // Provide the current offset to record the batch size metric + offset() int + + // Stacks, see PushEncoder + push(in pushEncoder) + pop() error + + // To record metrics when provided + metricRegistry() metrics.Registry +} + +// PushEncoder is the interface for encoding fields like CRCs and lengths where the value +// of the field depends on what is encoded after it in the packet. Start them with PacketEncoder.Push() where +// the actual value is located in the packet, then PacketEncoder.Pop() them when all the bytes they +// depend upon have been written. +type pushEncoder interface { + // Saves the offset into the input buffer as the location to actually write the calculated value when able. + saveOffset(in int) + + // Returns the length of data to reserve for the output of this encoder (eg 4 bytes for a CRC32). + reserveLength() int + + // Indicates that all required data is now available to calculate and write the field. + // SaveOffset is guaranteed to have been called first. The implementation should write ReserveLength() bytes + // of data to the saved offset, based on the data between the saved offset and curOffset. + run(curOffset int, buf []byte) error +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/partitioner.go b/vendor/src/gopkg.in/Shopify/sarama.v1/partitioner.go new file mode 100644 index 00000000..d24199da --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/partitioner.go @@ -0,0 +1,123 @@ +package sarama + +import ( + "hash" + "hash/fnv" + "math/rand" + "time" +) + +// Partitioner is anything that, given a Kafka message and a number of partitions indexed [0...numPartitions-1], +// decides to which partition to send the message. RandomPartitioner, RoundRobinPartitioner and HashPartitioner are provided +// as simple default implementations. +type Partitioner interface { + // Partition takes a message and partition count and chooses a partition + Partition(message *ProducerMessage, numPartitions int32) (int32, error) + + // RequiresConsistency indicates to the user of the partitioner whether the + // mapping of key->partition is consistent or not. Specifically, if a + // partitioner requires consistency then it must be allowed to choose from all + // partitions (even ones known to be unavailable), and its choice must be + // respected by the caller. The obvious example is the HashPartitioner. + RequiresConsistency() bool +} + +// PartitionerConstructor is the type for a function capable of constructing new Partitioners. +type PartitionerConstructor func(topic string) Partitioner + +type manualPartitioner struct{} + +// NewManualPartitioner returns a Partitioner which uses the partition manually set in the provided +// ProducerMessage's Partition field as the partition to produce to. +func NewManualPartitioner(topic string) Partitioner { + return new(manualPartitioner) +} + +func (p *manualPartitioner) Partition(message *ProducerMessage, numPartitions int32) (int32, error) { + return message.Partition, nil +} + +func (p *manualPartitioner) RequiresConsistency() bool { + return true +} + +type randomPartitioner struct { + generator *rand.Rand +} + +// NewRandomPartitioner returns a Partitioner which chooses a random partition each time. +func NewRandomPartitioner(topic string) Partitioner { + p := new(randomPartitioner) + p.generator = rand.New(rand.NewSource(time.Now().UTC().UnixNano())) + return p +} + +func (p *randomPartitioner) Partition(message *ProducerMessage, numPartitions int32) (int32, error) { + return int32(p.generator.Intn(int(numPartitions))), nil +} + +func (p *randomPartitioner) RequiresConsistency() bool { + return false +} + +type roundRobinPartitioner struct { + partition int32 +} + +// NewRoundRobinPartitioner returns a Partitioner which walks through the available partitions one at a time. +func NewRoundRobinPartitioner(topic string) Partitioner { + return &roundRobinPartitioner{} +} + +func (p *roundRobinPartitioner) Partition(message *ProducerMessage, numPartitions int32) (int32, error) { + if p.partition >= numPartitions { + p.partition = 0 + } + ret := p.partition + p.partition++ + return ret, nil +} + +func (p *roundRobinPartitioner) RequiresConsistency() bool { + return false +} + +type hashPartitioner struct { + random Partitioner + hasher hash.Hash32 +} + +// NewHashPartitioner returns a Partitioner which behaves as follows. If the message's key is nil then a +// random partition is chosen. Otherwise the FNV-1a hash of the encoded bytes of the message key is used, +// modulus the number of partitions. This ensures that messages with the same key always end up on the +// same partition. +func NewHashPartitioner(topic string) Partitioner { + p := new(hashPartitioner) + p.random = NewRandomPartitioner(topic) + p.hasher = fnv.New32a() + return p +} + +func (p *hashPartitioner) Partition(message *ProducerMessage, numPartitions int32) (int32, error) { + if message.Key == nil { + return p.random.Partition(message, numPartitions) + } + bytes, err := message.Key.Encode() + if err != nil { + return -1, err + } + p.hasher.Reset() + _, err = p.hasher.Write(bytes) + if err != nil { + return -1, err + } + partition := int32(p.hasher.Sum32()) % numPartitions + if partition < 0 { + partition = -partition + } + return partition, nil +} + +func (p *hashPartitioner) RequiresConsistency() bool { + return true +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/partitioner_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/partitioner_test.go new file mode 100644 index 00000000..3d391c59 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/partitioner_test.go @@ -0,0 +1,215 @@ +package sarama + +import ( + "crypto/rand" + "log" + "testing" +) + +func assertPartitioningConsistent(t *testing.T, partitioner Partitioner, message *ProducerMessage, numPartitions int32) { + choice, err := partitioner.Partition(message, numPartitions) + if err != nil { + t.Error(partitioner, err) + } + if choice < 0 || choice >= numPartitions { + t.Error(partitioner, "returned partition", choice, "outside of range for", message) + } + for i := 1; i < 50; i++ { + newChoice, err := partitioner.Partition(message, numPartitions) + if err != nil { + t.Error(partitioner, err) + } + if newChoice != choice { + t.Error(partitioner, "returned partition", newChoice, "inconsistent with", choice, ".") + } + } +} + +func TestRandomPartitioner(t *testing.T) { + partitioner := NewRandomPartitioner("mytopic") + + choice, err := partitioner.Partition(nil, 1) + if err != nil { + t.Error(partitioner, err) + } + if choice != 0 { + t.Error("Returned non-zero partition when only one available.") + } + + for i := 1; i < 50; i++ { + choice, err := partitioner.Partition(nil, 50) + if err != nil { + t.Error(partitioner, err) + } + if choice < 0 || choice >= 50 { + t.Error("Returned partition", choice, "outside of range.") + } + } +} + +func TestRoundRobinPartitioner(t *testing.T) { + partitioner := NewRoundRobinPartitioner("mytopic") + + choice, err := partitioner.Partition(nil, 1) + if err != nil { + t.Error(partitioner, err) + } + if choice != 0 { + t.Error("Returned non-zero partition when only one available.") + } + + var i int32 + for i = 1; i < 50; i++ { + choice, err := partitioner.Partition(nil, 7) + if err != nil { + t.Error(partitioner, err) + } + if choice != i%7 { + t.Error("Returned partition", choice, "expecting", i%7) + } + } +} + +func TestHashPartitioner(t *testing.T) { + partitioner := NewHashPartitioner("mytopic") + + choice, err := partitioner.Partition(&ProducerMessage{}, 1) + if err != nil { + t.Error(partitioner, err) + } + if choice != 0 { + t.Error("Returned non-zero partition when only one available.") + } + + for i := 1; i < 50; i++ { + choice, err := partitioner.Partition(&ProducerMessage{}, 50) + if err != nil { + t.Error(partitioner, err) + } + if choice < 0 || choice >= 50 { + t.Error("Returned partition", choice, "outside of range for nil key.") + } + } + + buf := make([]byte, 256) + for i := 1; i < 50; i++ { + if _, err := rand.Read(buf); err != nil { + t.Error(err) + } + assertPartitioningConsistent(t, partitioner, &ProducerMessage{Key: ByteEncoder(buf)}, 50) + } +} + +func TestHashPartitionerMinInt32(t *testing.T) { + partitioner := NewHashPartitioner("mytopic") + + msg := ProducerMessage{} + // "1468509572224" generates 2147483648 (uint32) result from Sum32 function + // which is -2147483648 or int32's min value + msg.Key = StringEncoder("1468509572224") + + choice, err := partitioner.Partition(&msg, 50) + if err != nil { + t.Error(partitioner, err) + } + if choice < 0 || choice >= 50 { + t.Error("Returned partition", choice, "outside of range for nil key.") + } +} + +func TestManualPartitioner(t *testing.T) { + partitioner := NewManualPartitioner("mytopic") + + choice, err := partitioner.Partition(&ProducerMessage{}, 1) + if err != nil { + t.Error(partitioner, err) + } + if choice != 0 { + t.Error("Returned non-zero partition when only one available.") + } + + for i := int32(1); i < 50; i++ { + choice, err := partitioner.Partition(&ProducerMessage{Partition: i}, 50) + if err != nil { + t.Error(partitioner, err) + } + if choice != i { + t.Error("Returned partition not the same as the input partition") + } + } +} + +// By default, Sarama uses the message's key to consistently assign a partition to +// a message using hashing. If no key is set, a random partition will be chosen. +// This example shows how you can partition messages randomly, even when a key is set, +// by overriding Config.Producer.Partitioner. +func ExamplePartitioner_random() { + config := NewConfig() + config.Producer.Partitioner = NewRandomPartitioner + + producer, err := NewSyncProducer([]string{"localhost:9092"}, config) + if err != nil { + log.Fatal(err) + } + defer func() { + if err := producer.Close(); err != nil { + log.Println("Failed to close producer:", err) + } + }() + + msg := &ProducerMessage{Topic: "test", Key: StringEncoder("key is set"), Value: StringEncoder("test")} + partition, offset, err := producer.SendMessage(msg) + if err != nil { + log.Fatalln("Failed to produce message to kafka cluster.") + } + + log.Printf("Produced message to partition %d with offset %d", partition, offset) +} + +// This example shows how to assign partitions to your messages manually. +func ExamplePartitioner_manual() { + config := NewConfig() + + // First, we tell the producer that we are going to partition ourselves. + config.Producer.Partitioner = NewManualPartitioner + + producer, err := NewSyncProducer([]string{"localhost:9092"}, config) + if err != nil { + log.Fatal(err) + } + defer func() { + if err := producer.Close(); err != nil { + log.Println("Failed to close producer:", err) + } + }() + + // Now, we set the Partition field of the ProducerMessage struct. + msg := &ProducerMessage{Topic: "test", Partition: 6, Value: StringEncoder("test")} + + partition, offset, err := producer.SendMessage(msg) + if err != nil { + log.Fatalln("Failed to produce message to kafka cluster.") + } + + if partition != 6 { + log.Fatal("Message should have been produced to partition 6!") + } + + log.Printf("Produced message to partition %d with offset %d", partition, offset) +} + +// This example shows how to set a different partitioner depending on the topic. +func ExamplePartitioner_per_topic() { + config := NewConfig() + config.Producer.Partitioner = func(topic string) Partitioner { + switch topic { + case "access_log", "error_log": + return NewRandomPartitioner(topic) + + default: + return NewHashPartitioner(topic) + } + } + + // ... +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/prep_encoder.go b/vendor/src/gopkg.in/Shopify/sarama.v1/prep_encoder.go new file mode 100644 index 00000000..fd5ea0f9 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/prep_encoder.go @@ -0,0 +1,121 @@ +package sarama + +import ( + "fmt" + "math" + + "github.com/rcrowley/go-metrics" +) + +type prepEncoder struct { + length int +} + +// primitives + +func (pe *prepEncoder) putInt8(in int8) { + pe.length++ +} + +func (pe *prepEncoder) putInt16(in int16) { + pe.length += 2 +} + +func (pe *prepEncoder) putInt32(in int32) { + pe.length += 4 +} + +func (pe *prepEncoder) putInt64(in int64) { + pe.length += 8 +} + +func (pe *prepEncoder) putArrayLength(in int) error { + if in > math.MaxInt32 { + return PacketEncodingError{fmt.Sprintf("array too long (%d)", in)} + } + pe.length += 4 + return nil +} + +// arrays + +func (pe *prepEncoder) putBytes(in []byte) error { + pe.length += 4 + if in == nil { + return nil + } + if len(in) > math.MaxInt32 { + return PacketEncodingError{fmt.Sprintf("byteslice too long (%d)", len(in))} + } + pe.length += len(in) + return nil +} + +func (pe *prepEncoder) putRawBytes(in []byte) error { + if len(in) > math.MaxInt32 { + return PacketEncodingError{fmt.Sprintf("byteslice too long (%d)", len(in))} + } + pe.length += len(in) + return nil +} + +func (pe *prepEncoder) putString(in string) error { + pe.length += 2 + if len(in) > math.MaxInt16 { + return PacketEncodingError{fmt.Sprintf("string too long (%d)", len(in))} + } + pe.length += len(in) + return nil +} + +func (pe *prepEncoder) putStringArray(in []string) error { + err := pe.putArrayLength(len(in)) + if err != nil { + return err + } + + for _, str := range in { + if err := pe.putString(str); err != nil { + return err + } + } + + return nil +} + +func (pe *prepEncoder) putInt32Array(in []int32) error { + err := pe.putArrayLength(len(in)) + if err != nil { + return err + } + pe.length += 4 * len(in) + return nil +} + +func (pe *prepEncoder) putInt64Array(in []int64) error { + err := pe.putArrayLength(len(in)) + if err != nil { + return err + } + pe.length += 8 * len(in) + return nil +} + +func (pe *prepEncoder) offset() int { + return pe.length +} + +// stackable + +func (pe *prepEncoder) push(in pushEncoder) { + pe.length += in.reserveLength() +} + +func (pe *prepEncoder) pop() error { + return nil +} + +// we do not record metrics during the prep encoder pass +func (pe *prepEncoder) metricRegistry() metrics.Registry { + return nil +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/produce_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_request.go new file mode 100644 index 00000000..40dc8015 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_request.go @@ -0,0 +1,209 @@ +package sarama + +import "github.com/rcrowley/go-metrics" + +// RequiredAcks is used in Produce Requests to tell the broker how many replica acknowledgements +// it must see before responding. Any of the constants defined here are valid. On broker versions +// prior to 0.8.2.0 any other positive int16 is also valid (the broker will wait for that many +// acknowledgements) but in 0.8.2.0 and later this will raise an exception (it has been replaced +// by setting the `min.isr` value in the brokers configuration). +type RequiredAcks int16 + +const ( + // NoResponse doesn't send any response, the TCP ACK is all you get. + NoResponse RequiredAcks = 0 + // WaitForLocal waits for only the local commit to succeed before responding. + WaitForLocal RequiredAcks = 1 + // WaitForAll waits for all in-sync replicas to commit before responding. + // The minimum number of in-sync replicas is configured on the broker via + // the `min.insync.replicas` configuration key. + WaitForAll RequiredAcks = -1 +) + +type ProduceRequest struct { + RequiredAcks RequiredAcks + Timeout int32 + Version int16 // v1 requires Kafka 0.9, v2 requires Kafka 0.10 + msgSets map[string]map[int32]*MessageSet +} + +func (r *ProduceRequest) encode(pe packetEncoder) error { + pe.putInt16(int16(r.RequiredAcks)) + pe.putInt32(r.Timeout) + err := pe.putArrayLength(len(r.msgSets)) + if err != nil { + return err + } + metricRegistry := pe.metricRegistry() + var batchSizeMetric metrics.Histogram + var compressionRatioMetric metrics.Histogram + if metricRegistry != nil { + batchSizeMetric = getOrRegisterHistogram("batch-size", metricRegistry) + compressionRatioMetric = getOrRegisterHistogram("compression-ratio", metricRegistry) + } + + totalRecordCount := int64(0) + for topic, partitions := range r.msgSets { + err = pe.putString(topic) + if err != nil { + return err + } + err = pe.putArrayLength(len(partitions)) + if err != nil { + return err + } + topicRecordCount := int64(0) + var topicCompressionRatioMetric metrics.Histogram + if metricRegistry != nil { + topicCompressionRatioMetric = getOrRegisterTopicHistogram("compression-ratio", topic, metricRegistry) + } + for id, msgSet := range partitions { + startOffset := pe.offset() + pe.putInt32(id) + pe.push(&lengthField{}) + err = msgSet.encode(pe) + if err != nil { + return err + } + err = pe.pop() + if err != nil { + return err + } + if metricRegistry != nil { + for _, messageBlock := range msgSet.Messages { + // Is this a fake "message" wrapping real messages? + if messageBlock.Msg.Set != nil { + topicRecordCount += int64(len(messageBlock.Msg.Set.Messages)) + } else { + // A single uncompressed message + topicRecordCount++ + } + // Better be safe than sorry when computing the compression ratio + if messageBlock.Msg.compressedSize != 0 { + compressionRatio := float64(len(messageBlock.Msg.Value)) / + float64(messageBlock.Msg.compressedSize) + // Histogram do not support decimal values, let's multiple it by 100 for better precision + intCompressionRatio := int64(100 * compressionRatio) + compressionRatioMetric.Update(intCompressionRatio) + topicCompressionRatioMetric.Update(intCompressionRatio) + } + } + batchSize := int64(pe.offset() - startOffset) + batchSizeMetric.Update(batchSize) + getOrRegisterTopicHistogram("batch-size", topic, metricRegistry).Update(batchSize) + } + } + if topicRecordCount > 0 { + getOrRegisterTopicMeter("record-send-rate", topic, metricRegistry).Mark(topicRecordCount) + getOrRegisterTopicHistogram("records-per-request", topic, metricRegistry).Update(topicRecordCount) + totalRecordCount += topicRecordCount + } + } + if totalRecordCount > 0 { + metrics.GetOrRegisterMeter("record-send-rate", metricRegistry).Mark(totalRecordCount) + getOrRegisterHistogram("records-per-request", metricRegistry).Update(totalRecordCount) + } + + return nil +} + +func (r *ProduceRequest) decode(pd packetDecoder, version int16) error { + requiredAcks, err := pd.getInt16() + if err != nil { + return err + } + r.RequiredAcks = RequiredAcks(requiredAcks) + if r.Timeout, err = pd.getInt32(); err != nil { + return err + } + topicCount, err := pd.getArrayLength() + if err != nil { + return err + } + if topicCount == 0 { + return nil + } + r.msgSets = make(map[string]map[int32]*MessageSet) + for i := 0; i < topicCount; i++ { + topic, err := pd.getString() + if err != nil { + return err + } + partitionCount, err := pd.getArrayLength() + if err != nil { + return err + } + r.msgSets[topic] = make(map[int32]*MessageSet) + for j := 0; j < partitionCount; j++ { + partition, err := pd.getInt32() + if err != nil { + return err + } + messageSetSize, err := pd.getInt32() + if err != nil { + return err + } + msgSetDecoder, err := pd.getSubset(int(messageSetSize)) + if err != nil { + return err + } + msgSet := &MessageSet{} + err = msgSet.decode(msgSetDecoder) + if err != nil { + return err + } + r.msgSets[topic][partition] = msgSet + } + } + return nil +} + +func (r *ProduceRequest) key() int16 { + return 0 +} + +func (r *ProduceRequest) version() int16 { + return r.Version +} + +func (r *ProduceRequest) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_9_0_0 + case 2: + return V0_10_0_0 + default: + return minVersion + } +} + +func (r *ProduceRequest) AddMessage(topic string, partition int32, msg *Message) { + if r.msgSets == nil { + r.msgSets = make(map[string]map[int32]*MessageSet) + } + + if r.msgSets[topic] == nil { + r.msgSets[topic] = make(map[int32]*MessageSet) + } + + set := r.msgSets[topic][partition] + + if set == nil { + set = new(MessageSet) + r.msgSets[topic][partition] = set + } + + set.addMessage(msg) +} + +func (r *ProduceRequest) AddSet(topic string, partition int32, set *MessageSet) { + if r.msgSets == nil { + r.msgSets = make(map[string]map[int32]*MessageSet) + } + + if r.msgSets[topic] == nil { + r.msgSets[topic] = make(map[int32]*MessageSet) + } + + r.msgSets[topic][partition] = set +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/produce_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_request_test.go new file mode 100644 index 00000000..21f4ba5b --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_request_test.go @@ -0,0 +1,47 @@ +package sarama + +import ( + "testing" +) + +var ( + produceRequestEmpty = []byte{ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} + + produceRequestHeader = []byte{ + 0x01, 0x23, + 0x00, 0x00, 0x04, 0x44, + 0x00, 0x00, 0x00, 0x00} + + produceRequestOneMessage = []byte{ + 0x01, 0x23, + 0x00, 0x00, 0x04, 0x44, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x05, 't', 'o', 'p', 'i', 'c', + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0xAD, + 0x00, 0x00, 0x00, 0x1C, + // messageSet + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, + // message + 0x23, 0x96, 0x4a, 0xf7, // CRC + 0x00, + 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x02, 0x00, 0xEE} +) + +func TestProduceRequest(t *testing.T) { + request := new(ProduceRequest) + testRequest(t, "empty", request, produceRequestEmpty) + + request.RequiredAcks = 0x123 + request.Timeout = 0x444 + testRequest(t, "header", request, produceRequestHeader) + + request.AddMessage("topic", 0xAD, &Message{Codec: CompressionNone, Key: nil, Value: []byte{0x00, 0xEE}}) + testRequest(t, "one message", request, produceRequestOneMessage) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/produce_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_response.go new file mode 100644 index 00000000..195abcb8 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_response.go @@ -0,0 +1,158 @@ +package sarama + +import "time" + +type ProduceResponseBlock struct { + Err KError + Offset int64 + // only provided if Version >= 2 and the broker is configured with `LogAppendTime` + Timestamp time.Time +} + +func (b *ProduceResponseBlock) decode(pd packetDecoder, version int16) (err error) { + tmp, err := pd.getInt16() + if err != nil { + return err + } + b.Err = KError(tmp) + + b.Offset, err = pd.getInt64() + if err != nil { + return err + } + + if version >= 2 { + if millis, err := pd.getInt64(); err != nil { + return err + } else if millis != -1 { + b.Timestamp = time.Unix(millis/1000, (millis%1000)*int64(time.Millisecond)) + } + } + + return nil +} + +type ProduceResponse struct { + Blocks map[string]map[int32]*ProduceResponseBlock + Version int16 + ThrottleTime time.Duration // only provided if Version >= 1 +} + +func (r *ProduceResponse) decode(pd packetDecoder, version int16) (err error) { + r.Version = version + + numTopics, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks = make(map[string]map[int32]*ProduceResponseBlock, numTopics) + for i := 0; i < numTopics; i++ { + name, err := pd.getString() + if err != nil { + return err + } + + numBlocks, err := pd.getArrayLength() + if err != nil { + return err + } + + r.Blocks[name] = make(map[int32]*ProduceResponseBlock, numBlocks) + + for j := 0; j < numBlocks; j++ { + id, err := pd.getInt32() + if err != nil { + return err + } + + block := new(ProduceResponseBlock) + err = block.decode(pd, version) + if err != nil { + return err + } + r.Blocks[name][id] = block + } + } + + if r.Version >= 1 { + if millis, err := pd.getInt32(); err != nil { + return err + } else { + r.ThrottleTime = time.Duration(millis) * time.Millisecond + } + } + + return nil +} + +func (r *ProduceResponse) encode(pe packetEncoder) error { + err := pe.putArrayLength(len(r.Blocks)) + if err != nil { + return err + } + for topic, partitions := range r.Blocks { + err = pe.putString(topic) + if err != nil { + return err + } + err = pe.putArrayLength(len(partitions)) + if err != nil { + return err + } + for id, prb := range partitions { + pe.putInt32(id) + pe.putInt16(int16(prb.Err)) + pe.putInt64(prb.Offset) + } + } + if r.Version >= 1 { + pe.putInt32(int32(r.ThrottleTime / time.Millisecond)) + } + return nil +} + +func (r *ProduceResponse) key() int16 { + return 0 +} + +func (r *ProduceResponse) version() int16 { + return r.Version +} + +func (r *ProduceResponse) requiredVersion() KafkaVersion { + switch r.Version { + case 1: + return V0_9_0_0 + case 2: + return V0_10_0_0 + default: + return minVersion + } +} + +func (r *ProduceResponse) GetBlock(topic string, partition int32) *ProduceResponseBlock { + if r.Blocks == nil { + return nil + } + + if r.Blocks[topic] == nil { + return nil + } + + return r.Blocks[topic][partition] +} + +// Testing API + +func (r *ProduceResponse) AddTopicPartition(topic string, partition int32, err KError) { + if r.Blocks == nil { + r.Blocks = make(map[string]map[int32]*ProduceResponseBlock) + } + byTopic, ok := r.Blocks[topic] + if !ok { + byTopic = make(map[int32]*ProduceResponseBlock) + r.Blocks[topic] = byTopic + } + byTopic[partition] = &ProduceResponseBlock{Err: err} +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/produce_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_response_test.go new file mode 100644 index 00000000..f71709fe --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_response_test.go @@ -0,0 +1,67 @@ +package sarama + +import "testing" + +var ( + produceResponseNoBlocks = []byte{ + 0x00, 0x00, 0x00, 0x00} + + produceResponseManyBlocks = []byte{ + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x03, 'f', 'o', 'o', + 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x03, 'b', 'a', 'r', + 0x00, 0x00, 0x00, 0x02, + + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +) + +func TestProduceResponse(t *testing.T) { + response := ProduceResponse{} + + testVersionDecodable(t, "no blocks", &response, produceResponseNoBlocks, 0) + if len(response.Blocks) != 0 { + t.Error("Decoding produced", len(response.Blocks), "topics where there were none") + } + + testVersionDecodable(t, "many blocks", &response, produceResponseManyBlocks, 0) + if len(response.Blocks) != 2 { + t.Error("Decoding produced", len(response.Blocks), "topics where there were 2") + } + if len(response.Blocks["foo"]) != 0 { + t.Error("Decoding produced", len(response.Blocks["foo"]), "partitions for 'foo' where there were none") + } + if len(response.Blocks["bar"]) != 2 { + t.Error("Decoding produced", len(response.Blocks["bar"]), "partitions for 'bar' where there were two") + } + block := response.GetBlock("bar", 1) + if block == nil { + t.Error("Decoding did not produce a block for bar/1") + } else { + if block.Err != ErrNoError { + t.Error("Decoding failed for bar/1/Err, got:", int16(block.Err)) + } + if block.Offset != 0xFF { + t.Error("Decoding failed for bar/1/Offset, got:", block.Offset) + } + } + block = response.GetBlock("bar", 2) + if block == nil { + t.Error("Decoding did not produce a block for bar/2") + } else { + if block.Err != ErrInvalidMessage { + t.Error("Decoding failed for bar/2/Err, got:", int16(block.Err)) + } + if block.Offset != 0 { + t.Error("Decoding failed for bar/2/Offset, got:", block.Offset) + } + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/produce_set.go b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_set.go new file mode 100644 index 00000000..158d9c47 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_set.go @@ -0,0 +1,176 @@ +package sarama + +import "time" + +type partitionSet struct { + msgs []*ProducerMessage + setToSend *MessageSet + bufferBytes int +} + +type produceSet struct { + parent *asyncProducer + msgs map[string]map[int32]*partitionSet + + bufferBytes int + bufferCount int +} + +func newProduceSet(parent *asyncProducer) *produceSet { + return &produceSet{ + msgs: make(map[string]map[int32]*partitionSet), + parent: parent, + } +} + +func (ps *produceSet) add(msg *ProducerMessage) error { + var err error + var key, val []byte + + if msg.Key != nil { + if key, err = msg.Key.Encode(); err != nil { + return err + } + } + + if msg.Value != nil { + if val, err = msg.Value.Encode(); err != nil { + return err + } + } + + partitions := ps.msgs[msg.Topic] + if partitions == nil { + partitions = make(map[int32]*partitionSet) + ps.msgs[msg.Topic] = partitions + } + + set := partitions[msg.Partition] + if set == nil { + set = &partitionSet{setToSend: new(MessageSet)} + partitions[msg.Partition] = set + } + + set.msgs = append(set.msgs, msg) + msgToSend := &Message{Codec: CompressionNone, Key: key, Value: val} + if ps.parent.conf.Version.IsAtLeast(V0_10_0_0) { + if msg.Timestamp.IsZero() { + msgToSend.Timestamp = time.Now() + } else { + msgToSend.Timestamp = msg.Timestamp + } + msgToSend.Version = 1 + } + set.setToSend.addMessage(msgToSend) + + size := producerMessageOverhead + len(key) + len(val) + set.bufferBytes += size + ps.bufferBytes += size + ps.bufferCount++ + + return nil +} + +func (ps *produceSet) buildRequest() *ProduceRequest { + req := &ProduceRequest{ + RequiredAcks: ps.parent.conf.Producer.RequiredAcks, + Timeout: int32(ps.parent.conf.Producer.Timeout / time.Millisecond), + } + if ps.parent.conf.Version.IsAtLeast(V0_10_0_0) { + req.Version = 2 + } + + for topic, partitionSet := range ps.msgs { + for partition, set := range partitionSet { + if ps.parent.conf.Producer.Compression == CompressionNone { + req.AddSet(topic, partition, set.setToSend) + } else { + // When compression is enabled, the entire set for each partition is compressed + // and sent as the payload of a single fake "message" with the appropriate codec + // set and no key. When the server sees a message with a compression codec, it + // decompresses the payload and treats the result as its message set. + payload, err := encode(set.setToSend, ps.parent.conf.MetricRegistry) + if err != nil { + Logger.Println(err) // if this happens, it's basically our fault. + panic(err) + } + compMsg := &Message{ + Codec: ps.parent.conf.Producer.Compression, + Key: nil, + Value: payload, + Set: set.setToSend, // Provide the underlying message set for accurate metrics + } + if ps.parent.conf.Version.IsAtLeast(V0_10_0_0) { + compMsg.Version = 1 + compMsg.Timestamp = set.setToSend.Messages[0].Msg.Timestamp + } + req.AddMessage(topic, partition, compMsg) + } + } + } + + return req +} + +func (ps *produceSet) eachPartition(cb func(topic string, partition int32, msgs []*ProducerMessage)) { + for topic, partitionSet := range ps.msgs { + for partition, set := range partitionSet { + cb(topic, partition, set.msgs) + } + } +} + +func (ps *produceSet) dropPartition(topic string, partition int32) []*ProducerMessage { + if ps.msgs[topic] == nil { + return nil + } + set := ps.msgs[topic][partition] + if set == nil { + return nil + } + ps.bufferBytes -= set.bufferBytes + ps.bufferCount -= len(set.msgs) + delete(ps.msgs[topic], partition) + return set.msgs +} + +func (ps *produceSet) wouldOverflow(msg *ProducerMessage) bool { + switch { + // Would we overflow our maximum possible size-on-the-wire? 10KiB is arbitrary overhead for safety. + case ps.bufferBytes+msg.byteSize() >= int(MaxRequestSize-(10*1024)): + return true + // Would we overflow the size-limit of a compressed message-batch for this partition? + case ps.parent.conf.Producer.Compression != CompressionNone && + ps.msgs[msg.Topic] != nil && ps.msgs[msg.Topic][msg.Partition] != nil && + ps.msgs[msg.Topic][msg.Partition].bufferBytes+msg.byteSize() >= ps.parent.conf.Producer.MaxMessageBytes: + return true + // Would we overflow simply in number of messages? + case ps.parent.conf.Producer.Flush.MaxMessages > 0 && ps.bufferCount >= ps.parent.conf.Producer.Flush.MaxMessages: + return true + default: + return false + } +} + +func (ps *produceSet) readyToFlush() bool { + switch { + // If we don't have any messages, nothing else matters + case ps.empty(): + return false + // If all three config values are 0, we always flush as-fast-as-possible + case ps.parent.conf.Producer.Flush.Frequency == 0 && ps.parent.conf.Producer.Flush.Bytes == 0 && ps.parent.conf.Producer.Flush.Messages == 0: + return true + // If we've passed the message trigger-point + case ps.parent.conf.Producer.Flush.Messages > 0 && ps.bufferCount >= ps.parent.conf.Producer.Flush.Messages: + return true + // If we've passed the byte trigger-point + case ps.parent.conf.Producer.Flush.Bytes > 0 && ps.bufferBytes >= ps.parent.conf.Producer.Flush.Bytes: + return true + default: + return false + } +} + +func (ps *produceSet) empty() bool { + return ps.bufferCount == 0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/produce_set_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_set_test.go new file mode 100644 index 00000000..d016a10b --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/produce_set_test.go @@ -0,0 +1,185 @@ +package sarama + +import ( + "testing" + "time" +) + +func makeProduceSet() (*asyncProducer, *produceSet) { + parent := &asyncProducer{ + conf: NewConfig(), + } + return parent, newProduceSet(parent) +} + +func safeAddMessage(t *testing.T, ps *produceSet, msg *ProducerMessage) { + if err := ps.add(msg); err != nil { + t.Error(err) + } +} + +func TestProduceSetInitial(t *testing.T) { + _, ps := makeProduceSet() + + if !ps.empty() { + t.Error("New produceSet should be empty") + } + + if ps.readyToFlush() { + t.Error("Empty produceSet must never be ready to flush") + } +} + +func TestProduceSetAddingMessages(t *testing.T) { + parent, ps := makeProduceSet() + parent.conf.Producer.Flush.MaxMessages = 1000 + + msg := &ProducerMessage{Key: StringEncoder(TestMessage), Value: StringEncoder(TestMessage)} + safeAddMessage(t, ps, msg) + + if ps.empty() { + t.Error("set shouldn't be empty when a message is added") + } + + if !ps.readyToFlush() { + t.Error("by default set should be ready to flush when any message is in place") + } + + for i := 0; i < 999; i++ { + if ps.wouldOverflow(msg) { + t.Error("set shouldn't fill up after only", i+1, "messages") + } + safeAddMessage(t, ps, msg) + } + + if !ps.wouldOverflow(msg) { + t.Error("set should be full after 1000 messages") + } +} + +func TestProduceSetPartitionTracking(t *testing.T) { + _, ps := makeProduceSet() + + m1 := &ProducerMessage{Topic: "t1", Partition: 0} + m2 := &ProducerMessage{Topic: "t1", Partition: 1} + m3 := &ProducerMessage{Topic: "t2", Partition: 0} + safeAddMessage(t, ps, m1) + safeAddMessage(t, ps, m2) + safeAddMessage(t, ps, m3) + + seenT1P0 := false + seenT1P1 := false + seenT2P0 := false + + ps.eachPartition(func(topic string, partition int32, msgs []*ProducerMessage) { + if len(msgs) != 1 { + t.Error("Wrong message count") + } + + if topic == "t1" && partition == 0 { + seenT1P0 = true + } else if topic == "t1" && partition == 1 { + seenT1P1 = true + } else if topic == "t2" && partition == 0 { + seenT2P0 = true + } + }) + + if !seenT1P0 { + t.Error("Didn't see t1p0") + } + if !seenT1P1 { + t.Error("Didn't see t1p1") + } + if !seenT2P0 { + t.Error("Didn't see t2p0") + } + + if len(ps.dropPartition("t1", 1)) != 1 { + t.Error("Got wrong messages back from dropping partition") + } + + if ps.bufferCount != 2 { + t.Error("Incorrect buffer count after dropping partition") + } +} + +func TestProduceSetRequestBuilding(t *testing.T) { + parent, ps := makeProduceSet() + parent.conf.Producer.RequiredAcks = WaitForAll + parent.conf.Producer.Timeout = 10 * time.Second + + msg := &ProducerMessage{ + Topic: "t1", + Partition: 0, + Key: StringEncoder(TestMessage), + Value: StringEncoder(TestMessage), + } + for i := 0; i < 10; i++ { + safeAddMessage(t, ps, msg) + } + msg.Partition = 1 + for i := 0; i < 10; i++ { + safeAddMessage(t, ps, msg) + } + msg.Topic = "t2" + for i := 0; i < 10; i++ { + safeAddMessage(t, ps, msg) + } + + req := ps.buildRequest() + + if req.RequiredAcks != WaitForAll { + t.Error("RequiredAcks not set properly") + } + + if req.Timeout != 10000 { + t.Error("Timeout not set properly") + } + + if len(req.msgSets) != 2 { + t.Error("Wrong number of topics in request") + } +} + +func TestProduceSetCompressedRequestBuilding(t *testing.T) { + parent, ps := makeProduceSet() + parent.conf.Producer.RequiredAcks = WaitForAll + parent.conf.Producer.Timeout = 10 * time.Second + parent.conf.Producer.Compression = CompressionGZIP + parent.conf.Version = V0_10_0_0 + + msg := &ProducerMessage{ + Topic: "t1", + Partition: 0, + Key: StringEncoder(TestMessage), + Value: StringEncoder(TestMessage), + Timestamp: time.Now(), + } + for i := 0; i < 10; i++ { + safeAddMessage(t, ps, msg) + } + + req := ps.buildRequest() + + if req.Version != 2 { + t.Error("Wrong request version") + } + + for _, msgBlock := range req.msgSets["t1"][0].Messages { + msg := msgBlock.Msg + err := msg.decodeSet() + if err != nil { + t.Error("Failed to decode set from payload") + } + for _, compMsgBlock := range msg.Set.Messages { + compMsg := compMsgBlock.Msg + if compMsg.Version != 1 { + t.Error("Wrong compressed message version") + } + } + if msg.Version != 1 { + t.Error("Wrong compressed parent message version") + } + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/real_decoder.go b/vendor/src/gopkg.in/Shopify/sarama.v1/real_decoder.go new file mode 100644 index 00000000..a0141af0 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/real_decoder.go @@ -0,0 +1,259 @@ +package sarama + +import ( + "encoding/binary" + "math" +) + +var errInvalidArrayLength = PacketDecodingError{"invalid array length"} +var errInvalidByteSliceLength = PacketDecodingError{"invalid byteslice length"} +var errInvalidStringLength = PacketDecodingError{"invalid string length"} +var errInvalidSubsetSize = PacketDecodingError{"invalid subset size"} + +type realDecoder struct { + raw []byte + off int + stack []pushDecoder +} + +// primitives + +func (rd *realDecoder) getInt8() (int8, error) { + if rd.remaining() < 1 { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } + tmp := int8(rd.raw[rd.off]) + rd.off++ + return tmp, nil +} + +func (rd *realDecoder) getInt16() (int16, error) { + if rd.remaining() < 2 { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } + tmp := int16(binary.BigEndian.Uint16(rd.raw[rd.off:])) + rd.off += 2 + return tmp, nil +} + +func (rd *realDecoder) getInt32() (int32, error) { + if rd.remaining() < 4 { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } + tmp := int32(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + return tmp, nil +} + +func (rd *realDecoder) getInt64() (int64, error) { + if rd.remaining() < 8 { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } + tmp := int64(binary.BigEndian.Uint64(rd.raw[rd.off:])) + rd.off += 8 + return tmp, nil +} + +func (rd *realDecoder) getArrayLength() (int, error) { + if rd.remaining() < 4 { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } + tmp := int(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + if tmp > rd.remaining() { + rd.off = len(rd.raw) + return -1, ErrInsufficientData + } else if tmp > 2*math.MaxUint16 { + return -1, errInvalidArrayLength + } + return tmp, nil +} + +// collections + +func (rd *realDecoder) getBytes() ([]byte, error) { + tmp, err := rd.getInt32() + + if err != nil { + return nil, err + } + + n := int(tmp) + + switch { + case n < -1: + return nil, errInvalidByteSliceLength + case n == -1: + return nil, nil + case n == 0: + return make([]byte, 0), nil + case n > rd.remaining(): + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + + tmpStr := rd.raw[rd.off : rd.off+n] + rd.off += n + return tmpStr, nil +} + +func (rd *realDecoder) getString() (string, error) { + tmp, err := rd.getInt16() + + if err != nil { + return "", err + } + + n := int(tmp) + + switch { + case n < -1: + return "", errInvalidStringLength + case n == -1: + return "", nil + case n == 0: + return "", nil + case n > rd.remaining(): + rd.off = len(rd.raw) + return "", ErrInsufficientData + } + + tmpStr := string(rd.raw[rd.off : rd.off+n]) + rd.off += n + return tmpStr, nil +} + +func (rd *realDecoder) getInt32Array() ([]int32, error) { + if rd.remaining() < 4 { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + n := int(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + + if rd.remaining() < 4*n { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + + if n == 0 { + return nil, nil + } + + if n < 0 { + return nil, errInvalidArrayLength + } + + ret := make([]int32, n) + for i := range ret { + ret[i] = int32(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + } + return ret, nil +} + +func (rd *realDecoder) getInt64Array() ([]int64, error) { + if rd.remaining() < 4 { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + n := int(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + + if rd.remaining() < 8*n { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + + if n == 0 { + return nil, nil + } + + if n < 0 { + return nil, errInvalidArrayLength + } + + ret := make([]int64, n) + for i := range ret { + ret[i] = int64(binary.BigEndian.Uint64(rd.raw[rd.off:])) + rd.off += 8 + } + return ret, nil +} + +func (rd *realDecoder) getStringArray() ([]string, error) { + if rd.remaining() < 4 { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + n := int(binary.BigEndian.Uint32(rd.raw[rd.off:])) + rd.off += 4 + + if n == 0 { + return nil, nil + } + + if n < 0 { + return nil, errInvalidArrayLength + } + + ret := make([]string, n) + for i := range ret { + if str, err := rd.getString(); err != nil { + return nil, err + } else { + ret[i] = str + } + } + return ret, nil +} + +// subsets + +func (rd *realDecoder) remaining() int { + return len(rd.raw) - rd.off +} + +func (rd *realDecoder) getSubset(length int) (packetDecoder, error) { + if length < 0 { + return nil, errInvalidSubsetSize + } else if length > rd.remaining() { + rd.off = len(rd.raw) + return nil, ErrInsufficientData + } + + start := rd.off + rd.off += length + return &realDecoder{raw: rd.raw[start:rd.off]}, nil +} + +// stacks + +func (rd *realDecoder) push(in pushDecoder) error { + in.saveOffset(rd.off) + + reserve := in.reserveLength() + if rd.remaining() < reserve { + rd.off = len(rd.raw) + return ErrInsufficientData + } + + rd.stack = append(rd.stack, in) + + rd.off += reserve + + return nil +} + +func (rd *realDecoder) pop() error { + // this is go's ugly pop pattern (the inverse of append) + in := rd.stack[len(rd.stack)-1] + rd.stack = rd.stack[:len(rd.stack)-1] + + return in.check(rd.off, rd.raw) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/real_encoder.go b/vendor/src/gopkg.in/Shopify/sarama.v1/real_encoder.go new file mode 100644 index 00000000..ced4267c --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/real_encoder.go @@ -0,0 +1,129 @@ +package sarama + +import ( + "encoding/binary" + + "github.com/rcrowley/go-metrics" +) + +type realEncoder struct { + raw []byte + off int + stack []pushEncoder + registry metrics.Registry +} + +// primitives + +func (re *realEncoder) putInt8(in int8) { + re.raw[re.off] = byte(in) + re.off++ +} + +func (re *realEncoder) putInt16(in int16) { + binary.BigEndian.PutUint16(re.raw[re.off:], uint16(in)) + re.off += 2 +} + +func (re *realEncoder) putInt32(in int32) { + binary.BigEndian.PutUint32(re.raw[re.off:], uint32(in)) + re.off += 4 +} + +func (re *realEncoder) putInt64(in int64) { + binary.BigEndian.PutUint64(re.raw[re.off:], uint64(in)) + re.off += 8 +} + +func (re *realEncoder) putArrayLength(in int) error { + re.putInt32(int32(in)) + return nil +} + +// collection + +func (re *realEncoder) putRawBytes(in []byte) error { + copy(re.raw[re.off:], in) + re.off += len(in) + return nil +} + +func (re *realEncoder) putBytes(in []byte) error { + if in == nil { + re.putInt32(-1) + return nil + } + re.putInt32(int32(len(in))) + copy(re.raw[re.off:], in) + re.off += len(in) + return nil +} + +func (re *realEncoder) putString(in string) error { + re.putInt16(int16(len(in))) + copy(re.raw[re.off:], in) + re.off += len(in) + return nil +} + +func (re *realEncoder) putStringArray(in []string) error { + err := re.putArrayLength(len(in)) + if err != nil { + return err + } + + for _, val := range in { + if err := re.putString(val); err != nil { + return err + } + } + + return nil +} + +func (re *realEncoder) putInt32Array(in []int32) error { + err := re.putArrayLength(len(in)) + if err != nil { + return err + } + for _, val := range in { + re.putInt32(val) + } + return nil +} + +func (re *realEncoder) putInt64Array(in []int64) error { + err := re.putArrayLength(len(in)) + if err != nil { + return err + } + for _, val := range in { + re.putInt64(val) + } + return nil +} + +func (re *realEncoder) offset() int { + return re.off +} + +// stacks + +func (re *realEncoder) push(in pushEncoder) { + in.saveOffset(re.off) + re.off += in.reserveLength() + re.stack = append(re.stack, in) +} + +func (re *realEncoder) pop() error { + // this is go's ugly pop pattern (the inverse of append) + in := re.stack[len(re.stack)-1] + re.stack = re.stack[:len(re.stack)-1] + + return in.run(re.off, re.raw) +} + +// we do record metrics during the real encoder pass +func (re *realEncoder) metricRegistry() metrics.Registry { + return re.registry +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/request.go new file mode 100644 index 00000000..73310ca8 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/request.go @@ -0,0 +1,119 @@ +package sarama + +import ( + "encoding/binary" + "fmt" + "io" +) + +type protocolBody interface { + encoder + versionedDecoder + key() int16 + version() int16 + requiredVersion() KafkaVersion +} + +type request struct { + correlationID int32 + clientID string + body protocolBody +} + +func (r *request) encode(pe packetEncoder) (err error) { + pe.push(&lengthField{}) + pe.putInt16(r.body.key()) + pe.putInt16(r.body.version()) + pe.putInt32(r.correlationID) + err = pe.putString(r.clientID) + if err != nil { + return err + } + err = r.body.encode(pe) + if err != nil { + return err + } + return pe.pop() +} + +func (r *request) decode(pd packetDecoder) (err error) { + var key int16 + if key, err = pd.getInt16(); err != nil { + return err + } + var version int16 + if version, err = pd.getInt16(); err != nil { + return err + } + if r.correlationID, err = pd.getInt32(); err != nil { + return err + } + r.clientID, err = pd.getString() + + r.body = allocateBody(key, version) + if r.body == nil { + return PacketDecodingError{fmt.Sprintf("unknown request key (%d)", key)} + } + return r.body.decode(pd, version) +} + +func decodeRequest(r io.Reader) (req *request, bytesRead int, err error) { + lengthBytes := make([]byte, 4) + if _, err := io.ReadFull(r, lengthBytes); err != nil { + return nil, bytesRead, err + } + bytesRead += len(lengthBytes) + + length := int32(binary.BigEndian.Uint32(lengthBytes)) + if length <= 4 || length > MaxRequestSize { + return nil, bytesRead, PacketDecodingError{fmt.Sprintf("message of length %d too large or too small", length)} + } + + encodedReq := make([]byte, length) + if _, err := io.ReadFull(r, encodedReq); err != nil { + return nil, bytesRead, err + } + bytesRead += len(encodedReq) + + req = &request{} + if err := decode(encodedReq, req); err != nil { + return nil, bytesRead, err + } + return req, bytesRead, nil +} + +func allocateBody(key, version int16) protocolBody { + switch key { + case 0: + return &ProduceRequest{} + case 1: + return &FetchRequest{} + case 2: + return &OffsetRequest{Version: version} + case 3: + return &MetadataRequest{} + case 8: + return &OffsetCommitRequest{Version: version} + case 9: + return &OffsetFetchRequest{} + case 10: + return &ConsumerMetadataRequest{} + case 11: + return &JoinGroupRequest{} + case 12: + return &HeartbeatRequest{} + case 13: + return &LeaveGroupRequest{} + case 14: + return &SyncGroupRequest{} + case 15: + return &DescribeGroupsRequest{} + case 16: + return &ListGroupsRequest{} + case 17: + return &SaslHandshakeRequest{} + case 18: + return &ApiVersionsRequest{} + } + return nil +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/request_test.go new file mode 100644 index 00000000..e5457543 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/request_test.go @@ -0,0 +1,91 @@ +package sarama + +import ( + "bytes" + "reflect" + "testing" + + "github.com/davecgh/go-spew/spew" +) + +type testRequestBody struct { +} + +func (s *testRequestBody) key() int16 { + return 0x666 +} + +func (s *testRequestBody) version() int16 { + return 0xD2 +} + +func (s *testRequestBody) encode(pe packetEncoder) error { + return pe.putString("abc") +} + +// not specific to request tests, just helper functions for testing structures that +// implement the encoder or decoder interfaces that needed somewhere to live + +func testEncodable(t *testing.T, name string, in encoder, expect []byte) { + packet, err := encode(in, nil) + if err != nil { + t.Error(err) + } else if !bytes.Equal(packet, expect) { + t.Error("Encoding", name, "failed\ngot ", packet, "\nwant", expect) + } +} + +func testDecodable(t *testing.T, name string, out decoder, in []byte) { + err := decode(in, out) + if err != nil { + t.Error("Decoding", name, "failed:", err) + } +} + +func testVersionDecodable(t *testing.T, name string, out versionedDecoder, in []byte, version int16) { + err := versionedDecode(in, out, version) + if err != nil { + t.Error("Decoding", name, "version", version, "failed:", err) + } +} + +func testRequest(t *testing.T, name string, rb protocolBody, expected []byte) { + // Encoder request + req := &request{correlationID: 123, clientID: "foo", body: rb} + packet, err := encode(req, nil) + headerSize := 14 + len("foo") + if err != nil { + t.Error(err) + } else if !bytes.Equal(packet[headerSize:], expected) { + t.Error("Encoding", name, "failed\ngot ", packet[headerSize:], "\nwant", expected) + } + // Decoder request + decoded, n, err := decodeRequest(bytes.NewReader(packet)) + if err != nil { + t.Error("Failed to decode request", err) + } else if decoded.correlationID != 123 || decoded.clientID != "foo" { + t.Errorf("Decoded header %q is not valid: %+v", name, decoded) + } else if !reflect.DeepEqual(rb, decoded.body) { + t.Error(spew.Sprintf("Decoded request %q does not match the encoded one\nencoded: %+v\ndecoded: %+v", name, rb, decoded.body)) + } else if n != len(packet) { + t.Errorf("Decoded request %q bytes: %d does not match the encoded one: %d\n", name, n, len(packet)) + } +} + +func testResponse(t *testing.T, name string, res protocolBody, expected []byte) { + encoded, err := encode(res, nil) + if err != nil { + t.Error(err) + } else if expected != nil && !bytes.Equal(encoded, expected) { + t.Error("Encoding", name, "failed\ngot ", encoded, "\nwant", expected) + } + + decoded := reflect.New(reflect.TypeOf(res).Elem()).Interface().(versionedDecoder) + if err := versionedDecode(encoded, decoded, res.version()); err != nil { + t.Error("Decoding", name, "failed:", err) + } + + if !reflect.DeepEqual(decoded, res) { + t.Errorf("Decoded response does not match the encoded one\nencoded: %#v\ndecoded: %#v", res, decoded) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/response_header.go b/vendor/src/gopkg.in/Shopify/sarama.v1/response_header.go new file mode 100644 index 00000000..f3f4d27d --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/response_header.go @@ -0,0 +1,21 @@ +package sarama + +import "fmt" + +type responseHeader struct { + length int32 + correlationID int32 +} + +func (r *responseHeader) decode(pd packetDecoder) (err error) { + r.length, err = pd.getInt32() + if err != nil { + return err + } + if r.length <= 4 || r.length > MaxResponseSize { + return PacketDecodingError{fmt.Sprintf("message of length %d too large or too small", r.length)} + } + + r.correlationID, err = pd.getInt32() + return err +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/response_header_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/response_header_test.go new file mode 100644 index 00000000..8f9fdb80 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/response_header_test.go @@ -0,0 +1,21 @@ +package sarama + +import "testing" + +var ( + responseHeaderBytes = []byte{ + 0x00, 0x00, 0x0f, 0x00, + 0x0a, 0xbb, 0xcc, 0xff} +) + +func TestResponseHeader(t *testing.T) { + header := responseHeader{} + + testDecodable(t, "response header", &header, responseHeaderBytes) + if header.length != 0xf00 { + t.Error("Decoding header length failed, got", header.length) + } + if header.correlationID != 0x0abbccff { + t.Error("Decoding header correlation id failed, got", header.correlationID) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sarama.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sarama.go new file mode 100644 index 00000000..7d5dc60d --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sarama.go @@ -0,0 +1,99 @@ +/* +Package sarama is a pure Go client library for dealing with Apache Kafka (versions 0.8 and later). It includes a high-level +API for easily producing and consuming messages, and a low-level API for controlling bytes on the wire when the high-level +API is insufficient. Usage examples for the high-level APIs are provided inline with their full documentation. + +To produce messages, use either the AsyncProducer or the SyncProducer. The AsyncProducer accepts messages on a channel +and produces them asynchronously in the background as efficiently as possible; it is preferred in most cases. +The SyncProducer provides a method which will block until Kafka acknowledges the message as produced. This can be +useful but comes with two caveats: it will generally be less efficient, and the actual durability guarantees +depend on the configured value of `Producer.RequiredAcks`. There are configurations where a message acknowledged by the +SyncProducer can still sometimes be lost. + +To consume messages, use the Consumer. Note that Sarama's Consumer implementation does not currently support automatic +consumer-group rebalancing and offset tracking. For Zookeeper-based tracking (Kafka 0.8.2 and earlier), the +https://github.com/wvanbergen/kafka library builds on Sarama to add this support. For Kafka-based tracking (Kafka 0.9 +and later), the https://github.com/bsm/sarama-cluster library builds on Sarama to add this support. + +For lower-level needs, the Broker and Request/Response objects permit precise control over each connection +and message sent on the wire; the Client provides higher-level metadata management that is shared between +the producers and the consumer. The Request/Response objects and properties are mostly undocumented, as they line up +exactly with the protocol fields documented by Kafka at +https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol + +Metrics are exposed through https://github.com/rcrowley/go-metrics library in a local registry. + +Broker related metrics: + + +----------------------------------------------+------------+---------------------------------------------------------------+ + | Name | Type | Description | + +----------------------------------------------+------------+---------------------------------------------------------------+ + | incoming-byte-rate | meter | Bytes/second read off all brokers | + | incoming-byte-rate-for-broker- | meter | Bytes/second read off a given broker | + | outgoing-byte-rate | meter | Bytes/second written off all brokers | + | outgoing-byte-rate-for-broker- | meter | Bytes/second written off a given broker | + | request-rate | meter | Requests/second sent to all brokers | + | request-rate-for-broker- | meter | Requests/second sent to a given broker | + | request-size | histogram | Distribution of the request size in bytes for all brokers | + | request-size-for-broker- | histogram | Distribution of the request size in bytes for a given broker | + | request-latency-in-ms | histogram | Distribution of the request latency in ms for all brokers | + | request-latency-in-ms-for-broker- | histogram | Distribution of the request latency in ms for a given broker | + | response-rate | meter | Responses/second received from all brokers | + | response-rate-for-broker- | meter | Responses/second received from a given broker | + | response-size | histogram | Distribution of the response size in bytes for all brokers | + | response-size-for-broker- | histogram | Distribution of the response size in bytes for a given broker | + +----------------------------------------------+------------+---------------------------------------------------------------+ + +Note that we do not gather specific metrics for seed brokers but they are part of the "all brokers" metrics. + +Producer related metrics: + + +-------------------------------------------+------------+--------------------------------------------------------------------------------------+ + | Name | Type | Description | + +-------------------------------------------+------------+--------------------------------------------------------------------------------------+ + | batch-size | histogram | Distribution of the number of bytes sent per partition per request for all topics | + | batch-size-for-topic- | histogram | Distribution of the number of bytes sent per partition per request for a given topic | + | record-send-rate | meter | Records/second sent to all topics | + | record-send-rate-for-topic- | meter | Records/second sent to a given topic | + | records-per-request | histogram | Distribution of the number of records sent per request for all topics | + | records-per-request-for-topic- | histogram | Distribution of the number of records sent per request for a given topic | + | compression-ratio | histogram | Distribution of the compression ratio times 100 of record batches for all topics | + | compression-ratio-for-topic- | histogram | Distribution of the compression ratio times 100 of record batches for a given topic | + +-------------------------------------------+------------+--------------------------------------------------------------------------------------+ + +*/ +package sarama + +import ( + "io/ioutil" + "log" +) + +// Logger is the instance of a StdLogger interface that Sarama writes connection +// management events to. By default it is set to discard all log messages via ioutil.Discard, +// but you can set it to redirect wherever you want. +var Logger StdLogger = log.New(ioutil.Discard, "[Sarama] ", log.LstdFlags) + +// StdLogger is used to log error messages. +type StdLogger interface { + Print(v ...interface{}) + Printf(format string, v ...interface{}) + Println(v ...interface{}) +} + +// PanicHandler is called for recovering from panics spawned internally to the library (and thus +// not recoverable by the caller's goroutine). Defaults to nil, which means panics are not recovered. +var PanicHandler func(interface{}) + +// MaxRequestSize is the maximum size (in bytes) of any request that Sarama will attempt to send. Trying +// to send a request larger than this will result in an PacketEncodingError. The default of 100 MiB is aligned +// with Kafka's default `socket.request.max.bytes`, which is the largest request the broker will attempt +// to process. +var MaxRequestSize int32 = 100 * 1024 * 1024 + +// MaxResponseSize is the maximum size (in bytes) of any response that Sarama will attempt to parse. If +// a broker returns a response message larger than this value, Sarama will return a PacketDecodingError to +// protect the client from running out of memory. Please note that brokers do not have any natural limit on +// the size of responses they send. In particular, they can send arbitrarily large fetch responses to consumers +// (see https://issues.apache.org/jira/browse/KAFKA-2063). +var MaxResponseSize int32 = 100 * 1024 * 1024 diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_request.go new file mode 100644 index 00000000..fbbc8947 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_request.go @@ -0,0 +1,33 @@ +package sarama + +type SaslHandshakeRequest struct { + Mechanism string +} + +func (r *SaslHandshakeRequest) encode(pe packetEncoder) error { + if err := pe.putString(r.Mechanism); err != nil { + return err + } + + return nil +} + +func (r *SaslHandshakeRequest) decode(pd packetDecoder, version int16) (err error) { + if r.Mechanism, err = pd.getString(); err != nil { + return err + } + + return nil +} + +func (r *SaslHandshakeRequest) key() int16 { + return 17 +} + +func (r *SaslHandshakeRequest) version() int16 { + return 0 +} + +func (r *SaslHandshakeRequest) requiredVersion() KafkaVersion { + return V0_10_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_request_test.go new file mode 100644 index 00000000..806e628f --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_request_test.go @@ -0,0 +1,17 @@ +package sarama + +import "testing" + +var ( + baseSaslRequest = []byte{ + 0, 3, 'f', 'o', 'o', // Mechanism + } +) + +func TestSaslHandshakeRequest(t *testing.T) { + var request *SaslHandshakeRequest + + request = new(SaslHandshakeRequest) + request.Mechanism = "foo" + testRequest(t, "basic", request, baseSaslRequest) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_response.go new file mode 100644 index 00000000..8379bbb2 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_response.go @@ -0,0 +1,38 @@ +package sarama + +type SaslHandshakeResponse struct { + Err KError + EnabledMechanisms []string +} + +func (r *SaslHandshakeResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + return pe.putStringArray(r.EnabledMechanisms) +} + +func (r *SaslHandshakeResponse) decode(pd packetDecoder, version int16) error { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + var err error + if r.EnabledMechanisms, err = pd.getStringArray(); err != nil { + return err + } + + return nil +} + +func (r *SaslHandshakeResponse) key() int16 { + return 17 +} + +func (r *SaslHandshakeResponse) version() int16 { + return 0 +} + +func (r *SaslHandshakeResponse) requiredVersion() KafkaVersion { + return V0_10_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_response_test.go new file mode 100644 index 00000000..1fd4c79e --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sasl_handshake_response_test.go @@ -0,0 +1,24 @@ +package sarama + +import "testing" + +var ( + saslHandshakeResponse = []byte{ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x03, 'f', 'o', 'o', + } +) + +func TestSaslHandshakeResponse(t *testing.T) { + var response *SaslHandshakeResponse + + response = new(SaslHandshakeResponse) + testVersionDecodable(t, "no error", response, saslHandshakeResponse, 0) + if response.Err != ErrNoError { + t.Error("Decoding error failed: no error expected but found", response.Err) + } + if response.EnabledMechanisms[0] != "foo" { + t.Error("Decoding error failed: expected 'foo' but found", response.EnabledMechanisms) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_request.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_request.go new file mode 100644 index 00000000..fe207080 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_request.go @@ -0,0 +1,100 @@ +package sarama + +type SyncGroupRequest struct { + GroupId string + GenerationId int32 + MemberId string + GroupAssignments map[string][]byte +} + +func (r *SyncGroupRequest) encode(pe packetEncoder) error { + if err := pe.putString(r.GroupId); err != nil { + return err + } + + pe.putInt32(r.GenerationId) + + if err := pe.putString(r.MemberId); err != nil { + return err + } + + if err := pe.putArrayLength(len(r.GroupAssignments)); err != nil { + return err + } + for memberId, memberAssignment := range r.GroupAssignments { + if err := pe.putString(memberId); err != nil { + return err + } + if err := pe.putBytes(memberAssignment); err != nil { + return err + } + } + + return nil +} + +func (r *SyncGroupRequest) decode(pd packetDecoder, version int16) (err error) { + if r.GroupId, err = pd.getString(); err != nil { + return + } + if r.GenerationId, err = pd.getInt32(); err != nil { + return + } + if r.MemberId, err = pd.getString(); err != nil { + return + } + + n, err := pd.getArrayLength() + if err != nil { + return err + } + if n == 0 { + return nil + } + + r.GroupAssignments = make(map[string][]byte) + for i := 0; i < n; i++ { + memberId, err := pd.getString() + if err != nil { + return err + } + memberAssignment, err := pd.getBytes() + if err != nil { + return err + } + + r.GroupAssignments[memberId] = memberAssignment + } + + return nil +} + +func (r *SyncGroupRequest) key() int16 { + return 14 +} + +func (r *SyncGroupRequest) version() int16 { + return 0 +} + +func (r *SyncGroupRequest) requiredVersion() KafkaVersion { + return V0_9_0_0 +} + +func (r *SyncGroupRequest) AddGroupAssignment(memberId string, memberAssignment []byte) { + if r.GroupAssignments == nil { + r.GroupAssignments = make(map[string][]byte) + } + + r.GroupAssignments[memberId] = memberAssignment +} + +func (r *SyncGroupRequest) AddGroupAssignmentMember(memberId string, memberAssignment *ConsumerGroupMemberAssignment) error { + bin, err := encode(memberAssignment, nil) + if err != nil { + return err + } + + r.AddGroupAssignment(memberId, bin) + return nil +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_request_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_request_test.go new file mode 100644 index 00000000..3f537ef9 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_request_test.go @@ -0,0 +1,38 @@ +package sarama + +import "testing" + +var ( + emptySyncGroupRequest = []byte{ + 0, 3, 'f', 'o', 'o', // Group ID + 0x00, 0x01, 0x02, 0x03, // Generation ID + 0, 3, 'b', 'a', 'z', // Member ID + 0, 0, 0, 0, // no assignments + } + + populatedSyncGroupRequest = []byte{ + 0, 3, 'f', 'o', 'o', // Group ID + 0x00, 0x01, 0x02, 0x03, // Generation ID + 0, 3, 'b', 'a', 'z', // Member ID + 0, 0, 0, 1, // one assignment + 0, 3, 'b', 'a', 'z', // Member ID + 0, 0, 0, 3, 'f', 'o', 'o', // Member assignment + } +) + +func TestSyncGroupRequest(t *testing.T) { + var request *SyncGroupRequest + + request = new(SyncGroupRequest) + request.GroupId = "foo" + request.GenerationId = 66051 + request.MemberId = "baz" + testRequest(t, "empty", request, emptySyncGroupRequest) + + request = new(SyncGroupRequest) + request.GroupId = "foo" + request.GenerationId = 66051 + request.MemberId = "baz" + request.AddGroupAssignment("baz", []byte("foo")) + testRequest(t, "populated", request, populatedSyncGroupRequest) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_response.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_response.go new file mode 100644 index 00000000..12aef673 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_response.go @@ -0,0 +1,40 @@ +package sarama + +type SyncGroupResponse struct { + Err KError + MemberAssignment []byte +} + +func (r *SyncGroupResponse) GetMemberAssignment() (*ConsumerGroupMemberAssignment, error) { + assignment := new(ConsumerGroupMemberAssignment) + err := decode(r.MemberAssignment, assignment) + return assignment, err +} + +func (r *SyncGroupResponse) encode(pe packetEncoder) error { + pe.putInt16(int16(r.Err)) + return pe.putBytes(r.MemberAssignment) +} + +func (r *SyncGroupResponse) decode(pd packetDecoder, version int16) (err error) { + if kerr, err := pd.getInt16(); err != nil { + return err + } else { + r.Err = KError(kerr) + } + + r.MemberAssignment, err = pd.getBytes() + return +} + +func (r *SyncGroupResponse) key() int16 { + return 14 +} + +func (r *SyncGroupResponse) version() int16 { + return 0 +} + +func (r *SyncGroupResponse) requiredVersion() KafkaVersion { + return V0_9_0_0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_response_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_response_test.go new file mode 100644 index 00000000..6fb70885 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_group_response_test.go @@ -0,0 +1,40 @@ +package sarama + +import ( + "reflect" + "testing" +) + +var ( + syncGroupResponseNoError = []byte{ + 0x00, 0x00, // No error + 0, 0, 0, 3, 0x01, 0x02, 0x03, // Member assignment data + } + + syncGroupResponseWithError = []byte{ + 0, 27, // ErrRebalanceInProgress + 0, 0, 0, 0, // No member assignment data + } +) + +func TestSyncGroupResponse(t *testing.T) { + var response *SyncGroupResponse + + response = new(SyncGroupResponse) + testVersionDecodable(t, "no error", response, syncGroupResponseNoError, 0) + if response.Err != ErrNoError { + t.Error("Decoding Err failed: no error expected but found", response.Err) + } + if !reflect.DeepEqual(response.MemberAssignment, []byte{0x01, 0x02, 0x03}) { + t.Error("Decoding MemberAssignment failed, found:", response.MemberAssignment) + } + + response = new(SyncGroupResponse) + testVersionDecodable(t, "no error", response, syncGroupResponseWithError, 0) + if response.Err != ErrRebalanceInProgress { + t.Error("Decoding Err failed: ErrRebalanceInProgress expected but found", response.Err) + } + if !reflect.DeepEqual(response.MemberAssignment, []byte{}) { + t.Error("Decoding MemberAssignment failed, found:", response.MemberAssignment) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sync_producer.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_producer.go new file mode 100644 index 00000000..c77ae314 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_producer.go @@ -0,0 +1,164 @@ +package sarama + +import "sync" + +// SyncProducer publishes Kafka messages, blocking until they have been acknowledged. It routes messages to the correct +// broker, refreshing metadata as appropriate, and parses responses for errors. You must call Close() on a producer +// to avoid leaks, it may not be garbage-collected automatically when it passes out of scope. +// +// The SyncProducer comes with two caveats: it will generally be less efficient than the AsyncProducer, and the actual +// durability guarantee provided when a message is acknowledged depend on the configured value of `Producer.RequiredAcks`. +// There are configurations where a message acknowledged by the SyncProducer can still sometimes be lost. +// +// For implementation reasons, the SyncProducer requires `Producer.Return.Errors` and `Producer.Return.Successes` to +// be set to true in its configuration. +type SyncProducer interface { + + // SendMessage produces a given message, and returns only when it either has + // succeeded or failed to produce. It will return the partition and the offset + // of the produced message, or an error if the message failed to produce. + SendMessage(msg *ProducerMessage) (partition int32, offset int64, err error) + + // SendMessages produces a given set of messages, and returns only when all + // messages in the set have either succeeded or failed. Note that messages + // can succeed and fail individually; if some succeed and some fail, + // SendMessages will return an error. + SendMessages(msgs []*ProducerMessage) error + + // Close shuts down the producer and flushes any messages it may have buffered. + // You must call this function before a producer object passes out of scope, as + // it may otherwise leak memory. You must call this before calling Close on the + // underlying client. + Close() error +} + +type syncProducer struct { + producer *asyncProducer + wg sync.WaitGroup +} + +// NewSyncProducer creates a new SyncProducer using the given broker addresses and configuration. +func NewSyncProducer(addrs []string, config *Config) (SyncProducer, error) { + if config == nil { + config = NewConfig() + config.Producer.Return.Successes = true + } + + if err := verifyProducerConfig(config); err != nil { + return nil, err + } + + p, err := NewAsyncProducer(addrs, config) + if err != nil { + return nil, err + } + return newSyncProducerFromAsyncProducer(p.(*asyncProducer)), nil +} + +// NewSyncProducerFromClient creates a new SyncProducer using the given client. It is still +// necessary to call Close() on the underlying client when shutting down this producer. +func NewSyncProducerFromClient(client Client) (SyncProducer, error) { + if err := verifyProducerConfig(client.Config()); err != nil { + return nil, err + } + + p, err := NewAsyncProducerFromClient(client) + if err != nil { + return nil, err + } + return newSyncProducerFromAsyncProducer(p.(*asyncProducer)), nil +} + +func newSyncProducerFromAsyncProducer(p *asyncProducer) *syncProducer { + sp := &syncProducer{producer: p} + + sp.wg.Add(2) + go withRecover(sp.handleSuccesses) + go withRecover(sp.handleErrors) + + return sp +} + +func verifyProducerConfig(config *Config) error { + if !config.Producer.Return.Errors { + return ConfigurationError("Producer.Return.Errors must be true to be used in a SyncProducer") + } + if !config.Producer.Return.Successes { + return ConfigurationError("Producer.Return.Successes must be true to be used in a SyncProducer") + } + return nil +} + +func (sp *syncProducer) SendMessage(msg *ProducerMessage) (partition int32, offset int64, err error) { + oldMetadata := msg.Metadata + defer func() { + msg.Metadata = oldMetadata + }() + + expectation := make(chan *ProducerError, 1) + msg.Metadata = expectation + sp.producer.Input() <- msg + + if err := <-expectation; err != nil { + return -1, -1, err.Err + } + + return msg.Partition, msg.Offset, nil +} + +func (sp *syncProducer) SendMessages(msgs []*ProducerMessage) error { + savedMetadata := make([]interface{}, len(msgs)) + for i := range msgs { + savedMetadata[i] = msgs[i].Metadata + } + defer func() { + for i := range msgs { + msgs[i].Metadata = savedMetadata[i] + } + }() + + expectations := make(chan chan *ProducerError, len(msgs)) + go func() { + for _, msg := range msgs { + expectation := make(chan *ProducerError, 1) + msg.Metadata = expectation + sp.producer.Input() <- msg + expectations <- expectation + } + close(expectations) + }() + + var errors ProducerErrors + for expectation := range expectations { + if err := <-expectation; err != nil { + errors = append(errors, err) + } + } + + if len(errors) > 0 { + return errors + } + return nil +} + +func (sp *syncProducer) handleSuccesses() { + defer sp.wg.Done() + for msg := range sp.producer.Successes() { + expectation := msg.Metadata.(chan *ProducerError) + expectation <- nil + } +} + +func (sp *syncProducer) handleErrors() { + defer sp.wg.Done() + for err := range sp.producer.Errors() { + expectation := err.Msg.Metadata.(chan *ProducerError) + expectation <- err + } +} + +func (sp *syncProducer) Close() error { + sp.producer.AsyncClose() + sp.wg.Wait() + return nil +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/sync_producer_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_producer_test.go new file mode 100644 index 00000000..c1519a14 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/sync_producer_test.go @@ -0,0 +1,199 @@ +package sarama + +import ( + "log" + "sync" + "testing" +) + +func TestSyncProducer(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + for i := 0; i < 10; i++ { + leader.Returns(prodSuccess) + } + + producer, err := NewSyncProducer([]string{seedBroker.Addr()}, nil) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + msg := &ProducerMessage{ + Topic: "my_topic", + Value: StringEncoder(TestMessage), + Metadata: "test", + } + + partition, offset, err := producer.SendMessage(msg) + + if partition != 0 || msg.Partition != partition { + t.Error("Unexpected partition") + } + if offset != 0 || msg.Offset != offset { + t.Error("Unexpected offset") + } + if str, ok := msg.Metadata.(string); !ok || str != "test" { + t.Error("Unexpected metadata") + } + if err != nil { + t.Error(err) + } + } + + safeClose(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestSyncProducerBatch(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + + config := NewConfig() + config.Producer.Flush.Messages = 3 + config.Producer.Return.Successes = true + producer, err := NewSyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + err = producer.SendMessages([]*ProducerMessage{ + &ProducerMessage{ + Topic: "my_topic", + Value: StringEncoder(TestMessage), + Metadata: "test", + }, + &ProducerMessage{ + Topic: "my_topic", + Value: StringEncoder(TestMessage), + Metadata: "test", + }, + &ProducerMessage{ + Topic: "my_topic", + Value: StringEncoder(TestMessage), + Metadata: "test", + }, + }) + + if err != nil { + t.Error(err) + } + + safeClose(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestConcurrentSyncProducer(t *testing.T) { + seedBroker := NewMockBroker(t, 1) + leader := NewMockBroker(t, 2) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(leader.Addr(), leader.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, leader.BrokerID(), nil, nil, ErrNoError) + seedBroker.Returns(metadataResponse) + + prodSuccess := new(ProduceResponse) + prodSuccess.AddTopicPartition("my_topic", 0, ErrNoError) + leader.Returns(prodSuccess) + + config := NewConfig() + config.Producer.Flush.Messages = 100 + config.Producer.Return.Successes = true + producer, err := NewSyncProducer([]string{seedBroker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + wg := sync.WaitGroup{} + + for i := 0; i < 100; i++ { + wg.Add(1) + go func() { + msg := &ProducerMessage{Topic: "my_topic", Value: StringEncoder(TestMessage)} + partition, _, err := producer.SendMessage(msg) + if partition != 0 { + t.Error("Unexpected partition") + } + if err != nil { + t.Error(err) + } + wg.Done() + }() + } + wg.Wait() + + safeClose(t, producer) + leader.Close() + seedBroker.Close() +} + +func TestSyncProducerToNonExistingTopic(t *testing.T) { + broker := NewMockBroker(t, 1) + + metadataResponse := new(MetadataResponse) + metadataResponse.AddBroker(broker.Addr(), broker.BrokerID()) + metadataResponse.AddTopicPartition("my_topic", 0, broker.BrokerID(), nil, nil, ErrNoError) + broker.Returns(metadataResponse) + + config := NewConfig() + config.Metadata.Retry.Max = 0 + config.Producer.Retry.Max = 0 + config.Producer.Return.Successes = true + + producer, err := NewSyncProducer([]string{broker.Addr()}, config) + if err != nil { + t.Fatal(err) + } + + metadataResponse = new(MetadataResponse) + metadataResponse.AddTopic("unknown", ErrUnknownTopicOrPartition) + broker.Returns(metadataResponse) + + _, _, err = producer.SendMessage(&ProducerMessage{Topic: "unknown"}) + if err != ErrUnknownTopicOrPartition { + t.Error("Uxpected ErrUnknownTopicOrPartition, found:", err) + } + + safeClose(t, producer) + broker.Close() +} + +// This example shows the basic usage pattern of the SyncProducer. +func ExampleSyncProducer() { + producer, err := NewSyncProducer([]string{"localhost:9092"}, nil) + if err != nil { + log.Fatalln(err) + } + defer func() { + if err := producer.Close(); err != nil { + log.Fatalln(err) + } + }() + + msg := &ProducerMessage{Topic: "my_topic", Value: StringEncoder("testing 123")} + partition, offset, err := producer.SendMessage(msg) + if err != nil { + log.Printf("FAILED to send message: %s\n", err) + } else { + log.Printf("> message sent to partition %d at offset %d\n", partition, offset) + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/tools/README.md b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/README.md new file mode 100644 index 00000000..3464c4ad --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/README.md @@ -0,0 +1,10 @@ +# Sarama tools + +This folder contains applications that are useful for exploration of your Kafka cluster, or instrumentation. +Some of these tools mirror tools that ship with Kafka, but these tools won't require installing the JVM to function. + +- [kafka-console-producer](./kafka-console-producer): a command line tool to produce a single message to your Kafka custer. +- [kafka-console-partitionconsumer](./kafka-console-partitionconsumer): (deprecated) a command line tool to consume a single partition of a topic on your Kafka cluster. +- [kafka-console-consumer](./kafka-console-consumer): a command line tool to consume arbitrary partitions of a topic on your Kafka cluster. + +To install all tools, run `go get github.com/Shopify/sarama/tools/...` diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-consumer/README.md b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-consumer/README.md new file mode 100644 index 00000000..4e77f0b7 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-consumer/README.md @@ -0,0 +1,29 @@ +# kafka-console-consumer + +A simple command line tool to consume partitions of a topic and print the +messages on the standard output. + +### Installation + + go get github.com/Shopify/sarama/tools/kafka-console-consumer + +### Usage + + # Minimum invocation + kafka-console-consumer -topic=test -brokers=kafka1:9092 + + # It will pick up a KAFKA_PEERS environment variable + export KAFKA_PEERS=kafka1:9092,kafka2:9092,kafka3:9092 + kafka-console-consumer -topic=test + + # You can specify the offset you want to start at. It can be either + # `oldest`, `newest`. The default is `newest`. + kafka-console-consumer -topic=test -offset=oldest + kafka-console-consumer -topic=test -offset=newest + + # You can specify the partition(s) you want to consume as a comma-separated + # list. The default is `all`. + kafka-console-consumer -topic=test -partitions=1,2,3 + + # Display all command line options + kafka-console-consumer -help diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-consumer/kafka-console-consumer.go b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-consumer/kafka-console-consumer.go new file mode 100644 index 00000000..0f1eb89a --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-consumer/kafka-console-consumer.go @@ -0,0 +1,145 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "os/signal" + "strconv" + "strings" + "sync" + + "github.com/Shopify/sarama" +) + +var ( + brokerList = flag.String("brokers", os.Getenv("KAFKA_PEERS"), "The comma separated list of brokers in the Kafka cluster") + topic = flag.String("topic", "", "REQUIRED: the topic to consume") + partitions = flag.String("partitions", "all", "The partitions to consume, can be 'all' or comma-separated numbers") + offset = flag.String("offset", "newest", "The offset to start with. Can be `oldest`, `newest`") + verbose = flag.Bool("verbose", false, "Whether to turn on sarama logging") + bufferSize = flag.Int("buffer-size", 256, "The buffer size of the message channel.") + + logger = log.New(os.Stderr, "", log.LstdFlags) +) + +func main() { + flag.Parse() + + if *brokerList == "" { + printUsageErrorAndExit("You have to provide -brokers as a comma-separated list, or set the KAFKA_PEERS environment variable.") + } + + if *topic == "" { + printUsageErrorAndExit("-topic is required") + } + + if *verbose { + sarama.Logger = logger + } + + var initialOffset int64 + switch *offset { + case "oldest": + initialOffset = sarama.OffsetOldest + case "newest": + initialOffset = sarama.OffsetNewest + default: + printUsageErrorAndExit("-offset should be `oldest` or `newest`") + } + + c, err := sarama.NewConsumer(strings.Split(*brokerList, ","), nil) + if err != nil { + printErrorAndExit(69, "Failed to start consumer: %s", err) + } + + partitionList, err := getPartitions(c) + if err != nil { + printErrorAndExit(69, "Failed to get the list of partitions: %s", err) + } + + var ( + messages = make(chan *sarama.ConsumerMessage, *bufferSize) + closing = make(chan struct{}) + wg sync.WaitGroup + ) + + go func() { + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Kill, os.Interrupt) + <-signals + logger.Println("Initiating shutdown of consumer...") + close(closing) + }() + + for _, partition := range partitionList { + pc, err := c.ConsumePartition(*topic, partition, initialOffset) + if err != nil { + printErrorAndExit(69, "Failed to start consumer for partition %d: %s", partition, err) + } + + go func(pc sarama.PartitionConsumer) { + <-closing + pc.AsyncClose() + }(pc) + + wg.Add(1) + go func(pc sarama.PartitionConsumer) { + defer wg.Done() + for message := range pc.Messages() { + messages <- message + } + }(pc) + } + + go func() { + for msg := range messages { + fmt.Printf("Partition:\t%d\n", msg.Partition) + fmt.Printf("Offset:\t%d\n", msg.Offset) + fmt.Printf("Key:\t%s\n", string(msg.Key)) + fmt.Printf("Value:\t%s\n", string(msg.Value)) + fmt.Println() + } + }() + + wg.Wait() + logger.Println("Done consuming topic", *topic) + close(messages) + + if err := c.Close(); err != nil { + logger.Println("Failed to close consumer: ", err) + } +} + +func getPartitions(c sarama.Consumer) ([]int32, error) { + if *partitions == "all" { + return c.Partitions(*topic) + } + + tmp := strings.Split(*partitions, ",") + var pList []int32 + for i := range tmp { + val, err := strconv.ParseInt(tmp[i], 10, 32) + if err != nil { + return nil, err + } + pList = append(pList, int32(val)) + } + + return pList, nil +} + +func printErrorAndExit(code int, format string, values ...interface{}) { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", fmt.Sprintf(format, values...)) + fmt.Fprintln(os.Stderr) + os.Exit(code) +} + +func printUsageErrorAndExit(format string, values ...interface{}) { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", fmt.Sprintf(format, values...)) + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, "Available command line options:") + flag.PrintDefaults() + os.Exit(64) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-partitionconsumer/README.md b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-partitionconsumer/README.md new file mode 100644 index 00000000..646dd5f5 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-partitionconsumer/README.md @@ -0,0 +1,28 @@ +# kafka-console-partitionconsumer + +NOTE: this tool is deprecated in favour of the more general and more powerful +`kafka-console-consumer`. + +A simple command line tool to consume a partition of a topic and print the messages +on the standard output. + +### Installation + + go get github.com/Shopify/sarama/tools/kafka-console-partitionconsumer + +### Usage + + # Minimum invocation + kafka-console-partitionconsumer -topic=test -partition=4 -brokers=kafka1:9092 + + # It will pick up a KAFKA_PEERS environment variable + export KAFKA_PEERS=kafka1:9092,kafka2:9092,kafka3:9092 + kafka-console-partitionconsumer -topic=test -partition=4 + + # You can specify the offset you want to start at. It can be either + # `oldest`, `newest`, or a specific offset number + kafka-console-partitionconsumer -topic=test -partition=3 -offset=oldest + kafka-console-partitionconsumer -topic=test -partition=2 -offset=1337 + + # Display all command line options + kafka-console-partitionconsumer -help diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-partitionconsumer/kafka-console-partitionconsumer.go b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-partitionconsumer/kafka-console-partitionconsumer.go new file mode 100644 index 00000000..d5e4464d --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-partitionconsumer/kafka-console-partitionconsumer.go @@ -0,0 +1,102 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "os/signal" + "strconv" + "strings" + + "github.com/Shopify/sarama" +) + +var ( + brokerList = flag.String("brokers", os.Getenv("KAFKA_PEERS"), "The comma separated list of brokers in the Kafka cluster") + topic = flag.String("topic", "", "REQUIRED: the topic to consume") + partition = flag.Int("partition", -1, "REQUIRED: the partition to consume") + offset = flag.String("offset", "newest", "The offset to start with. Can be `oldest`, `newest`, or an actual offset") + verbose = flag.Bool("verbose", false, "Whether to turn on sarama logging") + + logger = log.New(os.Stderr, "", log.LstdFlags) +) + +func main() { + flag.Parse() + + if *brokerList == "" { + printUsageErrorAndExit("You have to provide -brokers as a comma-separated list, or set the KAFKA_PEERS environment variable.") + } + + if *topic == "" { + printUsageErrorAndExit("-topic is required") + } + + if *partition == -1 { + printUsageErrorAndExit("-partition is required") + } + + if *verbose { + sarama.Logger = logger + } + + var ( + initialOffset int64 + offsetError error + ) + switch *offset { + case "oldest": + initialOffset = sarama.OffsetOldest + case "newest": + initialOffset = sarama.OffsetNewest + default: + initialOffset, offsetError = strconv.ParseInt(*offset, 10, 64) + } + + if offsetError != nil { + printUsageErrorAndExit("Invalid initial offset: %s", *offset) + } + + c, err := sarama.NewConsumer(strings.Split(*brokerList, ","), nil) + if err != nil { + printErrorAndExit(69, "Failed to start consumer: %s", err) + } + + pc, err := c.ConsumePartition(*topic, int32(*partition), initialOffset) + if err != nil { + printErrorAndExit(69, "Failed to start partition consumer: %s", err) + } + + go func() { + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Kill, os.Interrupt) + <-signals + pc.AsyncClose() + }() + + for msg := range pc.Messages() { + fmt.Printf("Offset:\t%d\n", msg.Offset) + fmt.Printf("Key:\t%s\n", string(msg.Key)) + fmt.Printf("Value:\t%s\n", string(msg.Value)) + fmt.Println() + } + + if err := c.Close(); err != nil { + logger.Println("Failed to close consumer: ", err) + } +} + +func printErrorAndExit(code int, format string, values ...interface{}) { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", fmt.Sprintf(format, values...)) + fmt.Fprintln(os.Stderr) + os.Exit(code) +} + +func printUsageErrorAndExit(format string, values ...interface{}) { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", fmt.Sprintf(format, values...)) + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, "Available command line options:") + flag.PrintDefaults() + os.Exit(64) +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-producer/README.md b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-producer/README.md new file mode 100644 index 00000000..6b3a65f2 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-producer/README.md @@ -0,0 +1,34 @@ +# kafka-console-producer + +A simple command line tool to produce a single message to Kafka. + +### Installation + + go get github.com/Shopify/sarama/tools/kafka-console-producer + + +### Usage + + # Minimum invocation + kafka-console-producer -topic=test -value=value -brokers=kafka1:9092 + + # It will pick up a KAFKA_PEERS environment variable + export KAFKA_PEERS=kafka1:9092,kafka2:9092,kafka3:9092 + kafka-console-producer -topic=test -value=value + + # It will read the value from stdin by using pipes + echo "hello world" | kafka-console-producer -topic=test + + # Specify a key: + echo "hello world" | kafka-console-producer -topic=test -key=key + + # Partitioning: by default, kafka-console-producer will partition as follows: + # - manual partitioning if a -partition is provided + # - hash partitioning by key if a -key is provided + # - random partioning otherwise. + # + # You can override this using the -partitioner argument: + echo "hello world" | kafka-console-producer -topic=test -key=key -partitioner=random + + # Display all command line options + kafka-console-producer -help diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-producer/kafka-console-producer.go b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-producer/kafka-console-producer.go new file mode 100644 index 00000000..83054ed7 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/tools/kafka-console-producer/kafka-console-producer.go @@ -0,0 +1,124 @@ +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "strings" + + "github.com/Shopify/sarama" + "github.com/rcrowley/go-metrics" +) + +var ( + brokerList = flag.String("brokers", os.Getenv("KAFKA_PEERS"), "The comma separated list of brokers in the Kafka cluster. You can also set the KAFKA_PEERS environment variable") + topic = flag.String("topic", "", "REQUIRED: the topic to produce to") + key = flag.String("key", "", "The key of the message to produce. Can be empty.") + value = flag.String("value", "", "REQUIRED: the value of the message to produce. You can also provide the value on stdin.") + partitioner = flag.String("partitioner", "", "The partitioning scheme to use. Can be `hash`, `manual`, or `random`") + partition = flag.Int("partition", -1, "The partition to produce to.") + verbose = flag.Bool("verbose", false, "Turn on sarama logging to stderr") + showMetrics = flag.Bool("metrics", false, "Output metrics on successful publish to stderr") + silent = flag.Bool("silent", false, "Turn off printing the message's topic, partition, and offset to stdout") + + logger = log.New(os.Stderr, "", log.LstdFlags) +) + +func main() { + flag.Parse() + + if *brokerList == "" { + printUsageErrorAndExit("no -brokers specified. Alternatively, set the KAFKA_PEERS environment variable") + } + + if *topic == "" { + printUsageErrorAndExit("no -topic specified") + } + + if *verbose { + sarama.Logger = logger + } + + config := sarama.NewConfig() + config.Producer.RequiredAcks = sarama.WaitForAll + config.Producer.Return.Successes = true + + switch *partitioner { + case "": + if *partition >= 0 { + config.Producer.Partitioner = sarama.NewManualPartitioner + } else { + config.Producer.Partitioner = sarama.NewHashPartitioner + } + case "hash": + config.Producer.Partitioner = sarama.NewHashPartitioner + case "random": + config.Producer.Partitioner = sarama.NewRandomPartitioner + case "manual": + config.Producer.Partitioner = sarama.NewManualPartitioner + if *partition == -1 { + printUsageErrorAndExit("-partition is required when partitioning manually") + } + default: + printUsageErrorAndExit(fmt.Sprintf("Partitioner %s not supported.", *partitioner)) + } + + message := &sarama.ProducerMessage{Topic: *topic, Partition: int32(*partition)} + + if *key != "" { + message.Key = sarama.StringEncoder(*key) + } + + if *value != "" { + message.Value = sarama.StringEncoder(*value) + } else if stdinAvailable() { + bytes, err := ioutil.ReadAll(os.Stdin) + if err != nil { + printErrorAndExit(66, "Failed to read data from the standard input: %s", err) + } + message.Value = sarama.ByteEncoder(bytes) + } else { + printUsageErrorAndExit("-value is required, or you have to provide the value on stdin") + } + + producer, err := sarama.NewSyncProducer(strings.Split(*brokerList, ","), config) + if err != nil { + printErrorAndExit(69, "Failed to open Kafka producer: %s", err) + } + defer func() { + if err := producer.Close(); err != nil { + logger.Println("Failed to close Kafka producer cleanly:", err) + } + }() + + partition, offset, err := producer.SendMessage(message) + if err != nil { + printErrorAndExit(69, "Failed to produce message: %s", err) + } else if !*silent { + fmt.Printf("topic=%s\tpartition=%d\toffset=%d\n", *topic, partition, offset) + } + if *showMetrics { + metrics.WriteOnce(config.MetricRegistry, os.Stderr) + } +} + +func printErrorAndExit(code int, format string, values ...interface{}) { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", fmt.Sprintf(format, values...)) + fmt.Fprintln(os.Stderr) + os.Exit(code) +} + +func printUsageErrorAndExit(message string) { + fmt.Fprintln(os.Stderr, "ERROR:", message) + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, "Available command line options:") + flag.PrintDefaults() + os.Exit(64) +} + +func stdinAvailable() bool { + stat, _ := os.Stdin.Stat() + return (stat.Mode() & os.ModeCharDevice) == 0 +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/utils.go b/vendor/src/gopkg.in/Shopify/sarama.v1/utils.go new file mode 100644 index 00000000..3cbab2d9 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/utils.go @@ -0,0 +1,152 @@ +package sarama + +import ( + "bufio" + "net" + "sort" +) + +type none struct{} + +// make []int32 sortable so we can sort partition numbers +type int32Slice []int32 + +func (slice int32Slice) Len() int { + return len(slice) +} + +func (slice int32Slice) Less(i, j int) bool { + return slice[i] < slice[j] +} + +func (slice int32Slice) Swap(i, j int) { + slice[i], slice[j] = slice[j], slice[i] +} + +func dupeAndSort(input []int32) []int32 { + ret := make([]int32, 0, len(input)) + for _, val := range input { + ret = append(ret, val) + } + + sort.Sort(int32Slice(ret)) + return ret +} + +func withRecover(fn func()) { + defer func() { + handler := PanicHandler + if handler != nil { + if err := recover(); err != nil { + handler(err) + } + } + }() + + fn() +} + +func safeAsyncClose(b *Broker) { + tmp := b // local var prevents clobbering in goroutine + go withRecover(func() { + if connected, _ := tmp.Connected(); connected { + if err := tmp.Close(); err != nil { + Logger.Println("Error closing broker", tmp.ID(), ":", err) + } + } + }) +} + +// Encoder is a simple interface for any type that can be encoded as an array of bytes +// in order to be sent as the key or value of a Kafka message. Length() is provided as an +// optimization, and must return the same as len() on the result of Encode(). +type Encoder interface { + Encode() ([]byte, error) + Length() int +} + +// make strings and byte slices encodable for convenience so they can be used as keys +// and/or values in kafka messages + +// StringEncoder implements the Encoder interface for Go strings so that they can be used +// as the Key or Value in a ProducerMessage. +type StringEncoder string + +func (s StringEncoder) Encode() ([]byte, error) { + return []byte(s), nil +} + +func (s StringEncoder) Length() int { + return len(s) +} + +// ByteEncoder implements the Encoder interface for Go byte slices so that they can be used +// as the Key or Value in a ProducerMessage. +type ByteEncoder []byte + +func (b ByteEncoder) Encode() ([]byte, error) { + return b, nil +} + +func (b ByteEncoder) Length() int { + return len(b) +} + +// bufConn wraps a net.Conn with a buffer for reads to reduce the number of +// reads that trigger syscalls. +type bufConn struct { + net.Conn + buf *bufio.Reader +} + +func newBufConn(conn net.Conn) *bufConn { + return &bufConn{ + Conn: conn, + buf: bufio.NewReader(conn), + } +} + +func (bc *bufConn) Read(b []byte) (n int, err error) { + return bc.buf.Read(b) +} + +// KafkaVersion instances represent versions of the upstream Kafka broker. +type KafkaVersion struct { + // it's a struct rather than just typing the array directly to make it opaque and stop people + // generating their own arbitrary versions + version [4]uint +} + +func newKafkaVersion(major, minor, veryMinor, patch uint) KafkaVersion { + return KafkaVersion{ + version: [4]uint{major, minor, veryMinor, patch}, + } +} + +// IsAtLeast return true if and only if the version it is called on is +// greater than or equal to the version passed in: +// V1.IsAtLeast(V2) // false +// V2.IsAtLeast(V1) // true +func (v KafkaVersion) IsAtLeast(other KafkaVersion) bool { + for i := range v.version { + if v.version[i] > other.version[i] { + return true + } else if v.version[i] < other.version[i] { + return false + } + } + return true +} + +// Effective constants defining the supported kafka versions. +var ( + V0_8_2_0 = newKafkaVersion(0, 8, 2, 0) + V0_8_2_1 = newKafkaVersion(0, 8, 2, 1) + V0_8_2_2 = newKafkaVersion(0, 8, 2, 2) + V0_9_0_0 = newKafkaVersion(0, 9, 0, 0) + V0_9_0_1 = newKafkaVersion(0, 9, 0, 1) + V0_10_0_0 = newKafkaVersion(0, 10, 0, 0) + V0_10_0_1 = newKafkaVersion(0, 10, 0, 1) + V0_10_1_0 = newKafkaVersion(0, 10, 1, 0) + minVersion = V0_8_2_0 +) diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/utils_test.go b/vendor/src/gopkg.in/Shopify/sarama.v1/utils_test.go new file mode 100644 index 00000000..a9e09502 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/utils_test.go @@ -0,0 +1,21 @@ +package sarama + +import "testing" + +func TestVersionCompare(t *testing.T) { + if V0_8_2_0.IsAtLeast(V0_8_2_1) { + t.Error("0.8.2.0 >= 0.8.2.1") + } + if !V0_8_2_1.IsAtLeast(V0_8_2_0) { + t.Error("! 0.8.2.1 >= 0.8.2.0") + } + if !V0_8_2_0.IsAtLeast(V0_8_2_0) { + t.Error("! 0.8.2.0 >= 0.8.2.0") + } + if !V0_9_0_0.IsAtLeast(V0_8_2_1) { + t.Error("! 0.9.0.0 >= 0.8.2.1") + } + if V0_8_2_1.IsAtLeast(V0_10_0_0) { + t.Error("0.8.2.1 >= 0.10.0.0") + } +} diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/boot_cluster.sh b/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/boot_cluster.sh new file mode 100644 index 00000000..95e47dde --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/boot_cluster.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -ex + +# Launch and wait for toxiproxy +${REPOSITORY_ROOT}/vagrant/run_toxiproxy.sh & +while ! nc -q 1 localhost 2181 ${KAFKA_INSTALL_ROOT}/zookeeper-${ZK_PORT}/myid +done diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/kafka.conf b/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/kafka.conf new file mode 100644 index 00000000..25101df5 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/kafka.conf @@ -0,0 +1,9 @@ +start on started zookeeper-ZK_PORT +stop on stopping zookeeper-ZK_PORT + +# Use a script instead of exec (using env stanza leaks KAFKA_HEAP_OPTS from zookeeper) +script + sleep 2 + export KAFKA_HEAP_OPTS="-Xmx320m" + exec /opt/kafka-KAFKAID/bin/kafka-server-start.sh /opt/kafka-KAFKAID/config/server.properties +end script diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/provision.sh b/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/provision.sh new file mode 100644 index 00000000..ace768f4 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/provision.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +set -ex + +apt-get update +yes | apt-get install default-jre + +export KAFKA_INSTALL_ROOT=/opt +export KAFKA_HOSTNAME=192.168.100.67 +export KAFKA_VERSION=0.9.0.1 +export REPOSITORY_ROOT=/vagrant + +sh /vagrant/vagrant/install_cluster.sh +sh /vagrant/vagrant/setup_services.sh +sh /vagrant/vagrant/create_topics.sh diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/run_toxiproxy.sh b/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/run_toxiproxy.sh new file mode 100644 index 00000000..e52c00e7 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/run_toxiproxy.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -ex + +${KAFKA_INSTALL_ROOT}/toxiproxy -port 8474 -host 0.0.0.0 & +PID=$! + +while ! nc -q 1 localhost 8474 + +# The number of threads handling network requests +num.network.threads=2 + +# The number of threads doing disk I/O +num.io.threads=8 + +# The send buffer (SO_SNDBUF) used by the socket server +socket.send.buffer.bytes=1048576 + +# The receive buffer (SO_RCVBUF) used by the socket server +socket.receive.buffer.bytes=1048576 + +# The maximum size of a request that the socket server will accept (protection against OOM) +socket.request.max.bytes=104857600 + + +############################# Log Basics ############################# + +# A comma seperated list of directories under which to store log files +log.dirs=KAFKA_DATADIR + +# The default number of log partitions per topic. More partitions allow greater +# parallelism for consumption, but this will also result in more files across +# the brokers. +num.partitions=2 + +# Create new topics with a replication factor of 2 so failover can be tested +# more easily. +default.replication.factor=2 + +auto.create.topics.enable=false +delete.topic.enable=true + +############################# Log Flush Policy ############################# + +# Messages are immediately written to the filesystem but by default we only fsync() to sync +# the OS cache lazily. The following configurations control the flush of data to disk. +# There are a few important trade-offs here: +# 1. Durability: Unflushed data may be lost if you are not using replication. +# 2. Latency: Very large flush intervals may lead to latency spikes when the flush does occur as there will be a lot of data to flush. +# 3. Throughput: The flush is generally the most expensive operation, and a small flush interval may lead to exceessive seeks. +# The settings below allow one to configure the flush policy to flush data after a period of time or +# every N messages (or both). This can be done globally and overridden on a per-topic basis. + +# The number of messages to accept before forcing a flush of data to disk +#log.flush.interval.messages=10000 + +# The maximum amount of time a message can sit in a log before we force a flush +#log.flush.interval.ms=1000 + +############################# Log Retention Policy ############################# + +# The following configurations control the disposal of log segments. The policy can +# be set to delete segments after a period of time, or after a given size has accumulated. +# A segment will be deleted whenever *either* of these criteria are met. Deletion always happens +# from the end of the log. + +# The minimum age of a log file to be eligible for deletion +log.retention.hours=168 + +# A size-based retention policy for logs. Segments are pruned from the log as long as the remaining +# segments don't drop below log.retention.bytes. +log.retention.bytes=268435456 + +# The maximum size of a log segment file. When this size is reached a new log segment will be created. +log.segment.bytes=268435456 + +# The interval at which log segments are checked to see if they can be deleted according +# to the retention policies +log.retention.check.interval.ms=60000 + +# By default the log cleaner is disabled and the log retention policy will default to just delete segments after their retention expires. +# If log.cleaner.enable=true is set the cleaner will be enabled and individual logs can then be marked for log compaction. +log.cleaner.enable=false + +############################# Zookeeper ############################# + +# Zookeeper connection string (see zookeeper docs for details). +# This is a comma separated host:port pairs, each corresponding to a zk +# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002". +# You can also append an optional chroot string to the urls to specify the +# root directory for all kafka znodes. +zookeeper.connect=localhost:ZK_PORT + +# Timeout in ms for connecting to zookeeper +zookeeper.session.timeout.ms=3000 +zookeeper.connection.timeout.ms=3000 diff --git a/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/setup_services.sh b/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/setup_services.sh new file mode 100644 index 00000000..81d8ea05 --- /dev/null +++ b/vendor/src/gopkg.in/Shopify/sarama.v1/vagrant/setup_services.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +set -ex + +stop toxiproxy || true +cp ${REPOSITORY_ROOT}/vagrant/toxiproxy.conf /etc/init/toxiproxy.conf +cp ${REPOSITORY_ROOT}/vagrant/run_toxiproxy.sh ${KAFKA_INSTALL_ROOT}/ +start toxiproxy + +for i in 1 2 3 4 5; do + ZK_PORT=`expr $i + 2180` + KAFKA_PORT=`expr $i + 9090` + + stop zookeeper-${ZK_PORT} || true + + # set up zk service + cp ${REPOSITORY_ROOT}/vagrant/zookeeper.conf /etc/init/zookeeper-${ZK_PORT}.conf + sed -i s/KAFKAID/${KAFKA_PORT}/g /etc/init/zookeeper-${ZK_PORT}.conf + + # set up kafka service + cp ${REPOSITORY_ROOT}/vagrant/kafka.conf /etc/init/kafka-${KAFKA_PORT}.conf + sed -i s/KAFKAID/${KAFKA_PORT}/g /etc/init/kafka-${KAFKA_PORT}.conf + sed -i s/ZK_PORT/${ZK_PORT}/g /etc/init/kafka-${KAFKA_PORT}.conf + + start zookeeper-${ZK_PORT} +done + +# Wait for the last kafka node to finish booting +while ! nc -q 1 localhost 29095

    Qgcjn4g^oJs_DDnZ<-EKxa?AMlg2!~vC42}P%} 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 $l7_Z5rpqT|55%g;SWEy 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�LyYP}Wyy!Yk2txQb zqWq#)A5UZ{jGLW;wdKwMllcuYY$McDDV8_4zE&>9BHvcTivqiq*3S8Fli!+BIdcmS`=WsU|cFCJuqRo2O9GVmO z1nl)aRsQc7Bjg(bA34TON2_d9NKwll&0EW80=>q?Nf_@VuzTxvG$s2J)~7vB%*>Us z!v1(FaxMPwRtn2@(6zNw;o7o1>#CqNWhS5;Kzq-3&(YH~Oom@{g@%g;Y}oM>)Cwnc zC~(yc^8Uc|$SXrm&XR+VT(}k1s7kGo6DR;Fd9($@D@38qQ<#=9h1EK;Jnacy&D(U~#VD9b z2Lrf>wB=?jT5Xeep2e-V+HA7IUj*Srn+v0bgK45iz}uqVVT&%BZ33h@^d|zam)601 zwXu1lJ=Ms8V=j3JcDbKvMG{{&!8w}zTAv< zuBSMwFdn5Rhf{Gt^WD(Y79rbKkOGdfs0vadjRlpF2@5iNl1$yUf>r+GLf3-I2o*MT zw@j!4N$mx3(eVfLQW4Lpk0`gY470BkIxmDRH2h+&p_9LMo6*={}#Tiubo7pZ3n?AbPz|{6XwQ@OP)L9){2$t|_Wt^@3t!?Y2)qK&lx$5J4! z@kDE&tkyVxoOS2uVF_$L&&6+{(1+9f0sqz+9&6c2{Tv)-EkY;7mZOxo(mmirikb~H zLxYD*axP(N?%@C&(#k9;cQVXMqr8iE!hzH>qgS;g4LwBy3#D z&jxV^lzcW(p^vB8mxCQ)yYMN_^K|3BF02CwAjmae@eyLg39ooP#UYBBstFJY20(bb zHLI7G`8J$qnn2;>1zFhZpF~GFMBQ=k(_FT4JvRBqH$Y@oFAdskIjw@s zXM(^>tcp=~+rFs7!D}98fH^0IU<#vdQA*=R-KO7ea|&aW3=op+F^x5i|6OqmXv5Zi zftI2eXJfwJiY~siLllDU+Y=_^p0i!}Q_yG4!-*%@ZCZJYvuz8plYlvVCZJ`>Z~?wj zpsEcQpnI)J5{{iJIITje4Fyd3LXvxsPw2g+!M>}!#2CjwsOTfvy zfws{?FVOp$<_?YP2u-$TpT(=7UfCCXb6JTntoyuP@PmkOIeg#WWx+*Ed*p@_4rvpo z{>jRQ?qZDQ8>}3zl{pw*jy4~+FWBIxJ?dC+DwB^daqX1PT+KF9!N>(Wf^Z+!j#x}K zinqLtuWu`iksU%*JgNils((YM_GxDhW}>gj!3b7Pz=n931mWv>E+!t3fQr!I36?a7 zGY+4J>YT8iw-gQ!cmVqRTAKF@^k~tZOTY+QL=Lja!B=knp5y)W=Y>p6r7SFea?H$sz7;t$#Xs6&b%!X_GQuS(ew%U)AnG1YAIQb2Em z)y=iN=Mjc{Tjj>S`jRW$Bo!*k=eq>^Vlx-wG6C`If#cs~F`xHf5@fiowNSJWMdj)w zm3?e+SnCW>67Dc3%GlL9gA&aFp9Uwf*VK#mauZ3V_Pz`~^(yQsQpJALHLM&?ZWNtF zwu4CW-fXX_>Y~meSnwZl85%IJ%RI%uW#1kJAT2b+i*PSrfoK3sW?`LycO9&R;=>lS zgU$yGU<1Y|YHTwD9v<$)B0P^V=MGX9D6C?bBNV;|g zeP<;Rnt{HscRGnAUId>5jgWE>MeE`~Tbc@=vc`kj`NDOPe3oe`lece@rg?*?Od+26 z+B%X%QNPV;x#0@5`;KFccn+LsJxu&K&aIH+3&YE;@I6TIM=IZ<{3tKFV)qx@D~IzR z0q8?MOisyX^TJ;crC$(lWERjyNwUXhe!=s8SSu~?*^f({cx#X?#E=w5EM)+lA$1G5 zVv0~7LG7dG_TYUZ9wK`$4m}`a0J_uvhbz?1N4Qi8yq*J~Be%FM?l3da$dPr}me100 zv|jM&gFkq#^ee6lbD&ZFO(jt!$>Qz&OjwQm->#Az?>A_a!uMoJpeTcN{3BxD-v%K( zTrd*yB*^;?8m`;)ZN>4bC&@3`BQp{4iGgJ};D8qg!PKu%8BIQ+4HrP3nENHJ!5%52 z1`E(7D17W_O4Lq3lg9X&$|4}a`j|5CuLW()VFB@ly4ZS|A(#Xfn2US!1tx)qYw*rV zfT8k#wE8fa=wv<%ujR)AobSe39?!?0c*u}N>J6!rjS755qZBB+}+rB<=pxrFC zn4fF}_hF6yvXq0@4AWsE9D>lIB)AwtGfW546h@2|y)*S9i@B)tn=SkCm=Tn)!a^%A zi7tZ@+7hPlqla2NL=}g@CzE z#{NZnIh+UuCRIE3u6712*0g`;gL~ejOVf=pc7m6%*y16U!B|;bFo3BY8XB9Wg~^QBYYVHnOx;gv={*> z#0c*LD=Z-d)Svls_(MK`JcbX6ZyiuG*6>@(G&pCZ@| z6p9w_6xSdoKmfaO0*tt#M`PASY%TsIK-h3)_~9WrZ>K7rqGS_c3so36?Of{_gc2j1 z<99GqClj526}yYf$HjY)bZT7P0qHQB$hopfH^GwWN@d}gu_+X>^NWav$sy*Po| z9c$Nx)CK#^Abgw?OluJl0~kWH_~-a*hmG}Z@(0$7BCOXh;KF_mqO_(EJC zKzyN{9RwP9Z-Ig&8h4^&z|YuzO!c7MwA)bIRP+s^<2wb|tz}+Cb~?`|2Sp9K!vU7E zU%wqZ!H(P{U4`E6KS2)%Gcsfgpxw?g`)zj66UJI;>z8f{ z)-Ku_M1-01(zEws!lUvQeAMis=Xuu#l(H>vGv;seX+5K|M<&Gwcsu*j^fcS|m?%a#TfBS}(*5-T3;AtoR2Bs^7wbr-xR)4^%R9~Ly_HQmx;V)7q#4?_G zPLOL{;*!9J#UEprQ>I&+*+N$9i16Z^C*aNPzMkv==v0#yl(tm7u76YmKq8 z7Gv`v@r{wP9q0*Q$)nReLB^pZK1ir~6lRSp+gq3N<%Y^ZAJ}xYC_`;F>-bAkr;GRx z)N?)|j*s7936SLb_|zCR_zD5{t3eY&;5hN@9Z+uV$mb{>heEH+NE==gFS$BMc!a3l zXV-^|>%$86Z5s~3ZuUQhHeDM8&zCZ!BmCl|G*O8j-*EE$92+LGenSJ59D68|PmHPC zGQw!OJcW^|; zS@;a+K%c^hi^8r-Jm35H6xm<(Dx6)WY%d=;?>F5fSRMCgeYIgIQhn(s{`%YZuc8Rz zzMOvvmj6pZ!~sQn>)XGXu>$-aKnLZx3VnPsgm$MLa~B-z0M-!KK#MU{PRzY_k%N{z z3iE8R--JmK&OK+o7vL$Av~+QsMMge|RUaWdP9RRzF0O4~?T+mLIGzq*YK#-DC$OF3 ze%zb3kZo~4=(l#Dbd=1>sJI_Tq#dyB$Wh~$fRyoBv*`s~0b1 zYIDzg{y)^&zbygC`K_%M%`}~aDgUZ>Q^DfJIKO5!G@-CG>h#^GlU*@Yb#DHQbRA|} z0xejTW&y<^>kXsp7hj<_ABedFpIOYK+`=O7N;I_WeR3gUjt0-NiD`H%tmH>eoe#Y2 zpB8_kVr?6yd}f};atZ>qGE&nXpeHvG^OfTt)u#@ncS;MR#~yfZ5`(R@5A_`-62elf>V`%?7Bc`z)t{^nR%kP7?XOkux}d0=+8gH z6PNTD77x%a#E1wbw}l9vWnF`Hhl>`6-s0ka1AUWTdZ&vr+cMZW}N zFjS1LtkrWLLm=zLUQ!21wmOvov1vKgBL|nMAg40McMi+obx!+w^({@8&CCbc3_tj+Kq?vwKLVSq-p=KRGuoWbT&ZE}ETZMu1V zhS_j)LnWP)&HcS-?sw#6hg&^oyNI_h2$*a{z992yyGikG?V1g(z}HJmmf3b4I!)PJ zC{23lX!)625~6eT#qtNLHhGt_gIfFQT+5pN&@vm{mLw(xotoVoHm03Jh?Lmxi+za|( zq2*aY;}}-UK8$KZ=LW*0K+m`$Ys+4>N%Dan>e?g$=Ay)!-si2twR-mVpye>jbAoXE zYY+c2DkzkmRoD8=@*MB18CX!~*Xd3MEb8zWoejLl`FvO1I_Gc4@xr^F$3os0J6P7R zU*r9DWRt^owxSO=enjj#uIkW!ip^fxf#c^F=BqA{571?vJ@DCE+Wu1%;HIJ6+VKk+ z@Ef?OGWRQ>F@UU$X*d^k?)UTI$CUxv)ss}y+yCsB10J(%J1q<9&Y#P1HTt1{)6DuW zeJ`-ft##P+5=Cz&swOiXw-~E`2shi(&0Kl-;1*Yy0dEf6naiq&Hf*H{LIo@=;mt!D zDr;HlNIbPA@Kcy#<6PT;v4fMWbEMeU=@sx0HLG4zn<&`^dM#k{g1SnQmHefDM$zzj z`mR?tmKx)@4-;p$B%L7@3#0>7 z1Qw|f>YqINhY}iCpKYYCh5GSsaLwiJ_lJId;oi}r=U1-jCFhiSD^@!Esxm;XzB-d} zzQ*Cis`I;7dV@Wq1Aq2kJFW!(-2Q1O_npfWr3rF0Gy|CvsxPDXG~7F&>3!e*koxcL zcL!_kU(;jMvv12R-Fq}x}O#^|JWZm{Stc%@$jXo#aheO z{SjK>wv4&7d7>3~bDUl{vg+tIuMX%ePO|{3jQbZ$jQsf)4w(a(;kL%b+tl+~nv}3D zv?tcPAS`5K;B;OtGQcvH)4Q582m-@4m;@iwhx9s^AkU@{#%P!VZ8zNL(ZT!3kYmFz z>Yp$dLon;Y{sGb|bOdCC3S)doA1donoL&v9WL4mWvX)I_)&&h4W&ks-UOUH4&XsGw z3mPWK`Z7oASv<*+2=Hdz!+p4hS8-6DD zu6sU=DQHKe2)ZujsX!<-+pl_5wgAXeRW+sdaXaiHC1%S@Mp=jBZfyDlaC3fo{Eauy za`Ufgk9BDW!vCxZk{oU9vgq6i5kdV{D_Q2KDUuzl?w9=}>}4@?={=qX)8s$uj`wk! zXAaN_K6e+UEsL_I?^lg8_16l9lp@%uhW>2P&CSi69mBjZ6D5LKjoXgfKKH;OQdXvc zs;9`Xd1~gw*I4A#ji*IV-BI-MoK2UhdDn_b|CVs~Pp8@Ic`BRRlN!&g1_g#lgHwT( zEf1q-R789=RACt%@bG(r+fBB)d*Wo{_xP#87V1B9I}ekdYyUu}A*y$Cs$7 zi2hSqc+)}x!>7OD-sw)`?ByxMH~y8l@2@{!RxwrPhc?{CWQ=|e)Ku}&a_^oGqIrWk zAA=@PLf+5p$Hy*sc*e|JiD+oBGZIEOEQkAw;xcC*-^c<9h`nU*NNZ1~*1qcz7?fIn zjKNX)+e!&3QvsoRCEs@->3iz=Elv1(eU@88Smde5`-cn93AYqr36r0+!~hNVl?zSR z0Pn1hCis-JlR6Kznu!|S=r}DIWr0Avg+jgeTWfPWvnfi>Ws9YkIryUA0T0>QpLr3= z_r)VETB4+k&I_1h9@Ec26$|j!95;-1qJDn}ZPg|HV;kJ)$59S(`JaI&Ke?xdbYAK# zfrrlAPw_bskN5wlWbxl2*0ix@9pfYCNCWNQIs>SgZz{=@K5cqXZ}NA&v9yE)N}BQvqm){*B5IHM!OaN1^in$xDKiT zb{}NqjiMEE>o8MG+1z@w9_zX~MEk+LhBKwGK6R9`wKv;Vbx=tfHhB=G9C&zMw9te5 zZ>3;%(2>$$Sqgnu_5(+_zC(!m@-oa)FJ*RS-b)CS4fDRr8bWcqNXMx)2ksPYy+~i4 zSqH82W_FjKPO^keit1g{Zi50ry6QTh*8GW@ppZ*%^Rk^yq5KMTt&`|*{wxTNn3Nn)$07;H<$&s zb-bO47ARCi$F1hKZ*jsVm(rKm!1q?qXK(fe`s4w+>U`uH>dHW>*vbTccTX>xK&hfN z60|BMjX)n$q)3LMBA&`pkPk%Lgj>YYGw?qr3_7Zmq5^#asvYKHY>#z1?&TVr_mG`9 zzH>2xM?1HalmmT+J@*A##lx2)8)|p`fi|du`L^C*mf-O&n#EpE(QJSRUgudx)}oIA zP}%TQ?oW1jpid<7g^tYSGIwJ5c$VVQ#N7!bD!za>Du13lHyxWOi8cPg# zd~|cv`a}OE*N4jldzK*#tTh}t<&nx&){uD@C0uE&_YM@j6g5pWIS2muB9VQJIN@3; z(>>$#X+NXh`5m!&jTp1-$K|H-2vR+E@Wby#4>h`=XYZRd4G&dnE%bHIMz#?qV%DOI zOwbE??;q@g*d19+cCLCUTHerHOYH$3IV!A%%;^r_Ueds{{4-iw6$5Jeyc1FMB))Pq zrg;N1x5fo6m0xVv_25o6E_lxG93h)+v;`^`I__bEii8lNt8r;liw$`}^p`BJTH^gC z$5bE9U$S?8&57N;^^>z2|0lOIaob8U9Y8r~cm!By5B>JT=#yM7TTpg$`&wck`tfm9 zRy1VfmR->nl$5=unbEK|5#H5M0E&sN+-3|KS~qJWF&CpSEtv7Vzc8uc!A0_z?Z?!B z$GiWqUok8DiIEpE8-b?oFIeuT0RP>wBt&O)eOsMzjVr4)q~QL3N|~tN4mZ7j+75dF z23pwf-DUsRSh7d(zs@abo9kBH(^alVrxArGzr06w`3#j|8_R+QbM4>*s)bh;-JU+D zl@Ib_dk1_Tsay}C0^$#viM_(>T@!M@XYPf+)^g)mLL(dZh!M4(mi$P5DXRbW`F7h_ zF_6dkBko4>48W=2eDE=n`PK#bAP|08RJ1$R^R)ZDtC)~Ca5GP>iKss(&M!azW!z{} z6b!xoz@y#Ya!aA8!*P(zSF|`#>Kl%_h z=X5-O3v&16KNl*TzAt1+hF)9##yo&LbI9-;aX)(B{v%F}8sM!6W)w^-!!0H9IeIZV zQl&mlrLej0Abp0ef7|JjV&Q8ro+9`q9c%y6K++C zLxzJF&mP3M85tekEcSj)Qi_2BC6(&z&ln|FYD{&K&^9d7lItffp9zD3{P zZ+L0yHT&!Dv%jGiX^`*{8ucG1s~w5HzfZmkT+ZO6wQXx$-hgK;9FGFE9{Ns2#=sq{ z!S&>Rt+We_U!*s_iThNk8Uaxcp$9R=qS_?EbekoTgzyg1UewCc%rELH&o>xY({VL~ z3w$Pd_T`w2$xBSV9eJD&2v2dI=F4bYnL7pjFymG$BBV5r3TLR|CnqF3vJ&%pKhG4; zb00Ql4S`AyU?zlKJUYJ^I$bLbJm6B7GETmSJ)&>iO@0Q=WBHWtwPmyWFUf_EzQ8=j zI&+wiKX0C@9BKfCWSJE#J()XoR@nW*Ljdkk@z@?RI8U%QBu_kEqG1T7-x#!xUTUm@ zQ5?&RM6d(sdGn)lmC&bA%-!V0ck8L54Zjde6>x|FiE!Utz#=VLq1+U#CV9Z%Q}?UwwxLVmk!N?+eL89bt5Gdu5L$s^zEIpc4T zOU!I6ri}`y3;01WvtcUGg9xJ|bHqNDwy#Yk=JBuXBJ9M-vOT+<*w-Z=ZPW8Mbw{{* z>-F;K6!Ao^mp+sV{3*6F=%w(E=J92}^L3iH^U#%iw1f9pNo+>e%3v{^wn!;)e`dtCmbMNUn ze|mWZ)m!x;4L|woUPv>vU}@pzA_Qz`AkgKwQ%(NyLwliRvoH$_3{a928AimllyNQ% zUaJIX8>X20OJvZR=TSd^zw>U-N!nRMXF)E9ht1zL&u%qs{ZVJ7KG_#yDP=X!p3uF_ z7(MAY*JT#c6>bn2{O3WK&*^4X-94gAIVU6^emyQ|Y)QS}PqvdgRtPB#YJrWB?{0hL zzW>f6M#WWoK+oQ9hsWP@J67||a`G#}C!N%r0q|7*FW>#ybbegjJ)f17@c6&aJoZEy z*7~=#FSMeT8;-Ewoas6re{PtyHBt`-;iHg)$e_KJ?VG08|EA(KVc7vG<9TY>75gke%D9}2eDTzLjjyh{4sGLQQbX{n7G3pg7k@Zjn@`WSJl&#mgW zTz^XLNPjzjuY}Dlui_{a_VGt+XXL?WGb`ah0!0(!{f5z|1{KyWsnbg!2JWv9d}U`T z37aCyoNtIlYJG{$OpHHX4fCkR1;{*V>Y;W^ANrJNHhk&X?=EB3M$>|)O<-dPPQ1<4 zVj@+ri{pU#R{9ZQmChOpFPsMc8p*iS-z9ethQ6160Bw#P`P7u;Qwcyn>_ z^8pg+$Sz+5Z3)jzU2^dkd?ZimR*QNCR{5bR(UY~da|lQJo~)G-IeyTr{A2>I#L=w1 zqvgGV(U;|Zn#CdXhxfn(b4$GQ%g49Vqzji&(~JM#11-q?aPZS$+;-vr&c74{O&NiG z$m>&=VBfuawzgjen5{oLQ@B+4e(CU@)|5cM#KWk^Jmo+02UQ^VBY~CVaN5U6IL@Y5 zG^qo)wb%SkKuoEjsAV?r2-xGtYUEG=JvChrGCjciuCE~~y72I`IShAS#p9g%sn4|A zK{lr$Beh0x+QXc0fhnGO=}Tu#&ZL|aSg&Fnq78|GLaoj+|)Z{L8d9v|OSLAK_@$D?>?b&%P`^NW$+sD*{Kji5}(0WB08cmNi2E?i3q4r3P*>jSC zkziGP1g(eP53p2JXIu#XqDuDkZ033ttyvSSU&1$Bx>i0?mcD)g!7Mu4IL`@50`-Gm z#V+$ZY{c&;3(r4L`d^11ymF($kIrp)nx*VidkfD?3Kz~HOd99gzIQNS`r8k*=C-Y; zp960+AAhbhFR2rp|3J=i-E;c+n9}$W!1TPhie(Q6**oRY(9bif0X`(f7(D&v5);un zE02ZKyeT~*6I;;!}p z&pMqb9vhj>9t!FHR>HB3E)AeKL!UbhPD zM0_VtNH#M)%0;=6jNd03maWN2X)IVuZtXtx$w&b7ZQype!l((IRe7xB=buZK9R0`~ZBm zxjBDv?~mcngf8qa#-`9V@OJB-{J^UmFtx&O3?Y({rTWK6r_AP&7h+vKGE;jP^nqm& z7?4+Q%yr!|TpShu0eOTuVw*s6D~#RhOqoMG+z7}#{^fo3KvqAsc~qH zaL>f7_m?=-2T8Y;IhDt!BRW%kPO1j^{DX()!?^#Rq0vUN53nW6l=lp&p40Q6|2F_l zi7ttw{Mm!$yAyYApZKry=F*?z%5haqL}sI5=lQ8$=1JS+k6Kn4A*3RNgP#XOlW8`&KF z%J}UzqAmn+Jbso-EtMI?v8@r_Xhg`gOjz#qSM+5-?gplroBGrdSRlin&;Az zB+bUeRDK!(sj5VG73+_3dAB97OZv;lQW?jiDp{cy{7wa)yllzgzUuCgbk1Wv^qC^= ziPt+1tS2nb?O3F5TM;ZDq+&qQx+awv*%{qoMF3kRdpq^*a^1%%^1=iqCVTO?(e-tZ zs@&J*hasj3RT~haLkr>})zmjXcauM$m_Oq`zH54O?#-L8p$j?WO``Y5gE+H1yaA(N z;D>6tY_yE|KuF39&BwL-*K*_M*1YGl^3M5`nW|V|wG%YRdS1n|3 z#ZCX-y}^fGSyT5%y2!+PB&6qmD8DyYC6}vurAr%6G|_Lt{R)%LY5qME^>3L!&s(Ew zv%!Xnl+w-t*O0H-VArGIxIQBTqqQl@AYWOuvG%s>aBircUJcTEP#Md>Ncnc!cl*v5LG#`XRO4^NN&I!a}9Sy$n1 z;LafbMwDuZcQR$J8f_ZVV?FKO7i@p+uB5w1vhtOk4POmfKdkOIlKOsf)q|I625nlV zH5nB+ROS9%OIKSv!OJ9l`Oea#SRotmHtjDNC;E%2e2<|!->qk7_?FZ^I(MdU%3>hFi$2HG4_ zTnt?by*F=h-QUu-+}gH1O!oFeYK%L`n^=#bzbt|)G+v==;haQ-yjXcE`g^wqQZF~ zNo$a2>x|!2Ol6jDzfsT&xMX?T*Y{|r&3AvY@t7u$0i?ny$o3WfYc;GEx1PRVdM88a z`l|NY^2h=1_mxlg9VOWhta`Ts8RacGwgoL>y3~e$)4QmK{A1;PTrm_9j z&)O~ansV-~Rn1$~yuYCwRy}keu=eC;&5#uB6QIhE(0aiGb0|y}pOpqCDYoS0_io_k zQkS`4F=OnlH)#DX1(#<|yUsAzN_|jwNRHcZPL*y%5NHu{d{lY21f&~ocX6i_Shm^e z^~M`}9lvB;XAr+T^}XFS+Y%PC7R_*{ zuVT{CWz$*0sGTlX_shYP<-)gwA8rHI(yk$v%nv!*xIG1aHR`fpf4yI&Q}&&L3zezV zi>HU}Z?neTly3FCah+|@KLd_3SiN0_Cp+Gp@qdB~4QcR@21+#-|KZoKRF}A!*wlALYKgOV$=oDTqTTEk^oLT*9mzI~hu>QZws)A$DyV$Pgq|Ua zYdZ35E%20Ja|4wspau<7F?;8C+Gb{KX5=L{;8jC zwe>O5Rz}Ae@b$xY*ITL^8*ncgz~qI?EY`kd;(&gm^7HN%qvdIxlnR~nasR~Li7Xq` z@ujKSaGWm;F3Zkt|lr&nBwS`f6v ze-H=;fT6G^Zdl|TYD$eErt)*G32(nImarVK|obJoh zsL=EajJKb@jl3qs*ZmbIugddx4@8_ey4f9>CrVpJ%^skCHY9s$hMZ+NaMA!fs&Bf# z`iMTimMYe5nlB2EB+5gRtI`T{ptf&0z%IRd?oCCM=Gvli_u?C%P8#QE22-oC4I&?C z1Wp><3al5%Y}|IqZfU*1J!`0X{_X&XRoWP7YXQZS?I1(~#e($;eR1)aR$14Oi5q2< z&#QT_Hjn&RddU?f`NrgCRJ8agvTs$PPp>x~E~<)p2obehRlvSt{T9)Yp7KnsY&@)X zJJ=nlJU6#tYLfYiMP_^ubqT)^vU8&Sy7BR9u;_(j?^FB_UhS%XS%RlhyGko}wdM+; zNwZ_{;8^CCt4$WD>xSgj4o9X^VxFQ+$X;4(E2 zAhm#pI!i8j-)rP=E@{r0cX3abGz=f$ToX#A2p4`tb=U$m&07x$K7?$8C`~sD;QY7T z`P`4w4j%kxl>od-IxRBAJ^3J;GyC;Q zw8#vhu(SNl_mxh_168cl%3$OmTRs@DmKv`^(IM##xHXhQ;&pnJ+RJ*3E_gaWcT-F0 zAziIfilOeMzdVU=vVM8(o6Otxj<9GUcD7k$6TAm$8I+-9z1<3A#Dz!Xus8YhRn8Gz7iwV zfD?QXT&2cbw0IemnOk+lMFHVp+;OKU>fneOj(YV8E+v(`4w7TR->l3RpCkLS z{u7<5>dL^RDCwyqAF8OUa4Q?(YfAAtO#60m>(>ay{7PAgn?LPu2hXUL;zLtSep-LW ze2N{H>W4`tnk5>|^u7VK_~|1hUx0&FD==JDUb>?FV^y-m+|h zTd@UP_D;N4d>?VFUF)s?NgRSUJ0MT@I$`f~j z6?yA6x@DW9Z*?pvN%)>`V5CjT+N4ZofLC%SlR4I(C)cr?9Tt z8N)tJ$|43gu}g}D(a|bsp&RUwX7*}LOhfe!Jn9$cEG8NKD<1gZL4tDSzqMVDAl`LF zl-`$SRWt^vwAPat-S8D4_kwD~Fm7Fc`%j{^0$_KwA?NP_IKFe@4D1?qmSa!-OYaEY zqKrEXv%KYRHo2KGUCL7UXu#ZrixP-6^Q>NKN&ni!+B|H{EWObV#x zDy1A=_$w1dT~d0X11GEdX{v&1|@j*ON)*&#c%=jeE_%VhIVm)g1B%+ya1$fFo! zk4e!oN8P`SZF0Oq@>Yu>rXGz6F0=6M->h(}6#XDc`dxQYzTyeyjh8^-yo$%!BG0Pi z$f@-Tmt|sb%Our}wXY#nObL0MFx|dogQ|;cL?1_MZ*Na2H)vHK!w}0hzC`A%L$o$@ z3Rl{$>|Y>%yuRF0DDgJA?uF_pZLlSH)BOuHUDuH2T)2RKY?N(sk-mK&HnNpXf^SoHANRPPZ%@UVscabpz^~WXJ6eqP3_jm z0B=h~G=ycy=6n%VVIN#T$+R0i=ZDY2mp1ve6>?%|6W`glC+T6enh(U@@+&W_16!ig z1hr4f*8VLXK;|a{T4e8I&l}dTm%!u+Ps!;<&Vjs+q{`9B`CKt||99Wg2*d{M;g8@d zZImhJ_R^K6!n)ubw?er2@BTtgi;n^nItDXwUuB{b zn7;5M#w4jf-hBV{j-{K|`T(wD)MzVPeCX>zz}N?r3y!AhtvS2VCSB2PdJ&KM(GZ1mqz zRod~YKjo!oLDTQ&VPQE9Tj9ooIy>M*S@TIbHsS5}i}fkb*Q0+SGLZRv-R=BWp7fSC zpt;@g@95REU7!P>Md$rJ0Zy9pn4sW)KDP8R=hAFlwr{WXnJ zPX8yjNi1YMg89mCY018Ty|ZbrW{w4ld`dOe`ZBmzfTQuaPZ0g3olx%CoLb z$UiT926`U2bJrGcX{(q*ySh>A{HqD}p3`d8xrLowZoErv--*~Jmdf=0UM>6k=fZ!6 z>2B4_IT;sqNlIPmAN~(b?;X~}_rwc-t=Lfz5dl#UktRX}q((&qX%Ud#rHPc#Yl@19 zbm^T~C{jc3B+@&P-iZ);PXeSTm*4x|`^R}^_q1ov&g`=@XXbo{M!aUBmXr1i|I@81 zIn=*EQ1SL5lpgoQ7%uUa>led1Dq{`W@*7Arwy3tTR;$oA3QUxVn|nh!%Wv=X)+Wo| zva^vDMVYPd=FlY1eM@vzE#^!aye~f-+v-uRn@Lqt+BvcN7zR0!S#d>06blM0*IRQg zwKt^5o!Z^6Ff(Ibzidhg*@qrQYaSaEm?o<1%cK2>AT1%f`w|^dT}S(p9^`(oUhSy0W^m(Y$ZX zlz^kyjy1KScOVuc7`*@?{VaaNg_?-G#ZHYQ#Q+v3%=yH_0lcAvu2Bxj8 z-7sQ)x6b(Oa&p^+0KvA+((=m6zQNz$(u0od!<_He50s>xv6QUf;3nvR`|||FhX@9$ z@||Ce(;HJR6nCzSCtIqf_NS(37gHd1h2@ovS)~dT@nkK^_=rJ{XtZqJ%5jjNM5VVB zca(PXtpfA%LEx7_35iL~6sZ@}+foi%lD;B>#@*n%lJ0kC#OL?r4=zFVasKZ(BBCWYR0?rc((CzE3b#J$ zM&&PC`o%fMSJ)c#;YxPESr(z@BBpdJOPu@MfM=sSsjLn?UMdW^d5YB)(?2lxEv`=(Y$wuDoj#yaz6-nYj-%oVi}$F~%LS(>;ItCOEX@ zM7f`-E|_gg62b0>r$HCbrYNz;uWsf9P_`pX{&be{V*BeDwVwg%JBA%9gU-_qy#e<_ z2PhS(tx?<|5J$cpcw1dVK7Mjq(d}AO>M?ZIL8LcJjWrqn6;nIee;^7w;rvu{mSdn(2*pym@J1uvdo-z8%L67rCAqvQq!H6 z!Z%WfWhia%=e{*pcYBArK{P7;4GIC{489LbgBg0z0I0#_Z6o`2Tq?^3y7uc5u;z?Ty8P6`BFs>ojRPVRqn$uk-6^4`i%GSL z$gb(lhGcai^4O}0jAiw49oQUN{YzCuI+-~Ax?_?lt=A{dlw5YL`M}7u5z00=m4Li` zHR~0rN|qD8Fd#yKQMFUk$;-kW5}g12!^o3)P`mQ-)Xn158z8l+{S`>O%dq!o$Q2X_ zt2s0{`Lq5m>jt?Ze46Gizuetg@0!hXX&u6u^gx%LcxaZ zEx0Np^P}NQnE=)a2z>L%MGpSu;k`tl8gDKHhjp6R1mQ5|j8XDv5&Rb1{O}a;FVj!Y z6xI&3qj1s{`Vs#yX0R2k^Xf>!zVk!Ib>`RzXb~jYlFUvl*w!qeKk?I&dQOpMX#ggk ziNRm;>#cx>?Zn_;P~B~D6mUlAf1?!Qm`xT?Z7s7Gp?e|;c!yc&)cbL%*kXkH>>M!p zn!JJ{JEA}v9D#WPe+^k;y-!)>Bzv(;s`&5Z;ss(LZi6!LIPz-oq)0D|&Pz_h>XfMD zJDwy5Mjb!xU7O-d^X~?G!7pn-JYVxv|GYT1D=UE=>B6e~pN>QQW zi#*gHz%i@p8~o8is#KFG%4r#tWYIl&!qKCNq#v!{Xm z>UE%^)Y=*xUr3ZVYg^3*;*o$8>~7z^R1Ord>}410Q3_ z@F+OKE*}@r2_|vNZ`Q=75z-CUU93RS7#631jFXDWYluzu%wS01OuNO);!)eU zmKL-hg|8v0s4NWxLcrv}owv2ahIqe^Ye3apNaKFCIy4CwuxGbMs}ca3Q>seo1w`j5 zX74gcswErPjsFz}oW%c1KEC>q3#$SXf9`h!xnO zPsa&}!kIXMP9Xm1%!>RLeJiFMeupV11mE3Z>x-lBE!wQ&Fet`T3Q>wBirsu+mqG>N z2?)ZP4NMEwAPZof{y?bN&;p89>9oFuq``*dB5u$Vr4R{_*?Yb-bmDTqKyLy6*(W?h z3nwaw&U+tDvzGfs3e4b*JPk3X0d?jzR4b4&$6DM8W&ESN_BX!MXXhPOXNnG#@hSH^ z$E_~dK;Ian2iHW~<-Y(ZFt~GhP0yF@?psZ?(5CtM?u>b#+0ay*306p1JRTx7#14sD zBS{x_bXOaUHhjVok5&raPKNnhrJV8B2d^ce<8)BFgoov^Hub|e?4#^Md~A$B!y;!H zSLO6IcspnJ{jtkeNTH7eSW6TwVQv0)5vUM6B?)Htp22RzL9^B4u( zIooOB3;cGlClYJ1_b-CFO%J*tfI~bWULkX50rox#K&@4(6>nw{TxmZ7ef!W9cXQq< zVH4Gog(>#V*=-8N{Vt&(thm*uCnbbhaq`7)eEXPl*m# zn(5q(AOlnd^r-CDRqn%|NoCFLV>+FQ4dRlEpK1lIV|=jBM?hS>19|P$Zm5Ioo|sj^ z01(bEH?gMdsP?hrNw8DN4Dh=@hX}ujV?d5H%9JXpI*5(mxJmvcWAegBM%D07Go3hp z#p2_^Wb!G^U3Y)rYP5W|0C7)*Z@a=wclH>}WN{OGAJr(H`|IDYzrH)27Xz?054+|8V1Nb%%eX`f9B?|#Vt)Z|GPLj z9DHJ^WuC1sMo%%7P{Vme0jv&8G^BKSY^^N=m|w)&{PQnxKo;!wEA}^@ZS9VZSS{<& z<p&Om-)wF9Txs?M9LtxMjX`c|c5^oq*Fx{uoIrEIx@R-x7=z1f zDqvFSzFJ(s&RqOpFPSc9xVj3>0#}6aSR7p%*|(>uj`%l-81IBhGn~oZwYLvXzA_=F zLmI;G*Opi=s&413k#22yyqpw;bpc(Q*|Zu@4F1~-oZH%M^r{oA>9VlX4#Z@%k*J%a z?B3iC^N{n;X)Ar!tzVYP9wJmIO*)4$AJfi^WzO(l+tR*0^j*m=pa~uqqEa+@_O2Ch zvbJ%Q#B!)wu{nS3iwOUtD#s?*EJ);)yO~mok}W`SZ~0(gNvx@! z6B2$&x3WSKNGHskA9VmF?1*SR;D?KnyHfI*nH8t1-Plv)U@HC)Bc!yS(+fMC{9F0I zc|t1`vULZknT6^2Ax~li>UOSBo)>p$?$56+Q+lNsO`GP|PkTS)#l%K-M<2{Z4OCSkvG_Kk{p)R+l; z(xNn+`Vm-TQ#+2NC?6wgOXtPU{+QkLDU3jjvj}`Nay;v89MIegEHyuDWkZ+Ney`TY ztzBGPoHx!v@@eW&;gOQ!o=Ayu?ay0*pz1AcSp$UUnKqISOK(iEB$1_M<(l5E+S(Ml zxt&X4l2q9WPe6@n-~Mw8OLM#ERJO+NiMT{+Qnwpwk8vi zc_X*_g=nne|2exG8{2NW7Q2Qy8mA?nj8g1p2S==c!?@o1mA*0W<4QHN^X`|}X)}nG z=BcZ%Ou={xDtE%&mIuf65PjVKS&L!DyTMWVjf>XGQclqjhLC?^Z63Sv#N`@BEQ2qJ z9S~(wNE)1aV+oNG@4xu#p9npmtEH$IbY*H|Xa`bO?z^`95<-*oq=2BxcA-evfreb0 zI*NcBy0~Ke`wjSlO+#WG6!lf=$0F_Jd1lJUlt+xN{7-gMPm@M*?X_AuYBx>7hbO`!c7 zSxmJFt``ahkw}gU7E;P$a&gOQ9rU03OVk%%xV5B#E8$PKJnZ9Zp31ou2B+>SPv0^) z{R$Tn;x;I5121XX6xhVcyrpSD3ZB9A`|B?Mx5SJdWZ7?XTxKEYkzvYgz@6K@CG=`} z(@{!X5q%bUZLkm2bPgyE+_{mw#L0>$KB=h015`;W$2C6x0Qh!=EYoRn<3W{WSpQNu z;0ZpG2wHkJ*hLxzuBr0EJs7;Kcpvn#CQf{iHfmk|9~MCpR_jP*iZc`h1ocrslG?dG zk%D1>`c-@$>m__B+%yTuQoG$pIz}cIqzpbpi%#u->b!`_>R_gKS}$5pwsbYSYZBR@ z=$fg0f8=HJ(&=dz`gF)sCHT>89fBm28yCw5Sa>c>AyzY=*wDbyB1#~pEZl!y9ddv^ zXY#{&jYdQ*YZ07xgY6+ByKBJ_&Wpt!wzVP>#wZ}o@Ugf+WTGFtry_7RvnUyvi5Z&{ z!mh$St`c9#u-UL&BH6!RSN&~ct*4*>WZZHP1L_U_e%@C{M)n)qT!61GVY)E&XEM4F z734o_BNn3QRYWyil%C!%fCm}F5LBCAyun1G^E)*F9&p=Wr~_dJ{|qz~b|5(aKHUeR zA~WB@{F&RU@|=7&P{g4 zn(k;$G9nEGi8`m*lbj?Yp}}4DfdqZK8DP^j`D3yrSbj&y*O2Uv%2q_h7yRx#P;k_3+SB3nq)^Xso*=a|JE z9Ff7*mGPHtjB_xYFKzVBX2gSy_k*vcGCs?-k_x4gMSDdkO9;%R;3`L87={(}w*r{gm2%fq+deKjPRrhJH~J0*;5xzkwa$j|KD%@Hv2BDDXoY)>pf6N#xuoU&0PZ zLqrS3;F$ej;JtYzVKr({h9gWO3D|i#YZ(zp8yiB{U;NvLfYRO&4sXh{jxvwc=cCMI zWVCa>T>}j!tH7x2Eol=KTr|1m@dy&Wj^Y^Qi-%;@1TJ%*0vSR{bX!*N?ETRBYQ$2VwsuF*m*;`<9o|!d@ zJdH(wsmcE^3XDpkGXnOCd7UL?MiW>^3;PF@n8p3ad{%ZHMLue15=NaAFWdUsZ8H)U z1vwALLjsfr&*)bTAsN2SA%qj*Fcn{LIPl{;-%iIF{x}eChIw+$i~t(og6!;v ziR-_)%{tp0h#uQ$q#KUpSvs@q(M1m>V4_?-m#*-^U+ieGa~Q50qab~bbTbFomn?#rc-m;# z$^D?eKM$o3Z=i2wxOLrND*OJ!UgzIau6auNF^N`PAHbb_j-RwD3qG_(&id80gp?g< z$mFqUFGh(os$M)LcYN$B^AG>#^85zVGVBp#1-)2VQk@RHc?Us**Z+}GcD?=uqg_a6 z|9bKTpfJaT1Y!QZn<&*rEP(t(Ml=%r2c%xyK*$^CXyf1I0Aafqu>4V=u%(DQReyNr z6Zey~uK|TW71I0Zu)Rx1LbH}FH^w$$a76PW4l26EGc=1@{*RtA=_0dYF=e7$d}1>~ z?hsgB%2GJwa=L})erenv;v*h(Mb&VRkN&qfKqaBb(l+|8<0%aDb*Y;`Ll(pS1;L6v}_9}&0;F-LI*`D zrvf*UT2)#MXKPgK<>*Nfrs)2&PO5C$TR>TKjpRb`=}^z^YAdIH`uPX0d~Q@_VOF2R z3IK*Xp$1$FC|!PHvj8;#*ls|ylSDI4hg|O0{`XbNY5ONp8u>N!V^GWhHevQQhX#bp zv#C?|PyX_%sPEJY^d={OqJmth;B&i&sE`ls{60}UjUe!<*6GjE{K_UT(HwWE&DJ*i z6jfJQ*iDvpJG<-P0ZC~y>*L|1+YHtrpYY~tV0PDv9;@PF+aWhCb-y=l2!ujk{zWQ? zYqCR@-R&2;$%|-4K<6&YtRIn(OY>sz?&<1Sn*nL)U&1!2b&6qn7 zZ6y3H-P%O)KQ2oKKd*7%#1WYLqBrNCd?5a%%0`1A>dFM{ghVf9AC@S!$}Lr(`yJTYP;Xc{^`b*&$I|)KdV|RL^*8Pv zp5Xg_vxc_3XzXRD*iZOOMYH1!J!k$|`#gOAaWB8}=EKb^3qR1o@>3>E*UxN#YvaGX zXN@#ke`){dXV}wdlF;`VL6`1OhH1aPD$Is|eSk&K?mSs?ZehIw_TRW@}x=Uo}l}1H56r1JT}V%#;-T~O{|AX5Qa+=( zhG~1r`~ZQ6d|54^yr1Yp-{52U?;T*y8^Y+cac6g4o`|ZzJ`jYJ4(XY!ffz*)Bn6&6 z@9~l$ApVK4>;!;?ZMXeKANO?vcpxyn;FmBZ|CF(K0UE5rQd5VKBDE4#d>Vug)1V6} zn;}B0_T|aGmJsSQ(AQH8NyM`3m?&iUoW!I3Gez=Hx8PZR|BRsfO0SmrvC#sTD0h3S1Cqyk(Bg=>Gbp^tgyjq^626wy1Pe$&vA&j2ivrZ&k11m7Vo(Uml)W z#Jvkw(qNnaTc=aE`%Iq_%Fv!9pe|MbfyD$t7crJhxht%Rrd zr)j)y8|{B}7@z^=V|eb)<#oUN3#QV$%alKl{IyXSB62p5Sz@s%TyBtC?(17kF)XuPQtpk0FC%AAbRt!eC`H} zQ9JH+$g5P3@@NR29Fv4@tPxGFgm2Zkw!;S*`!BbbWFuy$)CTvkU*Lc){<-}+*y*P> zwxH|ajqWal>gJWwQRL75FcZ(o1JafhN0!2>y8mT{?3M{zZ$EW13l>bCZ!Tx0ssu3p zHbzmuOk_8CclOzSxEvRBm-0Gs*2I2+1u+kFhi-^56k?L`#ruN?oTRvRqqV<&;+YFQ z?)hlmI!wkUu}1@E{FL?OTtFWE$Mb`b$^aMnQ2{*(N**Nx{U&Jr{505P8`M`z4S$uUOmD371pUmW~EQ9Yp$L-|64B3{bTlRaPDK7T=4Y2WgW-|G=AMSbD zI=fd!O9_0V&vxb=Y-#?9ZXNHPG64nyKH?DgzV!?b?Gns@@rv&%qvNnHxrs^Y87#wY zcOCpFaW&FV==I8?E0s&nOdQ6MYesAvcuw)P&JNl~Pl*HT1sM5-GDQ=eqfiLdKuxb1#-I;U7Cwicnl?d>j75u&OJME~^f6mU3nY zz@aYuPy9(agXE)Mhim9wdi~a@NH??Z)daH1z9F5_MLoi#2)@M_txVo!a0@8LTJupZ>$T_fH|S0<;}+B7 zD~adyQgp;NyDS<8DY94GPunlrYZ$@f>n`e$?UH(!i9vyG?^)QuKsOJdsmA7{!Q%;^ zU^{!{P0DYbzpob+-F|Z1I?A+y$JlgEtnmk5asiqeZ9aSKbpk|KoHqw5D;z_HVF10-I zDEto8;ihFFm{*>01w2YA^(?vEJ?#lOoj5;pA$0tJ%IULZY;Lo0$zJYK590k7=RWVW zSm%WL2NunDXnO%U(I@@w=sGCXYc){^D-o-hJ%&=3Gx7Ozny!C-{v>zz?ic$MpYtS6 zjE#gGvEWeoDfwaMmY??lw0|9BS&FgPbbVZ$$Q~iji|C&;4Y#mr-8#HniE8Dtm$E$F z&FB)~@|a76*sOQRdOJ-U#m6R)46Fdu;AH`wvH1$Lq`H4EQy_rJ z3dr_;yoHrr{5I9O_2yXu?BLHk2{W{EW8tHr!>S*xdAeWzR{rqQeM>AqRMRY-!OeQ19O#soPs*Tm_CY+QX$M3mYk>Ruzy}tkGSzb!s{4#? zzdsknX;W6xZj=eFjD$SGcYUF__l@kxYpbu!xGy-Zm>4$~A|Li2*heL6bWht4+!o2- zbx-kViiDKQhcwrj;YT@wqJc9D)?x(rYv{wkhebW0S@>)$-mHKZ=tqkliu2tGbev9i z*~kdALbjA(vyILCm2_$dX~FLigMp(*q^iEk*{bo%#0pqupgZm1tdmBPi2I844mM$b zvCKCKTlNdzVA$Cm(Xuy1`@T_CZB%v}5%p#)N3shuJQ`(&!r=!65ni+X@AZYf7;-cS~kgvyROq!{eVOMH(snk zRhO=W!Z?-g=^bYnFH0AAi{=F3FZpS^CVyn{rn$vHY!|7J;&=Zb5qEc5z>s63YWCOB zhJijjgV7@V18Ey_Tg!qnkfOCb3CrPdLujfW4LJ3ULf=s_+ZOq-Mk}X^Jfp|3ql&4c z$%6pbPdn6i3Tnq0YwEzpvPigM>k%_IbRMQy3hJbZ6fEsDja53wN!f!6d*HK(p%;y2 zn7Q$5hv5eJqrc3wqfxw5%UinZ1dNM|#5y=FZ~W0@a>~fMJe6mtjI@mse{Xtj>n<{vdA1_J(j~ERhThAEp;Z%&7X2acLrx0Hx`Cg zI4*5NZAH<8<{fT|Lpf0~WxHsziHV;}KCyyBss(?O<&K=pGh+c;pTRXfPV}lZEB?vp zdqX)PN)dn^PKm`^J1$EyDP{Aq`L~Zy_Tc*nmsB0jkS=f)k6h#ESHM)Oj%dMkXYT~dW>YsW8C}3 z$hs)ze7DnV)mlyUdsSzV*=cJ`?eD+_MGUheop{G8zhG%avDN>a*J^Nb%fcg{g56WJ zw5)^9>W?ZgnRVr>ZU__o%naQ8sL^uO(VBzo(Gz=8CKNSlw{agTx24|1xV3f^d(&MX z-!Oip5TxVsY`la&8r~~cKH1*oj|=v)try}v{AGZL_V3CYzO=tQ!ddbMF~LRbv~GGg zoib%EnMuuh%(g{V=qlq(;&#i{8*{p!7MyOcDU&9fcttgcPnLO0vpaLkJZi?VYU{n* zd+ey#du{#!N>neBrb$|xEG-?^s*<0@oDimcsIaHL)ELm2dgop#Jc;RwRS8Iw{p11y z$Zh*;#@gFsOK^VBs%I}MWEbMJ)E(3OwLKIUqIp^OxvXbpR%VE1VqDWMa&c3Pw?`oR zg5*Gehb}ywu~%8pGx0N{&fc{R#lH>nN=n)gS=zgp)gV75#?OJ^bM5tVL^dSuls}ld zQ5=X)qwg5gVG)A|;3|K>jy>eKtlB}DFo{eT7M{MR>DI*@=*Y(nJb5E_E5Ki=`fWQI zFxZEjUEKC{D42#+$_ItoaUJ!B0Px;}Uabpo!(39;G-U@mQyr>sC2eq5%HAf<#ongy zcUjb%X2xK~e05w)ZTW2Xw#`cn-NSH@)|pg1`Edr7E;Rrn%}5%)k)ER4R?Rj59t3(R zs-n|u>oU{T5^#NF`=$J%Kvo7mjgOTd>n^syyuYv;>U1dUDo{0F&{d1BHPh?}h|ho1 zEHH1or9TXFo+wLy0SnnVYOtk!iiG53P9+>x?xgv7KJ-MDEnB|m&cxG)BsG2;l($Gu zxheH}jU;@PcXx_o-QcRJ+K5_a&e}~^OiJ|1R`Rfp6dTk!yFrQ-JW7h|IL(5{RcQd* zj74VTDhoHgUF~Gwb`aq0A(L4#EpanbOTBim-rZ22x9<1v>_NUHOCMqA@Uzt7?s-++ z5nnjwV(qEql8?R_X51NsBv|V}d2TwcLT`*BuC@CkQ!&~k0KlI6DKt<^prguL0)Sc% zvcFfslL^Rhb3%h}yj>A3R11tz;Z82V(Z;9bTuUMb&;L$PoMC+5nZ{`pq~m`RHyH*P zHuiX@STCpOTL|A7>)Z`5%KH|D*4jI&_Xn6xU6m>+2e6WzEttX^bzEDn3;%pAz^EBk zb?TR7;XC+a``*vXHy@+YaN)Hoy6P)2@@Er?r7EzUh7rxthxsg-?T)CEi$#I+elQ>C zpDYs|MCQ(Dew>aqF7Z{SCWwVXzRH*ufC#&Ou=up&#B~h&1Z%04_5;_Vq+RmoGbkfJ zGuWC`YS6&~!-tvant;QJjeOS8-NDPXsb^*`@|g^J=*Db?<2$q1Y_7Sjot^bb=4bS?*OPzLg3%N7{P0-6the8`8XZet&hvZjf_9R1GoJ$j{D|2g` z(Q`#{a1PBfc7}|)tfm3wd%j(+y%?(1m|kHonicTrpdhzvmwg6R*3<&tv|W|3!kW=* zX{~&QN)@AJU04zGu_@Fm4@H&Ca(E)A+eHT(X`j}>X9as0u)79L2Jkv9egZw8-Ua03 z6UJC=*wW>3qmvddk1$H1J27I`Xxi8mbXJcQS(D!Ew2<~2x=mTVBkcYiq3bCL<@Z%N zJgj+0$Uw<3x4v&JpUuw5xsjJy({I2vuTj-60G=x-@#UN`Y6cyGeROkctd`8#lWHHY zWHR+P+>4~9nmuWi2HLf+8Zi5c67an<-}C|awYf=UPY0yj}IYp3&fogkY&*IUXa;MW6wMwUfQ9|HWg z4eh(*oB(VArbmMcISs~nZ<^t{JUI9KXuMo@_kq6f)Gm9il$eW#6-jhinpkAU`@zukvf$KO~lBa;{c3Mrh=HCXP zR#b!F)WdUE8l}!HuYbe`Z}_2d><@1KRo!eDIY{lbkIhuX>T3<1*PS11)ZbdShhD_# zDrE@AL6wKm0_PPQZ@2;3YZ19ij_F>%ajS-_7mXel=o*votCy?Nl{wGghz|bIm|)Aa ziaf>>(^po0InZ8Wl5MT&H+-nQPkBQt*yvJiroHP>L~XRu0@9_9TRc7V_5~O=GeI_g zNIny?npTDpjunAf|C`#bUIwh)Z2YgKEVJbfm$kP0#rIRIxwlqsg)}ZW<&5HNfV_40 zrY3&(pu9{2ahU#!e=YkF@Vij?PYmXhrD%I-R z)lMS&0w@FcE+cBAU9lo<)p%u-(V@6DPPt#KCZ=C@Y75t@D>lP6Dms4CB$Dj1JW6a) zEkKn0JS1H2&neD@?PqVCjdKV)gT?_DyO5hUYrogc|2ep)84L&en|vB7?oS)YuW+T({&;Q~fG>0G>TFe)4VU z#6L)kAXNysZB$SB@tFmHm8iP2pH758>0x1@Ww{dqbLkHduqUxqX!Fr<*VO1{ifuX|62=)df}=MfvT82E~< z$$SPp9$$KF4+VUhknVm5ieLv$T)jE6SF`X}Y*Gz*zP8vGlGjpkb~<}-0IRruI6oYG zQ4EiI3VRA}-IM${$I&zRQKInOwvHS#k@m?<`!l!NsgQ=JtJOMrZ+1UE)tj`?%D(NP z&vMh-p~_vxjx;sswu4&YG7rlaCW==lWd`yO2QpsH4*SdjlDA2Veh0Q|X(s1kb(-)D z)sbK)z71(&xGn8l0`ZHP9cto^P4Pn^_t?o*Q&bc2HCym%;J@`jbJL^Kvu{;CdK&m^ zm$%&G*E9N&({STAmrS2!yIC%Y@*Ncn2c1F5RGgOKb;}npXlmGKlv@P~yL0U-Ek4y> z%qQv^I$g#$+|d@EtKQv>)vj`}0&u^hd6XNy@#XVPie@}^T*rO)2p4Re`Lc_>>pJWD z=?UlYDT3^G(J^%!%*T_X)$Oqy0)v93vg`G7^FfUqiqf9SoR|KJ?#Liq7`;PvA~OS6 zZJmh%ock)QYJ=3oQ|IYR(mgChx<3O2IDr4hK@XmGH+qNRH4L0r1f0Cit^ z#bcPb*`Uc?c*`KnAdYh$>dfGkcONa=;+!6`8$Fbn%pV#0Wb2x|mVaaDLhbj08)u;{ zKHHZq9@UwW_1=O%S-2K3OIGl7js?)b0E)V;}Sat84Uj3}+ z(AQ(nBi=1mNUY$%Y6Wkd?~|3$0X|zAZP=GHdax2Gbo@gZrgl5fn28nXl_IkUM6@nu zFubs$wS)_x$?j4XTKm$hs({#@5`#-7kT*mvGJ*^cKv#=It5d<1avHsJp35vkKJP0a z{Pr2rLfS#Rdi+Ct)M97Aort}P!>HhI7eNg?ub848b%KY|xO0wdFF&vaJDvXRzN!%z z^YuWq2O3`>XoGsOyyJOx+GSbB0nyXhGi2MLAUPa_yj^UVJXcJHdyTp~@1p58QwP$~ z`8oHVNYCW8f8zb+D=5n;WTTs=ET=Y?wE({%?ERS=-S*3Lf0U|noj!!8fhNG`2{ei^ z{WU!x?l7c+($d;j)kbBQY>~dab?u|hPnUCULmO^TN=azf@hMN@r%r>#i7BuY8CsPr zLfgXyjrOo#IIbW0I&`S8;EP4J`6#LG4|4ACrqI(Y+7gA98 zAXg2^mur27tmP&u1W>ecsMk8j7Qri~)N`gQEm|M@j035g(OP^Qz~AXwpQYBX=%0S~ z9p7KszasrVEdM?c^@{#vcGDTRscImwHS`95$F<(^Y}5Ao`b{lB#@7i`w`%9d<`!a8 zQ=yjEVi!N#=Lg3?Gos71?mrke_4PL1O%taxeP2B`SQ<6oRG2LzJ^N_-*mC4g>eox+h+!GdSNw?QBg!s>aAT+>Abt$Lj2U@o=J)zh?fZ`- z&orKFI^`bWzKix$A4C0^Dcx*%9cB+Wu+SDZkcfJ-?mQal8v$#~pwB@t6Od7#{?4LT zp5PP@-8e>e0+x$7TS0Jkx8honmMg_x+{T($clm{$N=}BycN8QB1(ztRTn2`E@0IsO zvL*x_r+ZD&e)|J^V~@obm?|y!*}5gGU#<@&2o?xpm+I||OFsb9FC66XLRw(ma{8*y z4}HV-hh~?=3-{gHb-XX9yb_k3?Gx~=umiTnT%7`G2hZdd+@g%yAL7H?bvsg8zGZ(^ z17!zNZ+d(-vl~$_GJ97t$WO#Q5@(k0liT)EbB{A-yM3yIr9MXqHur9uqK%g7WYGLX zC5gKJq}knqfxWWzx)o$3QVQz0Es#%qynXtI_HK2y%LaU8gq|6xXT;2j?9SZ3zZIa* z!kJ&AqoyMpr(;P!vB9O-f{ZU((IZ8DQu3`TJ?|yZLR8U2;M+uO`RC|zSAqs#|K7=s zFYroEGroT8)T@L;FI-mS2)A&cbR~zQQE=T2J)A)Yo}h5W>5|Xa+9x@P!uD{0&c_?w zgiOb8t_O^+;1SO`6#M*jZ}s$Vx7tbV>8E)^NVAkGu^)R~4K?^#FV3uWsqP1VI1Ut- zwBOgMby9b}YMQyEpC7puP&htS?WNYKqvnzLnApxw6e8pWnYX2y-ntv~)j%&#AD!=V ztcknCT%A0ycb~ZD&XfcueM>zbx=3SE! z<0&C@`L<-I{Du@8p`BcChx)~iqa^!Rt;%marrc5{%BSz?!kiLZ#I%l8N_6&WT;?k1 zosUjNp^a9|d9JNGCF_|q{Trh`nRzvFi8u3ViX6U<%$*-OCuy94_??!WKSp*znIWUy z(|YpbOa0B?f2!_y5|t+lE8vLW>W{eZ(p%wL@aiT&va^pj@qJ!QA-(n;@O_Hh0xWlQ zxqGUtrk^*_yaFb|$?Jl;#d%9kH-lGOTld=yq?)p>Ec=dq_ek}sOZtnMwYTC`(k@;$ zOD?CKb_nv{%=Ew+9NiJ z1pwRj`H(g^_%A%D*7?fR@x-i!M^)2RLjV7)++p`Iyt~Iea`tVm8*HRZ)E>p^tR-y# zoSd8obCkdcC@B*@79rw?2%6vu1-B3_;0uMUB*1(^_B`y}*3z^|ZrQu0x4T>>B_MPy z&Zlr@iNBEgX?W~i|GVyW`mmY+_}E65wTIUn!?kQiiW{{0hf!U`if@DR#&JsR&Ywb7 z>%@Swa)a)@XA27@E#3t8r*vB!6fGy&GzYD_iqUb&+J~-cx8X7LR>EfZo;AaB|JS$U z$a2O*kCaD6c}04!N3E>1uC9JLZ1}WK9{Pbib7VdcSrAI~09;cR3-12Z8N=G~e^r*| zRO4UcA>^Jx*jdXw78BKl44uhVy*frY6P#-!?eQ(VSYD4KBN?q^*WB%=8_3)P5+?)CqY;&G~H=R|KT4|LVm}IcTJ* z*!_>MKJC8}9skE8l|`W3z#Go+gX}nv)7#^wW42BGm0P4g;=m}&xH|N=TI{Njx6e2W zWT}8#!%n^L{rcXB-9I`a$(UWu_jFi@x59KuW~tSAwgc3>*vb zRaNSOP;#KBhDT)hn5MR1^gSdYT1WeHeA$bey~1r@Q_rzNU>%?_jRfxfmkDb`q27xS zp==4XJK{g{zP}fg?R9VQ3n0N$2$W$Q~GwL5SwsY&ve8iZ*Ar3Sl|0?J=-sC znteM5`XZna%@<7J!klAeir4jOETA0wuVI@)4%-7*5^hOC8uysq9>1h=R1%sQstL`! zK<{p)x~avl!bdUWB*>p1n^fdpaE1X>5{bK{p2hBP+Md+6 zYx}fo+jDA6+E=U@^qU{co{+Ez**kchLQ|(2uJk>_ZzWhWOEpOWg4t0)3iudrfhqzt zo)Q-+5g;UReWUanp$N-uM*pF?XGYMI2#Dw*xT-tZ+^eMW1qp!h@8b{i_5nf2y<|ac z49CWmKP}54wLOFt!4}o{SPeQyd@_t+qfVEdYIvR-bmeC`65@{ZY?^Z^+!^G&Yb7Y| z*&;a7V!F8@X%} zg&t+B(!Qd43OUV~VoPXe-WBAh?_j~JdS+;?-2 z?_TAHk~_uA#c=&TKWwK`a9lnNn@S!@RX0YdhfJ=UY?|SI0avY^nP$ths2+)t=&Bj1 zWfSHZ4jW*W*TH47@+&Fy^S<5|BL}?GvdqjGVAbq;H@CsUnu|tPvWC+2IOi-r;ovh4 zl-E?6Hx-wDAR;g<+MMLIe{C9^9Wsrmix`*}syuRCjVdHK7$3o6LDQYH*3+jV~c1ze*Axv_F-4^KULs13ndqQqA1tHic z+@v^SEd#eQ&att30`E)u6BumXX>+ouq2+vCxk6oUYTL!!Cge5iSM5px=Ropw@5K{@ zR1a>LsAW*;K3lJiAWLh6F?lhQw3G6H^>V}&c@+k<49?qUy9BHs4N6rf5bSU3SS?Utj*h zN=fY|?K#|py6wI8k51fGyxvHlNVNB+kFB7rqC{$Q5_cs_y6H$K0}_` zW_>w#FWN4@sp%df7;W$MNEZFQdNN_3$rj@8m(ynNX^k>w^!G!L3^CE)=bh?KYRgN) zV(0qaw_fRAbuX|w7`ZuEAArN#RyWPhm%Ya(4fnSZ#!jC2ZXl}3*?b#>e7KHL-SlAb zso>~cT8)=SkGcS{=)^>}PyEMz2L?C{x|E4*p60c-x8G7`(u{InMiXr^D$@71_rpI2 zTbnusx2CK{Id>xtZ+N^sAkO!+x~%;2&05UmLg{*FxY~|-N|r0DIo2e6zgt`rMy|#t z?t66`ED}$s7#1tOoj!uaMvmPxVMnO@`qNdXCxdn!Fp~vVM{j!m-8Cru>xLIf{Lw3#1hweVz2j-(YZxoh{Rvgh6$m`zFkJ^LrqlEh|g;lUHpbj#E{Qzvv=(> zyr^^U@-FqgPvH8LS~Bp?y=Qw0*W7Av`(Q(_C2@OvxV`)5d%tI*>vK`XTQ83Np5v>_ z^e)^pLk@3H4x%GGQbG3Hj&nQc_WFfxr<7+ZJ|J=a zx;E~!v)3^=r3x?sPLE?A^KfD!KJYyTMDm?0q|XLDaI1${smmXZ?wD8$LR= z#9SF>Upa8tsuQvN(6QH-&qi!uVlpyk`X|3ThR1xITn_fXp7j=YMN?_^9bA2E*~d>W zt3%>3!_RN^2w(S@^GbH68mymcYQ=uOp}Gc~UU{Rsf^i7?`0&IkmvyEq#*e?dnu+=< zef9;>!>B1t8n0ZEaV9wQXo6R!9wu`#Q1t3eVlbe8l}oB42aX+D9@135(e9Q0ibzzM z7i)`b<$pfM>n=>)J1aH5yr;8k*BADc9tQYWbWUq~T4tu|MippJiT2!2LtT?Su8eo< z4|HtZq!<1!?&H1IBdg{~mk!Q{xSxXUyo+JH3S~6x^}f@+zA-XXUGUuiJn-ZapxMvN zd;_|mubNvcBwdWC&)-3A(}jl7GSJDMEY%i_Z{V(;tn~TG49BpMonNtP_N`0@#;Zw} zOFazjSH;(y&zH>COh<1X*sq>*)OV*JJ~Pz)m|+-tMjW*~o^|iEQO$I~siQ-&z&ZAN zr;|S#ulEry@I)))oICH?jz3^7aliTTt0N<`by{Q}h{a>r^XQ8gqbJAvvfZ7|J=JdPKUelW zIoM{m_hTwoP=4;=L+`nP<_+49125LU`W#ZT@A2b1BDT(IMu_J5Sbm@P2LPZSHuCU= z8*%+Mxuna{1x`;z-zI7{eXpO-JLeqr`Q8@!#nA_y8=9*gtbJhjQ~!mcO~! zcD&xg_`w`5>9Q$yL(;L!h8d*$Z&fiR%mLOH*NZaY8qTh7wVa>z9mf)Cif;wDJ-%3R z_|d+hh{y)_s|eY|{@KTmAOF147~r?393{By!ze4w@$!A+!}Vpw?TNRO@h&$r zM0YF~d77T8tNV?+H1U00<40be=EIzW&u;e$Ti*YsC(wLyT564_-apz@#?7g|`7qG* zIrQ<7lQ*9*r^*S-Vy94d^NO_p`(5ATe7iE2zWz)&Kg8m9^w*&X$~Wl#7^dyILYKXb z=M;TY1&ub{_IERj{S3p8E#Ez5@woQp_XzTxjnSg8_{2Xq2O7c5}Oe_vd$9FvF$Ex&uuwU?Lgx%`gD zbM>zGX+>=+Cf3n(=(^PQCuZUN*sqQk2v2MMHnkI0x}!x~IG;^CUu5mlw(A{2w~Xrh z>co8pq*LSCfD`p6v;Ul^IvvGt5xf5y(-xii+*-P6V4$k^CqGRqK$k*5>c$qn-S{+P zL;M+0z=M`|=YAx~E#g)`@O5too!rt(IE~OW1l>^&wc-~ zoaeLYvODekmW`X7CU(%4gx)Q6r+RUEd%76L77GWeZ-goejTA3eK|eesecBcfI%Hd6 z!dTrIT}Y2UQR74i=vaU5*YF#k5)11)_NAl8e^d_cCZ5urugMwsc6r<6v0ujq<`Z>4 z^$oU&F^%=%Yl#t=othb19q21W(S1K~YrD{6YWn+bqltGLCVPX!H(^+-a&qsxpHZ*8 z8GWvfYSXnrnY?gA`kNWbLQiL#@pYAe~jGNAN$aKd&t`V;Eqw79=TQTy1J$1 z5KZ??-bCEUy8l+tK-)EYiJsz!m?vA@T+TkMs$XM@jZ4(ew{k6V@;e;yzNxF?@rPgI z&kmK2=KMNZs?|}vE3%QZv^``Kx<+8)c4n=ilgp_nT>i653vSu`5Sp5;xWrj%lx6B1 zW7tz`_V)4E=@U*KdiMm+-(@@G?%#ZA;?wrlsVf&HKl@p(7td@p;GaL(fc12|m7K87 z|Moh*^Zd2jX0KpxFi&D&(aswwZj<&ut$ok*Kf9BX8+h(w3)yeWA1Czr;~haG7}MYC zW6Mio^gkWBT9Xtiw}4|+is8LPR@7zk#D9uj?B0;~k6&+|=J9l5w`IqRzCHU|1#%Yg ze#q-z9BqomihNm54StDX@pGGQx!w1?>u}4h?@d(l(7F86y439-?zUG^Gge8#Z)flR zb|Y?j`8(S4z2`x@>M8h$ugyu{$vwF#2S%S=-`d9!K8?vGIiFBn{~1$M`o8*N{s~%4 zz;gXxG{5mb<8!|*F3x-R(J!U3c28q2sW^B(;gsXWgAF}}t&2EuFG839det&@G`gq} zX{O5gdud4C-boi=kzPqUP zV;f&X@16AXZ1F-iZ@Ydfx@;ivzSWABucaQND=$6!bhD;o`oim|TLb-@N>VnxKTU8Y zd!@Y2&(-IpaE?8HG3_&o+^>hxv#`4&f3AV+e1iL`Ljj|v9inocppWu`HBaQ;c? z!7nLD^O{osbMse15(mpIUM_~9z+ot+5$EKK_N5Q#f1)OTJdPe#l3$KwaLjwnI6rov z3hvF>4B!?MKSe!JJmJK%Us}@JuTP$o6#izvpkJWSul)q&qjaA?Z0`VX`uyQ;py4NF z*lV+Q2a8ut-EY>w^Uv3}Ot3_GCIou!Z?fa> zaJcI`lZUbukmK18HyvAk^ddFT>`rRaM%SE;&kkUC8&&bq{T<6kjJ|7m~ih3U{$*Kj@B53cgR4{xt*_W$JW?iX@7GJ?Dz zZ*_1t9r2`SlTa&XqE5_G->2rKX(ljB# ziNZ_v6|LjM;myCmmorlAFIOb_)7QwX-h5x5-il7EI&&yq-fI;V*XvZB!WXRszC&#N7To zKN180O!&7xAK1O)e+i`7|D(wMi}&+@fA9kS&C>yR75{cq{12ZVAY9kK!i{(OyZJ2; zOyzqRAe> z*vg@jNcD0>@>(e&CQsp`KHBY>7e`>tj8~)~`aO*>l~`k${iA&0`!7f>OeK1)%tyUh z7~l+_a5%5wU=lcOGC!7?9lh>)O48n4Jl^fxU~S_%o%Cx9Pt<48kH zWrER!la=yurAO|Z2H5>DtC7mA%i(L@ zWDCRX`qyllF86OlcZrS9-*i^5;tk)#REke@-?fqcw_Y+A$7Ai5RyM`I&Jl92UluJ3 z-e~Mug^{m8@^Ci`3gP1M-2 z1ktr#&1$!P;9r2D>|yr&aI z>+Yk@9VcH;(x1RACJ%2z!qQs&1nLc8tbHn@Zo8J9%_Cp=u@6Ej)q(x|EGOWFCAY_ zy@u77ce#J@N_IH}6Ao%gt_vX_hZ7D|*syJ8pc582i|!c~ZWvDhl+w?=uJCq{LzKalS+mD!>?0Wy4Jq(%w1)g3$Vd1OB>L8Kc(%J-v5gGgwXhMab;fE>S z=g$&Y%3^WSfW}0shTKP;Gal;&n@CxNT+^@+4SSplv$2@4%*XoheT&tnyS?9sKS-$r z3Ji1_@EoI0?UtNyXn4u$4nfC6!z-bFzpD|M@aLdngXp;=T}V!cL4JYy(K^W1>xh2k zGMNv5Nj-f}v3Sn_Xd?B7()5}C8O2Iv>>*XcYS_fZDh2-_u*`DIMu{g>JZX;kolEa? z^x@YPVYESDFHWIpyK+Fq3TX<*=}-V z2RdsOn-N+mKh*6lLq1YejF1V;psJHs?Y zHSBy}X-;Rpg*c!%UkH1wKpsN$%k{@pCTapL=v*u>FoLfk<3?8kmi~iJm|hKV*&&#m zlwiSAVi(2sWNeip{uyL0Lk5zSaO^{<DGjc=zZS2Q!ZPSo zu@gJk#eqQH`QAm#{m^yq?|t!A?LJty)ZR91rQA<(=X%RJQNfme<%?Q(pzZK5 zymc4im%|75;ZG{9o4(A7TvgbpcXH5ITD;(-W9rJGq~gq$6+8^632lRB(%(JGzx=+y zDKcgKCnp;}*)pEZ5dRmwZYCDSqnr;{G-Y2pn}}5GlF6x~@!*vzSD`b{;u?%$oPT(3 z4Rj(&h|dgFylj7-uaa7dx_e7N?VztJAO2$Dvi;zG&!tVB{h>F>K_~bdc%E8Pz(!a& zVaL}#IpQi?FPXKY8%exeiCzTks?8ei>hA5&VfXQuogP+%@51);ry;NLLTpycid6I5 zP%841%BJ(A54ZWrC+Q8f|D8El$y|xCbf}6V^wmXA2MF+&6Lha$6UR#u)&b4`5dk-m zXRWL_kuQ@6bW|*Kt30I@?IiDH zK9ww{(jQwgI8Mo77TDU!vV0_Tr8+I#N1QLgts~IM#iEa?xyrsND`bD;P0`VPjkQex zt?^c>5L&Z_{KZ5GGBVas3i}w|`t#V1_w-6t01!YFyWa2l>Ksoa(<$asB3i(>S zsk`aMrMFp<4ubFNOyTVVG3m+&6>)^=xbE#Thg#<}i^>LLcls_E+K$-*cJI_vk?1EC z)s*S;fHkZb_2)SZ@Pj+wGC%t3Ue%YlcakiuEif*-+^v)k+&ieJZAuiGR8=U_Adf!!_+0sRI8z@eV%x~3f>-rl_wg(BB; zP{bUIHC3C0jisL<{Pt`;9y!-KjN_Y}W1*XLxAMJc7mUua@XbbB`QfxdyZ+{iq~%-r z&Mb{mu}a2YGO>Q?kB|E6KBIGTYLk#NU}kd%b4;t`H|A4m#9Y{j+XWVOaBe#Qmu|;w z<|ZwTX%2e7uD>}U+4%ws@)BW7X>Mp-;KGVEVDzHPkT*S!owBH&#Y;*N)^7@y+?7A= zv~JdQr2aW+{amns=ovVAm5E1BFAL6e0I*%b92_EuE4>iW}jpgtL z42`G?I%O!THV$qMs7!*1De^sd7m74`CpaaHusv%|i|`Ra_{lbQO8$JoMjqbi3R*a=N~b`UsT={TkT1t{(@T)mG_+Wb{n#6s6vhOzsMd#2y_LXj=bgX#EE@rZuX* z*SUfyfA51Y*?2f|EN6VoPDgsYOKmvYQk()QRK)=(W~Z!O5Ia?j0+k;D#{hWnt(;p$ z&>UVi(ORY$wo;Z^;~R2bwmqut@Yp2q?B}c?o@R9-_ob2+2C=94IWMWDksq5MrmnOG zp=(c+??)~@5Lv#Ox=R$#_qL9&ux`z^9C;%5Orckp zr$Y?Xdn+FfH(}Sm*@+C|{7Tp*Qtdv4ORc7Yl?SD-e7-tO^LKt{U##_Zzo_(-3LYKA z!%SQi-h}^32(F{A~INPf+SlT`-%wEv!73*+79Sk%tl@qskqu-AGc?bQK7 z1EgdBM}HHRc2o1i_4z}_&4$&~>EX_j!jizlkxuIedwTZHuBTj~zM@bi6YplM4Mw7N zCz^!-LF2L;uBR3hHPeF!l)w635Z%v+=0I>IEkxIPwVW5Mg1eYtpGBEEQlzHeDv}v* ztec)DTw0b~>wf%{%M_b>nmQ+_u^|60iWwMN%={Lg-f5`_^d`jK>s;5YOS8xw#c{O~ zoq5PDVKqDa0WEb69v$DO82^NrcPw*^yORv1Ep04FeqPrJYC_#EVM=Nt47MAuky+;D zxr_jIXmxmvalFb78~86J;h~;8l!7i&n=*fRpPD&n8$vQCi+AzwN_0zVmb%tfbf!2> z)V{xw%nNX9wh&bt1-mVfqZsMd4!)fbhWs@kF{i3luqd#AE=cRl1s#Bqz$F}3=1d8{ z`SRUMpxBHYI&{KPZ_eV@+LvML;yNNF5C~EW8*AixUUK?dl-1bKs<=5$@thuE$eZmF zl0Fo4gXdZ(2_itMO`aj;IQ4mgsVKAG;+rO|HE@)2@*1~ky$M{t>W=ag)>-vtcqwa- zXP(K#pcc#<6A6UHmVnVfCI&h0s-cz$wi#YU?sT<3!KYe#bBuXqS<3tyhj|@u^AA{t zG@CW?7(ZTFH<+oGN)xRPThPjHz)T27;0a`)4(e8V6ed~AwFqXBb3^4kQzqV}9p`jC zq_g=~3T`$6HXX@&ia9b0Cdt+lLVL}QBt0t{FyJ;EQrGQD2E;25?M8y+D6Q(0fK&WN z>mJA<#LL$F(BBWtL()SNIZ}xxl+z6ns22*cwr>`_SRwNS6mk)RQ~j}WZs7}Ko<{~^ z?jgPBW#W&LS!p$W6=_jE<#!X3wX0Yhtw?c`s@J`dpZGHm1 zIR`)!PB3ZPQgj|7lvOMUb=F8t51w=%y&m^P=Ab!lAvlQR(a}Oll0e*{ed?4APqbff^-7Y@29UJ* zX=VBo*t}BO*Kzd`A^q#Q0A?mS@Fa|-7sSCuKOO!kMDoIR$c`z}U8t?i-~7h(B=OHs zrjBj;72c{IAN-_%vVA}v2Pi;@7181$g8l(ZV)|lVK2p~hTjJ_cf-a;%7v1CEoJ!OG z-E@+1Qhj~^;@IwKCgA=khLmuoBfFcjW$jv|N$mkM5oa(yYZ7H7imAk~FQQb(21>6S zG;(Y&x98QybUT?;-@CGOaBhceu8}gGQybK#(vfmLqeMyHI;xPM8HgkJOS#JdwHYqQ zmxQqcnJGw=)ns4^-)!yoSHIDCEmBIAV08$tg|T1V@PO_X)DoJwoJIw_ zbkhv}3ToPs^SQBC!r@f|YGoyr1;Qy^`c*JWYj6UUisIN%Le-fq z`M+R1>`l?hvg+w4YPOqG0S}|Eiv0*9>2ZhmN-HQ8?&s)qof7shPfDZl)R6}sq~sbw z+s~{r`Ggb6075R4%?(lAF0@XPrYtJw%68)Cz;mG;2bfYl5etV6f84_IlM67Ps>OZf zkp5KEMCmuI^E?+#*aB}TlL5t6WK<4H)x^xikaFhk{}G>sF;glw(US;bP0m`PnjqLs zD~ii60LonIPqrce=Sh1sSn;JCrQ%W$FjUXfeKnju`-eHw+^y6c!(^!>Hlm0*;IlJ+FW}@7JHB%a zxUXp(Cb#*mK~w{WPN0-Va+h-~Y0;QOvkR?J$CR5y?{N-9?lONWj21svHA2^{XJ}Dq z3<1=ULOa13WZ+()Os_gE4Lka{r92ypnmHkpn=#2*GK3Gt(GL025o(#JBM;Jf5ql6u z0-ia};W5`SL52;Z<3dK2a?1Ig6yp z>*zRFzEkys6xztp+hWKIE`gSWSvHNcNOTBEi$_+bB-(@kp306n=C<9`@$RH{CUfNd zHXugQ+y*iy7g;u2I8u_T%?@WzR8;J*fcB-vdV1P>x$jI$E_;$uS0QpRP?_Dz62h0ry7%Gj4SYb_2!}Ilt@={fhnE(8K|1 z>?5^GZw@o(!Fb#&ra7Ptr&DjLlAu%PBtsO}>XWw`_FKMW;mKHgHRx;wwhwt)X6A_T zVXEzwQX>G!Yl`=pVS)YG@aiII#RHFzZjUq6YdDmWr?JP5VsNvD*dwGq>yXUJTCrhw z>}d;7!rRv|&%UTaO6J&`i1LjpRA{wAM-(ZJ5(a2vNG}eNgua{=Jk^a^Qgu+~i&}N` zKBn#jiU=Hn3^LL@!AEC;fbeH|!ZyA!QEEX(acmiApp5u5h zwub^)Q&yAs6Ov@WVDE#<)>F(l0|p$wkf1AP3bEk>5X)=~022TC%25}GW|P3WJ;N~8 z@kA@exgNn8cu&tv6Ziue130|lAm-fwsa&@t0*mdpkSyR)Z)xJdjhvEN^gG*W_sID=m(uF`91-IiYHvH&^tG&5=K)cj?c zv$wQFCx~r4NWFrx4?t5-lkk(jK1LOQ84)FuzZ!jKU_dz0{RUzgxR-Eh8e_n*8FeKi z>ODYq5P3yQ8UF@lX_@T{1l#g89&J~oo0>HPgY?i<`;mZJPCUj2JXT7NdI8F<8N#gz z@lsP&Zz-p%3r52BZeYP?~N?V64m=W*(3c!J%OMr?L`tkLu@#0^kvmT&E^*1eop-(Zf^N7?*JfU`o3 znQYK|O|yj@D78?qk64gWgUh;(9dubk*~P?^pl-`;5zR(4vYC9)ex^Yus25Y*bQT7Y z3wARxu=z}1R4YWzhgMTqAfNCI6=)(B9=@tfzM&C90Kb6fi`PB!NOa((?o5nCDs_QC z=6x=IjHzC()C%GpD5BwmwFCRGC_~585K_Vdb%S0keiB9B3$*@3TNHaDOXT}#RZsI9 z`NDIY=}8~;O_V7Ob6XW`M{My8mC_Y1**&N`<{)E zz;p~#X+5Ru{xeH|(7p$=hXjry??cBAztrQW>4zJMNcn-;4k*!!dWPEo)R9U9{Cslc z{FVVTN6HYRNOc8Bg4#pPvU~*_h&2acOsV#~=_ghuWeaJcn6*s`(G7|emr^_jp}ncT zfKB2)W7-EA&Ot~ri~dHZql5l#JWPo!u404Ob3ii?Qlzp5d|vi{5FgkBPxe}((nvXV zC>)MnBE{}Ys-<__jB`1puGnwMQ-u6gmiUymvw)qq90&TEls|!-h0Uhb)RsZ+ONF+Y z!{gVA4{|mEPF`iH%w=*leU6YMp#JdPYK0Moq_XFvmwXM+2e=$UepNRdP=yP)SB2`e z%>;S%kB+B&hZ&HFy|%ePUM(f-=2NbaK46&r!??McCs>tL2>u0%1MXMvQMc|s>gm|5 zd-ZA|4KtKc2$5gNc!7e7uhgyKZ8Aa+cLSM?ch%%W@%|V@h4kVxZ9;pTsM3RE< ztKjZla4IHh%ONH{8pyPI4-OlPq6lDg-8rY}<3Vh5@w1_pr!Zcx(KH66)MT*xL;8pJ zpnD&w**sSLaMNm7b^8y;KUB<&H8BY?Hs$3O!pawZX8x=YWly3wEkdq_&^`nQdUqdt zAFzewm{wHRU=+TokzVfU131m}xxs`Q;0Cm{JoAheNM9JLeXt~a8x{paVDF&r$_0Pc zP{3l&q+k`Pem}eiBOTySc9H&OHUuWOwFQ((AS;(Zqc?XBxHib&P4%r1L0!(AeT zhGYQ_yqY>xQQ6wjH;kHk#vF0gsL20lNTt0NI)!ASk$%z+Am>+(tjXsZ%-ZY3W|u9& zH6e1aKr~DS?kp<_c!Eswf6(du=V}}7P*#iH*vzH(Q>f|91M+yvkFPV(YN{jM^)P)g zORt2!ls4oIG#z0iwq7aMdNwD^rM91M$=5P~wuOux2AiK;aiTjk@OPc^Cu%Vl$ln<(lv2vEYUNSu9*X zDiQo49nCQh$)2lC-p0hwq27VikwyZN%UMTnBti9KvDaknuI1=wZDyQ%U63fJ2iPRXPq-YEV*rNiCl#C_Ey$;Q zjMCvt!1K7Kr0P}JH50XvCXb*)SuPYil3qz9o*T0krBO{WA!$d!o}>o#h5vRfi~6eG zGBDy=PtTvJ3Sg>r$EZh03!{?!tF*2oeXp)U+?LRpSd8%b-Kv975(HOWAy*u-7GfP!2YqKOC-;RlZTulV`z?RZx%mWQs z2J*?;j`-kPz+D9a!j4=fe$wea#`1A9^Z={kHKZgmHcP~Atkw%j?`cJ;YU(@uC|lqO z&J!M>K+MJ|!>HH?slOXHBtGJluq%?l296Y#!&4+3w+1o(Uh}H-&SV>MoE-EOi^42X zDT+kNMJOlwts_8z;o%+l{t#(V$?&SdS0tw{eCX%+Gq=QjtTp|^4uiL{$24osn}w+E zqtdy3dtpzIKr8G(H$ErfEArx~8m`nVY0v}IV(YxFBE7C+RZFHKW#v0rSe^zO+oA9YGSD$T75LporlO!dvLj`EKznm z(nR!|JxuSzmvsoDELFX?^0R)6+OddDKU>JCu~Qtqkm+U9z=f&mrJO0$*kMk(CdVNQ zgI6$g(V#6FhOVF;JEPgLO@bqe%1h+&!Yk zu?OMkrDMYmMAsEc`7XQcV&$uZzWge}JS`1n0FQ zh+|&$SBk*UL~y@+>qPCGMSsA31j@oO#$LIzpJRcVZu-Wzou&TdxDk=TOr_P;j-8AC^RV(548Sb@i~BDe7OxIB&L=)2UIIwMmY_bS>p7&7zOUX z*t0OWzPm@sq%u#nF$8M)+jYqJLix}2itQw^wL)q$fs!5&RyY#5Cwm_OWQ{crTQ{4~ zW)A!|r)xCj>jDi6@`H*F6%vqcLVpE)B{nAo{;q_3ZElL9??g?-1Mz_pT<%;Al+?G4 zXo8SS7M5wzWt1z-QfuA}@e)wDm>_J2&~~bQHbBwiNVkiUb_xSYI^1e&Og7*-blg2U zh-GU4Cq()20;hb5(iNTg66PTex#K6TZGfsmz2r0_mUh$__4{)?_n|N9qldjG1XEr_ zo65zI47eV%e1~SutD;Akr0Qc+PR&3LDYYAirD1F1SB^P71}Yd{`web=-5gH8HckL? zq_!x(iC4;&I8sA<)~F*m)*)HW4q1~`x(PM5p$O)yZWL!-+^01@Zuv@0IxKf?BN#G#|o!G5(!rb;hj^#^g$f1es z#KFBhpG>U=0HGd(Xn7tNj0O{m|eQIRIEbzsmno7e9 z^0|F~`>buDPL(a}g(1>fz#%JF&vRU_!U8=y!T>JjHp+m?EeVEB&<|n*xkp$z+6lV@ zNO2^UfFiUsRXilKHw~UHN8|C4+^_WzVpC9J$9hRTOf`H1@i%`^*-=&!HRLF*6`v`e6N^o*Ceeo750E~^tAY^))5F&>QuzDs zTRzA`Km#`-pRB)nmLmkZd(#+qRTJe1yh#Tuan}IKTrO=Ht@#ks)f;FNRpcO1(;f;A z-{1}R5Kz{Is;2K>PDh!FB=?)5@!y=+vcInHx$2d&fgQ4*uHO zptp2i!mUtGO{Dq1?`erK8dkcFpYVGGTI!Zr*Q> zlOv8D2xE#PU+qXr|H_U;)f>uK8H$>0Wn0(PVlHyOD%uv3Q6z~{`ZYXMxY>#`4@KL7 zv{9*^JP0^uTk2~kyYJWenVDuY%AW*F64X3*ucd}}-mX;sHdT{tRNIB3(cA71kco?l zKeH~>AaGkT1*cvdRWYqQ?1O z$-MYF{}SR)#xmuj(Pg}7-*iyh_aB|%%R~#sX@}UG;mP1`efh70>@d_aq6VIR%UpIe z&Ug?+%cx`bCH0Ay5J8X(FRm|e%BdMnf)X_#nVC?Zm`{k7X9a-o#|CLFt*xUW|SS z>V%ON%JqJnhC^s+>v_)mLi1)dKG-ydC>{CcqD&tcQ7d6o6p2`SHxhQn*jyv3ZB6a` z^6my58PYLn0dX%C!R#(d8T5evp z@&~1r)@k15$7I|scW}M+lj|BD=PXKk(_#mSsE9h_+TVeoOZ2+dGr6V;twi(X>O0nk zwB0C6`L@i9k`5E5*wj;7daiAL(oURyXsB?630;8R*1qk_ zB%xxk^&8d)Oe?(Lse?XIasIavGYTv@FdFOFT0tQG(DGQ9bk>qLqnn5j%8$i;TsR)S ze`U>2lZg_5N2l-43yBNt+fA7EW-A3BUmh3AU&nqQ&>x0ad7{kCe;nUL zMGW*JfL%R%+hZY^ho3|HqFUpvWO4L9`9q*iT*@f^-z(-7?CBqRB?9}@+jymUXF&6y~l zX$^ckmA#pyDZil^wbycycY7|=o48P%@v5%C6236zQ|m8V60G-EA4GnG$_AtKJc@tf z72cJ2OvfG+@=jTtqhs>Z@4>E6lg z)yxlwaa*|F8R$wfdjm-d{cBj7n8MQ9d^f#mP*hv4QCGV@Anub9btYqC`>u_sg}}Cj z*fvI)jHWxY*O4Ck#f_in(qzL)C$`MWqbfmQz(?z%o?0-}T2f8>_Vg`q?Df$w)FR^N zvVi-FyzErKip|Z()0BXQvuiq?;CkR!yQFDF5t9eIzHjV=!2y@~72yApMJv{HG?U7< zLKzI!Tgozu*llA4WDQxyqX?19D9C&f-Yqg5W!zi6E!pe=1g__w_7(8M%Xi7JCFUUe zcHU7UAK=gyUgVB_Jc^P45Q3AJ7taCpIlJ;tn zfKY%xv@6-$4#q7=)j7ycMG3Wu`0$K%fL9_JiP9=E+WZRL+s+9V!xNo_>99-#xCVI0 zI%yG6ORO*+OL7=(=WkzbuHhX^O_FTyWH~lM%$vO8MrsJ*C?vepU2WEhUNk|?-yyp+ zuEuuqmlPJU*+r}KiwFonZBq5PoCK?a-AS2s>?9=wC!NKSS=~IP^MvN@2Ua5Sz?}5k%h_}CBkr> zi@G>3+9+Ro8@1w!u&-YiSj^lT~}BHN4w`Q7Z;7<&E}T?gX}P zz2N8KJ65iS;PtmdE+IypN<0=I4PToSdI6oP#a&)()XumiiVZuDM*=Wzjh>N2>NEiH z#yg0bDrj09>n&sRR&=?N^*P`!sw+ZUgsZ^yB^M*%Bn?sKFm9VYuXLLXu!Ux$*?4oD zl3isrV2Eya@)9L79XiO_9+GoDWeer)PMYo}Qc#py52MPPZ4QZBXf8J!ogYzb=|sYl zExOfvN1fKV>Ys7hGmQ(!^FI4PQqB9t4^!9;R&mH#O&Vflqfx5)3CNyl&EuJcev&Ib z9vO8)SX&_8{a;fEQMRyOxP=Z;y%ykl=hW&~2|7 zz}7;oh2i56@?xH0mn+iffs5U7fj%Jx1n45aJr($x8XmXe0%n1{Jz(cjb4~j<1rVgs zcke!^xpL8%u7Auea~$kCJF3HK;J|4_}p}V-DXRr>{VKXkW9z-6!s= zL+vmf$Z0NJ8%?AIeBcyjnx?3IDnb6QiU&2wM(u%JRJLR-5f8h*%}l6eKVaw03Ceio zr3%9<3=8XA^Y%_-yy9N^#%U?`XSw)VF6i*jP!3b1!@uOzKJn(_j-RXZ>umGWinzYC zw)|a!9bKM+Lq;t}<7^a%PdOHuC&IWjX$aR=<1u}*$=ztXQo(T}tRA3{H-uknVT!}H z<#-RtGo2PNAiQ0(m<@`7^Wd>VTfqm24WZB-QyK zJC6v<4X}clYq(HqcCR2V@J1AcXdun@pdfcJKw{F-7AYC>$poC;HNbZBmczBrg!@9$ZL<1q&9yI~AhW3saFN*vsL%mfBJ6krFN4 zwS}Oz1CEWlsXN}VHBdgc%+rPo06J)Cb?p1vNdgCBz^(7|PIg7wu;Fk+S_U;6P=dTl zfbljvR~@A7C6~X*^;3PUExTISwux|VRpo+Nc9pHR{}}17W)yFL2{rI-+a>Gw05NhS zau$MIb=$5HLR`RA-1~6jz7uop?Ot|=t;VzlXm130FbM@x5Et#Wivj|RugPq9wj#}$ zy;$*Z(I+4Ov_}A&tIwg95}#7U9H`yaWn)Dn=K%{UGJcls+4kUAmx(KR4cih$0!uaQ zHCL0^6Jf zD9l{DPPY?DGBq#DoD=*s9?+U?+bGbv^SL8Qa_Rb3zypjFE)L*fra?Lj3u;lbi-SQqAaQc)h`xKGKn(xe`Lu z^5!t?uCDCXG}jyPP&C(O&R|e7onjZ@YxsQ+HrLJ^VCwpjLU*>!(H-AL!CWRr&%(K&kv|G(?_*M*Jz@dFiB{ zd_yiVr%7|AHr-~aCzx7=@u?>lGPWTl*Y~hiHUbYAyKs_G634FXlIyxdxwG_{7C3~w zv0V-nI&~1AnDpU0i3&A=P`EYNin1{vh1fGAq33TUQ}EFQX+jU&!IwDnVW6P`?ej zEF2zS&87L{j#ewT)V-yHAu@Vc8#s4)`Ed}^{F!Zkk93T5Bu+0C{w851)}l`w14sr{F{*mo2Qr6ib74D^*-Ywc{*}(* zl|0Qn#Hz*w&u;Oau3WSImH{?cHq*JUW{C{42ON{t>a-1slGrhA^ps({fFy=Aauj&M z1FFcgRp-oVM6uGE{n!l!Kp3;AESWnrYdM;(3G>Oj_-VeP4IwyLsM`1DipQ+nbu=^6 zrqCg|0O3@KMQTi-ZMlm3l`VybT*<3(gU-H+$DJqkyX zLmK-DQfBL2ElER`aioTA?aUxE%Xcje6YnA6tpYC87&>W%~p0 zIEcJy=Hz{(qWjeUSUT&dsM=_ae~N$%A|Eh-0)nV?j0i|G($Wo51JWTaF~p!CB8_wp zox;%Fh?I19cMr|Xz&+o+_dnJw)|xZ#+3()J=Q;1$yG?9)S$G?OXQ^Y67y@U1mbz5om z;hqLkP;J|g3YF-?2nT;(?%2N#&h&J60-X?5n$!n`Zxw5}B>`v_#8(L@S$jnYk%a?P z+H=x#hy3X11W7!9eg{A_9>V|4GN+)g|N0XwL9WWT7NYG_#ZC!9JRn5< zMYsd8#u8Ac)v5P)ZwyK4?^z)NutpJkX2X!J?uYZlgII=rSNu|_p395w*8fs)b{o}y zT=vvy8{Erj6ucK<$SSl&$blc>Ujmh>^)$cs9=GkkjRp0V?bPa5uG&?r$)^aM&Pt7+ywfzG=Tfl@aUqEaLSmwo{$bp zi^j9meGV0Z8Ur2!&SQNGmU&o4jPeIno;k<&;fZ~|nD!BG z6BG+0gh}Y}<9T9lQG8sx*z&q>8KIy%bpNNU7ik;4$)3bC9%6nJxc1v9fS~P(p`1ea zk4av%9O>>@DB@1jQh z|DV%>Pa1#+X}djEq$aowFarQ(HyV(X1gQiDce3y%5auhUO&##L?nRgbsuBNj3o8KB zCocdWhwlH-MgT&r;*SRbDquD>fm}NeQ1$R1w-3>KKfSm|*v^bSlxcgmEC@Jx_X(H2 zApl%B4q4|EeDt^#AJ-=DL~h9Q2m?sVJ?&{iy8A&(-&+9Q0MU68-hB0L{|Z!-pmwe! zNvIPj^?^VOA+F82>^ym$%;_N=+}H&y`cUOd00Th7n6`ar^h^*d0}y!kRRY$Q)c`LI zkdv)t-EzYKCdmPE`hg&pXB3b0%gi3|HqfE17pK#%=GvHpaB^|&k&+uc}3D)@+= zpu2705#qS*KY-MDWpE@P;V%V51L(2KRXAREyA6OC%@Coi4%KI#|I*zf(`sW(|Kd(|2f+jx1w*nSpnWC2~unaI==?DdGGJq3s{~H?yA044* z0PgXWSpc~ToO&<6eKNnygKVGhKk%x2vT-lMKL9BKEjt(L%YLxc4t!BvIT%PS{|m?_ z(k{H%`R@QAKbfWp!1`wc`kbVuC5nzy4$>$@iB$sd3|*Ya_lY6`{zEwO`OzQ$-NN_~tdgwPf14l` zKfi5-ZI~3O4Sc5D!?bfR_aOVifftnh~F{5rv##pYMP=`R;)xH zr~sY`F`}CS_)&oSq?ftA?7&Lu#2|Rzl31PoKMyIDz^YBTQ3}d13T&58WM_DCZ8lDz zzu0KJ&`cl}=m1A{ZQ1GJ4Pflf7xf4crP2uKs3{iX>&(SN~y!L;cJtv`F{4TvlgPo{ z-}F7A3o%w&AqTx6J7M6xabEOlv29%YK3Sc{` zR#ePD%qeA8E9INp!=91bTRfLZ_tJyB{thML%8=J?mQ6obSOU*db}*Fh@0>yyWElPV zWNv;w8$FnvpJ{fN!i13=&WeY z+!8ck`0E=eiOh0@oL&p`G^Mw@7ghPs3rbu>Qz00s_z}_i(oy|RHCn)K@#22uoVp3P zdr=flt&Vj8`3=Q*EU3l^SY2G8Rc6&;pzfcdaD3f2ItrOs1v%J498?~7urt>$qBkRv zp$!?^sT=+2LEfdBIh?`*xgA>{NN$!Qx;T9P`aWC=j$X{W>IRDs#9S^!_RNhhFs;vY zSjN1L{P%*KXzcpYMCbG;n4K~5ThnGS9Xv=K`vjDxD}*-H#g#SjyIM-Y;MR=2DY75w z13{KKl*zb=wdBnein{*9f>xLMf>n!~WUj38vJgHej1q`qIZ_XSO08Ur!cn+H(IR;fGS7*K`<)c# z!r@bbX!q85iENEd0wWx$n+zjwEGV zP=Yle)v&xEV{Gi_-m>~{_Ir8X+-#a;8!~BAKa=KNL0Eq^wA*ZT&p$`?=PunH9gO8W zyBml^aun|$=7o4k28w0GA9Lq^DSxYiLzomPu_Un^-3x(AFs89MS`)%WHoFh^Yvdn6 z#NQK9hrl+}tAA6tjETOGu8u*NMp4&|{1ia0GJ?Dpw|flS*GT*O&ru>|LeftkvHhF$ zwMj5{>LJ`O*E6I857;wbn*JoXFCuGEHuiRoP#yOTk{Tf{%&E~#rfRR-w%#C2y}w?* zl^uU1*PD-bssu90Ohou{i+vn*Cpi-|yYrb%z%wR$i9AG(^;b*p$kBKT;zMh7_Ri(U z76j$Rm$Bl50_2}lemYhBF&2Kq!Q+^8#z?7Qscj*plOZ;rxcseeDI3>@a33Mn%7gVI#y4QtuFAGt@Y!R zkdC96{x;TRcEAY$SptansdLc6T-eksUxss0l zO|aCUT6*dwTY4@K^Qk|PoGi%{;J?(d-%^LUB2uMT5l;eNIy$dcEuu9yOw6B45T8EC zWz2`F4laQGj;U7WI)0w2_Vh-)K}NZ}b#vUerG7ekU)hc3^xHHz+>)O%m8#FIK5^9&BBx94F=UCId#tZmhjI z%B=04wz}Z}v+;y)B&xuALhB-@bm8zX-qq30_}sP}eViYIFNIM4Z#l)~=rQk0iJEWN z5MqI}r)LcmUL>t$u9#YnQs#+o`a0E1ri;%-l44KbZZP&RwWOE?e^J+W^np$KA*#8r zUE6+o{4*#ZIkPmR-Vy8>$zzecLB zQgcFz!MJYR)7*5Tyg`-;{RxMGi6>Q`VXwQjhvta?sD}%^Ycx`)dX4?I)oXVAHs2>+ z4f_s6xWqg}gp=h+7)a|z9T+yZm!`|ODJ;JN1^!J@`;h8&DOsB0)--IUM_dofsbAnE zhU02C7Va{yo(Fb2y6&&E8o@5FbTt;^e;#Z&SQ||(PL9m75vE7hiTxG*n*=GTq@0+y z2cMkiXY$0MUfbCfUvcwwfL&|5HPr^|iwgOf#^97lwW5Sr&EdZw6iiJ;BIPwKyOpN~ z>7G@Ngbhup@eHa*EEiJ>W#pUGN6bCL`N^Neu%)^*X5T#>Hm2=zki1mZDwNT){VAr~ z0L*zJ0Ea_1`2twiz57tScDiu7tTX?p%g0@K96;y_)e9c7MwXU_ z7Kd9EDj0@yT&&nnh|@XvEf&lL5pFEqew+@9(XOz=r`2GFTaRzX*L;ag5eYWvdoreM zA^PWu+?wZ8sDg8fI54}`vP9?Inpd`tqAs3rT7Hk3NpyOZyF3_wlnxuld1{r}}zxhj$=B@UD3k)^A&uA^KXjj~pVv2EbLdv;#DmSpGhg#?DPvx)*veE? zqCVk)h$VZw#%6Z!Rk*(V&L{EUieI|Xw~Z&re)A7hE-6PYHvunMTjD#uH`3KlEis`K zEpnUA@9QVbpoG$?wIa7ld9qj+ z5OJWtax&_rlnD>|YO;kpc1#|<0Ez;<~9vFkjD|-Gs@Y;Xh-RNb?PMGrgXd~|i1KR7*eRCvV9jgZd;HilX zZiG^;>5o0a9BB4X9PsuBFt{-FJ8JEB%AlRtYe@;`keAjMD<0@^>LTAnYd=KZTu@Nq z05khcl=u?M>@T+2Pq?8vn|1wPk^1fTrK%=_`KTSo9~C{SzhJlAvCLesByK*>l1a+0 znc<(C{S`Dc{F|R|+u9u@8@>>dP&XfAv1cQ*r+15+Y|Ot@lHv1?8Ok)b;~Tqb`4F&4 z^F4klDghjX^AWJmi(mR7pR@3zSTu`lE+j1X`zNO~8uYicx9f6XM|Db@HQjkr;}xpF z*7oaQpJ-vDlzf#puw|@5*ZDV7os+k=x#vC=v#7d3Egv4+?puTF#DzX?UCw->qn#y^ zi2#|$Kf7CEH5pKuS6pBM4HeuIY1|Y01-9Mq3witTbkoT1dZE`@`$Co9WIs@&hOykW zR}2N=O?o~MlKRPJmF8dhS6U$6L$~$8MqSuc>zZhz@4(GP%^}t~`xV+X*}m@Ec;o^T z_TRu9?NdrLCR1vIC!Xc#Q;4zj3IvWW{nC`_7s*X}knySsG9ae-tqCQ+h)^Ih3%&Yu zjeE6Dvb6WNvNhvs3fvO#i1EmKFIH4&Z%*b2Y|`=%CQYvPC}1<0U-2bw6O(#Intk;X zth0DIHtJ{>zBvl@>prV|4}~Mgh89&%y4ghCkY*_A=X>6#C?BCL*uwz5E<_jlNBS;E zm5ATTNOY!vir1XV`sdDrLl1N%N7rR$**-#U(eWr@ia*i?+3ehRQexK_nWjX6HWR1? zMyK@$a9A7eWDWQE@KH1mYASP0D_`?ltLT5M<=uTBOMYTQbsF8&8aIcWFob04of0(} zuefO-)?dSwwstU&yP)~U+UYH83{g{V*u<9Nx!N7tqCEb2FAyP*vChXxuOfbD>iK-4 zG&hG2__K%fLt4$#8R~tn>l^*YqJzqf?Tk2m1kVBtGpC5a(BKZoV}Z;B{=Noa>W0XC zwe!I2`GKNAqd`)gh`rvvTbE?Rd%xp*R?RoYA%2Qqq1)??8xnA%F}pXo5MB4b9tNLz zA1J4fH0bj!qpQ#c=WH_a9Qo`QE0O3j+R6&yxvaq~`lgWPx52IU6gN{i^{!`lD1JTLC+EYy-t@E8$v%1@drnRkqEOzn5|G+k9(?ZZq zFD5Kjve(P+B=Vs?QL7L&Pa%k3E@|&x&3O<6t9CmZX)rfwuWAoRx=`t^V!;#QpLsY6 zE6LoLEqeQ{)E4Y=cJ>}6(?zVYLvoK3{q>Mc@%TlG=WN^yTNgWV7lQwIJX6kQ+h ze$q9R<8&bvv3MzQWY`+zbsKaBt3;gUMV!-ifht9tQoR~=!8g+>dd~U|b`w63-8X;i z?k%2dz(p~;mVBlQp_;4+zCbrp5wDih zvZm4-;6*fVrrV%J9e%)_P@HESR{Lio zPor6FMb`zvvcX_!z^gg%CAIX^n8hvyBh zT~ur_dEggO)3f%%B4D=h=usQUoqQ$e)jYLA-xt$$s#?M z@M(5@aiZDXYzt;&MBB(bB={k{y7#SAU{?-a@~d@zvE4H{IrXNX4*5vo>sGWnd|~5A z0WO8Q1J?_Ebz?gh+Mw5#FZ5f#SYd=GcCnjs*I3`1xVvA}PLIgi9E<1RwJ}B2U3~~- zCiz3h^kPK&P~&}9K3M>`b)3}J%QAPbA*@zrY9kRLW^9?C!3s$IfeCCb_A72 z*Q%Hayi*XrKB+qu>&s~_s$y5y{jA=VK4FRpw0^^`RfiMiP#|wK5K%27BtGYa6RyJo zw9Sq7`78*QkT)|Yl$+B=15yg-<^9ca`Zv>^3M`4>TK1*}`iy&0W7@h*B=$kJW7mv) zQCg?^7WHp?#p&~|;4Fc4Sp!>gYPj9_n=`S)`PTa6RRN7Fx%9=$cSq|wHu*nG=H@tN zXX|SYuDHEr^%8XM3TN+vkA!n0mU7w0zu*21zxD~4?K+MTRG}|np{u_aa-{Hagd$=- zg5@|+HAnO``(Wd6rUB9Hds)x^C#KIMgnW&6e<+A)yrL+q&+B?6FM&a3O@rt%xoSD< z@K@ASA|dVA?~d>khd7-$ zq{7yL1=5*fU2_az?5_~^(W#~gS^NM@HTz13^JC~c=Fk4350IaCPsl?Uq(5HA!1pRx zHr%o&%$mAi311K2CvPAOw0oqJ=2E^aO*3xo#2fZ-p!oM$tMYtMQO+NFL1|-$AKJ8} zbOjKKn2mpwmG3K_Go>4fQd{n67VZ=mG3uN+^o3N%sFsXs?m@L6Ir6)Q*xFU7RlZ8J zSBk0-PG78xMa|krA-%HSZ~Vk;;``+G`cv9SyCeNd#M+4xr@1ZOKBH)N?{nO?W(009 z<4Ok14QEHeq$Vrx;&vduc5*_`YUpTk(9&`Fu^!iAA<-I#S?zCf%e!ru)H{cCJW*Nr zHlsTfdju2t&TdH+@0(`IC25xx0^aHwbsPxT+;9EqQc}em@qn#`BT&Xht~Fo`-7wNk zQD|(S>uu+Ok$|%ksAyV~wfvZ{1YeLBTAk?Wv*8J5m(cTjgLw za0H5=&kC;dn@YDx*zPt3+zYHq_GSg9OIk$>=Z`9m@_hUB>}NY=3y71~3y-yq^@r3q z)fXjU#ldP^0r?>j;J+>br`)KZrBzY3bYKT^4F=lvSJaE*H-M>l= zM32u-PPW*@;M88`H4XY@|Bj`lJP|VX(W;nD9ORxT@}-nz99Zn)dKpKfey@wY-WIG@ z$(kcGE8X?1Ad6XByyjaeYi??xmL?7BVf9+NLK;TF`o%W;<=CrZ)`ORWQw11aY>sMN z_wbmCP)Wv>Fo+iEj&|(^R&#w08jYNJ1AQt2t)0ErV-;7}$EN-gxqhk$FPyc370LC6 z`We8Aa7-^CN3Ja@M$Bgqk<913NN2RV@`(_56B;9c^tQzKXf+8bh{yN(h?;G!>E|0_ zwNCgi8eju5;(40lzv=SATq=FV`}W@y0=*pKRI4I$RrDU#w#wN+LMo;^C$~NqPA&7Q zGVXVS&+hsw(G68{5l2H*VYu|$l(!{f4X*KGxYeP$qZNga*1Xvui(hY7%<%ra z(l{*82p!7iKUmx}?`!+4AGXamGs=2MVds~e=Y9P^KRzt;t2wpDN)u62+temo26Ht> z2@Ouvgi8HHeZ{(djZgm zm|3HP^WDXH+@-8Gs(m;{HDN^WqNmP3HVyflHKUCeTGI2*D!Soc)^3}96HWXy`jxgh zEjMjlUM77?*7b*YfPaj`R~qV!|t;^4%hn6Gt9^}pSMtX zVl%)suY30Jg1c!4M&I%wAOC_d1UIN+Kic)i zl7B!u%)XUR_aq#WM>boKG5YJo@YnIeUsImHwv`0}XThO=C1F-khui{Ob09Es3B^Yp zs|hpos?Xfx4qTOaq3(OXWQ%)wHarCVU@IInkbU1T`sM<<6{hH+j|iEXX#9S!yG zMevz7i_2qRII8R2Pe<*(k+DrjCz<`?IV9|K`nHXGoSUB%$w?lI?*g6N z+;jivcZzid`aHHMlOE$oE`;TuAWz=(SA`bmUJQ3>>#|WA`WcLP$5}Q=Pe|KwkJCuX z#J*!=vfI5_Xkyx6^eyjaIy|iB)SD%ooSK~?=;7{oOOv({Qv8Vu^18?~LjlE^|HV6? zF}A+H&tr}FzE|4Y(qF$f7={*L&EMjW0axqHVtfiWIGnB<2dY#NQWB9-FN!PtV_7|0 z2D%)J(156a*w(NSaAkFTCVfHx3YUuT)dheN*6p)Ce_4YPFx9A4O`zN9R1KkKRLOa) zYHU{RA$Hhu%5hi$tdH$^-RL+Xi zq_n5$R9$v~(>>|)zDrsiQu7p7T_VjqvOcZOmY zo#i#gy-6O8IMo`BEmAs7Vrm-aGgiZnFaNP|Pvc7%HGx|Pb}4Jlzd|QjoY_Nj>w*^c z;zuRD$h(-6#;ui4k`+c!XQe#M9yYUl;nYN~b*y>RSE1N;hU?Ah5JcgdK97Ve{)J+O zWmGnZ-8~eMd71*&e+O%`G2dRhsSl|beQD|tQu1@tjI610?#|K5r!ioaRL%2hDWdrf z-`nrV_tpI6(p&M+`=pSZ8=LakhnPszw`5eQ^MK~N3Fwar-ZkD*hUiGdz2YY^e{-8Uh|QY$y2@LGw* z%k)lRbWOMvQ+u#hdG|v&j~@|=1#TuyFN1gy)eUo5k5g}o@2E?lgO3?UC-@%WSma=f zp6cYYp)T9x@nYex;(sc&9+Ib&F=yW9Kd;?l%7;P&R<|_kUaKBjM2XD0rXFBU=VMZ5 zpYNSIUcO?vEOp&v%J-X7_|LT^dMeU9RN0*BcCh;Rq4v{Iqr(J&j&+X|nER-G-jxd| zs0kZ08W%ZMWx_KAT2?|umnJ-96HQeCy^RuNFcB0!|A`_ntbJv8=WvMws0 zj>sYYaY37EGk>$39_L4PRZ(foq}-xslMDr#tC&YAYrC^bbEBxOO=H=|*^TCF^WTmv zDs1WW=X={JNaN&x_z6W`I!U1f57r)rcxY^Ub&a6zDB%kQ7`mDgE1goCg>n1V2YU3P zy7RYb%8XnusEBj4;x&rIC@nMdw3Eh9J+&^Mcweu2xOQ46RuP{&n-w}1Wj!k3OSk48 zFy>DF4B5iVQ34%xS{gfVUgM)Q26EKyin1O1i_r~Nkvk$H#!JM3$){{sMd^?aUzEJL zmy%j0YFc7EiX7b}$jq!<5dv%!-I&y1-8784hX&RaWW2G1=?`n-KCT`=1*TuAEh#S; zxd6>QyV7G|?4-K=or0KC>Wi% z8Zb=&@8niCbMsh-a1Qa;S>K$7-53?fj{FcF6C4$7KOR4n^`qXaYjfWdOuklA=ukRm zsvoyhDN7LJJ@;zuul)u4L~-|ipz7ahM{(~`EhqpCht*!fQ22KY5s z>P~V|=rb1#+LiM5S5_*@+RFM5Nr+cmRss#8d0tdQB(*!%pT?rn+27^I+kuI9ctusA z=M3G5b1+ij;~zgd%)t!dEW%OdqHpUyz*=4I;zIOCe*0=HmZ2bwp z%N3Ps#RnTJWL~#MAjitAlM=8j`pm7B8`WQ8 zrHTB6LiyhLod0oPSM`>sg@3d4`Chs8o))4#|K%bsE4d-EytA6ADNtaW|9fJNf#>Ep zxowS9)QH|M7@mk~j{YLFJLx*QewC_Tp)hulor8=v3=ZM`P zExKWv^{Co$tiQ#WQZ%{&V|2jXDxO<5rd60CBWCh+XPrzquF>=7CeVCj?wagxhihoM z0G*gh{#79OHZ{MS3o0Mk?Bey8>6xY4bJ`L1O+5qB7-70d*%}@(+xkEKO{TC^%Do25@K*?eO2hrWG;FObgJqf!?xUU(neYvigr zh@b4jpc|M&W0?!h8*l7&=7TqwsiOit6X$AT0yuFW>M<9c5jd6XDCBJsao;m_i=Iq$=hKITK`|G!E|E*4-mzNI>dR)8vQo;NN;rF>a%&!?5U z$*fH~(^bQ&fr46bYdf`D`3xrK_b#q#&bpeQ!DpBy_sORK$B}_ln+~S;xO!*~#H!Bi z-n!M+l!Q9O4=tMZQ5My482zQO{R5abWNU}#zzA-1#ENmBbo^w%LUJO4p~rPzY_$rd zB#zE3Zd@#c>z7PV2NsDcpNKl}xbprU>y)(r>D$>h)XWqps;1vlXrc6LHME4BrhTDt zkGIJ4r-8siL+zl*;$FV~$gl8E-d`VFvUxAMogL)@3(f60HF5{rW(X&0)I^1JL=t&HE?uy*mr=oxEWzA8+|(M`5YWADJns89sS|@;zR7L zlf=YT3Z&GkFS`lrrnFz=eIqqZjc9!y=?nKVR6dzwosY}!E*>_kLQ{Hu(qCHSp74A( z-?kVh$&`|~zAx*2q{>6-M5bp=&EBV=EYMe<_+`fecA_(~IJ*<_Cdo{Id?50cE3*AE z4RP^Lh=4&VLSR%SclZ#j&f^;9aN_n)eb9K4Xn|m5QBq<0+gDhnvcN>@0eX_Iy(@ zoGo7!AXRN_V(_n79pvBs7(e<#;sn?r1+(e4 zA&R({i5`(Y+tUku8WS01ulLq3Cpk+Q4#eNPdfR>8KvTTsBDr|e97ED;|iSa)jk?P6jw`U6Ft>-4ri}R@DKW>VI8(YVcouBq{W+O z-ny#+HI_av{TU|N?+{AGq}j(z=~-lZJ+0BNd@-r)i+JX1=BSAr%c%FgsnAG|rp*M|`f5Zn~0g;l#x^O;SbD)I-kv8 zgPR}Vw_krA(sE~XMGs5b{p)CUFt~E~10NdGt(87+#diB9 zP$_+WWn|ryzPa92b1(TKj<6<_#e?aqtv6E1?1!(OT8G_l#fyn12}6d!rsYY|RtE5r zU-2>1evd&Q`su{dlUKF=C6DmqNtmQ|frLeYq z>ljr%y&)P87+I{{vlT-~VF((X^7}hTDiP!YQdr~dow*R8Nv`Ob@9z4ka0sbd9k1%5 zVwAva%jYJ>;uO1}>C>7&~lE0(nuYY$xDW>*2no#U9L^KbjBY>1%l< zRd-FdOM!I|FzdG|e0C+7m(UaAEz-r1du*OQuOF-W0K;y^fXy(hr^IseC<+*ebcJ@U@2d{(nFUmapQB50vLWYEsx*}RFYdcVJyTj*9I z+v%Wgk*Qc|y^u9kN8(E!4mrJ&DmpQcxh~G?VF?*Q<))7erFm5au3BjTdZYGLmwYI+RQejUG2cl!C$Ly^t zf+xI5n&gryT5j zk(w3kJ+=w1$W4*uYW89D7%|rq(d_~GacumSrSs*^xuOJ@_KmSr2Z%SLa2eu~;ZBsw zX8|vw=s_5rlNrZ{JNjHUS=6z#OdVFZMLyv;^*a)=zYsbxW=$XZKzw6CFHR|6x)MX# z^3Y)xHKnv&LlDU)g;=J2!hafcUM8o&m~WLa^gaZ{zAR&rek)ZN4pszSV9M!P9jRAX z4XN%t%1Bvk;Cp!YOh-UyfopNHybSrrBej>v7xbGW|0pw!v{7qd{0&bPiAl(9r1F^E{z}+g_Lj=r3w)KsxCH=9g z45mWF>5{fY--KO=Y6_xH)351kq91h+l##g7> z3lh+TC4bv92TRT8Zw6|c>VNq3cV>dir#~&{nRV-PI-OitJ1Wh+g0xFl&H8$Fq?i~t zZ+#$LO8eM4{II;npeadoT0y^#@a?P+hbDRjZS8$-R}XJgkHzKXs|pEszt z9pf4t{LL9UV@6uq4q8?EOwY$ib~GY~1ypci{;Mghba&y|-3!|uL78&P*XrkjtO9o& zk%sI(aac{CoNp@l;68asfc-|}NSl$(lX;8b)YzePmP3;S?St;~7bj;cy6X4-Pm(kjg8PzyV3QIk_@r`o({U z%55}-bQPv+ZNGl-wcZ@yM#R+BzVf^8z~*>mkl!SDE+LG6Dk4We=Zrj$Ku>_keLgQ!Gh;>yNq@*(L)WsLNa!GH^tKFPr`9c#yyp5sJej=qyW{7Ng5FpbD`5%Sfs zTMlt5U_tmt2}s&FHr~mYy%P##@A`R3vA^S)TG7>HL(AuXX24qV&nPrvl||#q4R!<7 zZxzvZy)Rvzas8JMWWbN<(sv{isF!$FD`8Zp%E7_$@oA6pR_}mD>g4!-<(4f1>R$BD$?qtczaO>k>~LI_NZgdw^$q$JceIL5;GC$fgV{#OW16HYjC39Ipf~N>)We4oR2ln1{bD&=;_5;1kWdZLn}S0{WWS2d8EdErz0gM&?xPGt?}#x zJZUG}OiKM@Anbi*56##H8AXrSwP>>9aJNwiRmFxC=eYMMWNOGE%QLKlYG9<5;pWcT zkHevGQ+B)UqZTc*T7mhP^|KV0I9JSMa{n;a zaenDA7)>V^D7RsZ8xbu&$IcFZY4lC}sNULQg>2{$RA1DfEaQ5TeA|W(RNZ<_08YjShV-G4h`J?H*k>GOswF3h-68`%mTmt7R zbWxDw$s33>iV)*|Q(N2JLzq3C-RvFcqn*c{sZuAcO}>j4;ww0L>mwlv0BcM9=gRgx zrjTj=^dvK%>b#L&eq$aF0q`*q{aA_3*rSz~s#A|-l!o_|#&T^ae&b!}|MW&3@bnyT zWojSXJKxl}3AOtB?q1fnUi!U%fMel1Ad?x&oP1Cc&RVGFgK4 zym!Xjt$QZpv<2AfQF*hC`r^{t?Rx|H1Dj(;-+fia?)&&}Wee^BJiMWf1}Jv!|8uVRCNpr6JT zaa?1)dM*@YE1)4ku&Z{bY%%9;h)6yiS9`MM-iLYfH^3h{dJBxQ+JAZ&eaNcO*X=^M zc|A@*&OE1K*d1E!EK7zQD8BN7d1rkXA9uk$=&#^2T50l+Uoqu)V3B6(!mIq{(>{M8 zpa-aR7mc+Vdur0C8~?42a{QH-(5RJg=rYr8@7J&mskDAK6WY3MdPTId3q}a%8Ixb7%Hmbch!6jJ8#lILGrT{=u5eJRz3q6qlbWxVz9Ej;E*ghs9I12k`YK;4@z}n?xDbV( z*kIw576HUY_?7{YULqk3#U8d6?;)4DG=oO2fs&@AJD#vz&9u55nl-YUC-mMA$D~op zrf0Gv-bH!cTVx9>pN#nITDYK}16SVUdu}I#N)dhMC5D<+Z&pl{(l?k&lXf5ZM%T@b z{`RgLC-USHp`4H#`1LMjhlZm@qkn!(;D$25yQ=(^LpqlLQ1xAIJm$z*g@Lg($E-XKNin4Dn*~!?X8?$w> zuu5WIV*hLue{^s40**%vw0YGdOG(%}$S-AfRGX()r#2i{RDL7cptDYK#5$!}*(%$+ zz?E@pF8l{4DTm?$Ljxq6hDY{Hx8uA~na+ez8M}trx!OW)^3>OwL=7Ka|1MQm@RXrc zp0zFL9U2dDamkJnG2H&k(wbeDvY8YpE_Zm?an-2EKOt=?6dSfA?VU* zZ``*oONDD^q#3gK|2;(?0ddHby~>js56e1V3~k7I8du5WJ|+`0o0F;pdY%~aKm{nE#8>QiOq^MHtJ8Is?K|r zV@>;T7iXCJQa+2h6*Ik(RP0lm)^SzeQ`$)Lxh-CV|Do)Tok{!pI`d(=F`N=r5xZIM z4aeO&Q{@+GiH1GRZ<)>>)4Sn1 z8$6?$RGTOfmcFaM3QaSupE`&Wskm6pXUEbG-W9Uyvi0?bTq{n|WABv)2D-9bQzS;Z zn+aVAeOoO7&vJE(TbVq2J&UoP+dn-WtnnenKO&cL3+k{Odxr*16zeCGMv*L}b4_aCo?JE`OIlvS-m{!sX-=C^Q!ipzOB)jZ&XiW7dw^K@k zsSmax>Hkm<&U3&Cam{L%yY3Fyj=8KK{Pj&{MuDqbT!_X}qfAyOzix8k+(kT@2plr& z%8#unE}^wN@n|bOWnVDDvESHX%rXRRI%M1u6(sytq@<$cqGioiTy{<-%<_BUm%XY# z=d%kfg=3sCp}G|Ft20+hJUyCw;+kaXEVl(}G@K0&y}%;4p&a#auG_^FcNj+N^gsCe{BlKXA8)-lb=e96w85Qe;swb<^?duZM<$#K#=TIoXR z;n%Vt-=H!g_Kt@IKUj$vAAsL0`7i5aXRT@|8;vwb7gJI4iwo=~TNPIO*5ow~&C+0g zX(LrN_bMlga7fpqwE0Nu7e`PhOO-b3E&%41>B$Qz`blJB~em5oZvj zp+Kg%z;p|FpV-H4m1nXQUV<0O3CisjI`>I*`z4k6VH?!NBj{10CB#FtLDb;;CvbcH z#dry9gF5}WAiJflLQ-sXR7b*=RN|`p<&uHp6uN;T&!<)T_VT^oSudtvAmON>A#E;a z?rRH`P;NYzs)?9Bm}Q;yS#pzZfAJvC#hU4Qq?|Bgch6jGw)m8&wa>z&Hc1Hy*KRCp z^J6B0pJf>bsU?||i-!6eM38T8jV~ygqswP$&YO+IuNQjmz&l&w*N(Q=jf6*X-Gyb( zt1pKqz5JDTRz4AS8KrVS*uASVqvA|H@r_GpZ$3%Yh74~E@w@N7S=W7;7HbEzw$=45 zmFf=qaA6$OpCCag;JBb(YriMtqR6c0O>%I$WL0h>_IU24eQ2LeOnbYG_M`7>J$*3) zsx7SX8uej_akzPYFjodAi8_3s zA*#kCs2%q_g5)!S$^C@Pfp}KzHQbV(J{)VFvjfjd?cO;*HMyX;{$k40%c+{P+waNV zllPIhwR0y2X<869rupGFV?3q#r<~yx4!y?sR#iV}FZ2s`?LDC{nsn!KEnqr`{Z@%U z;`~I=N$Qh6Z{vOPfvP)+1Xu;eIEs{g^T^ zU7lpF)6spViaTN9zC78t3|bZ_^kF~9$;9P1+U4H7VFE%x)?Df@E##;>n`lFWF5Gz< zOXSV|cJqaya&ZCi;7KM$_SK~YxSIBt@E#vF;>$jjJcr@}GGB#^STCz!nqA>}FjnK^ zfXAN^oBX=)u~$%P#N%lT=2LP6L4L|Xq1or_(}63RuUJry_H`Z>wNX4|vHF8Ah!g@X z4UI&fAAa=Jxd@^nVl;N#=E$<9tR~n zY?s-VI2P;DEr^cHf;FXkxocGxlv)X#o%5~Oytw69qnyBZxv-pQMY(HjM`NN@JkH@7 zfbVf=f)~ME1Ml*{<(!vCTEizg<+8Y}{dnE~3ru}2N4^$mQ-OMq>T9rlcI+gZ`Vag> z{3i0_Sc8;@Bw|=29l$=ehEuqRY#J)rGM-hIOq<|};xIW86r!S%&IAQ6>sY1RrNGPw z?;!toq<K)j`ZaF^t6o4=nb$P#mcYO4oNTh zD8vG&VDP8K*h_=bN3mFt8pC%;^&~1NLs}(V$6+GhB+d-b1l_zw;b<>3$va5k$~uwF=d4{!vS4V&TQKoadT%gV*|snmqr zp?o#Gf>t9_VLYnf<@WXD|1?s5J?lA9$xRg*Jva&ZMMz7F48D_#4%dSN{oPOvZE9?i z{-Md{Sxvlo1=2{QB!Z-9Yf04GHbihe6cJUiB-yejz?6Q!x2}`a_wO$<_4E|-KScVm z56AEH`-A1fXsmD8QMXaXBTYzW^L#d|le2xeE-OU~w1Rf|gJ`&n#Pvc2pTN><_4gH< z{xl8w8l=U=M((;|^|`^;>8%ZIOBbaZT2Q=frT8A|={amx7iaed=!$|z!EOZYIm987 zl|xg~)%cw!tMBbBHue7)^3Ni5`{e&z%YSAt`$o#&QrD_Xs)ceUnw4f339_n2$k;_d zmX+R-N^80KB}VQ7v(AAU$nBx?Tk~p4DZu_uM48jEfSayl}MG%60O_*;)7U2oBva+7_{(xQ7dGZa5we z%1@?T;aPSxkrI$oEuxD{*Ud*2`z$U@E8yL9hiRf zHR$o5GVM4M`GrVJQa(E{^$p{1OViG6o7!5oHa0f2NHv&9&63UlvufE@p#&_X6ZvWV z{ihQjOt zl$7gH_7y7<6nQX%@|Tc-9SU>lvDT~Gxlz4Vmm7V!3i(>3P2~pHMdj*qgU1;@99MnQ z_U263u<9#l?_-9%#yhJWSP$ZxZkItwgxp;4crZ{TAQH^+3c|dAPLF?t^0#RHTW;#> z4dnlX^yl&;8RrA=(6J(;{nS};_Higg**oabtmRY>Q?Ddv4)RNomJKuIU!~t4%r0NL zNOpld>;idgRt(RY40PS&@uawF7BaCpJo z82u(W6Ra%M5ubDTb^o|wXK4LbVd`lI@@+`FD-8atD~7HonYgN@Y3Ghj%63TK%;lW< zc_fJl=!#1SCR-pA?}h1R*KQ@gOUr+?!t{r?kpBqj6QBHGrTW~xd4sbM3G_+|JF;MKuC0+M{+<#`4R<+KQnSPF~WMpqpp7xD&^2 z35uvo7jp8e;x;a2?JOYl@wg@8#rbj(7=tWP2IWA?D}k@&(bDXon6@}5@F#2s%gv{| zQ|@S-uSdWr+99<)Tnl(~nCt{x2bV^a7-te>*~8_+xllw2iCAFAXfK-0BCR7kVLi@GBnr^2-&@?_0&{>8~L z0_|JR`Z48E+XZg`ni2a0Vj0YbDe$Hh{1*?O8hQqzf8kKd7e?NM= zDm%_q_1|7;`pNCc??*aN>09UO_XoG@7OL?}{awu{(yg-gcVw_CTN0@$7h5R(6StERQ<_Pt<%)Qis=L8u%W^(K1d(^?` zuRWZp!|bg@Qch(-F&wI*`SH14>RxW$#D~lKaZxb>^+6l1E-Y+K4=QnWJP}G~(0wSH z+VaEH(`<@@b_c~8Bd+`&Ztch3PpxBRD_GkC`GDZv${F^X>Jl%ub!A~djZdhQx=z#p;4n@ z-5Srqk*43gg8ZvUulw-4KXPdO(pY~K!y_K85zA~BT*j6A;E|e=_ zK}LRhkNVyjRi>XTL;eJ$ldFvUSF6}W%fNiF zWX(38O$Q-Lz1&NimS}o+1lW7|$#`6x3>)kuOqQ|2XiEyoadF zT%vueaj-E4$1vo_AdMemaLgH_>u-SlM0w)IYcLyH8XD=2QA@h1Y1<++pmxaH?}=1_ z8d7QYasdUyvp7|Z48zjzmt3RZu)SkU``n8By-4@_aJ)Tc=ic`fnRCzoLjE5} zU-)p8j8~sqGl+lF=Iw1ORxfBhZnbKlJ+gt8)6*^$#d=mBE}V+yfGgJ8CFFDmRot;D zcU2Aq0=8R2;g{RsbKOAk>lL$QylJ0vkl%x}cf7&%`1o&XpVs=i9qQIw^RFmePA;2+ zy}J}U4PBN8G8sMF30R^UHDVk)Q5pFlSdlPY(zCLhsZquji`#%p2f&USG{6aFUe888 zg*1GE!F9X#OSoRgiTkxZ@cwtp87)ms^45PBbn=IRcR{y<*n+HOgvg?}$Jmh<@Wiz| z3htF${S;l71u0RED|^oixluc4TO|>Qx{z>Avd{pUjpmH7u|zmCEP`Ml)@(Hti*xDf zAq2S|NS#c(Yb<$Qyf5ttU88adZ~mcthuWCN*65qw~M=YgNzkeDxa@Y;RCNx zFPEv8LirqFbNU3^52T%vsF6|vi{lmI_#fw;gcG`zQz&eRdZTfIFQOb;o&}>XHNg1G#L@|Y#)#j>)qgF$eERzZ?36dtmH@~fO=^=J>k=DSt-`X-uv zt>7fiN|4GYnR>W*lKR|Ry1$19^mnR<%`J7?8+K(3{IX6cmfrAt0`ldX58D-T3+pB zBkuy_uR`jWZ0h@fmfbg~+@q=AZQJITP2((;kH*EBNTqBJt{N_K%fWN4xSLlZCk#3* zvMAfx1eAW4xnLMSpyYiz*^Gze6x4Z0RZ|SExl`2VGJa?;eMKLyYM?up1FNL49sZul zbTg+5*dcdV_(~3yyeJ%^Y^AYK2-VY%xHz86FRXb`%b8;O<-N#1iu9xp&#yF|!Q#Mt z9UlBk(aC=)q>~QzO0>B@as}GSCD>ej94b&FK2Ckh1&fY@M~J8T?dHyh^?Wqd;F^K_ z5~QQ28eDZ#566|?I}lfzGAONXJ7Z&=TABCqci|1rdvP9`(-~mb2Wb=X47ne%%_$34 z0Io#?`E(?4J%@)lUn;+^<`E^QYpUr_KSlo6NU!?vyszyAi$Yeo5E18toeJStC&c+4IaLti+zFNwv#lbJPF-K*u#zVr69=>RaXtQhxV;&i zC6S6|7~E5598tZlAh6Z-Xey6J@^Hv=_Q#N{T3l~OJ-Vi5iTtc+o>k^i1@2NXSjQ9U z``c%j^YiPF??k%WhoeX1Sg&ym%nwQP(MBB#4RueGR6UaB?sP_u)qZnxo$aXZJcCoL{agBN?!g<-#tj=XCW<|X>hgARG+KT=RU8# z`Bhx~0bR;E0zXy3fNlgf=Vc2my-Do#@W>oQ=G9Wz9Gw0}xFKPS72zomuR?Pc+)A$~ zSQT|E#UiMgYUMbg$bWKpjpyV#MetMQ! ze{4ej5~Ry#8Tmie@`WA;QwHj%mWH$Y>kS+9Ss`1rQ_U&+)JuzeK35vqpG8KAY#HEa z5;pKja3!}V+Y>~Un2Sr4QdkTH)mWF4$2b!UoU!Bace(CFs6@j<@RK9X%p~n@J>s(F zZiOp8+vop+{9L33vkm?;XRFV>Gf4bn92YycH=C>6?fly^6Htes=N5WO;)Lz6x1+_7 z3OfM@ZTt$jfNpBzNcjsnEZoU)m{*93U{Ta6azc$DuWVn)#d$mp?*=%kFjjp?;pm=i z`sweH|1;9NKD__Xcr)W>|7!#B(h8hr_PZ>G|sgT`)e6%!e*?H)-A2HXQ?w&rmS>fP$XK|X z%iI-x8po@1jUIRx`45r)=EG5}{c;C87u?v`n%TFkeHYj~RHy5cP=b1sl2=V86kr9w zjYHgxXF+}hCKp&SayHDN@L2zznJ1fnqU3CuXYibZ{MAU;&NFxpX*>tCKHWdSA6uen z+M!j`RZ2Czsa{62d0hc^BV9tE1+~mc;>qpdnRIO}X5}rhqu6}`=Kv4QJ}WOAbc%4) zoGku>!x(-Hws7h{^!T4|a1KX)98&dsgL9ttgYDO!1MX)uHu;byYG%mY-g&j`x6<)3 zUxql!q3GRJ^3Pbimb=#{_j|}cj`Rbc+&|18y1lm3*6fBQJ6dDw5m-V=*F?R4=w|)HR^MRzErsOeDQVoGJD~}x~%abWLzYBQ0&ol!BIlG zw&5~48&`xBswxI4?>Zie=FlypkQfE);5a*1P{8fckQPT5g{BRIjmt;pWZR|gcoBom zuznW#%jL{>c(LsaqYHEuE}b7)!U|Oim>IV2#l^F*F6T~>l}B!|ZWMb=r9}y(OPmlL z_yu8vu%^@JY^wkbg>%G3w*6gz)2!d{z@;45piskW_|H}Odw!!{*Df%6xfS^fkuF(a z>gx{ePdwOqb5p~no%L<9z81AKY*Nk(HA!s7C#X#eaYO>U-bzv$Dt9Ed;v~q05Jm0f z4z=KNPzGwxZ*{*}VEWgW#4qG5ywKp8vT*4BwFzf6a!g;owN)9Y(rfu-sTiJ;A*)x) zoIv?#$yDHC-^r<<|)Eene|U2Nu=4gUClYB`Gxo{Nyb2I;y*zWvW5#?#hv z_R}A`Q5sy03RHR?F0ytbWwDxG8TR)uPzi9o!(h>}V7jP+G*8jpk?z-&ynTyJ ze|;4BXOaHhhwF{SL-$vMYtz=&=B8G4i|UPx2=^-_#jHf(SlV+cig9PLW zi{dIwpukJ7>v~w?TmK^e7}AqV%=j4G&nP30mXs6#s+!eQvnv9w%DqvozyDL;_a~0x ztPrW>s3ZA)+5p5sIBNX1rbgBFqFPLFX(YZJ5F#u;&T6!r+M|q|bCJIY>5~7m95ojE z<$Pe|q_v!$qf9$}g#70uW2tGU*wSxmr+#_$WDV}XnOs+3vbGy!bmN*nU{{G^Tz_`} z9SKG9>8i?IQnhveL4E()r3S|?*ag0k(VwMdPK`Wc0OKp;W z*RJLE`sDr<`OlEP@X3uF{f%-r@07Pl6RG7gIBHEZ>(f$)NvRG=&Fqi$X}N2U_Rasu zwE!H}IPvGo?I%jj9fg?i64HfY zNyeR;rT(Pb{}_YgY~;U#bb}Aa-@gHe4@7es7pF^+WY&y50ere2aI$gPrMAMOuoOxz zW|vEcq5`xh3rACsPSX0h5S~ug`ZMnxUJCtN+lrFEi8a?+h@W3%RY?DV;V_90hq3%+ z0kinEneo>Cw!)u2)|9gj`7@B3jy2`H@>pFTgUs_=>UL~u+Pql~w^z7~SYLyd-e-0a z=cz0-t^~}+c`FwRv8*_K(p~d1Xn=aIuIRS^Me9Kyj=v!P9@76DdnEdHdn;P%G)>7l zGsPCB*cB#jW2gT9>g8si6_%R1o4mUJ4w57@#E zmpz6{4(bM^%N!`d^%>nqSOIbAWD~^-KfxXbOYJEzR?LAyxobojn6BV-uP)&5TzSai zx>iwPz#3sq&8Lk-afPr)1WtnCyqvFN>e2V#3TN|iraXI)zZU7n<4k$@3iY}366)M7 zl^Af|EaN90t>eu11bz~JCBS{aS~O*g0#f6FP%v!COZ=sw@~la*31N!*eU7+*|AdQgk-VNyb$?%J>hBfg-$VMq zhj&E!Na|1HRamzZ$m30Pu$A<523y!E*o#)VO~D+jKs-7ZEYHEptfLb~D=QvHg&K~_ zOZh<;Vz_(`MxwEBDC*!~*bGmpD=B@S>HeQK^?Vuf*CO4RHn?qluWrjA_h%Jubwy3$ zPXC%RRKLa9!XAh1vsKE60#V`S#!K83R;ngZi}p#}o-MCJsGQ+p8M+>S&U0|27m6&H zPR@h*x!8e&l_4<{k_MVeVfma7pu@NU1e~L*7pVnJ6HALSgqY3k~PnBxt+8SC#F9+RO93s zRe<_4tZTQxm35d1(_YsCxQN5t3@)Z-%-yRDuA7j51nF@fuH#ng`BdNcd-ZRF<3bIv zys2JA4NP|O-#cLO$BNqpk|yAsJ|pl7*VV>) zZB=hwt4+QA6!~8v{dTpfw?FE78#-@?theQq0)fm*xsOoF7B;i{g9%th7rEwTZr-OI zB{#Lk^yi7lPeGc##?1GF-S^+v(AsvCoUEEjz`qQ}oBF>DF>O)|m3$ zjr>8RXV#eVeW_(;;?xYhzpBcY32M>F9|76^R|MqCSnRVl`*koWPgHSu+Z4tpOVBOA ze4O#m2QNGV&H!rWJQ#<~nvZK7M@+%ri~!GyIIb0*7{Z|jmjSsGX9XsT34z&&-&6S0 zCm8&jkl&8fe1gG$-U)jC%lK9N@$2yG5D6u$1Yrr*DY{GXBD_2Dbf z_j%va=SgGV9)M4FFRU!IsVM`Ztg~yWzHY=NLU(|@6Dfugw}N8eNDGq8e@jN-P|qsd zf@8Iia~hchk8(H%=0hT|faIi$6wWOt8=RLS{~e?oPBu7y^nb*;Ff&N~Sih85%dj*5 ze_^Eu&Q9_*f1PRfvB=Lss#$07Ub9Z&b^obw=6rfM-nvb==xV6f;rN?Br&anRbgFy> zS!yk!)2JNsHn0NA^@RMx|p4ZT4tWW@h8h5=hdPF{f@FqyOnk@Y2`x_ z=T|FSP|OkNt6WTiXE|)(Nim1t&#iH)JhdrRo_BoZ`4{rhQ#i{$#gu3DDXKh~^Q+-} zKwJ;$UFIuN?c)^xY#(_}or4|OVzB(J1iTd^iz*@5vY=!$M)MVvJDm8Kh7F1vxRQ_V1}Cj?lM}zYFPJAD-W8Ji~Q=T>RzXcqk5_ zuQ&Ga*SS=x?I2&C#y0J;*dOD?h{qGtK~+&iR#Bzxi7|)&#w~y~w7s=nT*~=mu?#Nd z)?|0AGsBxE#j={w3U~EsW*jX-{y3!LPcyh%PgA%%2g?uHuxnv|1*R{h9j=9JFy$tc`z6HX=i9YB?0fzFXCCrPk&fA5?zMo+FmKae&;b;Opepj@A0V z*7$LaLH;PDV``1u?ph`HeZ3#DY`{HGtkwR3Qq~9ei4TGI!5I1cctF1V2-xC2kKGPs zXsykr_`M#;@T3tywH~GoL2{1r#3+~oJsjeJXxM`soQr?R# z{!z$}Lz-A;%D=QumH+xd`gy~dGWiOVA^R62?Fp2E1-9J9wF6<#cAOwK>{d{b-_w({ z{inZ|jeewNCE>n}!@VYfX!z)2|wCSJFVMa2qB{{>a ziY&6R9#Y?5Jz3j-8x5XG$j?Tax6$BPuHTOjwysF`<4MFv#dtiy7N^;Zfdt+3BBJ}H zr6$f>yOz6eqv`h#A^$Ye^FFz6Xt|kl=|gXQo!sLx$;O8DS?{QzQ-0f`V*PYdhT^1JFyy&OXRRixK_^23{y{LDGZ zK>sr7E8B3EipDdn$2#W~i}zSp1?0<(*j2kN_L3Ne<0_0s*<$P=w8=EuZo$>@HXNy= zXzSRCSx(?I3MLY9g4sA2;FBA^4{My=y8R9gh%?{T zQde)X*Y)uKRrA`fP-md6wLh4|nKme+Ae`%tj_1G>Q6aartpeIkO+cjxdRD>9Tv!2@ zQq2!T4RbG`HF>g_z%Ss-n10mGR(Rb8Q?EtHS0RmU@b&YC!~0w9TVI2Bvuf642mhst zhn(^e@Zxk?Xc`1L*cEn;B`i@CaAl4LdUPz(`mfQ{_kQFb zLps=K>iea}Z?5n0s8wM~_qvwn*YWOk1#DS2XZPb=N(qA}qJ`>`^?m}JL4TKCtmMYG z7`eldABQw?i;;WmmZ9a!V7{$wbux)jLZ)w7#FpXw_nN>p53Zt}Yzx(z6AD0aJembO zNLOi7tVhf5@X5aq`F}%t!YBWiTZZoMn<=UR>J1emTY{(_h26fME$ig$(+r3lE7A`F z5((h)MsFOVe3<+?*1SZ|e_PEuW)|{`k(O;Wc+T0X@C=rRym@C!V}r!9DN`#V{tvpH zJ&7&DiD;h{!~uw1R7Y!eC7&<1h(q$#h1F1qi(XnNrh+&f)QIPRXC}1caoGFVXP1`7x_AuDY*wvH|_EY@~xeo zYyTJAp2H{0uVtxY6s~R`u2+$N7wLa|xJtGuT!ZFMSGaceU!qCYF2EIb0n#R2#h8)Lf2BSqP#cY)1vT|4{6=JUbQ$3MjWifU9scBX8kiv&MO>!ntLe&;JAY ztB^Xj8JsU`oSA#Z;oPFH!zqoH^3qqzc~AMz0`et`E$}5 zhO-jUKTy8N21d#>96S2YqJGaCc<2w7kLm z&Pkq%c`Jv}jQN7Cs6lgHJDsDEHcHS+qf^WKbi2{B?hekfkaBkT`pu4^^?XySj=Pyj z^0%UzElyC3%^+520y1%vd$hbQJ52e`M*b?K4xha5?HGEzHa4{FsBhlM%B|iDL zHVs|hjZF|05&JUW&cMdz=!MInOe)*sylVd~MV<-gNp#@|1Y zcbhp2HyimQo7G=r_P=(&IZ#jRYHG!`WxZ;Fzp7)kB*F-=yLb}HJQruI^=M88DSudj zu!=B( zhFgf8Ur;#1>Cm4qp;^n_a;9njUC3XEbcs*yJ^KAY*Y%k&x9Oi!zZ=h1&<>~!EM0Dw zV4ts~L}OkVt{VlXj6h)vYk!Wom2=w0VC}1Q`F%Ke3uhiuq{ZMUYZ554M|JT^+=i*AhqVgL1q-%|m+uLIHSwBMlpGaT&I5Y(-D=9Y5&83w+FOmh2erIG{Vh-)#q3;p4rdiP3x$q?vwnpRDlB*lF+`i~K626LuPWbvqBoH!yE`KR!8^%v%{HHFCR6?lY7{ z5fd>0lIr8^13QTeza$-b zLrAzXX$We|T*{LsuHbYwLyy{16ps8|roP7^KMiT-E`wvyuA%E&;mAacNu)|-_HV4~ zy-tF(740#O#A%{a%iFul^rwBu--&dOPu`=uhVD;|nQ|v;>#>Um*@|{FuuvA2xeT%$ zTxTy3^I2-W9{;}bMRs$Rhg7)R$eXlV$?MNUHSnIej2GKqzVu2|jpJ}q;_P-OA5s+B zC5+Q?Q2Jd6pleYli|MGBwfxI<&mrbB$j48}eU}tn-Y#JRSEn z6USojfO&LN!{&w-ZTE{#{w%6g6xhRAi-2LGAWj!15@LFGFmBli%C>tp+Tf_bYipJK z+Vf0#cO$_-3(WCG@=>lNPk`37$a`B6yY&Nq1H z>-RHu`a1*aOYXZ)mc3v;>ZEZjje7VApk!>Mi)9E%in(4dlw#`9a`&EZ+UXYL_ahzf z$u0eslDi(%zDOS*xIeN>RuhwP=)Uk|9J;>&OLs)sOY)Xb5{3iqvTwlJxt>D_jE4}M z%FH*O_z zog9!60N&=}e}KnP#u-px4HL0IDclmU4{%Y!bApcp>pfkSyZu{c9=HzqJCW}BmMM4q z0#)wLfR0Bd4lg$yx%dkHm@5nZIu^Vu#I6kxa7z#+vGBvOD94H{Xuy_`MI`SL*G&wM z=L-mwBUz3rj+2)Q^I-y%iQ!mb^Mq@WAJSvoQK^&Y5=6AX8D@>lb#T=e!yz{b{#!s1 zUmz~#;!Q3_1hzm^SpWH8yx3OCW+kNw1`w`0ByyI}8?;S2Qex{!P+D*G|NB&ZzD}3^v z(DLs7yOPuS>DTC;mWH;SEhJBL@L}>mtx`V!gUgpur~z;#B!qMpQI0@Cu%g4Enyy&T z^$P60^T;(Qk`xw&cdizVkQOI8NxN8zW9=9@{J{+fC zr2e2?>wzhO0dd=#G94q?$6t4(tL*z0OZP_PHT@t?6BW4DLW;(KLJ^kY=+M6rxtgnh z3F^ON1qtX52~?=Zl;|j^;RvJ z3q1}*DHku@3P^}NrXQ(um7M(-oALV$@;^j+@nTc1pIU$l4t)gtk*1$6g1U`DtSM0t^OnX0s{BuYz`0zM-Yjd#uLet*r znpDm2$XBt8o>23y>J)5MQeJSZf~ZF+n4)AN&=o1jvn|x;K>;FYM`dQHERSBpZdh2k zRyHikgDM=X<)p!;i9MX31S|QeP%iT$jmm2&BHU7c&+jaj@;5+y$ zLTdc`s7`J65Skz{_!~!{L0E`|pzQC}sAC)m+Hq0tQ4R_REQ%c+gpv99ezmZ&Dk9j| z*1;2$(jvr^a^wjNKNAgz`XRFXq{*nh>9N1ow zy@0Y*guS5Wc$850ELex_t#RzV%=jJLhWvh{13nyYX&l9`4>JGMwQO!`X~hY%SGfoyFe-hFudkxO<`s6`;uJAqf+1KIR)Wl?Tw*w#}xjm(Vygg^LHQf=mpBIYh z*uG~$rR&Nwol+jLU3)U*dBZ89EVk`YbD16qoeR(3cU9TOgd%^Y${!W8j+9=u1c_Rn*8 z8~Ev>F7OKu^Y{jFuCqkdZ~WU@|6Ojz{r8YRfYf!lZ@qN+(Bod(A^Ipck=lfvz-1@m zh+jyqe>C2+fC9l=sQ=k1qLOuJx$YH4ZVB=ukVai$={D&=zlJFyqo>0@OW${-Yb-=md}TXp8A;FU*EAFayeb|kh!E;}*JF6CrVS%F+SAyqdbJGH#MK6y7Ie;3j{K6wuxiM$=# z4wrZJSLO9-d7oZs#&PH>&T^2FR~dODuTt^`+kcbtHa0aWiQ`e?cy?klyB#GuP~lpE z3IU-Yoxze4H@AJbolQ5BFO6ChWzsd35~Rf(1CWC$yJzkt1ZV|B$TQmh$H=f zIh?{WkDK(wc8$T6hkO|lE;ajcjn#QChF6f+^mEgFn1McTCu*H+=1qWkSfZZLSj&UW& zsu*TpEnk8-89mGGLVi0vm9yS`TK{(#JzR|Z2&B;+2G7in!}ajj&O4d?>SX$EI;6&~ zf%ea10or=GgyW#I9IS__;(T7px^C9`zr)nS^>liGbeB)=!&>fO_u{17hRtZd_Iw_>u}gC8Tm3C3dh}edkN*gkxwJ7zRut{<+`D9 zENyBfpHP-rjIT?vm%+Cf@6mEPuQT`lx{!Yg={cXA544<3?|uFFp#30~XRD?Mu$yjS z>v{t0Re2~FrWkx!+$tCgBcy3KkB)&uxiWj2I2LaxK6u+BSm`(JPT zD^5gy1JcIp4ZdyHD|{V;?YBsL#&E1%vVqq+Y+Wt;5_`b{MB-3{=KlNcOh-67c)igZ zKSBPNNWbyPeN)TL#98{vd1+I|6*EyYUOH5*L;Ea{kf-k!oes+_QTN+mH+|)!0+v$YA+cI6oo1Crdb=ma+C!4mX z^UyqBgs-#>w7{|4DALWGn!~05CH1(h9RrK$(i4=5c@Pge%9h3TIBIlUvz;nF=CBc} zcp?8c@YaS(VZ6N&wAU#1-+Q(G^OYxhBWJ}(sT)msE?4d%{rm1O!NB{l(vQGbp359r z9vmj?+Jme&Kyk?m#6Sv4ZA2waVsXZTDo&o>h_~cMe6ie!mj%noMcbwT3dK^iZQKBD z!r#m(bGM9G`oxw& z?48X!cht)S1t}V$hiC&(KGOPoYi=_2xC;4GkWRbF)Z><$l#D^+EZ1$?uKj&7o9d_m zUlw0E&(rd{eDZ#X{L4tM_~iZP5z3o%xWHcz6xgHXrS=&;Hv{>(NHzP6yk+|R%zAWS z{&SSq(y)13Lw#GOl+CBIb2=eJYYrgi~J}YH%Kl(tQ`~Np!nhh4kVU-GfZQe*uhReGlsL z-)zc18Tt80i*7b}cHew>`M=^PL0UfJyVuTNk_(kMTi*w4Rnm@no;_TyLFiw0h7*+N z?^tqG5do2hkRvu_9)qQ*mKNb^^>fZ@A6EFfZ#MPy8|2?W`Y#{8zui1^eNkLra#LyB zse))-9YDj)W9zZL_H)`He2&w98JBdtxES~a^3PfP5#9f9G4*o-@*9xqZ!z-Eyk+Ql zPzJZ$Uf;A+rH8M+knSiYQ9c@uJc$*thI~mwNya7uiSE{N58h(R{WIkM6X_2=xv}pa zJ`M)1Cs5?}?M*vO%luxp%v@RWLljBZj=)-bIM6{w9H&M!LEC!s_PhoQg*%as>6HnPm)35BE2hlAb5nTHg;&EQyg zo5GQaLq9Oi8ySx3I$iBv0GdE$zX|}6#-SWwpHsAXlnRgwvvCzX4x4GDpd4HivCEVs z^NLB?1OsJK-8eCa0v}b21Dvi2j^Py|D=G4E<>k#2X%>diQ^hOzaXa!KY!ga;`RrGRHN`G&$V&%r7?8cvem({WJizuQee zo{IcDqy@Jd97}IkI0oAvr+#eoi;x$>vf26?))x>khnB|5fwo7>>+s2Y5cz{h&-mnh z{0;Kz>smLrG;QCoR3~iHdad@46gBrVz}B+ZK2Zja9gfra@_r+f;JsAkFT=x8|%~8eC_<{0IA7p+3WXOE>uTLy@MP|yy=i@ z=Qst$L8`??G-Y{o#POMe!8)E-OmnBfa~bmALAt?*=le&1r@pEA?2PB3sF67i@?^j6 zwS-8@www-;pyg)K38PvdRd?(0-)YAGzmWIt#PNTpk-zcI!{?2G@~NeydujFafaB>W z*rPfv_N7%E4@ToqlpplQLfoDN9?!uw_Gqk(=*)NvE-B^*CtF7a!(+WFy6K1iLZYel2iSw=X+r4A`P zGww3&xB~f;kWRVF;MsoH(Cvu5zIn}-hLf~*N~BIgOqFs{dC#F_x#K}+61Jig)_6Np zk1j3$;9W*PzJmO#NWb^VfA_AT^`oo}KY;jx7>|e8`daoW%BNh*C8!nU?fZrF_dil{ ztG{RDu0Vbr(rMo_a-Y)gXZCRh#;^33`=qUHTUIx0uTuud-{nsB@i^Em_KZtAIyur< z4MR%0FGX>RPeB0f!mzy5IF7Pf*;#B!_zc@|hj zmK_c_6?6h4e$Jsa@H<(cz8~uWdbcT87V!kQl!O}u##_85yD3R02*8u@e?DlSys zT(XHMv!sWWl}p$Dqzj6`Ph>*{n$_ir(C8XmS3B_n{M$;}3M+z=Fs>?-fYmi7!q{wa z1BbI<4zJ`dDHrk1pX&a9k15wO;U1sed(Y7QZ+j-uu!y%{#|uhB=0#6XT2R|X z%r3?DbSZwVJdMW@C6h*{{zLbFpZuR7|0|^5`Q%6Rh1o&x6G{2y694X5Zf6?kr3WXsc4&(4O39V0u~LqtKks-GiZs>~O2lsLrscyf&Ccv<0Fd#}+~ zrz5``>AZUlzE3p1P5)B34zU4#eN8P(>gu_=rP_&lk0U0=o^4=O2UPxJAyQ%>99OoiBUs_f7jWBY!^9h2Qtt z|KA_FeeiX4-R6cgoh%$BcYbSD<2-k|%>A;y4-M!@5^~(x*fO*liPB|p+Pq7IgE+)b z5+k`ZzghDy6`ps#Z|sy$kq_+W%-L`7EKun#`tL6fw0mVJ4&_Pm1}#W_fKAaQ*ozSr za5qn0Uavx>6|t+ua8W2#7LF-9mdK_U9D%|>m1{XUp+dQ(Sisov;wZQ|<9^FJf30wK z>^J@94&?7cdeDdSR~l!=@93-dnHx3{Op(46a3!0I(=)IaqXM$+DG-iEvr~{8%>r6K z5$32`a#uLzSZhmQCDd~jLAU!i3Qy`j(~gsoUx2jaK7;4m`u%*}jt4#;h-X*B?zWaX z?Z@(1K$>)SQ%4r;u2>SsSr&CWc~^?!pSyMicG(J`TqI>M!3)|6tluDAXh^6{S*$^; zFcXB0I~CY1tFSQFb9jN{v{@RUBa`Y^75-iy{tuD=6zOvx{_OjQ?uVONnwq6kd-Ylw zJcQKLzIZ}d9yt%@2wH?%j>wAB5pxkt$;1um((-HXH+DiR^5-G7-*4pKuH_Hrk0-;` zPzB01y#SlESekk-#sx0JZBk7*L?iS+XB@;RhcspOih({)N&lzr|M#1I^#$_c0qp+| z`1T7PP@f;neo{Ns{YX-!Wl^@intc)%P)N6{3v?W(b}eu11E$=Ykv|*he4o5KwY(XB zRdV)y{FQzqyG$3q7-YKa0{L7djkZg(DEv(kDAx*dvJ3$w2rZP_z$$VAIdtz}JRAc} zP-xMSP0wozSKkAsKl}^%-~rAe2Mn%72ZrtsWWOjia7{o4fnMJeU=L-{tdS#gewNA< zaV2gXdu<#I;39}&U#4JQu`DYe=M2?v9 zu?izdIFgaiqLVNl42tP8G|$Z(=jze$2$HuH}-6>`;2b_k1zpKzzD zS0Q&?i>ydaB^`@9EVY=Ii7uJ==P_W3)1VRdNQ_s z9#S@2-^`v#B*X+d=tP?yN9*MNc;ua0uKTc&TY~&Zq%jX0xhFsT&ErC92s!&CtA9f_ z)grl@*pr~qG0V;(uU8QkG$v%4G>$X@HRhU z@Lr1iGf3T!7`!*?yw`KW${xPe8(T5;t;iX$gPwE0~NM68cj+XwqvAD%FU^OT%1r!2FVn?mW-O~xpx|7@I$rb)w;zA5+@ZhguZ;$Ks$9Xbi5zvzD# z`elfyZQTdf{QxUn%E?j@f0A2Ia5w2p&7}i+yBK2jG|J85A-;l0b}kGP5Ob2&$!;t` zd#Yb>7{Ql`%Xy%k+iTziX9F(`mj&PF;oQ(OJh}m8eJd-)v*Cw8d6H`T^!R_&^y@O@ zMOsd0J2wn8N(i0e2}!54|WJg}3#zwaYG{vR{-v=I5_Na@E6 zzK0$=eEbhwN67QAovQEF-fnH+wWp&!XR|-%(}1HL4_bDXy8S)V2K+e{&zA93JUish z=%d5?Qp$^-#P_0hu)*4aD*j};mr^Q!XBD~S9u?+q9Mpd6IiD zu74hgf1>CA$IUuv1o9J*COvM-H%I4BAMCu?cr$E}#}x4-uI_Vb!~3d2@(1(C>d0(* z<0Gx*?tR>}`#$9FLb}%{x99Pp^*qVdp8lWG`Ya`zdtV{dY8b}jqGG1VL)|_`<~tH{ zw3R}FT>T52TwIQ=6Q6Ki%h;z1PyQ1I&p70#Bh7xoHy=JRv^~+N{9BIR-Yi2|q;4XA z^m1vvzFbJ5NJDb=D}|ZZoU4@^l9SBx^fn_)|3lAzJ{*rC{|wUeJ{&(gG90pM67dSP z)l$RWFHFb_V-&9_NEx)snR;|+x%p4}%8&dsq?u0|xl5n?Cb`WjoBu$`pMAaL9xb=y zNi)9gME-uH2Yqs%esX9%)Y#Opd#l{nNyIBrrb9BXC`!0tX{%W=N6Cz5Hs%kSa%Lf4 zgj9CW$UFAn(EU!yt7iQxf&w(R1FW-1&7Zd1k)z9aHpqyRVkS-iC&{Rj1vIaZE1w6w0HcQL{|7Q-Yp{$z@9d#sbZWQ^RrE63Y!cPAHO_u!FWk z8-zcw$YqQ5e5r7!e_-l!GxFP!ntxz$@7A~nJLepTx_aRRkF8I$he`y6k*5Of0?GD@*X$M8>-P{Wl&N||CDC~D*| z(EhqT8ppDy42}lmn~++cGB|F~?+<1_ABLl`epj8&c>JEqK|;GYFO|>|E{-6U_iyJF z;5tKsN`xtz@@(;-j(60@)Y7u|DbpVRB>rj6!cQAq$2_fZ={Psjk@TdKav(M959ksEpbeMM(LmX{SmhSDsD1DsG=5u!gh(y7(Nq zH*>$*sJV^Hm!NzOW6u@rqcSX{E%!jsXxS|$Vlj&$>?XXZNC>Y)(4HQ5t3vV<5i)r4 z=`x#VdnaKBxs!{#In3s5Vk~QSRXGkmYs&FEw_sZZxUzNV&?NaM?fL&j;G}gqG_^ zO0JmyIzWGslgjJZSFWUBwmI3CkF$#O8F0J)Y_F6j#KYh}gyddsevUF$-V86!Eq|aa z6;wKdpM^LTJ}Kw1C-nScJqbKe%9C2o;wO90FKzMp{wlW!H^1UKj4YKV_L%k;gc$~T zPhxo-ua&{#k$Y{Pkc<@-foWtF^eex_-}$7*|2FW~0$uOIzfn4KCjC_=0u=ShsNF8q56$F@441E zF3tqviU&ts^w*9sgHvD)?;%GDq_c^~Jh9JM_=v^Ay&p`k2hJu>gh7tS*)UEsSRFqm zipNVUoE3?%^o2a+OoSny%+pyCcr1A^I=)AH4mTy+EW^(5+x{$bZW4wKYhcsaON{Mj z8014B(fw;J7uAn28%-Hp~l_nP=jalnCpR z8(?iADR=9yUH6}XzZd9%Uu(HPS8~VVkjMKyn>NPsu-}R&`JhtPb#QWc2;M@@0r~Qk zd;$0=#g`b&OtqOW(}wkU0D5ak^jjz3P2>rSAd>$P|hcR_r ziFBn(xfea9$NibWR{?E$O3VG7r=;Bd`jHz&q-0U!KSK+&TFm)vL&JSlDy$WHD%B^> ztp0^E84Dn++W#p%e|7`^Z=nCVrWQ{y;V_F-f=iSs9)R343~$k< zuv9KCD$q0rjX0X)UQdg{U;DJiZvuV~(8W({{BJ)!@cg}@vRaDJ(9|3gA$DFDJoYsab?E63_F$92SxH5xP|QCBM<-F9d!G(DL8t z@>l-m1m(})364p9<(9b()ip7cV=)wXr7Qo(g>yIX2Y~K#;XHUEoP~2^rGMorokUdm z$9|*jpy#)gbs>Nrw3>N9uFvx7uzT2L1z}k6rp0&q#gx zd(MWtSF6iKCo6D) z{WBWB`gan)`hODlo#XDaHB>d$V2~#wuCrYm6!+M^F~LhrBYQ^0s{!nvR zdXjBm3eg<#zXDKJ1ZIs?LTcIj2D^o^`#sh&y3O8bji-smbY5)?WfN!?OQB;}4xKIP zF)~7p|KDjl{1)&Z0)6^B-46C4*$(~fTc~>~;t@*ZRO|(!2V6Ni1j}TPaLr8=4zFn7 zAy(`I_-a@9<%cwW74Y>yjfXV;&4&h_2V(fb!6?53pAh_viHD5$jLwD`s>DhT;zLAR zMEK(gcvL39e+1T_n;{?!TksO)^6)dfT1H8^j=JRf3i)SY9r&!4Yr?bgFJkw1Qu@B{ zBA$=6(U;}Lf=3K-`tOC&VIi51jd%PaePM#=1KtogCm>Tou9WKl4O~U-;n06p09{5s zL!sS@rF{FIb)9e(R$Y{X_9+ppZ>45(~s3A4hKJo-Ma&_!y|%WUpx^ zGQ2M2p*$%kH;nV)(lGoU|N2{$U+kEJmWqS5bSciPvARr0h0>R~RF#rRL3) zEunaoqIH6-hv0L%9wNXG2O9O9u7^j|_x(NxjBTN0wy?{=D{u3Xw&F~l=p=FVcZ-x^rb7hdtO9@(LI0F9_bKBxEE`%}Hi(DVyF<5}MTQFWr)uZ?4wcQQ^ zpA8gwUhBK#d8uztT>iK`UyU`*m79gz)1zIaUXP#GfbRl&$EC;D&ksC))NZZZrs$$#>HB#JW(x^|4vE$o%=QJ7 zE!zPxe1yC}@z4jn%4ewg?++S(9q{J^ZTo}9XD>+ndFq_oJKx0h8{DN9$$D`9>tc6V zZ!p@$Zt;qbPhlGDOe3A+^2C;;ZKbm7p(WY7)a%D-(D0XfK~Tp^7So}ef^3d^2!8c` zwV9VW3=d@#iZC$3K5_Zp!NTd;_&CnVu`4l%{R}8te)R@M?<-_z_%ZX-@G)k2$yy3QmvR*1)(DhOe{P{r5FX(!?^o4=vqpflo zR*rk1dnce7lUH#lZl2F(iA24+6<+5H`uWYfz<&nxFBjejl~TLEd+eLGG;9F={Mafg z8z!K?;VhI3jtC$R;e?ALWzKnUqkBcf0UeCnY|hK&Qsf?UeZa?HdVvSvjGy#j`N#?z$*>Yhp-rJFq$2>kARGm=Bk@ zWlJP(ZKrORUBF)j^j#P3;|jOG=W5s{O6`iB>uJTcxb3nOXgt_hgS1V`_S(=E(i($e zMcpHAakBc7uSrI=E$9sXkG>eBoxwYp_^20~o$pN=$CAMAWAf$E++vHVWld&5UYKIB z71Z*ku=CNv8@V2EGflsd7y_fcm3J8Ql9)f!xVYXT3G4c$C2MVV6F;e9O_BVCz zsAZLE|ChAfS-_708uyZx`^=Ymw|`&t2@7YH8yG`yV;Y^yv6s#eclVx|k_{3sz({MH zu`yy7H3EKF1|P)|smJ!)w#Sd>_D*LPvHN4qO~@K4-+`BOdv^f;63|~=@_q4A@Af_x zcMr9;a(hk9&S*^|{2;Gdw$dkL7|qkfdkRe3VBe-dA!PLpz#zO3!Z3gA})t$A6>f^x;rw@th1tBRFS>v7RnF5+60;9<&Vrk0SX zDz{aYf#n_m{yv}wT;;~E`;RO4wECzhS!@CPX=)aeH@8|<`Q0zO_J99Oi5DpFXI*~$ zI=NT*Rh9LtW$7(cYzXb0RssXr;+DxV-V6TS>1zJ_v({r9@OywR{QmjI z;AHH4P-y=&SL}Rzl_3`dfo}(T?MtAD0;Wg>2k?}G{FEGcK%U-h^=9r!As zO@GyLZvLy3GnTI)`~6t^if0@>O&rVa(?$Qz#GZOFsc1JyEfAT?He+V-Q;cG;uj`ck zci}z@{9k~MxNu+Z2e+ZA2ePtpQ(utv@sRR$uEZ@ltjEnv;1>cdIjnKdJ}hw$z1nxX zD9})3bRLaF$c75CAq4g&Rh)3g+g>X7a)rWcJFLe~JMfPK{n~|h*osudKhfZUcGt#zR;zwT5_>+L21GL~3jbHo9 ziSV&y*Kez@+bM-;lb1Rdkqs~@Tt~wWW20c&V$NycHg2cMZfQbz zfP8{0u=3zNj}^iD6cIHhgHI5#JTTWeGsVj`JsBK66HL4oRLTxmM7~<8mH&H0%YQNO zR|B;k(emfND!=dV{FvBhK*8JT4PNnxwTf(L^^xmX*zY*_5Xr-nlP%`0m@k4yjutUT zGAzw`z3?b5Ix$+=*i=(p zvtiq&?ZCm`dNXi?z*)q+)@tt(Hl#4IbP`^RgJrB^ zB!XKvpTX+U&T-7by_B8JN{vurz_$!%d+d0punp{7_G8LM858L~>MiyhrcRx$;_tTB ztNH&mJ>M(_emT&}*YrHPub*`czE#(4$2o?Q4M5kyDvH6{HWO??*!1|-3KrK_+zfNd zu};C>HYoe|nznz>0e=|iwbyh#ex_vDsqz*@WBXMy7)f#Su4v7cy86xHT5~sjMxKq` z2ByIvpTP3&45+`$DGbNaMhJ%EnHYv>1Y5}7p?s9^dCyn+|IKv|7WkDwYyPJ7?>Ejg z#`23cHx>iI{|u7qAh{eqf~wqBSGhk1{(hhbUFCN7Q*P17Sji)BPd`@lK9$a%L{$05 z{-)b4>2*pnfpT8g^*8kOf&BzGPF1Ba>1AVQVeGZ)a&jdMkrImG)>%ZtlBmM1eO>Ey z5%Avvy7cuE*H^TU`nnN5T2#3mu5w=i{xzUCULQ<-Mf<9+{jvILRpm$C(B)4Cek#z6 zH%=_~);{EJgO4^zr=F8DB)eYokw;J z+|D&Sn``Q;W$HsTyXB9`&5-JD@Hd=%uqO-#sVUAntc2l<*KE1zN$_Nv9^0@(AkI>D zHzjS2s{OmPzI%bc3}|1M*0;a=;zc8C!I`TEWg8lsH`nYE3U3UOgC41HyDGoaRsN@_ z>zlAXc~k4VN(J1HVxp{t-n|KE0Z_>-4EVRP zn~^)c`M6Dq^Cr)MZjUapY05kq`S>2N#BWWRJHxTjkrqFP#J708*W%_Zkoh|pnszC@ zK*$qmR{qbMdVTc^;GY8etxKO5ls@tMMZMM!cxPHZSHW=_35)o!wPhHaHzdQu=CeHU zXQV>mroW|e#{oYL=#;lK?t-@lhpY3A#X@7&mXPy~kBr%>a9iKf?ROXO2Z4U&!ZqKP zxUsmHzlzHn(d1SYoP-s^NBCGC&3cW4L+xPNOngR=fe#&$J#4W!qnaY_c4Y8j95>QZ z(-OrQRWrv!J^oiHD`n}9nIB2_h}<8~&?Ns9FK&U{M%e+%%8UbyZMSYwi(`0o>{RQ& zw{<->1HTXG>bJE%zgPOi?m<__-GlCxvMn6lhZ`a10zHIVBeyeB+iAg&&W4#O$vd2x zP6it-FQtfwC<$yB%wkTaSkou-RBk4C>=!BZ8=eH*$Mq)!U`fDXqC1P|R+hYpw^MDq<}+vorbXemy`$&(UjqLO(C=ONmUz$Ul?f6OH-W&gjIZrt6=!Imf;y1 zQ1TcLgOpK>-h~g{hA|lktgJ=Nd#ZfI|2FV90p0Ave@1;DTL)CX+q<4HaF1CVmX9%0JOLKAZ5vl8b=EE_PBOQD zOUe~|U)Re>;3oi0d0)$Q+WURiOV7Ro-UF(NZo|VNbz5YJ(del#R(Fx}U^@DWW{LB* zc>z3D0HYB)T?WhJ%(n0e@d8y#UKzaBWIDk6gUgvYDm%?g6%NBR*33pxd7rxT5>*dJ zbv--?{G&j>P`_iOfBmZ(E1PNw9;D}E9dcff{GIV+KjvMK<&qDyzRAGn0Ofz6_1*J9 z-}79oe2kyhSR;2BO0G|a8V2*Zr87iw!)z<7AMoG#>fct3IUd_#I^n+*te_iX2Rqxp zBlS4+f%fxW1K#{QC7!>#{Di+tJ@)-e%3l&cZ`N(X1LCsB=C!d0sEFqI85bXalRv#J zLwvR}@sUNgv?r6(i=iWr0}pTwbEq>c83uh4G_1)YJkN_4CIf7UKaJrH=TXdXX8LpB z=W`fKw$R>#c~}g8$H8Qod7z!g=QVw)W*X*bH*F)3WLFRId)W}n%N$rBhB==7_OMOf zcFHD$*-qz$06ia;?G>z+!{p};SmN+aS|RjrKgSdx&Xhz<5yH)+fKixedu+bUGQ)P( zNai@^CDfjkNXV}#|AoOmqx4eB+bBz?KQ!qy`hCi3sLj7ijh=iwT{o(A--o)smjQn^ z(E1Nu{pLei-?b_)&T;1i>Na6ii0CHFgu%<_fm1yNsP~Zd^j5B_y|msMmhw z2YjTBl z0DXOuu3gpXl<_fzJZU{p94zZ|W(3WKa1K72>7BRsK%kF95peB+K6rjg>#Tr~GnN zeuu04!@$1^^!iDb-_%onaZmXzs{F{OEZ~A?>Q%ovw1f3;cCJ zH=Ja-Q)A_hFCks3+)h`yM}hwk=#!HycU(!V;E6r;5&VHHzoc82zXD!<)T{vqI>1A5_P%byf0e`Zhl(VuD)0?LbhvQ3fPWk4z5f%AyDd)d!Rb^uC11)i5oZSQ^MMw9sr}xS>ihWh zSVNP0DH==>7f>5ZNG67EHVp^QB#RT3x2kskQv28U0{=A7?_4+^DV(*+ua4ix1+a}f zs-<^bamsos@=BZuGz_!j1Lcs$c1A{GXti{)0hP(JEsJ@ruzxDNTd>yfhP{b41=s&8 z%43PpOKwyB{$IKtmH@vJ=(K-n`F^0jkL_PP^6qi+^(1O-r5~82xy2$Fk4MC_urkH< zPi8t^%g1whW5|mO=Aj-o6eK;J!s906VKj_;D;&8H%hNf4qwvVTHC`(4xj^~<)_7z7 zE%Ex>@9Du4T}>Wq2$JpP(t3ew2VHiHbC5}3%=aD$b?dp3*UVcpv(e~QvF(sH-5dr*Fv z!cX`LY#vbVR~moBR}z0;SKs)X8XI;9{PiMUKpTBk9`8>eJ6jl8HJw?2eXgBANHbqS zXOfnC)V%+d#=Qji{Xn<4aJv+4_rE1x^viy55w(+kL0_b_leQV+W3NGWwmYPDF=`&f z)AqxhL}p}%L6$_enI&+%9y^@nW{wLLKu5*P1wl531~YD;Iq=^dkH=%Bb2bS^(Ib?9 z#prOpiA|%^c&4rPBirv)KVtBvRkBTP*;3a^WHQkKFqj69Y?BSgOLm+~C?kIVi8{~^$)E_o*W zSIRR(-Md=!?>^*-HZ*Jzfj&{F=&y|i5xR7Di%Bl07;(@Lx3B%;n6V^`ubafUIo6xb z1L7M@<>KS1JkglPnNe!nsW!LsY zf3^Hal>D)K2*<@0iph_G?}e56AzmE+8HnF)kQYGwIZOmf2#Zrbyp zlIIMy4H&94iI5BUqm-V*XNZve(RStc{ZGp`2l!<`<^R+2ZC5vr`j2-F@>Nw<)z&oD zY^)Qv48mofq4^w2cEdz;BMS%cLP(~FID$_F3+x1cCL6(qh-VEx)6Vh}GLflzXnRP_ z`!2a&1^!*24_tDEz8<_>J&&2npTUSxbI5KmCLJu_84J@+p19P6XSMR;1@qZ7fDPJ0 zSsNqrRrXUUU&YtjzU~J8QlNcbYxy2f^7R{Uy+^+FRUn_(PcQoj>ut2Cw|7|BNrg^0 zQrv0CVy0<(hp|XvatdZ#0P%bQp9oZNjg&0mA>U}ZF8@Z#wMN;W zb^qx@uGm<~Yh{N`abNLYhWH4=pz)G@#!?4^+C=P#t5UEk>EXP*IYgLXckn4aeoSugulp5E*G(la)u+UWPVu=2k& z#K#D-yVW80z#J2Revyb7(^!!|F_wjrjg=`$mQ8bli z6Zz`yQ1d^?6Kj|60RJPP`>2+87?bkerQ!e{_Gk4W@5aW;t?I&1nYbvFFW%oW#mCKF z=!QvTpFLHC{IYnE8&0AVQHfsJC9fFJ3d z=y>5j_*kT13=a-9Is8{A$2-0W*1& zZ=QF8F_K+I>2_l(n?i4;b`}#q|CGXy2Pla?tNcIEJ7&-B0lppR5vJ?qh^m)G{oHGi z^-^84QMO{Z>?)iFwn9fWNT(C#MNSG^0G(~Bndmi*5FWmuA(53O6bno}js26dYNB4x zDf@3|xn=^t2xyt1<*GFXBUclqOOwxv?xrF@=x*?qzI4JC&QDW~LqiYY*k9W zI0Ku{xy8BPo5U{1uqpU|y<;uBOP|k6fWRdVVC3O|i0GLCQ++x(0U0dA0gn!TzYP8& z!^v{;@t8mLjPp}_fl;TLS|g{@D*1-d`H* zbl)2^(9ZbB2D^u+-bRz*cV`+KNO_mC1D3A8JAl6n=tq`rpZNWSo_ed>f+_n59uM0c z1hZ-412brMRc^PX+ugQ-2THMZyNtGbkK_3D<)#J^QCGxG5-XpIQ(^qnf#*)iTmB+$ zGs7u~oggu$a5Etlmq6=?dX>DX>_6bd{G#swe=pDjE;-&)a`fvL)i&bkRnc3zXzrxTSlzGkOd;*mT5toT6p)ti{6vh%ghvvIi1VQ z&8Z?jjhZ*#Qsdvz?Xn2?(}B)%wA|OL?_>AG568{3=t`_csaHoU>zkxg@h5pD{2m5Y z+9V$(fKy=Qf&}Pr`oQ&cSRT})*GS67U}c#s(+v5+yYtM0dM-`H_xZMs=Ku>BEORe3 zE}_=9s8K3T5R|>E_CH*5{}*_}1LNJJeH7k{k=jfk7Jz~zU z#|^8Kv32xXN*56IYWqOy5%Dros`Quw{9K@gUaiLpuNp7?%r|a5M9#@p+90+na>$-G zN}3B;4MsHCz*J({vcF5*{ZQ^Ah5I1zzXW>Hh5L-cePW@W&vLeG~Taq=lPW#Qu{y$UyrjxxEHfwS948sgU&|Y z#-@rBA|3MBNE+D#E4BS}9CSI$$qY_q8(BeK8X@PgZ&MY4xBO#e_x-xR-2;3(&?7E+ z4k>xos{N=){QO+GL(0*-H7d;WRp{TGL-v55^#Yv(HYI~ic1(}Yn$8*8=F2EApl6cu zPb9vRz-0_wNDU26R_~ z*7LE1xO#sh4o`wK^x&eh9rPXgB&8j69#{piIcz%2)-bC(E7)jHfaib}1)uym%1dc1 z?s3PbO7DP{rx1Cdi2*Ioc>yWUK^2ECdUODJ8s+UlFzw%#3&r(N|C}6z)sijFh>JMH zrVl)jOg7rV@USHeQ*HWe%b$&ADj|`NhJ}Qk;Khu_&r!C^$Y*0{66yGdl=q-Z-j{%X z6X;!+ymn%5dCT7GqrDo%B|%pfed875y9RAFegqbx4W=SCE&vlbxGt46&pHRVa_;pO z8|Qn{ympcu^5OP1UkNi8A7zL%y`@j38jkP%p6 z_sEeSlybz*|Ht27lS0%r%ae>1`7oG}769c!C!^#y#xT4*Y5AcMgU%$DOl_a-gUJ|t z%W1fOE9IyS>Tz`;@Yeuc=aS=IB}Z(0^)JVGA;<_20BHq2(jj|b^>S1Qk|qR6cc!v5 zAqcFoZ=`GqDgT%9|AM;T7)gvI0)>*a98;2{9M7wE+4EjM_JxR}jr&B_*mAO`n~_$& zl8wMDjeG)h^I~daNE=VcVy124p<>$%Vs?ikl#K%Yj!Ai1l63pr2>e|@2VC+TQu6%j z{eI=a(eHW`aI1V2@Jr~z-3ED>PX!O47(^+yCSY_a^hFiJ9uw z3)#B=tJc5Cdf((J;9mwh?2_vvC0Fboe0qHT2|e7wTuu_!@&fT57QN^zUMTKsB=N~? z49lRRE01Ouvs`%~wex>cj?$3s&kKRC0ICjYIW7oEIUZ5{c+V^G_u3M6eVe%HPAbP~A;%;&No41h2!8z-Q>a8eSIFqhN@HlN5>3zc#lP&g<@ z2k_4V{lO*2U)1;gtzYmtrHJepTQbIiNw&~3a#4J?d9Y6kH+=XfV z)VI24xwU3%)s{wqmn|NRBHndW#LYB<0b>#&!-3x-u}7DO@M4+c^vPAwWf8jaw2PxIgc#tk#Gn!$e#joEW~u z2ab4#U>Fm5?pqb!&ahtpUjzJ2KsUSa?pApHJ$J?n<@J^I4fq3zMQ!v5CEw$i7c6Xe zFeTdf_h?wx@Ba`Zoe`ccvGBeBb0Q12)mPymUW{)OBzvJ2M?yhes@z5Cx_@o} zelt)*y4L4H^?kqjC>t;x~ZHOdO+`PW=Vorfs9fEM^2`(?`VO_K|wX6Azi zfx?}5^qn<}C|eFQoUxcHe6cw>V5Vji8mXQD4barYhv5$$Gtsu8XC5*5D0U}hr_wdX z514bVeJA(B>S+d>&1#a~Vcr#<+tD(21!R33&d}}rA@H9A9m~-5K{921^taE6t-YY3 zv3#y;1nq^+btG;CMG{r}XX^2DF7TUxHfL(Qrp$rIPpp5fkPkFMCF5ZTc>%JVyug4VGnd!Fa-U?hgFQjT$NiT0 z_`dw9NW6zY-WD%;!N>zAG{o~oK-pCo-ht1+;NI3HlzCEeoHoXniuih$QfB%ySjfJ> zHa)f{l$gdsAv^3RWI1~V_u3|~iS#-O>ovN?*>0asNLcDso1^Rd0^qL(x;97a^~0Qj z=d~)V?0Pvk!jY*k9>=LLy(yprxKIysOpTR`FH6OZ*8t#XKe=lQlM|U@P4T9V&|I< zy>>j_78o}o4s0i_5$AiZVB(`xyeESIod)Ryvxs-iE2!R%FlwOfnPjV*b9p}a=Dq! z{8kPdVJ6@;@^x$?k*}6)rGG^0-w1pQ&}AwOOERQfK#sI_!8?NpAmn)mSbeTl*8%woQ#b9 z+d?ly=e4#5lK4rjAO!1@9o<0gi;TFySBq$5|#5zW{8o0kH= z59m8CIew(%SkqrztD4H{?Uk^iz=LC*6vqH1hs|Lkr`vE0Rq9PO3||80)V85Tek>o~ zlGZ%c|MPW!unM5>1Emyb{DOjk`-50MY^{vO+9Yxgn4sy>1nsp(F`qTpDB#QviFgKu zq%5NBUxD_|z6Ja(KzF!spH#U0#f5IH*&${)^%O=nMKLzQFnsgl+pA(T#!D`xT?Uzv z%{apZK_+)ZVq7Q97cLTD}zEhXRc(bj|mLQoh)^(<0Sh zg>b94)Wmv6B8u=A(L3gl%dvNCz@SQ|l?g&%QXq_MJb{^Z7G`fw^r4kbWG$2~VUw`D zib5&R{z5%&+JXNC(Bm$7o>lVn7cX;DLu13XW-wH%pu-4nx@0sAoDz^JO6~%0x(K7v z;{n{sxJ^eo6>e~du7@JvCj(6%qH${g5<%_0hYZ|KunfY_#$~ZU)ZsRIwS2z!D=-(> zGEdNK3xjrhVW9X~BKM19c=(RNl@eGwH}ml@#`QD-EE>$XKV?iN<%U=LP$}m@B?rp+ z9Pobv`m0OMQ-;d#W9Ki+#w+?G*5L2Ly^?gt+&0kjOVe6I%<5v2@Uzz;tsCg4R}=%+t|Dv;ZG2>ahgE)rtFSZ}S-DgNu4^5w z?7vIiZ-Dm?XC!I3mUrv$6U$rOu%o_5;#PW|*w4I%gT$>SY2hd_uIf@bdc9_;IWC2b z!r#HqG0uelVORmHN1G|;WYj`xGaR)^71z9N@s2HFg0*_p0KL#+6w-33S7fZzt7EwK zD_;iwHJ~?LdVQw!>Tlg3LQaE8RZpuPrn9_cAMK#zzmzjP1(r%@S^*4#h!43R>X}!& z6n5zlw4zl!CD1iR2HH2 zC{UBGfv@L03MeZ0t<1%ir$ zJkZl7vU%`t8Jms=7{$RJ2UGqyCbM}OTP@U?!m{{0wvMe~vuLiB%<_sb_s(RV$dfrn z{B(?DFk35y)k|ayN^bI6(5pj0O>8CDws2}doXpzEO~c8z>1=xewR147g>BCcfm39e zW&nr}6-fkl@y|{6SIQot)~19qZzqNiXOoSoo*Sq?&o_)8p>&$`U)raub^k~`FFp_a zD?qQ0)b;p@s>j&;9RGY+)Z=U!j%LobjT>dR3$9G0!Bc=TWas~t6Nbe>2t2xU@Z&(# z7Rt*+Inf!){*BW8Yz^?|0BsoM+HV>q<>+t!PW5|n(n{log@L)Jd3>VCP zz}X5B6RCTa@_$Eb|MxQBzX!B`w3hpRC3k=RuWY|)RNX~tr7y|YFE`-mY%$1fo>@?9 z3uuBhm4)d{V}Sv6cO_%niF`$8tNoAB+7C`01APi8dyK38#z;B(kAEj55l5Lu6vuqh z3J{`#yzEJ1r{IN$WwGd1V3!nbbd0tGt-wDF^m7;PHwyPaKkH&Q?ix%2KB8ELMF%G) z@(qPm(KS?j+#o-`Wa8u7SUp`9>GBl7j2hyT_)?Y#hU^SzxDfR?4l7}p(~5(I$YDW> zK{n>FVc@ZbsfQ*|jG>-x+D2lk-)G~l)kgL>2PM;3HeG@8mCTp=l^5%E|M|dg1KM4z z_4`4w)bFl-;=}f#A8s|lAGc!PY{iIcU_=ZL$M_f}EXnkycoO|y2PRCP5j4|aDM?u= zDO;e{zs1^Km}40U040yr@??&c^7Owid7M1;H9JiE+K>llb#rLW+eATPt_sqDDN%ZKdmkX$+!eq~!0u5L+uE4f%2S%0DNOa<%>) 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�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�^=x_djZxBCXo2QJQ2>^) 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 z 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