1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.snapshot;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertTrue;
22
23 import java.io.IOException;
24 import java.util.List;
25
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.fs.FSDataOutputStream;
28 import org.apache.hadoop.fs.FileSystem;
29 import org.apache.hadoop.fs.Path;
30 import org.apache.hadoop.hbase.Cell;
31 import org.apache.hadoop.hbase.CellUtil;
32 import org.apache.hadoop.hbase.HBaseTestingUtility;
33 import org.apache.hadoop.hbase.HColumnDescriptor;
34 import org.apache.hadoop.hbase.HRegionInfo;
35 import org.apache.hadoop.hbase.HTableDescriptor;
36 import org.apache.hadoop.hbase.TableName;
37 import org.apache.hadoop.hbase.client.HTable;
38 import org.apache.hadoop.hbase.client.Result;
39 import org.apache.hadoop.hbase.client.ResultScanner;
40 import org.apache.hadoop.hbase.client.Scan;
41 import org.apache.hadoop.hbase.errorhandling.ForeignExceptionDispatcher;
42 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
43 import org.apache.hadoop.hbase.regionserver.BloomType;
44 import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
45 import org.apache.hadoop.hbase.util.Bytes;
46 import org.apache.hadoop.hbase.util.FSTableDescriptors;
47 import org.apache.hadoop.hbase.util.FSUtils;
48 import org.junit.Assert;
49
50 public class MobSnapshotTestingUtils {
51
52
53
54
55 public static void createMobTable(final HBaseTestingUtility util,
56 final TableName tableName, int regionReplication,
57 final byte[]... families) throws IOException, InterruptedException {
58 HTableDescriptor htd = new HTableDescriptor(tableName);
59 htd.setRegionReplication(regionReplication);
60 for (byte[] family : families) {
61 HColumnDescriptor hcd = new HColumnDescriptor(family);
62 hcd.setMobEnabled(true);
63 hcd.setMobThreshold(0L);
64 htd.addFamily(hcd);
65 }
66 byte[][] splitKeys = SnapshotTestingUtils.getSplitKeys();
67 util.getHBaseAdmin().createTable(htd, splitKeys);
68 SnapshotTestingUtils.waitForTableToBeOnline(util, tableName);
69 assertEquals((splitKeys.length + 1) * regionReplication, util
70 .getHBaseAdmin().getTableRegions(tableName).size());
71 }
72
73
74
75
76
77
78
79
80
81
82 public static HTable createMobTable(final HBaseTestingUtility util,
83 final TableName tableName, final byte[]... families) throws IOException {
84 HTableDescriptor htd = new HTableDescriptor(tableName);
85 for (byte[] family : families) {
86 HColumnDescriptor hcd = new HColumnDescriptor(family);
87
88
89
90
91
92 hcd.setBloomFilterType(BloomType.NONE);
93 hcd.setMobEnabled(true);
94 hcd.setMobThreshold(0L);
95 htd.addFamily(hcd);
96 }
97 util.getHBaseAdmin().createTable(htd);
98
99
100 util.waitUntilAllRegionsAssigned(htd.getTableName());
101 return new HTable(util.getConfiguration(), htd.getTableName());
102 }
103
104
105
106
107 public static int countMobRows(final HTable table) throws IOException {
108 Scan scan = new Scan();
109 ResultScanner results = table.getScanner(scan);
110 int count = 0;
111 for (Result res : results) {
112 count++;
113 List<Cell> cells = res.listCells();
114 for (Cell cell : cells) {
115
116 Assert.assertTrue(CellUtil.cloneValue(cell).length > 0);
117 }
118 }
119 results.close();
120 return count;
121 }
122
123
124
125
126 public static int countMobRows(final HTable table, final byte[]... families)
127 throws IOException {
128 Scan scan = new Scan();
129 for (byte[] family : families) {
130 scan.addFamily(family);
131 }
132 ResultScanner results = table.getScanner(scan);
133 int count = 0;
134 for (Result res : results) {
135 count++;
136 List<Cell> cells = res.listCells();
137 for (Cell cell : cells) {
138
139 Assert.assertTrue(CellUtil.cloneValue(cell).length > 0);
140 }
141 }
142 results.close();
143 return count;
144 }
145
146 public static void verifyMobRowCount(final HBaseTestingUtility util,
147 final TableName tableName, long expectedRows) throws IOException {
148 HTable table = new HTable(util.getConfiguration(), tableName);
149 try {
150 assertEquals(expectedRows, countMobRows(table));
151 } finally {
152 table.close();
153 }
154 }
155
156
157
158
159 public static class SnapshotMock {
160 private final static String TEST_FAMILY = "cf";
161 public final static int TEST_NUM_REGIONS = 4;
162
163 private final Configuration conf;
164 private final FileSystem fs;
165 private final Path rootDir;
166
167 static class RegionData {
168 public HRegionInfo hri;
169 public Path tableDir;
170 public Path[] files;
171
172 public RegionData(final Path tableDir, final HRegionInfo hri,
173 final int nfiles) {
174 this.tableDir = tableDir;
175 this.hri = hri;
176 this.files = new Path[nfiles];
177 }
178 }
179
180 public static class SnapshotBuilder {
181 private final RegionData[] tableRegions;
182 private final SnapshotDescription desc;
183 private final HTableDescriptor htd;
184 private final Configuration conf;
185 private final FileSystem fs;
186 private final Path rootDir;
187 private Path snapshotDir;
188 private int snapshotted = 0;
189
190 public SnapshotBuilder(final Configuration conf, final FileSystem fs,
191 final Path rootDir, final HTableDescriptor htd,
192 final SnapshotDescription desc, final RegionData[] tableRegions)
193 throws IOException {
194 this.fs = fs;
195 this.conf = conf;
196 this.rootDir = rootDir;
197 this.htd = htd;
198 this.desc = desc;
199 this.tableRegions = tableRegions;
200 this.snapshotDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc,
201 rootDir);
202 new FSTableDescriptors(conf).createTableDescriptorForTableDirectory(
203 snapshotDir, htd, false);
204 }
205
206 public HTableDescriptor getTableDescriptor() {
207 return this.htd;
208 }
209
210 public SnapshotDescription getSnapshotDescription() {
211 return this.desc;
212 }
213
214 public Path getSnapshotsDir() {
215 return this.snapshotDir;
216 }
217
218 public Path[] addRegion() throws IOException {
219 return addRegion(desc);
220 }
221
222 public Path[] addRegionV1() throws IOException {
223 return addRegion(desc.toBuilder()
224 .setVersion(SnapshotManifestV1.DESCRIPTOR_VERSION).build());
225 }
226
227 public Path[] addRegionV2() throws IOException {
228 return addRegion(desc.toBuilder()
229 .setVersion(SnapshotManifestV2.DESCRIPTOR_VERSION).build());
230 }
231
232 private Path[] addRegion(final SnapshotDescription desc)
233 throws IOException {
234 if (this.snapshotted == tableRegions.length) {
235 throw new UnsupportedOperationException(
236 "No more regions in the table");
237 }
238
239 RegionData regionData = tableRegions[this.snapshotted++];
240 ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher(
241 desc.getName());
242 SnapshotManifest manifest = SnapshotManifest.create(conf, fs,
243 snapshotDir, desc, monitor);
244 manifest.addRegion(regionData.tableDir, regionData.hri);
245 return regionData.files;
246 }
247
248 public Path commit() throws IOException {
249 ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher(
250 desc.getName());
251 SnapshotManifest manifest = SnapshotManifest.create(conf, fs,
252 snapshotDir, desc, monitor);
253 manifest.addTableDescriptor(htd);
254 manifest.consolidate();
255 SnapshotDescriptionUtils.completeSnapshot(desc, rootDir, snapshotDir,
256 fs);
257 snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(desc,
258 rootDir);
259 return snapshotDir;
260 }
261 }
262
263 public SnapshotMock(final Configuration conf, final FileSystem fs,
264 final Path rootDir) {
265 this.fs = fs;
266 this.conf = conf;
267 this.rootDir = rootDir;
268 }
269
270 public SnapshotBuilder createSnapshotV1(final String snapshotName)
271 throws IOException {
272 return createSnapshot(snapshotName, SnapshotManifestV1.DESCRIPTOR_VERSION);
273 }
274
275 public SnapshotBuilder createSnapshotV2(final String snapshotName)
276 throws IOException {
277 return createSnapshot(snapshotName, SnapshotManifestV2.DESCRIPTOR_VERSION);
278 }
279
280 private SnapshotBuilder createSnapshot(final String snapshotName,
281 final int version) throws IOException {
282 HTableDescriptor htd = createHtd(snapshotName);
283
284 RegionData[] regions = createTable(htd, TEST_NUM_REGIONS);
285
286 SnapshotDescription desc = SnapshotDescription.newBuilder()
287 .setTable(htd.getNameAsString()).setName(snapshotName)
288 .setVersion(version).build();
289
290 Path workingDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc,
291 rootDir);
292 SnapshotDescriptionUtils.writeSnapshotInfo(desc, workingDir, fs);
293 return new SnapshotBuilder(conf, fs, rootDir, htd, desc, regions);
294 }
295
296 public HTableDescriptor createHtd(final String tableName) {
297 HTableDescriptor htd = new HTableDescriptor(tableName);
298 HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY);
299 hcd.setMobEnabled(true);
300 hcd.setMobThreshold(0L);
301 htd.addFamily(hcd);
302 return htd;
303 }
304
305 private RegionData[] createTable(final HTableDescriptor htd,
306 final int nregions) throws IOException {
307 Path tableDir = FSUtils.getTableDir(rootDir, htd.getTableName());
308 new FSTableDescriptors(conf).createTableDescriptorForTableDirectory(
309 tableDir, htd, false);
310
311 assertTrue(nregions % 2 == 0);
312 RegionData[] regions = new RegionData[nregions];
313 for (int i = 0; i < regions.length; i += 2) {
314 byte[] startKey = Bytes.toBytes(0 + i * 2);
315 byte[] endKey = Bytes.toBytes(1 + i * 2);
316
317
318 HRegionInfo hri = new HRegionInfo(htd.getTableName(), startKey, endKey);
319 HRegionFileSystem rfs = HRegionFileSystem.createRegionOnFileSystem(
320 conf, fs, tableDir, hri);
321 regions[i] = new RegionData(tableDir, hri, 3);
322 for (int j = 0; j < regions[i].files.length; ++j) {
323 Path storeFile = createStoreFile(rfs.createTempName());
324 regions[i].files[j] = rfs.commitStoreFile(TEST_FAMILY, storeFile);
325 }
326
327
328
329 startKey = Bytes.toBytes(2 + i * 2);
330 endKey = Bytes.toBytes(3 + i * 2);
331 hri = new HRegionInfo(htd.getTableName());
332 rfs = HRegionFileSystem.createRegionOnFileSystem(conf, fs, tableDir,
333 hri);
334 regions[i + 1] = new RegionData(tableDir, hri, regions[i].files.length);
335 for (int j = 0; j < regions[i].files.length; ++j) {
336 String refName = regions[i].files[j].getName() + '.'
337 + regions[i].hri.getEncodedName();
338 Path refFile = createStoreFile(new Path(rootDir, refName));
339 regions[i + 1].files[j] = rfs.commitStoreFile(TEST_FAMILY, refFile);
340 }
341 }
342 return regions;
343 }
344
345 private Path createStoreFile(final Path storeFile) throws IOException {
346 FSDataOutputStream out = fs.create(storeFile);
347 try {
348 out.write(Bytes.toBytes(storeFile.toString()));
349 } finally {
350 out.close();
351 }
352 return storeFile;
353 }
354 }
355 }