uint32_t
map_asval_wire_size(const as_val *val)
{
	as_serializer s;
	as_msgpack_init(&s);

	uint32_t size = as_serializer_serialize_getsize(&s, (as_val *)val);

	as_serializer_destroy(&s);

	return size;
}
uint32_t
map_size_from_asval(const as_val *val)
{
	as_serializer s;
	as_msgpack_init(&s);

	uint32_t size = as_serializer_serialize_getsize(&s, (as_val *)val);

	as_serializer_destroy(&s);

	return (uint32_t)sizeof(map_mem) + size;
}
static int mod_lua_map_nbytes(lua_State * l) {
	as_map *    map     = mod_lua_checkmap(l, 1);
	uint32_t    nbytes  = 0;
	if ( map ) {
		as_serializer s;
		as_msgpack_init(&s);
		nbytes = as_serializer_serialize_getsize(&s, (as_val *) map);
		as_serializer_destroy(&s);
	}
	lua_pushinteger(l, nbytes);
	return 1;
}
Beispiel #4
0
int as_msg_make_response_bufbuilder(as_record *r, as_storage_rd *rd,
		cf_buf_builder **bb_r, bool nobindata, char *nsname, bool use_sets,
		bool include_key, bool skip_empty_records, cf_vector *binlist)
{
	// Sanity checks. Either rd should be there or nobindata and nsname should be present.
	if (!(rd || (nobindata && nsname))) {
		cf_detail(AS_PROTO, "Neither storage record nor nobindata is set. Skipping the record.");
		return 0;
	}

	// figure out the size of the entire buffer
	int         set_name_len = 0;
	const char *set_name     = NULL;
	int         ns_len       = rd ? strlen(rd->ns->name) : strlen(nsname);

	if (use_sets && as_index_get_set_id(r) != INVALID_SET_ID) {
		as_namespace *ns = NULL;

		if (rd) {
			ns = rd->ns;
		} else if (nsname) {
			ns = as_namespace_get_byname(nsname);
		}
		if (!ns) {
			cf_info(AS_PROTO, "Cannot get namespace, needed to get set information. Skipping record.");
			return -1;
		}
		set_name = as_index_get_set_name(r, ns);
		if (set_name) {
			set_name_len = strlen(set_name);
		}
	}

	uint8_t* key = NULL;
	uint32_t key_size = 0;

	if (include_key && as_index_is_flag_set(r, AS_INDEX_FLAG_KEY_STORED)) {
		if (! as_storage_record_get_key(rd)) {
			cf_info(AS_PROTO, "can't get key - skipping record");
			return -1;
		}

		key = rd->key;
		key_size = rd->key_size;
	}

	uint16_t n_fields = 2;
	int msg_sz = sizeof(as_msg);
	msg_sz += sizeof(as_msg_field) + sizeof(cf_digest);
	msg_sz += sizeof(as_msg_field) + ns_len;
	if (set_name) {
		n_fields++;
		msg_sz += sizeof(as_msg_field) + set_name_len;
	}
	if (key) {
		n_fields++;
		msg_sz += sizeof(as_msg_field) + key_size;
	}

	int list_bins   = 0;
	int num_bins = 0;
	if (rd) {
		num_bins = as_bin_inuse_count(rd);
	}
	if (binlist) {
		num_bins = cf_vector_size(binlist);
	}
	
	as_val *ldtBinVal[num_bins];
	as_particle_type ldtBinParticleType[num_bins];

	if (nobindata == false) {
		if (binlist) {
			for(uint16_t i = 0; i < num_bins; i++) {
				char binname[AS_ID_BIN_SZ];
				cf_vector_get(binlist, i, (void*)&binname);
				cf_debug(AS_PROTO, " Binname projected inside is |%s| \n", binname);
				as_bin *p_bin = as_bin_get (rd, (uint8_t*)binname, strlen(binname));
				if (!p_bin)
				{
					cf_debug(AS_PROTO, "To be projected bin |%s| not found \n", binname);
					continue;
				}
				cf_debug(AS_PROTO, "Adding bin |%s| to projected bins |%s| \n", binname);
				msg_sz += sizeof(as_msg_op);
				msg_sz += rd->ns->single_bin ? 0 : strlen(binname);
				uint32_t psz;
				if (as_bin_is_hidden(p_bin)) {
					ldtBinVal[list_bins] = as_llist_scan(rd->ns, rd->ns->partitions[as_partition_getid(rd->keyd)].sub_vp, rd, p_bin);
					if (ldtBinVal[list_bins]) {
						ldtBinParticleType[list_bins] = AS_PARTICLE_TYPE_HIDDEN_LIST;
					}
					as_serializer s;
					as_msgpack_init(&s);
					psz = as_serializer_serialize_getsize(&s, (as_val *)ldtBinVal[list_bins]);
					as_serializer_destroy(&s);
				} else {
					as_particle_tobuf(p_bin, 0, &psz); // get size
				}
				list_bins++;
				msg_sz += psz;
			}

			// Don't return an empty record.
			if (skip_empty_records && list_bins == 0) {
				return 0;
			}
		}
		else {
			msg_sz += sizeof(as_msg_op) * num_bins; // the bin headers
			for (uint16_t i = 0; i < num_bins; i++) {
				as_bin *p_bin = &rd->bins[i];
				msg_sz += rd->ns->single_bin ? 0 : strlen(as_bin_get_name_from_id(rd->ns, p_bin->id));
				uint32_t psz;
				if (as_bin_is_hidden(p_bin)) {
					ldtBinVal[list_bins] = as_llist_scan(rd->ns, rd->ns->partitions[as_partition_getid(rd->keyd)].sub_vp, rd, p_bin);
					if (ldtBinVal[list_bins]) {
						ldtBinParticleType[list_bins] = AS_PARTICLE_TYPE_HIDDEN_LIST;
					}
					as_serializer s;
					as_msgpack_init(&s);
					psz = as_serializer_serialize_getsize(&s, (as_val *)ldtBinVal[list_bins]);
					as_serializer_destroy(&s);
				} else {
					as_particle_tobuf(p_bin, 0, &psz); // get size
				}
				msg_sz += psz;
				list_bins++;
			}
		}
	}

	uint8_t *b;
	cf_buf_builder_reserve(bb_r, msg_sz, &b);

	// set up the header
	uint8_t *buf = b;
	as_msg *msgp = (as_msg *) buf;

	msgp->header_sz = sizeof(as_msg);
	msgp->info1 = (nobindata ? AS_MSG_INFO1_GET_NOBINDATA : 0);
	msgp->info2 = 0;
	msgp->info3 = 0;
	msgp->unused = 0;
	msgp->result_code = 0;
	msgp->generation = r->generation;
	msgp->record_ttl = r->void_time;
	msgp->transaction_ttl = 0;
	msgp->n_fields = n_fields;
	if (rd) {
		if (binlist)
			msgp->n_ops = list_bins;
		else
			msgp->n_ops = num_bins;
	} else {
		msgp->n_ops = 0;
	}
	as_msg_swap_header(msgp);

	buf += sizeof(as_msg);

	as_msg_field *mf = (as_msg_field *) buf;
	mf->field_sz = sizeof(cf_digest) + 1;
	mf->type = AS_MSG_FIELD_TYPE_DIGEST_RIPE;
	if (rd) {
		memcpy(mf->data, &rd->keyd, sizeof(cf_digest));
	} else {
		memcpy(mf->data, &r->key, sizeof(cf_digest));
	}
	as_msg_swap_field(mf);
	buf += sizeof(as_msg_field) + sizeof(cf_digest);

	mf = (as_msg_field *) buf;
	mf->field_sz = ns_len + 1;
	mf->type = AS_MSG_FIELD_TYPE_NAMESPACE;
	if (rd) {
		memcpy(mf->data, rd->ns->name, ns_len);
	} else {
		memcpy(mf->data, nsname, ns_len);
	}
	as_msg_swap_field(mf);
	buf += sizeof(as_msg_field) + ns_len;

	if (set_name) {
		mf = (as_msg_field *) buf;
		mf->field_sz = set_name_len + 1;
		mf->type = AS_MSG_FIELD_TYPE_SET;
		memcpy(mf->data, set_name, set_name_len);
		as_msg_swap_field(mf);
		buf += sizeof(as_msg_field) + set_name_len;
	}

	if (key) {
		mf = (as_msg_field *) buf;
		mf->field_sz = key_size + 1;
		mf->type = AS_MSG_FIELD_TYPE_KEY;
		memcpy(mf->data, key, key_size);
		as_msg_swap_field(mf);
		buf += sizeof(as_msg_field) + key_size;
	}

	if (nobindata) {
		goto Out;
	}
	list_bins = 0;

	if (binlist) {
		for (uint16_t i = 0; i < num_bins; i++) {

			char binname[AS_ID_BIN_SZ];
			cf_vector_get(binlist, i, (void*)&binname);
			cf_debug(AS_PROTO, " Binname projected inside is |%s| \n", binname);
			as_bin *p_bin = as_bin_get (rd, (uint8_t*)binname, strlen(binname));
			if (!p_bin) // should it be checked before ???
				continue;

			as_msg_op *op = (as_msg_op *)buf;
			buf += sizeof(as_msg_op);

			op->op = AS_MSG_OP_READ;

			op->name_sz = as_bin_memcpy_name(rd->ns, op->name, p_bin);
			buf += op->name_sz;

			// Since there are two variable bits, the size is everything after
			// the data bytes - and this is only the head, we're patching up
			// the rest in a minute.
			op->op_sz = 4 + op->name_sz;

			if (as_bin_inuse(p_bin)) {
				op->particle_type = as_particle_type_convert(as_bin_get_particle_type(p_bin));
				op->version = as_bin_get_version(p_bin, rd->ns->single_bin);

				uint32_t psz = msg_sz - (buf - b); // size remaining in buffer, for safety
				if (as_bin_is_hidden(p_bin)) {
					if (!ldtBinVal[list_bins]) {
						op->particle_type = AS_PARTICLE_TYPE_NULL;
						psz = 0;
					} else {
						op->particle_type = ldtBinParticleType[list_bins];
						as_buffer abuf;
						as_buffer_init(&abuf);
						as_serializer s;
						as_msgpack_init(&s);
						as_serializer_serialize(&s, (as_val *)ldtBinVal[list_bins], &abuf);
						psz = abuf.size;
						memcpy(buf, abuf.data, abuf.size);
						as_serializer_destroy(&s);
						as_buffer_destroy(&abuf);
						as_val_destroy(ldtBinVal[list_bins]);
					}
				} else {
					if (0 != as_particle_tobuf(p_bin, buf, &psz)) {
						cf_warning(AS_PROTO, "particle to buf: could not copy data!");
					}
				}
				list_bins++;
				buf += psz;
				op->op_sz += psz;
			}
			else {
				cf_debug(AS_PROTO, "Whoops !! bin not in use");
				op->particle_type = AS_PARTICLE_TYPE_NULL;
			}
			as_msg_swap_op(op);
		}
	}
	else {
		// over all bins, copy into the buffer
		for (uint16_t i = 0; i < num_bins; i++) {

			as_msg_op *op = (as_msg_op *)buf;
			buf += sizeof(as_msg_op);

			op->op = AS_MSG_OP_READ;

			op->name_sz = as_bin_memcpy_name(rd->ns, op->name, &rd->bins[i]);
			buf += op->name_sz;

			// Since there are two variable bits, the size is everything after
			// the data bytes - and this is only the head, we're patching up
			// the rest in a minute.
			op->op_sz = 4 + op->name_sz;

			if (as_bin_inuse(&rd->bins[i])) {
				op->particle_type = as_particle_type_convert(as_bin_get_particle_type(&rd->bins[i]));
				op->version = as_bin_get_version(&rd->bins[i], rd->ns->single_bin);

				uint32_t psz = msg_sz - (buf - b); // size remaining in buffer, for safety
				if (as_bin_is_hidden(&rd->bins[i])) {
					if (!ldtBinVal[list_bins]) {
						op->particle_type = AS_PARTICLE_TYPE_NULL;
						psz = 0;
					} else {
						op->particle_type = ldtBinParticleType[list_bins];
						as_buffer abuf;
						as_buffer_init(&abuf);
						as_serializer s;
						as_msgpack_init(&s);
						as_serializer_serialize(&s, (as_val *)ldtBinVal[list_bins], &abuf);
						psz = abuf.size;
						memcpy(buf, abuf.data, abuf.size);
						as_serializer_destroy(&s);
						as_buffer_destroy(&abuf);
						as_val_destroy(ldtBinVal[list_bins]);
					}
				} else {
					if (0 != as_particle_tobuf(&rd->bins[i], buf, &psz)) {
						cf_warning(AS_PROTO, "particle to buf: could not copy data!");
					}
				}
				list_bins++;
				buf += psz;
				op->op_sz += psz;
			}
			else {
				op->particle_type = AS_PARTICLE_TYPE_NULL;
			}
			as_msg_swap_op(op);
		}
	}
Out:
	return(0);
}
/**
 * Call with AS_OPERATIONS_CDT_OP only.
 */
