コード例 #1
0
ファイル: proto.c プロジェクト: Benguang/aerospike-server
int
as_msg_make_val_response_bufbuilder(const as_val *val, cf_buf_builder **bb_r, int val_sz, bool success)
{
	int msg_sz        = sizeof(as_msg);
	msg_sz           += sizeof(as_msg_op) + val_sz;
	if (success) {
		msg_sz       += strlen("SUCCESS");  // fake bin name
	} else {
		msg_sz       += strlen("FAILURE");  // fake bin name
	}
	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       = 0;
	msgp->info2       = 0;
	msgp->info3       = 0;
	msgp->unused      = 0;
	msgp->result_code = 0; // Default is OK
	msgp->generation  = 0;
	msgp->record_ttl  = 0;
	msgp->transaction_ttl = 0;
	msgp->n_fields    = 0; // No Fields corresponding to aggregation response
	msgp->n_ops       = 1; // only 1 bin
	as_msg_swap_header(msgp);

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

	op->op            = AS_MSG_OP_READ;
	if (success) {
		op->name_sz       = strlen("SUCCESS");
		memcpy(op->name, "SUCCESS", op->name_sz);
	} else {
		op->name_sz       = strlen("FAILURE");
		memcpy(op->name, "FAILURE", op->name_sz);
	}
	op->op_sz         = 4 + op->name_sz;
	op->particle_type = to_particle_type(as_val_type(val));
	op->version       = 0;
	buf              += op->name_sz;

	uint32_t psz      = msg_sz - (buf - b); // size remaining in buffer, for safety
	as_val_tobuf(val, buf, &psz);
	if (psz == 0) {
		cf_warning(AS_PROTO, "particle to buf: could not copy data!");
	}
	buf              += psz;
	op->op_sz        += psz;
	as_msg_swap_op(op);
	return(0);
}
コード例 #2
0
ファイル: proto.c プロジェクト: Benguang/aerospike-server
int
as_msg_make_error_response_bufbuilder(cf_digest *keyd, int result_code, cf_buf_builder **bb_r, char *nsname)
{
	// figure out the size of the entire buffer
	int ns_len = strlen(nsname);
	int msg_sz = sizeof(as_msg);
	msg_sz += sizeof(as_msg_field) + sizeof(cf_digest);
	msg_sz += sizeof(as_msg_field) + ns_len;

	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 = 0;
	msgp->info2 = 0;
	msgp->info3 = 0;
	msgp->unused = 0;
	msgp->result_code = result_code;
	msgp->generation = 0;
	msgp->record_ttl = 0;
	msgp->transaction_ttl = 0;
	msgp->n_fields = 2;
	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;
	memcpy(mf->data, keyd, 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;
	memcpy(mf->data, nsname, ns_len);
	as_msg_swap_field(mf);
	buf += sizeof(as_msg_field) + ns_len;

	return(0);
}
コード例 #3
0
ファイル: proto.c プロジェクト: Steve888888/aerospike-server
int
as_msg_make_val_response_bufbuilder(const as_val *val, cf_buf_builder **bb_r, int val_sz, bool success)
{
	int msg_sz        = sizeof(as_msg);
	msg_sz           += sizeof(as_msg_op) + val_sz;
	if (success) {
		msg_sz       += SUCCESS_BIN_NAME_LEN;  // fake bin name
	} else {
		msg_sz       += FAILURE_BIN_NAME_LEN;  // fake bin name
	}
	uint8_t *b;
	cf_buf_builder_reserve(bb_r, msg_sz, &b);

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

	msgp->header_sz   = sizeof(as_msg);
	msgp->info1       = 0;
	msgp->info2       = 0;
	msgp->info3       = 0;
	msgp->unused      = 0;
	msgp->result_code = 0; // Default is OK
	msgp->generation  = 0;
	msgp->record_ttl  = 0;
	msgp->transaction_ttl = 0;
	msgp->n_fields    = 0; // No Fields corresponding to aggregation response
	msgp->n_ops       = 1; // only 1 bin
	as_msg_swap_header(msgp);

	as_msg_op *op     = (as_msg_op *)(b + sizeof(as_msg));

	op->op            = AS_MSG_OP_READ;
	if (success) {
		op->name_sz = SUCCESS_BIN_NAME_LEN;
		memcpy(op->name, SUCCESS_BIN_NAME, op->name_sz);
	} else {
		op->name_sz = FAILURE_BIN_NAME_LEN;
		memcpy(op->name, FAILURE_BIN_NAME, op->name_sz);
	}
	op->op_sz         = 4 + op->name_sz;
	op->version       = 0;

	as_particle_asval_to_client(val, op);

	as_msg_swap_op(op);
	return(0);
}
コード例 #4
0
ファイル: proto.c プロジェクト: Benguang/aerospike-server
int
as_msg_send_fin(int fd, uint32_t result_code)
{
	cl_msg m;
	m.proto.version = PROTO_VERSION;
	m.proto.type = PROTO_TYPE_AS_MSG;
	m.proto.sz = sizeof(as_msg);
	as_proto_swap(&m.proto);
	m.msg.header_sz = sizeof(as_msg);
	m.msg.info1 = 0;
	m.msg.info2 = 0;
	m.msg.info3 = AS_MSG_INFO3_LAST;
	m.msg.unused = 0;
	m.msg.result_code = result_code;
	m.msg.generation = 0;
	m.msg.record_ttl = 0;
	m.msg.transaction_ttl = 0;
	m.msg.n_fields = 0;
	m.msg.n_ops = 0;
	as_msg_swap_header(&m.msg);

	return as_msg_send_response(fd, (uint8_t*) &m, sizeof(m), MSG_NOSIGNAL);
}
コード例 #5
0
ファイル: proto.c プロジェクト: Benguang/aerospike-server
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, 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 in_use_bins = 0;
	if (rd) {
		in_use_bins = as_bin_inuse_count(rd);
	}

	if (nobindata == false) {
		if(binlist) {
			int binlist_sz = cf_vector_size(binlist);
			for(uint16_t i = 0; i < binlist_sz; 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);
				list_bins++;
				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)) {
					psz = 0;
				} else {
					as_particle_tobuf(p_bin, 0, &psz); // get size
				}
				msg_sz += psz;
			}
		}
		else {
			msg_sz += sizeof(as_msg_op) * in_use_bins; // the bin headers
			for (uint16_t i = 0; i < in_use_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)) {
					psz = 0;
				} else {
					as_particle_tobuf(p_bin, 0, &psz); // get size
				}
				msg_sz += psz;
			}
		}
	}

	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 = in_use_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;
	}

	if(binlist) {
		int binlist_sz = cf_vector_size(binlist);
		for(uint16_t i = 0; i < binlist_sz; 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)) {
                	op->particle_type = AS_PARTICLE_TYPE_NULL;
					psz = 0;
				} else {
					if (0 != as_particle_tobuf(p_bin, buf, &psz)) {
						cf_warning(AS_PROTO, "particle to buf: could not copy data!");
					}
				}
				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 < in_use_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])) {
                	op->particle_type = AS_PARTICLE_TYPE_NULL;
					psz = 0;
				} else {
					if (0 != as_particle_tobuf(&rd->bins[i], buf, &psz)) {
						cf_warning(AS_PROTO, "particle to buf: could not copy data!");
					}
				}
				buf += psz;
				op->op_sz += psz;
			}
			else {
				op->particle_type = AS_PARTICLE_TYPE_NULL;
			}
			as_msg_swap_op(op);
		}
	}
