Beispiel #1
0
c_bool
d_publisherSampleChainWriterCopy(
    c_type type,
    void *data,
    void *to)
{
    d_sampleChain msgFrom = d_sampleChain(data);
    d_sampleChain msgTo   = d_sampleChain(to);
    c_base           base = c_getBase(type);
    static c_type    type0 = NULL;
    static c_type    type1 = NULL;
    unsigned int     valueSize;

    d_publisherMessageWriterCopy(&msgFrom->parentMsg, &msgTo->parentMsg);

    msgTo->partition       = c_stringNew(base, msgFrom->partition);
    msgTo->topic           = c_stringNew(base, msgFrom->topic);
    msgTo->durabilityKind  = msgFrom->durabilityKind;
    msgTo->msgBody._d      = msgFrom->msgBody._d;
    msgTo->addresseesCount = msgFrom->addresseesCount;

    assert(msgTo->addresseesCount > 0);
    if (type1 == NULL) {
        type1 = c_resolve(base, "durabilityModule2::d_networkAddress_s");
    }
    assert(type1 != NULL);
    msgTo->addressees = c_arrayNew(type1, msgTo->addresseesCount);
    assert(msgTo->addressees);
    memcpy(msgTo->addressees, msgFrom->addressees, msgTo->addresseesCount*C_SIZEOF(d_networkAddress));

    msgTo->source.systemId    = msgFrom->source.systemId;
    msgTo->source.localId     = msgFrom->source.localId;
    msgTo->source.lifecycleId = msgFrom->source.lifecycleId;

    switch(msgTo->msgBody._d) {
    case BEAD:
        if (type0 == NULL) {
            type0 = c_resolve(base, "c_octet");
        }
        assert(type0 != NULL);
        valueSize = msgFrom->msgBody._u.bead.size;
        msgTo->msgBody._u.bead.size  = valueSize;
        msgTo->msgBody._u.bead.value = c_arrayNew(type0, valueSize);
        memcpy(msgTo->msgBody._u.bead.value, msgFrom->msgBody._u.bead.value, valueSize);
    break;
    case LINK:
        msgTo->msgBody._u.link.nrSamples      = msgFrom->msgBody._u.link.nrSamples;
        msgTo->msgBody._u.link.completeness   = msgFrom->msgBody._u.link.completeness;
    break;
    default:
        OS_REPORT_1(OS_ERROR, "d_publisherSampleChainWriterCopy", 0,
                    "Illegal message body discriminant value (%d) detected.",
                    msgTo->msgBody._d);
        assert(FALSE);
    }

    return TRUE;
}
Beispiel #2
0
v_networkReader
v_networkReaderNew(
    v_subscriber subscriber,
    const c_char *name,
    v_readerQos qos,
    c_bool ignoreReliabilityQoS)
{
    /* Note: currently, no qos-es are supported. Everything is redirected
     *       to the defaultQueue */

    v_kernel kernel;
    v_networkReader reader;
    v_readerQos q;
    v_statistics s;
    c_type queueType;
    c_long i;

    assert(C_TYPECHECK(subscriber,v_subscriber));

    /* Creation */
    kernel = v_objectKernel(subscriber);
    q = v_readerQosNew(kernel,qos);
    if (q != NULL) {
        reader = v_networkReader(v_objectNew(kernel,K_NETWORKREADER));
        s = v_statistics(v_networkReaderStatisticsNew(kernel));

        /* Initialization of parent */
        v_readerInit(v_reader(reader), name, subscriber, q, s, TRUE);
        c_free(q); /* ref now in v_reader(queue)->qos */

        /* This function only ever called once per network instance so no
         * need to store queueType as static variable.  Look up as needed (once)
         */
        queueType = c_resolve(c_getBase(subscriber),"kernelModule::v_networkQueue");
        /* Initialization of self */
        reader->queues = NULL;
        reader->queues = c_arrayNew(queueType, NW_MAX_NOF_QUEUES);
        reader->nofQueues = 0;
        reader->defaultQueue = NULL;
        reader->remoteActivity = FALSE;
        reader->ignoreReliabilityQoS = ignoreReliabilityQoS;
        reader->queueCache = c_arrayNew(queueType, 2*NW_MAX_QUEUE_CACHE_PRIO);
        for( i= 0; i < 2*NW_MAX_QUEUE_CACHE_PRIO; i++) {
            reader->queueCache[i] = NULL;
        }
        c_free(queueType);
        /* Add to subscriber */
        v_subscriberAddReader(subscriber,v_reader(reader));
    } else {
        OS_REPORT(OS_ERROR, "v_networkReaderNew", 0,
            "NetworkReader not created: inconsistent qos");
        reader = NULL;
    }

    return reader;
}
Beispiel #3
0
c_array
c_metaArray(
    c_metaObject scope,
    c_iter iter,
    c_metaKind kind)
{
    c_long i;
    struct copyToArrayArg arg;
    c_type type;

    if (kind) {
        /* suppress warnings */
    }
    i = c_iterLength(iter);
    if (i == 0) {
        arg.a = NULL;
    } else {
        type = c_object_t(c__getBase(scope));
        arg.a = c_arrayNew(type,i);
        arg.index = 0;
        c_iterWalk(iter,copyToArray,&arg);
        c_iterFree(iter);
        c_free(type);
    }
    return arg.a;
}
Beispiel #4
0
static c_type
createKeyType(
    const c_char *name,
    c_array keyList)
{
    c_base base;
    c_type foundType;
    c_char *typeName;
    c_char keyName[16];
    c_long i, length, sres;
    c_array members;
    c_metaObject o;
    c_field field;

    if (keyList == NULL) {
        return NULL;
    }
    base = c_getBase(keyList);
    length = c_arraySize(keyList);
    if (length == 0) {
        return NULL;
    }
    o = c_metaDefine(c_metaObject(base),M_STRUCTURE);
    members = c_arrayNew(c_member_t(base),length);

    for (i=0;i<length;i++) {
        field = keyList[i];
        assert(field != NULL);
        members[i] = (c_voidp)c_metaDefine(c_metaObject(base),M_MEMBER);
            sprintf(keyName,"field%d",i);
            c_specifier(members[i])->name = c_stringNew(base,keyName);
            c_specifier(members[i])->type = c_keep(c_fieldType(field));
    }
    c_structure(o)->members = members;
    c_metaObject(o)->definedIn = c_metaObject(base);
    c_metaFinalize(o);
#define KEY_NAME   "<Key>"
#define KEY_FORMAT "%s<Key>"

    if (name != NULL) {
        length = sizeof(KEY_NAME) + strlen(name);
        typeName = os_malloc(length);
        sres = snprintf(typeName,length,KEY_FORMAT,name);
        assert(sres == (length-1));
    } else {
        assert(FALSE);
        length = 100;
        typeName = os_malloc(length);
        os_sprintf(typeName,PA_ADDRFMT KEY_NAME,(c_address)o);
    }
#undef KEY_NAME
#undef KEY_FORMAT
    foundType = c_type(c_metaBind(c_metaObject(base),typeName,o));

    c_free(o);
    os_free(typeName);

    return foundType;

}
v_historicalDataRequest
v_historicalDataRequestNew(
    v_kernel kernel,
    c_char* filter,
    c_char* params[],
    c_ulong nofParams,
    c_time minSourceTime,
    c_time maxSourceTime,
    struct v_resourcePolicy *resourceLimits)
{
    v_historicalDataRequest request;
    c_ulong i;
    c_type type;
    c_base base;

    request = c_new(v_kernelType(kernel,K_HISTORICALDATAREQUEST));

    if (request) {
        if(filter){
            base            = c_getBase(kernel);
            request->filter = c_stringNew(base, filter);

            if(params){
                type                  = c_string_t(base);
                request->filterParams = c_arrayNew(type, nofParams);

                for(i=0; i<nofParams; i++){
                    request->filterParams[i] = c_stringNew(base, params[i]);
                }
            } else {
                request->filterParams = NULL;
            }
        } else {
            request->filter       = NULL;
            request->filterParams = NULL;
        }
        if ((minSourceTime.seconds     == C_TIME_INVALID.seconds) &&
            (minSourceTime.nanoseconds == C_TIME_INVALID.nanoseconds)) {
            request->minSourceTimestamp = C_TIME_ZERO;
        } else {
            request->minSourceTimestamp  = minSourceTime;
        }
        if ((maxSourceTime.seconds     == C_TIME_INVALID.seconds) &&
            (maxSourceTime.nanoseconds == C_TIME_INVALID.nanoseconds)) {
            request->maxSourceTimestamp = C_TIME_INFINITE;
        } else {
            request->maxSourceTimestamp  = maxSourceTime;
        }
        request->resourceLimits.max_samples              = resourceLimits->max_samples;
        request->resourceLimits.max_instances            = resourceLimits->max_instances;
        request->resourceLimits.max_samples_per_instance = resourceLimits->max_samples_per_instance;
    } else {
        OS_REPORT(OS_ERROR,
                  "v_historicalDataRequestNew",0,
                  "Failed to allocate request.");
        assert(FALSE);
    }

