All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kairosdb.util.Util Maven / Gradle / Ivy

Go to download

KairosDB is a time series database that stores numeric values along with key/value tags to a nosql data store. Currently supported backends are Cassandra and H2. An H2 implementation is provided for development work.

There is a newer version: 1.3.0-1
Show newest version
/*
 * Copyright 2013 Proofpoint Inc.
 *
 *    Licensed 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.kairosdb.util;


import com.google.common.collect.ImmutableList;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.kairosdb.core.datastore.Sampling;

import java.io.*;
import java.net.*;
import java.util.Collections;
import java.util.List;

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

public class Util
{
	/**
	 Special thanks to Nadeau software consulting for publishing this code.
	 http://nadeausoftware.com/node/97
	 @param s string representation of number to parse
	 @return number
	 */
	public static long parseLong( final CharSequence s )
	{
		if ( s == null )
			throw new NumberFormatException( "Null string" );

		// Check for a sign.
		long num  = 0;
		long sign = -1;
		final int len  = s.length( );
		final char ch  = s.charAt( 0 );
		if ( ch == '-' )
		{
			if ( len == 1 )
				throw new NumberFormatException( "Missing digits:  " + s );
			sign = 1;
		}
		else
		{
			final int d = ch - '0';
			if ( d < 0 || d > 9 )
				throw new NumberFormatException( "Malformed:  " + s );
			num = -d;
		}

		// Build the number.
		final long max = (sign == -1L) ?
				-Long.MAX_VALUE : Long.MIN_VALUE;
		final long multmax = max / 10;
		int i = 1;
		while ( i < len )
		{
			long d = s.charAt(i++) - '0';
			if ( d < 0L || d > 9L )
				throw new NumberFormatException( "Malformed:  " + s );
			if ( num < multmax )
				throw new NumberFormatException( "Over/underflow:  " + s );
			num *= 10;
			if ( num < (max+d) )
				throw new NumberFormatException( "Over/underflow:  " + s );
			num -= d;
		}

		return sign * num;
	}

	/**
	 * Returns the host name. First tries to execute "hostname" on the machine. This should work for Linux, Windows,
	 * and Mac. If, for some reason hostname fails, then get the name from InetAddress (which might change depending
	 * on network setup)
	 *
	 * @return hostname
	 */
	public static String getHostName()
	{
		try
		{
			Runtime run = Runtime.getRuntime();
			Process process = run.exec("hostname");
			InputStreamReader isr = new InputStreamReader(process.getInputStream());
			BufferedReader br = new BufferedReader(isr);

			// Need to read all lines from the stream or the process could hang
			StringBuilder buffer = new StringBuilder();
			String line;
			while ((line = br.readLine()) != null)
				buffer.append(line);

			int returnValue = process.waitFor();
			if (returnValue == 0)
				return buffer.toString();
		}
		catch (Exception e)
		{
			// ignore
		}

		try
		{
			return InetAddress.getLocalHost().getHostName();
		}
		catch (UnknownHostException e)
		{
			return "";
		}
	}

	public static void packUnsignedLong(long value, DataOutput buffer) throws IOException
	{
		/* Encodes a value using the variable-length encoding from
		
		Google Protocol Buffers. Zig-zag is not used, so input must not be negative.
		If values can be negative, use {@link #writeSignedVarLong(long, DataOutput)}
		instead. This method treats negative input as like a large unsigned value. */
		while ((value & ~0x7FL) != 0L)
		{
			buffer.writeByte((int) ((value & 0x7F) | 0x80));
			value >>>= 7;
		}
		buffer.writeByte((int) value);
	}

	public static long unpackUnsignedLong(DataInput buffer) throws IOException
	{
		int shift = 0;
		long result = 0;
		while (shift < 64)
		{
			final byte b = buffer.readByte();
			result |= (long)(b & 0x7F) << shift;
			if ((b & 0x80) == 0)
			{
				return result;
			}
			shift += 7;
		}
		throw new IllegalArgumentException("Variable length quantity is too long");
	}

	public static void packLong(long value, DataOutput buffer) throws IOException
	{
		// Great trick from http://code.google.com/apis/protocolbuffers/docs/encoding.html#types
		packUnsignedLong((value << 1) ^ (value >> 63), buffer);

	}

	public static long unpackLong(DataInput buffer) throws IOException
	{
		long value = unpackUnsignedLong(buffer);

		return ((value >>> 1) ^ -(value & 1));
	}

	public static InetAddress findPublicIp()
	{
		// Check if local host address is a good v4 address
		InetAddress localAddress = null;
		try {
			localAddress = InetAddress.getLocalHost();
			if (isGoodV4Address(localAddress)) {
				return localAddress;
			}
		}
		catch (UnknownHostException ignored) {
		}
		if (localAddress == null) {
			try {
				localAddress = InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
			}
			catch (UnknownHostException e) {
				throw new AssertionError("Could not get local ip address");
			}
		}

		// check all up network interfaces for a good v4 address
		for (NetworkInterface networkInterface : getGoodNetworkInterfaces()) {
			for (InetAddress address : Collections.list(networkInterface.getInetAddresses())) {
				if (isGoodV4Address(address)) {
					return address;
				}
			}
		}
		// check all up network interfaces for a good v6 address
		for (NetworkInterface networkInterface : getGoodNetworkInterfaces()) {
			for (InetAddress address : Collections.list(networkInterface.getInetAddresses())) {
				if (isGoodV6Address(address)) {
					return address;
				}
			}
		}
		// just return the local host address
		// it is most likely that this is a disconnected developer machine
		return localAddress;
	}

	/**
	 Returns true if the string contains a number. This means it contains only digits, the minus sign, plus sign
	 and a period.

	 @param s string to test
	 @return true if only contains a number value
	 */
	public static boolean isNumber(String s)
	{
		checkNotNull(s);

		if (s.isEmpty())
			return false;

		int start = 0;
		char firstChar = s.charAt(0);
		if (firstChar == '+' || firstChar == '-' || firstChar == '.')
		{
			start = 1;
			if (s.length() == 1)
				return false;
		}

		for (int i = start; i < s.length(); i++)
		{
			char c = s.charAt(i);
			if (!Character.isDigit(c) && c != '.')
				return false;
		}

		//noinspection RedundantIfStatement
		if (s.charAt(s.length() - 1) == '.')
			return false; // can't have trailing period

		return true;
	}

	private static List getGoodNetworkInterfaces()
	{
		ImmutableList.Builder builder = ImmutableList.builder();
		try {
			for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) {
				try {
					if (!networkInterface.isLoopback() && networkInterface.isUp()) {
						builder.add(networkInterface);
					}
				}
				catch (Exception ignored) {
				}
			}
		}
		catch (SocketException ignored) {
		}
		return builder.build();
	}

	private static boolean isGoodV4Address(InetAddress address)
	{
		return address instanceof Inet4Address &&
				!address.isAnyLocalAddress() &&
				!address.isLoopbackAddress() &&
				!address.isMulticastAddress();
	}

	private static boolean isGoodV6Address(InetAddress address)
	{
		return address instanceof Inet6Address &&
				!address.isAnyLocalAddress() &&
				!address.isLoopbackAddress() &&
				!address.isMulticastAddress();
	}


	/**
	 Computes the duration of the sampling (value * unit) starting at timestamp.

	 @param timestamp unix timestamp of the start time.
	 @return the duration of the sampling in millisecond.
	 */
	public static long getSamplingDuration(long timestamp, Sampling sampling, DateTimeZone timeZone)
	{
		long ret = sampling.getValue();
		DateTime dt = new DateTime(timestamp, timeZone);
		switch (sampling.getUnit())
		{
			case YEARS:
				ret = new org.joda.time.Duration(dt, dt.plusYears((int)sampling.getValue())).getMillis();
				break;
			case MONTHS:
				ret = new org.joda.time.Duration(dt, dt.plusMonths((int)sampling.getValue())).getMillis();
				break;
			case WEEKS:
				ret = new org.joda.time.Duration(dt, dt.plusWeeks((int)sampling.getValue())).getMillis();
				break;
			case DAYS:
				ret = new org.joda.time.Duration(dt, dt.plusDays((int)sampling.getValue())).getMillis();
				break;
			case HOURS:
				ret = new org.joda.time.Duration(dt, dt.plusHours((int)sampling.getValue())).getMillis();
				break;
			case MINUTES:
				ret = new org.joda.time.Duration(dt, dt.plusMinutes((int)sampling.getValue())).getMillis();
				break;
			case SECONDS:
				ret = new org.joda.time.Duration(dt, dt.plusSeconds((int)sampling.getValue())).getMillis();
				break;
			case MILLISECONDS:
				ret = (long) sampling.getValue();
				break;
		}
		return ret;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy