コード例 #1
0
static as_status
as_command_parse_udf_failure(uint8_t* p, as_error* err, as_msg* msg, as_status status)
{
    p = as_command_ignore_fields(p, msg->n_fields);

    as_bin_name name;

    for (uint32_t i = 0; i < msg->n_ops; i++) {
        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(name, p, name_len);
        name[name_len] = 0;
        p += name_size;

        uint32_t value_size = (op_size - (name_size + 4));

        if (strcmp(name, "FAILURE") == 0) {
            as_val* val = 0;
            as_command_parse_value(p, type, value_size, &val);
            status = as_command_parse_udf_error(err, status, val);
            as_val_destroy(val);
            return status;
        }
        p += value_size;
    }
    return as_error_set_message(err, status, as_error_string(status));
}
コード例 #2
0
ファイル: as_admin.c プロジェクト: XeCycle/aerospike-client-c
as_status
as_authenticate(as_error* err, int fd, const char* user, const char* credential, uint64_t deadline_ms)
{
    uint8_t buffer[AS_STACK_BUF_SIZE];
    uint8_t* p = buffer + 8;

    p = as_admin_write_header(p, AUTHENTICATE, 2);
    p = as_admin_write_field_string(p, USER, user);
    p = as_admin_write_field_string(p, CREDENTIAL, credential);

    as_status status = as_admin_send(err, fd, buffer, p, deadline_ms);

    if (status) {
        return status;
    }

    status = as_socket_read_deadline(err, fd, buffer, HEADER_SIZE, deadline_ms);

    if (status) {
        return status;
    }

    status = buffer[RESULT_CODE];

    if (status) {
        as_error_set_message(err, status, as_error_string(status));
    }
    return status;
}
コード例 #3
0
static void
as_uv_auth_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
{
	if (uv_is_closing((uv_handle_t*)stream)) {
		return;
	}

	as_event_command* cmd = as_uv_auth_get_command(stream->data);
		
	if (nread < 0) {
		uv_read_stop(stream);
		as_error err;
		as_error_update(&err, AEROSPIKE_ERR_ASYNC_CONNECTION, "Authenticate socket read failed: %zd", nread);
		as_event_socket_error(cmd, &err);
		return;
	}
	
	cmd->pos += nread;
	
	if (cmd->pos < cmd->len) {
		// Read not finished.
		return;
	}
	
	if (cmd->state == AS_ASYNC_STATE_AUTH_READ_HEADER) {
		as_event_set_auth_parse_header(cmd);
		
		if (cmd->len > cmd->capacity) {
			uv_read_stop(stream);
			as_error err;
			as_error_update(&err, AEROSPIKE_ERR_CLIENT, "Authenticate response size is corrupt: %u", cmd->auth_len);
			as_event_socket_error(cmd, &err);
			return;
		}
		return;
	}
	
	// Done reading authentication data.
	uv_read_stop(stream);
	
	// Parse authentication response.
	cmd->len -= cmd->auth_len;
	uint8_t code = cmd->buf[cmd->len + AS_ASYNC_AUTH_RETURN_CODE];
	
	if (code) {
		// Can't authenticate socket, so must close it.
		as_error err;
		as_error_update(&err, code, "Authentication failed: %s", as_error_string(code));
		as_event_socket_error(cmd, &err);
		return;
	}
	
	cmd->pos = 0;
	as_uv_command_write_start(cmd, stream);
}
コード例 #4
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);
			}
		}
