3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Cellersion 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY CellIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 package org
.apache
.hadoop
.hbase
.regionserver
;
21 import org
.apache
.hadoop
.hbase
.Cell
;
22 import org
.apache
.yetus
.audience
.InterfaceAudience
;
23 import org
.slf4j
.Logger
;
24 import org
.slf4j
.LoggerFactory
;
26 import java
.util
.Collection
;
27 import java
.util
.Comparator
;
28 import java
.util
.Iterator
;
30 import java
.util
.NavigableSet
;
31 import java
.util
.NavigableMap
;
36 * CellFlatMap stores a constant number of elements and is immutable after creation stage.
37 * Being immutable, the CellFlatMap can be implemented as array.
38 * The actual array can be on- or off-heap and is implemented in concrete class derived from CellFlatMap.
39 * The CellFlatMap uses no synchronization primitives, it is assumed to be created by a
40 * single thread and then it can be read-only by multiple threads.
42 * The "flat" in the name, means that the memory layout of the Map is sequential array and thus
43 * requires less memory than ConcurrentSkipListMap.
45 @InterfaceAudience.Private
46 public abstract class CellFlatMap
implements NavigableMap
<Cell
,Cell
> {
47 private static final Logger LOG
= LoggerFactory
.getLogger(CellFlatMap
.class);
48 private final Comparator
<?
super Cell
> comparator
;
49 protected int minCellIdx
= 0; // the index of the minimal cell (for sub-sets)
50 protected int maxCellIdx
= 0; // the index of the cell after the maximal cell (for sub-sets)
51 private boolean descending
= false;
54 public CellFlatMap(Comparator
<?
super Cell
> comparator
, int min
, int max
, boolean d
){
55 this.comparator
= comparator
;
56 this.minCellIdx
= min
;
57 this.maxCellIdx
= max
;
61 /* Used for abstract CellFlatMap creation, implemented by derived class */
62 protected abstract CellFlatMap
createSubCellFlatMap(int min
, int max
, boolean descending
);
64 /* Returns the i-th cell in the cell block */
65 protected abstract Cell
getCell(int i
);
68 * Binary search for a given key in between given boundaries of the array.
69 * Positive returned numbers mean the index.
70 * Negative returned numbers means the key not found.
72 * The absolute value of the output is the
73 * possible insert index for the searched key
75 * In twos-complement, (-1 * insertion point)-1 is the bitwise not of the insert point.
78 * @param needle The key to look for in all of the entries
79 * @return Same return value as Arrays.binarySearch.
81 private int find(Cell needle
) {
82 int begin
= minCellIdx
;
83 int end
= maxCellIdx
- 1;
85 while (begin
<= end
) {
86 int mid
= begin
+ ((end
- begin
) >> 1);
87 Cell midCell
= getCell(mid
);
88 int compareRes
= comparator
.compare(midCell
, needle
);
90 if (compareRes
== 0) {
91 return mid
; // 0 means equals. We found the key
93 // Key not found. Check the comparison results; reverse the meaning of
94 // the comparison in case the order is descending (using XOR)
95 if ((compareRes
< 0) ^ descending
) {
96 // midCell is less than needle so we need to look at farther up
99 // midCell is greater than needle so we need to look down
104 return (-1 * begin
)-1;
108 * Get the index of the given anchor key for creating subsequent set.
109 * It doesn't matter whether the given key exists in the set or not.
110 * taking into consideration whether
111 * the key should be inclusive or exclusive.
113 private int getValidIndex(Cell key
, boolean inclusive
, boolean tail
) {
114 final int index
= find(key
);
115 // get the valid (positive) insertion point from the output of the find() method
116 int insertionPoint
= index
< 0 ? ~index
: index
;
118 // correct the insertion point in case the given anchor key DOES EXIST in the set
120 if ( descending
&& !(tail ^ inclusive
)) {
121 // for the descending case
122 // if anchor for head set (tail=false) AND anchor is not inclusive -> move the insertion pt
123 // if anchor for tail set (tail=true) AND the keys is inclusive -> move the insertion point
124 // because the end index of a set is the index of the cell after the maximal cell
126 } else if ( !descending
&& (tail ^ inclusive
)) {
127 // for the ascending case
128 // if anchor for head set (tail=false) AND anchor is inclusive -> move the insertion point
129 // because the end index of a set is the index of the cell after the maximal cell
130 // if anchor for tail set (tail=true) AND the keys is not inclusive -> move the insertion pt
134 // insert the insertion point into the valid range,
135 // as we may enlarge it too much in the above correction
136 return Math
.min(Math
.max(insertionPoint
, minCellIdx
), maxCellIdx
);
140 public Comparator
<?
super Cell
> comparator() {
146 return maxCellIdx
-minCellIdx
;
150 public boolean isEmpty() {
151 return ( size() == 0 );
155 // ---------------- Sub-Maps ----------------
157 public NavigableMap
<Cell
, Cell
> subMap( Cell fromKey
,
158 boolean fromInclusive
,
160 boolean toInclusive
) {
161 final int lessCellIndex
= getValidIndex(fromKey
, fromInclusive
, true);
162 final int greaterCellIndex
= getValidIndex(toKey
, toInclusive
, false);
164 return createSubCellFlatMap(greaterCellIndex
, lessCellIndex
, descending
);
166 return createSubCellFlatMap(lessCellIndex
, greaterCellIndex
, descending
);
171 public NavigableMap
<Cell
, Cell
> headMap(Cell toKey
, boolean inclusive
) {
173 return createSubCellFlatMap(getValidIndex(toKey
, inclusive
, false), maxCellIdx
, descending
);
175 return createSubCellFlatMap(minCellIdx
, getValidIndex(toKey
, inclusive
, false), descending
);
180 public NavigableMap
<Cell
, Cell
> tailMap(Cell fromKey
, boolean inclusive
) {
182 return createSubCellFlatMap(minCellIdx
, getValidIndex(fromKey
, inclusive
, true), descending
);
184 return createSubCellFlatMap(getValidIndex(fromKey
, inclusive
, true), maxCellIdx
, descending
);
189 public NavigableMap
<Cell
, Cell
> descendingMap() {
190 return createSubCellFlatMap(minCellIdx
, maxCellIdx
, true);
194 public NavigableMap
<Cell
, Cell
> subMap(Cell k1
, Cell k2
) {
195 return this.subMap(k1
, true, k2
, true);
199 public NavigableMap
<Cell
, Cell
> headMap(Cell k
) {
200 return this.headMap(k
, true);
204 public NavigableMap
<Cell
, Cell
> tailMap(Cell k
) {
205 return this.tailMap(k
, true);
209 // -------------------------------- Key's getters --------------------------------
211 public Cell
firstKey() {
215 return descending ?
getCell(maxCellIdx
- 1) : getCell(minCellIdx
);
219 public Cell
lastKey() {
223 return descending ?
getCell(minCellIdx
) : getCell(maxCellIdx
- 1);
227 public Cell
lowerKey(Cell k
) {
232 // If index>=0 there's a key exactly equal
233 index
= (index
>=0) ? index
-1 : -(index
);
234 return (index
< minCellIdx
|| index
>= maxCellIdx
) ?
null : getCell(index
);
238 public Cell
floorKey(Cell k
) {
243 index
= (index
>=0) ? index
: -(index
);
244 return (index
< minCellIdx
|| index
>= maxCellIdx
) ?
null : getCell(index
);
248 public Cell
ceilingKey(Cell k
) {
253 index
= (index
>=0) ? index
: -(index
)+1;
254 return (index
< minCellIdx
|| index
>= maxCellIdx
) ?
null : getCell(index
);
258 public Cell
higherKey(Cell k
) {
263 index
= (index
>=0) ? index
+1 : -(index
)+1;
264 return (index
< minCellIdx
|| index
>= maxCellIdx
) ?
null : getCell(index
);
268 public boolean containsKey(Object o
) {
269 int index
= find((Cell
) o
);
274 public boolean containsValue(Object o
) { // use containsKey(Object o) instead
275 throw new UnsupportedOperationException("Use containsKey(Object o) instead");
279 public Cell
get(Object o
) {
280 int index
= find((Cell
) o
);
281 return (index
>= 0) ?
getCell(index
) : null;
284 // -------------------------------- Entry's getters --------------------------------
286 private static class CellFlatMapEntry
implements Entry
<Cell
, Cell
> {
287 private final Cell cell
;
289 public CellFlatMapEntry (Cell cell
) {
294 public Cell
getKey() {
299 public Cell
getValue() {
304 public Cell
setValue(Cell value
) {
305 throw new UnsupportedOperationException();
310 public Entry
<Cell
, Cell
> lowerEntry(Cell k
) {
311 Cell cell
= lowerKey(k
);
315 return new CellFlatMapEntry(cell
);
319 public Entry
<Cell
, Cell
> higherEntry(Cell k
) {
320 Cell cell
= higherKey(k
);
324 return new CellFlatMapEntry(cell
);
328 public Entry
<Cell
, Cell
> ceilingEntry(Cell k
) {
329 Cell cell
= ceilingKey(k
);
333 return new CellFlatMapEntry(cell
);
337 public Entry
<Cell
, Cell
> floorEntry(Cell k
) {
338 Cell cell
= floorKey(k
);
342 return new CellFlatMapEntry(cell
);
346 public Entry
<Cell
, Cell
> firstEntry() {
347 Cell cell
= firstKey();
351 return new CellFlatMapEntry(cell
);
355 public Entry
<Cell
, Cell
> lastEntry() {
356 Cell cell
= lastKey();
360 return new CellFlatMapEntry(cell
);
363 // The following 2 methods (pollFirstEntry, pollLastEntry) are unsupported because these are updating methods.
365 public Entry
<Cell
, Cell
> pollFirstEntry() {
366 throw new UnsupportedOperationException();
370 public Entry
<Cell
, Cell
> pollLastEntry() {
371 throw new UnsupportedOperationException();
374 // -------------------------------- Updates --------------------------------
375 // All updating methods below are unsupported.
376 // Assuming an array of Cells will be allocated externally,
377 // fill up with Cells and provided in construction time.
378 // Later the structure is immutable.
380 public Cell
put(Cell k
, Cell v
) {
381 throw new UnsupportedOperationException();
385 public void clear() {
386 throw new UnsupportedOperationException();
390 public Cell
remove(Object o
) {
391 throw new UnsupportedOperationException();
395 public void putAll(Map
<?
extends Cell
, ?
extends Cell
> map
) {
396 throw new UnsupportedOperationException();
399 // -------------------------------- Sub-Sets --------------------------------
401 public NavigableSet
<Cell
> navigableKeySet() {
402 throw new UnsupportedOperationException();
406 public NavigableSet
<Cell
> descendingKeySet() {
407 throw new UnsupportedOperationException();
411 public NavigableSet
<Cell
> keySet() {
412 throw new UnsupportedOperationException();
416 public Collection
<Cell
> values() {
417 return new CellFlatMapCollection();
421 public Set
<Entry
<Cell
, Cell
>> entrySet() {
422 throw new UnsupportedOperationException();
426 // -------------------------------- Iterator K --------------------------------
427 private final class CellFlatMapIterator
implements Iterator
<Cell
> {
430 private CellFlatMapIterator() {
431 index
= descending ? maxCellIdx
-1 : minCellIdx
;
435 public boolean hasNext() {
436 return descending ?
(index
>= minCellIdx
) : (index
< maxCellIdx
);
441 Cell result
= getCell(index
);
451 public void remove() {
452 throw new UnsupportedOperationException();
456 // -------------------------------- Collection --------------------------------
457 private final class CellFlatMapCollection
implements Collection
<Cell
> {
461 return CellFlatMap
.this.size();
465 public boolean isEmpty() {
466 return CellFlatMap
.this.isEmpty();
470 public void clear() {
471 throw new UnsupportedOperationException();
475 public boolean contains(Object o
) {
476 return containsKey(o
);
480 public Iterator
<Cell
> iterator() {
481 return new CellFlatMapIterator();
485 public Object
[] toArray() {
486 throw new UnsupportedOperationException();
490 public <T
> T
[] toArray(T
[] ts
) {
491 throw new UnsupportedOperationException();
495 public boolean add(Cell k
) {
496 throw new UnsupportedOperationException();
500 public boolean remove(Object o
) {
501 throw new UnsupportedOperationException();
505 public boolean containsAll(Collection
<?
> collection
) {
506 throw new UnsupportedOperationException();
510 public boolean addAll(Collection
<?
extends Cell
> collection
) {
511 throw new UnsupportedOperationException();
515 public boolean removeAll(Collection
<?
> collection
) {
516 throw new UnsupportedOperationException();
520 public boolean retainAll(Collection
<?
> collection
) {
521 throw new UnsupportedOperationException();