static bool as_operations_cdt_op(as_operations *ops, const as_bin_name name, as_cdt_optype op, size_t n, ...)
{
	if (op >= cdt_op_table_size) {
		return false;
	}

	const cdt_op_table_entry *entry = &cdt_op_table[op];
	if (n < entry->count - entry->opt_args || n > entry->count) {
		return false;
	}

	va_list vl;
	if (n > 0) {
		va_start(vl, n);
	}

	as_arraylist list;
	as_arraylist_inita(&list, (uint32_t)n + 1); // +1 to avoid alloca(0) undefined behavior

	for (size_t i = 0; i < n; i++) {
		as_cdt_paramtype type = entry->args[i];
		switch (type) {
		case AS_CDT_PARAM_PAYLOAD: {
			as_val *arg = va_arg(vl, as_val *);

			if (as_arraylist_append(&list, arg) != AS_ARRAYLIST_OK) {
				va_end(vl);
				as_arraylist_destroy(&list);
				return false;
			}
			break;
		}
		case AS_CDT_PARAM_COUNT: {
			uint64_t arg = va_arg(vl, uint64_t);

			if (as_arraylist_append(&list, (as_val *)as_integer_new(arg)) != AS_ARRAYLIST_OK) {
				va_end(vl);
				as_arraylist_destroy(&list);
				return false;
			}
			break;
		}
		case AS_CDT_PARAM_INDEX: {
			int64_t arg = va_arg(vl, int64_t);

			if (as_arraylist_append(&list, (as_val *)as_integer_new(arg)) != AS_ARRAYLIST_OK) {
				va_end(vl);
				as_arraylist_destroy(&list);
				return false;
			}
			break;
		}
		default:
			break;
		}
	}

	if (n > 0) {
		va_end(vl);
	}

	as_serializer ser;
	as_msgpack_init(&ser);

	uint32_t list_size = as_serializer_serialize_getsize(&ser, (as_val *) &list);
	as_bytes *bytes = as_bytes_new(sizeof(uint16_t) + list_size);
	uint8_t *list_write = as_bytes_get(bytes);
	uint16_t *list_write_op = (uint16_t *)list_write;

	*list_write_op = cf_swap_to_be16(op);
	list_write += sizeof(uint16_t);

	as_serializer_serialize_presized(&ser, (const as_val *) &list, list_write);
	as_serializer_destroy(&ser);
	as_arraylist_destroy(&list);
	bytes->size = bytes->capacity;
	// as_bytes->type default to AS_BYTES_BLOB

	if (entry->rw_type == CDT_RW_TYPE_MODIFY) {
		return as_operations_add_cdt_modify(ops, name, (as_bin_value *) bytes);
	}

	return as_operations_add_cdt_read(ops, name, (as_bin_value *) bytes);
}