コード例 #5
0
ファイル: as_admin.c プロジェクト: XeCycle/aerospike-client-c
static as_status
as_admin_read_blocks(as_error* err, int fd, uint64_t deadline_ms, as_admin_parse_fn parse_fn, as_vector* list)
{
    as_status status = AEROSPIKE_OK;
    uint8_t* buf = 0;
    size_t capacity = 0;

    while (true) {
        // Read header
        as_proto proto;
        status = as_socket_read_deadline(err, fd, (uint8_t*)&proto, sizeof(as_proto), deadline_ms);

        if (status) {
            break;
        }
        as_proto_swap_from_be(&proto);
        size_t size = proto.sz;

        if (size > 0) {
            // Prepare buffer
            if (size > capacity) {
                as_command_free(buf, capacity);
                capacity = size;
                buf = as_command_init(capacity);
            }

            // Read remaining message bytes in group
            status = as_socket_read_deadline(err, fd, buf, size, deadline_ms);

            if (status) {
                break;
            }

            status = parse_fn(err, buf, size, list);

            if (status != AEROSPIKE_OK) {
                if (status == AEROSPIKE_QUERY_END) {
                    status = AEROSPIKE_OK;
                }
                else {
                    as_error_set_message(err, status, as_error_string(status));
                }
                break;
            }
        }
    }
    as_command_free(buf, capacity);
    return status;
}
コード例 #6
0
ファイル: as_admin.c プロジェクト: XeCycle/aerospike-client-c
static as_status
as_admin_execute(aerospike* as, as_error* err, const as_policy_admin* policy, uint8_t* buffer, uint8_t* end)
{
    uint32_t timeout_ms = (policy)? policy->timeout : as->config.policies.admin.timeout;
    if (timeout_ms <= 0) {
        timeout_ms = DEFAULT_TIMEOUT;
    }
    uint64_t deadline_ms = as_socket_deadline(timeout_ms);
    as_cluster* cluster = as->cluster;
    as_node* node = as_node_get_random(cluster);

    if (! node) {
        return as_error_set_message(err, AEROSPIKE_ERR_CLIENT, "Failed to find server node.");
    }

    int fd;
    as_status status = as_node_get_connection(err, node, deadline_ms, &fd);

    if (status) {
        as_node_release(node);
        return status;
    }

    status = as_admin_send(err, fd, buffer, end, deadline_ms);

    if (status) {
        as_node_close_connection(node, fd);
        as_node_release(node);
        return status;
    }

    status = as_socket_read_deadline(err, fd, buffer, HEADER_SIZE, deadline_ms);

    if (status) {
        as_node_close_connection(node, fd);
        as_node_release(node);
        return status;
    }

    as_node_put_connection(node, fd);
    as_node_release(node);

    status = buffer[RESULT_CODE];

    if (status) {
        return as_error_set_message(err, status, as_error_string(status));
    }
    return status;
}
コード例 #7
0
ファイル: as_event.c プロジェクト: XeCycle/aerospike-client-c
bool
as_event_command_parse_result(as_event_command* cmd)
{
    as_msg* msg = (as_msg*)cmd->buf;
    as_msg_swap_header_from_be(msg);
    uint8_t* p = cmd->buf + sizeof(as_msg);
    as_status status = msg->result_code;

    switch (status) {
    case AEROSPIKE_OK: {
        as_record rec;

        if (msg->n_ops < 1000) {
            as_record_inita(&rec, msg->n_ops);
        }
        else {
            as_record_init(&rec, msg->n_ops);
        }

        rec.gen = msg->generation;
        rec.ttl = cf_server_void_time_to_ttl(msg->record_ttl);

        p = as_command_ignore_fields(p, msg->n_fields);
        as_command_parse_bins(&rec, p, msg->n_ops, cmd->deserialize);

        as_event_response_complete(cmd);
        ((as_async_record_command*)cmd)->listener(0, &rec, cmd->udata, cmd->event_loop);
        as_event_command_release(cmd);
        as_record_destroy(&rec);
        break;
    }

    case AEROSPIKE_ERR_UDF: {
        as_error err;
        as_command_parse_udf_failure(p, &err, msg, status);
        as_event_response_error(cmd, &err);
        break;
    }

    default: {
        as_error err;
        as_error_set_message(&err, status, as_error_string(status));
        as_event_response_error(cmd, &err);
        break;
    }
    }
    return true;
}
コード例 #8
0
ファイル: as_event.c プロジェクト: XeCycle/aerospike-client-c
bool
as_event_command_parse_header(as_event_command* cmd)
{
    as_msg* msg = (as_msg*)cmd->buf;

    if (msg->result_code == AEROSPIKE_OK) {
        as_event_response_complete(cmd);
        ((as_async_write_command*)cmd)->listener(0, cmd->udata, cmd->event_loop);
        as_event_command_release(cmd);
    }
    else {
        as_error err;
        as_error_set_message(&err, msg->result_code, as_error_string(msg->result_code));
        as_event_response_error(cmd, &err);
    }
    return true;
}
コード例 #9
0
static bool
as_scan_parse_records_async(as_event_command* cmd)
{
	as_error err;
	as_event_executor* executor = cmd->udata;  // udata is overloaded to contain executor.
	uint8_t* p = cmd->buf;
	uint8_t* end = p + cmd->len;
	
	while (p < end) {
		as_msg* msg = (as_msg*)p;
		as_msg_swap_header_from_be(msg);
		
		if (msg->result_code) {
			// Special case - if we scan a set name that doesn't exist on a
			// node, it will return "not found".
			if (msg->result_code == AEROSPIKE_ERR_RECORD_NOT_FOUND) {
				as_event_query_complete(cmd);
				return true;
			}
			as_error_set_message(&err, msg->result_code, as_error_string(msg->result_code));
			as_event_response_error(cmd, &err);
			return true;
		}
		p += sizeof(as_msg);
		
		if (msg->info3 & AS_MSG_INFO3_LAST) {
			as_event_query_complete(cmd);
			return true;
		}
		
		if (! executor->valid) {
			as_error_set_message(&err, AEROSPIKE_ERR_CLIENT_ABORT, "");
			as_event_response_error(cmd, &err);
			return true;
		}

		if (as_scan_parse_record_async(cmd, &p, msg, &err) != AEROSPIKE_OK) {
			as_event_response_error(cmd, &err);
			return true;
		}
	}
	return false;
}
コード例 #10
0
ファイル: as_event.c プロジェクト: XeCycle/aerospike-client-c
bool
as_event_command_parse_success_failure(as_event_command* cmd)
{
    as_msg* msg = (as_msg*)cmd->buf;
    as_msg_swap_header_from_be(msg);
    uint8_t* p = cmd->buf + sizeof(as_msg);
    as_status status = msg->result_code;

    switch (status) {
    case AEROSPIKE_OK: {
        as_error err;
        as_val* val = 0;
        status = as_command_parse_success_failure_bins(&p, &err, msg, &val);

        if (status == AEROSPIKE_OK) {
            as_event_response_complete(cmd);
            ((as_async_value_command*)cmd)->listener(0, val, cmd->udata, cmd->event_loop);
            as_event_command_release(cmd);
            as_val_destroy(val);
        }
        else {
            as_event_response_error(cmd, &err);
        }
        break;
    }

    case AEROSPIKE_ERR_UDF: {
        as_error err;
        as_command_parse_udf_failure(p, &err, msg, status);
        as_event_response_error(cmd, &err);
        break;
    }

    default: {
        as_error err;
        as_error_set_message(&err, status, as_error_string(status));
        as_event_response_error(cmd, &err);
        break;
    }
    }
    return true;
}
コード例 #11
0
as_status
as_command_parse_header(as_error* err, int fd, uint64_t deadline_ms, void* user_data)
{
    // Read header
    as_proto_msg* msg = user_data;
    as_status status = as_socket_read_deadline(err, fd, (uint8_t*)msg, sizeof(as_proto_msg), deadline_ms);

    if (status) {
        return status;
    }

    // Ensure that there is no data left to read.
    as_proto_swap_from_be(&msg->proto);
    as_msg_swap_header_from_be(&msg->m);
    size_t size = msg->proto.sz  - msg->m.header_sz;

    if (size > 0) {
        as_log_warn("Unexpected data received from socket after a write: fd=%d size=%zu", fd, size);

        // Verify size is not corrupted.
        if (size > 100000) {
            // The socket will be closed on this error, so we don't have to worry about emptying it.
            return as_error_update(err, AEROSPIKE_ERR_CLIENT,
                                   "Unexpected data received from socket after a write: fd=%d size=%zu", fd, size);
        }

        // Empty socket.
        uint8_t* buf = cf_malloc(size);
        status = as_socket_read_deadline(err, fd, buf, size, deadline_ms);
        cf_free(buf);

        if (status) {
            return status;
        }
    }

    if (msg->m.result_code) {
        return as_error_set_message(err, msg->m.result_code, as_error_string(msg->m.result_code));
    }
    return msg->m.result_code;
}
コード例 #12
0
static as_status
as_scan_parse_records(uint8_t* buf, size_t size, as_scan_task* task, as_error* err)
{
	uint8_t* p = buf;
	uint8_t* end = buf + size;
	as_status status;
	
	while (p < end) {
		as_msg* msg = (as_msg*)p;
		as_msg_swap_header_from_be(msg);
		
		if (msg->result_code) {
			// Special case - if we scan a set name that doesn't exist on a
			// node, it will return "not found" - we unify this with the
			// case where OK is returned and no callbacks were made. [AKG]
			// We are sending "no more records back" to the caller which will
			// send OK to the main worker thread.
			if (msg->result_code == AEROSPIKE_ERR_RECORD_NOT_FOUND) {
				return AEROSPIKE_NO_MORE_RECORDS;
			}
			return as_error_set_message(err, msg->result_code, as_error_string(msg->result_code));
		}
		p += sizeof(as_msg);
		
		if (msg->info3 & AS_MSG_INFO3_LAST) {
			return AEROSPIKE_NO_MORE_RECORDS;
		}
		
		status = as_scan_parse_record(&p, msg, task);
		
		if (status != AEROSPIKE_OK) {
			return status;
		}
		
		if (ck_pr_load_32(task->error_mutex)) {
			err->code = AEROSPIKE_ERR_SCAN_ABORTED;
			return err->code;
		}
	}
	return AEROSPIKE_OK;
}
コード例 #13
0
static as_status
as_command_parse_udf_error(as_error* err, as_status status, as_val* val)
{
    if (val && val->type == AS_STRING) {
        char* begin = ((as_string*)val)->value;
        char* p = strrchr(begin, ':');

        if (p) {
            p = strrchr(++p, ':');

            if (p) {
                int code = atoi(++p);

                if (code > 0) {
                    return as_error_set_message(err, code, begin);
                }
            }
        }
        return as_error_set_message(err, status, begin);
    }
    return as_error_set_message(err, status, as_error_string(status));
}
コード例 #14
0
ファイル: as_event.c プロジェクト: XeCycle/aerospike-client-c
void
as_event_timeout(as_event_command* cmd)
{
    if (cmd->pipe_listener != NULL) {
        as_pipe_timeout(cmd);
        return;
    }

    as_error err;
    as_error_set_message(&err, AEROSPIKE_ERR_TIMEOUT, as_error_string(AEROSPIKE_ERR_TIMEOUT));

    // Command has timed out.
    // Stop watcher if it has been initialized.
    if (cmd->state > AS_ASYNC_STATE_UNREGISTERED) {
        as_event_stop_watcher(cmd, cmd->conn);
    }

    // Assume timer has already been stopped.
    // Do not put connection back in pool.
    as_event_release_async_connection(cmd);
    as_event_error_callback(cmd, &err);
}
コード例 #15
0
static void
as_ev_parse_authentication(as_event_command* cmd)
{
	if (cmd->state == AS_ASYNC_STATE_AUTH_READ_HEADER) {
		// Read response length
		if (! as_ev_read(cmd)) {
			return;
		}
		as_event_set_auth_parse_header(cmd);

		if (cmd->len > cmd->capacity) {
			as_error err;
			as_error_update(&err, AEROSPIKE_ERR_CLIENT, "Authenticate response size is corrupt: %u", cmd->auth_len);
			as_event_socket_error(cmd, &err);
			return;
		}
	}
	
	if (! as_ev_read(cmd)) {
		return;
	}
	
	// Parse authentication response.
	cmd->len -= cmd->auth_len;
	uint8_t code = cmd->buf[cmd->len + AS_ASYNC_AUTH_RETURN_CODE];
	
	if (code) {
		// Can't authenticate socket, so must close it.
		as_error err;
		as_error_update(&err, code, "Authentication failed: %s", as_error_string(code));
		as_event_socket_error(cmd, &err);
		return;
	}
	
	cmd->pos = 0;
	as_ev_command_write_start(cmd);
}
コード例 #16
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;
}
コード例 #17
0
as_status
as_command_parse_success_failure(as_error* err, int fd, uint64_t deadline_ms, void* user_data)
{
    // Read header
    as_proto_msg msg;
    as_status status = as_socket_read_deadline(err, fd, (uint8_t*)&msg, sizeof(as_proto_msg), deadline_ms);

    if (status) {
        return status;
    }

    as_proto_swap_from_be(&msg.proto);
    as_msg_swap_header_from_be(&msg.m);
    size_t size = msg.proto.sz  - msg.m.header_sz;
    uint8_t* buf = 0;

    if (size > 0) {
        // Read remaining message bytes.
        buf = as_command_init(size);
        status = as_socket_read_deadline(err, fd, buf, size, deadline_ms);

        if (status) {
            as_command_free(buf, size);
            return status;
        }
    }

    as_val** val = user_data;

    // Parse result code and record.
    status = msg.m.result_code;

    switch (status) {
    case AEROSPIKE_OK: {
        uint8_t* p = buf;
        status = as_command_parse_success_failure_bins(&p, err, &msg.m, val);

        if (status != AEROSPIKE_OK) {
            if (val) {
                *val = 0;
            }
        }
        break;
    }

    case AEROSPIKE_ERR_UDF: {
        status = as_command_parse_udf_failure(buf, err, &msg.m, status);
        if (val) {
            *val = 0;
        }
        break;
    }

    default:
        as_error_set_message(err, status, as_error_string(status));
        if (val) {
            *val = 0;
        }
        break;
    }
    as_command_free(buf, size);
    return status;
}
コード例 #18
0
as_status
as_command_parse_result(as_error* err, int fd, uint64_t deadline_ms, void* user_data)
{
    // Read header
    as_proto_msg msg;
    as_status status = as_socket_read_deadline(err, fd, (uint8_t*)&msg, sizeof(as_proto_msg), deadline_ms);

    if (status) {
        return status;
    }

    as_proto_swap_from_be(&msg.proto);
    as_msg_swap_header_from_be(&msg.m);
    size_t size = msg.proto.sz  - msg.m.header_sz;
    uint8_t* buf = 0;

    if (size > 0) {
        // Read remaining message bytes.
        buf = as_command_init(size);
        status = as_socket_read_deadline(err, fd, buf, size, deadline_ms);

        if (status) {
            as_command_free(buf, size);
            return status;
        }
    }

    // Parse result code and record.
    status = msg.m.result_code;
    as_command_parse_result_data* data = user_data;

    switch (status) {
    case AEROSPIKE_OK: {
        if (data->record) {
            as_record* rec = *data->record;

            if (rec) {
                if (msg.m.n_ops > rec->bins.capacity) {
                    if (rec->bins._free) {
                        free(rec->bins.entries);
                    }
                    rec->bins.capacity = msg.m.n_ops;
                    rec->bins.size = 0;
                    rec->bins.entries = malloc(sizeof(as_bin) * msg.m.n_ops);
                    rec->bins._free = true;
                }
            }
            else {
                rec = as_record_new(msg.m.n_ops);
                *data->record = rec;
            }
            rec->gen = msg.m.generation;
            rec->ttl = cf_server_void_time_to_ttl(msg.m.record_ttl);

            uint8_t* p = as_command_ignore_fields(buf, msg.m.n_fields);
            as_command_parse_bins(rec, p, msg.m.n_ops, data->deserialize);
        }
        break;
    }

    case AEROSPIKE_ERR_UDF: {
        status = as_command_parse_udf_failure(buf, err, &msg.m, status);
        break;
    }

    default:
        as_error_set_message(err, status, as_error_string(status));
        break;
    }
    as_command_free(buf, size);
    return status;
}