Out:
	return(0);
}
コード例 #6
0
ファイル: proto.c プロジェクト: Benguang/aerospike-server
cl_msg *
as_msg_make_response_msg( uint32_t result_code, uint32_t generation, uint32_t void_time,
		as_msg_op **ops, as_bin **bins, uint16_t bin_count, as_namespace *ns,
		cl_msg *msgp_in, size_t *msg_sz_in, uint64_t trid, const char *setname)
{
	int setname_len = 0;
	// figure out the size of the entire buffer
	int msg_sz = sizeof(cl_msg);
	msg_sz += sizeof(as_msg_op) * bin_count; // the bin headers
	for (uint16_t i = 0; i < bin_count; i++) {
		if (bins[i]) {
			msg_sz += ns->single_bin ? 0 :
					  strlen(as_bin_get_name_from_id(ns, bins[i]->id));
			uint32_t psz;
			if (as_bin_is_hidden(bins[i])) {
				psz = 0;
			} else {
				bool tojson = (as_bin_get_particle_type(bins[i]) ==
							   AS_PARTICLE_TYPE_LUA_BLOB);
				_as_particle_tobuf(bins[i], 0, &psz, tojson); // get size
			}
			msg_sz += psz;
		}
		else if (ops[i])  // no bin, only op, no particle size
			msg_sz += ops[i]->name_sz;
		else
			cf_warning(AS_PROTO, "internal error!");
	}

	//If a transaction-id is sent by the client, we should send it back in a field
	if (trid != 0) {
		msg_sz += (sizeof(as_msg_field) + sizeof(trid));
	}

	// If setname is present, we will send it as a field. Account for its space overhead.
	if (setname != 0) {
		setname_len = strlen(setname);
		msg_sz += (sizeof(as_msg_field) + setname_len);
	}

	// most cases are small messages - try to stack alloc if we can
	byte *b;
	if ((0 == msgp_in) || (*msg_sz_in < msg_sz)) {
		b = cf_malloc(msg_sz);
		if (!b)	return(0);
	}
	else {
		b = (byte *) msgp_in;
	}
	*msg_sz_in = msg_sz;

	// set up the header
	byte *buf = b; // current buffer pointer
	cl_msg *msgp = (cl_msg *) buf;
	msgp->proto.version = PROTO_VERSION;
	msgp->proto.type = PROTO_TYPE_AS_MSG;
	msgp->proto.sz = msg_sz - sizeof(as_proto);
	as_proto_swap(&msgp->proto);

	as_msg *m = &msgp->msg;
	m->header_sz = sizeof(as_msg);
	m->info1 = 0;
	m->info2 = 0;
	m->info3 = 0;
	m->unused = 0;
	m->result_code = result_code;
	m->generation = generation;
	m->record_ttl = void_time;
	m->transaction_ttl = 0;
	m->n_ops = bin_count;
	m->n_fields = 0;

	// Count the number of fields that we are going to send back
	if (trid != 0) {
		m->n_fields++;
	}
	if (setname != NULL) {
		m->n_fields++;
	}
	as_msg_swap_header(m);

	buf += sizeof(cl_msg);

	//If we have to send back the transaction-id, we have fields to send back
	if (trid != 0) {
		as_msg_field *trfield = (as_msg_field *) buf;
		//Allow space for the message field header
		buf += sizeof(as_msg_field);

		//Fill the field header
		trfield->type = AS_MSG_FIELD_TYPE_TRID;
		//Copy the transaction-id as field data in network byte order (big-endian)
		uint64_t trid_nbo = __cpu_to_be64(trid);
		trfield->field_sz = sizeof(trid_nbo);
		memcpy(trfield->data, &trid_nbo, sizeof(trid_nbo));
		as_msg_swap_field(trfield);

		//Allow space for the message field data
		buf += sizeof(trid_nbo);
	}

	// If we have to send back the setname, we have fields to send back
	if (setname != NULL) {
		as_msg_field *trfield = (as_msg_field *) buf;
		// Allow space for the message field header
		buf += sizeof(as_msg_field);

		// Fill the field header
		trfield->type = AS_MSG_FIELD_TYPE_SET;
		trfield->field_sz = setname_len + 1;
		memcpy(trfield->data, setname, setname_len);
		as_msg_swap_field(trfield);

		// Allow space for the message field data
		buf += setname_len;
	}

	// over all bins, copy into the buffer
	for (uint16_t i = 0; i < bin_count; i++) {

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

		op->op = AS_MSG_OP_READ;

		if (bins[i]) {
			op->version = as_bin_get_version(bins[i], ns->single_bin);
			op->name_sz = as_bin_memcpy_name(ns, op->name, bins[i]);
		}
		else {
			op->version = 0;
			memcpy(op->name, ops[i]->name, ops[i]->name_sz);
			op->name_sz = ops[i]->name_sz;
		}

		buf += op->name_sz;

		// cf_detail(AS_PROTO, "make response: bin %d %s : version %d",i,bins[i]->name,op->version);

		// 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 (bins[i] && as_bin_inuse(bins[i])) {
			op->particle_type = as_particle_type_convert(as_bin_get_particle_type(bins[i]));

			uint32_t psz = msg_sz - (buf - b); // size remaining in buffer, for safety
			if (as_bin_is_hidden(bins[i])) {
				op->particle_type = AS_PARTICLE_TYPE_NULL;
				psz = 0; // packet of size NULL
			} else {
				bool tojson = (as_bin_get_particle_type(bins[i]) ==
							   AS_PARTICLE_TYPE_LUA_BLOB);
				if (0 != _as_particle_tobuf(bins[i], buf, &psz, tojson)) {
					cf_warning(AS_PROTO, "particle to buf: could not copy data!");
				}
			}
			buf += psz;
			op->op_sz += psz;
		}
		else {
			op->particle_type = AS_PARTICLE_TYPE_NULL;
		}

		as_msg_swap_op(op);

	}

	return((cl_msg *) b);
}
コード例 #7
0
ファイル: proto.c プロジェクト: Steve888888/aerospike-server
int as_msg_make_response_bufbuilder(as_record *r, as_storage_rd *rd,
		cf_buf_builder **bb_r, bool nobindata, char *nsname, bool include_ldt_data,
		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 (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 in_use_bins = rd ? (int)as_bin_inuse_count(rd) : 0;
	as_val *ldt_bin_vals[in_use_bins];

	if (! nobindata) {
		if (binlist) {
			int binlist_sz = cf_vector_size(binlist);

			for (uint16_t i = 0; i < binlist_sz; i++) {
				char binname[AS_ID_BIN_SZ];

				cf_vector_get(binlist, i, (void*)&binname);

				as_bin *p_bin = as_bin_get(rd, binname);

				if (! p_bin) {
					continue;
				}

				msg_sz += sizeof(as_msg_op);
				msg_sz += rd->ns->single_bin ? 0 : strlen(binname);

				if (as_bin_is_hidden(p_bin)) {
					if (include_ldt_data) {
						msg_sz += (int)as_ldt_particle_client_value_size(rd, p_bin, &ldt_bin_vals[list_bins]);
					}
					else {
						ldt_bin_vals[list_bins] = NULL;
					}
				}
				else {
					msg_sz += (int)as_bin_particle_client_value_size(p_bin);
				}

				list_bins++;
			}

			// Don't return an empty record.
			if (skip_empty_records && list_bins == 0) {
				return 0;
			}
		}
		else {
			msg_sz += sizeof(as_msg_op) * in_use_bins;

			for (uint16_t i = 0; i < in_use_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));

				if (as_bin_is_hidden(p_bin)) {
					if (include_ldt_data) {
						msg_sz += (int)as_ldt_particle_client_value_size(rd, p_bin, &ldt_bin_vals[i]);
					}
					else {
						ldt_bin_vals[i] = NULL;
					}
				}
				else {
					msg_sz += (int)as_bin_particle_client_value_size(p_bin);
				}
			}
		}
	}

	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 = in_use_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) {
		return 0;
	}

	if (binlist) {
		list_bins = 0;

		int binlist_sz = cf_vector_size(binlist);

		for (uint16_t i = 0; i < binlist_sz; i++) {
			char binname[AS_ID_BIN_SZ];
			cf_vector_get(binlist, i, (void*)&binname);

			as_bin *p_bin = as_bin_get(rd, binname);

			if (! p_bin) {
				continue;
			}

			as_msg_op *op = (as_msg_op *)buf;

			op->op = AS_MSG_OP_READ;
			op->version = 0;
			op->name_sz = as_bin_memcpy_name(rd->ns, op->name, p_bin);
			op->op_sz = 4 + op->name_sz;

			buf += sizeof(as_msg_op) + op->name_sz;

			if (as_bin_is_hidden(p_bin)) {
				buf += as_ldt_particle_to_client(ldt_bin_vals[list_bins], op);
			}
			else {
				buf += as_bin_particle_to_client(p_bin, op);
			}

			list_bins++;

			as_msg_swap_op(op);
		}
	}
	else {
		for (uint16_t i = 0; i < in_use_bins; i++) {
			as_msg_op *op = (as_msg_op *)buf;

			op->op = AS_MSG_OP_READ;
			op->version = 0;
			op->name_sz = as_bin_memcpy_name(rd->ns, op->name, &rd->bins[i]);
			op->op_sz = 4 + op->name_sz;

			buf += sizeof(as_msg_op) + op->name_sz;

			if (as_bin_is_hidden(&rd->bins[i])) {
				buf += as_ldt_particle_to_client(ldt_bin_vals[i], op);
			}
			else {
				buf += as_bin_particle_to_client(&rd->bins[i], op);
			}

			as_msg_swap_op(op);
		}
	}

	return 0;
}
コード例 #8
0
ファイル: proto.c プロジェクト: Steve888888/aerospike-server
cl_msg *
as_msg_make_response_msg(uint32_t result_code, uint32_t generation,
		uint32_t void_time, as_msg_op **ops, as_bin **bins, uint16_t bin_count,
		as_namespace *ns, cl_msg *msgp_in, size_t *msg_sz_in, uint64_t trid,
		const char *setname)
{
	size_t msg_sz = sizeof(cl_msg);

	msg_sz += sizeof(as_msg_op) * bin_count;

	for (uint16_t i = 0; i < bin_count; i++) {
		if (ops) {
			msg_sz += ops[i]->name_sz;
		}
		else if (bins[i]) {
			msg_sz += ns->single_bin ?
					0 : strlen(as_bin_get_name_from_id(ns, bins[i]->id));
		}
		else {
			cf_crash(AS_PROTO, "making response message with null bin and op");
		}

		if (bins[i]) {
			msg_sz += as_bin_particle_client_value_size(bins[i]);
		}
	}

	if (trid != 0) {
		msg_sz += sizeof(as_msg_field) + sizeof(trid);
	}

	uint32_t setname_len = 0;

	if (setname) {
		setname_len = strlen(setname);
		msg_sz += sizeof(as_msg_field) + setname_len;
	}

	uint8_t *b;

	if (! msgp_in || *msg_sz_in < msg_sz) {
		b = cf_malloc(msg_sz);

		if (! b) {
			return NULL;
		}
	}
	else {
		b = (uint8_t *)msgp_in;
	}

	*msg_sz_in = msg_sz;

	uint8_t *buf = b;
	cl_msg *msgp = (cl_msg *)buf;

	msgp->proto.version = PROTO_VERSION;
	msgp->proto.type = PROTO_TYPE_AS_MSG;
	msgp->proto.sz = msg_sz - sizeof(as_proto);
	as_proto_swap(&msgp->proto);

	as_msg *m = &msgp->msg;

	m->header_sz = sizeof(as_msg);
	m->info1 = 0;
	m->info2 = 0;
	m->info3 = 0;
	m->unused = 0;
	m->result_code = result_code;
	m->generation = generation;
	m->record_ttl = void_time;
	m->transaction_ttl = 0;
	m->n_ops = bin_count;
	m->n_fields = 0;

	buf += sizeof(cl_msg);

	if (trid != 0) {
		m->n_fields++;

		as_msg_field *trfield = (as_msg_field *)buf;

		trfield->field_sz = 1 + sizeof(uint64_t);
		trfield->type = AS_MSG_FIELD_TYPE_TRID;
		*(uint64_t *)trfield->data = cf_swap_to_be64(trid);

		buf += sizeof(as_msg_field) + sizeof(uint64_t);
		as_msg_swap_field(trfield);
	}

	if (setname) {
		m->n_fields++;

		as_msg_field *trfield = (as_msg_field *)buf;

		trfield->field_sz = 1 + setname_len;
		trfield->type = AS_MSG_FIELD_TYPE_SET;
		memcpy(trfield->data, setname, setname_len);

		buf += sizeof(as_msg_field) + setname_len;
		as_msg_swap_field(trfield);
	}

	as_msg_swap_header(m);

	for (uint16_t i = 0; i < bin_count; i++) {
		as_msg_op *op = (as_msg_op *)buf;

		op->version = 0;

		if (ops) {
			op->op = ops[i]->op;
			memcpy(op->name, ops[i]->name, ops[i]->name_sz);
			op->name_sz = ops[i]->name_sz;
		}
		else {
			op->op = AS_MSG_OP_READ;
			op->name_sz = as_bin_memcpy_name(ns, op->name, bins[i]);
		}

		op->op_sz = 4 + op->name_sz;

		buf += sizeof(as_msg_op) + op->name_sz;
		buf += as_bin_particle_to_client(bins[i], op);

		as_msg_swap_op(op);
	}

	return (cl_msg *)b;
}
コード例 #9
0
/*
  The transaction prepare function fills out the fields of the tr structure,
  using the information in the msg structure. It also swaps the fields in the
  message header (which are originally in network byte order).

  Once the prepare function has been called on the transaction, the
  'preprocessed' flag is set and the transaction cannot be prepared again.
  Returns:
  0:  OK
  -1: General Error
  -2: Request received with no key
  -3: Request received with digest array
*/
int as_transaction_prepare(as_transaction *tr) {
	cl_msg *msgp = tr->msgp;
	as_msg *m = &msgp->msg;

#if defined(USE_SYSTEMTAP)
	uint64_t nodeid = g_config.self_node;
#endif

//	cf_assert(tr, AS_PROTO, CF_CRITICAL, "invalid transaction");

	void *limit = ((void *)m) + msgp->proto.sz;

	// Check processed flag.  It's a non-fatal error to call this function again.
	if( tr->preprocessed )
		return(0);

	if (0 != cf_digest_compare(&tr->keyd, &cf_digest_zero)) {
		cf_warning(AS_RW, "Internal inconsistency: transaction has keyd, but marked not swizzled");
	}

	as_msg_swap_header(m);
	if (0 != as_msg_swap_fields_and_ops(m, limit)) {
		cf_info(AS_PROTO, "msg swap field and ops returned error");
		return(-1);
	}

	if (m->n_fields>PROTO_NFIELDS_MAX_WARNING) {
		cf_info(AS_PROTO, "received too many n_fields! %d",m->n_fields);
    }

	// Set the transaction end time if available.
	if (m->transaction_ttl) {
//		cf_debug(AS_PROTO, "received non-zero transaction ttl: %d",m->transaction_ttl);
		tr->end_time = tr->start_time + ((uint64_t)m->transaction_ttl * 1000000);
	}

	// Set the preprocessed flag. All exits from here on out are considered
	// processed since the msg header has been swapped and the transaction
	// end time has been set.
	tr->preprocessed = true;
	tr->flag         = 0;
	UREQ_DATA_INIT(&tr->udata);
	as_msg_field *sfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_DIGEST_RIPE_ARRAY);
	if (sfp) {
		cf_debug(AS_PROTO, "received request with digest array, batch");
		return(-3);
	}

	// It's tempting to move this to the final return, but queries
	// actually escape in the if clause below ...
	ASD_TRANS_PREPARE(nodeid, (uint64_t) msgp, tr->trid);

	// Sent digest? Use!
	as_msg_field *dfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_DIGEST_RIPE);
	if (dfp) {
//		cf_detail(AS_PROTO, "transaction prepare: received sent digest\n");
		if (as_msg_field_get_value_sz(dfp) != sizeof(cf_digest)) {
			cf_info(AS_PROTO, "sent bad digest size %d, recomputing digest",as_msg_field_get_value_sz(dfp));
			goto Compute;
		}
		memcpy(&tr->keyd, dfp->data, sizeof(cf_digest));
	}
	// Not sent, so compute.
	else {
Compute:		;
		as_msg_field *kfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_KEY);
		if (!kfp) {
			cf_detail(AS_PROTO, "received request with no key, scan");
			return(-2);
		}
        if (as_msg_field_get_value_sz(kfp)> PROTO_FIELD_LENGTH_MAX) {
	        cf_info(AS_PROTO, "key field too big %d. Is it for real?",as_msg_field_get_value_sz(kfp));
        }

		as_msg_field *sfp = as_msg_field_get(m, AS_MSG_FIELD_TYPE_SET);
		if (sfp == 0 || as_msg_field_get_value_sz(sfp) == 0) {
			cf_digest_compute(kfp->data, as_msg_field_get_value_sz(kfp), &tr->keyd);
			// cf_info(AS_PROTO, "computing key for sz %d %"PRIx64" bytes %d %d %d %d",as_msg_field_get_value_sz(kfp),*(uint64_t *)&tr->keyd,kfp->data[0],kfp->data[1],kfp->data[2],kfp->data[3]);
		}
		else {
            if (as_msg_field_get_value_sz(sfp)> PROTO_FIELD_LENGTH_MAX) {
		        cf_info(AS_PROTO, "set field too big %d. Is this for real?",as_msg_field_get_value_sz(sfp));
            }
			cf_digest_compute2(sfp->data, as_msg_field_get_value_sz(sfp),
						kfp->data, as_msg_field_get_value_sz(kfp),
						&tr->keyd);
			// cf_info(AS_PROTO, "computing set with key for sz %d %"PRIx64" bytes %d %d",as_msg_field_get_value_sz(kfp),*(uint64_t *)&tr->keyd,kfp->data[0],kfp->data[1],kfp->data[2],kfp->data[3]);
		}
	}

	return(0);
}