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.master.cleaner; 019 020import java.io.IOException; 021import java.util.ArrayList; 022import java.util.List; 023import org.apache.hadoop.conf.Configuration; 024import org.apache.hadoop.hbase.HBaseTestingUtil; 025import org.apache.hadoop.hbase.Stoppable; 026import org.apache.hadoop.hbase.master.snapshot.SnapshotManager; 027import org.apache.hadoop.hbase.testclassification.MasterTests; 028import org.apache.hadoop.hbase.testclassification.SmallTests; 029import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 030import org.junit.jupiter.api.Tag; 031import org.junit.jupiter.api.Test; 032import org.mockito.Mockito; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos; 037 038/** 039 * Tests for SnapshotsCleanerChore 040 */ 041@Tag(MasterTests.TAG) 042@Tag(SmallTests.TAG) 043public class TestSnapshotCleanerChore { 044 045 private static final Logger LOG = LoggerFactory.getLogger(TestSnapshotCleanerChore.class); 046 047 private static final HBaseTestingUtil HBASE_TESTING_UTILITY = new HBaseTestingUtil(); 048 049 private SnapshotManager snapshotManager; 050 051 private Configuration getSnapshotCleanerConf() { 052 Configuration conf = HBASE_TESTING_UTILITY.getConfiguration(); 053 conf.setInt("hbase.master.cleaner.snapshot.interval", 100); 054 return conf; 055 } 056 057 @Test 058 public void testSnapshotCleanerWithoutAnyCompletedSnapshot() throws IOException { 059 snapshotManager = Mockito.mock(SnapshotManager.class); 060 Stoppable stopper = new StoppableImplementation(); 061 Configuration conf = getSnapshotCleanerConf(); 062 SnapshotCleanerChore snapshotCleanerChore = 063 new SnapshotCleanerChore(stopper, conf, snapshotManager); 064 try { 065 snapshotCleanerChore.chore(); 066 } finally { 067 stopper.stop("Stopping Test Stopper"); 068 } 069 Mockito.verify(snapshotManager, Mockito.times(0)).deleteSnapshot(Mockito.any()); 070 } 071 072 @Test 073 public void testSnapshotCleanerWithNoTtlExpired() throws IOException { 074 snapshotManager = Mockito.mock(SnapshotManager.class); 075 Stoppable stopper = new StoppableImplementation(); 076 Configuration conf = getSnapshotCleanerConf(); 077 SnapshotCleanerChore snapshotCleanerChore = 078 new SnapshotCleanerChore(stopper, conf, snapshotManager); 079 List<SnapshotProtos.SnapshotDescription> snapshotDescriptionList = new ArrayList<>(); 080 snapshotDescriptionList.add(getSnapshotDescription(-2, "snapshot01", "table01", 081 EnvironmentEdgeManager.currentTime() - 100000)); 082 snapshotDescriptionList.add( 083 getSnapshotDescription(10, "snapshot02", "table02", EnvironmentEdgeManager.currentTime())); 084 Mockito.when(snapshotManager.getCompletedSnapshots()).thenReturn(snapshotDescriptionList); 085 try { 086 LOG.info("2 Snapshots are completed but TTL is not expired for any of them"); 087 snapshotCleanerChore.chore(); 088 } finally { 089 stopper.stop("Stopping Test Stopper"); 090 } 091 Mockito.verify(snapshotManager, Mockito.times(0)).deleteSnapshot(Mockito.any()); 092 } 093 094 @Test 095 public void testSnapshotCleanerWithSomeTtlExpired() throws IOException { 096 snapshotManager = Mockito.mock(SnapshotManager.class); 097 Stoppable stopper = new StoppableImplementation(); 098 Configuration conf = getSnapshotCleanerConf(); 099 SnapshotCleanerChore snapshotCleanerChore = 100 new SnapshotCleanerChore(stopper, conf, snapshotManager); 101 List<SnapshotProtos.SnapshotDescription> snapshotDescriptionList = new ArrayList<>(); 102 snapshotDescriptionList.add(getSnapshotDescription(10, "snapshot01", "table01", 1)); 103 snapshotDescriptionList.add(getSnapshotDescription(5, "snapshot02", "table02", 2)); 104 snapshotDescriptionList.add( 105 getSnapshotDescription(30, "snapshot01", "table01", EnvironmentEdgeManager.currentTime())); 106 snapshotDescriptionList.add( 107 getSnapshotDescription(0, "snapshot02", "table02", EnvironmentEdgeManager.currentTime())); 108 snapshotDescriptionList.add( 109 getSnapshotDescription(40, "snapshot03", "table03", EnvironmentEdgeManager.currentTime())); 110 Mockito.when(snapshotManager.getCompletedSnapshots()).thenReturn(snapshotDescriptionList); 111 try { 112 LOG.info("5 Snapshots are completed. TTL is expired for 2 them. Going to delete them"); 113 snapshotCleanerChore.chore(); 114 } finally { 115 stopper.stop("Stopping Test Stopper"); 116 } 117 Mockito.verify(snapshotManager, Mockito.times(2)).deleteSnapshot(Mockito.any()); 118 } 119 120 @Test 121 public void testSnapshotCleanerWithReadIOE() throws IOException { 122 snapshotManager = Mockito.mock(SnapshotManager.class); 123 Stoppable stopper = new StoppableImplementation(); 124 Configuration conf = new HBaseTestingUtil().getConfiguration(); 125 SnapshotCleanerChore snapshotCleanerChore = 126 new SnapshotCleanerChore(stopper, conf, snapshotManager); 127 Mockito.when(snapshotManager.getCompletedSnapshots()).thenThrow(IOException.class); 128 try { 129 LOG.info("While getting completed Snapshots, IOException would occur. Hence, No Snapshot" 130 + " should be deleted"); 131 snapshotCleanerChore.chore(); 132 } finally { 133 stopper.stop("Stopping Test Stopper"); 134 } 135 Mockito.verify(snapshotManager, Mockito.times(0)).deleteSnapshot(Mockito.any()); 136 } 137 138 @Test 139 public void testSnapshotChoreWithTtlOutOfRange() throws IOException { 140 snapshotManager = Mockito.mock(SnapshotManager.class); 141 Stoppable stopper = new StoppableImplementation(); 142 Configuration conf = getSnapshotCleanerConf(); 143 List<SnapshotProtos.SnapshotDescription> snapshotDescriptionList = new ArrayList<>(); 144 snapshotDescriptionList.add(getSnapshotDescription(Long.MAX_VALUE, "snapshot01", "table01", 1)); 145 snapshotDescriptionList.add(getSnapshotDescription(5, "snapshot02", "table02", 2)); 146 Mockito.when(snapshotManager.getCompletedSnapshots()).thenReturn(snapshotDescriptionList); 147 SnapshotCleanerChore snapshotCleanerChore = 148 new SnapshotCleanerChore(stopper, conf, snapshotManager); 149 try { 150 LOG.info("Snapshot Chore is disabled. No cleanup performed for Expired Snapshots"); 151 snapshotCleanerChore.chore(); 152 } finally { 153 stopper.stop("Stopping Test Stopper"); 154 } 155 Mockito.verify(snapshotManager, Mockito.times(1)).getCompletedSnapshots(); 156 } 157 158 private SnapshotProtos.SnapshotDescription getSnapshotDescription(final long ttl, 159 final String snapshotName, final String tableName, final long snapshotCreationTime) { 160 SnapshotProtos.SnapshotDescription.Builder snapshotDescriptionBuilder = 161 SnapshotProtos.SnapshotDescription.newBuilder(); 162 snapshotDescriptionBuilder.setTtl(ttl); 163 snapshotDescriptionBuilder.setName(snapshotName); 164 snapshotDescriptionBuilder.setTable(tableName); 165 snapshotDescriptionBuilder.setType(SnapshotProtos.SnapshotDescription.Type.FLUSH); 166 snapshotDescriptionBuilder.setCreationTime(snapshotCreationTime); 167 return snapshotDescriptionBuilder.build(); 168 } 169 170 /** 171 * Simple helper class that just keeps track of whether or not its stopped. 172 */ 173 private static class StoppableImplementation implements Stoppable { 174 175 private volatile boolean stop = false; 176 177 @Override 178 public void stop(String why) { 179 this.stop = true; 180 } 181 182 @Override 183 public boolean isStopped() { 184 return this.stop; 185 } 186 187 } 188 189}