org.elasticsearch.index.fielddata.plain.ConcreteBytesRefAtomicFieldData.java Source code

Java tutorial

Introduction

Here is the source code for org.elasticsearch.index.fielddata.plain.ConcreteBytesRefAtomicFieldData.java

Source

/*
 * Licensed to ElasticSearch and Shay Banon under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. ElasticSearch licenses this
 * file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.elasticsearch.index.fielddata.plain;

import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.RamUsage;
import org.elasticsearch.common.lucene.HashedBytesRef;
import org.elasticsearch.index.fielddata.AtomicFieldData;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.index.fielddata.ordinals.EmptyOrdinals;
import org.elasticsearch.index.fielddata.ordinals.Ordinals;
import org.elasticsearch.index.fielddata.util.BytesRefArrayRef;
import org.elasticsearch.index.fielddata.util.IntArrayRef;
import org.elasticsearch.index.fielddata.util.StringArrayRef;

/**
 */
public class ConcreteBytesRefAtomicFieldData implements AtomicFieldData.WithOrdinals<ScriptDocValues.Strings> {

    public static ConcreteBytesRefAtomicFieldData empty(int numDocs) {
        return new Empty(numDocs);
    }

    // 0 ordinal in values means no value (its null)
    private final BytesRef[] values;
    protected final Ordinals ordinals;

    private int[] hashes;
    private long size = -1;

    public ConcreteBytesRefAtomicFieldData(BytesRef[] values, Ordinals ordinals) {
        this.values = values;
        this.ordinals = ordinals;
    }

    @Override
    public void close() {
    }

    @Override
    public boolean isMultiValued() {
        return ordinals.isMultiValued();
    }

    @Override
    public int getNumDocs() {
        return ordinals.getNumDocs();
    }

    @Override
    public boolean isValuesOrdered() {
        return true;
    }

    @Override
    public long getMemorySizeInBytes() {
        if (size == -1) {
            long size = RamUsage.NUM_BYTES_ARRAY_HEADER;
            for (BytesRef value : values) {
                if (value != null) {
                    size += RamUsage.NUM_BYTES_OBJECT_REF + RamUsage.NUM_BYTES_OBJECT_HEADER
                            + RamUsage.NUM_BYTES_ARRAY_HEADER + (value.length + (2 * RamUsage.NUM_BYTES_INT));
                }
            }
            size += ordinals.getMemorySizeInBytes();
            this.size = size;
        }
        return size;
    }

    @Override
    public BytesValues.WithOrdinals getBytesValues() {
        return ordinals.isMultiValued() ? new BytesValues.Multi(values, ordinals.ordinals())
                : new BytesValues.Single(values, ordinals.ordinals());
    }

    @Override
    public HashedBytesValues.WithOrdinals getHashedBytesValues() {
        if (hashes == null) {
            int[] hashes = new int[values.length];
            for (int i = 0; i < values.length; i++) {
                BytesRef value = values[i];
                hashes[i] = value == null ? 0 : value.hashCode();
            }
            this.hashes = hashes;
        }
        return ordinals.isMultiValued() ? new HashedBytesValues.Multi(values, hashes, ordinals.ordinals())
                : new HashedBytesValues.Single(values, hashes, ordinals.ordinals());
    }

    @Override
    public StringValues.WithOrdinals getStringValues() {
        return ordinals.isMultiValued() ? new StringValues.Multi(values, ordinals.ordinals())
                : new StringValues.Single(values, ordinals.ordinals());
    }

    @Override
    public ScriptDocValues.Strings getScriptValues() {
        return new ScriptDocValues.Strings(getStringValues());
    }

    static abstract class BytesValues implements org.elasticsearch.index.fielddata.BytesValues.WithOrdinals {

        protected final BytesRef[] values;
        protected final Ordinals.Docs ordinals;

        BytesValues(BytesRef[] values, Ordinals.Docs ordinals) {
            this.values = values;
            this.ordinals = ordinals;
        }

        @Override
        public Ordinals.Docs ordinals() {
            return this.ordinals;
        }

        @Override
        public BytesRef getValueByOrd(int ord) {
            return values[ord];
        }

        @Override
        public BytesRef getValueScratchByOrd(int ord, BytesRef ret) {
            BytesRef value = values[ord];
            if (value == null) {
                ret.length = 0;
            } else {
                ret.bytes = value.bytes;
                ret.offset = value.offset;
                ret.length = value.length;
            }
            return ret;
        }

