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;
}
Beispiel #2
0
uint16_t
as_bin_get_or_assign_id(as_namespace *ns, const char *name)
{
	if (ns->single_bin) {
		cf_crash(AS_BIN, "single-bin call of as_bin_get_or_assign_id()");
	}

	uint32_t idx;

	if (cf_vmapx_get_index(ns->p_bin_name_vmap, name, &idx) == CF_VMAPX_OK) {
		return (uint16_t)idx;
	}

	// Verify length just once here at insertion.
	if (strlen(name) >= BIN_NAME_MAX_SZ) {
		cf_crash(AS_BIN, "bin name %s too long", name);
	}

	cf_vmapx_err result = cf_vmapx_put_unique(ns->p_bin_name_vmap, name, &idx);

	if (! (result == CF_VMAPX_OK || result == CF_VMAPX_ERR_NAME_EXISTS)) {
		// Tedious to handle safely for all usage paths, so for now...
		cf_crash(AS_BIN, "could not add bin name %s, vmap err %d", name, result);
	}

	return (uint16_t)idx;
}
// At the moment this is only used by the enterprise build security feature.
uint16_t as_namespace_get_create_set_id(as_namespace *ns, const char *set_name)
{
	if (! set_name) {
		// Should be impossible.
		cf_warning(AS_NAMESPACE, "null set name");
		return INVALID_SET_ID;
	}

	uint32_t idx;
	cf_vmapx_err result = cf_vmapx_get_index(ns->p_sets_vmap, set_name, &idx);

	if (result == CF_VMAPX_OK) {
		return (uint16_t)(idx + 1);
	}

	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_warning(AS_NAMESPACE, "set name %s... too long", set.name);
			return INVALID_SET_ID;
		}

		set.num_elements = 0; // *not* adding an element
		result = cf_vmapx_put_unique(ns->p_sets_vmap, &set, &idx);

		if (result == CF_VMAPX_ERR_NAME_EXISTS) {
			return (uint16_t)(idx + 1);
		}

		if (result == CF_VMAPX_ERR_FULL) {
			cf_warning(AS_NAMESPACE, "at set names limit, can't add %s", set.name);
			return INVALID_SET_ID;
		}

		if (result != CF_VMAPX_OK) {
			// Currently, remaining errors are all some form of out-of-memory.
			cf_warning(AS_NAMESPACE, "error %d, can't add %s", result, set.name);
			return INVALID_SET_ID;
		}

		return (uint16_t)(idx + 1);
	}

	// Should be impossible.
	cf_warning(AS_NAMESPACE, "unexpected error %d", result);
	return INVALID_SET_ID;
}
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;
}
Beispiel #5
0
as_bin *
as_bin_get_and_reserve_name(as_storage_rd *rd, byte *name, size_t namesz,
		bool *p_reserved, uint32_t *p_idx)
{
	*p_reserved = true;

	if (rd->ns->single_bin) {
		return as_bin_inuse_has(rd) ? rd->bins : NULL;
	}

	char zname[namesz + 1];

	memcpy(zname, name, namesz);
	zname[namesz] = 0;

	if (cf_vmapx_get_index(rd->ns->p_bin_name_vmap, zname, p_idx) != CF_VMAPX_OK) {
		if (cf_vmapx_count(rd->ns->p_bin_name_vmap) >= BIN_NAMES_QUOTA) {
			cf_warning(AS_BIN, "{%s} bin-name quota full - can't add new bin-name %s", rd->ns->name, zname);
			*p_reserved = false;
		}
		else {
			cf_vmapx_err result = cf_vmapx_put_unique(rd->ns->p_bin_name_vmap, zname, p_idx);

			if (! (result == CF_VMAPX_OK || result == CF_VMAPX_ERR_NAME_EXISTS)) {
				cf_warning(AS_BIN, "{%s} can't add new bin name %s, vmap err %d", rd->ns->name, zname, result);
				*p_reserved = false;
			}
		}

		return NULL;
	}

	for (uint16_t i = 0; i < rd->n_bins; i++) {
		as_bin *b = &rd->bins[i];

		if (! as_bin_inuse(b)) {
			break;
		}

		if ((uint32_t)b->id == *p_idx) {
			return b;
		}
	}

	return NULL;
}
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;
}