blob: 5f9eb30c9450078dd5ed0f0b61ca8a4430b7c1e9 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.impala.catalog;
import static org.apache.impala.catalog.HdfsPartition.comparePartitionKeyValues;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.hadoop.fs.Path;
import org.apache.impala.analysis.BoolLiteral;
import org.apache.impala.analysis.LiteralExpr;
import org.apache.impala.analysis.NullLiteral;
import org.apache.impala.analysis.NumericLiteral;
import org.apache.impala.analysis.StringLiteral;
import org.apache.impala.catalog.HdfsPartition.FileDescriptor;
import org.apache.impala.service.FeSupport;
import org.apache.impala.thrift.TNetworkAddress;
import org.apache.impala.util.ListMap;
import org.junit.Test;
import com.google.common.collect.Lists;
public class HdfsPartitionTest {
static {
FeSupport.loadLibrary();
}
private List<LiteralExpr> valuesNull_= new ArrayList<>();
private List<LiteralExpr> valuesDecimal_ = new ArrayList<>();
private List<LiteralExpr> valuesDecimal1_ = new ArrayList<>();
private List<LiteralExpr> valuesDecimal2_ = new ArrayList<>();
private List<LiteralExpr> valuesMixed_= new ArrayList<>();
private List<LiteralExpr> valuesMixed1_ = new ArrayList<>();
private List<LiteralExpr> valuesMixed2_ = new ArrayList<>();
public HdfsPartitionTest() {
valuesNull_.add(NullLiteral.create(Type.BIGINT));
valuesDecimal_.add(NumericLiteral.create(1));
valuesDecimal1_.add(NumericLiteral.create(3));
valuesDecimal2_.add(NumericLiteral.create(5));
valuesMixed_.add(NumericLiteral.create(3));
valuesMixed_.add(NullLiteral.create(Type.BIGINT));
valuesMixed1_.add(NumericLiteral.create(1));
valuesMixed1_.add(NullLiteral.create(Type.STRING));
valuesMixed1_.add(new BoolLiteral(true));
valuesMixed2_.add(NumericLiteral.create(1));
valuesMixed2_.add(new StringLiteral("Large"));
valuesMixed2_.add(new BoolLiteral(false));
}
@Test
public void testCompare() {
List<List<LiteralExpr>> allLists = new ArrayList<>();
allLists.add(valuesNull_);
allLists.add(valuesDecimal_);
allLists.add(valuesDecimal1_);
allLists.add(valuesDecimal2_);
allLists.add(valuesMixed_);
allLists.add(valuesMixed1_);
allLists.add(valuesMixed2_);
for (List<LiteralExpr> l1: allLists) {
verifyReflexive(l1);
for (List<LiteralExpr> l2: allLists) {
verifySymmetric(l1, l2);
for (List<LiteralExpr> l3: allLists) {
verifyTransitive(l1, l2, l3);
}
}
}
List<LiteralExpr> valuesTest = new ArrayList<>();
valuesTest.add(NumericLiteral.create(3));
verifyAntiSymmetric(valuesDecimal1_, valuesTest, valuesNull_);
valuesTest.add(NullLiteral.create(Type.BIGINT));
verifyAntiSymmetric(valuesMixed_, valuesTest, valuesDecimal_);
}
private void verifySymmetric(List<LiteralExpr> o1, List<LiteralExpr> o2) {
// sgn(compare(x, y)) == -sgn(compare(y, x)),
// compare(x, y) == 0, then compare(y, x) == 0
assertTrue(Integer.signum(comparePartitionKeyValues(o1, o2)) ==
-Integer.signum(comparePartitionKeyValues(o2, o1)));
}
private void verifyTransitive(List<LiteralExpr> o1, List<LiteralExpr> o2,
List<LiteralExpr> o3) {
// ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0
if ((comparePartitionKeyValues(o1, o2) > 0) &&
(comparePartitionKeyValues(o2, o3) > 0)) {
assertTrue(comparePartitionKeyValues(o1, o3) > 0);
}
}
private void verifyReflexive(List<LiteralExpr> o1) {
// (compare(x, x)==0) is always true
assertTrue(comparePartitionKeyValues(o1, o1) == 0);
}
private void verifyAntiSymmetric(List<LiteralExpr> o1, List<LiteralExpr> o2,
List<LiteralExpr> o3) {
// compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z.
if (comparePartitionKeyValues(o1, o2) == 0) {
assertTrue(Integer.signum(comparePartitionKeyValues(o1, o3)) ==
Integer.signum(comparePartitionKeyValues(o2, o3)));
}
}
/**
* Get the list of all locations of blocks from the given file descriptor.
*/
private static List<TNetworkAddress> getAllReplicaAddresses(FileDescriptor fd,
ListMap<TNetworkAddress> hostIndex) {
List<TNetworkAddress> ret = new ArrayList<>();
for (int i = 0; i < fd.getNumFileBlocks(); i++) {
for (int j = 0; j < fd.getFbFileBlock(i).replicaHostIdxsLength(); j++) {
int idx = fd.getFbFileBlock(i).replicaHostIdxs(j);
ret.add(hostIndex.getEntry(idx));
}
}
return ret;
}
@Test
public void testCloneWithNewHostIndex() throws Exception {
// Fetch some metadata from a directory in HDFS.
Path p = new Path("hdfs://localhost:20500/test-warehouse/schemas");
ListMap<TNetworkAddress> origIndex = new ListMap<>();
FileMetadataLoader fml = new FileMetadataLoader(p, /* recursive= */false,
Collections.emptyList(), origIndex, /*validTxnList=*/null, /*writeIds=*/null);
fml.load();
List<FileDescriptor> fileDescriptors = fml.getLoadedFds();
assertTrue(!fileDescriptors.isEmpty());
FileDescriptor fd = fileDescriptors.get(0);
// Get the list of locations, using the original host index.
List<TNetworkAddress> origAddresses = getAllReplicaAddresses(fd, origIndex);
// Make a new host index with the hosts in the opposite order.
ListMap<TNetworkAddress> newIndex = new ListMap<>();
newIndex.populate(Lists.reverse(origIndex.getList()));
// Clone the FD over to the reversed index. The actual addresses should be the same.
FileDescriptor cloned = fd.cloneWithNewHostIndex(origIndex.getList(), newIndex);
List<TNetworkAddress> newAddresses = getAllReplicaAddresses(cloned, newIndex);
assertEquals(origAddresses, newAddresses);
}
}