ssize_t qb_ipcc_sendv_recv(qb_ipcc_connection_t * c, const struct iovec * iov, uint32_t iov_len, void *res_msg, size_t res_len, int32_t ms_timeout) { ssize_t res = 0; int32_t timeout_now; int32_t timeout_rem = ms_timeout; if (c == NULL) { return -EINVAL; } if (c->funcs.fc_get) { res = c->funcs.fc_get(&c->request); if (res < 0) { return res; } else if (res > 0 && res <= c->fc_enable_max) { return -EAGAIN; } else { /* * we can transmit */ } } res = qb_ipcc_sendv(c, iov, iov_len); if (res < 0) { return res; } do { if (timeout_rem > QB_IPC_MAX_WAIT_MS || ms_timeout == -1) { timeout_now = QB_IPC_MAX_WAIT_MS; } else { timeout_now = timeout_rem; } res = qb_ipcc_recv(c, res_msg, res_len, timeout_now); if (res == -ETIMEDOUT) { if (ms_timeout < 0) { res = -EAGAIN; } else { timeout_rem -= timeout_now; if (timeout_rem > 0) { res = -EAGAIN; } } } else if (res < 0 && res != -EAGAIN) { errno = -res; qb_util_perror(LOG_DEBUG, "qb_ipcc_recv %d timeout:(%d/%d)", res, timeout_now, timeout_rem); } } while (res == -EAGAIN && c->is_connected); return res; }
static int internal_ipc_send_request(crm_ipc_t * client, const void *iov, int ms_timeout) { int rc = 0; time_t timeout = time(NULL) + 1 + (ms_timeout / 1000); do { rc = qb_ipcc_sendv(client->ipc, iov, 2); } while (rc == -EAGAIN && time(NULL) < timeout && crm_ipc_connected(client)); return rc; }
static void _benchmark(qb_ipcc_connection_t *conn, int write_size) { struct timeval tv1, tv2, tv_elapsed; struct iovec iov[2]; unsigned int res; struct qb_ipc_request_header hdr; int write_count = 0; alarm_notice = 0; hdr.size = write_size; hdr.id = QB_IPC_MSG_USER_START + 1; iov[0].iov_base = &hdr; iov[0].iov_len = sizeof(struct qb_ipc_request_header); iov[1].iov_base = data; iov[1].iov_len = write_size - sizeof(struct qb_ipc_request_header); alarm (10); gettimeofday (&tv1, NULL); do { res = qb_ipcc_sendv(conn, iov, 2); if (res == write_size) { write_count++; } } while (alarm_notice == 0 && (res == write_size || res == -EAGAIN)); if (res < 0) { perror("qb_ipcc_sendv"); } gettimeofday (&tv2, NULL); timersub (&tv2, &tv1, &tv_elapsed); printf ("%5d messages sent ", write_count); printf ("%5d bytes per write ", write_size); printf ("%7.3f Seconds runtime ", (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0))); printf ("%9.3f TP/s ", ((float)write_count) / (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0))); printf ("%7.3f MB/s.\n", ((float)write_count) * ((float)write_size) / ((tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)) * 1000000.0)); }
static void _benchmark(qb_ipcc_connection_t *conn, int write_size) { struct iovec iov[2]; ssize_t res; struct qb_ipc_request_header hdr; int write_count = 0; float secs; alarm_notice = 0; hdr.size = write_size; hdr.id = QB_IPC_MSG_USER_START + 1; iov[0].iov_base = &hdr; iov[0].iov_len = sizeof(struct qb_ipc_request_header); iov[1].iov_base = data; iov[1].iov_len = write_size - sizeof(struct qb_ipc_request_header); alarm (10); qb_util_stopwatch_start(sw); do { res = qb_ipcc_sendv(conn, iov, 2); if (res == write_size) { write_count++; } } while (alarm_notice == 0 && (res == write_size || res == -EAGAIN)); if (res < 0) { perror("qb_ipcc_sendv"); } qb_util_stopwatch_stop(sw); secs = qb_util_stopwatch_sec_elapsed_get(sw); printf ("%5d messages sent ", write_count); printf ("%5d bytes per write ", write_size); printf ("%7.3f Seconds runtime ", secs); printf ("%9.3f TP/s ", ((float)write_count) / secs); printf ("%7.3f MB/s.\n", ((float)write_count) * ((float)write_size) / secs); }
json IPCClientPrivate::qbIPCSendRecvJSON(const json& jval) { if (!isConnected()) { throw IPCException(IPCException::ConnectionError, "Not connected"); } const std::string json_string = jval.dump(); struct qb_ipc_request_header hdr; hdr.id = 0; hdr.size = sizeof hdr + json_string.size(); struct iovec iov[2]; iov[0].iov_base = &hdr; iov[0].iov_len = sizeof hdr; iov[1].iov_base = (void *)json_string.c_str(); iov[1].iov_len = json_string.size(); const uint64_t id = jval["_i"]; /* Lock the return value slot map */ std::unique_lock<std::mutex> rv_map_lock(_rv_map_mutex); /* * Create the promise and future objects. * The promise will be fullfiled by the message * processing handlers after they process * a reply from the server. */ auto& promise = _rv_map[id]; auto future = promise.get_future(); qb_ipcc_sendv(_qb_conn, iov, 2); /* * Unlock the return value map so that the message * processing handler aren't blocked. */ rv_map_lock.unlock(); /* Wait for some time for the reply to be received */ const std::chrono::milliseconds timeout_ms(5*1000); const bool timed_out = \ future.wait_for(timeout_ms) == std::future_status::timeout; json retval; if (!timed_out) { retval = future.get(); } /* Remove the slot from the return value slot map */ rv_map_lock.lock(); _rv_map.erase(id); rv_map_lock.unlock(); if (timed_out) { throw IPCException(IPCException::TransientError, "Timed out while waiting for IPC reply"); } else { /* * We might have caused an exception. Check whether * that's the case and if true, throw it here. */ if (isExceptionJSON(retval)) { throw IPCException(IPCException::ProtocolError, "The remote end sent an exception"); } else { return std::move(retval); } } return json(); }