ERL_NIF_TERM x_pool_create_for_user(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { uint64_t id; char pool_name[MAX_NAME_LEN]; uint64_t uid; if (!enif_get_uint64(env, argv[0], &id) || !enif_get_string(env, argv[1], pool_name, MAX_NAME_LEN, ERL_NIF_LATIN1) || !enif_get_uint64(env, argv[2], &uid)) { return enif_make_badarg(env); } rados_t cluster = map_cluster_get(id); if (cluster == NULL) { return enif_make_badarg(env); } int err = rados_pool_create_with_auid(cluster, pool_name, uid); if (err < 0) { return make_error_tuple(env, -err); } return enif_make_atom(env, "ok"); }
ERL_NIF_TERM x_get_instance_id(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { const char * func_name = "x_get_instance_id()"; uint64_t id; if (!enif_get_uint64(env, argv[0], &id)) { logger.error(MOD_NAME, func_name, "enif get params failed"); return enif_make_badarg(env); } logger.debug(MOD_NAME, func_name, "cluster : %ld", id); rados_t cluster = map_cluster_get(id); if (cluster == NULL) { logger.error(MOD_NAME, func_name, "cluster non-existing : %ld", id); return enif_make_badarg(env); } uint64_t inst_id = rados_get_instance_id(cluster); return enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_uint64(env, inst_id)); }
ERL_NIF_TERM x_conf_set(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { const char * func_name = "x_conf_set()"; logger.debug(MOD_NAME, func_name, "Entered"); uint64_t id; char option[MAX_NAME_LEN]; memset(option, 0, MAX_NAME_LEN); char value[MAX_NAME_LEN]; memset(value, 0, MAX_NAME_LEN); if (!enif_get_uint64(env, argv[0], &id) || !enif_get_string(env, argv[1], option, MAX_NAME_LEN, ERL_NIF_LATIN1) || !enif_get_string(env, argv[1], option, MAX_NAME_LEN, ERL_NIF_LATIN1)) { logger.error(MOD_NAME, func_name, "enif get params failed"); return enif_make_badarg(env); } logger.debug(MOD_NAME, func_name, "cluster : %ld", id); rados_t cluster = map_cluster_get(id); if (cluster == NULL) { logger.error(MOD_NAME, func_name, "cluster non-existing : %ld", id); return enif_make_badarg(env); } int err = rados_conf_set(cluster, option, value); if (err < 0) { return make_error_tuple(env, -err); } return enif_make_atom(env, "ok"); }
void* cb_store_args(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { store_args_t* args = (store_args_t*)enif_alloc(sizeof(store_args_t)); ErlNifBinary value_binary; ErlNifBinary key_binary; if (!enif_get_int(env, argv[0], &args->operation)) goto error0; if (!enif_inspect_iolist_as_binary(env, argv[1], &key_binary)) goto error0; if (!enif_inspect_iolist_as_binary(env, argv[2], &value_binary)) goto error0; args->nkey = key_binary.size; args->nbytes = value_binary.size; args->key = (char*)malloc(key_binary.size); args->bytes = (char*)malloc(value_binary.size); memcpy(args->bytes, value_binary.data, value_binary.size); memcpy(args->key, key_binary.data, key_binary.size); if (!enif_get_uint(env, argv[3], &args->flags)) goto error1; if (!enif_get_int(env, argv[4], &args->exp)) goto error1; if (!enif_get_uint64(env, argv[5], (ErlNifUInt64*)&args->cas)) goto error1; return args; error1: free(args->bytes); free(args->key); error0: enif_free(args); return NULL; }
ERL_NIF_TERM x_pool_lookup(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { uint64_t id; char pool_name[MAX_NAME_LEN]; if (!enif_get_uint64(env, argv[0], &id) || !enif_get_string(env, argv[1], pool_name, MAX_NAME_LEN, ERL_NIF_LATIN1)) { return enif_make_badarg(env); } rados_t cluster = map_cluster_get(id); if (cluster == NULL) { return enif_make_badarg(env); } int64_t err = rados_pool_lookup(cluster, pool_name); if (err < 0) { return make_error_tuple(env, -err); } return enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_int64(env, err)); // Pool ID }
ERL_NIF_TERM x_conf_read_file(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { const char * func_name = "x_conf_read_file()"; logger.debug(MOD_NAME, func_name, "Entered"); uint64_t id; if (!enif_get_uint64(env, argv[0], &id)) { logger.error(MOD_NAME, func_name, "enif get params failed"); return enif_make_badarg(env); } logger.debug(MOD_NAME, func_name, "cluster : %ld", id); rados_t cluster = map_cluster_get(id); if (cluster == NULL) { logger.error(MOD_NAME, func_name, "cluster non-existing : %ld", id); return enif_make_badarg(env); } int err = rados_conf_read_file(cluster, NULL); if (err < 0) { logger.error(MOD_NAME, func_name, "failed to read default config file for cluster: %ld", id); return make_error_tuple(env, -err); } return enif_make_atom(env, "ok"); }
ERL_NIF_TERM x_cluster_stat(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { const char * func_name = "x_cluster_stat()"; uint64_t id; if (!enif_get_uint64(env, argv[0], &id)) { logger.error(MOD_NAME, func_name, "enif get params failed"); return enif_make_badarg(env); } logger.debug(MOD_NAME, func_name, "cluster : %ld", id); rados_t cluster = map_cluster_get(id); if (cluster == NULL) { logger.error(MOD_NAME, func_name, "cluster non-existing : %ld", id); return enif_make_badarg(env); } rados_cluster_stat_t stat; int err = rados_cluster_stat(cluster, &stat); if (err < 0) { logger.error(MOD_NAME, func_name, "failed to get stat for %ld: %s", id, strerror(-err)); return make_error_tuple(env, -err); } ERL_NIF_TERM term_list = enif_make_list(env, 0); ERL_NIF_TERM t = enif_make_uint64(env, stat.num_objects); term_list = enif_make_list_cell(env, enif_make_tuple2(env, enif_make_atom(env, "num_objects"), t), term_list); t = enif_make_uint64(env, stat.kb_avail); term_list = enif_make_list_cell(env, enif_make_tuple2(env, enif_make_atom(env, "kb_avail"), t), term_list); t = enif_make_uint64(env, stat.kb_used); term_list = enif_make_list_cell(env, enif_make_tuple2(env, enif_make_atom(env, "kb_used"), t), term_list); t = enif_make_uint64(env, stat.kb); term_list = enif_make_list_cell(env, enif_make_tuple2(env, enif_make_atom(env, "kb"), t), term_list); return enif_make_tuple2(env, enif_make_atom(env, "ok"), term_list); }
static ERL_NIF_TERM diff_timestamp(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { unsigned long start = 0; unsigned long end = 0; enif_get_uint64(env, argv[0], &end); enif_get_uint64(env, argv[1], &start); uint64_t elapsed = end - start; mach_timebase_info_data_t info; uint64_t nanosecs = 0; if (mach_timebase_info (&info) == KERN_SUCCESS) { nanosecs = elapsed * info.numer / info.denom; } return enif_make_uint64(env, nanosecs); }
/* create(Cache :: atom(), MaxSize :: integer(), MinQ1Size :: integer()) */ static ERL_NIF_TERM create(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM atom; ErlNifUInt64 max_size, min_q1_size; struct cache *c; if (!enif_is_atom(env, argv[0])) return enif_make_badarg(env); atom = argv[0]; if (!enif_get_uint64(env, argv[1], &max_size)) return enif_make_badarg(env); if (!enif_get_uint64(env, argv[2], &min_q1_size)) return enif_make_badarg(env); if ((c = get_cache(atom))) { ERL_NIF_TERM ret = enif_make_atom(env, "already_exists"); enif_consume_timeslice(env, 5); enif_rwlock_rwlock(c->cache_lock); /* expansion is safe because we don't have to engage the background thread and won't cause sudden eviction pressure TODO: a nice way to shrink the cache without seizing it up */ if (c->max_size < max_size && c->min_q1_size < min_q1_size) { c->max_size = max_size; c->min_q1_size = min_q1_size; enif_rwlock_rwunlock(c->cache_lock); ret = enif_make_atom(env, "ok"); enif_consume_timeslice(env, 10); } else { enif_rwlock_rwunlock(c->cache_lock); } return ret; } else { c = new_cache(atom, max_size, min_q1_size); enif_consume_timeslice(env, 20); return enif_make_atom(env, "ok"); } }
static ERL_NIF_TERM weight_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { unsigned long long input; unsigned int ret; if (!enif_get_uint64(env, argv[0], &input)) { return enif_make_badarg(env); } ret = weight(input); return enif_make_uint(env, ret); }
static int test_uint64(ErlNifEnv* env, ErlNifUInt64 i1) { ErlNifUInt64 i2 = 0; ERL_NIF_TERM int_term = enif_make_uint64(env, i1); if (!enif_get_uint64(env,int_term, &i2) || i1 != i2) { fprintf(stderr, "test_ulong(%lu) ...FAILED i2=%lu\r\n", (unsigned long)i1, (unsigned long)i2); return 0; } return 1; }
void* cb_arithmetic_args(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { arithmetic_args_t* args = (arithmetic_args_t*)enif_alloc(sizeof(arithmetic_args_t)); ErlNifBinary key_binary; if (!enif_inspect_iolist_as_binary(env, argv[0], &key_binary)) goto error0; args->key = malloc(sizeof(char) * key_binary.size); memcpy(args->key, key_binary.data, key_binary.size); args->nkey = key_binary.size; if (!enif_get_int64(env, argv[1], (ErlNifSInt64*)&args->delta)) goto error1; if (!enif_get_uint64(env, argv[2], (ErlNifUInt64 *)&args->exp)) goto error1; if (!enif_get_int(env, argv[3], &args->create)) goto error1; if (!enif_get_uint64(env, argv[4], (ErlNifUInt64 *)&args->initial)) goto error1; return (void*)args; error1: free(args->key); error0: enif_free(args); return NULL; }
ERL_NIF_TERM erlang_murmurhash64b_2_impl(ErlNifEnv* env, int, const ERL_NIF_TERM argv[]) { ErlNifBinary bin; uint64_t h; uint64_t seed; if (!check_and_unpack_data(env, argv[0], &bin)) { return enif_make_badarg(env); } if (!enif_get_uint64(env, argv[1], &seed)) { return enif_make_badarg(env); } h = MurmurHash64B(bin.data, bin.size, seed); return enif_make_uint64(env, h); }
ERL_NIF_TERM x_conf_read_file2(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { const char * func_name = "x_conf_read_file2()"; logger.debug(MOD_NAME, func_name, "Entered"); logger.flush(); uint64_t id; char conf_file[MAX_FILE_NAME_LEN]; memset(conf_file, 0, MAX_FILE_NAME_LEN); if (!enif_get_uint64(env, argv[0], &id) || !enif_get_string(env, argv[1], conf_file, MAX_FILE_NAME_LEN, ERL_NIF_LATIN1)) { logger.error(MOD_NAME, func_name, "enif get params failed"); return enif_make_badarg(env); } logger.debug(MOD_NAME, func_name, "cluster : %ld", id); logger.flush(); rados_t cluster = map_cluster_get(id); if (cluster == NULL) { logger.error(MOD_NAME, func_name, "cluster non-existing : %ld", id); return enif_make_badarg(env); } logger.debug(MOD_NAME, func_name, "cluster found: %ld", id); logger.flush(); int err = rados_conf_read_file(cluster, conf_file); if (err < 0) { logger.error(MOD_NAME, func_name, "failed to read default config file %s for cluster: %ld", conf_file, id); return make_error_tuple(env, -err); } logger.debug(MOD_NAME, func_name, "config file read: %ld", id); logger.flush(); return enif_make_atom(env, "ok"); }
void* cb_unlock_args(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { unlock_args_t* args = (unlock_args_t*)enif_alloc(sizeof(unlock_args_t)); ErlNifBinary key_binary; if (!enif_inspect_iolist_as_binary(env, argv[0], &key_binary)) goto error0; args->nkey = key_binary.size; args->key = (char *) malloc(key_binary.size); memcpy(args->key, key_binary.data, key_binary.size); if (!enif_get_uint64(env, argv[1], (ErlNifUInt64*)&args->cas)) goto error1; return (void*)args; error1: free(args->key); error0: enif_free(args); return NULL; }
/** * Initialize */ static ERL_NIF_TERM leo_mcerl_nif_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifUInt64 max_size; ERL_NIF_TERM term; ErlNifResourceType* pert; lcu_cache* cache; if (argc < 1) { return enif_make_badarg(env); } if (!enif_get_uint64(env, argv[0], &max_size)) { return enif_make_badarg(env); } pert = (ErlNifResourceType*)enif_priv_data(env); cache = enif_alloc_resource(pert, sizeof(lcu_cache)); lcu_cache_init(cache, auto_eject_on, max_size, 2, 256, 1024 * 1024 * 8); term = enif_make_resource(env, cache); enif_release_resource(cache); return enif_make_tuple2(env, atom_ok, term); }
ERL_NIF_TERM x_shutdown(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { const char * func_name = "x_shutdown()"; logger.debug(MOD_NAME, func_name, "Entered"); uint64_t id; if (!enif_get_uint64(env, argv[0], &id)) { logger.error(MOD_NAME, func_name, "enif get params failed"); return enif_make_badarg(env); } logger.debug(MOD_NAME, func_name, "cluster : %ld", id); logger.flush(); rados_t cluster = map_cluster_get(id); if (cluster == NULL) { logger.error(MOD_NAME, func_name, "cluster non-existing : %ld", id); return enif_make_badarg(env); } logger.debug(MOD_NAME, func_name, "found cluster: %ld", id); logger.flush(); rados_shutdown(cluster); logger.debug(MOD_NAME, func_name, "cluster shutdown: %ld", id); logger.flush(); map_cluster_remove(id); logger.debug(MOD_NAME, func_name, "cluster erased: %ld", id); logger.flush(); return enif_make_atom(env, "ok"); }
static ERL_NIF_TERM put(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM atom; ErlNifBinary kbin, vbin; struct cache *c; struct cache_node *n, *ng; ErlNifUInt64 lifetime = 0; if (!enif_is_atom(env, argv[0])) return enif_make_badarg(env); atom = argv[0]; if (!enif_inspect_binary(env, argv[1], &kbin)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[2], &vbin)) return enif_make_badarg(env); if ((c = get_cache(atom))) { enif_consume_timeslice(env, 1); } else { /* if we've been asked to put() in to a cache that doesn't exist yet then we should create it! */ ErlNifUInt64 max_size, min_q1_size; if (!enif_get_uint64(env, argv[3], &max_size)) return enif_make_badarg(env); if (!enif_get_uint64(env, argv[4], &min_q1_size)) return enif_make_badarg(env); c = new_cache(atom, max_size, min_q1_size); enif_consume_timeslice(env, 20); } if (argc > 5) if (!enif_get_uint64(env, argv[5], &lifetime)) return enif_make_badarg(env); n = enif_alloc(sizeof(*n)); memset(n, 0, sizeof(*n)); n->c = c; n->vsize = vbin.size; n->ksize = kbin.size; n->size = vbin.size + kbin.size; n->key = enif_alloc(kbin.size); memcpy(n->key, kbin.data, kbin.size); n->val = enif_alloc_resource(value_type, vbin.size); memcpy(n->val, vbin.data, vbin.size); n->q = &(c->q1); if (lifetime) { clock_now(&(n->expiry)); n->expiry.tv_sec += lifetime; } enif_rwlock_rwlock(c->cache_lock); enif_rwlock_rwlock(c->lookup_lock); HASH_FIND(hh, c->lookup, kbin.data, kbin.size, ng); if (ng) { enif_mutex_lock(c->ctrl_lock); destroy_cache_node(ng); enif_mutex_unlock(c->ctrl_lock); } TAILQ_INSERT_HEAD(&(c->q1.head), n, entry); c->q1.size += n->size; HASH_ADD_KEYPTR(hh, c->lookup, n->key, n->ksize, n); if (lifetime) { struct cache_node *rn; rn = RB_INSERT(expiry_tree, &(c->expiry_head), n); /* it's possible to get two timestamps that are the same, if this happens just bump us forwards by 1 usec until we're unique */ while (rn != NULL) { ++(n->expiry.tv_nsec); rn = RB_INSERT(expiry_tree, &(c->expiry_head), n); } } enif_rwlock_rwunlock(c->lookup_lock); enif_rwlock_rwunlock(c->cache_lock); enif_cond_broadcast(c->check_cond); enif_consume_timeslice(env, 50); return enif_make_atom(env, "ok"); }
ERL_NIF_TERM x_pool_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { const char * func_name = "x_pool_list()"; uint64_t id; if (!enif_get_uint64(env, argv[0], &id)) { logger.error(MOD_NAME, func_name, "enif get params failed"); return enif_make_badarg(env); } logger.debug(MOD_NAME, func_name, "cluster : %ld", id); rados_t cluster = map_cluster_get(id); if (cluster == NULL) { logger.error(MOD_NAME, func_name, "cluster non-existing : %ld", id); return enif_make_badarg(env); } // Call with a null buffer to get the buffer length first. int buf_len = rados_pool_list(cluster, NULL, 0); if (buf_len < 0) { return make_error_tuple(env, -buf_len); } if (buf_len > 0) { char * buf = (char *)malloc(buf_len + 10); if (buf == NULL) { logger.error(MOD_NAME, func_name, "unable to malloc: %ld", id); return make_error_tuple(env, ENOMEM); } int buf_len2 = rados_pool_list(cluster, buf, buf_len + 10); if (buf_len2 < 0) { logger.error(MOD_NAME, func_name, "failed to get pool list for %ld: %s", id, strerror(-buf_len2)); return make_error_tuple(env, -buf_len2); } list<int> pool_list; scan_pool_name_list(&pool_list, buf, buf_len); list<int>::const_iterator it; ERL_NIF_TERM term_list = enif_make_list(env, 0); for (it = pool_list.begin(); it != pool_list.end(); it++) { int off = *it; ERL_NIF_TERM head = enif_make_string(env, buf + off, ERL_NIF_LATIN1); term_list = enif_make_list_cell(env, head, term_list); } free(buf); return enif_make_tuple2(env, enif_make_atom(env, "ok"), term_list); } else { return enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_list(env, 0)); // empty list } }