Update of /cvsroot/monetdb/pathfinder/runtime
In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv6899
Modified Files:
Tag: XQuery_0-20
pf_support.mx
Log Message:
Another off-by-one error.
This was a bit harder to fix: in order to avoid touching non-existing
data (data beyond the end of the document which may well be on the
next page), I had to do some rewriting.
Also avoid the use of single quotes in comments (in my code anyway)
since my Mx mode gets confused by these.
This fixes bug 1854215.
Index: pf_support.mx
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/runtime/pf_support.mx,v
retrieving revision 1.267.2.5
retrieving revision 1.267.2.6
diff -u -d -r1.267.2.5 -r1.267.2.6
--- pf_support.mx 21 Dec 2007 12:32:28 -0000 1.267.2.5
+++ pf_support.mx 3 Jan 2008 15:39:54 -0000 1.267.2.6
@@ -3429,7 +3429,7 @@
var insertcont := batcont.fetch(idx);
var insertitem := $t;
- if (not(isnil(ws.fetch(PRE_KIND).find(insertcont).find(insertitem)))) {
# don't insert holes
+ if (not(isnil(ws.fetch(PRE_KIND).find(insertcont).find(insertitem)))) {
# do not insert holes
# insertsize - size of item to be inserted
# doccont - container of document-to-be-modified
var insertsize := ws.fetch(PRE_SIZE).find(insertcont).find(insertitem)
+ 1;
@@ -3517,21 +3517,14 @@
var docinsertbefore_newpre := oid(lng(docinsertafter_newpre) + 1);
var docinsertbefore_rid := antiswizzle(docinsertbefore_newpre,
map_pid_update);
- # the start of the page on which the new element is to be inserted
- var pageno := oid(lng(docinsertbefore_newpre) >> REMAP_PAGE_BITS);
- # the physical page id
- var pageid := map_pid_update.reverse().find(pageno);
- # the rid of the first element on the page
- var pagebase := oid(lng(pageid) << REMAP_PAGE_BITS);
- var pagelast := oid(lng(pagebase) + REMAP_PAGE_MASK);
- var isoldpage := false;
- if (map_pid.exist(pageid)) {
- isoldpage := not(isnil(map_pid.find(pageid)));
- }
-
if (docinsertcmd = lng(UPDATE_REPLACECONTENT)) {
var size;
extend_protect(ws, doccont);
+ var pageid := oid(lng(docinsertbefore_rid) >> REMAP_PAGE_BITS);
+ var isoldpage := false;
+ if (map_pid.exist(pageid)) {
+ isoldpage := not(isnil(map_pid.find(pageid)));
+ }
if (isoldpage) {
if (rid_size_update.exist(docinsertafter_rid)) {
size := rid_size_update.find(docinsertafter_rid);
@@ -3575,53 +3568,70 @@
# figure out the number of holes on the page on which the new
# element is to be inserted (we use the PRE_KIND table for this,
# holes are indicated with NIL)
- var rid_kind_page;
- if (isoldpage) {
- rid_kind_page := pre_kind.reverse().select(swizzle(pagebase,
map_pid), swizzle(pagelast, map_pid)).reverse().seqbase(pagebase);
- var rid_kind_page_update :=
rid_kind_update.reverse().select(pagebase, pagelast).reverse();
- rid_kind_page :=
rid_kind_page.copy().access(BAT_WRITE).key(true).myupdate(rid_kind_page_update);
- # record that this page gets changed (new pages don't need to be
recorded)
- ws.fetch(MODIFIED_PAGE).insert(doccont, pageid);
- } else {
- rid_kind_page := rid_kind.reverse().select(pagebase,
pagelast).reverse();
- }
- var holeatend; # size of hole at end of page
- {
- var rid_kind_page_used := rid_kind_page.tmark([EMAIL
PROTECTED]).uselect(chr_nil, chr_nil);
- if (rid_kind_page_used.count() > 0) {
- holeatend := int(REMAP_PAGE_MASK -
lng(max(reverse(rid_kind_page_used))));
+ var holeatend := 0; # size of hole at end of page
+ var holeatstart := 0; # size of hole at start of next page
+ if (int(docinsertbefore_newpre) < docsize) {
+ var rid_kind_page;
+ # the start of the page on which the new element is to be inserted
(the page exists)
+ var pageno := oid(lng(docinsertbefore_newpre) >> REMAP_PAGE_BITS);
+ # the physical page id
+ var pageid := map_pid_update.reverse().find(pageno);
+ # the rid of the first element on the page
+ var pagebase := oid(lng(pageid) << REMAP_PAGE_BITS);
+ var pagelast := oid(lng(pagebase) + REMAP_PAGE_MASK);
+ var isoldpage := false;
+ if (map_pid.exist(pageid)) {
+ isoldpage := not(isnil(map_pid.find(pageid)));
+ }
+
+ if (isoldpage) {
+ rid_kind_page := pre_kind.reverse().select(swizzle(pagebase,
map_pid), swizzle(pagelast, map_pid)).reverse().seqbase(pagebase);
+ var rid_kind_page_update :=
rid_kind_update.reverse().select(pagebase, pagelast).reverse();
+ rid_kind_page :=
rid_kind_page.copy().access(BAT_WRITE).key(true).myupdate(rid_kind_page_update);
+ # record that this page gets changed (new pages do not need to
be recorded)
+ ws.fetch(MODIFIED_PAGE).insert(doccont, pageid);
} else {
- holeatend := int(REMAP_PAGE_SIZE);
+ rid_kind_page := rid_kind.reverse().select(pagebase,
pagelast).reverse();
}
- }
- var holeatstart := 0;
- # if we're inserting at the position of the hole at the end
- # of the page and there's not enough space, also look at any
- # hole at the start of the next
- if ((((int(docinsertbefore_rid) + holeatend) and REMAP_PAGE_BITS) =
0) and (insertsize > holeatend)) {
- # not enough space on the current page, see if there is space at
the
- # start of the next
- var nxtpgno := oid(lng(pageno) + 1);
- if ((int(nxtpgno) << REMAP_PAGE_BITS) < docsize) {
- var nxtpgid := map_pid_update.reverse().find(nxtpgno);
- var nxtisoldpg := false;
- if (map_pid.exist(nxtpgid)) {
- nxtisoldpg := not(isnil(map_pid.find(nxtpgid)));
+ {
+ var rid_kind_page_used := rid_kind_page.tmark([EMAIL
PROTECTED]).uselect(chr_nil, chr_nil);
+ if (rid_kind_page_used.count() > 0) {
+ holeatend := int(REMAP_PAGE_MASK -
lng(max(reverse(rid_kind_page_used))));
+ } else {
+ holeatend := int(REMAP_PAGE_SIZE);
}
- var sz;
- if (nxtisoldpg) {
- if (rid_size_update.exist(oid(lng(nxtpgid) <<
REMAP_PAGE_BITS))) {
- sz := rid_size_update.find(oid(lng(nxtpgid) <<
REMAP_PAGE_BITS));
+ }
+ # if we are inserting at the position of the hole at the end
+ # of the page and there is not enough space, also look at any
+ # hole at the start of the next
+ if ((((int(docinsertbefore_rid) + holeatend) and REMAP_PAGE_BITS)
= 0) and (insertsize > holeatend)) {
+ # not enough space on the current page, see if there is space at
the
+ # start of the next
+ var nxtpgno := oid(lng(pageno) + 1);
+ if ((int(nxtpgno) << REMAP_PAGE_BITS) < docsize) {
+ var nxtpgid := map_pid_update.reverse().find(nxtpgno);
+ var nxtisoldpg := false;
+ if (map_pid.exist(nxtpgid)) {
+ nxtisoldpg := not(isnil(map_pid.find(nxtpgid)));
+ }
+ var sz;
+ if (nxtisoldpg) {
+ if (rid_size_update.exist(oid(lng(nxtpgid) <<
REMAP_PAGE_BITS))) {
+ sz := rid_size_update.find(oid(lng(nxtpgid) <<
REMAP_PAGE_BITS));
+ } else {
+ sz := pre_size.find(oid(lng(nxtpgno) << REMAP_PAGE_BITS));
+ }
} else {
- sz := pre_size.find(oid(lng(nxtpgno) << REMAP_PAGE_BITS));
+ sz := rid_size.find(oid(lng(nxtpgid) << REMAP_PAGE_BITS));
+ }
+ if (isnil(niland(sz, int_nil))) {
+ holeatstart := niland(sz, INT_MAX) + 1;
}
- } else {
- sz := rid_size.find(oid(lng(nxtpgid) << REMAP_PAGE_BITS));
- }
- if (isnil(niland(sz, int_nil))) {
- holeatstart := niland(sz, INT_MAX) + 1;
}
}
+ } else if (int(docinsertbefore_newpre) = docsize) {
+ # special case: insert at end of document, so the hole is the rest
of the page
+ holeatend := int((REMAP_PAGE_SIZE - (lng(docsize) and
REMAP_PAGE_MASK)) and REMAP_PAGE_MASK);
}
if (insertsize > holeatend + holeatstart) {
# not enough space on the current page and the start of the next
page
@@ -3632,7 +3642,7 @@
# number of new pages needed (we need to insert insertsize, we
# have holeatend available; round up to whole number of pages)
var npages := ((insertsize - holeatend) + int(REMAP_PAGE_MASK)) >>
REMAP_PAGE_BITS;
- # the size of the hole we're going to insert
+ # the size of the hole we are going to insert
# we move the bit after the insert point to the last inserted page
var shiftsize := npages << REMAP_PAGE_BITS;
@@ -3646,6 +3656,20 @@
}
new_page.insert(newpages.reverse().project(doccont).reverse());
var cpstart_rid, cpsize, cpwhere_rid, newholeatend;
+ # insert new pages before current if there is no hole at
+ # the end, we need to insert into the first half of the
+ # page, and we are not inserting on the first page
+ var pageno := oid(lng(docinsertbefore_newpre) >> REMAP_PAGE_BITS);
+ var isoldpage := false;
+ # the physical page id
+ var pageid;
+ if (int(docinsertbefore_newpre) < docsize) {
+ # inserting into existing page, figure out whether it is an old
one
+ pageid := map_pid_update.reverse().find(pageno);
+ if (map_pid.exist(pageid)) {
+ isoldpage := not(isnil(map_pid.find(pageid)));
+ }
+ }
if ((holeatend = 0) and (datasize > int(REMAP_PAGE_SIZE / 2)) and
(pageno > [EMAIL PROTECTED])) {
# insert new pages before current
newpages := newpages.seqbase(pageno);
@@ -3654,8 +3678,14 @@
docinsertafter_rid := antiswizzle(docinsertafter_newpre,
map_pid_update);
docinsertbefore_rid := antiswizzle(docinsertbefore_newpre,
map_pid_update);
# we need to copy the initial part of the current page to the
first new page
- cpstart_rid := oid(lng(pageid) << REMAP_PAGE_BITS);
- cpsize := int(REMAP_PAGE_SIZE) - datasize;
+ if (int(docinsertbefore_newpre) < docsize) {
+ cpstart_rid := oid(lng(pageid) << REMAP_PAGE_BITS);
+ cpsize := int(REMAP_PAGE_SIZE) - datasize;
+ } else {
+ # we are adding to the end of the document: nothing to copy
+ cpstart_rid := [EMAIL PROTECTED];
+ cpsize := 0;
+ }
cpwhere_rid := oid(lng(newpages.fetch(0)) << REMAP_PAGE_BITS);
newholeatend := holeatend;
} else {
@@ -3677,7 +3707,7 @@
}
if (cpwhere_rid > pgstart) {
- # fix up hole at start of last page since it doesn't
+ # fix up hole at start of last page since it does not
# extend to the end of the page anymore (this will be
# overwritten again)
extend_protect(ws, doccont);
@@ -3770,14 +3800,14 @@
}
}
- # We've inserted new pages and copied the data on the rest
+ # We have inserted new pages and copied the data on the rest
# of the page to the last inserted page. Now increase the
# sizes of all ancestors. Note that no holes can cross the
# insert point (docinsertafter_newpre points to a non-hole
# element)
# Note, that even though the sizes of the moved data are not
# yet consistent with the new situation, that is not a
- # problem, since we're only looking at sizes of data before
+ # problem, since we are only looking at sizes of data before
# the insertion point.
var ancestors_oldpre := new(void,oid).seqbase([EMAIL
PROTECTED]).append([EMAIL
PROTECTED]).append(ll_ancestor_or_self(new(void,oid).seqbase([EMAIL
PROTECTED]).append([EMAIL PROTECTED]), new(void,oid).seqbase([EMAIL
PROTECTED]).append(docinsertafter_oldpre), pre_size, pre_level));
var ancestors_nid := ancestors_oldpre.join(pre_nid);
@@ -3819,13 +3849,6 @@
}
# register which ancestors are being changed
ancestor_nid.insert(new_size.project(doccont).reverse().join(ancestors_nid));
-
- # recalculate isoldpage (and pageid) after having inserted the new
pages
- pageid := map_pid_update.reverse().find(pageno);
- isoldpage := false;
- if (map_pid.exist(pageid)) {
- isoldpage := not(isnil(map_pid.find(pageid)));
- }
} else {
# the inserted data fits on the current page but we may have to
# move data around to make a hole big ineough in the right place
@@ -3835,10 +3858,26 @@
{
var rid := docinsertbefore_rid;
var pre := docinsertbefore_newpre;
+ var pagelast := [EMAIL PROTECTED];
+ var isoldpage := false;
+ var loop := true;
if (int(pre) >= docsize) {
+ # note that the document cannot end at a page boundary
+ # (there would not be a hole to insert into, so we
+ # would not get here)
holesize := int(REMAP_PAGE_SIZE - (lng(docsize) and
REMAP_PAGE_MASK));
+ loop := false;
+ } else {
+ var pageno := oid(lng(docinsertbefore_newpre) >>
REMAP_PAGE_BITS);
+ # the physical page id
+ var pageid := map_pid_update.reverse().find(pageno);
+ # the rid of the first element on the page
+ var pagebase := oid(lng(pageid) << REMAP_PAGE_BITS);
+ pagelast := oid(lng(pagebase) + REMAP_PAGE_MASK);
+ if (map_pid.exist(pageid)) {
+ isoldpage := not(isnil(map_pid.find(pageid)));
+ }
}
- var loop := true;
while (loop and (int(pre) < docsize) and (rid <= pagelast)) {
var s := 0;
if (isoldpage) {
@@ -3854,7 +3893,7 @@
extend_unprotect(ws, doccont);
}
if (isnil(niland(s, int_nil))) {
- # we're looking at a hole
+ # we are looking at a hole
var h := niland(s, INT_MAX) + 1;
holesize :+= h;
pre := oid(lng(pre) + h);
@@ -3868,7 +3907,7 @@
holesize :+= (int(pagelast) - int(rid)) + 1;
}
}
- # note: holeatstart = 0 if the insert point isn't at the start of
the hole at the end of the page
+ # note: holeatstart = 0 if the insert point is not at the start of
the hole at the end of the page
if ((holesize + holeatstart) < insertsize) {
# not enough space in the right place
movedata(ws, doccont, oid(lng(docinsertbefore_newpre) +
holesize), int(REMAP_PAGE_SIZE - ((lng(docinsertbefore_newpre) and
REMAP_PAGE_MASK) + holesize + holeatend)), insertsize - holesize);
@@ -3956,7 +3995,7 @@
# if (debug) printf("leveldiff %d\n", leveldiff);
if (insert_pre_kind.find(insertitem) = TEXT) {
- # if we're inserting a text node, we may have to merge
+ # if we are inserting a text node, we may have to merge
# consecutive text nodes
# we remember the position in a hacky place
# note, insertsize == 1 in this case
@@ -3971,9 +4010,9 @@
while (insertsize > 0) {
# docinsertpoint_rid is the RID for the new data
var docinsertpoint_rid := antiswizzle(docinsertpoint,
map_pid_update);
- # recalculate isoldpage for this iteration
- pageid := oid(lng(docinsertpoint_rid) >> REMAP_PAGE_BITS);
- isoldpage := false;
+ # recalculate isoldpage for each iteration
+ var pageid := oid(lng(docinsertpoint_rid) >> REMAP_PAGE_BITS);
+ var isoldpage := false;
if (map_pid.exist(pageid)) {
isoldpage := not(isnil(map_pid.find(pageid)));
}
@@ -4185,8 +4224,8 @@
}
while (delsize >= 0) {
var rid := oid((lng(newpre) and REMAP_PAGE_MASK) or (lng(pageid) <<
REMAP_PAGE_BITS));
- var nsize; # new size we're going to write (may join with consecutive hole)
- var pgsize; # size of hole we're dealing with this iteration (does not
cross page boundary)
+ var nsize; # new size we are going to write (may join with consecutive
hole)
+ var pgsize; # size of hole we are dealing with this iteration (does not
cross page boundary)
if (oid(lng(newpre) + delsize) >= next_pagebase) {
# new hole extends into next page
nsize := (int(next_pagebase) - int(newpre)) - 1;
@@ -4241,7 +4280,7 @@
update_data := [swizzle](pre_nid.reverse().select(oldpre,
oid(lng(oldpre) + pgsize)), pid_map).hmark(rid);
update_data.access(BAT_WRITE).myupdate(rid_nid_update.reverse().select(rid,
oid(lng(rid) + pgsize)).reverse());
} else {
- # we're deleting a new node, so there is no data about it (or its
descendants) in pre_nid
+ # we are deleting a new node, so there is no data about it (or its
descendants) in pre_nid
update_data := rid_nid_update.reverse().select(rid, oid(lng(rid) +
pgsize)).reverse().sort();
}
} else {
@@ -4254,8 +4293,8 @@
# into NID_QN_{INS,DEL} tables for our convenience.
# Since previous work in this transaction may have added nodes we
# are going to delete, some of the nodes may already appear in
- # NID_QN_INS, so we need to remove them. That's easy, however, since
- # we can remove all entries that contain NIDs of nodes we're deleting.
+ # NID_QN_INS, so we need to remove them. That is easy, however, since
+ # we can remove all entries that contain NIDs of nodes we are deleting.
# Harder is figuring out which NID/QN combinations of original nodes
# are being deleted.
# Note that update_data contains RID/NID values of nodes being
@@ -4332,13 +4371,13 @@
var del_page := ws.fetch(DEL_PAGE);
del_page.insert(cont, pageid);
# use the *before* version of map_pid_update (not that this is
- # particularly important: we're dealing with ancestors which
+ # particularly important: we are dealing with ancestors which
# necessarily come before the to-be-deleted page)
var pid_map_update := map_pid_update.select(oid_nil,
oid_nil).reverse().sort().tmark([EMAIL PROTECTED]);
# now update map_pid_update
map_pid_update.replace([oid]([-]([int](map_pid_update.select(pageno,
oid_nil, false, true)), 1)), true);
map_pid_update.replace(pageid, oid_nil, true);
- # figure out which ancestors' sizes need to adjusted
+ # figure out which ancestor sizes need to adjusted
var ancestors_newrid := [swizzle](ancestors_newpre, pid_map_update);
var ancestors_isnewpage :=
[isnil](outerjoin([oid]([>>]([lng](ancestors_newrid), REMAP_PAGE_BITS)),
map_pid));
var ancestors_nid;
@@ -4520,7 +4559,7 @@
var rid_nid := ws.fetch(_RID_NID).find(cont);
var rid_nid_update := ws.fetch(RID_NID_UPDATE).find(cont);
- # record where we're deleting a node
+ # record where we are deleting a node
{
var pid_map_update := map_pid_update.select(oid_nil,
oid_nil).reverse().sort().tmark([EMAIL PROTECTED]);
var docsize; # current size of document
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Monetdb-pf-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-pf-checkins