1

我正在从记录的数据库中播放 DDS 数据,并编写了一个 Java 程序来监听数据。我能够很好地接收大部分消息,但我收到了一些一致的异常,如下所示:

PRESCstReaderCollator_storeSampleData:!deserialize
java.lang.IllegalStateException: not enough available space in CDR buffer
    at com.rti.dds.cdr.CdrBuffer.checkSize(Unknown Source)
    at com.rti.dds.cdr.CdrInputStream.readShortFromBigEndian(Unknown Source)
    at com.rti.dds.cdr.CdrInputStream.deserializeAndSetCdrEncapsulation(Unknown Source)
    at <my type>.deserialize_key_sample(<my type>TypeSupport.java:456)
    at com.rti.dds.topic.TypeSupportImpl.deserialize_key(Unknown Source)
    at com.rti.dds.topic.TypeSupportImpl.deserialize_keyI(Unknown Source)

有没有人看到这个或知道什么可能导致这个?

编辑:我还应该补充一点,我目前正在使用 rtireplay 通过重放数据库接收 DDS 数据。在放入我被赋予使用的新重播配置后,我开始收到此错误。所以也许问题是什么重播配置设置会影响这样的事情?我还应要求在 IDL 中发布了混淆的 @key 字段

struct MyType{
    Key1 key1; //@key
    Key2 key2; //@key
    ...
}

struct Key1 {
    long long m; //@key
    long long l; //@key
    ...
}

//key members only
struct Key2 {
    Key1 a; //@key
    ...
}
4

1 回答 1

0

尽管堆栈跟踪略有不同,但我能够通过以下输出重现类似情况:

Exception in thread "Thread-5" java.lang.IllegalArgumentException: string length (200)
exceeds maximum (10)
    at com.rti.dds.cdr.CdrInputStream.readString(CdrInputStream.java:364)
    at stringStructTypeSupport.deserialize_key_sample(stringStructTypeSupport.java:411)
    at com.rti.dds.topic.TypeSupportImpl.deserialize_key(TypeSupportImpl.java:1027)
    at com.rti.dds.topic.TypeSupportImpl.deserialize_keyI(TypeSupportImpl.java:965)
PRESCstReaderCollator_storeSampleData:!deserialize

请注意,我使用的是 5.1.0,它的错误消息有点冗长。

发生这种情况的条件如下:

  • DataReader 期望一个具有不同键定义的类型,或者更准确地说,一个与 DataWriter 生成的大小不同的键定义。在我的例子中,DataWriter 生成了一个 200 个字符的字符串键属性,而 DataReader 期望一个不超过 10 个字符的字符串。
  • DataWriter 将 QoS 设置protocol.serialize_key_with_dispose设置为 true,这意味着实际使用此不一致的密钥(与其密钥哈希相反)来确定实例,以防dispose()
  • 如果您使用的是 5.1.0 或更高版本:发布参与者的 QoS 设置为resource_limits.type_code_max_serialized_length并且resource_limits.type_object_max_serialized_length都设置为 0。这避免了类型信息的通信,因此防止检测到定义中的不一致。旧版本一开始就没有检查类型一致性,即使 resource_limits 设置为非零也是如此。
  • 错误发生在实例被删除的那dispose()一刻

尤其是不经常更改,这似乎是此函数可能出现在堆栈跟踪中protocol.serialize_key_with_dispose的唯一原因。deserialize_key如果您检查您的rtireplay配置并发现此特定设置设置为true,那么这里描述的场景很可能就是您的情况。

serialize_key_with_dispose设置是为了考虑到曾经收到的第一个键值样本恰好是 a 的情况dispose。这意味着该实例尚不为人所知。通常,实际的键值不会通过 dispose 传播,而只是散列键。这可能不足以确定 dispose 用于哪个实例。将此政策设为 true 会导致通过 dispose 传播完整的键值。它与propagate_dispose_of_unregistered_instances. 有关更多详细信息,请参阅Connext 用户手册的第6.5.3.5 节使用处置实例通知传播序列化密钥

于 2014-06-24T21:14:00.970 回答