org.apache.drill.exec.memory.BoundsChecking.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.drill.exec.memory.BoundsChecking.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.drill.exec.memory;

import java.lang.reflect.Field;
import java.util.Formatter;

import org.apache.drill.shaded.guava.com.google.common.base.Preconditions;

import io.netty.buffer.AbstractByteBuf;
import io.netty.buffer.DrillBuf;
import io.netty.util.IllegalReferenceCountException;

import static org.apache.drill.exec.util.SystemPropertyUtil.getBoolean;

public class BoundsChecking {
    private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(BoundsChecking.class);

    public static final String ENABLE_UNSAFE_BOUNDS_CHECK_PROPERTY = "drill.exec.memory.enable_unsafe_bounds_check";
    // for backward compatibility check "drill.enable_unsafe_memory_access" property and enable bounds checking when
    // unsafe memory access is explicitly disabled
    public static final String ENABLE_UNSAFE_MEMORY_ACCESS_PROPERTY = "drill.enable_unsafe_memory_access";
    public static final boolean BOUNDS_CHECKING_ENABLED = getBoolean(ENABLE_UNSAFE_BOUNDS_CHECK_PROPERTY,
            !getBoolean(ENABLE_UNSAFE_MEMORY_ACCESS_PROPERTY, true));
    private static final boolean checkAccessible = getStaticBooleanField(AbstractByteBuf.class, "checkAccessible",
            false);

    static {
        if (BOUNDS_CHECKING_ENABLED) {
            logger.warn(
                    "Drill is running with direct memory bounds checking enabled. If this is a production system, disable it.");
        } else if (logger.isDebugEnabled()) {
            logger.debug("Direct memory bounds checking is disabled.");
        }
    }

    private BoundsChecking() {
    }

    private static boolean getStaticBooleanField(Class cls, String name, boolean def) {
        try {
            Field field = cls.getDeclaredField(name);
            field.setAccessible(true);
            return field.getBoolean(null);
        } catch (ReflectiveOperationException e) {
            return def;
        }
    }

    private static void checkIndex(DrillBuf buf, int index, int fieldLength) {
        Preconditions.checkNotNull(buf);
        if (checkAccessible && buf.refCnt() == 0) {
            Formatter formatter = new Formatter().format("%s, refCnt: 0", buf);
            if (BaseAllocator.DEBUG) {
                formatter.format("%n%s", buf.toVerboseString());
            }
            throw new IllegalReferenceCountException(formatter.toString());
        }
        if (fieldLength < 0) {
            throw new IllegalArgumentException(String.format("length: %d (expected: >= 0)", fieldLength));
        }
        if (index < 0 || index > buf.capacity() - fieldLength) {
            Formatter formatter = new Formatter().format("%s, index: %d, length: %d (expected: range(0, %d))", buf,
                    index, fieldLength, buf.capacity());
            if (BaseAllocator.DEBUG) {
                formatter.format("%n%s", buf.toVerboseString());
            }
            throw new IndexOutOfBoundsException(formatter.toString());
        }
    }

    public static void lengthCheck(DrillBuf buf, int start, int length) {
        if (BOUNDS_CHECKING_ENABLED) {
            checkIndex(buf, start, length);
        }
    }

    public static void rangeCheck(DrillBuf buf, int start, int end) {
        if (BOUNDS_CHECKING_ENABLED) {
            checkIndex(buf, start, end - start);
        }
    }

    public static void rangeCheck(DrillBuf buf1, int start1, int end1, DrillBuf buf2, int start2, int end2) {
        if (BOUNDS_CHECKING_ENABLED) {
            checkIndex(buf1, start1, end1 - start1);
            checkIndex(buf2, start2, end2 - start2);
        }
    }

    public static void ensureWritable(DrillBuf buf, int minWritableBytes) {
        if (BOUNDS_CHECKING_ENABLED) {
            buf.ensureWritable(minWritableBytes);
        }
    }
}