Пример #1
1
/*
 * 	cagft()
 *
 *	ca get field test
 *
 *	test ca get over the range of CA data types
 */
static int cagft(char *pname)
{	
	const unsigned maxTries = 1000ul;
	unsigned ntries = 0u;
	chid chan_id;
	int status;
	int i;

	/* 
	 *	convert name to chan id 
	 */
	status = ca_search(pname, &chan_id);
	SEVCHK(status,NULL);
	status = ca_pend_io(5.0);
	if(status != ECA_NORMAL){
        SEVCHK(ca_clear_channel(chan_id),NULL);
		printf("Not Found %s\n", pname);
		return -1;
	}

	printf("name:\t%s\n", 
        ca_name(chan_id));
	printf("native type:\t%s\n", 
        dbr_type_to_text(ca_field_type(chan_id)));
	printf("native count:\t%lu\n", 
        ca_element_count(chan_id));


	/* 
 	 * fetch as each type 
	 */
	for(i=0; i<=LAST_BUFFER_TYPE; i++){
		if(ca_field_type(chan_id)==DBR_STRING) {
			if( (i!=DBR_STRING)
			  && (i!=DBR_STS_STRING)
			  && (i!=DBR_TIME_STRING)
			  && (i!=DBR_GR_STRING)
              && (i!=DBR_CTRL_STRING)) {
                  continue;
            }
        }
        /* ignore write only types */
        if ( 
            i == DBR_PUT_ACKT || 
            i == DBR_PUT_ACKS ) {
                continue;
        }

		status = ca_array_get_callback(
				i, 
				ca_element_count(chan_id),
				chan_id, 
				printit, 
				NULL);
		SEVCHK(status, NULL);

		outstanding++;
	}

	/*
	 * wait for the operation to complete
	 * before returning 
	 */
	while ( ntries < maxTries ) {
		unsigned long oldOut;

		oldOut = outstanding;
		ca_pend_event ( 0.05 );

		if ( ! outstanding ) {
            SEVCHK ( ca_clear_channel ( chan_id ), NULL );
			printf ( "\n\n" );
			return 0;
		}

		if ( outstanding == oldOut ) {
			ntries++;
		}
	}

    SEVCHK ( ca_clear_channel ( chan_id ), NULL );
	return -1;
}
Пример #2
0
static void conCB(CONNECT_ARGS args)
{
	/* void* node=(void*)ca_puser(args.chid); */
	long rc;
/*
	fprintf(stderr,"exCB: -------------------------------\n");
	fprintf(stderr,"conCB: name=%s\n",ca_name(args.chid));
	fprintf(stderr,"conCB: type=%d\n",ca_field_type(args.chid));
	fprintf(stderr,"conCB: number elements=%d\n",ca_element_count(args.chid));
	fprintf(stderr,"conCB: host name=%s\n",ca_host_name(args.chid));
	fprintf(stderr,"conCB: read access=%d\n",ca_read_access(args.chid));
	fprintf(stderr,"conCB: write access=%d\n",ca_write_access(args.chid));
	fprintf(stderr,"conCB: state=%d\n",ca_state(args.chid));
*/
	if(ca_state(args.chid)==cs_conn)
	{
	 	if (never_connected) {
			never_connected=0;
			/* issue a get */
			if(ca_field_type(args.chid)==DBF_ENUM)
			{
				pv_type=DBF_ENUM;
				rc=ca_array_get_callback(DBR_GR_ENUM,1,id,getCB,NULL);
			}
			else
			{
				pv_type=DBF_STRING;
				rc=ca_array_get_callback(DBR_STRING,1,id,getCB,NULL);
			}
			SEVCHK(rc,"get with callback bad");
		}
	}
	else
		fprintf(stderr,"PV <%s> not connected\n",pv_name);
}
void ProcessVariable::getValue(Guard &guard)
{
    guard.check(__FILE__, __LINE__, mutex);
    if (state != CONNECTED)
        return; // Can't get
    ++outstanding_gets;
    chid _id = id;
    GuardRelease release(__FILE__, __LINE__, guard); // Unlock while in CAC.
    {
        int status;
        try
        {
            status = ca_array_get_callback(dbr_type, dbr_count,
                                           _id, value_callback, this);
        }
        catch (std::exception &e)
        {
            LOG_MSG("ProcessVariable::getValue(%s): %s\n",
                    getName().c_str(), e.what());
        }
        catch (...)
        {
            LOG_MSG("ProcessVariable::getValue(%s): Unknown Exception\n",
                    getName().c_str());
        }                          
        if (status != ECA_NORMAL)
        {
            LOG_MSG("%s: ca_array_get_callback failed: %s\n",
                    getName().c_str(), ca_message(status));
            return;
        }
        Guard ctx_guard(__FILE__, __LINE__, ctx);
        ctx.requestFlush(ctx_guard);
    }    
}
Пример #4
0
int
channel_async_get(Channel *chan, CHANNEL_USERFUNC func, void * arg)
{
    DEBUGP printf("channel_async_get %s %s\n", chan->chan_name, chan->valid?"valid":"invalid");
    if(! chan->valid)
	return -1;
    
    chan->outstanding = 1;
    ca_array_get_callback(chan->chan_type, chan->maxelement, chan->chan_id, func, arg);
    
    /* no pend_io or flush_io, responsibility of caller to set that up */
    return 0;
}
Пример #5
0
/*
 * VERIFY_VALUE
 *
 * initiate print out the values in a database access interface structure
 */
static void verify_value(chid chan_id, chtype type)
{
	int status;

	/*
	 * issue a get which calls back `printit'
	 * upon completion
	 */
	status = ca_array_get_callback(
			type, 
			ca_element_count(chan_id),
			chan_id, 
			printit, 
			NULL);
	SEVCHK(status, NULL);

	outstanding++;
}
Пример #6
0
static void medmReplaceAccessRightsEventCb(
  struct access_rights_handler_args args)
{
    Channel *pCh = (Channel *) ca_puser(args.chid);
    Boolean readAccessChangedToRead = False;

  /* Increment the event counter */
    caTask.caEventCount++;

  /* Check for valid values */
    if(globalDisplayListTraversalMode != DL_EXECUTE) return;
    if(!pCh || !pCh->pr) {
	medmPostMsg(0,"medmReplaceAccessRightsEvent: "
	  "Invalid channel information\n");
	return;
    }

  /* Determine if the rights are changing from no read to read */
    if(!pCh->pr->readAccess && ca_read_access(pCh->chid)) {
	readAccessChangedToRead = True;
    }
  /* Change the access rights in the Record */
    pCh->pr->readAccess = ca_read_access(pCh->chid);
    pCh->pr->writeAccess = ca_write_access(pCh->chid);
    if(pCh->pr->updateValueCb)
      pCh->pr->updateValueCb((XtPointer)pCh->pr);

  /* Do a get as in medmConnectEventCb.  The get will cause the
     graphical info callback to be called.  This is necessary for some
     objects if the access rights are changing from no read to
     read. */
    if(pCh->pr->connected && pCh->previouslyConnected
      && readAccessChangedToRead) {
	int status = ca_array_get_callback(
	  dbf_type_to_DBR_CTRL(ca_field_type(args.chid)),
	  1, args.chid, medmUpdateGraphicalInfoCb, NULL);
	if(status != ECA_NORMAL) {
	    medmPostMsg(0,"medmReplaceAccessRightsEventCb: %s\n",
	      ca_message(status));
	}
    }
}
// Channel Access callback
void ProcessVariable::connection_handler(struct connection_handler_args arg)
{
    ProcessVariable *me = (ProcessVariable *) ca_puser(arg.chid);
    LOG_ASSERT(me != 0);
    try
    {
        if (arg.op == CA_OP_CONN_DOWN)
        {   // Connection is down
            {
                Guard guard(__FILE__, __LINE__, *me);
                me->state = DISCONNECTED;
            }
            me->firePvDisconnected();
            return;
        }
        {   // else: Connection is 'up'
            Guard guard(__FILE__, __LINE__, *me);
            if (me->id == 0)
            {
                LOG_MSG("ProcessVariable(%s) received "
                        "unexpected connection_handler\n",
                        me->getName().c_str());
                return;
            }
#           ifdef DEBUG_PV
            printf("ProcessVariable(%s) getting control info\n",
                   me->getName().c_str());
#           endif
            me->state = GETTING_INFO;
            // Get control information for this channel.
            // Bug in (at least older) CA: Works only for 1 element,
            // even for array channels.
            // We are in CAC callback, and managed to lock ourself,
            // so it should be OK to issue another CAC call.
            try
            {
                int status = ca_array_get_callback(
                    ca_field_type(me->id)+DBR_CTRL_STRING,
                    1 /* ca_element_count(me->ch_id) */,
                    me->id, control_callback, me);
                if (status != ECA_NORMAL)
                {
                    LOG_MSG("ProcessVariable('%s') connection_handler error %s\n",
                            me->getName().c_str(), ca_message (status));
                    return;
                }
            }
            catch (std::exception &e)
            {
                LOG_MSG("ProcessVariable::connection_handler(%s): %s\n",
                        me->getName().c_str(), e.what());
            }
            catch (...)
            {
                LOG_MSG("ProcessVariable::connection_handler(%s): "
                        "Unknown Exception\n", me->getName().c_str());
            } 
        }
        Guard ctx_guard(__FILE__, __LINE__, me->ctx);
        me->ctx.requestFlush(ctx_guard);
    }
    catch (GenericException &e)
    {
        LOG_MSG("ProcessVariable(%s) connection_handler exception:\n%s\n",
                me->getName().c_str(), e.what());
    }    
}
Пример #8
0
int cagetFuZE(char *pvName, char *pvValue) {

  RequestT request = get;
  OutputT format = plain;
  chtype dbrType = -1;
  unsigned long reqElems = 0;
  int n, result;
  pv* pvs;
  int i;
  unsigned long nElems;
  

  result = ca_context_create(ca_disable_preemptive_callback);

  pvs = calloc(1, sizeof(pv));

  pvs[0].name = pvName;
  
  connect_pvs(pvs, 1);
  
  for (n = 0; n < 1; n++) {
    
    /* Set up pvs structure */
    /* -------------------- */

    /* Get natural type and array count */
    nElems         = ca_element_count(pvs[n].chid);
    pvs[n].dbfType = ca_field_type(pvs[n].chid);
    pvs[n].dbrType = dbrType;

    /* Set up value structures */
    if (format != specifiedDbr)
      {
	pvs[n].dbrType = dbf_type_to_DBR_TIME(pvs[n].dbfType); /* Use native type */
	if (dbr_type_is_ENUM(pvs[n].dbrType))                  /* Enums honour -n option */
	  {
	    if (enumAsNr) pvs[n].dbrType = DBR_TIME_INT;
	    else          pvs[n].dbrType = DBR_TIME_STRING;
	  }
	else if (floatAsString &&
		 (dbr_type_is_FLOAT(pvs[n].dbrType) || dbr_type_is_DOUBLE(pvs[n].dbrType)))
	  {
	    pvs[n].dbrType = DBR_TIME_STRING;
	  }
      }

    /* Issue CA request */
    /* ---------------- */

    if (ca_state(pvs[n].chid) == cs_conn)
      {
  	nConn++;
  	pvs[n].onceConnected = 1;
  	if (request == callback)
  	  {
  	    /* Event handler will allocate value and set nElems */
  	    pvs[n].reqElems = reqElems > nElems ? nElems : reqElems;
  	    result = ca_array_get_callback(pvs[n].dbrType,
  					   pvs[n].reqElems,
  					   pvs[n].chid,
  					   event_handler,
  					   (void*)&pvs[n]);
  	  } else {
  	  /* We allocate value structure and set nElems */
	  pvs[n].nElems = reqElems && reqElems < nElems ? reqElems : nElems;
  	  pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].nElems));
	  if (!pvs[n].value) {
  	    fprintf(stderr,"Memory allocation failed\n");
  	    return -1;
  	  }
  	  result = ca_array_get(pvs[n].dbrType,
  				pvs[n].nElems,
  				pvs[n].chid,
  				pvs[n].value);
  	}
  	pvs[n].status = result;
      } else {
      pvs[n].status = ECA_DISCONN;
    }
  }

  if (!nConn) return -1;              /* No connection? We're done. */

  /* Wait for completion */
  /* ------------------- */

  result = ca_pend_io(caTimeout);
  if (result == ECA_TIMEOUT) {
    fprintf(stderr, "Read operation timed out: some PV data was not read.\n");
    return -1;
  }

  if (request == callback)    /* Also wait for callbacks */
    {
      if (caTimeout != 0)
        {
	  double slice = caTimeout / PEND_EVENT_SLICES;
	  for (n = 0; n < PEND_EVENT_SLICES; n++)
            {
	      ca_pend_event(slice);
	      if (nRead >= nConn) break;
            }
	  if (nRead < nConn) {
	    fprintf(stderr, "Read operation timed out: some PV data was not read.\n");
	    return -1;
	  }
	} else {
	/* For 0 timeout keep waiting until all are done */
	    while (nRead < nConn) {
	      ca_pend_event(1.0);
	    }
      }
    }


  // Does this kill the connection??
  ca_context_destroy();
  
  sprintf(pvValue, "%s\n", val2str(pvs[0].value, pvs[0].dbrType, 0));

  return 1;

}
Пример #9
0
/*
 * callback from connection handler: change the state of the channel valid
 * flag depending on the connection being up or down.
 * ASSUMPTIONS: chan_id is valid.
 */
