Hi, Thanks for your help! Yes, this is a bug.
The CompressTool is currently not multithreading safe. Because of this, the following database operations are also not multithreading safe (even when using different databases): the SCRIPT command (only when using compression), the COMPRESS function, and storing CLOB or BLOB data (only when compression is enabled). My solution is a bit different however: I will change CompressTool.getInstance() to return a new object for each call. Like this the internal buffer can still be used, but synchronization is no longer necessary. Concurrently calling compress on the same instance is not allowed of course (I will document that), but that shouldn't be a problem. Regards, Thomas On Fri, Nov 27, 2009 at 12:35 AM, Cyberax <[email protected]> wrote: > We've found a corruption which occurs when several threads do a > database dump (using "SCRIPT TO") command at the same time. > > We've traced it to the class org.h2.tools.CompressTool - it uses a > shared buffer (byte[] cachedBuffer) without proper synchronization in > "public byte[] compress(byte[] in, String algorithm)". > > Attached patch fixes this problem (and speeds up parallel dumps as a > nice side effect): > > Index: CompressTool.java > =================================================================== > --- CompressTool.java (revision 2028) > +++ CompressTool.java (working copy) > @@ -25,7 +25,6 @@ > import org.h2.compress.LZFInputStream; > import org.h2.compress.LZFOutputStream; > import org.h2.constant.ErrorCode; > -import org.h2.engine.Constants; > import org.h2.message.Message; > import org.h2.util.MemoryUtils; > import org.h2.util.StringUtils; > @@ -36,8 +35,6 @@ > public class CompressTool { > > private static final CompressTool INSTANCE = new CompressTool(); > - private static final int MAX_BUFFER_SIZE = 3 * > Constants.IO_BUFFER_SIZE_COMPRESS; > - private byte[] cachedBuffer; > > private CompressTool() { > // don't allow construction > @@ -77,7 +74,7 @@ > algorithm = "NO"; > } > Compressor compress = getCompressor(algorithm); > - byte[] buff = getBuffer((len < 100 ? len + 100 : len) * 2); > + byte[] buff = MemoryUtils.newBytes((len < 100 ? len + 100 : > len) * 2); > int newLen = compress(in, in.length, compress, buff); > byte[] out = MemoryUtils.newBytes(newLen); > System.arraycopy(buff, 0, out, 0, newLen); > @@ -87,7 +84,7 @@ > /** > * INTERNAL > */ > - public synchronized int compress(byte[] in, int len, Compressor > compress, byte[] out) { > + public int compress(byte[] in, int len, Compressor compress, byte > [] out) { > int newLen = 0; > out[0] = (byte) compress.getAlgorithm(); > int start = 1 + writeInt(out, 1, len); > > -- > > You received this message because you are subscribed to the Google Groups "H2 > Database" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/h2-database?hl=en. > > > -- You received this message because you are subscribed to the Google Groups "H2 Database" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/h2-database?hl=en.
