http://git-wip-us.apache.org/repos/asf/hbase/blob/6786b2b6/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnknownFieldSetLite.java ---------------------------------------------------------------------- diff --git a/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnknownFieldSetLite.java b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnknownFieldSetLite.java new file mode 100644 index 0000000..faa4c30 --- /dev/null +++ b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnknownFieldSetLite.java @@ -0,0 +1,432 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package org.apache.hadoop.hbase.shaded.com.google.protobuf; + +import java.io.IOException; +import java.util.Arrays; + +/** + * {@code UnknownFieldSetLite} is used to keep track of fields which were seen + * when parsing a protocol message but whose field numbers or types are + * unrecognized. This most frequently occurs when new fields are added to a + * message type and then messages containing those fields are read by old + * software that was compiled before the new types were added. + * + * <p>For use by generated code only. + * + * @author dw...@google.com (Daniel Weis) + */ +public final class UnknownFieldSetLite { + + // Arbitrarily chosen. + // TODO(dweis): Tune this number? + private static final int MIN_CAPACITY = 8; + + private static final UnknownFieldSetLite DEFAULT_INSTANCE = + new UnknownFieldSetLite(0, new int[0], new Object[0], false /* isMutable */); + + /** + * Get an empty {@code UnknownFieldSetLite}. + * + * <p>For use by generated code only. + */ + public static UnknownFieldSetLite getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + /** + * Returns a new mutable instance. + */ + static UnknownFieldSetLite newInstance() { + return new UnknownFieldSetLite(); + } + + /** + * Returns a mutable {@code UnknownFieldSetLite} that is the composite of {@code first} and + * {@code second}. + */ + static UnknownFieldSetLite mutableCopyOf(UnknownFieldSetLite first, UnknownFieldSetLite second) { + int count = first.count + second.count; + int[] tags = Arrays.copyOf(first.tags, count); + System.arraycopy(second.tags, 0, tags, first.count, second.count); + Object[] objects = Arrays.copyOf(first.objects, count); + System.arraycopy(second.objects, 0, objects, first.count, second.count); + return new UnknownFieldSetLite(count, tags, objects, true /* isMutable */); + } + + /** + * The number of elements in the set. + */ + private int count; + + /** + * The tag numbers for the elements in the set. + */ + private int[] tags; + + /** + * The boxed values of the elements in the set. + */ + private Object[] objects; + + /** + * The lazily computed serialized size of the set. + */ + private int memoizedSerializedSize = -1; + + /** + * Indicates that this object is mutable. + */ + private boolean isMutable; + + /** + * Constructs a mutable {@code UnknownFieldSetLite}. + */ + private UnknownFieldSetLite() { + this(0, new int[MIN_CAPACITY], new Object[MIN_CAPACITY], true /* isMutable */); + } + + /** + * Constructs the {@code UnknownFieldSetLite}. + */ + private UnknownFieldSetLite(int count, int[] tags, Object[] objects, boolean isMutable) { + this.count = count; + this.tags = tags; + this.objects = objects; + this.isMutable = isMutable; + } + + /** + * Marks this object as immutable. + * + * <p>Future calls to methods that attempt to modify this object will throw. + */ + public void makeImmutable() { + this.isMutable = false; + } + + /** + * Throws an {@link UnsupportedOperationException} if immutable. + */ + void checkMutable() { + if (!isMutable) { + throw new UnsupportedOperationException(); + } + } + + /** + * Serializes the set and writes it to {@code output}. + * + * <p>For use by generated code only. + */ + public void writeTo(CodedOutputStream output) throws IOException { + for (int i = 0; i < count; i++) { + int tag = tags[i]; + int fieldNumber = WireFormat.getTagFieldNumber(tag); + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + output.writeUInt64(fieldNumber, (Long) objects[i]); + break; + case WireFormat.WIRETYPE_FIXED32: + output.writeFixed32(fieldNumber, (Integer) objects[i]); + break; + case WireFormat.WIRETYPE_FIXED64: + output.writeFixed64(fieldNumber, (Long) objects[i]); + break; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + output.writeBytes(fieldNumber, (ByteString) objects[i]); + break; + case WireFormat.WIRETYPE_START_GROUP: + output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP); + ((UnknownFieldSetLite) objects[i]).writeTo(output); + output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); + break; + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + /** + * Serializes the set and writes it to {@code output} using {@code MessageSet} wire format. + * + * <p>For use by generated code only. + */ + public void writeAsMessageSetTo(CodedOutputStream output) throws IOException { + for (int i = 0; i < count; i++) { + int fieldNumber = WireFormat.getTagFieldNumber(tags[i]); + output.writeRawMessageSetExtension(fieldNumber, (ByteString) objects[i]); + } + } + + + /** + * Get the number of bytes required to encode this field, including field number, using {@code + * MessageSet} wire format. + */ + public int getSerializedSizeAsMessageSet() { + int size = memoizedSerializedSize; + if (size != -1) { + return size; + } + + size = 0; + for (int i = 0; i < count; i++) { + int tag = tags[i]; + int fieldNumber = WireFormat.getTagFieldNumber(tag); + size += CodedOutputStream.computeRawMessageSetExtensionSize( + fieldNumber, (ByteString) objects[i]); + } + + memoizedSerializedSize = size; + + return size; + } + + /** + * Get the number of bytes required to encode this set. + * + * <p>For use by generated code only. + */ + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) { + return size; + } + + size = 0; + for (int i = 0; i < count; i++) { + int tag = tags[i]; + int fieldNumber = WireFormat.getTagFieldNumber(tag); + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + size += CodedOutputStream.computeUInt64Size(fieldNumber, (Long) objects[i]); + break; + case WireFormat.WIRETYPE_FIXED32: + size += CodedOutputStream.computeFixed32Size(fieldNumber, (Integer) objects[i]); + break; + case WireFormat.WIRETYPE_FIXED64: + size += CodedOutputStream.computeFixed64Size(fieldNumber, (Long) objects[i]); + break; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + size += CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) objects[i]); + break; + case WireFormat.WIRETYPE_START_GROUP: + size += CodedOutputStream.computeTagSize(fieldNumber) * 2 + + ((UnknownFieldSetLite) objects[i]).getSerializedSize(); + break; + default: + throw new IllegalStateException(InvalidProtocolBufferException.invalidWireType()); + } + } + + memoizedSerializedSize = size; + + return size; + } + + private static boolean equals(int[] tags1, int[] tags2, int count) { + for (int i = 0; i < count; ++i) { + if (tags1[i] != tags2[i]) { + return false; + } + } + return true; + } + + private static boolean equals(Object[] objects1, Object[] objects2, int count) { + for (int i = 0; i < count; ++i) { + if (!objects1[i].equals(objects2[i])) { + return false; + } + } + return true; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null) { + return false; + } + + if (!(obj instanceof UnknownFieldSetLite)) { + return false; + } + + UnknownFieldSetLite other = (UnknownFieldSetLite) obj; + if (count != other.count + || !equals(tags, other.tags, count) + || !equals(objects, other.objects, count)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 17; + + hashCode = 31 * hashCode + count; + hashCode = 31 * hashCode + Arrays.hashCode(tags); + hashCode = 31 * hashCode + Arrays.deepHashCode(objects); + + return hashCode; + } + + /** + * Prints a String representation of the unknown field set. + * + * <p>For use by generated code only. + * + * @param buffer the buffer to write to + * @param indent the number of spaces the fields should be indented by + */ + final void printWithIndent(StringBuilder buffer, int indent) { + for (int i = 0; i < count; i++) { + int fieldNumber = WireFormat.getTagFieldNumber(tags[i]); + MessageLiteToString.printField(buffer, indent, String.valueOf(fieldNumber), objects[i]); + } + } + + // Package private for unsafe experimental runtime. + void storeField(int tag, Object value) { + ensureCapacity(); + + tags[count] = tag; + objects[count] = value; + count++; + } + + /** + * Ensures that our arrays are long enough to store more metadata. + */ + private void ensureCapacity() { + if (count == tags.length) { + int increment = count < (MIN_CAPACITY / 2) ? MIN_CAPACITY : count >> 1; + int newLength = count + increment; + + tags = Arrays.copyOf(tags, newLength); + objects = Arrays.copyOf(objects, newLength); + } + } + + /** + * Parse a single field from {@code input} and merge it into this set. + * + * <p>For use by generated code only. + * + * @param tag The field's tag number, which was already parsed. + * @return {@code false} if the tag is an end group tag. + */ + boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOException { + checkMutable(); + final int fieldNumber = WireFormat.getTagFieldNumber(tag); + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + storeField(tag, input.readInt64()); + return true; + case WireFormat.WIRETYPE_FIXED32: + storeField(tag, input.readFixed32()); + return true; + case WireFormat.WIRETYPE_FIXED64: + storeField(tag, input.readFixed64()); + return true; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + storeField(tag, input.readBytes()); + return true; + case WireFormat.WIRETYPE_START_GROUP: + final UnknownFieldSetLite subFieldSet = new UnknownFieldSetLite(); + subFieldSet.mergeFrom(input); + input.checkLastTagWas( + WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); + storeField(tag, subFieldSet); + return true; + case WireFormat.WIRETYPE_END_GROUP: + return false; + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + /** + * Convenience method for merging a new field containing a single varint + * value. This is used in particular when an unknown enum value is + * encountered. + * + * <p>For use by generated code only. + */ + UnknownFieldSetLite mergeVarintField(int fieldNumber, int value) { + checkMutable(); + if (fieldNumber == 0) { + throw new IllegalArgumentException("Zero is not a valid field number."); + } + + storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_VARINT), (long) value); + + return this; + } + + /** + * Convenience method for merging a length-delimited field. + * + * <p>For use by generated code only. + */ + UnknownFieldSetLite mergeLengthDelimitedField(final int fieldNumber, final ByteString value) { + checkMutable(); + if (fieldNumber == 0) { + throw new IllegalArgumentException("Zero is not a valid field number."); + } + + storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED), value); + + return this; + } + + /** + * Parse an entire message from {@code input} and merge its fields into + * this set. + */ + private UnknownFieldSetLite mergeFrom(final CodedInputStream input) throws IOException { + // Ensures initialization in mergeFieldFrom. + while (true) { + final int tag = input.readTag(); + if (tag == 0 || !mergeFieldFrom(tag, input)) { + break; + } + } + return this; + } +}
http://git-wip-us.apache.org/repos/asf/hbase/blob/6786b2b6/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnmodifiableLazyStringList.java ---------------------------------------------------------------------- diff --git a/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnmodifiableLazyStringList.java b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnmodifiableLazyStringList.java new file mode 100644 index 0000000..54786dd --- /dev/null +++ b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnmodifiableLazyStringList.java @@ -0,0 +1,210 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package org.apache.hadoop.hbase.shaded.com.google.protobuf; + +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.RandomAccess; + +/** + * An implementation of {@link LazyStringList} that wraps another + * {@link LazyStringList} such that it cannot be modified via the wrapper. + * + * @author j...@google.com (Jon Perlow) + */ +public class UnmodifiableLazyStringList extends AbstractList<String> + implements LazyStringList, RandomAccess { + + private final LazyStringList list; + + public UnmodifiableLazyStringList(LazyStringList list) { + this.list = list; + } + + @Override + public String get(int index) { + return list.get(index); + } + + @Override + public Object getRaw(int index) { + return list.getRaw(index); + } + + @Override + public int size() { + return list.size(); + } + + @Override + public ByteString getByteString(int index) { + return list.getByteString(index); + } + + @Override + public void add(ByteString element) { + throw new UnsupportedOperationException(); + } + + @Override + public void set(int index, ByteString element) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAllByteString(Collection<? extends ByteString> element) { + throw new UnsupportedOperationException(); + } + + @Override + public byte[] getByteArray(int index) { + return list.getByteArray(index); + } + + @Override + public void add(byte[] element) { + throw new UnsupportedOperationException(); + } + + @Override + public void set(int index, byte[] element) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAllByteArray(Collection<byte[]> element) { + throw new UnsupportedOperationException(); + } + + @Override + public ListIterator<String> listIterator(final int index) { + return new ListIterator<String>() { + ListIterator<String> iter = list.listIterator(index); + + @Override + public boolean hasNext() { + return iter.hasNext(); + } + + @Override + public String next() { + return iter.next(); + } + + @Override + public boolean hasPrevious() { + return iter.hasPrevious(); + } + + @Override + public String previous() { + return iter.previous(); + } + + @Override + public int nextIndex() { + return iter.nextIndex(); + } + + @Override + public int previousIndex() { + return iter.previousIndex(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public void set(String o) { + throw new UnsupportedOperationException(); + } + + @Override + public void add(String o) { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public Iterator<String> iterator() { + return new Iterator<String>() { + Iterator<String> iter = list.iterator(); + + @Override + public boolean hasNext() { + return iter.hasNext(); + } + + @Override + public String next() { + return iter.next(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public List<?> getUnderlyingElements() { + // The returned value is already unmodifiable. + return list.getUnderlyingElements(); + } + + @Override + public void mergeFrom(LazyStringList other) { + throw new UnsupportedOperationException(); + } + + @Override + public List<byte[]> asByteArrayList() { + return Collections.unmodifiableList(list.asByteArrayList()); + } + + @Override + public List<ByteString> asByteStringList() { + return Collections.unmodifiableList(list.asByteStringList()); + } + + @Override + public LazyStringList getUnmodifiableView() { + return this; + } +} http://git-wip-us.apache.org/repos/asf/hbase/blob/6786b2b6/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnsafeByteOperations.java ---------------------------------------------------------------------- diff --git a/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnsafeByteOperations.java b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnsafeByteOperations.java new file mode 100644 index 0000000..ad99372 --- /dev/null +++ b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnsafeByteOperations.java @@ -0,0 +1,131 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package org.apache.hadoop.hbase.shaded.com.google.protobuf; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * Provides a number of unsafe byte operations to be used by advanced applications with high + * performance requirements. These methods are referred to as "unsafe" due to the fact that they + * potentially expose the backing buffer of a {@link ByteString} to the application. + * + * <p><strong>DISCLAIMER:</strong> The methods in this class should only be called if it is + * guaranteed that the buffer backing the {@link ByteString} will never change! Mutation of a + * {@link ByteString} can lead to unexpected and undesirable consequences in your application, + * and will likely be difficult to debug. Proceed with caution! + * + * <p>This can have a number of significant side affects that have + * spooky-action-at-a-distance-like behavior. In particular, if the bytes value changes out from + * under a Protocol Buffer: + * <ul> + * <li>serialization may throw + * <li>serialization may succeed but the wrong bytes may be written out + * <li>messages are no longer threadsafe + * <li>hashCode may be incorrect + * <ul> + * <li>can result in a permanent memory leak when used as a key in a long-lived HashMap + * <li> the semantics of many programs may be violated if this is the case + * </ul> + * </ul> + * Each of these issues will occur in parts of the code base that are entirely distinct from the + * parts of the code base modifying the buffer. In fact, both parts of the code base may be correct + * - it is the bridging with the unsafe operations that was in error! + */ +@ExperimentalApi +public final class UnsafeByteOperations { + private UnsafeByteOperations() {} + + /** + * An unsafe operation that returns a {@link ByteString} that is backed by the provided buffer. + * + * @param buffer the buffer to be wrapped + * @return a {@link ByteString} backed by the provided buffer + */ + public static ByteString unsafeWrap(byte[] buffer) { + return ByteString.wrap(buffer); + } + + /** + * An unsafe operation that returns a {@link ByteString} that is backed by a subregion of the + * provided buffer. + * + * @param buffer the buffer to be wrapped + * @param offset the offset of the wrapped region + * @param length the number of bytes of the wrapped region + * @return a {@link ByteString} backed by the provided buffer + */ + public static ByteString unsafeWrap(byte[] buffer, int offset, int length) { + return ByteString.wrap(buffer, offset, length); + } + + /** + * An unsafe operation that returns a {@link ByteString} that is backed by the provided buffer. + * + * @param buffer the Java NIO buffer to be wrapped + * @return a {@link ByteString} backed by the provided buffer + */ + public static ByteString unsafeWrap(ByteBuffer buffer) { + return ByteString.wrap(buffer); + } + + /** + * An unsafe operation that returns a {@link ByteString} that is backed by the provided buffer. + * @param buffer the ByteInput buffer to be wrapped + * @param offset the offset of the wrapped byteinput + * @param length the number of bytes of the byteinput + * @return a {@link ByteString} backed by the provided buffer + */ + public static ByteString unsafeWrap(ByteInput buffer, int offset, int len) { + return ByteString.wrap(buffer, offset, len); + } + + /** + * Writes the given {@link ByteString} to the provided {@link ByteOutput}. Calling this method may + * result in multiple operations on the target {@link ByteOutput} + * (i.e. for roped {@link ByteString}s). + * + * <p>This method exposes the internal backing buffer(s) of the {@link ByteString} to the {@link + * ByteOutput} in order to avoid additional copying overhead. It would be possible for a malicious + * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution! + * + * <p> NOTE: The {@link ByteOutput} <strong>MUST NOT</strong> modify the provided buffers. Doing + * so may result in corrupted data, which would be difficult to debug. + * + * @param bytes the {@link ByteString} to be written + * @param output the output to receive the bytes + * @throws IOException if an I/O error occurs + */ + public static void unsafeWriteTo(ByteString bytes, ByteOutput output) throws IOException { + bytes.writeTo(output); + } + +} http://git-wip-us.apache.org/repos/asf/hbase/blob/6786b2b6/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnsafeUtil.java ---------------------------------------------------------------------- diff --git a/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnsafeUtil.java b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnsafeUtil.java new file mode 100644 index 0000000..bb4d8d6 --- /dev/null +++ b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/UnsafeUtil.java @@ -0,0 +1,295 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package org.apache.hadoop.hbase.shaded.com.google.protobuf; + +import java.lang.reflect.Field; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.security.AccessController; +import java.security.PrivilegedExceptionAction; +import sun.misc.Unsafe; + +/** Utility class for working with unsafe operations. */ +// TODO(nathanmittler): Add support for Android Memory/MemoryBlock +final class UnsafeUtil { + private static final sun.misc.Unsafe UNSAFE = getUnsafe(); + private static final boolean HAS_UNSAFE_BYTEBUFFER_OPERATIONS = + supportsUnsafeByteBufferOperations(); + private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations(); + private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset(); + private static final long BUFFER_ADDRESS_OFFSET = fieldOffset(field(Buffer.class, "address")); + + private UnsafeUtil() {} + + static boolean hasUnsafeArrayOperations() { + return HAS_UNSAFE_ARRAY_OPERATIONS; + } + + static boolean hasUnsafeByteBufferOperations() { + return HAS_UNSAFE_BYTEBUFFER_OPERATIONS; + } + + static Object allocateInstance(Class<?> clazz) { + try { + return UNSAFE.allocateInstance(clazz); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } + } + + static long objectFieldOffset(Field field) { + return UNSAFE.objectFieldOffset(field); + } + + static long getArrayBaseOffset() { + return ARRAY_BASE_OFFSET; + } + + static byte getByte(Object target, long offset) { + return UNSAFE.getByte(target, offset); + } + + static void putByte(Object target, long offset, byte value) { + UNSAFE.putByte(target, offset, value); + } + + static int getInt(Object target, long offset) { + return UNSAFE.getInt(target, offset); + } + + static void putInt(Object target, long offset, int value) { + UNSAFE.putInt(target, offset, value); + } + + static long getLong(Object target, long offset) { + return UNSAFE.getLong(target, offset); + } + + static void putLong(Object target, long offset, long value) { + UNSAFE.putLong(target, offset, value); + } + + static boolean getBoolean(Object target, long offset) { + return UNSAFE.getBoolean(target, offset); + } + + static void putBoolean(Object target, long offset, boolean value) { + UNSAFE.putBoolean(target, offset, value); + } + + static float getFloat(Object target, long offset) { + return UNSAFE.getFloat(target, offset); + } + + static void putFloat(Object target, long offset, float value) { + UNSAFE.putFloat(target, offset, value); + } + + static double getDouble(Object target, long offset) { + return UNSAFE.getDouble(target, offset); + } + + static void putDouble(Object target, long offset, double value) { + UNSAFE.putDouble(target, offset, value); + } + + static Object getObject(Object target, long offset) { + return UNSAFE.getObject(target, offset); + } + + static void putObject(Object target, long offset, Object value) { + UNSAFE.putObject(target, offset, value); + } + + static void copyMemory( + Object src, long srcOffset, Object target, long targetOffset, long length) { + UNSAFE.copyMemory(src, srcOffset, target, targetOffset, length); + } + + static byte getByte(long address) { + return UNSAFE.getByte(address); + } + + static void putByte(long address, byte value) { + UNSAFE.putByte(address, value); + } + + static int getInt(long address) { + return UNSAFE.getInt(address); + } + + static void putInt(long address, int value) { + UNSAFE.putInt(address, value); + } + + static long getLong(long address) { + return UNSAFE.getLong(address); + } + + static void putLong(long address, long value) { + UNSAFE.putLong(address, value); + } + + static void copyMemory(long srcAddress, long targetAddress, long length) { + UNSAFE.copyMemory(srcAddress, targetAddress, length); + } + + static void setMemory(long address, long numBytes, byte value) { + UNSAFE.setMemory(address, numBytes, value); + } + + /** + * Gets the offset of the {@code address} field of the given direct {@link ByteBuffer}. + */ + static long addressOffset(ByteBuffer buffer) { + return UNSAFE.getLong(buffer, BUFFER_ADDRESS_OFFSET); + } + + /** + * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this platform. + */ + private static sun.misc.Unsafe getUnsafe() { + sun.misc.Unsafe unsafe = null; + try { + unsafe = + AccessController.doPrivileged( + new PrivilegedExceptionAction<Unsafe>() { + @Override + public sun.misc.Unsafe run() throws Exception { + Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class; + + for (Field f : k.getDeclaredFields()) { + f.setAccessible(true); + Object x = f.get(null); + if (k.isInstance(x)) { + return k.cast(x); + } + } + // The sun.misc.Unsafe field does not exist. + return null; + } + }); + } catch (Throwable e) { + // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError + // for Unsafe. + } + return unsafe; + } + + /** Indicates whether or not unsafe array operations are supported on this platform. */ + private static boolean supportsUnsafeArrayOperations() { + boolean supported = false; + if (UNSAFE != null) { + try { + Class<?> clazz = UNSAFE.getClass(); + clazz.getMethod("objectFieldOffset", Field.class); + clazz.getMethod("allocateInstance", Class.class); + clazz.getMethod("arrayBaseOffset", Class.class); + clazz.getMethod("getByte", Object.class, long.class); + clazz.getMethod("putByte", Object.class, long.class, byte.class); + clazz.getMethod("getBoolean", Object.class, long.class); + clazz.getMethod("putBoolean", Object.class, long.class, boolean.class); + clazz.getMethod("getInt", Object.class, long.class); + clazz.getMethod("putInt", Object.class, long.class, int.class); + clazz.getMethod("getLong", Object.class, long.class); + clazz.getMethod("putLong", Object.class, long.class, long.class); + clazz.getMethod("getFloat", Object.class, long.class); + clazz.getMethod("putFloat", Object.class, long.class, float.class); + clazz.getMethod("getDouble", Object.class, long.class); + clazz.getMethod("putDouble", Object.class, long.class, double.class); + clazz.getMethod("getObject", Object.class, long.class); + clazz.getMethod("putObject", Object.class, long.class, Object.class); + clazz.getMethod( + "copyMemory", Object.class, long.class, Object.class, long.class, long.class); + supported = true; + } catch (Throwable e) { + // Do nothing. + } + } + return supported; + } + + private static boolean supportsUnsafeByteBufferOperations() { + boolean supported = false; + if (UNSAFE != null) { + try { + Class<?> clazz = UNSAFE.getClass(); + // Methods for getting direct buffer address. + clazz.getMethod("objectFieldOffset", Field.class); + clazz.getMethod("getLong", Object.class, long.class); + + clazz.getMethod("getByte", long.class); + clazz.getMethod("putByte", long.class, byte.class); + clazz.getMethod("getInt", long.class); + clazz.getMethod("putInt", long.class, int.class); + clazz.getMethod("getLong", long.class); + clazz.getMethod("putLong", long.class, long.class); + clazz.getMethod("setMemory", long.class, long.class, byte.class); + clazz.getMethod("copyMemory", long.class, long.class, long.class); + supported = true; + } catch (Throwable e) { + // Do nothing. + } + } + return supported; + } + + /** + * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not available. + */ + private static int byteArrayBaseOffset() { + return HAS_UNSAFE_ARRAY_OPERATIONS ? UNSAFE.arrayBaseOffset(byte[].class) : -1; + } + + /** + * Returns the offset of the provided field, or {@code -1} if {@code sun.misc.Unsafe} is not + * available. + */ + private static long fieldOffset(Field field) { + return field == null || UNSAFE == null ? -1 : UNSAFE.objectFieldOffset(field); + } + + /** + * Gets the field with the given name within the class, or {@code null} if not found. If found, + * the field is made accessible. + */ + private static Field field(Class<?> clazz, String fieldName) { + Field field; + try { + field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + } catch (Throwable t) { + // Failed to access the fields. + field = null; + } + return field; + } +}