IPropertyTree *CEsdlSvcEngine::createTargetContext(IEspContext &context, IPropertyTree *tgtcfg, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, IPropertyTree *req_pt) { const char *querytype = tgtcfg->queryProp("@querytype"); if (!querytype || !strieq(querytype, "ROXIE")) //only roxie? return NULL; StringBuffer trxid; generateTransactionId(context, trxid); Owned<IPropertyTree> localCtx(createPTreeFromIPT(m_service_ctx, ipt_none)); ensurePTree(localCtx, "Row/Common"); localCtx->setProp("Row/Common/TransactionId", trxid.str()); return localCtx.getLink(); }
/* Read all tags in Scanlist, * using MultiRequests for as many as possible. * Called by scan task, PLC is locked. * * Returns OK when the transactions worked out, * even if the read requests for the tags * returned no data. */ static eip_bool process_ScanList(EIPConnection *c, ScanList *scanlist) { TagInfo *info, *info_position; size_t count, requests_size, responses_size; size_t multi_request_size = 0, multi_response_size = 0; size_t send_size, i, elements; CN_USINT *send_request, *multi_request, *request; const CN_USINT *response, *single_response, *data; EncapsulationRRData rr_data; size_t single_response_size, data_size; epicsTimeStamp start_time, end_time; double transfer_time; TagCallback *cb; eip_bool ok; EIP_printf_time(10, "EIP process_ScanList %g s\n", scanlist->period); info = DLL_first(TagInfo, &scanlist->taginfos); while (info) { /* keep position, we'll loop several times: * 0) in determine_MultiRequest_count * 1) to send out the requests * 2) to handle the responses */ info_position = info; count = determine_MultiRequest_count( c->transfer_buffer_limit, info, &requests_size, &responses_size, &multi_request_size, &multi_response_size); EIP_printf(10, "EIP process_ScanList %lu items\n", (unsigned long)count); if (count == 0) /* Empty, or nothing fits in one request. */ return true; /* send <count> requests as one transfer */ send_size = CM_Unconnected_Send_size(multi_request_size); EIP_printf(10, " ------------------- New Request ------------\n"); TransactionID tid; generateTransactionId(&tid); if (!(send_request = EIP_make_SendRRData(c, send_size, &tid))) return false; multi_request = make_CM_Unconnected_Send(send_request, multi_request_size, c->slot); if (!(multi_request && prepare_CIP_MultiRequest(multi_request, count))) return false; /* Add read/write requests to the multi requests */ for (i=0; i<count; info=DLL_next(TagInfo, info)) { if (info->cip_r_request_size <= 0 || info->cip_w_request_size <= 0) continue; EIP_printf(10, "Request #%d (%s):\n", i, info->string_tag); if (info->is_writing) { request = CIP_MultiRequest_item(multi_request, i, info->cip_w_request_size); if (epicsMutexLock(info->data_lock) != epicsMutexLockOK) { EIP_printf_time(1, "EIP process_ScanList '%s': " "no data lock (write)\n", info->string_tag); info->is_writing = false; return false; } ok = request && make_CIP_WriteData( request, info->cip_w_request_size, info->tag, (CIP_Type)get_CIP_typecode(info->data), info->elements, info->data + CIP_Typecode_size); epicsMutexUnlock(info->data_lock); } else { /* reading, !is_writing */ request = CIP_MultiRequest_item( multi_request, i, info->cip_r_request_size); ok = request && make_CIP_ReadData(request, info->tag, info->elements); } if (!ok) return false; ++i; /* increment here, not in for() -> skip empty tags */ } /* for i=0..count */ epicsTimeGetCurrent(&start_time); if (!EIP_send_connection_buffer(c)) { EIP_printf_time(2, "EIP process_ScanList: Error while sending request\n"); return false; } /* read & disassemble response */ if (!EIP_read_connection_buffer(c)) { EIP_printf_time(2, "EIP process_ScanList: No response\n"); return false; } epicsTimeGetCurrent(&end_time); transfer_time = epicsTimeDiffInSeconds(&end_time, &start_time); response = EIP_unpack_RRData(c->buffer, &rr_data); /* Verify transmission ID */ TransactionID rid; extractTransactionId(&rr_data.header,&rid); if (! compareTransactionIds(&tid, &rid)) { char tidText[32], gidText[32]; transactionIdString(&tid,tidText,sizeof(tidText)); transactionIdString(&rid,gidText,sizeof(gidText)); EIP_printf_time(2, "EIP process_ScanList: Mismatch in transaction ID\n"); EIP_printf(2, "expected %s received %s\n", tidText, gidText); return false; } if (! check_CIP_MultiRequest_Response(response, rr_data.data_length)) { EIP_printf_time(2, "EIP process_ScanList: Error in response\n"); for (info=info_position,i=0; i<count; info=DLL_next(TagInfo, info)) { if (info->cip_r_request_size <= 0) continue; EIP_printf(2, "Tag %i: '%s'\n", i, info->string_tag); ++i; } if (EIP_verbosity >= 2) dump_CIP_MultiRequest_Response_Error(response, rr_data.data_length); return false; } /* Handle individual read/write responses */ for (info=info_position, i=0; i<count; info=DLL_next(TagInfo, info)) { if (info->cip_r_request_size <= 0 || info->cip_w_request_size <= 0) continue; info->transfer_time = transfer_time; single_response = get_CIP_MultiRequest_Response( response, rr_data.data_length, i, &single_response_size); if (! single_response) return false; if (EIP_verbosity >= 10) { EIP_printf(10, "Response #%d (%s):\n", i, info->string_tag); EIP_dump_raw_MR_Response(single_response, 0); } if (epicsMutexLock(info->data_lock) != epicsMutexLockOK) { EIP_printf_time(1, "EIP process_ScanList '%s': " "no data lock (receive)\n", info->string_tag); return false; } if (info->is_writing) { if (!check_CIP_WriteData_Response(single_response, single_response_size)) { EIP_printf_time(0, "EIP: CIPWrite failed for '%s'\n", info->string_tag); info->valid_data_size = 0; } info->is_writing = false; } else /* not writing, reading */ { data = check_CIP_ReadData_Response( single_response, single_response_size, &data_size); if (info->do_write) { /* Possible: Read request ... network delay ... response * and record requested write during the delay. * Ignore the read, because that would replace the data * that device support wants us to write in the next scan */ EIP_printf(8, "EIP '%s': Device support requested write " "in middle of read cycle.\n", info->string_tag); } else { if (data_size > 0 && reserve_tag_data(info, data_size)) { memcpy(info->data, data, data_size); info->valid_data_size = data_size; if (EIP_verbosity >= 10) { elements = CIP_Type_size(get_CIP_typecode(data)); if (elements > 0) { /* response = UINT type, raw data */ elements = (data_size-2) / elements; EIP_printf(10, "Data (%d elements): ", elements); dump_raw_CIP_data(data, elements); } else { EIP_printf(10, "Data: "); EIP_hexdump(0, data, data_size); } } } else info->valid_data_size = 0; } } epicsMutexUnlock(info->data_lock); /* Call all registered callbacks for this tag * so that records can show new value */ for (cb = DLL_first(TagCallback, &info->callbacks); cb; cb=DLL_next(TagCallback, cb)) (*cb->callback) (cb->arg); ++i; } /* "info" now on next unread TagInfo or 0 */ } /* while "info" ... */ return true; }