bool as_namespace_configure_sets(as_namespace *ns) { for (uint32_t i = 0; i < ns->sets_cfg_count; i++) { uint32_t idx; cf_vmapx_err result = cf_vmapx_put_unique(ns->p_sets_vmap, &ns->sets_cfg_array[i], &idx); if (result == CF_VMAPX_ERR_NAME_EXISTS) { as_set* p_set = NULL; if ((result = cf_vmapx_get_by_index(ns->p_sets_vmap, idx, (void**)&p_set)) != CF_VMAPX_OK) { // Should be impossible - just verified idx. cf_warning(AS_NAMESPACE, "unexpected error %d", result); return false; } // Rewrite configurable metadata - config values may have changed. p_set->stop_writes_count = ns->sets_cfg_array[i].stop_writes_count; p_set->disable_eviction = ns->sets_cfg_array[i].disable_eviction; p_set->enable_xdr = ns->sets_cfg_array[i].enable_xdr; } else if (result != CF_VMAPX_OK) { // Maybe exceeded max sets allowed, but try failing gracefully. cf_warning(AS_NAMESPACE, "vmap error %d", result); return false; } } return true; }
as_set *as_namespace_init_set(as_namespace *ns, const char *set_name) { if (! set_name) { return NULL; } uint32_t idx; cf_vmapx_err result = cf_vmapx_get_index(ns->p_sets_vmap, set_name, &idx); if (result == CF_VMAPX_ERR_NAME_NOT_FOUND) { as_set set; memset(&set, 0, sizeof(set)); // Check name length just once, here at insertion. (Other vmap calls are // safe if name is too long - they return CF_VMAPX_ERR_NAME_NOT_FOUND.) strncpy(set.name, set_name, AS_SET_NAME_MAX_SIZE); if (set.name[AS_SET_NAME_MAX_SIZE - 1]) { set.name[AS_SET_NAME_MAX_SIZE - 1] = 0; cf_info(AS_NAMESPACE, "set name %s... too long", set.name); return NULL; } result = cf_vmapx_put_unique(ns->p_sets_vmap, &set, &idx); // Since this function can be called via info, need to handle race with // as_namespace_get_create_set() that returns CF_VMAPX_ERR_NAME_EXISTS. if (result != CF_VMAPX_OK && result != CF_VMAPX_ERR_NAME_EXISTS) { cf_warning(AS_NAMESPACE, "unexpected error %d", result); return NULL; } } else if (result != CF_VMAPX_OK) { // Should be impossible. cf_warning(AS_NAMESPACE, "unexpected error %d", result); return NULL; } as_set *p_set = NULL; if ((result = cf_vmapx_get_by_index(ns->p_sets_vmap, idx, (void**)&p_set)) != CF_VMAPX_OK) { // Should be impossible - just verified idx. cf_warning(AS_NAMESPACE, "unexpected error %d", result); return NULL; } return p_set; }
const char *as_namespace_get_set_name(as_namespace *ns, uint16_t set_id) { // Note that set_id is 1-based, but cf_vmap index is 0-based. // (This is because 0 in the index structure means 'no set'.) if (set_id == INVALID_SET_ID) { return NULL; } as_set *p_set; return cf_vmapx_get_by_index(ns->p_sets_vmap, set_id - 1, (void**)&p_set) == CF_VMAPX_OK ? p_set->name : NULL; }
void as_namespace_release_set_id(as_namespace *ns, uint16_t set_id) { if (set_id == INVALID_SET_ID) { return; } as_set *p_set; if (cf_vmapx_get_by_index(ns->p_sets_vmap, set_id - 1, (void**)&p_set) != CF_VMAPX_OK) { return; } if (cf_atomic64_decr(&p_set->num_elements) < 0) { cf_warning(AS_NAMESPACE, "set_id %u - num_elements went negative!", set_id); } }
const char * as_bin_get_name_from_id(as_namespace *ns, uint16_t id) { if (ns->single_bin) { cf_crash(AS_BIN, "single-bin call of as_bin_get_name_from_id()"); } const char* name = NULL; if (cf_vmapx_get_by_index(ns->p_bin_name_vmap, id, (void**)&name) != CF_VMAPX_OK) { // TODO - Fail softly by returning forbidden bin name? (Empty string?) cf_crash(AS_BIN, "no bin name for id %u", id); } return name; }
void as_namespace_adjust_set_memory(as_namespace *ns, uint16_t set_id, int64_t delta_bytes) { if (set_id == INVALID_SET_ID) { return; } as_set *p_set; if (cf_vmapx_get_by_index(ns->p_sets_vmap, set_id - 1, (void**)&p_set) != CF_VMAPX_OK) { cf_warning(AS_NAMESPACE, "set_id %u - failed to get as_set from vmap", set_id); return; } if (cf_atomic64_add(&p_set->n_bytes_memory, delta_bytes) < 0) { cf_warning(AS_NAMESPACE, "set_id %u - n_bytes_memory went negative!", set_id); } }
void as_namespace_get_set_info(as_namespace *ns, const char *set_name, cf_dyn_buf *db) { as_set *p_set; if (set_name) { if (cf_vmapx_get_by_name(ns->p_sets_vmap, set_name, (void**)&p_set) == CF_VMAPX_OK) { append_set_props(p_set, db); } return; } for (uint32_t idx = 0; idx < cf_vmapx_count(ns->p_sets_vmap); idx++) { if (cf_vmapx_get_by_index(ns->p_sets_vmap, idx, (void**)&p_set) == CF_VMAPX_OK) { cf_dyn_buf_append_string(db, "ns_name="); cf_dyn_buf_append_string(db, ns->name); cf_dyn_buf_append_char(db, ':'); cf_dyn_buf_append_string(db, "set_name="); cf_dyn_buf_append_string(db, p_set->name); cf_dyn_buf_append_char(db, ':'); append_set_props(p_set, db); } } }
int as_namespace_get_create_set(as_namespace *ns, const char *set_name, uint16_t *p_set_id, bool apply_restrictions) { if (! set_name) { // Should be impossible. cf_warning(AS_NAMESPACE, "null set name"); return -1; } uint32_t idx; cf_vmapx_err result = cf_vmapx_get_index(ns->p_sets_vmap, set_name, &idx); bool already_in_vmap = false; if (result == CF_VMAPX_OK) { already_in_vmap = true; } else if (result == CF_VMAPX_ERR_NAME_NOT_FOUND) { as_set set; memset(&set, 0, sizeof(set)); // Check name length just once, here at insertion. (Other vmap calls are // safe if name is too long - they return CF_VMAPX_ERR_NAME_NOT_FOUND.) strncpy(set.name, set_name, AS_SET_NAME_MAX_SIZE); if (set.name[AS_SET_NAME_MAX_SIZE - 1]) { set.name[AS_SET_NAME_MAX_SIZE - 1] = 0; cf_info(AS_NAMESPACE, "set name %s... too long", set.name); return -1; } set.num_elements = 1; result = cf_vmapx_put_unique(ns->p_sets_vmap, &set, &idx); if (result == CF_VMAPX_ERR_NAME_EXISTS) { already_in_vmap = true; } else if (result == CF_VMAPX_ERR_FULL) { cf_info(AS_NAMESPACE, "at set names limit, can't add %s", set.name); return -1; } else if (result != CF_VMAPX_OK) { // Currently, remaining errors are all some form of out-of-memory. cf_info(AS_NAMESPACE, "error %d, can't add %s", result, set.name); return -1; } } else { // Should be impossible. cf_warning(AS_NAMESPACE, "unexpected error %d", result); return -1; } if (already_in_vmap) { as_set *p_set; if ((result = cf_vmapx_get_by_index(ns->p_sets_vmap, idx, (void**)&p_set)) != CF_VMAPX_OK) { // Should be impossible - just verified idx. cf_warning(AS_NAMESPACE, "unexpected error %d", result); return -1; } // If requested, fail if emptying set or stop-writes limit is breached. if (apply_restrictions && (IS_SET_DELETED(p_set) || as_set_stop_writes(p_set))) { return -2; } // The set passed all tests - need to increment its num_elements. cf_atomic64_incr(&p_set->num_elements); } *p_set_id = (uint16_t)(idx + 1); return 0; }