com.metamx.druid.index.v1.MetricHolder.java Source code

Java tutorial

Introduction

Here is the source code for com.metamx.druid.index.v1.MetricHolder.java

Source

/*
 * Druid - a distributed column store.
 * Copyright (C) 2012  Metamarkets Group Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package com.metamx.druid.index.v1;

import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
import com.google.common.io.InputSupplier;
import com.google.common.io.OutputSupplier;
import com.metamx.common.IAE;
import com.metamx.common.ISE;
import com.metamx.druid.index.v1.serde.ComplexMetricSerde;
import com.metamx.druid.index.v1.serde.ComplexMetrics;
import com.metamx.druid.kv.GenericIndexedWriter;
import com.metamx.druid.kv.GenericIndexed;
import com.metamx.druid.kv.Indexed;
import com.metamx.druid.kv.IndexedFloats;
import com.metamx.druid.kv.ObjectStrategy;
import com.metamx.druid.utils.SerializerUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.WritableByteChannel;

/**
 */
public class MetricHolder {
    private static final byte[] version = new byte[] { 0x0 };
    private static final SerializerUtils serializerUtils = new SerializerUtils();

    public static MetricHolder floatMetric(String name, CompressedFloatsIndexedSupplier column) {
        MetricHolder retVal = new MetricHolder(name, "float");
        retVal.floatType = column;
        return retVal;
    }

    public static MetricHolder complexMetric(String name, String typeName, Indexed column) {
        MetricHolder retVal = new MetricHolder(name, typeName);
        retVal.complexType = column;
        return retVal;
    }

    public static void writeComplexMetric(OutputSupplier<? extends OutputStream> outSupplier, String name,
            String typeName, GenericIndexedWriter column) throws IOException {
        OutputStream out = null;
        InputStream in = null;

        try {
            out = outSupplier.getOutput();

            out.write(version);
            serializerUtils.writeString(out, name);
            serializerUtils.writeString(out, typeName);

            final InputSupplier<InputStream> supplier = column.combineStreams();
            in = supplier.getInput();

            ByteStreams.copy(in, out);
        } finally {
            Closeables.closeQuietly(out);
            Closeables.closeQuietly(in);
        }
    }

    public static void writeFloatMetric(OutputSupplier<? extends OutputStream> outSupplier, String name,
            CompressedFloatsSupplierSerializer column) throws IOException {
        ByteStreams.write(version, outSupplier);
        serializerUtils.writeString(outSupplier, name);
        serializerUtils.writeString(outSupplier, "float");
        column.closeAndConsolidate(outSupplier);
    }

    public static void writeToChannel(MetricHolder holder, WritableByteChannel out) throws IOException {
        out.write(ByteBuffer.wrap(version));
        serializerUtils.writeString(out, holder.name);
        serializerUtils.writeString(out, holder.typeName);

        switch (holder.type) {
        case FLOAT:
            holder.floatType.writeToChannel(out);
            break;
        case COMPLEX:
            if (holder.complexType instanceof GenericIndexed) {
                ((GenericIndexed) holder.complexType).writeToChannel(out);
            } else {
                throw new IAE("Cannot serialize out MetricHolder for complex type that is not a GenericIndexed");
            }
            break;
        }
    }

    public static MetricHolder fromByteBuffer(ByteBuffer buf) throws IOException {
        return fromByteBuffer(buf, null);
    }

    public static MetricHolder fromByteBuffer(ByteBuffer buf, ObjectStrategy strategy) throws IOException {
        final byte ver = buf.get();
        if (version[0] != ver) {
            throw new ISE("Unknown version[%s] of MetricHolder", ver);
        }

        final String metricName = serializerUtils.readString(buf);
        final String typeName = serializerUtils.readString(buf);
        MetricHolder holder = new MetricHolder(metricName, typeName);

        switch (holder.type) {
        case FLOAT:
            holder.floatType = CompressedFloatsIndexedSupplier.fromByteBuffer(buf, ByteOrder.nativeOrder());
            break;
        case COMPLEX:
            if (strategy != null) {
                holder.complexType = GenericIndexed.read(buf, strategy);
            } else {
                final ComplexMetricSerde serdeForType = ComplexMetrics.getSerdeForType(holder.getTypeName());

                if (serdeForType == null) {
                    throw new ISE("Unknown type[%s], cannot load.", holder.getTypeName());
                }

                holder.complexType = GenericIndexed.read(buf, serdeForType.getObjectStrategy());
            }
            break;
        }

        return holder;
    }

    private final String name;
    private final String typeName;
    private final MetricType type;

    public enum MetricType {
        FLOAT, COMPLEX;

        static MetricType determineType(String typeName) {
            if ("float".equalsIgnoreCase(typeName)) {
                return FLOAT;
            }
            return COMPLEX;
        }
    }

    CompressedFloatsIndexedSupplier floatType = null;
    Indexed complexType = null;

    private MetricHolder(String name, String typeName) {
        this.name = name;
        this.typeName = typeName;
        this.type = MetricType.determineType(typeName);
    }

    public String getName() {
        return name;
    }

    public String getTypeName() {
        return typeName;
    }

    public MetricType getType() {
        return type;
    }

    public IndexedFloats getFloatType() {
        assertType(MetricType.FLOAT);
        return floatType.get();
    }

    public Indexed getComplexType() {
        assertType(MetricType.COMPLEX);
        return complexType;
    }

    public MetricHolder convertByteOrder(ByteOrder order) {
        switch (type) {
        case FLOAT:
            MetricHolder retVal = new MetricHolder(name, typeName);
            retVal.floatType = floatType.convertByteOrder(order);
            return retVal;
        case COMPLEX:
            return this;
        }

        return null;
    }

    private void assertType(MetricType type) {
        if (this.type != type) {
            throw new IAE("type[%s] cannot be cast to [%s]", typeName, type);
        }
    }
}