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;
    }
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.
/ acquire the lock before writing .