// Path: src/main/java/com/sun/marlin/ArrayCacheConst.java
// static final int[] ARRAY_SIZES = new int[BUCKETS];
// 
// Path: src/main/java/com/sun/marlin/ArrayCacheConst.java
// static final int BUCKETS = 8;
// 
// Path: src/main/java/com/sun/marlin/ArrayCacheConst.java
// static final int MAX_ARRAY_SIZE;
// 
// Path: src/main/java/com/sun/marlin/MarlinUtils.java
// public static void logInfo(final String msg) {
//     if (MarlinConst.USE_LOGGER) {
//         LOG.info(msg);
//     } else if (MarlinConst.ENABLE_LOGS) {
//         System.out.print("INFO: ");
//         System.out.println(msg);
//     }
// }
// 
// Path: src/main/java/com/sun/marlin/MarlinUtils.java
// public static void logException(final String msg, final Throwable th) {
//     if (MarlinConst.USE_LOGGER) {
//         LOG.log(java.util.logging.Level.WARNING, msg, th);
//     } else if (MarlinConst.ENABLE_LOGS) {
//         System.out.print("WARNING: ");
//         System.out.println(msg);
//         th.printStackTrace(System.err);
//     }
// }
// 
// Path: src/main/java/com/sun/marlin/ArrayCacheConst.java
// static final class BucketStats {
//     int getOp = 0;
//     int createOp = 0;
//     int returnOp = 0;
//     int maxSize = 0;
// 
//     void reset() {
//         getOp = 0;
//         createOp = 0;
//         returnOp = 0;
//         maxSize = 0;
//     }
// 
//     void updateMaxSize(final int size) {
//         if (size > maxSize) {
//             maxSize = size;
//         }
//     }
// }
// 
// Path: src/main/java/com/sun/marlin/ArrayCacheConst.java
// static final class CacheStats {
//     final String name;
//     final BucketStats[] bucketStats;
//     int resize = 0;
//     int oversize = 0;
//     long totalInitial = 0L;
// 
//     CacheStats(final String name) {
//         this.name = name;
// 
//         bucketStats = new BucketStats[BUCKETS];
//         for (int i = 0; i < BUCKETS; i++) {
//             bucketStats[i] = new BucketStats();
//         }
//     }
// 
//     void reset() {
//         resize = 0;
//         oversize = 0;
// 
//         for (int i = 0; i < BUCKETS; i++) {
//             bucketStats[i].reset();
//         }
//     }
// 
//     long dumpStats() {
//         long totalCacheBytes = 0L;
// 
//         if (DO_STATS) {
//             for (int i = 0; i < BUCKETS; i++) {
//                 final BucketStats s = bucketStats[i];
// 
//                 if (s.maxSize != 0) {
//                     totalCacheBytes += getByteFactor()
//                                        * (s.maxSize * ARRAY_SIZES[i]);
//                 }
//             }
// 
//             if (totalInitial != 0L || totalCacheBytes != 0L
//                 || resize != 0 || oversize != 0)
//             {
//                 logInfo(name + ": resize: " + resize
//                         + " - oversize: " + oversize
//                         + " - initial: " + getTotalInitialBytes()
//                         + " bytes (" + totalInitial + " elements)"
//                         + " - cache: " + totalCacheBytes + " bytes"
//                 );
//             }
// 
//             if (totalCacheBytes != 0L) {
//                 logInfo(name + ": usage stats:");
// 
//                 for (int i = 0; i < BUCKETS; i++) {
//                     final BucketStats s = bucketStats[i];
// 
//                     if (s.getOp != 0) {
//                         logInfo("  Bucket[" + ARRAY_SIZES[i] + "]: "
//                                 + "get: " + s.getOp
//                                 + " - put: " + s.returnOp
//                                 + " - create: " + s.createOp
//                                 + " :: max size: " + s.maxSize
//                         );
//                     }
//                 }
//             }
//         }
//         return totalCacheBytes;
//     }
// 
//     private int getByteFactor() {
//         int factor = 1;
//         if (name.contains("Int") || name.contains("Float")) {
//             factor = 4;
//         } else if (name.contains("Double")) {
//             factor = 8;
//         }
//         return factor;
//     }
// 
//     long getTotalInitialBytes() {
//         return getByteFactor() * totalInitial;
//     }
// }


import java.lang.ref.WeakReference;
import java.util.Arrays;
import com.sun.marlin.ArrayCacheConst.BucketStats;
import com.sun.marlin.ArrayCacheConst.CacheStats;
import static com.sun.marlin.ArrayCacheConst.ARRAY_SIZES;
import static com.sun.marlin.ArrayCacheConst.BUCKETS;
import static com.sun.marlin.ArrayCacheConst.MAX_ARRAY_SIZE;
import static com.sun.marlin.MarlinUtils.logInfo;
import static com.sun.marlin.MarlinUtils.logException;
            }
            if (DO_STATS) {
                cache.stats.oversize++;
            }
            if (DO_LOG_OVERSIZE) {
                logInfo(getLogPrefix(clean) + "ByteArrayCache: "
                        + "getArray[oversize]: length=\t" + length);
            }
            return createArray(length);
        }

        byte[] widenArray(final byte[] array, final int usedSize,
                          final int needSize)
        {
            final int length = array.length;
            if (DO_CHECKS && length >= needSize) {
                return array;
            }
            if (DO_STATS) {
                cache.stats.resize++;
            }

            // maybe change bucket:
            // ensure getNewSize() > newSize:
            final byte[] res = getArray(ArrayCacheConst.getNewSize(usedSize, needSize));

            // use wrapper to ensure proper copy:
            System.arraycopy(array, 0, res, 0, usedSize); // copy only used elements

            // maybe return current array:
// Path: src/main/java/com/sun/marlin/ArrayCacheConst.java
// static final int[] ARRAY_SIZES = new int[BUCKETS];
// 
// Path: src/main/java/com/sun/marlin/ArrayCacheConst.java
// static final int BUCKETS = 8;
// 
// Path: src/main/java/com/sun/marlin/ArrayCacheConst.java
// static final int MAX_ARRAY_SIZE;
// 
// Path: src/main/java/com/sun/marlin/MarlinUtils.java
// public static void logInfo(final String msg) {
//     if (MarlinConst.USE_LOGGER) {
//         LOG.info(msg);
//     } else if (MarlinConst.ENABLE_LOGS) {
//         System.out.print("INFO: ");
//         System.out.println(msg);
//     }
// }
// 
// Path: src/main/java/com/sun/marlin/MarlinUtils.java
// public static void logException(final String msg, final Throwable th) {
//     if (MarlinConst.USE_LOGGER) {
//         LOG.log(java.util.logging.Level.WARNING, msg, th);
//     } else if (MarlinConst.ENABLE_LOGS) {
//         System.out.print("WARNING: ");
//         System.out.println(msg);
//         th.printStackTrace(System.err);
//     }
// }
// 
// Path: src/main/java/com/sun/marlin/ArrayCacheConst.java
// static final class BucketStats {
//     int getOp = 0;
//     int createOp = 0;
//     int returnOp = 0;
//     int maxSize = 0;
// 
//     void reset() {
//         getOp = 0;
//         createOp = 0;
//         returnOp = 0;
//         maxSize = 0;
//     }
// 
//     void updateMaxSize(final int size) {
//         if (size > maxSize) {
//             maxSize = size;
//         }
//     }
// }
// 
// Path: src/main/java/com/sun/marlin/ArrayCacheConst.java
// static final class CacheStats {
//     final String name;
//     final BucketStats[] bucketStats;
//     int resize = 0;
//     int oversize = 0;
//     long totalInitial = 0L;
// 
//     CacheStats(final String name) {
//         this.name = name;
// 
//         bucketStats = new BucketStats[BUCKETS];
//         for (int i = 0; i < BUCKETS; i++) {
//             bucketStats[i] = new BucketStats();
//         }
//     }
// 
//     void reset() {
//         resize = 0;
//         oversize = 0;
// 
//         for (int i = 0; i < BUCKETS; i++) {
//             bucketStats[i].reset();
//         }
//     }
// 
//     long dumpStats() {
//         long totalCacheBytes = 0L;
// 
//         if (DO_STATS) {
//             for (int i = 0; i < BUCKETS; i++) {
//                 final BucketStats s = bucketStats[i];
// 
//                 if (s.maxSize != 0) {
//                     totalCacheBytes += getByteFactor()
//                                        * (s.maxSize * ARRAY_SIZES[i]);
//                 }
//             }
// 
//             if (totalInitial != 0L || totalCacheBytes != 0L
//                 || resize != 0 || oversize != 0)
//             {
//                 logInfo(name + ": resize: " + resize
//                         + " - oversize: " + oversize
//                         + " - initial: " + getTotalInitialBytes()
//                         + " bytes (" + totalInitial + " elements)"
//                         + " - cache: " + totalCacheBytes + " bytes"
//                 );
//             }
// 
//             if (totalCacheBytes != 0L) {
//                 logInfo(name + ": usage stats:");
// 
//                 for (int i = 0; i < BUCKETS; i++) {
//                     final BucketStats s = bucketStats[i];
// 
//                     if (s.getOp != 0) {
//                         logInfo("  Bucket[" + ARRAY_SIZES[i] + "]: "
//                                 + "get: " + s.getOp
//                                 + " - put: " + s.returnOp
//                                 + " - create: " + s.createOp
//                                 + " :: max size: " + s.maxSize
//                         );
//                     }
//                 }
//             }
//         }
//         return totalCacheBytes;
//     }
// 
//     private int getByteFactor() {
//         int factor = 1;
//         if (name.contains("Int") || name.contains("Float")) {
//             factor = 4;
//         } else if (name.contains("Double")) {
//             factor = 8;
//         }
//         return factor;
//     }
// 
//     long getTotalInitialBytes() {
//         return getByteFactor() * totalInitial;
//     }
// }


// Path: src/main/java/com/sun/marlin/ByteArrayCache.java
import java.lang.ref.WeakReference;
import java.util.Arrays;
import com.sun.marlin.ArrayCacheConst.BucketStats;
import com.sun.marlin.ArrayCacheConst.CacheStats;
import static com.sun.marlin.ArrayCacheConst.ARRAY_SIZES;
import static com.sun.marlin.ArrayCacheConst.BUCKETS;
import static com.sun.marlin.ArrayCacheConst.MAX_ARRAY_SIZE;
import static com.sun.marlin.MarlinUtils.logInfo;
import static com.sun.marlin.MarlinUtils.logException;

            }
            if (DO_STATS) {
                cache.stats.oversize++;
            }
            if (DO_LOG_OVERSIZE) {
                logInfo(getLogPrefix(clean) + "ByteArrayCache: "
                        + "getArray[oversize]: length=\t" + length);
            }
            return createArray(length);
        }

        byte[] widenArray(final byte[] array, final int usedSize,
                          final int needSize)
        {
            final int length = array.length;
            if (DO_CHECKS && length >= needSize) {
                return array;
            }
            if (DO_STATS) {
                cache.stats.resize++;
            }

            // maybe change bucket:
            // ensure getNewSize() > newSize:
            final byte[] res = getArray(ArrayCacheConst.getNewSize(usedSize, needSize));

            // use wrapper to ensure proper copy:
            System.arraycopy(array, 0, res, 0, usedSize); // copy only used elements

            // maybe return current array:
            putArray(array, 0, usedSize); // ensure array is cleared