DBR_GR_ENUM monitor updates dont contain enum strings

Bug #541217 reported by Jeff Hill
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
EPICS Base
Fix Released
High
Jeff Hill

Bug Description

From Ken Evans,

     There is a problem when using dbr_gr_enum's or dbr_ctrl_enum's
with the Gateway. If you monitor, they have the enum strings the
first time, but not thereafter. The num_str is 0 after the first
monitor callback.

     I made a test case:

With the Gateway:

48 krypton:simpleCA>O.solaris-sparc/testenum evans:bo01
Nov 08 17:19:10 Search started for evans:bo01
Nov 08 17:19:10 Connection successful
Nov 08 17:19:10 Value is: 0
  no_str=2
     0 Off
     1 On
Nov 08 17:19:10 Value is: 1
  no_str=0
Nov 08 17:19:11 Value is: 0
  no_str=0
Nov 08 17:19:13 Value is: 1
  no_str=0
Nov 08 17:19:14 Value is: 0
  no_str=0
Nov 08 17:19:16 Value is: 1
  no_str=0
Nov 08 17:19:17 Value is: 0
  no_str=0
Nov 08 17:19:19 Value is: 1
  no_str=0
Nov 08 17:19:20 Value is: 0
  no_str=0
Nov 08 17:19:20 All done after 10 sec
49 krypton:simpleCA>

Direct to the IOC:

45 chiron:simpleCA>O.solaris-sparc/testenum evans:bo01
Nov 08 17:22:09 Search started for evans:bo01
Nov 08 17:22:09 Connection successful
Nov 08 17:22:09 Value is: 0
  no_str=2
     0 Off
     1 On
Nov 08 17:22:10 Value is: 1
  no_str=2
     0 Off
     1 On
Nov 08 17:22:11 Value is: 0
  no_str=2
     0 Off
     1 On
Nov 08 17:22:13 Value is: 1
  no_str=2
     0 Off
     1 On
Nov 08 17:22:14 Value is: 0
  no_str=2
     0 Off
     1 On
Nov 08 17:22:16 Value is: 1
  no_str=2
     0 Off
     1 On
Nov 08 17:22:17 Value is: 0
  no_str=2
     0 Off
     1 On
Nov 08 17:22:19 All done after 10 sec
46 chiron:simpleCA>

   This is coming from the callback:

/***************************** valueChangedCB *************************/
static void valueChangedCB(struct event_handler_args args)
{
  /* Print the value */
    if(args.status == ECA_NORMAL && args.dbr) {
 int i;

 struct dbr_gr_enum *dbr=(struct dbr_gr_enum *)args.dbr;
 printf("%s Value is: %hd\\n",timeStamp(),dbr->value);
 printf(" no_str=%hd\\n",dbr->no_str);
 for(i=0; i < dbr->no_str; i++) {
     if(dbr->strs && dbr->strs[i]) {
  printf(" %2d %s\\n",i,dbr->strs[i]);
     } else {
  printf(" %2d NA\\n",i);
     }
 }
    } else {
 printf("%s Bad value\\n",timeStamp());
    }
}

     The whole file is:

--testenum.c------------------------------------------
/* Test dbr_gr_enum problem */

#define TIMEOUT 10.0
#define SCA_OK 1
#define SCA_ERR 0
#define MAX_STRING 40

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <cadef.h>

/* Function prototypes */
int main(int argc, char **argv);
static void connectionChangedCB(struct connection_handler_args args);
static void valueChangedCB(struct event_handler_args args);
static char *timeStamp(void);
static int parseCommand(int argc, char **argv);
static void usage(void);

/* Global variables */
int pvSpecified=0;
char name[MAX_STRING];
time_t curTime, startTime;
double timeout=TIMEOUT;
evid pEv;

/***************************** main ***********************************/
int main(int argc, char **argv)
{
    int stat;
    chid pCh;

  /* Parse the command line */
    if(parseCommand(argc,argv) != SCA_OK) exit(1);
    if(!pvSpecified) {
 printf("No PV specified\\n");
 exit(1);
    }

  /* Initialize */
#if 0
    stat=ca_context_create(ca_enable_preemptive_callback);
#else
    stat=ca_context_create(ca_disable_preemptive_callback);
#endif
    if(stat != ECA_NORMAL) {
 printf("ca_context_create failed:\\n%s\\n",ca_message(stat));
 exit(1);
    }

  /* Search */
    stat=ca_create_channel(name,connectionChangedCB,NULL,
      CA_PRIORITY_DEFAULT,&pCh);
    if(stat != ECA_NORMAL) {
 printf("ca_create_channel failed:\\n%s\\n",ca_message(stat));
 exit(1);
    }
    printf("%s Search started for %s\\n",timeStamp(),name);

  /* Wait */
    startTime=curTime;
    ca_pend_event(timeout);
    printf("%s All done after %ld sec\\n",timeStamp(),
      curTime-startTime);

  /* Clear the channel */
    stat=ca_clear_channel(pCh);
    if(stat != ECA_NORMAL) {
 printf("ca_clear_channel failed:\\n%s\\n",ca_message(stat));
    }

  /* Exit */
    ca_context_destroy();
    return(0);
}

