📄 gatevc.cc
字号:
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 + -