Skip to content

MDF3 channel error #150

@zhangyk99

Description

@zhangyk99

Hello, @ ihedvall,
I encountered an error while creating the MFD3 file channel.

If the number of channels created exceeds a certain limit, data recording will encounter problems, and data errors are only related to the number of channels. For example, using one time channel, 200 double channels with a size of 8 bytes, and 200 string channels with a size of 64 bytes may result in garbled or missing data during recording.
I am attaching a test code to illustrate the above issues.
May I ask if there is a specific quantity limit when creating MDF3 channels, or if it is possible to support recording data from nearly 5000 data channels simultaneously.

TEST(MDF3Error, test) {
    uint16_t channelNum = 200;
    string filePath = "D:/test/mdf3_test.mdf";
    ifstream f(filePath);
    if (f.good()) {
        f.close();
        ASSERT_EQ(remove(filePath.c_str()), 0);
    }
    auto writer = MdfFactory::CreateMdfWriterEx(MdfWriterType::Mdf3Basic);
    writer->Init(filePath);

    auto *header = writer->Header();
    ASSERT_TRUE(header != nullptr);

    auto *dg3 = writer->CreateDataGroup();
    auto *cg3 = mdf::MdfWriter::CreateChannelGroup(dg3);
    {
        auto *master = mdf::MdfWriter::CreateChannel(cg3);
        master->Name("Time");
        master->Description("Time channel");
        master->Type(ChannelType::Master);
        master->DataType(ChannelDataType::FloatLe);
        master->DataBytes(4);
        master->Unit("s");
    }
    for (uint32_t i = 0; i < channelNum; i++) {
        auto *channel = mdf::MdfWriter::CreateChannel(cg3);
        channel->Name("channel_double_" + to_string(i));
        channel->Description("float");
        channel->Type(ChannelType::FixedLength);
        channel->DataType(ChannelDataType::FloatLe);
        channel->DataBytes(sizeof(float));
    }
    for (uint32_t i = 0; i < channelNum; i++) {
        auto *channel = mdf::MdfWriter::CreateChannel(cg3);
        channel->Name("channel_string_" + to_string(i));
        channel->Description("string");
        channel->Type(ChannelType::FixedLength);
        channel->DataType(ChannelDataType::StringAscii);
        channel->DataBytes(64);
    }

    writer->InitMeasurement();
    writer->StartMeasurement(TimeStampToNs());
    for (size_t sample = 0; sample < 10; ++sample) {
        auto cn_list = cg3->Channels();
        cn_list[0]->SetChannelValue(0.01 * static_cast<double>(sample));
        for (uint32_t i = 0; i < channelNum; i++)
            cn_list[i + 1]->SetChannelValue(11.1 * static_cast<double>(sample));
        for (uint32_t i = 0; i < channelNum; i++)
            cn_list[i + channelNum + 1]->SetChannelValue(std::to_string(sample));

        auto ns70 = TimeStampToNs();

        writer->SaveSample(*cg3, ns70);
        this_thread::sleep_for(10ms);
    }
    writer->StopMeasurement(TimeStampToNs());
    writer->FinalizeMeasurement();

    MdfReader oRead(filePath);
    oRead.ReadEverythingButData();
    const auto *file = oRead.GetFile();
    DataGroupList dg_list;
    file->DataGroups(dg_list);
    for (auto *dg: dg_list) {
        ChannelObserverList observer_list;
        auto cg_list = dg->ChannelGroups();
        for (const auto *cg: cg_list) {
            CreateChannelObserverForChannelGroup(*dg, *cg, observer_list);
        }
        oRead.ReadData(*dg);

        double value = 0;
        uint32_t count = 0;
        bool valid = true;
        std::vector<double> values_exp{};
        std::vector<double> values_read{};
        for (const auto &channel: observer_list) {
            if (count == 0) {
                count++;
                continue;
            } else if (count < channelNum + 1) {
                size_t samples = channel->NofSamples();
                values_exp.clear();
                values_read.clear();
                bool fail = false;
                for (size_t sample = 0; sample < samples; ++sample) {
                    values_exp.push_back(11.1 * static_cast<double>(sample));
                    channel->GetEngValue(sample, value);
                    values_read.push_back(value);
                    if(11.1 * static_cast<double>(sample) - value > 0.00001)
                        fail = true;
                }
                if(fail)
                    EXPECT_EQ(values_read, values_exp);

            } else {
                size_t samples = channel->NofSamples();
                values_exp.clear();
                values_read.clear();
                bool fail = false;
                for (size_t sample = 0; sample < samples; ++sample) {
                    values_exp.push_back(sample);
                    channel->GetEngValue(sample, value);
                    values_read.push_back(value);
                    if(value == sample)
                        fail = true;
                }
                if(fail)
                    EXPECT_EQ(values_read, values_exp);
            }
            count++;
        }
    }
}

Extract some running results:

error: Expected equality of these values:
values_read
Which is: { 1.7219155529623352e-41, 1.7793687899996527e-41, 1.815242030686368e-41, 1.8366818971905377e-41, 1.8869885120597987e-41, 1.9012817563959118e-41, 1.9443016192506837e-41, 1.9873214821054556e-41, 2.0304814748066599e-41, 2.0735013376614318e-41 }
values_exp
Which is: { 0, 11.1, 22.2, 33.3, 44.4, 55.5, 66.6, 77.7, 88.8, 99.899999999999991 }

error: Expected equality of these values:
values_read
Which is: { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
values_exp
Which is: { 0, 11.1, 22.2, 33.3, 44.4, 55.5, 66.6, 77.7, 88.8, 99.899999999999991 }

C:\Users\79933\Documents\GitHub\PostMortemLogger\tests\PMLRecordTest.cpp(1171): error: Expected equality of these values:
values_read
Which is: { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
values_exp
Which is: { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }

There are probably several types of errors mentioned above, and only one truncation should be selected for each type.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions