package org.hivedb.util; import org.hivedb.Hive; import org.hivedb.HiveKeyNotFoundException; import org.hivedb.HiveLockableException; import org.hivedb.annotations.IndexType; import org.hivedb.configuration.EntityConfig; import org.hivedb.configuration.EntityHiveConfig; import org.hivedb.configuration.EntityIndexConfig; import org.hivedb.meta.Resource; import org.hivedb.meta.SecondaryIndex; import org.hivedb.util.database.JdbcTypeMapper; import org.hivedb.util.functional.*; import java.util.ArrayList; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; /** * HiveUpdater updates a hive to the configuration of a HiveScenarioConfig. When the HiveScenarioConfig's * configuration of its primary index, resources, and secondary indexes differ from that of its Hive * instance, it will update the referenced hive to match its configuration. This includes name changes, * and the addition or removal of resources and secondary indexes. * * @author Andy Likuski */ public class HiveSyncer { private Hive hive; public HiveSyncer(Hive hive) { this.hive = hive; } /** * Sync a Hive to the configuration of the given HiveScenarioConfig. This is an additive process only: * If the Hive contains Partition Dimensions, Resources, Secondary Indexes, or Data Nodes not * specified by the HiveScenarioConfig they will be left alone, not deleted. * @param entityHiveConfig * @return * @throws HiveLockableException */ public HiveDiff syncHive(EntityHiveConfig entityHiveConfig) throws HiveLockableException { HiveDiff hiveDiff = diffHive(entityHiveConfig); for(Resource resource: hiveDiff.getMissingResources()) hive.addResource(resource); for(Entry<Resource, Collection<SecondaryIndex>> entry : hiveDiff.getMissingSecondaryIndexes().entrySet()) for(SecondaryIndex index: entry.getValue()) hive.addSecondaryIndex(entry.getKey(), index); return hiveDiff; } /** * Returns a HiveDiff the difference between the HiveScenarioConfig instance and the current hive * @param hiveConfig Config file file for the given hive * @return a HiveDiff class that describes what partition dimensions are missing, what resources and nodes are missing * from existing partion dimensions, and what secondary indexes are missing from existing resources */ public HiveDiff diffHive(final EntityHiveConfig updater) { Collection<Resource> missingResources = Lists.newArrayList(); Map<Resource, Collection<SecondaryIndex>> indexMap = Maps.newHashMap(); for(EntityConfig config : updater.getEntityConfigs()) { try { Resource resource = hive.getPartitionDimension().getResource(config.getResourceName()); for(EntityIndexConfig indexConfig : getHiveIndexes(config)) { try { resource.getSecondaryIndex(indexConfig.getIndexName()); } catch(HiveKeyNotFoundException ex) { if(!indexMap.containsKey(resource)) indexMap.put(resource, new ArrayList<SecondaryIndex>()); indexMap.get(resource).add(configToIndex().f(indexConfig)); } } } catch(HiveKeyNotFoundException e) { Resource resource = new Resource( config.getResourceName(), JdbcTypeMapper.primitiveTypeToJdbcType(config.getIdClass()), config.isPartitioningResource()); missingResources.add(resource); indexMap.put(resource, Transform.map(configToIndex(), config.getEntityIndexConfigs())); } } return new HiveDiff(missingResources, indexMap); } private Unary<EntityIndexConfig, SecondaryIndex> configToIndex() { return new Unary<EntityIndexConfig, SecondaryIndex>(){ public SecondaryIndex f(EntityIndexConfig item) { return new SecondaryIndex(item.getIndexName(), JdbcTypeMapper.primitiveTypeToJdbcType(item.getIndexClass())); }}; } private static Collection<? extends EntityIndexConfig> getHiveIndexes(final EntityConfig entityConfig) { return Filter.grep(new Predicate<EntityIndexConfig>() { public boolean f(EntityIndexConfig entityIndexConfig) { return entityIndexConfig.getIndexType().equals(IndexType.Hive); }}, entityConfig.getEntityIndexConfigs()); } }