static struct pollfd *fds;
static unsigned int current_array_size;
static unsigned int nr_fds;
+static unsigned int delayed_requests;
static int sock = -1;
return true;
}
+static int undelay_request(void *_req)
+{
+ struct delayed_request *req = _req;
+
+ list_del(&req->list);
+ delayed_requests--;
+
+ return 0;
+}
+
+static void call_delayed(struct connection *conn, struct delayed_request *req)
+{
+ assert(conn->in == NULL);
+ conn->in = req->in;
+
+ if (req->func(req)) {
+ undelay_request(req);
+ talloc_set_destructor(req, NULL);
+ }
+
+ conn->in = NULL;
+}
+
+int delay_request(struct connection *conn, struct buffered_data *in,
+ bool (*func)(struct delayed_request *), void *data)
+{
+ struct delayed_request *req;
+
+ req = talloc(in, struct delayed_request);
+ if (!req)
+ return ENOMEM;
+
+ /* For the case of connection being closed. */
+ talloc_set_destructor(req, undelay_request);
+
+ req->in = in;
+ req->func = func;
+ req->data = data;
+
+ delayed_requests++;
+ list_add(&req->list, &conn->delayed);
+
+ conn->in = NULL;
+
+ return 0;
+}
+
static int destroy_conn(void *_conn)
{
struct connection *conn = _conn;
memset(fds, 0, sizeof(struct pollfd) * current_array_size);
nr_fds = 0;
- *ptimeout = -1;
+ /* In case of delayed requests pause for max 1 second. */
+ *ptimeout = delayed_requests ? 1000 : -1;
if (sock != -1)
*p_sock_pollfd_idx = set_fd(sock, POLLIN|POLLPRI);
INIT_LIST_HEAD(&new->out_list);
INIT_LIST_HEAD(&new->watches);
INIT_LIST_HEAD(&new->transaction_list);
+ INIT_LIST_HEAD(&new->delayed);
list_add_tail(&new->list, &connections);
talloc_set_destructor(new, destroy_conn);
}
}
+ if (delayed_requests) {
+ list_for_each_entry(conn, &connections, list) {
+ struct delayed_request *req, *tmp;
+
+ list_for_each_entry_safe(req, tmp,
+ &conn->delayed, list)
+ call_delayed(conn, req);
+ }
+ }
+
initialize_fds(&sock_pollfd_idx, &timeout);
}
}
char default_buffer[DEFAULT_BUFFER_SIZE];
};
+struct delayed_request {
+ /* Next delayed request. */
+ struct list_head list;
+
+ /* The delayed request. */
+ struct buffered_data *in;
+
+ /* Function to call. */
+ bool (*func)(struct delayed_request *req);
+
+ /* Further data. */
+ void *data;
+};
+
struct connection;
typedef int connwritefn_t(struct connection *, const void *, unsigned int);
typedef int connreadfn_t(struct connection *, void *, unsigned int);
uint32_t next_transaction_id;
unsigned int transaction_started;
+ /* List of delayed requests. */
+ struct list_head delayed;
+
/* The domain I'm associated with, if any. */
struct domain *domain;
/* Get name of parent node. */
char *get_parent(const void *ctx, const char *node);
+/* Delay a request. */
+int delay_request(struct connection *conn, struct buffered_data *in,
+ bool (*func)(struct delayed_request *), void *data);
+
/* Tracing infrastructure. */
void trace_create(const void *data, const char *type);
void trace_destroy(const void *data, const char *type);