001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.regionserver; 020 021import org.apache.hadoop.hbase.Cell; 022import org.apache.hadoop.hbase.CellComparator; 023import org.apache.hadoop.hbase.CellUtil; 024import org.apache.yetus.audience.InterfaceAudience; 025import org.apache.hadoop.hbase.util.ClassSize; 026 027import java.io.IOException; 028 029/** 030 * CellArrayImmutableSegment extends the API supported by a {@link Segment}, 031 * and {@link ImmutableSegment}. This immutable segment is working with CellSet with 032 * CellArrayMap delegatee. 033 */ 034@InterfaceAudience.Private 035public class CellArrayImmutableSegment extends ImmutableSegment { 036 037 public static final long DEEP_OVERHEAD_CAM = DEEP_OVERHEAD + ClassSize.CELL_ARRAY_MAP; 038 039 ///////////////////// CONSTRUCTORS ///////////////////// 040 /**------------------------------------------------------------------------ 041 * C-tor to be used when new CellArrayImmutableSegment is a result of compaction of a 042 * list of older ImmutableSegments. 043 * The given iterator returns the Cells that "survived" the compaction. 044 */ 045 protected CellArrayImmutableSegment(CellComparator comparator, MemStoreSegmentsIterator iterator, 046 MemStoreLAB memStoreLAB, int numOfCells, MemStoreCompactionStrategy.Action action) { 047 super(null, comparator, memStoreLAB); // initiailize the CellSet with NULL 048 incMemStoreSize(0, DEEP_OVERHEAD_CAM, 0); // CAM is always on-heap 049 // build the new CellSet based on CellArrayMap and update the CellSet of the new Segment 050 initializeCellSet(numOfCells, iterator, action); 051 } 052 053 /**------------------------------------------------------------------------ 054 * C-tor to be used when new CellChunkImmutableSegment is built as a result of flattening 055 * of CSLMImmutableSegment 056 * The given iterator returns the Cells that "survived" the compaction. 057 */ 058 protected CellArrayImmutableSegment(CSLMImmutableSegment segment, MemStoreSizing memstoreSizing, 059 MemStoreCompactionStrategy.Action action) { 060 super(segment); // initiailize the upper class 061 long indexOverhead = DEEP_OVERHEAD_CAM - CSLMImmutableSegment.DEEP_OVERHEAD_CSLM; 062 incMemStoreSize(0, indexOverhead, 0); // CAM is always on-heap 063 int numOfCells = segment.getCellsCount(); 064 // build the new CellSet based on CellChunkMap and update the CellSet of this Segment 065 reinitializeCellSet(numOfCells, segment.getScanner(Long.MAX_VALUE), segment.getCellSet(), 066 action); 067 // arrange the meta-data size, decrease all meta-data sizes related to SkipList; 068 // add sizes of CellArrayMap entry (reinitializeCellSet doesn't take the care for the sizes) 069 long newSegmentSizeDelta = numOfCells*(indexEntrySize()-ClassSize.CONCURRENT_SKIPLISTMAP_ENTRY); 070 incMemStoreSize(0, newSegmentSizeDelta, 0); 071 memstoreSizing.incMemStoreSize(0, newSegmentSizeDelta, 0); 072 } 073 074 @Override 075 protected long indexEntrySize() { 076 return ClassSize.CELL_ARRAY_MAP_ENTRY; 077 } 078 079 @Override 080 protected boolean canBeFlattened() { 081 return false; 082 } 083 084 ///////////////////// PRIVATE METHODS ///////////////////// 085 /*------------------------------------------------------------------------*/ 086 // Create CellSet based on CellArrayMap from compacting iterator 087 private void initializeCellSet(int numOfCells, MemStoreSegmentsIterator iterator, 088 MemStoreCompactionStrategy.Action action) { 089 090 boolean merge = (action == MemStoreCompactionStrategy.Action.MERGE || 091 action == MemStoreCompactionStrategy.Action.MERGE_COUNT_UNIQUE_KEYS); 092 Cell[] cells = new Cell[numOfCells]; // build the Cell Array 093 int i = 0; 094 int numUniqueKeys=0; 095 Cell prev = null; 096 while (iterator.hasNext()) { 097 Cell c = iterator.next(); 098 // The scanner behind the iterator is doing all the elimination logic 099 if (merge) { 100 // if this is merge we just move the Cell object without copying MSLAB 101 // the sizes still need to be updated in the new segment 102 cells[i] = c; 103 } else { 104 // now we just copy it to the new segment (also MSLAB copy) 105 cells[i] = maybeCloneWithAllocator(c, false); 106 } 107 // second parameter true, because in compaction/merge the addition of the cell to new segment 108 // is always successful 109 updateMetaInfo(cells[i], true, null); // updates the size per cell 110 if(action == MemStoreCompactionStrategy.Action.MERGE_COUNT_UNIQUE_KEYS) { 111 //counting number of unique keys 112 if (prev != null) { 113 if (!CellUtil.matchingRowColumnBytes(prev, c)) { 114 numUniqueKeys++; 115 } 116 } else { 117 numUniqueKeys++; 118 } 119 } 120 prev = c; 121 i++; 122 } 123 if(action == MemStoreCompactionStrategy.Action.COMPACT) { 124 numUniqueKeys = numOfCells; 125 } else if(action != MemStoreCompactionStrategy.Action.MERGE_COUNT_UNIQUE_KEYS) { 126 numUniqueKeys = CellSet.UNKNOWN_NUM_UNIQUES; 127 } 128 // build the immutable CellSet 129 CellArrayMap cam = new CellArrayMap(getComparator(), cells, 0, i, false); 130 this.setCellSet(null, new CellSet(cam, numUniqueKeys)); // update the CellSet of this Segment 131 } 132 133 /*------------------------------------------------------------------------*/ 134 // Create CellSet based on CellChunkMap from current ConcurrentSkipListMap based CellSet 135 // (without compacting iterator) 136 // We do not consider cells bigger than chunks! 137 private void reinitializeCellSet( 138 int numOfCells, KeyValueScanner segmentScanner, CellSet oldCellSet, 139 MemStoreCompactionStrategy.Action action) { 140 Cell[] cells = new Cell[numOfCells]; // build the Cell Array 141 Cell curCell; 142 int idx = 0; 143 int numUniqueKeys=0; 144 Cell prev = null; 145 try { 146 while ((curCell = segmentScanner.next()) != null) { 147 cells[idx++] = curCell; 148 if(action == MemStoreCompactionStrategy.Action.FLATTEN_COUNT_UNIQUE_KEYS) { 149 //counting number of unique keys 150 if (prev != null) { 151 if (!CellUtil.matchingRowColumn(prev, curCell)) { 152 numUniqueKeys++; 153 } 154 } else { 155 numUniqueKeys++; 156 } 157 } 158 prev = curCell; 159 } 160 } catch (IOException ie) { 161 throw new IllegalStateException(ie); 162 } finally { 163 segmentScanner.close(); 164 } 165 if(action != MemStoreCompactionStrategy.Action.FLATTEN_COUNT_UNIQUE_KEYS) { 166 numUniqueKeys = CellSet.UNKNOWN_NUM_UNIQUES; 167 } 168 // build the immutable CellSet 169 CellArrayMap cam = new CellArrayMap(getComparator(), cells, 0, idx, false); 170 // update the CellSet of this Segment 171 this.setCellSet(oldCellSet, new CellSet(cam, numUniqueKeys)); 172 } 173 174}