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, 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, 0); // CAM is always on-heap 063 memstoreSizing.incMemStoreSize(0, indexOverhead, 0, 0); 064 int numOfCells = segment.getCellsCount(); 065 // build the new CellSet based on CellChunkMap and update the CellSet of this Segment 066 reinitializeCellSet(numOfCells, segment.getScanner(Long.MAX_VALUE), segment.getCellSet(), 067 action); 068 // arrange the meta-data size, decrease all meta-data sizes related to SkipList; 069 // add sizes of CellArrayMap entry (reinitializeCellSet doesn't take the care for the sizes) 070 long newSegmentSizeDelta = 071 numOfCells * (indexEntrySize() - ClassSize.CONCURRENT_SKIPLISTMAP_ENTRY); 072 incMemStoreSize(0, newSegmentSizeDelta, 0, 0); 073 memstoreSizing.incMemStoreSize(0, newSegmentSizeDelta, 0, 0); 074 } 075 076 @Override 077 protected long indexEntrySize() { 078 return ClassSize.CELL_ARRAY_MAP_ENTRY; 079 } 080 081 @Override 082 protected boolean canBeFlattened() { 083 return false; 084 } 085 086 ///////////////////// PRIVATE METHODS ///////////////////// 087 /*------------------------------------------------------------------------*/ 088 // Create CellSet based on CellArrayMap from compacting iterator 089 private void initializeCellSet(int numOfCells, MemStoreSegmentsIterator iterator, 090 MemStoreCompactionStrategy.Action action) { 091 092 boolean merge = (action == MemStoreCompactionStrategy.Action.MERGE || 093 action == MemStoreCompactionStrategy.Action.MERGE_COUNT_UNIQUE_KEYS); 094 Cell[] cells = new Cell[numOfCells]; // build the Cell Array 095 int i = 0; 096 int numUniqueKeys=0; 097 Cell prev = null; 098 while (iterator.hasNext()) { 099 Cell c = iterator.next(); 100 // The scanner behind the iterator is doing all the elimination logic 101 if (merge) { 102 // if this is merge we just move the Cell object without copying MSLAB 103 // the sizes still need to be updated in the new segment 104 cells[i] = c; 105 } else { 106 // now we just copy it to the new segment (also MSLAB copy) 107 cells[i] = maybeCloneWithAllocator(c, false); 108 } 109 // second parameter true, because in compaction/merge the addition of the cell to new segment 110 // is always successful 111 updateMetaInfo(cells[i], true, null); // updates the size per cell 112 if(action == MemStoreCompactionStrategy.Action.MERGE_COUNT_UNIQUE_KEYS) { 113 //counting number of unique keys 114 if (prev != null) { 115 if (!CellUtil.matchingRowColumnBytes(prev, c)) { 116 numUniqueKeys++; 117 } 118 } else { 119 numUniqueKeys++; 120 } 121 } 122 prev = c; 123 i++; 124 } 125 if(action == MemStoreCompactionStrategy.Action.COMPACT) { 126 numUniqueKeys = numOfCells; 127 } else if(action != MemStoreCompactionStrategy.Action.MERGE_COUNT_UNIQUE_KEYS) { 128 numUniqueKeys = CellSet.UNKNOWN_NUM_UNIQUES; 129 } 130 // build the immutable CellSet 131 CellArrayMap cam = new CellArrayMap(getComparator(), cells, 0, i, false); 132 this.setCellSet(null, new CellSet(cam, numUniqueKeys)); // update the CellSet of this Segment 133 } 134 135 /*------------------------------------------------------------------------*/ 136 // Create CellSet based on CellChunkMap from current ConcurrentSkipListMap based CellSet 137 // (without compacting iterator) 138 // We do not consider cells bigger than chunks! 139 private void reinitializeCellSet( 140 int numOfCells, KeyValueScanner segmentScanner, CellSet oldCellSet, 141 MemStoreCompactionStrategy.Action action) { 142 Cell[] cells = new Cell[numOfCells]; // build the Cell Array 143 Cell curCell; 144 int idx = 0; 145 int numUniqueKeys=0; 146 Cell prev = null; 147 try { 148 while ((curCell = segmentScanner.next()) != null) { 149 cells[idx++] = curCell; 150 if(action == MemStoreCompactionStrategy.Action.FLATTEN_COUNT_UNIQUE_KEYS) { 151 //counting number of unique keys 152 if (prev != null) { 153 if (!CellUtil.matchingRowColumn(prev, curCell)) { 154 numUniqueKeys++; 155 } 156 } else { 157 numUniqueKeys++; 158 } 159 } 160 prev = curCell; 161 } 162 } catch (IOException ie) { 163 throw new IllegalStateException(ie); 164 } finally { 165 segmentScanner.close(); 166 } 167 if(action != MemStoreCompactionStrategy.Action.FLATTEN_COUNT_UNIQUE_KEYS) { 168 numUniqueKeys = CellSet.UNKNOWN_NUM_UNIQUES; 169 } 170 // build the immutable CellSet 171 CellArrayMap cam = new CellArrayMap(getComparator(), cells, 0, idx, false); 172 // update the CellSet of this Segment 173 this.setCellSet(oldCellSet, new CellSet(cam, numUniqueKeys)); 174 } 175 176}