com.netflix.hollow.tools.diff.exact.DiffEqualOrdinalMap Maven / Gradle / Ivy
/*
* Copyright 2016-2019 Netflix, Inc.
*
* Licensed 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 com.netflix.hollow.tools.diff.exact;
import com.netflix.hollow.core.memory.encoding.HashCodes;
import com.netflix.hollow.core.util.IntList;
import java.util.Arrays;
/**
* Not intended for external consumption.
*/
public class DiffEqualOrdinalMap {
public static final DiffEqualOrdinalMap EMPTY_MAP = new DiffEqualOrdinalMap(0);
private final long fromOrdinalsMap[];
private final IntList pivotedToOrdinalClusters;
private final long toOrdinalsIdentityMap[];
public DiffEqualOrdinalMap(int numMatches) {
int hashTableSize = 1 << (32 - Integer.numberOfLeadingZeros(numMatches * 2 - 1));
fromOrdinalsMap = new long[hashTableSize];
toOrdinalsIdentityMap = new long[hashTableSize];
pivotedToOrdinalClusters = new IntList();
Arrays.fill(fromOrdinalsMap, -1L);
Arrays.fill(toOrdinalsIdentityMap, -1L);
}
public void putEqualOrdinal(int fromOrdinal, int toOrdinal) {
long fromOrdinalMapEntry = (long)toOrdinal << 32 | fromOrdinal;
int hashCode = HashCodes.hashInt(fromOrdinal);
int bucket = hashCode & (fromOrdinalsMap.length - 1);
while(fromOrdinalsMap[bucket] != -1)
bucket = (bucket + 1) & (fromOrdinalsMap.length - 1);
fromOrdinalsMap[bucket] = fromOrdinalMapEntry;
}
public void putEqualOrdinals(int fromOrdinal, IntList toOrdinals) {
long fromOrdinalMapEntry = (long)toOrdinals.get(0) << 32 | fromOrdinal;
if(toOrdinals.size() > 1) {
fromOrdinalMapEntry = Long.MIN_VALUE | (long)pivotedToOrdinalClusters.size() << 32 | fromOrdinal;
for(int i=0;i= 0) {
int toOrdinal = (int)(fromOrdinalsMap[i] >> 32);
addToOrdinalIdentity(toOrdinal, toOrdinal);
}
}
boolean newCluster = true;
int currentIdentity = 0;
for(int i=0;i> 32));
return new SingleMatchIterator((int)(fromOrdinalsMap[bucket] >> 32));
}
bucket = (bucket + 1) & (fromOrdinalsMap.length - 1);
}
return EmptyMatchIterator.INSTANCE;
}
public int getIdentityFromOrdinal(int fromOrdinal) {
int hashCode = HashCodes.hashInt(fromOrdinal);
int bucket = hashCode & (fromOrdinalsMap.length - 1);
while(fromOrdinalsMap[bucket] != -1L) {
if((int)fromOrdinalsMap[bucket] == fromOrdinal) {
if((fromOrdinalsMap[bucket] & Long.MIN_VALUE) != 0L)
return pivotedToOrdinalClusters.get((int)((fromOrdinalsMap[bucket] & Long.MAX_VALUE) >> 32));
return (int)(fromOrdinalsMap[bucket] >> 32);
}
bucket = (bucket + 1) & (fromOrdinalsMap.length - 1);
}
return -1;
}
public int getIdentityToOrdinal(int toOrdinal) {
int hashCode = HashCodes.hashInt(toOrdinal);
int bucket = hashCode & (toOrdinalsIdentityMap.length - 1);
while(toOrdinalsIdentityMap[bucket] != -1L) {
if((int)toOrdinalsIdentityMap[bucket] == toOrdinal)
return (int)(toOrdinalsIdentityMap[bucket] >> 32);
bucket = (bucket + 1) & (toOrdinalsIdentityMap.length - 1);
}
return -1;
}
public static interface OrdinalIdentityTranslator {
public int getIdentityOrdinal(int ordinal);
}
private final OrdinalIdentityTranslator fromIdentityTranslator = new OrdinalIdentityTranslator() {
public int getIdentityOrdinal(int ordinal) {
return getIdentityFromOrdinal(ordinal);
}
};
private final OrdinalIdentityTranslator toIdentityTranslator = new OrdinalIdentityTranslator() {
public int getIdentityOrdinal(int ordinal) {
return getIdentityToOrdinal(ordinal);
}
};
public OrdinalIdentityTranslator getFromOrdinalIdentityTranslator() {
return fromIdentityTranslator;
}
public OrdinalIdentityTranslator getToOrdinalIdentityTranslator() {
return toIdentityTranslator;
}
public static interface MatchIterator {
public boolean hasNext();
public int next();
}
public static class EmptyMatchIterator implements MatchIterator {
static EmptyMatchIterator INSTANCE = new EmptyMatchIterator();
public boolean hasNext() { return false; }
public int next() { return -1; }
}
public static class SingleMatchIterator implements MatchIterator {
private final int singleMatch;
private boolean exhausted;
public SingleMatchIterator(int singleMatch) {
this.singleMatch = singleMatch;
}
public boolean hasNext() {
return !exhausted;
}
public int next() {
exhausted = true;
return singleMatch;
}
}
public class PivotedMatchIterator implements MatchIterator {
private int currentMatchListPosition;
private boolean exhausted;
public PivotedMatchIterator(int matchListPosition) {
this.currentMatchListPosition = matchListPosition;
}
public boolean hasNext() {
return !exhausted;
}
public int next() {
int nextVal = pivotedToOrdinalClusters.get(currentMatchListPosition++);
exhausted = (nextVal & Integer.MIN_VALUE) != 0;
return nextVal & Integer.MAX_VALUE;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy