LTP GCOV extension - code coverage report
Current view: directory - src/engine/tec - tec_events.c
Test: min.info
Date: 2009-06-18 Instrumented lines: 388
Code covered: 59.5 % Executed lines: 231

       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 (&param,
     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 (&param,
    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 (&param, &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 (&param, &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 (&param, NULL);
    1041               0 :                 if (e != INITPTR) {
    1042               0 :                         param.event.event_type_ = EState;
    1043               0 :                         status =
    1044                 :                             state_event_handle_release (&param, &event_src);
    1045                 :                 } else {
    1046               0 :                         param.event.event_type_ = EIndication;
    1047               0 :                         status =
    1048                 :                             ind_event_handle_release (&param, &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 (&param, &event_src);
    1062                 :                         }
    1063                 :                 } else {
    1064               0 :                         param.event.event_type_ = EIndication;
    1065               0 :                         ind_event_handle_set (&param, &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 (&param, &event_src);
    1124                 :                         }
    1125                 :                 } else {
    1126               0 :                         param.event.event_type_ = EIndication;
    1127               0 :                         ind_event_handle_set (&param, &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 */

Generated by: LTP GCOV extension version 1.6