| /** |
| * 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.lens.cube.metadata; |
| |
| import static org.apache.lens.cube.metadata.DateUtil.resolveDate; |
| import static org.apache.lens.cube.metadata.JAXBUtils.getStorageTableDescFromHiveTable; |
| import static org.apache.lens.cube.metadata.JAXBUtils.segmentationFromXSegmentation; |
| import static org.apache.lens.cube.metadata.MetastoreUtil.*; |
| |
| import java.text.ParseException; |
| import java.util.*; |
| import java.util.concurrent.ConcurrentHashMap; |
| |
| import org.apache.lens.api.metastore.*; |
| |
| import org.apache.lens.cube.authorization.AuthorizationUtil; |
| import org.apache.lens.cube.error.LensCubeErrorCode; |
| import org.apache.lens.cube.metadata.Storage.LatestInfo; |
| import org.apache.lens.cube.metadata.Storage.LatestPartColumnInfo; |
| import org.apache.lens.cube.metadata.timeline.PartitionTimeline; |
| import org.apache.lens.cube.metadata.timeline.PartitionTimelineFactory; |
| |
| import org.apache.lens.server.api.LensConfConstants; |
| import org.apache.lens.server.api.authorization.ActionType; |
| import org.apache.lens.server.api.authorization.LensAuthorizer; |
| import org.apache.lens.server.api.authorization.LensPrivilegeObject; |
| |
| import org.apache.lens.server.api.error.LensException; |
| import org.apache.lens.server.api.metastore.DataCompletenessChecker; |
| import org.apache.lens.server.api.util.LensUtil; |
| |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.hadoop.hive.conf.HiveConf; |
| import org.apache.hadoop.hive.metastore.TableType; |
| import org.apache.hadoop.hive.metastore.api.FieldSchema; |
| import org.apache.hadoop.hive.metastore.api.InvalidOperationException; |
| import org.apache.hadoop.hive.ql.io.HiveOutputFormat; |
| import org.apache.hadoop.hive.ql.metadata.Hive; |
| import org.apache.hadoop.hive.ql.metadata.HiveException; |
| import org.apache.hadoop.hive.ql.metadata.Partition; |
| import org.apache.hadoop.hive.ql.metadata.Table; |
| import org.apache.hadoop.hive.ql.session.SessionState; |
| import org.apache.hadoop.util.ReflectionUtils; |
| import org.apache.thrift.TException; |
| |
| import org.jvnet.jaxb2_commons.lang.Equals; |
| import org.jvnet.jaxb2_commons.lang.HashCode; |
| import org.jvnet.jaxb2_commons.lang.ToString; |
| |
| import com.google.common.base.Optional; |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Maps; |
| import com.google.common.collect.Sets; |
| |
| import lombok.extern.slf4j.Slf4j; |
| |
| /** |
| * Wrapper class around Hive metastore to do cube metastore operations. |
| */ |
| @Slf4j |
| public class CubeMetastoreClient { |
| private final HiveConf config; |
| private final boolean enableCaching; |
| |
| private CubeMetastoreClient(HiveConf conf) { |
| this.config = new HiveConf(conf); |
| this.enableCaching = conf.getBoolean(MetastoreConstants.METASTORE_ENABLE_CACHING, true); |
| } |
| |
| // map from table name to Table |
| private final Map<String, Table> allHiveTables = Maps.newConcurrentMap(); |
| private volatile boolean allTablesPopulated = false; |
| // map from dimension name to Dimension |
| private final Map<String, Dimension> allDims = Maps.newConcurrentMap(); |
| private volatile boolean allDimensionsPopulated = false; |
| // map from cube name to Cube |
| private final Map<String, CubeInterface> allCubes = Maps.newConcurrentMap(); |
| private volatile boolean allCubesPopulated = false; |
| // map from dimtable name to CubeDimensionTable |
| private final Map<String, CubeDimensionTable> allDimTables = Maps.newConcurrentMap(); |
| private volatile boolean allDimTablesPopulated = false; |
| // map from fact name to fact table |
| private final Map<String, FactTable> allFactTables = Maps.newConcurrentMap(); |
| // map from fact name to all virtual fact tables, any changes to facts must reflect in all of its virtual facts |
| private final Map<String, List<String>> factToVirtualFactMapping = Maps.newConcurrentMap(); |
| private volatile boolean allFactTablesPopulated = false; |
| //map from segmentation name to segmentation |
| private final Map<String, Segmentation> allSegmentations = Maps.newConcurrentMap(); |
| private volatile boolean allSegmentationPopulated = false; |
| // map from storage name to storage |
| private final Map<String, Storage> allStorages = Maps.newConcurrentMap(); |
| private volatile boolean allStoragesPopulated = false; |
| // Partition cache. Inner class since it logically belongs here |
| PartitionTimelineCache partitionTimelineCache = new PartitionTimelineCache(); |
| // dbname to client mapping |
| private static final Map<String, CubeMetastoreClient> CLIENT_MAPPING = Maps.newConcurrentMap(); |
| // Set of all storage table names for which latest partitions exist |
| private final Set<String> latestLookupCache = Sets.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); |
| private DataCompletenessChecker completenessChecker; |
| |
| private Boolean isDataCompletenessCheckEnabled; |
| |
| private Boolean isAuthorizationCheckEnabled; |
| |
| public DataCompletenessChecker getCompletenessChecker() { |
| if (completenessChecker == null) { |
| completenessChecker = ReflectionUtils.newInstance(config.getClass(LensConfConstants.COMPLETENESS_CHECKER_CLASS, |
| LensConfConstants.DEFAULT_COMPLETENESS_CHECKER, DataCompletenessChecker.class), this.config); |
| } |
| return completenessChecker; |
| } |
| |
| public boolean isDataCompletenessCheckEnabled() { |
| if (isDataCompletenessCheckEnabled == null) { |
| isDataCompletenessCheckEnabled = config.getBoolean(LensConfConstants.ENABLE_DATACOMPLETENESS_CHECK, |
| LensConfConstants.DEFAULT_ENABLE_DATACOMPLETENESS_CHECK); |
| } |
| return isDataCompletenessCheckEnabled; |
| } |
| |
| private boolean isAuthorizationEnabled() { |
| if (isAuthorizationCheckEnabled == null) { |
| isAuthorizationCheckEnabled = config.getBoolean(LensConfConstants.ENABLE_METASTORE_SCHEMA_AUTHORIZATION_CHECK, |
| LensConfConstants.DEFAULT_ENABLE_METASTORE_SCHEMA_AUTHORIZATION_CHECK); |
| } |
| return isAuthorizationCheckEnabled; |
| } |
| |
| private void checkIfAuthorized() throws LensException { |
| if (isAuthorizationEnabled()) { |
| String currentdb = SessionState.get().getCurrentDatabase(); |
| AuthorizationUtil.isAuthorized(LensAuthorizer.get().getAuthorizer(), currentdb, |
| LensPrivilegeObject.LensPrivilegeObjectType.DATABASE, ActionType.UPDATE, getConf(), |
| SessionState.getSessionConf()); |
| } |
| } |
| |
| /** extract storage name from fact and storage table name. String operation */ |
| private String extractStorageName(FactTable fact, String storageTableName) throws LensException { |
| int ind = storageTableName.lastIndexOf(fact.getSourceFactName()); |
| if (ind <= 0) { |
| throw new LensException("storageTable: " + storageTableName + ", does not belong to fact: " + fact.getName()); |
| } |
| String name = storageTableName.substring(0, ind - StorageConstants.STORGAE_SEPARATOR.length()); |
| for (String storageName : fact.getStorages()) { |
| if (name.equalsIgnoreCase(storageName)) { |
| return storageName; |
| } |
| } |
| throw new LensException("storageTable: " + storageTableName + ", does not belong to fact: " + fact.getName()); |
| } |
| |
| /** |
| * get latest date for timeDimension from all fact-storage tables belonging to the given cube having timeDimension, |
| * return the most recent of all. |
| * <p></p> |
| * latest date for a single fact-storage table for given time dimension is the latest of the latest dates for all its |
| * update periods |
| * |
| * @param cube Cube to get latest date of |
| * @param timeDimension time dimension |
| * @return latest date among all facts of cube in timeDimension |
| * @throws HiveException |
| * @throws LensException |
| */ |
| public Date getLatestDateOfCube(Cube cube, String timeDimension) throws HiveException, LensException { |
| String partCol = cube.getPartitionColumnOfTimeDim(timeDimension); |
| Date max = new Date(Long.MIN_VALUE); |
| boolean updated = false; |
| for (FactTable fact : getAllFacts(cube)) { |
| for (String storage : fact.getStorages()) { |
| for (UpdatePeriod updatePeriod : fact.getUpdatePeriods().get(storage)) { |
| PartitionTimeline timeline = partitionTimelineCache.get(fact.getSourceFactName(), storage, updatePeriod, |
| partCol); |
| if (timeline != null) {// this storage table is partitioned by partCol or not. |
| Date latest = timeline.getLatestDate(); |
| if (latest != null && latest.after(max)) { |
| max = latest; |
| updated = true; |
| } |
| } |
| } |
| } |
| } |
| return updated ? max : null; |
| } |
| |
| /** clear hive table cache */ |
| public void clearHiveTableCache() { |
| allHiveTables.clear(); |
| } |
| |
| public List<PartitionTimeline> getTimelines(String factName, String storage, String updatePeriodStr, |
| String timeDimension) |
| throws LensException, HiveException { |
| UpdatePeriod updatePeriod = updatePeriodStr == null ? null : UpdatePeriod.valueOf(updatePeriodStr.toUpperCase()); |
| List<PartitionTimeline> ret = Lists.newArrayList(); |
| CubeFactTable fact = getCubeFactTable(factName); |
| List<String> storageList = Lists.newArrayList(); |
| if (storage != null) { |
| storageList.add(storage); |
| } else { |
| storageList.addAll(fact.getStorages()); |
| } |
| String partCol = null; |
| if (timeDimension != null) { |
| Cube baseCube; |
| CubeInterface cube = getCube(fact.getCubeName()); |
| if (cube instanceof Cube) { |
| baseCube = (Cube) cube; |
| } else { |
| baseCube = ((DerivedCube) cube).getParent(); |
| } |
| partCol = baseCube.getPartitionColumnOfTimeDim(timeDimension); |
| } |
| for (String storageName : storageList) { |
| for (Map.Entry<UpdatePeriod, CaseInsensitiveStringHashMap<PartitionTimeline>> entry : partitionTimelineCache |
| .get(factName, storageName).entrySet()) { |
| if (updatePeriod == null || entry.getKey().equals(updatePeriod)) { |
| for (Map.Entry<String, PartitionTimeline> entry1 : entry.getValue().entrySet()) { |
| if (partCol == null || partCol.equals(entry1.getKey())) { |
| ret.add(entry1.getValue()); |
| } |
| } |
| } |
| } |
| } |
| return ret; |
| } |
| |
| public void updatePartition(String fact, String storageName, Partition partition, UpdatePeriod updatePeriod) |
| throws HiveException, InvalidOperationException, LensException { |
| Map<UpdatePeriod, List<Partition>> updatePeriodListMap = new HashMap<>(); |
| updatePeriodListMap.put(updatePeriod, Collections.singletonList(partition)); |
| updatePartitions(fact, storageName, updatePeriodListMap); |
| } |
| |
| public void updatePartitions(String factOrDimtableName, String storageName, |
| Map<UpdatePeriod, List<Partition>> partitions) throws HiveException, InvalidOperationException, LensException { |
| for (Map.Entry entry : partitions.entrySet()) { |
| List<Partition> partitionsToAlter = Lists.newArrayList(); |
| partitionsToAlter.addAll((List<Partition>) entry.getValue()); |
| String storageTableName = getStorageTableName(factOrDimtableName, storageName, (UpdatePeriod) entry.getKey()); |
| partitionsToAlter.addAll( |
| getAllLatestPartsEquivalentTo(factOrDimtableName, storageTableName, (List<Partition>) entry.getValue())); |
| getStorage(storageName).updatePartitions(storageTableName, getClient(), factOrDimtableName, partitionsToAlter); |
| } |
| } |
| |
| private List<Partition> getAllLatestPartsEquivalentTo(String factOrDimtableName, String storageTableName, |
| List<Partition> partitions) throws HiveException, LensException { |
| if (isFactTable(factOrDimtableName)) { |
| return Lists.newArrayList(); |
| } |
| Table storageTable = getTable(storageTableName); |
| List<String> timePartCols = getTimePartColNamesOfTable(storageTable); |
| List<Partition> latestParts = Lists.newArrayList(); |
| for (Partition partition : partitions) { |
| LinkedHashMap<String, String> partSpec = partition.getSpec(); |
| LinkedHashMap<String, String> timePartSpec = Maps.newLinkedHashMap(); |
| LinkedHashMap<String, String> nonTimePartSpec = Maps.newLinkedHashMap(); |
| for (Map.Entry<String, String> entry : partSpec.entrySet()) { |
| if (timePartCols.contains(entry.getKey())) { |
| timePartSpec.put(entry.getKey(), entry.getValue()); |
| } else { |
| nonTimePartSpec.put(entry.getKey(), entry.getValue()); |
| } |
| } |
| for (String timePartCol : timePartCols) { |
| Partition latestPart = getLatestPart(storageTableName, timePartCol, nonTimePartSpec); |
| if (latestPart != null) { |
| LinkedHashMap<String, String> latestPartSpec = latestPart.getSpec(); |
| latestPartSpec.put(timePartCol, partSpec.get(timePartCol)); |
| if (partSpec.equals(latestPartSpec)) { |
| latestPart.getParameters().putAll(partition.getParameters()); |
| latestPart.getParameters().put(getLatestPartTimestampKey(timePartCol), |
| partSpec.get(timePartCol)); |
| latestPart.getTPartition().getSd().getSerdeInfo().getParameters().putAll( |
| partition.getTPartition().getSd().getSerdeInfo().getParameters()); |
| latestPart.setLocation(partition.getLocation()); |
| latestPart.setInputFormatClass(partition.getInputFormatClass()); |
| latestPart.setOutputFormatClass(partition.getOutputFormatClass().asSubclass(HiveOutputFormat.class)); |
| latestPart.getTPartition().getSd().getSerdeInfo() |
| .setSerializationLib(partition.getTPartition().getSd().getSerdeInfo().getSerializationLib()); |
| latestParts.add(latestPart); |
| } |
| } |
| } |
| } |
| return latestParts; |
| } |
| |
| public boolean isLensQueryableTable(String tableName) { |
| try { |
| Table table = getTable(tableName); |
| String typeProperty = table.getProperty(MetastoreConstants.TABLE_TYPE_KEY); |
| if (StringUtils.isBlank(typeProperty)) { |
| return false; |
| } |
| CubeTableType type = CubeTableType.valueOf(typeProperty); |
| return type == CubeTableType.CUBE || type == CubeTableType.DIMENSION; |
| } catch (LensException e) { |
| return false; |
| } |
| } |
| |
| public void verifyStorageExists(AbstractCubeTable cdt, String storage) throws LensException { |
| if (cdt.getStorages() == null || !cdt.getStorages().contains(storage)) { |
| throw new LensException(LensCubeErrorCode.ENTITY_NOT_FOUND.getLensErrorInfo(), "storage " + storage + " for", |
| cdt.getTableType().name().toLowerCase() + " " + cdt.getName()); |
| } |
| } |
| |
| public void createCubeFactTable(String cubeName, String factName, List<FieldSchema> columns, |
| Map<String, Set<UpdatePeriod>> storageAggregatePeriods, double weight, Map<String, String> properties, |
| Map<String, StorageTableDesc> storageTableDescs, Map<String, Map<UpdatePeriod, String>> storageUpdatePeriodMap) |
| throws LensException { |
| checkIfAuthorized(); |
| CubeFactTable factTable = new CubeFactTable(cubeName, factName, columns, storageAggregatePeriods, weight, |
| properties, storageUpdatePeriodMap); |
| createCubeTable(factTable, storageTableDescs); |
| // do a get to update cache |
| getFactTable(factName); |
| |
| } |
| |
| public <T extends Equals & HashCode & ToString> void createEntity(T entity) |
| throws LensException { |
| if (entity instanceof XStorage) { |
| createStorage((XStorage) entity); |
| } else if (entity instanceof XCube) { |
| createCube((XCube) entity); |
| } else if (entity instanceof XDimension) { |
| createDimension((XDimension) entity); |
| } else if (entity instanceof XFact) { |
| createFactTable((XFact) entity); |
| } else if (entity instanceof XDimensionTable) { |
| createCubeDimensionTable((XDimensionTable) entity); |
| } else if (entity instanceof XSegmentation) { |
| createSegmentation((XSegmentation) entity); |
| } else { |
| throw new LensException("Unable to create entity " + entity + " as it's unrecognizable: " + entity.getClass()); |
| } |
| } |
| |
| public <T extends Equals & HashCode & ToString> void updateEntity(String name, T entity) |
| throws LensException, HiveException { |
| if (entity instanceof XStorage) { |
| alterStorage((XStorage) entity); |
| } else if (entity instanceof XCube) { |
| alterCube((XCube)entity); |
| } else if (entity instanceof XDimension) { |
| alterDimension((XDimension) entity); |
| } else if (entity instanceof XFact) { |
| alterCubeFactTable((XFact) entity); |
| } else if (entity instanceof XDimensionTable) { |
| alterCubeDimensionTable((XDimensionTable) entity); |
| } else if (entity instanceof XSegmentation) { |
| alterSegmentation((XSegmentation) entity); |
| } else { |
| throw new LensException("Unable to alter entity " + entity + " as it's unrecognizable: " + entity.getClass()); |
| } |
| } |
| |
| public static Map<String, String> addFactColStartTimePropertyToFactProperties(XFactTable fact) { |
| Map<String, String> props = new HashMap<String, String>(); |
| props.putAll(JAXBUtils.mapFromXProperties(fact.getProperties())); |
| props.putAll(JAXBUtils.columnStartAndEndTimeFromXColumns(fact.getColumns())); |
| return props; |
| } |
| |
| public void createFactTable(XFact fact) throws LensException { |
| |
| if (fact instanceof XVirtualFactTable) { |
| XVirtualFactTable xvf = (XVirtualFactTable) fact; |
| createVirtualFactTable(xvf.getCubeName(), xvf.getName(), xvf.getSourceFactName(), |
| xvf.getWeight(), JAXBUtils.mapFromXProperties(xvf.getProperties())); |
| } else { |
| XFactTable xf = (XFactTable) fact; |
| createCubeFactTable(fact.getCubeName(), |
| fact.getName(), |
| JAXBUtils.fieldSchemaListFromColumns(xf.getColumns()), |
| JAXBUtils.getFactUpdatePeriodsFromStorageTables(xf.getStorageTables()), |
| xf.getWeight(), |
| addFactColStartTimePropertyToFactProperties(xf), |
| JAXBUtils.tableDescPrefixMapFromXStorageTables(xf.getStorageTables()), |
| JAXBUtils.storageTablePrefixMapOfStorage(xf.getStorageTables())); |
| } |
| } |
| |
| public void createVirtualFactTable(String cubeName, String virtualFactName, String sourceFactName, Double weight, |
| Map<String, String> properties) throws LensException { |
| FactTable sourceFact = getFactTable(sourceFactName); |
| checkIfAuthorized(); |
| Optional<Double> optionalWeight = Optional.fromNullable(weight); |
| |
| CubeVirtualFactTable factTable = new CubeVirtualFactTable(cubeName, virtualFactName, |
| optionalWeight, properties, sourceFact); |
| createCubeTable(factTable, null); |
| // do a get to update cache |
| getFactTable(virtualFactName); |
| |
| } |
| |
| /** |
| * In-memory storage of {@link PartitionTimeline} objects for each valid |
| * storagetable-updateperiod-partitioncolumn tuple. also simultaneously stored in metastore table of the |
| * storagetable. |
| */ |
| class PartitionTimelineCache extends CaseInsensitiveStringHashMap<// storage table |
| TreeMap<UpdatePeriod, |
| CaseInsensitiveStringHashMap<// partition column |
| PartitionTimeline>>> { |
| /** |
| * |
| * @param fact fact |
| * @param storage storage |
| * @param partCol part column |
| * @return true if all the timelines for fact-storage table are empty for all valid update periods. |
| * @throws HiveException |
| * @throws LensException |
| */ |
| public boolean noPartitionsExist(String fact, String storage, String partCol) |
| throws HiveException, LensException { |
| if (get(fact, storage) == null) { |
| return true; |
| } |
| for (UpdatePeriod updatePeriod : get(fact, storage).keySet()) { |
| PartitionTimeline timeline = get(fact, storage, updatePeriod, partCol); |
| if (timeline != null && !timeline.isEmpty()) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * get all timelines for all update periods and partition columns for the given fact-storage pair. If already loaded |
| * in memory, it'll return that. If not, it'll first try to load it from table properties. If not found in table |
| * properties, it'll get all partitions, compute timelines in memory, write back all loads timelines to table |
| * properties for further usage and return them. |
| * |
| * @param fact fact |
| * @param storage storage |
| * @return all timelines for fact-storage pair. Load from properties/all partitions if needed. |
| * @throws HiveException |
| * @throws LensException |
| */ |
| public TreeMap<UpdatePeriod, CaseInsensitiveStringHashMap<PartitionTimeline>> get(String fact, String storage) |
| throws HiveException, LensException { |
| // SUSPEND CHECKSTYLE CHECK DoubleCheckedLockingCheck |
| // Unique key for the timeline cache, based on storage and fact. |
| String timeLineKey = (Storage.getPrefix(storage)+ fact).toLowerCase(); |
| synchronized (this) { |
| if (get(timeLineKey) == null) { |
| loadTimeLines(fact, storage, timeLineKey); |
| } |
| log.debug("timeline for {} is: {}", storage, get(timeLineKey)); |
| // return the final value from memory |
| return get(timeLineKey); |
| // RESUME CHECKSTYLE CHECK DoubleCheckedLockingCheck |
| } |
| } |
| |
| /** |
| * @param fact |
| * @param storage |
| */ |
| private void loadTimeLines(String fact, String storage, String timeLineKey) throws LensException, HiveException { |
| Set<String> uniqueStorageTables = new HashSet<>(); |
| Map<UpdatePeriod, String> updatePeriodTableName = new HashMap<>(); |
| for (UpdatePeriod updatePeriod : getFactTable(fact).getUpdatePeriods().get(storage)) { |
| String storageTableName = getStorageTableName(fact, storage, updatePeriod); |
| updatePeriodTableName.put(updatePeriod, storageTableName); |
| Table storageTable = getTable(storageTableName); |
| if ("true".equalsIgnoreCase(storageTable.getParameters().get(getPartitionTimelineCachePresenceKey()))) { |
| try { |
| loadTimelinesFromTableProperties(updatePeriod, storageTableName, timeLineKey); |
| } catch (Exception e) { |
| // Ideally this should never come. But since we have another source, |
| // let's piggyback on that for loading timeline |
| log.error("Error while loading timelines from table properties.", e); |
| ensureEntryForTimeLineKey(fact, storage, updatePeriod, storageTableName, timeLineKey); |
| if (!uniqueStorageTables.contains(storageTableName)) { |
| uniqueStorageTables.add(storageTableName); |
| loadTimelinesFromAllPartitions(storageTableName, timeLineKey); |
| } |
| } |
| } else { |
| ensureEntryForTimeLineKey(fact, storage, updatePeriod, storageTableName, timeLineKey); |
| if (!uniqueStorageTables.contains(storageTableName)) { |
| uniqueStorageTables.add(storageTableName); |
| loadTimelinesFromAllPartitions(storageTableName, timeLineKey); |
| } |
| } |
| } |
| for (Map.Entry entry : updatePeriodTableName.entrySet()) { |
| alterTablePartitionCache(timeLineKey, (UpdatePeriod) entry.getKey(), (String) entry.getValue()); |
| } |
| } |
| |
| private void ensureEntryForTimeLineKey(String fact, String storage, UpdatePeriod updatePeriod, |
| String storageTableName, String timeLineKey) throws LensException { |
| // Not found in table properties either, compute from all partitions of the fact-storage table. |
| // First make sure all combinations of update period and partition column have an entry even |
| // if no partitions exist |
| if (getFactTable(fact).getUpdatePeriods() != null && getFactTable(fact).getUpdatePeriods().get(storage) != null) { |
| log.info("loading from all partitions: {}", storageTableName); |
| Table storageTable = getTable(storageTableName); |
| for (String partCol : getTimePartColNamesOfTable(storageTable)) { |
| ensureEntry(timeLineKey, storageTableName, updatePeriod, partCol); |
| } |
| } |
| |
| } |
| |
| private void loadTimelinesFromAllPartitions(String storageTableName, String timeLineKey) |
| throws HiveException, LensException { |
| // Then add all existing partitions for batch addition in respective timelines. |
| Table storageTable = getTable(storageTableName); |
| List<String> timeParts = getTimePartColNamesOfTable(storageTable); |
| List<FieldSchema> partCols = storageTable.getPartCols(); |
| for (Partition partition : getPartitionsByFilter(storageTableName, null)) { |
| UpdatePeriod period = deduceUpdatePeriod(partition); |
| List<String> values = partition.getValues(); |
| if (values.contains(StorageConstants.LATEST_PARTITION_VALUE)) { |
| log.info("dropping latest partition from fact storage table: {}. Spec: {}", storageTableName, |
| partition.getSpec()); |
| getClient().dropPartition(storageTableName, values, false); |
| continue; |
| } |
| for (int i = 0; i < partCols.size(); i++) { |
| if (timeParts.contains(partCols.get(i).getName())) { |
| addForBatchAddition(timeLineKey, storageTableName, period, partCols.get(i).getName(), values.get(i)); |
| } |
| } |
| } |
| } |
| |
| private void loadTimelinesFromTableProperties(UpdatePeriod updatePeriod, |
| String storageTableName, String timeLineKey) throws HiveException, LensException { |
| log.info("loading from table properties: {}", storageTableName); |
| for (String partCol : getTimePartColNamesOfTable(storageTableName)) { |
| ensureEntry(timeLineKey, storageTableName, updatePeriod, partCol).init(getTable(storageTableName)); |
| } |
| } |
| |
| /** |
| * Adds given partition(for storageTable, updatePeriod, partitionColum=partition) for batch addition in an |
| * appropriate timeline object. Ignore if partition is not valid. |
| * |
| * @param timeLineKey key for the timeLine map |
| * @param storageTableName hive table name |
| * @param updatePeriod update period |
| * @param partitionColumn partition column |
| * @param partition partition |
| */ |
| public void addForBatchAddition(String timeLineKey, String storageTableName, UpdatePeriod updatePeriod, |
| String partitionColumn, String partition) { |
| try { |
| ensureEntry(timeLineKey, storageTableName, updatePeriod, partitionColumn) |
| .addForBatchAddition(TimePartition.of(updatePeriod, partition)); |
| } catch (LensException e) { |
| // to take care of the case where partition name is something like `latest` |
| log.error("Couldn't parse partition: {} with update period: {}, skipping.", partition, updatePeriod, e); |
| } |
| } |
| |
| /** |
| * helper method for ensuring get(storageTable).get(updatePeriod).get(partitionColumn) gives a non-null object. |
| * <p></p> |
| * kind of like mkdir -p |
| * |
| * @param timeLineKey storage table |
| * @param updatePeriod update period |
| * @param partitionColumn partition column |
| * @return timeline if already exists, or puts a new timeline and returns. |
| */ |
| public PartitionTimeline ensureEntry(String timeLineKey, String storagTableName, UpdatePeriod updatePeriod, |
| String partitionColumn) { |
| return this |
| .computeIfAbsent(timeLineKey, s -> new TreeMap<>()) |
| .computeIfAbsent(updatePeriod, k -> new CaseInsensitiveStringHashMap<>()) |
| .computeIfAbsent(partitionColumn, c -> PartitionTimelineFactory.get( |
| CubeMetastoreClient.this, storagTableName, updatePeriod, c)); |
| } |
| |
| /** check partition existence in the appropriate timeline if it exists */ |
| public boolean partitionTimeExists(String name, String storage, UpdatePeriod period, String partCol, Date partSpec) |
| throws HiveException, LensException { |
| return get(name, storage, period, partCol) != null |
| && get(name, storage, period, partCol).exists(TimePartition.of(period, partSpec)); |
| } |
| |
| /** |
| * returns the timeline corresponding to fact-storage table, updatePeriod, partCol. null if doesn't exist, which |
| * would only happen if the combination is not valid/supported |
| */ |
| public PartitionTimeline get(String fact, String storage, UpdatePeriod updatePeriod, String partCol) |
| throws HiveException, LensException { |
| return get(fact, storage) != null && get(fact, storage).get(updatePeriod) != null |
| && get(fact, storage).get(updatePeriod).get(partCol) != null ? get(fact, storage).get(updatePeriod) |
| .get(partCol) : null; |
| } |
| |
| /** |
| * returns the timeline corresponding to fact-storage table, updatePeriod, partCol. throws exception if not |
| * exists, which would most probably mean the combination is incorrect. |
| */ |
| public PartitionTimeline getAndFailFast(String fact, String storage, UpdatePeriod updatePeriod, String partCol) |
| throws HiveException, LensException { |
| PartitionTimeline timeline = get(fact, storage, updatePeriod, partCol); |
| if (timeline == null) { |
| throw new LensException(LensCubeErrorCode.TIMELINE_ABSENT.getLensErrorInfo(), fact, storage, updatePeriod, |
| partCol); |
| } |
| return timeline; |
| } |
| |
| /** update partition timeline cache for addition of time partition */ |
| public void updateForAddition(String cubeTableName, String storageName, UpdatePeriod updatePeriod, |
| Map<String, TreeSet<Date>> timePartSpec) throws HiveException, LensException { |
| // fail fast. All part cols mentioned in all partitions should exist. |
| for (String partCol : timePartSpec.keySet()) { |
| getAndFailFast(cubeTableName, storageName, updatePeriod, partCol); |
| } |
| for (Map.Entry<String, TreeSet<Date>> entry : timePartSpec.entrySet()) { |
| for (Date dt : entry.getValue()) { |
| get(cubeTableName, storageName, updatePeriod, entry.getKey()).add(TimePartition.of(updatePeriod, dt)); |
| } |
| } |
| } |
| |
| /** update partition timeline cache for deletion of time partition */ |
| public boolean updateForDeletion(String cubeTableName, String storageName, UpdatePeriod updatePeriod, |
| Map<String, Date> timePartSpec) throws HiveException, LensException { |
| // fail fast. All part cols mentioned in all partitions should exist. |
| for (String partCol : timePartSpec.keySet()) { |
| getAndFailFast(cubeTableName, storageName, updatePeriod, partCol); |
| } |
| boolean updated = false; |
| for (Map.Entry<String, Date> entry : timePartSpec.entrySet()) { |
| TimePartition part = TimePartition.of(updatePeriod, entry.getValue()); |
| if (!partitionExistsByFilter(cubeTableName, storageName, updatePeriod, |
| StorageConstants.getPartFilter(entry.getKey(), part.getDateString()))) { |
| get(cubeTableName, storageName, updatePeriod, entry.getKey()).drop(part); |
| updated = true; |
| } |
| } |
| return updated; |
| } |
| } |
| |
| |
| /** |
| * Get the instance of {@link CubeMetastoreClient} corresponding to {@link HiveConf} |
| * |
| * @param conf conf |
| * @return CubeMetastoreClient instance |
| * @throws HiveException |
| */ |
| public static CubeMetastoreClient getInstance(HiveConf conf) throws HiveException { |
| String currentdb = SessionState.get().getCurrentDatabase(); |
| if (CLIENT_MAPPING.get(currentdb) == null) { |
| CLIENT_MAPPING.put(currentdb, new CubeMetastoreClient(conf)); |
| } |
| return CLIENT_MAPPING.get(currentdb); |
| } |
| |
| private Hive getClient() throws HiveException { |
| return Hive.get(config); |
| } |
| |
| /** |
| * Get cube metastore client conf |
| * |
| * @return HiveConf |
| */ |
| public HiveConf getConf() { |
| return config; |
| } |
| |
| /** |
| * Close the current metastore client |
| */ |
| public static void close() { |
| Hive.closeCurrent(); |
| } |
| |
| private void createOrAlterStorageHiveTable(Table parent, String storageTableNamePrefix, StorageTableDesc crtTblDesc) |
| throws LensException { |
| try { |
| Table tbl = Storage.getStorageTable(storageTableNamePrefix, getClient(), parent, crtTblDesc); |
| if (tableExists(tbl.getTableName())) { |
| // alter table |
| alterHiveTable(tbl.getTableName(), tbl); |
| } else { |
| getClient().createTable(tbl); |
| // do get to update cache |
| getTable(tbl.getTableName()); |
| } |
| } catch (HiveException e) { |
| throw new LensException("Exception creating table", e); |
| } |
| } |
| |
| private Table createCubeHiveTable(AbstractCubeTable table) throws LensException { |
| try { |
| Table tbl = getClient().newTable(table.getName().toLowerCase()); |
| tbl.setTableType(TableType.MANAGED_TABLE); |
| tbl.getTTable().getSd().setCols(table.getColumns()); |
| tbl.getTTable().getParameters().putAll(table.getProperties()); |
| getClient().createTable(tbl); |
| // do get to update cache |
| getTable(tbl.getTableName()); |
| return tbl; |
| } catch (Exception e) { |
| throw new LensException("Exception creating table", e); |
| } |
| } |
| |
| public void createStorage(XStorage storage) throws LensException { |
| createStorage(JAXBUtils.storageFromXStorage(storage)); |
| } |
| |
| public void createStorage(Storage storage) throws LensException { |
| checkIfAuthorized(); |
| createCubeHiveTable(storage); |
| // do a get to update cache |
| getStorage(storage.getName()); |
| } |
| |
| public void createCube(XCube cube) throws LensException { |
| Cube parent = cube instanceof XDerivedCube ? (Cube) getCube( |
| ((XDerivedCube) cube).getParent()) : null; |
| createCube(JAXBUtils.hiveCubeFromXCube(cube, parent)); |
| } |
| |
| /** |
| * Create cube in metastore defined by {@link Cube} or {@link DerivedCube} object |
| * |
| * @param cube the {@link Cube} object. |
| * @throws LensException |
| */ |
| public void createCube(CubeInterface cube) throws LensException { |
| checkIfAuthorized(); |
| createCubeHiveTable((AbstractCubeTable) cube); |
| // do a get to update cache |
| getCube(cube.getName()); |
| } |
| |
| /** |
| * Create cube defined by measures and dimensions |
| * |
| * @param name Name of the cube |
| * @param measures Measures of the cube |
| * @param dimensions Dimensions of the cube |
| * @throws LensException |
| */ |
| public void createCube(String name, Set<CubeMeasure> measures, Set<CubeDimAttribute> dimensions) |
| throws LensException { |
| Cube cube = new Cube(name, measures, dimensions); |
| createCube(cube); |
| } |
| |
| /** |
| * Create cube defined by measures, dimensions and properties |
| * |
| * @param name Name of the cube |
| * @param measures Measures of the cube |
| * @param dimensions Dimensions of the cube |
| * @param properties Properties of the cube |
| * @throws LensException |
| */ |
| public void createCube(String name, Set<CubeMeasure> measures, Set<CubeDimAttribute> dimensions, |
| Map<String, String> properties) throws LensException { |
| Cube cube = new Cube(name, measures, dimensions, properties); |
| createCube(cube); |
| } |
| |
| /** |
| * Create cube defined by measures, dimensions and properties |
| * |
| * @param name Name of the cube |
| * @param measures Measures of the cube |
| * @param dimensions Dimensions of the cube |
| * @param properties Properties of the cube |
| * @throws LensException |
| */ |
| public void createCube(String name, Set<CubeMeasure> measures, Set<CubeDimAttribute> dimensions, |
| Set<ExprColumn> expressions, Map<String, String> properties) throws LensException { |
| Cube cube = new Cube(name, measures, dimensions, expressions, null, properties, 0L); |
| createCube(cube); |
| } |
| |
| /** |
| * Create cube defined by measures, dimensions and properties |
| * |
| * @param name Name of the cube |
| * @param measures Measures of the cube |
| * @param dimensions Dimensions of the cube |
| * @param expressions Expressions of the cube |
| * @param chains JoinChains of the cube |
| * @param properties Properties of the cube |
| * @throws LensException |
| */ |
| public void createCube(String name, Set<CubeMeasure> measures, Set<CubeDimAttribute> dimensions, |
| Set<ExprColumn> expressions, Set<JoinChain> chains, Map<String, String> properties) |
| throws LensException { |
| Cube cube = new Cube(name, measures, dimensions, expressions, chains, properties, 0L); |
| createCube(cube); |
| } |
| |
| /** |
| * Create dimension defined by attributes and properties |
| * |
| * @param name Name of the dimension |
| * @param attributes Attributes of the dimension |
| * @param properties Properties of the dimension |
| * @param weight Weight of the dimension |
| * @throws LensException |
| */ |
| public void createDimension(String name, Set<CubeDimAttribute> attributes, Map<String, String> properties, |
| double weight) throws LensException { |
| Dimension dim = new Dimension(name, attributes, properties, weight); |
| createDimension(dim); |
| } |
| |
| public void createDimension(XDimension dim) throws LensException { |
| createDimension(JAXBUtils.dimensionFromXDimension(dim)); |
| } |
| |
| /** |
| * Create dimension in metastore defined by {@link Dimension} object |
| * |
| * @param dim the {@link Dimension} object. |
| * @throws LensException |
| */ |
| public void createDimension(Dimension dim) throws LensException { |
| checkIfAuthorized(); |
| createCubeHiveTable(dim); |
| // do a get to update cache |
| getDimension(dim.getName()); |
| } |
| |
| /** |
| * Create derived cube defined by measures, dimensions and properties |
| * |
| * @param parent Name of the parent cube |
| * @param name Name of the derived cube |
| * @param measures Measures of the derived cube |
| * @param dimensions Dimensions of the derived cube |
| * @param properties Properties of the derived cube |
| * @param weight Weight of the derived cube |
| * @throws LensException |
| */ |
| public void createDerivedCube(String parent, String name, Set<String> measures, Set<String> dimensions, |
| Map<String, String> properties, double weight) throws LensException { |
| DerivedCube cube = new DerivedCube(name, measures, dimensions, properties, weight, (Cube) getCube(parent)); |
| createCube(cube); |
| } |
| |
| /** |
| * Create a cube fact table |
| * |
| * @param cubeName The cube name to which fact belongs to. |
| * @param factName The fact name |
| * @param columns The columns of fact table |
| * @param storageAggregatePeriods Aggregate periods for the storages |
| * @param weight Weight of the cube |
| * @param properties Properties of fact table |
| * @param storageTableDescs Map of storage table prefix to its storage table description |
| * @throws LensException |
| */ |
| public void createCubeFactTable(String cubeName, String factName, List<FieldSchema> columns, |
| Map<String, Set<UpdatePeriod>> storageAggregatePeriods, double weight, Map<String, String> properties, |
| Map<String, StorageTableDesc> storageTableDescs) throws LensException { |
| CubeFactTable factTable = |
| new CubeFactTable(cubeName, factName, columns, storageAggregatePeriods, weight, properties); |
| checkIfAuthorized(); |
| createCubeTable(factTable, storageTableDescs); |
| // do a get to update cache |
| getFactTable(factName); |
| } |
| |
| /** |
| * |
| * @param baseCubeName The cube name ot which segmentation belong to |
| * @param segmentationName The segmentation name |
| * @param segments Participating cube segements |
| * @param weight Weight of segmentation |
| * @param properties Properties of segmentation |
| * @throws LensException |
| */ |
| public void createSegmentation(String baseCubeName, String segmentationName, Set<Segment> segments, |
| double weight, Map<String, String> properties) throws LensException { |
| Segmentation cubeSeg = |
| new Segmentation(baseCubeName, segmentationName, segments, weight, properties); |
| createSegmentation(cubeSeg); |
| // do a get to update cache |
| getSegmentation(segmentationName); |
| } |
| |
| public void createCubeDimensionTable(XDimensionTable xDimTable) throws LensException { |
| List<FieldSchema> columns = JAXBUtils.fieldSchemaListFromColumns(xDimTable.getColumns()); |
| Map<String, UpdatePeriod> updatePeriodMap = |
| JAXBUtils.dumpPeriodsFromStorageTables(xDimTable.getStorageTables()); |
| |
| Map<String, String> properties = JAXBUtils.mapFromXProperties(xDimTable.getProperties()); |
| Map<String, StorageTableDesc> storageDesc = JAXBUtils.tableDescPrefixMapFromXStorageTables( |
| xDimTable.getStorageTables()); |
| log.info("# Columns: " + columns); |
| createCubeDimensionTable(xDimTable.getDimensionName(), xDimTable.getTableName(), columns, xDimTable.getWeight(), |
| updatePeriodMap, properties, storageDesc); |
| } |
| |
| /** |
| * Create a cube dimension table |
| * |
| * @param dimName The dimension name to which the dim-table belongs to |
| * @param dimTblName dimension table name |
| * @param columns Columns of the dimension table |
| * @param weight Weight of the dimension table |
| * @param storageNames Storages on which dimension is available without any dumps |
| * @param properties Properties of dimension table |
| * @param storageTableDescs Map of storage to its storage table description |
| * @throws LensException |
| */ |
| public void createCubeDimensionTable(String dimName, String dimTblName, List<FieldSchema> columns, double weight, |
| Set<String> storageNames, Map<String, String> properties, Map<String, StorageTableDesc> storageTableDescs) |
| throws LensException { |
| CubeDimensionTable dimTable = |
| new CubeDimensionTable(dimName, dimTblName, columns, weight, storageNames, properties); |
| checkIfAuthorized(); |
| createCubeTable(dimTable, storageTableDescs); |
| // do a get to update cache |
| getDimensionTable(dimTblName); |
| } |
| |
| /** |
| * Create a cube dimension table |
| * |
| * @param dimName The dimension name to which the dim-table belongs to |
| * @param dimTblName dimension table name |
| * @param columns Columns of the dimension table |
| * @param weight Weight of the dimension table |
| * @param dumpPeriods Storage names and their dump periods on which dimension is available |
| * @param properties properties of dimension table |
| * @param storageTableDescs Map of storage to its storage table description |
| * @throws LensException |
| */ |
| public void createCubeDimensionTable(String dimName, String dimTblName, List<FieldSchema> columns, double weight, |
| Map<String, UpdatePeriod> dumpPeriods, Map<String, String> properties, |
| Map<String, StorageTableDesc> storageTableDescs) throws LensException { |
| checkIfAuthorized(); |
| CubeDimensionTable dimTable = new CubeDimensionTable(dimName, dimTblName, columns, weight, dumpPeriods, properties); |
| createCubeTable(dimTable, storageTableDescs); |
| // do a get to update cache |
| getDimensionTable(dimTblName); |
| } |
| |
| /** |
| * Create cube table defined and create all the corresponding storage tables |
| * |
| * @param cubeTable Can be fact or dimension table |
| * @param storageTableDescs Map of storage tableName prefix to its storage table description |
| * @throws LensException |
| */ |
| public void createCubeTable(AbstractCubeTable cubeTable, Map<String, StorageTableDesc> storageTableDescs) |
| throws LensException { |
| // create virtual cube table in metastore |
| Table cTable = createCubeHiveTable(cubeTable); |
| |
| if (storageTableDescs != null) { |
| // create tables for each storage |
| for (Map.Entry<String, StorageTableDesc> entry : storageTableDescs.entrySet()) { |
| createOrAlterStorageHiveTable(cTable, entry.getKey(), entry.getValue()); |
| } |
| } |
| } |
| |
| public void createSegmentation(XSegmentation cubeSeg) throws LensException { |
| createSegmentation( |
| cubeSeg.getCubeName(), |
| cubeSeg.getName(), |
| JAXBUtils.segmentsFromXSegments(cubeSeg.getSegements()), |
| cubeSeg.getWeight(), |
| JAXBUtils.mapFromXProperties(cubeSeg.getProperties())); |
| } |
| |
| public void createSegmentation(Segmentation cubeSeg) |
| throws LensException { |
| checkIfAuthorized(); |
| // create virtual cube table in metastore |
| createCubeHiveTable(cubeSeg); |
| } |
| |
| /** |
| * Adds storage to fact and creates corresponding storage table |
| * |
| * @param fact The CubeFactTable |
| * @param storage The storage |
| * @param updatePeriods Update periods of the fact on the storage |
| * @param storageTableDescs The storage table description |
| * @throws LensException |
| */ |
| public void addStorage(CubeFactTable fact, String storage, Set<UpdatePeriod> updatePeriods, |
| Map<String, StorageTableDesc> storageTableDescs, Map<UpdatePeriod, String> updatePeriodStoragePrefix) |
| throws LensException { |
| checkIfAuthorized(); |
| fact.addStorage(storage, updatePeriods, updatePeriodStoragePrefix); |
| for (Map.Entry entry : storageTableDescs.entrySet()) { |
| createOrAlterStorageHiveTable(getTableWithTypeFailFast(fact.getName(), CubeTableType.FACT), |
| (String) entry.getKey(), (StorageTableDesc) entry.getValue()); |
| } |
| alterCubeTable(fact.getName(), getTableWithTypeFailFast(fact.getName(), CubeTableType.FACT), fact); |
| updateFactCache(fact.getName()); |
| } |
| |
| /** |
| * Adds storage to dimension and creates corresponding storage table |
| * |
| * @param dim The CubeDimensionTable |
| * @param storage The storage |
| * @param dumpPeriod The dumpPeriod if any, null otherwise |
| * @param storageTableDesc The storage table description |
| * @throws LensException |
| */ |
| public void addStorage(CubeDimensionTable dim, String storage, UpdatePeriod dumpPeriod, |
| StorageTableDesc storageTableDesc) throws LensException { |
| checkIfAuthorized(); |
| dim.alterSnapshotDumpPeriod(storage, dumpPeriod); |
| createOrAlterStorageHiveTable(getTableWithTypeFailFast(dim.getName(), CubeTableType.DIM_TABLE), storage, |
| storageTableDesc); |
| alterCubeTable(dim.getName(), getTableWithTypeFailFast(dim.getName(), CubeTableType.DIM_TABLE), dim); |
| updateDimCache(dim.getName()); |
| } |
| |
| /** |
| * Add a partition specified by the storage partition desc on the storage passed. |
| * <p></p> |
| * TODO: separate methods for fact and dim partition addition. |
| * |
| * @param partSpec The storage partition description |
| * @param storageName The storage object |
| * @param type |
| * @throws HiveException |
| */ |
| public List<Partition> addPartition(StoragePartitionDesc partSpec, String storageName, CubeTableType type) |
| throws HiveException, LensException { |
| return addPartitions(Collections.singletonList(partSpec), storageName, type); |
| } |
| |
| /** batch addition */ |
| public List<Partition> addPartitions(List<StoragePartitionDesc> storagePartitionDescs, String storageName, |
| CubeTableType type) |
| throws HiveException, LensException { |
| List<Partition> partsAdded = Lists.newArrayList(); |
| for (Map.Entry<String, Map<UpdatePeriod, List<StoragePartitionDesc>>> group : groupPartitionDescs( |
| storagePartitionDescs).entrySet()) { |
| String factOrDimtable = group.getKey(); |
| for (Map.Entry<UpdatePeriod, List<StoragePartitionDesc>> entry : group.getValue().entrySet()) { |
| partsAdded.addAll(addPartitions(factOrDimtable, storageName, entry.getKey(), entry.getValue(), type)); |
| } |
| } |
| return partsAdded; |
| } |
| |
| /** |
| * @param factOrDimTable |
| * @param storageName |
| * @param updatePeriod |
| * @param storagePartitionDescs |
| * @param type |
| * @return |
| * @throws HiveException |
| * @throws LensException |
| */ |
| private List<Partition> addPartitions(String factOrDimTable, String storageName, UpdatePeriod updatePeriod, |
| List<StoragePartitionDesc> storagePartitionDescs, CubeTableType type) |
| throws HiveException, LensException { |
| String storageTableName = getStorageTableName(factOrDimTable, storageName, updatePeriod); |
| if (type == CubeTableType.DIM_TABLE) { |
| // Adding partition in dimension table. |
| Map<Map<String, String>, LatestInfo> latestInfos = Maps.newHashMap(); |
| for (Map.Entry<Map<String, String>, List<StoragePartitionDesc>> entry : groupByNonTimePartitions( |
| storagePartitionDescs).entrySet()) { |
| latestInfos.put(entry.getKey(), |
| getDimTableLatestInfo(storageTableName, entry.getKey(), getTimePartSpecs(entry.getValue()), updatePeriod)); |
| } |
| List<Partition> partsAdded = |
| getStorage(storageName).addPartitions(getClient(), factOrDimTable, updatePeriod, storagePartitionDescs, |
| latestInfos, storageTableName); |
| ListIterator<Partition> iter = partsAdded.listIterator(); |
| while (iter.hasNext()) { |
| if (iter.next().getSpec().values().contains(StorageConstants.LATEST_PARTITION_VALUE)) { |
| iter.remove(); |
| } |
| } |
| latestLookupCache.add(storageTableName); |
| return partsAdded; |
| } else if (type == CubeTableType.FACT) { |
| List<Partition> partsAdded = new ArrayList<>(); |
| // first update in memory, then add to hive table's partitions. delete is reverse. |
| partitionTimelineCache.updateForAddition(factOrDimTable, storageName, updatePeriod, |
| getTimePartSpecs(storagePartitionDescs, getStorageTableStartDate(storageTableName, |
| getFactTable(factOrDimTable)), getStorageTableEndDate(storageTableName, getFactTable(factOrDimTable)))); |
| // Adding partition in fact table. |
| if (storagePartitionDescs.size() > 0) { |
| partsAdded = getStorage(storageName).addPartitions(getClient(), factOrDimTable, updatePeriod, |
| storagePartitionDescs, null, storageTableName); |
| } |
| // update hive table |
| alterTablePartitionCache((Storage.getPrefix(storageName) + factOrDimTable).toLowerCase(), updatePeriod, |
| storageTableName); |
| return partsAdded; |
| } else { |
| throw new LensException("Can't add partitions to anything other than fact or dimtable"); |
| } |
| } |
| |
| public Date getStorageTableStartDate(String storageTable, FactTable factTableName) |
| throws LensException { |
| List<Date> startDates = getStorageTimes(storageTable, MetastoreUtil.getStoragetableStartTimesKey()); |
| startDates.add(factTableName.getStartTime()); |
| return Collections.max(startDates); |
| } |
| |
| public Date getStorageTableEndDate(String storageTable, FactTable factTableName) |
| throws LensException { |
| List<Date> endDates = getStorageTimes(storageTable, MetastoreUtil.getStoragetableEndTimesKey()); |
| endDates.add(factTableName.getEndTime()); |
| return Collections.min(endDates); |
| } |
| |
| private Map<String, TreeSet<Date>> getTimePartSpecs(List<StoragePartitionDesc> storagePartitionDescs) { |
| Map<String, TreeSet<Date>> timeSpecs = Maps.newHashMap(); |
| for (StoragePartitionDesc storagePartitionDesc : storagePartitionDescs) { |
| for (Map.Entry<String, Date> entry : storagePartitionDesc.getTimePartSpec().entrySet()) { |
| if (!timeSpecs.containsKey(entry.getKey())) { |
| timeSpecs.put(entry.getKey(), Sets.<Date>newTreeSet()); |
| } |
| timeSpecs.get(entry.getKey()).add(entry.getValue()); |
| } |
| } |
| return timeSpecs; |
| } |
| |
| |
| private Map<String, TreeSet<Date>> getTimePartSpecs(List<StoragePartitionDesc> storagePartitionDescs, |
| Date storageStartDate, Date storageEndDate) throws LensException { |
| Date now = new Date(); |
| Map<String, HashSet<Date>> skippedParts = Maps.newHashMap(); |
| Map<String, TreeSet<Date>> timeSpecs = Maps.newHashMap(); |
| Iterator<StoragePartitionDesc> itr = storagePartitionDescs.iterator(); |
| while (itr.hasNext()) { |
| StoragePartitionDesc storageDesc = itr.next(); |
| for (Map.Entry<String, Date> entry : storageDesc.getTimePartSpec().entrySet()) { |
| if (!timeSpecs.containsKey(entry.getKey())) { |
| timeSpecs.put(entry.getKey(), Sets.<Date>newTreeSet()); |
| } |
| // check whether partition falls between storage table start_time and |
| // end_time or d+2, in such case partition is eligible for registration. |
| if ((entry.getValue().compareTo(storageStartDate) >= 0 && entry.getValue().compareTo(storageEndDate) < 0) |
| && entry.getValue().compareTo(DateUtil.resolveRelativeDate("now +2 days", now)) < 0) { |
| timeSpecs.get(entry.getKey()).add(entry.getValue()); |
| } else { |
| if (!skippedParts.containsKey(entry.getKey())) { |
| skippedParts.put(entry.getKey(), Sets.newHashSet(entry.getValue())); |
| } else { |
| skippedParts.get(entry.getKey()).add(entry.getValue()); |
| } |
| itr.remove(); |
| break; |
| } |
| } |
| } |
| if (!skippedParts.isEmpty()) { |
| log.info("List of partitions skipped : {}, because they fall before fact start time " |
| + "or after end time or they are future partitions", skippedParts); |
| } |
| return timeSpecs; |
| } |
| |
| private Map<String, Map<UpdatePeriod, List<StoragePartitionDesc>>> groupPartitionDescs( |
| List<StoragePartitionDesc> partitionDescs) { |
| Map<String, Map<UpdatePeriod, List<StoragePartitionDesc>>> ret = Maps.newHashMap(); |
| for (StoragePartitionDesc partitionDesc : partitionDescs) { |
| if (ret.get(partitionDesc.getCubeTableName()) == null) { |
| ret.put(partitionDesc.getCubeTableName(), Maps.<UpdatePeriod, List<StoragePartitionDesc>>newHashMap()); |
| } |
| if (ret.get(partitionDesc.getCubeTableName()).get(partitionDesc.getUpdatePeriod()) == null) { |
| ret.get(partitionDesc.getCubeTableName()).put(partitionDesc.getUpdatePeriod(), |
| Lists.<StoragePartitionDesc>newArrayList()); |
| } |
| ret.get(partitionDesc.getCubeTableName()).get(partitionDesc.getUpdatePeriod()).add(partitionDesc); |
| } |
| return ret; |
| } |
| |
| /** |
| * store back all timelines of given storage to table properties |
| * |
| * @param timeLineKey key for the time line |
| * @param storageTableName Storage table name |
| * @throws HiveException |
| */ |
| private void alterTablePartitionCache(String timeLineKey, UpdatePeriod updatePeriod, String storageTableName) |
| throws HiveException, LensException { |
| Table table = getTable(storageTableName); |
| Map<String, String> params = table.getParameters(); |
| if (partitionTimelineCache.get(timeLineKey) != null) { |
| for (Map.Entry<String, PartitionTimeline> entry : partitionTimelineCache.get(timeLineKey).get(updatePeriod) |
| .entrySet()) { |
| entry.getValue().updateTableParams(table); |
| } |
| params.put(getPartitionTimelineCachePresenceKey(), "true"); |
| alterHiveTable(storageTableName, table); |
| } |
| } |
| |
| /** extract update period from partition properties */ |
| private UpdatePeriod deduceUpdatePeriod(Partition partition) { |
| return UpdatePeriod.valueOf(partition.getParameters().get(MetastoreConstants.PARTITION_UPDATE_PERIOD)); |
| } |
| |
| private LatestInfo getDimTableLatestInfo(String storageTableName, Map<String, String> nonTimeParts, |
| Map<String, TreeSet<Date>> timePartSpecs, |
| UpdatePeriod updatePeriod) throws HiveException, LensException { |
| Table hiveTable = getHiveTable(storageTableName); |
| String timePartColsStr = hiveTable.getTTable().getParameters().get(MetastoreConstants.TIME_PART_COLUMNS); |
| if (timePartColsStr != null) { |
| LatestInfo latest = new LatestInfo(); |
| String[] timePartCols = StringUtils.split(timePartColsStr, ','); |
| for (String partCol : timePartCols) { |
| if (!timePartSpecs.containsKey(partCol)) { |
| continue; |
| } |
| boolean makeLatest = true; |
| Partition part = getLatestPart(storageTableName, partCol, nonTimeParts); |
| Date pTimestamp = timePartSpecs.get(partCol).last(); |
| Date latestTimestamp = getLatestTimeStampFromPartition(part, partCol); |
| if (latestTimestamp != null && pTimestamp.before(latestTimestamp)) { |
| makeLatest = false; |
| } |
| |
| if (makeLatest) { |
| Map<String, String> latestParams = LensUtil.getHashMap(getLatestPartTimestampKey(partCol), |
| updatePeriod.format(pTimestamp)); |
| latest.latestParts.put(partCol, new LatestPartColumnInfo(latestParams)); |
| } |
| } |
| return latest; |
| } else { |
| return null; |
| } |
| } |
| |
| private Map<Map<String, String>, List<StoragePartitionDesc>> groupByNonTimePartitions( |
| List<StoragePartitionDesc> storagePartitionDescs) { |
| Map<Map<String, String>, List<StoragePartitionDesc>> result = Maps.newHashMap(); |
| for (StoragePartitionDesc storagePartitionDesc : storagePartitionDescs) { |
| if (result.get(storagePartitionDesc.getNonTimePartSpec()) == null) { |
| result.put(storagePartitionDesc.getNonTimePartSpec(), Lists.<StoragePartitionDesc>newArrayList()); |
| } |
| result.get(storagePartitionDesc.getNonTimePartSpec()).add(storagePartitionDesc); |
| } |
| return result; |
| } |
| |
| private boolean isLatestPartOfDimtable(Partition part) { |
| return part.getValues().contains(StorageConstants.LATEST_PARTITION_VALUE); |
| } |
| |
| private Date getPartDate(Partition part, int timeColIndex) { |
| String partVal = part.getValues().get(timeColIndex); |
| String updatePeriodStr = part.getParameters().get(MetastoreConstants.PARTITION_UPDATE_PERIOD); |
| Date partDate = null; |
| if (updatePeriodStr != null) { |
| UpdatePeriod partInterval = UpdatePeriod.valueOf(updatePeriodStr); |
| try { |
| partDate = partInterval.parse(partVal); |
| } catch (ParseException e) { |
| // ignore |
| } |
| } |
| return partDate; |
| } |
| |
| private LatestInfo getNextLatestOfDimtable(Table hiveTable, String timeCol, final int timeColIndex, |
| UpdatePeriod updatePeriod, Map<String, String> nonTimePartSpec) |
| throws HiveException { |
| // getClient().getPartitionsByNames(tbl, partNames) |
| List<Partition> partitions; |
| try { |
| partitions = getClient().getPartitionsByFilter(hiveTable, StorageConstants.getPartFilter(nonTimePartSpec)); |
| filterPartitionsByUpdatePeriod(partitions, updatePeriod); |
| filterPartitionsByNonTimeParts(partitions, nonTimePartSpec, timeCol); |
| } catch (TException e) { |
| throw new HiveException(e); |
| } |
| |
| // tree set contains partitions with timestamp as value for timeCol, in |
| // descending order |
| TreeSet<Partition> allPartTimeVals = new TreeSet<>(new Comparator<Partition>() { |
| @Override |
| public int compare(Partition o1, Partition o2) { |
| Date partDate1 = getPartDate(o1, timeColIndex); |
| Date partDate2 = getPartDate(o2, timeColIndex); |
| if (partDate1 != null && partDate2 == null) { |
| return -1; |
| } else if (partDate1 == null && partDate2 != null) { |
| return 1; |
| } else if (partDate1 == null) { |
| return o2.getTPartition().compareTo(o1.getTPartition()); |
| } else if (!partDate2.equals(partDate1)) { |
| return partDate2.compareTo(partDate1); |
| } else { |
| return o2.getTPartition().compareTo(o1.getTPartition()); |
| } |
| } |
| }); |
| for (Partition part : partitions) { |
| if (!isLatestPartOfDimtable(part)) { |
| Date partDate = getPartDate(part, timeColIndex); |
| if (partDate != null) { |
| allPartTimeVals.add(part); |
| } |
| } |
| } |
| Iterator<Partition> it = allPartTimeVals.iterator(); |
| it.next(); // Skip itself. We have to find next latest. |
| LatestInfo latest = null; |
| if (it.hasNext()) { |
| Partition nextLatest = it.next(); |
| latest = new LatestInfo(); |
| latest.setPart(nextLatest); |
| Map<String, String> latestParams = LensUtil.getHashMap(getLatestPartTimestampKey(timeCol), |
| nextLatest.getValues().get(timeColIndex)); |
| latest.addLatestPartInfo(timeCol, new LatestPartColumnInfo(latestParams)); |
| } |
| return latest; |
| } |
| |
| /** |
| * Add a partition specified by the storage partition desc on the storage passed. |
| * |
| * @param cubeTableName cube fact/dimension table name |
| * @param storageName storage name |
| * @param timePartSpec time partitions |
| * @param nonTimePartSpec non time partitions |
| * @param updatePeriod update period of the partition |
| * @throws HiveException |
| */ |
| public void dropPartition(String cubeTableName, String storageName, Map<String, Date> timePartSpec, |
| Map<String, String> nonTimePartSpec, UpdatePeriod updatePeriod) throws HiveException, LensException { |
| String storageTableName = getStorageTableName(cubeTableName.trim(), storageName, updatePeriod); |
| Table hiveTable = getHiveTable(storageTableName); |
| List<FieldSchema> partCols = hiveTable.getPartCols(); |
| List<String> partColNames = new ArrayList<>(partCols.size()); |
| List<String> partVals = new ArrayList<>(partCols.size()); |
| for (FieldSchema column : partCols) { |
| partColNames.add(column.getName()); |
| if (timePartSpec.containsKey(column.getName())) { |
| partVals.add(updatePeriod.format(timePartSpec.get(column.getName()))); |
| } else if (nonTimePartSpec.containsKey(column.getName())) { |
| partVals.add(nonTimePartSpec.get(column.getName())); |
| } else { |
| throw new HiveException("Invalid partspec, missing value for" + column.getName()); |
| } |
| } |
| if (isDimensionTable(cubeTableName)) { |
| String timePartColsStr = hiveTable.getTTable().getParameters().get(MetastoreConstants.TIME_PART_COLUMNS); |
| Map<String, LatestInfo> latest = new HashMap<>(); |
| boolean latestAvailable = false; |
| if (timePartColsStr != null) { |
| List<String> timePartCols = Arrays.asList(StringUtils.split(timePartColsStr, ',')); |
| for (String timeCol : timePartSpec.keySet()) { |
| if (!timePartCols.contains(timeCol)) { |
| throw new HiveException("Not a time partition column:" + timeCol); |
| } |
| int timeColIndex = partColNames.indexOf(timeCol); |
| Partition part = getLatestPart(storageTableName, timeCol, nonTimePartSpec); |
| |
| Date latestTimestamp = getLatestTimeStampFromPartition(part, timeCol); |
| Date dropTimestamp; |
| try { |
| dropTimestamp = updatePeriod.parse(updatePeriod.format(timePartSpec.get(timeCol))); |
| } catch (ParseException e) { |
| throw new HiveException(e); |
| } |
| // check if partition being dropped is the latest partition |
| boolean isLatest = latestTimestamp != null && dropTimestamp.equals(latestTimestamp); |
| if (isLatest) { |
| for (int i = 0; i < partVals.size(); i++) { |
| if (i != timeColIndex) { |
| if (!part.getValues().get(i).equals(partVals.get(i))) { |
| isLatest = false; |
| break; |
| } |
| } |
| } |
| } |
| if (isLatest) { |
| LatestInfo latestInfo = |
| getNextLatestOfDimtable(hiveTable, timeCol, timeColIndex, updatePeriod, nonTimePartSpec); |
| latestAvailable = (latestInfo != null && latestInfo.part != null); |
| latest.put(timeCol, latestInfo); |
| } else { |
| latestAvailable = true; |
| } |
| } |
| } else { |
| if (timePartSpec != null && !timePartSpec.isEmpty()) { |
| throw new HiveException("Not time part columns" + timePartSpec.keySet()); |
| } |
| } |
| getStorage(storageName).dropPartition(getClient(), storageTableName, partVals, latest, nonTimePartSpec); |
| if (!latestAvailable) { |
| // dropping latest and could not find latest, removing the entry from latest lookup cache |
| latestLookupCache.remove(storageTableName); |
| } |
| } else { |
| // dropping fact partition |
| getStorage(storageName).dropPartition(getClient(), storageTableName, partVals, null, null); |
| if (partitionTimelineCache.updateForDeletion(cubeTableName, storageName, updatePeriod, timePartSpec)) { |
| this.alterTablePartitionCache((Storage.getPrefix(storageName) + cubeTableName).toLowerCase(), updatePeriod, |
| storageTableName); |
| } |
| } |
| } |
| |
| private Map<String, String> getPartitionSpec(UpdatePeriod updatePeriod, Map<String, Date> partitionTimestamps) { |
| Map<String, String> partSpec = new HashMap<>(); |
| for (Map.Entry<String, Date> entry : partitionTimestamps.entrySet()) { |
| String pval = updatePeriod.format(entry.getValue()); |
| partSpec.put(entry.getKey(), pval); |
| } |
| return partSpec; |
| } |
| |
| public boolean tableExists(String tblName) throws HiveException { |
| try { |
| return (getClient().getTable(tblName.toLowerCase(), false) != null); |
| } catch (HiveException e) { |
| throw new HiveException("Could not check whether table exists", e); |
| } |
| } |
| |
| /** extract storage name and check in timeline cache for existance */ |
| public boolean factPartitionExists(FactTable fact, FactPartition part, String storageTableName) |
| throws HiveException, LensException { |
| String storage = extractStorageName(fact, storageTableName); |
| return partitionTimelineCache.partitionTimeExists(fact.getSourceFactName(), storage, |
| part.getPeriod(), part.getPartCol(), part.getPartSpec()); |
| } |
| |
| public boolean factPartitionExists(String factName, String storageName, UpdatePeriod updatePeriod, |
| Map<String, Date> partitionTimestamp, |
| Map<String, String> partSpec) throws HiveException, LensException { |
| String storageTableName = getStorageTableName(factName, storageName, updatePeriod); |
| return partitionExists(storageTableName, updatePeriod, partitionTimestamp, partSpec); |
| } |
| |
| public boolean partitionExists(String storageTableName, UpdatePeriod updatePeriod, |
| Map<String, Date> partitionTimestamps) throws HiveException, LensException { |
| return partitionExists(storageTableName, getPartitionSpec(updatePeriod, partitionTimestamps)); |
| } |
| |
| public boolean partitionExistsByFilter(String cubeTableName, String storageName, UpdatePeriod updatePeriod, |
| String filter) throws LensException { |
| return partitionExistsByFilter(getStorageTableName(cubeTableName, storageName, updatePeriod), filter); |
| } |
| |
| public boolean partitionExistsByFilter(String storageTableName, String filter) throws LensException { |
| int parts; |
| Table tbl; |
| try { |
| tbl = getTable(storageTableName); |
| } catch (Exception e) { |
| return false; |
| } |
| try { |
| parts = getClient().getNumPartitionsByFilter(tbl, filter); |
| } catch (Exception e) { |
| throw new LensException("Could not find partitions for given filter", e); |
| } |
| return parts > 0; |
| } |
| |
| public List<Partition> getAllParts(String storageTableName) throws HiveException, LensException { |
| return getClient().getPartitions(getHiveTable(storageTableName)); |
| } |
| |
| public Partition getPartitionByFilter(String storageTableName, String filter) throws HiveException { |
| List<Partition> parts = getPartitionsByFilter(storageTableName, filter); |
| if (parts.size() != 1) { |
| throw new HiveException( |
| "filter " + filter + " did not result in unique partition. Got " + parts.size() + "partitions"); |
| } |
| return parts.iterator().next(); |
| } |
| |
| public List<Partition> getPartitionsByFilter(String storageTableName, String filter) throws HiveException { |
| try { |
| return getClient().getPartitionsByFilter(getTable(storageTableName), filter); |
| } catch (Exception e) { |
| throw new HiveException(e); |
| } |
| } |
| |
| boolean partitionExists(String storageTableName, UpdatePeriod updatePeriod, Map<String, Date> partitionTimestamps, |
| Map<String, String> nonTimePartSpec) throws HiveException, LensException { |
| HashMap<String, String> partSpec = new HashMap<>(nonTimePartSpec); |
| partSpec.putAll(getPartitionSpec(updatePeriod, partitionTimestamps)); |
| return partitionExists(storageTableName, partSpec); |
| } |
| |
| private boolean partitionExists(String storageTableName, Map<String, String> partSpec) throws LensException { |
| try { |
| Table storageTbl = getTable(storageTableName); |
| Partition p = getClient().getPartition(storageTbl, partSpec, false); |
| return (p != null && p.getTPartition() != null); |
| } catch (HiveException e) { |
| throw new LensException("Could not check whether table exists", e); |
| } |
| } |
| |
| boolean dimPartitionExists(String dimTblName, String storageName, Map<String, Date> partitionTimestamps) |
| throws HiveException, LensException { |
| String storageTableName = getFactOrDimtableStorageTableName(dimTblName, storageName); |
| return partitionExists(storageTableName, getDimensionTable(dimTblName).getSnapshotDumpPeriods().get(storageName), |
| partitionTimestamps); |
| } |
| |
| boolean latestPartitionExists(String factOrDimTblName, String storageName, String latestPartCol) |
| throws HiveException, LensException { |
| String storageTableName = MetastoreUtil.getStorageTableName(factOrDimTblName, Storage.getPrefix(storageName)); |
| if (isDimensionTable(factOrDimTblName)) { |
| return dimTableLatestPartitionExists(storageTableName); |
| } else { |
| return !partitionTimelineCache.noPartitionsExist(factOrDimTblName, storageName, latestPartCol); |
| } |
| } |
| |
| private boolean dimTableLatestPartitionExistsInMetastore(String storageTableName, String latestPartCol) |
| throws LensException { |
| return partitionExistsByFilter(storageTableName, StorageConstants.getLatestPartFilter(latestPartCol)); |
| } |
| |
| public boolean dimTableLatestPartitionExists(String storageTableName) { |
| return latestLookupCache.contains(storageTableName.trim().toLowerCase()); |
| } |
| |
| Partition getLatestPart(String storageTableName, String latestPartCol, Map<String, String> nonTimeParts) |
| throws HiveException { |
| List<Partition> latestParts = |
| getPartitionsByFilter(storageTableName, StorageConstants.getLatestPartFilter(latestPartCol, nonTimeParts)); |
| if (latestParts != null && !latestParts.isEmpty()) { |
| return latestParts.get(0); |
| } |
| return null; |
| } |
| |
| /** |
| * Get the hive {@link Table} corresponding to the name |
| * |
| * @param tableName table name |
| * @return {@link Table} object corresponding to the name |
| * @throws LensException |
| */ |
| public Table getHiveTable(String tableName) throws LensException { |
| return getTable(tableName); |
| } |
| |
| public List<String> getTimePartColNamesOfTable(String storageTableName) throws LensException { |
| return getTimePartColNamesOfTable(getTable(storageTableName)); |
| } |
| |
| /** extract from table properties */ |
| public List<String> getTimePartColNamesOfTable(Table table) { |
| List<String> ret = null; |
| if (table.getParameters().containsKey(MetastoreConstants.TIME_PART_COLUMNS)) { |
| ret = Arrays.asList(StringUtils.split(table.getParameters().get(MetastoreConstants.TIME_PART_COLUMNS), ",")); |
| } |
| return ret == null ? new ArrayList<String>() : ret; |
| } |
| |
| public Table getTableWithTypeFailFast(String tableName, CubeTableType type) throws LensException { |
| return getTableWithType(tableName, type, true); |
| } |
| |
| public Table getTableWithType(String tableName, CubeTableType type, boolean throwException) throws LensException { |
| String typeName = type == null ? "nativetable" : type.name().toLowerCase(); |
| Table table = getTable(tableName, false); |
| if (table == null) { |
| if (throwException) { |
| throw new LensException(LensCubeErrorCode.ENTITY_NOT_FOUND.getLensErrorInfo(), typeName, tableName); |
| } else { |
| return null; |
| } |
| } |
| if (type == null && table.getParameters().get(MetastoreConstants.TABLE_TYPE_KEY) != null) { |
| if (throwException) { |
| throw new LensException(LensCubeErrorCode.ENTITY_NOT_FOUND.getLensErrorInfo(), typeName, tableName); |
| } else { |
| return null; |
| } |
| } |
| if (type != null) { |
| String typeStr = table.getParameters().get(MetastoreConstants.TABLE_TYPE_KEY); |
| if (typeStr == null || CubeTableType.valueOf(typeStr.toUpperCase()) != type) { |
| if (throwException) { |
| throw new LensException(LensCubeErrorCode.ENTITY_NOT_FOUND.getLensErrorInfo(), typeName, tableName); |
| } else { |
| return null; |
| } |
| } |
| } |
| return table; |
| } |
| |
| public Table getTable(String tableName) throws LensException { |
| return getTable(tableName, true); |
| } |
| |
| public Table getTable(String tableName, boolean throwException) throws LensException { |
| Table tbl; |
| try { |
| tableName = tableName.trim().toLowerCase(); |
| tbl = allHiveTables.get(tableName); |
| if (tbl == null) { |
| synchronized (allHiveTables) { |
| if (!allHiveTables.containsKey(tableName)) { |
| tbl = getClient().getTable(tableName, throwException); |
| if (enableCaching && tbl != null) { |
| allHiveTables.put(tableName, tbl); |
| } |
| } else { |
| tbl = allHiveTables.get(tableName); |
| } |
| } |
| } |
| } catch (HiveException e) { |
| throw new LensException("Could not get table: " + tableName, e); |
| } |
| return tbl; |
| } |
| |
| private Table refreshTable(String tableName) throws LensException { |
| Table tbl; |
| try { |
| tableName = tableName.trim().toLowerCase(); |
| tbl = getClient().getTable(tableName); |
| allHiveTables.put(tableName, tbl); |
| } catch (HiveException e) { |
| throw new LensException("Could not get table: " + tableName, e); |
| } |
| return tbl; |
| } |
| |
| public void dropHiveTable(String table) throws LensException { |
| try { |
| getClient().dropTable(table); |
| } catch (HiveException e) { |
| throw new LensException("Couldn't drop hive table: " + table, e); |
| } |
| allHiveTables.remove(table.trim().toLowerCase()); |
| } |
| |
| /** |
| * Is the table name passed a fact table? |
| * |
| * @param tableName table name |
| * @return true if it is cube fact, false otherwise |
| * @throws HiveException |
| */ |
| public boolean isFactTable(String tableName) throws LensException { |
| Table tbl = getTable(tableName); |
| return isFactTable(tbl); |
| } |
| |
| boolean isFactTable(Table tbl) { |
| String tableType = tbl.getParameters().get(MetastoreConstants.TABLE_TYPE_KEY); |
| return CubeTableType.FACT.name().equals(tableType) |
| && tbl.getParameters().get(getSourceFactNameKey(tbl.getTableName())) == null; |
| } |
| |
| boolean isFactTableForCube(Table tbl, String cube) { |
| return isFactTable(tbl) && tbl.getParameters().get(MetastoreUtil.getFactCubeNameKey(tbl.getTableName())) |
| .equalsIgnoreCase(cube.toLowerCase()); |
| } |
| |
| /** |
| * Is the table name passed a virtual fact table? |
| * |
| * @param virtualTableName table name |
| * @return true if it is virtual fact, false otherwise |
| * @throws HiveException |
| */ |
| public boolean isVirtualFactTable(String virtualTableName) throws LensException { |
| Table tbl = getTable(virtualTableName); |
| return isVirtualFactTable(tbl); |
| } |
| |
| boolean isVirtualFactTable(Table tbl) { |
| String tableType = tbl.getParameters().get(MetastoreConstants.TABLE_TYPE_KEY); |
| return CubeTableType.FACT.name().equals(tableType) |
| && tbl.getParameters().get(getSourceFactNameKey(tbl.getTableName())) != null; |
| } |
| |
| boolean isVirtualFactTableForCube(Table tbl, String cube) { |
| return isVirtualFactTable(tbl) && tbl.getParameters().get(MetastoreUtil.getFactCubeNameKey(tbl.getTableName())) |
| .equalsIgnoreCase(cube.toLowerCase()); |
| } |
| |
| /** |
| * Is the table name passed a dimension table? |
| * |
| * @param tableName table name |
| * @return true if it is cube dimension, false otherwise |
| * @throws LensException |
| */ |
| public boolean isDimensionTable(String tableName) throws LensException { |
| Table tbl = getTable(tableName); |
| return isDimensionTable(tbl); |
| } |
| |
| boolean isDimensionTable(Table tbl) { |
| String tableType = tbl.getParameters().get(MetastoreConstants.TABLE_TYPE_KEY); |
| return CubeTableType.DIM_TABLE.name().equals(tableType); |
| } |
| |
| /** |
| * Is the table name passed a cube? |
| * |
| * @param tableName table name |
| * @return true if it is cube, false otherwise |
| * @throws LensException |
| */ |
| public boolean isCube(String tableName) throws LensException { |
| if (allCubesPopulated) { |
| if (allCubes.containsKey(tableName.trim().toLowerCase())) { |
| return true; |
| } |
| } else { |
| Table tbl = getTable(tableName); |
| return isCube(tbl); |
| } |
| return false; |
| } |
| |
| /** |
| * Is the table name passed a dimension? |
| * |
| * @param tableName table name |
| * @return true if it is dimension, false otherwise |
| * @throws LensException |
| */ |
| public boolean isDimension(String tableName) throws LensException { |
| if (allDimensionsPopulated) { |
| if (allDims.containsKey(tableName.trim().toLowerCase())) { |
| return true; |
| } |
| } else { |
| Table tbl = getTable(tableName); |
| return isDimension(tbl); |
| } |
| return false; |
| } |
| |
| /** |
| * Is the hive table a cube table? |
| * |
| * @param tbl table |
| * @return whether it's a cube table or not |
| */ |
| boolean isCube(Table tbl) { |
| String tableType = tbl.getParameters().get(MetastoreConstants.TABLE_TYPE_KEY); |
| return CubeTableType.CUBE.name().equals(tableType); |
| } |
| |
| /** |
| * Is the hive table a dimension? |
| * |
| * @param tbl table |
| * @return whether the hive table is a dimension or not |
| */ |
| boolean isDimension(Table tbl) { |
| String tableType = tbl.getParameters().get(MetastoreConstants.TABLE_TYPE_KEY); |
| return CubeTableType.DIMENSION.name().equals(tableType); |
| } |
| |
| public XFact getXFactTable(String tableName) throws LensException { |
| return getXFactTable(getFactTable(tableName)); |
| } |
| |
| public XFact getXFactTable(FactTable ft) throws LensException { |
| |
| XFact fact; |
| if (ft.isVirtualFact()) { |
| CubeVirtualFactTable cvft = (CubeVirtualFactTable) ft; |
| XVirtualFactTable factTable = JAXBUtils.virtualFactTableFromVirtualCubeFactTable(cvft); |
| factTable.setSourceFactName(cvft.getSourceCubeFactTable().getName()); |
| fact = factTable; |
| } else { |
| CubeFactTable cft = (CubeFactTable) ft; |
| XFactTable factTable = JAXBUtils.factTableFromCubeFactTable(cft); |
| Map<String, Map<UpdatePeriod, String>> storageMap = cft.getStoragePrefixUpdatePeriodMap(); |
| for (String storageName : cft.getStorages()) { |
| Set<UpdatePeriod> updatePeriods = cft.getUpdatePeriods().get(storageName); |
| // This map tells if there are different tables for different update period. |
| Map<UpdatePeriod, String> updatePeriodToTableMap = storageMap.get(storageName); |
| Set<String> tableNames = new HashSet<>(); |
| for (UpdatePeriod updatePeriod : updatePeriods) { |
| tableNames.add(updatePeriodToTableMap.get(updatePeriod)); |
| } |
| if (tableNames.size() <= 1) { |
| XStorageTableElement tblElement = JAXBUtils.getXStorageTableFromHiveTable( |
| getHiveTable(MetastoreUtil.getFactOrDimtableStorageTableName(cft.getName(), storageName))); |
| tblElement.setStorageName(storageName); |
| for (UpdatePeriod p : updatePeriods) { |
| tblElement.getUpdatePeriods().getUpdatePeriod().add(XUpdatePeriod.valueOf(p.name())); |
| } |
| factTable.getStorageTables().getStorageTable().add(tblElement); |
| } else { |
| // Multiple storage tables. |
| XStorageTableElement tblElement = new XStorageTableElement(); |
| tblElement.setStorageName(storageName); |
| XUpdatePeriods xUpdatePeriods = new XUpdatePeriods(); |
| tblElement.setUpdatePeriods(xUpdatePeriods); |
| for (Map.Entry entry : updatePeriodToTableMap.entrySet()) { |
| XUpdatePeriodTableDescriptor updatePeriodTableDescriptor = new XUpdatePeriodTableDescriptor(); |
| updatePeriodTableDescriptor.setTableDesc(getStorageTableDescFromHiveTable( |
| this.getHiveTable(MetastoreUtil.getFactOrDimtableStorageTableName(cft.getName(), |
| (String) entry.getValue())))); |
| updatePeriodTableDescriptor.setUpdatePeriod(XUpdatePeriod.valueOf(((UpdatePeriod) entry.getKey()).name())); |
| xUpdatePeriods.getUpdatePeriodTableDescriptor().add(updatePeriodTableDescriptor); |
| } |
| factTable.getStorageTables().getStorageTable().add(tblElement); |
| } |
| } |
| fact = factTable; |
| } |
| return fact; |
| } |
| |
| public Segmentation getSegmentationTable(String tableName) throws HiveException, LensException { |
| return new Segmentation(getTableWithTypeFailFast(tableName, CubeTableType.SEGMENTATION)); |
| } |
| |
| public XDimensionTable getXDimensionTable(String dimTable) throws LensException { |
| return getXDimensionTable(getDimensionTable(dimTable)); |
| } |
| |
| public XDimensionTable getXDimensionTable(CubeDimensionTable dimTable) throws LensException { |
| XDimensionTable dt = JAXBUtils.dimTableFromCubeDimTable(dimTable); |
| if (!dimTable.getStorages().isEmpty()) { |
| for (String storageName : dimTable.getStorages()) { |
| XStorageTableElement tblElement = JAXBUtils.getXStorageTableFromHiveTable( |
| this.getHiveTable(MetastoreUtil.getFactOrDimtableStorageTableName(dimTable.getName(), storageName))); |
| tblElement.setStorageName(storageName); |
| UpdatePeriod p = dimTable.getSnapshotDumpPeriods().get(storageName); |
| if (p != null) { |
| tblElement.getUpdatePeriods().getUpdatePeriod().add(XUpdatePeriod.valueOf(p.name())); |
| } |
| dt.getStorageTables().getStorageTable().add(tblElement); |
| } |
| } |
| return dt; |
| } |
| |
| /** |
| * Get {@link CubeDimensionTable} object corresponding to the name |
| * |
| * @param tableName The cube dimension name |
| * @return Returns CubeDimensionTable if table name passed is a dimension table |
| * @throws LensException if there is no dimension table with the name |
| */ |
| public CubeDimensionTable getDimensionTable(String tableName) throws LensException { |
| return getDimensionTable(tableName, true); |
| } |
| |
| private CubeDimensionTable getDimensionTable(String tableName, boolean throwException) |
| throws LensException { |
| tableName = tableName.trim().toLowerCase(); |
| CubeDimensionTable dimTable = allDimTables.get(tableName); |
| if (dimTable == null) { |
| synchronized (allDimTables) { |
| if (!allDimTables.containsKey(tableName)) { |
| Table tbl = getTableWithType(tableName, CubeTableType.DIM_TABLE, throwException); |
| dimTable = tbl == null ? null : getDimensionTable(tbl); |
| if (enableCaching && dimTable != null) { |
| allDimTables.put(tableName, dimTable); |
| // update latest partition cache for all storages |
| if (!dimTable.getStorages().isEmpty()) { |
| for (String storageName : dimTable.getStorages()) { |
| if (dimTable.hasStorageSnapshots(storageName)) { |
| String storageTableName = getFactOrDimtableStorageTableName(dimTable.getName(), |
| storageName); |
| if (dimTableLatestPartitionExistsInMetastore(storageTableName, |
| getDimension(dimTable.getDimName()).getTimedDimension())) { |
| latestLookupCache.add(storageTableName.trim().toLowerCase()); |
| } |
| } |
| } |
| } |
| } |
| } else { |
| dimTable = allDimTables.get(tableName); |
| } |
| } |
| } |
| return dimTable; |
| } |
| |
| private CubeDimensionTable getDimensionTable(Table tbl) { |
| return new CubeDimensionTable(tbl); |
| } |
| |
| /** |
| * Get {@link Storage} object corresponding to the name |
| * |
| * @param storageName The storage name |
| * @return Returns storage if name passed is a storage |
| * @throws LensException if there is no storage by the name |
| */ |
| public Storage getStorage(String storageName) throws LensException { |
| return getStorage(storageName, true); |
| } |
| |
| public Storage getStorage(String storageName, boolean throwException) throws LensException { |
| storageName = storageName.trim().toLowerCase(); |
| Storage storage = allStorages.get(storageName); |
| if (storage == null) { |
| synchronized (allStorages) { |
| if (!allStorages.containsKey(storageName)) { |
| Table tbl = getTableWithType(storageName, CubeTableType.STORAGE, throwException); |
| if (tbl != null) { |
| storage = getStorage(tbl); |
| if (enableCaching && storage != null) { |
| allStorages.put(storageName, storage); |
| } |
| } |
| } else { |
| storage = allStorages.get(storageName); |
| } |
| } |
| } |
| return storage; |
| } |
| |
| private Storage getStorage(Table tbl) throws LensException { |
| return Storage.createInstance(tbl); |
| } |
| |
| /** |
| * Get {@link Cube} object corresponding to the name |
| * |
| * @param tableName The cube name |
| * @return Returns cube is table name passed is a cube |
| * @throws LensException when the table name does not correspond to a cube |
| */ |
| public CubeInterface getCube(String tableName) throws LensException { |
| return getCube(tableName, true); |
| } |
| |
| private CubeInterface getCube(String tableName, boolean throwException) throws LensException { |
| if (tableName == null) { |
| return null; |
| } |
| tableName = tableName.trim().toLowerCase(); |
| CubeInterface cube = allCubes.get(tableName); |
| if (cube == null) { |
| synchronized (allCubes) { |
| if (!allCubes.containsKey(tableName)) { |
| Table tbl = getTableWithType(tableName, CubeTableType.CUBE, throwException); |
| cube = tbl == null ? null : getCube(tbl); |
| if (enableCaching && cube != null) { |
| allCubes.put(tableName, cube); |
| } |
| } else { |
| cube = allCubes.get(tableName); |
| } |
| } |
| } |
| return cube; |
| } |
| |
| /** |
| * Get {@link Cube} object corresponding to the name |
| * |
| * @param tableName The cube name |
| * @return Returns Dimension if table name passed is a Dimension |
| * @throws LensException if the table name passed is not a Dimension |
| */ |
| public Dimension getDimension(String tableName) throws LensException { |
| return getDimension(tableName, true); |
| } |
| |
| private Dimension getDimension(String tableName, boolean throwException) throws LensException { |
| if (tableName == null) { |
| return null; |
| } |
| tableName = tableName.trim().toLowerCase(); |
| Dimension dim = allDims.get(tableName); |
| if (dim == null) { |
| synchronized (allDims) { |
| if (!allDims.containsKey(tableName)) { |
| Table tbl = getTableWithType(tableName, CubeTableType.DIMENSION, throwException); |
| dim = tbl == null ? null : getDimension(tbl); |
| if (enableCaching && dim != null) { |
| allDims.put(tableName, dim); |
| } |
| } else { |
| dim = allDims.get(tableName); |
| } |
| } |
| } |
| return dim; |
| } |
| |
| /** |
| * Get {@link Cube} object corresponding to the name |
| * |
| * @param tableName The cube name |
| * @return Returns cube is table name passed is a cube |
| * @throws LensException if there is no cube by the name |
| */ |
| public FactTable getFactTable(String tableName) throws LensException { |
| return getFactTable(tableName, true); |
| } |
| |
| private FactTable getFactTable(String tableName, boolean throwException) throws LensException { |
| tableName = tableName.trim().toLowerCase(); |
| FactTable fact = allFactTables.get(tableName); |
| if (fact == null) { |
| synchronized (allFactTables) { |
| if (!allFactTables.containsKey(tableName)) { |
| Table tbl = getTableWithType(tableName, CubeTableType.FACT, throwException); |
| if (tbl != null) { |
| String sourceFactName = tbl.getParameters().get(getSourceFactNameKey(tbl.getTableName())); |
| if (sourceFactName != null) { |
| fact = new CubeVirtualFactTable(tbl, getCubeFactTable(sourceFactName)); |
| if (factToVirtualFactMapping.get(sourceFactName) != null) { |
| List<String> prevList = factToVirtualFactMapping.get(sourceFactName); |
| prevList.add(tableName); |
| } else { |
| List<String> newList = new ArrayList<>(); |
| newList.add(tableName); |
| factToVirtualFactMapping.put(sourceFactName, newList); |
| } |
| } else { |
| fact = new CubeFactTable(tbl); |
| } |
| } |
| if (enableCaching && fact != null) { |
| allFactTables.put(tableName, fact); |
| } |
| } else { |
| fact = allFactTables.get(tableName); |
| } |
| } |
| } |
| return fact; |
| } |
| |
| private FactTable getFactTable(Table tbl) throws LensException { |
| String sourceFact = tbl.getParameters().get(getSourceFactNameKey(tbl.getTableName())); |
| if (sourceFact != null) { |
| return new CubeVirtualFactTable(tbl, getCubeFactTable(sourceFact)); |
| } else { |
| return new CubeFactTable(tbl); |
| } |
| } |
| |
| public Segmentation getSegmentation(String segName) throws LensException { |
| return getSegmentation(segName, true); |
| } |
| |
| public Segmentation getSegmentation(String segName, boolean throwException) throws LensException { |
| segName = segName.trim().toLowerCase(); |
| Segmentation seg = allSegmentations.get(segName); |
| if (seg == null) { |
| synchronized (allSegmentations) { |
| if (!allSegmentations.containsKey(segName)) { |
| Table tbl = getTableWithType(segName, CubeTableType.SEGMENTATION, throwException); |
| seg = tbl == null ? null : new Segmentation(tbl); |
| if (enableCaching && seg != null) { |
| allSegmentations.put(segName, seg); |
| } |
| } else { |
| seg = allSegmentations.get(segName); |
| } |
| } |
| } |
| return seg; |
| } |
| |
| |
| private CubeInterface getCube(Table tbl) throws LensException { |
| String parentCube = tbl.getParameters().get(getParentCubeNameKey(tbl.getTableName())); |
| if (parentCube != null) { |
| return new DerivedCube(tbl, (Cube) getCube(parentCube)); |
| } else { |
| return new Cube(tbl); |
| } |
| } |
| |
| private Dimension getDimension(Table tbl) { |
| return new Dimension(tbl); |
| } |
| |
| /** |
| * Get all dimension tables in metastore |
| * |
| * @return List of dimension tables |
| * @throws LensException |
| */ |
| public Collection<CubeDimensionTable> getAllDimensionTables() throws LensException { |
| if (!allDimTablesPopulated) { |
| List<CubeDimensionTable> dimTables = new ArrayList<>(); |
| try { |
| for (String table : getAllHiveTableNames()) { |
| CubeDimensionTable dim = getDimensionTable(table, false); |
| if (dim != null) { |
| dimTables.add(dim); |
| } |
| } |
| } catch (HiveException e) { |
| throw new LensException("Could not get all dimension tables", e); |
| } |
| allDimTablesPopulated = enableCaching; |
| return dimTables; |
| } else { |
| return allDimTables.values(); |
| } |
| } |
| |
| /** |
| * Get all storages in metastore |
| * |
| * @return List of Storage objects |
| * @throws LensException |
| */ |
| public Collection<Storage> getAllStorages() throws LensException { |
| if (!allStoragesPopulated) { |
| List<Storage> storages = new ArrayList<>(); |
| try { |
| for (String table : getAllHiveTableNames()) { |
| Storage storage = getStorage(table, false); |
| if (storage != null) { |
| storages.add(storage); |
| } |
| } |
| } catch (HiveException e) { |
| throw new LensException("Could not get all storages", e); |
| } |
| allStoragesPopulated = enableCaching; |
| return storages; |
| } else { |
| return allStorages.values(); |
| } |
| } |
| |
| /** |
| * Get all cubes in metastore |
| * |
| * @return List of Cube objects |
| * @throws LensException |
| */ |
| public Collection<CubeInterface> getAllCubes() throws LensException { |
| if (!allCubesPopulated) { |
| List<CubeInterface> cubes = new ArrayList<>(); |
| try { |
| for (String table : getAllHiveTableNames()) { |
| CubeInterface cube = getCube(table, false); |
| if (cube != null) { |
| cubes.add(cube); |
| } |
| } |
| } catch (HiveException e) { |
| throw new LensException("Could not get all cubes", e); |
| } |
| allCubesPopulated = enableCaching; |
| return cubes; |
| } else { |
| return allCubes.values(); |
| } |
| } |
| |
| /** |
| * Get all cubes in metastore |
| * |
| * @return List of Cube objects |
| * @throws LensException |
| */ |
| public Collection<Dimension> getAllDimensions() throws LensException { |
| if (!allDimensionsPopulated) { |
| List<Dimension> dims = new ArrayList<>(); |
| try { |
| for (String table : getAllHiveTableNames()) { |
| Dimension dim = getDimension(table, false); |
| if (dim != null) { |
| dims.add(dim); |
| } |
| } |
| } catch (HiveException e) { |
| throw new LensException("Could not get all dimensions", e); |
| } |
| allDimensionsPopulated = enableCaching; |
| return dims; |
| } else { |
| return allDims.values(); |
| } |
| } |
| |
| /** |
| * Get all facts in metastore |
| * |
| * @return List of Cube Fact Table objects |
| * @throws LensException |
| */ |
| public Collection<FactTable> getAllFacts() throws LensException { |
| if (!allFactTablesPopulated) { |
| List<FactTable> facts = new ArrayList<>(); |
| try { |
| for (String table : getAllHiveTableNames()) { |
| FactTable fact = getFactTable(table, false); |
| if (fact != null) { |
| facts.add(fact); |
| } |
| } |
| } catch (HiveException e) { |
| throw new LensException("Could not get all fact tables", e); |
| } |
| allFactTablesPopulated = enableCaching; |
| return facts; |
| } else { |
| return allFactTables.values(); |
| } |
| } |
| |
| /** |
| * Get all facts in metastore (virtual facts optional) |
| * @param includeVirtualFacts set true for including virtual facts |
| * @return List of Cube Fact Table objects |
| * @throws LensException |
| */ |
| public Collection<FactTable> getAllFacts(boolean includeVirtualFacts) throws LensException { |
| if (!allFactTablesPopulated) { |
| List<FactTable> facts = new ArrayList<>(); |
| try { |
| for (String table : getAllHiveTableNames()) { |
| FactTable fact = getFactTable(table, false); |
| if (fact != null) { |
| if (fact.getProperties().get(getSourceFactNameKey(fact.getName())) != null) { //is virtual fact |
| if (includeVirtualFacts) { |
| facts.add(fact); |
| } |
| } else { |
| facts.add(fact); |
| } |
| } |
| } |
| } catch (HiveException e) { |
| throw new LensException("Could not get all fact tables", e); |
| } |
| allFactTablesPopulated = enableCaching; |
| return facts; |
| } else { |
| return allFactTables.values(); |
| } |
| } |
| |
| /** |
| * Get all segmentations in metastore |
| * |
| * @return List of segmentation objects |
| * @throws LensException |
| */ |
| public Collection<Segmentation> getAllSegmentations() throws LensException { |
| if (!allSegmentationPopulated) { |
| List<Segmentation> segs = new ArrayList<>(); |
| try { |
| for (String table : getAllHiveTableNames()) { |
| Segmentation seg = getSegmentation(table, false); |
| if (seg != null) { |
| segs.add(seg); |
| } |
| } |
| } catch (HiveException e) { |
| throw new LensException("Could not get all fact tables", e); |
| } |
| allFactTablesPopulated = enableCaching; |
| return segs; |
| } else { |
| return allSegmentations.values(); |
| } |
| } |
| |
| private Collection<String> getAllHiveTableNames() throws HiveException, LensException { |
| if (!allTablesPopulated) { |
| List<String> allTables = getClient().getAllTables(); |
| for (String tblName : allTables) { |
| // getTable call here would add the table to allHiveTables |
| getTable(tblName); |
| } |
| allTablesPopulated = enableCaching; |
| return allTables; |
| } else { |
| return allHiveTables.keySet(); |
| } |
| } |
| |
| /** |
| * Get all fact tables of the cube. |
| * |
| * @param cube Cube object |
| * @return List of fact tables |
| * @throws LensException |
| */ |
| public List<FactTable> getAllFacts(CubeInterface cube) throws LensException { |
| String cubeName = null; |
| if (cube != null) { |
| if (cube instanceof DerivedCube) { |
| cube = ((DerivedCube) cube).getParent(); |
| } |
| cubeName = cube.getName(); |
| } |
| List<FactTable> cubeFacts = new ArrayList<>(); |
| for (FactTable fact : getAllFacts()) { |
| if (cubeName == null || fact.getCubeName().equalsIgnoreCase(cubeName)) { |
| cubeFacts.add(fact); |
| } |
| } |
| return cubeFacts; |
| } |
| |
| /** |
| * Get all facts of cube (optional virtual facts) |
| * |
| * @param cube Cube object |
| * @param includeVirtualFacts set true for virtual facts |
| * @return List of fact tables with optional virtual facts |
| * @throws LensException |
| */ |
| public List<FactTable> getAllFacts(CubeInterface cube, boolean includeVirtualFacts) throws LensException { |
| String cubeName = null; |
| if (cube != null) { |
| if (cube instanceof DerivedCube) { |
| cube = ((DerivedCube) cube).getParent(); |
| } |
| cubeName = cube.getName(); |
| } |
| List<FactTable> cubeFacts = new ArrayList<>(); |
| for (FactTable fact : getAllFacts(includeVirtualFacts)) { |
| if (cubeName == null || fact.getCubeName().equalsIgnoreCase(cubeName)) { |
| cubeFacts.add(fact); |
| } |
| } |
| return cubeFacts; |
| } |
| |
| public List<Segmentation> getAllSegmentations(CubeInterface cube) throws LensException { |
| String cubeName = null; |
| if (cube != null) { |
| if (cube instanceof DerivedCube) { |
| cube = ((DerivedCube) cube).getParent(); |
| } |
| cubeName = cube.getName(); |
| } |
| List<Segmentation> cubeSegs = new ArrayList<>(); |
| for (Segmentation seg : getAllSegmentations()) { |
| if (cubeName == null || seg.getBaseCube().equalsIgnoreCase(cubeName)) { |
| cubeSegs.add(seg); |
| } |
| } |
| return cubeSegs; |
| } |
| |
| |
| /** |
| * Get all derived cubes of the cube, that have all fields queryable together |
| * |
| * @param cube Cube object |
| * @return List of DerivedCube objects |
| * @throws LensException |
| */ |
| public List<DerivedCube> getAllDerivedQueryableCubes(CubeInterface cube) throws LensException { |
| List<DerivedCube> dcubes = new ArrayList<>(); |
| for (CubeInterface cb : getAllCubes()) { |
| if (cb.isDerivedCube() && ((DerivedCube) cb).getParent().getName().equalsIgnoreCase(cube.getName()) |
| && cb.allFieldsQueriable()) { |
| dcubes.add((DerivedCube) cb); |
| } |
| } |
| return dcubes; |
| } |
| |
| /** |
| * Get all dimension tables of the dimension. |
| * |
| * @param dim Dimension object |
| * @return List of fact tables |
| * @throws LensException |
| */ |
| public List<CubeDimensionTable> getAllDimensionTables(Dimension dim) throws LensException { |
| List<CubeDimensionTable> dimTables = new ArrayList<>(); |
| for (CubeDimensionTable dimTbl : getAllDimensionTables()) { |
| if (dim == null || dimTbl.getDimName().equalsIgnoreCase(dim.getName().toLowerCase())) { |
| dimTables.add(dimTbl); |
| } |
| } |
| return dimTables; |
| } |
| |
| public boolean partColExists(FactTable factTable, String storage, String partCol) throws LensException { |
| for (String storageTable : getStorageTables(factTable, storage)) { |
| for (FieldSchema f : getTable(storageTable).getPartCols()) { |
| if (f.getName().equalsIgnoreCase(partCol)) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Returns storage table names for a storage. |
| * Note: If each update period in the storage has a different storage table, this method will return N Storage Tables |
| * where N is the number of update periods in the storage (LENS-1386) |
| * |
| * @param factTable |
| * @param storage |
| * @return |
| * @throws LensException |
| */ |
| public Set<String> getStorageTables(FactTable factTable, String storage) throws LensException { |
| Set<String> uniqueStorageTables = new HashSet<>(); |
| |
| for (UpdatePeriod updatePeriod : factTable.getUpdatePeriods().get(storage)) { |
| String factName = factTable.getSourceFactName(); |
| uniqueStorageTables.add(getStorageTableName(factName, storage, updatePeriod)); |
| } |
| return uniqueStorageTables; |
| } |
| |
| /** |
| * |
| * @param table table name |
| * @param hiveTable hive table |
| * @param cubeTable lens cube table |
| * @return true if columns changed in alter |
| * @throws LensException |
| */ |
| private boolean alterCubeTable(String table, Table hiveTable, AbstractCubeTable cubeTable) throws LensException { |
| hiveTable.getParameters().putAll(cubeTable.getProperties()); |
| boolean columnsChanged = !(hiveTable.getCols().equals(cubeTable.getColumns())); |
| if (columnsChanged) { |
| hiveTable.getTTable().getSd().setCols(cubeTable.getColumns()); |
| } |
| hiveTable.getTTable().getParameters().putAll(cubeTable.getProperties()); |
| try { |
| getClient().alterTable(table, hiveTable, null); |
| } catch (Exception e) { |
| throw new LensException(e); |
| } |
| return columnsChanged; |
| } |
| |
| public void pushHiveTable(Table hiveTable) throws HiveException, LensException { |
| alterHiveTable(hiveTable.getTableName(), hiveTable); |
| } |
| |
| public void alterHiveTable(String table, Table hiveTable) throws HiveException, LensException { |
| try { |
| getClient().alterTable(table, hiveTable, null); |
| } catch (InvalidOperationException e) { |
| throw new HiveException(e); |
| } |
| if (enableCaching) { |
| // refresh the table in cache |
| refreshTable(table); |
| } |
| } |
| |
| public void alterCube(XCube cube) throws HiveException, LensException { |
| Cube parent = cube instanceof XDerivedCube ? (Cube) getCube( |
| ((XDerivedCube) cube).getParent()) : null; |
| alterCube(cube.getName(), JAXBUtils.hiveCubeFromXCube(cube, parent)); |
| } |
| |
| /** |
| * Alter cube specified by the name to new definition |
| * |
| * @param cubeName The cube name to be altered |
| * @param cube The new cube definition {@link Cube} or {@link DerivedCube} |
| * @throws HiveException |
| */ |
| public void alterCube(String cubeName, CubeInterface cube) |
| throws HiveException, LensException { |
| checkIfAuthorized(); |
| Table cubeTbl = getTableWithTypeFailFast(cubeName, CubeTableType.CUBE); |
| alterCubeTable(cubeName, cubeTbl, (AbstractCubeTable) cube); |
| if (enableCaching) { |
| allCubes.put(cubeName.trim().toLowerCase(), getCube(refreshTable(cubeName))); |
| } |
| } |
| |
| /** |
| * Alter dimension specified by the dimension name to new definition |
| * |
| * @param newDim The new dimension definition |
| * @throws HiveException |
| */ |
| public void alterDimension(XDimension newDim) throws HiveException, LensException { |
| alterDimension(newDim.getName(), JAXBUtils.dimensionFromXDimension(newDim)); |
| } |
| |
| public void alterDimension(String dimName, Dimension newDim) |
| throws HiveException, LensException { |
| checkIfAuthorized(); |
| Table tbl = getTableWithTypeFailFast(dimName, CubeTableType.DIMENSION); |
| alterCubeTable(dimName, tbl, newDim); |
| if (enableCaching) { |
| allDims.put(dimName.trim().toLowerCase(), getDimension(refreshTable(dimName))); |
| } |
| } |
| |
| /** |
| * Alter storage specified by the name to new definition |
| * |
| * @param storage The new storage definition |
| * @throws LensException |
| */ |
| public void alterStorage(XStorage storage) throws LensException, HiveException { |
| alterStorage(storage.getName(), JAXBUtils.storageFromXStorage(storage)); |
| } |
| |
| public void alterStorage(String storageName, Storage storage) |
| throws LensException, HiveException { |
| checkIfAuthorized(); |
| Table storageTbl = getTableWithTypeFailFast(storageName, CubeTableType.STORAGE); |
| alterCubeTable(storageName, storageTbl, storage); |
| if (enableCaching) { |
| allStorages.put(storageName.trim().toLowerCase(), getStorage(refreshTable(storageName))); |
| } |
| } |
| |
| /** |
| * Drop a storage |
| * |
| * @param storageName storage name |
| * @throws LensException |
| */ |
| public void dropStorage(String storageName) throws LensException { |
| getTableWithTypeFailFast(storageName, CubeTableType.STORAGE); |
| allStorages.remove(storageName.trim().toLowerCase()); |
| dropHiveTable(storageName); |
| } |
| |
| /** |
| * Drop a cube |
| * |
| * @param cubeName cube name |
| * @throws LensException |
| */ |
| public void dropCube(String cubeName) throws LensException { |
| checkIfAuthorized(); |
| getCube(getTableWithTypeFailFast(cubeName, CubeTableType.CUBE)); |
| allCubes.remove(cubeName.trim().toLowerCase()); |
| dropHiveTable(cubeName); |
| } |
| |
| /** |
| * Drop a dimension |
| * |
| * @param dimName dimension name to be dropped |
| * @throws LensException |
| */ |
| public void dropDimension(String dimName) throws LensException { |
| getTableWithTypeFailFast(dimName, CubeTableType.DIMENSION); |
| checkIfAuthorized(); |
| allDims.remove(dimName.trim().toLowerCase()); |
| dropHiveTable(dimName); |
| } |
| |
| /** |
| * Drop a fact with cascade flag |
| * |
| * @param factName fact name |
| * @param cascade If true, will drop all the storages of the fact |
| * @throws LensException |
| */ |
| public void dropFact(String factName, boolean cascade) throws LensException { |
| getTableWithTypeFailFast(factName, CubeTableType.FACT); |
| FactTable fact = getFactTable(factName); |
| checkIfAuthorized(); |
| if (cascade) { |
| for (String storage : fact.getStorages()) { |
| dropStorageFromFact(factName, storage, false); |
| } |
| } |
| dropHiveTable(factName); |
| allFactTables.remove(factName.trim().toLowerCase()); |
| if (fact.isVirtualFact()) { |
| String sourceFactTable = fact.getProperties().get(getSourceFactNameKey(fact.getName())); |
| if (factToVirtualFactMapping.get(sourceFactTable) != null |
| && factToVirtualFactMapping.get(sourceFactTable).contains(fact.getName())) { |
| factToVirtualFactMapping.get(sourceFactTable).remove(fact.getName()); |
| } |
| } else { |
| dropAllVirtualFactTables(factName); |
| } |
| } |
| |
| private void dropAllVirtualFactTables(String cubeFactTableName) throws LensException { |
| if (enableCaching) { |
| cubeFactTableName = cubeFactTableName.trim().toLowerCase(); |
| if (factToVirtualFactMapping.get(cubeFactTableName) != null) { |
| List<String> virtualFactTableNames = factToVirtualFactMapping.get(cubeFactTableName); |
| factToVirtualFactMapping.remove(cubeFactTableName); |
| for (String vf : virtualFactTableNames) { |
| dropVirtualFact(vf.trim().toLowerCase()); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Drop a virtual fact |
| * |
| * @param virtualFactName virtual fact name |
| * @throws LensException |
| */ |
| public void dropVirtualFact(String virtualFactName) throws LensException { |
| virtualFactName = virtualFactName.trim().toLowerCase(); |
| Table virtualTbl = getTableWithTypeFailFast(virtualFactName, CubeTableType.FACT); |
| String sourceFactTable = virtualTbl.getParameters().get(getSourceFactNameKey(virtualTbl.getTableName())); |
| if (factToVirtualFactMapping.get(sourceFactTable) != null |
| && factToVirtualFactMapping.get(sourceFactTable).contains(virtualFactName)) { |
| factToVirtualFactMapping.get(sourceFactTable).remove(virtualFactName); |
| } |
| dropHiveTable(virtualFactName); |
| allFactTables.remove(virtualFactName.trim().toLowerCase()); |
| |
| } |
| |
| public void dropSegmentation(String segName) throws LensException { |
| getTableWithTypeFailFast(segName, CubeTableType.SEGMENTATION); |
| checkIfAuthorized(); |
| dropHiveTable(segName); |
| allSegmentations.remove(segName.trim().toLowerCase()); |
| } |
| |
| /** |
| * Drop a storage from fact |
| * |
| * @param factName fact name |
| * @param storage storage name |
| * @throws LensException |
| */ |
| public void dropStorageFromFact(String factName, String storage) throws LensException { |
| CubeFactTable cft = getCubeFactTable(factName); |
| checkIfAuthorized(); |
| dropHiveTablesForStorage(factName, storage); |
| cft.dropStorage(storage); |
| alterCubeTable(factName, getTableWithTypeFailFast(factName, CubeTableType.FACT), cft); |
| updateFactCache(factName); |
| } |
| |
| private void dropHiveTablesForStorage(String factName, String storage) throws LensException { |
| CubeFactTable cft = getCubeFactTable(factName); |
| Set<String> droppedTables = new HashSet<>(); |
| for (Map.Entry updatePeriodEntry : cft.getStoragePrefixUpdatePeriodMap().get(storage).entrySet()) { |
| UpdatePeriod updatePeriod = (UpdatePeriod) updatePeriodEntry.getKey(); |
| String storageTableName = getStorageTableName(factName, storage, updatePeriod); |
| if (!droppedTables.contains(storageTableName)) { |
| dropHiveTable(storageTableName); |
| } |
| droppedTables.add(storageTableName); |
| } |
| } |
| |
| // updateFact will be false when fact is fully dropped |
| private void dropStorageFromFact(String factName, String storage, boolean updateFact) |
| throws LensException { |
| dropHiveTablesForStorage(factName, storage); |
| if (updateFact) { |
| CubeFactTable cft = getCubeFactTable(factName); |
| cft.dropStorage(storage); |
| alterCubeTable(factName, getTableWithTypeFailFast(factName, CubeTableType.FACT), cft); |
| updateFactCache(factName); |
| } |
| } |
| |
| |
| /** |
| * Drop a storage from dimension |
| * |
| * @param dimTblName dim table name |
| * @param storage storage |
| * @throws HiveException |
| */ |
| public void dropStorageFromDim(String dimTblName, String storage) |
| throws HiveException, LensException { |
| dropStorageFromDim(dimTblName, storage, true); |
| } |
| |
| // updateDimTbl will be false when dropping dimTbl |
| private void dropStorageFromDim(String dimTblName, String storage, boolean updateDimTbl) |
| throws LensException { |
| checkIfAuthorized(); |
| CubeDimensionTable cdt = getDimensionTable(dimTblName); |
| String storageTableName = getFactOrDimtableStorageTableName(dimTblName, storage); |
| dropHiveTable(storageTableName); |
| latestLookupCache.remove(storageTableName.trim().toLowerCase()); |
| if (updateDimTbl) { |
| cdt.dropStorage(storage); |
| alterCubeTable(dimTblName, getTableWithTypeFailFast(dimTblName, CubeTableType.DIM_TABLE), cdt); |
| updateDimCache(dimTblName); |
| } |
| } |
| |
| /** |
| * Drop the dimension table |
| * |
| * @param dimTblName dim table name |
| * @param cascade If true, will drop all the dimension storages |
| * @throws HiveException |
| */ |
| public void dropDimensionTable(String dimTblName, boolean cascade) |
| throws LensException { |
| checkIfAuthorized(); |
| getTableWithTypeFailFast(dimTblName, CubeTableType.DIM_TABLE); |
| CubeDimensionTable dim = getDimensionTable(dimTblName); |
| if (cascade) { |
| for (String storage : dim.getStorages()) { |
| dropStorageFromDim(dimTblName, storage, false); |
| } |
| } |
| dropHiveTable(dimTblName); |
| allDimTables.remove(dimTblName.trim().toLowerCase()); |
| } |
| |
| public void alterCubeFactTable(XFact fact) throws LensException, HiveException { |
| if (fact instanceof XVirtualFactTable) { |
| XVirtualFactTable xvf = (XVirtualFactTable) fact; |
| alterCubeFactTable(xvf.getName(), JAXBUtils.cubeVirtualFactFromFactTable(xvf, |
| getFactTable(xvf.getSourceFactName())), null, new HashMap<>()); |
| } else { |
| XFactTable xf = (XFactTable) fact; |
| alterCubeFactTable(fact.getName(), JAXBUtils.cubeFactFromFactTable(xf), |
| JAXBUtils.tableDescPrefixMapFromXStorageTables(xf.getStorageTables()), |
| JAXBUtils.columnStartAndEndTimeFromXColumns(xf.getColumns())); |
| } |
| } |
| |
| /** |
| * Alter a cubefact with new definition and alter underlying storage tables as well. |
| * |
| * @param factTableName fact table name |
| * @param cubeFactTable cube fact table |
| * @param storageTableDescs storage table desc objects |
| * |
| * @throws HiveException |
| */ |
| public void alterCubeFactTable(String factTableName, FactTable cubeFactTable, |
| Map<String, StorageTableDesc> storageTableDescs, |
| Map<String, String> props) |
| throws HiveException, LensException { |
| Table factTbl = getTableWithTypeFailFast(factTableName, CubeTableType.FACT); |
| checkIfAuthorized(); |
| if (!props.isEmpty()) { |
| cubeFactTable.getProperties().putAll(props); |
| } |
| alterCubeTable(factTableName, factTbl, (AbstractCubeTable) cubeFactTable); |
| if (storageTableDescs != null) { |
| // create/alter tables for each storage |
| for (Map.Entry<String, StorageTableDesc> entry : storageTableDescs.entrySet()) { |
| createOrAlterStorageHiveTable(getTable(factTableName), entry.getKey(), entry.getValue()); |
| } |
| } |
| updateFactCache(factTableName); |
| |
| updateAllVirtualFacts(getFactTable(factTableName)); |
| } |
| |
| public void alterSegmentation(XSegmentation cubeSeg) throws LensException, |
| HiveException { |
| alterSegmentation(cubeSeg.getName(), segmentationFromXSegmentation(cubeSeg)); |
| } |
| |
| /** |
| * Alter a virtual cube fact with new definition |
| * @param cubeVirtualFactTable cube virtual fact table |
| * @throws HiveException |
| */ |
| public void alterVirtualCubeFactTable(CubeVirtualFactTable cubeVirtualFactTable) |
| throws HiveException, LensException { |
| alterCubeFactTable(cubeVirtualFactTable.getName(), cubeVirtualFactTable, null, new HashMap<>()); |
| } |
| |
| public void alterSegmentation(String segName, Segmentation seg) |
| throws HiveException, LensException { |
| getTableWithTypeFailFast(segName, CubeTableType.SEGMENTATION); |
| checkIfAuthorized(); |
| if (!(getSegmentation(segName) == seg)) { |
| dropSegmentation(segName); |
| createSegmentation(seg); |
| updateSegmentationCache(segName); |
| } |
| } |
| |
| private void updateSegmentationCache(String segmentName) throws HiveException, LensException { |
| if (enableCaching) { |
| allSegmentations.put(segmentName.trim().toLowerCase(), new Segmentation(refreshTable(segmentName))); |
| } |
| } |
| |
| private void updateFactCache(String factTableName) throws LensException { |
| if (enableCaching) { |
| Table factTbl = getTableWithTypeFailFast(factTableName, CubeTableType.FACT); |
| FactTable refreshedTable; |
| if (factTbl.getParameters().get(getSourceFactNameKey(factTableName)) != null) { |
| String sourceFactName = factTbl.getParameters().get(getSourceFactNameKey(factTableName)); |
| refreshedTable = new CubeVirtualFactTable(refreshTable(factTableName), |
| getCubeFactTable(sourceFactName)); |
| } else { |
| refreshedTable = new CubeFactTable(refreshTable(factTableName)); |
| } |
| allFactTables.put(factTableName.trim().toLowerCase(), refreshedTable); |
| } |
| } |
| |
| public CubeFactTable getCubeFactTable(String factName) throws LensException { |
| FactTable factTable = getFactTable(factName); |
| if (factTable instanceof CubeFactTable) { |
| return (CubeFactTable) factTable; |
| } else { |
| throw new LensException(new LensException(LensCubeErrorCode.ENTITY_TYPE_NOT_AS_EXPECTED.getLensErrorInfo(), |
| factName, "Fact")); |
| } |
| } |
| |
| public CubeVirtualFactTable getCubeVirtualFactTable(String factName) throws LensException { |
| FactTable factTable = getFactTable(factName); |
| if (factTable instanceof CubeVirtualFactTable) { |
| return (CubeVirtualFactTable) factTable; |
| } else { |
| throw new LensException(new LensException(LensCubeErrorCode.ENTITY_TYPE_NOT_AS_EXPECTED.getLensErrorInfo(), |
| factName, "VirtualFact")); |
| } |
| } |
| |
| private void updateAllVirtualFacts(FactTable cubeFactTable) throws LensException { |
| if (enableCaching) { |
| String cubeFactTableName = cubeFactTable.getName().trim().toLowerCase(); |
| if (factToVirtualFactMapping.get(cubeFactTableName) != null) { |
| synchronized (allFactTables) { |
| List<String> virtualFactTableNames = factToVirtualFactMapping.get(cubeFactTableName); |
| for (String vf : virtualFactTableNames) { |
| CubeVirtualFactTable cvf = getCubeVirtualFactTable(vf); |
| cvf.setSourceCubeFactTable(cubeFactTable); |
| allFactTables.put(vf.trim().toLowerCase(), cvf); |
| } |
| } |
| } |
| } |
| } |
| |
| private void updateDimCache(String dimTblName) throws LensException { |
| if (enableCaching) { |
| allDimTables.put(dimTblName.trim().toLowerCase(), getDimensionTable(refreshTable(dimTblName))); |
| } |
| } |
| |
| public void alterCubeDimensionTable(XDimensionTable dimensionTable) |
| throws LensException, HiveException { |
| alterCubeDimensionTable(dimensionTable.getTableName(), |
| JAXBUtils.cubeDimTableFromDimTable(dimensionTable), |
| JAXBUtils.tableDescPrefixMapFromXStorageTables(dimensionTable.getStorageTables())); |
| } |
| |
| /** |
| * Alter dimension table with new dimension definition and underlying storage tables as well |
| * |
| * @param dimTableName dim table name |
| * @param cubeDimensionTable cube dimention table |
| * @throws HiveException |
| */ |
| public void alterCubeDimensionTable(String dimTableName, CubeDimensionTable cubeDimensionTable, |
| Map<String, StorageTableDesc> storageTableDescs) |
| throws HiveException, LensException { |
| checkIfAuthorized(); |
| Table dimTbl = getTableWithTypeFailFast(dimTableName, CubeTableType.DIM_TABLE); |
| alterCubeTable(dimTableName, dimTbl, cubeDimensionTable); |
| if (storageTableDescs != null) { |
| // create/alter tables for each storage |
| for (Map.Entry<String, StorageTableDesc> entry : storageTableDescs.entrySet()) { |
| createOrAlterStorageHiveTable(getTable(dimTableName), entry.getKey(), entry.getValue()); |
| } |
| } |
| updateDimCache(dimTableName); |
| } |
| |
| private List<Date> getStorageTimes(String storageTableName, String timeKey) throws LensException { |
| Date now = new Date(); |
| List<Date> storageTimes = new ArrayList<>(); |
| String property; |
| property = getTable(storageTableName).getProperty(timeKey); |
| if (StringUtils.isNotBlank(property)) { |
| for (String timeStr : property.split("\\s*,\\s*")) { |
| storageTimes.add(resolveDate(timeStr, now)); |
| } |
| } |
| return storageTimes; |
| } |
| |
| /* |
| * Storage table is not a candidate for range (t0, tn) : |
| * if start_time is after tn; or end date is before t0. |
| */ |
| public boolean isStorageTableCandidateForRange(String storageTableName, Date fromDate, Date toDate) |
| throws LensException { |
| List<Date> storageEndDates = getStorageTimes(storageTableName, MetastoreUtil.getStoragetableEndTimesKey()); |
| for (Date endDate : storageEndDates) { |
| // endDate is exclusive |
| if (endDate.before(fromDate) || endDate.equals(fromDate)) { |
| log.debug("from date {} is after validity end time: {}, hence discarding {}", |
| fromDate, endDate, storageTableName); |
| return false; |
| } |
| } |
| |
| List<Date> storageStartDates = getStorageTimes(storageTableName, MetastoreUtil.getStoragetableStartTimesKey()); |
| for (Date startDate : storageStartDates) { |
| // toDate is exclusive on the range |
| if (startDate.after(toDate) || startDate.equals(toDate)) { |
| log.debug("to date {} is before validity start time: {}, hence discarding {}", |
| toDate, startDate, storageTableName); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| // Check if partition is valid wrt start and end dates |
| public boolean isStorageTablePartitionACandidate(String storageTableName, Date partDate) |
| throws LensException { |
| List<Date> storageStartDates = getStorageTimes(storageTableName, MetastoreUtil.getStoragetableStartTimesKey()); |
| for (Date startDate : storageStartDates) { |
| if (partDate.before(startDate)) { |
| log.info("part date {} is before validity start time: {}, hence discarding {}", |
| partDate, startDate, storageTableName); |
| return false; |
| } |
| } |
| |
| List<Date> storageEndDates = getStorageTimes(storageTableName, MetastoreUtil.getStoragetableEndTimesKey()); |
| for (Date endDate : storageEndDates) { |
| // end date should be exclusive |
| if (partDate.after(endDate) || partDate.equals(endDate)) { |
| log.info("part date {} is after validity end time: {}, hence discarding {}", |
| partDate, endDate, storageTableName); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| public boolean isStorageTableCandidateForRange(String storageTableName, String fromDate, String toDate) throws |
| HiveException, LensException { |
| Date now = new Date(); |
| return isStorageTableCandidateForRange(storageTableName, resolveDate(fromDate, now), resolveDate(toDate, now)); |
| } |
| |
| private String getStorageTablePrefixFromStorage(String factOrDimTableName, String storage, UpdatePeriod updatePeriod) |
| throws LensException { |
| if (updatePeriod == null) { |
| return storage; |
| } |
| if (isVirtualFactTable(factOrDimTableName)) { |
| CubeFactTable sourceFact = (CubeFactTable) getCubeVirtualFactTable(factOrDimTableName).getSourceCubeFactTable(); |
| return sourceFact.getTablePrefix(storage, updatePeriod); |
| } else if (isFactTable(factOrDimTableName)) { |
| return getCubeFactTable(factOrDimTableName).getTablePrefix(storage, updatePeriod); |
| } else { |
| return storage; |
| } |
| } |
| |
| public String getStorageTableName(String factOrDimTableName, String storage, UpdatePeriod updatePeriod) |
| throws LensException { |
| return MetastoreUtil.getFactOrDimtableStorageTableName(factOrDimTableName, |
| getStorageTablePrefixFromStorage(factOrDimTableName, storage, updatePeriod)); |
| } |
| } |