TtreePage.java :  » Database-DBMS » perst » org » garret » perst » impl » Java Open Source

Java Open Source » Database DBMS » perst 
perst » org » garret » perst » impl » TtreePage.java
package org.garret.perst.impl;

import org.garret.perst.*;
import java.util.ArrayList;

public class TtreePage extends Persistent  { 
    static final int maxItems = (Page.pageSize-ObjectHeader.sizeof-4*5)/4;
    static final int minItems = maxItems - 2; // minimal number of items in internal node

    TtreePage   left;
    TtreePage   right;
    int         balance;
    int         nItems;
    IPersistent item[];

    static class PageReference { 
        TtreePage pg;
        
        PageReference(TtreePage p) { pg = p; }
    }

    public boolean recursiveLoading() {
        return false;
    }

    TtreePage() {}

    TtreePage(IPersistent mbr) { 
        nItems = 1;
        item = new IPersistent[maxItems];
        item[0] = mbr;
    }

    final IPersistent loadItem(int i) 
    { 
        IPersistent mbr = item[i];
        mbr.load();
        return mbr;
    }

    final boolean find(PersistentComparator comparator, Object minValue, int minInclusive, 
                       Object maxValue, int maxInclusive, ArrayList selection)
    { 
        int l, r, m, n;
        load();
        n = nItems;
        if (minValue != null) { 
            if (-comparator.compareMemberWithKey(loadItem(0), minValue) >= minInclusive) {       
                if (-comparator.compareMemberWithKey(loadItem(n-1), minValue) >= minInclusive) { 
                    if (right != null) { 
                        return right.find(comparator, minValue, minInclusive, maxValue, maxInclusive, selection); 
                    } 
                    return true;
                }
                for (l = 0, r = n; l < r;) { 
                    m = (l + r) >> 1;
                    if (-comparator.compareMemberWithKey(loadItem(m), minValue) >= minInclusive) {
                        l = m+1;
                    } else { 
                        r = m;
                    }
                }
                while (r < n) { 
                    if (maxValue != null
                        && comparator.compareMemberWithKey(loadItem(r), maxValue) >= maxInclusive)
                    { 
                        return false;
                    }
                    selection.add(loadItem(r));
                    r += 1;
                }
                if (right != null) { 
                    return right.find(comparator, minValue, minInclusive, maxValue, maxInclusive, selection); 
                } 
                return true;    
            }
        }       
        if (left != null) { 
            if (!left.find(comparator, minValue, minInclusive, maxValue, maxInclusive, selection)) { 
                return false;
            }
        }
        for (l = 0; l < n; l++) { 
            if (maxValue != null && comparator.compareMemberWithKey(loadItem(l), maxValue) >= maxInclusive) {
                return false;
            }
            selection.add(loadItem(l));
        }
        if (right != null) { 
            return right.find(comparator, minValue, minInclusive, maxValue, maxInclusive, selection);
        }         
        return true;
    }
    
    final boolean contains(PersistentComparator comparator, IPersistent key)
    { 
        int l, r, m, n;
        load();
        n = nItems;
        if (comparator.compareMembers(loadItem(0), key) < 0) {      
            if (comparator.compareMembers(loadItem(n-1), key) < 0) { 
                if (right != null) { 
                    return right.contains(comparator, key); 
                } 
                return false;
            }
            for (l = 0, r = n; l < r;) { 
                m = (l + r) >> 1;
                if (comparator.compareMembers(loadItem(m), key) < 0) {
                    l = m+1;
                } else { 
                    r = m;
                }
            }
            while (r < n) { 
                if (key.equals(loadItem(r))) { 
                    return true;
                }
                if (comparator.compareMembers(item[r], key) > 0) { 
                    return false;
                }
                r += 1;
            }
            if (right != null) { 
                return right.contains(comparator, key); 
            } 
            return false;       
        }
        if (left != null) { 
            if (left.contains(comparator, key)) { 
                return true;
            }
        }
        for (l = 0; l < n; l++) { 
            if (key.equals(loadItem(l))) { 
                return true;
            }
            if (comparator.compareMembers(item[l], key) > 0) {
                return false;
            }
        }
        if (right != null) { 
            return right.contains(comparator, key);
        }         
        return false;
    }

