couchbase 3.1.1-universal-darwin-20 → 3.2.0-universal-darwin-20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/CMakeLists.txt +3 -1
  4. data/ext/build_version.hxx.in +1 -1
  5. data/ext/cmake/Testing.cmake +1 -0
  6. data/ext/cmake/ThirdPartyDependencies.cmake +6 -0
  7. data/ext/cmake/VersionInfo.cmake +3 -0
  8. data/ext/couchbase/bucket.hxx +47 -28
  9. data/ext/couchbase/cbsasl/client.h +1 -1
  10. data/ext/couchbase/cbsasl/context.cc +1 -1
  11. data/ext/couchbase/cbsasl/context.h +3 -3
  12. data/ext/couchbase/cbsasl/mechanism.cc +5 -8
  13. data/ext/couchbase/cbsasl/mechanism.h +1 -4
  14. data/ext/couchbase/cbsasl/plain/plain.cc +1 -1
  15. data/ext/couchbase/cbsasl/scram-sha/scram-sha.cc +30 -36
  16. data/ext/couchbase/cluster.hxx +40 -22
  17. data/ext/couchbase/cluster_options.hxx +7 -1
  18. data/ext/couchbase/configuration.hxx +37 -16
  19. data/ext/couchbase/couchbase.cxx +1145 -291
  20. data/ext/couchbase/error_map.hxx +1 -1
  21. data/ext/couchbase/errors.hxx +25 -17
  22. data/ext/couchbase/io/dns_client.hxx +3 -3
  23. data/ext/couchbase/io/dns_codec.hxx +4 -5
  24. data/ext/couchbase/io/dns_config.hxx +5 -6
  25. data/ext/couchbase/io/dns_message.hxx +3 -3
  26. data/ext/couchbase/io/http_command.hxx +70 -35
  27. data/ext/couchbase/io/http_session.hxx +4 -3
  28. data/ext/couchbase/io/http_session_manager.hxx +28 -19
  29. data/ext/couchbase/io/mcbp_command.hxx +51 -19
  30. data/ext/couchbase/io/mcbp_context.hxx +1 -1
  31. data/ext/couchbase/io/mcbp_parser.hxx +4 -4
  32. data/ext/couchbase/io/mcbp_session.hxx +91 -101
  33. data/ext/couchbase/io/query_cache.hxx +2 -2
  34. data/ext/couchbase/io/retry_orchestrator.hxx +2 -4
  35. data/ext/couchbase/io/retry_reason.hxx +2 -2
  36. data/ext/couchbase/io/retry_strategy.hxx +1 -6
  37. data/ext/couchbase/io/streams.hxx +7 -7
  38. data/ext/couchbase/metrics/logging_meter.hxx +228 -0
  39. data/ext/couchbase/metrics/logging_meter_options.hxx +28 -0
  40. data/ext/couchbase/metrics/meter.hxx +49 -0
  41. data/ext/couchbase/metrics/noop_meter.hxx +43 -0
  42. data/ext/couchbase/operations.hxx +4 -0
  43. data/ext/couchbase/operations/analytics_dataset_create.hxx +16 -12
  44. data/ext/couchbase/operations/analytics_dataset_drop.hxx +11 -11
  45. data/ext/couchbase/operations/analytics_dataset_get_all.hxx +6 -6
  46. data/ext/couchbase/operations/analytics_dataverse_create.hxx +10 -11
  47. data/ext/couchbase/operations/analytics_dataverse_drop.hxx +10 -11
  48. data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +9 -11
  49. data/ext/couchbase/operations/analytics_index_create.hxx +14 -13
  50. data/ext/couchbase/operations/analytics_index_drop.hxx +18 -12
  51. data/ext/couchbase/operations/analytics_index_get_all.hxx +8 -6
  52. data/ext/couchbase/operations/analytics_link.hxx +39 -0
  53. data/ext/couchbase/operations/analytics_link_azure_blob_external.hxx +145 -0
  54. data/ext/couchbase/operations/analytics_link_connect.hxx +14 -12
  55. data/ext/couchbase/operations/analytics_link_couchbase_remote.hxx +220 -0
  56. data/ext/couchbase/operations/analytics_link_create.hxx +128 -0
  57. data/ext/couchbase/operations/analytics_link_disconnect.hxx +11 -12
  58. data/ext/couchbase/operations/analytics_link_drop.hxx +130 -0
  59. data/ext/couchbase/operations/analytics_link_get_all.hxx +160 -0
  60. data/ext/couchbase/operations/analytics_link_replace.hxx +128 -0
  61. data/ext/couchbase/operations/analytics_link_s3_external.hxx +122 -0
  62. data/ext/couchbase/operations/bucket_create.hxx +8 -8
  63. data/ext/couchbase/operations/bucket_drop.hxx +5 -5
  64. data/ext/couchbase/operations/bucket_flush.hxx +5 -5
  65. data/ext/couchbase/operations/bucket_get.hxx +7 -7
  66. data/ext/couchbase/operations/bucket_get_all.hxx +7 -5
  67. data/ext/couchbase/operations/bucket_settings.hxx +40 -49
  68. data/ext/couchbase/operations/bucket_update.hxx +8 -8
  69. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +7 -7
  70. data/ext/couchbase/operations/collection_create.hxx +11 -11
  71. data/ext/couchbase/operations/collection_drop.hxx +12 -10
  72. data/ext/couchbase/operations/collections_manifest_get.hxx +3 -3
  73. data/ext/couchbase/operations/design_document.hxx +2 -2
  74. data/ext/couchbase/operations/document_analytics.hxx +29 -36
  75. data/ext/couchbase/operations/document_append.hxx +3 -3
  76. data/ext/couchbase/operations/document_decrement.hxx +3 -3
  77. data/ext/couchbase/operations/document_exists.hxx +2 -2
  78. data/ext/couchbase/operations/document_get.hxx +3 -3
  79. data/ext/couchbase/operations/document_get_and_lock.hxx +5 -3
  80. data/ext/couchbase/operations/document_get_and_touch.hxx +5 -3
  81. data/ext/couchbase/operations/document_get_projected.hxx +10 -11
  82. data/ext/couchbase/operations/document_increment.hxx +3 -3
  83. data/ext/couchbase/operations/document_insert.hxx +3 -3
  84. data/ext/couchbase/operations/document_lookup_in.hxx +12 -18
  85. data/ext/couchbase/operations/document_mutate_in.hxx +13 -18
  86. data/ext/couchbase/operations/document_prepend.hxx +3 -3
  87. data/ext/couchbase/operations/document_query.hxx +39 -41
  88. data/ext/couchbase/operations/document_remove.hxx +3 -3
  89. data/ext/couchbase/operations/document_replace.hxx +3 -3
  90. data/ext/couchbase/operations/document_search.hxx +56 -61
  91. data/ext/couchbase/operations/document_touch.hxx +3 -3
  92. data/ext/couchbase/operations/document_unlock.hxx +3 -3
  93. data/ext/couchbase/operations/document_upsert.hxx +3 -3
  94. data/ext/couchbase/operations/document_view.hxx +23 -23
  95. data/ext/couchbase/operations/group_drop.hxx +5 -5
  96. data/ext/couchbase/operations/group_get.hxx +7 -7
  97. data/ext/couchbase/operations/group_get_all.hxx +6 -6
  98. data/ext/couchbase/operations/group_upsert.hxx +11 -11
  99. data/ext/couchbase/operations/http_noop.hxx +6 -6
  100. data/ext/couchbase/operations/mcbp_noop.hxx +3 -3
  101. data/ext/couchbase/operations/query_index_build_deferred.hxx +6 -6
  102. data/ext/couchbase/operations/query_index_create.hxx +10 -8
  103. data/ext/couchbase/operations/query_index_drop.hxx +8 -8
  104. data/ext/couchbase/operations/query_index_get_all.hxx +43 -39
  105. data/ext/couchbase/operations/rbac.hxx +40 -63
  106. data/ext/couchbase/operations/role_get_all.hxx +6 -6
  107. data/ext/couchbase/operations/scope_create.hxx +10 -10
  108. data/ext/couchbase/operations/scope_drop.hxx +9 -9
  109. data/ext/couchbase/operations/scope_get_all.hxx +8 -8
  110. data/ext/couchbase/operations/search_get_stats.hxx +5 -3
  111. data/ext/couchbase/operations/search_index.hxx +6 -15
  112. data/ext/couchbase/operations/search_index_analyze_document.hxx +11 -11
  113. data/ext/couchbase/operations/search_index_control_ingest.hxx +9 -9
  114. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +9 -9
  115. data/ext/couchbase/operations/search_index_control_query.hxx +9 -9
  116. data/ext/couchbase/operations/search_index_drop.hxx +11 -9
  117. data/ext/couchbase/operations/search_index_get.hxx +11 -9
  118. data/ext/couchbase/operations/search_index_get_all.hxx +11 -11
  119. data/ext/couchbase/operations/search_index_get_documents_count.hxx +10 -10
  120. data/ext/couchbase/operations/search_index_get_stats.hxx +10 -8
  121. data/ext/couchbase/operations/search_index_upsert.hxx +12 -10
  122. data/ext/couchbase/operations/user_drop.hxx +5 -5
  123. data/ext/couchbase/operations/user_get.hxx +7 -7
  124. data/ext/couchbase/operations/user_get_all.hxx +6 -6
  125. data/ext/couchbase/operations/user_upsert.hxx +9 -9
  126. data/ext/couchbase/operations/view_index_drop.hxx +10 -10
  127. data/ext/couchbase/operations/view_index_get.hxx +13 -15
  128. data/ext/couchbase/operations/view_index_get_all.hxx +17 -20
  129. data/ext/couchbase/operations/view_index_upsert.hxx +9 -7
  130. data/ext/couchbase/origin.hxx +14 -10
  131. data/ext/couchbase/platform/backtrace.c +1 -1
  132. data/ext/couchbase/platform/base64.cc +5 -5
  133. data/ext/couchbase/platform/base64.h +2 -5
  134. data/ext/couchbase/protocol/client_opcode.hxx +7 -4
  135. data/ext/couchbase/protocol/client_request.hxx +2 -2
  136. data/ext/couchbase/protocol/client_response.hxx +41 -16
  137. data/ext/couchbase/protocol/cmd_append.hxx +17 -16
  138. data/ext/couchbase/protocol/cmd_cluster_map_change_notification.hxx +4 -4
  139. data/ext/couchbase/protocol/cmd_decrement.hxx +10 -11
  140. data/ext/couchbase/protocol/cmd_exists.hxx +12 -15
  141. data/ext/couchbase/protocol/cmd_get.hxx +11 -14
  142. data/ext/couchbase/protocol/cmd_get_and_lock.hxx +10 -12
  143. data/ext/couchbase/protocol/cmd_get_and_touch.hxx +10 -12
  144. data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +13 -18
  145. data/ext/couchbase/protocol/cmd_get_collection_id.hxx +12 -15
  146. data/ext/couchbase/protocol/cmd_get_collections_manifest.hxx +12 -16
  147. data/ext/couchbase/protocol/cmd_get_error_map.hxx +14 -17
  148. data/ext/couchbase/protocol/cmd_hello.hxx +8 -10
  149. data/ext/couchbase/protocol/cmd_increment.hxx +9 -10
  150. data/ext/couchbase/protocol/cmd_insert.hxx +9 -9
  151. data/ext/couchbase/protocol/cmd_lookup_in.hxx +12 -13
  152. data/ext/couchbase/protocol/cmd_mutate_in.hxx +11 -11
  153. data/ext/couchbase/protocol/cmd_noop.hxx +16 -20
  154. data/ext/couchbase/protocol/cmd_prepend.hxx +9 -10
  155. data/ext/couchbase/protocol/cmd_remove.hxx +10 -13
  156. data/ext/couchbase/protocol/cmd_replace.hxx +7 -7
  157. data/ext/couchbase/protocol/cmd_sasl_auth.hxx +8 -10
  158. data/ext/couchbase/protocol/cmd_sasl_list_mechs.hxx +10 -15
  159. data/ext/couchbase/protocol/cmd_sasl_step.hxx +10 -12
  160. data/ext/couchbase/protocol/cmd_select_bucket.hxx +14 -18
  161. data/ext/couchbase/protocol/cmd_touch.hxx +8 -11
  162. data/ext/couchbase/protocol/cmd_unlock.hxx +10 -14
  163. data/ext/couchbase/protocol/cmd_upsert.hxx +8 -8
  164. data/ext/couchbase/protocol/datatype.hxx +3 -3
  165. data/ext/couchbase/protocol/durability_level.hxx +2 -2
  166. data/ext/couchbase/protocol/frame_info_id.hxx +4 -4
  167. data/ext/couchbase/protocol/hello_feature.hxx +2 -2
  168. data/ext/couchbase/protocol/magic.hxx +2 -2
  169. data/ext/couchbase/protocol/server_opcode.hxx +2 -2
  170. data/ext/couchbase/protocol/server_request.hxx +1 -1
  171. data/ext/couchbase/protocol/status.hxx +4 -7
  172. data/ext/couchbase/protocol/unsigned_leb128.h +5 -20
  173. data/ext/couchbase/service_type.hxx +4 -4
  174. data/ext/couchbase/tracing/constants.hxx +261 -0
  175. data/ext/couchbase/tracing/noop_tracer.hxx +50 -0
  176. data/ext/couchbase/tracing/request_tracer.hxx +77 -0
  177. data/ext/couchbase/tracing/threshold_logging_options.hxx +64 -0
  178. data/ext/couchbase/tracing/threshold_logging_tracer.hxx +366 -0
  179. data/ext/couchbase/utils/byteswap.hxx +1 -1
  180. data/ext/couchbase/utils/connection_string.hxx +21 -1
  181. data/ext/couchbase/utils/name_codec.hxx +41 -0
  182. data/ext/couchbase/utils/url_codec.hxx +236 -0
  183. data/ext/couchbase/version.hxx +1 -1
  184. data/ext/test/CMakeLists.txt +1 -0
  185. data/ext/test/test_native_trivial_query.cxx +60 -0
  186. data/ext/third_party/hdr_histogram_c/CMakeLists.txt +84 -0
  187. data/ext/third_party/hdr_histogram_c/COPYING.txt +121 -0
  188. data/ext/third_party/hdr_histogram_c/LICENSE.txt +41 -0
  189. data/ext/third_party/hdr_histogram_c/config.cmake.in +6 -0
  190. data/ext/third_party/hdr_histogram_c/src/CMakeLists.txt +83 -0
  191. data/ext/third_party/hdr_histogram_c/src/hdr_atomic.h +146 -0
  192. data/ext/third_party/hdr_histogram_c/src/hdr_encoding.c +322 -0
  193. data/ext/third_party/hdr_histogram_c/src/hdr_encoding.h +79 -0
  194. data/ext/third_party/hdr_histogram_c/src/hdr_endian.h +116 -0
  195. data/ext/third_party/hdr_histogram_c/src/hdr_histogram.c +1196 -0
  196. data/ext/third_party/hdr_histogram_c/src/hdr_histogram.h +516 -0
  197. data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log.c +1290 -0
  198. data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log.h +236 -0
  199. data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log_no_op.c +171 -0
  200. data/ext/third_party/hdr_histogram_c/src/hdr_interval_recorder.c +227 -0
  201. data/ext/third_party/hdr_histogram_c/src/hdr_interval_recorder.h +109 -0
  202. data/ext/third_party/hdr_histogram_c/src/hdr_malloc.h +19 -0
  203. data/ext/third_party/hdr_histogram_c/src/hdr_tests.h +22 -0
  204. data/ext/third_party/hdr_histogram_c/src/hdr_thread.c +108 -0
  205. data/ext/third_party/hdr_histogram_c/src/hdr_thread.h +55 -0
  206. data/ext/third_party/hdr_histogram_c/src/hdr_time.c +98 -0
  207. data/ext/third_party/hdr_histogram_c/src/hdr_time.h +49 -0
  208. data/ext/third_party/hdr_histogram_c/src/hdr_writer_reader_phaser.c +143 -0
  209. data/ext/third_party/hdr_histogram_c/src/hdr_writer_reader_phaser.h +51 -0
  210. data/lib/couchbase/cluster.rb +1 -0
  211. data/lib/couchbase/errors.rb +3 -0
  212. data/lib/couchbase/libcouchbase.bundle +0 -0
  213. data/lib/couchbase/management/analytics_index_manager.rb +920 -226
  214. data/lib/couchbase/management/bucket_manager.rb +207 -69
  215. data/lib/couchbase/management/collection_manager.rb +173 -61
  216. data/lib/couchbase/management/query_index_manager.rb +357 -169
  217. data/lib/couchbase/options.rb +75 -3
  218. data/lib/couchbase/scope.rb +102 -0
  219. data/lib/couchbase/utils/time.rb +4 -0
  220. data/lib/couchbase/version.rb +6 -6
  221. metadata +48 -5
@@ -0,0 +1,79 @@
1
+ /**
2
+ * hdr_encoding.h
3
+ * Written by Michael Barker and released to the public domain,
4
+ * as explained at http://creativecommons.org/publicdomain/zero/1.0/
5
+ */
6
+
7
+ #ifndef HDR_ENCODING_H
8
+ #define HDR_ENCODING_H
9
+
10
+ #include <stdint.h>
11
+
12
+ #define MAX_BYTES_LEB128 9
13
+
14
+ #ifdef __cplusplus
15
+ extern "C" {
16
+ #endif
17
+
18
+ /**
19
+ * Writes a int64_t value to the given buffer in LEB128 ZigZag encoded format
20
+ *
21
+ * @param buffer the buffer to write to
22
+ * @param signed_value the value to write to the buffer
23
+ * @return the number of bytes written to the buffer
24
+ */
25
+ int zig_zag_encode_i64(uint8_t* buffer, int64_t signed_value);
26
+
27
+ /**
28
+ * Read an LEB128 ZigZag encoded long value from the given buffer
29
+ *
30
+ * @param buffer the buffer to read from
31
+ * @param retVal out value to capture the read value
32
+ * @return the number of bytes read from the buffer
33
+ */
34
+ int zig_zag_decode_i64(const uint8_t* buffer, int64_t* signed_value);
35
+
36
+ /**
37
+ * Gets the length in bytes of base64 data, given the input size.
38
+ *
39
+ * @param decoded_size the size of the unencoded values.
40
+ * @return the encoded size
41
+ */
42
+ size_t hdr_base64_encoded_len(size_t decoded_size);
43
+
44
+ /**
45
+ * Encode into base64.
46
+ *
47
+ * @param input the data to encode
48
+ * @param input_len the length of the data to encode
49
+ * @param output the buffer to write the output to
50
+ * @param output_len the number of bytes to write to the output
51
+ */
52
+ int hdr_base64_encode(
53
+ const uint8_t* input, size_t input_len, char* output, size_t output_len);
54
+
55
+ /**
56
+ * Gets the length in bytes of decoded base64 data, given the size of the base64 encoded
57
+ * data.
58
+ *
59
+ * @param encoded_size the size of the encoded value.
60
+ * @return the decoded size
61
+ */
62
+ size_t hdr_base64_decoded_len(size_t encoded_size);
63
+
64
+ /**
65
+ * Decode from base64.
66
+ *
67
+ * @param input the base64 encoded data
68
+ * @param input_len the size in bytes of the endcoded data
69
+ * @param output the buffer to write the decoded data to
70
+ * @param output_len the number of bytes to write to the output data
71
+ */
72
+ int hdr_base64_decode(
73
+ const char* input, size_t input_len, uint8_t* output, size_t output_len);
74
+
75
+ #ifdef __cplusplus
76
+ }
77
+ #endif
78
+
79
+ #endif /* HDR_HISTOGRAM_HDR_ENCODING_H */
@@ -0,0 +1,116 @@
1
+ /**
2
+ * hdr_time.h
3
+ * Released to the public domain, as explained at http://creativecommons.org/publicdomain/zero/1.0/
4
+ */
5
+
6
+ #ifndef HDR_ENDIAN_H__
7
+ #define HDR_ENDIAN_H__
8
+
9
+ #if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
10
+
11
+ # define __WINDOWS__
12
+
13
+ #endif
14
+
15
+ #if defined(__linux__) || defined(__CYGWIN__)
16
+
17
+ # include <endian.h>
18
+
19
+ #elif defined(__APPLE__)
20
+
21
+ # include <libkern/OSByteOrder.h>
22
+
23
+ # define htobe16(x) OSSwapHostToBigInt16(x)
24
+ # define htole16(x) OSSwapHostToLittleInt16(x)
25
+ # define be16toh(x) OSSwapBigToHostInt16(x)
26
+ # define le16toh(x) OSSwapLittleToHostInt16(x)
27
+
28
+ # define htobe32(x) OSSwapHostToBigInt32(x)
29
+ # define htole32(x) OSSwapHostToLittleInt32(x)
30
+ # define be32toh(x) OSSwapBigToHostInt32(x)
31
+ # define le32toh(x) OSSwapLittleToHostInt32(x)
32
+
33
+ # define htobe64(x) OSSwapHostToBigInt64(x)
34
+ # define htole64(x) OSSwapHostToLittleInt64(x)
35
+ # define be64toh(x) OSSwapBigToHostInt64(x)
36
+ # define le64toh(x) OSSwapLittleToHostInt64(x)
37
+
38
+ # define __BYTE_ORDER BYTE_ORDER
39
+ # define __BIG_ENDIAN BIG_ENDIAN
40
+ # define __LITTLE_ENDIAN LITTLE_ENDIAN
41
+ # define __PDP_ENDIAN PDP_ENDIAN
42
+
43
+ #elif defined(__OpenBSD__)
44
+
45
+ # include <sys/endian.h>
46
+
47
+ #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
48
+
49
+ # include <sys/endian.h>
50
+
51
+ # define be16toh(x) betoh16(x)
52
+ # define le16toh(x) letoh16(x)
53
+
54
+ # define be32toh(x) betoh32(x)
55
+ # define le32toh(x) letoh32(x)
56
+
57
+ # define be64toh(x) betoh64(x)
58
+ # define le64toh(x) letoh64(x)
59
+
60
+ #elif defined(__WINDOWS__)
61
+
62
+ # include <winsock2.h>
63
+
64
+ # if BYTE_ORDER == LITTLE_ENDIAN
65
+
66
+ # define htobe16(x) htons(x)
67
+ # define htole16(x) (x)
68
+ # define be16toh(x) ntohs(x)
69
+ # define le16toh(x) (x)
70
+
71
+ # define htobe32(x) htonl(x)
72
+ # define htole32(x) (x)
73
+ # define be32toh(x) ntohl(x)
74
+ # define le32toh(x) (x)
75
+
76
+ # define htobe64(x) htonll(x)
77
+ # define htole64(x) (x)
78
+ # define be64toh(x) ntohll(x)
79
+ # define le64toh(x) (x)
80
+
81
+ # elif BYTE_ORDER == BIG_ENDIAN
82
+
83
+ /* that would be xbox 360 */
84
+ # define htobe16(x) (x)
85
+ # define htole16(x) __builtin_bswap16(x)
86
+ # define be16toh(x) (x)
87
+ # define le16toh(x) __builtin_bswap16(x)
88
+
89
+ # define htobe32(x) (x)
90
+ # define htole32(x) __builtin_bswap32(x)
91
+ # define be32toh(x) (x)
92
+ # define le32toh(x) __builtin_bswap32(x)
93
+
94
+ # define htobe64(x) (x)
95
+ # define htole64(x) __builtin_bswap64(x)
96
+ # define be64toh(x) (x)
97
+ # define le64toh(x) __builtin_bswap64(x)
98
+
99
+ # else
100
+
101
+ # error byte order not supported
102
+
103
+ # endif
104
+
105
+ # define __BYTE_ORDER BYTE_ORDER
106
+ # define __BIG_ENDIAN BIG_ENDIAN
107
+ # define __LITTLE_ENDIAN LITTLE_ENDIAN
108
+ # define __PDP_ENDIAN PDP_ENDIAN
109
+
110
+ #else
111
+
112
+ # error platform not supported
113
+
114
+ #endif
115
+
116
+ #endif
@@ -0,0 +1,1196 @@
1
+ /**
2
+ * hdr_histogram.c
3
+ * Written by Michael Barker and released to the public domain,
4
+ * as explained at http://creativecommons.org/publicdomain/zero/1.0/
5
+ */
6
+
7
+ #include <stdlib.h>
8
+ #include <stdbool.h>
9
+ #include <math.h>
10
+ #include <stdio.h>
11
+ #include <string.h>
12
+ #include <stdint.h>
13
+ #include <errno.h>
14
+ #include <inttypes.h>
15
+
16
+ #include "hdr_histogram.h"
17
+ #include "hdr_tests.h"
18
+ #include "hdr_atomic.h"
19
+
20
+ #ifndef HDR_MALLOC_INCLUDE
21
+ #define HDR_MALLOC_INCLUDE "hdr_malloc.h"
22
+ #endif
23
+
24
+ #include HDR_MALLOC_INCLUDE
25
+
26
+ /* ###### ####### ## ## ## ## ######## ###### */
27
+ /* ## ## ## ## ## ## ### ## ## ## ## */
28
+ /* ## ## ## ## ## #### ## ## ## */
29
+ /* ## ## ## ## ## ## ## ## ## ###### */
30
+ /* ## ## ## ## ## ## #### ## ## */
31
+ /* ## ## ## ## ## ## ## ### ## ## ## */
32
+ /* ###### ####### ####### ## ## ## ###### */
33
+
34
+ static int32_t normalize_index(const struct hdr_histogram* h, int32_t index)
35
+ {
36
+ int32_t normalized_index;
37
+ int32_t adjustment = 0;
38
+ if (h->normalizing_index_offset == 0)
39
+ {
40
+ return index;
41
+ }
42
+
43
+ normalized_index = index - h->normalizing_index_offset;
44
+
45
+ if (normalized_index < 0)
46
+ {
47
+ adjustment = h->counts_len;
48
+ }
49
+ else if (normalized_index >= h->counts_len)
50
+ {
51
+ adjustment = -h->counts_len;
52
+ }
53
+
54
+ return normalized_index + adjustment;
55
+ }
56
+
57
+ static int64_t counts_get_direct(const struct hdr_histogram* h, int32_t index)
58
+ {
59
+ return h->counts[index];
60
+ }
61
+
62
+ static int64_t counts_get_normalised(const struct hdr_histogram* h, int32_t index)
63
+ {
64
+ return counts_get_direct(h, normalize_index(h, index));
65
+ }
66
+
67
+ static void counts_inc_normalised(
68
+ struct hdr_histogram* h, int32_t index, int64_t value)
69
+ {
70
+ int32_t normalised_index = normalize_index(h, index);
71
+ h->counts[normalised_index] += value;
72
+ h->total_count += value;
73
+ }
74
+
75
+ static void counts_inc_normalised_atomic(
76
+ struct hdr_histogram* h, int32_t index, int64_t value)
77
+ {
78
+ int32_t normalised_index = normalize_index(h, index);
79
+
80
+ hdr_atomic_add_fetch_64(&h->counts[normalised_index], value);
81
+ hdr_atomic_add_fetch_64(&h->total_count, value);
82
+ }
83
+
84
+ static void update_min_max(struct hdr_histogram* h, int64_t value)
85
+ {
86
+ h->min_value = (value < h->min_value && value != 0) ? value : h->min_value;
87
+ h->max_value = (value > h->max_value) ? value : h->max_value;
88
+ }
89
+
90
+ static void update_min_max_atomic(struct hdr_histogram* h, int64_t value)
91
+ {
92
+ int64_t current_min_value;
93
+ int64_t current_max_value;
94
+ do
95
+ {
96
+ current_min_value = hdr_atomic_load_64(&h->min_value);
97
+
98
+ if (0 == value || current_min_value <= value)
99
+ {
100
+ break;
101
+ }
102
+ }
103
+ while (!hdr_atomic_compare_exchange_64(&h->min_value, &current_min_value, value));
104
+
105
+ do
106
+ {
107
+ current_max_value = hdr_atomic_load_64(&h->max_value);
108
+
109
+ if (value <= current_max_value)
110
+ {
111
+ break;
112
+ }
113
+ }
114
+ while (!hdr_atomic_compare_exchange_64(&h->max_value, &current_max_value, value));
115
+ }
116
+
117
+
118
+ /* ## ## ######## #### ## #### ######## ## ## */
119
+ /* ## ## ## ## ## ## ## ## ## */
120
+ /* ## ## ## ## ## ## ## #### */
121
+ /* ## ## ## ## ## ## ## ## */
122
+ /* ## ## ## ## ## ## ## ## */
123
+ /* ## ## ## ## ## ## ## ## */
124
+ /* ####### ## #### ######## #### ## ## */
125
+
126
+ static int64_t power(int64_t base, int64_t exp)
127
+ {
128
+ int64_t result = 1;
129
+ while(exp)
130
+ {
131
+ result *= base; exp--;
132
+ }
133
+ return result;
134
+ }
135
+
136
+ #if defined(_MSC_VER)
137
+ # if defined(_WIN64)
138
+ # pragma intrinsic(_BitScanReverse64)
139
+ # else
140
+ # pragma intrinsic(_BitScanReverse)
141
+ # endif
142
+ #endif
143
+
144
+ static int32_t count_leading_zeros_64(int64_t value)
145
+ {
146
+ #if defined(_MSC_VER)
147
+ uint32_t leading_zero = 0;
148
+ #if defined(_WIN64)
149
+ _BitScanReverse64(&leading_zero, value);
150
+ #else
151
+ uint32_t high = value >> 32;
152
+ if (_BitScanReverse(&leading_zero, high))
153
+ {
154
+ leading_zero += 32;
155
+ }
156
+ else
157
+ {
158
+ uint32_t low = value & 0x00000000FFFFFFFF;
159
+ _BitScanReverse(&leading_zero, low);
160
+ }
161
+ #endif
162
+ return 63 - leading_zero; /* smallest power of 2 containing value */
163
+ #else
164
+ return __builtin_clzll(value); /* smallest power of 2 containing value */
165
+ #endif
166
+ }
167
+
168
+ static int32_t get_bucket_index(const struct hdr_histogram* h, int64_t value)
169
+ {
170
+ int32_t pow2ceiling = 64 - count_leading_zeros_64(value | h->sub_bucket_mask); /* smallest power of 2 containing value */
171
+ return pow2ceiling - h->unit_magnitude - (h->sub_bucket_half_count_magnitude + 1);
172
+ }
173
+
174
+ static int32_t get_sub_bucket_index(int64_t value, int32_t bucket_index, int32_t unit_magnitude)
175
+ {
176
+ return (int32_t)(value >> (bucket_index + unit_magnitude));
177
+ }
178
+
179
+ static int32_t counts_index(const struct hdr_histogram* h, int32_t bucket_index, int32_t sub_bucket_index)
180
+ {
181
+ /* Calculate the index for the first entry in the bucket: */
182
+ /* (The following is the equivalent of ((bucket_index + 1) * subBucketHalfCount) ): */
183
+ int32_t bucket_base_index = (bucket_index + 1) << h->sub_bucket_half_count_magnitude;
184
+ /* Calculate the offset in the bucket: */
185
+ int32_t offset_in_bucket = sub_bucket_index - h->sub_bucket_half_count;
186
+ /* The following is the equivalent of ((sub_bucket_index - subBucketHalfCount) + bucketBaseIndex; */
187
+ return bucket_base_index + offset_in_bucket;
188
+ }
189
+
190
+ static int64_t value_from_index(int32_t bucket_index, int32_t sub_bucket_index, int32_t unit_magnitude)
191
+ {
192
+ return ((int64_t) sub_bucket_index) << (bucket_index + unit_magnitude);
193
+ }
194
+
195
+ int32_t counts_index_for(const struct hdr_histogram* h, int64_t value)
196
+ {
197
+ int32_t bucket_index = get_bucket_index(h, value);
198
+ int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, h->unit_magnitude);
199
+
200
+ return counts_index(h, bucket_index, sub_bucket_index);
201
+ }
202
+
203
+ int64_t hdr_value_at_index(const struct hdr_histogram *h, int32_t index)
204
+ {
205
+ int32_t bucket_index = (index >> h->sub_bucket_half_count_magnitude) - 1;
206
+ int32_t sub_bucket_index = (index & (h->sub_bucket_half_count - 1)) + h->sub_bucket_half_count;
207
+
208
+ if (bucket_index < 0)
209
+ {
210
+ sub_bucket_index -= h->sub_bucket_half_count;
211
+ bucket_index = 0;
212
+ }
213
+
214
+ return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude);
215
+ }
216
+
217
+ int64_t hdr_size_of_equivalent_value_range(const struct hdr_histogram* h, int64_t value)
218
+ {
219
+ int32_t bucket_index = get_bucket_index(h, value);
220
+ int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, h->unit_magnitude);
221
+ int32_t adjusted_bucket = (sub_bucket_index >= h->sub_bucket_count) ? (bucket_index + 1) : bucket_index;
222
+ return INT64_C(1) << (h->unit_magnitude + adjusted_bucket);
223
+ }
224
+
225
+ static int64_t lowest_equivalent_value(const struct hdr_histogram* h, int64_t value)
226
+ {
227
+ int32_t bucket_index = get_bucket_index(h, value);
228
+ int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, h->unit_magnitude);
229
+ return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude);
230
+ }
231
+
232
+ int64_t hdr_next_non_equivalent_value(const struct hdr_histogram *h, int64_t value)
233
+ {
234
+ return lowest_equivalent_value(h, value) + hdr_size_of_equivalent_value_range(h, value);
235
+ }
236
+
237
+ static int64_t highest_equivalent_value(const struct hdr_histogram* h, int64_t value)
238
+ {
239
+ return hdr_next_non_equivalent_value(h, value) - 1;
240
+ }
241
+
242
+ int64_t hdr_median_equivalent_value(const struct hdr_histogram *h, int64_t value)
243
+ {
244
+ return lowest_equivalent_value(h, value) + (hdr_size_of_equivalent_value_range(h, value) >> 1);
245
+ }
246
+
247
+ static int64_t non_zero_min(const struct hdr_histogram* h)
248
+ {
249
+ if (INT64_MAX == h->min_value)
250
+ {
251
+ return INT64_MAX;
252
+ }
253
+
254
+ return lowest_equivalent_value(h, h->min_value);
255
+ }
256
+
257
+ void hdr_reset_internal_counters(struct hdr_histogram* h)
258
+ {
259
+ int min_non_zero_index = -1;
260
+ int max_index = -1;
261
+ int64_t observed_total_count = 0;
262
+ int i;
263
+
264
+ for (i = 0; i < h->counts_len; i++)
265
+ {
266
+ int64_t count_at_index;
267
+
268
+ if ((count_at_index = counts_get_direct(h, i)) > 0)
269
+ {
270
+ observed_total_count += count_at_index;
271
+ max_index = i;
272
+ if (min_non_zero_index == -1 && i != 0)
273
+ {
274
+ min_non_zero_index = i;
275
+ }
276
+ }
277
+ }
278
+
279
+ if (max_index == -1)
280
+ {
281
+ h->max_value = 0;
282
+ }
283
+ else
284
+ {
285
+ int64_t max_value = hdr_value_at_index(h, max_index);
286
+ h->max_value = highest_equivalent_value(h, max_value);
287
+ }
288
+
289
+ if (min_non_zero_index == -1)
290
+ {
291
+ h->min_value = INT64_MAX;
292
+ }
293
+ else
294
+ {
295
+ h->min_value = hdr_value_at_index(h, min_non_zero_index);
296
+ }
297
+
298
+ h->total_count = observed_total_count;
299
+ }
300
+
301
+ static int32_t buckets_needed_to_cover_value(int64_t value, int32_t sub_bucket_count, int32_t unit_magnitude)
302
+ {
303
+ int64_t smallest_untrackable_value = ((int64_t) sub_bucket_count) << unit_magnitude;
304
+ int32_t buckets_needed = 1;
305
+ while (smallest_untrackable_value <= value)
306
+ {
307
+ if (smallest_untrackable_value > INT64_MAX / 2)
308
+ {
309
+ return buckets_needed + 1;
310
+ }
311
+ smallest_untrackable_value <<= 1;
312
+ buckets_needed++;
313
+ }
314
+
315
+ return buckets_needed;
316
+ }
317
+
318
+ /* ## ## ######## ## ## ####### ######## ## ## */
319
+ /* ### ### ## ### ### ## ## ## ## ## ## */
320
+ /* #### #### ## #### #### ## ## ## ## #### */
321
+ /* ## ### ## ###### ## ### ## ## ## ######## ## */
322
+ /* ## ## ## ## ## ## ## ## ## ## */
323
+ /* ## ## ## ## ## ## ## ## ## ## */
324
+ /* ## ## ######## ## ## ####### ## ## ## */
325
+
326
+ int hdr_calculate_bucket_config(
327
+ int64_t lowest_discernible_value,
328
+ int64_t highest_trackable_value,
329
+ int significant_figures,
330
+ struct hdr_histogram_bucket_config* cfg)
331
+ {
332
+ int32_t sub_bucket_count_magnitude;
333
+ int64_t largest_value_with_single_unit_resolution;
334
+
335
+ if (lowest_discernible_value < 1 ||
336
+ significant_figures < 1 || 5 < significant_figures ||
337
+ lowest_discernible_value * 2 > highest_trackable_value)
338
+ {
339
+ return EINVAL;
340
+ }
341
+
342
+ cfg->lowest_discernible_value = lowest_discernible_value;
343
+ cfg->significant_figures = significant_figures;
344
+ cfg->highest_trackable_value = highest_trackable_value;
345
+
346
+ largest_value_with_single_unit_resolution = 2 * power(10, significant_figures);
347
+ sub_bucket_count_magnitude = (int32_t) ceil(log((double)largest_value_with_single_unit_resolution) / log(2));
348
+ cfg->sub_bucket_half_count_magnitude = ((sub_bucket_count_magnitude > 1) ? sub_bucket_count_magnitude : 1) - 1;
349
+
350
+ double unit_magnitude = log((double)lowest_discernible_value) / log(2);
351
+ if (INT32_MAX < unit_magnitude)
352
+ {
353
+ return EINVAL;
354
+ }
355
+
356
+ cfg->unit_magnitude = (int32_t) unit_magnitude;
357
+ cfg->sub_bucket_count = (int32_t) pow(2, (cfg->sub_bucket_half_count_magnitude + 1));
358
+ cfg->sub_bucket_half_count = cfg->sub_bucket_count / 2;
359
+ cfg->sub_bucket_mask = ((int64_t) cfg->sub_bucket_count - 1) << cfg->unit_magnitude;
360
+
361
+ if (cfg->unit_magnitude + cfg->sub_bucket_half_count_magnitude > 61)
362
+ {
363
+ return EINVAL;
364
+ }
365
+
366
+ cfg->bucket_count = buckets_needed_to_cover_value(highest_trackable_value, cfg->sub_bucket_count, (int32_t)cfg->unit_magnitude);
367
+ cfg->counts_len = (cfg->bucket_count + 1) * (cfg->sub_bucket_count / 2);
368
+
369
+ return 0;
370
+ }
371
+
372
+ void hdr_init_preallocated(struct hdr_histogram* h, struct hdr_histogram_bucket_config* cfg)
373
+ {
374
+ h->lowest_discernible_value = cfg->lowest_discernible_value;
375
+ h->highest_trackable_value = cfg->highest_trackable_value;
376
+ h->unit_magnitude = (int32_t)cfg->unit_magnitude;
377
+ h->significant_figures = (int32_t)cfg->significant_figures;
378
+ h->sub_bucket_half_count_magnitude = cfg->sub_bucket_half_count_magnitude;
379
+ h->sub_bucket_half_count = cfg->sub_bucket_half_count;
380
+ h->sub_bucket_mask = cfg->sub_bucket_mask;
381
+ h->sub_bucket_count = cfg->sub_bucket_count;
382
+ h->min_value = INT64_MAX;
383
+ h->max_value = 0;
384
+ h->normalizing_index_offset = 0;
385
+ h->conversion_ratio = 1.0;
386
+ h->bucket_count = cfg->bucket_count;
387
+ h->counts_len = cfg->counts_len;
388
+ h->total_count = 0;
389
+ }
390
+
391
+ int hdr_init(
392
+ int64_t lowest_discernible_value,
393
+ int64_t highest_trackable_value,
394
+ int significant_figures,
395
+ struct hdr_histogram** result)
396
+ {
397
+ int64_t* counts;
398
+ struct hdr_histogram_bucket_config cfg;
399
+ struct hdr_histogram* histogram;
400
+
401
+ int r = hdr_calculate_bucket_config(lowest_discernible_value, highest_trackable_value, significant_figures, &cfg);
402
+ if (r)
403
+ {
404
+ return r;
405
+ }
406
+
407
+ counts = (int64_t*) hdr_calloc((size_t) cfg.counts_len, sizeof(int64_t));
408
+ if (!counts)
409
+ {
410
+ return ENOMEM;
411
+ }
412
+
413
+ histogram = (struct hdr_histogram*) hdr_calloc(1, sizeof(struct hdr_histogram));
414
+ if (!histogram)
415
+ {
416
+ hdr_free(counts);
417
+ return ENOMEM;
418
+ }
419
+
420
+ histogram->counts = counts;
421
+
422
+ hdr_init_preallocated(histogram, &cfg);
423
+ *result = histogram;
424
+
425
+ return 0;
426
+ }
427
+
428
+ void hdr_close(struct hdr_histogram* h)
429
+ {
430
+ if (h) {
431
+ hdr_free(h->counts);
432
+ hdr_free(h);
433
+ }
434
+ }
435
+
436
+ int hdr_alloc(int64_t highest_trackable_value, int significant_figures, struct hdr_histogram** result)
437
+ {
438
+ return hdr_init(1, highest_trackable_value, significant_figures, result);
439
+ }
440
+
441
+ /* reset a histogram to zero. */
442
+ void hdr_reset(struct hdr_histogram *h)
443
+ {
444
+ h->total_count=0;
445
+ h->min_value = INT64_MAX;
446
+ h->max_value = 0;
447
+ memset(h->counts, 0, (sizeof(int64_t) * h->counts_len));
448
+ }
449
+
450
+ size_t hdr_get_memory_size(struct hdr_histogram *h)
451
+ {
452
+ return sizeof(struct hdr_histogram) + h->counts_len * sizeof(int64_t);
453
+ }
454
+
455
+ /* ## ## ######## ######## ### ######## ######## ###### */
456
+ /* ## ## ## ## ## ## ## ## ## ## ## ## */
457
+ /* ## ## ## ## ## ## ## ## ## ## ## */
458
+ /* ## ## ######## ## ## ## ## ## ###### ###### */
459
+ /* ## ## ## ## ## ######### ## ## ## */
460
+ /* ## ## ## ## ## ## ## ## ## ## ## */
461
+ /* ####### ## ######## ## ## ## ######## ###### */
462
+
463
+
464
+ bool hdr_record_value(struct hdr_histogram* h, int64_t value)
465
+ {
466
+ return hdr_record_values(h, value, 1);
467
+ }
468
+
469
+ bool hdr_record_value_atomic(struct hdr_histogram* h, int64_t value)
470
+ {
471
+ return hdr_record_values_atomic(h, value, 1);
472
+ }
473
+
474
+ bool hdr_record_values(struct hdr_histogram* h, int64_t value, int64_t count)
475
+ {
476
+ int32_t counts_index;
477
+
478
+ if (value < 0)
479
+ {
480
+ return false;
481
+ }
482
+
483
+ counts_index = counts_index_for(h, value);
484
+
485
+ if (counts_index < 0 || h->counts_len <= counts_index)
486
+ {
487
+ return false;
488
+ }
489
+
490
+ counts_inc_normalised(h, counts_index, count);
491
+ update_min_max(h, value);
492
+
493
+ return true;
494
+ }
495
+
496
+ bool hdr_record_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count)
497
+ {
498
+ int32_t counts_index;
499
+
500
+ if (value < 0)
501
+ {
502
+ return false;
503
+ }
504
+
505
+ counts_index = counts_index_for(h, value);
506
+
507
+ if (counts_index < 0 || h->counts_len <= counts_index)
508
+ {
509
+ return false;
510
+ }
511
+
512
+ counts_inc_normalised_atomic(h, counts_index, count);
513
+ update_min_max_atomic(h, value);
514
+
515
+ return true;
516
+ }
517
+
518
+ bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t expected_interval)
519
+ {
520
+ return hdr_record_corrected_values(h, value, 1, expected_interval);
521
+ }
522
+
523
+ bool hdr_record_corrected_value_atomic(struct hdr_histogram* h, int64_t value, int64_t expected_interval)
524
+ {
525
+ return hdr_record_corrected_values_atomic(h, value, 1, expected_interval);
526
+ }
527
+
528
+ bool hdr_record_corrected_values(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval)
529
+ {
530
+ int64_t missing_value;
531
+
532
+ if (!hdr_record_values(h, value, count))
533
+ {
534
+ return false;
535
+ }
536
+
537
+ if (expected_interval <= 0 || value <= expected_interval)
538
+ {
539
+ return true;
540
+ }
541
+
542
+ missing_value = value - expected_interval;
543
+ for (; missing_value >= expected_interval; missing_value -= expected_interval)
544
+ {
545
+ if (!hdr_record_values(h, missing_value, count))
546
+ {
547
+ return false;
548
+ }
549
+ }
550
+
551
+ return true;
552
+ }
553
+
554
+ bool hdr_record_corrected_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval)
555
+ {
556
+ int64_t missing_value;
557
+
558
+ if (!hdr_record_values_atomic(h, value, count))
559
+ {
560
+ return false;
561
+ }
562
+
563
+ if (expected_interval <= 0 || value <= expected_interval)
564
+ {
565
+ return true;
566
+ }
567
+
568
+ missing_value = value - expected_interval;
569
+ for (; missing_value >= expected_interval; missing_value -= expected_interval)
570
+ {
571
+ if (!hdr_record_values_atomic(h, missing_value, count))
572
+ {
573
+ return false;
574
+ }
575
+ }
576
+
577
+ return true;
578
+ }
579
+
580
+ int64_t hdr_add(struct hdr_histogram* h, const struct hdr_histogram* from)
581
+ {
582
+ struct hdr_iter iter;
583
+ int64_t dropped = 0;
584
+ hdr_iter_recorded_init(&iter, from);
585
+
586
+ while (hdr_iter_next(&iter))
587
+ {
588
+ int64_t value = iter.value;
589
+ int64_t count = iter.count;
590
+
591
+ if (!hdr_record_values(h, value, count))
592
+ {
593
+ dropped += count;
594
+ }
595
+ }
596
+
597
+ return dropped;
598
+ }
599
+
600
+ int64_t hdr_add_while_correcting_for_coordinated_omission(
601
+ struct hdr_histogram* h, struct hdr_histogram* from, int64_t expected_interval)
602
+ {
603
+ struct hdr_iter iter;
604
+ int64_t dropped = 0;
605
+ hdr_iter_recorded_init(&iter, from);
606
+
607
+ while (hdr_iter_next(&iter))
608
+ {
609
+ int64_t value = iter.value;
610
+ int64_t count = iter.count;
611
+
612
+ if (!hdr_record_corrected_values(h, value, count, expected_interval))
613
+ {
614
+ dropped += count;
615
+ }
616
+ }
617
+
618
+ return dropped;
619
+ }
620
+
621
+
622
+
623
+ /* ## ## ### ## ## ## ######## ###### */
624
+ /* ## ## ## ## ## ## ## ## ## ## */
625
+ /* ## ## ## ## ## ## ## ## ## */
626
+ /* ## ## ## ## ## ## ## ###### ###### */
627
+ /* ## ## ######### ## ## ## ## ## */
628
+ /* ## ## ## ## ## ## ## ## ## ## */
629
+ /* ### ## ## ######## ####### ######## ###### */
630
+
631
+
632
+ int64_t hdr_max(const struct hdr_histogram* h)
633
+ {
634
+ if (0 == h->max_value)
635
+ {
636
+ return 0;
637
+ }
638
+
639
+ return highest_equivalent_value(h, h->max_value);
640
+ }
641
+
642
+ int64_t hdr_min(const struct hdr_histogram* h)
643
+ {
644
+ if (0 < hdr_count_at_index(h, 0))
645
+ {
646
+ return 0;
647
+ }
648
+
649
+ return non_zero_min(h);
650
+ }
651
+
652
+ int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile)
653
+ {
654
+ struct hdr_iter iter;
655
+ int64_t total = 0;
656
+ double requested_percentile = percentile < 100.0 ? percentile : 100.0;
657
+ int64_t count_at_percentile =
658
+ (int64_t) (((requested_percentile / 100) * h->total_count) + 0.5);
659
+ count_at_percentile = count_at_percentile > 1 ? count_at_percentile : 1;
660
+
661
+ hdr_iter_init(&iter, h);
662
+
663
+ while (hdr_iter_next(&iter))
664
+ {
665
+ total += iter.count;
666
+
667
+ if (total >= count_at_percentile)
668
+ {
669
+ int64_t value_from_index = iter.value;
670
+ return highest_equivalent_value(h, value_from_index);
671
+ }
672
+ }
673
+
674
+ return 0;
675
+ }
676
+
677
+ int hdr_value_at_percentiles(const struct hdr_histogram *h, const double *percentiles, int64_t *values, size_t length)
678
+ {
679
+ if (NULL == percentiles || NULL == values)
680
+ {
681
+ return EINVAL;
682
+ }
683
+
684
+ struct hdr_iter iter;
685
+ const int64_t total_count = h->total_count;
686
+ // to avoid allocations we use the values array for intermediate computation
687
+ // i.e. to store the expected cumulative count at each percentile
688
+ for (size_t i = 0; i < length; i++)
689
+ {
690
+ const double requested_percentile = percentiles[i] < 100.0 ? percentiles[i] : 100.0;
691
+ const int64_t count_at_percentile =
692
+ (int64_t) (((requested_percentile / 100) * total_count) + 0.5);
693
+ values[i] = count_at_percentile > 1 ? count_at_percentile : 1;
694
+ }
695
+
696
+ hdr_iter_init(&iter, h);
697
+ int64_t total = 0;
698
+ size_t at_pos = 0;
699
+ while (hdr_iter_next(&iter) && at_pos < length)
700
+ {
701
+ total += iter.count;
702
+ while (total >= values[at_pos] && at_pos < length)
703
+ {
704
+ values[at_pos] = highest_equivalent_value(h, iter.value);
705
+ at_pos++;
706
+ }
707
+ }
708
+ return 0;
709
+ }
710
+
711
+ double hdr_mean(const struct hdr_histogram* h)
712
+ {
713
+ struct hdr_iter iter;
714
+ int64_t total = 0;
715
+
716
+ hdr_iter_init(&iter, h);
717
+
718
+ while (hdr_iter_next(&iter))
719
+ {
720
+ if (0 != iter.count)
721
+ {
722
+ total += iter.count * hdr_median_equivalent_value(h, iter.value);
723
+ }
724
+ }
725
+
726
+ return (total * 1.0) / h->total_count;
727
+ }
728
+
729
+ double hdr_stddev(const struct hdr_histogram* h)
730
+ {
731
+ double mean = hdr_mean(h);
732
+ double geometric_dev_total = 0.0;
733
+
734
+ struct hdr_iter iter;
735
+ hdr_iter_init(&iter, h);
736
+
737
+ while (hdr_iter_next(&iter))
738
+ {
739
+ if (0 != iter.count)
740
+ {
741
+ double dev = (hdr_median_equivalent_value(h, iter.value) * 1.0) - mean;
742
+ geometric_dev_total += (dev * dev) * iter.count;
743
+ }
744
+ }
745
+
746
+ return sqrt(geometric_dev_total / h->total_count);
747
+ }
748
+
749
+ bool hdr_values_are_equivalent(const struct hdr_histogram* h, int64_t a, int64_t b)
750
+ {
751
+ return lowest_equivalent_value(h, a) == lowest_equivalent_value(h, b);
752
+ }
753
+
754
+ int64_t hdr_lowest_equivalent_value(const struct hdr_histogram* h, int64_t value)
755
+ {
756
+ return lowest_equivalent_value(h, value);
757
+ }
758
+
759
+ int64_t hdr_count_at_value(const struct hdr_histogram* h, int64_t value)
760
+ {
761
+ return counts_get_normalised(h, counts_index_for(h, value));
762
+ }
763
+
764
+ int64_t hdr_count_at_index(const struct hdr_histogram* h, int32_t index)
765
+ {
766
+ return counts_get_normalised(h, index);
767
+ }
768
+
769
+
770
+ /* #### ######## ######## ######## ### ######## ####### ######## ###### */
771
+ /* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
772
+ /* ## ## ## ## ## ## ## ## ## ## ## ## ## */
773
+ /* ## ## ###### ######## ## ## ## ## ## ######## ###### */
774
+ /* ## ## ## ## ## ######### ## ## ## ## ## ## */
775
+ /* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
776
+ /* #### ## ######## ## ## ## ## ## ####### ## ## ###### */
777
+
778
+
779
+ static bool has_buckets(struct hdr_iter* iter)
780
+ {
781
+ return iter->counts_index < iter->h->counts_len;
782
+ }
783
+
784
+ static bool has_next(struct hdr_iter* iter)
785
+ {
786
+ return iter->cumulative_count < iter->total_count;
787
+ }
788
+
789
+ static bool move_next(struct hdr_iter* iter)
790
+ {
791
+ iter->counts_index++;
792
+
793
+ if (!has_buckets(iter))
794
+ {
795
+ return false;
796
+ }
797
+
798
+ iter->count = counts_get_normalised(iter->h, iter->counts_index);
799
+ iter->cumulative_count += iter->count;
800
+
801
+ iter->value = hdr_value_at_index(iter->h, iter->counts_index);
802
+ iter->highest_equivalent_value = highest_equivalent_value(iter->h, iter->value);
803
+ iter->lowest_equivalent_value = lowest_equivalent_value(iter->h, iter->value);
804
+ iter->median_equivalent_value = hdr_median_equivalent_value(iter->h, iter->value);
805
+
806
+ return true;
807
+ }
808
+
809
+ static int64_t peek_next_value_from_index(struct hdr_iter* iter)
810
+ {
811
+ return hdr_value_at_index(iter->h, iter->counts_index + 1);
812
+ }
813
+
814
+ static bool next_value_greater_than_reporting_level_upper_bound(
815
+ struct hdr_iter *iter, int64_t reporting_level_upper_bound)
816
+ {
817
+ if (iter->counts_index >= iter->h->counts_len)
818
+ {
819
+ return false;
820
+ }
821
+
822
+ return peek_next_value_from_index(iter) > reporting_level_upper_bound;
823
+ }
824
+
825
+ static bool basic_iter_next(struct hdr_iter *iter)
826
+ {
827
+ if (!has_next(iter) || iter->counts_index >= iter->h->counts_len)
828
+ {
829
+ return false;
830
+ }
831
+
832
+ move_next(iter);
833
+
834
+ return true;
835
+ }
836
+
837
+ static void update_iterated_values(struct hdr_iter* iter, int64_t new_value_iterated_to)
838
+ {
839
+ iter->value_iterated_from = iter->value_iterated_to;
840
+ iter->value_iterated_to = new_value_iterated_to;
841
+ }
842
+
843
+ static bool all_values_iter_next(struct hdr_iter* iter)
844
+ {
845
+ bool result = move_next(iter);
846
+
847
+ if (result)
848
+ {
849
+ update_iterated_values(iter, iter->value);
850
+ }
851
+
852
+ return result;
853
+ }
854
+
855
+ void hdr_iter_init(struct hdr_iter* iter, const struct hdr_histogram* h)
856
+ {
857
+ iter->h = h;
858
+
859
+ iter->counts_index = -1;
860
+ iter->total_count = h->total_count;
861
+ iter->count = 0;
862
+ iter->cumulative_count = 0;
863
+ iter->value = 0;
864
+ iter->highest_equivalent_value = 0;
865
+ iter->value_iterated_from = 0;
866
+ iter->value_iterated_to = 0;
867
+
868
+ iter->_next_fp = all_values_iter_next;
869
+ }
870
+
871
+ bool hdr_iter_next(struct hdr_iter* iter)
872
+ {
873
+ return iter->_next_fp(iter);
874
+ }
875
+
876
+ /* ######## ######## ######## ###### ######## ## ## ######## #### ## ######## ###### */
877
+ /* ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## ## */
878
+ /* ## ## ## ## ## ## ## #### ## ## ## ## ## ## */
879
+ /* ######## ###### ######## ## ###### ## ## ## ## ## ## ###### ###### */
880
+ /* ## ## ## ## ## ## ## #### ## ## ## ## ## */
881
+ /* ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## */
882
+ /* ## ######## ## ## ###### ######## ## ## ## #### ######## ######## ###### */
883
+
884
+ static bool percentile_iter_next(struct hdr_iter* iter)
885
+ {
886
+ int64_t temp, half_distance, percentile_reporting_ticks;
887
+
888
+ struct hdr_iter_percentiles* percentiles = &iter->specifics.percentiles;
889
+
890
+ if (!has_next(iter))
891
+ {
892
+ if (percentiles->seen_last_value)
893
+ {
894
+ return false;
895
+ }
896
+
897
+ percentiles->seen_last_value = true;
898
+ percentiles->percentile = 100.0;
899
+
900
+ return true;
901
+ }
902
+
903
+ if (iter->counts_index == -1 && !basic_iter_next(iter))
904
+ {
905
+ return false;
906
+ }
907
+
908
+ do
909
+ {
910
+ double current_percentile = (100.0 * (double) iter->cumulative_count) / iter->h->total_count;
911
+ if (iter->count != 0 &&
912
+ percentiles->percentile_to_iterate_to <= current_percentile)
913
+ {
914
+ update_iterated_values(iter, highest_equivalent_value(iter->h, iter->value));
915
+
916
+ percentiles->percentile = percentiles->percentile_to_iterate_to;
917
+ temp = (int64_t)(log(100 / (100.0 - (percentiles->percentile_to_iterate_to))) / log(2)) + 1;
918
+ half_distance = (int64_t) pow(2, (double) temp);
919
+ percentile_reporting_ticks = percentiles->ticks_per_half_distance * half_distance;
920
+ percentiles->percentile_to_iterate_to += 100.0 / percentile_reporting_ticks;
921
+
922
+ return true;
923
+ }
924
+ }
925
+ while (basic_iter_next(iter));
926
+
927
+ return true;
928
+ }
929
+
930
+ void hdr_iter_percentile_init(struct hdr_iter* iter, const struct hdr_histogram* h, int32_t ticks_per_half_distance)
931
+ {
932
+ iter->h = h;
933
+
934
+ hdr_iter_init(iter, h);
935
+
936
+ iter->specifics.percentiles.seen_last_value = false;
937
+ iter->specifics.percentiles.ticks_per_half_distance = ticks_per_half_distance;
938
+ iter->specifics.percentiles.percentile_to_iterate_to = 0.0;
939
+ iter->specifics.percentiles.percentile = 0.0;
940
+
941
+ iter->_next_fp = percentile_iter_next;
942
+ }
943
+
944
+ static void format_line_string(char* str, size_t len, int significant_figures, format_type format)
945
+ {
946
+ #if defined(_MSC_VER)
947
+ #define snprintf _snprintf
948
+ #pragma warning(push)
949
+ #pragma warning(disable: 4996)
950
+ #endif
951
+ const char* format_str = "%s%d%s";
952
+
953
+ switch (format)
954
+ {
955
+ case CSV:
956
+ snprintf(str, len, format_str, "%.", significant_figures, "f,%f,%d,%.2f\n");
957
+ break;
958
+ case CLASSIC:
959
+ snprintf(str, len, format_str, "%12.", significant_figures, "f %12f %12d %12.2f\n");
960
+ break;
961
+ default:
962
+ snprintf(str, len, format_str, "%12.", significant_figures, "f %12f %12d %12.2f\n");
963
+ }
964
+ #if defined(_MSC_VER)
965
+ #undef snprintf
966
+ #pragma warning(pop)
967
+ #endif
968
+ }
969
+
970
+
971
+ /* ######## ######## ###### ####### ######## ######## ######## ######## */
972
+ /* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
973
+ /* ## ## ## ## ## ## ## ## ## ## ## ## ## */
974
+ /* ######## ###### ## ## ## ######## ## ## ###### ## ## */
975
+ /* ## ## ## ## ## ## ## ## ## ## ## ## ## */
976
+ /* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
977
+ /* ## ## ######## ###### ####### ## ## ######## ######## ######## */
978
+
979
+
980
+ static bool recorded_iter_next(struct hdr_iter* iter)
981
+ {
982
+ while (basic_iter_next(iter))
983
+ {
984
+ if (iter->count != 0)
985
+ {
986
+ update_iterated_values(iter, iter->value);
987
+
988
+ iter->specifics.recorded.count_added_in_this_iteration_step = iter->count;
989
+ return true;
990
+ }
991
+ }
992
+
993
+ return false;
994
+ }
995
+
996
+ void hdr_iter_recorded_init(struct hdr_iter* iter, const struct hdr_histogram* h)
997
+ {
998
+ hdr_iter_init(iter, h);
999
+
1000
+ iter->specifics.recorded.count_added_in_this_iteration_step = 0;
1001
+
1002
+ iter->_next_fp = recorded_iter_next;
1003
+ }
1004
+
1005
+ /* ## #### ## ## ######## ### ######## */
1006
+ /* ## ## ### ## ## ## ## ## ## */
1007
+ /* ## ## #### ## ## ## ## ## ## */
1008
+ /* ## ## ## ## ## ###### ## ## ######## */
1009
+ /* ## ## ## #### ## ######### ## ## */
1010
+ /* ## ## ## ### ## ## ## ## ## */
1011
+ /* ######## #### ## ## ######## ## ## ## ## */
1012
+
1013
+
1014
+ static bool iter_linear_next(struct hdr_iter* iter)
1015
+ {
1016
+ struct hdr_iter_linear* linear = &iter->specifics.linear;
1017
+
1018
+ linear->count_added_in_this_iteration_step = 0;
1019
+
1020
+ if (has_next(iter) ||
1021
+ next_value_greater_than_reporting_level_upper_bound(
1022
+ iter, linear->next_value_reporting_level_lowest_equivalent))
1023
+ {
1024
+ do
1025
+ {
1026
+ if (iter->value >= linear->next_value_reporting_level_lowest_equivalent)
1027
+ {
1028
+ update_iterated_values(iter, linear->next_value_reporting_level);
1029
+
1030
+ linear->next_value_reporting_level += linear->value_units_per_bucket;
1031
+ linear->next_value_reporting_level_lowest_equivalent =
1032
+ lowest_equivalent_value(iter->h, linear->next_value_reporting_level);
1033
+
1034
+ return true;
1035
+ }
1036
+
1037
+ if (!move_next(iter))
1038
+ {
1039
+ return true;
1040
+ }
1041
+
1042
+ linear->count_added_in_this_iteration_step += iter->count;
1043
+ }
1044
+ while (true);
1045
+ }
1046
+
1047
+ return false;
1048
+ }
1049
+
1050
+
1051
+ void hdr_iter_linear_init(struct hdr_iter* iter, const struct hdr_histogram* h, int64_t value_units_per_bucket)
1052
+ {
1053
+ hdr_iter_init(iter, h);
1054
+
1055
+ iter->specifics.linear.count_added_in_this_iteration_step = 0;
1056
+ iter->specifics.linear.value_units_per_bucket = value_units_per_bucket;
1057
+ iter->specifics.linear.next_value_reporting_level = value_units_per_bucket;
1058
+ iter->specifics.linear.next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(h, value_units_per_bucket);
1059
+
1060
+ iter->_next_fp = iter_linear_next;
1061
+ }
1062
+
1063
+ /* ## ####### ###### ### ######## #### ######## ## ## ## ## #### ###### */
1064
+ /* ## ## ## ## ## ## ## ## ## ## ## ## ## ### ### ## ## ## */
1065
+ /* ## ## ## ## ## ## ## ## ## ## ## ## #### #### ## ## */
1066
+ /* ## ## ## ## #### ## ## ######## ## ## ######### ## ### ## ## ## */
1067
+ /* ## ## ## ## ## ######### ## ## ## ## ## ## ## ## ## ## */
1068
+ /* ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
1069
+ /* ######## ####### ###### ## ## ## ## #### ## ## ## ## ## #### ###### */
1070
+
1071
+ static bool log_iter_next(struct hdr_iter *iter)
1072
+ {
1073
+ struct hdr_iter_log* logarithmic = &iter->specifics.log;
1074
+
1075
+ logarithmic->count_added_in_this_iteration_step = 0;
1076
+
1077
+ if (has_next(iter) ||
1078
+ next_value_greater_than_reporting_level_upper_bound(
1079
+ iter, logarithmic->next_value_reporting_level_lowest_equivalent))
1080
+ {
1081
+ do
1082
+ {
1083
+ if (iter->value >= logarithmic->next_value_reporting_level_lowest_equivalent)
1084
+ {
1085
+ update_iterated_values(iter, logarithmic->next_value_reporting_level);
1086
+
1087
+ logarithmic->next_value_reporting_level *= (int64_t)logarithmic->log_base;
1088
+ logarithmic->next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(iter->h, logarithmic->next_value_reporting_level);
1089
+
1090
+ return true;
1091
+ }
1092
+
1093
+ if (!move_next(iter))
1094
+ {
1095
+ return true;
1096
+ }
1097
+
1098
+ logarithmic->count_added_in_this_iteration_step += iter->count;
1099
+ }
1100
+ while (true);
1101
+ }
1102
+
1103
+ return false;
1104
+ }
1105
+
1106
+ void hdr_iter_log_init(
1107
+ struct hdr_iter* iter,
1108
+ const struct hdr_histogram* h,
1109
+ int64_t value_units_first_bucket,
1110
+ double log_base)
1111
+ {
1112
+ hdr_iter_init(iter, h);
1113
+ iter->specifics.log.count_added_in_this_iteration_step = 0;
1114
+ iter->specifics.log.log_base = log_base;
1115
+ iter->specifics.log.next_value_reporting_level = value_units_first_bucket;
1116
+ iter->specifics.log.next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(h, value_units_first_bucket);
1117
+
1118
+ iter->_next_fp = log_iter_next;
1119
+ }
1120
+
1121
+ /* Printing. */
1122
+
1123
+ static const char* format_head_string(format_type format)
1124
+ {
1125
+ switch (format)
1126
+ {
1127
+ case CSV:
1128
+ return "%s,%s,%s,%s\n";
1129
+ case CLASSIC:
1130
+ default:
1131
+ return "%12s %12s %12s %12s\n\n";
1132
+ }
1133
+ }
1134
+
1135
+ static const char CLASSIC_FOOTER[] =
1136
+ "#[Mean = %12.3f, StdDeviation = %12.3f]\n"
1137
+ "#[Max = %12.3f, Total count = %12" PRIu64 "]\n"
1138
+ "#[Buckets = %12d, SubBuckets = %12d]\n";
1139
+
1140
+ int hdr_percentiles_print(
1141
+ struct hdr_histogram* h, FILE* stream, int32_t ticks_per_half_distance,
1142
+ double value_scale, format_type format)
1143
+ {
1144
+ char line_format[25];
1145
+ const char* head_format;
1146
+ int rc = 0;
1147
+ struct hdr_iter iter;
1148
+ struct hdr_iter_percentiles * percentiles;
1149
+
1150
+ format_line_string(line_format, 25, h->significant_figures, format);
1151
+ head_format = format_head_string(format);
1152
+
1153
+ hdr_iter_percentile_init(&iter, h, ticks_per_half_distance);
1154
+
1155
+ if (fprintf(
1156
+ stream, head_format,
1157
+ "Value", "Percentile", "TotalCount", "1/(1-Percentile)") < 0)
1158
+ {
1159
+ rc = EIO;
1160
+ goto cleanup;
1161
+ }
1162
+
1163
+ percentiles = &iter.specifics.percentiles;
1164
+ while (hdr_iter_next(&iter))
1165
+ {
1166
+ double value = iter.highest_equivalent_value / value_scale;
1167
+ double percentile = percentiles->percentile / 100.0;
1168
+ int64_t total_count = iter.cumulative_count;
1169
+ double inverted_percentile = (1.0 / (1.0 - percentile));
1170
+
1171
+ if (fprintf(
1172
+ stream, line_format, value, percentile, total_count, inverted_percentile) < 0)
1173
+ {
1174
+ rc = EIO;
1175
+ goto cleanup;
1176
+ }
1177
+ }
1178
+
1179
+ if (CLASSIC == format)
1180
+ {
1181
+ double mean = hdr_mean(h) / value_scale;
1182
+ double stddev = hdr_stddev(h) / value_scale;
1183
+ double max = hdr_max(h) / value_scale;
1184
+
1185
+ if (fprintf(
1186
+ stream, CLASSIC_FOOTER, mean, stddev, max,
1187
+ h->total_count, h->bucket_count, h->sub_bucket_count) < 0)
1188
+ {
1189
+ rc = EIO;
1190
+ goto cleanup;
1191
+ }
1192
+ }
1193
+
1194
+ cleanup:
1195
+ return rc;
1196
+ }