001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import java.io.IOException; 021import org.apache.hadoop.hbase.Cell; 022import org.apache.hadoop.hbase.CellComparator; 023import org.apache.hadoop.hbase.CellUtil; 024import org.apache.hadoop.hbase.ExtendedCell; 025import org.apache.hadoop.hbase.util.ClassSize; 026import org.apache.yetus.audience.InterfaceAudience; 027 028/** 029 * CellArrayImmutableSegment extends the API supported by a {@link Segment}, and 030 * {@link ImmutableSegment}. This immutable segment is working with CellSet with CellArrayMap 031 * delegatee. 032 */ 033@InterfaceAudience.Private 034public class CellArrayImmutableSegment extends ImmutableSegment { 035 036 public static final long DEEP_OVERHEAD_CAM = DEEP_OVERHEAD + ClassSize.CELL_ARRAY_MAP; 037 038 ///////////////////// CONSTRUCTORS ///////////////////// 039 /** 040 * ------------------------------------------------------------------------ C-tor to be used when 041 * new CellArrayImmutableSegment is a result of compaction of a list of older ImmutableSegments. 042 * The given iterator returns the Cells that "survived" the compaction. 043 */ 044 protected CellArrayImmutableSegment(CellComparator comparator, MemStoreSegmentsIterator iterator, 045 MemStoreLAB memStoreLAB, int numOfCells, MemStoreCompactionStrategy.Action action) { 046 super(null, comparator, memStoreLAB); // initiailize the CellSet with NULL 047 incMemStoreSize(0, DEEP_OVERHEAD_CAM, 0, 0); // CAM is always on-heap 048 // build the new CellSet based on CellArrayMap and update the CellSet of the new Segment 049 initializeCellSet(numOfCells, iterator, action); 050 } 051 052 /** 053 * ------------------------------------------------------------------------ C-tor to be used when 054 * new CellChunkImmutableSegment is built as a result of flattening of CSLMImmutableSegment The 055 * given iterator returns the Cells that "survived" the compaction. 056 */ 057 protected CellArrayImmutableSegment(CSLMImmutableSegment segment, MemStoreSizing mss, 058 MemStoreCompactionStrategy.Action action) { 059 super(segment); // initiailize the upper class 060 long indexOverhead = DEEP_OVERHEAD_CAM - CSLMImmutableSegment.DEEP_OVERHEAD_CSLM; 061 incMemStoreSize(0, indexOverhead, 0, 0); // CAM is always on-heap 062 mss.incMemStoreSize(0, indexOverhead, 0, 0); 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 = 070 numOfCells * (indexEntrySize() - ClassSize.CONCURRENT_SKIPLISTMAP_ENTRY); 071 incMemStoreSize(0, newSegmentSizeDelta, 0, 0); 072 mss.incMemStoreSize(0, newSegmentSizeDelta, 0, 0); 073 } 074 075 @Override 076 protected long indexEntrySize() { 077 return ClassSize.CELL_ARRAY_MAP_ENTRY; 078 } 079 080 @Override 081 protected boolean canBeFlattened() { 082 return false; 083 } 084 085 ///////////////////// PRIVATE METHODS ///////////////////// 086 /*------------------------------------------------------------------------*/ 087 // Create CellSet based on CellArrayMap from compacting iterator 088 private void initializeCellSet(int numOfCells, MemStoreSegmentsIterator iterator, 089 MemStoreCompactionStrategy.Action action) { 090 boolean merge = (action == MemStoreCompactionStrategy.Action.MERGE 091 || action == MemStoreCompactionStrategy.Action.MERGE_COUNT_UNIQUE_KEYS); 092 ExtendedCell[] cells = new ExtendedCell[numOfCells]; // build the Cell Array 093 int i = 0; 094 int numUniqueKeys = 0; 095 Cell prev = null; 096 while (iterator.hasNext()) { 097 ExtendedCell 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<ExtendedCell> 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(int numOfCells, KeyValueScanner segmentScanner, 138 CellSet<ExtendedCell> oldCellSet, MemStoreCompactionStrategy.Action action) { 139 ExtendedCell[] cells = new ExtendedCell[numOfCells]; // build the Cell Array 140 ExtendedCell curCell; 141 int idx = 0; 142 int numUniqueKeys = 0; 143 ExtendedCell prev = null; 144 try { 145 while ((curCell = segmentScanner.next()) != null) { 146 cells[idx++] = curCell; 147 if (action == MemStoreCompactionStrategy.Action.FLATTEN_COUNT_UNIQUE_KEYS) { 148 // counting number of unique keys 149 if (prev != null) { 150 if (!CellUtil.matchingRowColumn(prev, curCell)) { 151 numUniqueKeys++; 152 } 153 } else { 154 numUniqueKeys++; 155 } 156 } 157 prev = curCell; 158 } 159 } catch (IOException ie) { 160 throw new IllegalStateException(ie); 161 } finally { 162 segmentScanner.close(); 163 } 164 if (action != MemStoreCompactionStrategy.Action.FLATTEN_COUNT_UNIQUE_KEYS) { 165 numUniqueKeys = CellSet.UNKNOWN_NUM_UNIQUES; 166 } 167 // build the immutable CellSet 168 CellArrayMap<ExtendedCell> cam = new CellArrayMap<>(getComparator(), cells, 0, idx, false); 169 // update the CellSet of this Segment 170 this.setCellSet(oldCellSet, new CellSet<>(cam, numUniqueKeys)); 171 } 172 173}