View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.master.cleaner;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.List;
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.HBaseTestingUtility;
28  import org.apache.hadoop.hbase.Stoppable;
29  import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
30  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
31  import org.apache.hadoop.hbase.testclassification.MasterTests;
32  import org.apache.hadoop.hbase.testclassification.SmallTests;
33  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
34  import org.junit.Test;
35  import org.junit.experimental.categories.Category;
36  import org.mockito.Mockito;
37  
38  /**
39   * Tests for SnapshotsCleanerChore
40   */
41  @Category({MasterTests.class, SmallTests.class})
42  public class TestSnapshotCleanerChore {
43  
44    private static final Log LOG = LogFactory.getLog(TestSnapshotCleanerChore.class);
45  
46    private static final HBaseTestingUtility HBASE_TESTING_UTILITY = new HBaseTestingUtility();
47  
48    private SnapshotManager snapshotManager;
49  
50    private Configuration getSnapshotCleanerConf() {
51      Configuration conf = HBASE_TESTING_UTILITY.getConfiguration();
52      conf.setInt("hbase.master.cleaner.snapshot.interval", 100);
53      return conf;
54    }
55  
56  
57    @Test
58    public void testSnapshotCleanerWithoutAnyCompletedSnapshot() throws IOException {
59      snapshotManager = Mockito.mock(SnapshotManager.class);
60      Stoppable stopper = new StoppableImplementation();
61      Configuration conf = getSnapshotCleanerConf();
62      SnapshotCleanerChore snapshotCleanerChore =
63              new SnapshotCleanerChore(stopper, conf, snapshotManager);
64      try {
65        snapshotCleanerChore.chore();
66      } finally {
67        stopper.stop("Stopping Test Stopper");
68      }
69      Mockito.verify(snapshotManager, Mockito.times(0))
70        .deleteSnapshot(Mockito.any(SnapshotDescription.class));
71    }
72  
73    @Test
74    public void testSnapshotCleanerWithNoTtlExpired() throws IOException {
75      snapshotManager = Mockito.mock(SnapshotManager.class);
76      Stoppable stopper = new StoppableImplementation();
77      Configuration conf = getSnapshotCleanerConf();
78      SnapshotCleanerChore snapshotCleanerChore =
79              new SnapshotCleanerChore(stopper, conf, snapshotManager);
80      List<SnapshotDescription> snapshotDescriptionList = new ArrayList<>();
81      snapshotDescriptionList.add(getSnapshotDescription(-2, "snapshot01", "table01",
82              EnvironmentEdgeManager.currentTime() - 100000));
83      snapshotDescriptionList.add(getSnapshotDescription(10, "snapshot02", "table02",
84              EnvironmentEdgeManager.currentTime()));
85      Mockito.when(snapshotManager.getCompletedSnapshots()).thenReturn(snapshotDescriptionList);
86      try {
87        LOG.info("2 Snapshots are completed but TTL is not expired for any of them");
88        snapshotCleanerChore.chore();
89      } finally {
90        stopper.stop("Stopping Test Stopper");
91      }
92      Mockito.verify(snapshotManager, Mockito.times(0))
93        .deleteSnapshot(Mockito.any(SnapshotDescription.class));
94    }
95  
96    @Test
97    public void testSnapshotCleanerWithSomeTtlExpired() throws IOException {
98      snapshotManager = Mockito.mock(SnapshotManager.class);
99      Stoppable stopper = new StoppableImplementation();
100     Configuration conf = getSnapshotCleanerConf();
101     SnapshotCleanerChore snapshotCleanerChore =
102             new SnapshotCleanerChore(stopper, conf, snapshotManager);
103     List<SnapshotDescription> snapshotDescriptionList = new ArrayList<>();
104     snapshotDescriptionList.add(getSnapshotDescription(10, "snapshot01", "table01", 1));
105     snapshotDescriptionList.add(getSnapshotDescription(5, "snapshot02", "table02", 2));
106     snapshotDescriptionList.add(getSnapshotDescription(30, "snapshot01", "table01",
107             EnvironmentEdgeManager.currentTime()));
108     snapshotDescriptionList.add(getSnapshotDescription(0, "snapshot02", "table02",
109             EnvironmentEdgeManager.currentTime()));
110     snapshotDescriptionList.add(getSnapshotDescription(40, "snapshot03", "table03",
111             EnvironmentEdgeManager.currentTime()));
112     Mockito.when(snapshotManager.getCompletedSnapshots()).thenReturn(snapshotDescriptionList);
113     try {
114       LOG.info("5 Snapshots are completed. TTL is expired for 2 them. Going to delete them");
115       snapshotCleanerChore.chore();
116     } finally {
117       stopper.stop("Stopping Test Stopper");
118     }
119     Mockito.verify(snapshotManager, Mockito.times(2))
120       .deleteSnapshot(Mockito.any(SnapshotDescription.class));
121   }
122 
123   @Test
124   public void testSnapshotCleanerWithReadIOE() throws IOException {
125     snapshotManager = Mockito.mock(SnapshotManager.class);
126     Stoppable stopper = new StoppableImplementation();
127     Configuration conf = new HBaseTestingUtility().getConfiguration();
128     SnapshotCleanerChore snapshotCleanerChore =
129             new SnapshotCleanerChore(stopper, conf, snapshotManager);
130     Mockito.when(snapshotManager.getCompletedSnapshots()).thenThrow(IOException.class);
131     try {
132       LOG.info("While getting completed Snapshots, IOException would occur. Hence, No Snapshot"
133               + " should be deleted");
134       snapshotCleanerChore.chore();
135     } finally {
136       stopper.stop("Stopping Test Stopper");
137     }
138     Mockito.verify(snapshotManager, Mockito.times(0))
139       .deleteSnapshot(Mockito.any(SnapshotDescription.class));
140   }
141 
142   @Test
143   public void testSnapshotChoreWithTtlOutOfRange() throws IOException {
144     snapshotManager = Mockito.mock(SnapshotManager.class);
145     Stoppable stopper = new StoppableImplementation();
146     Configuration conf = getSnapshotCleanerConf();
147     List<SnapshotDescription> snapshotDescriptionList = new ArrayList<>();
148     snapshotDescriptionList.add(getSnapshotDescription(Long.MAX_VALUE, "snapshot01", "table01", 1));
149     snapshotDescriptionList.add(getSnapshotDescription(5, "snapshot02", "table02", 2));
150     Mockito.when(snapshotManager.getCompletedSnapshots()).thenReturn(snapshotDescriptionList);
151     SnapshotCleanerChore snapshotCleanerChore =
152             new SnapshotCleanerChore(stopper, conf, snapshotManager);
153     try {
154       LOG.info("Snapshot Chore is disabled. No cleanup performed for Expired Snapshots");
155       snapshotCleanerChore.chore();
156     } finally {
157       stopper.stop("Stopping Test Stopper");
158     }
159     Mockito.verify(snapshotManager, Mockito.times(1)).getCompletedSnapshots();
160   }
161 
162   private SnapshotDescription getSnapshotDescription(final long ttl,
163           final String snapshotName, final String tableName, final long snapshotCreationTime) {
164     SnapshotDescription.Builder snapshotDescriptionBuilder =
165         SnapshotDescription.newBuilder();
166     snapshotDescriptionBuilder.setTtl(ttl);
167     snapshotDescriptionBuilder.setName(snapshotName);
168     snapshotDescriptionBuilder.setTable(tableName);
169     snapshotDescriptionBuilder.setType(SnapshotDescription.Type.FLUSH);
170     snapshotDescriptionBuilder.setCreationTime(snapshotCreationTime);
171     return snapshotDescriptionBuilder.build();
172   }
173 
174   /**
175    * Simple helper class that just keeps track of whether or not its stopped.
176    */
177   private static class StoppableImplementation implements Stoppable {
178 
179     private volatile boolean stop = false;
180 
181     @Override
182     public void stop(String why) {
183       this.stop = true;
184     }
185 
186     @Override
187     public boolean isStopped() {
188       return this.stop;
189     }
190 
191   }
192 
193 }