Package org.exist.indexing.sort

Source Code of org.exist.indexing.sort.SortIndexWorker

package org.exist.indexing.sort;

import org.exist.EXistException;
import org.exist.collections.Collection;
import org.exist.dom.*;
import org.exist.indexing.IndexController;
import org.exist.indexing.IndexWorker;
import org.exist.indexing.MatchListener;
import org.exist.indexing.StreamListener;
import org.exist.storage.DBBroker;
import org.exist.storage.NodePath;
import org.exist.storage.btree.BTreeCallback;
import org.exist.storage.btree.BTreeException;
import org.exist.storage.btree.IndexQuery;
import org.exist.storage.btree.Value;
import org.exist.storage.lock.Lock;
import org.exist.util.*;
import org.exist.xquery.QueryRewriter;
import org.exist.xquery.TerminatedException;
import org.exist.xquery.XQueryContext;
import org.w3c.dom.NodeList;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class SortIndexWorker implements IndexWorker {

    private int mode = 0;
    private DocumentImpl document = null;
    private SortIndex index;

    public SortIndexWorker(SortIndex index) {
        this.index = index;
    }

    public void setDocument(DocumentImpl doc, int mode) {
        this.document = doc;
        this.mode = mode;
    }

    public void setMode(int mode) {
        this.mode = mode;
    }

    public String getIndexId() {
        return SortIndex.ID;
    }

    public String getIndexName() {
        return index.getIndexName();
    }

    @Override
    public QueryRewriter getQueryRewriter(XQueryContext context) {
        return null;
    }

    public void flush() {
        switch (mode) {
            case StreamListener.REMOVE_ALL_NODES:
                remove(document);
                break;
        }
    }

    /**
     * Create a new sort index identified by a name. The method iterates through all items in
     * the items list and adds the nodes to the index. It assumes that the list is already ordered.
     *
     * @param name the name by which the index will be identified
     * @param items ordered list of items to store
     *
     * @throws EXistException
     * @throws LockException
     */
    public void createIndex(String name, List<SortItem> items) throws EXistException, LockException {
        // get an id for the new index
        short id = getOrRegisterId(name);
        final Lock lock = index.btree.getLock();
        try {
            lock.acquire(Lock.WRITE_LOCK);
            long idx = 0;
            for (SortItem item : items) {
                byte[] key = computeKey(id, item.getNode());
                index.btree.addValue(new Value(key), idx++);
            }
        } catch (LockException e) {
            throw new EXistException("Exception caught while creating sort index: " + e.getMessage(), e);
        } catch (BTreeException e) {
            throw new EXistException("Exception caught while creating sort index: " + e.getMessage(), e);
        } catch (IOException e) {
            throw new EXistException("Exception caught while creating sort index: " + e.getMessage(), e);
        } finally {
            lock.release(Lock.WRITE_LOCK);
        }
    }

    public boolean hasIndex(String name) throws EXistException, LockException {
        return getId(name) > 0;
    }
    /**
     * Looks up the given node in the specified index and returns its original position
     * in the ordered set as a long integer.
     *
     * @param name the name of the index
     * @param proxy the node
     * @return the original position of the node in the ordered set
     * @throws EXistException
     * @throws LockException
     */
    public long getIndex(String name, NodeProxy proxy) throws EXistException, LockException {
        short id = getId(name);
        final Lock lock = index.btree.getLock();
        try {
            lock.acquire(Lock.READ_LOCK);
            byte[] key = computeKey(id, proxy);
            return index.btree.findValue(new Value(key));
        } catch (LockException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (BTreeException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (IOException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } finally {
            lock.release(Lock.READ_LOCK);
        }
    }

    /**
     * Completely remove the index identified by its name.
     *
     * @param name the name of the index
     *
     * @throws EXistException
     * @throws LockException
     */
    public void remove(String name) throws EXistException, LockException {
        short id = getId(name);
        final Lock lock = index.btree.getLock();
        try {
            lock.acquire(Lock.READ_LOCK);
            byte[] fromKey = computeKey(id);
            byte[] toKey = computeKey((short) (id + 1));
            final IndexQuery query = new IndexQuery(IndexQuery.RANGE, new Value(fromKey), new Value(toKey));
            index.btree.remove(query, null);

            removeId(name);
        } catch (BTreeException e) {
            throw new EXistException("Exception caught while deleting sort index: " + e.getMessage(), e);
        } catch (IOException e) {
            throw new EXistException("Exception caught while deleting sort index: " + e.getMessage(), e);
        } catch (TerminatedException e) {
            throw new EXistException("Exception caught while deleting sort index: " + e.getMessage(), e);
        } finally {
            lock.release(Lock.READ_LOCK);
        }
    }

    public void remove(String name, DocumentImpl doc) throws EXistException, LockException {
        short id = getId(name);
        remove(doc, id);
    }

    private void remove(DocumentImpl doc, short id) throws LockException, EXistException {
        final Lock lock = index.btree.getLock();
        try {
            lock.acquire(Lock.READ_LOCK);
            byte[] fromKey = computeKey(id, doc.getDocId());
            byte[] toKey = computeKey(id, doc.getDocId() + 1);
            final IndexQuery query = new IndexQuery(IndexQuery.RANGE, new Value(fromKey), new Value(toKey));
            index.btree.remove(query, null);
        } catch (BTreeException e) {
            throw new EXistException("Exception caught while deleting sort index: " + e.getMessage(), e);
        } catch (IOException e) {
            throw new EXistException("Exception caught while deleting sort index: " + e.getMessage(), e);
        } catch (TerminatedException e) {
            throw new EXistException("Exception caught while deleting sort index: " + e.getMessage(), e);
        } finally {
            lock.release(Lock.READ_LOCK);
        }
    }

    public void remove(DocumentImpl doc) {
        if (index.btree == null)
            return;
        byte[] fromKey = new byte[] { 1 };
        byte[] endKey = new byte[] { 2 };

        final Lock lock = index.btree.getLock();
        try {
            lock.acquire(Lock.READ_LOCK);
            IndexQuery query = new IndexQuery(IndexQuery.RANGE, new Value(fromKey), new Value(endKey));
            FindIdCallback callback = new FindIdCallback(true);
            index.btree.query(query, callback);

            for (long id : callback.allIds) {
                remove(doc, (short) id);
            }

        } catch (BTreeException e) {
            SortIndex.LOG.debug("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (IOException e) {
            SortIndex.LOG.debug("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (TerminatedException e) {
            SortIndex.LOG.debug("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (LockException e) {
            SortIndex.LOG.debug("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (EXistException e) {
            SortIndex.LOG.debug("Exception caught while reading sort index: " + e.getMessage(), e);
        } finally {
            lock.release(Lock.READ_LOCK);
        }
    }

    /**
     * Register the given index name and return a short id for it.
     *
     * @param name the name of the index
     * @return a unique id to be used for the index entries
     *
     * @throws EXistException
     * @throws LockException
     */
    private short getOrRegisterId(String name) throws EXistException, LockException {
        short id = getId(name);
        if (id < 0) {
            byte[] fromKey = { 1 };
            byte[] endKey = { 2 };
            IndexQuery query = new IndexQuery(IndexQuery.RANGE, new Value(fromKey), new Value(endKey));
            final Lock lock = index.btree.getLock();
            try {
                lock.acquire(Lock.READ_LOCK);
                FindIdCallback callback = new FindIdCallback(false);
                index.btree.query(query, callback);
                id = (short)(callback.max + 1);
                registerId(id, name);
            } catch (IOException e) {
                throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
            } catch (BTreeException e) {
                throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
            } catch (TerminatedException e) {
                throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
            } finally {
                lock.release(Lock.READ_LOCK);
            }
        }
        return id;
    }

    private final static class FindIdCallback implements BTreeCallback {
        long max = 0;
        List<Long> allIds = null;

        private FindIdCallback(boolean findIds) {
            if (findIds)
                allIds = new ArrayList<Long>(10);
        }

        public boolean indexInfo(Value value, long pointer) throws TerminatedException {
            max = Math.max(max, pointer);
            if (allIds != null) {
                allIds.add(pointer);
            }
            return true;
        }
    }

    private void registerId(short id, String name) throws EXistException {
        byte[] key = new byte[1 + UTF8.encoded(name)];
        key[0] = 1;
        UTF8.encode(name, key, 1);
        final Lock lock = index.btree.getLock();
        try {
            lock.acquire(Lock.READ_LOCK);
            index.btree.addValue(new Value(key), id);
        } catch (LockException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (BTreeException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (IOException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } finally {
            lock.release(Lock.READ_LOCK);
        }
    }

    private void removeId(String name) throws EXistException {
        byte[] key = new byte[1 + UTF8.encoded(name)];
        key[0] = 1;
        UTF8.encode(name, key, 1);
        final Lock lock = index.btree.getLock();
        try {
            lock.acquire(Lock.READ_LOCK);
            index.btree.removeValue(new Value(key));
        } catch (LockException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (BTreeException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (IOException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } finally {
            lock.release(Lock.READ_LOCK);
        }
    }

    private short getId(String name) throws EXistException, LockException {
        byte[] key = new byte[1 + UTF8.encoded(name)];
        key[0] = 1;
        UTF8.encode(name, key, 1);
        final Lock lock = index.btree.getLock();
        try {
            lock.acquire(Lock.READ_LOCK);
            return (short) index.btree.findValue(new Value(key));
        } catch (BTreeException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } catch (IOException e) {
            throw new EXistException("Exception caught while reading sort index: " + e.getMessage(), e);
        } finally {
            lock.release(Lock.READ_LOCK);
        }
    }

    private byte[] computeKey(short id, NodeProxy proxy) {
        byte[] data = new byte[7 + proxy.getNodeId().size()];
        data[0] = 0;
        ByteConversion.shortToByteH(id, data, 1);
        ByteConversion.intToByteH(proxy.getDocument().getDocId(), data, 3);
        proxy.getNodeId().serialize(data, 7);
        return data;
    }

    private byte[] computeKey(short id, int docId) {
        byte[] data = new byte[7];
        data[0] = 0;
        ByteConversion.shortToByteH(id, data, 1);
        ByteConversion.intToByteH(docId, data, 3);
        return data;
    }

    private byte[] computeKey(short id) {
        byte[] data = new byte[3];
        data[0] = 0;
        ByteConversion.shortToByteH(id, data, 1);
        return data;
    }

    public Object configure(IndexController controller, NodeList configNodes, Map<String, String> namespaces) throws DatabaseConfigurationException {
        return null;
    }

    public void setDocument(DocumentImpl doc) {
        this.document = doc;
    }

    public DocumentImpl getDocument() {
        return document;
    }

    public int getMode() {
        return mode;
    }

    public StoredNode getReindexRoot(StoredNode node, NodePath path, boolean insert, boolean includeSelf) {
        return insert ? null : node;
    }

    public StreamListener getListener() {
        return null;
    }

    public MatchListener getMatchListener(DBBroker broker, NodeProxy proxy) {
        return null;
    }

    public void removeCollection(Collection collection, DBBroker broker, boolean reindex) {
    }

    public boolean checkIndex(DBBroker broker) {
        return false;
    }

    public Occurrences[] scanIndex(XQueryContext context, DocumentSet docs, NodeSet contextSet, Map hints) {
        return new Occurrences[0];
    }
}
TOP

Related Classes of org.exist.indexing.sort.SortIndexWorker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.