/**
* 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.Order;
import org.apache.hadoop.hive.metastore.api.SerDeInfo;
import org.apache.hadoop.hive.metastore.api.SkewedInfo;
import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* A {@link org.apache.hadoop.hive.metastore.api.StorageDescriptor} with most of it's content
* shallow copied from the underlying storage descriptor. Location and parameters are left alone.
* To avoid issues when users change the contents, all lists and nested structures (cols, serde,
* buckets, sortCols, and skewed) are deep copied when they are accessed for reading or writing.
* (It has to be done on read as well because there's no way to guarantee the user won't change the
* nested structure or list, which would result in changing every storage descriptor sharing that
* structure.) Users wishing better performance can call setReadyOnly(), which will prevent the
* copies.
*/
public class SharedStorageDescriptor extends StorageDescriptor {
static final private Logger LOG = LoggerFactory.getLogger(SharedStorageDescriptor.class.getName());
private boolean colsCopied = false;
private boolean serdeCopied = false;
private boolean bucketsCopied = false;
private boolean sortCopied = false;
private boolean skewedCopied = false;
SharedStorageDescriptor() {
}
void setShared(StorageDescriptor shared) {
if (shared.getCols() != null) super.setCols(shared.getCols());
// Skip location
if (shared.getInputFormat() != null) super.setInputFormat(shared.getInputFormat());
if (shared.getOutputFormat() != null) super.setOutputFormat(shared.getOutputFormat());
super.setCompressed(shared.isCompressed());
super.setNumBuckets(shared.getNumBuckets());
if (shared.getSerdeInfo() != null) super.setSerdeInfo(shared.getSerdeInfo());
if (shared.getBucketCols() != null) super.setBucketCols(shared.getBucketCols());
if (shared.getSortCols() != null) super.setSortCols(shared.getSortCols());
// skip parameters
if (shared.getSkewedInfo() != null) super.setSkewedInfo(shared.getSkewedInfo());
super.setStoredAsSubDirectories(shared.isStoredAsSubDirectories());
}
/**
* Promise that you'll only use this shared storage descriptor in a read only mode.
* This prevents the copies of the nested structures and lists when reading them. However, the
* caller must not change the structures or lists returned to it, as this will change all
* storage descriptor sharing that list.
*/
public void setReadOnly() {
colsCopied = serdeCopied = bucketsCopied = sortCopied = skewedCopied = true;
}
@Override
public void addToCols(FieldSchema fs) {
copyCols();
super.addToCols(fs);
}
@Override
public List<FieldSchema> getCols() {
copyCols();
return super.getCols();
}
@Override
public void setCols(List<FieldSchema> cols) {
colsCopied = true;
super.setCols(cols);
}
@Override
public void unsetCols() {
colsCopied = true;
super.unsetCols();
}
@Override
public Iterator<FieldSchema> getColsIterator() {
copyCols();
return super.getColsIterator();
}
private void copyCols() {
if (!colsCopied) {
colsCopied = true;
if (super.getCols() != null) {
List<FieldSchema> cols = new ArrayList<FieldSchema>(super.getColsSize());
for (FieldSchema fs : super.getCols()) cols.add(new FieldSchema(fs));
super.setCols(cols);
}
}
}
@Override
public SerDeInfo getSerdeInfo() {
copySerde();
return super.getSerdeInfo();
}
@Override
public void setSerdeInfo(SerDeInfo serdeInfo) {
serdeCopied = true;
super.setSerdeInfo(serdeInfo);
}
@Override
public void unsetSerdeInfo() {
serdeCopied = true;
super.unsetSerdeInfo();
}
private void copySerde() {
if (!serdeCopied) {
serdeCopied = true;
if (super.getSerdeInfo() != null) super.setSerdeInfo(new SerDeInfo(super.getSerdeInfo()));
}
}
@Override
public void addToBucketCols(String bucket) {
copyBucketCols();
super.addToBucketCols(bucket);
}
@Override
public List<String> getBucketCols() {
copyBucketCols();
return super.getBucketCols();
}
@Override
public void setBucketCols(List<String> buckets) {
bucketsCopied = true;
super.setBucketCols(buckets);
}
@Override
public void unsetBucketCols() {
bucketsCopied = true;
super.unsetBucketCols();
}
@Override
public Iterator<String> getBucketColsIterator() {
copyBucketCols();
return super.getBucketColsIterator();
}
private void copyBucketCols() {
if (!bucketsCopied) {
bucketsCopied = true;
if (super.getBucketCols() != null) {
List<String> buckets = new ArrayList<String>(super.getBucketColsSize());
for (String bucket : super.getBucketCols()) buckets.add(bucket);
super.setBucketCols(buckets);
}
}
}
@Override
public void addToSortCols(Order sort) {
copySort();
super.addToSortCols(sort);
}
@Override
public List<Order> getSortCols() {
copySort();
return super.getSortCols();
}
@Override
public void setSortCols(List<Order> sorts) {
sortCopied = true;
super.setSortCols(sorts);
}
@Override
public void unsetSortCols() {
sortCopied = true;
super.unsetSortCols();
}
@Override
public Iterator<Order> getSortColsIterator() {
copySort();
return super.getSortColsIterator();
}
private void copySort() {
if (!sortCopied) {
sortCopied = true;
if (super.getSortCols() != null) {
List<Order> sortCols = new ArrayList<Order>(super.getSortColsSize());
for (Order sortCol : super.getSortCols()) sortCols.add(new Order(sortCol));
super.setSortCols(sortCols);
}
}
}
@Override
public SkewedInfo getSkewedInfo() {
copySkewed();
return super.getSkewedInfo();
}
@Override
public void setSkewedInfo(SkewedInfo skewedInfo) {
skewedCopied = true;
super.setSkewedInfo(skewedInfo);
}
@Override
public void unsetSkewedInfo() {
skewedCopied = true;
super.unsetSkewedInfo();
}
private void copySkewed() {
if (!skewedCopied) {
skewedCopied = true;
if (super.getSkewedInfo() != null) super.setSkewedInfo(new SkewedInfo(super.getSkewedInfo()));
}
}
}