    final boolean containsKey(PersistentComparator comparator, Object key)
    { 
        int l, r, m, n;
        load();
        n = nItems;
        if (comparator.compareMemberWithKey(loadItem(0), key) < 0) {      
            if (comparator.compareMemberWithKey(loadItem(n-1), key) < 0) { 
                if (right != null) { 
                    return right.containsKey(comparator, key); 
                } 
                return false;
            }
            for (l = 0, r = n; l < r;) { 
                m = (l + r) >> 1;
                if (comparator.compareMemberWithKey(loadItem(m), key) < 0) {
                    l = m+1;
                } else { 
                    r = m;
                }
            }
            while (r < n) { 
                int diff = comparator.compareMemberWithKey(loadItem(r), key);
                if (diff == 0) { 
                    return true;
                } else if (diff > 0) { 
                    return false;
                }
                r += 1;
            }
            if (right != null) { 
                return right.containsKey(comparator, key); 
            } 
            return false;       
        }
        if (left != null) { 
            if (left.containsKey(comparator, key)) { 
                return true;
            }
        }
        for (l = 0; l < n; l++) { 
            int diff = comparator.compareMemberWithKey(loadItem(l), key);
            if (diff == 0) { 
                return true;
            } else if (diff > 0) { 
                return false;
            }
        }
        if (right != null) { 
            return right.containsKey(comparator, key);
        }         
        return false;
    }

    final boolean containsObject(PersistentComparator comparator, IPersistent mbr)
    { 
        int l, r, m, n;
        load();
        n = nItems;
        if (comparator.compareMembers(loadItem(0), mbr) < 0) {      
            if (comparator.compareMembers(loadItem(n-1), mbr) < 0) { 
                if (right != null) { 
                    return right.containsObject(comparator, mbr); 
                } 
                return false;
            }
            for (l = 0, r = n; l < r;) { 
                m = (l + r) >> 1;
                if (comparator.compareMembers(loadItem(m), mbr) < 0) {
                    l = m+1;
                } else { 
                    r = m;
                }
            }
            while (r < n) { 
                if (mbr == item[r]) { 
                    return true;
                }
                if (comparator.compareMembers(item[r], mbr) > 0) { 
                    return false;
                }
                r += 1;
            }
            if (right != null) { 
                return right.containsObject(comparator, mbr); 
            } 
            return false;       
        }
        if (left != null) { 
            if (left.containsObject(comparator, mbr)) { 
                return true;
            }
        }
        for (l = 0; l < n; l++) { 
            if (mbr == item[l]) { 
                return true;
            }
            if (comparator.compareMembers(item[l], mbr) > 0) {
                return false;
            }
        }
        if (right != null) { 
            return right.containsObject(comparator, mbr);
        }         
        return false;
    }

    
    static final int OK         = 0;
    static final int NOT_UNIQUE = 1;
    static final int NOT_FOUND  = 2;
    static final int OVERFLOW   = 3;
    static final int UNDERFLOW  = 4;

