several fixes/ improvements related to byte bufs

- using a.writeBytes(b) instead of b.readBytes(a) in all cases
because the latter only fills up to the transient writeableBytes()
value of a, whereas the former calls ensureCapacity and makes sure
that all data is transferred. IIRC, this was only done in a few
edge cases that require a user to be doing manual stream appends
(instead of just using the higher level filename based api like
hydra does), but might as well fix it.

- stopped using composite buffers for now due to a bug I discovered
in netty that wastes half of the buffer pool.

- more robust in-place buffer clean up. Composite buffers' discard
bytes methods had some unexpected behaviors that are different from
the spec. They can release components to the allocator (thus reducing
capacity) -- this is the behavior I wanted, but they do it pretty
inconsistently and so the trim buffers method has been made more
aggressive to match its former function.

- output buffers are io buffers with 0 initial capacity, and I
added some logic to bootstrap them up to 64k on the initial read.
This will cause them to get closer to 130k due to the netty bug,
but at least they will make use of that space as they get written
to. The vast majority of jobs will still need to expand the buffer
several times, but making it larger could potentially destroy an
edge case with many small writes.