/*
* 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.engine.subindex;
import org.compass.core.CompassException;
import org.compass.core.Property;
import org.compass.core.config.CompassConfigurable;
import org.compass.core.config.CompassSettings;
import org.compass.core.config.ConfigurationException;
import org.compass.core.engine.SearchEngineException;
/**
* Uses a hash function based on hash code computation of alias and ids,
* and using the modulo operation against the configured size.
* <p/>
* The sub index name is <code>prefix_(hashCode % size)</code>.
* <p/>
* If using configuration, expects <code>prefix</code> as the setting name,
* and <code>size</code> as the modulo right hand side operation.
*
* @author kimchy
*/
public class ModuloSubIndexHash implements SubIndexHash, CompassConfigurable {
private String prefix;
private int size;
/**
* Constructs a new instance, will have to be configured.
*/
public ModuloSubIndexHash() {
}
/**
* Constructs a new instance, using the given prefix and size.
*
* @param prefix The prefix sed for the sub index prefix name
* @param size The size the modulo will be used
*/
public ModuloSubIndexHash(String prefix, int size) {
this.prefix = prefix;
this.size = size;
}
/**
* Using configuration, expects <code>prefix</code> as the setting name,
* and <code>size</code> as the modulo right hand side operation.
*
* @param settings The setting to configure by
* @throws CompassException
*/
public void configure(CompassSettings settings) throws CompassException {
prefix = settings.getSetting("prefix", null);
if (prefix == null) {
throw new ConfigurationException("prefix must be set for Modulo sub index hash");
}
size = settings.getSettingAsInt("size", -1);
if (size < 0) {
throw new ConfigurationException("size must be set for Modulo sub index hash");
}
}
/**
* Returns all the sub indexes possible, basically in the form of
* <code>prefix_(0..size)</code> (not including size).
*/
public String[] getSubIndexes() {
String[] subIndexes = new String[size];
for (int i = 0; i < size; i++) {
subIndexes[i] = prefix + '_' + i;
}
return subIndexes;
}
/**
* Computes the hash code of alias and all the ids, and then modulo it by size.
* The prefix is prepended (with an underscore), and the sub index is constructed.
* The formula is: <code>prefix_(hashCode % size)</code>.
*/
public String mapSubIndex(String alias, Property[] ids) throws SearchEngineException {
int hash = alias.hashCode();
for (int i = 0; i < ids.length; i++) {
hash = hash * 31 + ids[i].getStringValue().hashCode();
}
return prefix + '_' + (Math.abs(hash) % size);
}
public String toString() {
return "ModuloSubIndexHash[prefix[" + prefix + "] size[" + size + "]]";
}
}