コード例 #1
0
// Byte swap header from network byte order (big endian) to current machine byte order.
void
as_msg_swap_header_from_be(as_msg *m)
{
	m->generation = cf_swap_from_be32(m->generation);
	m->record_ttl =  cf_swap_from_be32(m->record_ttl);
	m->transaction_ttl = cf_swap_from_be32(m->transaction_ttl);
	m->n_fields = cf_swap_from_be16(m->n_fields);
	m->n_ops= cf_swap_from_be16(m->n_ops);
}
コード例 #2
0
static void
as_uv_connected(uv_connect_t* req, int status)
{
	if (uv_is_closing((uv_handle_t*)req->handle)) {
		return;
	}

	as_event_command* cmd = req->data;

	if (status == 0) {
		if (cmd->cluster->user) {
			as_uv_auth_write_start(cmd, req->handle);
		}
		else {
			as_uv_command_write_start(cmd, req->handle);
		}
	}
	else if (status != UV_ECANCELED) {
		as_node* node = cmd->node;
		as_address* primary = as_vector_get(&node->addresses, node->address_index);
		
		as_error err;
		as_error_update(&err, AEROSPIKE_ERR_ASYNC_CONNECTION, "Failed to connect: %s %s:%d",
						node->name, primary->name, (int)cf_swap_from_be16(primary->addr.sin_port));
		as_uv_connect_error(cmd, &err);
	}
}
コード例 #3
0
ファイル: cdt.c プロジェクト: BruceZhou2012/aerospike-server
bool
cdt_process_state_init(cdt_process_state *cdt_state, const as_msg_op *op)
{
	const uint8_t *data = op->name + op->name_sz;
	uint32_t size = op->op_sz - 4 - op->name_sz;

	if (size < sizeof(uint16_t)) {
		cf_warning(AS_PARTICLE, "cdt_parse_state_init() as_msg_op data too small to be valid: size=%u", size);
		return false;
	}

	const uint16_t *type_ptr = (const uint16_t *)data;
	cdt_state->type = cf_swap_from_be16(*type_ptr);

	cdt_state->pk.buffer = data + sizeof(uint16_t);
	cdt_state->pk.length = size - sizeof(uint16_t);
	cdt_state->pk.offset = 0;

	int ele_count = (cdt_state->pk.length == 0) ? 0 : as_unpack_list_header_element_count(&cdt_state->pk);

	if (ele_count < 0) {
		cf_warning(AS_PARTICLE, "cdt_parse_state_init() unpack list header failed: size=%u type=%u", size, cdt_state->type);
		return false;
	}

	cdt_state->ele_count = ele_count;

	return true;
}
コード例 #4
0
ファイル: record.c プロジェクト: aerospike/aerospike-server
// TODO - old pickle - remove in "six months".
int
old_record_apply_ssd_single_bin(as_remote_record *rr, as_storage_rd *rd,
		bool *is_delete)
{
	as_namespace* ns = rr->rsv->ns;
	as_record* r = rd->r;

	uint16_t n_new_bins = cf_swap_from_be16(*(uint16_t *)rr->pickle);

	if (n_new_bins > 1) {
		cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: single-bin got %u bins ", ns->name, n_new_bins);
		return AS_ERR_UNKNOWN;
	}

	as_bin stack_bin = { { 0 } };

	rd->n_bins = 1;
	rd->bins = &stack_bin;

	// Fill the new bin and particle.
	cf_ll_buf_define(particles_llb, STACK_PARTICLES_SIZE);

	int result;

	if (n_new_bins == 1 &&
			(result = unpickle_bins(rr, rd, &particles_llb)) != 0) {
		cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed unpickle bin ", ns->name);
		cf_ll_buf_free(&particles_llb);
		return result;
	}

	// Apply changes to metadata in as_index needed for and writing.
	index_metadata old_metadata;

	update_index_metadata(rr, &old_metadata, r);

	// Prepare to store or drop key, as determined by message.
	rd->key = rr->key;
	rd->key_size = rr->key_size;

	// Write the record to storage.
	if ((result = as_record_write_from_pickle(rd)) < 0) {
		cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed write ", ns->name);
		unwind_index_metadata(&old_metadata, r);
		cf_ll_buf_free(&particles_llb);
		return -result;
	}

	// Now ok to store or drop key, as determined by message.
	as_record_finalize_key(r, ns, rd->key, rd->key_size);

	*is_delete = n_new_bins == 0;

	cf_ll_buf_free(&particles_llb);

	return AS_OK;
}
コード例 #5
0
ファイル: as_node.c プロジェクト: Benguang/aerospike-client-c
static int
as_node_create_connection(as_node* node, int* fd)
{
	// Create a non-blocking socket.
	*fd = cf_socket_create_nb();
	
	if (*fd == -1) {
		// Local problem - socket create failed.
		cf_debug("Socket create failed for %s", node->name);
		return CITRUSLEAF_FAIL_CLIENT;
	}
	
	// Try primary address.
	as_address* primary = as_vector_get(&node->addresses, node->address_index);
	
	if (cf_socket_start_connect_nb(*fd, &primary->addr) == 0) {
		// Connection started ok - we have our socket.
		return as_node_authenticate_connection(node, fd);
	}
	
	// Try other addresses.
	as_vector* addresses = &node->addresses;
	for (uint32_t i = 0; i < addresses->size; i++) {
		as_address* address = as_vector_get(addresses, i);
		
		// Address points into alias array, so pointer comparison is sufficient.
		if (address != primary) {
			if (cf_socket_start_connect_nb(*fd, &address->addr) == 0) {
				// Replace invalid primary address with valid alias.
				// Other threads may not see this change immediately.
				// It's just a hint, not a requirement to try this new address first.
				cf_debug("Change node address %s %s:%d", node->name, address->name, (int)cf_swap_from_be16(address->addr.sin_port));
				ck_pr_store_32(&node->address_index, i);
				return as_node_authenticate_connection(node, fd);
			}
		}
	}
	
	// Couldn't start a connection on any socket address - close the socket.
	cf_info("Failed to connect: %s %s:%d", node->name, primary->name, (int)cf_swap_from_be16(primary->addr.sin_port));
	cf_close(*fd);
	*fd = -1;
	return CITRUSLEAF_FAIL_UNAVAILABLE;
}
コード例 #6
0
static void
as_cluster_find_nodes_to_add(as_cluster* cluster, as_vector* /* <as_host> */ friends, as_vector* /* <as_node*> */ nodes_to_add)
{
	as_error err;
	as_error_init(&err);
	as_vector addresses;
	as_vector_inita(&addresses, sizeof(struct sockaddr_in), 5);
	
	as_node_info node_info;

	for (uint32_t i = 0; i < friends->size; i++) {
		as_host* friend = as_vector_get(friends, i);
		as_vector_clear(&addresses);
		
		as_status status = as_lookup(&err, friend->name, friend->port, &addresses);
		
		if (status != AEROSPIKE_OK) {
			as_log_warn("%s %s", as_error_string(status), err.message);
			continue;
		}
		
		for (uint32_t i = 0; i < addresses.size; i++) {
			struct sockaddr_in* addr = as_vector_get(&addresses, i);
			status = as_lookup_node(cluster, &err, addr, &node_info);
			
			if (status == AEROSPIKE_OK) {
				as_node* node = as_cluster_find_node(cluster->nodes, nodes_to_add, node_info.name);
				
				if (node) {
					// Duplicate node name found.  This usually occurs when the server
					// services list contains both internal and external IP addresses
					// for the same node.  Add new host to list of alias filters
					// and do not add new node.
					as_close(node_info.fd);
					as_address* a = as_node_get_address_full(node);
					as_log_info("Node %s:%d already exists with nodeid %s and address %s:%d", 
						friend->name, friend->port, node->name, a->name,
						(int)cf_swap_from_be16(a->addr.sin_port));
					node->friends++;
					as_node_add_address(node, friend, addr);
					continue;
				}
				
				node = as_node_create(cluster, friend, addr, &node_info);
				as_address* a = as_node_get_address_full(node);
				as_log_info("Add node %s %s:%d", node_info.name, a->name, (int)cf_swap_from_be16(a->addr.sin_port));
				as_vector_append(nodes_to_add, &node);
			}
			else {
				as_log_warn("Failed to connect to friend %s:%d. %s %s", friend->name, friend->port, as_error_string(status), err.message);
			}
		}
コード例 #7
0
int32_t
geojson_size_from_wire(const uint8_t *wire_value, uint32_t value_size)
{
	// NOTE - Unfortunately we would need to run the JSON parser and region
	// coverer to find out exactly how many cells we need to allocate for this
	// particle.
	//
	// For now we always allocate the maximum number of cells (MAX_REGION_CELLS)
	// for the in-memory particle.
	//
	// For now also ignore any incoming cells entirely.

	uint8_t const *incp = (uint8_t const *)wire_value + 1;
	uint16_t incells = cf_swap_from_be16(*(uint16_t const *)incp);
	size_t incellsz = incells * sizeof(uint64_t);
	size_t injsonsz = value_size - sizeof(uint8_t) - sizeof(uint16_t) - incellsz;

	return (int32_t)(sizeof(geojson_mem) + (MAX_REGION_CELLS * sizeof(uint64_t)) + injsonsz);
}
コード例 #8
0
static as_status
as_cluster_seed_nodes(as_cluster* cluster, as_error* err, bool enable_warnings)
{
	// Add all nodes at once to avoid copying entire array multiple times.
	as_vector nodes_to_add;
	as_vector_inita(&nodes_to_add, sizeof(as_node*), 64);
	
	as_vector addresses;
	as_vector_inita(&addresses, sizeof(struct sockaddr_in), 5);
	
	as_node_info node_info;
	as_error error_local;
	as_error_init(&error_local); // AEROSPIKE_ERR_TIMEOUT doesn't come with a message; make sure it's initialized.
	as_status status = AEROSPIKE_OK;
	
	as_seeds* seeds = as_seeds_reserve(cluster);

	for (uint32_t i = 0; i < seeds->size; i++) {
		as_seed* seed = &seeds->array[i];
		as_vector_clear(&addresses);
		
		status = as_lookup(&error_local, seed->name, seed->port, &addresses);
		
		if (status != AEROSPIKE_OK) {
			if (enable_warnings) {
				as_log_warn("Failed to lookup %s:%d. %s %s", seed->name, seed->port, as_error_string(status), error_local.message);
			}
			continue;
		}

		for (uint32_t i = 0; i < addresses.size; i++) {
			struct sockaddr_in* addr = as_vector_get(&addresses, i);
			status = as_lookup_node(cluster, &error_local, addr, &node_info);
			
			if (status == AEROSPIKE_OK) {
				as_host host;
				if (as_strncpy(host.name, seed->name, sizeof(host.name))) {
					as_log_warn("Hostname has been truncated: %s", host.name);
				}
				host.port = seed->port;

				as_node* node = as_cluster_find_node_in_vector(&nodes_to_add, node_info.name);
				
				if (node) {
					as_close(node_info.fd);
					as_node_add_address(node, &host, addr);
				}
				else {
					node = as_node_create(cluster, &host, addr, &node_info);
					as_address* a = as_node_get_address_full(node);
					as_log_info("Add node %s %s:%d", node->name, a->name, (int)cf_swap_from_be16(a->addr.sin_port));
					as_vector_append(&nodes_to_add, &node);
				}
			}
			else {
				if (enable_warnings) {
					as_log_warn("Failed to connect to seed %s:%d. %s %s", seed->name, seed->port, as_error_string(status), error_local.message);
				}
			}
		}
	}
	
	as_seeds_release(seeds);

	if (nodes_to_add.size > 0) {
		as_cluster_add_nodes(cluster, &nodes_to_add);
		status = AEROSPIKE_OK;
	}
	else {
		status = as_error_set_message(err, AEROSPIKE_ERR_CLIENT, "Failed to seed cluster");
	}
	
	as_vector_destroy(&nodes_to_add);
	as_vector_destroy(&addresses);
	return status;
}
コード例 #9
0
static void
as_ev_connect(as_event_command* cmd)
{
	int fd = as_event_create_socket(cmd);
	
	if (fd < 0) {
		return;
	}
		
	// Try primary address.
	as_node* node = cmd->node;
	as_address* primary = as_vector_get(&node->addresses, node->address_index);
	
	// Attempt non-blocking connection.
	if (connect(fd, (struct sockaddr*)&primary->addr, sizeof(struct sockaddr)) == 0) {
		as_ev_watcher_init(cmd, fd);
		return;
	}
	
	// Check if connection is in progress.
	if (errno == EINPROGRESS) {
		as_ev_watcher_init(cmd, fd);
		return;
	}
	
	// Try other addresses.
	as_vector* addresses = &node->addresses;
	for (uint32_t i = 0; i < addresses->size; i++) {
		as_address* address = as_vector_get(addresses, i);
		
		// Address points into alias array, so pointer comparison is sufficient.
		if (address != primary) {
			if (connect(fd, (struct sockaddr*)&address->addr, sizeof(struct sockaddr)) == 0) {
				// Replace invalid primary address with valid alias.
				// Other threads may not see this change immediately.
				// It's just a hint, not a requirement to try this new address first.
				as_log_debug("Change node address %s %s:%d", node->name, address->name, (int)cf_swap_from_be16(address->addr.sin_port));
				ck_pr_store_32(&node->address_index, i);
				as_ev_watcher_init(cmd, fd);
				return;
			}
			
			// Check if connection is in progress.
			if (errno == EINPROGRESS) {
				// Replace invalid primary address with valid alias.
				// Other threads may not see this change immediately.
				// It's just a hint, not a requirement to try this new address first.
				as_log_debug("Change node address %s %s:%d", node->name, address->name, (int)cf_swap_from_be16(address->addr.sin_port));
				ck_pr_store_32(&node->address_index, i);
				
				// Connection hasn't finished.
				as_ev_watcher_init(cmd, fd);
				return;
			}
		}
	}
	
	// Failed to start a connection on any socket address.
	as_error err;
	as_error_update(&err, AEROSPIKE_ERR_ASYNC_CONNECTION, "Failed to connect: %s %s:%d",
					node->name, primary->name, (int)cf_swap_from_be16(primary->addr.sin_port));
	as_event_connect_error(cmd, &err, fd);
}
コード例 #10
0
ファイル: record.c プロジェクト: aerospike/aerospike-server
// TODO - old pickle - remove in "six months".
int
old_record_apply_dim(as_remote_record *rr, as_storage_rd *rd, bool skip_sindex,
		bool *is_delete)
{
	as_namespace* ns = rr->rsv->ns;
	as_record* r = rd->r;

	// Set rd->n_bins!
	as_storage_rd_load_n_bins(rd);

	// Set rd->bins!
	as_storage_rd_load_bins(rd, NULL);

	// For memory accounting, note current usage.
	uint64_t memory_bytes = as_storage_record_get_n_bytes_memory(rd);

	// Keep old bins intact for sindex adjustment and unwinding.
	uint16_t n_old_bins = rd->n_bins;
	as_bin* old_bins = rd->bins;

	uint16_t n_new_bins = cf_swap_from_be16(*(uint16_t *)rr->pickle);
	as_bin new_bins[n_new_bins];

	memset(new_bins, 0, sizeof(new_bins));
	rd->n_bins = n_new_bins;
	rd->bins = new_bins;

	// Fill the new bins and particles.
	int result = unpickle_bins(rr, rd, NULL);

	if (result != 0) {
		cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed unpickle bins ", ns->name);
		destroy_stack_bins(new_bins, n_new_bins);
		return result;
	}

	// Apply changes to metadata in as_index needed for and writing.
	index_metadata old_metadata;

	update_index_metadata(rr, &old_metadata, r);

	// Prepare to store or drop key, as determined by message.
	rd->key = rr->key;
	rd->key_size = rr->key_size;

	// Write the record to storage.
	if ((result = as_record_write_from_pickle(rd)) < 0) {
		cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed write ", ns->name);
		unwind_index_metadata(&old_metadata, r);
		destroy_stack_bins(new_bins, n_new_bins);
		return -result;
	}

	// Success - adjust sindex, looking at old and new bins.
	if (! (skip_sindex &&
			next_generation(r->generation, (uint16_t)rr->generation, ns)) &&
					record_has_sindex(r, ns)) {
		write_sindex_update(ns, as_index_get_set_name(r, ns), rr->keyd,
				old_bins, n_old_bins, new_bins, n_new_bins);
	}

	// Cleanup - destroy relevant bins, can't unwind after.
	destroy_stack_bins(old_bins, n_old_bins);

	// Fill out new_bin_space.
	as_bin_space* new_bin_space = NULL;

	if (n_new_bins != 0) {
		new_bin_space = (as_bin_space*)
				cf_malloc_ns(sizeof(as_bin_space) + sizeof(new_bins));

		new_bin_space->n_bins = rd->n_bins;
		memcpy((void*)new_bin_space->bins, new_bins, sizeof(new_bins));
	}

	// Swizzle the index element's as_bin_space pointer.
	as_bin_space* old_bin_space = as_index_get_bin_space(r);

	if (old_bin_space) {
		cf_free(old_bin_space);
	}

	as_index_set_bin_space(r, new_bin_space);

	// Now ok to store or drop key, as determined by message.
	as_record_finalize_key(r, ns, rd->key, rd->key_size);

	as_storage_record_adjust_mem_stats(rd, memory_bytes);
	*is_delete = n_new_bins == 0;

	return AS_OK;
}
コード例 #11
0
ファイル: record.c プロジェクト: aerospike/aerospike-server
// TODO - old pickle - remove in "six months".
int
old_record_apply_dim_single_bin(as_remote_record *rr, as_storage_rd *rd,
		bool *is_delete)
{
	as_namespace* ns = rr->rsv->ns;
	as_record* r = rd->r;

	rd->n_bins = 1;

	// Set rd->bins!
	as_storage_rd_load_bins(rd, NULL);

	// For memory accounting, note current usage.
	uint64_t memory_bytes = 0;

	// TODO - as_storage_record_get_n_bytes_memory() could check bins in use.
	if (as_bin_inuse(rd->bins)) {
		memory_bytes = as_storage_record_get_n_bytes_memory(rd);
	}

	uint16_t n_new_bins = cf_swap_from_be16(*(uint16_t *)rr->pickle);

	if (n_new_bins > 1) {
		cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: single-bin got %u bins ", ns->name, n_new_bins);
		return AS_ERR_UNKNOWN;
	}

	// Keep old bin intact for unwinding, clear record bin for incoming.
	as_bin old_bin;

	as_single_bin_copy(&old_bin, rd->bins);
	as_bin_set_empty(rd->bins);

	int result;

	// Fill the new bins and particles.
	if (n_new_bins == 1 &&
			(result = unpickle_bins(rr, rd, NULL)) != 0) {
		cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed unpickle bin ", ns->name);
		unwind_dim_single_bin(&old_bin, rd->bins);
		return result;
	}

	// Apply changes to metadata in as_index needed for and writing.
	index_metadata old_metadata;

	update_index_metadata(rr, &old_metadata, r);

	// Write the record to storage.
	if ((result = as_record_write_from_pickle(rd)) < 0) {
		cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed write ", ns->name);
		unwind_index_metadata(&old_metadata, r);
		unwind_dim_single_bin(&old_bin, rd->bins);
		return -result;
	}

	// Cleanup - destroy old bin, can't unwind after.
	as_bin_particle_destroy(&old_bin, true);

	as_storage_record_adjust_mem_stats(rd, memory_bytes);
	*is_delete = n_new_bins == 0;

	return AS_OK;
}
コード例 #12
0
ファイル: record.c プロジェクト: aerospike/aerospike-server
// TODO - old pickle - remove in "six months".
int
old_record_apply_ssd(as_remote_record *rr, as_storage_rd *rd, bool skip_sindex,
		bool *is_delete)
{
	as_namespace* ns = rr->rsv->ns;
	as_record* r = rd->r;
	bool has_sindex = ! (skip_sindex &&
			next_generation(r->generation, (uint16_t)rr->generation, ns)) &&
					record_has_sindex(r, ns);

	uint16_t n_old_bins = 0;
	int result;

	if (has_sindex) {
		// Set rd->n_bins!
		if ((result = as_storage_rd_load_n_bins(rd)) < 0) {
			cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed load n-bins ", ns->name);
			return -result;
		}

		n_old_bins = rd->n_bins;
	}

	as_bin old_bins[n_old_bins];

	if (has_sindex) {
		// Set rd->bins!
		if ((result = as_storage_rd_load_bins(rd, old_bins)) < 0) {
			cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed load bins ", ns->name);
			return -result;
		}
	}

	// Stack space for resulting record's bins.
	uint16_t n_new_bins = cf_swap_from_be16(*(uint16_t *)rr->pickle);
	as_bin new_bins[n_new_bins];

	memset(new_bins, 0, sizeof(new_bins));
	rd->n_bins = n_new_bins;
	rd->bins = new_bins;

	// Fill the new bins and particles.
	cf_ll_buf_define(particles_llb, STACK_PARTICLES_SIZE);

	if ((result = unpickle_bins(rr, rd, &particles_llb)) != 0) {
		cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed unpickle bins ", ns->name);
		cf_ll_buf_free(&particles_llb);
		return result;
	}

	// Apply changes to metadata in as_index needed for and writing.
	index_metadata old_metadata;

	update_index_metadata(rr, &old_metadata, r);

	// Prepare to store or drop key, as determined by message.
	rd->key = rr->key;
	rd->key_size = rr->key_size;

	// Write the record to storage.
	if ((result = as_record_write_from_pickle(rd)) < 0) {
		cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed write ", ns->name);
		unwind_index_metadata(&old_metadata, r);
		cf_ll_buf_free(&particles_llb);
		return -result;
	}

	// Success - adjust sindex, looking at old and new bins.
	if (has_sindex) {
		write_sindex_update(ns, as_index_get_set_name(r, ns), rr->keyd,
				old_bins, n_old_bins, new_bins, n_new_bins);
	}

	// Now ok to store or drop key, as determined by message.
	as_record_finalize_key(r, ns, rd->key, rd->key_size);

	*is_delete = n_new_bins == 0;

	cf_ll_buf_free(&particles_llb);

	return AS_OK;
}
コード例 #13
0
ファイル: as_command.c プロジェクト: nutsi/aerospike-client-c
uint8_t*
as_command_parse_bins(as_record* rec, uint8_t* p, uint32_t n_bins, bool deserialize)
{
	as_bin* bin = rec->bins.entries;
	
	// Parse bins
	for (uint32_t i = 0; i < n_bins; i++, bin++) {
		uint32_t op_size = cf_swap_from_be32(*(uint32_t*)p);
		p += 5;
		uint8_t type = *p;
		p += 2;
		
		uint8_t name_size = *p++;
		uint8_t name_len = (name_size <= AS_BIN_NAME_MAX_LEN)? name_size : AS_BIN_NAME_MAX_LEN;
		memcpy(bin->name, p, name_len);
		bin->name[name_len] = 0;
		p += name_size;
		
		uint32_t value_size = (op_size - (name_size + 4));
		
		switch (type) {
			case AS_BYTES_UNDEF: {
				bin->valuep = (as_bin_value*)&as_nil;
				break;
			}
			case AS_BYTES_INTEGER: {
				int64_t value;
				if (as_command_bytes_to_int(p, value_size, &value) == 0) {
					as_integer_init((as_integer*)&bin->value, value);
					bin->valuep = &bin->value;
				}
				break;
			}
			case AS_BYTES_DOUBLE: {
				double value = cf_swap_from_big_float64(*(double*)p);
				as_double_init((as_double*)&bin->value, value);
				bin->valuep = &bin->value;
				break;
			}
			case AS_BYTES_STRING: {
				char* value = cf_malloc(value_size + 1);
				memcpy(value, p, value_size);
				value[value_size] = 0;
				as_string_init_wlen((as_string*)&bin->value, (char*)value, value_size, true);
				bin->valuep = &bin->value;
				break;
			}
			case AS_BYTES_GEOJSON: {
				uint8_t * ptr = p;

				// skip flags
				ptr++;

				// ncells
				uint16_t ncells = cf_swap_from_be16(* (uint16_t *) ptr);
				ptr += sizeof(uint16_t);

				// skip any cells
				ptr += sizeof(uint64_t) * ncells;

				// Use the json bytes.
				size_t jsonsz = value_size - 1 - 2 - (ncells * sizeof(uint64_t));
				char* v = cf_malloc(jsonsz + 1);
				memcpy(v, ptr, jsonsz);
				v[jsonsz] = 0;
				as_geojson_init_wlen((as_geojson*)&bin->value,
									 (char*)v, jsonsz, true);
				bin->valuep = &bin->value;
				break;
			}
			case AS_BYTES_LDT:
			case AS_BYTES_LIST:
			case AS_BYTES_MAP: {
				if (deserialize) {
					as_val* value = 0;
					
					as_buffer buffer;
					buffer.data = p;
					buffer.size = value_size;
					
					as_serializer ser;
					as_msgpack_init(&ser);
					as_serializer_deserialize(&ser, &buffer, &value);
					as_serializer_destroy(&ser);
					
					bin->valuep = (as_bin_value*)value;
				}
				else {
					void* value = cf_malloc(value_size);
					memcpy(value, p, value_size);
					as_bytes_init_wrap((as_bytes*)&bin->value, value, value_size, true);
					bin->value.bytes.type = (as_bytes_type)type;
					bin->valuep = &bin->value;
				}
				break;
			}
			default: {
				void* value = cf_malloc(value_size);
				memcpy(value, p, value_size);
				as_bytes_init_wrap((as_bytes*)&bin->value, value, value_size, true);
				bin->value.bytes.type = (as_bytes_type)type;
				bin->valuep = &bin->value;
				break;
			}
		}
		rec->bins.size++;
		p += value_size;
	}
	return p;
}
コード例 #14
0
ファイル: as_command.c プロジェクト: nutsi/aerospike-client-c
static void
as_command_parse_value(uint8_t* p, uint8_t type, uint32_t value_size, as_val** value)
{
	// Allocate values on heap.
	switch (type) {
		case AS_BYTES_UNDEF: {
			*value = (as_val*)&as_nil;
			break;
		}
		case AS_BYTES_INTEGER: {
			int64_t v = 0;
			as_command_bytes_to_int(p, value_size, &v);
			*value = (as_val*)as_integer_new(v);
			break;
		}
		case AS_BYTES_DOUBLE: {
			double v = cf_swap_from_big_float64(*(double*)p);
			*value = (as_val*)as_double_new(v);
			break;
		}
		case AS_BYTES_STRING: {
			char* v = cf_malloc(value_size + 1);
			memcpy(v, p, value_size);
			v[value_size] = 0;
			*value = (as_val*)as_string_new_wlen(v, value_size, true);
			break;
		}
		case AS_BYTES_GEOJSON: {
			uint8_t * ptr = p;

			// skip flags
			ptr++;

			// ncells
			uint16_t ncells = cf_swap_from_be16(* (uint16_t *) ptr);
			ptr += sizeof(uint16_t);

			// skip any cells
			ptr += sizeof(uint64_t) * ncells;

			// Use the json bytes.
			size_t jsonsz = value_size - 1 - 2 - (ncells * sizeof(uint64_t));
			char* v = cf_malloc(jsonsz + 1);
			memcpy(v, ptr, jsonsz);
			v[jsonsz] = 0;
			*value = (as_val*) as_geojson_new_wlen(v, jsonsz, true);
			break;
		}
		case AS_BYTES_LIST:
		case AS_BYTES_MAP: {
			as_buffer buffer;
			buffer.data = p;
			buffer.size = value_size;
			
			as_serializer ser;
			as_msgpack_init(&ser);
			as_serializer_deserialize(&ser, &buffer, value);
			as_serializer_destroy(&ser);
			break;
		}
		default: {
			void* v = cf_malloc(value_size);
			memcpy(v, p, value_size);
			*value = (as_val*)as_bytes_new_wrap(v, value_size, true);
			break;
		}
	}
}
コード例 #15
0
int
geojson_from_wire(as_particle_type wire_type, const uint8_t *wire_value, uint32_t value_size, as_particle **pp)
{
	uint8_t const *incp = (uint8_t const *)wire_value + 1;
	uint16_t incells = cf_swap_from_be16(*(uint16_t const *)incp);
	size_t incellsz = incells * sizeof(uint64_t);
	char const *injsonptr = (char const *)incp + sizeof(uint16_t) + incellsz;
	size_t injsonsz = value_size - sizeof(uint8_t) - sizeof(uint16_t) - incellsz;

	// We ignore any incoming cells entirely.

	uint64_t cellid = 0;
	geo_region_t region = NULL;

	if (! geo_parse(NULL, injsonptr, injsonsz, &cellid, &region)) {
		cf_warning(AS_PARTICLE, "geo_parse failed");
		return -AS_PROTO_RESULT_FAIL_GEO_INVALID_GEOJSON;
	}

	if (cellid && region) {
		geo_region_destroy(region);
		cf_warning(AS_PARTICLE, "geo_parse found both point and region");
		return -AS_PROTO_RESULT_FAIL_GEO_INVALID_GEOJSON;
	}

	if (! cellid && ! region) {
		cf_warning(AS_PARTICLE, "geo_parse found neither point nor region");
		return -AS_PROTO_RESULT_FAIL_GEO_INVALID_GEOJSON;
	}

	geojson_mem *p_geojson_mem = (geojson_mem *)*pp;

	p_geojson_mem->type = wire_type;

	// We'll come back and set the size at the end.
	uint64_t *p_outcells = (uint64_t *)p_geojson_mem->data;

	p_geojson_mem->flags = 0;

	if (cellid) {
		// POINT
		p_geojson_mem->flags &= ~GEOJSON_ISREGION;
		p_geojson_mem->ncells = 1;
		p_outcells[0] = cellid;
	}
	else {
		// REGION
		p_geojson_mem->flags |= GEOJSON_ISREGION;

		int numcells;

		if (! geo_region_cover(NULL, region, MAX_REGION_CELLS, p_outcells, NULL, NULL, &numcells)) {
			geo_region_destroy(region);
			cf_warning(AS_PARTICLE, "geo_region_cover failed");
			return -AS_PROTO_RESULT_FAIL_GEO_INVALID_GEOJSON;
		}

		p_geojson_mem->ncells = numcells;
	}

	if (region) {
		geo_region_destroy(region);
	}

	// Copy the JSON into place.
	char *p_outjson = (char *)&p_outcells[p_geojson_mem->ncells];

	memcpy(p_outjson, injsonptr, injsonsz);

	// Set the actual size; we will waste some space at the end of the allocated
	// particle.
	p_geojson_mem->sz = sizeof(uint8_t) + sizeof(uint16_t) + (p_geojson_mem->ncells * sizeof(uint64_t)) + injsonsz;

	return AS_PROTO_RESULT_OK;
}