1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.mob;
19
20 import static org.junit.Assert.assertEquals;
21
22 import java.util.Random;
23
24 import org.apache.hadoop.conf.Configuration;
25 import org.apache.hadoop.fs.FileStatus;
26 import org.apache.hadoop.fs.Path;
27 import org.apache.hadoop.hbase.HBaseTestingUtility;
28 import org.apache.hadoop.hbase.HColumnDescriptor;
29 import org.apache.hadoop.hbase.HTableDescriptor;
30 import org.apache.hadoop.hbase.testclassification.MediumTests;
31 import org.apache.hadoop.hbase.TableName;
32 import org.apache.hadoop.hbase.client.Admin;
33 import org.apache.hadoop.hbase.client.HTable;
34 import org.apache.hadoop.hbase.client.Put;
35 import org.apache.hadoop.hbase.mob.ExpiredMobFileCleaner;
36 import org.apache.hadoop.hbase.mob.MobUtils;
37 import org.apache.hadoop.hbase.util.Bytes;
38 import org.apache.hadoop.util.ToolRunner;
39 import org.junit.After;
40 import org.junit.AfterClass;
41 import org.junit.Before;
42 import org.junit.BeforeClass;
43 import org.junit.Test;
44 import org.junit.experimental.categories.Category;
45
46 @Category(MediumTests.class)
47 public class TestExpiredMobFileCleaner {
48
49 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
50 private final static TableName tableName = TableName.valueOf("TestExpiredMobFileCleaner");
51 private final static String family = "family";
52 private final static byte[] row1 = Bytes.toBytes("row1");
53 private final static byte[] row2 = Bytes.toBytes("row2");
54 private final static byte[] qf = Bytes.toBytes("qf");
55
56 private static HTable table;
57 private static Admin admin;
58
59 @BeforeClass
60 public static void setUpBeforeClass() throws Exception {
61 TEST_UTIL.getConfiguration().setInt("hbase.master.info.port", 0);
62 TEST_UTIL.getConfiguration().setBoolean("hbase.regionserver.info.port.auto", true);
63
64 TEST_UTIL.getConfiguration().setInt("hfile.format.version", 3);
65 }
66
67 @AfterClass
68 public static void tearDownAfterClass() throws Exception {
69
70 }
71
72 @Before
73 public void setUp() throws Exception {
74 TEST_UTIL.startMiniCluster(1);
75 }
76
77 @After
78 public void tearDown() throws Exception {
79 admin.disableTable(tableName);
80 admin.deleteTable(tableName);
81 admin.close();
82 TEST_UTIL.shutdownMiniCluster();
83 TEST_UTIL.getTestFileSystem().delete(TEST_UTIL.getDataTestDir(), true);
84 }
85
86 private void init() throws Exception {
87 HTableDescriptor desc = new HTableDescriptor(tableName);
88 HColumnDescriptor hcd = new HColumnDescriptor(family);
89 hcd.setMobEnabled(true);
90 hcd.setMobThreshold(3L);
91 hcd.setMaxVersions(4);
92 desc.addFamily(hcd);
93
94 admin = TEST_UTIL.getHBaseAdmin();
95 admin.createTable(desc);
96 table = new HTable(TEST_UTIL.getConfiguration(), tableName);
97 table.setAutoFlush(false, false);
98 }
99
100 private void modifyColumnExpiryDays(int expireDays) throws Exception {
101 HColumnDescriptor hcd = new HColumnDescriptor(family);
102 hcd.setMobEnabled(true);
103 hcd.setMobThreshold(3L);
104
105 int timeToLive = expireDays * secondsOfDay();
106 hcd.setTimeToLive(timeToLive);
107
108 admin.modifyColumn(tableName, hcd);
109 }
110
111 private void putKVAndFlush(HTable table, byte[] row, byte[] value, long ts)
112 throws Exception {
113
114 Put put = new Put(row, ts);
115 put.add(Bytes.toBytes(family), qf, value);
116 table.put(put);
117
118 table.flushCommits();
119 admin.flush(tableName);
120 }
121
122
123
124
125
126
127 @Test
128 public void testCleaner() throws Exception {
129 init();
130
131 Path mobDirPath = getMobFamilyPath(TEST_UTIL.getConfiguration(), tableName, family);
132
133 byte[] dummyData = makeDummyData(600);
134 long ts = System.currentTimeMillis() - 3 * secondsOfDay() * 1000;
135 putKVAndFlush(table, row1, dummyData, ts);
136 FileStatus[] firstFiles = TEST_UTIL.getTestFileSystem().listStatus(mobDirPath);
137
138 assertEquals("Before cleanup without delay 1", 1, firstFiles.length);
139 String firstFile = firstFiles[0].getPath().getName();
140
141 ts = System.currentTimeMillis() - 1 * secondsOfDay() * 1000;
142 putKVAndFlush(table, row2, dummyData, ts);
143 FileStatus[] secondFiles = TEST_UTIL.getTestFileSystem().listStatus(mobDirPath);
144
145 assertEquals("Before cleanup without delay 2", 2, secondFiles.length);
146 String f1 = secondFiles[0].getPath().getName();
147 String f2 = secondFiles[1].getPath().getName();
148 String secondFile = f1.equals(firstFile) ? f2 : f1;
149
150 modifyColumnExpiryDays(2);
151
152
153 String[] args = new String[2];
154 args[0] = tableName.getNameAsString();
155 args[1] = family;
156 ToolRunner.run(TEST_UTIL.getConfiguration(), new ExpiredMobFileCleaner(), args);
157
158 FileStatus[] filesAfterClean = TEST_UTIL.getTestFileSystem().listStatus(mobDirPath);
159 String lastFile = filesAfterClean[0].getPath().getName();
160
161 assertEquals("After cleanup without delay 1", 1, filesAfterClean.length);
162 assertEquals("After cleanup without delay 2", secondFile, lastFile);
163 }
164
165 private Path getMobFamilyPath(Configuration conf, TableName tableName, String familyName) {
166 Path p = new Path(MobUtils.getMobRegionPath(conf, tableName), familyName);
167 return p;
168 }
169
170 private int secondsOfDay() {
171 return 24 * 3600;
172 }
173
174 private byte[] makeDummyData(int size) {
175 byte [] dummyData = new byte[size];
176 new Random().nextBytes(dummyData);
177 return dummyData;
178 }
179 }