Пример #1
0
static int32_t
s1_msg_process_fn(qb_ipcs_connection_t * c, void *data, size_t size)
{
	struct qb_ipc_request_header *hdr;
	struct my_req *req_pt;
	struct qb_ipc_response_header response;
	ssize_t res;
	struct iovec iov[2];
	char resp[100];
	int32_t sl;
	int32_t send_ten_events = QB_FALSE;

	hdr = (struct qb_ipc_request_header *)data;
	if (hdr->id == (QB_IPC_MSG_USER_START + 1)) {
		return 0;
	}

	req_pt = (struct my_req *)data;
	qb_log(LOG_DEBUG, "msg received (id:%d, size:%d, data:%s)",
	       req_pt->hdr.id, req_pt->hdr.size, req_pt->message);

	if (strcmp(req_pt->message, "kill") == 0) {
		exit(0);
	}
	response.size = sizeof(struct qb_ipc_response_header);
	response.id = 13;
	response.error = 0;

	sl = snprintf(resp, 100, "ACK %zd bytes", size) + 1;
	iov[0].iov_len = sizeof(response);
	iov[0].iov_base = &response;
	iov[1].iov_len = sl;
	iov[1].iov_base = resp;
	response.size += sl;

	send_ten_events = (strcmp(req_pt->message, "events") == 0);

	if (use_events && !send_ten_events) {
		res = qb_ipcs_event_sendv(c, iov, 2);
	} else {
		res = qb_ipcs_response_sendv(c, iov, 2);
	}
	if (res < 0) {
		errno = - res;
		qb_perror(LOG_ERR, "qb_ipcs_response_send");
	}
	if (send_ten_events) {
		int32_t i;
		qb_log(LOG_INFO, "request to send 10 events");
		for (i = 0; i < 10; i++) {
			res = qb_ipcs_event_sendv(c, iov, 2);
			qb_log(LOG_INFO, "sent event %d res:%d", i, res);
		}
	}
	return 0;
}
Пример #2
0
ssize_t
crm_ipcs_send(qb_ipcs_connection_t *c, xmlNode *message, enum ipcs_send_flags flags)
{
    int rc;
    int lpc = 0;
    struct iovec iov[2];
    static uint32_t id = 0;
    const char *type = "Response";
    struct qb_ipc_response_header header;
    char *buffer = dump_xml_unformatted(message);

    iov[0].iov_len = sizeof(struct qb_ipc_response_header);
    iov[0].iov_base = &header;
    iov[1].iov_len = 1 + strlen(buffer);
    iov[1].iov_base = buffer;

    header.id = id++; /* We don't really use it, but doesn't hurt to set one */
    header.error = 0; /* unused */
    header.size = iov[0].iov_len + iov[1].iov_len;

    do {
        if(flags & ipcs_send_event) {
            rc = qb_ipcs_event_sendv(c, iov, 2);
            type = "Event";
            
        } else {
            rc = qb_ipcs_response_sendv(c, iov, 2);
        }

        if(rc != -EAGAIN) {
            break;
        } else if(lpc > 3 && (flags & ipcs_send_error)) {
            break;
        }

        crm_debug("Attempting resend %d of %s %d (%d bytes) to %p[%d]: %.120s",
                  ++lpc, type, header.id, header.size, c, crm_ipcs_client_pid(c), buffer);
        sleep(1);

        /* Only retry for important stuff, and even then only a limited amount for ipcs_send_error
         * Unless ipcs_send_info or ipcs_send_error is specified, we block by default
         */
    } while((flags & ipcs_send_info) == 0);

    if(rc < header.size) {
        do_crm_log((flags & ipcs_send_error)?LOG_ERR:LOG_INFO,
                   "%s %d failed, size=%d, to=%p[%d], rc=%d: %.120s",
                   type, header.id, header.size, c, crm_ipcs_client_pid(c), rc, buffer);
    } else {
        crm_trace("%s %d sent, %d bytes to %p: %.120s", type, header.id, rc, c, buffer);
    }
    free(buffer);
    return rc;
}
Пример #3
0
ssize_t
crm_ipcs_flush_events(crm_client_t * c)
{
    int sent = 0;
    ssize_t rc = 0;
    int queue_len = 0;

    if (c == NULL) {
        return pcmk_ok;

    } else if (c->event_timer) {
        /* There is already a timer, wait until it goes off */
        crm_trace("Timer active for %p - %d", c->ipcs, c->event_timer);
        return pcmk_ok;
    }

    queue_len = g_list_length(c->event_queue);
    while (c->event_queue && sent < 100) {
        struct crm_ipc_response_header *header = NULL;
        struct iovec *event = c->event_queue->data;

        rc = qb_ipcs_event_sendv(c->ipcs, event, 2);
        if (rc < 0) {
            break;
        }

        sent++;
        header = event[0].iov_base;
        if (header->size_compressed) {
            crm_trace("Event %d to %p[%d] (%zu compressed bytes) sent",
                      header->qb.id, c->ipcs, c->pid, rc);
        } else {
            crm_trace("Event %d to %p[%d] (%zu bytes) sent: %.120s",
                      header->qb.id, c->ipcs, c->pid, rc, (char *)(event[1].iov_base));
        }

        c->event_queue = g_list_remove(c->event_queue, event);
        free(event[0].iov_base);
        free(event[1].iov_base);
        free(event);
    }

    queue_len -= sent;
    if (sent > 0 || c->event_queue) {
        crm_trace("Sent %d events (%d remaining) for %p[%d]: %s (%zd)",
                  sent, queue_len, c->ipcs, c->pid, pcmk_strerror(rc < 0 ? rc : 0), rc);
    }

    if (c->event_queue) {
        if (queue_len % 100 == 0 && queue_len > 99) {
            crm_warn("Event queue for %p[%d] has grown to %d", c->ipcs, c->pid, queue_len);

        } else if (queue_len > 500) {
            crm_err("Evicting slow client %p[%d]: event queue reached %d entries",
                    c->ipcs, c->pid, queue_len);
            qb_ipcs_disconnect(c->ipcs);
            return rc;
        }

        c->event_timer = g_timeout_add(1000 + 100 * queue_len, crm_ipcs_flush_events_cb, c);
    }

    return rc;
}
Пример #4
0
ssize_t
crm_ipcs_send(qb_ipcs_connection_t *c, uint32_t request, xmlNode *message, enum crm_ipc_server_flags flags)
{
    int rc;
    int lpc = 0;
    int retries = 40;
    int level = LOG_CRIT;
    struct iovec iov[2];
    static uint32_t id = 1;
    const char *type = "Response";
    struct qb_ipc_response_header header;
    char *buffer = dump_xml_unformatted(message);
    struct timespec delay = { 0, 250000000 }; /* 250ms */

    memset(&iov, 0, 2 * sizeof(struct iovec));
    iov[0].iov_len = sizeof(struct qb_ipc_response_header);
    iov[0].iov_base = &header;
    iov[1].iov_len = 1 + strlen(buffer);
    iov[1].iov_base = buffer;

    if(flags & crm_ipc_server_event) {
        header.id = id++;    /* We don't really use it, but doesn't hurt to set one */
    } else {
        CRM_LOG_ASSERT (request != 0);
        header.id = request; /* Replying to a specific request */
    }

    header.error = 0; /* unused */
    header.size = iov[0].iov_len + iov[1].iov_len;

    if(flags & crm_ipc_server_error) {
        retries = 20;
        level = LOG_ERR;

    } else if(flags & crm_ipc_server_info) {
        retries = 10;
        level = LOG_INFO;
    }

    while(lpc < retries) {
        if(flags & crm_ipc_server_event) {
            type = "Event";
            rc = qb_ipcs_event_sendv(c, iov, 2);
            if(rc == -EPIPE || rc == -ENOTCONN) {
                crm_trace("Client %p disconnected", c);
                level = LOG_INFO;
            }
            
        } else {
            rc = qb_ipcs_response_sendv(c, iov, 2);
        }

        if(rc != -EAGAIN) {
            break;
        }

        lpc++;
        crm_debug("Attempting resend %d of %s %d (%d bytes) to %p[%d]: %.120s",
                  lpc, type, header.id, header.size, c, crm_ipcs_client_pid(c), buffer);
        nanosleep(&delay, NULL);
    }

    if(rc < header.size) {
        struct qb_ipcs_connection_stats_2 *stats = qb_ipcs_connection_stats_get_2(c, 0);
        do_crm_log(level,
                   "%s %d failed, size=%d, to=%p[%d], queue=%d, rc=%d: %.120s",
                   type, header.id, header.size, c, stats->client_pid, stats->event_q_length, rc, buffer);
        free(stats);

    } else {
        crm_trace("%s %d sent, %d bytes to %p[%d]: %.120s", type, header.id, rc,
                  c, crm_ipcs_client_pid(c), buffer);
    }
    free(buffer);
    return rc;
}
Пример #5
0
ssize_t
crm_ipcs_flush_events(crm_client_t * c)
{
    ssize_t rc = 0;
    unsigned int sent = 0;
    unsigned int queue_len = 0;

    if (c == NULL) {
        return pcmk_ok;

    } else if (c->event_timer) {
        /* There is already a timer, wait until it goes off */
        crm_trace("Timer active for %p - %d", c->ipcs, c->event_timer);
        return pcmk_ok;
    }

    queue_len = g_list_length(c->event_queue);
    while (c->event_queue && sent < 100) {
        struct crm_ipc_response_header *header = NULL;
        struct iovec *event = c->event_queue->data;

        rc = qb_ipcs_event_sendv(c->ipcs, event, 2);
        if (rc < 0) {
            break;
        }

        sent++;
        header = event[0].iov_base;
        if (header->size_compressed) {
            crm_trace("Event %d to %p[%d] (%lld compressed bytes) sent",
                      header->qb.id, c->ipcs, c->pid, (long long) rc);
        } else {
            crm_trace("Event %d to %p[%d] (%lld bytes) sent: %.120s",
                      header->qb.id, c->ipcs, c->pid, (long long) rc,
                      (char *) (event[1].iov_base));
        }

        c->event_queue = g_list_remove(c->event_queue, event);
        free(event[0].iov_base);
        free(event[1].iov_base);
        free(event);
    }

    queue_len -= sent;
    if (sent > 0 || queue_len) {
        crm_trace("Sent %d events (%d remaining) for %p[%d]: %s (%lld)",
                  sent, queue_len, c->ipcs, c->pid,
                  pcmk_strerror(rc < 0 ? rc : 0), (long long) rc);
    }

    if (queue_len) {

        /* Allow clients to briefly fall behind on processing incoming messages,
         * but drop completely unresponsive clients so the connection doesn't
         * consume resources indefinitely.
         */
        if (queue_len > QB_MAX(c->queue_max, PCMK_IPC_DEFAULT_QUEUE_MAX)) {
            if ((c->queue_backlog <= 1) || (queue_len < c->queue_backlog)) {
                /* Don't evict for a new or shrinking backlog */
                crm_warn("Client with process ID %u has a backlog of %u messages "
                         CRM_XS " %p", c->pid, queue_len, c->ipcs);
            } else {
                crm_err("Evicting client with process ID %u due to backlog of %u messages "
                         CRM_XS " %p", c->pid, queue_len, c->ipcs);
                c->queue_backlog = 0;
                qb_ipcs_disconnect(c->ipcs);
                return rc;
            }
        }

        c->queue_backlog = queue_len;
        delay_next_flush(c, queue_len);

    } else {
        /* Event queue is empty, there is no backlog */
        c->queue_backlog = 0;
    }

    return rc;
}