001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.core.engine.subindex;
018:
019: import org.compass.core.CompassException;
020: import org.compass.core.Property;
021: import org.compass.core.config.CompassConfigurable;
022: import org.compass.core.config.CompassSettings;
023: import org.compass.core.config.ConfigurationException;
024: import org.compass.core.engine.SearchEngineException;
025:
026: /**
027: * Uses a hash function based on hash code computation of alias and ids,
028: * and using the modulo operation against the configured size.
029: * <p/>
030: * The sub index name is <code>prefix_(hashCode % size)</code>.
031: * <p/>
032: * If using configuration, expects <code>prefix</code> as the setting name,
033: * and <code>size</code> as the modulo right hand side operation.
034: *
035: * @author kimchy
036: */
037: public class ModuloSubIndexHash implements SubIndexHash,
038: CompassConfigurable {
039:
040: private String prefix;
041:
042: private int size;
043:
044: /**
045: * Constructs a new instance, will have to be configured.
046: */
047: public ModuloSubIndexHash() {
048: }
049:
050: /**
051: * Constructs a new instance, using the given prefix and size.
052: *
053: * @param prefix The prefix sed for the sub index prefix name
054: * @param size The size the modulo will be used
055: */
056: public ModuloSubIndexHash(String prefix, int size) {
057: this .prefix = prefix;
058: this .size = size;
059: }
060:
061: /**
062: * Using configuration, expects <code>prefix</code> as the setting name,
063: * and <code>size</code> as the modulo right hand side operation.
064: *
065: * @param settings The setting to configure by
066: * @throws CompassException
067: */
068: public void configure(CompassSettings settings)
069: throws CompassException {
070: prefix = settings.getSetting("prefix", null);
071: if (prefix == null) {
072: throw new ConfigurationException(
073: "prefix must be set for Modulo sub index hash");
074: }
075: size = settings.getSettingAsInt("size", -1);
076: if (size < 0) {
077: throw new ConfigurationException(
078: "size must be set for Modulo sub index hash");
079: }
080: }
081:
082: /**
083: * Returns all the sub indexes possible, basically in the form of
084: * <code>prefix_(0..size)</code> (not including size).
085: */
086: public String[] getSubIndexes() {
087: String[] subIndexes = new String[size];
088: for (int i = 0; i < size; i++) {
089: subIndexes[i] = prefix + '_' + i;
090: }
091: return subIndexes;
092: }
093:
094: /**
095: * Computes the hash code of alias and all the ids, and then modulo it by size.
096: * The prefix is prepended (with an underscore), and the sub index is constructed.
097: * The formula is: <code>prefix_(hashCode % size)</code>.
098: */
099: public String mapSubIndex(String alias, Property[] ids)
100: throws SearchEngineException {
101: int hash = alias.hashCode();
102: for (int i = 0; i < ids.length; i++) {
103: hash = hash * 31 + ids[i].getStringValue().hashCode();
104: }
105: return prefix + '_' + (Math.abs(hash) % size);
106: }
107:
108: public String toString() {
109: return "ModuloSubIndexHash[prefix[" + prefix + "] size[" + size
110: + "]]";
111: }
112: }
|