summaryrefslogtreecommitdiff
path: root/src/metrics/python_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/metrics/python_api.c')
-rw-r--r--src/metrics/python_api.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/metrics/python_api.c b/src/metrics/python_api.c
new file mode 100644
index 0000000..83ad75c
--- /dev/null
+++ b/src/metrics/python_api.c
@@ -0,0 +1,140 @@
+#include <string.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "histogram_encoder.h"
+#include "base64/b64.h"
+#include "st_hyperloglog.h"
+
+// user must free the buf after use
+void *histogram_base64_decode(char *buf)
+{
+ size_t buffer_size = strlen(buf);
+ struct hdr_histogram *hdr = histogram_decode_from_b64(buf, buffer_size);
+
+ return hdr;
+}
+
+long long histogram_value_at_percentile(void* h, double percentile)
+{
+ return hdr_value_at_percentile((const struct hdr_histogram *)h, percentile);
+}
+
+long long histogram_count_le_value(void* h, long long value)
+{
+ return hdr_count_le_value((const struct hdr_histogram *)h, value);
+}
+
+long long histogram_value_min(void* h)
+{
+ return hdr_min((const struct hdr_histogram *)h);
+}
+
+long long histogram_value_max(void* h)
+{
+ return hdr_max((const struct hdr_histogram *)h);
+}
+
+double histogram_value_mean(void* h)
+{
+ return hdr_mean((const struct hdr_histogram *)h);
+}
+
+double histogram_value_stddev(void* h)
+{
+ return hdr_stddev((const struct hdr_histogram *)h);
+}
+
+long long histogram_value_total_count(void *h)
+{
+ return ((struct hdr_histogram *)h)->total_count;
+}
+
+long long histogram_value_sum(void *h)
+{
+ struct hdr_iter iter;
+ long long sum = 0;
+ hdr_iter_recorded_init(&iter, (const struct hdr_histogram *)h);
+ while (hdr_iter_next(&iter))
+ {
+ sum+=(long long)iter.value;
+ }
+ return sum;
+}
+
+void histogram_free(void *h)
+{
+ hdr_close((struct hdr_histogram *)h);
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* hyperloglog */
+/* -------------------------------------------------------------------------- */
+void *hll_base64_decode(char *buf);
+double hll_base64_to_count(char *buf)
+{
+ struct ST_hyperloglog *hll = hll_base64_decode(buf);
+ double count = ST_hyperloglog_count(hll);
+ ST_hyperloglog_free(hll);
+ return count;
+}
+
+#define BigLittleSwap32(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \
+ (((uint32_t)(A) & 0x00ff0000) >> 8) | \
+ (((uint32_t)(A) & 0x0000ff00) << 8) | \
+ (((uint32_t)(A) & 0x000000ff) << 24))
+
+void *hll_base64_decode(char *buf)
+{
+ size_t buffer_size = strlen(buf);
+ size_t dec_size = 0;
+ unsigned char *dec = b64_decode_ex(buf, buffer_size, &dec_size);
+
+ unsigned char version;
+ memcpy(&version, dec, sizeof(unsigned char));
+ if (version != 1) {
+ return NULL;
+ }
+
+ unsigned char precision;
+ memcpy(&precision, dec + sizeof(unsigned char), sizeof(unsigned char));
+
+ struct ST_hyperloglog *hll_from_blob = ST_hyperloglog_new(precision);
+
+ int num_reg = NUM_REG(precision);
+ int words = INT_CEIL(num_reg, REG_PER_WORD);
+ size_t reg_size = words * sizeof(uint32_t);
+ uint32_t *registers = (uint32_t *)malloc(reg_size);
+ memcpy(registers, dec + 2 * sizeof(unsigned char), reg_size);
+ for (int i = 0; i < words; i++) {
+ registers[i] = BigLittleSwap32(registers[i]);
+ }
+ memcpy(hll_from_blob->registers, registers, reg_size);
+ free(registers);
+
+ free(dec);
+ return hll_from_blob;
+}
+
+void hll_free(void *hll)
+{
+ ST_hyperloglog_free((struct ST_hyperloglog *)hll);
+}
+
+// cppcheck-suppress [constParameterPointer, unmatchedSuppression]
+bool is_hll(char *buf)
+{
+ size_t dec_size = 0;
+ unsigned char *dec = b64_decode_ex(buf, 4, &dec_size); // 4: base64 convert every 3 bytes to 4 bytes
+ char cookie = *(char *)dec;
+ free(dec);
+
+ if (cookie == 1) { // hll version is 1
+ return true;
+ }
+
+ // histogram cookie is also fixed, it's first byte is always 28, refer to V2_ENCODING_COOKIE (1c == 28)
+ return false;
+}