1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.io.hfile.bucket;
20
21 import org.apache.hadoop.hbase.HBaseConfiguration;
22 import org.apache.hadoop.hbase.testclassification.SmallTests;
23 import org.apache.hadoop.hbase.io.hfile.BlockCacheKey;
24 import org.apache.hadoop.hbase.io.hfile.Cacheable;
25 import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache.BucketEntry;
26 import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache.RAMQueueEntry;
27 import org.junit.After;
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.junit.experimental.categories.Category;
31 import org.mockito.Mockito;
32
33 import java.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.concurrent.BlockingQueue;
38 import java.util.concurrent.atomic.AtomicLong;
39
40 import static org.hamcrest.CoreMatchers.is;
41 import static org.junit.Assert.assertEquals;
42 import static org.junit.Assert.assertThat;
43 import static org.junit.Assert.assertTrue;
44
45 @Category(SmallTests.class)
46 public class TestBucketWriterThread {
47 private BucketCache bc;
48 private BucketCache.WriterThread wt;
49 private BlockingQueue<RAMQueueEntry> q;
50 private Cacheable plainCacheable;
51 private BlockCacheKey plainKey;
52
53
54 private static class MockBucketCache extends BucketCache {
55
56 public MockBucketCache(String ioEngineName, long capacity, int blockSize, int[] bucketSizes,
57 int writerThreadNum, int writerQLen, String persistencePath, int ioErrorsTolerationDuration)
58 throws FileNotFoundException, IOException {
59 super(ioEngineName, capacity, blockSize, bucketSizes, writerThreadNum, writerQLen,
60 persistencePath, ioErrorsTolerationDuration, HBaseConfiguration.create());
61 }
62
63 @Override
64 protected void startWriterThreads() {
65
66 }
67 }
68
69
70
71
72
73
74 @Before
75 public void setUp() throws Exception {
76
77 final int capacity = 16;
78
79
80 final int writerThreadsCount = 1;
81 this.bc = new MockBucketCache("heap", capacity, 1, new int [] {1}, writerThreadsCount,
82 capacity, null, 100
83 assertEquals(writerThreadsCount, bc.writerThreads.length);
84 assertEquals(writerThreadsCount, bc.writerQueues.size());
85
86 this.wt = bc.writerThreads[0];
87 this.q = bc.writerQueues.get(0);
88
89 wt.disableWriter();
90 this.plainKey = new BlockCacheKey("f", 0);
91 this.plainCacheable = Mockito.mock(Cacheable.class);
92
93 assertThat(bc.ramCache.isEmpty(), is(true));
94 assertTrue(q.isEmpty());
95 }
96
97 @After
98 public void tearDown() throws Exception {
99 if (this.bc != null) this.bc.shutdown();
100 }
101
102
103
104
105
106
107
108 @Test (timeout=30000)
109 public void testNonErrorCase() throws IOException, InterruptedException {
110 bc.cacheBlock(this.plainKey, this.plainCacheable);
111 doDrainOfOneEntry(this.bc, this.wt, this.q);
112 }
113
114
115
116
117
118
119 @Test
120 public void testTooBigEntry() throws InterruptedException {
121 Cacheable tooBigCacheable = Mockito.mock(Cacheable.class);
122 Mockito.when(tooBigCacheable.getSerializedLength()).thenReturn(Integer.MAX_VALUE);
123 this.bc.cacheBlock(this.plainKey, tooBigCacheable);
124 doDrainOfOneEntry(this.bc, this.wt, this.q);
125 }
126
127
128
129
130
131
132
133 @SuppressWarnings("unchecked")
134 @Test (timeout=30000)
135 public void testIOE() throws IOException, InterruptedException {
136 this.bc.cacheBlock(this.plainKey, plainCacheable);
137 RAMQueueEntry rqe = q.remove();
138 RAMQueueEntry spiedRqe = Mockito.spy(rqe);
139 Mockito.doThrow(new IOException("Mocked!")).when(spiedRqe).
140 writeToCache((IOEngine)Mockito.any(), (BucketAllocator)Mockito.any(),
141 (UniqueIndexMap<Integer>)Mockito.any(), (AtomicLong)Mockito.any());
142 this.q.add(spiedRqe);
143 doDrainOfOneEntry(bc, wt, q);
144
145 assertTrue(!bc.isCacheEnabled());
146 }
147
148
149
150
151
152
153 @Test (timeout=30000)
154 public void testCacheFullException()
155 throws IOException, InterruptedException {
156 this.bc.cacheBlock(this.plainKey, plainCacheable);
157 RAMQueueEntry rqe = q.remove();
158 RAMQueueEntry spiedRqe = Mockito.spy(rqe);
159 final CacheFullException cfe = new CacheFullException(0, 0);
160 BucketEntry mockedBucketEntry = Mockito.mock(BucketEntry.class);
161 Mockito.doThrow(cfe).
162 doReturn(mockedBucketEntry).
163 when(spiedRqe).writeToCache((IOEngine)Mockito.any(), (BucketAllocator)Mockito.any(),
164 (UniqueIndexMap<Integer>)Mockito.any(), (AtomicLong)Mockito.any());
165 this.q.add(spiedRqe);
166 doDrainOfOneEntry(bc, wt, q);
167 }
168
169 private static void doDrainOfOneEntry(final BucketCache bc, final BucketCache.WriterThread wt,
170 final BlockingQueue<RAMQueueEntry> q)
171 throws InterruptedException {
172 List<RAMQueueEntry> rqes = BucketCache.getRAMQueueEntries(q, new ArrayList<RAMQueueEntry>(1));
173 wt.doDrain(rqes);
174 assertTrue(q.isEmpty());
175 assertTrue(bc.ramCache.isEmpty());
176 assertEquals(0, bc.heapSize());
177 }
178 }