Skip to content

Commit dc02e53

Browse files
committed
HADOOP-19161. Improvements
- Round tripping (with tests) - remove synchronization with docs to say "just make immutable" - better tests - source enumset is copied to ensure immutability. Change-Id: I55fb1f37a9553bcb257225f27806d341613cd2d6
1 parent e21a449 commit dc02e53

File tree

9 files changed

+191
-72
lines changed

9 files changed

+191
-72
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import java.util.Arrays;
5050
import java.util.Collection;
5151
import java.util.Collections;
52+
import java.util.EnumSet;
5253
import java.util.Enumeration;
5354
import java.util.HashMap;
5455
import java.util.HashSet;
@@ -99,7 +100,7 @@
99100
import org.apache.hadoop.security.alias.CredentialProvider.CredentialEntry;
100101
import org.apache.hadoop.security.alias.CredentialProviderFactory;
101102
import org.apache.hadoop.thirdparty.com.google.common.base.Strings;
102-
import org.apache.hadoop.util.ConfigurationUtil;
103+
import org.apache.hadoop.util.ConfigurationHelper;
103104
import org.apache.hadoop.util.Preconditions;
104105
import org.apache.hadoop.util.ReflectionUtils;
105106
import org.apache.hadoop.util.StringInterner;
@@ -1799,12 +1800,12 @@ public <T extends Enum<T>> T getEnum(String name, T defaultValue) {
17991800
* @throws IllegalArgumentException if one of the entries was unknown and ignoreUnknown is false,
18001801
* or there are two entries in the enum which differ only by case.
18011802
*/
1802-
public <E extends Enum<E>> Set<E> getEnumSet(
1803+
public <E extends Enum<E>> EnumSet<E> getEnumSet(
18031804
final String key,
18041805
final Class<E> enumClass,
18051806
final boolean ignoreUnknown) throws IllegalArgumentException {
18061807
final String value = get(key, "");
1807-
return ConfigurationUtil.parseEnumSet(key, value, enumClass, ignoreUnknown);
1808+
return ConfigurationHelper.parseEnumSet(key, value, enumClass, ignoreUnknown);
18081809
}
18091810

18101811
enum ParsedTimeDuration {

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/impl/FlagSet.java

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,28 @@
1818

1919
package org.apache.hadoop.fs.impl;
2020

21-
import java.util.Collections;
21+
import java.util.EnumSet;
2222
import java.util.Map;
23+
import java.util.Objects;
2324
import java.util.Set;
2425
import java.util.concurrent.atomic.AtomicBoolean;
2526
import java.util.stream.Collectors;
2627

2728
import org.apache.hadoop.conf.Configuration;
2829
import org.apache.hadoop.fs.StreamCapabilities;
30+
import org.apache.hadoop.util.ConfigurationHelper;
2931
import org.apache.hadoop.util.Preconditions;
3032

31-
import static java.util.Objects.requireNonNull;
32-
import static org.apache.hadoop.util.ConfigurationUtil.mapEnumNamesToValues;
33+
import static org.apache.hadoop.util.ConfigurationHelper.mapEnumNamesToValues;
3334

3435
/**
3536
* A set of flags, constructed from a configuration option or from a string,
3637
* with the semantics of
37-
* {@link org.apache.hadoop.util.ConfigurationUtil#parseEnumSet(String, String, Class, boolean)}
38+
* {@link ConfigurationHelper#parseEnumSet(String, String, Class, boolean)}
3839
* and implementing {@link StreamCapabilities}.
39-
* Once declared immutable, flags cannot be changed.
40-
* While mutable, all getters and setters are synchronized, so
41-
* an instance is always thread-safe.
40+
* Thread safety: there is no synchronization on a mutable {@code FlagSet}.
41+
* Once declared immutable, flags cannot be changed, so they
42+
* becomes implicitly thread-safe.
4243
*/
4344
public final class FlagSet<E extends Enum<E>> implements StreamCapabilities {
4445

@@ -61,10 +62,10 @@ public final class FlagSet<E extends Enum<E>> implements StreamCapabilities {
6162
* Create a FlagSet.
6263
* @param enumClass class of enum
6364
* @param prefix prefix (with trailing ".") for path capabilities probe
64-
* @param flags flags
65+
* @param flags flags. A copy of these are made.
6566
*/
66-
private FlagSet(final Class<E> enumClass, final String prefix, final Set<E> flags) {
67-
this.flags = requireNonNull(flags);
67+
private FlagSet(final Class<E> enumClass, final String prefix, final EnumSet<E> flags) {
68+
this.flags = EnumSet.copyOf(flags);
6869
this.namesToValues = mapEnumNamesToValues(prefix, enumClass);
6970
}
7071

@@ -73,16 +74,24 @@ private FlagSet(final Class<E> enumClass, final String prefix, final Set<E> flag
7374
* This is immutable.
7475
* @return the flags.
7576
*/
76-
public synchronized Set<E> flags() {
77-
return Collections.unmodifiableSet(flags);
77+
public EnumSet<E> flags() {
78+
return EnumSet.copyOf(flags);
79+
}
80+
81+
/**
82+
* Probe for the FlagSet being empty.
83+
* @return true if there are no flags set.
84+
*/
85+
public boolean isEmpty() {
86+
return flags.isEmpty();
7887
}
7988

8089
/**
8190
* Is a flag enabled?
8291
* @param flag flag to check
8392
* @return true if it is in the set of enabled flags.
8493
*/
85-
public synchronized boolean enabled(final E flag) {
94+
public boolean enabled(final E flag) {
8695
return flags.contains(flag);
8796
}
8897

@@ -98,7 +107,7 @@ private void checkMutable() {
98107
* Enable a flag.
99108
* @param flag flag to enable.
100109
*/
101-
public synchronized void enable(final E flag) {
110+
public void enable(final E flag) {
102111
checkMutable();
103112
flags.add(flag);
104113
}
@@ -107,7 +116,7 @@ public synchronized void enable(final E flag) {
107116
* Disable a flag.
108117
* @param flag flag to disable
109118
*/
110-
public synchronized void disable(final E flag) {
119+
public void disable(final E flag) {
111120
checkMutable();
112121
flags.remove(flag);
113122
}
@@ -140,7 +149,7 @@ public boolean hasCapability(final String capability) {
140149
/**
141150
* Make immutable; no-op if already set.
142151
*/
143-
public synchronized void makeImmutable() {
152+
public void makeImmutable() {
144153
immutable.set(true);
145154
}
146155

@@ -153,18 +162,51 @@ public String toString() {
153162
+ '}';
154163
}
155164

165+
/**
166+
* Equality is based on the set.
167+
* @param o
168+
* @return
169+
*/
170+
@Override
171+
public boolean equals(final Object o) {
172+
if (this == o) {return true;}
173+
if (o == null || getClass() != o.getClass()) {return false;}
174+
FlagSet<?> flagSet = (FlagSet<?>) o;
175+
return Objects.equals(flags, flagSet.flags);
176+
}
177+
178+
/**
179+
* Hash code is based on the flags.
180+
* @return a hash code.
181+
*/
182+
@Override
183+
public int hashCode() {
184+
return Objects.hashCode(flags);
185+
}
186+
187+
/**
188+
* Convert to a string which can be then set in a configuration.
189+
* This is effectively a marshalled form of the flags.
190+
* @return a comma separated list of flag names.
191+
*/
192+
public String toConfigurationString() {
193+
return flags.stream()
194+
.map(e -> e.name())
195+
.collect(Collectors.joining(", "));
196+
}
197+
156198
/**
157199
* Create a FlagSet.
158200
* @param enumClass class of enum
159201
* @param prefix prefix (with trailing ".") for path capabilities probe
160202
* @param flags flags
161-
* @return a FlagSet
162203
* @param <E> enum type
204+
* @return a mutable FlagSet
163205
*/
164-
public static <E extends Enum<E>> FlagSet<E> createFlagSet(
206+
public static <E extends Enum<E>> FlagSet<E> createFlagSet(
165207
final Class<E> enumClass,
166208
final String prefix,
167-
final Set<E> flags) {
209+
final EnumSet<E> flags) {
168210
return new FlagSet<>(enumClass, prefix, flags);
169211
}
170212

@@ -176,17 +218,17 @@ public static <E extends Enum<E>> FlagSet<E> createFlagSet(
176218
* @param conf configuration
177219
* @param key key to look for
178220
* @param ignoreUnknown should unknown values raise an exception?
179-
* @return a FlagSet
180221
* @param <E> enumeration type
222+
* @return a mutable FlagSet
181223
* @throws IllegalArgumentException if one of the entries was unknown and ignoreUnknown is false,
182-
* or there are two entries in the enum which differ only by case.
224+
* or there are two entries in the enum which differ only by case.
183225
*/
184-
public static <E extends Enum<E>> FlagSet<E> buildFlagSet(
226+
public static <E extends Enum<E>> FlagSet<E> buildFlagSet(
185227
final Class<E> enumClass,
186228
final Configuration conf,
187229
final String key,
188230
final boolean ignoreUnknown) {
189-
final Set<E> flags = conf.getEnumSet(key, enumClass, ignoreUnknown);
231+
final EnumSet<E> flags = conf.getEnumSet(key, enumClass, ignoreUnknown);
190232
return createFlagSet(enumClass, key + ".", flags);
191233
}
192234

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.util.HashMap;
2323
import java.util.Locale;
2424
import java.util.Map;
25-
import java.util.Set;
2625
import java.util.stream.Collectors;
2726

2827
import org.apache.hadoop.classification.InterfaceAudience;
@@ -34,11 +33,11 @@
3433
import static org.apache.hadoop.util.StringUtils.getTrimmedStringCollection;
3534

3635
/**
37-
* Configuration Utils to provide advanced configuration parsing.
36+
* Configuration Helper class to provide advanced configuration parsing.
3837
* Private; external code MUST use {@link Configuration} instead
3938
*/
4039
@InterfaceAudience.Private
41-
public final class ConfigurationUtil {
40+
public final class ConfigurationHelper {
4241

4342
/**
4443
* Error string if there are multiple enum elements which only differ
@@ -48,7 +47,7 @@ public final class ConfigurationUtil {
4847
static final String ERROR_MULTIPLE_ELEMENTS_MATCHING_TO_LOWER_CASE_VALUE =
4948
"has multiple elements matching to lower case value";
5049

51-
private ConfigurationUtil() {
50+
private ConfigurationHelper() {
5251
}
5352

5453
/**
@@ -67,7 +66,7 @@ private ConfigurationUtil() {
6766
* or there are two entries in the enum which differ only by case.
6867
*/
6968
@SuppressWarnings("unchecked")
70-
public static <E extends Enum<E>> Set<E> parseEnumSet(final String key,
69+
public static <E extends Enum<E>> EnumSet<E> parseEnumSet(final String key,
7170
final String valueString,
7271
final Class<E> enumClass,
7372
final boolean ignoreUnknown) throws IllegalArgumentException {

0 commit comments

Comments
 (0)