[
http://opensource.atlassian.com/projects/hibernate/browse/HHH-3628?page=c...
]
Hassan Hammoud commented on HHH-3628:
-------------------------------------
Hello Cyril :), I still think that in the ticket they didn't describe the case
correctly. I don't think they meant in one call of generate() but instead two or more
threads are calling the generate().
In brief,
1- Thread one called "value = callback.getNextValue()" inside the
"else if ( value >= hiValue )";
2- Thread two called "value = callback.getNextValue()" inside the
"if ( hiValue < 0 )" hence resetting the value variable;
3- Thread one called "hiValue = callback.getNextValue();" inside the
"else if ( value >= hiValue )";
check the attached PooledOptimizerTest.java in HHH-3608 and run it you will understand
what they mean.
Although the generate() is a synchronized function it is still not static -> so only
synchronized inside the same PooledOptimizer Object. If another PooledOptimizer in
another thread calls the generate(), it will execute. It's only that the value
variable is common to the two objects through the DB or the callback.getNextValue();
Hilo optimizer problem in case of multiple threads accessing the
sequence table
-------------------------------------------------------------------------------
Key: HHH-3628
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-3628
Project: Hibernate Core
Issue Type: Bug
Affects Versions: 3.2.6
Environment: Sybase
Reporter: Montagnon Cyril
If 2 (or more) threads access the table storing the ids, this optimizer won't work
and will try to insert entities with twice the same idea.
The problem is the way the HiLoOptimizer class generates the id :
public synchronized Serializable generate(AccessCallback callback) {
if ( lastSourceValue < 0 ) {
lastSourceValue = callback.getNextValue();
while ( lastSourceValue <= 0 ) {
lastSourceValue = callback.getNextValue();
}
hiValue = ( lastSourceValue * incrementSize ) + 1;
value = hiValue - incrementSize;
}
else if ( value >= hiValue ) {
lastSourceValue = callback.getNextValue();
hiValue = ( lastSourceValue * incrementSize ) + 1;
}
return make( value++ );
}
In the 'else if' part, the 'value' variable isn't reaffected, which
means the current thread will try to insert entities with an id that has already been used
by another thread. The value should be reset with hiValue - incrementSize.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira