1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.yarn.server.timeline.util; 20 21 22 import org.apache.hadoop.io.WritableComparator; 23 24 import java.io.ByteArrayOutputStream; 25 import java.io.IOException; 26 import java.nio.charset.Charset; 27 28 import static org.apache.hadoop.yarn.server.timeline.GenericObjectMapper.readReverseOrderedLong; 29 30 public class LeveldbUtils { 31 32 public static class KeyBuilder { 33 private static final int MAX_NUMBER_OF_KEY_ELEMENTS = 10; 34 private byte[][] b; 35 private boolean[] useSeparator; 36 private int index; 37 private int length; 38 KeyBuilder(int size)39 public KeyBuilder(int size) { 40 b = new byte[size][]; 41 useSeparator = new boolean[size]; 42 index = 0; 43 length = 0; 44 } 45 newInstance()46 public static KeyBuilder newInstance() { 47 return new KeyBuilder(MAX_NUMBER_OF_KEY_ELEMENTS); 48 } 49 add(String s)50 public KeyBuilder add(String s) { 51 return add(s.getBytes(Charset.forName("UTF-8")), true); 52 } 53 add(byte[] t)54 public KeyBuilder add(byte[] t) { 55 return add(t, false); 56 } 57 add(byte[] t, boolean sep)58 public KeyBuilder add(byte[] t, boolean sep) { 59 b[index] = t; 60 useSeparator[index] = sep; 61 length += t.length; 62 if (sep) { 63 length++; 64 } 65 index++; 66 return this; 67 } 68 getBytes()69 public byte[] getBytes() throws IOException { 70 ByteArrayOutputStream baos = new ByteArrayOutputStream(length); 71 for (int i = 0; i < index; i++) { 72 baos.write(b[i]); 73 if (i < index - 1 && useSeparator[i]) { 74 baos.write(0x0); 75 } 76 } 77 return baos.toByteArray(); 78 } 79 getBytesForLookup()80 public byte[] getBytesForLookup() throws IOException { 81 ByteArrayOutputStream baos = new ByteArrayOutputStream(length); 82 for (int i = 0; i < index; i++) { 83 baos.write(b[i]); 84 if (useSeparator[i]) { 85 baos.write(0x0); 86 } 87 } 88 return baos.toByteArray(); 89 } 90 } 91 92 public static class KeyParser { 93 private final byte[] b; 94 private int offset; 95 KeyParser(byte[] b, int offset)96 public KeyParser(byte[] b, int offset) { 97 this.b = b; 98 this.offset = offset; 99 } 100 getNextString()101 public String getNextString() throws IOException { 102 if (offset >= b.length) { 103 throw new IOException( 104 "tried to read nonexistent string from byte array"); 105 } 106 int i = 0; 107 while (offset + i < b.length && b[offset + i] != 0x0) { 108 i++; 109 } 110 String s = new String(b, offset, i, Charset.forName("UTF-8")); 111 offset = offset + i + 1; 112 return s; 113 } 114 getNextLong()115 public long getNextLong() throws IOException { 116 if (offset + 8 >= b.length) { 117 throw new IOException("byte array ran out when trying to read long"); 118 } 119 long l = readReverseOrderedLong(b, offset); 120 offset += 8; 121 return l; 122 } 123 getOffset()124 public int getOffset() { 125 return offset; 126 } 127 } 128 129 /** 130 * Returns true if the byte array begins with the specified prefix. 131 */ prefixMatches(byte[] prefix, int prefixlen, byte[] b)132 public static boolean prefixMatches(byte[] prefix, int prefixlen, 133 byte[] b) { 134 if (b.length < prefixlen) { 135 return false; 136 } 137 return WritableComparator.compareBytes(prefix, 0, prefixlen, b, 0, 138 prefixlen) == 0; 139 } 140 141 } 142