List of usage examples for com.google.common.collect BiMap containsKey
boolean containsKey(Object key);
From source file:org.apache.druid.indexing.common.task.CompactionTask.java
private static DimensionsSpec createDimensionsSpec(List<Pair<QueryableIndex, DataSegment>> queryableIndices) { final BiMap<String, Integer> uniqueDims = HashBiMap.create(); final Map<String, DimensionSchema> dimensionSchemaMap = new HashMap<>(); // Here, we try to retain the order of dimensions as they were specified since the order of dimensions may be // optimized for performance. // Dimensions are extracted from the recent segments to olders because recent segments are likely to be queried more // frequently, and thus the performance should be optimized for recent ones rather than old ones. // timelineSegments are sorted in order of interval, but we do a sanity check here. final Comparator<Interval> intervalComparator = Comparators.intervalsByStartThenEnd(); for (int i = 0; i < queryableIndices.size() - 1; i++) { final Interval shouldBeSmaller = queryableIndices.get(i).lhs.getDataInterval(); final Interval shouldBeLarger = queryableIndices.get(i + 1).lhs.getDataInterval(); Preconditions.checkState(intervalComparator.compare(shouldBeSmaller, shouldBeLarger) <= 0, "QueryableIndexes are not sorted! Interval[%s] of segment[%s] is laster than interval[%s] of segment[%s]", shouldBeSmaller, queryableIndices.get(i).rhs.getIdentifier(), shouldBeLarger, queryableIndices.get(i + 1).rhs.getIdentifier()); }/*from w w w . java 2 s. co m*/ int index = 0; for (Pair<QueryableIndex, DataSegment> pair : Lists.reverse(queryableIndices)) { final QueryableIndex queryableIndex = pair.lhs; final Map<String, DimensionHandler> dimensionHandlerMap = queryableIndex.getDimensionHandlers(); for (String dimension : queryableIndex.getAvailableDimensions()) { final ColumnHolder columnHolder = Preconditions.checkNotNull( queryableIndex.getColumnHolder(dimension), "Cannot find column for dimension[%s]", dimension); if (!uniqueDims.containsKey(dimension)) { final DimensionHandler dimensionHandler = Preconditions.checkNotNull( dimensionHandlerMap.get(dimension), "Cannot find dimensionHandler for dimension[%s]", dimension); uniqueDims.put(dimension, index++); dimensionSchemaMap.put(dimension, createDimensionSchema(columnHolder.getCapabilities().getType(), dimension, dimensionHandler.getMultivalueHandling(), columnHolder.getCapabilities().hasBitmapIndexes())); } } } final BiMap<Integer, String> orderedDims = uniqueDims.inverse(); final List<DimensionSchema> dimensionSchemas = IntStream.range(0, orderedDims.size()).mapToObj(i -> { final String dimName = orderedDims.get(i); return Preconditions.checkNotNull(dimensionSchemaMap.get(dimName), "Cannot find dimension[%s] from dimensionSchemaMap", dimName); }).collect(Collectors.toList()); return new DimensionsSpec(dimensionSchemas, null, null); }
From source file:cpw.mods.fml.common.Loader.java
/** * Sort the mods into a sorted list, using dependency information from the * containers. The sorting is performed using a {@link TopologicalSort} * based on the pre- and post- dependency information provided by the mods. *///from www . j a v a 2 s. c o m private void sortModList() { FMLLog.finer("Verifying mod requirements are satisfied"); try { BiMap<String, ArtifactVersion> modVersions = HashBiMap.create(); for (ModContainer mod : getActiveModList()) { modVersions.put(mod.getModId(), mod.getProcessedVersion()); } ArrayListMultimap<String, String> reqList = ArrayListMultimap.create(); for (ModContainer mod : getActiveModList()) { if (!mod.acceptableMinecraftVersionRange().containsVersion(minecraft.getProcessedVersion())) { FMLLog.severe( "The mod %s does not wish to run in Minecraft version %s. You will have to remove it to play.", mod.getModId(), getMCVersionString()); throw new WrongMinecraftVersionException(mod); } Map<String, ArtifactVersion> names = Maps.uniqueIndex(mod.getRequirements(), new ArtifactVersionNameFunction()); Set<ArtifactVersion> versionMissingMods = Sets.newHashSet(); Set<String> missingMods = Sets.difference(names.keySet(), modVersions.keySet()); if (!missingMods.isEmpty()) { FMLLog.severe("The mod %s (%s) requires mods %s to be available", mod.getModId(), mod.getName(), missingMods); for (String modid : missingMods) { versionMissingMods.add(names.get(modid)); } throw new MissingModsException(versionMissingMods); } reqList.putAll(mod.getModId(), names.keySet()); ImmutableList<ArtifactVersion> allDeps = ImmutableList.<ArtifactVersion>builder() .addAll(mod.getDependants()).addAll(mod.getDependencies()).build(); for (ArtifactVersion v : allDeps) { if (modVersions.containsKey(v.getLabel())) { if (!v.containsVersion(modVersions.get(v.getLabel()))) { versionMissingMods.add(v); } } } if (!versionMissingMods.isEmpty()) { FMLLog.severe("The mod %s (%s) requires mod versions %s to be available", mod.getModId(), mod.getName(), versionMissingMods); throw new MissingModsException(versionMissingMods); } } FMLLog.finer("All mod requirements are satisfied"); reverseDependencies = Multimaps.invertFrom(reqList, ArrayListMultimap.<String, String>create()); ModSorter sorter = new ModSorter(getActiveModList(), namedMods); try { FMLLog.finer("Sorting mods into an ordered list"); List<ModContainer> sortedMods = sorter.sort(); // Reset active list to the sorted list modController.getActiveModList().clear(); modController.getActiveModList().addAll(sortedMods); // And inject the sorted list into the overall list mods.removeAll(sortedMods); sortedMods.addAll(mods); mods = sortedMods; FMLLog.finer("Mod sorting completed successfully"); } catch (ModSortingException sortException) { FMLLog.severe( "A dependency cycle was detected in the input mod set so an ordering cannot be determined"); SortingExceptionData<ModContainer> exceptionData = sortException.getExceptionData(); FMLLog.severe("The first mod in the cycle is %s", exceptionData.getFirstBadNode()); FMLLog.severe("The mod cycle involves"); for (ModContainer mc : exceptionData.getVisitedNodes()) { FMLLog.severe("%s : before: %s, after: %s", mc.toString(), mc.getDependants(), mc.getDependencies()); } FMLLog.log(Level.ERROR, sortException, "The full error"); throw sortException; } } finally { FMLLog.fine("Mod sorting data"); int unprintedMods = mods.size(); for (ModContainer mod : getActiveModList()) { if (!mod.isImmutable()) { FMLLog.fine("\t%s(%s:%s): %s (%s)", mod.getModId(), mod.getName(), mod.getVersion(), mod.getSource().getName(), mod.getSortingRules()); unprintedMods--; } } if (unprintedMods == mods.size()) { FMLLog.fine("No user mods found to sort"); } } }
From source file:net.minecraftforge.fml.common.Loader.java
/** * Sort the mods into a sorted list, using dependency information from the * containers. The sorting is performed using a {@link TopologicalSort} * based on the pre- and post- dependency information provided by the mods. *//* w w w. ja v a2 s .com*/ private void sortModList() { FMLLog.finer("Verifying mod requirements are satisfied"); try { BiMap<String, ArtifactVersion> modVersions = HashBiMap.create(); for (ModContainer mod : Iterables.concat(getActiveModList(), ModAPIManager.INSTANCE.getAPIList())) { modVersions.put(mod.getModId(), mod.getProcessedVersion()); } ArrayListMultimap<String, String> reqList = ArrayListMultimap.create(); for (ModContainer mod : getActiveModList()) { if (!mod.acceptableMinecraftVersionRange().containsVersion(minecraft.getProcessedVersion())) { FMLLog.severe( "The mod %s does not wish to run in Minecraft version %s. You will have to remove it to play.", mod.getModId(), getMCVersionString()); throw new WrongMinecraftVersionException(mod); } Map<String, ArtifactVersion> names = Maps.uniqueIndex(mod.getRequirements(), new ArtifactVersionNameFunction()); Set<ArtifactVersion> versionMissingMods = Sets.newHashSet(); Set<String> missingMods = Sets.difference(names.keySet(), modVersions.keySet()); if (!missingMods.isEmpty()) { FMLLog.severe("The mod %s (%s) requires mods %s to be available", mod.getModId(), mod.getName(), missingMods); for (String modid : missingMods) { versionMissingMods.add(names.get(modid)); } throw new MissingModsException(versionMissingMods, mod.getModId(), mod.getName()); } reqList.putAll(mod.getModId(), names.keySet()); ImmutableList<ArtifactVersion> allDeps = ImmutableList.<ArtifactVersion>builder() .addAll(mod.getDependants()).addAll(mod.getDependencies()).build(); for (ArtifactVersion v : allDeps) { if (modVersions.containsKey(v.getLabel())) { if (!v.containsVersion(modVersions.get(v.getLabel()))) { versionMissingMods.add(v); } } } if (!versionMissingMods.isEmpty()) { FMLLog.severe("The mod %s (%s) requires mod versions %s to be available", mod.getModId(), mod.getName(), versionMissingMods); throw new MissingModsException(versionMissingMods, mod.getModId(), mod.getName()); } } FMLLog.finer("All mod requirements are satisfied"); reverseDependencies = Multimaps.invertFrom(reqList, ArrayListMultimap.<String, String>create()); ModSorter sorter = new ModSorter(getActiveModList(), namedMods); try { FMLLog.finer("Sorting mods into an ordered list"); List<ModContainer> sortedMods = sorter.sort(); // Reset active list to the sorted list modController.getActiveModList().clear(); modController.getActiveModList().addAll(sortedMods); // And inject the sorted list into the overall list mods.removeAll(sortedMods); sortedMods.addAll(mods); mods = sortedMods; FMLLog.finer("Mod sorting completed successfully"); } catch (ModSortingException sortException) { FMLLog.severe( "A dependency cycle was detected in the input mod set so an ordering cannot be determined"); SortingExceptionData<ModContainer> exceptionData = sortException.getExceptionData(); FMLLog.severe("The first mod in the cycle is %s", exceptionData.getFirstBadNode()); FMLLog.severe("The mod cycle involves"); for (ModContainer mc : exceptionData.getVisitedNodes()) { FMLLog.severe("%s : before: %s, after: %s", mc.toString(), mc.getDependants(), mc.getDependencies()); } FMLLog.log(Level.ERROR, sortException, "The full error"); throw sortException; } } finally { FMLLog.fine("Mod sorting data"); int unprintedMods = mods.size(); for (ModContainer mod : getActiveModList()) { if (!mod.isImmutable()) { FMLLog.fine("\t%s(%s:%s): %s (%s)", mod.getModId(), mod.getName(), mod.getVersion(), mod.getSource().getName(), mod.getSortingRules()); unprintedMods--; } } if (unprintedMods == mods.size()) { FMLLog.fine("No user mods found to sort"); } } }
From source file:com.moz.fiji.schema.layout.FijiTableLayout.java
/** * Constructs a FijiTableLayout from an Avro descriptor and an optional reference layout. * * @param desc Avro layout descriptor (relative to the reference layout). * @param reference Optional reference layout, or null. * @throws InvalidLayoutException if the descriptor is invalid or inconsistent wrt reference. */// w w w . j a va 2 s . c om private FijiTableLayout(TableLayoutDesc desc, FijiTableLayout reference) throws InvalidLayoutException { // Deep-copy the descriptor to prevent mutating a parameter: mDesc = TableLayoutDesc.newBuilder(Preconditions.checkNotNull(desc)).build(); // Ensure the array of locality groups is mutable: mDesc.setLocalityGroups(Lists.newArrayList(mDesc.getLocalityGroups())); // Check that the version specified in the layout matches the features used. // Any compatibility checks belong in this section. mLayoutVersion = computeLayoutVersion(mDesc.getVersion()); if (!Objects.equal(LAYOUT_PROTOCOL_NAME, mLayoutVersion.getProtocolName())) { final String exceptionMessage; if (Objects.equal(Versions.LAYOUT_FIJI_1_0_0_DEPRECATED.getProtocolName(), mLayoutVersion.getProtocolName())) { // Warn the user if they tried a version number like 'fiji-0.9' or 'fiji-1.1'. exceptionMessage = String.format( "Deprecated layout version protocol '%s' only valid for version '%s'," + " but received version '%s'. You should specify a layout version protocol" + " as '%s-x.y', not '%s-x.y'.", Versions.LAYOUT_FIJI_1_0_0_DEPRECATED.getProtocolName(), Versions.LAYOUT_FIJI_1_0_0_DEPRECATED, mLayoutVersion, LAYOUT_PROTOCOL_NAME, Versions.LAYOUT_FIJI_1_0_0_DEPRECATED.getProtocolName()); } else { exceptionMessage = String.format("Invalid version protocol: '%s'. Expected '%s'.", mLayoutVersion.getProtocolName(), LAYOUT_PROTOCOL_NAME); } throw new InvalidLayoutException(exceptionMessage); } if (Versions.MAX_LAYOUT_VERSION.compareTo(mLayoutVersion) < 0) { throw new InvalidLayoutException("The maximum layout version we support is " + Versions.MAX_LAYOUT_VERSION + "; this layout requires " + mLayoutVersion); } else if (Versions.MIN_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0) { throw new InvalidLayoutException("The minimum layout version we support is " + Versions.MIN_LAYOUT_VERSION + "; this layout requires " + mLayoutVersion); } // max_filesize and memstore_flushsize were introduced in version 1.2. if (Versions.BLOCK_SIZE_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0) { if (mDesc.getMaxFilesize() != null) { // Cannot use max_filesize if this is the case. throw new InvalidLayoutException("Support for specifying max_filesize begins with layout version " + Versions.BLOCK_SIZE_LAYOUT_VERSION.toString()); } if (mDesc.getMemstoreFlushsize() != null) { // Cannot use memstore_flushsize if this is the case. throw new InvalidLayoutException( "Support for specifying memstore_flushsize begins with layout version " + Versions.BLOCK_SIZE_LAYOUT_VERSION); } } else { if (mDesc.getMaxFilesize() != null && mDesc.getMaxFilesize() <= 0) { throw new InvalidLayoutException("max_filesize must be greater than 0"); } if (mDesc.getMemstoreFlushsize() != null && mDesc.getMemstoreFlushsize() <= 0) { throw new InvalidLayoutException("memstore_flushsize must be greater than 0"); } } // Ability to configure column name translation was introduced in version 1.5 if (Versions.CONFIGURE_COLUMN_NAME_TRANSLATION_VERSION.compareTo(mLayoutVersion) > 0) { if (mDesc.getColumnNameTranslator() != ColumnNameTranslator.SHORT) { throw new InvalidLayoutException( "Support for specifiying non-short column name translators begins with layout version " + Versions.CONFIGURE_COLUMN_NAME_TRANSLATION_VERSION); } } // Composite keys and RowKeyFormat2 was introduced in version 1.1. if (Versions.RKF2_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0 && mDesc.getKeysFormat() instanceof RowKeyFormat2) { // Cannot use RowKeyFormat2 if this is the case. throw new InvalidLayoutException( "Support for specifying keys_format as a RowKeyFormat2 begins with layout version " + Versions.RKF2_LAYOUT_VERSION); } if (!isValidName(getName())) { throw new InvalidLayoutException(String.format("Invalid table name: '%s'.", getName())); } if (reference != null) { if (!getName().equals(reference.getName())) { throw new InvalidLayoutException(String.format( "Invalid layout update: layout name '%s' does not match reference layout name '%s'.", getName(), reference.getName())); } if (!mDesc.getKeysFormat().equals(reference.getDesc().getKeysFormat())) { throw new InvalidLayoutException(String.format( "Invalid layout update from reference row keys format '%s' to row keys format '%s'.", reference.getDesc().getKeysFormat(), mDesc.getKeysFormat())); } } // Layout ID: if (mDesc.getLayoutId() == null) { try { final long refLayoutId = (reference == null) ? 0 : Long.parseLong(reference.getDesc().getLayoutId()); final long layoutId = refLayoutId + 1; mDesc.setLayoutId(Long.toString(layoutId)); } catch (NumberFormatException nfe) { throw new InvalidLayoutException( String.format("Reference layout for table '%s' has an invalid layout ID: '%s'", getName(), reference.getDesc().getLayoutId())); } } if (mDesc.getKeysFormat() instanceof RowKeyFormat) { isValidRowKeyFormat1((RowKeyFormat) mDesc.getKeysFormat()); } else if (mDesc.getKeysFormat() instanceof RowKeyFormat2) { // Check validity of row key format. isValidRowKeyFormat2((RowKeyFormat2) mDesc.getKeysFormat()); } // Build localities: /** * Reference map from locality group name to locality group ID. * Entries are removed as we process locality group descriptors in the new layout. * At the end of the process, this map must be empty. */ final BiMap<String, ColumnId> refLGIdMap = (reference == null) ? HashBiMap.<String, ColumnId>create() : HashBiMap.create(reference.mLocalityGroupIdNameMap.inverse()); /** Map of locality groups in the new layout. */ final List<LocalityGroupLayout> localityGroups = Lists.newArrayList(); final Map<String, LocalityGroupLayout> lgMap = Maps.newHashMap(); final BiMap<ColumnId, String> idMap = HashBiMap.create(); /** Locality group with no ID assigned yet. */ final List<LocalityGroupLayout> unassigned = Lists.newArrayList(); /** All the families in the table. */ final List<FamilyLayout> families = Lists.newArrayList(); /** Map from family name or alias to family layout. */ final Map<String, FamilyLayout> familyMap = Maps.newHashMap(); /** All primary column names (including map-type families). */ final Set<FijiColumnName> columnNames = Sets.newTreeSet(); final Map<FijiColumnName, ColumnLayout> columnMap = Maps.newHashMap(); final Iterator<LocalityGroupDesc> itLGDesc = mDesc.getLocalityGroups().iterator(); while (itLGDesc.hasNext()) { final LocalityGroupDesc lgDesc = itLGDesc.next(); final boolean isRename = (lgDesc.getRenamedFrom() != null); final String refLGName = isRename ? lgDesc.getRenamedFrom() : lgDesc.getName(); lgDesc.setRenamedFrom(null); if (isRename && (reference == null)) { throw new InvalidLayoutException(String .format("Invalid rename: no reference table layout for locality group '%s'.", refLGName)); } final LocalityGroupLayout refLGLayout = (reference != null) ? reference.mLocalityGroupMap.get(refLGName) : null; if (isRename && (refLGLayout == null)) { throw new InvalidLayoutException( String.format("Invalid rename: cannot find reference locality group '%s'.", refLGName)); } final ColumnId refLGId = refLGIdMap.remove(refLGName); if (lgDesc.getDelete()) { // This locality group is deleted: if (refLGId == null) { throw new InvalidLayoutException(String.format( "Attempting to delete locality group '%s' unknown in reference layout.", refLGName)); } itLGDesc.remove(); continue; } // BloomType, block_size were introduced in version 1.2. if (Versions.BLOCK_SIZE_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0) { if (lgDesc.getBlockSize() != null) { // Cannot use max_filesize if this is the case. throw new InvalidLayoutException("Support for specifying block_size begins with layout version " + Versions.BLOCK_SIZE_LAYOUT_VERSION); } if (lgDesc.getBloomType() != null) { // Cannot use bloom_type if this is the case. throw new InvalidLayoutException("Support for specifying bloom_type begins with layout version " + Versions.BLOCK_SIZE_LAYOUT_VERSION); } } else { if (lgDesc.getBlockSize() != null && lgDesc.getBlockSize() <= 0) { throw new InvalidLayoutException("block_size must be greater than 0"); } } final LocalityGroupLayout lgLayout = new LocalityGroupLayout(lgDesc, refLGLayout); localityGroups.add(lgLayout); for (String lgName : lgLayout.getNames()) { Preconditions.checkState(lgMap.put(lgName, lgLayout) == null, "Duplicate locality group name: " + lgName); } if (lgLayout.getId() != null) { final String previous = idMap.put(lgLayout.getId(), lgLayout.getName()); Preconditions.checkState(previous == null, String.format("Duplicate locality group ID '%s' associated to '%s' and '%s'.", lgLayout.getId(), lgLayout.getName(), previous)); } else { unassigned.add(lgLayout); } families.addAll(lgLayout.getFamilies()); for (FamilyLayout familyLayout : lgLayout.getFamilies()) { for (String familyName : familyLayout.getNames()) { if (null != familyMap.put(familyName, familyLayout)) { throw new InvalidLayoutException( String.format("Layout for table '%s' contains duplicate family name '%s'.", getName(), familyName)); } } if (familyLayout.isMapType()) { Preconditions.checkState(columnNames.add(FijiColumnName.create(familyLayout.getName(), null))); } for (ColumnLayout columnLayout : familyLayout.getColumns()) { for (String columnName : columnLayout.getNames()) { final FijiColumnName column = FijiColumnName.create(familyLayout.getName(), columnName); if (null != columnMap.put(column, columnLayout)) { throw new InvalidLayoutException(String.format( "Layout for table '%s' contains duplicate column '%s'.", getName(), column)); } } Preconditions.checkState( columnNames.add(FijiColumnName.create(familyLayout.getName(), columnLayout.getName()))); } } } if (!refLGIdMap.isEmpty()) { throw new InvalidLayoutException(String.format("Missing descriptor(s) for locality group(s): %s.", Joiner.on(",").join(refLGIdMap.keySet()))); } mLocalityGroups = ImmutableList.copyOf(localityGroups); mLocalityGroupMap = ImmutableMap.copyOf(lgMap); mFamilies = ImmutableList.copyOf(families); mFamilyMap = ImmutableMap.copyOf(familyMap); mColumnNames = ImmutableSet.copyOf(columnNames); // Assign IDs to locality groups: int nextColumnId = 1; for (LocalityGroupLayout localityGroup : unassigned) { Preconditions.checkState(localityGroup.getId() == null); while (true) { final ColumnId columnId = new ColumnId(nextColumnId); nextColumnId += 1; if (!idMap.containsKey(columnId)) { localityGroup.setId(columnId); idMap.put(columnId, localityGroup.getName()); break; } } } mLocalityGroupIdNameMap = ImmutableBiMap.copyOf(idMap); }
From source file:org.kiji.schema.layout.KijiTableLayout.java
/** * Constructs a KijiTableLayout from an Avro descriptor and an optional reference layout. * * @param desc Avro layout descriptor (relative to the reference layout). * @param reference Optional reference layout, or null. * @throws InvalidLayoutException if the descriptor is invalid or inconsistent wrt reference. *//*from w w w .j av a2s . c o m*/ private KijiTableLayout(TableLayoutDesc desc, KijiTableLayout reference) throws InvalidLayoutException { // Deep-copy the descriptor to prevent mutating a parameter: mDesc = TableLayoutDesc.newBuilder(Preconditions.checkNotNull(desc)).build(); // Ensure the array of locality groups is mutable: mDesc.setLocalityGroups(Lists.newArrayList(mDesc.getLocalityGroups())); // Check that the version specified in the layout matches the features used. // Any compatibility checks belong in this section. mLayoutVersion = computeLayoutVersion(mDesc.getVersion()); if (!Objects.equal(LAYOUT_PROTOCOL_NAME, mLayoutVersion.getProtocolName())) { final String exceptionMessage; if (Objects.equal(Versions.LAYOUT_KIJI_1_0_0_DEPRECATED.getProtocolName(), mLayoutVersion.getProtocolName())) { // Warn the user if they tried a version number like 'kiji-0.9' or 'kiji-1.1'. exceptionMessage = String.format( "Deprecated layout version protocol '%s' only valid for version '%s'," + " but received version '%s'. You should specify a layout version protocol" + " as '%s-x.y', not '%s-x.y'.", Versions.LAYOUT_KIJI_1_0_0_DEPRECATED.getProtocolName(), Versions.LAYOUT_KIJI_1_0_0_DEPRECATED, mLayoutVersion, LAYOUT_PROTOCOL_NAME, Versions.LAYOUT_KIJI_1_0_0_DEPRECATED.getProtocolName()); } else { exceptionMessage = String.format("Invalid version protocol: '%s'. Expected '%s'.", mLayoutVersion.getProtocolName(), LAYOUT_PROTOCOL_NAME); } throw new InvalidLayoutException(exceptionMessage); } if (Versions.MAX_LAYOUT_VERSION.compareTo(mLayoutVersion) < 0) { throw new InvalidLayoutException("The maximum layout version we support is " + Versions.MAX_LAYOUT_VERSION + "; this layout requires " + mLayoutVersion); } else if (Versions.MIN_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0) { throw new InvalidLayoutException("The minimum layout version we support is " + Versions.MIN_LAYOUT_VERSION + "; this layout requires " + mLayoutVersion); } // max_filesize and memstore_flushsize were introduced in version 1.2. if (Versions.BLOCK_SIZE_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0) { if (mDesc.getMaxFilesize() != null) { // Cannot use max_filesize if this is the case. throw new InvalidLayoutException("Support for specifying max_filesize begins with layout version " + Versions.BLOCK_SIZE_LAYOUT_VERSION.toString()); } if (mDesc.getMemstoreFlushsize() != null) { // Cannot use memstore_flushsize if this is the case. throw new InvalidLayoutException( "Support for specifying memstore_flushsize begins with layout version " + Versions.BLOCK_SIZE_LAYOUT_VERSION); } } else { if (mDesc.getMaxFilesize() != null && mDesc.getMaxFilesize() <= 0) { throw new InvalidLayoutException("max_filesize must be greater than 0"); } if (mDesc.getMemstoreFlushsize() != null && mDesc.getMemstoreFlushsize() <= 0) { throw new InvalidLayoutException("memstore_flushsize must be greater than 0"); } } // Ability to configure column name translation was introduced in version 1.5 if (Versions.CONFIGURE_COLUMN_NAME_TRANSLATION_VERSION.compareTo(mLayoutVersion) > 0) { if (mDesc.getColumnNameTranslator() != ColumnNameTranslator.SHORT) { throw new InvalidLayoutException( "Support for specifiying non-short column name translators begins with layout version " + Versions.CONFIGURE_COLUMN_NAME_TRANSLATION_VERSION); } } // Composite keys and RowKeyFormat2 was introduced in version 1.1. if (Versions.RKF2_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0 && mDesc.getKeysFormat() instanceof RowKeyFormat2) { // Cannot use RowKeyFormat2 if this is the case. throw new InvalidLayoutException( "Support for specifying keys_format as a RowKeyFormat2 begins with layout version " + Versions.RKF2_LAYOUT_VERSION); } if (!isValidName(getName())) { throw new InvalidLayoutException(String.format("Invalid table name: '%s'.", getName())); } if (reference != null) { if (!getName().equals(reference.getName())) { throw new InvalidLayoutException(String.format( "Invalid layout update: layout name '%s' does not match reference layout name '%s'.", getName(), reference.getName())); } if (!mDesc.getKeysFormat().equals(reference.getDesc().getKeysFormat())) { throw new InvalidLayoutException(String.format( "Invalid layout update from reference row keys format '%s' to row keys format '%s'.", reference.getDesc().getKeysFormat(), mDesc.getKeysFormat())); } } // Layout ID: if (mDesc.getLayoutId() == null) { try { final long refLayoutId = (reference == null) ? 0 : Long.parseLong(reference.getDesc().getLayoutId()); final long layoutId = refLayoutId + 1; mDesc.setLayoutId(Long.toString(layoutId)); } catch (NumberFormatException nfe) { throw new InvalidLayoutException( String.format("Reference layout for table '%s' has an invalid layout ID: '%s'", getName(), reference.getDesc().getLayoutId())); } } if (mDesc.getKeysFormat() instanceof RowKeyFormat) { isValidRowKeyFormat1((RowKeyFormat) mDesc.getKeysFormat()); } else if (mDesc.getKeysFormat() instanceof RowKeyFormat2) { // Check validity of row key format. isValidRowKeyFormat2((RowKeyFormat2) mDesc.getKeysFormat()); } // Build localities: /** * Reference map from locality group name to locality group ID. * Entries are removed as we process locality group descriptors in the new layout. * At the end of the process, this map must be empty. */ final BiMap<String, ColumnId> refLGIdMap = (reference == null) ? HashBiMap.<String, ColumnId>create() : HashBiMap.create(reference.mLocalityGroupIdNameMap.inverse()); /** Map of locality groups in the new layout. */ final List<LocalityGroupLayout> localityGroups = Lists.newArrayList(); final Map<String, LocalityGroupLayout> lgMap = Maps.newHashMap(); final BiMap<ColumnId, String> idMap = HashBiMap.create(); /** Locality group with no ID assigned yet. */ final List<LocalityGroupLayout> unassigned = Lists.newArrayList(); /** All the families in the table. */ final List<FamilyLayout> families = Lists.newArrayList(); /** Map from family name or alias to family layout. */ final Map<String, FamilyLayout> familyMap = Maps.newHashMap(); /** All primary column names (including map-type families). */ final Set<KijiColumnName> columnNames = Sets.newTreeSet(); final Map<KijiColumnName, ColumnLayout> columnMap = Maps.newHashMap(); final Iterator<LocalityGroupDesc> itLGDesc = mDesc.getLocalityGroups().iterator(); while (itLGDesc.hasNext()) { final LocalityGroupDesc lgDesc = itLGDesc.next(); final boolean isRename = (lgDesc.getRenamedFrom() != null); final String refLGName = isRename ? lgDesc.getRenamedFrom() : lgDesc.getName(); lgDesc.setRenamedFrom(null); if (isRename && (reference == null)) { throw new InvalidLayoutException(String .format("Invalid rename: no reference table layout for locality group '%s'.", refLGName)); } final LocalityGroupLayout refLGLayout = (reference != null) ? reference.mLocalityGroupMap.get(refLGName) : null; if (isRename && (refLGLayout == null)) { throw new InvalidLayoutException( String.format("Invalid rename: cannot find reference locality group '%s'.", refLGName)); } final ColumnId refLGId = refLGIdMap.remove(refLGName); if (lgDesc.getDelete()) { // This locality group is deleted: if (refLGId == null) { throw new InvalidLayoutException(String.format( "Attempting to delete locality group '%s' unknown in reference layout.", refLGName)); } itLGDesc.remove(); continue; } // BloomType, block_size were introduced in version 1.2. if (Versions.BLOCK_SIZE_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0) { if (lgDesc.getBlockSize() != null) { // Cannot use max_filesize if this is the case. throw new InvalidLayoutException("Support for specifying block_size begins with layout version " + Versions.BLOCK_SIZE_LAYOUT_VERSION); } if (lgDesc.getBloomType() != null) { // Cannot use bloom_type if this is the case. throw new InvalidLayoutException("Support for specifying bloom_type begins with layout version " + Versions.BLOCK_SIZE_LAYOUT_VERSION); } } else { if (lgDesc.getBlockSize() != null && lgDesc.getBlockSize() <= 0) { throw new InvalidLayoutException("block_size must be greater than 0"); } } final LocalityGroupLayout lgLayout = new LocalityGroupLayout(lgDesc, refLGLayout); localityGroups.add(lgLayout); for (String lgName : lgLayout.getNames()) { Preconditions.checkState(lgMap.put(lgName, lgLayout) == null, "Duplicate locality group name: " + lgName); } if (lgLayout.getId() != null) { final String previous = idMap.put(lgLayout.getId(), lgLayout.getName()); Preconditions.checkState(previous == null, String.format("Duplicate locality group ID '%s' associated to '%s' and '%s'.", lgLayout.getId(), lgLayout.getName(), previous)); } else { unassigned.add(lgLayout); } families.addAll(lgLayout.getFamilies()); for (FamilyLayout familyLayout : lgLayout.getFamilies()) { for (String familyName : familyLayout.getNames()) { if (null != familyMap.put(familyName, familyLayout)) { throw new InvalidLayoutException( String.format("Layout for table '%s' contains duplicate family name '%s'.", getName(), familyName)); } } if (familyLayout.isMapType()) { Preconditions.checkState(columnNames.add(KijiColumnName.create(familyLayout.getName(), null))); } for (ColumnLayout columnLayout : familyLayout.getColumns()) { for (String columnName : columnLayout.getNames()) { final KijiColumnName column = KijiColumnName.create(familyLayout.getName(), columnName); if (null != columnMap.put(column, columnLayout)) { throw new InvalidLayoutException(String.format( "Layout for table '%s' contains duplicate column '%s'.", getName(), column)); } } Preconditions.checkState( columnNames.add(KijiColumnName.create(familyLayout.getName(), columnLayout.getName()))); } } } if (!refLGIdMap.isEmpty()) { throw new InvalidLayoutException(String.format("Missing descriptor(s) for locality group(s): %s.", Joiner.on(",").join(refLGIdMap.keySet()))); } mLocalityGroups = ImmutableList.copyOf(localityGroups); mLocalityGroupMap = ImmutableMap.copyOf(lgMap); mFamilies = ImmutableList.copyOf(families); mFamilyMap = ImmutableMap.copyOf(familyMap); mColumnNames = ImmutableSet.copyOf(columnNames); // Assign IDs to locality groups: int nextColumnId = 1; for (LocalityGroupLayout localityGroup : unassigned) { Preconditions.checkState(localityGroup.getId() == null); while (true) { final ColumnId columnId = new ColumnId(nextColumnId); nextColumnId += 1; if (!idMap.containsKey(columnId)) { localityGroup.setId(columnId); idMap.put(columnId, localityGroup.getName()); break; } } } mLocalityGroupIdNameMap = ImmutableBiMap.copyOf(idMap); }