    return request;
}
Beispiel #6
0
c_bool
d_publisherSampleRequestWriterCopy(
    c_type type,
    void *data,
    void *to)
{
    c_bool result;
    c_ulong i;
    static c_type type3;
    d_sampleRequest msgFrom = d_sampleRequest(data);
    d_sampleRequest msgTo   = d_sampleRequest(to);
    c_base base             = c_getBase(type);

    result = d_publisherMessageWriterCopy(&msgFrom->parentMsg, &msgTo->parentMsg);

    msgTo->partition      = c_stringNew(base, msgFrom->partition);
    msgTo->topic          = c_stringNew(base, msgFrom->topic);
    msgTo->durabilityKind = msgFrom->durabilityKind;
    msgTo->requestTime    = msgFrom->requestTime;
    msgTo->withTimeRange  = msgFrom->withTimeRange;
    msgTo->beginTime      = msgFrom->beginTime;
    msgTo->endTime        = msgFrom->endTime;

    msgTo->source.systemId    = msgFrom->source.systemId;
    msgTo->source.localId     = msgFrom->source.localId;
    msgTo->source.lifecycleId = msgFrom->source.lifecycleId;

    if(msgFrom->filter){
        msgTo->filter = c_stringNew(base, msgFrom->filter);
    } else {
        msgTo->filter = NULL;
    }
    if(msgFrom->filterParams){
        if (type3 == NULL) {
            type3 = c_resolve(base, "c_string");
        }
        assert(type3 != NULL);
        msgTo->filterParamsCount = msgFrom->filterParamsCount;
        msgTo->filterParams = c_arrayNew(type3, msgFrom->filterParamsCount);


        for(i=0; i<msgFrom->filterParamsCount; i++){
            msgTo->filterParams[i] = c_stringNew(base, msgFrom->filterParams[i]);
        }
    }
    msgTo->maxSamples            = msgFrom->maxSamples;
    msgTo->maxInstances          = msgFrom->maxInstances;
    msgTo->maxSamplesPerInstance = msgFrom->maxSamplesPerInstance;

    return result;
}
void
v_networkingStatisticsInit(
    v_networkingStatistics _this,
    v_kernel k)
{
    assert(_this != NULL);
    assert(C_TYPECHECK(_this, v_networkingStatistics));

    v_statisticsInit(v_statistics(_this));

    _this->numberOfErrors = 0;
    _this->channelsCount = 0;
    _this->channels = c_arrayNew(c_resolve(c_getBase(c_object(k)),
                                 "kernelModule::v_networkChannelStatistics"),64);

}
Beispiel #8
0
v_handleServer
v_handleServerNew (
    c_base base)
{
    v_handleServer server;
    c_type type;

    assert(base != NULL);

    type = c_resolve(base,"kernelModule::v_handleServer");
    server = c_new(type);
    c_free(type);
    if (server) {
        type = c_resolve(base,"kernelModule::v_handleInfoList");
        server->handleInfos = c_arrayNew(type,NROFCOL);
#ifdef DDS_1958_CANNOT_CALL_REGISTERED_FUNC_PTR_FROM_DIFF_PROCESS
        server->lowMemWarningCount = 0;
#endif
        c_free(type);
        if (server->handleInfos) {
            server->firstFree = NOHANDLE;
            server->lastIndex = NOHANDLE;
            server->suspended = FALSE;
            c_mutexInit(&server->mutex,SHARED_MUTEX);
            c_baseOnOutOfMemory(base, disableHandleServer,server);
            c_baseOnLowOnMemory(base, issueLowMemoryWarning, server);
        } else {
            c_free(server);
            server = NULL;
            OS_REPORT(OS_ERROR,"v_handleServerNew",0,
                      "Failed to allocate handle info records");
        }
    } else {
        OS_REPORT(OS_ERROR,"v_handleServerNew",0,
                  "Failed to allocate handle server");
    }
    return server;
}
Beispiel #9
0
static c_array
copyReaderGIDsFromPublications(
    v_deliveryGuard _this)
{
    /* copy system Ids from _this->publications */
    C_STRUCT(copySystemIdsArg) arg;
    c_long size;

    if (_this->publications) {
        size = c_count(_this->publications);
    } else {
        size = 0;
    }
    if (size > 0) {
        arg.readerGID = c_arrayNew(_this->gidType,size);
        arg.index = 0;
        c_walk(_this->publications, copySystemIds, &arg);
    } else {
        arg.readerGID = NULL;
    }

    return arg.readerGID;
}
Beispiel #10
0
c_unionCase
c_unionCaseNew (
    c_metaObject scope,
    const c_char *name,
    c_type type,
    c_iter labels)
{
    c_unionCase o;
    c_ulong nrOfLabels;
    c_type subType;

    nrOfLabels = c_iterLength(labels);
    o = c_unionCase(c_metaDefine(scope,M_UNIONCASE));
    subType = c_type(c_metaResolve(scope,"c_literal"));
    o->labels = c_arrayNew(subType,nrOfLabels);
    c_free(subType);
    c_iterArray(labels,o->labels);
    c_specifier(o)->name = c_stringNew(c__getBase(scope),name);
    /* Do not keep type as usage expects transferral of refcount.
     * If changed then odlpp and idlpp must be adapted accordingly.
     */
    c_specifier(o)->type = type;
    return o;
}
Beispiel #11
0
static c_array
createKeyList(
    c_type instanceType,
    c_array keyList)
{
    c_ulong size, i;
    c_array newKeyList = NULL;

    assert(instanceType);

    if (keyList) {
        size = c_arraySize(keyList);

        newKeyList = c_arrayNew(c_field_t(c_getBase(instanceType)), size);

        if (newKeyList) {
            for(i = 0; i<size; i++){
                c_field f = c_fieldNew(instanceType, PREFIX);
                assert(f);
                if (f) {
                    newKeyList[i] = c_fieldConcat(f, keyList[i]);
                    c_free(f);
                } else {
                    OS_REPORT(OS_CRITICAL,
                                "createKeyList", V_RESULT_INTERNAL_ERROR,
                                "Could not create c_field");
                }
            }
        } else {
            OS_REPORT(OS_FATAL,
                        "createKeyList", V_RESULT_INTERNAL_ERROR,
                        "Could not create array");
        }
    }
    return newKeyList;
}
Beispiel #12
0
v_handle
v_handleServerRegister(
    v_handleServer server,
    c_object o)
{
    c_type type;
    v_handle handle;
    v_handleInfo *info, *block;
    c_long row, idx;

    assert(C_TYPECHECK(server,v_handleServer));
    assert(o != NULL);

    if(server->suspended == TRUE) {
        /* For now the suspended state means that an unrecoverable error has
         * occured. This implies that from now on any access to the kernel is
         * unsafe and the result is undefined.
         * So because of this and that registering new object are useless
         * skip this action and return NULL.
         */
        return V_HANDLE_NIL;
    }

    c_mutexLock(&server->mutex);

    if (server->firstFree != NOHANDLE) {
        idx = server->firstFree;
        block = ((v_handleInfo**)server->handleInfos)[COL(idx)];
        info = &block[ROW(idx)];
        server->firstFree = info->nextFree;
    } else {
        if (server->lastIndex == ((NROFCOL*NROFROW)-1)) {
            OS_REPORT(OS_ERROR,"Kernel v_handle",0,"Out of handle space");
            c_mutexUnlock(&server->mutex);

            exit(-1);
        }
        if (server->lastIndex == NOHANDLE) {
            server->lastIndex = 0;
        } else {
            server->lastIndex++;
        }
        idx = server->lastIndex;
        row = ROW(idx);
        if (row == 0) {
            type = c_resolve(c_getBase(o),"kernelModule::v_handleInfo");
            server->handleInfos[COL(idx)] = c_arrayNew(type,NROFROW);
        }
        block = ((v_handleInfo**)server->handleInfos)[COL(idx)];
        if (block) {
            info = &block[row];
            info->serial = SERIALSTART;
            c_mutexInit(&info->mutex,SHARED_MUTEX);
        } else {
            OS_REPORT(OS_ERROR,"v_handleServerRegister",0,
                      "Failed to allocate a new list of handles");
        }
    }

    if (info) {
        info->object   = c_keep(o);
        info->nextFree = NOHANDLE;
        info->count    = 0;
        info->freed    = FALSE;

        handle.server  = (c_address)server;
        handle.serial  = info->serial;
        handle.index   = idx;
    } else {
        handle  = V_HANDLE_NIL;
    }

    c_mutexUnlock(&server->mutex);

    return handle;
}
/* TODO should propagate the result code, might have an out of memory error
 * if allocation of the array failed
 */
