3 #include <minix/sysutil.h>
5 /* SEF Live update variables. */
6 static int sef_lu_state
;
8 /* SEF Live update callbacks. */
9 static struct sef_cbs
{
10 sef_cb_lu_prepare_t sef_cb_lu_prepare
;
11 sef_cb_lu_state_isvalid_t sef_cb_lu_state_isvalid
;
12 sef_cb_lu_state_changed_t sef_cb_lu_state_changed
;
13 sef_cb_lu_state_dump_t sef_cb_lu_state_dump
;
14 sef_cb_lu_state_save_t sef_cb_lu_state_save
;
15 sef_cb_lu_response_t sef_cb_lu_response
;
17 SEF_CB_LU_PREPARE_DEFAULT
,
18 SEF_CB_LU_STATE_ISVALID_DEFAULT
,
19 SEF_CB_LU_STATE_CHANGED_DEFAULT
,
20 SEF_CB_LU_STATE_DUMP_DEFAULT
,
21 SEF_CB_LU_STATE_SAVE_DEFAULT
,
22 SEF_CB_LU_RESPONSE_DEFAULT
25 /* SEF Live update prototypes for sef_receive(). */
26 void do_sef_lu_before_receive(void);
27 int do_sef_lu_request(message
*m_ptr
);
29 /* SEF Live update helpers. */
30 static void sef_lu_ready(int result
);
33 EXTERN
char* sef_debug_header(void);
34 static int sef_lu_debug_cycle
= 0;
36 /* Information about SELF. */
37 EXTERN endpoint_t sef_self_endpoint
;
38 EXTERN
int sef_self_first_receive_done
;
40 /*===========================================================================*
41 * do_sef_lu_before_receive *
42 *===========================================================================*/
43 void do_sef_lu_before_receive()
45 /* Handle SEF Live update before receive events. */
48 /* Initialize on first receive. */
49 if(!sef_self_first_receive_done
) {
50 sef_lu_state
= SEF_LU_STATE_NULL
;
53 /* Nothing to do if we are not preparing for a live update. */
54 if(sef_lu_state
== SEF_LU_STATE_NULL
) {
62 sef_lu_dprint("%s, cycle=%d. Dumping state variables:\n",
63 sef_debug_header(), sef_lu_debug_cycle
);
64 sef_cbs
.sef_cb_lu_state_dump(sef_lu_state
);
68 /* Let the callback code handle the event.
69 * For SEF_LU_STATE_WORK_FREE, we're always ready, tell immediately.
72 if(sef_lu_state
!= SEF_LU_STATE_WORK_FREE
) {
73 r
= sef_cbs
.sef_cb_lu_prepare(sef_lu_state
);
80 /*===========================================================================*
82 *===========================================================================*/
83 int do_sef_lu_request(message
*m_ptr
)
85 /* Handle a SEF Live update request. */
86 int state
, old_state
, is_valid_state
;
88 sef_lu_debug_cycle
= 0;
89 old_state
= sef_lu_state
;
90 state
= m_ptr
->RS_LU_STATE
;
92 /* Deal with prepare cancel requests first. */
93 is_valid_state
= (state
== SEF_LU_STATE_NULL
);
95 /* Otherwise only accept live update requests with a valid state. */
96 is_valid_state
= is_valid_state
|| sef_cbs
.sef_cb_lu_state_isvalid(state
);
98 if(sef_cbs
.sef_cb_lu_state_isvalid
== SEF_CB_LU_STATE_ISVALID_NULL
) {
102 sef_lu_ready(EINVAL
);
106 /* Set the new live update state. */
107 sef_lu_state
= state
;
109 /* If the live update state changed, let the callback code
112 if(old_state
!= sef_lu_state
) {
113 sef_cbs
.sef_cb_lu_state_changed(old_state
, sef_lu_state
);
117 /* Return OK not to let anybody else intercept the request. */
121 /*===========================================================================*
123 *===========================================================================*/
124 static void sef_lu_ready(int result
)
130 sef_lu_debug_begin();
131 sef_lu_dprint("%s, cycle=%d. Ready to update with result: %d%s\n",
132 sef_debug_header(), sef_lu_debug_cycle
,
133 result
, (result
== OK
? "(OK)" : ""));
137 /* If result is OK, let the callback code save
138 * any state that must be carried over to the new version.
141 r
= sef_cbs
.sef_cb_lu_state_save(sef_lu_state
);
143 /* Abort update if callback returned error. */
148 /* Let the callback code produce a live update response and block.
149 * We should get beyond this point only if either result is an error or
150 * something else goes wrong in the callback code.
152 m
.m_source
= sef_self_endpoint
;
153 m
.m_type
= RS_LU_PREPARE
;
154 m
.RS_LU_STATE
= sef_lu_state
;
155 m
.RS_LU_RESULT
= result
;
156 r
= sef_cbs
.sef_cb_lu_response(&m
);
159 sef_lu_debug_begin();
160 sef_lu_dprint("%s, cycle=%d. The %s aborted the update with result %d!\n",
161 sef_debug_header(), sef_lu_debug_cycle
,
162 (result
== OK
? "server" : "client"),
163 (result
== OK
? r
: result
)); /* EINTR if update was canceled. */
167 /* Something went wrong. Update was aborted and we didn't get updated.
168 * Restore things back to normal and continue executing.
170 old_state
= sef_lu_state
;
171 sef_lu_state
= SEF_LU_STATE_NULL
;
172 if(old_state
!= sef_lu_state
) {
173 sef_cbs
.sef_cb_lu_state_changed(old_state
, sef_lu_state
);
177 /*===========================================================================*
178 * sef_setcb_lu_prepare *
179 *===========================================================================*/
180 void sef_setcb_lu_prepare(sef_cb_lu_prepare_t cb
)
183 sef_cbs
.sef_cb_lu_prepare
= cb
;
186 /*===========================================================================*
187 * sef_setcb_lu_state_isvalid *
188 *===========================================================================*/
189 void sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_t cb
)
192 sef_cbs
.sef_cb_lu_state_isvalid
= cb
;
195 /*===========================================================================*
196 * sef_setcb_lu_state_changed *
197 *===========================================================================*/
198 void sef_setcb_lu_state_changed(sef_cb_lu_state_changed_t cb
)
201 sef_cbs
.sef_cb_lu_state_changed
= cb
;
204 /*===========================================================================*
205 * sef_setcb_lu_state_dump *
206 *===========================================================================*/
207 void sef_setcb_lu_state_dump(sef_cb_lu_state_dump_t cb
)
210 sef_cbs
.sef_cb_lu_state_dump
= cb
;
213 /*===========================================================================*
214 * sef_setcb_lu_state_save *
215 *===========================================================================*/
216 void sef_setcb_lu_state_save(sef_cb_lu_state_save_t cb
)
219 sef_cbs
.sef_cb_lu_state_save
= cb
;
222 /*===========================================================================*
223 * sef_setcb_lu_response *
224 *===========================================================================*/
225 void sef_setcb_lu_response(sef_cb_lu_response_t cb
)
228 sef_cbs
.sef_cb_lu_response
= cb
;
231 /*===========================================================================*
232 * sef_cb_lu_prepare_null *
233 *===========================================================================*/
234 int sef_cb_lu_prepare_null(int UNUSED(state
))
239 /*===========================================================================*
240 * sef_cb_lu_state_isvalid_null *
241 *===========================================================================*/
242 int sef_cb_lu_state_isvalid_null(int UNUSED(state
))
247 /*===========================================================================*
248 * sef_cb_lu_state_changed_null *
249 *===========================================================================*/
250 void sef_cb_lu_state_changed_null(int UNUSED(old_state
),
255 /*===========================================================================*
256 * sef_cb_lu_state_dump_null *
257 *===========================================================================*/
258 void sef_cb_lu_state_dump_null(int UNUSED(state
))
260 sef_lu_dprint("NULL\n");
263 /*===========================================================================*
264 * sef_cb_lu_state_save_null *
265 *===========================================================================*/
266 int sef_cb_lu_state_save_null(int UNUSED(result
))
271 /*===========================================================================*
272 * sef_cb_lu_response_null *
273 *===========================================================================*/
274 int sef_cb_lu_response_null(message
* UNUSED(m_ptr
))
279 /*===========================================================================*
280 * sef_cb_lu_prepare_always_ready *
281 *===========================================================================*/
282 int sef_cb_lu_prepare_always_ready(int UNUSED(state
))
287 /*===========================================================================*
288 * sef_cb_lu_prepare_never_ready *
289 *===========================================================================*/
290 int sef_cb_lu_prepare_never_ready(int UNUSED(state
))
293 sef_lu_debug_begin();
294 sef_lu_dprint("%s, cycle=%d. Simulating a service never ready to update...\n",
295 sef_debug_header(), sef_lu_debug_cycle
);
302 /*===========================================================================*
303 * sef_cb_lu_prepare_crash *
304 *===========================================================================*/
305 int sef_cb_lu_prepare_crash(int UNUSED(state
))
307 panic("Simulating a crash at update prepare time...");
312 /*===========================================================================*
313 * sef_cb_lu_state_isvalid_standard *
314 *===========================================================================*/
315 int sef_cb_lu_state_isvalid_standard(int state
)
317 return SEF_LU_STATE_IS_STANDARD(state
);
320 /*===========================================================================*
321 * sef_cb_lu_state_isvalid_workfree *
322 *===========================================================================*/
323 int sef_cb_lu_state_isvalid_workfree(int state
)
325 return (state
== SEF_LU_STATE_WORK_FREE
);
328 /*===========================================================================*
329 * sef_cb_lu_response_rs_reply *
330 *===========================================================================*/
331 int sef_cb_lu_response_rs_reply(message
*m_ptr
)
335 /* Inform RS that we're ready with the given result. */
336 r
= sendrec(RS_PROC_NR
, m_ptr
);
341 return m_ptr
->m_type
== RS_LU_PREPARE
? EINTR
: m_ptr
->m_type
;