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();
}
Example #2
0
/* 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;
}