org.apache.accumulo.core.client.BatchWriterConfig.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.accumulo.core.client.BatchWriterConfig.java

Source

/*
 * 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 java.nio.charset.StandardCharsets.UTF_8;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.accumulo.core.client.impl.DurabilityImpl;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.util.StringUtils;

/**
 * This object holds configuration settings used to instantiate a {@link BatchWriter}
 *
 * @since 1.5.0
 */
public class BatchWriterConfig implements Writable {

    private static final Long DEFAULT_MAX_MEMORY = 50 * 1024 * 1024l;
    private Long maxMemory = null;

    private static final Long DEFAULT_MAX_LATENCY = 2 * 60 * 1000l;
    private Long maxLatency = null;

    private static final Long DEFAULT_TIMEOUT = Long.MAX_VALUE;
    private Long timeout = null;

    private static final Integer DEFAULT_MAX_WRITE_THREADS = 3;
    private Integer maxWriteThreads = null;

    private Durability durability = Durability.DEFAULT;

    /**
     * Sets the maximum memory to batch before writing. The smaller this value, the more frequently the {@link BatchWriter} will write.<br>
     * If set to a value smaller than a single mutation, then it will {@link BatchWriter#flush()} after each added mutation. Must be non-negative.
     *
     * <p>
     * <b>Default:</b> 50M
     *
     * @param maxMemory
     *          max size in bytes
     * @throws IllegalArgumentException
     *           if {@code maxMemory} is less than 0
     * @return {@code this} to allow chaining of set methods
     */
    public BatchWriterConfig setMaxMemory(long maxMemory) {
        if (maxMemory < 0)
            throw new IllegalArgumentException("Max memory must be non-negative.");
        this.maxMemory = maxMemory;
        return this;
    }

    /**
     * Sets the maximum amount of time to hold the data in memory before flushing it to servers.<br>
     * For no maximum, set to zero, or {@link Long#MAX_VALUE} with {@link TimeUnit#MILLISECONDS}.
     *
     * <p>
     * {@link TimeUnit#MICROSECONDS} or {@link TimeUnit#NANOSECONDS} will be truncated to the nearest {@link TimeUnit#MILLISECONDS}.<br>
     * If this truncation would result in making the value zero when it was specified as non-zero, then a minimum value of one {@link TimeUnit#MILLISECONDS} will
     * be used.
     *
     * <p>
     * <b>Default:</b> 120 seconds
     *
     * @param maxLatency
     *          the maximum latency, in the unit specified by the value of {@code timeUnit}
     * @param timeUnit
     *          determines how {@code maxLatency} will be interpreted
     * @throws IllegalArgumentException
     *           if {@code maxLatency} is less than 0
     * @return {@code this} to allow chaining of set methods
     */
    public BatchWriterConfig setMaxLatency(long maxLatency, TimeUnit timeUnit) {
        if (maxLatency < 0)
            throw new IllegalArgumentException("Negative max latency not allowed " + maxLatency);

        if (maxLatency == 0)
            this.maxLatency = Long.MAX_VALUE;
        else
            // make small, positive values that truncate to 0 when converted use the minimum millis instead
            this.maxLatency = Math.max(1, timeUnit.toMillis(maxLatency));
        return this;
    }

    /**
     * Sets the maximum amount of time an unresponsive server will be re-tried. When this timeout is exceeded, the {@link BatchWriter} should throw an exception.<br>
     * For no timeout, set to zero, or {@link Long#MAX_VALUE} with {@link TimeUnit#MILLISECONDS}.
     *
     * <p>
     * {@link TimeUnit#MICROSECONDS} or {@link TimeUnit#NANOSECONDS} will be truncated to the nearest {@link TimeUnit#MILLISECONDS}.<br>
     * If this truncation would result in making the value zero when it was specified as non-zero, then a minimum value of one {@link TimeUnit#MILLISECONDS} will
     * be used.
     *
     * <p>
     * <b>Default:</b> {@link Long#MAX_VALUE} (no timeout)
     *
     * @param timeout
     *          the timeout, in the unit specified by the value of {@code timeUnit}
     * @param timeUnit
     *          determines how {@code timeout} will be interpreted
     * @throws IllegalArgumentException
     *           if {@code timeout} is less than 0
     * @return {@code this} to allow chaining of set methods
     */
    public BatchWriterConfig setTimeout(long timeout, TimeUnit timeUnit) {
        if (timeout < 0)
            throw new IllegalArgumentException("Negative timeout not allowed " + timeout);

        if (timeout == 0)
            this.timeout = Long.MAX_VALUE;
        else
            // make small, positive values that truncate to 0 when converted use the minimum millis instead
            this.timeout = Math.max(1, timeUnit.toMillis(timeout));
        return this;
    }

    /**
     * Sets the maximum number of threads to use for writing data to the tablet servers.
     *
     * <p>
     * <b>Default:</b> 3
     *
     * @param maxWriteThreads
     *          the maximum threads to use
     * @throws IllegalArgumentException
     *           if {@code maxWriteThreads} is non-positive
     * @return {@code this} to allow chaining of set methods
     */
    public BatchWriterConfig setMaxWriteThreads(int maxWriteThreads) {
        if (maxWriteThreads <= 0)
            throw new IllegalArgumentException("Max threads must be positive " + maxWriteThreads);

        this.maxWriteThreads = maxWriteThreads;
        return this;
    }