static void
connect_callback(struct connection_handler_args args)
{
    Connector *conp;
    
    Channel *chan = ca_puser( args.chid);
    int status;
    
    DEBUGP printf("connect callback %p\n", chan);
    switch( args.op)
    {
    case CA_OP_CONN_UP:
    	if( chan->initData == 1)
	{
		chan->maxelement = ca_element_count(chan->chan_id);
		chan->chan_type = ca_field_type(chan->chan_id);
		chan->initData = 0;
	}
	/*
	 * note that a dropped and recreated connection can cause a free and alloc. This
	 * is not always redundant, as software may have restarted with different sizes
	 * for the field!
	 */
	if( chan->createData == 1 )
	{
		if( chan->dataval)
			free( chan->dataval);
		chan->dataval = calloc(dbr_size[chan->chan_type], chan->maxelement+1);
	}

	chan->readAccess = ca_read_access( chan->chan_id);
	chan->writeAccess = ca_write_access( chan->chan_id);
	status = ca_array_get_callback( dbf_type_to_DBR_CTRL(ca_field_type(chan->chan_id)), 1, chan->chan_id, getChanInfo, (void*)chan);
	SEVCHK(status, "connect_callback : ca_get_DBR_CTRL_event failed");
	status = ca_replace_access_rights_event( chan->chan_id, getAccessRights);
	SEVCHK(status, "connect_callback : ca_replace_access_rights_event failed");

	chan->valid = 1;
	chan->outstanding = 0;
	if( chan->monitor)
	{
	    chan->status = 100;	/* MAGIC: an absurd status */
	    status = ca_add_array_event(dbf_type_to_DBR_STS(chan->chan_type), chan->maxelement, chan->chan_id, monitorCallback, chan, 
		    		(double) 0.0, (double) 0.0, (double) 0.0, &(chan->eventId));
	    SEVCHK(status, "connect_callback : ca_add_event failed");
	    status = ca_flush_io();
	    SEVCHK(status, "connect_callback : ca_flush_io failed");
	}
	break;
	
    case CA_OP_CONN_DOWN:
	if( chan->valid && chan->eventId)
	    ca_clear_event(chan->eventId);
	chan->valid = 0;
	chan->status = 99;
	
	/*
	 * update the access rights and severity for all the connectors
	 */
	for(conp=chan->first_connector; conp ; conp=conp->next)
	{
	    if(conp->newAccess)
		(*conp->newAccess)(conp);
	    if( conp->newState)
	    	(*conp->newState)(conp);
	}
	
	break;
    default:
	break;
    }

    return;
}
Пример #10
0
static void medmConnectEventCb(struct connection_handler_args args) {
    int status;
    Channel *pCh = (Channel *)ca_puser(args.chid);
    int count;

  /* Increment the event counter */
    caTask.caEventCount++;

  /* Check for valid values */
    if(globalDisplayListTraversalMode != DL_EXECUTE) return;
    if(!pCh || !pCh->chid || !pCh->pr) {
	medmPostMsg(0,"medmConnectEventCb: Invalid channel information\n");
	return;
    }

  /* Do a get every time a channel is connected or reconnected and has
   * read access.  The get will cause the graphical info callback to
   * be called */
    if(args.op == CA_OP_CONN_UP && ca_read_access(pCh->chid)) {
	status = ca_array_get_callback(
	  dbf_type_to_DBR_CTRL(ca_field_type(args.chid)),
	  1, args.chid, medmUpdateGraphicalInfoCb, NULL);
	if(status != ECA_NORMAL) {
	    medmPostMsg(0,"medmConnectEventCb: "
	      "ca_array_get_callback [%s]:\n %s\n",
	      ca_name(pCh->chid)?ca_name(pCh->chid):"Unknown",
	      ca_message(status));
#if DEBUG_CONNECTION
# if 0
	    system("netstat | grep iocacis");
# endif
	    print("  pCh->chid %s args.chid\n",
	      pCh->chid == args.chid?"==":"!=");
	    print(
	      "  Channel Name: %s\n"
	      "  State: %s\n"
	      "  Native Type: %s\n"
	      "  Native Count: %hu\n"
	      "  Access: %s%s\n"
	      "  IOC: %s\n",
	      args.chid?ca_name(args.chid):"Unavailable",
	      args.chid?ca_state(args.chid) == cs_never_conn?"Never":
	      ca_state(args.chid) == cs_prev_conn?"Prev":
	      ca_state(args.chid) == cs_conn?"Conn":
	      ca_state(args.chid) == cs_closed?"Closed":"Unknown":"Unavailable",
	      args.chid?dbf_type_to_text(ca_field_type(args.chid)):"Unavailable",
	      args.chid?ca_element_count(args.chid):0,
	      args.chid?(ca_read_access(args.chid)?"R":"None"):"Unavailable",
	      args.chid?(ca_write_access(args.chid)?"W":""):"",
	      args.chid?ca_host_name(args.chid):"Unavailable");
#endif
	}
    }

  /* Handle four cases: connected or not and previously connected or not */
    if(args.op == CA_OP_CONN_UP) {
      /* Connected */
	if(pCh->previouslyConnected == False) {
	  /* Connected and not previously connected */
	  /* Set these first so they will be right for the updateValueCb */
	    pCh->pr->elementCount = ca_element_count(pCh->chid);
	    pCh->pr->dataType = ca_field_type(args.chid);
	    pCh->pr->connected = True;
	    caTask.channelConnected++;
	  /* Add the access-rights-change callback and the
	     significant-change (value, alarm or severity)
	     callback. Don't call the updateValueCb because
	     ca_replace_access_rights_event will call it. */
	    status = ca_replace_access_rights_event(
	      pCh->chid,medmReplaceAccessRightsEventCb);
	    if(status != ECA_NORMAL) {
		medmPostMsg(0,"medmConnectEventCb: "
		  "ca_replace_access_rights_event [%s]: %s\n",
		  ca_name(pCh->chid)?ca_name(pCh->chid):"Unknown",
		  ca_message(status));
	    }
	    if(pCh->pr->currentCount == -2) {
                count=0;
            } else {
                count=ca_element_count(pCh->chid);
            }
#ifdef __USING_TIME_STAMP__
	    status = ca_add_array_event(
	      dbf_type_to_DBR_TIME(ca_field_type(pCh->chid)),
	      count, pCh->chid,
	      medmUpdateChannelCb, pCh, 0.0,0.0,0.0, &(pCh->evid));
#else
	    status = ca_add_array_event(
	      dbf_type_to_DBR_STS(ca_field_type(pCh->chid)),
	      count, pCh->chid,
	      medmUpdateChannelCb, pCh, 0.0,0.0,0.0, &(pCh->evid));
#endif
	    if(status != ECA_NORMAL) {
	      /* Set the pointer to NULL in case CA didn't.  We don't
                 want to use it or clear it later. */
#if DEBUG_CONNECTION
		if(!pCh->evid) {
		    print("medmConnectEventCb: ca_add_array_event: \n"
		      "  status[%d] != ECA_NORMAL and pCh->evid != NULL\n",
		      status);
		}
#endif
		pCh->evid = NULL;
		medmPostMsg(0,"medmConnectEventCb: "
		  "ca_add_array_event [%s]:\n %s\n",
		  ca_name(pCh->chid)?ca_name(pCh->chid):"Unknown",
		  ca_message(status));
#if DEBUG_CONNECTION
# if 0
		system("netstat | grep iocacis");
# endif
		print("  pCh->chid %s args.chid\n",
		  pCh->chid == args.chid?"==":"!=");
		print(
		  "  Channel Name: %s\n"
		  "  State: %s\n"
		  "  Native Type: %s\n"
		  "  Native Count: %hu\n"
		  "  Access: %s%s\n"
		  "  IOC: %s\n",
		  args.chid?ca_name(args.chid):"Unavailable",
		  args.chid?ca_state(args.chid) == cs_never_conn?"Never":
		  ca_state(args.chid) == cs_prev_conn?"Prev":
		  ca_state(args.chid) == cs_conn?"Conn":
		  ca_state(args.chid) == cs_closed?"Closed":"Unknown":"Unavailable",
		  args.chid?dbf_type_to_text(ca_field_type(args.chid)):"Unavailable",
		  args.chid?ca_element_count(args.chid):0,
		  args.chid?(ca_read_access(args.chid)?"R":"None"):"Unavailable",
		  args.chid?(ca_write_access(args.chid)?"W":""):"",
		  args.chid?ca_host_name(args.chid):"Unavailable");
#endif
	    }
	  /* Set this one last so ca_replace_access_rights_event can
             use the old value */
	    pCh->previouslyConnected = True;
	} else {
	  /* Connected and previously connected */
	    pCh->pr->connected = True;
	    caTask.channelConnected++;
	    if(pCh->pr->updateValueCb)
	      pCh->pr->updateValueCb((XtPointer)pCh->pr);
	}
    } else {
      /* Not connected */
	if(pCh->previouslyConnected == False) {
	  /* Not connected and not previously connected */
	  /* Probably doesn't happen -- if CA can't connect, this
	   *   routine never gets called */
	    pCh->pr->connected = False;
	} else {
	  /* Not connected but previously connected */
	    pCh->pr->connected = False;
	    caTask.channelConnected--;
	    if(pCh->pr->updateValueCb)
	      pCh->pr->updateValueCb((XtPointer)pCh->pr);
	}
    }
}