From 24aea0d0a73c7becb2c1be75e3cd5009914fb4a3 Mon Sep 17 00:00:00 2001 From: anastas Date: Thu, 3 Mar 2016 13:08:24 +0200 Subject: [PATCH 01/11] Initial CellBlocksMap --- .../hbase/regionserver/CellBlocksMap.java | 442 ++++++++++++++++++ 1 file changed, 442 insertions(+) create mode 100644 hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java new file mode 100644 index 000000000000..3d24ecbec9af --- /dev/null +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java @@ -0,0 +1,442 @@ +/** + * + * 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.hbase.regionserver; + +import org.apache.hadoop.hbase.Cell; + +import java.lang.reflect.Array; +import java.util.*; +import java.util.concurrent.ConcurrentNavigableMap; + +/** + * BlocksMap stores a constant number of elements and is immutable after creation stage. + * Due to being immutable the BlocksMap can be implemented as array. + * The BlocksMap uses no synchronization primitives, it is assumed to be created by a + * single thread and then it can be read-only by multiple threads. + */ +public class CellBlocksMap implements ConcurrentNavigableMap { + + private final Comparator comparator; + private K blocks[]; // with hope to transfer to direct NIO byte buffers + + private int minCellIdx = 0; // the index of the minimal cell (for sub-sets) + private int maxCellIdx = 0; // the index of the maximal cell (for sub-sets) + private boolean isDescending = false; // array can be easily traversed backward in descending order + + + public CellBlocksMap(Class c, int maxSize, Comparator comparator) { + this.comparator = comparator; + // Use Array native method to create array of a type only known at run time + final K[] b = (K[]) Array.newInstance(c,maxSize); + this.blocks = b; + this.maxCellIdx = b.length; + } + + private CellBlocksMap(Comparator comparator, K[] b, int min, int max, boolean d){ + this.comparator = comparator; + this.blocks = b; + this.minCellIdx = min; + this.maxCellIdx = max; + this.isDescending = d; + } + + /** + * Binary search for a given key in between given boundaries of the array + * @param needle The key to look for in all of the entries + * @return Same return value as Arrays.binarySearch. + * Positive numbers mean the index. + * Otherwise (-1 * insertion point) - 1 + */ + private int find(K needle) { + int begin = minCellIdx; + int end = maxCellIdx - 1; + + while (begin <= end) { + int mid = begin + ((end - begin) / 2); + K midCell = blocks[mid]; + int compareRes = comparator.compare(midCell, needle); + + // 0 means equals. We found the key. + if (compareRes == 0) return mid; + else if (compareRes < 0) { + // midKey is less than needle so we need to look at farther up + begin = mid + 1; + } else { + // midKey is greater than needle so we need to look down + end = mid - 1; + } + } + + return (-1 * begin) - 1; + } + + @Override public Comparator comparator() { return comparator; } + + @Override public int size() { return maxCellIdx-minCellIdx; } + + @Override public boolean isEmpty() { return (maxCellIdx==minCellIdx); } + + + // ---------------- Sub-Maps ---------------- + @Override public ConcurrentNavigableMap subMap( K fromKey, + boolean fromInclusive, + K toKey, + boolean toInclusive) { + int toIndex = find(toKey); + if (toInclusive && toIndex >= 0) toIndex++; + else if (toIndex < 0) toIndex = -(toIndex + 1) - 1; + + int fromIndex = find(fromKey); + if (!fromInclusive && fromIndex >= 0) fromIndex++; + else if (fromIndex < 0) fromIndex = -(fromIndex + 1); + + return new CellBlocksMap<>(comparator,blocks,fromIndex,toIndex,false); + } + + @Override public ConcurrentNavigableMap headMap(K toKey, boolean inclusive) { + int index = find(toKey); + if (inclusive && index >= 0) index++; + else if (index < 0) index = -(index + 1) - 1; + return new CellBlocksMap<>(comparator,blocks,minCellIdx,index,false); + } + + @Override public ConcurrentNavigableMap tailMap(K fromKey, boolean inclusive) { + int index = find(fromKey); + if (!inclusive && index >= 0) index++; + else if (index < 0) index = -(index + 1); + return new CellBlocksMap<>(comparator,blocks,index,maxCellIdx,false); + } + + @Override public ConcurrentNavigableMap descendingMap() { + return new CellBlocksMap<>(comparator,blocks,minCellIdx,maxCellIdx,true); + } + + @Override public ConcurrentNavigableMap subMap(K k, K k1) { + return this.subMap(k, true, k1, true); + } + + @Override public ConcurrentNavigableMap headMap(K k) { return this.headMap(k, true); } + + @Override public ConcurrentNavigableMap tailMap(K k) { return this.tailMap(k, true); } + + + // -------------------------------- Key's getters -------------------------------- + @Override public K firstKey() { + if (isDescending) return lastKey(); + if (isEmpty()) return null; + return blocks[minCellIdx]; + } + + @Override public K lastKey() { + if (isDescending) return firstKey(); + if (isEmpty()) return null; + return blocks[maxCellIdx-1]; + } + + @Override public K lowerKey(K k) { + if (isDescending) return higherKey(k); + if (isEmpty()) return null; + int index = find(k); + if (index >= 0) index -= 1; // There's a key exactly equal. + else index = -(index + 1) - 1; + if (index < minCellIdx || index >= maxCellIdx) return null; + return blocks[index]; + } + + @Override public K floorKey(K k) { + if (isDescending) ceilingEntry(k); + if (isEmpty()) return null; + int index = find(k); + if (index < 0) index = -(index + 1) - 1; + if (index < minCellIdx || index >= maxCellIdx) return null; + return blocks[index]; + } + + @Override public K ceilingKey(K k) { + if (isDescending) return floorKey(k); + if (isEmpty()) return null; + int index = find(k); + if (index < 0) index = -(index + 1); + if (index < minCellIdx || index >= maxCellIdx) return null; + return blocks[index]; + } + + @Override public K higherKey(K k) { + if (isDescending) return lowerKey(k); + if (isEmpty()) return null; + int index = find(k); + if (index >= 0) index += 1; // There's a key exactly equal. + else index = -(index + 1); + if (index < minCellIdx || index >= maxCellIdx) return null; + return blocks[index]; + } + + @Override public boolean containsKey(Object o) { + int index = find((K) o); + return (index >= 0); + } + + @Override public boolean containsValue(Object o) { // use containsKey(Object o) instead + throw new UnsupportedOperationException(); + } + + @Override public V get(Object o) { + int index = find((K) o); + if (index >= 0) { + return (V)blocks[index]; + } + return null; + } + + // -------------------------------- Entry's getters -------------------------------- + // all interfaces returning Entries are unsupported because we are dealing only with the keys + @Override public Entry lowerEntry(K k) { throw new UnsupportedOperationException(); } + + @Override public Entry higherEntry(K k) { throw new UnsupportedOperationException(); } + + @Override public Entry ceilingEntry(K k) { throw new UnsupportedOperationException(); } + + @Override public Entry floorEntry(K k) { throw new UnsupportedOperationException(); } + + @Override public Entry firstEntry() { throw new UnsupportedOperationException(); } + + @Override public Entry lastEntry() { throw new UnsupportedOperationException(); } + + @Override public Entry pollFirstEntry() { throw new UnsupportedOperationException(); } + + @Override public Entry pollLastEntry() { throw new UnsupportedOperationException(); } + + + // -------------------------------- Updates -------------------------------- + // All updating methods below are unsupported. + // Assuming an array of Cells will be allocated externally, + // fill up with Cells and provided in construction time. + // Later the structure is immutable. + @Override public V put(K k, V v) { throw new UnsupportedOperationException(); } + + @Override public void clear() { throw new UnsupportedOperationException(); } + + @Override public V remove(Object o) { throw new UnsupportedOperationException(); } + + @Override public boolean replace(K k, V v, V v1) { throw new UnsupportedOperationException(); } + + @Override public void putAll(Map map) { + throw new UnsupportedOperationException(); + } + + @Override public V putIfAbsent(K k, V v) { throw new UnsupportedOperationException(); } + + @Override public boolean remove(Object o, Object o1) { throw new UnsupportedOperationException(); } + + @Override public V replace(K k, V v) { throw new UnsupportedOperationException(); } + + + // -------------------------------- Sub-Sets -------------------------------- + @Override public NavigableSet navigableKeySet() { return new CellBlocksSet(); } + + @Override public NavigableSet descendingKeySet() { throw new UnsupportedOperationException(); } + + @Override public NavigableSet keySet() { throw new UnsupportedOperationException(); } + + @Override public Collection values() { return new CellBlocksCollection(); } + + @Override public Set> entrySet() { throw new UnsupportedOperationException(); } + + + // -------------------------------- Iterator K -------------------------------- + private final class CellBlocksIteratorK implements Iterator { + int index; + + private CellBlocksIteratorK(boolean d) { + isDescending = d; + index = isDescending ? maxCellIdx-1 : minCellIdx; + } + + @Override + public boolean hasNext() { + return isDescending ? (index >= minCellIdx) : (index < maxCellIdx); + } + + @Override + public K next() { + K result = blocks[index]; + if (isDescending) index--; else index++; + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + // -------------------------------- Iterator V -------------------------------- + private final class CellBlocksIteratorV implements Iterator { + int index; + + private CellBlocksIteratorV(boolean d) { + isDescending = d; + index = isDescending ? maxCellIdx-1 : minCellIdx; + } + + @Override + public boolean hasNext() { + return isDescending ? (index >= minCellIdx) : (index < maxCellIdx); + } + + @Override + public V next() { + V result = (V) blocks[index]; + if (isDescending) index--; else index++; + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + // -------------------------------- Navigable Set -------------------------------- + private final class CellBlocksSet implements NavigableSet { + + @Override public K lower(K k) { return lowerKey(k); } + + @Override public K floor(K k) { return floorKey(k); } + + @Override public K ceiling(K k) { return ceilingKey(k); } + + @Override public K higher(K k) { return higherKey(k); } + + @Override public K first() { return firstKey(); } + + @Override public K last() { return lastKey(); } + + @Override public K pollFirst() { throw new UnsupportedOperationException(); } + + @Override public K pollLast() { throw new UnsupportedOperationException(); } + + @Override public int size() { return size(); } + + @Override public boolean isEmpty() { return isEmpty(); } + + @Override public void clear() { throw new UnsupportedOperationException(); } + + @Override public boolean contains(Object o) { return containsKey(o); } + + @Override public Comparator comparator() { return comparator; } + + @Override public Iterator iterator() { return new CellBlocksIteratorK(false); } + + @Override public Iterator descendingIterator() { return new CellBlocksIteratorK(true); } + + @Override public Object[] toArray() { throw new UnsupportedOperationException(); } + + @Override public T[] toArray(T[] ts) { throw new UnsupportedOperationException(); } + + @Override public boolean add(K k) { throw new UnsupportedOperationException(); } + + @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } + + @Override public boolean containsAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override public boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override public boolean retainAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override public boolean removeAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override public NavigableSet descendingSet() { throw new UnsupportedOperationException(); } + + @Override public SortedSet subSet(K k, K e1) { throw new UnsupportedOperationException(); } + + @Override public NavigableSet subSet(K k, boolean b, K e1, boolean b1) { + throw new UnsupportedOperationException(); + } + + @Override public NavigableSet headSet(K k, boolean b) { // headMap should be used instead + throw new UnsupportedOperationException(); + } + + @Override public NavigableSet tailSet(K k, boolean b) { // tailMap should be used instead + throw new UnsupportedOperationException(); + } + + @Override public SortedSet headSet(K k) { // headMap should be used instead + throw new UnsupportedOperationException(); + } + + @Override public SortedSet tailSet(K k) { // tailMap should be used instead + throw new UnsupportedOperationException(); + } + + + } + + // -------------------------------- Collection -------------------------------- + private final class CellBlocksCollection implements Collection { + + @Override public int size() { return size(); } + + @Override public boolean isEmpty() { return isEmpty(); } + + @Override public void clear() { throw new UnsupportedOperationException(); } + + @Override public boolean contains(Object o) { return containsKey(o); } + + @Override public Iterator iterator() { return new CellBlocksIteratorV(false); } + + @Override public Object[] toArray() { throw new UnsupportedOperationException(); } + + @Override public T[] toArray(T[] ts) { throw new UnsupportedOperationException(); } + + @Override public boolean add(V k) { throw new UnsupportedOperationException(); } + + @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } + + @Override public boolean containsAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override public boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override public boolean removeAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override public boolean retainAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + + } + + + +} From d3fa554baa03c00918ca530b771b832785bed110 Mon Sep 17 00:00:00 2001 From: anastas Date: Sun, 6 Mar 2016 11:43:56 +0200 Subject: [PATCH 02/11] Initial test for CellBlocksMAp --- .../hbase/regionserver/CellBlocksMap.java | 2 +- .../hbase/regionserver/TestCellBlocksSet.java | 171 ++++++++++++++++++ 2 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java index 3d24ecbec9af..0578b21b1694 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java @@ -48,7 +48,7 @@ public CellBlocksMap(Class c, int maxSize, Comparator comparator) this.maxCellIdx = b.length; } - private CellBlocksMap(Comparator comparator, K[] b, int min, int max, boolean d){ + public CellBlocksMap(Comparator comparator, K[] b, int min, int max, boolean d){ this.comparator = comparator; this.blocks = b; this.minCellIdx = min; diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java new file mode 100644 index 000000000000..f17ad302eff0 --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java @@ -0,0 +1,171 @@ +/** + * + * 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.hbase.regionserver; + +import junit.framework.TestCase; +import org.apache.hadoop.hbase.Cell; +import org.apache.hadoop.hbase.CellComparator; +import org.apache.hadoop.hbase.CellUtil; +import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.testclassification.RegionServerTests; +import org.apache.hadoop.hbase.testclassification.SmallTests; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.experimental.categories.Category; + +import java.util.Iterator; +import java.util.SortedSet; + +@Category({RegionServerTests.class, SmallTests.class}) +public class TestCellBlocksSet extends TestCase { + + private static final int NUM_OF_CELLS = 3; + + private Cell cells[]; + private CellBlocksMap cbMap; + private CellSet cbSet; + + protected void setUp() throws Exception { + super.setUp(); + + // create array of Cells to bass to the CellBlocks under CellSet + final byte[] one = Bytes.toBytes(1); + final byte[] two = Bytes.toBytes(2); + final byte[] three = Bytes.toBytes(3); + final byte[] f = Bytes.toBytes("f"); + final byte[] q = Bytes.toBytes("q"); + final byte[] v = Bytes.toBytes(4); + + final KeyValue kv1 = new KeyValue(one, f, q, 10, v); + final KeyValue kv2 = new KeyValue(two, f, q, 20, v); + final KeyValue kv3 = new KeyValue(three, f, q, 30, v); + + cells = new Cell[] {kv1,kv2,kv3}; + cbMap = new CellBlocksMap(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS,false); + cbSet = new CellSet(cbMap); + } + + /*public void testAdd() throws Exception { + byte [] bytes = Bytes.toBytes(getName()); + KeyValue kv = new KeyValue(bytes, bytes, bytes, bytes); + this.cbSet.add(kv); + assertTrue(this.cbSet.contains(kv)); + assertEquals(1, this.cbSet.size()); + Cell first = this.cbSet.first(); + assertTrue(kv.equals(first)); + assertTrue(Bytes.equals(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength(), + first.getValueArray(), first.getValueOffset(), first.getValueLength())); + // Now try overwritting + byte [] overwriteValue = Bytes.toBytes("overwrite"); + KeyValue overwrite = new KeyValue(bytes, bytes, bytes, overwriteValue); + this.cbSet.add(overwrite); + assertEquals(1, this.cbSet.size()); + first = this.cbSet.first(); + assertTrue(Bytes.equals(overwrite.getValueArray(), overwrite.getValueOffset(), + overwrite.getValueLength(), first.getValueArray(), first.getValueOffset(), + first.getValueLength())); + assertFalse(Bytes.equals(CellUtil.cloneValue(overwrite), CellUtil.cloneValue(kv))); + }*/ + + public void testIterators() throws Exception { + + // Assert that we have NUM_OF_CELLS values and that they are in order + int count = 0; + for (Cell kv: this.cbSet) { + assertEquals("" + count, + Bytes.toString(kv.getQualifierArray(), kv.getQualifierOffset(), kv.getQualifierLength())); + count++; + } + assertEquals(NUM_OF_CELLS, count); + + // Test descending iterator + count = 0; + for (Iterator i = this.cbSet.descendingIterator(); i.hasNext();) { + Cell kv = i.next(); + assertEquals("" + (NUM_OF_CELLS - (count + 1)), + Bytes.toString(kv.getQualifierArray(), kv.getQualifierOffset(), kv.getQualifierLength())); + count++; + } + assertEquals(NUM_OF_CELLS, count); + } + +// public void testDescendingIterator() throws Exception { +// byte [] bytes = Bytes.toBytes(getName()); +// byte [] value1 = Bytes.toBytes("1"); +// byte [] value2 = Bytes.toBytes("2"); +// final int total = 3; +// for (int i = 0; i < total; i++) { +// this.cbSet.add(new KeyValue(bytes, bytes, Bytes.toBytes("" + i), value1)); +// } +// // Assert that we added 'total' values and that they are in order +// int count = 0; +// for (Iterator i = this.cbSet.descendingIterator(); i.hasNext();) { +// Cell kv = i.next(); +// assertEquals("" + (total - (count + 1)), +// Bytes.toString(kv.getQualifierArray(), kv.getQualifierOffset(), kv.getQualifierLength())); +// assertTrue(Bytes.equals(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength(), value1, +// 0, value1.length)); +// count++; +// } +// assertEquals(total, count); +// // Now overwrite with a new value. +// for (int i = 0; i < total; i++) { +// this.cbSet.add(new KeyValue(bytes, bytes, Bytes.toBytes("" + i), value2)); +// } +// // Assert that we added 'total' values and that they are in order and that +// // we are getting back value2 +// count = 0; +// for (Iterator i = this.cbSet.descendingIterator(); i.hasNext();) { +// Cell kv = i.next(); +// assertEquals("" + (total - (count + 1)), +// Bytes.toString(kv.getQualifierArray(), kv.getQualifierOffset(), kv.getQualifierLength())); +// assertTrue(Bytes.equals(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength(), value2, +// 0, value2.length)); +// count++; +// } +// assertEquals(total, count); +// } +// +// public void testHeadTail() throws Exception { +// byte [] bytes = Bytes.toBytes(getName()); +// byte [] value1 = Bytes.toBytes("1"); +// byte [] value2 = Bytes.toBytes("2"); +// final int total = 3; +// KeyValue splitter = null; +// for (int i = 0; i < total; i++) { +// KeyValue kv = new KeyValue(bytes, bytes, Bytes.toBytes("" + i), value1); +// if (i == 1) splitter = kv; +// this.cbSet.add(kv); +// } +// SortedSet tail = this.cbSet.tailSet(splitter); +// assertEquals(2, tail.size()); +// SortedSet head = this.cbSet.headSet(splitter); +// assertEquals(1, head.size()); +// // Now ensure that we get back right answer even when we do tail or head. +// // Now overwrite with a new value. +// for (int i = 0; i < total; i++) { +// this.cbSet.add(new KeyValue(bytes, bytes, Bytes.toBytes("" + i), value2)); +// } +// tail = this.cbSet.tailSet(splitter); +// assertTrue(Bytes.equals(tail.first().getValueArray(), tail.first().getValueOffset(), +// tail.first().getValueLength(), value2, 0, value2.length)); +// head = this.cbSet.headSet(splitter); +// assertTrue(Bytes.equals(head.first().getValueArray(), head.first().getValueOffset(), +// head.first().getValueLength(), value2, 0, value2.length)); +// } +} From 11f44e6bf95c29464970719b4399f9bc47afb1d6 Mon Sep 17 00:00:00 2001 From: anastas Date: Sun, 6 Mar 2016 17:00:51 +0200 Subject: [PATCH 03/11] Test is passing --- .../hbase/regionserver/CellBlocksMap.java | 21 ++- .../hbase/regionserver/TestCellBlocksSet.java | 122 +++++------------- 2 files changed, 52 insertions(+), 91 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java index 0578b21b1694..b8aaa15c1323 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java @@ -23,6 +23,7 @@ import java.lang.reflect.Array; import java.util.*; import java.util.concurrent.ConcurrentNavigableMap; +import junit.framework.Assert; /** * BlocksMap stores a constant number of elements and is immutable after creation stage. @@ -49,6 +50,7 @@ public CellBlocksMap(Class c, int maxSize, Comparator comparator) } public CellBlocksMap(Comparator comparator, K[] b, int min, int max, boolean d){ + //assert(false); this.comparator = comparator; this.blocks = b; this.minCellIdx = min; @@ -261,9 +263,11 @@ else if (compareRes < 0) { // -------------------------------- Iterator K -------------------------------- private final class CellBlocksIteratorK implements Iterator { - int index; + int index = minCellIdx; private CellBlocksIteratorK(boolean d) { +// org.junit.Assert.assertTrue("\nInitializing K iterator, descending?:" + d + "\n",false); + isDescending = d; index = isDescending ? maxCellIdx-1 : minCellIdx; } @@ -288,9 +292,12 @@ public void remove() { // -------------------------------- Iterator V -------------------------------- private final class CellBlocksIteratorV implements Iterator { - int index; + int index = minCellIdx; private CellBlocksIteratorV(boolean d) { +// org.junit.Assert.assertTrue("\n\nInitializing V iterator, descending?:" + d +// + ". The CellBlocksMap first element is " + firstKey() + "\n",false); + isDescending = d; index = isDescending ? maxCellIdx-1 : minCellIdx; } @@ -302,7 +309,13 @@ public boolean hasNext() { @Override public V next() { + V result = (V) blocks[index]; + +// org.junit.Assert.assertTrue("\n\nGetting next from V iterator, descending?:" + isDescending +// + ". The CellBlocksMap first element is " + firstKey() + " and Iterator's index is " +// + index + ". Going to return " + result + "\n",false); + if (isDescending) index--; else index++; return result; } @@ -408,7 +421,9 @@ private final class CellBlocksCollection implements Collection { @Override public boolean contains(Object o) { return containsKey(o); } - @Override public Iterator iterator() { return new CellBlocksIteratorV(false); } + @Override public Iterator iterator() { + return (isDescending) ? new CellBlocksIteratorV(true) : new CellBlocksIteratorV(false); + } @Override public Object[] toArray() { throw new UnsupportedOperationException(); } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java index f17ad302eff0..58339a62cfcb 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java @@ -60,35 +60,45 @@ protected void setUp() throws Exception { cbSet = new CellSet(cbMap); } - /*public void testAdd() throws Exception { - byte [] bytes = Bytes.toBytes(getName()); - KeyValue kv = new KeyValue(bytes, bytes, bytes, bytes); - this.cbSet.add(kv); - assertTrue(this.cbSet.contains(kv)); - assertEquals(1, this.cbSet.size()); + public void testBasics() throws Exception { + + assertEquals(3, this.cbSet.size()); // check size + + assertTrue(this.cbSet.contains(cells[0])); // check first Cell first = this.cbSet.first(); - assertTrue(kv.equals(first)); - assertTrue(Bytes.equals(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength(), - first.getValueArray(), first.getValueOffset(), first.getValueLength())); - // Now try overwritting - byte [] overwriteValue = Bytes.toBytes("overwrite"); - KeyValue overwrite = new KeyValue(bytes, bytes, bytes, overwriteValue); - this.cbSet.add(overwrite); - assertEquals(1, this.cbSet.size()); - first = this.cbSet.first(); - assertTrue(Bytes.equals(overwrite.getValueArray(), overwrite.getValueOffset(), - overwrite.getValueLength(), first.getValueArray(), first.getValueOffset(), - first.getValueLength())); - assertFalse(Bytes.equals(CellUtil.cloneValue(overwrite), CellUtil.cloneValue(kv))); - }*/ + assertTrue(cells[0].equals(first)); + + assertTrue(this.cbSet.contains(cells[NUM_OF_CELLS - 1])); // check last + Cell last = this.cbSet.last(); + assertTrue(cells[NUM_OF_CELLS - 1].equals(last)); + + SortedSet tail = this.cbSet.tailSet(cells[1]); // check tail abd head sizes + assertEquals(2, tail.size()); + SortedSet head = this.cbSet.headSet(cells[1]); + assertEquals(1, head.size()); + + Cell tailFirst = tail.first(); + assertTrue(cells[1].equals(tailFirst)); + Cell tailLast = tail.last(); + assertTrue(cells[2].equals(tailLast)); + + Cell headFirst = head.first(); + assertTrue(cells[0].equals(headFirst)); + Cell headLast = head.last(); + assertTrue(cells[0].equals(headLast)); + } public void testIterators() throws Exception { // Assert that we have NUM_OF_CELLS values and that they are in order int count = 0; for (Cell kv: this.cbSet) { - assertEquals("" + count, - Bytes.toString(kv.getQualifierArray(), kv.getQualifierOffset(), kv.getQualifierLength())); + assertEquals("\n\n-------------------------------------------------------------------\n" + + "Comparing iteration number " + (count + 1) + " the returned cell: " + kv + + ", the first Cell in the CellBlocksMap: " + cells[count] + + ", and the same transformed to String: " + cells[count].toString() + + "\n-------------------------------------------------------------------\n", + cells[count], kv); count++; } assertEquals(NUM_OF_CELLS, count); @@ -97,75 +107,11 @@ public void testIterators() throws Exception { count = 0; for (Iterator i = this.cbSet.descendingIterator(); i.hasNext();) { Cell kv = i.next(); - assertEquals("" + (NUM_OF_CELLS - (count + 1)), - Bytes.toString(kv.getQualifierArray(), kv.getQualifierOffset(), kv.getQualifierLength())); + assertEquals(cells[NUM_OF_CELLS - (count + 1)], kv); count++; } assertEquals(NUM_OF_CELLS, count); } -// public void testDescendingIterator() throws Exception { -// byte [] bytes = Bytes.toBytes(getName()); -// byte [] value1 = Bytes.toBytes("1"); -// byte [] value2 = Bytes.toBytes("2"); -// final int total = 3; -// for (int i = 0; i < total; i++) { -// this.cbSet.add(new KeyValue(bytes, bytes, Bytes.toBytes("" + i), value1)); -// } -// // Assert that we added 'total' values and that they are in order -// int count = 0; -// for (Iterator i = this.cbSet.descendingIterator(); i.hasNext();) { -// Cell kv = i.next(); -// assertEquals("" + (total - (count + 1)), -// Bytes.toString(kv.getQualifierArray(), kv.getQualifierOffset(), kv.getQualifierLength())); -// assertTrue(Bytes.equals(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength(), value1, -// 0, value1.length)); -// count++; -// } -// assertEquals(total, count); -// // Now overwrite with a new value. -// for (int i = 0; i < total; i++) { -// this.cbSet.add(new KeyValue(bytes, bytes, Bytes.toBytes("" + i), value2)); -// } -// // Assert that we added 'total' values and that they are in order and that -// // we are getting back value2 -// count = 0; -// for (Iterator i = this.cbSet.descendingIterator(); i.hasNext();) { -// Cell kv = i.next(); -// assertEquals("" + (total - (count + 1)), -// Bytes.toString(kv.getQualifierArray(), kv.getQualifierOffset(), kv.getQualifierLength())); -// assertTrue(Bytes.equals(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength(), value2, -// 0, value2.length)); -// count++; -// } -// assertEquals(total, count); -// } -// -// public void testHeadTail() throws Exception { -// byte [] bytes = Bytes.toBytes(getName()); -// byte [] value1 = Bytes.toBytes("1"); -// byte [] value2 = Bytes.toBytes("2"); -// final int total = 3; -// KeyValue splitter = null; -// for (int i = 0; i < total; i++) { -// KeyValue kv = new KeyValue(bytes, bytes, Bytes.toBytes("" + i), value1); -// if (i == 1) splitter = kv; -// this.cbSet.add(kv); -// } -// SortedSet tail = this.cbSet.tailSet(splitter); -// assertEquals(2, tail.size()); -// SortedSet head = this.cbSet.headSet(splitter); -// assertEquals(1, head.size()); -// // Now ensure that we get back right answer even when we do tail or head. -// // Now overwrite with a new value. -// for (int i = 0; i < total; i++) { -// this.cbSet.add(new KeyValue(bytes, bytes, Bytes.toBytes("" + i), value2)); -// } -// tail = this.cbSet.tailSet(splitter); -// assertTrue(Bytes.equals(tail.first().getValueArray(), tail.first().getValueOffset(), -// tail.first().getValueLength(), value2, 0, value2.length)); -// head = this.cbSet.headSet(splitter); -// assertTrue(Bytes.equals(head.first().getValueArray(), head.first().getValueOffset(), -// head.first().getValueLength(), value2, 0, value2.length)); -// } + } From 114e1e3ea9291d9c4f09201b9b2947a71cb8660b Mon Sep 17 00:00:00 2001 From: anastas Date: Sun, 13 Mar 2016 12:27:05 +0200 Subject: [PATCH 04/11] Adding off/on-heap CellBlicks --- .../{CellBlocksMap.java => CellBlocks.java} | 246 ++++++++---------- .../hbase/regionserver/CellBlocksOffHeap.java | 63 +++++ .../hbase/regionserver/CellBlocksOnHeap.java | 54 ++++ .../hbase/regionserver/HeapMemStoreLAB.java | 19 +- .../hbase/regionserver/MemStoreChunkPool.java | 27 +- .../hbase/regionserver/TestCellBlocksSet.java | 111 +++++++- 6 files changed, 368 insertions(+), 152 deletions(-) rename hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/{CellBlocksMap.java => CellBlocks.java} (54%) create mode 100644 hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java create mode 100644 hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java similarity index 54% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java rename to hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java index b8aaa15c1323..6547e95925b0 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksMap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java @@ -4,7 +4,7 @@ * 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 + * to you under the Apache License, Cellersion 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 * @@ -12,7 +12,7 @@ * * 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. + * WITHOUT WARRANTIES OR CONDITIONS OF ANY CellIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ @@ -20,44 +20,38 @@ import org.apache.hadoop.hbase.Cell; -import java.lang.reflect.Array; import java.util.*; import java.util.concurrent.ConcurrentNavigableMap; import junit.framework.Assert; /** - * BlocksMap stores a constant number of elements and is immutable after creation stage. - * Due to being immutable the BlocksMap can be implemented as array. - * The BlocksMap uses no synchronization primitives, it is assumed to be created by a + * CellBlocks stores a constant number of elements and is immutable after creation stage. + * Due to being immutable the CellBlocks can be implemented as array. + * The CellBlocks uses no synchronization primitives, it is assumed to be created by a * single thread and then it can be read-only by multiple threads. */ -public class CellBlocksMap implements ConcurrentNavigableMap { +public abstract class CellBlocks implements ConcurrentNavigableMap { - private final Comparator comparator; - private K blocks[]; // with hope to transfer to direct NIO byte buffers + private final Comparator comparator; private int minCellIdx = 0; // the index of the minimal cell (for sub-sets) private int maxCellIdx = 0; // the index of the maximal cell (for sub-sets) private boolean isDescending = false; // array can be easily traversed backward in descending order - public CellBlocksMap(Class c, int maxSize, Comparator comparator) { - this.comparator = comparator; - // Use Array native method to create array of a type only known at run time - final K[] b = (K[]) Array.newInstance(c,maxSize); - this.blocks = b; - this.maxCellIdx = b.length; - } - - public CellBlocksMap(Comparator comparator, K[] b, int min, int max, boolean d){ + public CellBlocks(Comparator comparator, int min, int max, boolean d){ //assert(false); this.comparator = comparator; - this.blocks = b; this.minCellIdx = min; this.maxCellIdx = max; this.isDescending = d; } + protected abstract CellBlocks createCellBlocksMap(Comparator comparator, + int min, int max, boolean d); + + protected abstract Cell getCellFromIndex(int i); + /** * Binary search for a given key in between given boundaries of the array * @param needle The key to look for in all of the entries @@ -65,13 +59,13 @@ public CellBlocksMap(Comparator comparator, K[] b, int min, int max, * Positive numbers mean the index. * Otherwise (-1 * insertion point) - 1 */ - private int find(K needle) { + private int find(Cell needle) { int begin = minCellIdx; int end = maxCellIdx - 1; while (begin <= end) { int mid = begin + ((end - begin) / 2); - K midCell = blocks[mid]; + Cell midCell = getCellFromIndex(mid); int compareRes = comparator.compare(midCell, needle); // 0 means equals. We found the key. @@ -88,7 +82,7 @@ else if (compareRes < 0) { return (-1 * begin) - 1; } - @Override public Comparator comparator() { return comparator; } + @Override public Comparator comparator() { return comparator; } @Override public int size() { return maxCellIdx-minCellIdx; } @@ -96,9 +90,9 @@ else if (compareRes < 0) { // ---------------- Sub-Maps ---------------- - @Override public ConcurrentNavigableMap subMap( K fromKey, + @Override public ConcurrentNavigableMap subMap( Cell fromKey, boolean fromInclusive, - K toKey, + Cell toKey, boolean toInclusive) { int toIndex = find(toKey); if (toInclusive && toIndex >= 0) toIndex++; @@ -108,89 +102,91 @@ else if (compareRes < 0) { if (!fromInclusive && fromIndex >= 0) fromIndex++; else if (fromIndex < 0) fromIndex = -(fromIndex + 1); - return new CellBlocksMap<>(comparator,blocks,fromIndex,toIndex,false); + return createCellBlocksMap(comparator,fromIndex,toIndex,false); } - @Override public ConcurrentNavigableMap headMap(K toKey, boolean inclusive) { + @Override public ConcurrentNavigableMap headMap(Cell toKey, boolean inclusive) { int index = find(toKey); if (inclusive && index >= 0) index++; else if (index < 0) index = -(index + 1) - 1; - return new CellBlocksMap<>(comparator,blocks,minCellIdx,index,false); + return createCellBlocksMap(comparator,minCellIdx,index,false); } - @Override public ConcurrentNavigableMap tailMap(K fromKey, boolean inclusive) { + @Override public ConcurrentNavigableMap tailMap(Cell fromKey, boolean inclusive) { int index = find(fromKey); if (!inclusive && index >= 0) index++; else if (index < 0) index = -(index + 1); - return new CellBlocksMap<>(comparator,blocks,index,maxCellIdx,false); + return createCellBlocksMap(comparator,index,maxCellIdx,false); } - @Override public ConcurrentNavigableMap descendingMap() { - return new CellBlocksMap<>(comparator,blocks,minCellIdx,maxCellIdx,true); + @Override public ConcurrentNavigableMap descendingMap() { + return createCellBlocksMap(comparator,minCellIdx,maxCellIdx,true); } - @Override public ConcurrentNavigableMap subMap(K k, K k1) { + @Override public ConcurrentNavigableMap subMap(Cell k, Cell k1) { return this.subMap(k, true, k1, true); } - @Override public ConcurrentNavigableMap headMap(K k) { return this.headMap(k, true); } + @Override + public ConcurrentNavigableMap headMap(Cell k) { return this.headMap(k, true); } - @Override public ConcurrentNavigableMap tailMap(K k) { return this.tailMap(k, true); } + @Override + public ConcurrentNavigableMap tailMap(Cell k) { return this.tailMap(k, true); } // -------------------------------- Key's getters -------------------------------- - @Override public K firstKey() { + @Override public Cell firstKey() { if (isDescending) return lastKey(); if (isEmpty()) return null; - return blocks[minCellIdx]; + return getCellFromIndex(minCellIdx); } - @Override public K lastKey() { + @Override public Cell lastKey() { if (isDescending) return firstKey(); if (isEmpty()) return null; - return blocks[maxCellIdx-1]; + return getCellFromIndex(maxCellIdx-1); } - @Override public K lowerKey(K k) { + @Override public Cell lowerKey(Cell k) { if (isDescending) return higherKey(k); if (isEmpty()) return null; int index = find(k); if (index >= 0) index -= 1; // There's a key exactly equal. else index = -(index + 1) - 1; if (index < minCellIdx || index >= maxCellIdx) return null; - return blocks[index]; + return getCellFromIndex(index); } - @Override public K floorKey(K k) { + @Override public Cell floorKey(Cell k) { if (isDescending) ceilingEntry(k); if (isEmpty()) return null; int index = find(k); if (index < 0) index = -(index + 1) - 1; if (index < minCellIdx || index >= maxCellIdx) return null; - return blocks[index]; + return getCellFromIndex(index); } - @Override public K ceilingKey(K k) { + @Override public Cell ceilingKey(Cell k) { if (isDescending) return floorKey(k); if (isEmpty()) return null; int index = find(k); if (index < 0) index = -(index + 1); if (index < minCellIdx || index >= maxCellIdx) return null; - return blocks[index]; + return getCellFromIndex(index); } - @Override public K higherKey(K k) { + @Override public Cell higherKey(Cell k) { if (isDescending) return lowerKey(k); if (isEmpty()) return null; int index = find(k); if (index >= 0) index += 1; // There's a key exactly equal. else index = -(index + 1); if (index < minCellIdx || index >= maxCellIdx) return null; - return blocks[index]; + return getCellFromIndex(index); } @Override public boolean containsKey(Object o) { - int index = find((K) o); + int index = find((Cell) o); return (index >= 0); } @@ -198,31 +194,39 @@ else if (compareRes < 0) { throw new UnsupportedOperationException(); } - @Override public V get(Object o) { - int index = find((K) o); + @Override public Cell get(Object o) { + int index = find((Cell) o); if (index >= 0) { - return (V)blocks[index]; + return getCellFromIndex(index); } return null; } // -------------------------------- Entry's getters -------------------------------- // all interfaces returning Entries are unsupported because we are dealing only with the keys - @Override public Entry lowerEntry(K k) { throw new UnsupportedOperationException(); } + @Override + public Entry lowerEntry(Cell k) { throw new UnsupportedOperationException(); } - @Override public Entry higherEntry(K k) { throw new UnsupportedOperationException(); } + @Override + public Entry higherEntry(Cell k) { throw new UnsupportedOperationException(); } - @Override public Entry ceilingEntry(K k) { throw new UnsupportedOperationException(); } + @Override + public Entry ceilingEntry(Cell k) { throw new UnsupportedOperationException(); } - @Override public Entry floorEntry(K k) { throw new UnsupportedOperationException(); } + @Override + public Entry floorEntry(Cell k) { throw new UnsupportedOperationException(); } - @Override public Entry firstEntry() { throw new UnsupportedOperationException(); } + @Override + public Entry firstEntry() { throw new UnsupportedOperationException(); } - @Override public Entry lastEntry() { throw new UnsupportedOperationException(); } + @Override + public Entry lastEntry() { throw new UnsupportedOperationException(); } - @Override public Entry pollFirstEntry() { throw new UnsupportedOperationException(); } + @Override + public Entry pollFirstEntry() { throw new UnsupportedOperationException(); } - @Override public Entry pollLastEntry() { throw new UnsupportedOperationException(); } + @Override + public Entry pollLastEntry() { throw new UnsupportedOperationException(); } // -------------------------------- Updates -------------------------------- @@ -230,43 +234,46 @@ else if (compareRes < 0) { // Assuming an array of Cells will be allocated externally, // fill up with Cells and provided in construction time. // Later the structure is immutable. - @Override public V put(K k, V v) { throw new UnsupportedOperationException(); } + @Override public Cell put(Cell k, Cell v) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } - @Override public V remove(Object o) { throw new UnsupportedOperationException(); } + @Override public Cell remove(Object o) { throw new UnsupportedOperationException(); } - @Override public boolean replace(K k, V v, V v1) { throw new UnsupportedOperationException(); } + @Override + public boolean replace(Cell k, Cell v, Cell v1) { throw new UnsupportedOperationException(); } - @Override public void putAll(Map map) { + @Override public void putAll(Map map) { throw new UnsupportedOperationException(); } - @Override public V putIfAbsent(K k, V v) { throw new UnsupportedOperationException(); } + @Override public Cell putIfAbsent(Cell k, Cell v) { throw new UnsupportedOperationException(); } - @Override public boolean remove(Object o, Object o1) { throw new UnsupportedOperationException(); } + @Override + public boolean remove(Object o, Object o1) { throw new UnsupportedOperationException(); } - @Override public V replace(K k, V v) { throw new UnsupportedOperationException(); } + @Override public Cell replace(Cell k, Cell v) { throw new UnsupportedOperationException(); } // -------------------------------- Sub-Sets -------------------------------- - @Override public NavigableSet navigableKeySet() { return new CellBlocksSet(); } + @Override public NavigableSet navigableKeySet() { return new CellBlocksSet(); } - @Override public NavigableSet descendingKeySet() { throw new UnsupportedOperationException(); } + @Override + public NavigableSet descendingKeySet() { throw new UnsupportedOperationException(); } - @Override public NavigableSet keySet() { throw new UnsupportedOperationException(); } + @Override public NavigableSet keySet() { throw new UnsupportedOperationException(); } - @Override public Collection values() { return new CellBlocksCollection(); } + @Override public Collection values() { return new CellBlocksCollection(); } - @Override public Set> entrySet() { throw new UnsupportedOperationException(); } + @Override public Set> entrySet() { throw new UnsupportedOperationException(); } // -------------------------------- Iterator K -------------------------------- - private final class CellBlocksIteratorK implements Iterator { + private final class CellBlocksIterator implements Iterator { int index = minCellIdx; - private CellBlocksIteratorK(boolean d) { -// org.junit.Assert.assertTrue("\nInitializing K iterator, descending?:" + d + "\n",false); + private CellBlocksIterator(boolean d) { +// org.junit.Assert.assertTrue("\nInitializing Cell iterator, descending?:" + d + "\n",false); isDescending = d; index = isDescending ? maxCellIdx-1 : minCellIdx; @@ -278,44 +285,8 @@ public boolean hasNext() { } @Override - public K next() { - K result = blocks[index]; - if (isDescending) index--; else index++; - return result; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - // -------------------------------- Iterator V -------------------------------- - private final class CellBlocksIteratorV implements Iterator { - int index = minCellIdx; - - private CellBlocksIteratorV(boolean d) { -// org.junit.Assert.assertTrue("\n\nInitializing V iterator, descending?:" + d -// + ". The CellBlocksMap first element is " + firstKey() + "\n",false); - - isDescending = d; - index = isDescending ? maxCellIdx-1 : minCellIdx; - } - - @Override - public boolean hasNext() { - return isDescending ? (index >= minCellIdx) : (index < maxCellIdx); - } - - @Override - public V next() { - - V result = (V) blocks[index]; - -// org.junit.Assert.assertTrue("\n\nGetting next from V iterator, descending?:" + isDescending -// + ". The CellBlocksMap first element is " + firstKey() + " and Iterator's index is " -// + index + ". Going to return " + result + "\n",false); - + public Cell next() { + Cell result = getCellFromIndex(index); if (isDescending) index--; else index++; return result; } @@ -326,24 +297,25 @@ public void remove() { } } + // -------------------------------- Navigable Set -------------------------------- - private final class CellBlocksSet implements NavigableSet { + private final class CellBlocksSet implements NavigableSet { - @Override public K lower(K k) { return lowerKey(k); } + @Override public Cell lower(Cell k) { return lowerKey(k); } - @Override public K floor(K k) { return floorKey(k); } + @Override public Cell floor(Cell k) { return floorKey(k); } - @Override public K ceiling(K k) { return ceilingKey(k); } + @Override public Cell ceiling(Cell k) { return ceilingKey(k); } - @Override public K higher(K k) { return higherKey(k); } + @Override public Cell higher(Cell k) { return higherKey(k); } - @Override public K first() { return firstKey(); } + @Override public Cell first() { return firstKey(); } - @Override public K last() { return lastKey(); } + @Override public Cell last() { return lastKey(); } - @Override public K pollFirst() { throw new UnsupportedOperationException(); } + @Override public Cell pollFirst() { throw new UnsupportedOperationException(); } - @Override public K pollLast() { throw new UnsupportedOperationException(); } + @Override public Cell pollLast() { throw new UnsupportedOperationException(); } @Override public int size() { return size(); } @@ -353,17 +325,17 @@ private final class CellBlocksSet implements NavigableSet { @Override public boolean contains(Object o) { return containsKey(o); } - @Override public Comparator comparator() { return comparator; } + @Override public Comparator comparator() { return comparator; } - @Override public Iterator iterator() { return new CellBlocksIteratorK(false); } + @Override public Iterator iterator() { return new CellBlocksIterator(false); } - @Override public Iterator descendingIterator() { return new CellBlocksIteratorK(true); } + @Override public Iterator descendingIterator() { return new CellBlocksIterator(true); } @Override public Object[] toArray() { throw new UnsupportedOperationException(); } @Override public T[] toArray(T[] ts) { throw new UnsupportedOperationException(); } - @Override public boolean add(K k) { throw new UnsupportedOperationException(); } + @Override public boolean add(Cell k) { throw new UnsupportedOperationException(); } @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } @@ -371,7 +343,7 @@ private final class CellBlocksSet implements NavigableSet { throw new UnsupportedOperationException(); } - @Override public boolean addAll(Collection collection) { + @Override public boolean addAll(Collection collection) { throw new UnsupportedOperationException(); } @@ -383,27 +355,27 @@ private final class CellBlocksSet implements NavigableSet { throw new UnsupportedOperationException(); } - @Override public NavigableSet descendingSet() { throw new UnsupportedOperationException(); } + @Override public NavigableSet descendingSet() { throw new UnsupportedOperationException(); } - @Override public SortedSet subSet(K k, K e1) { throw new UnsupportedOperationException(); } + @Override public SortedSet subSet(Cell k, Cell e1) { throw new UnsupportedOperationException(); } - @Override public NavigableSet subSet(K k, boolean b, K e1, boolean b1) { + @Override public NavigableSet subSet(Cell k, boolean b, Cell e1, boolean b1) { throw new UnsupportedOperationException(); } - @Override public NavigableSet headSet(K k, boolean b) { // headMap should be used instead + @Override public NavigableSet headSet(Cell k, boolean b) { // headMap should be used instead throw new UnsupportedOperationException(); } - @Override public NavigableSet tailSet(K k, boolean b) { // tailMap should be used instead + @Override public NavigableSet tailSet(Cell k, boolean b) { // tailMap should be used instead throw new UnsupportedOperationException(); } - @Override public SortedSet headSet(K k) { // headMap should be used instead + @Override public SortedSet headSet(Cell k) { // headMap should be used instead throw new UnsupportedOperationException(); } - @Override public SortedSet tailSet(K k) { // tailMap should be used instead + @Override public SortedSet tailSet(Cell k) { // tailMap should be used instead throw new UnsupportedOperationException(); } @@ -411,7 +383,7 @@ private final class CellBlocksSet implements NavigableSet { } // -------------------------------- Collection -------------------------------- - private final class CellBlocksCollection implements Collection { + private final class CellBlocksCollection implements Collection { @Override public int size() { return size(); } @@ -421,15 +393,15 @@ private final class CellBlocksCollection implements Collection { @Override public boolean contains(Object o) { return containsKey(o); } - @Override public Iterator iterator() { - return (isDescending) ? new CellBlocksIteratorV(true) : new CellBlocksIteratorV(false); + @Override public Iterator iterator() { + return (isDescending) ? new CellBlocksIterator(true) : new CellBlocksIterator(false); } @Override public Object[] toArray() { throw new UnsupportedOperationException(); } @Override public T[] toArray(T[] ts) { throw new UnsupportedOperationException(); } - @Override public boolean add(V k) { throw new UnsupportedOperationException(); } + @Override public boolean add(Cell k) { throw new UnsupportedOperationException(); } @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } @@ -437,7 +409,7 @@ private final class CellBlocksCollection implements Collection { throw new UnsupportedOperationException(); } - @Override public boolean addAll(Collection collection) { + @Override public boolean addAll(Collection collection) { throw new UnsupportedOperationException(); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java new file mode 100644 index 000000000000..997d7638bec4 --- /dev/null +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java @@ -0,0 +1,63 @@ +/** + * + * 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, Cellersion 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 CellIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hbase.regionserver; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.Cell; +import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.util.Bytes; + +import java.util.Comparator; + +/** + * CellBlocks stores a constant number of elements and is immutable after creation stage. + * Due to being immutable the CellBlocks can be implemented as array. + * The CellBlocks uses no synchronization primitives, it is assumed to be created by a + * single thread and then it can be read-only by multiple threads. + */ +public class CellBlocksOffHeap extends CellBlocks { + + byte block[]; + private final Configuration conf; + + public CellBlocksOffHeap(Comparator comparator, Configuration conf, + byte b[], int min, int max, boolean d) { + super(comparator,min,max,d); + this.block = b; + this.conf = conf; + } + + @Override + protected CellBlocks createCellBlocksMap(Comparator comparator, int min, int max, + boolean d) { + return new CellBlocksOffHeap(comparator, this.conf, this.block, min, max, d); + } + + @Override + protected Cell getCellFromIndex(int i) { + int offsetInBytes = 3*i*(Integer.SIZE / Byte.SIZE); + int chunkId = Bytes.toInt(block,offsetInBytes); + int offsetOfCell = Bytes.toInt(block,offsetInBytes+3*(Integer.SIZE / Byte.SIZE)); + int lengthOfCell = Bytes.toInt(block,offsetInBytes+6*(Integer.SIZE / Byte.SIZE)); + byte[] chunk = MemStoreChunkPool.getPool(conf).translateIdToChunk(chunkId).getData(); + Cell result = new KeyValue(chunk, offsetOfCell, lengthOfCell); + return result; + } +} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java new file mode 100644 index 000000000000..de0f4f6a17ae --- /dev/null +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java @@ -0,0 +1,54 @@ +/** + * + * 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, Cellersion 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 CellIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hbase.regionserver; + +import org.apache.hadoop.hbase.Cell; + +import java.util.*; +import java.util.concurrent.ConcurrentNavigableMap; +import junit.framework.Assert; + +/** + * CellBlocks stores a constant number of elements and is immutable after creation stage. + * Due to being immutable the CellBlocks can be implemented as array. + * The CellBlocks uses no synchronization primitives, it is assumed to be created by a + * single thread and then it can be read-only by multiple threads. + */ +public class CellBlocksOnHeap extends CellBlocks { + + Cell block[]; + + public CellBlocksOnHeap(Comparator comparator, Cell b[], int min, int max, + boolean d) { + super(comparator,min,max,d); + this.block = b; + } + + @Override + protected CellBlocks createCellBlocksMap(Comparator comparator, int min, int max, + boolean d) { + return new CellBlocksOnHeap(comparator,this.block,min,max,d); + } + + @Override + protected Cell getCellFromIndex(int i) { + return block[i]; + } +} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java index f22a6e5c1ac8..ef7a94577f6e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java @@ -191,7 +191,8 @@ private Chunk getOrMakeChunk() { // No current chunk, so we want to allocate one. We race // against other allocators to CAS in an uninitialized chunk // (which is cheap to allocate) - c = (chunkPool != null) ? chunkPool.getChunk() : new Chunk(chunkSize); + //c = (chunkPool != null) ? chunkPool.getChunk() : new Chunk(chunkSize); + c = chunkPool.getChunk(); if (curChunk.compareAndSet(null, c)) { // we won race - now we need to actually do the expensive // allocation step @@ -227,12 +228,18 @@ static class Chunk { /** Size of chunk in bytes */ private final int size; + /* A unique identifier of a chunk inside MemStoreChunkPool */ + private final long id; + + /* Chunk's index serves as replacement for pointer */ + /** * Create an uninitialized chunk. Note that memory is not allocated yet, so * this is cheap. * @param size in bytes */ - Chunk(int size) { + Chunk(int size, long id) { + this.id = id; this.size = size; } @@ -311,5 +318,13 @@ public String toString() { " allocs=" + allocCount.get() + "waste=" + (data.length - nextFreeOffset.get()); } + + public long getId() { + return id; + } + + public byte[] getData() { + return data; + } } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java index 628506059eef..262e098493d9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java @@ -19,11 +19,8 @@ package org.apache.hadoop.hbase.regionserver; import java.lang.management.ManagementFactory; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.logging.Log; @@ -76,6 +73,10 @@ public class MemStoreChunkPool { private static final int statThreadPeriod = 60 * 5; private AtomicLong createdChunkCount = new AtomicLong(); private AtomicLong reusedChunkCount = new AtomicLong(); + private AtomicInteger totalChunkCount = new AtomicInteger(); + + // IDs Mapping of all chunks + private final ConcurrentMap chunksMap = new ConcurrentHashMap(); MemStoreChunkPool(Configuration conf, int chunkSize, int maxCount, int initialCount) { @@ -83,10 +84,12 @@ public class MemStoreChunkPool { this.chunkSize = chunkSize; this.reclaimedChunks = new LinkedBlockingQueue(); for (int i = 0; i < initialCount; i++) { - Chunk chunk = new Chunk(chunkSize); + Chunk chunk = new Chunk(chunkSize,i); + chunksMap.put(i, chunk); chunk.init(); reclaimedChunks.add(chunk); } + totalChunkCount.set(initialCount); final String n = Thread.currentThread().getName(); scheduleThreadPool = Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setNameFormat(n+"-MemStoreChunkPool Statistics") @@ -103,7 +106,9 @@ public class MemStoreChunkPool { Chunk getChunk() { Chunk chunk = reclaimedChunks.poll(); if (chunk == null) { - chunk = new Chunk(chunkSize); + int i = totalChunkCount.getAndIncrement(); + chunk = new Chunk(chunkSize,i); + chunksMap.put(i, chunk); createdChunkCount.incrementAndGet(); } else { chunk.reset(); @@ -125,6 +130,14 @@ void putbackChunks(BlockingQueue chunks) { chunks.drainTo(reclaimedChunks, maxNumToPutback); } + /** + * Given a chunk ID return reference to the relevant chunk + * @return a chunk + */ + Chunk translateIdToChunk(long id) { + return chunksMap.get(new Long(id)); + } + /** * Add the chunk to the pool, if the pool has achieved the max size, it will * skip it diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java index 58339a62cfcb..ee8faddaa31c 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java @@ -19,10 +19,7 @@ package org.apache.hadoop.hbase.regionserver; import junit.framework.TestCase; -import org.apache.hadoop.hbase.Cell; -import org.apache.hadoop.hbase.CellComparator; -import org.apache.hadoop.hbase.CellUtil; -import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.*; import org.apache.hadoop.hbase.testclassification.RegionServerTests; import org.apache.hadoop.hbase.testclassification.SmallTests; import org.apache.hadoop.hbase.util.Bytes; @@ -36,8 +33,11 @@ public class TestCellBlocksSet extends TestCase { private static final int NUM_OF_CELLS = 3; + private byte[] deepBuffer; // deep cell data + private byte[] shallowBuffer; // shallow cell data + private Cell cells[]; - private CellBlocksMap cbMap; + private CellBlocksOnHeap cbMap; private CellSet cbSet; protected void setUp() throws Exception { @@ -56,8 +56,32 @@ protected void setUp() throws Exception { final KeyValue kv3 = new KeyValue(three, f, q, 30, v); cells = new Cell[] {kv1,kv2,kv3}; - cbMap = new CellBlocksMap(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS,false); + cbMap = new CellBlocksOnHeap(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS,false); cbSet = new CellSet(cbMap); + + /*---------------- shallow cells to bytes start ----------------*/ + deepBuffer = new byte[128]; + shallowBuffer = new byte[64]; + int offset = 0; + int pos = offset; + + KeyValueUtil.appendToByteArray(kv1, deepBuffer, offset); + pos = Bytes.putInt(shallowBuffer, pos, 0); // chunk index + pos = Bytes.putInt(shallowBuffer, pos, offset); // offset + pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv1)); // length + offset += KeyValueUtil.length(kv1); + + KeyValueUtil.appendToByteArray(kv2, deepBuffer, offset); + pos = Bytes.putInt(shallowBuffer, pos, 0); // chunk index + pos = Bytes.putInt(shallowBuffer, pos, offset); // offset + pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv2)); // length + offset += KeyValueUtil.length(kv2); + + KeyValueUtil.appendToByteArray(kv3, deepBuffer, offset); + pos = Bytes.putInt(shallowBuffer, pos, 0); // chunk index + pos = Bytes.putInt(shallowBuffer, pos, offset); // offset + pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv3)); // length + /*---------------- shallow cells to bytes end ----------------*/ } public void testBasics() throws Exception { @@ -114,4 +138,79 @@ public void testIterators() throws Exception { } + + /*---------------------------------- Shallow Cell ----------------------------------*/ + static class ShallowCell implements Cell { + @Override public byte[] getRowArray() { + return new byte[0]; + } + + @Override public int getRowOffset() { + return 0; + } + + @Override public short getRowLength() { + return 0; + } + + @Override public byte[] getFamilyArray() { + return new byte[0]; + } + + @Override public int getFamilyOffset() { + return 0; + } + + @Override public byte getFamilyLength() { + return 0; + } + + @Override public byte[] getQualifierArray() { + return new byte[0]; + } + + @Override public int getQualifierOffset() { + return 0; + } + + @Override public int getQualifierLength() { + return 0; + } + + @Override public long getTimestamp() { + return 0; + } + + @Override public byte getTypeByte() { + return 0; + } + + @Override public long getSequenceId() { + return 0; + } + + @Override public byte[] getValueArray() { + return new byte[0]; + } + + @Override public int getValueOffset() { + return 0; + } + + @Override public int getValueLength() { + return 0; + } + + @Override public byte[] getTagsArray() { + return new byte[0]; + } + + @Override public int getTagsOffset() { + return 0; + } + + @Override public int getTagsLength() { + return 0; + } + } } From 9b8265963bc0ae052a9ced874c91649b8d743c25 Mon Sep 17 00:00:00 2001 From: anastas Date: Mon, 14 Mar 2016 15:27:31 +0200 Subject: [PATCH 05/11] CellBlocksOffHeap passes its tests --- .../hadoop/hbase/regionserver/CellBlocks.java | 22 +-- .../hbase/regionserver/CellBlocksOffHeap.java | 28 ++- .../hbase/regionserver/CellBlocksOnHeap.java | 9 +- .../hbase/regionserver/HeapMemStoreLAB.java | 25 ++- .../hbase/regionserver/MemStoreChunkPool.java | 36 ++-- .../hbase/regionserver/TestCellBlocksSet.java | 177 +++++++----------- 6 files changed, 145 insertions(+), 152 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java index 6547e95925b0..542b217d1454 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java @@ -22,34 +22,34 @@ import java.util.*; import java.util.concurrent.ConcurrentNavigableMap; -import junit.framework.Assert; /** * CellBlocks stores a constant number of elements and is immutable after creation stage. * Due to being immutable the CellBlocks can be implemented as array. + * The actual array is on- or off-heap and is implemented in concrete class derived from CellBlocks. * The CellBlocks uses no synchronization primitives, it is assumed to be created by a * single thread and then it can be read-only by multiple threads. */ public abstract class CellBlocks implements ConcurrentNavigableMap { private final Comparator comparator; - private int minCellIdx = 0; // the index of the minimal cell (for sub-sets) private int maxCellIdx = 0; // the index of the maximal cell (for sub-sets) private boolean isDescending = false; // array can be easily traversed backward in descending order - + /* C-tor */ public CellBlocks(Comparator comparator, int min, int max, boolean d){ - //assert(false); this.comparator = comparator; this.minCellIdx = min; this.maxCellIdx = max; this.isDescending = d; } - protected abstract CellBlocks createCellBlocksMap(Comparator comparator, - int min, int max, boolean d); + /* Used for abstract CellBlocks creation, implemented by derived class */ + protected abstract CellBlocks createCellBlocks(Comparator comparator, int min, + int max, boolean d); + /* Assuming array underneath implementation this comes instead of array[i] */ protected abstract Cell getCellFromIndex(int i); /** @@ -102,25 +102,25 @@ else if (compareRes < 0) { if (!fromInclusive && fromIndex >= 0) fromIndex++; else if (fromIndex < 0) fromIndex = -(fromIndex + 1); - return createCellBlocksMap(comparator,fromIndex,toIndex,false); + return createCellBlocks(comparator, fromIndex, toIndex, false); } @Override public ConcurrentNavigableMap headMap(Cell toKey, boolean inclusive) { int index = find(toKey); if (inclusive && index >= 0) index++; else if (index < 0) index = -(index + 1) - 1; - return createCellBlocksMap(comparator,minCellIdx,index,false); + return createCellBlocks(comparator, minCellIdx, index, false); } @Override public ConcurrentNavigableMap tailMap(Cell fromKey, boolean inclusive) { int index = find(fromKey); if (!inclusive && index >= 0) index++; else if (index < 0) index = -(index + 1); - return createCellBlocksMap(comparator,index,maxCellIdx,false); + return createCellBlocks(comparator, index, maxCellIdx, false); } @Override public ConcurrentNavigableMap descendingMap() { - return createCellBlocksMap(comparator,minCellIdx,maxCellIdx,true); + return createCellBlocks(comparator, minCellIdx, maxCellIdx, true); } @Override public ConcurrentNavigableMap subMap(Cell k, Cell k1) { @@ -424,6 +424,4 @@ private final class CellBlocksCollection implements Collection { } - - } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java index 997d7638bec4..5e57d5133841 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java @@ -25,16 +25,15 @@ import org.apache.hadoop.hbase.util.Bytes; import java.util.Comparator; +import junit.framework.Assert; /** - * CellBlocks stores a constant number of elements and is immutable after creation stage. - * Due to being immutable the CellBlocks can be implemented as array. - * The CellBlocks uses no synchronization primitives, it is assumed to be created by a - * single thread and then it can be read-only by multiple threads. + * CellBlocksOffHeap is a byte array holding all that is needed to access a Cell, which + * is actually saved on another deeper byte array */ public class CellBlocksOffHeap extends CellBlocks { - byte block[]; + private byte block[]; private final Configuration conf; public CellBlocksOffHeap(Comparator comparator, Configuration conf, @@ -45,18 +44,31 @@ public CellBlocksOffHeap(Comparator comparator, Configuration conf } @Override - protected CellBlocks createCellBlocksMap(Comparator comparator, int min, int max, + protected CellBlocks createCellBlocks(Comparator comparator, int min, int max, boolean d) { return new CellBlocksOffHeap(comparator, this.conf, this.block, min, max, d); } @Override protected Cell getCellFromIndex(int i) { +// org.junit.Assert.assertTrue("\nGetting Cell from index:" + i + "\n",false); + int offsetInBytes = 3*i*(Integer.SIZE / Byte.SIZE); + +// org.junit.Assert.assertTrue("\n\nGetting Cell from index: " + i +// + ", offset to the start: " + offsetInBytes + ", the start of bytes array: " + block +// + "\n\n",false); + int chunkId = Bytes.toInt(block,offsetInBytes); - int offsetOfCell = Bytes.toInt(block,offsetInBytes+3*(Integer.SIZE / Byte.SIZE)); - int lengthOfCell = Bytes.toInt(block,offsetInBytes+6*(Integer.SIZE / Byte.SIZE)); + int offsetOfCell = Bytes.toInt(block,offsetInBytes+(Integer.SIZE / Byte.SIZE)); + int lengthOfCell = Bytes.toInt(block,offsetInBytes+2*(Integer.SIZE / Byte.SIZE)); byte[] chunk = MemStoreChunkPool.getPool(conf).translateIdToChunk(chunkId).getData(); + +// org.junit.Assert.assertTrue("\n\n<<<<<< Getting Cell from index: " + i +// + "(got deep chunk), offset to the start: " + offsetInBytes + ", the start of bytes array: " +// + block + ", the (deep) chunk id: " + chunkId + ", offset of cell in deep buffer: " +// + offsetOfCell + "\n\n",false); + Cell result = new KeyValue(chunk, offsetOfCell, lengthOfCell); return result; } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java index de0f4f6a17ae..332f09c0b25e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java @@ -22,14 +22,11 @@ import org.apache.hadoop.hbase.Cell; import java.util.*; -import java.util.concurrent.ConcurrentNavigableMap; import junit.framework.Assert; /** - * CellBlocks stores a constant number of elements and is immutable after creation stage. - * Due to being immutable the CellBlocks can be implemented as array. - * The CellBlocks uses no synchronization primitives, it is assumed to be created by a - * single thread and then it can be read-only by multiple threads. + * CellBlocksOnHeap is a simple array of Cells allocated using JVM. + * As all java arrays it is array of references pointing to Cell objects */ public class CellBlocksOnHeap extends CellBlocks { @@ -42,7 +39,7 @@ public CellBlocksOnHeap(Comparator comparator, Cell b[], int min, } @Override - protected CellBlocks createCellBlocksMap(Comparator comparator, int min, int max, + protected CellBlocks createCellBlocks(Comparator comparator, int min, int max, boolean d) { return new CellBlocksOnHeap(comparator,this.block,min,max,d); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java index ef7a94577f6e..e84c856d58d5 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java @@ -88,9 +88,8 @@ public HeapMemStoreLAB(Configuration conf) { this.chunkPool = MemStoreChunkPool.getPool(conf); // if we don't exclude allocations >CHUNK_SIZE, we'd infiniteloop on one! - Preconditions.checkArgument( - maxAlloc <= chunkSize, - MAX_ALLOC_KEY + " must be less than " + CHUNK_SIZE_KEY); + Preconditions.checkArgument(maxAlloc <= chunkSize, + MAX_ALLOC_KEY + " must be less than " + CHUNK_SIZE_KEY); } /** @@ -191,12 +190,12 @@ private Chunk getOrMakeChunk() { // No current chunk, so we want to allocate one. We race // against other allocators to CAS in an uninitialized chunk // (which is cheap to allocate) - //c = (chunkPool != null) ? chunkPool.getChunk() : new Chunk(chunkSize); - c = chunkPool.getChunk(); + //c = (chunkPool != null) ? chunkPool.getChunk() : new Chunk(chunkSize); 14921 + c = chunkPool.getChunk(); // 14921 if (curChunk.compareAndSet(null, c)) { // we won race - now we need to actually do the expensive // allocation step - c.init(); + // c.init(); 14921 this.chunkQueue.add(c); return c; } else if (chunkPool != null) { @@ -207,6 +206,14 @@ private Chunk getOrMakeChunk() { } } + /** 14921 + * Given a chunk ID return reference to the relevant chunk + * @return a chunk + */ + Chunk translateIdToChunk(int id) { + return chunkPool.translateIdToChunk(id); + } + /** * A chunk of memory out of which allocations are sliced. */ @@ -229,7 +236,7 @@ static class Chunk { private final int size; /* A unique identifier of a chunk inside MemStoreChunkPool */ - private final long id; + private final int id; /* Chunk's index serves as replacement for pointer */ @@ -238,7 +245,7 @@ static class Chunk { * this is cheap. * @param size in bytes */ - Chunk(int size, long id) { + Chunk(int size, int id) { this.id = id; this.size = size; } @@ -319,7 +326,7 @@ public String toString() { (data.length - nextFreeOffset.get()); } - public long getId() { + public int getId() { return id; } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java index 262e098493d9..32fbd748025d 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java @@ -73,9 +73,8 @@ public class MemStoreChunkPool { private static final int statThreadPeriod = 60 * 5; private AtomicLong createdChunkCount = new AtomicLong(); private AtomicLong reusedChunkCount = new AtomicLong(); - private AtomicInteger totalChunkCount = new AtomicInteger(); - // IDs Mapping of all chunks + // IDs Mapping of all chunks (key 0 is forbidden) private final ConcurrentMap chunksMap = new ConcurrentHashMap(); MemStoreChunkPool(Configuration conf, int chunkSize, int maxCount, @@ -83,13 +82,12 @@ public class MemStoreChunkPool { this.maxCount = maxCount; this.chunkSize = chunkSize; this.reclaimedChunks = new LinkedBlockingQueue(); + for (int i = 0; i < initialCount; i++) { - Chunk chunk = new Chunk(chunkSize,i); - chunksMap.put(i, chunk); - chunk.init(); + Chunk chunk = allocateChunk(); reclaimedChunks.add(chunk); } - totalChunkCount.set(initialCount); + final String n = Thread.currentThread().getName(); scheduleThreadPool = Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setNameFormat(n+"-MemStoreChunkPool Statistics") @@ -106,9 +104,7 @@ public class MemStoreChunkPool { Chunk getChunk() { Chunk chunk = reclaimedChunks.poll(); if (chunk == null) { - int i = totalChunkCount.getAndIncrement(); - chunk = new Chunk(chunkSize,i); - chunksMap.put(i, chunk); + chunk = allocateChunk(); createdChunkCount.incrementAndGet(); } else { chunk.reset(); @@ -134,8 +130,8 @@ void putbackChunks(BlockingQueue chunks) { * Given a chunk ID return reference to the relevant chunk * @return a chunk */ - Chunk translateIdToChunk(long id) { - return chunksMap.get(new Long(id)); + Chunk translateIdToChunk(int id) { + return chunksMap.get(id); } /** @@ -161,6 +157,24 @@ void clearChunks() { this.reclaimedChunks.clear(); } + /* + * Only used in testing + */ + ConcurrentMap getChunksMap() { + return this.chunksMap; + } + + /* + * Allocate and register Chunk + */ + private Chunk allocateChunk() { + int newId = chunksMap.size() + 1; // the number of the new chunk + Chunk chunk = new Chunk(chunkSize,newId); + chunksMap.put(newId, chunk); + chunk.init(); + return chunk; + } + private static class StatisticsThread extends Thread { MemStoreChunkPool mcp; diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java index ee8faddaa31c..84a8ad51b2ff 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java @@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.regionserver; import junit.framework.TestCase; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.*; import org.apache.hadoop.hbase.testclassification.RegionServerTests; import org.apache.hadoop.hbase.testclassification.SmallTests; @@ -27,18 +28,22 @@ import java.util.Iterator; import java.util.SortedSet; +import static org.junit.Assert.assertTrue; @Category({RegionServerTests.class, SmallTests.class}) public class TestCellBlocksSet extends TestCase { private static final int NUM_OF_CELLS = 3; - private byte[] deepBuffer; // deep cell data - private byte[] shallowBuffer; // shallow cell data - private Cell cells[]; - private CellBlocksOnHeap cbMap; - private CellSet cbSet; + private CellBlocksOnHeap cbOnHeap; + private CellBlocksOffHeap cbOffHeap; + + private final static Configuration conf = new Configuration(); + private static MemStoreChunkPool chunkPool; + + + protected void setUp() throws Exception { super.setUp(); @@ -56,49 +61,47 @@ protected void setUp() throws Exception { final KeyValue kv3 = new KeyValue(three, f, q, 30, v); cells = new Cell[] {kv1,kv2,kv3}; - cbMap = new CellBlocksOnHeap(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS,false); - cbSet = new CellSet(cbMap); - - /*---------------- shallow cells to bytes start ----------------*/ - deepBuffer = new byte[128]; - shallowBuffer = new byte[64]; - int offset = 0; - int pos = offset; + cbOnHeap = new CellBlocksOnHeap(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS,false); - KeyValueUtil.appendToByteArray(kv1, deepBuffer, offset); - pos = Bytes.putInt(shallowBuffer, pos, 0); // chunk index - pos = Bytes.putInt(shallowBuffer, pos, offset); // offset - pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv1)); // length - offset += KeyValueUtil.length(kv1); + conf.setBoolean(SegmentFactory.USEMSLAB_KEY, true); + conf.setFloat(MemStoreChunkPool.CHUNK_POOL_MAXSIZE_KEY, 0.2f); + MemStoreChunkPool.chunkPoolDisabled = false; + chunkPool = MemStoreChunkPool.getPool(conf); + assertTrue(chunkPool != null); - KeyValueUtil.appendToByteArray(kv2, deepBuffer, offset); - pos = Bytes.putInt(shallowBuffer, pos, 0); // chunk index - pos = Bytes.putInt(shallowBuffer, pos, offset); // offset - pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv2)); // length - offset += KeyValueUtil.length(kv2); + byte[] b = shallowCellsToBuffer(kv1, kv2, kv3); + cbOffHeap = new CellBlocksOffHeap(CellComparator.COMPARATOR, conf, b, 0, NUM_OF_CELLS, false); + } - KeyValueUtil.appendToByteArray(kv3, deepBuffer, offset); - pos = Bytes.putInt(shallowBuffer, pos, 0); // chunk index - pos = Bytes.putInt(shallowBuffer, pos, offset); // offset - pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv3)); // length - /*---------------- shallow cells to bytes end ----------------*/ + /* Create and test CellSet based on CellBlocksOnHeap */ + public void testCellBlocksOnHeap() throws Exception { + CellSet cs = new CellSet(cbOnHeap); + testCellBlocks(cs); + testIterators(cs); } - public void testBasics() throws Exception { + /* Create and test CellSet based on CellBlocksOffHeap */ + public void testCellBlocksOffHeap() throws Exception { + CellSet cs = new CellSet(cbOffHeap); + testCellBlocks(cs); + testIterators(cs); + } - assertEquals(3, this.cbSet.size()); // check size + /* Generic basic test for immutable CellSet */ + private void testCellBlocks(CellSet cs) throws Exception { + assertEquals(NUM_OF_CELLS, cs.size()); // check size - assertTrue(this.cbSet.contains(cells[0])); // check first - Cell first = this.cbSet.first(); + assertTrue(cs.contains(cells[0])); // check first + Cell first = cs.first(); assertTrue(cells[0].equals(first)); - assertTrue(this.cbSet.contains(cells[NUM_OF_CELLS - 1])); // check last - Cell last = this.cbSet.last(); + assertTrue(cs.contains(cells[NUM_OF_CELLS - 1])); // check last + Cell last = cs.last(); assertTrue(cells[NUM_OF_CELLS - 1].equals(last)); - SortedSet tail = this.cbSet.tailSet(cells[1]); // check tail abd head sizes + SortedSet tail = cs.tailSet(cells[1]); // check tail abd head sizes assertEquals(2, tail.size()); - SortedSet head = this.cbSet.headSet(cells[1]); + SortedSet head = cs.headSet(cells[1]); assertEquals(1, head.size()); Cell tailFirst = tail.first(); @@ -112,11 +115,12 @@ public void testBasics() throws Exception { assertTrue(cells[0].equals(headLast)); } - public void testIterators() throws Exception { + /* Generic iterators test for immutable CellSet */ + private void testIterators(CellSet cs) throws Exception { // Assert that we have NUM_OF_CELLS values and that they are in order int count = 0; - for (Cell kv: this.cbSet) { + for (Cell kv: cs) { assertEquals("\n\n-------------------------------------------------------------------\n" + "Comparing iteration number " + (count + 1) + " the returned cell: " + kv + ", the first Cell in the CellBlocksMap: " + cells[count] @@ -129,7 +133,7 @@ public void testIterators() throws Exception { // Test descending iterator count = 0; - for (Iterator i = this.cbSet.descendingIterator(); i.hasNext();) { + for (Iterator i = cs.descendingIterator(); i.hasNext();) { Cell kv = i.next(); assertEquals(cells[NUM_OF_CELLS - (count + 1)], kv); count++; @@ -137,80 +141,41 @@ public void testIterators() throws Exception { assertEquals(NUM_OF_CELLS, count); } + /* Create byte array holding shallow Cells referencing to the deep Cells data */ + private byte[] shallowCellsToBuffer(Cell kv1, Cell kv2, Cell kv3) { + HeapMemStoreLAB.Chunk chunkD = chunkPool.getChunk(); + HeapMemStoreLAB.Chunk chunkS = chunkPool.getChunk(); + byte[] deepBuffer = chunkD.getData(); + byte[] shallowBuffer = chunkS.getData(); + int offset = 0; + int pos = offset; - /*---------------------------------- Shallow Cell ----------------------------------*/ - static class ShallowCell implements Cell { - @Override public byte[] getRowArray() { - return new byte[0]; - } - - @Override public int getRowOffset() { - return 0; - } - - @Override public short getRowLength() { - return 0; - } - - @Override public byte[] getFamilyArray() { - return new byte[0]; - } - - @Override public int getFamilyOffset() { - return 0; - } - - @Override public byte getFamilyLength() { - return 0; - } - - @Override public byte[] getQualifierArray() { - return new byte[0]; - } - - @Override public int getQualifierOffset() { - return 0; - } - - @Override public int getQualifierLength() { - return 0; - } - - @Override public long getTimestamp() { - return 0; - } - - @Override public byte getTypeByte() { - return 0; - } +// assertTrue("\n\n<<<<< Preparing for CellBlocksOffHeap, shallow chunk: " + chunkS +// + " has index: " + chunkS.getId() + " \n\n", false); - @Override public long getSequenceId() { - return 0; - } + KeyValueUtil.appendToByteArray(kv1, deepBuffer, offset); // write deep cell data - @Override public byte[] getValueArray() { - return new byte[0]; - } +// assertTrue("\n\n<<<<< Preparing for CellBlocksOffHeap, shallow chunk: " + chunkS +// + " has index: " + chunkS.getId() + ", deep chunk: " + chunkD +// + " has index: " + chunkD.getId() + "\n\n", false); - @Override public int getValueOffset() { - return 0; - } - - @Override public int getValueLength() { - return 0; - } + pos = Bytes.putInt(shallowBuffer, pos, chunkD.getId()); // write deep chunk index + pos = Bytes.putInt(shallowBuffer, pos, offset); // offset + pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv1)); // length + offset += KeyValueUtil.length(kv1); - @Override public byte[] getTagsArray() { - return new byte[0]; - } + KeyValueUtil.appendToByteArray(kv2, deepBuffer, offset); // write deep cell data + pos = Bytes.putInt(shallowBuffer, pos, chunkD.getId()); // deep chunk index + pos = Bytes.putInt(shallowBuffer, pos, offset); // offset + pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv2)); // length + offset += KeyValueUtil.length(kv2); - @Override public int getTagsOffset() { - return 0; - } + KeyValueUtil.appendToByteArray(kv3, deepBuffer, offset); // write deep cell data + pos = Bytes.putInt(shallowBuffer, pos, chunkD.getId()); // deep chunk index + pos = Bytes.putInt(shallowBuffer, pos, offset); // offset + pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv3)); // length - @Override public int getTagsLength() { - return 0; - } + return shallowBuffer; } } From 3b8e57101fa54e4f06b1d7c75db436019240ae2c Mon Sep 17 00:00:00 2001 From: anastas Date: Mon, 14 Mar 2016 16:29:08 +0200 Subject: [PATCH 06/11] Ready to code review --- .../hadoop/hbase/regionserver/CellBlocksOffHeap.java | 10 +++++----- .../hadoop/hbase/regionserver/HeapMemStoreLAB.java | 10 ++++++++++ .../hadoop/hbase/regionserver/TestCellBlocksSet.java | 12 +++++------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java index 5e57d5133841..0f68ecbd877c 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java @@ -34,19 +34,19 @@ public class CellBlocksOffHeap extends CellBlocks { private byte block[]; - private final Configuration conf; + private final HeapMemStoreLAB memStoreLAB; - public CellBlocksOffHeap(Comparator comparator, Configuration conf, + public CellBlocksOffHeap(Comparator comparator, HeapMemStoreLAB memStoreLAB, byte b[], int min, int max, boolean d) { super(comparator,min,max,d); this.block = b; - this.conf = conf; + this.memStoreLAB = memStoreLAB; } @Override protected CellBlocks createCellBlocks(Comparator comparator, int min, int max, boolean d) { - return new CellBlocksOffHeap(comparator, this.conf, this.block, min, max, d); + return new CellBlocksOffHeap(comparator, this.memStoreLAB, this.block, min, max, d); } @Override @@ -62,7 +62,7 @@ protected Cell getCellFromIndex(int i) { int chunkId = Bytes.toInt(block,offsetInBytes); int offsetOfCell = Bytes.toInt(block,offsetInBytes+(Integer.SIZE / Byte.SIZE)); int lengthOfCell = Bytes.toInt(block,offsetInBytes+2*(Integer.SIZE / Byte.SIZE)); - byte[] chunk = MemStoreChunkPool.getPool(conf).translateIdToChunk(chunkId).getData(); + byte[] chunk = memStoreLAB.translateIdToChunk(chunkId).getData(); // org.junit.Assert.assertTrue("\n\n<<<<<< Getting Cell from index: " + i // + "(got deep chunk), offset to the start: " + offsetInBytes + ", the start of bytes array: " diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java index e84c856d58d5..f245cbe5586d 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java @@ -214,6 +214,16 @@ Chunk translateIdToChunk(int id) { return chunkPool.translateIdToChunk(id); } + /** 14921 + * Use instead of allocateBytes() when new full chunk is needed + * @return a chunk + */ + Chunk allocateChunk() { + Chunk c = chunkPool.getChunk(); + this.chunkQueue.add(c); + return c; + } + /** * A chunk of memory out of which allocations are sliced. */ diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java index 84a8ad51b2ff..ecaa5fcdcc7d 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java @@ -40,8 +40,7 @@ public class TestCellBlocksSet extends TestCase { private CellBlocksOffHeap cbOffHeap; private final static Configuration conf = new Configuration(); - private static MemStoreChunkPool chunkPool; - + private HeapMemStoreLAB mslab; @@ -66,11 +65,10 @@ protected void setUp() throws Exception { conf.setBoolean(SegmentFactory.USEMSLAB_KEY, true); conf.setFloat(MemStoreChunkPool.CHUNK_POOL_MAXSIZE_KEY, 0.2f); MemStoreChunkPool.chunkPoolDisabled = false; - chunkPool = MemStoreChunkPool.getPool(conf); - assertTrue(chunkPool != null); + mslab = new HeapMemStoreLAB(conf); byte[] b = shallowCellsToBuffer(kv1, kv2, kv3); - cbOffHeap = new CellBlocksOffHeap(CellComparator.COMPARATOR, conf, b, 0, NUM_OF_CELLS, false); + cbOffHeap = new CellBlocksOffHeap(CellComparator.COMPARATOR, mslab, b, 0, NUM_OF_CELLS, false); } /* Create and test CellSet based on CellBlocksOnHeap */ @@ -143,8 +141,8 @@ private void testIterators(CellSet cs) throws Exception { /* Create byte array holding shallow Cells referencing to the deep Cells data */ private byte[] shallowCellsToBuffer(Cell kv1, Cell kv2, Cell kv3) { - HeapMemStoreLAB.Chunk chunkD = chunkPool.getChunk(); - HeapMemStoreLAB.Chunk chunkS = chunkPool.getChunk(); + HeapMemStoreLAB.Chunk chunkD = mslab.allocateChunk(); + HeapMemStoreLAB.Chunk chunkS = mslab.allocateChunk(); byte[] deepBuffer = chunkD.getData(); byte[] shallowBuffer = chunkS.getData(); From 5e397c7c1426e20b5bc66e1f335796c0542631dd Mon Sep 17 00:00:00 2001 From: anastas Date: Wed, 16 Mar 2016 15:35:20 +0200 Subject: [PATCH 07/11] After code review --- .../hadoop/hbase/regionserver/CellBlock.java | 492 ++++++++++++++++++ .../hbase/regionserver/CellBlockOffHeap.java | 83 +++ ...BlocksOnHeap.java => CellBlockOnHeap.java} | 18 +- .../hadoop/hbase/regionserver/CellBlocks.java | 427 --------------- .../hbase/regionserver/CellBlocksOffHeap.java | 75 --- .../hadoop/hbase/regionserver/CellSet.java | 3 +- .../hbase/regionserver/TestCellBlocksSet.java | 26 +- 7 files changed, 600 insertions(+), 524 deletions(-) create mode 100644 hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java create mode 100644 hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java rename hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/{CellBlocksOnHeap.java => CellBlockOnHeap.java} (66%) delete mode 100644 hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java delete mode 100644 hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java new file mode 100644 index 000000000000..c9d694cb4d8e --- /dev/null +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java @@ -0,0 +1,492 @@ +/** + * + * 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, Cellersion 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 CellIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.regionserver; + +import org.apache.hadoop.hbase.Cell; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.SortedSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentNavigableMap; + +/** + * CellBlock stores a constant number of elements and is immutable after creation stage. + * Due to being immutable the CellBlock can be implemented as array. + * The actual array is on- or off-heap and is implemented in concrete class derived from CellBlock. + * The CellBlock uses no synchronization primitives, it is assumed to be created by a + * single thread and then it can be read-only by multiple threads. + */ +public abstract class CellBlock implements ConcurrentNavigableMap { + + private final Comparator comparator; + private int minCellIdx = 0; // the index of the minimal cell (for sub-sets) + private int maxCellIdx = 0; // the index of the maximal cell (for sub-sets) + + + /* C-tor */ + public CellBlock(Comparator comparator, int min, int max){ + this.comparator = comparator; + this.minCellIdx = min; + this.maxCellIdx = max; + } + + /* Used for abstract CellBlock creation, implemented by derived class */ + protected abstract CellBlock createCellBlocks(Comparator comparator, int min, + int max); + + /* Returns the i-th cell in the cell block */ + protected abstract Cell getCellFromIndex(int i); + + /** + * Binary search for a given key in between given boundaries of the array + * @param needle The key to look for in all of the entries + * @return Same return value as Arrays.binarySearch. + * Positive returned numbers mean the index. + * Negative returned numbers means the key not found. + * The absolute value of the output is the + * possible insert index for the searched key: (-1 * insertion point) - 1 + */ + private int find(Cell needle) { + int begin = minCellIdx; + int end = maxCellIdx - 1; + + while (begin <= end) { + int mid = begin + ((end - begin) / 2); + Cell midCell = getCellFromIndex(mid); + int compareRes = comparator.compare(midCell, needle); + + // 0 means equals. We found the key. + if (compareRes == 0) return mid; + else if (compareRes < 0) { + // midCell is less than needle so we need to look at farther up + begin = mid + 1; + } else { + // midCell is greater than needle so we need to look down + end = mid - 1; + } + } + + return (-1 * begin) - 1; + } + + private int getValidIndex(Cell key, boolean inclusive) { + int index = find(key); + if (inclusive && index >= 0) index++; + else if (index < 0) index = -(index + 1) - 1; + return index; + } + + @Override + public Comparator comparator() { return comparator; } + + @Override + public int size() { return maxCellIdx-minCellIdx; } + + @Override + public boolean isEmpty() { return (maxCellIdx==minCellIdx); } + + + // ---------------- Sub-Maps ---------------- + @Override + public ConcurrentNavigableMap subMap( Cell fromKey, + boolean fromInclusive, + Cell toKey, + boolean toInclusive) { + int toIndex = getValidIndex(toKey, toInclusive); + int fromIndex = (getValidIndex(fromKey, !fromInclusive))-1; + + if (fromIndex > toIndex) throw new IllegalArgumentException("inconsistent range"); + return createCellBlocks(comparator, fromIndex, toIndex); + } + + @Override + public ConcurrentNavigableMap headMap(Cell toKey, boolean inclusive) { + int index = getValidIndex(toKey, inclusive); + return createCellBlocks(comparator, minCellIdx, index); + } + + @Override + public ConcurrentNavigableMap tailMap(Cell fromKey, boolean inclusive) { + int index = (getValidIndex(fromKey, !inclusive))-1; + return createCellBlocks(comparator, index, maxCellIdx); + } + + @Override + public ConcurrentNavigableMap descendingMap() { + return createCellBlocks(comparator, minCellIdx, maxCellIdx); + } + + @Override + public ConcurrentNavigableMap subMap(Cell k1, Cell k2) { + return this.subMap(k1, true, k2, true); + } + + @Override + public ConcurrentNavigableMap headMap(Cell k) { return this.headMap(k, true); } + + @Override + public ConcurrentNavigableMap tailMap(Cell k) { return this.tailMap(k, true); } + + + // -------------------------------- Key's getters -------------------------------- + @Override + public Cell firstKey() { + if (isEmpty()) return null; + return getCellFromIndex(minCellIdx); + } + + @Override + public Cell lastKey() { + if (isEmpty()) return null; + return getCellFromIndex(maxCellIdx-1); + } + + @Override + public Cell lowerKey(Cell k) { + if (isEmpty()) return null; + int index = find(k); + if (index >= 0) index -= 1; // There's a key exactly equal. + else index = -(index + 1) - 1; + return (index < minCellIdx || index >= maxCellIdx) ? null : getCellFromIndex(index); + } + + @Override + public Cell floorKey(Cell k) { + if (isEmpty()) return null; + int index = find(k); + if (index < 0) index = -(index + 1) - 1; + return (index < minCellIdx || index >= maxCellIdx) ? null : getCellFromIndex(index); + } + + @Override + public Cell ceilingKey(Cell k) { + if (isEmpty()) return null; + int index = find(k); + if (index < 0) index = -(index + 1); + return (index < minCellIdx || index >= maxCellIdx) ? null : getCellFromIndex(index); + } + + @Override + public Cell higherKey(Cell k) { + if (isEmpty()) return null; + int index = find(k); + if (index >= 0) index++; // There's a key exactly equal. + else index = -(index + 1); + return (index < minCellIdx || index >= maxCellIdx) ? null : getCellFromIndex(index); + } + + @Override + public boolean containsKey(Object o) { + int index = find((Cell) o); + return (index >= 0); + } + + @Override + public boolean containsValue(Object o) { // use containsKey(Object o) instead + throw new UnsupportedOperationException(); + } + + @Override + public Cell get(Object o) { + int index = find((Cell) o); + if (index >= 0) { + return getCellFromIndex(index); + } + return null; + } + + // -------------------------------- Entry's getters -------------------------------- + // all interfaces returning Entries are unsupported because we are dealing only with the keys + @Override + public Entry lowerEntry(Cell k) { throw new UnsupportedOperationException(); } + + @Override + public Entry higherEntry(Cell k) { throw new UnsupportedOperationException(); } + + @Override + public Entry ceilingEntry(Cell k) { throw new UnsupportedOperationException(); } + + @Override + public Entry floorEntry(Cell k) { throw new UnsupportedOperationException(); } + + @Override + public Entry firstEntry() { throw new UnsupportedOperationException(); } + + @Override + public Entry lastEntry() { throw new UnsupportedOperationException(); } + + @Override + public Entry pollFirstEntry() { throw new UnsupportedOperationException(); } + + @Override + public Entry pollLastEntry() { throw new UnsupportedOperationException(); } + + + // -------------------------------- Updates -------------------------------- + // All updating methods below are unsupported. + // Assuming an array of Cells will be allocated externally, + // fill up with Cells and provided in construction time. + // Later the structure is immutable. + @Override + public Cell put(Cell k, Cell v) { throw new UnsupportedOperationException(); } + + @Override + public void clear() { throw new UnsupportedOperationException(); } + + @Override + public Cell remove(Object o) { throw new UnsupportedOperationException(); } + + @Override + public boolean replace(Cell k, Cell v, Cell v1) { throw new UnsupportedOperationException(); } + + @Override + public void putAll(Map map) { + throw new UnsupportedOperationException(); + } + + @Override + public Cell putIfAbsent(Cell k, Cell v) { throw new UnsupportedOperationException(); } + + @Override + public boolean remove(Object o, Object o1) { throw new UnsupportedOperationException(); } + + @Override + public Cell replace(Cell k, Cell v) { throw new UnsupportedOperationException(); } + + + // -------------------------------- Sub-Sets -------------------------------- + @Override + public NavigableSet navigableKeySet() { return new CellBlocksSet(); } + + @Override + public NavigableSet descendingKeySet() { throw new UnsupportedOperationException(); } + + @Override + public NavigableSet keySet() { throw new UnsupportedOperationException(); } + + @Override + public Collection values() { return new CellBlocksCollection(); } + + @Override + public Set> entrySet() { throw new UnsupportedOperationException(); } + + + // -------------------------------- Iterator K -------------------------------- + private final class CellBlocksIterator implements Iterator { + int index = minCellIdx; + boolean isDescending = false; + + private CellBlocksIterator(boolean d) { + isDescending = d; + index = d ? maxCellIdx-1 : minCellIdx; + } + + @Override + public boolean hasNext() { + return isDescending ? (index >= minCellIdx) : (index < maxCellIdx); + } + + @Override + public Cell next() { + Cell result = getCellFromIndex(index); + if (isDescending) index--; else index++; + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + + // -------------------------------- Navigable Set -------------------------------- + private final class CellBlocksSet implements NavigableSet { + + @Override + public Cell lower(Cell k) { return lowerKey(k); } + + @Override + public Cell floor(Cell k) { return floorKey(k); } + + @Override + public Cell ceiling(Cell k) { return ceilingKey(k); } + + @Override + public Cell higher(Cell k) { return higherKey(k); } + + @Override + public Cell first() { return firstKey(); } + + @Override + public Cell last() { return lastKey(); } + + @Override + public Cell pollFirst() { throw new UnsupportedOperationException(); } + + @Override + public Cell pollLast() { throw new UnsupportedOperationException(); } + + @Override + public int size() { return size(); } + + @Override + public boolean isEmpty() { return isEmpty(); } + + @Override + public void clear() { throw new UnsupportedOperationException(); } + + @Override + public boolean contains(Object o) { return containsKey(o); } + + @Override + public Comparator comparator() { return comparator; } + + @Override + public Iterator iterator() { return new CellBlocksIterator(false); } + + @Override + public Iterator descendingIterator() { return new CellBlocksIterator(true); } + + @Override + public Object[] toArray() { throw new UnsupportedOperationException(); } + + @Override + public T[] toArray(T[] ts) { throw new UnsupportedOperationException(); } + + @Override + public boolean add(Cell k) { throw new UnsupportedOperationException(); } + + @Override + public boolean remove(Object o) { throw new UnsupportedOperationException(); } + + @Override + public boolean containsAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + public NavigableSet descendingSet() { throw new UnsupportedOperationException(); } + + @Override + public SortedSet subSet(Cell k, Cell e1) { throw new UnsupportedOperationException(); } + + @Override + public NavigableSet subSet(Cell k, boolean b, Cell e1, boolean b1) { + throw new UnsupportedOperationException(); + } + + @Override + public NavigableSet headSet(Cell k, boolean b) { // headMap should be used instead + throw new UnsupportedOperationException(); + } + + @Override + public NavigableSet tailSet(Cell k, boolean b) { // tailMap should be used instead + throw new UnsupportedOperationException(); + } + + @Override + public SortedSet headSet(Cell k) { // headMap should be used instead + throw new UnsupportedOperationException(); + } + + @Override + public SortedSet tailSet(Cell k) { // tailMap should be used instead + throw new UnsupportedOperationException(); + } + + + } + + // -------------------------------- Collection -------------------------------- + private final class CellBlocksCollection implements Collection { + + @Override + public int size() { return size(); } + + @Override + public boolean isEmpty() { return isEmpty(); } + + @Override + public void clear() { throw new UnsupportedOperationException(); } + + @Override + public boolean contains(Object o) { return containsKey(o); } + + @Override + public Iterator iterator() { + return new CellBlocksIterator(false); + } + + @Override + public Object[] toArray() { throw new UnsupportedOperationException(); } + + @Override + public T[] toArray(T[] ts) { throw new UnsupportedOperationException(); } + + @Override + public boolean add(Cell k) { throw new UnsupportedOperationException(); } + + @Override + public boolean remove(Object o) { throw new UnsupportedOperationException(); } + + @Override + public boolean containsAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + + } + +} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java new file mode 100644 index 000000000000..fd6970d0c7c1 --- /dev/null +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java @@ -0,0 +1,83 @@ +/** + * + * 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, Cellersion 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 CellIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hbase.regionserver; + +import org.apache.hadoop.hbase.Cell; +import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.util.Bytes; + +import java.util.Comparator; + +/** + * CellBlockOffHeap is a byte array holding all that is needed to access a Cell, which + * is actually saved on another deeper byte array. + * Per Cell we have a reference to this deeper byte array B, offset in bytes in B (integer), + * and length in bytes in B (integer). In order to save reference to byte array we use the Chunk's + * indexes given by MSLAB (also integer). + * + * The B memory layout: + * + * <----------------- first Cell ---------------------> <-------------- second Cell + * ------------------------------------------------------------------------------------- ... + * | integer = x bytes | integer = x bytes | integer = x bytes | integer = x bytes | + * | reference to B | offset in B where | length of Cell's | reference to may be| ... + * | holding Cell data | Cell's data starts| data in B | another byte array | + * ------------------------------------------------------------------------------------- ... + */ +public class CellBlockOffHeap extends CellBlock { + + private HeapMemStoreLAB.Chunk chunks[]; + private final HeapMemStoreLAB memStoreLAB; + private int numOfCellsInsideChunk; + private final int bytesInCell = 3*(Integer.SIZE / Byte.SIZE); // each Cell requires 3 integers + + public CellBlockOffHeap(Comparator comparator, HeapMemStoreLAB memStoreLAB, + HeapMemStoreLAB.Chunk chunks[], int min, int max, int chunkSize) { + super(comparator,min,max); + this.chunks = chunks; + this.memStoreLAB = memStoreLAB; + this.numOfCellsInsideChunk = chunkSize / bytesInCell; + } + + /* To be used by base class only to create a sub-CellBlock */ + @Override + protected CellBlock createCellBlocks(Comparator comparator, int min, int max) { + return new CellBlockOffHeap(comparator, this.memStoreLAB, this.chunks, min, max, + this.numOfCellsInsideChunk*bytesInCell); + } + + @Override + protected Cell getCellFromIndex(int i) { + // find correct chunk + int chunkIndex = (i / numOfCellsInsideChunk); + byte[] block = chunks[chunkIndex].getData(); + i = i - chunkIndex*numOfCellsInsideChunk; + + // find inside chunk + int offsetInBytes = 3*i*(Integer.SIZE / Byte.SIZE); + int chunkId = Bytes.toInt(block,offsetInBytes); + int offsetOfCell = Bytes.toInt(block,offsetInBytes+(Integer.SIZE / Byte.SIZE)); + int lengthOfCell = Bytes.toInt(block,offsetInBytes+2*(Integer.SIZE / Byte.SIZE)); + byte[] chunk = memStoreLAB.translateIdToChunk(chunkId).getData(); + + Cell result = new KeyValue(chunk, offsetOfCell, lengthOfCell); + return result; + } +} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOnHeap.java similarity index 66% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java rename to hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOnHeap.java index 332f09c0b25e..608edfef636f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOnHeap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOnHeap.java @@ -22,26 +22,26 @@ import org.apache.hadoop.hbase.Cell; import java.util.*; -import junit.framework.Assert; /** - * CellBlocksOnHeap is a simple array of Cells allocated using JVM. + * CellBlockOnHeap is a simple array of Cells allocated using JVM. * As all java arrays it is array of references pointing to Cell objects */ -public class CellBlocksOnHeap extends CellBlocks { +public class CellBlockOnHeap extends CellBlock { Cell block[]; - public CellBlocksOnHeap(Comparator comparator, Cell b[], int min, int max, - boolean d) { - super(comparator,min,max,d); + /* The Cells Array is created only when CellBlockOnHeap is created, all sub-CellBlocks use + * boundary indexes */ + public CellBlockOnHeap(Comparator comparator, Cell b[], int min, int max) { + super(comparator,min,max); this.block = b; } + /* To be used by base class only to create a sub-CellBlock */ @Override - protected CellBlocks createCellBlocks(Comparator comparator, int min, int max, - boolean d) { - return new CellBlocksOnHeap(comparator,this.block,min,max,d); + protected CellBlock createCellBlocks(Comparator comparator, int min, int max) { + return new CellBlockOnHeap(comparator,this.block,min,max); } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java deleted file mode 100644 index 542b217d1454..000000000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocks.java +++ /dev/null @@ -1,427 +0,0 @@ -/** - * - * 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, Cellersion 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 CellIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hbase.regionserver; - -import org.apache.hadoop.hbase.Cell; - -import java.util.*; -import java.util.concurrent.ConcurrentNavigableMap; - -/** - * CellBlocks stores a constant number of elements and is immutable after creation stage. - * Due to being immutable the CellBlocks can be implemented as array. - * The actual array is on- or off-heap and is implemented in concrete class derived from CellBlocks. - * The CellBlocks uses no synchronization primitives, it is assumed to be created by a - * single thread and then it can be read-only by multiple threads. - */ -public abstract class CellBlocks implements ConcurrentNavigableMap { - - private final Comparator comparator; - private int minCellIdx = 0; // the index of the minimal cell (for sub-sets) - private int maxCellIdx = 0; // the index of the maximal cell (for sub-sets) - private boolean isDescending = false; // array can be easily traversed backward in descending order - - /* C-tor */ - public CellBlocks(Comparator comparator, int min, int max, boolean d){ - this.comparator = comparator; - this.minCellIdx = min; - this.maxCellIdx = max; - this.isDescending = d; - } - - /* Used for abstract CellBlocks creation, implemented by derived class */ - protected abstract CellBlocks createCellBlocks(Comparator comparator, int min, - int max, boolean d); - - /* Assuming array underneath implementation this comes instead of array[i] */ - protected abstract Cell getCellFromIndex(int i); - - /** - * Binary search for a given key in between given boundaries of the array - * @param needle The key to look for in all of the entries - * @return Same return value as Arrays.binarySearch. - * Positive numbers mean the index. - * Otherwise (-1 * insertion point) - 1 - */ - private int find(Cell needle) { - int begin = minCellIdx; - int end = maxCellIdx - 1; - - while (begin <= end) { - int mid = begin + ((end - begin) / 2); - Cell midCell = getCellFromIndex(mid); - int compareRes = comparator.compare(midCell, needle); - - // 0 means equals. We found the key. - if (compareRes == 0) return mid; - else if (compareRes < 0) { - // midKey is less than needle so we need to look at farther up - begin = mid + 1; - } else { - // midKey is greater than needle so we need to look down - end = mid - 1; - } - } - - return (-1 * begin) - 1; - } - - @Override public Comparator comparator() { return comparator; } - - @Override public int size() { return maxCellIdx-minCellIdx; } - - @Override public boolean isEmpty() { return (maxCellIdx==minCellIdx); } - - - // ---------------- Sub-Maps ---------------- - @Override public ConcurrentNavigableMap subMap( Cell fromKey, - boolean fromInclusive, - Cell toKey, - boolean toInclusive) { - int toIndex = find(toKey); - if (toInclusive && toIndex >= 0) toIndex++; - else if (toIndex < 0) toIndex = -(toIndex + 1) - 1; - - int fromIndex = find(fromKey); - if (!fromInclusive && fromIndex >= 0) fromIndex++; - else if (fromIndex < 0) fromIndex = -(fromIndex + 1); - - return createCellBlocks(comparator, fromIndex, toIndex, false); - } - - @Override public ConcurrentNavigableMap headMap(Cell toKey, boolean inclusive) { - int index = find(toKey); - if (inclusive && index >= 0) index++; - else if (index < 0) index = -(index + 1) - 1; - return createCellBlocks(comparator, minCellIdx, index, false); - } - - @Override public ConcurrentNavigableMap tailMap(Cell fromKey, boolean inclusive) { - int index = find(fromKey); - if (!inclusive && index >= 0) index++; - else if (index < 0) index = -(index + 1); - return createCellBlocks(comparator, index, maxCellIdx, false); - } - - @Override public ConcurrentNavigableMap descendingMap() { - return createCellBlocks(comparator, minCellIdx, maxCellIdx, true); - } - - @Override public ConcurrentNavigableMap subMap(Cell k, Cell k1) { - return this.subMap(k, true, k1, true); - } - - @Override - public ConcurrentNavigableMap headMap(Cell k) { return this.headMap(k, true); } - - @Override - public ConcurrentNavigableMap tailMap(Cell k) { return this.tailMap(k, true); } - - - // -------------------------------- Key's getters -------------------------------- - @Override public Cell firstKey() { - if (isDescending) return lastKey(); - if (isEmpty()) return null; - return getCellFromIndex(minCellIdx); - } - - @Override public Cell lastKey() { - if (isDescending) return firstKey(); - if (isEmpty()) return null; - return getCellFromIndex(maxCellIdx-1); - } - - @Override public Cell lowerKey(Cell k) { - if (isDescending) return higherKey(k); - if (isEmpty()) return null; - int index = find(k); - if (index >= 0) index -= 1; // There's a key exactly equal. - else index = -(index + 1) - 1; - if (index < minCellIdx || index >= maxCellIdx) return null; - return getCellFromIndex(index); - } - - @Override public Cell floorKey(Cell k) { - if (isDescending) ceilingEntry(k); - if (isEmpty()) return null; - int index = find(k); - if (index < 0) index = -(index + 1) - 1; - if (index < minCellIdx || index >= maxCellIdx) return null; - return getCellFromIndex(index); - } - - @Override public Cell ceilingKey(Cell k) { - if (isDescending) return floorKey(k); - if (isEmpty()) return null; - int index = find(k); - if (index < 0) index = -(index + 1); - if (index < minCellIdx || index >= maxCellIdx) return null; - return getCellFromIndex(index); - } - - @Override public Cell higherKey(Cell k) { - if (isDescending) return lowerKey(k); - if (isEmpty()) return null; - int index = find(k); - if (index >= 0) index += 1; // There's a key exactly equal. - else index = -(index + 1); - if (index < minCellIdx || index >= maxCellIdx) return null; - return getCellFromIndex(index); - } - - @Override public boolean containsKey(Object o) { - int index = find((Cell) o); - return (index >= 0); - } - - @Override public boolean containsValue(Object o) { // use containsKey(Object o) instead - throw new UnsupportedOperationException(); - } - - @Override public Cell get(Object o) { - int index = find((Cell) o); - if (index >= 0) { - return getCellFromIndex(index); - } - return null; - } - - // -------------------------------- Entry's getters -------------------------------- - // all interfaces returning Entries are unsupported because we are dealing only with the keys - @Override - public Entry lowerEntry(Cell k) { throw new UnsupportedOperationException(); } - - @Override - public Entry higherEntry(Cell k) { throw new UnsupportedOperationException(); } - - @Override - public Entry ceilingEntry(Cell k) { throw new UnsupportedOperationException(); } - - @Override - public Entry floorEntry(Cell k) { throw new UnsupportedOperationException(); } - - @Override - public Entry firstEntry() { throw new UnsupportedOperationException(); } - - @Override - public Entry lastEntry() { throw new UnsupportedOperationException(); } - - @Override - public Entry pollFirstEntry() { throw new UnsupportedOperationException(); } - - @Override - public Entry pollLastEntry() { throw new UnsupportedOperationException(); } - - - // -------------------------------- Updates -------------------------------- - // All updating methods below are unsupported. - // Assuming an array of Cells will be allocated externally, - // fill up with Cells and provided in construction time. - // Later the structure is immutable. - @Override public Cell put(Cell k, Cell v) { throw new UnsupportedOperationException(); } - - @Override public void clear() { throw new UnsupportedOperationException(); } - - @Override public Cell remove(Object o) { throw new UnsupportedOperationException(); } - - @Override - public boolean replace(Cell k, Cell v, Cell v1) { throw new UnsupportedOperationException(); } - - @Override public void putAll(Map map) { - throw new UnsupportedOperationException(); - } - - @Override public Cell putIfAbsent(Cell k, Cell v) { throw new UnsupportedOperationException(); } - - @Override - public boolean remove(Object o, Object o1) { throw new UnsupportedOperationException(); } - - @Override public Cell replace(Cell k, Cell v) { throw new UnsupportedOperationException(); } - - - // -------------------------------- Sub-Sets -------------------------------- - @Override public NavigableSet navigableKeySet() { return new CellBlocksSet(); } - - @Override - public NavigableSet descendingKeySet() { throw new UnsupportedOperationException(); } - - @Override public NavigableSet keySet() { throw new UnsupportedOperationException(); } - - @Override public Collection values() { return new CellBlocksCollection(); } - - @Override public Set> entrySet() { throw new UnsupportedOperationException(); } - - - // -------------------------------- Iterator K -------------------------------- - private final class CellBlocksIterator implements Iterator { - int index = minCellIdx; - - private CellBlocksIterator(boolean d) { -// org.junit.Assert.assertTrue("\nInitializing Cell iterator, descending?:" + d + "\n",false); - - isDescending = d; - index = isDescending ? maxCellIdx-1 : minCellIdx; - } - - @Override - public boolean hasNext() { - return isDescending ? (index >= minCellIdx) : (index < maxCellIdx); - } - - @Override - public Cell next() { - Cell result = getCellFromIndex(index); - if (isDescending) index--; else index++; - return result; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - - // -------------------------------- Navigable Set -------------------------------- - private final class CellBlocksSet implements NavigableSet { - - @Override public Cell lower(Cell k) { return lowerKey(k); } - - @Override public Cell floor(Cell k) { return floorKey(k); } - - @Override public Cell ceiling(Cell k) { return ceilingKey(k); } - - @Override public Cell higher(Cell k) { return higherKey(k); } - - @Override public Cell first() { return firstKey(); } - - @Override public Cell last() { return lastKey(); } - - @Override public Cell pollFirst() { throw new UnsupportedOperationException(); } - - @Override public Cell pollLast() { throw new UnsupportedOperationException(); } - - @Override public int size() { return size(); } - - @Override public boolean isEmpty() { return isEmpty(); } - - @Override public void clear() { throw new UnsupportedOperationException(); } - - @Override public boolean contains(Object o) { return containsKey(o); } - - @Override public Comparator comparator() { return comparator; } - - @Override public Iterator iterator() { return new CellBlocksIterator(false); } - - @Override public Iterator descendingIterator() { return new CellBlocksIterator(true); } - - @Override public Object[] toArray() { throw new UnsupportedOperationException(); } - - @Override public T[] toArray(T[] ts) { throw new UnsupportedOperationException(); } - - @Override public boolean add(Cell k) { throw new UnsupportedOperationException(); } - - @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } - - @Override public boolean containsAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override public boolean addAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override public boolean retainAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override public boolean removeAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override public NavigableSet descendingSet() { throw new UnsupportedOperationException(); } - - @Override public SortedSet subSet(Cell k, Cell e1) { throw new UnsupportedOperationException(); } - - @Override public NavigableSet subSet(Cell k, boolean b, Cell e1, boolean b1) { - throw new UnsupportedOperationException(); - } - - @Override public NavigableSet headSet(Cell k, boolean b) { // headMap should be used instead - throw new UnsupportedOperationException(); - } - - @Override public NavigableSet tailSet(Cell k, boolean b) { // tailMap should be used instead - throw new UnsupportedOperationException(); - } - - @Override public SortedSet headSet(Cell k) { // headMap should be used instead - throw new UnsupportedOperationException(); - } - - @Override public SortedSet tailSet(Cell k) { // tailMap should be used instead - throw new UnsupportedOperationException(); - } - - - } - - // -------------------------------- Collection -------------------------------- - private final class CellBlocksCollection implements Collection { - - @Override public int size() { return size(); } - - @Override public boolean isEmpty() { return isEmpty(); } - - @Override public void clear() { throw new UnsupportedOperationException(); } - - @Override public boolean contains(Object o) { return containsKey(o); } - - @Override public Iterator iterator() { - return (isDescending) ? new CellBlocksIterator(true) : new CellBlocksIterator(false); - } - - @Override public Object[] toArray() { throw new UnsupportedOperationException(); } - - @Override public T[] toArray(T[] ts) { throw new UnsupportedOperationException(); } - - @Override public boolean add(Cell k) { throw new UnsupportedOperationException(); } - - @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } - - @Override public boolean containsAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override public boolean addAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override public boolean removeAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override public boolean retainAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - - } - -} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java deleted file mode 100644 index 0f68ecbd877c..000000000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlocksOffHeap.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * - * 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, Cellersion 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 CellIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hbase.regionserver; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.Cell; -import org.apache.hadoop.hbase.KeyValue; -import org.apache.hadoop.hbase.util.Bytes; - -import java.util.Comparator; -import junit.framework.Assert; - -/** - * CellBlocksOffHeap is a byte array holding all that is needed to access a Cell, which - * is actually saved on another deeper byte array - */ -public class CellBlocksOffHeap extends CellBlocks { - - private byte block[]; - private final HeapMemStoreLAB memStoreLAB; - - public CellBlocksOffHeap(Comparator comparator, HeapMemStoreLAB memStoreLAB, - byte b[], int min, int max, boolean d) { - super(comparator,min,max,d); - this.block = b; - this.memStoreLAB = memStoreLAB; - } - - @Override - protected CellBlocks createCellBlocks(Comparator comparator, int min, int max, - boolean d) { - return new CellBlocksOffHeap(comparator, this.memStoreLAB, this.block, min, max, d); - } - - @Override - protected Cell getCellFromIndex(int i) { -// org.junit.Assert.assertTrue("\nGetting Cell from index:" + i + "\n",false); - - int offsetInBytes = 3*i*(Integer.SIZE / Byte.SIZE); - -// org.junit.Assert.assertTrue("\n\nGetting Cell from index: " + i -// + ", offset to the start: " + offsetInBytes + ", the start of bytes array: " + block -// + "\n\n",false); - - int chunkId = Bytes.toInt(block,offsetInBytes); - int offsetOfCell = Bytes.toInt(block,offsetInBytes+(Integer.SIZE / Byte.SIZE)); - int lengthOfCell = Bytes.toInt(block,offsetInBytes+2*(Integer.SIZE / Byte.SIZE)); - byte[] chunk = memStoreLAB.translateIdToChunk(chunkId).getData(); - -// org.junit.Assert.assertTrue("\n\n<<<<<< Getting Cell from index: " + i -// + "(got deep chunk), offset to the start: " + offsetInBytes + ", the start of bytes array: " -// + block + ", the (deep) chunk id: " + chunkId + ", offset of cell in deep buffer: " -// + offsetOfCell + "\n\n",false); - - Cell result = new KeyValue(chunk, offsetOfCell, lengthOfCell); - return result; - } -} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellSet.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellSet.java index 443330283a18..875ca57b6b44 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellSet.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellSet.java @@ -59,7 +59,8 @@ public Cell ceiling(Cell e) { } public Iterator descendingIterator() { - return this.delegatee.descendingMap().values().iterator(); + return this.delegatee.navigableKeySet().descendingIterator(); + //return this.delegatee.descendingMap().values().iterator(); } public NavigableSet descendingSet() { diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java index ecaa5fcdcc7d..bc1a105d9deb 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java @@ -36,8 +36,8 @@ public class TestCellBlocksSet extends TestCase { private static final int NUM_OF_CELLS = 3; private Cell cells[]; - private CellBlocksOnHeap cbOnHeap; - private CellBlocksOffHeap cbOffHeap; + private CellBlockOnHeap cbOnHeap; + private CellBlockOffHeap cbOffHeap; private final static Configuration conf = new Configuration(); private HeapMemStoreLAB mslab; @@ -47,7 +47,7 @@ public class TestCellBlocksSet extends TestCase { protected void setUp() throws Exception { super.setUp(); - // create array of Cells to bass to the CellBlocks under CellSet + // create array of Cells to bass to the CellBlock under CellSet final byte[] one = Bytes.toBytes(1); final byte[] two = Bytes.toBytes(2); final byte[] three = Bytes.toBytes(3); @@ -60,25 +60,26 @@ protected void setUp() throws Exception { final KeyValue kv3 = new KeyValue(three, f, q, 30, v); cells = new Cell[] {kv1,kv2,kv3}; - cbOnHeap = new CellBlocksOnHeap(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS,false); + cbOnHeap = new CellBlockOnHeap(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS); conf.setBoolean(SegmentFactory.USEMSLAB_KEY, true); conf.setFloat(MemStoreChunkPool.CHUNK_POOL_MAXSIZE_KEY, 0.2f); MemStoreChunkPool.chunkPoolDisabled = false; mslab = new HeapMemStoreLAB(conf); - byte[] b = shallowCellsToBuffer(kv1, kv2, kv3); - cbOffHeap = new CellBlocksOffHeap(CellComparator.COMPARATOR, mslab, b, 0, NUM_OF_CELLS, false); + HeapMemStoreLAB.Chunk[] c = shallowCellsToBuffer(kv1, kv2, kv3); + int chunkSize = conf.getInt(HeapMemStoreLAB.CHUNK_SIZE_KEY, HeapMemStoreLAB.CHUNK_SIZE_DEFAULT); + cbOffHeap = new CellBlockOffHeap(CellComparator.COMPARATOR, mslab, c, 0, NUM_OF_CELLS, chunkSize); } - /* Create and test CellSet based on CellBlocksOnHeap */ + /* Create and test CellSet based on CellBlockOnHeap */ public void testCellBlocksOnHeap() throws Exception { CellSet cs = new CellSet(cbOnHeap); testCellBlocks(cs); testIterators(cs); } - /* Create and test CellSet based on CellBlocksOffHeap */ + /* Create and test CellSet based on CellBlockOffHeap */ public void testCellBlocksOffHeap() throws Exception { CellSet cs = new CellSet(cbOffHeap); testCellBlocks(cs); @@ -140,21 +141,22 @@ private void testIterators(CellSet cs) throws Exception { } /* Create byte array holding shallow Cells referencing to the deep Cells data */ - private byte[] shallowCellsToBuffer(Cell kv1, Cell kv2, Cell kv3) { + private HeapMemStoreLAB.Chunk[] shallowCellsToBuffer(Cell kv1, Cell kv2, Cell kv3) { HeapMemStoreLAB.Chunk chunkD = mslab.allocateChunk(); HeapMemStoreLAB.Chunk chunkS = mslab.allocateChunk(); + HeapMemStoreLAB.Chunk result[] = {chunkS}; byte[] deepBuffer = chunkD.getData(); byte[] shallowBuffer = chunkS.getData(); int offset = 0; int pos = offset; -// assertTrue("\n\n<<<<< Preparing for CellBlocksOffHeap, shallow chunk: " + chunkS +// assertTrue("\n\n<<<<< Preparing for CellBlockOffHeap, shallow chunk: " + chunkS // + " has index: " + chunkS.getId() + " \n\n", false); KeyValueUtil.appendToByteArray(kv1, deepBuffer, offset); // write deep cell data -// assertTrue("\n\n<<<<< Preparing for CellBlocksOffHeap, shallow chunk: " + chunkS +// assertTrue("\n\n<<<<< Preparing for CellBlockOffHeap, shallow chunk: " + chunkS // + " has index: " + chunkS.getId() + ", deep chunk: " + chunkD // + " has index: " + chunkD.getId() + "\n\n", false); @@ -174,6 +176,6 @@ private byte[] shallowCellsToBuffer(Cell kv1, Cell kv2, Cell kv3) { pos = Bytes.putInt(shallowBuffer, pos, offset); // offset pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv3)); // length - return shallowBuffer; + return result; } } From 70184fbb68969065f3455012b248abe1aeefa19a Mon Sep 17 00:00:00 2001 From: anastas Date: Thu, 17 Mar 2016 11:13:24 +0200 Subject: [PATCH 08/11] After Code Review and Bug Fixes --- .../apache/hadoop/hbase/regionserver/CellBlock.java | 10 ++++++++-- .../hadoop/hbase/regionserver/TestCellBlocksSet.java | 10 +++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java index c9d694cb4d8e..6ffbbb75c1c1 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java @@ -28,6 +28,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentNavigableMap; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * CellBlock stores a constant number of elements and is immutable after creation stage. @@ -113,7 +115,7 @@ public ConcurrentNavigableMap subMap( Cell fromKey, Cell toKey, boolean toInclusive) { int toIndex = getValidIndex(toKey, toInclusive); - int fromIndex = (getValidIndex(fromKey, !fromInclusive))-1; + int fromIndex = (getValidIndex(fromKey, !fromInclusive)); if (fromIndex > toIndex) throw new IllegalArgumentException("inconsistent range"); return createCellBlocks(comparator, fromIndex, toIndex); @@ -127,7 +129,11 @@ public ConcurrentNavigableMap headMap(Cell toKey, boolean inclusive) @Override public ConcurrentNavigableMap tailMap(Cell fromKey, boolean inclusive) { - int index = (getValidIndex(fromKey, !inclusive))-1; + int index = (getValidIndex(fromKey, !inclusive)); + +// assertTrue("\n\n<<<<<<<<<<<< Getting tailMap from index: " + index +// + ", inclusive?:" + inclusive + "; the cell: " + fromKey.toString() + "\n\n",false); + return createCellBlocks(comparator, index, maxCellIdx); } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java index bc1a105d9deb..f7981007e4e5 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java @@ -80,11 +80,11 @@ public void testCellBlocksOnHeap() throws Exception { } /* Create and test CellSet based on CellBlockOffHeap */ - public void testCellBlocksOffHeap() throws Exception { - CellSet cs = new CellSet(cbOffHeap); - testCellBlocks(cs); - testIterators(cs); - } +// public void testCellBlocksOffHeap() throws Exception { +// CellSet cs = new CellSet(cbOffHeap); +// testCellBlocks(cs); +// testIterators(cs); +// } /* Generic basic test for immutable CellSet */ private void testCellBlocks(CellSet cs) throws Exception { From 1f0be6c741bb5bec2d77bd81165f2894055b58fc Mon Sep 17 00:00:00 2001 From: anastas Date: Thu, 17 Mar 2016 22:29:11 +0200 Subject: [PATCH 09/11] intermediate --- .../hadoop/hbase/regionserver/CellBlock.java | 177 ++++-------------- .../hbase/regionserver/CellBlockOffHeap.java | 9 +- .../hbase/regionserver/CellBlockOnHeap.java | 10 +- .../hadoop/hbase/regionserver/CellSet.java | 3 +- .../hbase/regionserver/HeapMemStoreLAB.java | 4 +- .../hbase/regionserver/TestCellBlocksSet.java | 15 +- 6 files changed, 63 insertions(+), 155 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java index 6ffbbb75c1c1..da097f672c4b 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java @@ -43,18 +43,19 @@ public abstract class CellBlock implements ConcurrentNavigableMap { private final Comparator comparator; private int minCellIdx = 0; // the index of the minimal cell (for sub-sets) private int maxCellIdx = 0; // the index of the maximal cell (for sub-sets) - + private boolean descending = false; /* C-tor */ - public CellBlock(Comparator comparator, int min, int max){ + public CellBlock(Comparator comparator, int min, int max, boolean d){ this.comparator = comparator; this.minCellIdx = min; this.maxCellIdx = max; + this.descending = d; } /* Used for abstract CellBlock creation, implemented by derived class */ protected abstract CellBlock createCellBlocks(Comparator comparator, int min, - int max); + int max, boolean descending); /* Returns the i-th cell in the cell block */ protected abstract Cell getCellFromIndex(int i); @@ -118,13 +119,13 @@ public ConcurrentNavigableMap subMap( Cell fromKey, int fromIndex = (getValidIndex(fromKey, !fromInclusive)); if (fromIndex > toIndex) throw new IllegalArgumentException("inconsistent range"); - return createCellBlocks(comparator, fromIndex, toIndex); + return createCellBlocks(comparator, fromIndex, toIndex, descending); } @Override public ConcurrentNavigableMap headMap(Cell toKey, boolean inclusive) { int index = getValidIndex(toKey, inclusive); - return createCellBlocks(comparator, minCellIdx, index); + return createCellBlocks(comparator, minCellIdx, index, descending); } @Override @@ -134,12 +135,12 @@ public ConcurrentNavigableMap tailMap(Cell fromKey, boolean inclusiv // assertTrue("\n\n<<<<<<<<<<<< Getting tailMap from index: " + index // + ", inclusive?:" + inclusive + "; the cell: " + fromKey.toString() + "\n\n",false); - return createCellBlocks(comparator, index, maxCellIdx); + return createCellBlocks(comparator, index, maxCellIdx, descending); } @Override public ConcurrentNavigableMap descendingMap() { - return createCellBlocks(comparator, minCellIdx, maxCellIdx); + return createCellBlocks(comparator, minCellIdx, maxCellIdx, true); } @Override @@ -158,12 +159,14 @@ public ConcurrentNavigableMap subMap(Cell k1, Cell k2) { @Override public Cell firstKey() { if (isEmpty()) return null; + if (descending) getCellFromIndex(maxCellIdx-1); return getCellFromIndex(minCellIdx); } @Override public Cell lastKey() { if (isEmpty()) return null; + if (descending) return getCellFromIndex(minCellIdx); return getCellFromIndex(maxCellIdx-1); } @@ -171,8 +174,13 @@ public Cell lastKey() { public Cell lowerKey(Cell k) { if (isEmpty()) return null; int index = find(k); - if (index >= 0) index -= 1; // There's a key exactly equal. - else index = -(index + 1) - 1; + if (descending) { + if (index >= 0) index++; // There's a key exactly equal. + else index = -(index + 1); + } else { + if (index >= 0) index--; // There's a key exactly equal. + else index = -(index + 1) - 1; + } return (index < minCellIdx || index >= maxCellIdx) ? null : getCellFromIndex(index); } @@ -180,7 +188,11 @@ public Cell lowerKey(Cell k) { public Cell floorKey(Cell k) { if (isEmpty()) return null; int index = find(k); - if (index < 0) index = -(index + 1) - 1; + if (descending) { + if (index < 0) index = -(index + 1); + } else { + if (index < 0) index = -(index + 1) - 1; + } return (index < minCellIdx || index >= maxCellIdx) ? null : getCellFromIndex(index); } @@ -188,7 +200,11 @@ public Cell floorKey(Cell k) { public Cell ceilingKey(Cell k) { if (isEmpty()) return null; int index = find(k); - if (index < 0) index = -(index + 1); + if (descending) { + if (index < 0) index = -(index + 1) - 1; + } else { + if (index < 0) index = -(index + 1); + } return (index < minCellIdx || index >= maxCellIdx) ? null : getCellFromIndex(index); } @@ -196,8 +212,13 @@ public Cell ceilingKey(Cell k) { public Cell higherKey(Cell k) { if (isEmpty()) return null; int index = find(k); - if (index >= 0) index++; // There's a key exactly equal. - else index = -(index + 1); + if (descending) { + if (index >= 0) index--; // There's a key exactly equal. + else index = -(index + 1) - 1; + } else { + if (index >= 0) index++; // There's a key exactly equal. + else index = -(index + 1); + } return (index < minCellIdx || index >= maxCellIdx) ? null : getCellFromIndex(index); } @@ -282,7 +303,7 @@ public void putAll(Map map) { // -------------------------------- Sub-Sets -------------------------------- @Override - public NavigableSet navigableKeySet() { return new CellBlocksSet(); } + public NavigableSet navigableKeySet() { throw new UnsupportedOperationException(); } @Override public NavigableSet descendingKeySet() { throw new UnsupportedOperationException(); } @@ -299,23 +320,21 @@ public void putAll(Map map) { // -------------------------------- Iterator K -------------------------------- private final class CellBlocksIterator implements Iterator { - int index = minCellIdx; - boolean isDescending = false; + int index; - private CellBlocksIterator(boolean d) { - isDescending = d; - index = d ? maxCellIdx-1 : minCellIdx; + private CellBlocksIterator() { + index = descending ? maxCellIdx-1 : minCellIdx; } @Override public boolean hasNext() { - return isDescending ? (index >= minCellIdx) : (index < maxCellIdx); + return descending ? (index >= minCellIdx) : (index < maxCellIdx); } @Override public Cell next() { Cell result = getCellFromIndex(index); - if (isDescending) index--; else index++; + if (descending) index--; else index++; return result; } @@ -326,120 +345,6 @@ public void remove() { } - // -------------------------------- Navigable Set -------------------------------- - private final class CellBlocksSet implements NavigableSet { - - @Override - public Cell lower(Cell k) { return lowerKey(k); } - - @Override - public Cell floor(Cell k) { return floorKey(k); } - - @Override - public Cell ceiling(Cell k) { return ceilingKey(k); } - - @Override - public Cell higher(Cell k) { return higherKey(k); } - - @Override - public Cell first() { return firstKey(); } - - @Override - public Cell last() { return lastKey(); } - - @Override - public Cell pollFirst() { throw new UnsupportedOperationException(); } - - @Override - public Cell pollLast() { throw new UnsupportedOperationException(); } - - @Override - public int size() { return size(); } - - @Override - public boolean isEmpty() { return isEmpty(); } - - @Override - public void clear() { throw new UnsupportedOperationException(); } - - @Override - public boolean contains(Object o) { return containsKey(o); } - - @Override - public Comparator comparator() { return comparator; } - - @Override - public Iterator iterator() { return new CellBlocksIterator(false); } - - @Override - public Iterator descendingIterator() { return new CellBlocksIterator(true); } - - @Override - public Object[] toArray() { throw new UnsupportedOperationException(); } - - @Override - public T[] toArray(T[] ts) { throw new UnsupportedOperationException(); } - - @Override - public boolean add(Cell k) { throw new UnsupportedOperationException(); } - - @Override - public boolean remove(Object o) { throw new UnsupportedOperationException(); } - - @Override - public boolean containsAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean addAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean retainAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeAll(Collection collection) { - throw new UnsupportedOperationException(); - } - - @Override - public NavigableSet descendingSet() { throw new UnsupportedOperationException(); } - - @Override - public SortedSet subSet(Cell k, Cell e1) { throw new UnsupportedOperationException(); } - - @Override - public NavigableSet subSet(Cell k, boolean b, Cell e1, boolean b1) { - throw new UnsupportedOperationException(); - } - - @Override - public NavigableSet headSet(Cell k, boolean b) { // headMap should be used instead - throw new UnsupportedOperationException(); - } - - @Override - public NavigableSet tailSet(Cell k, boolean b) { // tailMap should be used instead - throw new UnsupportedOperationException(); - } - - @Override - public SortedSet headSet(Cell k) { // headMap should be used instead - throw new UnsupportedOperationException(); - } - - @Override - public SortedSet tailSet(Cell k) { // tailMap should be used instead - throw new UnsupportedOperationException(); - } - - - } - // -------------------------------- Collection -------------------------------- private final class CellBlocksCollection implements Collection { @@ -457,7 +362,7 @@ private final class CellBlocksCollection implements Collection { @Override public Iterator iterator() { - return new CellBlocksIterator(false); + return new CellBlocksIterator(); } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java index fd6970d0c7c1..1e963ee3e08b 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java @@ -49,8 +49,8 @@ public class CellBlockOffHeap extends CellBlock { private final int bytesInCell = 3*(Integer.SIZE / Byte.SIZE); // each Cell requires 3 integers public CellBlockOffHeap(Comparator comparator, HeapMemStoreLAB memStoreLAB, - HeapMemStoreLAB.Chunk chunks[], int min, int max, int chunkSize) { - super(comparator,min,max); + HeapMemStoreLAB.Chunk chunks[], int min, int max, int chunkSize, boolean d) { + super(comparator,min,max, d); this.chunks = chunks; this.memStoreLAB = memStoreLAB; this.numOfCellsInsideChunk = chunkSize / bytesInCell; @@ -58,9 +58,10 @@ public CellBlockOffHeap(Comparator comparator, HeapMemStoreLAB mem /* To be used by base class only to create a sub-CellBlock */ @Override - protected CellBlock createCellBlocks(Comparator comparator, int min, int max) { + protected CellBlock createCellBlocks(Comparator comparator, + int min, int max, boolean d) { return new CellBlockOffHeap(comparator, this.memStoreLAB, this.chunks, min, max, - this.numOfCellsInsideChunk*bytesInCell); + this.numOfCellsInsideChunk*bytesInCell, d); } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOnHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOnHeap.java index 608edfef636f..afa596b70758 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOnHeap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOnHeap.java @@ -33,15 +33,17 @@ public class CellBlockOnHeap extends CellBlock { /* The Cells Array is created only when CellBlockOnHeap is created, all sub-CellBlocks use * boundary indexes */ - public CellBlockOnHeap(Comparator comparator, Cell b[], int min, int max) { - super(comparator,min,max); + public CellBlockOnHeap(Comparator comparator, Cell b[], + int min, int max, boolean d) { + super(comparator,min,max,d); this.block = b; } /* To be used by base class only to create a sub-CellBlock */ @Override - protected CellBlock createCellBlocks(Comparator comparator, int min, int max) { - return new CellBlockOnHeap(comparator,this.block,min,max); + protected CellBlock createCellBlocks(Comparator comparator, + int min, int max, boolean d) { + return new CellBlockOnHeap(comparator,this.block,min,max,d); } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellSet.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellSet.java index 875ca57b6b44..443330283a18 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellSet.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellSet.java @@ -59,8 +59,7 @@ public Cell ceiling(Cell e) { } public Iterator descendingIterator() { - return this.delegatee.navigableKeySet().descendingIterator(); - //return this.delegatee.descendingMap().values().iterator(); + return this.delegatee.descendingMap().values().iterator(); } public NavigableSet descendingSet() { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java index f245cbe5586d..7c8295a5c3a1 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java @@ -190,8 +190,8 @@ private Chunk getOrMakeChunk() { // No current chunk, so we want to allocate one. We race // against other allocators to CAS in an uninitialized chunk // (which is cheap to allocate) - //c = (chunkPool != null) ? chunkPool.getChunk() : new Chunk(chunkSize); 14921 - c = chunkPool.getChunk(); // 14921 + c = (chunkPool != null) ? chunkPool.getChunk() : new Chunk(chunkSize, 5); //14921 + //c = chunkPool.getChunk(); // 14921 if (curChunk.compareAndSet(null, c)) { // we won race - now we need to actually do the expensive // allocation step diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java index f7981007e4e5..1bb3b7e73b0f 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java @@ -60,7 +60,7 @@ protected void setUp() throws Exception { final KeyValue kv3 = new KeyValue(three, f, q, 30, v); cells = new Cell[] {kv1,kv2,kv3}; - cbOnHeap = new CellBlockOnHeap(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS); + cbOnHeap = new CellBlockOnHeap(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS,false); conf.setBoolean(SegmentFactory.USEMSLAB_KEY, true); conf.setFloat(MemStoreChunkPool.CHUNK_POOL_MAXSIZE_KEY, 0.2f); @@ -69,7 +69,8 @@ protected void setUp() throws Exception { HeapMemStoreLAB.Chunk[] c = shallowCellsToBuffer(kv1, kv2, kv3); int chunkSize = conf.getInt(HeapMemStoreLAB.CHUNK_SIZE_KEY, HeapMemStoreLAB.CHUNK_SIZE_DEFAULT); - cbOffHeap = new CellBlockOffHeap(CellComparator.COMPARATOR, mslab, c, 0, NUM_OF_CELLS, chunkSize); + cbOffHeap = new CellBlockOffHeap(CellComparator.COMPARATOR, mslab, + c, 0, NUM_OF_CELLS, chunkSize, false); } /* Create and test CellSet based on CellBlockOnHeap */ @@ -80,11 +81,11 @@ public void testCellBlocksOnHeap() throws Exception { } /* Create and test CellSet based on CellBlockOffHeap */ -// public void testCellBlocksOffHeap() throws Exception { -// CellSet cs = new CellSet(cbOffHeap); -// testCellBlocks(cs); -// testIterators(cs); -// } + public void testCellBlocksOffHeap() throws Exception { + CellSet cs = new CellSet(cbOffHeap); + testCellBlocks(cs); + testIterators(cs); + } /* Generic basic test for immutable CellSet */ private void testCellBlocks(CellSet cs) throws Exception { From 8e4c571174017fbbc13db59a93523477fc83610a Mon Sep 17 00:00:00 2001 From: anastas Date: Mon, 21 Mar 2016 10:16:45 +0200 Subject: [PATCH 10/11] Passing regression --- .../hadoop/hbase/regionserver/CellBlock.java | 6 ++-- .../hbase/regionserver/CellBlockOffHeap.java | 2 +- .../hbase/regionserver/HeapMemStoreLAB.java | 36 +++++++++++++------ .../hbase/regionserver/MemStoreChunkPool.java | 7 ++-- .../hbase/regionserver/TestCellBlocksSet.java | 10 +----- 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java index da097f672c4b..f664c5dc0582 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java @@ -75,7 +75,9 @@ private int find(Cell needle) { while (begin <= end) { int mid = begin + ((end - begin) / 2); + Cell midCell = getCellFromIndex(mid); + int compareRes = comparator.compare(midCell, needle); // 0 means equals. We found the key. @@ -131,10 +133,6 @@ public ConcurrentNavigableMap headMap(Cell toKey, boolean inclusive) @Override public ConcurrentNavigableMap tailMap(Cell fromKey, boolean inclusive) { int index = (getValidIndex(fromKey, !inclusive)); - -// assertTrue("\n\n<<<<<<<<<<<< Getting tailMap from index: " + index -// + ", inclusive?:" + inclusive + "; the cell: " + fromKey.toString() + "\n\n",false); - return createCellBlocks(comparator, index, maxCellIdx, descending); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java index 1e963ee3e08b..b0c2b6701c00 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java @@ -72,7 +72,7 @@ protected Cell getCellFromIndex(int i) { i = i - chunkIndex*numOfCellsInsideChunk; // find inside chunk - int offsetInBytes = 3*i*(Integer.SIZE / Byte.SIZE); + int offsetInBytes = i*bytesInCell; int chunkId = Bytes.toInt(block,offsetInBytes); int offsetOfCell = Bytes.toInt(block,offsetInBytes+(Integer.SIZE / Byte.SIZE)); int lengthOfCell = Bytes.toInt(block,offsetInBytes+2*(Integer.SIZE / Byte.SIZE)); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java index 7c8295a5c3a1..f673d314b8ee 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java @@ -30,6 +30,7 @@ import org.apache.hadoop.hbase.util.SimpleMutableByteRange; import com.google.common.base.Preconditions; +import static org.junit.Assert.assertTrue; /** * A memstore-local allocation buffer. @@ -109,9 +110,9 @@ public ByteRange allocateBytes(int size) { } while (true) { - Chunk c = getOrMakeChunk(); + Chunk c = getOrMakeChunk(size); - // Try to allocate from this chunk + // Try to allocate from this chunk int allocOffset = c.alloc(size); if (allocOffset != -1) { // We succeeded - this is the common case - small alloc @@ -178,8 +179,10 @@ private void tryRetireChunk(Chunk c) { /** * Get the current chunk, or, if there is no current chunk, * allocate a new one from the JVM. + * @param size */ - private Chunk getOrMakeChunk() { + private Chunk getOrMakeChunk(int size) { + while (true) { // Try to get the chunk Chunk c = curChunk.get(); @@ -190,12 +193,21 @@ private Chunk getOrMakeChunk() { // No current chunk, so we want to allocate one. We race // against other allocators to CAS in an uninitialized chunk // (which is cheap to allocate) - c = (chunkPool != null) ? chunkPool.getChunk() : new Chunk(chunkSize, 5); //14921 - //c = chunkPool.getChunk(); // 14921 + + //c = (chunkPool != null) ? chunkPool.getChunk() : new Chunk(chunkSize, 5); //14921 + + if(chunkPool != null) { + c = chunkPool.getChunk(); + } else { + c = new Chunk(chunkSize, 5); + c.init(); + } + if (curChunk.compareAndSet(null, c)) { // we won race - now we need to actually do the expensive // allocation step - // c.init(); 14921 + + //c.init(); //14921 this.chunkQueue.add(c); return c; } else if (chunkPool != null) { @@ -245,7 +257,7 @@ static class Chunk { /** Size of chunk in bytes */ private final int size; - /* A unique identifier of a chunk inside MemStoreChunkPool */ + /* 14921: A unique identifier of a chunk inside MemStoreChunkPool */ private final int id; /* Chunk's index serves as replacement for pointer */ @@ -276,13 +288,15 @@ public void init() { assert failInit; // should be true. throw e; } + // Mark that it's ready for use boolean initted = nextFreeOffset.compareAndSet( UNINITIALIZED, 0); // We should always succeed the above CAS since only one thread // calls init()! - Preconditions.checkState(initted, - "Multiple threads tried to init same chunk"); + Preconditions.checkState(initted, "Multiple threads tried to init same chunk"); + + //org.junit.Assert.assertTrue("\n\n inside chunk initialization 3", false); } /** @@ -338,10 +352,10 @@ public String toString() { public int getId() { return id; - } + } // 14921 public byte[] getData() { return data; - } + } // 14921 } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java index 32fbd748025d..9753981bc379 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java @@ -73,8 +73,9 @@ public class MemStoreChunkPool { private static final int statThreadPeriod = 60 * 5; private AtomicLong createdChunkCount = new AtomicLong(); private AtomicLong reusedChunkCount = new AtomicLong(); + private AtomicInteger chunkIDs = new AtomicInteger(1); // 14921 - // IDs Mapping of all chunks (key 0 is forbidden) + // 14921: IDs Mapping of all chunks (key 0 is forbidden) private final ConcurrentMap chunksMap = new ConcurrentHashMap(); MemStoreChunkPool(Configuration conf, int chunkSize, int maxCount, @@ -85,7 +86,6 @@ public class MemStoreChunkPool { for (int i = 0; i < initialCount; i++) { Chunk chunk = allocateChunk(); - reclaimedChunks.add(chunk); } final String n = Thread.currentThread().getName(); @@ -108,6 +108,7 @@ Chunk getChunk() { createdChunkCount.incrementAndGet(); } else { chunk.reset(); + chunk.init(); // 14921 reusedChunkCount.incrementAndGet(); } return chunk; @@ -168,7 +169,7 @@ ConcurrentMap getChunksMap() { * Allocate and register Chunk */ private Chunk allocateChunk() { - int newId = chunksMap.size() + 1; // the number of the new chunk + int newId = chunkIDs.getAndAdd(1); // the number of the new chunk Chunk chunk = new Chunk(chunkSize,newId); chunksMap.put(newId, chunk); chunk.init(); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java index 1bb3b7e73b0f..f37af2536fa8 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java @@ -91,7 +91,7 @@ public void testCellBlocksOffHeap() throws Exception { private void testCellBlocks(CellSet cs) throws Exception { assertEquals(NUM_OF_CELLS, cs.size()); // check size - assertTrue(cs.contains(cells[0])); // check first + assertTrue(cs.contains(cells[0])); // check existance of the first Cell first = cs.first(); assertTrue(cells[0].equals(first)); @@ -151,16 +151,8 @@ private HeapMemStoreLAB.Chunk[] shallowCellsToBuffer(Cell kv1, Cell kv2, Cell kv byte[] shallowBuffer = chunkS.getData(); int offset = 0; int pos = offset; - -// assertTrue("\n\n<<<<< Preparing for CellBlockOffHeap, shallow chunk: " + chunkS -// + " has index: " + chunkS.getId() + " \n\n", false); - KeyValueUtil.appendToByteArray(kv1, deepBuffer, offset); // write deep cell data -// assertTrue("\n\n<<<<< Preparing for CellBlockOffHeap, shallow chunk: " + chunkS -// + " has index: " + chunkS.getId() + ", deep chunk: " + chunkD -// + " has index: " + chunkD.getId() + "\n\n", false); - pos = Bytes.putInt(shallowBuffer, pos, chunkD.getId()); // write deep chunk index pos = Bytes.putInt(shallowBuffer, pos, offset); // offset pos = Bytes.putInt(shallowBuffer, pos, KeyValueUtil.length(kv1)); // length From d570bc466df26eaf67ed9bbba5994375b29d36b2 Mon Sep 17 00:00:00 2001 From: anastas Date: Tue, 22 Mar 2016 13:21:44 +0200 Subject: [PATCH 11/11] Some code style fixes --- .../hadoop/hbase/regionserver/CellBlock.java | 150 +++++++++++++----- ...kOnHeap.java => CellBlockObjectArray.java} | 17 +- ...kOffHeap.java => CellBlockSerialized.java} | 23 +-- .../hbase/regionserver/HeapMemStoreLAB.java | 7 +- .../hbase/regionserver/MemStoreChunkPool.java | 9 +- .../hbase/regionserver/TestCellBlocksSet.java | 12 +- 6 files changed, 145 insertions(+), 73 deletions(-) rename hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/{CellBlockOnHeap.java => CellBlockObjectArray.java} (74%) rename hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/{CellBlockOffHeap.java => CellBlockSerialized.java} (80%) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java index f664c5dc0582..6403a5266f1f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlock.java @@ -22,14 +22,13 @@ import java.util.Collection; import java.util.Comparator; +import java.util.concurrent.ConcurrentNavigableMap; import java.util.Iterator; -import java.util.NavigableSet; -import java.util.SortedSet; import java.util.Map; +import java.util.NavigableSet; import java.util.Set; -import java.util.concurrent.ConcurrentNavigableMap; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; + + /** * CellBlock stores a constant number of elements and is immutable after creation stage. @@ -61,13 +60,13 @@ protected abstract CellBlock createCellBlocks(Comparator comparato protected abstract Cell getCellFromIndex(int i); /** - * Binary search for a given key in between given boundaries of the array - * @param needle The key to look for in all of the entries - * @return Same return value as Arrays.binarySearch. + * Binary search for a given key in between given boundaries of the array. * Positive returned numbers mean the index. * Negative returned numbers means the key not found. * The absolute value of the output is the * possible insert index for the searched key: (-1 * insertion point) - 1 + * @param needle The key to look for in all of the entries + * @return Same return value as Arrays.binarySearch. */ private int find(Cell needle) { int begin = minCellIdx; @@ -102,13 +101,19 @@ private int getValidIndex(Cell key, boolean inclusive) { } @Override - public Comparator comparator() { return comparator; } + public Comparator comparator() { + return comparator; + } @Override - public int size() { return maxCellIdx-minCellIdx; } + public int size() { + return maxCellIdx-minCellIdx; + } @Override - public boolean isEmpty() { return (maxCellIdx==minCellIdx); } + public boolean isEmpty() { + return (maxCellIdx==minCellIdx); + } // ---------------- Sub-Maps ---------------- @@ -147,10 +152,14 @@ public ConcurrentNavigableMap subMap(Cell k1, Cell k2) { } @Override - public ConcurrentNavigableMap headMap(Cell k) { return this.headMap(k, true); } + public ConcurrentNavigableMap headMap(Cell k) { + return this.headMap(k, true); + } @Override - public ConcurrentNavigableMap tailMap(Cell k) { return this.tailMap(k, true); } + public ConcurrentNavigableMap tailMap(Cell k) { + return this.tailMap(k, true); + } // -------------------------------- Key's getters -------------------------------- @@ -243,28 +252,44 @@ public Cell get(Object o) { // -------------------------------- Entry's getters -------------------------------- // all interfaces returning Entries are unsupported because we are dealing only with the keys @Override - public Entry lowerEntry(Cell k) { throw new UnsupportedOperationException(); } + public Entry lowerEntry(Cell k) { + throw new UnsupportedOperationException(); + } @Override - public Entry higherEntry(Cell k) { throw new UnsupportedOperationException(); } + public Entry higherEntry(Cell k) { + throw new UnsupportedOperationException(); + } @Override - public Entry ceilingEntry(Cell k) { throw new UnsupportedOperationException(); } + public Entry ceilingEntry(Cell k) { + throw new UnsupportedOperationException(); + } @Override - public Entry floorEntry(Cell k) { throw new UnsupportedOperationException(); } + public Entry floorEntry(Cell k) { + throw new UnsupportedOperationException(); + } @Override - public Entry firstEntry() { throw new UnsupportedOperationException(); } + public Entry firstEntry() { + throw new UnsupportedOperationException(); + } @Override - public Entry lastEntry() { throw new UnsupportedOperationException(); } + public Entry lastEntry() { + throw new UnsupportedOperationException(); + } @Override - public Entry pollFirstEntry() { throw new UnsupportedOperationException(); } + public Entry pollFirstEntry() { + throw new UnsupportedOperationException(); + } @Override - public Entry pollLastEntry() { throw new UnsupportedOperationException(); } + public Entry pollLastEntry() { + throw new UnsupportedOperationException(); + } // -------------------------------- Updates -------------------------------- @@ -273,16 +298,24 @@ public Cell get(Object o) { // fill up with Cells and provided in construction time. // Later the structure is immutable. @Override - public Cell put(Cell k, Cell v) { throw new UnsupportedOperationException(); } + public Cell put(Cell k, Cell v) { + throw new UnsupportedOperationException(); + } @Override - public void clear() { throw new UnsupportedOperationException(); } + public void clear() { + throw new UnsupportedOperationException(); + } @Override - public Cell remove(Object o) { throw new UnsupportedOperationException(); } + public Cell remove(Object o) { + throw new UnsupportedOperationException(); + } @Override - public boolean replace(Cell k, Cell v, Cell v1) { throw new UnsupportedOperationException(); } + public boolean replace(Cell k, Cell v, Cell v1) { + throw new UnsupportedOperationException(); + } @Override public void putAll(Map map) { @@ -290,30 +323,46 @@ public void putAll(Map map) { } @Override - public Cell putIfAbsent(Cell k, Cell v) { throw new UnsupportedOperationException(); } + public Cell putIfAbsent(Cell k, Cell v) { + throw new UnsupportedOperationException(); + } @Override - public boolean remove(Object o, Object o1) { throw new UnsupportedOperationException(); } + public boolean remove(Object o, Object o1) { + throw new UnsupportedOperationException(); + } @Override - public Cell replace(Cell k, Cell v) { throw new UnsupportedOperationException(); } + public Cell replace(Cell k, Cell v) { + throw new UnsupportedOperationException(); + } // -------------------------------- Sub-Sets -------------------------------- @Override - public NavigableSet navigableKeySet() { throw new UnsupportedOperationException(); } + public NavigableSet navigableKeySet() { + throw new UnsupportedOperationException(); + } @Override - public NavigableSet descendingKeySet() { throw new UnsupportedOperationException(); } + public NavigableSet descendingKeySet() { + throw new UnsupportedOperationException(); + } @Override - public NavigableSet keySet() { throw new UnsupportedOperationException(); } + public NavigableSet keySet() { + throw new UnsupportedOperationException(); + } @Override - public Collection values() { return new CellBlocksCollection(); } + public Collection values() { + return new CellBlocksCollection(); + } @Override - public Set> entrySet() { throw new UnsupportedOperationException(); } + public Set> entrySet() { + throw new UnsupportedOperationException(); + } // -------------------------------- Iterator K -------------------------------- @@ -332,7 +381,8 @@ public boolean hasNext() { @Override public Cell next() { Cell result = getCellFromIndex(index); - if (descending) index--; else index++; + if (descending) index--; + else index++; return result; } @@ -347,16 +397,24 @@ public void remove() { private final class CellBlocksCollection implements Collection { @Override - public int size() { return size(); } + public int size() { + return CellBlock.this.size(); + } @Override - public boolean isEmpty() { return isEmpty(); } + public boolean isEmpty() { + return CellBlock.this.isEmpty(); + } @Override - public void clear() { throw new UnsupportedOperationException(); } + public void clear() { + throw new UnsupportedOperationException(); + } @Override - public boolean contains(Object o) { return containsKey(o); } + public boolean contains(Object o) { + return containsKey(o); + } @Override public Iterator iterator() { @@ -364,16 +422,24 @@ public Iterator iterator() { } @Override - public Object[] toArray() { throw new UnsupportedOperationException(); } + public Object[] toArray() { + throw new UnsupportedOperationException(); + } @Override - public T[] toArray(T[] ts) { throw new UnsupportedOperationException(); } + public T[] toArray(T[] ts) { + throw new UnsupportedOperationException(); + } @Override - public boolean add(Cell k) { throw new UnsupportedOperationException(); } + public boolean add(Cell k) { + throw new UnsupportedOperationException(); + } @Override - public boolean remove(Object o) { throw new UnsupportedOperationException(); } + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } @Override public boolean containsAll(Collection collection) { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOnHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockObjectArray.java similarity index 74% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOnHeap.java rename to hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockObjectArray.java index afa596b70758..bebdd7aee5f7 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOnHeap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockObjectArray.java @@ -19,22 +19,21 @@ package org.apache.hadoop.hbase.regionserver; +import java.util.Comparator; import org.apache.hadoop.hbase.Cell; -import java.util.*; - /** - * CellBlockOnHeap is a simple array of Cells allocated using JVM. + * CellBlockObjectArray is a simple array of Cells allocated using JVM. * As all java arrays it is array of references pointing to Cell objects */ -public class CellBlockOnHeap extends CellBlock { +public class CellBlockObjectArray extends CellBlock { - Cell block[]; + Cell[] block; - /* The Cells Array is created only when CellBlockOnHeap is created, all sub-CellBlocks use + /* The Cells Array is created only when CellBlockObjectArray is created, all sub-CellBlocks use * boundary indexes */ - public CellBlockOnHeap(Comparator comparator, Cell b[], - int min, int max, boolean d) { + public CellBlockObjectArray(Comparator comparator, Cell[] b, int min, int max, + boolean d) { super(comparator,min,max,d); this.block = b; } @@ -43,7 +42,7 @@ public CellBlockOnHeap(Comparator comparator, Cell b[], @Override protected CellBlock createCellBlocks(Comparator comparator, int min, int max, boolean d) { - return new CellBlockOnHeap(comparator,this.block,min,max,d); + return new CellBlockObjectArray(comparator,this.block,min,max,d); } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockSerialized.java similarity index 80% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java rename to hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockSerialized.java index b0c2b6701c00..003cb952db66 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockOffHeap.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CellBlockSerialized.java @@ -19,14 +19,15 @@ package org.apache.hadoop.hbase.regionserver; +import java.util.Comparator; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.util.Bytes; -import java.util.Comparator; + /** - * CellBlockOffHeap is a byte array holding all that is needed to access a Cell, which + * CellBlockSerialized is a byte array holding all that is needed to access a Cell, which * is actually saved on another deeper byte array. * Per Cell we have a reference to this deeper byte array B, offset in bytes in B (integer), * and length in bytes in B (integer). In order to save reference to byte array we use the Chunk's @@ -41,27 +42,27 @@ * | holding Cell data | Cell's data starts| data in B | another byte array | * ------------------------------------------------------------------------------------- ... */ -public class CellBlockOffHeap extends CellBlock { +public class CellBlockSerialized extends CellBlock { - private HeapMemStoreLAB.Chunk chunks[]; + private HeapMemStoreLAB.Chunk[] chunks; private final HeapMemStoreLAB memStoreLAB; private int numOfCellsInsideChunk; - private final int bytesInCell = 3*(Integer.SIZE / Byte.SIZE); // each Cell requires 3 integers + private static final int BYTES_IN_CELL = 3*(Integer.SIZE / Byte.SIZE); // each Cell requires 3 integers - public CellBlockOffHeap(Comparator comparator, HeapMemStoreLAB memStoreLAB, - HeapMemStoreLAB.Chunk chunks[], int min, int max, int chunkSize, boolean d) { + public CellBlockSerialized(Comparator comparator, HeapMemStoreLAB memStoreLAB, + HeapMemStoreLAB.Chunk[] chunks, int min, int max, int chunkSize, boolean d) { super(comparator,min,max, d); this.chunks = chunks; this.memStoreLAB = memStoreLAB; - this.numOfCellsInsideChunk = chunkSize / bytesInCell; + this.numOfCellsInsideChunk = chunkSize / BYTES_IN_CELL; } /* To be used by base class only to create a sub-CellBlock */ @Override protected CellBlock createCellBlocks(Comparator comparator, int min, int max, boolean d) { - return new CellBlockOffHeap(comparator, this.memStoreLAB, this.chunks, min, max, - this.numOfCellsInsideChunk*bytesInCell, d); + return new CellBlockSerialized(comparator, this.memStoreLAB, this.chunks, min, max, + this.numOfCellsInsideChunk* BYTES_IN_CELL, d); } @Override @@ -72,7 +73,7 @@ protected Cell getCellFromIndex(int i) { i = i - chunkIndex*numOfCellsInsideChunk; // find inside chunk - int offsetInBytes = i*bytesInCell; + int offsetInBytes = i* BYTES_IN_CELL; int chunkId = Bytes.toInt(block,offsetInBytes); int offsetOfCell = Bytes.toInt(block,offsetInBytes+(Integer.SIZE / Byte.SIZE)); int lengthOfCell = Bytes.toInt(block,offsetInBytes+2*(Integer.SIZE / Byte.SIZE)); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java index f673d314b8ee..228616bade7e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemStoreLAB.java @@ -30,7 +30,7 @@ import org.apache.hadoop.hbase.util.SimpleMutableByteRange; import com.google.common.base.Preconditions; -import static org.junit.Assert.assertTrue; + /** * A memstore-local allocation buffer. @@ -110,7 +110,7 @@ public ByteRange allocateBytes(int size) { } while (true) { - Chunk c = getOrMakeChunk(size); + Chunk c = getOrMakeChunk(); // Try to allocate from this chunk int allocOffset = c.alloc(size); @@ -179,9 +179,8 @@ private void tryRetireChunk(Chunk c) { /** * Get the current chunk, or, if there is no current chunk, * allocate a new one from the JVM. - * @param size */ - private Chunk getOrMakeChunk(int size) { + private Chunk getOrMakeChunk() { while (true) { // Try to get the chunk diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java index 9753981bc379..bc85bc0e95ee 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java @@ -19,9 +19,16 @@ package org.apache.hadoop.hbase.regionserver; import java.lang.management.ManagementFactory; -import java.util.concurrent.*; +//import java.util.concurrent.*; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java index f37af2536fa8..1a368df9ea96 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCellBlocksSet.java @@ -36,8 +36,8 @@ public class TestCellBlocksSet extends TestCase { private static final int NUM_OF_CELLS = 3; private Cell cells[]; - private CellBlockOnHeap cbOnHeap; - private CellBlockOffHeap cbOffHeap; + private CellBlockObjectArray cbOnHeap; + private CellBlockSerialized cbOffHeap; private final static Configuration conf = new Configuration(); private HeapMemStoreLAB mslab; @@ -60,7 +60,7 @@ protected void setUp() throws Exception { final KeyValue kv3 = new KeyValue(three, f, q, 30, v); cells = new Cell[] {kv1,kv2,kv3}; - cbOnHeap = new CellBlockOnHeap(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS,false); + cbOnHeap = new CellBlockObjectArray(CellComparator.COMPARATOR,cells,0,NUM_OF_CELLS,false); conf.setBoolean(SegmentFactory.USEMSLAB_KEY, true); conf.setFloat(MemStoreChunkPool.CHUNK_POOL_MAXSIZE_KEY, 0.2f); @@ -69,18 +69,18 @@ protected void setUp() throws Exception { HeapMemStoreLAB.Chunk[] c = shallowCellsToBuffer(kv1, kv2, kv3); int chunkSize = conf.getInt(HeapMemStoreLAB.CHUNK_SIZE_KEY, HeapMemStoreLAB.CHUNK_SIZE_DEFAULT); - cbOffHeap = new CellBlockOffHeap(CellComparator.COMPARATOR, mslab, + cbOffHeap = new CellBlockSerialized(CellComparator.COMPARATOR, mslab, c, 0, NUM_OF_CELLS, chunkSize, false); } - /* Create and test CellSet based on CellBlockOnHeap */ + /* Create and test CellSet based on CellBlockObjectArray */ public void testCellBlocksOnHeap() throws Exception { CellSet cs = new CellSet(cbOnHeap); testCellBlocks(cs); testIterators(cs); } - /* Create and test CellSet based on CellBlockOffHeap */ + /* Create and test CellSet based on CellBlockSerialized */ public void testCellBlocksOffHeap() throws Exception { CellSet cs = new CellSet(cbOffHeap); testCellBlocks(cs);