/*
* Copyright 2006-2012 Amazon Technologies, Inc. or its affiliates.
* Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
* of Amazon Technologies, Inc. or its affiliates. All rights reserved.
*
* 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 com.amazon.carbonado.repo.indexed;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicReference;
import com.amazon.carbonado.ConfigurationException;
import com.amazon.carbonado.Repository;
import com.amazon.carbonado.RepositoryBuilder;
import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.TriggerFactory;
import com.amazon.carbonado.spi.AbstractRepositoryBuilder;
/**
* Repository builder for the indexed repository.
* <p>
* In addition to supporting the capabilities of the wrapped repository, the
* following extra capabilities are supported:
* <ul>
* <li>{@link com.amazon.carbonado.capability.IndexInfoCapability IndexInfoCapability}
* <li>{@link com.amazon.carbonado.capability.StorableInfoCapability StorableInfoCapability}
* <li>{@link IndexEntryAccessCapability IndexEntryAccessCapability}
* </ul>
*
* @author Brian S O'Neill
*/
public class IndexedRepositoryBuilder extends AbstractRepositoryBuilder {
private String mName;
private boolean mIsMaster = true;
private RepositoryBuilder mRepoBuilder;
private boolean mIndexRepairEnabled = true;
private double mIndexThrottle = 1.0;
private boolean mIndexDiscardDuplicates;
private boolean mIndexRepairVerifyOnly;
private boolean mAllClustered;
private boolean mStrictTriggers;
public IndexedRepositoryBuilder() {
}
public Repository build(AtomicReference<Repository> rootRef) throws RepositoryException {
assertReady();
Repository wrapped;
boolean originalOption = mRepoBuilder.isMaster();
try {
mRepoBuilder.setMaster(mIsMaster);
for (TriggerFactory factory : getTriggerFactories()) {
mRepoBuilder.addTriggerFactory(factory);
}
wrapped = mRepoBuilder.build(rootRef);
} finally {
mRepoBuilder.setMaster(originalOption);
}
if (wrapped instanceof IndexedRepository) {
return wrapped;
}
Repository repo = new IndexedRepository(rootRef, getName(), wrapped,
isIndexRepairEnabled(),
getIndexRepairThrottle(),
mIndexDiscardDuplicates,
mIndexRepairVerifyOnly,
isAllClustered(),
mStrictTriggers);
rootRef.set(repo);
return repo;
}
public String getName() {
String name = mName;
if (name == null && mRepoBuilder != null) {
name = mRepoBuilder.getName();
}
return name;
}
public void setName(String name) {
mName = name;
}
public boolean isMaster() {
return mIsMaster;
}
public void setMaster(boolean b) {
mIsMaster = b;
}
/**
* @return wrapped respository
*/
public RepositoryBuilder getWrappedRepository() {
return mRepoBuilder;
}
/**
* Set the required wrapped respository, which must support the
* {@link com.amazon.carbonado.capability.IndexInfoCapability IndexInfoCapability}.
*/
public void setWrappedRepository(RepositoryBuilder repoBuilder) {
mRepoBuilder = repoBuilder;
}
/**
* @see #setIndexRepairEnabled(boolean)
*
* @return true by default
*/
public boolean isIndexRepairEnabled() {
return mIndexRepairEnabled;
}
/**
* By default, index repair is enabled. In this mode, the first time a
* Storable type is used, new indexes are populated and old indexes are
* removed. Until finished, access to the Storable is blocked.
*
* <p>When index repair is disabled, the Storable is immediately
* available. This does have consequences, however. The set of indexes
* available for queries is defined by the <i>intersection</i> of the old
* and new index sets. The set of indexes that are kept up-to-date is
* defined by the <i>union</i> of the old and new index sets.
*
* <p>While index repair is disabled, another process can safely repair the
* indexes in the background. When it is complete, index repair can be
* enabled for this repository too.
*/
public void setIndexRepairEnabled(boolean enabled) {
mIndexRepairEnabled = enabled;
}
/**
* Returns the throttle parameter used when indexes are added, dropped or
* bulk repaired. By default this value is 1.0, or maximum speed.
*/
public double getIndexRepairThrottle() {
return mIndexThrottle;
}
/**
* Sets the throttle parameter used when indexes are added, dropped or bulk
* repaired. By default this value is 1.0, or maximum speed.
*
* @param desiredSpeed 1.0 = perform work at full speed,
* 0.5 = perform work at half speed, 0.0 = fully suspend work
*/
public void setIndexRepairThrottle(double desiredSpeed) {
if (desiredSpeed < 0.0) {
desiredSpeed = 0.0;
} else if (desiredSpeed > 1.0) {
desiredSpeed = 1.0;
}
mIndexThrottle = desiredSpeed;
}
/**
* Set true to skip collisions during index repair, logging each as a
* warning.
*/
public void setIndexRepairDiscardDuplicates(boolean discardDuplicates) {
mIndexDiscardDuplicates = discardDuplicates;
}
/**
* Set true to build and verify indexes, but don't apply any changes.
*/
public void setIndexRepairVerifyOnly(boolean verifyOnly) {
mIndexRepairVerifyOnly = verifyOnly;
}
/**
* Returns true if all indexes should be identified as clustered. This
* affects how indexes are selected by the query analyzer.
*
* @since 1.2
*/
public boolean isAllClustered() {
return mAllClustered;
}
/**
* When all indexes are identified as clustered, the query analyzer treats
* all indexes as performing equally well. This is suitable for indexing
* repositories that never read from a slow storage medium.
*
* @since 1.2
*/
public void setAllClustered(boolean clustered) {
mAllClustered = clustered;
}
/**
* Set to true to require that index maintenance triggers use a "for update" transaction,
* avoiding deadlocks and lock upgrade failures.
*/
public void setStrictTriggers(boolean strict) {
mStrictTriggers = strict;
}
@Override
public void errorCheck(Collection<String> messages) throws ConfigurationException {
super.errorCheck(messages);
if (null == getWrappedRepository()) {
messages.add("wrapped repository missing");
}
}
}