com.facebook.presto.jdbc.internal.common.block.BlockEncodingManager Maven / Gradle / Ivy
/*
* 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.facebook.presto.jdbc.internal.common.block;
import com.facebook.presto.jdbc.internal.io.airlift.slice.SliceInput;
import com.facebook.presto.jdbc.internal.io.airlift.slice.SliceOutput;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static java.lang.String.format;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
public final class BlockEncodingManager
implements BlockEncodingSerde
{
private final ConcurrentMap blockEncodings = new ConcurrentHashMap<>();
public BlockEncodingManager()
{
// This function should be called from Guice and tests only
// always add the built-in BlockEncodings
addBlockEncoding(new VariableWidthBlockEncoding());
addBlockEncoding(new ByteArrayBlockEncoding());
addBlockEncoding(new ShortArrayBlockEncoding());
addBlockEncoding(new IntArrayBlockEncoding());
addBlockEncoding(new LongArrayBlockEncoding());
addBlockEncoding(new Int128ArrayBlockEncoding());
addBlockEncoding(new DictionaryBlockEncoding());
addBlockEncoding(new ArrayBlockEncoding());
addBlockEncoding(new MapBlockEncoding());
addBlockEncoding(new SingleMapBlockEncoding());
addBlockEncoding(new RowBlockEncoding());
addBlockEncoding(new SingleRowBlockEncoding());
addBlockEncoding(new RunLengthBlockEncoding());
addBlockEncoding(new LazyBlockEncoding());
}
public void addBlockEncoding(BlockEncoding blockEncoding)
{
requireNonNull(blockEncoding, "blockEncoding is null");
BlockEncoding existingEntry = blockEncodings.putIfAbsent(blockEncoding.getName(), blockEncoding);
if (existingEntry != null) {
throw new IllegalArgumentException(format("Encoding %s is already registered", blockEncoding.getName()));
}
}
@Override
public Block readBlock(SliceInput input)
{
// read the encoding name
String encodingName = readLengthPrefixedString(input);
// look up the encoding factory
BlockEncoding blockEncoding = blockEncodings.get(encodingName);
if (blockEncoding == null) {
throw new IllegalArgumentException(format("Unknown block encoding %s", encodingName));
}
// load read the encoding factory from the output stream
return blockEncoding.readBlock(this, input);
}
@Override
public void writeBlock(SliceOutput output, Block block)
{
while (true) {
// get the encoding name
String encodingName = block.getEncodingName();
// look up the BlockEncoding
BlockEncoding blockEncoding = blockEncodings.get(encodingName);
// see if a replacement block should be written instead
Optional replacementBlock = blockEncoding.replacementBlockForWrite(block);
if (replacementBlock.isPresent()) {
block = replacementBlock.get();
continue;
}
// write the name to the output
writeLengthPrefixedString(output, encodingName);
// write the block to the output
blockEncoding.writeBlock(this, output, block);
break;
}
}
private static String readLengthPrefixedString(SliceInput input)
{
int length = input.readInt();
byte[] bytes = new byte[length];
input.readBytes(bytes);
return new String(bytes, UTF_8);
}
private static void writeLengthPrefixedString(SliceOutput output, String value)
{
byte[] bytes = value.getBytes(UTF_8);
output.writeInt(bytes.length);
output.writeBytes(bytes);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy