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

Sign up to get free protection for your applications and to get access to all the features.
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,1290 @@
1
+ /**
2
+ * hdr_histogram_log.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 <stdint.h>
8
+ #include <stdlib.h>
9
+ #include <stdbool.h>
10
+ #include <inttypes.h>
11
+ #include <stdio.h>
12
+ #include <string.h>
13
+ #if defined(_MSC_VER)
14
+ #undef HAVE_UNISTD_H
15
+ #endif
16
+ #include <zlib.h>
17
+ #include <errno.h>
18
+ #include <time.h>
19
+
20
+ #include "hdr_encoding.h"
21
+ #include "hdr_histogram.h"
22
+ #include "hdr_histogram_log.h"
23
+ #include "hdr_tests.h"
24
+
25
+ #if defined(_MSC_VER)
26
+ #include <intsafe.h>
27
+ typedef SSIZE_T ssize_t;
28
+ #pragma comment(lib, "ws2_32.lib")
29
+ #pragma warning(push)
30
+ #pragma warning(disable: 4996)
31
+ #endif
32
+
33
+ #include "hdr_endian.h"
34
+
35
+ #ifndef HDR_MALLOC_INCLUDE
36
+ #define HDR_MALLOC_INCLUDE "hdr_malloc.h"
37
+ #endif
38
+
39
+ #include HDR_MALLOC_INCLUDE
40
+
41
+ /* Private prototypes useful for the logger */
42
+ int32_t counts_index_for(const struct hdr_histogram* h, int64_t value);
43
+
44
+
45
+ #define FAIL_AND_CLEANUP(label, error_name, error) \
46
+ do \
47
+ { \
48
+ error_name = error; \
49
+ goto label; \
50
+ } \
51
+ while (0)
52
+
53
+ /* ######## ## ## ###### ####### ######## #### ## ## ###### */
54
+ /* ## ### ## ## ## ## ## ## ## ## ### ## ## ## */
55
+ /* ## #### ## ## ## ## ## ## ## #### ## ## */
56
+ /* ###### ## ## ## ## ## ## ## ## ## ## ## ## ## #### */
57
+ /* ## ## #### ## ## ## ## ## ## ## #### ## ## */
58
+ /* ## ## ### ## ## ## ## ## ## ## ## ### ## ## */
59
+ /* ######## ## ## ###### ####### ######## #### ## ## ###### */
60
+
61
+ static const uint32_t V0_ENCODING_COOKIE = 0x1c849308;
62
+ static const uint32_t V0_COMPRESSION_COOKIE = 0x1c849309;
63
+
64
+ static const uint32_t V1_ENCODING_COOKIE = 0x1c849301;
65
+ static const uint32_t V1_COMPRESSION_COOKIE = 0x1c849302;
66
+
67
+ static const uint32_t V2_ENCODING_COOKIE = 0x1c849303;
68
+ static const uint32_t V2_COMPRESSION_COOKIE = 0x1c849304;
69
+
70
+ static uint32_t get_cookie_base(uint32_t cookie)
71
+ {
72
+ return (cookie & ~0xf0U);
73
+ }
74
+
75
+ static uint32_t word_size_from_cookie(uint32_t cookie)
76
+ {
77
+ return (cookie & 0xf0U) >> 4U;
78
+ }
79
+
80
+ const char* hdr_strerror(int errnum)
81
+ {
82
+ switch (errnum)
83
+ {
84
+ case HDR_COMPRESSION_COOKIE_MISMATCH:
85
+ return "Compression cookie mismatch";
86
+ case HDR_ENCODING_COOKIE_MISMATCH:
87
+ return "Encoding cookie mismatch";
88
+ case HDR_DEFLATE_INIT_FAIL:
89
+ return "Deflate initialisation failed";
90
+ case HDR_DEFLATE_FAIL:
91
+ return "Deflate failed";
92
+ case HDR_INFLATE_INIT_FAIL:
93
+ return "Inflate initialisation failed";
94
+ case HDR_INFLATE_FAIL:
95
+ return "Inflate failed";
96
+ case HDR_LOG_INVALID_VERSION:
97
+ return "Log - invalid version in log header";
98
+ case HDR_TRAILING_ZEROS_INVALID:
99
+ return "Invalid number of trailing zeros";
100
+ case HDR_VALUE_TRUNCATED:
101
+ return "Truncated value found when decoding";
102
+ case HDR_ENCODED_INPUT_TOO_LONG:
103
+ return "The encoded input exceeds the size of the histogram";
104
+ default:
105
+ return strerror(errnum);
106
+ }
107
+ }
108
+
109
+ static void strm_init(z_stream* strm)
110
+ {
111
+ memset(strm, 0, sizeof(z_stream));
112
+ }
113
+
114
+ union uint64_dbl_cvt
115
+ {
116
+ uint64_t l;
117
+ double d;
118
+ };
119
+
120
+ static double int64_bits_to_double(int64_t i)
121
+ {
122
+ union uint64_dbl_cvt x;
123
+
124
+ x.l = (uint64_t) i;
125
+ return x.d;
126
+ }
127
+
128
+ static uint64_t double_to_int64_bits(double d)
129
+ {
130
+ union uint64_dbl_cvt x;
131
+
132
+ x.d = d;
133
+ return x.l;
134
+ }
135
+
136
+ #pragma pack(push, 1)
137
+ typedef struct /*__attribute__((__packed__))*/
138
+ {
139
+ uint32_t cookie;
140
+ int32_t significant_figures;
141
+ int64_t lowest_discernible_value;
142
+ int64_t highest_trackable_value;
143
+ int64_t total_count;
144
+ int64_t counts[1];
145
+ } encoding_flyweight_v0_t;
146
+
147
+ typedef struct /*__attribute__((__packed__))*/
148
+ {
149
+ uint32_t cookie;
150
+ int32_t payload_len;
151
+ int32_t normalizing_index_offset;
152
+ int32_t significant_figures;
153
+ int64_t lowest_discernible_value;
154
+ int64_t highest_trackable_value;
155
+ uint64_t conversion_ratio_bits;
156
+ uint8_t counts[1];
157
+ } encoding_flyweight_v1_t;
158
+
159
+ typedef struct /*__attribute__((__packed__))*/
160
+ {
161
+ uint32_t cookie;
162
+ int32_t length;
163
+ uint8_t data[1];
164
+ } compression_flyweight_t;
165
+ #pragma pack(pop)
166
+
167
+ #define SIZEOF_ENCODING_FLYWEIGHT_V0 (sizeof(encoding_flyweight_v0_t) - sizeof(int64_t))
168
+ #define SIZEOF_ENCODING_FLYWEIGHT_V1 (sizeof(encoding_flyweight_v1_t) - sizeof(uint8_t))
169
+ #define SIZEOF_COMPRESSION_FLYWEIGHT (sizeof(compression_flyweight_t) - sizeof(uint8_t))
170
+
171
+ int hdr_encode_compressed(
172
+ struct hdr_histogram* h,
173
+ uint8_t** compressed_histogram,
174
+ size_t* compressed_len)
175
+ {
176
+ encoding_flyweight_v1_t* encoded = NULL;
177
+ compression_flyweight_t* compressed = NULL;
178
+ int i;
179
+ int result = 0;
180
+ int data_index = 0;
181
+ int32_t payload_len;
182
+ uLong encoded_size;
183
+ uLongf dest_len;
184
+ size_t compressed_size;
185
+
186
+ int32_t len_to_max = counts_index_for(h, h->max_value) + 1;
187
+ int32_t counts_limit = len_to_max < h->counts_len ? len_to_max : h->counts_len;
188
+
189
+ const size_t encoded_len = SIZEOF_ENCODING_FLYWEIGHT_V1 + MAX_BYTES_LEB128 * (size_t) counts_limit;
190
+ if ((encoded = (encoding_flyweight_v1_t*) hdr_calloc(encoded_len, sizeof(uint8_t))) == NULL)
191
+ {
192
+ FAIL_AND_CLEANUP(cleanup, result, ENOMEM);
193
+ }
194
+
195
+ for (i = 0; i < counts_limit;)
196
+ {
197
+ int64_t value = h->counts[i];
198
+ i++;
199
+
200
+ if (value == 0)
201
+ {
202
+ int32_t zeros = 1;
203
+
204
+ while (i < counts_limit && 0 == h->counts[i])
205
+ {
206
+ zeros++;
207
+ i++;
208
+ }
209
+
210
+ data_index += zig_zag_encode_i64(&encoded->counts[data_index], -zeros);
211
+ }
212
+ else
213
+ {
214
+ data_index += zig_zag_encode_i64(&encoded->counts[data_index], value);
215
+ }
216
+ }
217
+
218
+ payload_len = data_index;
219
+ encoded_size = SIZEOF_ENCODING_FLYWEIGHT_V1 + data_index;
220
+
221
+ encoded->cookie = htobe32(V2_ENCODING_COOKIE | 0x10U);
222
+ encoded->payload_len = htobe32(payload_len);
223
+ encoded->normalizing_index_offset = htobe32(h->normalizing_index_offset);
224
+ encoded->significant_figures = htobe32(h->significant_figures);
225
+ encoded->lowest_discernible_value = htobe64(h->lowest_discernible_value);
226
+ encoded->highest_trackable_value = htobe64(h->highest_trackable_value);
227
+ encoded->conversion_ratio_bits = htobe64(double_to_int64_bits(h->conversion_ratio));
228
+
229
+
230
+ /* Estimate the size of the compressed histogram. */
231
+ dest_len = compressBound(encoded_size);
232
+ compressed_size = SIZEOF_COMPRESSION_FLYWEIGHT + dest_len;
233
+
234
+ if ((compressed = (compression_flyweight_t*) hdr_malloc(compressed_size)) == NULL)
235
+ {
236
+ FAIL_AND_CLEANUP(cleanup, result, ENOMEM);
237
+ }
238
+
239
+ if (Z_OK != compress(compressed->data, &dest_len, (Bytef*) encoded, encoded_size))
240
+ {
241
+ FAIL_AND_CLEANUP(cleanup, result, HDR_DEFLATE_FAIL);
242
+ }
243
+
244
+ compressed->cookie = htobe32(V2_COMPRESSION_COOKIE | 0x10U);
245
+ compressed->length = htobe32((int32_t)dest_len);
246
+
247
+ *compressed_histogram = (uint8_t*) compressed;
248
+ *compressed_len = SIZEOF_COMPRESSION_FLYWEIGHT + dest_len;
249
+
250
+ cleanup:
251
+ hdr_free(encoded);
252
+ if (result == HDR_DEFLATE_FAIL)
253
+ {
254
+ hdr_free(compressed);
255
+ }
256
+
257
+ return result;
258
+ }
259
+
260
+ /* ######## ######## ###### ####### ######## #### ## ## ###### */
261
+ /* ## ## ## ## ## ## ## ## ## ## ### ## ## ## */
262
+ /* ## ## ## ## ## ## ## ## ## #### ## ## */
263
+ /* ## ## ###### ## ## ## ## ## ## ## ## ## ## #### */
264
+ /* ## ## ## ## ## ## ## ## ## ## #### ## ## */
265
+ /* ## ## ## ## ## ## ## ## ## ## ## ### ## ## */
266
+ /* ######## ######## ###### ####### ######## #### ## ## ###### */
267
+
268
+ static void apply_to_counts_16(struct hdr_histogram* h, const int16_t* counts_data, const int32_t counts_limit)
269
+ {
270
+ int i;
271
+ for (i = 0; i < counts_limit; i++)
272
+ {
273
+ h->counts[i] = be16toh(counts_data[i]);
274
+ }
275
+ }
276
+
277
+ static void apply_to_counts_32(struct hdr_histogram* h, const int32_t* counts_data, const int32_t counts_limit)
278
+ {
279
+ int i;
280
+ for (i = 0; i < counts_limit; i++)
281
+ {
282
+ h->counts[i] = be32toh(counts_data[i]);
283
+ }
284
+ }
285
+
286
+ static void apply_to_counts_64(struct hdr_histogram* h, const int64_t* counts_data, const int32_t counts_limit)
287
+ {
288
+ int i;
289
+ for (i = 0; i < counts_limit; i++)
290
+ {
291
+ h->counts[i] = be64toh(counts_data[i]);
292
+ }
293
+ }
294
+
295
+ static int apply_to_counts_zz(struct hdr_histogram* h, const uint8_t* counts_data, const int32_t data_limit)
296
+ {
297
+ int64_t data_index = 0;
298
+ int32_t counts_index = 0;
299
+ int64_t value;
300
+
301
+ while (data_index < data_limit && counts_index < h->counts_len)
302
+ {
303
+ data_index += zig_zag_decode_i64(&counts_data[data_index], &value);
304
+
305
+ if (value < 0)
306
+ {
307
+ int64_t zeros = -value;
308
+
309
+ if (value <= INT32_MIN || counts_index + zeros > h->counts_len)
310
+ {
311
+ return HDR_TRAILING_ZEROS_INVALID;
312
+ }
313
+
314
+ counts_index += (int32_t) zeros;
315
+ }
316
+ else
317
+ {
318
+ h->counts[counts_index] = value;
319
+ counts_index++;
320
+ }
321
+ }
322
+
323
+ if (data_index > data_limit)
324
+ {
325
+ return HDR_VALUE_TRUNCATED;
326
+ }
327
+ else if (data_index < data_limit)
328
+ {
329
+ return HDR_ENCODED_INPUT_TOO_LONG;
330
+ }
331
+
332
+ return 0;
333
+ }
334
+
335
+ static int apply_to_counts(
336
+ struct hdr_histogram* h, const int32_t word_size, const uint8_t* counts_data, const int32_t counts_limit)
337
+ {
338
+ switch (word_size)
339
+ {
340
+ case 2:
341
+ apply_to_counts_16(h, (const int16_t*) counts_data, counts_limit);
342
+ return 0;
343
+
344
+ case 4:
345
+ apply_to_counts_32(h, (const int32_t*) counts_data, counts_limit);
346
+ return 0;
347
+
348
+ case 8:
349
+ apply_to_counts_64(h, (const int64_t*) counts_data, counts_limit);
350
+ return 0;
351
+
352
+ case 1:
353
+ return apply_to_counts_zz(h, counts_data, counts_limit);
354
+
355
+ default:
356
+ return -1;
357
+ }
358
+ }
359
+
360
+ static int hdr_decode_compressed_v0(
361
+ compression_flyweight_t* compression_flyweight,
362
+ size_t length,
363
+ struct hdr_histogram** histogram)
364
+ {
365
+ struct hdr_histogram* h = NULL;
366
+ int result = 0;
367
+ uint8_t* counts_array = NULL;
368
+ encoding_flyweight_v0_t encoding_flyweight;
369
+ z_stream strm;
370
+ uint32_t encoding_cookie;
371
+ int32_t compressed_len, word_size, significant_figures, counts_array_len;
372
+ int64_t lowest_discernible_value, highest_trackable_value;
373
+
374
+ strm_init(&strm);
375
+ if (inflateInit(&strm) != Z_OK)
376
+ {
377
+ FAIL_AND_CLEANUP(cleanup, result, HDR_INFLATE_FAIL);
378
+ }
379
+
380
+ compressed_len = be32toh(compression_flyweight->length);
381
+
382
+ if (compressed_len < 0 || (length - SIZEOF_COMPRESSION_FLYWEIGHT) < (size_t)compressed_len)
383
+ {
384
+ FAIL_AND_CLEANUP(cleanup, result, EINVAL);
385
+ }
386
+
387
+ strm.next_in = compression_flyweight->data;
388
+ strm.avail_in = (uInt) compressed_len;
389
+ strm.next_out = (uint8_t *) &encoding_flyweight;
390
+ strm.avail_out = SIZEOF_ENCODING_FLYWEIGHT_V0;
391
+
392
+ if (inflate(&strm, Z_SYNC_FLUSH) != Z_OK)
393
+ {
394
+ FAIL_AND_CLEANUP(cleanup, result, HDR_INFLATE_FAIL);
395
+ }
396
+
397
+ encoding_cookie = get_cookie_base(be32toh(encoding_flyweight.cookie));
398
+ if (V0_ENCODING_COOKIE != encoding_cookie)
399
+ {
400
+ FAIL_AND_CLEANUP(cleanup, result, HDR_ENCODING_COOKIE_MISMATCH);
401
+ }
402
+
403
+ word_size = word_size_from_cookie(be32toh(encoding_flyweight.cookie));
404
+ lowest_discernible_value = be64toh(encoding_flyweight.lowest_discernible_value);
405
+ highest_trackable_value = be64toh(encoding_flyweight.highest_trackable_value);
406
+ significant_figures = be32toh(encoding_flyweight.significant_figures);
407
+
408
+ if (hdr_init(
409
+ lowest_discernible_value,
410
+ highest_trackable_value,
411
+ significant_figures,
412
+ &h) != 0)
413
+ {
414
+ FAIL_AND_CLEANUP(cleanup, result, ENOMEM);
415
+ }
416
+
417
+ counts_array_len = h->counts_len * word_size;
418
+ if ((counts_array = (uint8_t*) hdr_calloc(1, (size_t) counts_array_len)) == NULL)
419
+ {
420
+ FAIL_AND_CLEANUP(cleanup, result, ENOMEM);
421
+ }
422
+
423
+ strm.next_out = counts_array;
424
+ strm.avail_out = (uInt) counts_array_len;
425
+
426
+ if (inflate(&strm, Z_FINISH) != Z_STREAM_END)
427
+ {
428
+ FAIL_AND_CLEANUP(cleanup, result, HDR_INFLATE_FAIL);
429
+ }
430
+
431
+ apply_to_counts(h, word_size, counts_array, h->counts_len);
432
+
433
+ hdr_reset_internal_counters(h);
434
+ h->normalizing_index_offset = 0;
435
+ h->conversion_ratio = 1.0;
436
+
437
+ cleanup:
438
+ (void)inflateEnd(&strm);
439
+ hdr_free(counts_array);
440
+
441
+ if (result != 0)
442
+ {
443
+ hdr_free(h);
444
+ }
445
+ else if (NULL == *histogram)
446
+ {
447
+ *histogram = h;
448
+ }
449
+ else
450
+ {
451
+ hdr_add(*histogram, h);
452
+ hdr_free(h);
453
+ }
454
+
455
+ return result;
456
+ }
457
+
458
+ static int hdr_decode_compressed_v1(
459
+ compression_flyweight_t* compression_flyweight,
460
+ size_t length,
461
+ struct hdr_histogram** histogram)
462
+ {
463
+ struct hdr_histogram* h = NULL;
464
+ int result = 0;
465
+ uint8_t* counts_array = NULL;
466
+ encoding_flyweight_v1_t encoding_flyweight;
467
+ z_stream strm;
468
+ uint32_t encoding_cookie;
469
+ int32_t compressed_length, word_size, significant_figures, counts_limit, counts_array_len;
470
+ int64_t lowest_discernible_value, highest_trackable_value;
471
+
472
+ strm_init(&strm);
473
+ if (inflateInit(&strm) != Z_OK)
474
+ {
475
+ FAIL_AND_CLEANUP(cleanup, result, HDR_INFLATE_FAIL);
476
+ }
477
+
478
+ compressed_length = be32toh(compression_flyweight->length);
479
+
480
+ if (compressed_length < 0 || length - SIZEOF_COMPRESSION_FLYWEIGHT < (size_t)compressed_length)
481
+ {
482
+ FAIL_AND_CLEANUP(cleanup, result, EINVAL);
483
+ }
484
+
485
+ strm.next_in = compression_flyweight->data;
486
+ strm.avail_in = (uInt) compressed_length;
487
+ strm.next_out = (uint8_t *) &encoding_flyweight;
488
+ strm.avail_out = SIZEOF_ENCODING_FLYWEIGHT_V1;
489
+
490
+ if (inflate(&strm, Z_SYNC_FLUSH) != Z_OK)
491
+ {
492
+ FAIL_AND_CLEANUP(cleanup, result, HDR_INFLATE_FAIL);
493
+ }
494
+
495
+ encoding_cookie = get_cookie_base(be32toh(encoding_flyweight.cookie));
496
+ if (V1_ENCODING_COOKIE != encoding_cookie)
497
+ {
498
+ FAIL_AND_CLEANUP(cleanup, result, HDR_ENCODING_COOKIE_MISMATCH);
499
+ }
500
+
501
+ word_size = word_size_from_cookie(be32toh(encoding_flyweight.cookie));
502
+ counts_limit = be32toh(encoding_flyweight.payload_len) / word_size;
503
+ lowest_discernible_value = be64toh(encoding_flyweight.lowest_discernible_value);
504
+ highest_trackable_value = be64toh(encoding_flyweight.highest_trackable_value);
505
+ significant_figures = be32toh(encoding_flyweight.significant_figures);
506
+
507
+ if (hdr_init(
508
+ lowest_discernible_value,
509
+ highest_trackable_value,
510
+ significant_figures,
511
+ &h) != 0)
512
+ {
513
+ FAIL_AND_CLEANUP(cleanup, result, ENOMEM);
514
+ }
515
+
516
+ /* Give the temp uncompressed array a little bif of extra */
517
+ counts_array_len = counts_limit * word_size;
518
+
519
+ if ((counts_array = (uint8_t*) hdr_calloc(1, (size_t) counts_array_len)) == NULL)
520
+ {
521
+ FAIL_AND_CLEANUP(cleanup, result, ENOMEM);
522
+ }
523
+
524
+ strm.next_out = counts_array;
525
+ strm.avail_out = (uInt) counts_array_len;
526
+
527
+ if (inflate(&strm, Z_FINISH) != Z_STREAM_END)
528
+ {
529
+ FAIL_AND_CLEANUP(cleanup, result, HDR_INFLATE_FAIL);
530
+ }
531
+
532
+ apply_to_counts(h, word_size, counts_array, counts_limit);
533
+
534
+ h->normalizing_index_offset = be32toh(encoding_flyweight.normalizing_index_offset);
535
+ h->conversion_ratio = int64_bits_to_double(be64toh(encoding_flyweight.conversion_ratio_bits));
536
+ hdr_reset_internal_counters(h);
537
+
538
+ cleanup:
539
+ (void)inflateEnd(&strm);
540
+ hdr_free(counts_array);
541
+
542
+ if (result != 0)
543
+ {
544
+ hdr_free(h);
545
+ }
546
+ else if (NULL == *histogram)
547
+ {
548
+ *histogram = h;
549
+ }
550
+ else
551
+ {
552
+ hdr_add(*histogram, h);
553
+ hdr_free(h);
554
+ }
555
+
556
+ return result;
557
+ }
558
+
559
+ static int hdr_decode_compressed_v2(
560
+ compression_flyweight_t* compression_flyweight,
561
+ size_t length,
562
+ struct hdr_histogram** histogram)
563
+ {
564
+ struct hdr_histogram* h = NULL;
565
+ int result = 0;
566
+ int rc = 0;
567
+ uint8_t* counts_array = NULL;
568
+ encoding_flyweight_v1_t encoding_flyweight;
569
+ z_stream strm;
570
+ uint32_t encoding_cookie;
571
+ int32_t compressed_length, counts_limit, significant_figures;
572
+ int64_t lowest_discernible_value, highest_trackable_value;
573
+
574
+ strm_init(&strm);
575
+ if (inflateInit(&strm) != Z_OK)
576
+ {
577
+ FAIL_AND_CLEANUP(cleanup, result, HDR_INFLATE_FAIL);
578
+ }
579
+
580
+ compressed_length = be32toh(compression_flyweight->length);
581
+
582
+ if (compressed_length < 0 || length - SIZEOF_COMPRESSION_FLYWEIGHT < (size_t)compressed_length)
583
+ {
584
+ FAIL_AND_CLEANUP(cleanup, result, EINVAL);
585
+ }
586
+
587
+ strm.next_in = compression_flyweight->data;
588
+ strm.avail_in = (uInt) compressed_length;
589
+ strm.next_out = (uint8_t *) &encoding_flyweight;
590
+ strm.avail_out = SIZEOF_ENCODING_FLYWEIGHT_V1;
591
+
592
+ if (inflate(&strm, Z_SYNC_FLUSH) != Z_OK)
593
+ {
594
+ FAIL_AND_CLEANUP(cleanup, result, HDR_INFLATE_FAIL);
595
+ }
596
+
597
+ encoding_cookie = get_cookie_base(be32toh(encoding_flyweight.cookie));
598
+ if (V2_ENCODING_COOKIE != encoding_cookie)
599
+ {
600
+ FAIL_AND_CLEANUP(cleanup, result, HDR_ENCODING_COOKIE_MISMATCH);
601
+ }
602
+
603
+ counts_limit = be32toh(encoding_flyweight.payload_len);
604
+ lowest_discernible_value = be64toh(encoding_flyweight.lowest_discernible_value);
605
+ highest_trackable_value = be64toh(encoding_flyweight.highest_trackable_value);
606
+ significant_figures = be32toh(encoding_flyweight.significant_figures);
607
+
608
+ rc = hdr_init(lowest_discernible_value, highest_trackable_value, significant_figures, &h);
609
+ if (rc)
610
+ {
611
+ FAIL_AND_CLEANUP(cleanup, result, rc);
612
+ }
613
+
614
+ /* Make sure there at least 9 bytes to read */
615
+ /* if there is a corrupt value at the end */
616
+ /* of the array we won't read corrupt data or crash. */
617
+ if ((counts_array = (uint8_t*) hdr_calloc(1, (size_t) counts_limit + 9)) == NULL)
618
+ {
619
+ FAIL_AND_CLEANUP(cleanup, result, ENOMEM);
620
+ }
621
+
622
+ strm.next_out = counts_array;
623
+ strm.avail_out = (uInt) counts_limit;
624
+
625
+ if (inflate(&strm, Z_FINISH) != Z_STREAM_END)
626
+ {
627
+ FAIL_AND_CLEANUP(cleanup, result, HDR_INFLATE_FAIL);
628
+ }
629
+
630
+ rc = apply_to_counts_zz(h, counts_array, counts_limit);
631
+ if (rc)
632
+ {
633
+ FAIL_AND_CLEANUP(cleanup, result, rc);
634
+ }
635
+
636
+ h->normalizing_index_offset = be32toh(encoding_flyweight.normalizing_index_offset);
637
+ h->conversion_ratio = int64_bits_to_double(be64toh(encoding_flyweight.conversion_ratio_bits));
638
+ hdr_reset_internal_counters(h);
639
+
640
+ cleanup:
641
+ (void)inflateEnd(&strm);
642
+ hdr_free(counts_array);
643
+
644
+ if (result != 0)
645
+ {
646
+ hdr_free(h);
647
+ }
648
+ else if (NULL == *histogram)
649
+ {
650
+ *histogram = h;
651
+ }
652
+ else
653
+ {
654
+ hdr_add(*histogram, h);
655
+ hdr_free(h);
656
+ }
657
+
658
+ return result;
659
+ }
660
+
661
+ int hdr_decode_compressed(
662
+ uint8_t* buffer, size_t length, struct hdr_histogram** histogram)
663
+ {
664
+ uint32_t compression_cookie;
665
+ compression_flyweight_t* compression_flyweight;
666
+
667
+ if (length < SIZEOF_COMPRESSION_FLYWEIGHT)
668
+ {
669
+ return EINVAL;
670
+ }
671
+
672
+ compression_flyweight = (compression_flyweight_t*) buffer;
673
+
674
+ compression_cookie = get_cookie_base(be32toh(compression_flyweight->cookie));
675
+ if (V0_COMPRESSION_COOKIE == compression_cookie)
676
+ {
677
+ return hdr_decode_compressed_v0(compression_flyweight, length, histogram);
678
+ }
679
+ else if (V1_COMPRESSION_COOKIE == compression_cookie)
680
+ {
681
+ return hdr_decode_compressed_v1(compression_flyweight, length, histogram);
682
+ }
683
+ else if (V2_COMPRESSION_COOKIE == compression_cookie)
684
+ {
685
+ return hdr_decode_compressed_v2(compression_flyweight, length, histogram);
686
+ }
687
+
688
+ return HDR_COMPRESSION_COOKIE_MISMATCH;
689
+ }
690
+
691
+ /* ## ## ######## #### ######## ######## ######## */
692
+ /* ## ## ## ## ## ## ## ## ## ## */
693
+ /* ## ## ## ## ## ## ## ## ## ## */
694
+ /* ## ## ## ######## ## ## ###### ######## */
695
+ /* ## ## ## ## ## ## ## ## ## ## */
696
+ /* ## ## ## ## ## ## ## ## ## ## */
697
+ /* ### ### ## ## #### ## ######## ## ## */
698
+
699
+ int hdr_log_writer_init(struct hdr_log_writer* writer)
700
+ {
701
+ (void)writer;
702
+ return 0;
703
+ }
704
+
705
+ #define LOG_VERSION "1.2"
706
+ #define LOG_MAJOR_VERSION 1
707
+
708
+ static int print_user_prefix(FILE* f, const char* prefix)
709
+ {
710
+ if (!prefix)
711
+ {
712
+ return 0;
713
+ }
714
+
715
+ return fprintf(f, "#[%s]\n", prefix);
716
+ }
717
+
718
+ static int print_version(FILE* f, const char* version)
719
+ {
720
+ return fprintf(f, "#[Histogram log format version %s]\n", version);
721
+ }
722
+
723
+ static int print_time(FILE* f, hdr_timespec* timestamp)
724
+ {
725
+ char time_str[128];
726
+ struct tm date_time;
727
+
728
+ if (!timestamp)
729
+ {
730
+ return 0;
731
+ }
732
+
733
+ #if defined(__WINDOWS__)
734
+ _gmtime32_s(&date_time, &timestamp->tv_sec);
735
+ #else
736
+ gmtime_r(&timestamp->tv_sec, &date_time);
737
+ #endif
738
+
739
+ strftime(time_str, 128, "%a %b %X %Z %Y", &date_time);
740
+
741
+ return fprintf(
742
+ f, "#[StartTime: %.3f (seconds since epoch), %s]\n",
743
+ hdr_timespec_as_double(timestamp), time_str);
744
+ }
745
+
746
+ static int print_header(FILE* f)
747
+ {
748
+ return fprintf(f, "\"StartTimestamp\",\"EndTimestamp\",\"Interval_Max\",\"Interval_Compressed_Histogram\"\n");
749
+ }
750
+
751
+ /* Example log */
752
+ /* #[Logged with jHiccup version 2.0.3-SNAPSHOT] */
753
+ /* #[Histogram log format version 1.01] */
754
+ /* #[StartTime: 1403476110.183 (seconds since epoch), Mon Jun 23 10:28:30 NZST 2014] */
755
+ /* "StartTimestamp","EndTimestamp","Interval_Max","Interval_Compressed_Histogram" */
756
+ int hdr_log_write_header(
757
+ struct hdr_log_writer* writer, FILE* file,
758
+ const char* user_prefix, hdr_timespec* timestamp)
759
+ {
760
+ (void)writer;
761
+
762
+ if (print_user_prefix(file, user_prefix) < 0)
763
+ {
764
+ return EIO;
765
+ }
766
+ if (print_version(file, LOG_VERSION) < 0)
767
+ {
768
+ return EIO;
769
+ }
770
+ if (print_time(file, timestamp) < 0)
771
+ {
772
+ return EIO;
773
+ }
774
+ if (print_header(file) < 0)
775
+ {
776
+ return EIO;
777
+ }
778
+
779
+ return 0;
780
+ }
781
+
782
+ int hdr_log_write(
783
+ struct hdr_log_writer* writer,
784
+ FILE* file,
785
+ const hdr_timespec* start_timestamp,
786
+ const hdr_timespec* end_timestamp,
787
+ struct hdr_histogram* histogram)
788
+ {
789
+ uint8_t* compressed_histogram = NULL;
790
+ size_t compressed_len = 0;
791
+ char* encoded_histogram = NULL;
792
+ int rc = 0;
793
+ int result = 0;
794
+ size_t encoded_len;
795
+
796
+ (void)writer;
797
+
798
+ rc = hdr_encode_compressed(histogram, &compressed_histogram, &compressed_len);
799
+ if (rc != 0)
800
+ {
801
+ FAIL_AND_CLEANUP(cleanup, result, rc);
802
+ }
803
+
804
+ encoded_len = hdr_base64_encoded_len(compressed_len);
805
+ encoded_histogram = (char*) hdr_calloc(encoded_len + 1, sizeof(char));
806
+
807
+ rc = hdr_base64_encode(
808
+ compressed_histogram, compressed_len, encoded_histogram, encoded_len);
809
+ if (rc != 0)
810
+ {
811
+ FAIL_AND_CLEANUP(cleanup, result, rc);
812
+ }
813
+
814
+ if (fprintf(
815
+ file, "%.3f,%.3f,%" PRIu64 ".0,%s\n",
816
+ hdr_timespec_as_double(start_timestamp),
817
+ hdr_timespec_as_double(end_timestamp),
818
+ hdr_max(histogram),
819
+ encoded_histogram) < 0)
820
+ {
821
+ result = EIO;
822
+ }
823
+
824
+ cleanup:
825
+ hdr_free(compressed_histogram);
826
+ hdr_free(encoded_histogram);
827
+
828
+ return result;
829
+ }
830
+
831
+ int hdr_log_write_entry(
832
+ struct hdr_log_writer* writer,
833
+ FILE* file,
834
+ struct hdr_log_entry* entry,
835
+ struct hdr_histogram* histogram)
836
+ {
837
+ uint8_t* compressed_histogram = NULL;
838
+ size_t compressed_len = 0;
839
+ char* encoded_histogram = NULL;
840
+ int rc = 0;
841
+ int result = 0;
842
+ size_t encoded_len;
843
+ int has_tag = 0;
844
+ const char* tag_prefix;
845
+ const char* tag_value;
846
+ const char* tag_separator;
847
+
848
+ (void)writer;
849
+
850
+ rc = hdr_encode_compressed(histogram, &compressed_histogram, &compressed_len);
851
+ if (rc != 0)
852
+ {
853
+ FAIL_AND_CLEANUP(cleanup, result, rc);
854
+ }
855
+
856
+ encoded_len = hdr_base64_encoded_len(compressed_len);
857
+ encoded_histogram = (char*) hdr_calloc(encoded_len + 1, sizeof(char));
858
+
859
+ rc = hdr_base64_encode(
860
+ compressed_histogram, compressed_len, encoded_histogram, encoded_len);
861
+ if (rc != 0)
862
+ {
863
+ FAIL_AND_CLEANUP(cleanup, result, rc);
864
+ }
865
+
866
+ has_tag = NULL != entry->tag && 0 < entry->tag_len;
867
+ tag_prefix = has_tag ? "Tag=" : "";
868
+ tag_value = has_tag ? entry->tag : "";
869
+ tag_separator = has_tag ? "," : "";
870
+
871
+ if (fprintf(
872
+ file, "%s%.*s%s%.3f,%.3f,%" PRIu64 ".0,%s\n",
873
+ tag_prefix, (int) entry->tag_len, tag_value, tag_separator,
874
+ hdr_timespec_as_double(&entry->start_timestamp),
875
+ hdr_timespec_as_double(&entry->interval),
876
+ hdr_max(histogram),
877
+ encoded_histogram) < 0)
878
+ {
879
+ result = EIO;
880
+ }
881
+
882
+ cleanup:
883
+ hdr_free(compressed_histogram);
884
+ hdr_free(encoded_histogram);
885
+
886
+ return result;
887
+ }
888
+
889
+ /* ######## ######## ### ######## ######## ######## */
890
+ /* ## ## ## ## ## ## ## ## ## ## */
891
+ /* ## ## ## ## ## ## ## ## ## ## */
892
+ /* ######## ###### ## ## ## ## ###### ######## */
893
+ /* ## ## ## ######### ## ## ## ## ## */
894
+ /* ## ## ## ## ## ## ## ## ## ## */
895
+ /* ## ## ######## ## ## ######## ######## ## ## */
896
+
897
+ int hdr_log_reader_init(struct hdr_log_reader* reader)
898
+ {
899
+ reader->major_version = 0;
900
+ reader->minor_version = 0;
901
+ reader->start_timestamp.tv_sec = 0;
902
+ reader->start_timestamp.tv_nsec = 0;
903
+
904
+ return 0;
905
+ }
906
+
907
+ static void scan_log_format(struct hdr_log_reader* reader, const char* line)
908
+ {
909
+ const char* format = "#[Histogram log format version %d.%d]";
910
+ sscanf(line, format, &reader->major_version, &reader->minor_version);
911
+ }
912
+
913
+ static void scan_start_time(struct hdr_log_reader* reader, const char* line)
914
+ {
915
+ const char* format = "#[StartTime: %lf [^\n]";
916
+ double timestamp = 0.0;
917
+
918
+ if (sscanf(line, format, &timestamp) == 1)
919
+ {
920
+ hdr_timespec_from_double(&reader->start_timestamp, timestamp);
921
+ }
922
+ }
923
+
924
+ static void scan_header_line(struct hdr_log_reader* reader, const char* line)
925
+ {
926
+ scan_log_format(reader, line);
927
+ scan_start_time(reader, line);
928
+ }
929
+
930
+ static bool validate_log_version(struct hdr_log_reader* reader)
931
+ {
932
+ return reader->major_version == LOG_MAJOR_VERSION &&
933
+ (reader->minor_version == 0 || reader->minor_version == 1 ||
934
+ reader->minor_version == 2 || reader->minor_version == 3);
935
+ }
936
+
937
+ #define HEADER_LINE_LENGTH 128
938
+
939
+ int hdr_log_read_header(struct hdr_log_reader* reader, FILE* file)
940
+ {
941
+ char line[HEADER_LINE_LENGTH]; /* TODO: check for overflow. */
942
+
943
+ bool parsing_header = true;
944
+
945
+ do
946
+ {
947
+ int c = fgetc(file);
948
+ ungetc(c, file);
949
+
950
+ switch (c)
951
+ {
952
+
953
+ case '#':
954
+ if (fgets(line, HEADER_LINE_LENGTH, file) == NULL)
955
+ {
956
+ return EIO;
957
+ }
958
+
959
+ scan_header_line(reader, line);
960
+ break;
961
+
962
+ case '"':
963
+ if (fgets(line, HEADER_LINE_LENGTH, file) == NULL)
964
+ {
965
+ return EIO;
966
+ }
967
+
968
+ parsing_header = false;
969
+ break;
970
+
971
+ default:
972
+ parsing_header = false;
973
+ }
974
+ }
975
+ while (parsing_header);
976
+
977
+ if (!validate_log_version(reader))
978
+ {
979
+ return HDR_LOG_INVALID_VERSION;
980
+ }
981
+
982
+ return 0;
983
+ }
984
+
985
+ int hdr_log_read(
986
+ struct hdr_log_reader* reader, FILE* file, struct hdr_histogram** histogram,
987
+ hdr_timespec* timestamp, hdr_timespec* interval)
988
+ {
989
+ int result;
990
+ struct hdr_log_entry log_entry;
991
+ memset(&log_entry, 0, sizeof(log_entry));
992
+
993
+ result = hdr_log_read_entry(reader, file, &log_entry, histogram);
994
+
995
+ if (0 == result)
996
+ {
997
+ if (NULL != timestamp)
998
+ {
999
+ memcpy(timestamp, &log_entry.start_timestamp, sizeof(*timestamp));
1000
+ }
1001
+ if (NULL != interval)
1002
+ {
1003
+ memcpy(interval, &log_entry.interval, sizeof(*interval));
1004
+ }
1005
+ }
1006
+
1007
+ return result;
1008
+ }
1009
+
1010
+ static int read_ahead(FILE* f, const char* prefix, size_t prefix_len)
1011
+ {
1012
+ size_t i;
1013
+ for (i = 0; i < prefix_len; i++)
1014
+ {
1015
+ if (prefix[i] != fgetc(f))
1016
+ {
1017
+ return 0;
1018
+ }
1019
+ }
1020
+
1021
+ return 1;
1022
+ }
1023
+
1024
+ static int read_ahead_timestamp(FILE* f, hdr_timespec* timestamp, char expected_terminator)
1025
+ {
1026
+ int c;
1027
+ int is_seconds = 1;
1028
+ long sec = 0;
1029
+ long nsec = 0;
1030
+ long nsec_multipler = 1000000000;
1031
+
1032
+ while (EOF != (c = fgetc(f)))
1033
+ {
1034
+ if (expected_terminator == c)
1035
+ {
1036
+ timestamp->tv_sec = sec;
1037
+ timestamp->tv_nsec = (nsec * nsec_multipler);
1038
+ return 1;
1039
+ }
1040
+ else if ('.' == c)
1041
+ {
1042
+ is_seconds = 0;
1043
+ }
1044
+ else if ('0' <= c && c <= '9')
1045
+ {
1046
+ if (is_seconds)
1047
+ {
1048
+ sec = (sec * 10) + (c - '0');
1049
+ }
1050
+ else
1051
+ {
1052
+ nsec = (nsec * 10) + (c - '0');
1053
+ nsec_multipler /= 10;
1054
+ }
1055
+ }
1056
+ else
1057
+ {
1058
+ return 0;
1059
+ }
1060
+ }
1061
+
1062
+ return 0;
1063
+ }
1064
+
1065
+ enum parse_log_state {
1066
+ INIT, TAG, BEGIN_TIMESTAMP, INTERVAL, MAX, HISTOGRAM, DONE
1067
+ };
1068
+
1069
+ int hdr_log_read_entry(
1070
+ struct hdr_log_reader* reader, FILE* file, struct hdr_log_entry *entry, struct hdr_histogram** histogram)
1071
+ {
1072
+ enum parse_log_state state = INIT;
1073
+ size_t capacity = 1024;
1074
+ size_t base64_len = 0;
1075
+ size_t tag_offset = 0;
1076
+ char* base64_histogram = hdr_calloc(capacity, sizeof(char));
1077
+ size_t compressed_len = 0;
1078
+ uint8_t* compressed_histogram = NULL;
1079
+ int result = -EINVAL;
1080
+
1081
+ (void)reader;
1082
+
1083
+ if (NULL == entry)
1084
+ {
1085
+ return -EINVAL;
1086
+ }
1087
+
1088
+ do
1089
+ {
1090
+ int c;
1091
+
1092
+ switch (state)
1093
+ {
1094
+ case INIT:
1095
+ c = fgetc(file);
1096
+ if ('T' == c)
1097
+ {
1098
+ if (read_ahead(file, "ag=", 3))
1099
+ {
1100
+ state = TAG;
1101
+ }
1102
+ else
1103
+ {
1104
+ FAIL_AND_CLEANUP(cleanup, result, -EINVAL);
1105
+ }
1106
+ }
1107
+ else if ('0' <= c && c <= '9')
1108
+ {
1109
+ ungetc(c, file);
1110
+ state = BEGIN_TIMESTAMP;
1111
+ }
1112
+ else if ('\r' == c || '\n' == c)
1113
+ {
1114
+ /* Skip over trailing/preceding new lines. */
1115
+ }
1116
+ else if (EOF == c)
1117
+ {
1118
+ FAIL_AND_CLEANUP(cleanup, result, EOF);
1119
+ }
1120
+ else
1121
+ {
1122
+ FAIL_AND_CLEANUP(cleanup, result, -EINVAL);
1123
+ }
1124
+ break;
1125
+ case TAG:
1126
+ c = fgetc(file);
1127
+ if (',' == c)
1128
+ {
1129
+ if (NULL != entry->tag && tag_offset < entry->tag_len)
1130
+ {
1131
+ entry->tag[tag_offset] = '\0';
1132
+ }
1133
+ state = BEGIN_TIMESTAMP;
1134
+ }
1135
+ else if ('\r' == c || '\n' == c || EOF == c)
1136
+ {
1137
+ FAIL_AND_CLEANUP(cleanup, result, -EINVAL);
1138
+ }
1139
+ else
1140
+ {
1141
+ if (NULL != entry->tag && tag_offset < entry->tag_len)
1142
+ {
1143
+ entry->tag[tag_offset] = (char) c;
1144
+ tag_offset++;
1145
+ }
1146
+ }
1147
+ break;
1148
+ case BEGIN_TIMESTAMP:
1149
+ if (read_ahead_timestamp(file, &entry->start_timestamp, ','))
1150
+ {
1151
+ state = INTERVAL;
1152
+ }
1153
+ else
1154
+ {
1155
+ FAIL_AND_CLEANUP(cleanup, result, -EINVAL);
1156
+ }
1157
+ break;
1158
+ case INTERVAL:
1159
+ if (read_ahead_timestamp(file, &entry->interval, ','))
1160
+ {
1161
+ state = MAX;
1162
+ }
1163
+ else
1164
+ {
1165
+ FAIL_AND_CLEANUP(cleanup, result, -EINVAL);
1166
+ }
1167
+ break;
1168
+ case MAX:
1169
+ if (read_ahead_timestamp(file, &entry->max, ','))
1170
+ {
1171
+ state = HISTOGRAM;
1172
+ }
1173
+ else
1174
+ {
1175
+ FAIL_AND_CLEANUP(cleanup, result, -EINVAL);
1176
+ }
1177
+ break;
1178
+ case HISTOGRAM:
1179
+ c = fgetc(file);
1180
+ if (c != '\r' && c != '\n' && c != EOF)
1181
+ {
1182
+ if (base64_len == capacity)
1183
+ {
1184
+ capacity *= 2;
1185
+ base64_histogram = hdr_realloc(base64_histogram, capacity * sizeof(char));
1186
+ if (NULL == base64_histogram)
1187
+ {
1188
+ FAIL_AND_CLEANUP(cleanup, result, -ENOMEM);
1189
+ }
1190
+ }
1191
+ base64_histogram[base64_len++] = (char) c;
1192
+ }
1193
+ else
1194
+ {
1195
+ state = DONE;
1196
+ }
1197
+ break;
1198
+
1199
+ default:
1200
+ FAIL_AND_CLEANUP(cleanup, result, -EINVAL);
1201
+ }
1202
+ }
1203
+ while (DONE != state);
1204
+
1205
+ compressed_histogram = hdr_calloc(base64_len, sizeof(uint8_t));
1206
+ compressed_len = hdr_base64_decoded_len(base64_len);
1207
+
1208
+ result = hdr_base64_decode(
1209
+ base64_histogram, base64_len, compressed_histogram, compressed_len);
1210
+ if (result != 0)
1211
+ {
1212
+ goto cleanup;
1213
+ }
1214
+
1215
+ result = hdr_decode_compressed(compressed_histogram, compressed_len, histogram);
1216
+
1217
+ cleanup:
1218
+ hdr_free(base64_histogram);
1219
+ hdr_free(compressed_histogram);
1220
+ return result;
1221
+ }
1222
+
1223
+
1224
+ int hdr_log_encode(struct hdr_histogram* histogram, char** encoded_histogram)
1225
+ {
1226
+ char *encoded_histogram_tmp = NULL;
1227
+ uint8_t* compressed_histogram = NULL;
1228
+ size_t compressed_len = 0;
1229
+ int rc = 0;
1230
+ int result = 0;
1231
+ size_t encoded_len;
1232
+
1233
+ rc = hdr_encode_compressed(histogram, &compressed_histogram, &compressed_len);
1234
+ if (rc != 0)
1235
+ {
1236
+ FAIL_AND_CLEANUP(cleanup, result, rc);
1237
+ }
1238
+
1239
+ encoded_len = hdr_base64_encoded_len(compressed_len);
1240
+ encoded_histogram_tmp = (char*) hdr_calloc(encoded_len + 1, sizeof(char));
1241
+
1242
+ rc = hdr_base64_encode(
1243
+ compressed_histogram, compressed_len, encoded_histogram_tmp, encoded_len);
1244
+ if (rc != 0)
1245
+ {
1246
+ hdr_free(encoded_histogram_tmp);
1247
+ FAIL_AND_CLEANUP(cleanup, result, rc);
1248
+ }
1249
+
1250
+ *encoded_histogram = encoded_histogram_tmp;
1251
+
1252
+ cleanup:
1253
+ hdr_free(compressed_histogram);
1254
+
1255
+ return result;
1256
+ }
1257
+
1258
+ int hdr_log_decode(struct hdr_histogram** histogram, char* base64_histogram, size_t base64_len)
1259
+ {
1260
+ int r;
1261
+ uint8_t* compressed_histogram = NULL;
1262
+ int result = 0;
1263
+
1264
+ size_t compressed_len = hdr_base64_decoded_len(base64_len);
1265
+ compressed_histogram = (uint8_t*) hdr_malloc(sizeof(uint8_t)*compressed_len);
1266
+ memset(compressed_histogram, 0, compressed_len);
1267
+
1268
+ r = hdr_base64_decode(
1269
+ base64_histogram, base64_len, compressed_histogram, compressed_len);
1270
+
1271
+ if (r != 0)
1272
+ {
1273
+ FAIL_AND_CLEANUP(cleanup, result, r);
1274
+ }
1275
+
1276
+ r = hdr_decode_compressed(compressed_histogram, compressed_len, histogram);
1277
+ if (r != 0)
1278
+ {
1279
+ FAIL_AND_CLEANUP(cleanup, result, r);
1280
+ }
1281
+
1282
+ cleanup:
1283
+ hdr_free(compressed_histogram);
1284
+
1285
+ return result;
1286
+ }
1287
+
1288
+ #if defined(_MSC_VER)
1289
+ #pragma warning(pop)
1290
+ #endif