1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.client;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.fail;
23
24 import java.io.IOException;
25 import java.util.HashSet;
26 import java.util.Set;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.fs.Path;
31 import org.apache.hadoop.hbase.HBaseTestingUtility;
32 import org.apache.hadoop.hbase.HColumnDescriptor;
33 import org.apache.hadoop.hbase.HTableDescriptor;
34 import org.apache.hadoop.hbase.LargeTests;
35 import org.apache.hadoop.hbase.master.MasterFileSystem;
36 import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
37 import org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException;
38 import org.apache.hadoop.hbase.snapshot.CorruptedSnapshotException;
39 import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;
40 import org.apache.hadoop.hbase.util.Bytes;
41 import org.apache.hadoop.hbase.util.FSUtils;
42 import org.junit.After;
43 import org.junit.AfterClass;
44 import org.junit.Before;
45 import org.junit.BeforeClass;
46 import org.junit.Test;
47 import org.junit.experimental.categories.Category;
48
49
50
51
52 @Category(LargeTests.class)
53 public class TestRestoreSnapshotFromClient {
54 final Log LOG = LogFactory.getLog(getClass());
55
56 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
57
58 private final byte[] FAMILY = Bytes.toBytes("cf");
59
60 private byte[] emptySnapshot;
61 private byte[] snapshotName0;
62 private byte[] snapshotName1;
63 private byte[] snapshotName2;
64 private int snapshot0Rows;
65 private int snapshot1Rows;
66 private byte[] tableName;
67 private HBaseAdmin admin;
68
69 @BeforeClass
70 public static void setUpBeforeClass() throws Exception {
71 TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
72 TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
73 TEST_UTIL.getConfiguration().setInt("hbase.hstore.compactionThreshold", 10);
74 TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
75 TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
76 TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6);
77 TEST_UTIL.getConfiguration().setBoolean(
78 "hbase.master.enabletable.roundrobin", true);
79 TEST_UTIL.startMiniCluster(3);
80 }
81
82 @AfterClass
83 public static void tearDownAfterClass() throws Exception {
84 TEST_UTIL.shutdownMiniCluster();
85 }
86
87
88
89
90
91
92 @Before
93 public void setup() throws Exception {
94 this.admin = TEST_UTIL.getHBaseAdmin();
95
96 long tid = System.currentTimeMillis();
97 tableName = Bytes.toBytes("testtb-" + tid);
98 emptySnapshot = Bytes.toBytes("emptySnaptb-" + tid);
99 snapshotName0 = Bytes.toBytes("snaptb0-" + tid);
100 snapshotName1 = Bytes.toBytes("snaptb1-" + tid);
101 snapshotName2 = Bytes.toBytes("snaptb2-" + tid);
102
103
104 SnapshotTestingUtils.createTable(TEST_UTIL, tableName, FAMILY);
105 admin.disableTable(tableName);
106
107
108 admin.snapshot(emptySnapshot, tableName);
109
110 HTable table = new HTable(TEST_UTIL.getConfiguration(), tableName);
111
112 admin.enableTable(tableName);
113 SnapshotTestingUtils.loadData(TEST_UTIL, table, 500, FAMILY);
114 snapshot0Rows = TEST_UTIL.countRows(table);
115 admin.disableTable(tableName);
116
117
118 admin.snapshot(snapshotName0, tableName);
119
120
121 admin.enableTable(tableName);
122 SnapshotTestingUtils.loadData(TEST_UTIL, table, 500, FAMILY);
123 snapshot1Rows = TEST_UTIL.countRows(table);
124 table.close();
125 }
126
127 @After
128 public void tearDown() throws Exception {
129 TEST_UTIL.deleteTable(tableName);
130 SnapshotTestingUtils.deleteAllSnapshots(TEST_UTIL.getHBaseAdmin());
131 SnapshotTestingUtils.deleteArchiveDirectory(TEST_UTIL);
132 }
133
134 @Test
135 public void testRestoreSnapshot() throws IOException {
136 SnapshotTestingUtils.verifyRowCount(TEST_UTIL, tableName, snapshot1Rows);
137 admin.disableTable(tableName);
138 admin.snapshot(snapshotName1, tableName);
139
140 admin.restoreSnapshot(snapshotName0);
141 admin.enableTable(tableName);
142 SnapshotTestingUtils.verifyRowCount(TEST_UTIL, tableName, snapshot0Rows);
143
144
145 admin.disableTable(tableName);
146 admin.restoreSnapshot(emptySnapshot);
147 admin.enableTable(tableName);
148 SnapshotTestingUtils.verifyRowCount(TEST_UTIL, tableName, 0);
149
150
151 admin.disableTable(tableName);
152 admin.restoreSnapshot(snapshotName1);
153 admin.enableTable(tableName);
154 SnapshotTestingUtils.verifyRowCount(TEST_UTIL, tableName, snapshot1Rows);
155 }
156
157 @Test
158 public void testRestoreSchemaChange() throws Exception {
159 byte[] TEST_FAMILY2 = Bytes.toBytes("cf2");
160
161 HTable table = new HTable(TEST_UTIL.getConfiguration(), tableName);
162
163
164 admin.disableTable(tableName);
165 admin.addColumn(tableName, new HColumnDescriptor(TEST_FAMILY2));
166 admin.enableTable(tableName);
167 assertEquals(2, table.getTableDescriptor().getFamilies().size());
168 HTableDescriptor htd = admin.getTableDescriptor(tableName);
169 assertEquals(2, htd.getFamilies().size());
170 SnapshotTestingUtils.loadData(TEST_UTIL, table, 500, TEST_FAMILY2);
171 long snapshot2Rows = snapshot1Rows + 500;
172 assertEquals(snapshot2Rows, TEST_UTIL.countRows(table));
173 assertEquals(500, TEST_UTIL.countRows(table, TEST_FAMILY2));
174 Set<String> fsFamilies = getFamiliesFromFS(tableName);
175 assertEquals(2, fsFamilies.size());
176 table.close();
177
178
179 admin.disableTable(tableName);
180 admin.snapshot(snapshotName2, tableName);
181
182
183 admin.restoreSnapshot(snapshotName0);
184 assertEquals(1, table.getTableDescriptor().getFamilies().size());
185 admin.enableTable(tableName);
186 try {
187 TEST_UTIL.countRows(table, TEST_FAMILY2);
188 fail("family '" + Bytes.toString(TEST_FAMILY2) + "' should not exists");
189 } catch (NoSuchColumnFamilyException e) {
190
191 }
192 assertEquals(snapshot0Rows, TEST_UTIL.countRows(table));
193 htd = admin.getTableDescriptor(tableName);
194 assertEquals(1, htd.getFamilies().size());
195 fsFamilies = getFamiliesFromFS(tableName);
196 assertEquals(1, fsFamilies.size());
197 table.close();
198
199
200 admin.disableTable(tableName);
201 admin.restoreSnapshot(snapshotName2);
202 admin.enableTable(tableName);
203 htd = admin.getTableDescriptor(tableName);
204 assertEquals(2, htd.getFamilies().size());
205 assertEquals(2, table.getTableDescriptor().getFamilies().size());
206 assertEquals(500, TEST_UTIL.countRows(table, TEST_FAMILY2));
207 assertEquals(snapshot2Rows, TEST_UTIL.countRows(table));
208 fsFamilies = getFamiliesFromFS(tableName);
209 assertEquals(2, fsFamilies.size());
210 table.close();
211 }
212
213 @Test
214 public void testCloneSnapshotOfCloned() throws IOException, InterruptedException {
215 byte[] clonedTableName = Bytes.toBytes("clonedtb-" + System.currentTimeMillis());
216 admin.cloneSnapshot(snapshotName0, clonedTableName);
217 SnapshotTestingUtils.verifyRowCount(TEST_UTIL, clonedTableName, snapshot0Rows);
218 admin.disableTable(clonedTableName);
219 admin.snapshot(snapshotName2, clonedTableName);
220 admin.deleteTable(clonedTableName);
221 waitCleanerRun();
222
223 admin.cloneSnapshot(snapshotName2, clonedTableName);
224 SnapshotTestingUtils.verifyRowCount(TEST_UTIL, clonedTableName, snapshot0Rows);
225 TEST_UTIL.deleteTable(clonedTableName);
226 }
227
228 @Test
229 public void testCloneAndRestoreSnapshot() throws IOException, InterruptedException {
230 TEST_UTIL.deleteTable(tableName);
231 waitCleanerRun();
232
233 admin.cloneSnapshot(snapshotName0, tableName);
234 SnapshotTestingUtils.verifyRowCount(TEST_UTIL, tableName, snapshot0Rows);
235 waitCleanerRun();
236
237 admin.disableTable(tableName);
238 admin.restoreSnapshot(snapshotName0);
239 admin.enableTable(tableName);
240 SnapshotTestingUtils.verifyRowCount(TEST_UTIL, tableName, snapshot0Rows);
241 }
242
243 @Test
244 public void testCorruptedSnapshot() throws IOException, InterruptedException {
245 SnapshotTestingUtils.corruptSnapshot(TEST_UTIL, Bytes.toString(snapshotName0));
246 byte[] cloneName = Bytes.toBytes("corruptedClone-" + System.currentTimeMillis());
247 try {
248 admin.cloneSnapshot(snapshotName0, cloneName);
249 fail("Expected CorruptedSnapshotException, got succeeded cloneSnapshot()");
250 } catch (CorruptedSnapshotException e) {
251
252
253 assertFalse(admin.tableExists(cloneName));
254 } catch (Exception e) {
255 fail("Expected CorruptedSnapshotException got: " + e);
256 }
257 }
258
259
260
261
262 private void waitCleanerRun() throws InterruptedException {
263 TEST_UTIL.getMiniHBaseCluster().getMaster().getHFileCleaner().choreForTesting();
264 }
265
266 private Set<String> getFamiliesFromFS(final byte[] tableName) throws IOException {
267 MasterFileSystem mfs = TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterFileSystem();
268 Set<String> families = new HashSet<String>();
269 Path tableDir = HTableDescriptor.getTableDir(mfs.getRootDir(), tableName);
270 for (Path regionDir: FSUtils.getRegionDirs(mfs.getFileSystem(), tableDir)) {
271 for (Path familyDir: FSUtils.getFamilyDirs(mfs.getFileSystem(), regionDir)) {
272 families.add(familyDir.getName());
273 }
274 }
275 return families;
276 }
277 }