Esempio n. 1
0
static bool
proxy_client_worker_next_reply(struct proxy_client_dsync_worker *worker,
                               const char *line)
{
    const struct proxy_client_request *requests;
    struct proxy_client_request request;
    bool ret = TRUE;

    i_assert(worker->msg_get_data.input == NULL);

    if (aqueue_count(worker->request_queue) == 0) {
        i_error("Unexpected reply from server: %s", line);
        proxy_client_fail(worker);
        return FALSE;
    }

    requests = array_idx(&worker->request_array, 0);
    request = requests[aqueue_idx(worker->request_queue, 0)];
    aqueue_delete_tail(worker->request_queue);

    switch (request.type) {
    case PROXY_CLIENT_REQUEST_TYPE_COPY:
        ret = proxy_client_worker_next_copy(worker, &request, line);
        break;
    case PROXY_CLIENT_REQUEST_TYPE_GET:
        ret = proxy_client_worker_next_msg_get(worker, &request, line);
        break;
    case PROXY_CLIENT_REQUEST_TYPE_FINISH:
        proxy_client_worker_next_finish(worker, &request, line);
        break;
    }
    return ret;
}
Esempio n. 2
0
static void worker_connection_disconnect(struct worker_connection *conn)
{
	unsigned int i, count = aqueue_count(conn->request_queue);

	if (conn->fd != -1) {
		io_remove(&conn->io);
		i_stream_destroy(&conn->input);
		o_stream_destroy(&conn->output);

		if (close(conn->fd) < 0)
			i_error("close(%s) failed: %m", conn->socket_path);
		conn->fd = -1;
	}

	/* cancel any pending requests */
	if (count > 0) {
		i_error("Indexer worker disconnected, "
			"discarding %u requests for %s",
			count, conn->request_username);
	}

	/* conn->callback() can try to destroy us */
	conn->refcount++;
	for (i = 0; i < count; i++) {
		void *const *contextp =
			array_idx(&conn->request_contexts,
				  aqueue_idx(conn->request_queue, 0));
		void *context = *contextp;

		aqueue_delete_tail(conn->request_queue);
		conn->callback(-1, context);
	}
	i_free_and_null(conn->request_username);
	worker_connection_unref(conn);
}
void auth_request_handler_flush_failures(bool flush_all)
{
	struct auth_request **auth_requests, *auth_request;
	unsigned int i, count;
	time_t diff;

	count = aqueue_count(auth_failures);
	if (count == 0) {
		if (to_auth_failures != NULL)
			timeout_remove(&to_auth_failures);
		return;
	}

	auth_requests = array_idx_modifiable(&auth_failures_arr, 0);
	for (i = 0; i < count; i++) {
		auth_request = auth_requests[aqueue_idx(auth_failures, 0)];

		/* FIXME: assumess that failure_delay is always the same. */
		diff = ioloop_time - auth_request->last_access;
		if (diff < (time_t)auth_request->set->failure_delay &&
		    !flush_all)
			break;

		aqueue_delete_tail(auth_failures);

		i_assert(auth_request->state == AUTH_REQUEST_STATE_FINISHED);
		auth_request_handler_reply(auth_request,
					   AUTH_CLIENT_RESULT_FAILURE,
					   &uchar_nul, 0);
		auth_request_unref(&auth_request);
	}
}
Esempio n. 4
0
static
void ldap_connection_abort_request(struct ldap_op_queue_entry *req)
{
	struct ldap_result res;

	/* too bad */
	if (req->to_abort != NULL)
		timeout_remove(&req->to_abort);
	if (req->msgid > -1)
		ldap_abandon_ext(req->conn->conn, req->msgid, NULL, NULL);

	memset(&res, 0, sizeof(res));
	res.openldap_ret = LDAP_TIMEOUT;
	res.error_string = "Aborting LDAP request after timeout";
	if (req->result_callback != NULL)
		req->result_callback(&res, req->result_callback_ctx);

	unsigned int n = aqueue_count(req->conn->request_queue);
	for (unsigned int i = 0; i < n; i++) {
		struct ldap_op_queue_entry *const *reqp =
			array_idx(&(req->conn->request_array),
				  aqueue_idx(req->conn->request_queue, i));
		if (req == *reqp) {
			aqueue_delete(req->conn->request_queue, i);
			ldap_connection_request_destroy(&req);
			return;
		}
	}
	i_unreached();
}
Esempio n. 5
0
static int
worker_connection_input_line(struct worker_connection *conn, const char *line)
{
	void *const *contextp, *context;
	int percentage;

	if (aqueue_count(conn->request_queue) == 0) {
		i_error("Input from worker without pending requests: %s", line);
		return -1;
	}

	if (str_to_int(line, &percentage) < 0 ||
	    percentage < -1 || percentage > 100) {
		i_error("Invalid input from worker: %s", line);
		return -1;
	}

	contextp = array_idx(&conn->request_contexts,
			     aqueue_idx(conn->request_queue, 0));
	context = *contextp;
	if (percentage < 0 || percentage == 100) {
		/* the request is finished */
		aqueue_delete_tail(conn->request_queue);
		if (aqueue_count(conn->request_queue) == 0)
			i_free_and_null(conn->request_username);
	}

	conn->callback(percentage, context);
	return 0;
}
Esempio n. 6
0
void ldap_connection_kill(struct ldap_connection *conn)
{
	if (conn->io != NULL)
		io_remove_closed(&(conn->io));
	if (conn->to_disconnect != NULL)
		timeout_remove(&(conn->to_disconnect));
	if (conn->to_reconnect != NULL)
		timeout_remove(&(conn->to_reconnect));
	if (conn->request_queue != NULL) {
		unsigned int n = aqueue_count(conn->request_queue);

		for (unsigned int i = 0; i < n; i++) {
			struct ldap_op_queue_entry *const *reqp =
				array_idx(&(conn->request_array),
					  aqueue_idx(conn->request_queue, i));
			if ((*reqp)->msgid > -1)
				ldap_abandon_ext(conn->conn, (*reqp)->msgid, NULL, NULL);
			(*reqp)->msgid = -1;
		}
	}
	if (conn->conn != NULL) {
		ldap_unbind_ext(conn->conn, NULL, NULL);
		ldap_memfree(conn->scred);
	}
	conn->conn = NULL;
	conn->state = LDAP_STATE_DISCONNECT;
}
Esempio n. 7
0
static
void ldap_connection_send_next(struct ldap_connection *conn)
{
	unsigned int i = 0, n;
	struct ldap_op_queue_entry *req;

	if (conn->to_reconnect != NULL)
		timeout_remove(&(conn->to_reconnect));

	if (conn->state == LDAP_STATE_DISCONNECT) {
		if (ldap_connection_connect(conn) == -1)
			conn->to_reconnect = timeout_add(1000, ldap_connection_send_next, conn);
		return;
	}

	if (conn->state != LDAP_STATE_CONNECT) {
		return;
	}

	if (conn->pending > 10) return; /* try again later */

	req = NULL;
	/* get next request */
	n = aqueue_count(conn->request_queue);

	for(i=0; i < n; i++) {
		struct ldap_op_queue_entry *const *reqp =
			array_idx(&(conn->request_array),
				  aqueue_idx(conn->request_queue, i));
		if ((*reqp)->msgid > -1)
			break;
		req = *reqp;
	}

	i--;

	/* nothing to actually send */
	if (req == NULL) return;

	i_assert(req->msgid == -1);

	const char *error;
	int ret;
	if ((ret = req->send_request_cb(conn, req, &error)) != LDAP_SUCCESS) {
		/* did not succeed */
		struct ldap_result res;

		memset(&res, 0, sizeof(res));
		res.openldap_ret = ret;
		if (req->result_callback != NULL)
			req->result_callback(&res, req->result_callback_ctx);

		ldap_connection_request_destroy(&req);
		aqueue_delete(conn->request_queue, i);
	} else conn->pending++;
}
Esempio n. 8
0
static bool aqueue_is_ok(struct aqueue *aqueue, unsigned int deleted_n)
{
	const unsigned int *p;
	unsigned int n, i, count;

	count = aqueue_count(aqueue);
	for (i = 0, n = 1; i < count; i++, n++) {
		p = array_idx_i(aqueue->arr, aqueue_idx(aqueue, i));
		if (i == deleted_n)
			n++;
		if (*p != n)
			return FALSE;
	}
	return TRUE;
}
Esempio n. 9
0
static struct ldap_op_queue_entry *
ldap_connection_find_req_by_msgid(struct ldap_connection *conn, int msgid,
				  unsigned int *idx_r)
{
	unsigned int i, n = aqueue_count(conn->request_queue);
	for (i = 0; i < n; i++) {
		struct ldap_op_queue_entry *const *reqp =
			array_idx(&(conn->request_array),
				  aqueue_idx(conn->request_queue, i));
		if ((*reqp)->msgid == msgid) {
			*idx_r = i;
			return *reqp;
		}
	}
	return NULL;
}
Esempio n. 10
0
void ldap_connection_deinit(struct ldap_connection **_conn)
{
	struct ldap_connection *conn = *_conn;

	*_conn = NULL;

	ldap_connection_kill(conn);

	unsigned int n = aqueue_count(conn->request_queue);
	for (unsigned int i = 0; i < n; i++) {
		struct ldap_op_queue_entry *const *reqp =
			array_idx(&(conn->request_array),
				  aqueue_idx(conn->request_queue, i));
		if ((*reqp)->to_abort != NULL)
			timeout_remove(&(*reqp)->to_abort);
	}
	pool_unref(&conn->pool);
}
Esempio n. 11
0
void ldap_connection_switch_ioloop(struct ldap_connection *conn)
{
	if (conn->io != NULL)
		conn->io = io_loop_move_io(&conn->io);
	if (conn->to_disconnect != NULL)
		conn->to_disconnect = io_loop_move_timeout(&conn->to_disconnect);
	if (conn->to_reconnect != NULL)
		conn->to_reconnect = io_loop_move_timeout(&conn->to_reconnect);
	unsigned int n = aqueue_count(conn->request_queue);

	for (unsigned int i = 0; i < n; i++) {
		struct ldap_op_queue_entry *const *reqp =
			array_idx(&(conn->request_array),
				  aqueue_idx(conn->request_queue, i));
		if ((*reqp)->to_abort != NULL)
			(*reqp)->to_abort = io_loop_move_timeout(&((*reqp)->to_abort));
	}
}
static bool
dsync_mailbox_tree_bfs_iter_next(struct dsync_mailbox_tree_bfs_iter *iter,
				 struct dsync_mailbox_node **node_r)
{
	struct dsync_mailbox_node *const *nodep;

	if (iter->cur == NULL) {
		if (aqueue_count(iter->queue) == 0)
			return FALSE;
		nodep = array_idx(&iter->queue_arr, aqueue_idx(iter->queue, 0));
		iter->cur = *nodep;
		aqueue_delete_tail(iter->queue);
	}
	*node_r = iter->cur;

	if (iter->cur->first_child != NULL)
		aqueue_append(iter->queue, &iter->cur->first_child);
	iter->cur = iter->cur->next;
	return TRUE;
}
Esempio n. 13
0
void aqueue_delete(struct aqueue *aqueue, unsigned int n)
{
	unsigned int idx, count = aqueue_count(aqueue);

	i_assert(n < count);

	aqueue->full = FALSE;
	if (n == 0) {
		/* optimized deletion from tail */
		aqueue->tail = (aqueue->tail + 1) % aqueue->area_size;
		return;
	}
	if (n == count-1) {
		/* optimized deletion from head */
		aqueue->head = (aqueue->head + aqueue->area_size - 1) %
			aqueue->area_size;
		return;
	}

	idx = aqueue_idx(aqueue, n);
	if ((n < count/2 || idx > aqueue->head) && idx > aqueue->tail) {
		/* move tail forward.
		   ..tail##idx##head.. or ##head..tail##idx## */
		array_copy(aqueue->arr, aqueue->tail + 1,
			   aqueue->arr, aqueue->tail,
			   idx - aqueue->tail);
		aqueue->tail++;
		i_assert(aqueue->tail < aqueue->area_size);
	} else {
		/* move head backward.
		   ..tail##idx##head.. or ##idx##head..tail## */
		i_assert(idx < aqueue->head);
		array_copy(aqueue->arr, idx,
			   aqueue->arr, idx + 1,
			   aqueue->head - idx);
		aqueue->head = (aqueue->head + aqueue->area_size - 1) %
			aqueue->area_size;
	}
	i_assert(aqueue->head < aqueue->area_size &&
		 aqueue->head != aqueue->tail);
}
Esempio n. 14
0
static
void ldap_connection_abort_all_requests(struct ldap_connection *conn)
{
	struct ldap_result res;
	memset(&res, 0, sizeof(res));
	res.openldap_ret = LDAP_TIMEOUT;
	res.error_string = "Aborting LDAP requests due to failure";

	unsigned int n = aqueue_count(conn->request_queue);
	for (unsigned int i = 0; i < n; i++) {
		struct ldap_op_queue_entry **reqp =
			array_idx_modifiable(&(conn->request_array),
		aqueue_idx(conn->request_queue, i));
		if ((*reqp)->to_abort != NULL)
			timeout_remove(&(*reqp)->to_abort);
		if ((*reqp)->result_callback != NULL)
			(*reqp)->result_callback(&res, (*reqp)->result_callback_ctx);
		ldap_connection_request_destroy(reqp);
	}
	aqueue_clear(conn->request_queue);
}