DatastoreImpl not thread safe for ensureIndexes() call ?

46 views
Skip to first unread message

joseph

unread,
Nov 8, 2010, 4:39:51 AM11/8/10
to Morphia
hi

I had this exception in some test we use, with this stack trace

java.lang.RuntimeException: com.google.inject.CreationException: Guice
creation errors:

1) Error injecting constructor,
java.util.ConcurrentModificationException
at com.softculture.utilities.morphia.guice.MorphiaIntializerModule
$Initializer.<init>(MorphiaIntializerModule.java:28)
while locating
com.softculture.utilities.morphia.guice.MorphiaIntializerModule
$Initializer

1 error
at
com.softculture.utilities.morphia.test.MorphiaTestCase.setUp(MorphiaTestCase.java:
63)
at junit.framework.TestCase.runBare(TestCase.java:132)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at
org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:
81)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:
49)
at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:
38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
467)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
683)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:
390)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:
197)
Caused by: com.google.inject.CreationException: Guice creation errors:

1) Error injecting constructor,
java.util.ConcurrentModificationException
at com.softculture.utilities.morphia.guice.MorphiaIntializerModule
$Initializer.<init>(MorphiaIntializerModule.java:28)
while locating
com.softculture.utilities.morphia.guice.MorphiaIntializerModule
$Initializer

1 error
at
com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:
354)
at
com.google.inject.InjectorBuilder.injectDynamically(InjectorBuilder.java:
179)
at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:113)
at com.google.inject.Guice.createInjector(Guice.java:92)
at com.google.inject.Guice.createInjector(Guice.java:69)
at com.google.inject.Guice.createInjector(Guice.java:59)
at
com.softculture.utilities.morphia.test.MorphiaTestCase.setUp(MorphiaTestCase.java:
52)
... 14 more
Caused by: java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
at java.util.HashMap$ValueIterator.next(HashMap.java:822)
at
com.google.code.morphia.DatastoreImpl.ensureIndexes(DatastoreImpl.java:
333)
at
com.google.code.morphia.DatastoreImpl.ensureIndexes(DatastoreImpl.java:
327)
at com.softculture.utilities.morphia.guice.MorphiaIntializerModule
$Initializer.<init>(MorphiaIntializerModule.java:43)
at com.softculture.utilities.morphia.guice.MorphiaIntializerModule
$Initializer$$FastClassByGuice$$7c84a053.newInstance(<generated>)
at
com.google.inject.internal.cglib.reflect.FastConstructor.newInstance(FastConstructor.java:
40)
at com.google.inject.DefaultConstructionProxyFactory
$1.newInstance(DefaultConstructionProxyFactory.java:60)
at
com.google.inject.ConstructorInjector.construct(ConstructorInjector.java:
85)
at com.google.inject.ConstructorBindingImpl
$Factory.get(ConstructorBindingImpl.java:111)
at com.google.inject.ProviderToInternalFactoryAdapter
$1.call(ProviderToInternalFactoryAdapter.java:45)
at com.google.inject.InjectorImpl.callInContext(InjectorImpl.java:
811)
at
com.google.inject.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:
42)
at com.google.inject.Scopes$1$1.get(Scopes.java:54)
at
com.google.inject.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:
48)
at com.google.inject.InjectorBuilder$1.call(InjectorBuilder.java:200)
at com.google.inject.InjectorBuilder$1.call(InjectorBuilder.java:194)
at com.google.inject.InjectorImpl.callInContext(InjectorImpl.java:
804)
at
com.google.inject.InjectorBuilder.loadEagerSingletons(InjectorBuilder.java:
194)
at
com.google.inject.InjectorBuilder.injectDynamically(InjectorBuilder.java:
176)
... 19 more


While trying to create a proper failing test case for inclusion in
some issue, I looked at the code and saw in DatastoreImpl:
public void ensureIndexes(boolean background) {
// loops over mappedClasses and call ensureIndex for each @Entity
object
// (for now)
for (MappedClass mc : mapr.getMappedClasses().values()) {
ensureIndexes(mc, background);
}
}

with in Mapper :
/** Set of classes that registered by this mapper */
private final Map<String, MappedClass> mappedClasses = new
HashMap<String, MappedClass>();

/** Returns map of MappedClasses by class name */
public Map<String, MappedClass> getMappedClasses() {
return mappedClasses;
}

isn't it inherently not thread safe ?

thanks in advance
joseph

Scott Hernandez

unread,
Nov 8, 2010, 12:17:17 PM11/8/10
to mor...@googlegroups.com
Yep, that was a bug. I have a fix that and it will go into the next release.
.

joseph

unread,
Nov 9, 2010, 5:34:06 AM11/9/10
to Morphia
thanks :)

btw: do you prefer that people open issues or discuss the matter on
the ML first ?

NB: I'm short on time, I'll answer on the issues tomorrow I guess

Scott Hernandez

unread,
Nov 9, 2010, 9:41:58 AM11/9/10
to mor...@googlegroups.com
If it is a feature-request/bug/stacktrace it probably goes in as an
issue. If there is a question about how things (should) work, or it
will start a discussion then it should probably come here.
Reply all
Reply to author
Forward
0 new messages