1 /*
2 * Copyright (C) 2003 Sam Horrocks
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 */
19
20 #include "speedy.h"
21
speedy_backend_dispose(slotnum_t gslotnum,slotnum_t bslotnum)22 void speedy_backend_dispose(slotnum_t gslotnum, slotnum_t bslotnum) {
23 if (gslotnum && bslotnum) {
24 gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum);
25
26 if (FILE_SLOT(be_slot, bslotnum).fe_running)
27 speedy_backend_died(bslotnum);
28
29 speedy_slot_remove(bslotnum, &(gslot->be_head), &(gslot->be_tail));
30 speedy_ipc_cleanup(bslotnum);
31 SLOT_FREE(bslotnum, "backend (speedy_backend_dispose)");
32 }
33 }
34
35 #ifdef SPEEDY_FRONTEND
speedy_backend_be_wait_get(slotnum_t gslotnum)36 slotnum_t speedy_backend_be_wait_get(slotnum_t gslotnum) {
37 gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum);
38 slotnum_t head = gslot->be_head;
39
40 /* Don't grab a backend while a backend is starting */
41 if (speedy_group_be_starting(gslotnum) ||
42 !head || FILE_SLOT(be_slot, head).fe_running)
43 {
44 return 0;
45 }
46 speedy_slot_move_tail(head, &(gslot->be_head), &(gslot->be_tail));
47 return head;
48 }
49 #endif /* SPEEDY_FRONTEND */
50
51 #ifdef SPEEDY_BACKEND
52
53 /* Move waiting be to the begining of the list, order reverse by maturity.
54 * We also want waiting be's to go before non-waiting be's.
55 * We want to go at the beginning of our maturity list to preserve LIFO
56 * ordering so inactive be's will die off.
57 */
58
do_sort(slotnum_t bslotnum_a,slotnum_t bslotnum_b)59 static int do_sort(slotnum_t bslotnum_a, slotnum_t bslotnum_b) {
60 be_slot_t *a = &FILE_SLOT(be_slot, bslotnum_a);
61 be_slot_t *b = &FILE_SLOT(be_slot, bslotnum_b);
62 int diff;
63
64 /* We want waiting be's to go before non-waiting.
65 * If we return < 0, a will go before b.
66 * If A is waiting and B is not, we return (B=0) - (A=1) == -1
67 * and A is first.
68 * If B is waiting and A is not, we return (B=1) - (A=0) == 1
69 * and B is first.
70 */
71 diff = ((b->fe_running ? 0 : 1) - (a->fe_running ? 0 : 1));
72 if (diff != 0)
73 return diff;
74
75 /* We want higher maturity#'s at the beginning.
76 * If we return < 0, a will go before b
77 * if A = 2 and B = 1, then we return -1 (B=1) - (A=2) == -1.
78 * If A = 1 and B = 2, then we return 1 (B=2) - (A=1) == 1.
79 */
80 return b->maturity - a->maturity;
81 }
82
speedy_backend_be_wait_put(slotnum_t gslotnum,slotnum_t bslotnum)83 void speedy_backend_be_wait_put(slotnum_t gslotnum, slotnum_t bslotnum) {
84 gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum);
85
86 FILE_SLOT(be_slot, bslotnum).fe_running = 0;
87 speedy_slot_remove(bslotnum, &(gslot->be_head), &(gslot->be_tail));
88 speedy_slot_insert_sorted(
89 bslotnum, &(gslot->be_head), &(gslot->be_tail), &do_sort
90 );
91 }
92
speedy_backend_create_slot(slotnum_t gslotnum)93 slotnum_t speedy_backend_create_slot(slotnum_t gslotnum) {
94 gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum);
95 slotnum_t bslotnum;
96
97 /* Create our backend slot */
98 bslotnum = SLOT_ALLOC("backend (speedy_backend_create_slot)");
99 FILE_SLOT(be_slot, bslotnum).fe_running = bslotnum;
100
101 /* Put our slot at the end of group's be list */
102 speedy_slot_append(bslotnum, &(gslot->be_head), &(gslot->be_tail));
103
104 return bslotnum;
105 }
106 #endif /* SPEEDY_BACKEND */
107
108 /* Kill and remove all be's in the be_wait list */
speedy_backend_remove_be_wait(slotnum_t gslotnum)109 void speedy_backend_remove_be_wait(slotnum_t gslotnum) {
110 gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum);
111 slotnum_t bslotnum, next;
112
113 for (bslotnum = gslot->be_head;
114 bslotnum && !FILE_SLOT(be_slot, bslotnum).fe_running;
115 bslotnum = next)
116 {
117 next = speedy_slot_next(bslotnum);
118 speedy_util_kill(FILE_SLOT(be_slot, bslotnum).pid, SIGTERM);
119 }
120 }
121
count_bes(slotnum_t gslotnum,int max)122 static int count_bes(slotnum_t gslotnum, int max) {
123 slotnum_t bslotnum;
124 int count;
125
126 for (bslotnum = FILE_SLOT(gr_slot, gslotnum).be_head, count = 0;
127 bslotnum && count < max;
128 bslotnum = speedy_slot_next(bslotnum))
129 {
130 ++count;
131 }
132 return count;
133 }
134
speedy_backend_below_maxbe(slotnum_t gslotnum)135 int speedy_backend_below_maxbe(slotnum_t gslotnum) {
136 return !OPTVAL_MAXBACKENDS ||
137 count_bes(gslotnum, OPTVAL_MAXBACKENDS) < OPTVAL_MAXBACKENDS;
138 }
139
speedy_backend_exited(slotnum_t bslotnum,int exit_on_sig,int exit_val)140 void speedy_backend_exited(slotnum_t bslotnum, int exit_on_sig, int exit_val) {
141 be_slot_t *bslot = &FILE_SLOT(be_slot, bslotnum);
142 slotnum_t fslotnum;
143
144 if ((fslotnum = bslot->fe_running)) {
145 bslot->fe_running = bslotnum;
146 if (fslotnum != bslotnum) {
147 fe_slot_t *fslot = &FILE_SLOT(fe_slot, fslotnum);
148 fslot->backend = 0;
149 fslot->exit_on_sig = exit_on_sig;
150 fslot->exit_val = exit_val;
151 if (speedy_util_kill(fslot->pid, SIGUSR1) == -1)
152 speedy_frontend_remove_running(fslotnum);
153 }
154 }
155 }
156