MAPREDUCE-3749. ConcurrentModificationException in counter groups.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1238734 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas White 2012-01-31 18:30:58 +00:00
parent a8b6ee0491
commit 05efddf28e
4 changed files with 39 additions and 11 deletions

View File

@ -627,6 +627,9 @@ Release 0.23.1 - Unreleased
MAPREDUCE-3764. Fixed resource usage metrics for queues and users. MAPREDUCE-3764. Fixed resource usage metrics for queues and users.
(acmurthy) (acmurthy)
MAPREDUCE-3749. ConcurrentModificationException in counter groups.
(tomwhite)
Release 0.23.0 - 2011-11-01 Release 0.23.0 - 2011-11-01
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -24,6 +24,7 @@
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators; import com.google.common.collect.Iterators;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -56,7 +57,7 @@ public AbstractCounterGroup(String name, String displayName,
} }
@Override @Override
public synchronized String getName() { public String getName() {
return name; return name;
} }
@ -95,7 +96,7 @@ private T addCounterImpl(String name, String displayName, long value) {
} }
@Override @Override
public T findCounter(String counterName, String displayName) { public synchronized T findCounter(String counterName, String displayName) {
String saveName = limits.filterCounterName(counterName); String saveName = limits.filterCounterName(counterName);
T counter = findCounterImpl(saveName, false); T counter = findCounterImpl(saveName, false);
if (counter == null) { if (counter == null) {
@ -109,7 +110,7 @@ public synchronized T findCounter(String counterName, boolean create) {
return findCounterImpl(limits.filterCounterName(counterName), create); return findCounterImpl(limits.filterCounterName(counterName), create);
} }
private T findCounterImpl(String counterName, boolean create) { private synchronized T findCounterImpl(String counterName, boolean create) {
T counter = counters.get(counterName); T counter = counters.get(counterName);
if (counter == null && create) { if (counter == null && create) {
String localized = String localized =
@ -142,7 +143,7 @@ protected abstract T newCounter(String counterName, String displayName,
@Override @Override
public synchronized Iterator<T> iterator() { public synchronized Iterator<T> iterator() {
return counters.values().iterator(); return ImmutableSet.copyOf(counters.values()).iterator();
} }
/** /**

View File

@ -24,6 +24,7 @@
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators; import com.google.common.collect.Iterators;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -179,13 +180,14 @@ public synchronized C findCounter(String scheme, FileSystemCounter key) {
* @return Set of counter names. * @return Set of counter names.
*/ */
public synchronized Iterable<String> getGroupNames() { public synchronized Iterable<String> getGroupNames() {
return Iterables.concat(fgroups.keySet(), groups.keySet()); return Iterables.concat(ImmutableSet.copyOf(fgroups.keySet()),
ImmutableSet.copyOf(groups.keySet()));
} }
@Override @Override
public Iterator<G> iterator() { public synchronized Iterator<G> iterator() {
return Iterators.concat(fgroups.values().iterator(), return Iterators.concat(ImmutableSet.copyOf(fgroups.values()).iterator(),
groups.values().iterator()); ImmutableSet.copyOf(groups.values()).iterator());
} }
/** /**

View File

@ -21,9 +21,11 @@
import java.io.IOException; import java.io.IOException;
import java.text.ParseException; import java.text.ParseException;
import java.util.Iterator;
import java.util.Random; import java.util.Random;
import org.apache.hadoop.mapred.Counters.Counter; import org.apache.hadoop.mapred.Counters.Counter;
import org.apache.hadoop.mapred.Counters.Group;
import org.apache.hadoop.mapreduce.FileSystemCounter; import org.apache.hadoop.mapreduce.FileSystemCounter;
import org.apache.hadoop.mapreduce.JobCounter; import org.apache.hadoop.mapreduce.JobCounter;
import org.apache.hadoop.mapreduce.TaskCounter; import org.apache.hadoop.mapreduce.TaskCounter;
@ -71,8 +73,6 @@ private void testCounter(Counters counter) throws ParseException {
// Check for recovery from string // Check for recovery from string
assertEquals("Recovered counter does not match on content", assertEquals("Recovered counter does not match on content",
counter, recoveredCounter); counter, recoveredCounter);
assertEquals("recovered counter has wrong hash code",
counter.hashCode(), recoveredCounter.hashCode());
} }
@Test @Test
@ -159,6 +159,28 @@ public void testLegacyNames() {
"FILE_BYTES_READ").getValue()); "FILE_BYTES_READ").getValue());
} }
@SuppressWarnings("deprecation")
@Test
public void testCounterIteratorConcurrency() {
Counters counters = new Counters();
counters.incrCounter("group1", "counter1", 1);
Iterator<Group> iterator = counters.iterator();
counters.incrCounter("group2", "counter2", 1);
iterator.next();
}
@SuppressWarnings("deprecation")
@Test
public void testGroupIteratorConcurrency() {
Counters counters = new Counters();
counters.incrCounter("group1", "counter1", 1);
Group group = counters.getGroup("group1");
Iterator<Counter> iterator = group.iterator();
counters.incrCounter("group1", "counter2", 1);
iterator.next();
}
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
new TestCounters().testCounters(); new TestCounters().testCounters();
} }