multiindex.java

来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 1,855 行 · 第 1/5 页

JAVA
1,855
字号
     * @return the index document.     * @throws RepositoryException if an error occurs while reading from the     *                             workspace.     */    Document createDocument(NodeState node) throws RepositoryException {        return handler.createDocument(node, nsMappings);    }    /**     * Returns a lucene Document for the Node with <code>id</code>.     *     * @param id the id of the node to index.     * @return the index document.     * @throws RepositoryException if an error occurs while reading from the     *                             workspace or if there is no node with     *                             <code>id</code>.     */    Document createDocument(NodeId id) throws RepositoryException {        try {            NodeState state = (NodeState) handler.getContext().getItemStateManager().getItemState(id);            return createDocument(state);        } catch (NoSuchItemStateException e) {            throw new RepositoryException("Node " + id + " does not exist", e);        } catch (ItemStateException e) {            throw new RepositoryException("Error retrieving node: " + id, e);        }    }    /**     * Returns <code>true</code> if the redo log contained entries while     * this index was instantiated; <code>false</code> otherwise.     * @return <code>true</code> if the redo log contained entries.     */    boolean getRedoLogApplied() {        return redoLogApplied;    }    /**     * Removes the <code>index</code> from the list of active sub indexes. The     * Index is not acutally deleted right away, but postponed to the transaction     * commit.     * <p/>     * This method does not close the index, but rather expects that the index     * has already been closed.     *     * @param index the index to delete.     */    synchronized void deleteIndex(PersistentIndex index) {        // remove it from the lists if index is registered        indexes.remove(index);        indexNames.removeName(index.getName());        // during recovery it may happen that an index had already been marked        // deleted, so we need to check if it is already marked deleted.        if (!deletable.contains(index.getName())) {            deletable.addName(index.getName());        }    }    /**     * Flushes this <code>MultiIndex</code>. Persists all pending changes and     * resets the redo log.     *     * @throws IOException if the flush fails.     */    synchronized void flush() throws IOException {        // commit volatile index        executeAndLog(new Start(Action.INTERNAL_TRANSACTION));        commitVolatileIndex();        // commit persistent indexes        for (int i = indexes.size() - 1; i >= 0; i--) {            PersistentIndex index = (PersistentIndex) indexes.get(i);            // only commit indexes we own            // index merger also places PersistentIndex instances in indexes,            // but does not make them public by registering the name in indexNames            if (indexNames.contains(index.getName())) {                index.commit();                // check if index still contains documents                if (index.getNumDocuments() == 0) {                    executeAndLog(new DeleteIndex(getTransactionId(), index.getName()));                }            }        }        executeAndLog(new Commit(getTransactionId()));        indexNames.write(indexDir);        // reset redo log        redoLog.clear();        lastFlushTime = System.currentTimeMillis();        // delete obsolete indexes        attemptDelete();    }    //-------------------------< internal >-------------------------------------    /**     * Resets the volatile index to a new instance.     */    private void resetVolatileIndex() throws IOException {        volatileIndex = new VolatileIndex(                handler.getTextAnalyzer(), indexingQueue);        volatileIndex.setUseCompoundFile(handler.getUseCompoundFile());        volatileIndex.setMaxFieldLength(handler.getMaxFieldLength());        volatileIndex.setBufferSize(handler.getBufferSize());    }    /**     * Returns the current transaction id.     *     * @return the current transaction id.     */    private long getTransactionId() {        return currentTransactionId;    }    /**     * Executes action <code>a</code> and appends the action to the redo log if     * successful.     *     * @param a the <code>Action</code> to execute.     * @return the executed action.     * @throws IOException         if an error occurs while executing the action     *                             or appending the action to the redo log.     */    private Action executeAndLog(Action a)            throws IOException {        a.execute(this);        redoLog.append(a);        // please note that flushing the redo log is only required on        // commit, but we also want to keep track of new indexes for sure.        // otherwise it might happen that unused index folders are orphaned        // after a crash.        if (a.getType() == Action.TYPE_COMMIT || a.getType() == Action.TYPE_ADD_INDEX) {            redoLog.flush();            // also flush indexing queue            indexingQueue.commit();        }        return a;    }    /**     * Checks if it is needed to commit the volatile index according to {@link     * SearchIndex#getMinMergeDocs()}.     *     * @return <code>true</code> if the volatile index has been committed,     *         <code>false</code> otherwise.     * @throws IOException if an error occurs while committing the volatile     *                     index.     */    private boolean checkVolatileCommit() throws IOException {        if (volatileIndex.getNumDocuments() >= handler.getMinMergeDocs()) {            commitVolatileIndex();            return true;        }        return false;    }    /**     * Commits the volatile index to a persistent index. The new persistent     * index is added to the list of indexes but not written to disk. When this     * method returns a new volatile index has been created.     *     * @throws IOException if an error occurs while writing the volatile index     *                     to disk.     */    private void commitVolatileIndex() throws IOException {        // check if volatile index contains documents at all        if (volatileIndex.getNumDocuments() > 0) {            long time = System.currentTimeMillis();            // create index            CreateIndex create = new CreateIndex(getTransactionId(), null, true);            executeAndLog(create);            // commit volatile index            executeAndLog(new VolatileCommit(getTransactionId(), create.getIndexName()));            // add new index            AddIndex add = new AddIndex(getTransactionId(), create.getIndexName());            executeAndLog(add);            // create new volatile index            resetVolatileIndex();            time = System.currentTimeMillis() - time;            log.debug("Committed in-memory index in " + time + "ms.");        }    }    /**     * Recursively creates an index starting with the NodeState     * <code>node</code>.     *     * @param node     the current NodeState.     * @param stateMgr the shared item state manager.     * @throws IOException         if an error occurs while writing to the     *                             index.     * @throws ItemStateException  if an node state cannot be found.     * @throws RepositoryException if any other error occurs     */    private void createIndex(NodeState node, ItemStateManager stateMgr)            throws IOException, ItemStateException, RepositoryException {        NodeId id = node.getNodeId();        if (excludedIDs.contains(id)) {            return;        }        executeAndLog(new AddNode(getTransactionId(), id.getUUID()));        checkVolatileCommit();        List children = node.getChildNodeEntries();        for (Iterator it = children.iterator(); it.hasNext();) {            NodeState.ChildNodeEntry child = (NodeState.ChildNodeEntry) it.next();            NodeState childState = (NodeState) stateMgr.getItemState(child.getId());            createIndex(childState, stateMgr);        }    }    /**     * Attempts to delete all files recorded in {@link #deletable}.     */    private void attemptDelete() {        for (int i = deletable.size() - 1; i >= 0; i--) {            String indexName = deletable.getName(i);            File dir = new File(indexDir, indexName);            if (deleteIndex(dir)) {                deletable.removeName(i);            } else {                log.info("Unable to delete obsolete index: " + indexName);            }        }        try {            deletable.write(indexDir);        } catch (IOException e) {            log.warn("Exception while writing deletable indexes: " + e);        }    }    /**     * Deletes the index <code>directory</code>.     *     * @param directory the index directory to delete.     * @return <code>true</code> if the delete was successful,     *         <code>false</code> otherwise.     */    private boolean deleteIndex(File directory) {        // trivial if it does not exist anymore        if (!directory.exists()) {            return true;        }        // delete files first        File[] files = directory.listFiles();        for (int i = 0; i < files.length; i++) {            if (!files[i].delete()) {                return false;            }        }        // now delete directory itself        return directory.delete();    }    /**     * Returns an new index folder which is empty.     *     * @return the new index folder.     * @throws IOException if the folder cannot be created.     */    private File newIndexFolder() throws IOException {        // create new index folder. make sure it does not exist        File sub;        do {            sub = new File(indexDir, indexNames.newName());        } while (sub.exists());        if (!sub.mkdir()) {            throw new IOException("Unable to create directory: " + sub.getAbsolutePath());        }        return sub;    }    /**     * Checks the duration between the last commit to this index and the     * current time and flushes the index (if there are changes at all)     * if the duration (idle time) is more than {@link SearchIndex#getVolatileIdleTime()}     * seconds.     */    private synchronized void checkFlush() {        long idleTime = System.currentTimeMillis() - lastFlushTime;        // do not flush if volatileIdleTime is zero or negative        if (handler.getVolatileIdleTime() > 0                && idleTime > handler.getVolatileIdleTime() * 1000) {            try {                if (redoLog.hasEntries()) {                    log.debug("Flushing index after being idle for "                            + idleTime + " ms.");                    synchronized (updateMonitor) {                        updateInProgress = true;                    }                    try {                        flush();                    } finally {                        synchronized (updateMonitor) {                            updateInProgress = false;                            updateMonitor.notifyAll();                            if (multiReader != null) {                                multiReader.close();                                multiReader = null;                            }                        }                    }                }            } catch (IOException e) {                log.error("Unable to commit volatile index", e);            }        }    }    /**     * Checks the indexing queue for finished text extrator jobs and     * updates the index accordingly if there are any new ones.     */    private synchronized void checkIndexingQueue() {        Document[] docs = indexingQueue.getFinishedDocuments();        Map finished = new HashMap();        for (int i = 0; i < docs.length; i++) {            String uuid = docs[i].get(FieldNames.UUID);            finished.put(UUID.fromString(uuid), docs[i]);        }        // now update index with the remaining ones if there are any        if (!finished.isEmpty()) {            log.debug("updating index with {} nodes from indexing queue.",                    new Long(finished.size()));            // remove documents from the queue            for (Iterator it = finished.keySet().iterator(); it.hasNext(); ) {                try {                    indexingQueue.removeDocument(it.next().toString());                } catch (IOException e) {                    log.error("Failed to remove node from indexing queue", e);                }            }            try {                update(finished.keySet().iterator(),                        finished.values().iterator());            } catch (IOException e) {                // update failed                log.warn("Failed to update index with deferred text extraction", e);            }        }    }    //------------------------< Actions >---------------------------------------    /**     * Defines an action on an <code>MultiIndex</code>.     */    public abstract static class Action {        /**         * Action identifier in redo log for transaction start action.         */        static final String START = "STR";        /**         * Action type for start action.         */        public static final int TYPE_START = 0;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?