Issue 8221 - getting MDB_PAGE_FULL using mdb_cursor_del
Summary: getting MDB_PAGE_FULL using mdb_cursor_del
Status: VERIFIED FIXED
Alias: None
Product: OpenLDAP
Classification: Unclassified
Component: slapd (show other issues)
Version: unspecified
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: OpenLDAP project
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-08-25 07:01 UTC by sergej.jurecko@gmail.com
Modified: 2015-11-30 18:26 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description sergej.jurecko@gmail.com 2015-08-25 07:01:48 UTC
Full_Name: Sergej Jurečko
Version: lmdb 0.9.16
OS: osx
URL: ftp://ftp.openldap.org/incoming/delerror.zip
Submission from: (NULL) (193.189.172.218)


Code and lmdb file is uploaded to ftp. Code is also here:
https://gist.github.com/SergejJurecko/68979ff6460806581ad5

If you run the code on the uploaded lmdb file, it will result in MDB_PAGE_FULL
error out of mdb_cursor_del. 

I use dupsorts a lot in my app. Every value in the dupsort has 2 64bit integers
and 1 u8 in the beginning, which are used in the custom comparison function to
sort the values. 

During normal operation values are added to the end of the dupsort and
eventually a cleanup operation occurs that deletes unused values. 

The example app tries to delete the first value in the dupsort. But it will fail
the same if it tries to delete the next one instead. 
Comment 1 Howard Chu 2015-09-26 15:35:47 UTC
sergej.jurecko@gmail.com wrote:
> Full_Name: Sergej Jurečko
> Version: lmdb 0.9.16
> OS: osx
> URL: ftp://ftp.openldap.org/incoming/delerror.zip
> Submission from: (NULL) (193.189.172.218)
>
>
> Code and lmdb file is uploaded to ftp. Code is also here:
> https://gist.github.com/SergejJurecko/68979ff6460806581ad5
>
> If you run the code on the uploaded lmdb file, it will result in MDB_PAGE_FULL
> error out of mdb_cursor_del.
>
> I use dupsorts a lot in my app. Every value in the dupsort has 2 64bit integers
> and 1 u8 in the beginning, which are used in the custom comparison function to
> sort the values.
>
> During normal operation values are added to the end of the dupsort and
> eventually a cleanup operation occurs that deletes unused values.
>
> The example app tries to delete the first value in the dupsort. But it will fail
> the same if it tries to delete the next one instead.

Thanks for the code and data, it shows the problem pretty clearly. 
Unfortunately the solution is less obvious at the moment, still working on it.

The situation is this: deleting the record causes the leaf page to become too 
empty, so it gets merged with a neighboring page - this is no problem. The 
merge causes its parent branch page to also become too empty, so that is also 
merged with a neighboring branch page. This is where the problem arises:

In a branch page, the key for slot 0 is always empty - it's never stored. So 
we have two branch pages, each with two nodes, and node 0 of each is 
essentially zero length. But when merging, we need to store a valid key.
We go from
   page 1, slot 0; page 1, slot 1;  and page 2, slot 0; page 2, slot 1
to
   page 1, slot 0, slot 1, slot 2, slot 3

In this case, we have to retrieve the key corresponding to page 2 slot 0 and 
store it in page 1 slot 2. In this DB this key is very large, and storing it 
leaves no room for the last key in slot 3.





-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 2 Howard Chu 2015-09-26 15:52:15 UTC
hyc@symas.com wrote:
> sergej.jurecko@gmail.com wrote:
>> Full_Name: Sergej Jurečko
>> Version: lmdb 0.9.16
>> OS: osx
>> URL: ftp://ftp.openldap.org/incoming/delerror.zip
>> Submission from: (NULL) (193.189.172.218)
>>
>>
>> Code and lmdb file is uploaded to ftp. Code is also here:
>> https://gist.github.com/SergejJurecko/68979ff6460806581ad5
>>
>> If you run the code on the uploaded lmdb file, it will result in MDB_PAGE_FULL
>> error out of mdb_cursor_del.
>>
>> I use dupsorts a lot in my app. Every value in the dupsort has 2 64bit integers
>> and 1 u8 in the beginning, which are used in the custom comparison function to
>> sort the values.
>>
>> During normal operation values are added to the end of the dupsort and
>> eventually a cleanup operation occurs that deletes unused values.
>>
>> The example app tries to delete the first value in the dupsort. But it will fail
>> the same if it tries to delete the next one instead.
>
> Thanks for the code and data, it shows the problem pretty clearly.
> Unfortunately the solution is less obvious at the moment, still working on it.

Fixed now in mdb.master, please test and followup with results. Thanks.

-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 3 OpenLDAP project 2015-09-26 15:52:40 UTC
fixed in mdb.master
Comment 4 Howard Chu 2015-09-26 15:52:40 UTC
changed notes
changed state Open to Test
moved from Incoming to Software Bugs
Comment 5 sergej.jurecko@gmail.com 2015-09-26 17:51:55 UTC
> Fixed now in mdb.master, please test and followup with results. Thanks.


Yes this fixed it. Thank you.


Sergej


Comment 6 Quanah Gibson-Mount 2015-11-30 18:26:54 UTC
changed state Test to Closed