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.util.ClassSize; 025import org.apache.yetus.audience.InterfaceAudience; 026 027/** 028 * CellArrayImmutableSegment extends the API supported by a {@link Segment}, and 029 * {@link ImmutableSegment}. This immutable segment is working with CellSet with CellArrayMap 030 * delegatee. 031 */ 032@InterfaceAudience.Private 033public class CellArrayImmutableSegment extends ImmutableSegment { 034 035 public static final long DEEP_OVERHEAD_CAM = DEEP_OVERHEAD + ClassSize.CELL_ARRAY_MAP; 036 037 ///////////////////// CONSTRUCTORS ///////////////////// 038 /** 039 * ------------------------------------------------------------------------ C-tor to be used when 040 * new CellArrayImmutableSegment is a result of compaction of a list of older ImmutableSegments. 041 * The given iterator returns the Cells that "survived" the compaction. 042 */ 043 protected CellArrayImmutableSegment(CellComparator comparator, MemStoreSegmentsIterator iterator, 044 MemStoreLAB memStoreLAB, int numOfCells, MemStoreCompactionStrategy.Action action) { 045 super(null, comparator, memStoreLAB); // initiailize the CellSet with NULL 046 incMemStoreSize(0, DEEP_OVERHEAD_CAM, 0, 0); // CAM is always on-heap 047 // build the new CellSet based on CellArrayMap and update the CellSet of the new Segment 048 initializeCellSet(numOfCells, iterator, action); 049 } 050 051 /** 052 * ------------------------------------------------------------------------ C-tor to be used when 053 * new CellChunkImmutableSegment is built as a result of flattening of CSLMImmutableSegment The 054 * given iterator returns the Cells that "survived" the compaction. 055 */ 056 protected CellArrayImmutableSegment(CSLMImmutableSegment segment, MemStoreSizing mss, 057 MemStoreCompactionStrategy.Action action) { 058 super(segment); // initiailize the upper class 059 long indexOverhead = DEEP_OVERHEAD_CAM - CSLMImmutableSegment.DEEP_OVERHEAD_CSLM; 060 incMemStoreSize(0, indexOverhead, 0, 0); // CAM is always on-heap 061 mss.incMemStoreSize(0, indexOverhead, 0, 0); 062 int numOfCells = segment.getCellsCount(); 063 // build the new CellSet based on CellChunkMap and update the CellSet of this Segment 064 reinitializeCellSet(numOfCells, segment.getScanner(Long.MAX_VALUE), segment.getCellSet(), 065 action); 066 // arrange the meta-data size, decrease all meta-data sizes related to SkipList; 067 // add sizes of CellArrayMap entry (reinitializeCellSet doesn't take the care for the sizes) 068 long newSegmentSizeDelta = 069 numOfCells * (indexEntrySize() - ClassSize.CONCURRENT_SKIPLISTMAP_ENTRY); 070 incMemStoreSize(0, newSegmentSizeDelta, 0, 0); 071 mss.incMemStoreSize(0, newSegmentSizeDelta, 0, 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(int numOfCells, KeyValueScanner segmentScanner, 138 CellSet oldCellSet, MemStoreCompactionStrategy.Action action) { 139 Cell[] cells = new Cell[numOfCells]; // build the Cell Array 140 Cell curCell; 141 int idx = 0; 142 int numUniqueKeys = 0; 143 Cell 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 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}