2 * Copyright (c) 2006, Maxime Henrion <mux@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * A synchronized queue to implement fixups. The updater thread adds
40 * fixup requests to the queue with fixups_put() when a checksum
41 * mismatch error occured. It then calls fixups_close() when he's
42 * done requesting fixups. The detailer thread gets the fixups with
43 * fixups_get() and then send the requests to the server.
45 * The queue is synchronized with a mutex and a condition variable.
51 STAILQ_HEAD(, fixup) fixupq;
57 static void fixups_lock(struct fixups *);
58 static void fixups_unlock(struct fixups *);
60 static struct fixup *fixup_new(struct coll *, const char *);
61 static void fixup_free(struct fixup *);
64 fixups_lock(struct fixups *f)
68 error = pthread_mutex_lock(&f->lock);
73 fixups_unlock(struct fixups *f)
77 error = pthread_mutex_unlock(&f->lock);
82 fixup_new(struct coll *coll, const char *name)
86 fixup = xmalloc(sizeof(struct fixup));
87 fixup->f_name = xstrdup(name);
93 fixup_free(struct fixup *fixup)
100 /* Create a new fixup queue. */
106 f = xmalloc(sizeof(struct fixups));
110 STAILQ_INIT(&f->fixupq);
111 pthread_mutex_init(&f->lock, NULL);
112 pthread_cond_init(&f->cond, NULL);
116 /* Add a fixup request to the queue. */
118 fixups_put(struct fixups *f, struct coll *coll, const char *name)
124 fixup = fixup_new(coll, name);
127 STAILQ_INSERT_TAIL(&f->fixupq, fixup, f_link);
132 pthread_cond_signal(&f->cond);
135 /* Get a fixup request from the queue. */
137 fixups_get(struct fixups *f)
139 struct fixup *fixup, *tofree;
142 while (f->size == 0 && !f->closed)
143 pthread_cond_wait(&f->cond, &f->lock);
149 fixup = STAILQ_FIRST(&f->fixupq);
152 STAILQ_REMOVE_HEAD(&f->fixupq, f_link);
160 /* Close the writing end of the queue. */
162 fixups_close(struct fixups *f)
168 if (f->size == 0 && !f->closed)
173 pthread_cond_signal(&f->cond);
176 /* Free a fixups queue. */
178 fixups_free(struct fixups *f)
180 struct fixup *fixup, *fixup2;
184 * Free any fixup that has been left on the queue.
185 * This can happen if we have been aborted prematurely.
187 fixup = STAILQ_FIRST(&f->fixupq);
188 while (fixup != NULL) {
189 fixup2 = STAILQ_NEXT(fixup, f_link);
195 pthread_cond_destroy(&f->cond);
196 pthread_mutex_destroy(&f->lock);