*/
uint32 worker_index;
+
+ /**
+ * @brief How many association groups this process serves right now
+ *
+ * @note while this is uint32, we currently only support 16-bit
+ * values, as we use the worker_index in the high 16-bits of
+ * so we only have 16-bit per worker in order to form the 32-bit
+ * association group id.
+ */
+ uint32 num_association_groups;
+
/**
- * @brief How many clients this process serves right now
+ * @brief How many client connections this process serves right now
+ *
+ * @note might be greater or equal to num_association_groups.
*/
- uint32 num_clients;
+ uint32 num_connections;
} rpc_worker_status;
}
* MSG_RPC_HOST_WORKER_STATUS sent by workers whenever a
* client exits.
*/
- uint32_t num_clients;
+ uint32_t num_associations;
+ uint32_t num_connections;
/*
* Send SHUTDOWN to an idle child after a while
if (!worker->available) {
continue;
}
- if (worker->num_clients == 0) {
+ if (worker->num_associations == 0) {
/*
* We have an idle worker...
*/
best_worker = worker;
continue;
}
- if (worker->num_clients < best_worker->num_clients) {
+ if (worker->num_associations < best_worker->num_associations) {
/*
- * It's also busy, but has less clients
+ * It's also busy, but has less association groups
+ * (logical clients)
*/
best_worker = worker;
continue;
}
+ if (worker->num_associations > best_worker->num_associations) {
+ /*
+ * It's not better
+ */
+ continue;
+ }
+ /*
+ * Ok, with the same number of association groups
+ * we pick the one with the lowest number of connections
+ */
+ if (worker->num_connections < best_worker->num_connections) {
+ best_worker = worker;
+ continue;
+ }
}
if (perfect_worker != NULL) {
if (!worker->available) {
continue;
}
- if (worker->num_clients == 0) {
+ if (worker->num_associations == 0) {
return &server->workers[i];
}
}
goto done;
}
- DBG_INFO("Sending %s client %s to %d with %"PRIu32" clients\n",
+ DBG_INFO("Sending %s client %s to %d with "
+ "%"PRIu32" associations and %"PRIu32" connections\n",
client_type,
server->rpc_server_exe,
worker->pid,
- worker->num_clients);
+ worker->num_associations,
+ worker->num_connections);
iov = (struct iovec) {
.iov_base = blob.data, .iov_len = blob.length,
nt_errstr(status));
goto done;
}
- worker->num_clients += 1;
+ if (assoc_group_id == 0) {
+ worker->num_associations += 1;
+ }
+ worker->num_connections += 1;
TALLOC_FREE(worker->exit_timer);
TALLOC_FREE(server->host->np_helper_shutdown);
}
w->exit_timer = NULL;
- SMB_ASSERT(w->num_clients == 0);
+ SMB_ASSERT(w->num_associations == 0);
status = messaging_send(
server->host->msg_ctx,
}
worker->available = true;
- worker->num_clients = status_message.num_clients;
+ worker->num_associations = status_message.num_association_groups;
+ worker->num_connections = status_message.num_connections;
- if (worker->num_clients != 0) {
+ if (worker->num_associations != 0) {
TALLOC_FREE(worker->exit_timer);
} else {
worker->exit_timer = tevent_add_timer(
}
fprintf(f,
- " worker[%zu]: pid=%d, num_clients=%"PRIu32"\n",
+ " worker[%zu]: pid=%d, num_associations=%"PRIu32", num_connections=%"PRIu32"\n",
j,
(int)w->pid,
- w->num_clients);
+ w->num_associations,
+ w->num_connections);
}
}
static NTSTATUS rpc_worker_report_status(struct rpc_worker *worker)
{
- uint8_t buf[12];
+ uint8_t buf[16];
DATA_BLOB blob = { .data = buf, .length = sizeof(buf), };
enum ndr_err_code ndr_err;
NTSTATUS status;
+ worker->status.num_association_groups = worker->dce_ctx->assoc_groups_num;
+
if (DEBUGLEVEL >= 10) {
NDR_PRINT_DEBUG(rpc_worker_status, &worker->status);
}
NTSTATUS status;
bool found = false;
- SMB_ASSERT(worker->status.num_clients > 0);
+ /*
+ * We need to drop the association group reference
+ * explicitly here in order to avoid the order given
+ * by the destructors. rpc_worker_report_status() below,
+ * expects worker->dce_ctx->assoc_groups_num to be updated
+ * already.
+ */
+ if (conn->assoc_group != NULL) {
+ talloc_unlink(conn, conn->assoc_group);
+ conn->assoc_group = NULL;
+ }
+
+ SMB_ASSERT(worker->status.num_connections > 0);
for (w = worker->conns; w != NULL; w = w->next) {
if (w == ncacn_conn) {
DLIST_REMOVE(worker->conns, ncacn_conn);
- worker->status.num_clients -= 1;
+ worker->status.num_connections -= 1;
status = rpc_worker_report_status(worker);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(client);
DLIST_ADD(worker->conns, ncacn_conn);
- worker->status.num_clients += 1;
+ worker->status.num_connections += 1;
dcesrv_loop_next_packet(dcesrv_conn, pkt, buffer);