public HollowHashIndexResult findMatches(Object... query) {
        if (hashStateVolatile == null) {
            throw new IllegalStateException(this + " wasn't initialized");
        }
        int hashCode = 0;

        for(int i=0;i<query.length;i++) {
            if(query[i] == null)
                throw new IllegalArgumentException("querying by null unsupported; i=" + i);
            hashCode ^= HashCodes.hashInt(keyHashCode(query[i], i));
        }

        HollowHashIndexResult result;
        HollowHashIndexState hashState;
        do {
            result = null;
            hashState = hashStateVolatile;
            long bucket = hashCode & hashState.getMatchHashMask();
            long hashBucketBit = bucket * hashState.getBitsPerMatchHashEntry();
            boolean bucketIsEmpty = hashState.getMatchHashTable().getElementValue(hashBucketBit, hashState.getBitsPerTraverserField()[0]) == 0;

            while (!bucketIsEmpty) {
                if (matchIsEqual(hashState.getMatchHashTable(), hashBucketBit, query)) {
                    int selectSize = (int) hashState.getMatchHashTable().getElementValue(hashBucketBit + hashState.getBitsPerMatchHashKey(), hashState.getBitsPerSelectTableSize());
                    long selectBucketPointer = hashState.getMatchHashTable().getElementValue(hashBucketBit + hashState.getBitsPerMatchHashKey() + hashState.getBitsPerSelectTableSize(), hashState.getBitsPerSelectTablePointer());

                    result = new HollowHashIndexResult(hashState, selectBucketPointer, selectSize);
                    break;
                }

                bucket = (bucket + 1) & hashState.getMatchHashMask();
                hashBucketBit = bucket * hashState.getBitsPerMatchHashEntry();
                bucketIsEmpty = hashState.getMatchHashTable().getElementValue(hashBucketBit, hashState.getBitsPerTraverserField()[0]) == 0;
            }
        } while (hashState != hashStateVolatile);

        return result;
    }
@Test
    public void testNotBindable() throws IOException {
        HollowWriteStateEngine writeEngine = new HollowWriteStateEngine();
        HollowObjectSchema movieSchema = new HollowObjectSchema("Movie", 3);
        movieSchema.addField("id", HollowObjectSchema.FieldType.LONG);
        movieSchema.addField("title", HollowObjectSchema.FieldType.REFERENCE, "String");
        movieSchema.addField("releaseYear", HollowObjectSchema.FieldType.INT);
        HollowObjectTypeWriteState movieState = new HollowObjectTypeWriteState(movieSchema);
        writeEngine.addTypeState(movieState);

        HollowObjectWriteRecord movieRec = new HollowObjectWriteRecord(movieSchema);
        movieRec.setLong("id", 1);
        movieRec.setReference("title", 0);  // NOTE that String type wasn't added
        movieRec.setInt("releaseYear", 1999);
        writeEngine.add("Movie", movieRec);

        HollowReadStateEngine readEngine = new HollowReadStateEngine();
        StateEngineRoundTripper.roundTripSnapshot(writeEngine, readEngine);

        // invalid because root type doesn't exist
        HollowHashIndex invalidHashIndex1 = new HollowHashIndex(readEngine, "String", "value", "value");
        try {
            invalidHashIndex1.findMatches("test");
            fail("Index on root type not bound is expected to fail hard at query time");
        } catch (IllegalStateException e) {}

        // invalid because a type in the field paths doesn't exist
        HollowHashIndex invalidHashIndex2 = new HollowHashIndex(readEngine, "Movie", "id", "title.value");
        try {
            invalidHashIndex2.findMatches("test");
            fail("Index on field path not bound is expected to fail hard at query time");
        } catch (IllegalStateException e) {}

        // valid index despite a non-indexed field (title) not bindable to a type (String)
        HollowPrimaryKeyIndex validPki = new HollowPrimaryKeyIndex(readEngine, "Movie", "id");
        Assert.assertEquals(0, validPki.getMatchingOrdinal(1L));
    }