001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase.regionserver;
020
021import org.apache.hadoop.hbase.HConstants;
022import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
023import java.util.Collection;
024import java.util.Comparator;
025import java.util.Iterator;
026import java.util.NavigableSet;
027import java.util.NavigableMap;
028import java.util.SortedSet;
029import java.util.concurrent.ConcurrentSkipListMap;
030
031import org.apache.hadoop.hbase.Cell;
032import org.apache.hadoop.hbase.CellComparator;
033import org.apache.yetus.audience.InterfaceAudience;
034
035/**
036 * A {@link java.util.Set} of {@link Cell}s, where an add will overwrite the entry if already
037 * exists in the set.  The call to add returns true if no value in the backing map or false if
038 * there was an entry with same key (though value may be different).
039 * implementation is tolerant of concurrent get and set and won't throw
040 * ConcurrentModificationException when iterating.
041 */
042@InterfaceAudience.Private
043public class CellSet implements NavigableSet<Cell>  {
044
045  public static final int UNKNOWN_NUM_UNIQUES = -1;
046  // Implemented on top of a {@link java.util.concurrent.ConcurrentSkipListMap}
047  // Differ from CSLS in one respect, where CSLS does "Adds the specified element to this set if it
048  // is not already present.", this implementation "Adds the specified element to this set EVEN
049  // if it is already present overwriting what was there previous".
050  // Otherwise, has same attributes as ConcurrentSkipListSet
051  private final NavigableMap<Cell, Cell> delegatee; ///
052
053  private final int numUniqueKeys;
054
055  CellSet(final CellComparator c) {
056    this.delegatee = new ConcurrentSkipListMap<>(c.getSimpleComparator());
057    this.numUniqueKeys = UNKNOWN_NUM_UNIQUES;
058  }
059
060  CellSet(final NavigableMap<Cell, Cell> m, int numUniqueKeys) {
061    this.delegatee = m;
062    this.numUniqueKeys = numUniqueKeys;
063  }
064
065  @VisibleForTesting
066  CellSet(final NavigableMap<Cell, Cell> m) {
067    this.delegatee = m;
068    this.numUniqueKeys = UNKNOWN_NUM_UNIQUES;
069  }
070
071  @VisibleForTesting
072  NavigableMap<Cell, Cell> getDelegatee() {
073    return delegatee;
074  }
075
076  @Override
077  public Cell ceiling(Cell e) {
078    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
079  }
080
081  @Override
082  public Iterator<Cell> descendingIterator() {
083    return this.delegatee.descendingMap().values().iterator();
084  }
085
086  @Override
087  public NavigableSet<Cell> descendingSet() {
088    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
089  }
090
091  @Override
092  public Cell floor(Cell e) {
093    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
094  }
095
096  @Override
097  public SortedSet<Cell> headSet(final Cell toElement) {
098    return headSet(toElement, false);
099  }
100
101  @Override
102  public NavigableSet<Cell> headSet(final Cell toElement,
103      boolean inclusive) {
104    return new CellSet(this.delegatee.headMap(toElement, inclusive), UNKNOWN_NUM_UNIQUES);
105  }
106
107  @Override
108  public Cell higher(Cell e) {
109    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
110  }
111
112  @Override
113  public Iterator<Cell> iterator() {
114    return this.delegatee.values().iterator();
115  }
116
117  @Override
118  public Cell lower(Cell e) {
119    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
120  }
121
122  @Override
123  public Cell pollFirst() {
124    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
125  }
126
127  @Override
128  public Cell pollLast() {
129    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
130  }
131
132  @Override
133  public SortedSet<Cell> subSet(Cell fromElement, Cell toElement) {
134    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
135  }
136
137  @Override
138  public NavigableSet<Cell> subSet(Cell fromElement,
139      boolean fromInclusive, Cell toElement, boolean toInclusive) {
140    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
141  }
142
143  @Override
144  public SortedSet<Cell> tailSet(Cell fromElement) {
145    return tailSet(fromElement, true);
146  }
147
148  @Override
149  public NavigableSet<Cell> tailSet(Cell fromElement, boolean inclusive) {
150    return new CellSet(this.delegatee.tailMap(fromElement, inclusive), UNKNOWN_NUM_UNIQUES);
151  }
152
153  @Override
154  public Comparator<? super Cell> comparator() {
155    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
156  }
157
158  @Override
159  public Cell first() {
160    return this.delegatee.firstEntry().getValue();
161  }
162
163  @Override
164  public Cell last() {
165    return this.delegatee.lastEntry().getValue();
166  }
167
168  @Override
169  public boolean add(Cell e) {
170    return this.delegatee.put(e, e) == null;
171  }
172
173  @Override
174  public boolean addAll(Collection<? extends Cell> c) {
175    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
176  }
177
178  @Override
179  public void clear() {
180    this.delegatee.clear();
181  }
182
183  @Override
184  public boolean contains(Object o) {
185    //noinspection SuspiciousMethodCalls
186    return this.delegatee.containsKey(o);
187  }
188
189  @Override
190  public boolean containsAll(Collection<?> c) {
191    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
192  }
193
194  @Override
195  public boolean isEmpty() {
196    return this.delegatee.isEmpty();
197  }
198
199  @Override
200  public boolean remove(Object o) {
201    return this.delegatee.remove(o) != null;
202  }
203
204  @Override
205  public boolean removeAll(Collection<?> c) {
206    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
207  }
208
209  @Override
210  public boolean retainAll(Collection<?> c) {
211    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
212  }
213
214  public Cell get(Cell kv) {
215    return this.delegatee.get(kv);
216  }
217
218  @Override
219  public int size() {
220    if (delegatee instanceof ConcurrentSkipListMap) {
221      throw new UnsupportedOperationException("ConcurrentSkipListMap.size() is time-consuming");
222    }
223    return this.delegatee.size();
224  }
225
226  @Override
227  public Object[] toArray() {
228    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
229  }
230
231  @Override
232  public <T> T[] toArray(T[] a) {
233    throw new UnsupportedOperationException(HConstants.NOT_IMPLEMENTED);
234  }
235
236  public int getNumUniqueKeys() {
237    return numUniqueKeys;
238  }
239}