/***************************** connectionChangedCB ********************/
static void connectionChangedCB(struct connection_handler_args args)
{
    chid pCh=args.chid;
    int stat;

  /* Branch depending on the state */
    switch (ca_state(pCh)) {
    case cs_conn:
 printf("%s Connection successful\\n",timeStamp());
 if(ca_field_type(pCh) != DBR_ENUM) {
     printf("This program only works with ENUM process variables\\n");
     exit(1);
 }
 stat=ca_create_subscription(DBR_GR_ENUM,1,pCh,
   DBE_VALUE|DBE_LOG|DBE_ALARM,
   valueChangedCB,NULL,&pEv);
 if(stat != ECA_NORMAL) {
     printf("ca_array_get_callback:\\n%s\\n",ca_message(stat));
     exit(1);
 }
 break;
    case cs_never_conn:
 printf("%s Cannot connect\\n",timeStamp());
 break;
    case cs_prev_conn:
 printf("%s Lost connection\\n",timeStamp());
 break;
    case cs_closed:
 printf("%s Connection closed\\n",timeStamp());
    break;
    }
}

/***************************** valueChangedCB *************************/
static void valueChangedCB(struct event_handler_args args)
{
  /* Print the value */
    if(args.status == ECA_NORMAL && args.dbr) {
 int i;

 struct dbr_gr_enum *dbr=(struct dbr_gr_enum *)args.dbr;
 printf("%s Value is: %hd\\n",timeStamp(),dbr->value);
 printf(" no_str=%hd\\n",dbr->no_str);
 for(i=0; i < dbr->no_str; i++) {
     if(dbr->strs && dbr->strs[i]) {
  printf(" %2d %s\\n",i,dbr->strs[i]);
     } else {
  printf(" %2d NA\\n",i);
     }
 }
    } else {
 printf("%s Bad value\\n",timeStamp());
    }
}

/***************************** timeStamp ******************************/
static char *timeStamp(void)
  /* Gets current time and puts it in a static array
   * The calling program should copy it to a safe place
   * e.g. strcpy(savetime,timestamp()); */
{
 static char timeStampStr[16];
 time_t now;
 struct tm *tblock;

 time(&now);
 curTime=now;
 tblock=localtime(&now);
 strftime(timeStampStr,20,"%b %d %H:%M:%S",tblock);

 return timeStampStr;
}

/**************************** parseCommand ********************************/
static int parseCommand(int argc, char **argv)
{
    int i;

    for(i=1; i < argc; i++) {
 if (argv[i][0] == '-') {
     switch(argv[i][1]) {
     case 'h':
  usage();
  exit(0);
     case 't':
  timeout=atof(argv[++i]);
  break;
     default:
  fprintf(stderr,"\\n\\nInvalid option: %s\\n",argv[i]);
  usage();
  return SCA_ERR;
     }
 } else {
     if(!pvSpecified) {
  strncpy(name,argv[i],MAX_STRING);
  name[MAX_STRING-1]='\\0';
  pvSpecified=1;
     } else {
  printf("\\n\\nInvalid option: %s\\n",argv[i]);
  usage();
  return SCA_ERR;
     }
 }
    }
    return SCA_OK;
}

/**************************** usage ***************************************/
static void usage(void)
{
    printf(
      "\\nUsage: testenum [Options] pvname\\n"
      " Connects to pvname and monitors the value\\n"
      "\\n"
      " Options:\\n"
      " -h help This message\\n"
      " -t float Timeout in seconds (Default: %g)\\n",TIMEOUT);
}

Original Mantis Bug: mantis-159
    http://www.aps.anl.gov/epics/mantis/view_bug_page.php?f_id=159

Tags: cas 3.14
Revision history for this message
Jeff Hill (johill-lanl) wrote :

patch was committed to src/gdd/dbMapper.cc
fixed in R3.14.7

Revision history for this message
Andrew Johnson (anj) wrote :

R3.14.7 Released

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.