コード例 #1
0
ファイル: as_event.c プロジェクト: XeCycle/aerospike-client-c
void
as_event_executor_complete(as_event_command* cmd)
{
    as_event_response_complete(cmd);

    as_event_executor* executor = cmd->udata;
    pthread_mutex_lock(&executor->lock);
    bool notify = executor->valid;
    executor->count++;
    bool complete = executor->count == executor->max;
    int next = executor->count + executor->max_concurrent - 1;
    bool start_new_command = next < executor->max && executor->valid;
    pthread_mutex_unlock(&executor->lock);

    if (complete) {
        // All commands completed.
        if (notify) {
            executor->complete_fn(executor, 0);
        }
        as_event_executor_destroy(executor);
    }
    else {
        // Determine if a new command needs to be started.
        if (start_new_command) {
            as_error err;
            as_status status = as_event_command_execute(executor->commands[next], &err);

            if (status != AEROSPIKE_OK) {
                as_event_executor_error(executor, &err, next);
            }
        }
    }
    as_event_command_release(cmd);
}
コード例 #2
0
static as_status
as_scan_async(
	aerospike* as, as_error* err, const as_policy_scan* policy, const as_scan* scan, uint64_t* scan_id,
	as_async_scan_listener listener, void* udata, as_event_loop* event_loop,
	as_node** nodes, uint32_t n_nodes
	)
{
	if (! policy) {
		policy = &as->config.policies.scan;
	}
	
	// Assign task id.
	uint64_t task_id;
	if (scan_id) {
		if (*scan_id == 0) {
			*scan_id = as_random_get_uint64();
		}
		task_id = *scan_id;
	}
	else {
		task_id = as_random_get_uint64();
	}
	
	bool daisy_chain = ! (scan->concurrent || n_nodes == 1);

	// Scan will be split up into a command for each node.
	// Allocate scan data shared by each command.
	as_async_scan_executor* executor = cf_malloc(sizeof(as_async_scan_executor));
	as_event_executor* exec = &executor->executor;
	pthread_mutex_init(&exec->lock, NULL);
	exec->commands = cf_malloc(sizeof(as_event_command*) * n_nodes);
	exec->event_loop = as_event_assign(event_loop);
	exec->complete_fn = as_scan_complete_async;
	exec->udata = udata;
	exec->err = NULL;
	exec->ns = NULL;
	exec->cluster_key = 0;
	exec->max_concurrent = daisy_chain ? 1 : n_nodes;
	exec->max = n_nodes;
	exec->count = 0;
	exec->queued = 0;
	exec->notify = true;
	exec->valid = true;
	executor->listener = listener;

	// Create scan command buffer.
	as_buffer argbuffer;
	uint16_t n_fields = 0;
	uint32_t predexp_sz = 0;
	size_t size = as_scan_command_size(scan, &n_fields, &argbuffer, &predexp_sz);
	uint8_t* cmd_buf = as_command_buffer_init(size);
	size = as_scan_command_init(cmd_buf, policy, scan, task_id, n_fields, &argbuffer, predexp_sz);
	
	// Allocate enough memory to cover, then, round up memory size in 8KB increments to allow socket
	// read to reuse buffer.
	size_t s = (sizeof(as_async_scan_command) + size + AS_AUTHENTICATION_MAX_SIZE + 8191) & ~8191;

	// Create all scan commands.
	for (uint32_t i = 0; i < n_nodes; i++) {
		as_event_command* cmd = cf_malloc(s);
		cmd->total_deadline = policy->base.total_timeout;
		cmd->socket_timeout = policy->base.socket_timeout;
		cmd->max_retries = policy->base.max_retries;
		cmd->iteration = 0;
		cmd->replica = AS_POLICY_REPLICA_MASTER;
		cmd->event_loop = exec->event_loop;
		cmd->cluster = as->cluster;
		cmd->node = nodes[i];
		cmd->ns = NULL;
		cmd->partition = NULL;
		cmd->udata = executor;  // Overload udata to be the executor.
		cmd->parse_results = as_scan_parse_records_async;
		cmd->pipe_listener = NULL;
		cmd->buf = ((as_async_scan_command*)cmd)->space;
		cmd->write_len = (uint32_t)size;
		cmd->read_capacity = (uint32_t)(s - size - sizeof(as_async_scan_command));
		cmd->type = AS_ASYNC_TYPE_SCAN;
		cmd->state = AS_ASYNC_STATE_UNREGISTERED;
		cmd->flags = AS_ASYNC_FLAGS_MASTER;
		cmd->flags2 = scan->deserialize_list_map ? AS_ASYNC_FLAGS2_DESERIALIZE : 0;
		memcpy(cmd->buf, cmd_buf, size);
		exec->commands[i] = cmd;
	}

	// Free command buffer.
	as_command_buffer_free(cmd_buf, size);

	if (policy->fail_on_cluster_change && (nodes[0]->features & AS_FEATURES_CLUSTER_STABLE)) {
		// Verify migrations are not in progress.
		return as_query_validate_begin_async(exec, scan->ns, err);
	}

	// Run scan commands.
	for (uint32_t i = 0; i < exec->max_concurrent; i++) {
		exec->queued++;
		as_event_command* cmd = exec->commands[i];
		as_status status = as_event_command_execute(cmd, err);

		if (status != AEROSPIKE_OK) {
			as_event_executor_cancel(exec, i);
			return status;
		}
	}
	return AEROSPIKE_OK;
}