Esempio n. 1
0
/**
 *	Set specified bin's value to an as_map.
 *	as_stringmap map;
 *	as_stringmap_init(&map);
 *	as_stringmap_set_int64(&map, "a", 1);
 *	as_stringmap_set_int64(&map, "b", 2);
 *	as_stringmap_set_int64(&map, "c", 3);
 *	as_record_set_map(rec, "bin", &map);
 *	@param rec 	- the record containing the bin
 *	@param name 	- the name of the bin
 *	@param value - the value of the bin
 *	@return true on success, false on failure.
 */
bool as_record_set_map(as_record * rec, const as_bin_name name, as_map * value) 
{
	as_bin * bin = as_record_bin_forupdate(rec, name);
	if ( !bin ) return false;
	as_bin_init(bin, name, (as_bin_value *) value);
	return true;
}
Esempio n. 2
0
// Does not check bin name length.
as_bin *
as_bin_create(as_storage_rd *rd, const char *name)
{
	if (rd->ns->single_bin) {
		if (as_bin_inuse(rd->bins)) {
			cf_crash(AS_BIN, "single bin create found bin in use");
		}

		as_bin_init_nameless(rd->bins);

		return rd->bins;
	}

	as_bin *b = NULL;

	for (uint16_t i = 0; i < rd->n_bins; i++) {
		if (! as_bin_inuse(&rd->bins[i])) {
			b = &rd->bins[i];
			break;
		}
	}

	if (b) {
		as_bin_init(rd->ns, b, name);
	}

	return b;
}
/**
 *	Add a AS_OPERATOR_WRITE bin operation.
 *
 *	@param ops			The `as_operations` to append the operation to.
 *	@param name 		The name of the bin to perform the operation on.
 *	@param value 		The value to be used in the operation.
 *
 *	@return true on success. Otherwise an error occurred.
 */
bool as_operations_add_write(as_operations * ops, const as_bin_name name, as_bin_value * value)
{
	as_binop * binop = as_binop_forappend(ops, AS_OPERATOR_WRITE, name);
	if ( !binop ) return false;
	as_bin_init(&binop->bin, name, value);
	return true;
}
static bool as_operations_add_cdt_read(as_operations *ops, const as_bin_name name, as_bin_value *value)
{
	as_binop *binop = as_binop_forappend(ops, AS_OPERATOR_CDT_READ, name);
	if (! binop) {
		return false;
	}
	as_bin_init(&binop->bin, name, value);
	return true;
}
Esempio n. 5
0
// Does not check bin name length.
// Checks bin name quota - use appropriately.
as_bin *
as_bin_get_or_create(as_storage_rd *rd, const char *name)
{
	if (rd->ns->single_bin) {
		if (! as_bin_inuse_has(rd)) {
			as_bin_init_nameless(rd->bins);
		}

		return rd->bins;
	}

	uint32_t id = (uint32_t)-1;
	uint16_t i;
	as_bin *b;

	if (cf_vmapx_get_index(rd->ns->p_bin_name_vmap, name, &id) == CF_VMAPX_OK) {
		for (i = 0; i < rd->n_bins; i++) {
			b = &rd->bins[i];

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

			if ((uint32_t)b->id == id) {
				return b;
			}
		}
	}
	else {
		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, name);
			return NULL;
		}

		i = as_bin_inuse_count(rd);
	}

	if (i >= rd->n_bins) {
		cf_crash(AS_BIN, "ran out of allocated bins in rd");
	}

	b = &rd->bins[i];

	if (id == (uint32_t)-1) {
		as_bin_init(rd->ns, b, name);
	}
	else {
		as_bin_init_nameless(b);
		b->id = (uint16_t)id;
	}

	return b;
}
Esempio n. 6
0
/* Internal Function: Packs up passed in data into as_bin which is
 *                    used to send result after the UDF execution.
 */
static bool
make_send_bin(as_namespace *ns, as_bin *bin, uint8_t **sp_pp, uint sp_sz,
			  const char *key, size_t klen, int  vtype,  void *val, size_t vlen)
{
	uint        sz          = 0;
	int         tsz         = sz + vlen + as_particle_get_base_size(vtype);
	uint8_t *   v           = NULL;
	int64_t     swapped_int = 0;
	uint8_t     *sp_p = *sp_pp;

	if (tsz > sp_sz) {
		sp_p = cf_malloc(tsz);
		if (!sp_p) {
			cf_warning(AS_UDF, "data too much. malloc failed. going down. bin %s not sent back", key);
			return(-1);
		}
	}

	as_bin_init(ns, bin, (byte *) key/*name*/, klen/*namelen*/, 0/*version*/);

	switch (vtype) {
		case AS_PARTICLE_TYPE_NULL:
		{
			v = NULL;
			break;
		}
		case AS_PARTICLE_TYPE_INTEGER:
		{
			if (vlen != 8) {
				cf_crash(AS_UDF, "unexpected int %d", vlen);
			}
			swapped_int = __be64_to_cpup(val);
			v = (uint8_t *) &swapped_int;
			break;
		}
		case AS_PARTICLE_TYPE_BLOB:
		case AS_PARTICLE_TYPE_STRING:
		case AS_PARTICLE_TYPE_LIST:
		case AS_PARTICLE_TYPE_MAP:
			v = val;
			break;
		default:
		{
			cf_warning(AS_UDF, "unrecognized object type %d ignored", vtype);
			return -1;
		}
	}

	as_particle_frombuf(bin, vtype, v, vlen, sp_p, ns->storage_data_in_memory);
	*sp_pp = sp_p;
	return 0;
}
Esempio n. 7
0
/* as_bin_create
 * Create a new bin with the specified name in a record
 * NB: You must be holding the value lock for the record! */
