All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.compass.core.lucene.engine.transaction.support.AbstractJobBasedTransactionProcessor Maven / Gradle / Ivy

/*
 * Copyright 2004-2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.compass.core.lucene.engine.transaction.support;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.lucene.store.Lock;
import org.compass.core.Resource;
import org.compass.core.engine.SearchEngineException;
import org.compass.core.lucene.engine.LuceneSearchEngine;
import org.compass.core.lucene.engine.LuceneSearchEngineHits;
import org.compass.core.lucene.engine.LuceneSearchEngineInternalSearch;
import org.compass.core.lucene.engine.LuceneSearchEngineQuery;
import org.compass.core.lucene.engine.transaction.support.job.CreateTransactionJob;
import org.compass.core.lucene.engine.transaction.support.job.DeleteByQueryTransactionJob;
import org.compass.core.lucene.engine.transaction.support.job.DeleteTransactionJob;
import org.compass.core.lucene.engine.transaction.support.job.TransactionJob;
import org.compass.core.lucene.engine.transaction.support.job.TransactionJobs;
import org.compass.core.lucene.engine.transaction.support.job.UpdateTransactionJob;
import org.compass.core.spi.InternalResource;
import org.compass.core.spi.ResourceKey;

/**
 * Base class for jobs based ({@link org.compass.core.lucene.engine.transaction.support.job.TransactionJobs})
 * transaction processor. Mainly used for simple accumelating of {@link org.compass.core.lucene.engine.transaction.support.job.TransactionJob}s
 * and then processing them during commit/rollback time.
 *
 * 

Allows for optionl ordering guarantees of transaction operations across several concurrent transactions from the * same or from different JVMs. The setting name to control it is maintainOrder and the constructor allows * to control its default value. * *

Note, if only search based operations were performed, then prepare/commit/rollback will not be called. * * @author kimchy */ public abstract class AbstractJobBasedTransactionProcessor extends AbstractSearchTransactionProcessor { private TransactionJobs jobs; private final boolean maintainOrder; private final Map orderLocks; /** * Constructs a new job based transction processor. The defaultMaintainOrderLock will control if, by * default when no setting is specified (setting name is maintainOrder), what will be the default value * of it. */ public AbstractJobBasedTransactionProcessor(Log logger, LuceneSearchEngine searchEngine, boolean defaultMaintainOrderLock) { super(logger, searchEngine); maintainOrder = searchEngine.getSettings().getSettingAsBoolean(getSettingName("maintainOrder"), defaultMaintainOrderLock); if (maintainOrder) { orderLocks = new HashMap(); } else { orderLocks = null; } } public void begin() throws SearchEngineException { // nothing to do here } public void prepare() throws SearchEngineException { if (jobs == null) { return; } doPrepare(jobs); } abstract protected void doPrepare(TransactionJobs jobs) throws SearchEngineException; public void commit(boolean onePhase) throws SearchEngineException { if (jobs == null) { return; } try { doCommit(onePhase, jobs); } finally { clearLocksIfNeeded(); } } abstract protected void doCommit(boolean onePhase, TransactionJobs jobs) throws SearchEngineException; public void rollback() throws SearchEngineException { if (jobs == null) { return; } try { doRollback(jobs); } finally { clearLocksIfNeeded(); } } abstract protected void doRollback(TransactionJobs jobs) throws SearchEngineException; public void create(InternalResource resource) throws SearchEngineException { obtainOrderLockIfNeeded(resource.getSubIndex()); getTransactionJobs().add(new CreateTransactionJob(resource)); } public void update(InternalResource resource) throws SearchEngineException { obtainOrderLockIfNeeded(resource.getSubIndex()); getTransactionJobs().add(new UpdateTransactionJob(resource)); } public void delete(ResourceKey resourceKey) throws SearchEngineException { obtainOrderLockIfNeeded(resourceKey.getSubIndex()); getTransactionJobs().add(new DeleteTransactionJob(resourceKey)); } public void delete(LuceneSearchEngineQuery query) throws SearchEngineException { flush(); String[] calcSubIndexes = indexManager.getStore().calcSubIndexes(query.getSubIndexes(), query.getAliases()); for (String subIndex : calcSubIndexes) { obtainOrderLockIfNeeded(subIndex); getTransactionJobs().add(new DeleteByQueryTransactionJob(query.getQuery(), subIndex)); } } public void flush() throws SearchEngineException { // nothing to do here } /** * Calls {@link #doFlushCommit(org.compass.core.lucene.engine.transaction.support.job.TransactionJobs)} and then * clears the jobs listed to be processed. */ public void flushCommit(String ... aliases) throws SearchEngineException { flush(); if (aliases == null || aliases.length == 0) { doFlushCommit(jobs); jobs = null; } else { Set subIndexes = new HashSet(Arrays.asList(indexManager.polyCalcSubIndexes(null, aliases, null))); TransactionJobs flushJobs = new TransactionJobs(); TransactionJobs leftoverJobs = new TransactionJobs(); for (TransactionJob job : jobs.getJobs()) { if (subIndexes.contains(job.getSubIndex())) { flushJobs.add(job); } else { leftoverJobs.add(job); } } doFlushCommit(flushJobs); jobs = leftoverJobs; } } protected abstract void doFlushCommit(TransactionJobs jobs); public LuceneSearchEngineHits find(LuceneSearchEngineQuery query) throws SearchEngineException { return performFind(query); } public LuceneSearchEngineInternalSearch internalSearch(String[] subIndexes, String[] aliases) throws SearchEngineException { return performInternalSearch(subIndexes, aliases); } public Resource[] get(ResourceKey resourceKey) throws SearchEngineException { return performGet(resourceKey); } private TransactionJobs getTransactionJobs() { if (jobs == null) { jobs = new TransactionJobs(); } return jobs; } private void obtainOrderLockIfNeeded(String subIndex) throws SearchEngineException { if (!maintainOrder) { return; } Lock lock = orderLocks.get(subIndex); if (lock == null) { lock = searchEngine.getSearchEngineFactory().getLuceneIndexManager().getStore().openDirectory(subIndex).makeLock("order.lock"); try { lock.obtain(searchEngine.getSearchEngineFactory().getLuceneSettings().getTransactionLockTimout()); } catch (IOException e) { clearLocksIfNeeded(); throw new SearchEngineException("Failed to obtain order lock on sub index [" + subIndex + "]", e); } orderLocks.put(subIndex, lock); } } private void clearLocksIfNeeded() { if (!maintainOrder) { return; } for (Map.Entry entry : orderLocks.entrySet()) { try { entry.getValue().release(); } catch (IOException e) { logger.warn("Failed to release lock for sub index [" + entry.getKey() + "]", e); } } orderLocks.clear(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy