func comp(comp_buf, block *Block, in, out DuplexPipe, wg *sync.WaitGroup) {

	defer wg.Done()

	if block.NBytes == in.BlockSize {

		// We are allocating comp_chunk extra here to know length
		// ! Fork snappy to return len(comp_buf.Buf) instead of
		// the the actual slice of comp_buf.Buf
		_, comp_buf.NBytes = snappy.Encode(comp_buf.Buf, block.Buf)
		//fmt.Println("Compressing block", block.BlockID, block_size, len(comp_chunk))

		// this misses the point of having reusable slices... :-(
		//comp_buf.NBytes = len(comp_chunk)
		comp_buf.BlockID = block.BlockID

	} else {
		comp_buf.NBytes = block.NBytes
		comp_buf.BlockID = block.BlockID
		copy(comp_buf.Buf[:comp_buf.NBytes], block.Buf)
	}

	in.Upstream <- block
	out.Downstream <- comp_buf
}
func comp(block *Block, out chan *Block, block_size int, wg *sync.WaitGroup) {

	defer wg.Done()

	comp_len := snappy.MaxEncodedLen(block_size)
	comp_block := &Block{make([]byte, comp_len), 0, 0}

	if block.NBytes == block_size {
		comp_block.Buf, comp_block.NBytes = snappy.Encode(comp_block.Buf, block.Buf)
		comp_block.BlockID = block.BlockID

	} else {
		comp_block.NBytes = block.NBytes
		comp_block.BlockID = block.BlockID
		copy(comp_block.Buf[:comp_block.NBytes], block.Buf)
	}

	out <- comp_block
}