/**
* 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.hadoop.hive.metastore.hbase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.hive.metastore.api.FieldSchema;
import org.apache.hadoop.hive.metastore.api.Partition;
import org.apache.hadoop.hive.metastore.api.SerDeInfo;
import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
import org.apache.hadoop.hive.metastore.api.Table;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Integration tests with HBase Mini-cluster for HBaseStore
*/
public class TestStorageDescriptorSharing extends HBaseIntegrationTests {
private static final Logger LOG = LoggerFactory.getLogger(TestHBaseStoreIntegration.class.getName());
private MessageDigest md;
@BeforeClass
public static void startup() throws Exception {
HBaseIntegrationTests.startMiniCluster();
}
@AfterClass
public static void shutdown() throws Exception {
HBaseIntegrationTests.shutdownMiniCluster();
}
@Before
public void setup() throws IOException {
setupConnection();
setupHBaseStore();
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
@Test
public void createManyPartitions() throws Exception {
String dbName = "default";
String tableName = "manyParts";
int startTime = (int)(System.currentTimeMillis() / 1000);
List<FieldSchema> cols = new ArrayList<FieldSchema>();
cols.add(new FieldSchema("col1", "int", "nocomment"));
SerDeInfo serde = new SerDeInfo("serde", "seriallib", null);
StorageDescriptor sd = new StorageDescriptor(cols, "file:/tmp", "input", "output", false, 0,
serde, null, null, emptyParameters);
List<FieldSchema> partCols = new ArrayList<FieldSchema>();
partCols.add(new FieldSchema("pc", "string", ""));
Table table = new Table(tableName, dbName, "me", startTime, startTime, 0, sd, partCols,
emptyParameters, null, null, null);
store.createTable(table);
List<String> partVals = Arrays.asList("alan", "bob", "carl", "doug", "ethan");
for (String val : partVals) {
List<String> vals = new ArrayList<String>();
vals.add(val);
StorageDescriptor psd = new StorageDescriptor(sd);
psd.setLocation("file:/tmp/pc=" + val);
Partition part = new Partition(vals, dbName, tableName, startTime, startTime, psd,
emptyParameters);
store.addPartition(part);
Partition p = store.getPartition(dbName, tableName, vals);
Assert.assertEquals("file:/tmp/pc=" + val, p.getSd().getLocation());
}
Assert.assertEquals(1, HBaseReadWrite.getInstance().countStorageDescriptor());
String tableName2 = "differentTable";
sd = new StorageDescriptor(cols, "file:/tmp", "input2", "output", false, 0,
serde, null, null, emptyParameters);
table = new Table(tableName2, "default", "me", startTime, startTime, 0, sd, null,
emptyParameters, null, null, null);
store.createTable(table);
Assert.assertEquals(2, HBaseReadWrite.getInstance().countStorageDescriptor());
// Drop one of the partitions and make sure it doesn't drop the storage descriptor
store.dropPartition(dbName, tableName, Arrays.asList(partVals.get(0)));
Assert.assertEquals(2, HBaseReadWrite.getInstance().countStorageDescriptor());
// Alter the second table in a few ways to make sure it changes it's descriptor properly
table = store.getTable(dbName, tableName2);
byte[] sdHash = HBaseUtils.hashStorageDescriptor(table.getSd(), md);
// Alter the table without touching the storage descriptor
table.setLastAccessTime(startTime + 1);
store.alterTable(dbName, tableName2, table);
Assert.assertEquals(2, HBaseReadWrite.getInstance().countStorageDescriptor());
table = store.getTable(dbName, tableName2);
byte[] alteredHash = HBaseUtils.hashStorageDescriptor(table.getSd(), md);
Assert.assertArrayEquals(sdHash, alteredHash);
// Alter the table, changing the storage descriptor
table.getSd().setOutputFormat("output_changed");
store.alterTable(dbName, tableName2, table);
Assert.assertEquals(2, HBaseReadWrite.getInstance().countStorageDescriptor());
table = store.getTable(dbName, tableName2);
alteredHash = HBaseUtils.hashStorageDescriptor(table.getSd(), md);
Assert.assertFalse(Arrays.equals(sdHash, alteredHash));
// Alter one of the partitions without touching the storage descriptor
Partition part = store.getPartition(dbName, tableName, Arrays.asList(partVals.get(1)));
sdHash = HBaseUtils.hashStorageDescriptor(part.getSd(), md);
part.setLastAccessTime(part.getLastAccessTime() + 1);
store.alterPartition(dbName, tableName, Arrays.asList(partVals.get(1)), part);
Assert.assertEquals(2, HBaseReadWrite.getInstance().countStorageDescriptor());
part = store.getPartition(dbName, tableName, Arrays.asList(partVals.get(1)));
alteredHash = HBaseUtils.hashStorageDescriptor(part.getSd(), md);
Assert.assertArrayEquals(sdHash, alteredHash);
// Alter the partition, changing the storage descriptor
part.getSd().setOutputFormat("output_changed_some_more");
store.alterPartition(dbName, tableName, Arrays.asList(partVals.get(1)), part);
Assert.assertEquals(3, HBaseReadWrite.getInstance().countStorageDescriptor());
part = store.getPartition(dbName, tableName, Arrays.asList(partVals.get(1)));
alteredHash = HBaseUtils.hashStorageDescriptor(part.getSd(), md);
Assert.assertFalse(Arrays.equals(sdHash, alteredHash));
// Alter multiple partitions without touching the storage descriptors
List<Partition> parts = store.getPartitions(dbName, tableName, -1);
sdHash = HBaseUtils.hashStorageDescriptor(parts.get(1).getSd(), md);
for (int i = 1; i < 3; i++) {
parts.get(i).setLastAccessTime(97);
}
List<List<String>> listPartVals = new ArrayList<List<String>>();
for (String pv : partVals.subList(1, partVals.size())) {
listPartVals.add(Arrays.asList(pv));
}
store.alterPartitions(dbName, tableName, listPartVals, parts);
Assert.assertEquals(3, HBaseReadWrite.getInstance().countStorageDescriptor());
parts = store.getPartitions(dbName, tableName, -1);
alteredHash = HBaseUtils.hashStorageDescriptor(parts.get(1).getSd(), md);
Assert.assertArrayEquals(sdHash, alteredHash);
// Alter multiple partitions changning the storage descriptors
parts = store.getPartitions(dbName, tableName, -1);
sdHash = HBaseUtils.hashStorageDescriptor(parts.get(1).getSd(), md);
for (int i = 1; i < 3; i++) {
parts.get(i).getSd().setOutputFormat("yet_a_different_of");
}
store.alterPartitions(dbName, tableName, listPartVals, parts);
Assert.assertEquals(4, HBaseReadWrite.getInstance().countStorageDescriptor());
parts = store.getPartitions(dbName, tableName, -1);
alteredHash = HBaseUtils.hashStorageDescriptor(parts.get(1).getSd(), md);
Assert.assertFalse(Arrays.equals(sdHash, alteredHash));
for (String partVal : partVals.subList(1, partVals.size())) {
store.dropPartition(dbName, tableName, Arrays.asList(partVal));
}
store.dropTable(dbName, tableName);
store.dropTable(dbName, tableName2);
Assert.assertEquals(0, HBaseReadWrite.getInstance().countStorageDescriptor());
}
}