as_bin *
as_bin_create(as_record *r, as_storage_rd *rd, byte *name, size_t namesz, uint version)
{
	cf_detail(AS_BIN, "as_bin_create: %s %zu", name, namesz);

	// what policy should we make for too-large bins passed in?

	if (namesz > (AS_ID_BIN_SZ - 1)) {
		cf_warning(AS_RW, "WARNING: too large bin name %d passed in, internal error", namesz);
		return(NULL);
	}

	as_bin *b = 0;

	if (rd->ns->single_bin) {
		if (as_bin_inuse(rd->bins)) {
			cf_warning(AS_RW, "WARNING: cannot allocate more than 1 bin in a single bin namespace");
			return (NULL);
		}
		// do not store bin name
		byte c = 0;
		as_bin_init(rd->ns, rd->bins, &c, 0, version);
		return (rd->bins);
	}

	// seek for an empty one
	for (uint16_t i = 0; i < rd->n_bins; i++) {
		if (! as_bin_inuse(&rd->bins[i])) {
			b = &rd->bins[i];
			break;
		}
	}

	if (b) {
		as_bin_init(rd->ns, b, name, namesz, version);
	}

	return (b);
}
Esempio n. 8
0
/* Workhorse function to send response back to the client after UDF execution.
 *
 * Assumption: The call should be setup properly pointing to the tr.
 *
 * Special Handling: If it is background udf job do not send any
 * 					 response to client
 */
int
send_response(udf_call *call, const char *bin_name, const as_val *val)
{
	// NO response if background UDF
	if (call->def.type == AS_UDF_OP_BACKGROUND) {
		return 0;
	}
	// Note - this function quietly handles a null val. The response call will
	// be given a bin with a name but not 'in use', and it does the right thing.

	as_bin stack_bin;
	as_bin *bin = &stack_bin;

	uint32_t particle_size = as_particle_size_from_asval(val);

	static const size_t MAX_STACK_SIZE = 32 * 1024;
	uint8_t stack_particle[particle_size > MAX_STACK_SIZE ? 0 : particle_size];
	uint8_t *particle_buf = stack_particle;

	if (particle_size > MAX_STACK_SIZE) {
		particle_buf = (uint8_t *)cf_malloc(particle_size);

		if (! particle_buf) {
			cf_warning(AS_UDF, "failed alloc for particle size %u", particle_size);
			return -1;
		}
	}

	as_transaction *tr = call->tr;
	as_namespace *ns = tr->rsv.ns;

	as_bin_init(ns, bin, bin_name);
	as_bin_particle_stack_from_asval(bin, particle_buf, val);

	single_transaction_response(tr, ns, NULL, &bin, 1, tr->generation, tr->void_time, NULL, NULL);

	if (particle_buf != stack_particle) {
		cf_free(particle_buf);
	}

	return 0;
} // end send_response()
Esempio n. 9
0
/* Workhorse function to send response back to the client after UDF execution.
 *
 * Assumption: The call should be setup properly pointing to the tr.
 *
 * Special Handling: If it is background udf job do not send any
 * 					 response to client
 */
int
process_response(udf_call *call, const char *bin_name, const as_val *val, cf_dyn_buf *db)
{
	// NO response if background UDF
	if (call->def->type == AS_UDF_OP_BACKGROUND) {
		return 0;
	}
	// Note - this function quietly handles a null val. The response call will
	// be given a bin with a name but not 'in use', and it does the right thing.

	as_bin stack_bin;
	as_bin *bin = &stack_bin;

	uint32_t particle_size = as_particle_size_from_asval(val);

	static const size_t MAX_STACK_SIZE = 32 * 1024;
	uint8_t stack_particle[particle_size > MAX_STACK_SIZE ? 0 : particle_size];
	uint8_t *particle_buf = stack_particle;

	if (particle_size > MAX_STACK_SIZE) {
		particle_buf = (uint8_t *)cf_malloc(particle_size);

		if (! particle_buf) {
			cf_warning(AS_UDF, "failed alloc for particle size %u", particle_size);
			return -1;
		}
	}

	as_transaction *tr = call->tr;
	as_namespace *ns = tr->rsv.ns;

	as_bin_init(ns, bin, bin_name);
	as_bin_particle_stack_from_asval(bin, particle_buf, val);

	if (db) {
		size_t msg_sz = 0;
		uint8_t *msgp = (uint8_t *)as_msg_make_response_msg(tr->result_code,
				tr->generation, tr->void_time, NULL, &bin, 1, ns, NULL, &msg_sz,
				as_transaction_trid(tr), NULL);

		if (! msgp)	{
			cf_warning_digest(AS_RW, &tr->keyd, "{%s} UDF failed to make response msg ", ns->name);

			if (particle_buf != stack_particle) {
				cf_free(particle_buf);
			}

			return -1;
		}

		// Stash the message, to be sent later.
		db->buf = msgp;
		db->is_stack = false;
		db->alloc_sz = msg_sz;
		db->used_sz = msg_sz;
	}
	else {
		single_transaction_response(tr, ns, NULL, &bin, 1, tr->generation, tr->void_time, NULL, NULL);
	}

	if (particle_buf != stack_particle) {
		cf_free(particle_buf);
	}

	return 0;
}