free(ctx);
}
+static struct fireperf_worker* fireperf_ctx_find_idle_worker(struct fireperf_ctx* ctx) {
+ const struct fireperf_stats* stats = NULL;
+
+ for (unsigned int i = 0; i < ctx->num_workers; i++) {
+ if (!ctx->workers[i])
+ continue;
+
+ // Fetch the worker's stats
+ stats = fireperf_worker_get_stats(ctx->workers[i]);
+ if (!stats)
+ continue;
+
+ printf("C %lu\n", stats->open_connections);
+
+ // If the worker has no open connections, we can use it
+ if (stats->open_connections == 0)
+ return ctx->workers[i];
+ }
+
+ return NULL;
+}
+
+static struct fireperf_worker* fireperf_ctx_find_least_busy_worker(struct fireperf_ctx* ctx) {
+ const struct fireperf_stats* stats = NULL;
+
+ struct fireperf_worker* worker = NULL;
+ unsigned int open_connections = 0;
+
+ for (unsigned int i = 0; i < ctx->num_workers; i++) {
+ if (!ctx->workers[i])
+ continue;
+
+ // Fetch the worker's stats
+ stats = fireperf_worker_get_stats(ctx->workers[i]);
+ if (!stats)
+ continue;
+
+ // If we have not seen a worker, we will save the first one;
+ // or replace it if we found a better match
+ if (!worker || stats->open_connections < open_connections) {
+ worker = ctx->workers[i];
+
+ // Save the number of connections
+ open_connections = stats->open_connections;
+ }
+ }
+
+ return worker;
+}
+
/*
This function returns a free worker
*/
struct fireperf_worker* worker = NULL;
int r;
- /*
- XXX TODO
- To keep things simple, we create a new worker for each call.
+ // Return the first idle worker if available
+ worker = fireperf_ctx_find_idle_worker(ctx);
+ if (worker)
+ return worker;
+
+ // If all current workers are busy and we have not reached our maximum,
+ // we create a new one.
+ if (ctx->num_workers < ctx->max_workers) {
+ // Create a new worker
+ r = fireperf_worker_create(&worker, ctx);
+ if (r < 0) {
+ ERROR(ctx, "Could not create worker: %s\n", strerror(-r));
+ goto ERROR;
+ }
- This should be replaced by a method that searches for the worker with
- the least amount of connections and start up to as many workers as we
- have CPU cores.
- */
+ // Launch the worker
+ r = fireperf_worker_launch(worker);
+ if (r < 0) {
+ ERROR(ctx, "Could not launch worker: %s\n", strerror(-r));
+ goto ERROR;
+ }
- // Create a new worker
- r = fireperf_worker_create(&worker, ctx);
- if (r < 0) {
- ERROR(ctx, "Could not create worker: %s\n", strerror(-r));
- goto ERROR;
- }
+ // Store a reference
+ ctx->workers[ctx->num_workers++] = worker;
- // Launch the worker
- r = fireperf_worker_launch(worker);
- if (r < 0) {
- ERROR(ctx, "Could not launch worker: %s\n", strerror(-r));
- goto ERROR;
+ return worker;
}
- // Store a reference
- ctx->workers[ctx->num_workers++] = worker;
-
- return worker;
+ // Return the least busy worker
+ worker = fireperf_ctx_find_least_busy_worker(ctx);
+ if (worker)
+ return worker;
ERROR:
if (worker)