1 /* conn.c - network connection state */
14 /* Doubly-linked list of free connections. */
15 static struct conn pool
= { &pool
, &pool
, 0 };
17 static int cur_conn_ct
= 0, cur_worker_ct
= 0, cur_producer_ct
= 0;
18 static unsigned int tot_conn_ct
= 0;
23 return conn_remove(pool
.next
) ? : malloc(sizeof(struct conn
));
30 conn_insert(&pool
, c
);
34 make_conn(int fd
, char start_state
)
40 if (!c
) return twarn("OOM"), NULL
;
43 c
->state
= start_state
;
46 c
->in_job
= c
->out_job
= NULL
;
47 c
->in_job_read
= c
->out_job_sent
= 0;
48 c
->prev
= c
->next
= c
; /* must be out of a linked list right now */
49 j
= &c
->reserved_jobs
;
50 j
->prev
= j
->next
= j
;
60 conn_set_producer(conn c
)
62 if (c
->type
& CONN_TYPE_PRODUCER
) return;
63 c
->type
|= CONN_TYPE_PRODUCER
;
64 cur_producer_ct
++; /* stats */
68 conn_set_worker(conn c
)
70 if (c
->type
& CONN_TYPE_WORKER
) return;
71 c
->type
|= CONN_TYPE_WORKER
;
72 cur_worker_ct
++; /* stats */
90 return cur_producer_ct
;
100 conn_set_evq(conn c
, const int events
, evh handler
)
103 struct timeval tv
= {0, 0};
105 event_set(&c
->evq
, c
->fd
, events
, handler
, c
);
107 if (has_reserved_job(c
)) tv
.tv_sec
= soonest_job(c
)->deadline
- time(NULL
);
109 r
= event_add(&c
->evq
, has_reserved_job(c
) ? &tv
: NULL
);
110 if (r
== -1) return twarn("event_add() err %d", errno
), -1;
116 conn_update_evq(conn c
, const int events
)
122 /* If it's been added, try to delete it first */
123 if (c
->evq
.ev_base
) {
124 r
= event_del(&c
->evq
);
125 if (r
== -1) return -1;
128 return conn_set_evq(c
, events
, c
->evq
.ev_callback
);
132 conn_list_any_p(conn head
)
134 return head
->next
!= head
|| head
->prev
!= head
;
140 if (!conn_list_any_p(c
)) return NULL
; /* not in a doubly-linked list */
142 c
->next
->prev
= c
->prev
;
143 c
->prev
->next
= c
->next
;
145 c
->prev
= c
->next
= c
;
150 conn_insert(conn head
, conn c
)
152 if (conn_list_any_p(c
)) return; /* already in a linked list */
154 c
->prev
= head
->prev
;
156 head
->prev
->next
= c
;
169 /* was this a peek or stats command? */
170 if (!has_reserved_this_job(c
, c
->out_job
)) free(c
->out_job
);
172 c
->in_job
= c
->out_job
= NULL
;
174 if (c
->type
& CONN_TYPE_PRODUCER
) cur_producer_ct
--; /* stats */
175 if (c
->type
& CONN_TYPE_WORKER
) cur_worker_ct
--; /* stats */
177 cur_conn_ct
--; /* stats */
180 remove_waiting_conn(c
);
182 if (has_reserved_job(c
)) enqueue_reserved_jobs(c
);