Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for LZ4 compressed elevation tiles. #3401

Merged
merged 8 commits into from
Dec 7, 2021

Conversation

lseelenbinder
Copy link
Contributor

@lseelenbinder lseelenbinder commented Nov 13, 2021

This is not fully baked, but since I'm by no means a CMake or C++ expert, I wanted to ensure this was a reasonable start.

I'll still need to add tests and some additional documentation.

According to the tests, it does what it says on the cover. 😄

Issue

Adds drop-in support for lz4 elevation tiles. Briefly discussed here: #3071 (comment)

Tasklist

  • Add tests
  • Add #fixes with the issue number that this PR addresses
  • Update the docs with any new request parameters or changes to behavior described
  • Update the changelog
  • If you made changes to the lua files, update the taginfo too.

Requirements / Relations

Link any requirements here. Other pull requests this PR is based on?

@lseelenbinder lseelenbinder marked this pull request as draft November 13, 2021 12:01
@kevinkreiser
Copy link
Member

We'll want to add some unit tests just to exorcise the code paths, you can find some here for gzip, a similar approach can be used to check that lz4 is working properly: https://github.com/valhalla/valhalla/blob/master/test/sample.cc

@kevinkreiser kevinkreiser self-requested a review November 13, 2021 17:44

class cache_item_t {
private:
format_t format;
valhalla::midgard::mem_map<char> data;
int usages;
const char* unpacked;
Copy link
Member

Choose a reason for hiding this comment

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

this is unfortunate but i assume its an artifact of LZ4F_decompress taking a non const parameter

Copy link
Member

Choose a reason for hiding this comment

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

the good news is you dont need all of these removals of const because when we create the bytes where we unpack the data, we create it as non-const. so we can const cast it back before you make that call. ill make a suggestion below and then we can remove a lot of the changes here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, great! I cleaned it all up as suggested.

size_t dest_size = HGT_BYTES;
size_t result;
do {
result = LZ4F_decompress(decode, this->unpacked, &dest_size, data.get(), &src_size, &options);
Copy link
Member

Choose a reason for hiding this comment

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

we can revert all the changes you made to remove constness from this and just cast the const away at the time when we need to do that. this is ok because when we create unpacked we do so without const.

Suggested change
result = LZ4F_decompress(decode, this->unpacked, &dest_size, data.get(), &src_size, &options);
result = LZ4F_decompress(decode, const_cast<char *>(this->unpacked), &dest_size, data.get(), &src_size, &options);

@@ -353,6 +390,7 @@ tile_data cache_t::source(uint16_t index) {
}
}
}

if (!unpacked) {
unpacked = (char*)malloc(HGT_BYTES);
Copy link
Member

Choose a reason for hiding this comment

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

^^ this is why we can use const_cast, because here unpacked is not actually const so casting it away will not be undefined behavior

@kevinkreiser
Copy link
Member

@lseelenbinder this looks generally good, i think you can revert the changes to constness and add a unit test and we can get it reviewed. thanks!

@lseelenbinder
Copy link
Contributor Author

lseelenbinder commented Nov 13, 2021

@kevinkreiser I'm having difficulty tracking down where the test data files are for elevation. I found the test, but test/data/(sample|samplegz) don't exist on my branch so the current tests fail, as well? Is there some automated process for generating them, or should I download these from somewhere?

@kevinkreiser
Copy link
Member

@lseelenbinder its kind of tricky but we create this header file called test/pixels.h which has the binary data of a real tile (though not all of it) as an array of pixel values. we include this header with the vector and then in the test we turn it into elevation tiles: https://github.com/valhalla/valhalla/blob/master/test/sample.cc#L30-L70 then the actual tests check those.

so you'll want to lz4 compress that data in that same function and write it to another location. then you can add a unit test that checks that it loads ok like the other tests do: https://github.com/valhalla/valhalla/blob/master/test/sample.cc#L102-L104

@lseelenbinder lseelenbinder marked this pull request as ready for review November 26, 2021 23:12
@lseelenbinder lseelenbinder changed the title Draft: Add rudimentary support for LZ4 compressed elevation tiles. Add rudimentary support for LZ4 compressed elevation tiles. Nov 26, 2021
@lseelenbinder lseelenbinder changed the title Add rudimentary support for LZ4 compressed elevation tiles. Add support for LZ4 compressed elevation tiles. Nov 26, 2021
@lseelenbinder
Copy link
Contributor Author

Hey @kevinkreiser, I think this is ready for a final review now. Thanks for your help finishing it up!

Comment on lines +148 to +150
LZ4F_decompressionContext_t decode;
LZ4F_decompressOptions_t options;
LZ4F_createDecompressionContext(&decode, LZ4F_VERSION);
Copy link
Member

Choose a reason for hiding this comment

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

can you refresh my memory, does this also support LZ4_HC or other variants? i vaguely remember there were 3 formats, one was roughly normal but not fixed endian, another was fixed endian (probably network order) and one was "high compression". does this support all of them automatically or just one of them, and if the latter, which one? it was 3 years ago when i implemented it and i think i ended up going with the first one becuase its what the command line tool spits out maybe the others were containerless and more for streaming situations? sorry i just cant remember

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No worries, @kevinkreiser.

I just went with whatever the command line tool spit out. There's other formats that seem to be more for streaming, but it seemed the most logical target was the command line results. I made a few mistakes on the decompression side using lz4.h functions instead of lz4_frame.h functions, so it appears at least the lz4 command line outputs a framed format?

Should we just state we support files compressed with lz4 command line in the release notes? The command line doesn't seem to offer any options for this (https://linuxcommandlibrary.com/man/lz4).

Copy link
Member

Choose a reason for hiding this comment

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

nope thats all good. i just wanted to confirm my recollection. ill review this tonight hopefully when i have a free moment. thanks for the efforts!

@kevinkreiser
Copy link
Member

kevinkreiser commented Dec 6, 2021

this looks good to me but you need to resolve the conflicts, i would do it for you but you have that setting turned off

kevinkreiser
kevinkreiser previously approved these changes Dec 6, 2021
@@ -334,7 +376,7 @@ tile_data cache_t::source(uint16_t index) {
}

// item in cache is already unpacked
const char* unpacked = item.get_unpacked();
Copy link
Member

Choose a reason for hiding this comment

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

please revert this change, or use const auto *. auto is great and all but when we use it to hide qualifiers it makes everyones lives harder

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Whoops, that was an oversight. Good catch!

@lseelenbinder
Copy link
Contributor Author

Thanks again @kevinkreiser. Assuming tests pass, this should be good to go!

kevinkreiser
kevinkreiser previously approved these changes Dec 6, 2021
@kevinkreiser kevinkreiser merged commit b69f201 into valhalla:master Dec 7, 2021
@lseelenbinder lseelenbinder deleted the add-lz4-elevation-support branch December 7, 2021 14:11
ianthetechie pushed a commit to stadiamaps/valhalla that referenced this pull request Jan 12, 2022
* Add rudimentary support for LZ4 compressed elevation tiles.

* Tidy up code.

* Revert unnecessary const removals. Update CHANGELOG.md and add (failing) test.

* Add missing free for LZ4 context.

* Add attempt at compressing LZ4 elevation tiles.

* Add working lz4 elevation test.

* Cleanup formatting and pin lz4 to 1.9.3.

* Revert unnecessary `auto` usage.
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.

None yet

2 participants