uber/statsrelay — pull request #19 by eklitzke (2014-12-10 01:18:22+00:00)
Title: implement the carbon protocol

This implements the carbon protocol.

Here's what you should know:
* In addition to the new end-to-end tests, I've validated this change with valgrind and whatnot. I even fixed some bugs in the old code where things were not passing valgrind.
* The `statsrelay` binary will run EITHER in "statsd" mode or "carbon" mode. The default is statsd mode. To run with carbon, you invoke as `statsrelay --protocol=carbon`.
* In the long term, I'd like to remove the `--protocol` flag and put them in the same binary, and just have it bind on all ports; the current way I've done it though isolates the carbon change a little more, although it means we need to run two binaries in production. I can easily merge this into a single binary now, though, if people prefer.
* Protocol parsing logic is now abstracted into `protocol.{c,h}` -- the statsd code there is primarily just moved from `stats.c` where it lived before (with some small changes).
* Protocol validation logic is now abstracted into `validate.{c,h` -- the statsd code there is primarily just moved from `stats.c` where it lived before (with some small changes).
* The stats object is now parameterized by a protocol parser and validator.
* I made a TON of const-correctness changes, since the old code essentially did not ever use const pointers.... there was a LOT of really iffy code that was munging passed in `char *` types and then trying to re-munge on the way out. In a lot of cases I was able to just convert things to `const char *` with no changes. In the munging cases, I'm trypically copying the string with `strdup(3)` or `strndup(3)` and then free'ing the copied string later. I think this is MUCH safer and has negligible overhead. In a few places I've had to do a const cast to a non-const type, but the methods where that applied are actually const.
* In some cases we're making unnecessary memory allocations and copies as a result of the const correctness changes. For instance, `validate_statsd()` now allocates memory (the old did not). I can go back and clean these up later (I mostly added TODO notes I believe), however, I think the overhead is negligible.
* I implemented some further optimizations like a static line buffer in the UDP recv function but I haven't finished all of these; for instance, the same optimization could be moved to the TCP recv function.
* Note that the carbon protocol will accept UDP messages even though the actual carbon protocol only works over TCP (I believe). I figured we might as well support UDP because why not.

There's definitely more cleanup work to be done, but this works and I think is probably as fast or faster than the old code, even with the additional memory allocations.