I'm glad to be able to help you stabilize MVStore!  writeDelay(-1) fixed 
the IllegalStateException (and slow memory leak), but even with the 
h2-latest.jar I still have the original BufferOverflowException, plus a new 
NPE that I had not seen yet (both stack's below):

I found that I'm getting the exception with one entity based on data 
anomaly with 84K+ relationships in one file (I was never expecting more 
than a few hundred), so I'm trying to store a map with 84K entries as a 
value and eventually it fails.  So I thought that would be fairly easy to 
test with a unit test, but I tried a few things and can't seem to replicate.

So, now that I have checked out the code, I instrumented 
ObjectDataType.SerializedObjectType.write(ByteBuffer buff, Object obj) like 
this to better capture the state:

        @Override
>         public ByteBuffer write(ByteBuffer buff, Object obj) {
>             DataType t = getType(obj);
>             if (t != this) {
>                 return t.write(buff, obj);
>             }
>             buff.put((byte) TYPE_SERIALIZED_OBJECT);
>             byte[] data = serialize(obj);
>             DataUtils.writeVarInt(buff, data.length);
>             int prevbuffremain = buff.remaining();
>             buff = DataUtils.ensureCapacity(buff, data.length);
>             try {
>             buff.put(data);
>             } catch (BufferOverflowException ex) {
>             if (obj instanceof Map) {
>             System.err.println("map.size: " + ((Map) obj).size());
>             }
>             System.err.println("data.length: " + data.length);
>             System.err.println("buff.limit:" + buff.limit());
>             System.err.println("buff.pos:" +buff.position());
>             System.err.println("buff.capacity: " +buff.capacity());
>             System.err.println("buff.remain: " + buff.remaining());
>             System.err.println("buff.prevbuffremain: " + prevbuffremain);
>             ex.printStackTrace();
>             }
>             return buff;
>         }


Then ran my app and after about 7 million rows processed it finally failed 
with this:

map.size: 84083
> data.length: *3424297*
> buff.limit:4752468
> buff.pos:2329143
> buff.capacity: 4752468
> buff.remain: *2423325*
> buff.prevbuffremain: 47091
> java.nio.BufferOverflowException
> at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:183)
> at java.nio.ByteBuffer.put(ByteBuffer.java:832)
> at 
> org.h2.mvstore.type.ObjectDataType$SerializedObjectType.write(ObjectDataType.java:1519)
> at org.h2.mvstore.type.ObjectDataType.write(ObjectDataType.java:115)
> at org.h2.mvstore.Page.write(Page.java:801)
> at org.h2.mvstore.Page.writeUnsavedRecursive(Page.java:862)
> at org.h2.mvstore.Page.writeUnsavedRecursive(Page.java:857)
> at org.h2.mvstore.Page.writeUnsavedRecursive(Page.java:857)
> at org.h2.mvstore.Page.writeUnsavedRecursive(Page.java:857)
> at org.h2.mvstore.MVStore.storeNow(MVStore.java:903)
> at org.h2.mvstore.MVStore.store(MVStore.java:822)
> at org.h2.mvstore.MVStore.store(MVStore.java:791)


So it looks like DataUtils.ensureCapacity() isn't making a large enough 
ByteBuffer?  But its under some strange circumstance that I can't seem to 
isolate.  I also tried switching from Map values to StringBuilder values 
and got the same result, with a large serialized object value, it seems to 
fail to expand the ByteBuffer large enough sometimes.

As a side node, at one point I also got this NPE, but only once, I couldn't 
get it to happen again:

Caused by: java.lang.NullPointerException
>         at 
> org.h2.mvstore.cache.CacheLongKeyLIRS$Segment.pruneStack(CacheLongKeyLIRS.java:824)
>         at 
> org.h2.mvstore.cache.CacheLongKeyLIRS$Segment.convertOldestHotToCold(CacheLongKeyLIRS.java:815)
>         at 
> org.h2.mvstore.cache.CacheLongKeyLIRS$Segment.evict(CacheLongKeyLIRS.java:783)
>         at 
> org.h2.mvstore.cache.CacheLongKeyLIRS$Segment.put(CacheLongKeyLIRS.java:711)
>         at 
> org.h2.mvstore.cache.CacheLongKeyLIRS.put(CacheLongKeyLIRS.java:162)
>         at org.h2.mvstore.MVStore.readPage(MVStore.java:1443)
>         at org.h2.mvstore.MVMap.readPage(MVMap.java:759)
>         at org.h2.mvstore.Page.getChildPage(Page.java:207)
>         at org.h2.mvstore.MVMap.binarySearch(MVMap.java:449)
>         at org.h2.mvstore.MVMap.binarySearch(MVMap.java:450)
>         at org.h2.mvstore.MVMap.binarySearch(MVMap.java:450)
>         at org.h2.mvstore.MVMap.get(MVMap.java:431)


Hope this helps,
Brian

On Thursday, October 10, 2013 3:10:21 AM UTC-6, Thomas Mueller wrote:
>
> Hi,
>
> Thanks a lot for the great test case! I think I found the problem, but 
> couldn't fix it yet. It is a concurrency problem. By default, the MVStore 
> now stores changes in a background thread. This background writing thread 
> conflicts with the main thread. Concurrency problems are always hard to 
> test... I'm thinking about how to ensure things like this can't happen.
>
> Anyway, for your use case, the solution is quite easy: disable the 
> background thread. You don't need it, as you call store yourself. To do 
> that, use a write delay of -1:
>
>         MVStore mvstore = new MVStore.Builder().
>              writeBufferSize(25).
>              writeDelay(-1).
>              fileName(fileName).
>              cacheSize(100).
>              open();
>
> Regards,
> Thomas
>
>
> On Thu, Oct 10, 2013 at 3:16 AM, Brian Bray <[email protected]<javascript:>
> > wrote:
>
>> I was able to boil my stuff down quite a bit by focusing on the 
>> troublemaker portion. See attached unit test.  Using h2-latest.jar, I seem 
>> to get the IllegalStateException ("negative position exception") after 2-5 
>> minutes of letting this run.  Using h2-1.3.173-release, after 5-6 minutes I 
>> see the classic signs of a memory leak in jvisualvm (I didn't wait long 
>> enough for a OutOfMemoryError).
>>
>> I've tinkered with a bunch of different aspects of this:
>> - writeBufferSize()
>> - w/ and wo/ mvstore.store() calls every 25k records.
>> - various cache sizes
>> - store-per-map instead of storing all maps in 1 store/file.
>> - Tried different data types in mrrels MVMap (string[], List<String>, 
>> Map<String,String>)
>>
>> I realize this test may look a little strange, but there is a lot more 
>> going on in my real tool and this is representative how it works and the 
>> strange data I'm working with. 
>>
>> It seems like my issue is in the second loop, where I'm interspersing 
>> lots of .get()'s from 1 map and .put()'s to another.
>>
>> Thanks for your help,
>> Brian
>>
>>
>> On Wednesday, October 9, 2013 5:05:38 PM UTC-6, Thomas Mueller wrote:
>>
>>> Hi,
>>>
>>> I'm sorry I can't say what the problem is. It kind of looks like it's 
>>> trying to read from a chunk while the chunk is not yet written. But I would 
>>> need to know what your are doing exactly.
>>>
>>> - Did you start with a new file?
>>> - How large is the file when the problem occurs?
>>> - How do you open the MVStore?
>>> - How to you process the data (concurrently, when do you call commit, do 
>>> you call save yourself and if yes when,...)? 
>>> - How large is a typical record?
>>> - What data types do you use?
>>>
>>> Regards,
>>> Thomas
>>>
>>>
>>>
>>> On Wed, Oct 9, 2013 at 11:41 PM, Brian Bray <[email protected]> wrote:
>>>
>>>> Thanks Thomas!  So I switched to h2-latest.jar and it fails sooner with 
>>>> an IllegalStateException:
>>>>
>>>> Caused by: java.lang.**IllegalStateException: Negative position 
>>>> -9223372036854646992 [1.3.173/6]
>>>>         at org.h2.mvstore.DataUtils.**newIllegalStateException(**
>>>> DataUtils.java:709)
>>>>         at org.h2.mvstore.MVStore.**readPage(MVStore.java:1439)
>>>>         at org.h2.mvstore.MVMap.readPage(**MVMap.java:759)
>>>>         at org.h2.mvstore.Page.**getChildPage(Page.java:207)
>>>>         at org.h2.mvstore.MVMap.**binarySearch(MVMap.java:449)
>>>>         at org.h2.mvstore.MVMap.**binarySearch(MVMap.java:450)
>>>>         at org.h2.mvstore.MVMap.get(**MVMap.java:431)
>>>>
>>>> Here is whats odd though, I basically have 3 large CSV files I'm 
>>>> parsing right now (#1=500MB/4M rows, #2=2.2GB/26M rows, #3=1.3GB/15M 
>>>> rows), 
>>>> it makes it through the first 2 fine, then I get the above exception about 
>>>> 100k rows into file #3. 
>>>>
>>>> File #3 was also the only file failing with the previously mentioned 
>>>> BufferOverflowException in 1.3.173-release (it also seemed to have a slow 
>>>> memory leak), So I'm wondering if I have some weird data in file #3 that 
>>>> is 
>>>> causing issues?  Again, it might be difficult to extract a unit test out 
>>>> of 
>>>> this, but focusing on replicating file #3 might make it a bit easier.
>>>>
>>>> Brian
>>>>
>>>> On Wednesday, October 9, 2013 1:00:32 PM UTC-6, Thomas Mueller wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> We fixed quite a number of bugs in the MVStore recently. I suggest to 
>>>>> try again with the nightly build at http://h2database.com/html/**bui**
>>>>> ld.html#automated <http://h2database.com/html/build.html#automated> - 
>>>>> direct link 
>>>>> http://www.h2database.**com**/automated/h2-latest.jar<http://www.h2database.com/automated/h2-latest.jar>-
>>>>>  or of course you could build it yourself.
>>>>>
>>>>> > I'm currently using MVStore as a large, temporary disk cache
>>>>>
>>>>> Noel and me recently implemented an off-heap storage for the MVStore, 
>>>>> so it's using memory (not disk) outside the normal Java heap. This might 
>>>>> be 
>>>>> interesting for you. The documentation is not online yet (as it's not 
>>>>> released yet), it is only available in source form yet at 
>>>>> https://h2database.**googleco**de.com/svn/trunk/h2/**src/**
>>>>> docsrc/html/mvstore.html<https://h2database.googlecode.com/svn/trunk/h2/src/docsrc/html/mvstore.html>(see
>>>>>  'off-heap'). To use it, call:
>>>>>
>>>>> OffHeapStore offHeap = new OffHeapStore();
>>>>> MVStore s = new MVStore.Builder().
>>>>>         fileStore(offHeap).open();
>>>>>
>>>>> I'm also thinking about combining the LIRS cache with the MVStore, so 
>>>>> that you could build an off-heap LIRS cache. It shouldn't be complicated 
>>>>> to 
>>>>> implement (the cache would simply needs a map factory).
>>>>> Regards,
>>>>> Thomas
>>>>>
>>>>>
>>>>>
>>>>> On Wed, Oct 9, 2013 at 7:52 PM, Brian Bray <[email protected]> wrote:
>>>>>
>>>>>> Thomas,
>>>>>>
>>>>>> Here is a more elusive issue that I'm wondering if its a bug in 
>>>>>> MVMap/MVStore.  
>>>>>>
>>>>>> I'm currently using MVStore as a large, temporary disk cache, I have 
>>>>>> a java program that scans about 10GB of raw CSV-ish files, and for each 
>>>>>> file, plucks out a few fields I care about and stores it in a MVMap. At 
>>>>>> the 
>>>>>> end, I merge the data from several MVMaps into a small JSON document 
>>>>>> which 
>>>>>> represents all the data buried in the CSV files for a particular entity. 
>>>>>>  I 
>>>>>> then store that JSON document in H2 for my app to use.
>>>>>>
>>>>>> Its been working fairly well (and fast!), but there is one weird 
>>>>>> issue I'm encountering, that throws the exception below after 6-8M rows 
>>>>>> have been processed. Its going to be tough to extrapolate a test case, I 
>>>>>> was wondering if you had any insight into this?  It seems to go away 
>>>>>> when I 
>>>>>> shorten some key sizes, but I don't know if I'm just delaying the 
>>>>>> problem 
>>>>>> and eventually this would still happen?
>>>>>>
>>>>>> I'm using 1.3.173, basically every 50k records or so I call 
>>>>>> MVstore.store() to flush to disk and eventually its throwing this:
>>>>>>
>>>>>> Caused by: java.nio.**BufferOverflowExcepti**on
>>>>>>         at java.nio.HeapByteBuffer.put(**He**apByteBuffer.java:183)
>>>>>>         at java.nio.ByteBuffer.put(**ByteBu**ffer.java:832)
>>>>>>         at org.h2.mvstore.type.**ObjectData**Type$**
>>>>>> SerializedObjectType.**write(**ObjectDataTpe.java:1515)
>>>>>>          at org.h2.mvstore.type.**ObjectData**Type.write(**
>>>>>> ObjectDataType.**java:113)
>>>>>>         at org.h2.mvstore.Page.write(**Page**.java:799)
>>>>>>         at org.h2.mvstore.Page.**writeUnsav**edRecursive(Page.**
>>>>>> java:860)
>>>>>>         at org.h2.mvstore.Page.**writeUnsav**edRecursive(Page.**
>>>>>> java:855)
>>>>>>         at org.h2.mvstore.Page.**writeUnsav**edRecursive(Page.**
>>>>>> java:855)
>>>>>>         at org.h2.mvstore.Page.**writeUnsav**edRecursive(Page.**
>>>>>> java:855)
>>>>>>         at org.h2.mvstore.MVStore.store(**M**VStore.java:921)
>>>>>>         at org.h2.mvstore.MVStore.store(**M**VStore.java:813)
>>>>>>
>>>>>> Thanks,
>>>>>> Brian
>>>>>>
>>>>>> -- 
>>>>>> 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 h2-database...@**googlegroups.**com.
>>>>>> To post to this group, send email to [email protected].
>>>>>>
>>>>>> Visit this group at 
>>>>>> http://groups.google.com/**group**/h2-database<http://groups.google.com/group/h2-database>
>>>>>> .
>>>>>> For more options, visit 
>>>>>> https://groups.google.com/**grou**ps/opt_out<https://groups.google.com/groups/opt_out>
>>>>>> .
>>>>>>
>>>>>
>>>>>  -- 
>>>> 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 h2-database...@**googlegroups.com.
>>>> To post to this group, send email to [email protected].
>>>> Visit this group at 
>>>> http://groups.google.com/**group/h2-database<http://groups.google.com/group/h2-database>
>>>> .
>>>> For more options, visit 
>>>> https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out>
>>>> .
>>>>
>>>
>>>  -- 
>> 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] <javascript:>.
>> To post to this group, send email to [email protected]<javascript:>
>> .
>> Visit this group at http://groups.google.com/group/h2-database.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>
>
>

-- 
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 post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/h2-database.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to