ERL_NIF_TERM _hh_to_binary_uncompressed(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hh_ctx_t* ctx = NULL; ErlNifBinary target; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 1 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL) { return enif_make_badarg(env); } int size = 0; uint8_t* data = NULL; int success = hdr_encode_uncompressed(ctx->data, &data, &size); if (!enif_alloc_binary(size, &target)) { return make_error(env, "bad_hdr_binary_alloc"); } target.size = size; memcpy(target.data,data,size); free(data); if (success != 0) { return make_error(env, "bad_hdr_binary"); } return enif_make_binary(env, &target); }
ERL_NIF_TERM _hh_lowest_at(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int64_t value = 0; hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 2 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL || !enif_get_int64(env, argv[1], &value)) { return enif_make_badarg(env); } if (ctx != NULL) { return enif_make_int64( env, hdr_lowest_equivalent_value(ctx->data, value) ); } return make_error(env, "bad_hdr_histogram_nif_impl"); }
ERL_NIF_TERM _hh_from_binary(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary source; if (!enif_inspect_binary(env, argv[0], &source)) { return enif_make_badarg(env); } hdr_histogram_t* target = NULL; int success = hdr_decode(source.data, source.size, &target); if (success != 0) { return make_error(env, "bad_hdr_binary"); } ErlNifResourceType* ctx_type = get_hh_ctx_type(env); hh_ctx_t* ctx = (hh_ctx_t*)enif_alloc_resource(ctx_type, sizeof(hh_ctx_t)); ctx->data = (hdr_histogram_t*)target; ctx->highest_trackable_value = target->highest_trackable_value; ctx->significant_figures = target->significant_figures; ERL_NIF_TERM result = enif_make_resource(env, ctx); enif_release_resource(ctx); return enif_make_tuple2(env, ATOM_OK, result); }
ERL_NIF_TERM _hh_log_csv(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { char fname[64]; hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 2 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL || !enif_get_string(env, argv[1], fname, 64, ERL_NIF_LATIN1)) { return enif_make_badarg(env); } FILE* stream = fopen(fname,"w+"); if (stream == NULL) { return make_error(env, "cannot_create_or_write_to_file"); } if (ctx != NULL) { hdr_percentiles_print(ctx->data, stream, 5, 1.0, CSV); if (fclose(stream) != 0) { return make_error(env, "bad_file"); } return ATOM_OK; } (void)fclose(stream); return make_error(env, "bad_hdr_histogram_nif_impl"); }
ERL_NIF_TERM _hh_same(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int64_t a = 0; int64_t b = 0; hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 3 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL || !enif_get_int64(env, argv[1], &a) || !enif_get_int64(env, argv[2], &b)) { return enif_make_badarg(env); } if (ctx != NULL) { return hdr_values_are_equivalent(ctx->data,a,b) ? ATOM_TRUE : ATOM_FALSE; } return make_error(env, "bad_hdr_histogram_nif_impl"); }
ERL_NIF_TERM _hh_percentile(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { double percentile; hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 2 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL || !enif_get_double(env, argv[1], &percentile)) { return enif_make_badarg(env); } if (ctx != NULL) { if (ctx->data->total_count == 0) { return enif_make_double(env, 0.); } else { return enif_make_double( env, round_to_significant_figures( hdr_value_at_percentile(ctx->data,percentile), ctx->significant_figures ) ); } } return make_error(env, "bad_hdr_histogram_nif_impl"); }
ERL_NIF_TERM _hh_max(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 1 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL) { return enif_make_badarg(env); } if (ctx != NULL) { if (ctx->data->total_count == 0) { return enif_make_int64(env, 0); } else { return enif_make_int64(env, hdr_max(ctx->data)); } } return make_error(env, "bad_hdr_histogram_nif_impl"); }
ERL_NIF_TERM _hh_record_many(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int64_t value = 0; int64_t count = 0; hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if(argc != 3 || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL || !enif_get_int64(env, argv[1], &value) || !enif_get_int64(env, argv[2], &count)) { return enif_make_badarg(env); } if (value < 0 || value > ctx->highest_trackable_value) { return make_error(env, "value_out_of_range"); } if (ctx != NULL && ctx->data != NULL) { hdr_record_values(ctx->data, value, count); } return ATOM_OK; }
ERL_NIF_TERM _hh_rotate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hh_ctx_t* ctx = NULL; hh_ctx_t* to = NULL; ErlNifBinary target; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 2 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL || !enif_get_resource(env, argv[1], ctx_type, (void **)&to) || to->data == NULL) { return enif_make_badarg(env); } hdr_histogram_t* diff_histogram; int rc = 0; rc = hdr_alloc(ctx->highest_trackable_value, ctx->significant_figures, &diff_histogram); if (ENOMEM == rc) { return make_error(env, "not_enough_memory"); } hdr_rotate(ctx->data, to->data, diff_histogram); int size = 0; uint8_t* data = NULL; int success = hdr_encode_uncompressed(diff_histogram, &data, &size); if (!enif_alloc_binary(size, &target)) { return make_error(env, "bad_hdr_binary_alloc"); } target.size = size; memcpy(target.data, data, size); free(data); free(diff_histogram); if (success != 0) { return make_error(env, "bad_hdr_binary"); } return enif_make_binary(env, &target); }
ERL_NIF_TERM _hh_get_total_count(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (ctx_type != NULL && !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx)) { return enif_make_badarg(env); } if (ctx != NULL) { return enif_make_ulong(env,ctx->data->total_count); } return make_error(env, "bad_hdr_histogram_nif_impl"); }
ERL_NIF_TERM _hh_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (ctx_type != NULL && !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx)) { return enif_make_badarg(env); } if (ctx != NULL && ctx->data != NULL) { free(ctx->data); ctx->data = NULL; } return ATOM_OK; }
ERL_NIF_TERM _hh_print_csv(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (ctx_type != NULL && !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx)) { return enif_make_badarg(env); } if (ctx != NULL) { hdr_percentiles_print(ctx->data, stdout, 5, 1.0, CSV); return ATOM_OK; } return make_error(env, "bad_hdr_histogram_nif_impl"); }
ERL_NIF_TERM _hh_min(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 1 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx)) { return enif_make_badarg(env); } if (ctx != NULL) { return enif_make_long(env, hdr_min(ctx->data)); } return make_error(env, "bad_hdr_histogram_nif_impl"); }
ERL_NIF_TERM _hh_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { long highest_trackable_value = 0; int significant_figures = 0; if (argc != 2 || !enif_get_int64(env, argv[0], &highest_trackable_value) || !enif_get_int(env, argv[1], &significant_figures)) { return enif_make_badarg(env); } hdr_histogram_t* raw_histogram; int rc = 0; rc = hdr_alloc(highest_trackable_value, significant_figures, &raw_histogram); if (EINVAL == rc) { return make_error(env, "bad_significant_factor"); } if (ENOMEM == rc) { return make_error(env, "not_enough_memory"); } ErlNifResourceType* ctx_type = get_hh_ctx_type(env); hh_ctx_t* ctx = (hh_ctx_t*)enif_alloc_resource(ctx_type, sizeof(hh_ctx_t)); ctx->data = raw_histogram; ctx->highest_trackable_value = highest_trackable_value; ctx->significant_figures = significant_figures; ERL_NIF_TERM result = enif_make_resource(env, ctx); enif_release_resource(ctx); return enif_make_tuple2(env, ATOM_OK, result); }
ERL_NIF_TERM _hh_add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hh_ctx_t* ctx = NULL; hh_ctx_t* from = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 2 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL || !enif_get_resource(env, argv[1], ctx_type, (void **)&from) || from->data == NULL) { return enif_make_badarg(env); } if (ctx != NULL) { return enif_make_int64(env, hdr_add(ctx->data, from->data)); } return make_error(env, "bad_hdr_histogram_nif_impl"); }
ERL_NIF_TERM _hi_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hi_ctx_t* ctx = NULL; hh_ctx_t* hdr = NULL; hi_opts_t* opts = NULL; ErlNifResourceType* hh_ctx_type = get_hh_ctx_type(env); ErlNifResourceType* hi_ctx_type = get_hi_ctx_type(env); if (argc != 3 || hh_ctx_type == NULL || hi_ctx_type == NULL || !enif_get_resource(env, argv[0], hi_ctx_type, (void **)&ctx) || !enif_get_resource(env, argv[1], hh_ctx_type, (void **)&hdr) || !enif_is_list(env, argv[2])) { return enif_make_badarg(env); } opts = (hi_opts_t *)enif_alloc(sizeof(hi_opts_t)); parse_opts(env, argv[2], opts, (void *)parse_opt); uint32_t iterator_type = ctx->type; void* it = NULL; if (iterator_type == HDR_ITER_REC) { struct hdr_recorded_iter * iter = enif_alloc(sizeof(struct hdr_recorded_iter)); hdr_recorded_iter_init(iter, hdr->data); it = iter; } if (iterator_type == HDR_ITER_LIN) { if (opts->linear_value_units_per_bucket <= 0) { return make_error(env, "bad_linear_value_unit"); } struct hdr_linear_iter * iter = enif_alloc(sizeof(struct hdr_linear_iter)); hdr_linear_iter_init( iter, hdr->data, opts->linear_value_units_per_bucket); it = iter; } if (iterator_type == HDR_ITER_LOG) { if (opts->log_value_units_first_bucket <= 0) { return make_error(env, "bad_log_value_unit"); } if (opts->log_base <= 0) { return make_error(env, "bad_log_base"); } struct hdr_log_iter * iter = enif_alloc(sizeof(struct hdr_log_iter)); hdr_log_iter_init( iter, hdr->data, opts->log_value_units_first_bucket, opts->log_base); it = iter; } if (iterator_type == HDR_ITER_PCT) { if (opts->percentile_ticks_per_half_distance <= 0) { return make_error(env, "bad_percentile_half_ticks"); } struct hdr_percentile_iter * iter = enif_alloc(sizeof(struct hdr_percentile_iter)); hdr_percentile_iter_init( iter, hdr->data, opts->percentile_ticks_per_half_distance); it = iter; } ctx->type = iterator_type; ctx->opts = opts; ctx->iter = it; return ATOM_OK; }