Uploaded image for project: 'Go Driver'
  1. Go Driver
  2. GODRIVER-836

zLib compression does not work

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 1.0.0-rc2
    • Affects Version/s: 0.3.0
    • Component/s: Core API
    • None

      It looks like zLib compression is broken.

      Running the tests with `MONGO_GO_DRIVER_COMPRESSOR=zlib` causes failures. To recreate this first set up a mongod with `--networkMessageCompressors="zlib"`. Many tests fail, but here is one example:

      TOPOLOGY=server MONGO_GO_DRIVER_COMPRESSOR=zlib go test -v ./x/network/integration -run TestCompression

      And the result:

      === RUN   TestCompression
      --- FAIL: TestCompression (0.01s)
              Error Trace:    config.go:192
                              once.go:44
                              config.go:175
                              compressor_test.go:30
              Error:          Received unexpected error:
                              connection(localhost:27017[-2]) unable to decode message length: EOF
      FAIL
      FAIL    github.com/mongodb/mongo-go-driver/x/network/integration        0.029s
      

      I believe there are three underlying problems with the zLib compression.

      Firstly, `(z *ZlibCompressor) CompressBytes()` will always return an empty slice. This is because the `dest` slice is copied into a writer as the `buf` value. This `buf` is resliced as it is written to by the zLib compressor. So although the underlying array of dest is being updated, `dest`'s length is not being updated. So returning `dest` just returns a slice of zero elements. 

      Secondly, `(z *ZlibCompressor) UncompressBytes()` will also always return an empty slice. `io.ReadFull(zlibReader, dest)` reads exactly `len(dest)` bytes from `zlibReader` into `dest`. Since `c.uncompressBuf` is passed into `UncompressBytes` as a zero element slice, zlibReader will never read anything into dest. See connection.go for context.

      Thirdly, the way compressors are initialized leads to race conditions for the zLib compressor. Currently, a single compressor is initialized by `topology.WithConnString()` and is used for every connection (see topology_options.go). This is fine for Snappy. But for zLib, if multiple connections use the same zLib writer at the same time, they will all be accessing and modifying the writer's internal buffers. I think initializing a new compressor per connection is probably the way to go.

      I'm submitting a PR to address these three issues. Would love some more eyes to ensure I haven't misunderstood anything here.
       

            Assignee:
            tim.fogarty@mongodb.com Tim Fogarty
            Reporter:
            tim.fogarty@mongodb.com Tim Fogarty
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: