]> git.saurik.com Git - redis.git/blame - src/bio.c
Enforce upper bound for number of requests in redis-benchmark
[redis.git] / src / bio.c
CommitLineData
02925dd9 1/* Background I/O service for Redis.
2 *
3 * This file implements operations that we need to perform in the background.
4 * Currently there is only a single operation, that is a background close(2)
5 * system call. This is needed as when the process is the last owner of a
6 * reference to a file closing it means unlinking it, and the deletion of the
7 * file is slow, blocking the server.
8 *
9 * In the future we'll either continue implementing new things we need or
10 * we'll switch to libeio. However there are probably long term uses for this
11 * file as we may want to put here Redis specific background tasks (for instance
12 * it is not impossible that we'll need a non blocking FLUSHDB/FLUSHALL
13 * implementation).
14 *
15 * DESIGN
16 * ------
17 *
18 * The design is trivial, we have a structure representing a job to perform
19 * and a single thread performing all the I/O operations in the queue.
20 * Currently there is no way for the creator of the job to be notified about
21 * the completion of the operation, this will only be added when/if needed.
22 */
23
24#include "redis.h"
25#include "bio.h"
26
27static pthread_mutex_t bio_mutex;
28static pthread_cond_t bio_condvar;
d47ded66 29static list *bio_jobs;
02925dd9 30
31/* This structure represents a background Job. It is only used locally to this
32 * file as the API deos not expose the internals at all. */
33struct bio_job {
34 int type; /* Job type, for instance BIO_JOB_CLOSE */
35 void *data; /* Job specific arguments pointer. */
f81a5f54 36};
02925dd9 37
38void *bioProcessBackgroundJobs(void *arg);
39
f81a5f54 40/* Make sure we have enough stack to perform all the things we do in the
41 * main thread. */
42#define REDIS_THREAD_STACK_SIZE (1024*1024*4)
43
02925dd9 44/* Initialize the background system, spawning the thread. */
45void bioInit(void) {
46 pthread_attr_t attr;
47 pthread_t thread;
48 size_t stacksize;
49
f81a5f54 50 pthread_mutex_init(&bio_mutex,NULL);
51 pthread_cond_init(&bio_condvar,NULL);
02925dd9 52 bio_jobs = listCreate();
53
54 /* Set the stack size as by default it may be small in some system */
55 pthread_attr_init(&attr);
f81a5f54 56 pthread_attr_getstacksize(&attr,&stacksize);
02925dd9 57 if (!stacksize) stacksize = 1; /* The world is full of Solaris Fixes */
58 while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2;
59 pthread_attr_setstacksize(&attr, stacksize);
60
61 /* Ready to spawn our thread */
62 if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,NULL) != 0) {
63 redisLog(REDIS_WARNING,"Fatal: Can't initialize Background Jobs.");
64 exit(1);
65 }
66}
67
68void bioCreateBackgroundJob(int type, void *data) {
69 struct bio_job *job = zmalloc(sizeof(*job));
70
71 job->type = type;
72 job->data = data;
73 pthread_mutex_lock(&bio_mutex);
74 listAddNodeTail(bio_jobs,job);
b7c739b0 75 pthread_cond_signal(&bio_condvar);
02925dd9 76 pthread_mutex_unlock(&bio_mutex);
77}
78
79void *bioProcessBackgroundJobs(void *arg) {
80 struct bio_job *job;
f81a5f54 81 REDIS_NOTUSED(arg);
02925dd9 82
83 pthread_detach(pthread_self());
84 pthread_mutex_lock(&bio_mutex);
85 while(1) {
86 listNode *ln;
87
88 /* The loop always starts with the lock hold. */
8ea2dfd7 89 if (listLength(bio_jobs) == 0) {
02925dd9 90 pthread_cond_wait(&bio_condvar,&bio_mutex);
91 continue;
92 }
93 /* Pop the job from the queue. */
94 ln = listFirst(bio_jobs);
95 job = ln->value;
96 listDelNode(bio_jobs,ln);
97 /* It is now possible to unlock the background system as we know have
98 * a stand alone job structure to process.*/
99 pthread_mutex_unlock(&bio_mutex);
100
101 /* Process the job accordingly to its type. */
102 if (job->type == REDIS_BIO_CLOSE_FILE) {
103 close((long)job->data);
104 } else {
105 redisPanic("Wrong job type in bioProcessBackgroundJobs().");
106 }
107 zfree(job);
108
109 /* Lock again before reiterating the loop, if there are no longer
110 * jobs to process we'll block again in pthread_cond_wait(). */
111 pthread_mutex_lock(&bio_mutex);
112 }
113}