When I'm running 1.4.199 the execution ends in the same method
for addDatabaseObject(Session session, DbObject obj) which seems unchanged
with a casual glance.
session = {Session} "#0 (user: DBA)"
serialId = 0
database = {Database} "SVIFT:org.h2.engine.Database"
connectionInfo = null
user = {User} "DBA:0:org.h2.engine.User"
id = 1
locks = {ArrayList} size = 1
undoLog = null
autoCommit = true
random = null
lockTimeout = 2000
lastIdentity = {ValueLong} "0"
lastScopeIdentity = {ValueLong} "0"
lastTriggerIdentity = null
generatedKeys = null
firstUncommittedLog = -1
firstUncommittedPos = -1
savepoints = null
localTempTables = null
localTempTableIndexes = null
localTempTableConstraints = null
throttleNs = 0
lastThrottle = 0
currentCommand = null
allowLiterals = false
currentSchemaName = "PUBLIC"
schemaSearchPath = null
trace = null
removeLobMap = null
systemIdentifier = 0
procedures = null
undoLogEnabled = true
redoLogBinary = true
autoCommitAtTransactionEnd = false
currentTransactionName = null
cancelAtNs = 0
sessionStart = 1698238342161
transactionStart = null
currentCommandStart = null
variables = null
temporaryResults = null
queryTimeout = 0
commitOrRollbackDisabled = false
waitForLock = null
waitForLockThread = null
modificationId = 0
objectId = 0
queryCacheSize = 8
queryCache = null
modificationMetaID = -1
subQueryInfo = null
viewNameStack = null
preparingQueryExpression = 0
viewIndexCache = null
subQueryIndexCache = null
joinBatchEnabled = false
forceJoinOrder = false
lazyQueryExecution = false
columnNamerConfiguration = {ColumnNamerConfiguration}
tablesToAnalyze = null
temporaryResultLobs = null
temporaryLobs = null
transaction = null
state = {AtomicReference} "INIT"
startStatement = -1
idsToRelease = null
sessionState = null
sessionStateChanged = true
sessionStateUpdating = false
obj = {User} "PUBLIC:2:org.h2.engine.User"
systemUser = false
salt = {byte[8]
passwordHash = {byte[32]
admin = true
grantedRoles = null
grantedRights = null
database = {Database} "SVIFT:org.h2.engine.Database@691500ab"
trace = {Trace}
comment = null
id = 2
objectName = "PUBLIC"
modificationId = 1
temporary = false
The getMap() method returns the content of the Database.user variable which
has no content.
name is still "PUBLIC"
thus the test in
if (SysProperties.CHECK && map.get(name) != null)
isn't true and no exception is thrown.
On Wednesday, 25 October 2023 at 14:46:55 UTC+2 Knut Skomedal wrote:
> I've debugged the last part of the process where hibernate tries to get a
> connection to the database, starting with a breakpoint
> in org.h2.engine.Engine.createSession(Engine.java:201)
>
> public static SessionLocal createSession(ConnectionInfo ci) {
> try {
> SessionLocal session = openSession(ci);
>
> ci = {ConnectionInfo}
> prop = {Properties} size = 5 <-- The properties are parsed correctly
> from the original url.
> "LOCK_TIMEOUT" -> "60000"
> "DB_CLOSE_DELAY" -> "-1"
> "MODE" -> "Oracle"
> "DB_CLOSE_ON_EXIT" -> "FALSE"
> "TRACE_LEVEL_SYSTEM_OUT" -> "0"
> originalURL =
> "jdbc:h2:mem:SVIFT;MODE=Oracle;DB_CLOSE_DELAY=-1;TRACE_LEVEL_SYSTEM_OUT=0;LOCK_TIMEOUT=60000;DB_CLOSE_ON_EXIT=FALSE"
> url = "jdbc:h2:mem:SVIFT"
> user = "PUBLIC"
> name = "mem:SVIFT"
>
> This runs to L222: session = openSession(ci, ifExists, forbidCreation,
> cipher);
> ifExists (slot_1) = 0
> forbidCreation (slot_2) = 0
> ignoreUnknownSetting (slot_3) = 0
> cipher (slot_4) = null
>
> Then to L107:
> if (!found) {
> // users is the last thing we add, so if no user is
> around,
> // the database is new (or not initialized correctly)
> user = new User(database, database.allocateObjectId(),
> ci.getUserName(), false);
> user.setAdmin(true);
> user.setUserPasswordHash(ci.getUserPasswordHash());
> database.setMasterUser(user); <-- Here
>
> public synchronized void setMasterUser(User user) {
> lockMeta(systemSession);
> addDatabaseObject(systemSession, user); <-- Here
>
> systemSession:
> result = {SessionLocal} "#0 (user: DBA, INIT)"
> serialId = 0
> database = {Database} "SVIFT:org.h2.engine.Database"
> user = {User} "DBA:0:org.h2.engine.User"
> id = 1
> networkConnectionInfo = null
> locks = {ArrayList} size = 1
> autoCommit = true
> random = null
> lockTimeout = 2000
> nextValueFor = null
> currentValueFor = null
> lastIdentity = {ValueNul} "NULL"
> savepoints = null
> localTempTables = null
> localTempTableIndexes = null
> localTempTableConstraints = null
> throttleMs = 0
> lastThrottleNs = 0
> currentCommand = null
> allowLiterals = false
> currentSchemaName = "PUBLIC"
> schemaSearchPath = null
> trace = null
> removeLobMap = null
> systemIdentifier = 0
> procedures = null
> autoCommitAtTransactionEnd = false
> currentTransactionName = null
> cancelAtNs = 0
> sessionStart = {ValueTimestampTimeZone} "TIMESTAMP WITH TIME ZONE
> '2023-10-25 12:48:23.230424874+02'"
> commandStartOrEnd = {Instant} "2023-10-25T10:48:23.230424874Z"
> currentTimestamp = null
> variables = null
> queryTimeout = 0
> commitOrRollbackDisabled = false
> waitForLock = null
> waitForLockThread = null
> modificationId = 0
> objectId = 0
> queryCacheSize = 8
> queryCache = null
> modificationMetaID = -1
> createViewLevel = 0
> viewIndexCache = null
> derivedTableIndexCache = null
> lazyQueryExecution = false
> nonKeywords = null
> timeZone = {TimeZoneProvider$WithTimeZone} "TimeZoneProvider Europe/Oslo"
> tablesToAnalyze = null
> temporaryResultLobs = null
> temporaryLobs = null
> transaction = null
> state = {AtomicReference} "INIT"
> startStatement = -1
> isolationLevel = {IsolationLevel} "READ_COMMITTED"
> snapshotDataModificationId = 0
> idsToRelease = null
> truncateLargeLength = false
> variableBinary = false
> oldInformationSchema = false
> quirksMode = false
> lock = {ReentrantLock}
> "java.util.concurrent.locks.ReentrantLock[Unlocked]"
> sessionState = null
> sessionStateChanged = true
> sessionStateUpdating = false
> staticSettings = null
>
> user = {User} "PUBLIC:2:org.h2.engine.User"
> systemUser = false
> salt = {byte[8]
> passwordHash = {byte[32]}
> admin = true
> grantedRoles = null
> grantedRights = null
> database = {Database} "SVIFT:org.h2.engine.Database"
> trace = {Trace}
> comment = null
> id = 2
> objectName = "PUBLIC"
> modificationId = 1
> temporary = false
>
> Then to public synchronized void addDatabaseObject(SessionLocal
> session, DbObject obj) { <-- obj is the User above
> int id = obj.getId();
> if (id > 0 && !starting) {
> checkWritingAllowed(); <-- OK
> }
> ConcurrentHashMap<String, DbObject> map = getMap(obj.getType());
> <-- getMap(type = 2 which is USER) returns the content of
> Database.usersAndRoles
> if (obj.getType() == DbObject.USER) {
> User user = (User) obj;
> if (user.isAdmin() &&
> systemUser.getName().equals(SYSTEM_USER_NAME)) {
> systemUser.rename(user.getName());
> }
> }
> String name = obj.getName(); <-- returns PUBLIC
> if (SysProperties.CHECK && map.get(name) != null) {
> throw DbException.getInternalError("object already exists");
> <-- Enters this, both names are "PUBLIC".
> }
>
> map (slot_4) = {ConcurrentHashMap} size = 1
> "PUBLIC" -> {Role} "PUBLIC:0:org.h2.engine.Role"
> key = "PUBLIC"
> value = {Role} "PUBLIC:0:org.h2.engine.Role"
> system = true
> grantedRoles = null
> grantedRights = null
> database = {Database} "SVIFT:org.h2.engine.Database"
> trace = {Trace}
> comment = null
> id = 0
> objectName = "PUBLIC"
> modificationId = 0
> temporary = false
>
> In the getInternalError()-method of DbException, the static content of the
> class contains the OutOfMemoryError posted previously. It might not be
> related to the problem that occurs.
>
> Does any of this indicate to you what the problem is?
>
> On Wednesday, 25 October 2023 at 11:08:39 UTC+2 Knut Skomedal wrote:
>
>> The same Exception occurs when I run a single test manually in
>> intelliJ, so I doubt that it's a race condition between two tests.
>>
>> By setting a breakpoint where the previous stacktrace has the last
>> statement:
>> Caused by: java.lang.RuntimeException: object already exists
>> at org.h2.message.DbException.getInternalError(DbException.java:355)
>> I find an OutOfMEmoryError:
>>
>> serialVersionUID = 1
>> HIDE_SQL = "--hide--"
>> MESSAGES = {Properties@5409} size = 202
>> SQL_OOME = {SQLException@5410} "java.sql.SQLException: OutOfMemoryError"
>> SQLState = "HY000"
>> vendorCode = 90108
>> next = null
>> backtrace = {Object[6]@7812}
>> detailMessage = "OutOfMemoryError"
>> cause = {OutOfMemoryError@7813} "java.lang.OutOfMemoryError"
>> stackTrace = {StackTraceElement[63]@7815}
>> 0 = {StackTraceElement@7817}
>> "org.h2.message.DbException.<clinit>(DbException.java:62)"
>> 1 = {StackTraceElement@7818}
>> "org.h2.message.TraceObject.<clinit>(TraceObject.java:108)"
>> 2 = {StackTraceElement@7819}
>> "java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native
>>
>>
>> Method)"
>> 3 = {StackTraceElement@7820}
>> "java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)"
>>
>>
>> 4 = {StackTraceElement@7821}
>> "java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)"
>>
>>
>> 5 = {StackTraceElement@7822}
>> "java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)"
>>
>>
>> 6 = {StackTraceElement@7823}
>> "java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)"
>>
>> 7 = {StackTraceElement@7824}
>> "org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:211)"
>>
>> 8 = {StackTraceElement@7825}
>> "org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)"
>>
>>
>> 9 = {StackTraceElement@7826}
>> "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1326)"
>>
>>
>> 10 = {StackTraceElement@7827}
>> "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1232)"
>>
>>
>> 11 = {StackTraceElement@7828}
>> "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)"
>>
>>
>> 12 = {StackTraceElement@7829}
>> "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)"
>>
>>
>> 13 = {StackTraceElement@7830}
>> "org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)"
>>
>>
>> 14 = {StackTraceElement@7831}
>> "org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)"
>>
>>
>> 15 = {StackTraceElement@7832}
>> "org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)"
>>
>>
>> 16 = {StackTraceElement@7833}
>> "org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)"
>>
>>
>> 17 = {StackTraceElement@7834}
>> "org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330)"
>>
>>
>> 18 = {StackTraceElement@7835}
>> "org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:113)"
>>
>>
>> 19 = {StackTraceElement@7836}
>> "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1707)"
>>
>>
>> 20 = {StackTraceElement@7837}
>> "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1452)"
>>
>>
>> 21 = {StackTraceElement@7838}
>> "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619)"
>>
>>
>> 22 = {StackTraceElement@7839}
>> "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)"
>>
>>
>> 23 = {StackTraceElement@7840}
>> "org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)"
>>
>>
>> 24 = {StackTraceElement@7841}
>> "org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)"
>>
>>
>> 25 = {StackTraceElement@7842}
>> "org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)"
>>
>>
>> 26 = {StackTraceElement@7843}
>> "org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)"
>>
>>
>> 27 = {StackTraceElement@7844}
>> "org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154)"
>>
>>
>> 28 = {StackTraceElement@7845}
>> "org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908)"
>>
>>
>> 29 = {StackTraceElement@7846}
>> "org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)"
>>
>>
>> 30 = {StackTraceElement@7847}
>> "org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:127)"
>>
>>
>> 31 = {StackTraceElement@7848}
>> "org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)"
>>
>>
>> 32 = {StackTraceElement@7849}
>> "org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:276)"
>>
>>
>> 33 = {StackTraceElement@7850}
>> "org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:244)"
>>
>>
>> 34 = {StackTraceElement@7851}
>> "org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:141)"
>>
>>
>> 35 = {StackTraceElement@7852}
>> "org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:90)"
>>
>>
>> 36 = {StackTraceElement@7853}
>> "org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)"
>>
>>
>> 37 = {StackTraceElement@7854}
>> "org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)"
>>
>>
>> 38 = {StackTraceElement@7855}
>> "org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)"
>>
>>
>> 39 = {StackTraceElement@7856}
>> "org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248)"
>>
>>
>> 40 = {StackTraceElement@7857}
>> "org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)"
>>
>>
>> 41 = {StackTraceElement@7858}
>> "org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)"
>>
>>
>> 42 = {StackTraceElement@7859}
>> "org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)"
>>
>>
>> 43 = {StackTraceElement@7860}
>> "org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)"
>>
>>
>> 44 = {StackTraceElement@7861}
>> "org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)"
>>
>>
>> 45 = {StackTraceElement@7862}
>> "org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)"
>>
>>
>> 46 = {StackTraceElement@7863}
>> "org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)"
>> 47 = {StackTraceElement@7864}
>> "org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)"
>> 48 = {StackTraceElement@7865}
>> "org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)"
>> 49 = {StackTraceElement@7866}
>> "org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)"
>> 50 = {StackTraceElement@7867}
>> "org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)"
>> 51 = {StackTraceElement@7868}
>> "org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)"
>>
>>
>> 52 = {StackTraceElement@7869}
>> "org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)"
>>
>>
>> 53 = {StackTraceElement@7870}
>> "org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)"
>> 54 = {StackTraceElement@7871}
>> "org.junit.runners.ParentRunner.run(ParentRunner.java:413)"
>> 55 = {StackTraceElement@7872}
>> "org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)"
>>
>>
>> 56 = {StackTraceElement@7873}
>> "org.junit.runner.JUnitCore.run(JUnitCore.java:137)"
>> 57 = {StackTraceElement@7874}
>> "com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)"
>>
>>
>> 58 = {StackTraceElement@7875}
>> "com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)"
>>
>>
>> 59 = {StackTraceElement@7876}
>> "com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)"
>>
>>
>> 60 = {StackTraceElement@7877}
>> "com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)"
>>
>>
>> 61 = {StackTraceElement@7878}
>> "com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)"
>>
>>
>> 62 = {StackTraceElement@7879}
>> "com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)"
>> depth = 63
>> suppressedExceptions = {Collections$EmptyList@5413} size = 0
>>
>> On Wed, Oct 25, 2023 at 9:27 AM Noel Grandin <[email protected]> wrote:
>> >
>> > My best guess right now is that you are using named in-memory
>> databases, which means that the unit tests are sharing an
>> > in-memory database, and you are hitting a race condition (TOCTOU) in
>> that chunk of code.
>> >
>> > Short of fixing the H2 code, the only thing I can suggest is using
>> different databases for different unit tests.
>>
>
--
You received this message because you are subscribed to the Google Groups "H2
Database" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/h2-database/aed1475c-0c67-439b-a2ea-345bebb9323bn%40googlegroups.com.