001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.client;
019
020import static org.junit.jupiter.api.Assertions.assertArrayEquals;
021import static org.junit.jupiter.api.Assertions.assertEquals;
022import static org.junit.jupiter.api.Assertions.assertNotNull;
023import static org.junit.jupiter.api.Assertions.assertTrue;
024
025import java.io.IOException;
026import java.util.Collections;
027import java.util.List;
028import java.util.function.Supplier;
029import java.util.regex.Pattern;
030import org.apache.hadoop.hbase.HBaseParameterizedTestTemplate;
031import org.apache.hadoop.hbase.TableName;
032import org.apache.hadoop.hbase.testclassification.ClientTests;
033import org.apache.hadoop.hbase.testclassification.LargeTests;
034import org.apache.hadoop.hbase.util.Bytes;
035import org.junit.jupiter.api.AfterAll;
036import org.junit.jupiter.api.AfterEach;
037import org.junit.jupiter.api.BeforeAll;
038import org.junit.jupiter.api.Tag;
039import org.junit.jupiter.api.TestInfo;
040import org.junit.jupiter.api.TestTemplate;
041
042@Tag(LargeTests.TAG)
043@Tag(ClientTests.TAG)
044@HBaseParameterizedTestTemplate(name = "{index}: policy = {0}")
045public class TestAsyncSnapshotAdminApi extends TestAsyncAdminBase {
046
047  private static final Pattern MATCH_ALL = Pattern.compile(".*");
048
049  String snapshotName1 = "snapshotName1";
050  String snapshotName2 = "snapshotName2";
051  String snapshotName3 = "snapshotName3";
052
053  public TestAsyncSnapshotAdminApi(Supplier<AsyncAdmin> admin) {
054    super(admin);
055  }
056
057  @BeforeAll
058  public static void setUpBeforeClass() throws Exception {
059    TestAsyncAdminBase.setUpBeforeClass();
060  }
061
062  @AfterAll
063  public static void tearDownAfterClass() throws Exception {
064    TestAsyncAdminBase.tearDownAfterClass();
065  }
066
067  @AfterEach
068  public void cleanup() throws Exception {
069    admin.deleteSnapshots(MATCH_ALL).get();
070    admin.listTableNames().get().forEach(t -> admin.disableTable(t).join());
071    admin.listTableNames().get().forEach(t -> admin.deleteTable(t).join());
072  }
073
074  @TestTemplate
075  public void testTakeSnapshot() throws Exception {
076    Admin syncAdmin = TEST_UTIL.getAdmin();
077
078    Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
079    for (int i = 0; i < 3000; i++) {
080      table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
081        Bytes.toBytes(i)));
082    }
083
084    admin.snapshot(snapshotName1, tableName).get();
085    admin.snapshot(snapshotName2, tableName).get();
086    List<SnapshotDescription> snapshots = syncAdmin.listSnapshots();
087    Collections.sort(snapshots, (snap1, snap2) -> {
088      assertNotNull(snap1);
089      assertNotNull(snap1.getName());
090      assertNotNull(snap2);
091      assertNotNull(snap2.getName());
092      return snap1.getName().compareTo(snap2.getName());
093    });
094
095    assertEquals(snapshotName1, snapshots.get(0).getName());
096    assertEquals(tableName, snapshots.get(0).getTableName());
097    assertEquals(SnapshotType.FLUSH, snapshots.get(0).getType());
098    assertEquals(snapshotName2, snapshots.get(1).getName());
099    assertEquals(tableName, snapshots.get(1).getTableName());
100    assertEquals(SnapshotType.FLUSH, snapshots.get(1).getType());
101  }
102
103  @TestTemplate
104  public void testCloneSnapshot() throws Exception {
105    TableName tableName2 = TableName.valueOf("testCloneSnapshot2");
106    Admin syncAdmin = TEST_UTIL.getAdmin();
107
108    Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
109    for (int i = 0; i < 3000; i++) {
110      table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
111        Bytes.toBytes(i)));
112    }
113
114    admin.snapshot(snapshotName1, tableName).get();
115    List<SnapshotDescription> snapshots = syncAdmin.listSnapshots();
116    assertEquals(1, snapshots.size());
117    assertEquals(snapshotName1, snapshots.get(0).getName());
118    assertEquals(tableName, snapshots.get(0).getTableName());
119    assertEquals(SnapshotType.FLUSH, snapshots.get(0).getType());
120
121    // cloneSnapshot into a existed table.
122    boolean failed = false;
123    try {
124      admin.cloneSnapshot(snapshotName1, tableName).get();
125    } catch (Exception e) {
126      failed = true;
127    }
128    assertTrue(failed);
129
130    // cloneSnapshot into a new table.
131    assertTrue(!syncAdmin.tableExists(tableName2));
132    admin.cloneSnapshot(snapshotName1, tableName2).get();
133    syncAdmin.tableExists(tableName2);
134  }
135
136  private void assertResult(TableName tableName, int expectedRowCount) throws IOException {
137    try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
138      Scan scan = new Scan();
139      try (ResultScanner scanner = table.getScanner(scan)) {
140        Result result;
141        int rowCount = 0;
142        while ((result = scanner.next()) != null) {
143          assertArrayEquals(result.getRow(), Bytes.toBytes(rowCount));
144          assertArrayEquals(result.getValue(Bytes.toBytes("f1"), Bytes.toBytes("cq")),
145            Bytes.toBytes(rowCount));
146          rowCount += 1;
147        }
148        assertEquals(rowCount, expectedRowCount);
149      }
150    }
151  }
152
153  @TestTemplate
154  public void testRestoreSnapshot() throws Exception {
155    Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
156    for (int i = 0; i < 3000; i++) {
157      table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
158        Bytes.toBytes(i)));
159    }
160    assertEquals(0, admin.listSnapshots().get().size());
161
162    admin.snapshot(snapshotName1, tableName).get();
163    admin.snapshot(snapshotName2, tableName).get();
164    assertEquals(2, admin.listSnapshots().get().size());
165
166    admin.disableTable(tableName).get();
167    admin.restoreSnapshot(snapshotName1, true).get();
168    admin.enableTable(tableName).get();
169    assertResult(tableName, 3000);
170
171    admin.disableTable(tableName).get();
172    admin.restoreSnapshot(snapshotName2, false).get();
173    admin.enableTable(tableName).get();
174    assertResult(tableName, 3000);
175  }
176
177  @TestTemplate
178  public void testListSnapshots(TestInfo testInfo) throws Exception {
179    tableName = TableName.valueOf(testInfo.getTestMethod().get().getName());
180    Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
181    for (int i = 0; i < 3000; i++) {
182      table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
183        Bytes.toBytes(i)));
184    }
185    assertEquals(0, admin.listSnapshots().get().size());
186
187    admin.snapshot(snapshotName1, tableName).get();
188    admin.snapshot(snapshotName2, tableName).get();
189    admin.snapshot(snapshotName3, tableName).get();
190    assertEquals(3, admin.listSnapshots().get().size());
191
192    assertEquals(3, admin.listSnapshots(Pattern.compile("(.*)")).get().size());
193    assertEquals(3, admin.listSnapshots(Pattern.compile("snapshotName(\\d+)")).get().size());
194    assertEquals(2, admin.listSnapshots(Pattern.compile("snapshotName[1|3]")).get().size());
195    assertEquals(3, admin.listSnapshots(Pattern.compile("snapshot(.*)")).get().size());
196    assertEquals(3,
197      admin.listTableSnapshots(Pattern.compile("testListSnapshots"), Pattern.compile("s(.*)")).get()
198        .size());
199    assertEquals(0,
200      admin.listTableSnapshots(Pattern.compile("fakeTableName"), Pattern.compile("snap(.*)")).get()
201        .size());
202    assertEquals(2,
203      admin.listTableSnapshots(Pattern.compile("test(.*)"), Pattern.compile("snap(.*)[1|3]")).get()
204        .size());
205  }
206
207  @TestTemplate
208  public void testDeleteSnapshots() throws Exception {
209    Table table = TEST_UTIL.createTable(tableName, Bytes.toBytes("f1"));
210    for (int i = 0; i < 3000; i++) {
211      table.put(new Put(Bytes.toBytes(i)).addColumn(Bytes.toBytes("f1"), Bytes.toBytes("cq"),
212        Bytes.toBytes(i)));
213    }
214    assertEquals(0, admin.listSnapshots().get().size());
215
216    admin.snapshot(snapshotName1, tableName).get();
217    admin.snapshot(snapshotName2, tableName).get();
218    admin.snapshot(snapshotName3, tableName).get();
219    assertEquals(3, admin.listSnapshots().get().size());
220
221    admin.deleteSnapshot(snapshotName1).get();
222    assertEquals(2, admin.listSnapshots().get().size());
223
224    admin.deleteSnapshots(Pattern.compile("(.*)abc")).get();
225    assertEquals(2, admin.listSnapshots().get().size());
226
227    admin.deleteSnapshots(Pattern.compile("(.*)1")).get();
228    assertEquals(2, admin.listSnapshots().get().size());
229
230    admin.deleteTableSnapshots(Pattern.compile("(.*)"), Pattern.compile("(.*)1")).get();
231    assertEquals(2, admin.listSnapshots().get().size());
232
233    admin.deleteTableSnapshots(Pattern.compile("(.*)"), Pattern.compile("(.*)2")).get();
234    assertEquals(1, admin.listSnapshots().get().size());
235
236    admin.deleteTableSnapshots(Pattern.compile("(.*)"), Pattern.compile("(.*)3")).get();
237    assertEquals(0, admin.listSnapshots().get().size());
238  }
239}