Skip to content

Add Lossless Data Product Compression Components#5235

Open
kubiak-jpl wants to merge 64 commits into
nasa:develfrom
kubiak-jpl:dev/dpcompressproc
Open

Add Lossless Data Product Compression Components#5235
kubiak-jpl wants to merge 64 commits into
nasa:develfrom
kubiak-jpl:dev/dpcompressproc

Conversation

@kubiak-jpl

Copy link
Copy Markdown
Collaborator
Related Issue(s) #4941
Has Unit Tests (y/n) y
Documentation Included (y/n) y
Generative AI was used in this contribution (y/n) n

Change Description

This PR makes the following changes

  • Adds the DpCompressProc component
    • This component plugs into the DpWriter Proc interface and is responsible for creating compressed data products. It uses a port call to a second compression component for the actual compression
  • Adds the DpZLibCompressor component
    • Uses libz to compress chunks of data
    • DpZLibCompressor requires libz to compile. This is a very common library, even in embedded contexts, but I currently don't have any CMake stuff to guard against it. @LeStarch Any thoughts here?
  • Adds compressed data product pipeline to TestDeployment and DpDemo subtopology
  • Adds command arguments to DpDemo to trigger compression of demo data products via command
  • Updates SerializeFrom to use memmove instead of memcpy
    • DpCompressProc re-serializes data into an existing buffer and can encounter situations where memory overlap occurs between input buffer and the destination serialized buffer. In those situations memcpy would execute with overlapping buffers and trigger undefined behavior
    • This change allows me to use serializeFrom method calls which make the algorithm to re-write the data product cleaner. However, I can also revert this change and modify my code to use memmove directly

Rationale

Implements lossless compressible data products seamlessly into the F Prime Data Product subsystem

Testing/Review Recommendations

The algorithm to modify the data product in place is non-trivial. I believe I have sufficiently thought through the state machine and have unit tests to cover all the cases. But it could use thorough review.

I had this integrated into the Ref deployment before that was moved.

Future Work

  1. Implement a compressor using LZMA for better compression ratios

AI Usage (see policy)

N/A

LeStarch
LeStarch previously approved these changes Jun 9, 2026
Comment thread Svc/DpZLibCompressor/DpZLibCompressor.hpp Fixed
@thomas-bc

thomas-bc commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

#5319 - looks like the TestUtils/Optional was moved/modified in devel so it's now breaking the UTs here

Comment thread TestDeploymentsProject/Ref/DpDemo/DpDemo.fpp

@thomas-bc thomas-bc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - one comment on CI testing

Comment thread TestDeploymentsProject/Ref/Top/topology.fpp
thomas-bc
thomas-bc previously approved these changes Jul 6, 2026

@thomas-bc thomas-bc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened follow-up ticket for integration tests: #5358

Comment thread Svc/DpCompressProc/DpCompressProc.cpp Outdated
Comment thread Svc/DpZLibCompressor/test/ut/DpZLibCompressorTester.cpp
lestarch-autobot

This comment was marked as resolved.

std::numeric_limits<uInt>::max());
return CompressionAlgorithm::UNCOMPRESSED;
}

static_cast<FwAssertArgType>(buffer.getSize()), static_cast<FwAssertArgType>(write_offset),
static_cast<FwAssertArgType>(ctx.compression_buffer.getSize()));

std::memcpy(buffer.getData() + write_offset, ctx.compression_buffer.getData(),

if (alg != CompressionAlgorithm::UNCOMPRESSED) {
// Compression completed and the size is <= min size
// Copy the compressed data into the original buffer
if (ctx.zlib_alloc_buffer.getSize() == 0) {
log_WARNING_LO_ZLibAllocBadBuffer(zlib_alloc_size);

cleanupContext(ctx);

ctx.compression_buffer = bufferCompressionGet_out(0, min_compression);
if (ctx.compression_buffer.getSize() == 0) {
log_WARNING_LO_ZLibCompressionBadBuffer(min_compression);
container.deserializeHeader();

FwSizeType prm_chunk_size = paramGet_CHUNK_SIZE(param_valid);
FW_ASSERT((param_valid == Fw::ParamValid::DEFAULT) || (param_valid == Fw::ParamValid::VALID), param_valid);
FW_ASSERT(ok == Fw::FW_SERIALIZE_OK, ok);
ok = serializer.serializeFrom(metadata);
FW_ASSERT(ok == Fw::FW_SERIALIZE_OK, ok);
}
ok = serializer.serializeFrom(record_id);
FW_ASSERT(ok == Fw::FW_SERIALIZE_OK, ok);
ok = serializer.serializeFrom(
static_cast<FwSizeStoreType>(compressed_payload_size + CompressionMetadata::SERIALIZED_SIZE));
ok = serializer.serializeFrom(record_id);
FW_ASSERT(ok == Fw::FW_SERIALIZE_OK, ok);
ok = serializer.serializeFrom(
static_cast<FwSizeStoreType>(compressed_payload_size + CompressionMetadata::SERIALIZED_SIZE));
Comment thread Fw/Types/Serializable.cpp
FW_ASSERT(this->getBuffAddr());
// copy buffer to our buffer
(void)memcpy(&this->getBuffAddr()[this->m_serLoc], buff, static_cast<size_t>(length));
(void)memmove(&this->getBuffAddr()[this->m_serLoc], buff, static_cast<size_t>(length));
@thomas-bc thomas-bc requested a review from LeStarch July 8, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants