⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gatevc.cc

📁 EPICS CA gateway, base on channel access protocol
💻 CC
📖 第 1 页 / 共 3 页
字号:
		iter++;	}}void gateVcData::vcRemove(void){	gateDebug1(1,"gateVcData::vcRemove() name=%s\n",name());	switch(getState())	{	case gateVcClear:		gateDebug0(1,"gateVcData::vcRemove() clear\n");		break;	case gateVcConnect:	case gateVcReady:		gateDebug0(1,"gateVcData::vcRemove() connect/ready -> clear\n");		setState(gateVcClear);#if DEBUG_VC_DELETE		printf("gateVcData::vcRemove %s\n",pv?pv->name():"NULL");#endif		pv->deactivate();		break;	default:		gateDebug0(1,"gateVcData::vcRemove() default state\n");		break;	}}// This function is called by the gatePvData::eventCB to copy the gdd// generated there into the event_data when needAddRemove is True,// otherwise setEventData is called.  For ENUM's the event_data's// related gdd is set to the pv_data, which holds the enum strings.void gateVcData::vcAdd(void){	// an add indicates that the pv_data and event_data are ready	gateDebug1(1,"gateVcData::vcAdd() name=%s\n",name());#if DEBUG_DELAY	if(!strncmp("Xorbit",name(),6)) {		printf("%s gateVcData::vcAdd: %s state=%d\n",timeStamp(),name(),		  getState());	}#endif	switch(getState())	{	case gateVcConnect:		gateDebug0(1,"gateVcData::vcAdd() connecting -> ready\n");		setState(gateVcReady);		vcNew();		break;	case gateVcReady:		gateDebug0(1,"gateVcData::vcAdd() ready ?\n");	case gateVcClear:		gateDebug0(1,"gateVcData::vcAdd() clear ?\n");	default:		gateDebug0(1,"gateVcData::vcAdd() default state ?\n");	}}// This function is called by the gatePvData::eventCB to copy the gdd// generated there into the event_data when needAddRemove is False,// otherwise vcAdd is called.  For ENUM's the event_data's related gdd// is set to the pv_data, which holds the enum strings.void gateVcData::setEventData(gdd* dd){	gddApplicationTypeTable& app_table=gddApplicationTypeTable::AppTable();	gdd* ndd=event_data;	gateDebug2(10,"gateVcData::setEventData(dd=%p) name=%s\n",(void *)dd,name());#if DEBUG_GDD	heading("gateVcData::setEventData",name());	dumpdd(1,"dd (incoming)",name(),dd);#endif#if DEBUG_DELAY	if(!strncmp("Xorbit",name(),6)) {		printf("%s gateVcData::setEventData: %s state=%d\n",timeStamp(),name(),		  getState());	}#endif	if(event_data)	{		// Containers get special treatment (for performance reasons)		if(event_data->isContainer())		{			// If the gdd has already been posted, clone a new one			if(event_data->isConstant())			{				ndd = app_table.getDD(event_data->applicationType());				app_table.smartCopy(ndd,event_data);				event_data->unreference();			}			// Fill in the new value			app_table.smartCopy(ndd,dd);			event_data = ndd;			dd->unreference();		}		// Scalar and atomic data: Just replace the event_data		else		{			event_data = dd;			ndd->unreference();		}	}	// No event_data present: just set it to the incoming gdd	else	{		event_data = dd;	}#if DEBUG_GDD	dumpdd(4,"event_data(after)",name(),event_data);#endif#if DEBUG_STATE	switch(getState())	{	case gateVcConnect:		gateDebug0(2,"gateVcData::setEventData() connecting\n");		break;	case gateVcClear:		gateDebug0(2,"gateVcData::setEventData() clear\n");		break;	case gateVcReady:		gateDebug0(2,"gateVcData::setEventData() ready\n");		break;	default:		gateDebug0(2,"gateVcData::setEventData() default state\n");		break;	}#endif#if DEBUG_EVENT_DATA	if(pv->fieldType() == DBF_ENUM) {		dumpdd(99,"event_data",name(),event_data);		heading("*** gateVcData::setEventData: end",name());	}#endif}// This function is called by the gatePvData::alhCB to copy the ackt and// acks fields of the gdd generated there into the event_data. If ackt// or acks are changed, an event is generatedvoid gateVcData::setAlhData(gdd* dd){	gddApplicationTypeTable& app_table=gddApplicationTypeTable::AppTable();	gdd* ndd=event_data;	int ackt_acks_changed=1;	gateDebug2(10,"gateVcData::setAlhData(dd=%p) name=%s\n",(void *)dd,name());#if DEBUG_GDD	heading("gateVcData::setAlhData",name());	dumpdd(1,"dd (incoming)",name(),dd);	dumpdd(2,"event_data(before)",name(),event_data);#endif	if(event_data)	{		// If the event_data is already an ALH Container, ackt/acks are adjusted		if(event_data->applicationType() == gddAppType_dbr_stsack_string)		{			// If the gdd has already been posted, clone a new one			if(event_data->isConstant())			{				ndd = app_table.getDD(event_data->applicationType());				app_table.smartCopy(ndd,event_data);				event_data->unreference();			}			// Check for acks and ackt changes and fill in the new values			unsigned short oldacks = ndd[gddAppTypeIndex_dbr_stsack_string_acks];			unsigned short oldackt = ndd[gddAppTypeIndex_dbr_stsack_string_ackt];			unsigned short newacks = dd[gddAppTypeIndex_dbr_stsack_string_acks];			unsigned short newackt = dd[gddAppTypeIndex_dbr_stsack_string_ackt];			ndd[gddAppTypeIndex_dbr_stsack_string_ackt].			  put(&dd[gddAppTypeIndex_dbr_stsack_string_ackt]);			ndd[gddAppTypeIndex_dbr_stsack_string_acks].			  put(&dd[gddAppTypeIndex_dbr_stsack_string_acks]);			if(oldacks == newacks && oldackt == newackt) ackt_acks_changed=0;			event_data= ndd;			dd->unreference();		}		// If event_data is a value: use the incoming gdd and adjust the value		else		{			event_data = dd;#if DEBUG_GDD			dumpdd(31,"event_data(before fill in)",name(),event_data);#endif			// But replace the (string) value with the old value			app_table.smartCopy(event_data,ndd);			ndd->unreference();#if DEBUG_GDD			dumpdd(32,"event_data(old value filled in)",name(),event_data);#endif		}	}	// No event_data present: just set it to the incoming gdd	else	{		event_data = dd;	}	#if DEBUG_GDD	dumpdd(4,"event_data(after)",name(),event_data);#endif	// Post the extra alarm data event if there is a change	if(ackt_acks_changed) vcPostEvent();#if DEBUG_STATE	switch(getState())	{	case gateVcConnect:		gateDebug0(2,"gateVcData::setAlhData() connecting\n");		break;	case gateVcClear:		gateDebug0(2,"gateVcData::setAlhData() clear\n");		break;	case gateVcReady:		gateDebug0(2,"gateVcData::setAlhData() ready\n");		break;	default:		gateDebug0(2,"gateVcData::setAlhData() default state\n");		break;	}#endif}// This function is called by the gatePvData::getCB to copy the gdd// generated there into the pv_datavoid gateVcData::setPvData(gdd* dd){	// always accept the data transaction - no matter what state	// this is the PV atttributes, which come in during the connect state	// currently	gateDebug2(2,"gateVcData::setPvData(gdd=%p) name=%s\n",(void *)dd,name());	if(pv_data) pv_data->unreference();	pv_data=dd;	switch(getState())	{	case gateVcClear:		gateDebug0(2,"gateVcData::setPvData() clear\n");		break;	default:		gateDebug0(2,"gateVcData::setPvData() default state\n");		break;	}	vcData();}// The state of a process variable in the gateway is maintained in two// gdd's, the pv_data and the event_data.  The pv_data is filled in// from the gatePvData's getCB.  For most native types, its// application type is attributes.  (See the gatePvData:: dataXxxCB// routines.)  The event_data is filled in by the gatePvData's// eventCB.  It gets changed whenever a significant change occurs to// the process variable.  When a read (get) is requested, this// function copies the pv_data and event_data into the gdd that comes// with the read.  This dd has the appropriate application type but// its primitive type is 0 (aitEnumInvalid).void gateVcData::copyState(gdd &dd){	gddApplicationTypeTable& table=gddApplicationTypeTable::AppTable();#if DEBUG_GDD || DEBUG_ENUM	heading("gateVcData::copyState",name());	dumpdd(1,"dd(incoming)",name(),&dd);#endif	// The pv_data gdd for all DBF types except DBF_STRING and	// DBF_ENUM has an application type of attributes.  For DBF_STRING	// pv_data is NULL. For DBF_STRING pv_data has application type	// enums, and is the list of strings.  See the dataXxxCB	// gatePvData routines.	if(pv_data) table.smartCopy(&dd,pv_data);#if DEBUG_GDD || DEBUG_ENUM	dumpdd(2,"pv_data",name(),pv_data);	dumpdd(3,"dd(after pv_data)",name(),&dd);#endif	// The event_data gdd has an application type of value for all DBF	// types.  The primitive type and whether it is scalar or atomic	// varies with the DBR type.  See the eventXxxCB gatePvData	// routines.  If the pv is alh monitored, the event_data is a	// container type (gddAppType_dbr_stsack_string)	if(event_data) table.smartCopy(&dd,event_data);	#if DEBUG_GDD || DEBUG_ENUM	if(event_data) dumpdd(4,"event_data",name(),event_data);	dumpdd(5,"dd(after event_data)",name(),&dd);#endif#if DEBUG_EVENT_DATA	if(pv->fieldType() == DBF_ENUM) {		dumpdd(99,"event_data",name(),event_data);		heading("*** gateVcData::copyState: end",name());	}#endif}void gateVcData::vcNew(void){	gateDebug1(10,"gateVcData::vcNew() name=%s\n",name());#if DEBUG_DELAY	if(!strncmp("Xorbit",name(),6)) {		printf("%s gateVcData::vcNew: %s state=%d\n",timeStamp(),name(),		  getState());	}#endif	// Flush any accumulated reads and writes	if(wio.count()) flushAsyncWriteQueue(GATE_NOCALLBACK);	if(rio.count()) flushAsyncReadQueue();	if(!pv->alhGetPending()) {		if(alhRio.count()) flushAsyncAlhReadQueue();	}#if DEBUG_EVENT_DATA		if(pv->fieldType() == DBF_ENUM) {			heading("gateVcData::vcNew",name());			dumpdd(99,"event_data",name(),event_data);		}#endif}void gateVcData::markAlhDataAvailable(void){	gateDebug1(10,"gateVcData::markAlhDataAvailable() name=%s\n",name());	// Flush any accumulated reads	if(ready()) {		if(alhRio.count()) flushAsyncAlhReadQueue();	}}// The asynchronous io queues are filled when the vc is not ready.// This routine, called from vcNew, flushes the write queue.void gateVcData::flushAsyncWriteQueue(int docallback){	gateDebug1(10,"gateVcData::flushAsyncWriteQueue() name=%s\n",name());	gateAsyncW* asyncw;	while((asyncw=wio.first()))	{		asyncw->removeFromQueue();		pv->put(&asyncw->DD(),docallback);		asyncw->postIOCompletion(S_casApp_success);	}}// The asynchronous io queues are filled when the vc is not ready.// This routine, called from vcNew, flushes the read queue.void gateVcData::flushAsyncReadQueue(void){	gateDebug1(10,"gateVcData::flushAsyncReadQueue() name=%s\n",name());	gateAsyncR* asyncr;	while((asyncr=rio.first()))	{		gateDebug2(5,"gateVcData::flushAsyncReadQueue() "		  "posting asyncr %p (DD at %p)\n",		  (void *)asyncr,(void *)&asyncr->DD());		asyncr->removeFromQueue();		#if DEBUG_GDD		heading("gateVcData::flushAsyncReadQueue",name());		dumpdd(1,"asyncr->DD()(before)",name(),&asyncr->DD());#endif		// Copy the current state into the asyncr->DD()		copyState(asyncr->DD());#if DEBUG_DELAY		if(!strncmp("Xorbit",name(),6)) {			printf("%s gateVcData::flushAsyncReadQueue: %s state=%d\n",			  timeStamp(),name(),getState());			printf("  S_casApp_success\n");		}#endif		asyncr->postIOCompletion(S_casApp_success,asyncr->DD());	}}// The alh asynchronous read queue is filled when the alh data is not// ready.  This routine, called from vcNew, flushes the alh read// queue.  There is no separate alh write queue.void gateVcData::flushAsyncAlhReadQueue(void){	gateDebug1(10,"gateVcData::flushAsyncAlhAlhReadQueue() name=%s\n",name());	gateAsyncR* asyncr;	while((asyncr=alhRio.first()))	{		gateDebug2(5,"gateVcData::flushAsyncAlhReadQueue() posting asyncr %p (DD at %p)\n",		  (void *)asyncr,(void *)&asyncr->DD());		asyncr->removeFromQueue();		#if DEBUG_GDD		heading("gateVcData::flushAsyncAlhReadQueue",name());		dumpdd(1,"asyncr->DD()(before)",name(),&asyncr->DD());#endif		// Copy the current state into the asyncr->DD()		copyState(asyncr->DD());#if DEBUG_DELAY		if(!strncmp("Xorbit",name(),6)) {			printf("%s gateVcData::flushAsyncAlhReadQueue: %s state=%d\n",			  timeStamp(),name(),getState());			printf("  S_casApp_success\n");		}#endif		asyncr->postIOCompletion(S_casApp_success,asyncr->DD());	}}// Called from setEventData, which is called from the gatePvData's// eventCB.  Posts an event to the server library owing to changes in// the process variable.void gateVcData::vcPostEvent(void){	gateDebug1(10,"gateVcData::vcPostEvent() name=%s\n",name());//	time_t t;#if DEBUG_DELAY	if(!strncmp("Xorbit",name(),6)) {		printf("%s gateVcData::vcPostEvent: %s state=%d\n",timeStamp(),name(),		  getState());	}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -