<commit_before>package org.voovan.tools;

import org.voovan.Global;
import org.voovan.tools.log.Logger;
import org.voovan.tools.reflect.TReflect;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * ByteBuffer 工具类
 *
 * @author helyho
 *
 * Java Framework.
 * WebSite: https://github.com/helyho/Voovan
 * Licence: Apache v2 License
 */
public class TByteBuffer {

    public static ConcurrentLinkedQueue<ByteBuffer> BYTE_BUFFER_MANUAL_RELEASE_POOL = new ConcurrentLinkedQueue<ByteBuffer>();

    public static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0);

    public static Class DIRECT_BYTE_BUFFER_CLASS = EMPTY_BYTE_BUFFER.getClass();

    public static Constructor DIRECT_BYTE_BUFFER_CONSTURCTOR = getConsturctor();
    static {
        DIRECT_BYTE_BUFFER_CONSTURCTOR.setAccessible(true);
    }

    public static Class CLEANER_ClASS = null;
    public static Method CLEANER_CREATE_METHOD = null;
    static {
        try {
            if (TEnv.JDK_VERSION < 9F) {
                CLEANER_ClASS = Class.forName("sun.misc.Cleaner");
            } else {
                CLEANER_ClASS = Class.forName("jdk.internal.ref.Cleaner");
            }

            CLEANER_CREATE_METHOD = TReflect.findMethod(CLEANER_ClASS, "create", Object.class, Runnable.class);
        } catch (Exception e){
            Logger.error("Cleaner class not found: ", e);
        }
    }

    public static Field addressField = ByteBufferField("address");
    public static Field limitField = ByteBufferField("limit");
    public static Field capacityField = ByteBufferField("capacity");
    public static Field attField = ByteBufferField("att");

    private static Constructor getConsturctor(){
        try {
            Constructor constructor = DIRECT_BYTE_BUFFER_CLASS.getDeclaredConstructor(long.class, int.class, Object.class);
            constructor.setAccessible(true);
            return constructor;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return null;
    }

    private static Field ByteBufferField(String fieldName){
        try {
            Field field = TReflect.findField(DIRECT_BYTE_BUFFER_CLASS, fieldName);
            field.setAccessible(true);
            return field;
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分配可能手工进行释放的 ByteBuffer
     * @param capacity 容量
     * @return ByteBuffer 对象
     */
    protected static ByteBuffer allocateManualReleaseBuffer(int capacity){
        try {
            long address = (TUnsafe.getUnsafe().allocateMemory(capacity));
            TUnsafe.getUnsafe().setMemory(address, capacity, (byte) 0);

            Deallocator deallocator = new Deallocator(new Long(address));

            ByteBuffer byteBuffer =  (ByteBuffer) DIRECT_BYTE_BUFFER_CONSTURCTOR.newInstance(address, capacity, deallocator);

            //内存自动释放部分
            TReflect.invokeMethod(CLEANER_ClASS, CLEANER_CREATE_METHOD, byteBuffer, deallocator);

            return byteBuffer;

        } catch (Exception e) {
            Logger.error("Create ByteBufferChannel error. ", e);
            return null;
        }
    }

    /**
     * 借出缓冲对象
     * @param capacity
     * @return 容量
     */
    public static ByteBuffer borrowBuffer(int capacity){
        ByteBuffer byteBuffer = BYTE_BUFFER_MANUAL_RELEASE_POOL.poll();
        if(byteBuffer == null){
            return allocateManualReleaseBuffer(capacity);
        }

        if(byteBuffer.capacity() >= capacity){
            byteBuffer.limit(capacity);
            return byteBuffer;
        } else if(reallocate(byteBuffer, capacity)){
            return byteBuffer;
        } else {
            return null;
        }
    }

    /**
     * 归还缓冲对象
     * @param byteBuffer
     */
    public static void returnBuffer(ByteBuffer byteBuffer){
        byteBuffer.position(0);
        byteBuffer.limit(byteBuffer.capacity());
        BYTE_BUFFER_MANUAL_RELEASE_POOL.offer(byteBuffer);
    }


    /**
     * 根据框架的非堆内存配置, 分配 ByteBuffer
     * @param capacity 容量
     * @return ByteBuffer 对象
     */<commit_msg>fix: 修复 TByteBuffer.borrowBuffer 的 bug<commit_after>package org.voovan.tools;

import org.voovan.Global;
import org.voovan.tools.log.Logger;
import org.voovan.tools.reflect.TReflect;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * ByteBuffer 工具类
 *
 * @author helyho
 *
 * Java Framework.
 * WebSite: https://github.com/helyho/Voovan
 * Licence: Apache v2 License
 */
public class TByteBuffer {

    public static ConcurrentLinkedQueue<ByteBuffer> BYTE_BUFFER_MANUAL_RELEASE_POOL = new ConcurrentLinkedQueue<ByteBuffer>();

    public static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0);

    public static Class DIRECT_BYTE_BUFFER_CLASS = EMPTY_BYTE_BUFFER.getClass();

    public static Constructor DIRECT_BYTE_BUFFER_CONSTURCTOR = getConsturctor();
    static {
        DIRECT_BYTE_BUFFER_CONSTURCTOR.setAccessible(true);
    }

    public static Class CLEANER_ClASS = null;
    public static Method CLEANER_CREATE_METHOD = null;
    static {
        try {
            if (TEnv.JDK_VERSION < 9F) {
                CLEANER_ClASS = Class.forName("sun.misc.Cleaner");
            } else {
                CLEANER_ClASS = Class.forName("jdk.internal.ref.Cleaner");
            }

            CLEANER_CREATE_METHOD = TReflect.findMethod(CLEANER_ClASS, "create", Object.class, Runnable.class);
        } catch (Exception e){
            Logger.error("Cleaner class not found: ", e);
        }
    }

    public static Field addressField = ByteBufferField("address");
    public static Field limitField = ByteBufferField("limit");
    public static Field capacityField = ByteBufferField("capacity");
    public static Field attField = ByteBufferField("att");

    private static Constructor getConsturctor(){
        try {
            Constructor constructor = DIRECT_BYTE_BUFFER_CLASS.getDeclaredConstructor(long.class, int.class, Object.class);
            constructor.setAccessible(true);
            return constructor;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return null;
    }

    private static Field ByteBufferField(String fieldName){
        try {
            Field field = TReflect.findField(DIRECT_BYTE_BUFFER_CLASS, fieldName);
            field.setAccessible(true);
            return field;
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分配可能手工进行释放的 ByteBuffer
     * @param capacity 容量
     * @return ByteBuffer 对象
     */
    protected static ByteBuffer allocateManualReleaseBuffer(int capacity){
        try {
            long address = (TUnsafe.getUnsafe().allocateMemory(capacity));
            TUnsafe.getUnsafe().setMemory(address, capacity, (byte) 0);

            Deallocator deallocator = new Deallocator(new Long(address));

            ByteBuffer byteBuffer =  (ByteBuffer) DIRECT_BYTE_BUFFER_CONSTURCTOR.newInstance(address, capacity, deallocator);

            //内存自动释放部分
            TReflect.invokeMethod(CLEANER_ClASS, CLEANER_CREATE_METHOD, byteBuffer, deallocator);

            return byteBuffer;

        } catch (Exception e) {
            Logger.error("Create ByteBufferChannel error. ", e);
            return null;
        }
    }

    /**
     * 借出缓冲对象
     * @param capacity
     * @return 容量
     */
    public static ByteBuffer borrowBuffer(int capacity){
        ByteBuffer byteBuffer = BYTE_BUFFER_MANUAL_RELEASE_POOL.poll();
        if(byteBuffer == null){
            return allocateManualReleaseBuffer(capacity);
        }

        if(byteBuffer.capacity() >= capacity){
            byteBuffer.limit(capacity);
            return byteBuffer;
        } else if(reallocate(byteBuffer, capacity)){
            byteBuffer.limit(capacity);
            return byteBuffer;
        } else {
            return null;
        }
    }

    /**
     * 归还缓冲对象
     * @param byteBuffer
     */
    public static void returnBuffer(ByteBuffer byteBuffer){
        byteBuffer.position(0);
        byteBuffer.limit(byteBuffer.capacity());
        BYTE_BUFFER_MANUAL_RELEASE_POOL.offer(byteBuffer);
    }


    /**
     * 根据框架的非堆内存配置, 分配 ByteBuffer
     * @param capacity 容量
     * @return ByteBuffer 对象
     */
{'fraction_non_alphanumeric': 0.09193566784532907, 'fraction_numerical': 0.0011406410402646286, 'mean_word_length': 2.629139072847682, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5624414', 'n_tokens_mistral': 2562, 'n_tokens_neox': 2511, 'n_words': 505}