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

com.datastax.dse.driver.internal.core.protocol.TinkerpopBufferPrimitiveCodec Maven / Gradle / Ivy

The newest version!
/*
 * Copyright DataStax, 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 com.datastax.dse.driver.internal.core.protocol;

import com.datastax.dse.driver.internal.core.graph.binary.buffer.DseNettyBufferFactory;
import com.datastax.oss.driver.internal.core.protocol.ByteBufPrimitiveCodec;
import com.datastax.oss.driver.shaded.guava.common.base.Charsets;
import com.datastax.oss.protocol.internal.PrimitiveCodec;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.zip.CRC32;
import org.apache.tinkerpop.gremlin.structure.io.Buffer;

/**
 * Minimal implementation of {@link PrimitiveCodec} for Tinkerpop {@link Buffer} instances.
 *
 * 

This approach represents a temporary design compromise. PrimitiveCodec is primarily used for * handling data directly from Netty, a task satisfied by {@link ByteBufPrimitiveCodec}. But * PrimitiveCodec is also used to implement graph serialization for some of the "dynamic" types * (notably UDTs and tuples). Since we're converting graph serialization to use the new Tinkerpop * Buffer API we need just enough of a PrimitiveCodec impl to satisfy the needs of graph * serialization... and nothing more. * *

A more explicit approach would be to change graph serialization to use a different interface, * some kind of subset of PrimitiveCodec.... and then make PrimitiveCodec extend this interface. * This is left as future work for now since it involves changes to the native-protocol lib(s). */ public class TinkerpopBufferPrimitiveCodec implements PrimitiveCodec { private final DseNettyBufferFactory factory; public TinkerpopBufferPrimitiveCodec(DseNettyBufferFactory factory) { this.factory = factory; } @Override public Buffer allocate(int size) { // Note: we use io() here to match up to what ByteBufPrimitiveCodec does, but be warned that // ByteBufs created in this way don't support the array() method used elsewhere in this codec // (readString() specifically). As such usage of this method to create Buffer instances is // discouraged; we have a factory for that. return this.factory.io(size, size); } @Override public void release(Buffer toRelease) { toRelease.release(); } @Override public int sizeOf(Buffer toMeasure) { return toMeasure.readableBytes(); } // TODO @Override public Buffer concat(Buffer left, Buffer right) { boolean leftReadable = left.readableBytes() > 0; boolean rightReadable = right.readableBytes() > 0; if (!(leftReadable || rightReadable)) { return factory.heap(); } if (!leftReadable) { return right; } if (!rightReadable) { return left; } Buffer rv = factory.composite(left, right); // c.readerIndex() is 0, which is the first readable byte in left rv.writerIndex( left.writerIndex() - left.readerIndex() + right.writerIndex() - right.readerIndex()); return rv; } @Override public void markReaderIndex(Buffer source) { throw new UnsupportedOperationException(); } @Override public void resetReaderIndex(Buffer source) { throw new UnsupportedOperationException(); } @Override public byte readByte(Buffer source) { return source.readByte(); } @Override public int readInt(Buffer source) { return source.readInt(); } @Override public int readInt(Buffer source, int offset) { throw new UnsupportedOperationException(); } @Override public InetAddress readInetAddr(Buffer source) { int length = readByte(source) & 0xFF; byte[] bytes = new byte[length]; source.readBytes(bytes); return newInetAddress(bytes); } @Override public long readLong(Buffer source) { return source.readLong(); } @Override public int readUnsignedShort(Buffer source) { return source.readShort() & 0xFFFF; } @Override public ByteBuffer readBytes(Buffer source) { int length = readInt(source); if (length < 0) return null; return source.nioBuffer(source.readerIndex(), length); } @Override public byte[] readShortBytes(Buffer source) { try { int length = readUnsignedShort(source); byte[] bytes = new byte[length]; source.readBytes(bytes); return bytes; } catch (IndexOutOfBoundsException e) { throw new IllegalArgumentException( "Not enough bytes to read a byte array preceded by its 2 bytes length"); } } // Copy of PrimitiveCodec impl @Override public String readString(Buffer source) { int length = readUnsignedShort(source); return readString(source, length); } @Override public String readLongString(Buffer source) { int length = readInt(source); return readString(source, length); } @Override public Buffer readRetainedSlice(Buffer source, int sliceLength) { throw new UnsupportedOperationException(); } @Override public void updateCrc(Buffer source, CRC32 crc) { throw new UnsupportedOperationException(); } @Override public void writeByte(byte b, Buffer dest) { dest.writeByte(b); } @Override public void writeInt(int i, Buffer dest) { dest.writeInt(i); } @Override public void writeInetAddr(InetAddress address, Buffer dest) { byte[] bytes = address.getAddress(); writeByte((byte) bytes.length, dest); dest.writeBytes(bytes); } @Override public void writeLong(long l, Buffer dest) { dest.writeLong(l); } @Override public void writeUnsignedShort(int i, Buffer dest) { dest.writeShort(i); } // Copy of PrimitiveCodec impl @Override public void writeString(String s, Buffer dest) { byte[] bytes = s.getBytes(Charsets.UTF_8); writeUnsignedShort(bytes.length, dest); dest.writeBytes(bytes); } @Override public void writeLongString(String s, Buffer dest) { byte[] bytes = s.getBytes(Charsets.UTF_8); writeInt(bytes.length, dest); dest.writeBytes(bytes); } @Override public void writeBytes(ByteBuffer bytes, Buffer dest) { if (bytes == null) { writeInt(-1, dest); } else { writeInt(bytes.remaining(), dest); dest.writeBytes(bytes.duplicate()); } } @Override public void writeBytes(byte[] bytes, Buffer dest) { if (bytes == null) { writeInt(-1, dest); } else { writeInt(bytes.length, dest); dest.writeBytes(bytes); } } @Override public void writeShortBytes(byte[] bytes, Buffer dest) { writeUnsignedShort(bytes.length, dest); dest.writeBytes(bytes); } // Based on PrimitiveCodec impl, although that method leverages some // Netty built-ins which we have to do manually here private static String readString(Buffer buff, int length) { try { // Basically what com.datastax.oss.driver.shaded.netty.buffer.ByteBufUtil.decodeString() does minus some extra // ByteBuf-specific ops int offset; byte[] bytes; ByteBuffer byteBuff = buff.nioBuffer(); if (byteBuff.hasArray()) { bytes = byteBuff.array(); offset = byteBuff.arrayOffset(); } else { bytes = new byte[length]; byteBuff.get(bytes, 0, length); offset = 0; } String str = new String(bytes, offset, length, Charsets.UTF_8); // Ops against the NIO buffers don't impact the read/write indexes for he Buffer // itself so we have to do that manually buff.readerIndex(buff.readerIndex() + length); return str; } catch (IndexOutOfBoundsException e) { throw new IllegalArgumentException( "Not enough bytes to read an UTF-8 serialized string of size " + length, e); } } // TODO: Code below copied directly from ByteBufPrimitiveCodec, probably want to consolidate this // somewhere private static InetAddress newInetAddress(byte[] bytes) { try { return InetAddress.getByAddress(bytes); } catch (UnknownHostException e) { // Per the Javadoc, the only way this can happen is if the length is illegal throw new IllegalArgumentException( String.format("Invalid address length: %d (%s)", bytes.length, Arrays.toString(bytes))); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy