1 : /*
2 : * This file is part of MIN Test Framework. Copyright © 2008 Nokia Corporation
3 : * and/or its subsidiary(-ies).
4 : * Contact: Sampo Saaristo
5 : * Contact e-mail: DG.MIN-Support@nokia.com
6 : *
7 : * This program is free software: you can redistribute it and/or modify it
8 : * under the terms of the GNU General Public License as published by the Free
9 : * Software Foundation, version 2 of the License.
10 : *
11 : * This program is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 : * more details. You should have received a copy of the GNU General Public
15 : * License along with this program. If not, see
16 : * <http://www.gnu.org/licenses/>.
17 : */
18 :
19 :
20 : /**
21 : * @file tec_events.c
22 : * @version 0.1
23 : * @brief This file contains implementation of engine part of MIN
24 : * event system
25 : */
26 :
27 : /* ------------------------------------------------------------------------- */
28 : /* INCLUDE FILES */
29 : #include <tec.h>
30 : #include <tec_events.h>
31 : #include <min_common.h>
32 : #include <min_test_event_if.h>
33 :
34 : /* ------------------------------------------------------------------------- */
35 : /* EXTERNAL DATA STRUCTURES */
36 : /* None */
37 :
38 : /* ------------------------------------------------------------------------- */
39 : /* EXTERNAL FUNCTION PROTOTYPES */
40 : /* None */
41 :
42 : /* ------------------------------------------------------------------------- */
43 : /* CONSTANTS */
44 : /* None */
45 :
46 : /* ------------------------------------------------------------------------- */
47 : /* MACROS */
48 : /* None */
49 :
50 : /* ------------------------------------------------------------------------- */
51 : /* LOCAL CONSTANTS AND MACROS */
52 : /* None */
53 :
54 : /* ------------------------------------------------------------------------- */
55 : /* MODULE DATA STRUCTURES */
56 : typedef enum {
57 : EState_UNSET,
58 : EState_SET,
59 : EState_UNSET_pending
60 : } Event_state_t;
61 :
62 : typedef enum {
63 : ereg_unset,
64 : ereg_unset_registered,
65 : ereg_waiting_registered, /* Not for state events */
66 : ereg_set,
67 : ereg_set_registered
68 : } event_reg_state_t;
69 :
70 : typedef struct {
71 : minTestEventDescr_t descr_;
72 : Event_state_t state_;
73 : DLList *registrations_;
74 : minEventSrc_t controller_;
75 : } min_event_t;
76 :
77 : typedef struct {
78 : minEventSrc_t registrar_;
79 : event_reg_state_t regstate_;
80 : min_event_t *backp_;
81 : } e_registration_t;
82 :
83 :
84 : const char *regstate_str[] = {
85 : "unset",
86 : "unset registered",
87 : "waiting registered",
88 : "unset pending",
89 : "set",
90 : "set registered"
91 : };
92 :
93 : DLList *state_events, *ind_events;
94 :
95 :
96 : /* ------------------------------------------------------------------------- */
97 : /* LOCAL FUNCTION PROTOTYPES */
98 :
99 : /** List comparison function for events. Passed as an arg to dl_list_find().
100 : * The event is searched by event name.
101 : * @param list_data list item data to be compared
102 : * @param user_data the data searched.
103 : * @returns a matching event if found, INITPTR if not found
104 : *
105 : */
106 : LOCAL int event_comp (const void *list_data, const void *user_data);
107 :
108 : /** Checks if the pid is already registered for the event.
109 : * @param event the event registartion list of which is searched
110 : * @param registrar the pid to be searched
111 : * @returns 1 if registrar is already registered for the event, 0 if not
112 : */
113 : LOCAL int event_is_registered (min_event_t * event,
114 : minEventSrc_t * registrar);
115 :
116 : /** Adds a registration for the event
117 : * @param event the event to be registered for
118 : * @param registrar the pid of registrating process
119 : * @returns pointer to event registration entry
120 : */
121 : LOCAL e_registration_t *event_add_registration (min_event_t * event,
122 : minEventSrc_t * registrar);
123 :
124 : /** Removes a registration from the event
125 : * @param event the event to be unregistered for
126 : * @param registrar the pid of unregistrating process
127 : * @returns 0 if the registration is found and removed,
128 : * 1 if no registration is found.
129 : */
130 : LOCAL int event_del_registration (min_event_t * event,
131 : minEventSrc_t * registrar);
132 :
133 : /** Searches for registration entry on the event
134 : * @param event the event to be searched
135 : * @param registrar the pid of searched process
136 : * @returns pointer to the event registration if found
137 : * INITPTR if no registration is found.
138 : */
139 : LOCAL e_registration_t *event_find_registration (min_event_t * event,
140 : minEventSrc_t * registrar,
141 : DLListIterator * itp);
142 :
143 : /** Delete event from the list of events
144 : * @param it the list iterator containing the event
145 : * @param event event to removed
146 : */
147 : LOCAL void del_event (DLListIterator it, min_event_t * event);
148 :
149 : /** Add event to the list of indication events
150 : * @param param the description of event to be added
151 : * @returns a pointer to the event or INITPTR if event by that name exists
152 : */
153 : LOCAL min_event_t *add_ind_event (minTestEventParam_t * param);
154 :
155 : /** Add event to the list of state events
156 : * @param param the description of event to be added
157 : * @returns a pointer to the event or INITPTR if event by that name exists
158 : */
159 : LOCAL min_event_t *add_state_event (minTestEventParam_t * param);
160 :
161 :
162 : /** Searches for indication event
163 : * @param param the event describtion of the event to be searched
164 : * @param [IN/OUT] it used to return also the address of the list iterator
165 : * @returns pointer to the event if found, INITPTR if not
166 : */
167 : LOCAL min_event_t *find_ind_event (minTestEventParam_t * param,
168 : DLListIterator * it);
169 :
170 : /** Searches for state event
171 : * @param param the event describtion of the event to be searched
172 : * @param [IN/OUT] it used to return also the address of the list iterator
173 : * @returns pointer to the event if found, INITPTR if not
174 : */
175 : LOCAL min_event_t *find_state_event (minTestEventParam_t * param,
176 : DLListIterator * it);
177 :
178 : /** Sends EVENT_IND IPC message to TMC with pid mathing the argument
179 : * @param receiver pid of the receiving process
180 : * @param status ok/err to be informed to TP
181 : */
182 : LOCAL void send_event_ind (minEventSrc_t * reveicer, int status);
183 :
184 : /** Handles the SET event on a state event registration.
185 : * @param data pointer to event registrations
186 : */
187 : LOCAL void do_set_on_state_reg (void *data);
188 :
189 : /** Handles the SET event on an indication event registration.
190 : * @param data pointer to event registrations
191 : */
192 : LOCAL void do_set_on_ind_reg (void *data);
193 :
194 : /** The state change of an event registrations is done by calling this func
195 : * @param ereg the event registration entry
196 : * @param next_state the state we are making the transition to
197 : */
198 : LOCAL void registration_state_change (e_registration_t * ereg,
199 : event_reg_state_t next_state);
200 :
201 : /** Build and send remote event request response
202 : * @param eventname name of the event
203 : * @param status set, active, error
204 : * @param etype state or indication
205 : */
206 : LOCAL void remote_event_req_response (char *eventname, int status,
207 : TEventType_t etype);
208 :
209 : /** Build and send remote event release response
210 : * @param eventname name of the event
211 : * @param status set, active, error
212 : */
213 : LOCAL void remote_event_rel_response (char *eventname, int status);
214 : /* ------------------------------------------------------------------------- */
215 : /* FORWARD DECLARATIONS */
216 : /* None */
217 :
218 : /* ==================== LOCAL FUNCTIONS ==================================== */
219 : LOCAL int event_comp (const void *list_data, const void *user_data)
220 25 : {
221 : min_event_t *e;
222 : minTestEventParam_t *p;
223 :
224 25 : e = (min_event_t *) list_data;
225 25 : p = (minTestEventParam_t *) user_data;
226 :
227 25 : return strncmp (e->descr_.event_name_, p->event.event_name_,
228 : MaxMinEventName);
229 : }
230 :
231 : LOCAL void
232 : registration_state_change (e_registration_t * ereg,
233 : event_reg_state_t next_state)
234 9 : {
235 : event_reg_state_t cur_state;
236 :
237 9 : cur_state = ereg->regstate_;
238 9 : MIN_DEBUG ("Event reg state change: %s -> %s\n",
239 : regstate_str[cur_state], regstate_str[next_state]);
240 :
241 9 : ereg->regstate_ = next_state;
242 9 : }
243 :
244 : LOCAL e_registration_t *event_find_registration (min_event_t * event,
245 : minEventSrc_t * registrar,
246 : DLListIterator * itp)
247 18 : {
248 : DLListIterator it;
249 : e_registration_t *reg;
250 :
251 18 : for (it = dl_list_head (event->registrations_);
252 19 : it != DLListNULLIterator; it = dl_list_next (it)) {
253 14 : reg = (e_registration_t *) dl_list_data (it);
254 14 : if (reg->registrar_.pid == registrar->pid) {
255 13 : if (itp != NULL)
256 0 : *itp = it;
257 13 : return reg;
258 : }
259 : }
260 5 : return INITPTR;
261 : }
262 :
263 : LOCAL int
264 : event_is_registered (min_event_t * event, minEventSrc_t * registrar)
265 12 : {
266 : e_registration_t *reg;
267 :
268 12 : reg = event_find_registration (event, registrar, NULL);
269 12 : if (reg != INITPTR)
270 7 : return 1;
271 :
272 5 : return 0;
273 : }
274 :
275 : LOCAL void do_set_on_ind_reg (void *data)
276 1 : {
277 : e_registration_t *ereg;
278 :
279 1 : ereg = (e_registration_t *) data;
280 :
281 1 : switch (ereg->regstate_) {
282 : case ereg_waiting_registered:
283 : #ifndef MIN_UNIT_TEST
284 0 : send_event_ind (&ereg->registrar_, EventStatOK);
285 : #endif
286 0 : if (ereg->registrar_.remote)
287 0 : remote_event_req_response (ereg->backp_->descr_.
288 : event_name_,
289 : REM_E_STAT_SET,
290 : EIndication);
291 : else
292 0 : registration_state_change (ereg, ereg_unset_registered);
293 0 : break;
294 : case ereg_unset_registered:
295 1 : registration_state_change (ereg, ereg_set_registered);
296 :
297 1 : break;
298 : default:
299 0 : MIN_WARN ("unhandled state %s",
300 : regstate_str[ereg->regstate_]);
301 0 : return;
302 : }
303 : }
304 :
305 : LOCAL void do_set_on_state_reg (void *data)
306 2 : {
307 : e_registration_t *ereg;
308 :
309 2 : ereg = (e_registration_t *) data;
310 :
311 2 : switch (ereg->regstate_) {
312 : case ereg_waiting_registered:
313 : #ifndef MIN_UNIT_TEST
314 0 : send_event_ind (&ereg->registrar_, EventStatOK);
315 : #endif
316 1 : if (ereg->registrar_.remote)
317 0 : remote_event_req_response (ereg->backp_->descr_.
318 : event_name_,
319 : REM_E_STAT_SET, EState);
320 : else
321 1 : registration_state_change (ereg, ereg_set_registered);
322 1 : break;
323 : case ereg_unset_registered:
324 1 : registration_state_change (ereg, ereg_set_registered);
325 :
326 1 : break;
327 : default:
328 0 : MIN_WARN ("%s unhandled state %s", __FUNCTION__,
329 : regstate_str[ereg->regstate_]);
330 0 : return;
331 : }
332 : }
333 :
334 :
335 : LOCAL min_event_t *add_ind_event (minTestEventParam_t * param)
336 10 : {
337 : min_event_t *e;
338 :
339 10 : if (param->event.event_type_ != EIndication) {
340 1 : MIN_WARN ("invalid event type");
341 1 : return INITPTR;
342 : }
343 9 : e = NEW (min_event_t);
344 9 : e->registrations_ = dl_list_create ();
345 9 : e->descr_ = param->event;
346 9 : param->event.event_name_ = NULL;
347 9 : dl_list_add (ind_events, e);
348 :
349 9 : return e;
350 : }
351 :
352 : LOCAL min_event_t *add_state_event (minTestEventParam_t * param)
353 13 : {
354 : min_event_t *e;
355 :
356 13 : if (param->event.event_type_ != EState) {
357 1 : MIN_WARN ("%s: invalid event type", __FUNCTION__);
358 1 : return INITPTR;
359 : }
360 12 : e = NEW (min_event_t);
361 12 : e->registrations_ = dl_list_create ();
362 12 : if (e == NULL || e->registrations_ == NULL) {
363 0 : MIN_FATAL ("%s OOM situation!");
364 0 : return INITPTR;
365 : }
366 12 : e->state_ = EState_UNSET;
367 12 : e->descr_ = param->event;
368 12 : param->event.event_name_ = NULL;
369 :
370 12 : dl_list_add (state_events, e);
371 :
372 12 : return e;
373 : }
374 :
375 :
376 : LOCAL e_registration_t *event_add_registration (min_event_t * event,
377 : minEventSrc_t * registrar)
378 14 : {
379 : e_registration_t *reg;
380 :
381 14 : reg = NEW (e_registration_t);
382 14 : reg->registrar_ = *registrar;
383 14 : reg->regstate_ = ereg_unset_registered;
384 14 : reg->backp_ = event;
385 14 : dl_list_add (event->registrations_, reg);
386 14 : return reg;
387 :
388 : }
389 :
390 : LOCAL int
391 : event_del_registration (min_event_t * event, minEventSrc_t * registrar)
392 5 : {
393 : DLListIterator it, next_it;
394 : e_registration_t *reg;
395 :
396 5 : it = dl_list_head (event->registrations_);
397 10 : while (it != DLListNULLIterator) {
398 5 : next_it = dl_list_next (it);
399 5 : reg = (e_registration_t *) dl_list_data (it);
400 5 : if (reg->registrar_.remote == registrar->remote &&
401 : reg->registrar_.pid == registrar->pid) {
402 5 : dl_list_remove_it (it);
403 5 : MIN_DEBUG ("removing registration for %d",
404 : registrar->pid);
405 :
406 5 : DELETE (reg);
407 :
408 5 : return 0;
409 : }
410 0 : it = next_it;
411 : }
412 :
413 0 : return 1;
414 : }
415 :
416 : LOCAL min_event_t *find_ind_event (minTestEventParam_t * param,
417 : DLListIterator * itp)
418 14 : {
419 : DLListIterator it;
420 14 : it = dl_list_find (ind_events->head_, ind_events->tail_, event_comp,
421 : (void *)param);
422 14 : if (itp != NULL)
423 3 : *itp = it;
424 14 : return (min_event_t *) dl_list_data (it);
425 : }
426 :
427 : LOCAL min_event_t *find_state_event (minTestEventParam_t * param,
428 : DLListIterator * itp)
429 31 : {
430 : DLListIterator it;
431 31 : it = dl_list_find (state_events->head_, state_events->tail_,
432 : event_comp, (void *)param);
433 31 : if (itp != NULL)
434 19 : *itp = it;
435 31 : return (min_event_t *) dl_list_data (it);
436 : }
437 :
438 : LOCAL void free_event (void *event)
439 14 : {
440 14 : dl_list_free_data (&((min_event_t *) (event))->registrations_);
441 14 : dl_list_free (&((min_event_t *) (event))->registrations_);
442 :
443 14 : DELETE (((min_event_t *) (event))->descr_.event_name_);
444 14 : DELETE (event);
445 14 : }
446 :
447 : LOCAL void del_event (DLListIterator it, min_event_t * event)
448 7 : {
449 7 : if (dl_list_data (it) != event) {
450 0 : MIN_FATAL ("Fatal pointer error");
451 0 : return;
452 : }
453 7 : dl_list_remove_it (it);
454 7 : free_event ((void *)event);
455 :
456 7 : return;
457 : }
458 :
459 : LOCAL void send_event_ind (minEventSrc_t * receiver, int status)
460 14 : {
461 : MsgBuffer message;
462 :
463 14 : if (receiver->remote == 0) {
464 14 : MIN_DEBUG ("Sending EVENT_IND to %d\n", receiver->pid);
465 14 : message.type_ = MSG_EVENT_IND;
466 14 : message.sender_ = getpid ();
467 14 : message.receiver_ = receiver->pid;
468 14 : message.param_ = status;
469 14 : STRCPY (message.desc_, "\0", MaxDescSize);
470 14 : STRCPY (message.message_, "\0", MaxMsgSize);
471 14 : mq_send_message (mq_id, &message);
472 : } else
473 0 : MIN_DEBUG ("remote event (status %d)", status);
474 14 : }
475 :
476 : /* ======================== FUNCTIONS ====================================== */
477 :
478 : /* ------------------------------------------------------------------------- */
479 : /** Initializes the Event System on engine.
480 : * Create lists of indication and state events.
481 : */
482 : void event_system_init (void)
483 136 : {
484 136 : ind_events = dl_list_create ();
485 136 : state_events = dl_list_create ();
486 136 : }
487 :
488 : /* ------------------------------------------------------------------------- */
489 : /** See if event System is initialized
490 : * @returns 1 if event system is initialize, 0 if not
491 : */
492 : int event_system_up (void)
493 14 : {
494 14 : if (ind_events == INITPTR)
495 0 : return 0;
496 14 : if (state_events == INITPTR)
497 0 : return 0;
498 14 : return 1;
499 :
500 : }
501 :
502 : /* ------------------------------------------------------------------------- */
503 : /** Removes the Event System from the engine.
504 : * Delete lists of indication and state events.
505 : */
506 : void event_system_cleanup (void)
507 31 : {
508 31 : if (dl_list_size (ind_events) > 0)
509 5 : dl_list_foreach (ind_events->head_, ind_events->tail_,
510 : free_event);
511 31 : dl_list_free (&ind_events);
512 :
513 31 : if (dl_list_size (state_events) > 0)
514 2 : dl_list_foreach (state_events->head_, state_events->tail_,
515 : free_event);
516 31 : dl_list_free (&state_events);
517 31 : }
518 :
519 :
520 : /* ------------------------------------------------------------------------- */
521 : /** Handles a SET for Indication Event.
522 : * @param param contains the event description
523 : * @param event_src pid of the setting process.
524 : * @returns 0 on ok, 1 on error
525 : */
526 : int
527 : ind_event_handle_set (minTestEventParam_t * param,
528 : minEventSrc_t * event_src)
529 1 : {
530 : min_event_t *e;
531 : DLListIterator it;
532 1 : e = find_ind_event (param, &it);
533 1 : if (e == INITPTR) {
534 : #ifndef MIN_UNIT_TEST
535 0 : send_event_ind (event_src, EventStatOK);
536 : #endif
537 0 : return 1;
538 :
539 : }
540 :
541 1 : dl_list_foreach (e->registrations_->head_, e->registrations_->tail_,
542 : do_set_on_ind_reg);
543 : #ifndef MIN_UNIT_TEST
544 1 : send_event_ind (event_src, EventStatOK);
545 : #endif
546 1 : return 0;
547 : }
548 :
549 : /* ------------------------------------------------------------------------- */
550 : /** Handles a WAIT for Indication Event.
551 : * @param param contains the event description
552 : * @param event_src pid of the waiting process.
553 : * @returns 0 on ok, 1 on error
554 : */
555 : int
556 : ind_event_handle_wait (minTestEventParam_t * param,
557 : minEventSrc_t * event_src, int *status)
558 2 : {
559 : min_event_t *e;
560 2 : e_registration_t *ereg = INITPTR;
561 :
562 2 : e = find_ind_event (param, NULL);
563 2 : if (e == INITPTR) {
564 0 : MIN_WARN ("Indication event: no event %s found to wait\n",
565 : param->event.event_name_);
566 0 : goto iehw_err_out;
567 : }
568 :
569 2 : ereg = event_find_registration (e, event_src, NULL);
570 :
571 2 : if (ereg == INITPTR) {
572 0 : MIN_WARN ("Indication event: no regisration found %d for "
573 : "event %s\n", event_src->pid,
574 : param->event.event_name_);
575 0 : goto iehw_err_out;
576 :
577 : }
578 :
579 2 : switch (ereg->regstate_) {
580 : case ereg_set_registered:
581 : #ifndef MIN_UNIT_TEST
582 0 : send_event_ind (&ereg->registrar_, EventStatOK);
583 : #endif
584 0 : *status = REM_E_STAT_SET;
585 0 : registration_state_change (ereg, ereg_unset_registered);
586 0 : break;
587 : case ereg_unset_registered:
588 1 : registration_state_change (ereg, ereg_waiting_registered);
589 1 : break;
590 : default:
591 1 : MIN_WARN ("%s unhandled state %s", __FUNCTION__,
592 : regstate_str[ereg->regstate_]);
593 1 : goto iehw_err_out;
594 : break;
595 :
596 : }
597 1 : return 0;
598 1 : iehw_err_out:
599 : #ifndef MIN_UNIT_TEST
600 0 : send_event_ind (event_src, EventStatErr);
601 : #endif
602 :
603 1 : return 1;
604 : }
605 :
606 : /* ------------------------------------------------------------------------- */
607 : /** Handles a REQUEST for Indication Event.
608 : * @param param contains the event description
609 : * @param event_src pid of the registering event.
610 : * @returns 0 if the request can be handled.
611 : */
612 : int
613 : ind_event_handle_request (minTestEventParam_t * param,
614 : minEventSrc_t * event_src)
615 7 : {
616 7 : min_event_t *e = INITPTR;
617 7 : e = find_ind_event (param, NULL);
618 7 : if (e == INITPTR) {
619 6 : e = add_ind_event (param);
620 : } else {
621 1 : if (event_is_registered (e, event_src)) {
622 1 : MIN_WARN ("process %d already registered for "
623 : "event %s\n", event_src->pid,
624 : param->event.event_name_);
625 : #ifndef MIN_UNIT_TEST
626 0 : send_event_ind (event_src, EventStatErr);
627 : #endif
628 1 : return 1;
629 : }
630 : }
631 :
632 6 : event_add_registration (e, event_src);
633 :
634 : #ifndef MIN_UNIT_TEST
635 3 : send_event_ind (event_src, EventStatOK);
636 : #endif
637 :
638 :
639 6 : return 0;
640 : }
641 :
642 : /* ------------------------------------------------------------------------- */
643 : /** Handles a RELEASE of Indication Event.
644 : * @param param contains the event description
645 : * @param event_src pid of the releasing event.
646 : * @returns 0 if the release can be handled.
647 : */
648 : int
649 : ind_event_handle_release (minTestEventParam_t * param,
650 : minEventSrc_t * event_src)
651 2 : {
652 2 : min_event_t *e = INITPTR;
653 : DLListIterator it;
654 2 : e = find_ind_event (param, &it);
655 2 : if (e == INITPTR) {
656 0 : MIN_WARN ("no event %s found\n",
657 : param->event.event_name_);
658 : #ifndef MIN_UNIT_TEST
659 0 : send_event_ind (event_src, EventStatErr);
660 : #endif
661 0 : return 1;
662 : }
663 2 : if (!event_is_registered (e, event_src)) {
664 1 : MIN_WARN ("process %d not registered for event %s\n",
665 : event_src->pid, param->event.event_name_);
666 : #ifndef MIN_UNIT_TEST
667 0 : send_event_ind (event_src, EventStatErr);
668 : #endif
669 1 : return 1;
670 : }
671 :
672 1 : event_del_registration (e, event_src);
673 :
674 1 : if (dl_list_size (e->registrations_) == 0)
675 1 : del_event (it, e);
676 :
677 : #ifndef MIN_UNIT_TEST
678 0 : send_event_ind (event_src, EventStatOK);
679 : #endif
680 :
681 1 : return 0;
682 : }
683 :
684 : /* ------------------------------------------------------------------------- */
685 : /** Handles a SET for State Event.
686 : * @param param contains the event description
687 : * @param event_src pid of the setting process.
688 : * @returns 0 on ok, 1 on error
689 : */
690 : int
691 : state_event_handle_set (minTestEventParam_t * param,
692 : minEventSrc_t * event_src)
693 9 : {
694 : min_event_t *e;
695 : DLListIterator it;
696 9 : e = find_state_event (param, &it);
697 9 : if (e == INITPTR) {
698 6 : e = add_state_event (param);
699 : }
700 9 : if (e->state_ != EState_UNSET) {
701 1 : MIN_DEBUG ("State Event %s in state %s\n",
702 : e->descr_.event_name_,
703 : (e->state_ ==
704 : EState_SET) ? "SET" : "UNSET PENDING");
705 : #ifndef MIN_UNIT_TEST
706 0 : send_event_ind (event_src, EventStatOK);
707 : #endif
708 1 : return 1;
709 : }
710 8 : e->state_ = EState_SET;
711 8 : dl_list_foreach (e->registrations_->head_, e->registrations_->tail_,
712 : do_set_on_state_reg);
713 :
714 : #ifndef MIN_UNIT_TEST
715 3 : send_event_ind (event_src, EventStatOK);
716 : #endif
717 :
718 8 : return 0;
719 : }
720 :
721 : /* ------------------------------------------------------------------------- */
722 : /** Handles a UNSET for State Event.
723 : * @param param contains the event description
724 : * @param event_src pid of the setting process.
725 : * @returns 0 on ok, 1 on error
726 : */
727 : int
728 : state_event_handle_unset (minTestEventParam_t * param,
729 : minEventSrc_t * event_src)
730 6 : {
731 : min_event_t *e;
732 : DLListIterator it;
733 6 : e = find_state_event (param, &it);
734 :
735 6 : if (e == INITPTR) {
736 1 : MIN_WARN ("%s no State Event %s found\n", __FUNCTION__,
737 : param->event.event_name_);
738 :
739 1 : goto sehu_err_out;
740 : }
741 :
742 5 : if (e->state_ != EState_SET) {
743 0 : MIN_WARN ("%s State Event %s in state %s\n",
744 : __FUNCTION__,
745 : param->event.event_name_,
746 : (e->state_ ==
747 : EState_UNSET) ? "UNSET" : "UNSET PENDING");
748 0 : goto sehu_err_out;
749 : }
750 :
751 5 : if (dl_list_size (e->registrations_)) {
752 0 : MIN_WARN ("State Event %s still has %d registrations "
753 : "UNSET pending",
754 : param->event.event_name_,
755 : dl_list_size (e->registrations_));
756 0 : e->state_ = EState_UNSET_pending;
757 0 : e->controller_ = *event_src;
758 : } else {
759 : #ifndef MIN_UNIT_TEST
760 1 : send_event_ind (event_src, EventStatOK);
761 : #endif
762 5 : del_event (it, e);
763 : }
764 5 : return 0;
765 1 : sehu_err_out:
766 : #ifndef MIN_UNIT_TEST
767 0 : send_event_ind (event_src, EventStatErr);
768 : #endif
769 1 : return 1;
770 : }
771 :
772 :
773 : /* ------------------------------------------------------------------------- */
774 : /** Handles a WAIT for State Event.
775 : * @param param contains the event description
776 : * @param event_src pid of the waiting process.
777 : * @returns 0 on ok, 1 on error
778 : */
779 : int
780 : state_event_handle_wait (minTestEventParam_t * param,
781 : minEventSrc_t * event_src, int *status)
782 4 : {
783 : min_event_t *e;
784 : e_registration_t *ereg;
785 :
786 4 : e = find_state_event (param, NULL);
787 4 : if (e == INITPTR) {
788 0 : MIN_WARN ("State event: no event %s found to wait\n",
789 : param->event.event_name_);
790 0 : goto sehw_err_out;
791 : }
792 :
793 4 : ereg = event_find_registration (e, event_src, NULL);
794 :
795 4 : if (ereg == INITPTR) {
796 0 : MIN_WARN ("State event: no regisration found %d for "
797 : "event %s\n", event_src,
798 : param->event.event_name_);
799 0 : goto sehw_err_out;
800 : }
801 :
802 4 : if (ereg->regstate_ != ereg_unset_registered &&
803 : ereg->regstate_ != ereg_set_registered) {
804 1 : MIN_WARN ("State event: %d already waiting for event %s\n",
805 : event_src->pid, param->event.event_name_);
806 1 : goto sehw_err_out;
807 : }
808 :
809 3 : switch (e->state_) {
810 : case EState_SET:
811 : case EState_UNSET_pending:
812 : #ifndef MIN_UNIT_TEST
813 1 : send_event_ind (&ereg->registrar_, EventStatOK);
814 : #endif
815 2 : *status = REM_E_STAT_SET;
816 2 : registration_state_change (ereg, ereg_set_registered);
817 2 : break;
818 : case EState_UNSET:
819 1 : registration_state_change (ereg, ereg_waiting_registered);
820 1 : break;
821 : default:
822 0 : MIN_WARN ("%s unhandled state %d\n", __FUNCTION__);
823 0 : goto sehw_err_out;
824 : break;
825 : }
826 3 : return 0;
827 1 : sehw_err_out:
828 : #ifndef MIN_UNIT_TEST
829 0 : send_event_ind (event_src, EventStatErr);
830 : #endif
831 1 : return 1;
832 : }
833 :
834 : /* ------------------------------------------------------------------------- */
835 : /** Handles a REQUEST for State Event.
836 : * @param param contains the event description
837 : * @param event_src pid of the registering event.
838 : * @returns 0 if the request can be handled.
839 : */
840 : int
841 : state_event_handle_request (minTestEventParam_t * param,
842 : minEventSrc_t * event_src)
843 8 : {
844 8 : min_event_t *e = INITPTR;
845 : e_registration_t *ereg;
846 :
847 8 : e = find_state_event (param, NULL);
848 8 : if (e == INITPTR) {
849 5 : e = add_state_event (param);
850 : } else {
851 3 : if (event_is_registered (e, event_src)) {
852 1 : MIN_WARN ("process %d already registered for "
853 : "event %s\n", event_src->pid,
854 : param->event.event_name_);
855 : #ifndef MIN_UNIT_TEST
856 0 : send_event_ind (event_src, EventStatErr);
857 : #endif
858 1 : return 1;
859 : }
860 : }
861 :
862 7 : ereg = event_add_registration (e, event_src);
863 7 : if (e->state_ == EState_SET) {
864 2 : registration_state_change (ereg, ereg_set_registered);
865 : }
866 : #ifndef MIN_UNIT_TEST
867 4 : send_event_ind (event_src, EventStatOK);
868 : #endif
869 :
870 7 : return 0;
871 : }
872 :
873 : /* ------------------------------------------------------------------------- */
874 : /** Handles a RELEASE of State Event.
875 : * @param param contains the event description
876 : * @param event_src pid of the releasing event.
877 : * @returns 0 if the release can be handled.
878 : */
879 : int
880 : state_event_handle_release (minTestEventParam_t * param,
881 : minEventSrc_t * event_src)
882 4 : {
883 4 : min_event_t *e = INITPTR;
884 : DLListIterator it;
885 4 : e = find_state_event (param, &it);
886 4 : if (e == INITPTR) {
887 1 : MIN_WARN ("%s: no event %s found\n",
888 : __FUNCTION__, param->event.event_name_);
889 :
890 : #ifndef MIN_UNIT_TEST
891 0 : send_event_ind (event_src, EventStatErr);
892 : #endif
893 1 : return 1;
894 : }
895 3 : if (!event_is_registered (e, event_src)) {
896 0 : MIN_WARN ("process %d not registered for event %s\n",
897 : event_src->pid, param->event.event_name_);
898 :
899 : #ifndef MIN_UNIT_TEST
900 0 : send_event_ind (event_src, EventStatErr);
901 : #endif
902 0 : return 1;
903 : }
904 :
905 3 : event_del_registration (e, event_src);
906 :
907 3 : if (dl_list_size (e->registrations_) == 0 && e->state_ != EState_SET) {
908 1 : if (e->state_ == EState_UNSET_pending)
909 0 : send_event_ind (&e->controller_, EventStatOK);
910 1 : del_event (it, e);
911 : }
912 : #ifndef MIN_UNIT_TEST
913 1 : send_event_ind (event_src, EventStatOK);
914 : #endif
915 3 : return 0;
916 : }
917 :
918 : LOCAL void
919 : remote_event_req_response (char *eventname, int status, TEventType_t etype)
920 0 : {
921 : char *buff;
922 :
923 0 : buff =
924 : NEW2 (char,
925 : strlen ("remote request active type state") +
926 : MaxMinEventName);
927 :
928 0 : sprintf (buff, "remote request %s %s",
929 : status == REM_E_STAT_SET ? "set" :
930 : (status == REM_E_STAT_ACTIVE ? "active" : "error"),
931 : eventname);
932 0 : if (etype == EState)
933 0 : sprintf (buff + strlen (buff), " type=state");
934 :
935 0 : send_to_master (0, buff);
936 :
937 0 : DELETE (buff);
938 0 : }
939 :
940 : LOCAL void remote_event_rel_response (char *eventname, int status)
941 0 : {
942 : char *buff;
943 :
944 0 : buff = NEW2 (char, strlen ("remote release ") + MaxMinEventName);
945 :
946 0 : sprintf (buff, "remote release %s", eventname);
947 :
948 0 : send_to_master (0, buff);
949 :
950 0 : DELETE (buff);
951 :
952 0 : }
953 :
954 : /** Handles remote event commands arriving over external controller
955 : * @param command Event command
956 : * @param parameters command parameters
957 : */
958 : int
959 : handle_remote_event (TScripterKeyword command, MinItemParser * parameters)
960 0 : {
961 0 : char *token = INITPTR, *token2 = INITPTR;
962 : int status;
963 : minTestEventParam_t param;
964 : minEventSrc_t event_src;
965 : min_event_t *e;
966 :
967 0 : event_src.pid = -1;
968 0 : event_src.remote = 1;
969 :
970 0 : mip_get_next_string (parameters, &token);
971 :
972 0 : if (token == INITPTR) {
973 0 : MIN_WARN ("%s: missing event name", __FUNCTION__);
974 0 : goto err_out;
975 : }
976 :
977 0 : param.event.event_name_ = NEW2 (char, strlen (token) + 1);
978 0 : STRCPY (param.event.event_name_, token, MaxMinEventName);
979 :
980 0 : switch (command) {
981 : case EKeywordRequest:
982 0 : param.command_ = EReqEvent;
983 :
984 :
985 0 : if (mip_get_next_tagged_string (parameters, "type", &token2)
986 : == ENOERR) {
987 0 : if (strcmp (token2, "state"))
988 0 : MIN_WARN ("unknown type=%s", token2);
989 : else {
990 0 : param.event.event_type_ = EState;
991 0 : status =
992 : state_event_handle_request (¶m,
993 : &event_src);
994 0 : if (!status) {
995 : /*
996 : * Remote request is
997 : * also implicit wait
998 : */
999 0 : param.command_ = EWaitEvent;
1000 0 : if (!param.event.event_name_) {
1001 0 : param.event.event_name_ =
1002 : NEW2 (char, strlen (token) + 1);
1003 0 : STRCPY (param.event.event_name_,
1004 : token,
1005 : MaxMinEventName);
1006 : }
1007 0 : state_event_handle_wait (¶m,
1008 : &event_src,
1009 : &status);
1010 : }
1011 :
1012 : }
1013 : } else {
1014 0 : param.event.event_type_ = EIndication;
1015 0 : status =
1016 : ind_event_handle_request (¶m, &event_src);
1017 0 : if (!status) {
1018 0 : param.command_ = EWaitEvent;
1019 0 : if (!param.event.event_name_) {
1020 0 : param.event.event_name_ =
1021 : NEW2 (char, strlen (token) + 1);
1022 0 : STRCPY (param.event.event_name_,
1023 : token, MaxMinEventName);
1024 : }
1025 0 : ind_event_handle_wait (¶m, &event_src,
1026 : &status);
1027 : }
1028 : }
1029 :
1030 0 : remote_event_req_response (token, status,
1031 : param.event.event_type_);
1032 0 : break;
1033 : case EKeywordRelease:
1034 0 : param.command_ = ERelEvent;
1035 : /*
1036 : ** The protocol is brain damaged...
1037 : ** We need to first see if the release is for
1038 : ** state or indication event
1039 : */
1040 0 : e = find_state_event (¶m, NULL);
1041 0 : if (e != INITPTR) {
1042 0 : param.event.event_type_ = EState;
1043 0 : status =
1044 : state_event_handle_release (¶m, &event_src);
1045 : } else {
1046 0 : param.event.event_type_ = EIndication;
1047 0 : status =
1048 : ind_event_handle_release (¶m, &event_src);
1049 : }
1050 0 : remote_event_rel_response (token, status);
1051 0 : break;
1052 : case EKeywordSet:
1053 0 : param.command_ = ESetEvent;
1054 0 : if (mip_get_next_tagged_string (parameters, "type", &token2)
1055 : == ENOERR) {
1056 0 : if (strcmp (token2, "state"))
1057 0 : MIN_WARN ("%s: unknown type=%s",
1058 : __FUNCTION__, token2);
1059 : else {
1060 0 : param.event.event_type_ = EState;
1061 0 : state_event_handle_set (¶m, &event_src);
1062 : }
1063 : } else {
1064 0 : param.event.event_type_ = EIndication;
1065 0 : ind_event_handle_set (¶m, &event_src);
1066 : }
1067 :
1068 0 : break;
1069 : case EKeywordUnset:
1070 0 : param.command_ = EUnsetEvent;
1071 : break;
1072 : default:
1073 : break;
1074 : }
1075 :
1076 0 : DELETE (param.event.event_name_);
1077 :
1078 0 : return 0;
1079 0 : err_out:
1080 0 : return 1;
1081 : }
1082 :
1083 :
1084 : /** Handles remote event request response commands arriving
1085 : * from external controller
1086 : * @param parameters command parameters
1087 : */
1088 : int handle_remote_event_request_resp (MinItemParser * parameters)
1089 0 : {
1090 0 : char *token = NULL, *token2 = NULL, *token3 = NULL;
1091 : minTestEventParam_t param;
1092 : minEventSrc_t event_src;
1093 :
1094 0 : event_src.pid = -1;
1095 0 : event_src.remote = 1;
1096 :
1097 0 : if (mip_get_next_string (parameters, &token) != ENOERR) {
1098 0 : MIN_WARN ("%s: missing parameters!", __FUNCTION__);
1099 0 : return 1;
1100 : }
1101 :
1102 0 : if (!strcasecmp (token, "active")) {
1103 0 : DELETE (token);
1104 0 : return 0; /* Just an ack, no need to handle further */
1105 : }
1106 :
1107 0 : if (!strcasecmp (token, "set")) {
1108 :
1109 0 : if (mip_get_next_string (parameters, &token2) != ENOERR) {
1110 0 : MIN_WARN ("%s: event name missing!", __FUNCTION__);
1111 0 : return 1;
1112 : }
1113 0 : param.event.event_name_ = NEW2 (char, strlen (token2) + 1);
1114 0 : STRCPY (param.event.event_name_, token2, MaxMinEventName);
1115 :
1116 0 : if (mip_get_next_tagged_string (parameters, "type", &token3)
1117 : == ENOERR) {
1118 0 : if (strcmp (token3, "state"))
1119 0 : MIN_WARN ("%s: unknown type=%s",
1120 : __FUNCTION__, token3);
1121 : else {
1122 0 : param.event.event_type_ = EState;
1123 0 : state_event_handle_set (¶m, &event_src);
1124 : }
1125 : } else {
1126 0 : param.event.event_type_ = EIndication;
1127 0 : ind_event_handle_set (¶m, &event_src);
1128 : }
1129 0 : DELETE (param.event.event_name_);
1130 : } else {
1131 0 : MIN_WARN ("%s: unhandled: %s", __FUNCTION__, token);
1132 : }
1133 :
1134 0 : DELETE (token);
1135 0 : DELETE (token2);
1136 0 : DELETE (token3);
1137 0 : return 0;
1138 : }
1139 :
1140 :
1141 : /* ================= OTHER EXPORTED FUNCTIONS ============================== */
1142 : /* None */
1143 :
1144 :
1145 : /* ================= TESTS FOR LOCAL FUNCTIONS ============================= */
1146 : #ifdef MIN_UNIT_TEST
1147 : #include "tec_events.tests"
1148 : #endif /* MIN_UNIT_TEST */
1149 :
1150 : /* End of file */
|