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