summaryrefslogtreecommitdiff
path: root/src/conn/workq.c
blob: 0213fc590dabbe027db9e28fc78fc5e15e91e8f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 2008-2011 WiredTiger, Inc.
 *	All rights reserved.
 */

#include "wt_internal.h"

/*
 * __wt_workq_srvr --
 *      Routine to process the WT_SESSION_IMPL work queue.
 */
void *
__wt_workq_srvr(void *arg)
{
	WT_CONNECTION_IMPL *conn;
	WT_SESSION_IMPL **tp, *session;
	int call_evict, call_read, request;

	conn = (WT_CONNECTION_IMPL *)arg;

	/* Walk the WT_SESSION_IMPL list and execute requests. */
	while (F_ISSET(conn, WT_WORKQ_RUN)) {
		WT_STAT_INCR(conn->stats, workq_passes);

		call_evict = call_read = request = 0;
		for (tp = conn->sessions; (session = *tp) != NULL; ++tp) {
			switch (session->wq_state) {
			case WT_WORKQ_NONE:
				break;
			case WT_WORKQ_FUNC:
				request = 1;
				session->wq_func(session);
				break;
			case WT_WORKQ_READ:
				/*
				 * Call a function which makes a request of the
				 * read server.  There are two read states: READ
				 * (the initial request), and READ_SCHED (the
				 * function has been called and we're waiting on
				 * the read to complete).  There are two states
				 * because we can race with the server: if the
				 * called function adds itself to the queue just
				 * as the server is going to sleep, the server
				 * might not see the request.   So, READ_SCHED
				 * means we don't have to call the function, but
				 * we do have check if the server is running.
				 *
				 * The read state is eventually reset by the
				 * read server, so we set it before we call the
				 * function that will contact the server, so we
				 * can't race on that update.
				 */
				session->wq_state = WT_WORKQ_READ_SCHED;

				/* Queue the request for the read server. */
				session->wq_func(session);
				/* FALLTHROUGH */
			case WT_WORKQ_READ_SCHED:
				call_read = 1;
				break;
			case WT_WORKQ_EVICT:
				/*
				 * See comment above regarding read scheduling;
				 * eviction works the same as read, as far as
				 * the workq is concerned.
				 *
				 * We don't have to call a function to contact
				 * the eviction server, currently the eviction
				 * server checks the list of open tables each
				 * time it runs.
				 */
				session->wq_state = WT_WORKQ_EVICT_SCHED;

				/* Queue the request for the eviction server. */
				session->wq_func(session);
				/* FALLTHROUGH */
			case WT_WORKQ_EVICT_SCHED:
				call_evict = 1;
				break;
			}
		}

		/* If a read is scheduled, check on the read server. */
		if (call_read)
			__wt_workq_read_server(conn, 0);

		/* Check on the eviction server. */
		__wt_workq_evict_server(conn, call_evict);

		/* If we didn't find work, yield the processor. */
		if (!request) {
			WT_STAT_INCR(conn->stats, workq_yield);
			__wt_yield();
		}
	}
	return (NULL);
}