28
28
import java .util .concurrent .atomic .AtomicInteger ;
29
29
import java .util .concurrent .atomic .AtomicLong ;
30
30
import java .util .concurrent .atomic .LongAdder ;
31
+
31
32
import org .apache .hadoop .hbase .regionserver .HeapMemoryManager .HeapMemoryTuneObserver ;
32
33
import org .apache .hadoop .hbase .util .Bytes ;
33
34
import org .apache .hadoop .util .StringUtils ;
@@ -134,51 +135,36 @@ public static ChunkCreator getInstance() {
134
135
return instance ;
135
136
}
136
137
137
- /**
138
- * Creates and inits a chunk. The default implementation for a specific chunk size.
139
- * @return the chunk that was initialized
140
- */
141
- Chunk getChunk (ChunkType chunkType ) {
142
- return getChunk (CompactingMemStore .IndexType .ARRAY_MAP , chunkType );
143
- }
144
138
145
139
/**
146
- * Creates and inits a chunk. The default implementation.
140
+ * Creates and inits a data chunk. The default implementation.
147
141
* @return the chunk that was initialized
148
142
*/
149
143
Chunk getChunk () {
150
- return getChunk (CompactingMemStore . IndexType . ARRAY_MAP , ChunkType .DATA_CHUNK );
144
+ return getChunk (ChunkType .DATA_CHUNK );
151
145
}
152
146
153
147
/**
154
- * Creates and inits a chunk. The default implementation for a specific index type.
148
+ * Creates and inits a chunk with specific type.
155
149
* @return the chunk that was initialized
156
150
*/
157
- Chunk getChunk (CompactingMemStore .IndexType chunkIndexType ) {
158
- return getChunk (chunkIndexType , ChunkType .DATA_CHUNK );
159
- }
160
-
161
- /**
162
- * Creates and inits a chunk with specific index type and type.
163
- * @return the chunk that was initialized
164
- */
165
- Chunk getChunk (CompactingMemStore .IndexType chunkIndexType , ChunkType chunkType ) {
151
+ Chunk getChunk (ChunkType chunkType ) {
166
152
switch (chunkType ) {
167
153
case INDEX_CHUNK :
168
154
if (indexChunksPool == null ) {
169
155
if (indexChunkSize <= 0 ) {
170
156
throw new IllegalArgumentException (
171
157
"chunkType is INDEX_CHUNK but indexChunkSize is:[" + this .indexChunkSize + "]" );
172
158
}
173
- return getChunk (chunkIndexType , chunkType , indexChunkSize );
159
+ return getChunk (chunkType , indexChunkSize );
174
160
} else {
175
- return getChunk (chunkIndexType , chunkType , indexChunksPool .getChunkSize ());
161
+ return getChunk (chunkType , indexChunksPool .getChunkSize ());
176
162
}
177
163
case DATA_CHUNK :
178
164
if (dataChunksPool == null ) {
179
- return getChunk (chunkIndexType , chunkType , chunkSize );
165
+ return getChunk (chunkType , chunkSize );
180
166
} else {
181
- return getChunk (chunkIndexType , chunkType , dataChunksPool .getChunkSize ());
167
+ return getChunk (chunkType , dataChunksPool .getChunkSize ());
182
168
}
183
169
default :
184
170
throw new IllegalArgumentException (
@@ -189,10 +175,9 @@ Chunk getChunk(CompactingMemStore.IndexType chunkIndexType, ChunkType chunkType)
189
175
/**
190
176
* Creates and inits a chunk.
191
177
* @return the chunk that was initialized
192
- * @param chunkIndexType whether the requested chunk is going to be used with CellChunkMap index
193
178
* @param size the size of the chunk to be allocated, in bytes
194
179
*/
195
- Chunk getChunk (CompactingMemStore . IndexType chunkIndexType , ChunkType chunkType , int size ) {
180
+ Chunk getChunk (ChunkType chunkType , int size ) {
196
181
Chunk chunk = null ;
197
182
MemStoreChunkPool pool = null ;
198
183
@@ -217,9 +202,7 @@ Chunk getChunk(CompactingMemStore.IndexType chunkIndexType, ChunkType chunkType,
217
202
}
218
203
219
204
if (chunk == null ) {
220
- // the second parameter explains whether CellChunkMap index is requested,
221
- // in that case, put allocated on demand chunk mapping into chunkIdMap
222
- chunk = createChunk (false , chunkIndexType , chunkType , size );
205
+ chunk = createChunk (false , chunkType , size );
223
206
}
224
207
225
208
// now we need to actually do the expensive memory allocation step in case of a new chunk,
@@ -240,22 +223,21 @@ Chunk getJumboChunk(int jumboSize) {
240
223
if (allocSize <= this .getChunkSize (ChunkType .DATA_CHUNK )) {
241
224
LOG .warn ("Jumbo chunk size " + jumboSize + " must be more than regular chunk size "
242
225
+ this .getChunkSize (ChunkType .DATA_CHUNK ) + ". Converting to regular chunk." );
243
- return getChunk (CompactingMemStore . IndexType . CHUNK_MAP );
226
+ return getChunk ();
244
227
}
245
228
// the new chunk is going to hold the jumbo cell data and needs to be referenced by
246
- // a strong map. Therefore the CCM index type
247
- return getChunk (CompactingMemStore . IndexType . CHUNK_MAP , ChunkType .JUMBO_CHUNK , allocSize );
229
+ // a strong map.
230
+ return getChunk (ChunkType .JUMBO_CHUNK , allocSize );
248
231
}
249
232
250
233
/**
251
234
* Creates the chunk either onheap or offheap
252
235
* @param pool indicates if the chunks have to be created which will be used by the Pool
253
- * @param chunkIndexType whether the requested chunk is going to be used with CellChunkMap index
236
+ * @param chunkType whether the requested chunk is data chunk or index chunk.
254
237
* @param size the size of the chunk to be allocated, in bytes
255
238
* @return the chunk
256
239
*/
257
- private Chunk createChunk (boolean pool , CompactingMemStore .IndexType chunkIndexType ,
258
- ChunkType chunkType , int size ) {
240
+ private Chunk createChunk (boolean pool , ChunkType chunkType , int size ) {
259
241
Chunk chunk = null ;
260
242
int id = chunkID .getAndIncrement ();
261
243
assert id > 0 ;
@@ -265,22 +247,39 @@ private Chunk createChunk(boolean pool, CompactingMemStore.IndexType chunkIndexT
265
247
} else {
266
248
chunk = new OnheapChunk (size , id , chunkType , pool );
267
249
}
268
- if (pool || (chunkIndexType == CompactingMemStore .IndexType .CHUNK_MAP )) {
269
- // put the pool chunk into the chunkIdMap so it is not GC-ed
270
- this .chunkIdMap .put (chunk .getId (), chunk );
271
- }
250
+
251
+ /**
252
+ * Here we always put the chunk into the {@link ChunkCreator#chunkIdMap} no matter whether the
253
+ * chunk is pooled or not. <br/>
254
+ * For {@link CompactingMemStore},because the chunk could only be acquired from
255
+ * {@link ChunkCreator} through {@link MemStoreLABImpl}, and
256
+ * {@link CompactingMemStore#indexType} could only be {@link IndexType.CHUNK_MAP} when using
257
+ * {@link MemStoreLABImpl}, so we must put chunk into this {@link ChunkCreator#chunkIdMap} to
258
+ * make sure the chunk could be got by chunkId.
259
+ * <p>
260
+ * For {@link DefaultMemStore},it is also reasonable to put the chunk in
261
+ * {@link ChunkCreator#chunkIdMap} because: <br/>
262
+ * 1.When the {@link MemStoreLAB} which created the chunk is not closed, this chunk is used by
263
+ * the {@link Segment} which references this {@link MemStoreLAB}, so this chunk certainly should
264
+ * not be GC-ed, putting the chunk in {@link ChunkCreator#chunkIdMap} does not prevent useless
265
+ * chunk to be GC-ed. <br/>
266
+ * 2.When the {@link MemStoreLAB} which created the chunk is closed, and if the chunk is not
267
+ * pooled, {@link ChunkCreator#removeChunk} is invoked to remove the chunk from this
268
+ * {@link ChunkCreator#chunkIdMap}, so there is no memory leak.
269
+ */
270
+ this .chunkIdMap .put (chunk .getId (), chunk );
271
+
272
272
return chunk ;
273
273
}
274
274
275
- // Chunks from pool are created covered with strong references anyway
276
- // TODO: change to CHUNK_MAP if it is generally defined
277
- private Chunk createChunkForPool (CompactingMemStore .IndexType chunkIndexType , ChunkType chunkType ,
275
+ // Chunks from pool are created covered with strong references anyway.
276
+ private Chunk createChunkForPool (ChunkType chunkType ,
278
277
int chunkSize ) {
279
278
if (chunkSize != dataChunksPool .getChunkSize () &&
280
279
chunkSize != indexChunksPool .getChunkSize ()) {
281
280
return null ;
282
281
}
283
- return createChunk (true , chunkIndexType , chunkType , chunkSize );
282
+ return createChunk (true , chunkType , chunkSize );
284
283
}
285
284
286
285
// Used to translate the ChunkID into a chunk ref
@@ -346,7 +345,7 @@ private class MemStoreChunkPool implements HeapMemoryTuneObserver {
346
345
this .reclaimedChunks = new LinkedBlockingQueue <>();
347
346
for (int i = 0 ; i < initialCount ; i ++) {
348
347
Chunk chunk =
349
- createChunk (true , CompactingMemStore . IndexType . ARRAY_MAP , chunkType , chunkSize );
348
+ createChunk (true , chunkType , chunkSize );
350
349
chunk .init ();
351
350
reclaimedChunks .add (chunk );
352
351
}
@@ -368,10 +367,6 @@ private class MemStoreChunkPool implements HeapMemoryTuneObserver {
368
367
* @see #putbackChunks(Chunk)
369
368
*/
370
369
Chunk getChunk () {
371
- return getChunk (CompactingMemStore .IndexType .ARRAY_MAP );
372
- }
373
-
374
- Chunk getChunk (CompactingMemStore .IndexType chunkIndexType ) {
375
370
Chunk chunk = reclaimedChunks .poll ();
376
371
if (chunk != null ) {
377
372
chunk .reset ();
@@ -382,7 +377,7 @@ Chunk getChunk(CompactingMemStore.IndexType chunkIndexType) {
382
377
long created = this .chunkCount .get ();
383
378
if (created < this .maxCount ) {
384
379
if (this .chunkCount .compareAndSet (created , created + 1 )) {
385
- chunk = createChunkForPool (chunkIndexType , chunkType , chunkSize );
380
+ chunk = createChunkForPool (chunkType , chunkSize );
386
381
break ;
387
382
}
388
383
} else {
@@ -559,7 +554,7 @@ int getPoolSize(ChunkType chunkType) {
559
554
560
555
boolean isChunkInPool (int chunkId ) {
561
556
Chunk c = getChunk (chunkId );
562
- if (c == null ) {
557
+ if (c == null ) {
563
558
return false ;
564
559
}
565
560
0 commit comments