        @Override
        public BytesRef getSafeValueByOrd(int ord) {
            return values[ord];
        }

        @Override
        public boolean hasValue(int docId) {
            return ordinals.getOrd(docId) != 0;
        }

        @Override
        public BytesRef makeSafe(BytesRef bytes) {
            // no need to do anything, its already concrete bytes...
            return bytes;
        }

        @Override
        public BytesRef getValue(int docId) {
            return values[ordinals.getOrd(docId)];
        }

        @Override
        public BytesRef getValueScratch(int docId, BytesRef ret) {
            BytesRef value = values[ordinals.getOrd(docId)];
            if (value == null) {
                ret.length = 0;
            } else {
                ret.bytes = value.bytes;
                ret.offset = value.offset;
                ret.length = value.length;
            }
            return ret;
        }

        static class Single extends BytesValues {

            private final BytesRefArrayRef arrayScratch = new BytesRefArrayRef(new BytesRef[1], 1);
            private final Iter.Single iter = new Iter.Single();

            Single(BytesRef[] values, Ordinals.Docs ordinals) {
                super(values, ordinals);
            }

            @Override
            public boolean isMultiValued() {
                return false;
            }

            @Override
            public BytesRefArrayRef getValues(int docId) {
                int ord = ordinals.getOrd(docId);
                if (ord == 0)
                    return BytesRefArrayRef.EMPTY;
                arrayScratch.values[0] = values[ord];
                return arrayScratch;
            }

            @Override
            public Iter getIter(int docId) {
                int ord = ordinals.getOrd(docId);
                if (ord == 0)
                    return Iter.Empty.INSTANCE;
                return iter.reset(values[ord]);
            }

            @Override
            public void forEachValueInDoc(int docId, ValueInDocProc proc) {
                int ord = ordinals.getOrd(docId);
                if (ord == 0) {
                    proc.onMissing(docId);
                } else {
                    proc.onValue(docId, values[ord]);
                }
            }
        }

        static class Multi extends BytesValues {

            private final BytesRefArrayRef arrayScratch = new BytesRefArrayRef(new BytesRef[10], 0);
            private final ValuesIter iter;

            Multi(BytesRef[] values, Ordinals.Docs ordinals) {
                super(values, ordinals);
                this.iter = new ValuesIter(values);
            }

            @Override
            public boolean isMultiValued() {
                return true;
            }

            @Override
            public BytesRefArrayRef getValues(int docId) {
                IntArrayRef ords = ordinals.getOrds(docId);
                int size = ords.size();
                if (size == 0)
                    return BytesRefArrayRef.EMPTY;

                arrayScratch.reset(size);
                for (int i = ords.start; i < ords.end; i++) {
                    arrayScratch.values[arrayScratch.end++] = values[ords.values[i]];
                }
                return arrayScratch;
            }

            @Override
            public Iter getIter(int docId) {
                return iter.reset(ordinals.getIter(docId));
            }

            @Override
            public void forEachValueInDoc(int docId, ValueInDocProc proc) {
                Ordinals.Docs.Iter iter = ordinals.getIter(docId);
                int ord = iter.next();
                if (ord == 0) {
                    proc.onMissing(docId);
                    return;
                }
                do {
                    proc.onValue(docId, values[ord]);
                } while ((ord = iter.next()) != 0);
            }

            static class ValuesIter implements Iter {

                private final BytesRef[] values;
                private Ordinals.Docs.Iter ordsIter;
                private int ord;

                ValuesIter(BytesRef[] values) {
                    this.values = values;
                }

                public ValuesIter reset(Ordinals.Docs.Iter ordsIter) {
                    this.ordsIter = ordsIter;
                    this.ord = ordsIter.next();
                    return this;
                }

                @Override
                public boolean hasNext() {
                    return ord != 0;
                }

                @Override
                public BytesRef next() {
                    BytesRef value = values[ord];
                    ord = ordsIter.next();
                    return value;
                }
            }
        }
    }

    static abstract class HashedBytesValues
            implements org.elasticsearch.index.fielddata.HashedBytesValues.WithOrdinals {

        protected final BytesRef[] values;
        protected final int[] hashes;
        protected final Ordinals.Docs ordinals;

        protected final HashedBytesRef scratch = new HashedBytesRef();

        HashedBytesValues(BytesRef[] values, int[] hashes, Ordinals.Docs ordinals) {
            this.values = values;
            this.hashes = hashes;
            this.ordinals = ordinals;
        }

        @Override
        public Ordinals.Docs ordinals() {
            return this.ordinals;
        }

        @Override
        public HashedBytesRef getValueByOrd(int ord) {
            return scratch.reset(values[ord], hashes[ord]);
        }

        @Override
        public HashedBytesRef getSafeValueByOrd(int ord) {
            return new HashedBytesRef(values[ord], hashes[ord]);
        }

        @Override
        public boolean hasValue(int docId) {
            return ordinals.getOrd(docId) != 0;
        }

        @Override
        public HashedBytesRef makeSafe(HashedBytesRef bytes) {
            // we just need to create a copy of the bytes ref, no need
            // to create a copy of the actual BytesRef, as its concrete
            return new HashedBytesRef(bytes.bytes, bytes.hash);
        }

        @Override
        public HashedBytesRef getValue(int docId) {
            int ord = ordinals.getOrd(docId);
            if (ord == 0)
                return null;
            return scratch.reset(values[ord], hashes[ord]);
        }

        static class Single extends HashedBytesValues {

            private final Iter.Single iter = new Iter.Single();

            Single(BytesRef[] values, int[] hashes, Ordinals.Docs ordinals) {
                super(values, hashes, ordinals);
            }

            @Override
            public boolean isMultiValued() {
                return false;
            }

            @Override
            public Iter getIter(int docId) {
                int ord = ordinals.getOrd(docId);
                if (ord == 0)
                    return Iter.Empty.INSTANCE;
                return iter.reset(scratch.reset(values[ord], hashes[ord]));
            }

            @Override
            public void forEachValueInDoc(int docId, ValueInDocProc proc) {
                int ord = ordinals.getOrd(docId);
                if (ord == 0) {
                    proc.onMissing(docId);
                } else {
                    proc.onValue(docId, scratch.reset(values[ord], hashes[ord]));
                }
            }
        }

        static class Multi extends HashedBytesValues {

            private final ValuesIter iter;

            Multi(BytesRef[] values, int[] hashes, Ordinals.Docs ordinals) {
                super(values, hashes, ordinals);
                this.iter = new ValuesIter(values, hashes);
            }

            @Override
            public boolean isMultiValued() {
                return true;
            }

            @Override
            public Iter getIter(int docId) {
                return iter.reset(ordinals.getIter(docId));
            }

            @Override
            public void forEachValueInDoc(int docId, ValueInDocProc proc) {
                Ordinals.Docs.Iter iter = ordinals.getIter(docId);
                int ord = iter.next();
                if (ord == 0) {
                    proc.onMissing(docId);
                    return;
                }
                do {
                    proc.onValue(docId, scratch.reset(values[ord], hashes[ord]));
                } while ((ord = iter.next()) != 0);
            }

            static class ValuesIter implements Iter {

                private final BytesRef[] values;
                private final int[] hashes;
                private Ordinals.Docs.Iter ordsIter;
                private int ord;

                private final HashedBytesRef scratch = new HashedBytesRef();

                ValuesIter(BytesRef[] values, int[] hashes) {
                    this.values = values;
                    this.hashes = hashes;
                }

                public ValuesIter reset(Ordinals.Docs.Iter ordsIter) {
                    this.ordsIter = ordsIter;
                    this.ord = ordsIter.next();
                    return this;
                }

                @Override
                public boolean hasNext() {
                    return ord != 0;
                }

                @Override
                public HashedBytesRef next() {
                    HashedBytesRef value = scratch.reset(values[ord], hashes[ord]);
                    ord = ordsIter.next();
                    return value;
                }
            }
        }
    }

    static abstract class StringValues implements org.elasticsearch.index.fielddata.StringValues.WithOrdinals {

        protected final BytesRef[] values;
        protected final Ordinals.Docs ordinals;

        protected StringValues(BytesRef[] values, Ordinals.Docs ordinals) {
            this.values = values;
            this.ordinals = ordinals;
        }

        @Override
        public Ordinals.Docs ordinals() {
            return ordinals;
        }

        @Override
        public String getValueByOrd(int ord) {
            BytesRef value = values[ord];
            if (value == null)
                return null;
            return value.utf8ToString();
        }

        @Override
        public boolean hasValue(int docId) {
            return ordinals.getOrd(docId) != 0;
        }

        @Override
        public String getValue(int docId) {
            BytesRef value = values[ordinals.getOrd(docId)];
            if (value == null)
                return null;
            return value.utf8ToString();
        }

        static class Single extends StringValues {

            private final StringArrayRef arrayScratch = new StringArrayRef(new String[1], 1);
            private final Iter.Single iter = new Iter.Single();

            Single(BytesRef[] values, Ordinals.Docs ordinals) {
                super(values, ordinals);
            }

            @Override
            public boolean isMultiValued() {
                return false;
            }

            @Override
            public StringArrayRef getValues(int docId) {
                int ord = ordinals.getOrd(docId);
                if (ord == 0)
                    return StringArrayRef.EMPTY;
                BytesRef value = values[ord];
                arrayScratch.values[0] = value == null ? null : value.utf8ToString();
                return arrayScratch;
            }

            @Override
            public Iter getIter(int docId) {
                int ord = ordinals.getOrd(docId);
                if (ord == 0)
                    return Iter.Empty.INSTANCE;
                return iter.reset(values[ord].utf8ToString());
            }

            @Override
            public void forEachValueInDoc(int docId, ValueInDocProc proc) {
                int ord = ordinals.getOrd(docId);
                if (ord == 0) {
                    proc.onMissing(docId);
                    return;
                }
                proc.onValue(docId, values[ord].utf8ToString());
            }
        }

        static class Multi extends StringValues {

            private final StringArrayRef arrayScratch = new StringArrayRef(new String[10], 0);
            private final ValuesIter iter;

            Multi(BytesRef[] values, Ordinals.Docs ordinals) {
                super(values, ordinals);
                iter = new ValuesIter(values);
            }

            @Override
            public boolean isMultiValued() {
                return true;
            }

            @Override
            public StringArrayRef getValues(int docId) {
                IntArrayRef ords = ordinals.getOrds(docId);
                int size = ords.size();
                if (size == 0)
                    return StringArrayRef.EMPTY;

                arrayScratch.reset(size);
                for (int i = ords.start; i < ords.end; i++) {
                    BytesRef value = values[ords.values[i]];
                    arrayScratch.values[arrayScratch.end++] = value == null ? null : value.utf8ToString();
                }
                return arrayScratch;
            }

            @Override
            public Iter getIter(int docId) {
                return iter.reset(ordinals.getIter(docId));
            }

            @Override
            public void forEachValueInDoc(int docId, ValueInDocProc proc) {
                Ordinals.Docs.Iter iter = ordinals.getIter(docId);
                int ord = iter.next();
                if (ord == 0) {
                    proc.onMissing(docId);
                    return;
                }
                do {
                    BytesRef value = values[ord];
                    proc.onValue(docId, value == null ? null : value.utf8ToString());
                } while ((ord = iter.next()) != 0);
            }

            static class ValuesIter implements StringValues.Iter {

                private final BytesRef[] values;
                private Ordinals.Docs.Iter ordsIter;
                private int ord;

                ValuesIter(BytesRef[] values) {
                    this.values = values;
                }

                public ValuesIter reset(Ordinals.Docs.Iter ordsIter) {
                    this.ordsIter = ordsIter;
                    this.ord = ordsIter.next();
                    return this;
                }

                @Override
                public boolean hasNext() {
                    return ord != 0;
                }

                @Override
                public String next() {
                    BytesRef value = values[ord];
                    ord = ordsIter.next();
                    return value == null ? null : value.utf8ToString();
                }
            }
        }
    }

    static class Empty extends ConcreteBytesRefAtomicFieldData {

        Empty(int numDocs) {
            super(null, new EmptyOrdinals(numDocs));
        }

        @Override
        public boolean isMultiValued() {
            return false;
        }

        @Override
        public int getNumDocs() {
            return ordinals.getNumDocs();
        }

        @Override
        public boolean isValuesOrdered() {
            return true;
        }

        @Override
        public long getMemorySizeInBytes() {
            return 0;
        }

        @Override
        public BytesValues.WithOrdinals getBytesValues() {
            return new BytesValues.WithOrdinals.Empty((EmptyOrdinals) ordinals);
        }

        @Override
        public HashedBytesValues.WithOrdinals getHashedBytesValues() {
            return new HashedBytesValues.WithOrdinals.Empty((EmptyOrdinals) ordinals);
        }

        @Override
        public StringValues.WithOrdinals getStringValues() {
            return new StringValues.WithOrdinals.Empty((EmptyOrdinals) ordinals);
        }

        @Override
        public ScriptDocValues.Strings getScriptValues() {
            return ScriptDocValues.EMPTY_STRINGS;
        }
    }
}