blob: c5279abf542f20ab8b6cbb1d86e2d09b18608491 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.accumulo.core.client;
import static com.google.common.base.Preconditions.checkArgument;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
import org.apache.accumulo.core.util.Pair;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableUtils;
/**
* Configure an iterator for minc, majc, and/or scan. By default, IteratorSetting will be configured
* for scan.
*
* Every iterator has a priority, a name, a class, a set of scopes, and configuration parameters.
*
* A typical use case configured for scan:
*
* <pre>
* IteratorSetting cfg = new IteratorSetting(priority, &quot;myIter&quot;, MyIterator.class);
* MyIterator.addOption(cfg, 42);
* scanner.addScanIterator(cfg);
* </pre>
*/
public class IteratorSetting implements Writable {
private int priority;
private String name;
private String iteratorClass;
private Map<String,String> properties;
/**
* Get layer at which this iterator applies. See {@link #setPriority(int)} for how the priority is
* used.
*
* @return the priority of this Iterator
*/
public int getPriority() {
return priority;
}
/**
* Set layer at which this iterator applies.
*
* @param priority
* determines the order in which iterators are applied (system iterators are always
* applied first, then user-configured iterators, lowest priority first)
*/
public void setPriority(int priority) {
checkArgument(priority > 0, "property must be strictly positive");
this.priority = priority;
}
/**
* Get the iterator's name.
*
* @return the name of the iterator
*/
public String getName() {
return name;
}
/**
* Set the iterator's name. Must be a simple alphanumeric identifier. The iterator name also may
* not contain a dot/period.
*/
public void setName(String name) {
checkArgument(name != null, "name is null");
checkArgument(!name.contains("."), "Iterator name cannot contain a dot/period: " + name);
this.name = name;
}
/**
* Get the name of the class that implements the iterator.
*
* @return the iterator's class name
*/
public String getIteratorClass() {
return iteratorClass;
}
/**
* Set the name of the class that implements the iterator. The class does not have to be present
* on the client, but it must be available to all tablet servers.
*/
public void setIteratorClass(String iteratorClass) {
checkArgument(iteratorClass != null, "iteratorClass is null");
this.iteratorClass = iteratorClass;
}
/**
* Constructs an iterator setting configured for the scan scope with no parameters. (Parameters
* can be added later.)
*
* @param priority
* the priority for the iterator (see {@link #setPriority(int)})
* @param name
* the distinguishing name for the iterator
* @param iteratorClass
* the fully qualified class name for the iterator
*/
public IteratorSetting(int priority, String name, String iteratorClass) {
this(priority, name, iteratorClass, new HashMap<>());
}
/**
* Constructs an iterator setting configured for the specified scopes with the specified
* parameters.
*
* @param priority
* the priority for the iterator (see {@link #setPriority(int)})
* @param name
* the distinguishing name for the iterator
* @param iteratorClass
* the fully qualified class name for the iterator
* @param properties
* any properties for the iterator
*/
public IteratorSetting(int priority, String name, String iteratorClass,
Map<String,String> properties) {
setPriority(priority);
setName(name);
setIteratorClass(iteratorClass);
this.properties = new HashMap<>();
addOptions(properties);
}
/**
* Constructs an iterator setting using the given class's SimpleName for the iterator name. The
* iterator setting will be configured for the scan scope with no parameters.
*
* @param priority
* the priority for the iterator (see {@link #setPriority(int)})
* @param iteratorClass
* the class for the iterator
*/
public IteratorSetting(int priority,
Class<? extends SortedKeyValueIterator<Key,Value>> iteratorClass) {
this(priority, iteratorClass.getSimpleName(), iteratorClass.getName());
}
/**
*
* Constructs an iterator setting using the given class's SimpleName for the iterator name and
* configured for the specified scopes with the specified parameters.
*
* @param priority
* the priority for the iterator (see {@link #setPriority(int)})
* @param iteratorClass
* the class for the iterator
* @param properties
* any properties for the iterator
*/
public IteratorSetting(int priority,
Class<? extends SortedKeyValueIterator<Key,Value>> iteratorClass,
Map<String,String> properties) {
this(priority, iteratorClass.getSimpleName(), iteratorClass.getName(), properties);
}
/**
* Constructs an iterator setting configured for the scan scope with no parameters.
*
* @param priority
* the priority for the iterator (see {@link #setPriority(int)})
* @param name
* the distinguishing name for the iterator
* @param iteratorClass
* the class for the iterator
*/
public IteratorSetting(int priority, String name,
Class<? extends SortedKeyValueIterator<Key,Value>> iteratorClass) {
this(priority, name, iteratorClass.getName());
}
/**
* Constructs an iterator setting using the provided name and the provided class's name for the
* scan scope with the provided parameters.
*
* @param priority
* The priority for the iterator (see {@link #setPriority(int)})
* @param name
* The distinguishing name for the iterator
* @param iteratorClass
* The class for the iterator
* @param properties
* Any properties for the iterator
*
* @since 1.6.0
*/
public IteratorSetting(int priority, String name,
Class<? extends SortedKeyValueIterator<Key,Value>> iteratorClass,
Map<String,String> properties) {
this(priority, name, iteratorClass.getName(), properties);
}
/**
* @since 1.5.0
*/
public IteratorSetting(DataInput din) throws IOException {
this.properties = new HashMap<>();
this.readFields(din);
}
/**
* Add another option to the iterator.
*
* @param option
* the name of the option
* @param value
* the value of the option
*/
public void addOption(String option, String value) {
checkArgument(option != null, "option is null");
checkArgument(value != null, "value is null");
properties.put(option, value);
}
/**
* Remove an option from the iterator.
*
* @param option
* the name of the option
* @return the value previously associated with the option, or null if no such option existed
*/
public String removeOption(String option) {
checkArgument(option != null, "option is null");
return properties.remove(option);
}
/**
* Add many options to the iterator.
*
* @param propertyEntries
* a set of entries to add to the options
*/
public void addOptions(Set<Entry<String,String>> propertyEntries) {
checkArgument(propertyEntries != null, "propertyEntries is null");
for (Entry<String,String> keyValue : propertyEntries) {
addOption(keyValue.getKey(), keyValue.getValue());
}
}
/**
* Add many options to the iterator.
*
* @param properties
* a map of entries to add to the options
*/
public void addOptions(Map<String,String> properties) {
checkArgument(properties != null, "properties is null");
addOptions(properties.entrySet());
}
/**
* Get the configuration parameters for this iterator.
*
* @return the properties
*/
public Map<String,String> getOptions() {
return Collections.unmodifiableMap(properties);
}
/**
* Remove all options from the iterator.
*/
public void clearOptions() {
properties.clear();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((iteratorClass == null) ? 0 : iteratorClass.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + priority;
result = prime * result + ((properties == null) ? 0 : properties.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof IteratorSetting))
return false;
IteratorSetting other = (IteratorSetting) obj;
if (iteratorClass == null) {
if (other.iteratorClass != null)
return false;
} else if (!iteratorClass.equals(other.iteratorClass))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (priority != other.priority)
return false;
if (properties == null) {
return other.properties == null;
} else {
return properties.equals(other.properties);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("name:");
sb.append(name);
sb.append(", priority:");
sb.append(Integer.toString(priority));
sb.append(", class:");
sb.append(iteratorClass);
sb.append(", properties:");
sb.append(properties);
return sb.toString();
}
/**
* A convenience class for passing column family and column qualifiers to iterator configuration
* methods.
*/
public static class Column extends Pair<Text,Text> {
public Column(Text columnFamily, Text columnQualifier) {
super(columnFamily, columnQualifier);
}
public Column(Text columnFamily) {
super(columnFamily, null);
}
public Column(String columnFamily, String columnQualifier) {
super(new Text(columnFamily), new Text(columnQualifier));
}
public Column(String columnFamily) {
super(new Text(columnFamily), null);
}
public Text getColumnFamily() {
return getFirst();
}
public Text getColumnQualifier() {
return getSecond();
}
}
/**
* @since 1.5.0
* @see Writable
*/
@Override
public void readFields(DataInput din) throws IOException {
priority = WritableUtils.readVInt(din);
name = WritableUtils.readString(din);
iteratorClass = WritableUtils.readString(din);
properties.clear();
int size = WritableUtils.readVInt(din);
while (size > 0) {
properties.put(WritableUtils.readString(din), WritableUtils.readString(din));
size--;
}
}
/**
* @since 1.5.0
* @see Writable
*/
@Override
public void write(DataOutput dout) throws IOException {
WritableUtils.writeVInt(dout, priority);
WritableUtils.writeString(dout, name);
WritableUtils.writeString(dout, iteratorClass);
WritableUtils.writeVInt(dout, properties.size());
for (Entry<String,String> e : properties.entrySet()) {
WritableUtils.writeString(dout, e.getKey());
WritableUtils.writeString(dout, e.getValue());
}
}
}