hollow/src/main/java/com/netflix/hollow/core/memory/ByteArrayOrdinalMap.java
private synchronized int assignOrdinal(ByteDataBuffer serializedRepresentation, int hash, int preferredOrdinal) {
        if (preferredOrdinal < -1 || preferredOrdinal > ORDINAL_MASK) {
            throw new IllegalArgumentException(String.format(
                    "The given preferred ordinal %s is out of bounds and not within the closed interval [-1, %s]",
                    preferredOrdinal, ORDINAL_MASK));
        }
        if (size > sizeBeforeGrow) {
            growKeyArray();
        }

        /// check to make sure that after acquiring the lock, the element still does not exist.
        /// this operation is akin to double-checked locking which is 'fixed' with the JSR 133 memory model in JVM >= 1.5.
        /// Note that this also requires pointersAndOrdinals be volatile so resizes are also visible
        AtomicLongArray pao = pointersAndOrdinals;

        int modBitmask = pao.length() - 1;
        int bucket = hash & modBitmask;
        long key = pao.get(bucket);

        while (key != EMPTY_BUCKET_VALUE) {
            if (compare(serializedRepresentation, key)) {
                return (int) (key >>> BITS_PER_POINTER);
            }

            bucket = (bucket + 1) & modBitmask;
            key = pao.get(bucket);
        }

        /// the ordinal for this object still does not exist in the list, even after the lock has been acquired.
        /// it is up to this thread to add it at the current bucket position.
        int ordinal = findFreeOrdinal(preferredOrdinal);
        if (ordinal > ORDINAL_MASK) {
            throw new IllegalStateException(String.format(
                    "Ordinal cannot be assigned. The to be assigned ordinal, %s, is greater than the maximum supported ordinal value of %s",
                    ordinal, ORDINAL_MASK));
        }

        long pointer = byteData.length();

        VarInt.writeVInt(byteData, (int) serializedRepresentation.length());
        /// Copying might cause a resize to the segmented array held by byteData
        /// A reading thread may observe a null value for a segment during the creation
        /// of a new segments array (see SegmentedByteArray.ensureCapacity).
        serializedRepresentation.copyTo(byteData);
        if (byteData.length() > MAX_BYTE_DATA_LENGTH) {
            throw new IllegalStateException(String.format(
                    "The number of bytes for the serialized representations, %s, is too large and is greater than the maximum of %s bytes",
                    byteData.length(), MAX_BYTE_DATA_LENGTH));
        }

        key = ((long) ordinal << BITS_PER_POINTER) | pointer;

        size++;

        /// this set on the AtomicLongArray has volatile semantics (i.e. behaves like a monitor release).
        /// Any other thread reading this element in the AtomicLongArray will have visibility to all memory writes this thread has made up to this point.
        /// This means the entire byte sequence is guaranteed to be visible to any thread which reads the pointer to that data.
        pao.set(bucket, key);

        return ordinal;
    }
private synchronized int assignOrdinal(ByteDataBuffer serializedRepresentation, int hash, int preferredOrdinal) {
        if (preferredOrdinal < -1 || preferredOrdinal > ORDINAL_MASK) {
            throw new IllegalArgumentException(String.format(
                    "The given preferred ordinal %s is out of bounds and not within the closed interval [-1, %s]",
                    preferredOrdinal, ORDINAL_MASK));
        }
        if (size > sizeBeforeGrow) {
            growKeyArray();
        }

        /// check to make sure that after acquiring the lock, the element still does not exist.
        /// this operation is akin to double-checked locking which is 'fixed' with the JSR 133 memory model in JVM >= 1.5.
        /// Note that this also requires pointersAndOrdinals be volatile so resizes are also visible
        AtomicLongArray pao = pointersAndOrdinals;

        int modBitmask = pao.length() - 1;
        int bucket = hash & modBitmask;
        long key = pao.get(bucket);

        while (key != EMPTY_BUCKET_VALUE) {
            if (compare(serializedRepresentation, key)) {
                return (int) (key >>> BITS_PER_POINTER);
            }

            bucket = (bucket + 1) & modBitmask;
            key = pao.get(bucket);
        }

        /// the ordinal for this object still does not exist in the list, even after the lock has been acquired.
        /// it is up to this thread to add it at the current bucket position.
        int ordinal = findFreeOrdinal(preferredOrdinal);
        if (ordinal > ORDINAL_MASK) {
            throw new IllegalStateException(String.format(
                    "Ordinal cannot be assigned. The to be assigned ordinal, %s, is greater than the maximum supported ordinal value of %s",
                    ordinal, ORDINAL_MASK));
        }

        long pointer = byteData.length();

        VarInt.writeVInt(byteData, (int) serializedRepresentation.length());
        /// Copying might cause a resize to the segmented array held by byteData
        /// A reading thread may observe a null value for a segment during the creation
        /// of a new segments array (see SegmentedByteArray.ensureCapacity).
        serializedRepresentation.copyTo(byteData);
        if (byteData.length() > MAX_BYTE_DATA_LENGTH) {
            throw new IllegalStateException(String.format(
                    "The number of bytes for the serialized representations, %s, is too large and is greater than the maximum of %s bytes",
                    byteData.length(), MAX_BYTE_DATA_LENGTH));
        }

        key = ((long) ordinal << BITS_PER_POINTER) | pointer;

        size++;

        /// this set on the AtomicLongArray has volatile semantics (i.e. behaves like a monitor release).
        /// Any other thread reading this element in the AtomicLongArray will have visibility to all memory writes this thread has made up to this point.
        /// This means the entire byte sequence is guaranteed to be visible to any thread which reads the pointer to that data.
        pao.set(bucket, key);

        return ordinal;
    }
/ acquire the lock before writing.