Rculbertson/tombstone rebase

With this PR, we no longer use tombstones. Instead when a job is removed, the master will delete the job from zookeeper. To protect against the case where operational error causes zookeeper to lose all data, or we aim an agent at the wrong zookeeper cluster, we check for the existence of a cluster ID node. If this node is not present, the zookeeper client will throw an exception, and the agent will not sync down the latest jobs.

Sorry, my bad.  I made a few leaps here and used rationale that I totally didn't explain at all.  Let me fix that.  Apologies for the wall o' text.
* I suggested the implementation as a separate method since the code went from one line to about twenty in a function that was only about twenty to start with.  So now a function named `sync()` is now spending about half it's code loading rather than doing what it's name implies.
    * This way, in the cases where the reader doesn't care about how the children are obtained and only cares about the syncing operation itself can now ignore how children are gotten. 
    *  It documents intent better.  
    * Contrary to just about every other language I know, function calls in java are cheap, so runtime overhead is negligible, and in some cases the JVM can even make methods extracted this way faster than the inline case.  FWIW, in Java, it's a common enough operation that IDE's have hotkeys to do method extraction, as well as "jump to function" in the case they do care to know.  
    * Decomposition into methods allows you to minimize what the reader needs to keep in their heads.  They can understand an algorithm in it's parts.  Specifically, it makes explicit to the reader the effective lifetimes of variables.  It can expose more clearly the structure of conditional logic with respect to the parts.  It can also assist the compiler in doing dataflow and escape analysis, since dependencies between functions are made explicit.  In this case, if they only care about how we deal with the handling of the id node, they don't have to learn about how syncing works.
    * It can aid in testing as you can now test these smaller functions independently.
* Extraction as a method allows us to conveniently bail out of the loop via return, making the condition of the while altogether unnecessary.  This allows for a simpler top-down reading of the code, since the reader doesn't have to keep the loop condition in their head -- especially since looping a second time is the exceptional case, rather than the norm.  Nor do you have to set up the condition to be true on the first go around, and subsequently false to bail out.
* Use of `final`: unlike the properties of `const`-correctness in C/C++, in Java, we only have `final` which guarantees that the variable won't be reassigned after initialization.  Generally, if it's fairly trivial to be able to make variables final, it's preferable for readability -- this way, when you see something that isn't final, it's a strong signal to the reader that they need to pay closer attention to how it's used.  It also can make the compiler/jvm able to perform some optimizations.

As for code bloat, even though I spaced things out a bit more (including breaking of lines in the assignment of `possibleChildren`), unless I miscounted, it's a line or two shorter; depending on how you count.  The suggested code also has only three assigments and one conditional, yours has five and two respectively.

As for "Function is a minimal unit of reusable code": In monolithic functions that do more than one "thing", the lifetime of the variables can be muddled; for example, is a variable defined at the top of the function only used near the top, or is it used throughout the whole thing?  You have to read the whole function to know.  If there's significant amounts of conditional logic with long then/else bodies, readability suffers quite a bit too, especially when you see a series of close braces -- which block did these close?  How far up do I need to scroll to find out?  Oh crap, what line was I on again?...  When functions like this are decomposed, most of these problems vanish.  Decomposed functions tend to evolve nicely over time too, whereby the monolithic functions tend to get more and more complex over time.

In short: The easiest code to read is the code you, or future-you, do not **have** to read.

I think the book Effective Java 2nd Edition has something to say on this kind of thing, but I may be wrong.  Either way, EJ2E is definitely worth a read just anyway.

Lastly: in the code I suggested, I goofed.  I should have, instead of writing `String.format("/config/id/%s", clusterId)`, it should instead have written `Paths.configId(clusterId)`.