palantir / atlasdb

Transactional Distributed Database Layer

Home Page:https://palantir.github.io/atlasdb/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RangeRequest Breaches The hashCode() Contract

jeremyk-91 opened this issue · comments

    @Test
    public void wat() {
        RangeRequest r1 = RangeRequest.builder()
                .startRowInclusive(PtBytes.toBytes("tom"))
                .endRowExclusive(PtBytes.toBytes("zzzz"))
                .retainColumns(ImmutableList.of(PtBytes.toBytes("name")))
                .build();
        RangeRequest r2 = RangeRequest.builder()
                .startRowInclusive(PtBytes.toBytes("tom"))
                .endRowExclusive(PtBytes.toBytes("zzzz"))
                .retainColumns(ImmutableList.of(PtBytes.toBytes("name")))
                .build();

        assertThat(r1).isEqualTo(r2); // passes
        assertThat(r1.hashCode()).isEqualTo(r2.hashCode()); // :(
        assertThat(ImmutableSet.of(r1, r2).size()).isEqualTo(1); // :(
    }

Ran into this when trying to work on the range requests issue. Looks like this is caused by the way the hash calls Object.hash on an ImmutableSortedSet of byte arrays, among other things - this extracts the hash code of the ImmutableSortedSet, which is based on the hash code of its elements (but of course for arrays these are identity-hashcodes).

This is not a problem for Guava, because they do warn about undefined behaviour for users of arrays with a comparator like unsigned bytes.

Unsure about the scope of the badness, but uses of things like Map<RangeRequest, T> where we expect multiple updates to a key to replace its value / use computeIfAbsent style workflows are broken.