Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* 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.hadoop.hdfs.util;
import org.apache.hadoop.util.Time;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.SortedSet;
/**
* A memory efficient implementation of RBTree. Instead of having a Node for
* each entry each node contains an array holding 64 entries.
*
* Based on the Apache Harmony folded TreeMap.
*
* @param Entry type
*/
public class FoldedTreeSet implements SortedSet {
private static final boolean RED = true;
private static final boolean BLACK = false;
private final Comparator comparator;
private Node root;
private int size;
private int nodeCount;
private int modCount;
private Node cachedNode;
/**
* Internal tree node that holds a sorted array of entries.
*
* @param type of the elements
*/
private static class Node {
private static final int NODE_SIZE = 64;
// Tree structure
private Node parent, left, right;
private boolean color;
private final E[] entries;
private int leftIndex = 0, rightIndex = -1;
private int size = 0;
// List for fast ordered iteration
private Node prev, next;
@SuppressWarnings("unchecked")
public Node() {
entries = (E[]) new Object[NODE_SIZE];
}
public boolean isRed() {
return color == RED;
}
public boolean isBlack() {
return color == BLACK;
}
public Node getLeftMostNode() {
Node node = this;
while (node.left != null) {
node = node.left;
}
return node;
}
public Node getRightMostNode() {
Node node = this;
while (node.right != null) {
node = node.right;
}
return node;
}
public void addEntryLeft(E entry) {
assert rightIndex < entries.length;
assert !isFull();
if (leftIndex == 0) {
rightIndex++;
// Shift entries right/up
System.arraycopy(entries, 0, entries, 1, size);
} else {
leftIndex--;
}
size++;
entries[leftIndex] = entry;
}
public void addEntryRight(E entry) {
assert !isFull();
if (rightIndex == NODE_SIZE - 1) {
assert leftIndex > 0;
// Shift entries left/down
System.arraycopy(entries, leftIndex, entries, --leftIndex, size);
} else {
rightIndex++;
}
size++;
entries[rightIndex] = entry;
}
public void addEntryAt(E entry, int index) {
assert !isFull();
if (leftIndex == 0 || ((rightIndex != Node.NODE_SIZE - 1)
&& (rightIndex - index <= index - leftIndex))) {
rightIndex++;
System.arraycopy(entries, index,
entries, index + 1, rightIndex - index);
entries[index] = entry;
} else {
int newLeftIndex = leftIndex - 1;
System.arraycopy(entries, leftIndex,
entries, newLeftIndex, index - leftIndex);
leftIndex = newLeftIndex;
entries[index - 1] = entry;
}
size++;
}
public void addEntriesLeft(Node from) {
leftIndex -= from.size;
size += from.size;
System.arraycopy(from.entries, from.leftIndex,
entries, leftIndex, from.size);
}
public void addEntriesRight(Node from) {
System.arraycopy(from.entries, from.leftIndex,
entries, rightIndex + 1, from.size);
size += from.size;
rightIndex += from.size;
}
public E insertEntrySlideLeft(E entry, int index) {
E pushedEntry = entries[0];
System.arraycopy(entries, 1, entries, 0, index - 1);
entries[index - 1] = entry;
return pushedEntry;
}
public E insertEntrySlideRight(E entry, int index) {
E movedEntry = entries[rightIndex];
System.arraycopy(entries, index, entries, index + 1, rightIndex - index);
entries[index] = entry;
return movedEntry;
}
public E removeEntryLeft() {
assert !isEmpty();
E entry = entries[leftIndex];
entries[leftIndex] = null;
leftIndex++;
size--;
return entry;
}
public E removeEntryRight() {
assert !isEmpty();
E entry = entries[rightIndex];
entries[rightIndex] = null;
rightIndex--;
size--;
return entry;
}
public E removeEntryAt(int index) {
assert !isEmpty();
E entry = entries[index];
int rightSize = rightIndex - index;
int leftSize = index - leftIndex;
if (rightSize <= leftSize) {
System.arraycopy(entries, index + 1, entries, index, rightSize);
entries[rightIndex] = null;
rightIndex--;
} else {
System.arraycopy(entries, leftIndex, entries, leftIndex + 1, leftSize);
entries[leftIndex] = null;
leftIndex++;
}
size--;
return entry;
}
public boolean isFull() {
return size == NODE_SIZE;
}
public boolean isEmpty() {
return size == 0;
}
public void clear() {
if (leftIndex < rightIndex) {
Arrays.fill(entries, leftIndex, rightIndex + 1, null);
}
size = 0;
leftIndex = 0;
rightIndex = -1;
prev = null;
next = null;
parent = null;
left = null;
right = null;
color = BLACK;
}
}
private static final class TreeSetIterator implements Iterator {
private final FoldedTreeSet tree;
private int iteratorModCount;
private Node node;
private int index;
private E lastEntry;
private int lastIndex;
private Node lastNode;
private TreeSetIterator(FoldedTreeSet tree) {
this.tree = tree;
this.iteratorModCount = tree.modCount;
if (!tree.isEmpty()) {
this.node = tree.root.getLeftMostNode();
this.index = this.node.leftIndex;
}
}
@Override
public boolean hasNext() {
checkForModification();
return node != null;
}
@Override
public E next() {
if (hasNext()) {
lastEntry = node.entries[index];
lastIndex = index;
lastNode = node;
if (++index > node.rightIndex) {
node = node.next;
if (node != null) {
index = node.leftIndex;
}
}
return lastEntry;
} else {
throw new NoSuchElementException("Iterator exhausted");
}
}
@Override
public void remove() {
if (lastEntry == null) {
throw new IllegalStateException("No current element");
}
checkForModification();
if (lastNode.size == 1) {
// Safe to remove lastNode, the iterator is on the next node
tree.deleteNode(lastNode);
} else if (lastNode.leftIndex == lastIndex) {
// Safe to remove leftmost entry, the iterator is on the next index
lastNode.removeEntryLeft();
} else if (lastNode.rightIndex == lastIndex) {
// Safe to remove the rightmost entry, the iterator is on the next node
lastNode.removeEntryRight();
} else {
// Remove entry in the middle of the array
assert node == lastNode;
int oldRIndex = lastNode.rightIndex;
lastNode.removeEntryAt(lastIndex);
if (oldRIndex > lastNode.rightIndex) {
// Entries moved to the left in the array so index must be reset
index = lastIndex;
}
}
lastEntry = null;
iteratorModCount++;
tree.modCount++;
tree.size--;
}
private void checkForModification() {
if (iteratorModCount != tree.modCount) {
throw new ConcurrentModificationException("Tree has been modified "
+ "outside of iterator");
}
}
}
/**
* Create a new TreeSet that uses the natural ordering of objects. The element
* type must implement Comparable.
*/
public FoldedTreeSet() {
this(null);
}
/**
* Create a new TreeSet that orders the elements using the supplied
* Comparator.
*
* @param comparator Comparator able to compare elements of type E
*/
public FoldedTreeSet(Comparator comparator) {
this.comparator = comparator;
}
private Node cachedOrNewNode(E entry) {
Node node = (cachedNode != null) ? cachedNode : new Node();
cachedNode = null;
nodeCount++;
// Since BlockIDs are always increasing for new blocks it is best to
// add values on the left side to enable quicker inserts on the right
node.addEntryLeft(entry);
return node;
}
private void cacheAndClear(Node node) {
if (cachedNode == null) {
node.clear();
cachedNode = node;
}
}
@Override
public Comparator super E> comparator() {
return comparator;
}
@Override
public SortedSet subSet(E fromElement, E toElement) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public SortedSet headSet(E toElement) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public SortedSet tailSet(E fromElement) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public E first() {
if (!isEmpty()) {
Node node = root.getLeftMostNode();
return node.entries[node.leftIndex];
}
return null;
}
@Override
public E last() {
if (!isEmpty()) {
Node node = root.getRightMostNode();
return node.entries[node.rightIndex];
}
return null;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return root == null;
}
/**
* Lookup and return a stored object using a user provided comparator.
*
* @param obj Lookup key
* @param cmp User provided Comparator. The comparator should expect that the
* proved obj will always be the first method parameter and any
* stored object will be the second parameter.
*
* @return A matching stored object or null if non is found
*/
public E get(Object obj, Comparator> cmp) {
Objects.requireNonNull(obj);
Node node = root;
while (node != null) {
E[] entries = node.entries;
int leftIndex = node.leftIndex;
int result = compare(obj, entries[leftIndex], cmp);
if (result < 0) {
node = node.left;
} else if (result == 0) {
return entries[leftIndex];
} else {
int rightIndex = node.rightIndex;
if (leftIndex != rightIndex) {
result = compare(obj, entries[rightIndex], cmp);
}
if (result == 0) {
return entries[rightIndex];
} else if (result > 0) {
node = node.right;
} else {
int low = leftIndex + 1;
int high = rightIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
result = compare(obj, entries[mid], cmp);
if (result > 0) {
low = mid + 1;
} else if (result < 0) {
high = mid - 1;
} else {
return entries[mid];
}
}
return null;
}
}
}
return null;
}
/**
* Lookup and return a stored object.
*
* @param entry Lookup entry
*
* @return A matching stored object or null if non is found
*/
public E get(E entry) {
return get(entry, comparator);
}
@Override
@SuppressWarnings("unchecked")
public boolean contains(Object obj) {
return get((E) obj) != null;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private static int compare(Object lookup, Object stored, Comparator cmp) {
return cmp != null
? cmp.compare(lookup, stored)
: ((Comparable