    final int insert(PersistentComparator comparator, IPersistent mbr, boolean unique, PageReference ref) 
    { 
        load();
        int n = nItems;
        TtreePage pg;
        int diff = comparator.compareMembers(mbr, loadItem(0));
        if (diff <= 0) { 
            if (unique && diff == 0) { 
                return NOT_UNIQUE;
            }
            if ((left == null || diff == 0) && n != maxItems) { 
                modify();
                //for (int i = n; i > 0; i--) item[i] = item[i-1];
                System.arraycopy(item, 0, item, 1, n);
                item[0] = mbr;
                nItems += 1;
                return OK;
            } 
            if (left == null) { 
                modify();
                left = new TtreePage(mbr);
            } else {
                pg = ref.pg;
                ref.pg = left;
                int result = left.insert(comparator, mbr, unique, ref);
                if (result == NOT_UNIQUE) { 
                    return NOT_UNIQUE;
                }
                modify();
                left = ref.pg;
                ref.pg = pg;
                if (result == OK) return OK;
            }
            if (balance > 0) { 
                balance = 0;
                return OK;
            } else if (balance == 0) { 
                balance = -1;
                return OVERFLOW;
            } else { 
                TtreePage left = this.left;
                left.load();
                left.modify();
                if (left.balance < 0) { // single LL turn
                    this.left = left.right;
                    left.right = this;
                    balance = 0;
                    left.balance = 0;
                    ref.pg = left;
                } else { // double LR turn
                    TtreePage right = left.right;
                    right.load();
                    right.modify();
                    left.right = right.left;
                    right.left = left;
                    this.left = right.right;
                    right.right = this;
                    balance = (right.balance < 0) ? 1 : 0;
                    left.balance = (right.balance > 0) ? -1 : 0;
                    right.balance = 0;
                    ref.pg = right;
                }
                return OK;
            }
        } 
        diff = comparator.compareMembers(mbr, loadItem(n-1));
        if (diff >= 0) { 
            if (unique && diff == 0) { 
                return NOT_UNIQUE;
            }
            if ((right == null || diff == 0) && n != maxItems) { 
                modify();
                item[n] = mbr;
                nItems += 1;
                return OK;
            }
            if (right == null) { 
                 modify();
                 right = new TtreePage(mbr);
            } else { 
                pg = ref.pg;
                ref.pg = right;
                int result = right.insert(comparator, mbr, unique, ref);
                if (result == NOT_UNIQUE) { 
                    return NOT_UNIQUE;
                }
                modify();
                right = ref.pg;
                ref.pg = pg;
                if (result == OK) return OK;
            }
            if (balance < 0) { 
                balance = 0;
                return OK;
            } else if (balance == 0) { 
                balance = 1;
                return OVERFLOW;
            } else { 
                TtreePage right = this.right;
                right.load();
                right.modify();
                if (right.balance > 0) { // single RR turn
                    this.right = right.left;
                    right.left = this;
                    balance = 0;
                    right.balance = 0;
                    ref.pg = right;
                } else { // double RL turn
                    TtreePage left = right.left;
                    left.load();
                    left.modify();
                    right.left = left.right;
                    left.right = right;
                    this.right = left.left;
                    left.left = this;
                    balance = (left.balance > 0) ? -1 : 0;
                    right.balance = (left.balance < 0) ? 1 : 0;
                    left.balance = 0;
                    ref.pg = left;
                }
                return OK;
            }
        }
        int l = 1, r = n-1;
        while (l < r)  {
            int i = (l+r) >> 1;
            diff = comparator.compareMembers(mbr, loadItem(i));
            if (diff > 0) { 
                l = i + 1;
            } else { 
                r = i;
                if (diff == 0) { 
                    if (unique) { 
                        return NOT_UNIQUE;
                    }
                    break;
                }
            }
        }
        // Insert before item[r]
        modify();
        if (n != maxItems) {
            System.arraycopy(item, r, item, r+1, n-r);
            //for (int i = n; i > r; i--) item[i] = item[i-1]; 
            item[r] = mbr;
            nItems += 1;
            return OK;
        } else { 
            IPersistent reinsertItem;
            if (balance >= 0) { 
                reinsertItem = loadItem(0);
                System.arraycopy(item, 1, item, 0, r-1);
                //for (int i = 1; i < r; i++) item[i-1] = item[i]; 
                item[r-1] = mbr;
            } else { 
                reinsertItem = loadItem(n-1);
                System.arraycopy(item, r, item, r+1, n-r-1);
                //for (int i = n-1; i > r; i--) item[i] = item[i-1]; 
                item[r] = mbr;
            }
            return insert(comparator, reinsertItem, unique, ref);
        }
    }
       
    final int balanceLeftBranch(PageReference ref) 
    {
        if (balance < 0) { 
            balance = 0;
            return UNDERFLOW;
        } else if (balance == 0) { 
            balance = 1;
            return OK;
        } else { 
            TtreePage right = this.right;
            right.load();
            right.modify();
            if (right.balance >= 0) { // single RR turn
                this.right = right.left;
                right.left = this;
                if (right.balance == 0) { 
                    this.balance = 1;
                    right.balance = -1;
                    ref.pg = right;
                    return OK;
                } else { 
                    balance = 0;
                    right.balance = 0;
                    ref.pg = right;
                    return UNDERFLOW;
                }
            } else { // double RL turn
                TtreePage left = right.left;
                left.load();
                left.modify();
                right.left = left.right;
                left.right = right;
                this.right = left.left;
                left.left = this;
                balance = left.balance > 0 ? -1 : 0;
                right.balance = left.balance < 0 ? 1 : 0;
                left.balance = 0;
                ref.pg = left;
                return UNDERFLOW;
            }
        }
    }

    final int balanceRightBranch(PageReference ref) 
    {
        if (balance > 0) { 
            balance = 0;
            return UNDERFLOW;
        } else if (balance == 0) { 
            balance = -1;
            return OK;
        } else { 
            TtreePage left = this.left;
            left.load();
            left.modify();
            if (left.balance <= 0) { // single LL turn
                this.left = left.right;
                left.right = this;
                if (left.balance == 0) { 
                    balance = -1;
                    left.balance = 1;
                    ref.pg = left;
                    return OK;
                } else { 
                    balance = 0;
                    left.balance = 0;
                    ref.pg = left;
                    return UNDERFLOW;
                }
            } else { // double LR turn
                TtreePage right = left.right;
                right.load();
                right.modify();
                left.right = right.left;
                right.left = left;
                this.left = right.right;
                right.right = this;
                balance = right.balance < 0 ? 1 : 0;
                left.balance = right.balance > 0 ? -1 : 0;
                right.balance = 0;
                ref.pg = right;
                return UNDERFLOW;
            }
        }
    }
    
    final int remove(PersistentComparator comparator, IPersistent mbr, PageReference ref)
    {
        load();
        TtreePage pg;
        int n = nItems;
        int diff = comparator.compareMembers(mbr, loadItem(0));
        if (diff <= 0) { 
            if (left != null) { 
                modify();
                pg = ref.pg;
                ref.pg = left;
                int h = left.remove(comparator, mbr, ref);
                left = ref.pg;
                ref.pg = pg;
                if (h == UNDERFLOW) { 
                    return balanceLeftBranch(ref);
                } else if (h == OK) { 
                    return OK;
                }
            }
        }
        diff = comparator.compareMembers(mbr, loadItem(n-1));
        if (diff <= 0) {            
            for (int i = 0; i < n; i++) { 
                if (item[i] == mbr) { 
                    if (n == 1) { 
                        if (right == null) { 
                            deallocate();
                            ref.pg = left;
                            return UNDERFLOW;
                        } else if (left == null) { 
                            deallocate();
                            ref.pg = right;
                            return UNDERFLOW;
                        } 
                    }
                    modify();
                    if (n <= minItems) { 
                        if (left != null && balance <= 0) {  
                            TtreePage prev = left;
                            prev.load();
                            while (prev.right != null) {                                 
                                prev = prev.right;
                                prev.load();
                            }
                            System.arraycopy(item, 0, item, 1, i);
                            //while (--i >= 0) { 
                            //    item[i+1] = item[i];
                            //}
                            item[0] = prev.item[prev.nItems-1];
                            pg = ref.pg;
                            ref.pg = left;
                            int h = left.remove(comparator, loadItem(0), ref);
                            left = ref.pg;
                            ref.pg = pg;
                            if (h == UNDERFLOW) {
                                h = balanceLeftBranch(ref);
                            }
                            return h;
                        } else if (right != null) { 
                            TtreePage next = right;
                            next.load();
                            while (next.left != null) { 
                                next = next.left;
                                next.load();
                            }
                            System.arraycopy(item, i+1, item, i, n-i-1);
                            //while (++i < n) { 
                            //    item[i-1] = item[i];
                            //}
                            item[n-1] = next.item[0];
                            pg = ref.pg;
                            ref.pg = right;
                            int h = right.remove(comparator, loadItem(n-1), ref);
                            right = ref.pg;
                            ref.pg = pg;
                            if (h == UNDERFLOW) {
                                h = balanceRightBranch(ref);
                            }
                            return h;
                        }
                    }
                    System.arraycopy(item, i+1, item, i, n-i-1);
                    //while (++i < n) { 
                    //    item[i-1] = item[i];
                    //}
                    item[n-1] = null;
                    nItems -= 1;
                    return OK;
                }
            }
        }
        if (right != null) { 
            modify();
            pg = ref.pg;
            ref.pg = right;
            int h = right.remove(comparator, mbr, ref);
            right = ref.pg;
            ref.pg = pg;
            if (h == UNDERFLOW) { 
                return balanceRightBranch(ref);
            } else { 
                return h;
            }
        }
        return NOT_FOUND;
    }


    final int toArray(IPersistent[] arr, int index) { 
        load();
        if (left != null) { 
            index = left.toArray(arr, index);
        }
        for (int i = 0, n = nItems; i < n; i++) { 
            arr[index++] = loadItem(i);
        }
        if (right != null) { 
            index = right.toArray(arr, index);
        }
        return index;
    }

    final void prune() { 
        load();
        if (left != null) { 
            left.prune();
        }
        if (right != null) { 
            right.prune();
        }
        deallocate();
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.