Package com.nearinfinity.honeycomb.mysql

Source Code of com.nearinfinity.honeycomb.mysql.Util

/*
* 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.
*
* Copyright 2013 Near Infinity Corporation.
*/


package com.nearinfinity.honeycomb.mysql;

import com.google.common.collect.*;
import com.nearinfinity.honeycomb.exceptions.RuntimeIOException;
import com.nearinfinity.honeycomb.mysql.schema.IndexSchema;
import org.apache.avro.io.*;
import org.apache.log4j.Logger;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
* Utility class containing helper functions.
*/
public class Util {
    public static final int UUID_WIDTH = 16;
    private static final Logger logger = Logger.getLogger(Util.class);

    /**
     * Returns a byte wide buffer from a {@link UUID}.
     *
     * @param uuid The {@link UUID} to convert
     * @return A byte array representation that is {@value #UUID_WIDTH} bytes wide
     */
    public static byte[] UUIDToBytes(UUID uuid) {
        checkNotNull(uuid, "uuid must not be null.");
        return ByteBuffer.allocate(UUID_WIDTH)
                .putLong(uuid.getMostSignificantBits())
                .putLong(uuid.getLeastSignificantBits())
                .array();
    }

    /**
     * Create a {@link UUID} from the provided byte array.
     *
     * @param bytes A byte array that must be {@value #UUID_WIDTH} bytes wide, not null
     * @return A {@link UUID} representation
     */
    public static UUID bytesToUUID(byte[] bytes) {
        checkNotNull(bytes, "bytes must not be null.");
        checkArgument(bytes.length == UUID_WIDTH, "bytes must be of length " + UUID_WIDTH + ".");
        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        return new UUID(buffer.getLong(), buffer.getLong());
    }

    /**
     * Serialize an object to a byte array
     *
     * @param obj    The object to serialize
     * @param writer The datum writer for the class
     * @return Serialized row
     */
    public static <T> byte[] serializeAvroObject(T obj, DatumWriter<T> writer) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Encoder encoder = EncoderFactory.get().binaryEncoder(out, null);

        try {
            writer.write(obj, encoder);
            encoder.flush();
        } catch (IOException e) {
            throw serializationError(obj, e);
        }

        return out.toByteArray();
    }

    /**
     * Deserialize the provided serialized data into an instance of the specified class type
     *
     * @param serializedData a buffer containing the serialized data
     * @param reader         the datum reader for the class
     * @return A new instance of the specified class representing the deserialized data
     */
    public static <T> T deserializeAvroObject(byte[] serializedData, DatumReader<T> reader) {
        checkNotNull(serializedData);
        checkNotNull(reader);

        Decoder binaryDecoder = DecoderFactory.get().binaryDecoder(serializedData, null);
        try {
            return reader.read(null, binaryDecoder);
        } catch (IOException e) {
            throw deserializationError(serializedData, e, null);
        }
    }

    /**
     * Create a hex string for a byte string. The string will be formatted {@code "A2BE"}
     *
     * @param bytes Byte string
     * @return Hex string
     */
    public static String generateHexString(final byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }

        return sb.toString();
    }

    /**
     * Quietly close a {@link Closeable} suppressing the IOException thrown
     *
     * @param closeable Closeable
     */
    public static void closeQuietly(Closeable closeable) {
        try {
            closeable.close();
        } catch (IOException e) {
            logger.error(String.format("IOException thrown while closing resource of type %s", closeable.getClass().getName()), e);
            throw new RuntimeIOException(e);
        }
    }

    /**
     * Retrieve from a list of indices which ones have been changed.
     *
     * @param indices    Table indices
     * @param oldRecords Old MySQL row
     * @param newRecords New MySQL row
     * @return List of changed indices
     */
    public static ImmutableList<IndexSchema> getChangedIndices(Collection<IndexSchema> indices,
                                                               Map<String, ByteBuffer> oldRecords,
                                                               Map<String, ByteBuffer> newRecords) {
        if (indices.isEmpty()) {
            return ImmutableList.of();
        }

        MapDifference<String, ByteBuffer> diff = Maps.difference(oldRecords,
                newRecords);

        Set<String> changedColumns = Sets.difference(
                Sets.union(newRecords.keySet(), oldRecords.keySet()),
                diff.entriesInCommon().keySet());

        ImmutableList.Builder<IndexSchema> changedIndices = ImmutableList.builder();

        for (IndexSchema index : indices) {
            Set<String> indexColumns = ImmutableSet.copyOf(index.getColumns());
            if (!Sets.intersection(changedColumns, indexColumns).isEmpty()) {
                changedIndices.add(index);
            }
        }

        return changedIndices.build();
    }

    private static <T> RuntimeException deserializationError(byte[] serializedData, IOException e, Class<T> clazz) {
        String clazzMessage = clazz == null ? "" : "of class type " + clazz.getName();
        String format = String.format("Deserialization failed for data (%s) " + clazzMessage,
                Util.generateHexString(serializedData));
        logger.error(format, e);
        return new RuntimeException(format, e);
    }

    private static <T> RuntimeException serializationError(T obj, IOException e) {
        String format = String.format("Serialization failed for data (%s) of class type %s",
                obj.toString(), obj.getClass().getName());
        logger.error(format, e);
        return new RuntimeException(format, e);
    }
}
TOP

Related Classes of com.nearinfinity.honeycomb.mysql.Util

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.