org.apache.flink.runtime.state.KeyGroupRange Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.apache.flink.runtime.state;
import org.apache.flink.util.Preconditions;
import java.io.Serializable;
import java.util.Iterator;
/**
* This class defines a range of key-group indexes. Key-groups are the granularity into which the keyspace of a job
* is partitioned for keyed state-handling in state backends. The boundaries of the range are inclusive.
*/
public class KeyGroupRange implements KeyGroupsList, Serializable {
private static final long serialVersionUID = 4869121477592070607L;
/** The empty key-group */
public static final KeyGroupRange EMPTY_KEY_GROUP_RANGE = new KeyGroupRange();
private final int startKeyGroup;
private final int endKeyGroup;
/**
* Empty KeyGroup Constructor
*/
private KeyGroupRange() {
this.startKeyGroup = 0;
this.endKeyGroup = -1;
}
/**
* Defines the range [startKeyGroup, endKeyGroup]
*
* @param startKeyGroup start of the range (inclusive)
* @param endKeyGroup end of the range (inclusive)
*/
public KeyGroupRange(int startKeyGroup, int endKeyGroup) {
Preconditions.checkArgument(startKeyGroup >= 0);
Preconditions.checkArgument(startKeyGroup <= endKeyGroup);
this.startKeyGroup = startKeyGroup;
this.endKeyGroup = endKeyGroup;
Preconditions.checkArgument(getNumberOfKeyGroups() >= 0, "Potential overflow detected.");
}
/**
* Checks whether or not a single key-group is contained in the range.
*
* @param keyGroup Key-group to check for inclusion.
* @return True, only if the key-group is in the range.
*/
@Override
public boolean contains(int keyGroup) {
return keyGroup >= startKeyGroup && keyGroup <= endKeyGroup;
}
/**
* Create a range that represent the intersection between this range and the given range.
*
* @param other A KeyGroupRange to intersect.
* @return Key-group range that is the intersection between this and the given key-group range.
*/
public KeyGroupRange getIntersection(KeyGroupRange other) {
int start = Math.max(startKeyGroup, other.startKeyGroup);
int end = Math.min(endKeyGroup, other.endKeyGroup);
return start <= end ? new KeyGroupRange(start, end) : EMPTY_KEY_GROUP_RANGE;
}
/**
*
* @return The number of key-groups in the range
*/
@Override
public int getNumberOfKeyGroups() {
return 1 + endKeyGroup - startKeyGroup;
}
/**
*
* @return The first key-group in the range.
*/
public int getStartKeyGroup() {
return startKeyGroup;
}
/**
*
* @return The last key-group in the range.
*/
public int getEndKeyGroup() {
return endKeyGroup;
}
@Override
public int getKeyGroupId(int idx) {
if (idx < 0 || idx > getNumberOfKeyGroups()) {
throw new IndexOutOfBoundsException("Key group index out of bounds: " + idx);
}
return startKeyGroup + idx;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof KeyGroupRange)) {
return false;
}
KeyGroupRange that = (KeyGroupRange) o;
return startKeyGroup == that.startKeyGroup && endKeyGroup == that.endKeyGroup;
}
@Override
public int hashCode() {
int result = startKeyGroup;
result = 31 * result + endKeyGroup;
return result;
}
@Override
public String toString() {
return "KeyGroupRange{" +
"startKeyGroup=" + startKeyGroup +
", endKeyGroup=" + endKeyGroup +
'}';
}
@Override
public Iterator iterator() {
return new KeyGroupIterator();
}
private final class KeyGroupIterator implements Iterator {
public KeyGroupIterator() {
this.iteratorPos = 0;
}
private int iteratorPos;
@Override
public boolean hasNext() {
return iteratorPos < getNumberOfKeyGroups();
}
@Override
public Integer next() {
int rv = startKeyGroup + iteratorPos;
++iteratorPos;
return rv;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Unsupported by this iterator!");
}
}
/**
* Factory method that also handles creation of empty key-groups.
*
* @param startKeyGroup start of the range (inclusive)
* @param endKeyGroup end of the range (inclusive)
* @return the key-group from start to end or an empty key-group range.
*/
public static KeyGroupRange of(int startKeyGroup, int endKeyGroup) {
return startKeyGroup <= endKeyGroup ? new KeyGroupRange(startKeyGroup, endKeyGroup) : EMPTY_KEY_GROUP_RANGE;
}
}