    public long getMaxMemory() {
        return maxMemory != null ? maxMemory : DEFAULT_MAX_MEMORY;
    }

    public long getMaxLatency(TimeUnit timeUnit) {
        return timeUnit.convert(maxLatency != null ? maxLatency : DEFAULT_MAX_LATENCY, TimeUnit.MILLISECONDS);
    }

    public long getTimeout(TimeUnit timeUnit) {
        return timeUnit.convert(timeout != null ? timeout : DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
    }

    public int getMaxWriteThreads() {
        return maxWriteThreads != null ? maxWriteThreads : DEFAULT_MAX_WRITE_THREADS;
    }

    /**
     * @since 1.7.0
     * @return the durability to be used by the BatchWriter
     */
    public Durability getDurability() {
        return durability;
    }

    /**
     * Change the durability for the BatchWriter session. The default durability is "default" which is the table's durability setting. If the durability is set to
     * something other than the default, it will override the durability setting of the table.
     *
     * @param durability
     *          the Durability to be used by the BatchWriter
     * @since 1.7.0
     *
     */
    public BatchWriterConfig setDurability(Durability durability) {
        this.durability = durability;
        return this;
    }

    @Override
    public void write(DataOutput out) throws IOException {
        // write this out in a human-readable way
        ArrayList<String> fields = new ArrayList<String>();
        if (maxMemory != null)
            addField(fields, "maxMemory", maxMemory);
        if (maxLatency != null)
            addField(fields, "maxLatency", maxLatency);
        if (maxWriteThreads != null)
            addField(fields, "maxWriteThreads", maxWriteThreads);
        if (timeout != null)
            addField(fields, "timeout", timeout);
        if (durability != Durability.DEFAULT)
            addField(fields, "durability", durability);
        String output = StringUtils.join(",", fields);

        byte[] bytes = output.getBytes(UTF_8);
        byte[] len = String.format("%6s#", Integer.toString(bytes.length, 36)).getBytes(UTF_8);
        if (len.length != 7)
            throw new IllegalStateException("encoded length does not match expected value");
        out.write(len);
        out.write(bytes);
    }

    private void addField(List<String> fields, String name, Object value) {
        String key = StringUtils.escapeString(name, '\\', new char[] { ',', '=' });
        String val = StringUtils.escapeString(String.valueOf(value), '\\', new char[] { ',', '=' });
        fields.add(key + '=' + val);
    }

    @Override
    public void readFields(DataInput in) throws IOException {
        byte[] len = new byte[7];
        in.readFully(len);
        String strLen = new String(len, UTF_8);
        if (!strLen.endsWith("#"))
            throw new IllegalStateException("length was not encoded correctly");
        byte[] bytes = new byte[Integer.parseInt(strLen.substring(strLen.lastIndexOf(' ') + 1, strLen.length() - 1),
                36)];
        in.readFully(bytes);

        String strFields = new String(bytes, UTF_8);
        String[] fields = StringUtils.split(strFields, '\\', ',');
        for (String field : fields) {
            String[] keyValue = StringUtils.split(field, '\\', '=');
            String key = keyValue[0];
            String value = keyValue[1];
            if ("maxMemory".equals(key)) {
                maxMemory = Long.valueOf(value);
            } else if ("maxLatency".equals(key)) {
                maxLatency = Long.valueOf(value);
            } else if ("maxWriteThreads".equals(key)) {
                maxWriteThreads = Integer.valueOf(value);
            } else if ("timeout".equals(key)) {
                timeout = Long.valueOf(value);
            } else if ("durability".equals(key)) {
                durability = DurabilityImpl.fromString(value);
            } else {
                /* ignore any other properties */
            }
        }
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof BatchWriterConfig) {
            BatchWriterConfig other = (BatchWriterConfig) o;

            if (null != maxMemory) {
                if (!maxMemory.equals(other.maxMemory)) {
                    return false;
                }
            } else {
                if (null != other.maxMemory) {
                    return false;
                }
            }

            if (null != maxLatency) {
                if (!maxLatency.equals(other.maxLatency)) {
                    return false;
                }
            } else {
                if (null != other.maxLatency) {
                    return false;
                }
            }

            if (null != maxWriteThreads) {
                if (!maxWriteThreads.equals(other.maxWriteThreads)) {
                    return false;
                }
            } else {
                if (null != other.maxWriteThreads) {
                    return false;
                }
            }

            if (null != timeout) {
                if (!timeout.equals(other.timeout)) {
                    return false;
                }
            } else {
                if (null != other.timeout) {
                    return false;
                }
            }
            if (durability != other.durability) {
                return false;
            }

            return true;
        }

        return false;
    }

    @Override
    public int hashCode() {
        HashCodeBuilder hcb = new HashCodeBuilder();
        hcb.append(maxMemory).append(maxLatency).append(maxWriteThreads).append(timeout).append(durability);
        return hcb.toHashCode();
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(32);
        sb.append("[maxMemory=").append(getMaxMemory()).append(", maxLatency=")
                .append(getMaxLatency(TimeUnit.MILLISECONDS)).append(", maxWriteThreads=")
                .append(getMaxWriteThreads()).append(", timeout=").append(getTimeout(TimeUnit.MILLISECONDS))
                .append(", durability=").append(durability).append("]");
        return sb.toString();
    }
}