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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org
.apache
.hadoop
.hbase
.util
;
20 import static org
.junit
.Assert
.assertEquals
;
21 import static org
.junit
.Assert
.assertNull
;
23 import java
.io
.IOException
;
24 import java
.util
.ArrayList
;
25 import java
.util
.Arrays
;
26 import java
.util
.Collections
;
27 import java
.util
.List
;
28 import org
.apache
.hadoop
.conf
.Configuration
;
29 import org
.apache
.hadoop
.fs
.FileStatus
;
30 import org
.apache
.hadoop
.fs
.FileSystem
;
31 import org
.apache
.hadoop
.fs
.Path
;
32 import org
.apache
.hadoop
.hbase
.HBaseTestingUtil
;
33 import org
.apache
.hadoop
.hbase
.regionserver
.HRegion
;
34 import org
.apache
.hadoop
.hbase
.regionserver
.Store
;
35 import org
.slf4j
.Logger
;
36 import org
.slf4j
.LoggerFactory
;
39 * Test helper for testing archiving of HFiles
41 public class HFileArchiveTestingUtil
{
43 private static final Logger LOG
= LoggerFactory
.getLogger(HFileArchiveTestingUtil
.class);
45 private HFileArchiveTestingUtil() {
46 // NOOP private ctor since this is just a utility class
49 public static boolean compareArchiveToOriginal(FileStatus
[] previous
, FileStatus
[] archived
,
50 FileSystem fs
, boolean hasTimedBackup
) {
52 List
<List
<String
>> lists
= getFileLists(previous
, archived
);
53 List
<String
> original
= lists
.get(0);
54 Collections
.sort(original
);
56 List
<String
> currentFiles
= lists
.get(1);
57 Collections
.sort(currentFiles
);
59 List
<String
> backedup
= lists
.get(2);
60 Collections
.sort(backedup
);
62 // check the backed up files versus the current (should match up, less the
63 // backup time in the name)
64 if (!hasTimedBackup
== (backedup
.size() > 0)) {
65 LOG
.debug("backedup files doesn't match expected.");
70 msg
= assertArchiveEquality(original
, backedup
);
76 msg
= assertArchiveEquality(original
, currentFiles
);
85 * Compare the archived files to the files in the original directory
86 * @param expected original files that should have been archived
87 * @param actual files that were archived
88 * @param fs filessystem on which the archiving took place
91 public static void assertArchiveEqualToOriginal(FileStatus
[] expected
, FileStatus
[] actual
,
92 FileSystem fs
) throws IOException
{
93 assertArchiveEqualToOriginal(expected
, actual
, fs
, false);
97 * Compare the archived files to the files in the original directory
98 * @param expected original files that should have been archived
99 * @param actual files that were archived
100 * @param fs {@link FileSystem} on which the archiving took place
101 * @param hasTimedBackup <tt>true</tt> if we expect to find an archive backup directory with a
102 * copy of the files in the archive directory (and the original files).
103 * @throws IOException
105 public static void assertArchiveEqualToOriginal(FileStatus
[] expected
, FileStatus
[] actual
,
106 FileSystem fs
, boolean hasTimedBackup
) throws IOException
{
108 List
<List
<String
>> lists
= getFileLists(expected
, actual
);
109 List
<String
> original
= lists
.get(0);
110 Collections
.sort(original
);
112 List
<String
> currentFiles
= lists
.get(1);
113 Collections
.sort(currentFiles
);
115 List
<String
> backedup
= lists
.get(2);
116 Collections
.sort(backedup
);
118 // check the backed up files versus the current (should match up, less the
119 // backup time in the name)
120 assertEquals("Didn't expect any backup files, but got: " + backedup
, hasTimedBackup
,
121 backedup
.size() > 0);
123 if (hasTimedBackup
) {
124 assertArchiveEquality(original
, backedup
);
125 assertNull(msg
, msg
);
128 // do the rest of the comparison
129 msg
= assertArchiveEquality(original
, currentFiles
);
130 assertNull(msg
, msg
);
133 private static String
assertArchiveEquality(List
<String
> expected
, List
<String
> archived
) {
134 String compare
= compareFileLists(expected
, archived
);
135 if (!(expected
.size() == archived
.size())) return "Not the same number of current files\n"
137 if (!expected
.equals(archived
)) return "Different backup files, but same amount\n" + compare
;
142 * @return <expected, gotten, backup>, where each is sorted
144 private static List
<List
<String
>> getFileLists(FileStatus
[] previous
, FileStatus
[] archived
) {
145 List
<List
<String
>> files
= new ArrayList
<>(3);
147 // copy over the original files
148 List
<String
> originalFileNames
= convertToString(previous
);
149 files
.add(originalFileNames
);
151 List
<String
> currentFiles
= new ArrayList
<>(previous
.length
);
152 List
<FileStatus
> backedupFiles
= new ArrayList
<>(previous
.length
);
153 for (FileStatus f
: archived
) {
154 String name
= f
.getPath().getName();
155 // if the file has been backed up
156 if (name
.contains(".")) {
157 Path parent
= f
.getPath().getParent();
158 String shortName
= name
.split("[.]")[0];
159 Path modPath
= new Path(parent
, shortName
);
160 FileStatus file
= new FileStatus(f
.getLen(), f
.isDirectory(), f
.getReplication(),
161 f
.getBlockSize(), f
.getModificationTime(), modPath
);
162 backedupFiles
.add(file
);
164 // otherwise, add it to the list to compare to the original store files
165 currentFiles
.add(name
);
169 files
.add(currentFiles
);
170 files
.add(convertToString(backedupFiles
));
174 private static List
<String
> convertToString(FileStatus
[] files
) {
175 return convertToString(Arrays
.asList(files
));
178 private static List
<String
> convertToString(List
<FileStatus
> files
) {
179 List
<String
> originalFileNames
= new ArrayList
<>(files
.size());
180 for (FileStatus f
: files
) {
181 originalFileNames
.add(f
.getPath().getName());
183 return originalFileNames
;
186 /* Get a pretty representation of the differences */
187 private static String
compareFileLists(List
<String
> expected
, List
<String
> gotten
) {
188 StringBuilder sb
= new StringBuilder("Expected (" + expected
.size() + "): \t\t Gotten ("
189 + gotten
.size() + "):\n");
190 List
<String
> notFound
= new ArrayList
<>();
191 for (String s
: expected
) {
192 if (gotten
.contains(s
)) sb
.append(s
+ "\t\t" + s
+ "\n");
193 else notFound
.add(s
);
195 sb
.append("Not Found:\n");
196 for (String s
: notFound
) {
199 sb
.append("\nExtra:\n");
200 for (String s
: gotten
) {
201 if (!expected
.contains(s
)) sb
.append(s
+ "\n");
203 return sb
.toString();
207 * Helper method to get the archive directory for the specified region
208 * @param conf {@link Configuration} to check for the name of the archive directory
209 * @param region region that is being archived
210 * @return {@link Path} to the archive directory for the given region
212 public static Path
getRegionArchiveDir(Configuration conf
, HRegion region
) throws IOException
{
213 return HFileArchiveUtil
.getRegionArchiveDir(CommonFSUtils
.getRootDir(conf
),
214 region
.getTableDescriptor().getTableName(), region
.getRegionInfo().getEncodedName());
218 * Helper method to get the store archive directory for the specified region
219 * @param conf {@link Configuration} to check for the name of the archive directory
220 * @param region region that is being archived
221 * @param store store that is archiving files
222 * @return {@link Path} to the store archive directory for the given region
224 public static Path
getStoreArchivePath(Configuration conf
, HRegion region
, Store store
)
226 return HFileArchiveUtil
.getStoreArchivePath(conf
, region
.getRegionInfo(),
227 region
.getRegionFileSystem().getTableDir(), store
.getColumnFamilyDescriptor().getName());
230 public static Path
getStoreArchivePath(HBaseTestingUtil util
, String tableName
,
231 byte[] storeName
) throws IOException
{
232 byte[] table
= Bytes
.toBytes(tableName
);
233 // get the RS and region serving our table
234 List
<HRegion
> servingRegions
= util
.getHBaseCluster().getRegions(table
);
235 HRegion region
= servingRegions
.get(0);
237 // check that we actually have some store files that were archived
238 Store store
= region
.getStore(storeName
);
239 return HFileArchiveTestingUtil
.getStoreArchivePath(util
.getConfiguration(), region
, store
);