Branch data Line data Source code
1 : : /*
2 : : SSSD
3 : :
4 : : Data Provider Process - Callback
5 : :
6 : : Authors:
7 : :
8 : : Stephen Gallagher <sgallagh@redhat.com>
9 : : Sumit Bose <sbose@redhat.com>
10 : :
11 : : Copyright (C) 2010 Red Hat
12 : :
13 : : This program is free software; you can redistribute it and/or modify
14 : : it under the terms of the GNU General Public License as published by
15 : : the Free Software Foundation; either version 3 of the License, or
16 : : (at your option) any later version.
17 : :
18 : : This program is distributed in the hope that it will be useful,
19 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : : GNU General Public License for more details.
22 : :
23 : : You should have received a copy of the GNU General Public License
24 : : along with this program. If not, see <http://www.gnu.org/licenses/>.
25 : : */
26 : :
27 : : #include "util/util.h"
28 : : #include "providers/dp_backend.h"
29 : :
30 : : struct be_cb {
31 : : struct be_cb *prev;
32 : : struct be_cb *next;
33 : :
34 : : be_callback_t cb;
35 : : void *pvt;
36 : :
37 : : struct be_cb *list;
38 : : struct be_ctx *be;
39 : : };
40 : :
41 : : struct be_cb_ctx {
42 : : struct be_ctx *be;
43 : : struct be_cb *callback;
44 : : };
45 : :
46 : 0 : static int cb_destructor(TALLOC_CTX *ptr)
47 : : {
48 : 0 : struct be_cb *cb = talloc_get_type(ptr, struct be_cb);
49 [ # # ][ # # ]: 0 : DLIST_REMOVE(cb->list, cb);
[ # # ][ # # ]
[ # # ]
50 : 0 : return 0;
51 : : }
52 : :
53 : 0 : static int be_add_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
54 : : be_callback_t cb, void *pvt, struct be_cb **cb_list,
55 : : struct be_cb **return_cb)
56 : : {
57 : : struct be_cb *new_cb;
58 : :
59 [ # # ]: 0 : if (!ctx || !cb) {
60 : : return EINVAL;
61 : : }
62 : :
63 : 0 : new_cb = talloc(mem_ctx, struct be_cb);
64 [ # # ]: 0 : if (!new_cb) {
65 : : return ENOMEM;
66 : : }
67 : :
68 : 0 : new_cb->cb = cb;
69 : 0 : new_cb->pvt = pvt;
70 : 0 : new_cb->list = *cb_list;
71 : 0 : new_cb->be = ctx;
72 : :
73 [ # # ]: 0 : DLIST_ADD(*cb_list, new_cb);
74 : :
75 : 0 : talloc_set_destructor((TALLOC_CTX *) new_cb, cb_destructor);
76 : :
77 [ # # ]: 0 : if (return_cb) {
78 : 0 : *return_cb = new_cb;
79 : : }
80 : :
81 : : return EOK;
82 : : }
83 : :
84 : 0 : static void be_run_cb_step(struct tevent_context *ev, struct tevent_timer *te,
85 : : struct timeval current_time, void *pvt)
86 : : {
87 : 0 : struct be_cb_ctx *cb_ctx = talloc_get_type(pvt, struct be_cb_ctx);
88 : : struct tevent_timer *tev;
89 : : struct timeval soon;
90 : :
91 : : /* Call the callback */
92 : 0 : cb_ctx->callback->cb(cb_ctx->callback->pvt);
93 : :
94 [ # # ]: 0 : if (cb_ctx->callback->next) {
95 : 0 : cb_ctx->callback = cb_ctx->callback->next;
96 : :
97 : : /* Delay 30ms so we don't block any other events */
98 : 0 : soon = tevent_timeval_current_ofs(0, 30000);
99 : 0 : tev = tevent_add_timer(cb_ctx->be->ev, cb_ctx, soon,
100 : : be_run_cb_step,
101 : : cb_ctx);
102 [ # # ]: 0 : if (!tev) {
103 [ # # ][ # # ]: 0 : DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
[ # # ][ # # ]
[ # # ]
104 : : goto final;
105 : : }
106 : 0 : return;
107 : : }
108 : :
109 : : final:
110 : : /* Steal the timer event onto the be_ctx so it doesn't
111 : : * get freed with the cb_ctx
112 : : */
113 : 0 : talloc_steal(cb_ctx->be, te);
114 : 0 : talloc_free(cb_ctx);
115 : : }
116 : :
117 : 0 : static errno_t be_run_cb(struct be_ctx *be, struct be_cb *cb_list) {
118 : : struct timeval soon;
119 : : struct tevent_timer *te;
120 : : struct be_cb_ctx *cb_ctx;
121 : :
122 : 0 : cb_ctx = talloc(be, struct be_cb_ctx);
123 [ # # ]: 0 : if (!cb_ctx) {
124 [ # # ][ # # ]: 0 : DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
[ # # ][ # # ]
[ # # ]
125 : : return ENOMEM;
126 : : }
127 : 0 : cb_ctx->be = be;
128 : 0 : cb_ctx->callback = cb_list;
129 : :
130 : : /* Delay 30ms so we don't block any other events */
131 : 0 : soon = tevent_timeval_current_ofs(0, 30000);
132 : 0 : te = tevent_add_timer(be->ev, cb_ctx, soon,
133 : : be_run_cb_step,
134 : : cb_ctx);
135 [ # # ]: 0 : if (!te) {
136 [ # # ][ # # ]: 0 : DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
[ # # ][ # # ]
[ # # ]
137 : 0 : talloc_free(cb_ctx);
138 : : return ENOMEM;
139 : : }
140 : :
141 : : return EOK;
142 : : }
143 : :
144 : 0 : int be_add_reconnect_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t cb,
145 : : void *pvt, struct be_cb **reconnect_cb)
146 : : {
147 : : int ret;
148 : :
149 : 0 : ret = be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->reconnect_cb_list, reconnect_cb);
150 [ # # ]: 0 : if (ret != EOK) {
151 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("be_add_cb failed.\n"));
[ # # ][ # # ]
[ # # ]
152 : 0 : return ret;
153 : : }
154 : :
155 : : return EOK;
156 : : }
157 : :
158 : 0 : void be_run_reconnect_cb(struct be_ctx *be)
159 : : {
160 : 0 : struct be_cb *callback = be->reconnect_cb_list;
161 : :
162 [ # # ]: 0 : if (callback) {
163 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("Reconnecting. Running callbacks.\n"));
[ # # ][ # # ]
[ # # ]
164 : :
165 : : /**
166 : : * Call the callback: we have to call this right away
167 : : * so the provider doesn't go into offline even for
168 : : * a little while
169 : : */
170 : : do {
171 : 0 : callback->cb(callback->pvt);
172 : 0 : callback = callback->next;
173 [ # # ]: 0 : } while(callback != NULL);
174 : : } else {
175 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_INTERNAL, ("Reconnect call back list is empty, nothing to do.\n"));
[ # # ][ # # ]
[ # # ]
176 : : }
177 : 0 : }
178 : :
179 : 0 : int be_add_online_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t cb,
180 : : void *pvt, struct be_cb **online_cb)
181 : : {
182 : : int ret;
183 : :
184 : 0 : ret = be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->online_cb_list, online_cb);
185 [ # # ]: 0 : if (ret != EOK) {
186 [ # # ][ # # ]: 0 : DEBUG(1, ("be_add_cb failed.\n"));
[ # # ][ # # ]
[ # # ]
187 : 0 : return ret;
188 : : }
189 : :
190 : : /* Make sure we run the callback for the first
191 : : * connection after startup.
192 : : */
193 : 0 : ctx->run_online_cb = true;
194 : :
195 : 0 : return EOK;
196 : : }
197 : :
198 : 0 : void be_run_online_cb(struct be_ctx *be) {
199 : : int ret;
200 : :
201 [ # # ]: 0 : if (be->run_online_cb) {
202 : : /* Reset the flag. We only want to run these
203 : : * callbacks when transitioning to online
204 : : */
205 : 0 : be->run_online_cb = false;
206 : :
207 [ # # ]: 0 : if (be->online_cb_list) {
208 [ # # ][ # # ]: 0 : DEBUG(3, ("Going online. Running callbacks.\n"));
[ # # ][ # # ]
[ # # ]
209 : :
210 : 0 : ret = be_run_cb(be, be->online_cb_list);
211 [ # # ]: 0 : if (ret != EOK) {
212 [ # # ][ # # ]: 0 : DEBUG(1, ("be_run_cb failed.\n"));
[ # # ][ # # ]
[ # # ]
213 : : }
214 : :
215 : : } else {
216 [ # # ][ # # ]: 0 : DEBUG(9, ("Online call back list is empty, nothing to do.\n"));
[ # # ][ # # ]
[ # # ]
217 : : }
218 : : }
219 : 0 : }
220 : :
221 : 0 : int be_add_offline_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t cb,
222 : : void *pvt, struct be_cb **offline_cb)
223 : : {
224 : 0 : return be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->offline_cb_list, offline_cb);
225 : : }
226 : :
227 : 0 : void be_run_offline_cb(struct be_ctx *be) {
228 : : int ret;
229 : :
230 [ # # ]: 0 : if (be->offline_cb_list) {
231 [ # # ][ # # ]: 0 : DEBUG(3, ("Going offline. Running callbacks.\n"));
[ # # ][ # # ]
[ # # ]
232 : :
233 : 0 : ret = be_run_cb(be, be->offline_cb_list);
234 [ # # ]: 0 : if (ret != EOK) {
235 [ # # ][ # # ]: 0 : DEBUG(1, ("be_run_cb failed.\n"));
[ # # ][ # # ]
[ # # ]
236 : : }
237 : :
238 : : } else {
239 [ # # ][ # # ]: 0 : DEBUG(9, ("Offline call back list is empty, nothing to do.\n"));
[ # # ][ # # ]
[ # # ]
240 : : }
241 : 0 : }
|