void
in_messageDeserializerReadArray(
    in_messageDeserializer _this,
    c_type type,
    c_voidp data)
{
    in_result result = IN_RESULT_OK;
    c_collectionType ctype = c_collectionType(type);
    os_uint32 size;
    os_uint32 length;
    os_uint32 i;
    c_voidp array = NULL;
    c_object o;
    c_collKind typeKind;
    c_metaKind subTypeKind;

    assert(_this);
    assert(in_messageDeserializerIsValid(_this));
    assert(type);
    assert(data);

    /* First determine the length of the array. For IDL array types the length
     * is known, but for sequences it is encoded ahead of the elements as an
     * unsigned long
     */
    typeKind = ctype->kind;

    if(typeKind == C_ARRAY)
    {
        array = data;
        length = ctype->maxSize;
        assert(array);
    } else
    {
        assert(typeKind == C_SEQUENCE);
        /* For a sequence the length is encoded as an unsigned long, which in
         * CDR is 4 octets(bytes) in size.
         */
        assert(sizeof(os_uint32) == 4);
        in_messageDeserializerReadPrim(_this, 4, &length);
        /* Verify that the length is equal to or smaller then the maxSize if
         * maxSize is bigger then 0
         */
        if(ctype->maxSize > 0)
        {
            array = data;
            assert((c_long)length <= ctype->maxSize);
            assert(array);
        } else
        {
            if(*(c_voidp *)data)
            {
                array = *(c_voidp *)data;
            } else
            {
                array = c_arrayNew(type, (c_long)length);
                if(length > 0 && !array)
                {
                    result = IN_RESULT_OUT_OF_MEMORY;
                }
                *(c_voidp *)data = array;
            }
        }
    }

    if (length > 0 && result == IN_RESULT_OK)
    {
        assert(array);
        subTypeKind = c_baseObjectKind(c_baseObject(ctype->subType));
        if((subTypeKind == M_PRIMITIVE) ||(subTypeKind == M_ENUMERATION))
        {
            o = array;
           /* in_messageDeserializerReadPrimArray(
                _this,
                ctype->subType->size,
                length,
                o);*/
        } else
        {
            if (c_typeIsRef(ctype->subType))
            {
                size = sizeof(c_voidp);
            } else
            {
                size = ctype->subType->size;
            }
            o = array;
            for (i = 0; i < length; i++)
            {
                in_messageDeserializerReadType(_this, ctype->subType, o);
                o = C_DISPLACE(o, size);
            }
        }
    }
}
Beispiel #14
0
c_bool
d_publisherNameSpacesWriterCopy(
    c_type type,
    void *data,
    void *to)
{
    c_bool result;
    c_ulong i;
    static c_type mergeStateType = NULL;

    d_nameSpaces msgFrom = d_nameSpaces(data);
    d_nameSpaces msgTo   = d_nameSpaces(to);
    c_base base          = c_getBase(type);
    OS_UNUSED_ARG(type);

    result = d_publisherMessageWriterCopy(&msgFrom->parentMsg, &msgTo->parentMsg);

    msgTo->name                       = c_stringNew(base, msgFrom->name);
    msgTo->durabilityKind             = msgFrom->durabilityKind;
    msgTo->alignmentKind              = msgFrom->alignmentKind;
    msgTo->aligner                    = msgFrom->aligner;
    msgTo->total                      = msgFrom->total;
    msgTo->initialQuality.seconds     = msgFrom->initialQuality.seconds;
    msgTo->initialQuality.nanoseconds = msgFrom->initialQuality.nanoseconds;
    msgTo->master.systemId            = msgFrom->master.systemId;
    msgTo->master.localId             = msgFrom->master.localId;
    msgTo->master.lifecycleId         = msgFrom->master.lifecycleId;
    msgTo->isComplete                 = msgFrom->isComplete;
    msgTo->masterConfirmed            = msgFrom->masterConfirmed;
    msgTo->state.value                = msgFrom->state.value;

    if(msgFrom->partitions) {
        msgTo->partitions = c_stringNew(base, msgFrom->partitions);
    } else {
        msgTo->partitions = NULL;
    }
    if(msgFrom->state.role) {
        msgTo->state.role    = c_stringNew(base, msgFrom->state.role);
    } else {
        msgTo->state.role    = NULL;
    }
    msgTo->state.value       = msgFrom->state.value;
    msgTo->mergedStatesCount = msgFrom->mergedStatesCount;

    if (mergeStateType == NULL) {
        mergeStateType = c_resolve(base, "durabilityModule2::d_mergeState_s");
    }
    assert(mergeStateType);

    if(msgTo->mergedStatesCount > 0){
        msgTo->mergedStates = c_arrayNew(mergeStateType, msgTo->mergedStatesCount);
        assert(msgTo->mergedStates);
    } else {
        msgTo->mergedStates = NULL;
    }

    for(i=0; i<msgTo->mergedStatesCount; i++){
        (((d_mergeState)(msgTo->mergedStates))[i]).value =
            (((d_mergeState)msgFrom->mergedStates)[i]).value;
        (((d_mergeState)msgTo->mergedStates)[i]).role  =
            c_stringNew(base, (((d_mergeState)msgFrom->mergedStates)[i]).role);
    }


    return result;
}
Beispiel #15
0
static c_bool
createMessageKeyList(
    c_type messageType,
    const c_char *topicKeyExpr,
    c_array *keyListRef)
{
    c_array keyList;
    c_type fieldType;
    c_field field;
    c_iter splitNames, newNames;
    c_char *name, *newName;
    c_long i,length,sres;

    assert(keyListRef != NULL);

    *keyListRef = NULL;
    if (topicKeyExpr == NULL) {
        return TRUE;
    }
    newNames = NULL;
    splitNames = c_splitString(topicKeyExpr,", \t");
    while ((name = c_iterTakeFirst(splitNames)) != NULL) {
#define PATH_SEPARATOR "."
#define PREFIX "userData"
        length = strlen(PREFIX) + sizeof(PATH_SEPARATOR) + strlen(name);
        newName = (char *)os_malloc(length);
        sres = snprintf(newName,length,"%s"PATH_SEPARATOR"%s",PREFIX, name);
        assert(sres == (length-1));
#undef PREFIX
#undef PATH_SEPARATOR

        os_free(name);
        newNames = c_iterAppend(newNames,newName);
    }
    c_iterFree(splitNames);
    length = c_iterLength(newNames);
    if (length == 0) {
        return TRUE;
    }

    fieldType = c_field_t(c_getBase(messageType));
    keyList = c_arrayNew(fieldType,length);
    c_free(fieldType);
    i=0;
    while ((name = c_iterTakeFirst(newNames)) != NULL) {
        field = c_fieldNew(messageType,name);
        if (field == NULL) {
            OS_REPORT_1(OS_API_INFO,
                        "create message key list failed", 21,
                        "specified key field name %s not found",
                        name);
            os_free(name);
            c_iterFree(newNames);
            c_free(keyList);

            return FALSE;
        }
        keyList[i++] = field;
        os_free(name);
    }
    c_iterFree(newNames);
    *keyListRef = keyList;
    return TRUE;
}
Beispiel #16
0
struct v_messageExtCdrInfo *
v_messageExtCdrInfoNew(
    c_type topicMessageType,
    const struct sd_cdrControl *control)
{
    static const char headerTypeName[] = "kernelModule::v_messageExt";
    c_base base = c_getBase (topicMessageType);
    c_property userDataProperty = c_property(c_metaResolve(c_metaObject(topicMessageType),"userData"));
    c_type topicDataType = userDataProperty->type;
    c_type headerClass = c_resolve (base, headerTypeName);
    c_type dataClass;
    c_type type;
    c_object o;
    c_array members;
    struct v_messageExtCdrInfo *xci;
    struct c_type_s const *tstk[2];
    c_free(userDataProperty);

    /* Wrap user data in a class, so that we can make a struct with a pointer to it */
    dataClass = c_type(c_metaDefine(c_metaObject(base), M_CLASS));
    c_class(dataClass)->extends = NULL;
    o = c_metaDeclare(c_metaObject(dataClass), "userData", M_ATTRIBUTE);
    c_property(o)->type = c_keep(topicDataType);
    c_metaObject(dataClass)->definedIn = c_keep(base);
    c_metaFinalize(c_metaObject(dataClass));
    c_free(o);

    /* Make a struct containing two pointers, one to the v_messageExt class, and one to
     the just-created anonymous dataClass type, corresponding to struct v_messageExtCdrTmp */
    type = c_type(c_metaDefine(c_metaObject(base),M_STRUCTURE));
    members = c_arrayNew(c_member_t(base),2);
    members[0] = (c_voidp)c_metaDefine(c_metaObject(base),M_MEMBER);
    c_specifier(members[0])->name = c_stringNew(base,"h");
    c_specifier(members[0])->type = c_keep(headerClass);
    members[1] = (c_voidp)c_metaDefine(c_metaObject(base),M_MEMBER);
    c_specifier(members[1])->name = c_stringNew(base,"d");
    c_specifier(members[1])->type = c_keep(dataClass);
    c_structure(type)->members = members;
    c_metaObject(type)->definedIn = c_keep(base);
    c_metaFinalize(c_metaObject(type));
    c_free(dataClass);
    c_free(headerClass);

    xci = os_malloc(sizeof(*xci));
    xci->ci = sd_cdrInfoNewControl(type, control);

    /* Note: current simplistic annotation processing requires the annotations
     to be made in the order in which they are encountered when walking the
     type */
    tstk[0] = type;
    tstk[1] = headerClass;
    if (sd_cdrNoteQuietRef(xci->ci, 2, tstk) < 0) {
        goto err_note;
    }
    tstk[1] = dataClass;
    if (sd_cdrNoteQuietRef(xci->ci, 2, tstk) < 0) {
        goto err_note;
    }

    if (sd_cdrCompile(xci->ci) < 0) {
        goto err_compile;
    }
    xci->vmsgType = c_keep(topicMessageType);
    c_free(type);
    return xci;

err_compile:
err_note:
    os_free(xci);
    c_free(type);
    return NULL;
}