xref: /minix/minix/lib/libsys/sef_liveupdate.c (revision 83133719)
1 #include "syslib.h"
2 #include <assert.h>
3 #include <minix/sysutil.h>
4 
5 /* SEF Live update variables. */
6 static int sef_lu_state;
7 
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;
16 } sef_cbs = {
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
23 };
24 
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);
28 
29 /* SEF Live update helpers. */
30 static void sef_lu_ready(int result);
31 
32 /* Debug. */
33 EXTERN char* sef_debug_header(void);
34 static int sef_lu_debug_cycle = 0;
35 
36 /* Information about SELF. */
37 EXTERN endpoint_t sef_self_endpoint;
38 EXTERN int sef_self_first_receive_done;
39 
40 /*===========================================================================*
41  *                         do_sef_lu_before_receive             	     *
42  *===========================================================================*/
43 void do_sef_lu_before_receive(void)
44 {
45 /* Handle SEF Live update before receive events. */
46   int r;
47 
48   /* Initialize on first receive. */
49   if(!sef_self_first_receive_done) {
50       sef_lu_state = SEF_LU_STATE_NULL;
51   }
52 
53   /* Nothing to do if we are not preparing for a live update. */
54   if(sef_lu_state == SEF_LU_STATE_NULL) {
55       return;
56   }
57 
58   /* Debug. */
59 #if SEF_LU_DEBUG
60   sef_lu_debug_cycle++;
61   sef_lu_debug_begin();
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);
65   sef_lu_debug_end();
66 #endif
67 
68   /* Let the callback code handle the event.
69    * For SEF_LU_STATE_WORK_FREE, we're always ready, tell immediately.
70    */
71   r = OK;
72   if(sef_lu_state != SEF_LU_STATE_WORK_FREE) {
73       r = sef_cbs.sef_cb_lu_prepare(sef_lu_state);
74   }
75   if(r == OK) {
76       sef_lu_ready(OK);
77   }
78 }
79 
80 /*===========================================================================*
81  *                               do_sef_lu_request              	     *
82  *===========================================================================*/
83 int do_sef_lu_request(message *m_ptr)
84 {
85 /* Handle a SEF Live update request. */
86   int state, old_state, is_valid_state;
87 
88   sef_lu_debug_cycle = 0;
89   old_state = sef_lu_state;
90   state = m_ptr->m_rs_update.state;
91 
92   /* Deal with prepare cancel requests first. */
93   is_valid_state = (state == SEF_LU_STATE_NULL);
94 
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);
97   if(!is_valid_state) {
98       if(sef_cbs.sef_cb_lu_state_isvalid == SEF_CB_LU_STATE_ISVALID_NULL) {
99           sef_lu_ready(ENOSYS);
100       }
101       else {
102           sef_lu_ready(EINVAL);
103       }
104   }
105   else {
106       /* Set the new live update state. */
107       sef_lu_state = state;
108 
109       /* If the live update state changed, let the callback code
110        * handle the rest.
111        */
112       if(old_state != sef_lu_state) {
113           sef_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state);
114       }
115   }
116 
117   /* Return OK not to let anybody else intercept the request. */
118   return(OK);
119 }
120 
121 /*===========================================================================*
122  *				  sef_lu_ready				     *
123  *===========================================================================*/
124 static void sef_lu_ready(int result)
125 {
126   message m;
127   int old_state, r;
128 
129 #if SEF_LU_DEBUG
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)" : ""));
134   sef_lu_debug_end();
135 #endif
136 
137   /* If result is OK, let the callback code save
138    * any state that must be carried over to the new version.
139    */
140   if(result == OK) {
141       r = sef_cbs.sef_cb_lu_state_save(sef_lu_state);
142       if(r != OK) {
143           /* Abort update if callback returned error. */
144           result = r;
145       }
146   }
147 
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.
151    */
152   m.m_source = sef_self_endpoint;
153   m.m_type = RS_LU_PREPARE;
154   m.m_rs_update.state = sef_lu_state;
155   m.m_rs_update.result = result;
156   r = sef_cbs.sef_cb_lu_response(&m);
157 
158 #if SEF_LU_DEBUG
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. */
164   sef_lu_debug_end();
165 #endif
166 
167   /* Something went wrong. Update was aborted and we didn't get updated.
168    * Restore things back to normal and continue executing.
169    */
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);
174   }
175 }
176 
177 /*===========================================================================*
178  *                            sef_setcb_lu_prepare                           *
179  *===========================================================================*/
180 void sef_setcb_lu_prepare(sef_cb_lu_prepare_t cb)
181 {
182   assert(cb != NULL);
183   sef_cbs.sef_cb_lu_prepare = cb;
184 }
185 
186 /*===========================================================================*
187  *                         sef_setcb_lu_state_isvalid                        *
188  *===========================================================================*/
189 void sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_t cb)
190 {
191   assert(cb != NULL);
192   sef_cbs.sef_cb_lu_state_isvalid = cb;
193 }
194 
195 /*===========================================================================*
196  *                         sef_setcb_lu_state_changed                        *
197  *===========================================================================*/
198 void sef_setcb_lu_state_changed(sef_cb_lu_state_changed_t cb)
199 {
200   assert(cb != NULL);
201   sef_cbs.sef_cb_lu_state_changed = cb;
202 }
203 
204 /*===========================================================================*
205  *                          sef_setcb_lu_state_dump                          *
206  *===========================================================================*/
207 void sef_setcb_lu_state_dump(sef_cb_lu_state_dump_t cb)
208 {
209   assert(cb != NULL);
210   sef_cbs.sef_cb_lu_state_dump = cb;
211 }
212 
213 /*===========================================================================*
214  *                          sef_setcb_lu_state_save                           *
215  *===========================================================================*/
216 void sef_setcb_lu_state_save(sef_cb_lu_state_save_t cb)
217 {
218   assert(cb != NULL);
219   sef_cbs.sef_cb_lu_state_save = cb;
220 }
221 
222 /*===========================================================================*
223  *                          sef_setcb_lu_response                            *
224  *===========================================================================*/
225 void sef_setcb_lu_response(sef_cb_lu_response_t cb)
226 {
227   assert(cb != NULL);
228   sef_cbs.sef_cb_lu_response = cb;
229 }
230 
231 /*===========================================================================*
232  *      	            sef_cb_lu_prepare_null 	 	             *
233  *===========================================================================*/
234 int sef_cb_lu_prepare_null(int UNUSED(state))
235 {
236   return ENOTREADY;
237 }
238 
239 /*===========================================================================*
240  *      	         sef_cb_lu_state_isvalid_null		             *
241  *===========================================================================*/
242 int sef_cb_lu_state_isvalid_null(int UNUSED(state))
243 {
244   return FALSE;
245 }
246 
247 /*===========================================================================*
248  *                       sef_cb_lu_state_changed_null        		     *
249  *===========================================================================*/
250 void sef_cb_lu_state_changed_null(int UNUSED(old_state),
251    int UNUSED(state))
252 {
253 }
254 
255 /*===========================================================================*
256  *                       sef_cb_lu_state_dump_null        		     *
257  *===========================================================================*/
258 void sef_cb_lu_state_dump_null(int UNUSED(state))
259 {
260   sef_lu_dprint("NULL\n");
261 }
262 
263 /*===========================================================================*
264  *                       sef_cb_lu_state_save_null        		     *
265  *===========================================================================*/
266 int sef_cb_lu_state_save_null(int UNUSED(result))
267 {
268   return OK;
269 }
270 
271 /*===========================================================================*
272  *                       sef_cb_lu_response_null        		     *
273  *===========================================================================*/
274 int sef_cb_lu_response_null(message * UNUSED(m_ptr))
275 {
276   return ENOSYS;
277 }
278 
279 /*===========================================================================*
280  *      	       sef_cb_lu_prepare_always_ready	                     *
281  *===========================================================================*/
282 int sef_cb_lu_prepare_always_ready(int UNUSED(state))
283 {
284   return OK;
285 }
286 
287 /*===========================================================================*
288  *      	       sef_cb_lu_prepare_never_ready	                     *
289  *===========================================================================*/
290 int sef_cb_lu_prepare_never_ready(int UNUSED(state))
291 {
292 #if SEF_LU_DEBUG
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);
296   sef_lu_debug_end();
297 #endif
298 
299   return ENOTREADY;
300 }
301 
302 /*===========================================================================*
303  *      	         sef_cb_lu_prepare_crash	                     *
304  *===========================================================================*/
305 int sef_cb_lu_prepare_crash(int UNUSED(state))
306 {
307   panic("Simulating a crash at update prepare time...");
308 
309   return OK;
310 }
311 
312 /*===========================================================================*
313  *      	      sef_cb_lu_state_isvalid_standard                       *
314  *===========================================================================*/
315 int sef_cb_lu_state_isvalid_standard(int state)
316 {
317   return SEF_LU_STATE_IS_STANDARD(state);
318 }
319 
320 /*===========================================================================*
321  *      	      sef_cb_lu_state_isvalid_workfree                       *
322  *===========================================================================*/
323 int sef_cb_lu_state_isvalid_workfree(int state)
324 {
325   return (state == SEF_LU_STATE_WORK_FREE);
326 }
327 
328 /*===========================================================================*
329  *                       sef_cb_lu_response_rs_reply        		     *
330  *===========================================================================*/
331 int sef_cb_lu_response_rs_reply(message *m_ptr)
332 {
333   int r;
334 
335   /* Inform RS that we're ready with the given result. */
336   r = ipc_sendrec(RS_PROC_NR, m_ptr);
337   if ( r != OK) {
338       return r;
339   }
340 
341   return m_ptr->m_type == RS_LU_PREPARE ? EINTR : m_ptr->m_type;
342 }
343 
344