com.persistit.util.Util Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of akiban-persistit Show documentation
Show all versions of akiban-persistit Show documentation
Java B+Tree Key-Value Store Library
/**
* Copyright © 2005-2012 Akiban Technologies, Inc. All rights reserved.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* This program may also be available under different license terms.
* For more information, see www.akiban.com or contact [email protected].
*
* Contributors:
* Akiban Technologies, Inc.
*/
package com.persistit.util;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Pattern;
import com.persistit.KeyState;
import com.persistit.Persistit;
import com.persistit.ValueState;
import com.persistit.exception.AppendableIOException;
import com.persistit.exception.PersistitInterruptedException;
/**
* @author pbeaman
*/
public class Util {
final static byte[] NULLS = new byte[1024];
final static String SPACES = " ";
private final static String UTF8 = "UTF-8";
public final static String NEW_LINE = System.getProperty("line.separator");
private final static String REGEX_QUOTE = "^$*+?()[].";
public final static long NS_PER_S = 1000000000L;
public final static long MS_PER_S = 1000L;
public final static long NS_PER_MS = 1000000L;
public final static char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
'E', 'F' };
public static int getByte(final byte[] bytes, final int index) {
return (bytes[index + 0] & 0xFF);
}
public static int getShort(final byte[] bytes, final int index) {
if (Persistit.BIG_ENDIAN) {
return (bytes[index + 1] & 0xFF) | (bytes[index + 0]) << 8;
} else {
return (bytes[index + 0] & 0xFF) | (bytes[index + 1]) << 8;
}
}
public static int getChar(final byte[] bytes, final int index) {
if (Persistit.BIG_ENDIAN) {
return (bytes[index + 1] & 0xFF) | (bytes[index + 0] & 0xFF) << 8;
} else {
return (bytes[index + 0] & 0xFF) | (bytes[index + 1] & 0xFF) << 8;
}
}
public static int getInt(final byte[] bytes, final int index) {
if (Persistit.BIG_ENDIAN) {
return (bytes[index + 3] & 0xFF) | (bytes[index + 2] & 0xFF) << 8 | (bytes[index + 1] & 0xFF) << 16
| (bytes[index + 0] & 0xFF) << 24;
} else {
return (bytes[index + 0] & 0xFF) | (bytes[index + 1] & 0xFF) << 8 | (bytes[index + 2] & 0xFF) << 16
| (bytes[index + 3] & 0xFF) << 24;
}
}
public static long getLong(final byte[] bytes, final int index) {
if (Persistit.BIG_ENDIAN) {
return (bytes[index + 7] & 0xFF) | (long) (bytes[index + 6] & 0xFF) << 8
| (long) (bytes[index + 5] & 0xFF) << 16 | (long) (bytes[index + 4] & 0xFF) << 24
| (long) (bytes[index + 3] & 0xFF) << 32 | (long) (bytes[index + 2] & 0xFF) << 40
| (long) (bytes[index + 1] & 0xFF) << 48 | (long) (bytes[index + 0] & 0xFF) << 56;
} else {
return (bytes[index + 0] & 0xFF) | (long) (bytes[index + 1] & 0xFF) << 8
| (long) (bytes[index + 2] & 0xFF) << 16 | (long) (bytes[index + 3] & 0xFF) << 24
| (long) (bytes[index + 4] & 0xFF) << 32 | (long) (bytes[index + 5] & 0xFF) << 40
| (long) (bytes[index + 6] & 0xFF) << 48 | (long) (bytes[index + 7] & 0xFF) << 56;
}
}
public static void putByte(final byte[] bytes, final int index, final int value) {
bytes[index + 0] = (byte) (value);
}
public static void putShort(final byte[] bytes, final int index, final int value) {
if (Persistit.BIG_ENDIAN) {
bytes[index + 1] = (byte) (value);
bytes[index + 0] = (byte) (value >>> 8);
} else {
bytes[index + 0] = (byte) (value);
bytes[index + 1] = (byte) (value >>> 8);
}
}
public static void putChar(final byte[] bytes, final int index, final int value) {
if (Persistit.BIG_ENDIAN) {
bytes[index + 1] = (byte) (value);
bytes[index + 0] = (byte) (value >>> 8);
} else {
bytes[index + 0] = (byte) (value);
bytes[index + 1] = (byte) (value >>> 8);
}
}
public static void putInt(final byte[] bytes, final int index, final int value) {
if (Persistit.BIG_ENDIAN) {
bytes[index + 3] = (byte) (value);
bytes[index + 2] = (byte) (value >>> 8);
bytes[index + 1] = (byte) (value >>> 16);
bytes[index + 0] = (byte) (value >>> 24);
} else {
bytes[index + 0] = (byte) (value);
bytes[index + 1] = (byte) (value >>> 8);
bytes[index + 2] = (byte) (value >>> 16);
bytes[index + 3] = (byte) (value >>> 24);
}
}
public static void putLong(final byte[] bytes, final int index, final long value) {
if (Persistit.BIG_ENDIAN) {
bytes[index + 7] = (byte) (value);
bytes[index + 6] = (byte) (value >>> 8);
bytes[index + 5] = (byte) (value >>> 16);
bytes[index + 4] = (byte) (value >>> 24);
bytes[index + 3] = (byte) (value >>> 32);
bytes[index + 2] = (byte) (value >>> 40);
bytes[index + 1] = (byte) (value >>> 48);
bytes[index + 0] = (byte) (value >>> 56);
} else {
bytes[index + 0] = (byte) (value);
bytes[index + 1] = (byte) (value >>> 8);
bytes[index + 2] = (byte) (value >>> 16);
bytes[index + 3] = (byte) (value >>> 24);
bytes[index + 4] = (byte) (value >>> 32);
bytes[index + 5] = (byte) (value >>> 40);
bytes[index + 6] = (byte) (value >>> 48);
bytes[index + 7] = (byte) (value >>> 56);
}
}
public static int putBytes(final byte[] bytes, final int index, final byte[] value) {
System.arraycopy(value, 0, bytes, index, value.length);
return value.length;
}
public static boolean changeBytes(final byte[] bytes, final int index, final byte[] value) {
final boolean same = equalsByteSubarray(bytes, index, value);
if (same) {
return false;
} else {
putBytes(bytes, index, value);
return true;
}
}
public static boolean changeByte(final byte[] bytes, final int index, final byte value) {
if (getByte(bytes, index) == value) {
return false;
} else {
putByte(bytes, index, value);
return true;
}
}
public static boolean changeChar(final byte[] bytes, final int index, final char value) {
if (getChar(bytes, index) == value) {
return false;
} else {
putChar(bytes, index, value);
return true;
}
}
public static boolean changeShort(final byte[] bytes, final int index, final short value) {
if (getShort(bytes, index) == value) {
return false;
} else {
putShort(bytes, index, value);
return true;
}
}
public static boolean changeInt(final byte[] bytes, final int index, final int value) {
if (getInt(bytes, index) == value) {
return false;
} else {
putInt(bytes, index, value);
return true;
}
}
public static boolean changeLong(final byte[] bytes, final int index, final long value) {
if (getLong(bytes, index) == value) {
return false;
} else {
putLong(bytes, index, value);
return true;
}
}
public static String format(final String s, final int width, final boolean right) {
final int pad = width - s.length();
if (pad < 0)
return s.substring(0, width - 1) + "&";
if (pad == 0)
return s;
if (right)
return SPACES.substring(0, pad) + s;
else
return s + SPACES.substring(0, pad);
}
public static String format(final int i) {
return format(i, 10);
}
public static String format(final long i) {
return format(i, 22);
}
public static String format(final long i, final int width) {
return format(Long.toString(i), width, true);
}
public static String abridge(final String s, final int maxLength) {
if (s.length() > maxLength) {
return s.substring(0, maxLength - 3) + "...";
} else {
return s;
}
}
public static boolean equalsByteSubarray(final byte[] source, final int next, final byte[] target) {
return equalsByteSubarray(source, next, target, 0, target.length);
}
public static boolean equalsByteSubarray(final byte[] source, final int soffset, final byte[] target,
final int toffset, final int length) {
for (int index = 0; index < length; index++) {
if (source[soffset + index] != target[toffset + index])
return false;
}
return true;
}
public static void fill(final StringBuilder sb, final long value, final int width) {
fill(sb, Long.toString(value), width);
}
public static void fill(final StringBuilder sb, final String s, final int width) {
for (int i = s.length(); i < width; i++)
sb.append(' ');
sb.append(s);
}
public static String dump(final KeyState ks) {
final byte[] bytes = ks.getBytes();
return dump(bytes, 0, bytes.length);
}
public static String dump(final ValueState vs) {
final byte[] bytes = vs.getEncodedBytes();
return dump(bytes, 0, bytes.length);
}
public static String dump(final byte[] b, final int offset, final int size) {
final StringBuilder sb = new StringBuilder();
final StringBuilder sb2 = new StringBuilder();
for (int m = 0; m < size - offset; m += 16) {
sb2.setLength(0);
hex(sb, m, 4);
sb.append(": ");
for (int i = 0; i < 16; i++) {
sb.append(" ");
if (i % 8 == 0)
sb.append(" ");
final int j = m + i;
if (j < size - offset) {
hex(sb, b[j + offset], 2);
final char c = (char) (b[j + offset] & 0xFF);
if (c >= 32 && c < 127)
sb2.append(c);
else
sb2.append(".");
} else
sb.append(" ");
}
sb.append(" ");
sb.append(sb2.toString());
sb.append(NEW_LINE);
}
return sb.toString();
}
public static String dump(final char[] c, final int offset, final int size) {
final StringBuilder sb = new StringBuilder();
final StringBuilder sb2 = new StringBuilder();
for (int m = 0; m < size - offset; m += 8) {
sb2.setLength(0);
hex(sb, m, 4);
sb.append(":");
for (int i = 0; i < 8; i++) {
sb.append(" ");
if (i % 4 == 0)
sb.append(" ");
final int j = m + i;
if (j < size - offset) {
hex(sb, c[j + offset], 4);
if (c[j + offset] >= 32 && c[j] < 127)
sb2.append(c[j]);
else
sb2.append(".");
} else
sb.append(" ");
}
sb.append(" ");
sb.append(sb2.toString());
sb.append(NEW_LINE);
}
return sb.toString();
}
public static String hexDump(final byte[] b) {
return hexDump(b, 0, b.length);
}
public static String hexDump(final byte[] b, final int offset, final int length) {
final StringBuilder sb = new StringBuilder();
final StringBuilder sb2 = new StringBuilder();
sb2.setLength(0);
for (int i = offset; i < offset + length; i++) {
sb.append(" ");
hex(sb, b[i], 2);
final char c = (char) (b[i] & 0xFF);
if (c >= 32 && c < 127)
sb2.append(c);
else
sb2.append(".");
}
sb.append(" / ");
sb.append(sb2.toString());
return sb.toString();
}
public static Appendable hex(final Appendable sb, final long value, final int length) {
for (int i = length - 1; i >= 0; i--) {
append(sb, HEX_DIGITS[(int) (value >> (i * 4)) & 0xF]);
}
return sb;
}
public static byte[] stringToBytes(final String s) {
if (s == null)
return new byte[0];
try {
return s.getBytes(UTF8);
} catch (final UnsupportedEncodingException e) {
return s.getBytes();
}
}
public static boolean isValidName(final String s) {
if (s == null || s.length() == 0)
return false;
if (!Character.isJavaIdentifierStart(s.charAt(0)))
return false;
for (int i = 1; i < s.length(); i++) {
if (!Character.isJavaIdentifierPart(s.charAt(i)))
return false;
}
return true;
}
public static String bytesToHex(final byte[] bytes) {
final StringBuilder sb = new StringBuilder();
bytesToHex(sb, bytes, 0, bytes.length);
return sb.toString();
}
public static void bytesToHex(final Appendable sb, final byte[] bytes, final int offset, int length) {
length += offset;
for (int i = offset; i < length; i++) {
append(sb, HEX_DIGITS[(bytes[i] >>> 4) & 0x0F]);
append(sb, HEX_DIGITS[(bytes[i] >>> 0) & 0x0F]);
}
}
public static byte[] hexToBytes(final String hex) {
int count = 0;
for (int i = 0; i < hex.length(); i++) {
final int c = hex.charAt(i);
if (c == '/' || c == '}')
break;
if (c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F') {
count++;
} else if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
throw new IllegalArgumentException();
}
}
if ((count % 2) == 1)
throw new IllegalArgumentException();
final byte[] result = new byte[count / 2];
int t = 0;
count = 0;
for (int i = 0; i < hex.length(); i++) {
final int c = hex.charAt(i);
if (c == '/' || c == '}')
break;
if (c >= '0' && c <= '9') {
t = t * 16 + c - '0';
} else if (c >= 'a' && c <= 'f') {
t = t * 16 + c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
t = t * 16 + c - 'A' + 10;
} else
continue;
count++;
if ((count % 2) == 0) {
result[(count / 2) - 1] = (byte) t;
t = 0;
}
}
return result;
}
public static String replaceFileSuffix(final String name, final String suffix) {
//
// If suffix is a full path, return it.
//
if (suffix.indexOf('/') >= 0 || suffix.indexOf('\\') > 0)
return suffix;
//
// Find final file separator
//
int p = name.lastIndexOf('/');
p = Math.max(p, name.lastIndexOf('\\'));
//
// Just replace the extension - i.e., the part of the path name to the
// right of the period.
//
if (suffix.startsWith(".")) {
final int q = name.lastIndexOf('.');
if (q > p)
p = q - 1;
}
if (p > 0)
return name.substring(0, p + 1) + suffix;
else
return name + suffix;
}
public static void clearBytes(final byte[] bytes, final int from, final int to) {
for (int offset = from; offset < to; offset += NULLS.length) {
int count = to - offset;
if (count > NULLS.length)
count = NULLS.length;
System.arraycopy(NULLS, 0, bytes, offset, count);
}
}
public static void appendQuotedString(final Appendable sb, final String s, final int start, final int length) {
final int end = Math.min(start + length, s.length());
for (int index = start; index < end; index++) {
appendQuotedChar(sb, s.charAt(index));
}
}
public static void append(final Appendable sb, final char c) {
try {
sb.append(c);
} catch (final IOException e) {
throw new AppendableIOException(e);
}
}
public static void append(final Appendable sb, final CharSequence s) {
try {
sb.append(s);
} catch (final IOException e) {
throw new AppendableIOException(e);
}
}
public static void appendQuotedChar(final Appendable sb, final int c) {
int q = 0;
if (c == '\b')
q = 'b';
else if (c == '\n')
q = 'n';
else if (c == '\r')
q = 'r';
else if (c == '\t')
q = 't';
else if (c == '\"' || c == '\\')
q = c;
if (q != 0) {
append(sb, '\\');
append(sb, (char) q);
} else if (c >= 127 || c < 20) {
append(sb, '\\');
append(sb, 'u');
Util.hex(sb, c, 4);
} else
append(sb, (char) c);
}
public static String date(final long t) {
if (t == 0) {
return "none";
} else {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(t));
}
}
public static void println(final String template, final Object... args) {
System.out.println(String.format(template, args));
}
/**
* Utility method to determine whether a subarray of bytes in a byte-array
* source
matches the byte-array in target
.
*
* @param source
* The source byte array
* @param offset
* The offset of the sub-array within the source.
* @param target
* The target byte array
* @return true
if the byte subarrays are equal
*/
public static boolean bytesEqual(final byte[] source, final int offset, final byte[] target) {
for (int index = 0; index < target.length; index++) {
if (source[index + offset] != target[index]) {
return false;
}
}
return true;
}
public static void sleep(final long millis) throws PersistitInterruptedException {
try {
Thread.sleep(millis);
} catch (final InterruptedException ie) {
throw new PersistitInterruptedException(ie);
}
}
public static void spinSleep() throws PersistitInterruptedException {
sleep(1);
}
public static String toString(final Object object) {
return object == null ? null : object.toString();
}
public static int rangeCheck(final int value, final int min, final int max) {
if (value >= min && value <= max) {
return value;
}
if (min == Integer.MIN_VALUE) {
throw new IllegalArgumentException(String.format("Value must be less than or equals to %,d: %,d", max,
value));
}
if (max == Integer.MAX_VALUE) {
throw new IllegalArgumentException(String.format("Value must be greater than or equal to %,d: %,d", min,
value));
} else {
throw new IllegalArgumentException(String.format("Value must be between %d and %d, inclusive: ", min, max,
value));
}
}
public static long rangeCheck(final long value, final long min, final long max) {
if (value >= min && value <= max) {
return value;
}
if (min == Long.MIN_VALUE) {
throw new IllegalArgumentException(String.format("Value must be less than or equals to %,d: %,d", max,
value));
}
if (max == Long.MAX_VALUE) {
throw new IllegalArgumentException(String.format("Value must be greater than or equal to %,d: %,d", min,
value));
} else {
throw new IllegalArgumentException(String.format("Value must be between %d and %d, inclusive: ", min, max,
value));
}
}
public static float rangeCheck(final float value, final float min, final float max) {
if (value >= min && value <= max) {
return value;
}
if (min == Float.MIN_VALUE) {
throw new IllegalArgumentException(String.format("Value must be less than or equals to %,f: %,f", max,
value));
}
if (max == Float.MAX_VALUE) {
throw new IllegalArgumentException(String.format("Value must be greater than or equal to %,f: %,f", min,
value));
} else {
throw new IllegalArgumentException(String.format("Value must be between %f and %f, inclusive: ", min, max,
value));
}
}
public static Pattern pattern(final String s, final boolean caseInsensitive) {
final StringBuilder sb = new StringBuilder();
if (s == null) {
sb.append(".*");
} else {
for (int index = 0; index < s.length(); index++) {
final char c = s.charAt(index);
if (c == '*') {
sb.append(".*");
} else if (c == '?') {
sb.append(".");
} else if (REGEX_QUOTE.indexOf(c) != -1) {
sb.append('\\');
sb.append(c);
} else {
sb.append(c);
}
}
}
return Pattern.compile(sb.toString(), caseInsensitive ? Pattern.CASE_INSENSITIVE : 0);
}
}