// Path: src/main/java/com/lmax/angler/monitoring/network/monitor/util/FileLoader.java
// public final class FileLoader
// {
//     private final Path path;
//     private final ByteBuffer tmp = ByteBuffer.allocateDirect(4096);
//     private ByteBuffer buffer;
//     private FileChannel fileChannel;
// 
//     public FileLoader(final Path path, final int initialBufferCapacity)
//     {
//         this.path = path;
//         buffer = ByteBuffer.allocateDirect(initialBufferCapacity);
//     }
// 
//     /**
//      * Opens a channel to the specified path if it does not already exist.
//      * Allocates a larger ByteBuffer if file size &gt; current buffer size.
//      * Reads file data into ByteBuffer.
//      */
//     public void load()
//     {
//         try
//         {
//             if (fileChannel == null)
//             {
//                 fileChannel = FileChannel.open(path, StandardOpenOption.READ);
//             }
// 
//             fileChannel.position(0L);
//             buffer.clear();
//             tmp.clear();
//             while(fileChannel.read(tmp) > 0)
//             {
//                 tmp.flip();
//                 if(tmp.remaining() > buffer.capacity() - buffer.position())
//                 {
//                     final ByteBuffer next = ByteBuffer.allocateDirect(Math.max(buffer.capacity() * 2, tmp.remaining()));
//                     buffer.flip();
//                     next.put(buffer);
//                     buffer = next;
//                 }
//                 buffer.put(tmp);
//                 tmp.clear();
//             }
// 
//             buffer.flip();
//         }
//         catch(final IOException e)
//         {
//             throw new UncheckedIOException(e);
//         }
//     }
// 
//     public ByteBuffer getBuffer()
//     {
//         return buffer;
//     }
// }
// 
// Path: src/main/java/com/lmax/angler/monitoring/network/monitor/util/TokenHandler.java
// public interface TokenHandler
// {
//     /**
//      * Handle a single token.
//      * @param src data source
//      * @param startPosition the start position of the token
//      * @param endPosition the end position of the token
//      */
//     void handleToken(final ByteBuffer src, final int startPosition, final int endPosition);
// 
//     /**
//      * Current token set is complete.
//      */
//     void complete();
// 
//     /**
//      * Reset state in preparation for handling a new data set.
//      */
//     void reset();
// }
// 
// Path: src/main/java/com/lmax/angler/monitoring/network/monitor/util/Parsers.java
// public static TokenHandler rowColumnParser(
//         TokenHandler tokenHandler)
// {
//     return new DelimitedDataParser(
//             new DelimitedDataParser(
//                     tokenHandler,
//                     COLUMN_DELIMITER,
//                     true),
//             ROW_DELIMITER,
//             true);
// }


import com.lmax.angler.monitoring.network.monitor.util.FileLoader;
import com.lmax.angler.monitoring.network.monitor.util.TokenHandler;
import org.agrona.collections.Int2ObjectHashMap;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.nio.file.Paths;
import static com.lmax.angler.monitoring.network.monitor.util.Parsers.rowColumnParser;
import static java.lang.Runtime.getRuntime;
package com.lmax.angler.monitoring.network.monitor.system.softnet;




/**
 * Monitor for reporting changes in /proc/net/softnet_stat, which can indicate that the kernel thread
 * responsible for processing incoming network softIRQs is unable to keep up with the ingress rate.
 */
public final class SoftnetStatsMonitor
{
    private static final int ESTIMATED_LINE_LENGTH = 120;

    private final Int2ObjectHashMap<CpuSoftIrqData> cpuSoftIrqDataMap = new Int2ObjectHashMap<>();
    private final TokenHandler lineParser = rowColumnParser(new SoftnetStatColumnHandler(this::handleEntry));
// Path: src/main/java/com/lmax/angler/monitoring/network/monitor/util/FileLoader.java
// public final class FileLoader
// {
//     private final Path path;
//     private final ByteBuffer tmp = ByteBuffer.allocateDirect(4096);
//     private ByteBuffer buffer;
//     private FileChannel fileChannel;
// 
//     public FileLoader(final Path path, final int initialBufferCapacity)
//     {
//         this.path = path;
//         buffer = ByteBuffer.allocateDirect(initialBufferCapacity);
//     }
// 
//     /**
//      * Opens a channel to the specified path if it does not already exist.
//      * Allocates a larger ByteBuffer if file size &gt; current buffer size.
//      * Reads file data into ByteBuffer.
//      */
//     public void load()
//     {
//         try
//         {
//             if (fileChannel == null)
//             {
//                 fileChannel = FileChannel.open(path, StandardOpenOption.READ);
//             }
// 
//             fileChannel.position(0L);
//             buffer.clear();
//             tmp.clear();
//             while(fileChannel.read(tmp) > 0)
//             {
//                 tmp.flip();
//                 if(tmp.remaining() > buffer.capacity() - buffer.position())
//                 {
//                     final ByteBuffer next = ByteBuffer.allocateDirect(Math.max(buffer.capacity() * 2, tmp.remaining()));
//                     buffer.flip();
//                     next.put(buffer);
//                     buffer = next;
//                 }
//                 buffer.put(tmp);
//                 tmp.clear();
//             }
// 
//             buffer.flip();
//         }
//         catch(final IOException e)
//         {
//             throw new UncheckedIOException(e);
//         }
//     }
// 
//     public ByteBuffer getBuffer()
//     {
//         return buffer;
//     }
// }
// 
// Path: src/main/java/com/lmax/angler/monitoring/network/monitor/util/TokenHandler.java
// public interface TokenHandler
// {
//     /**
//      * Handle a single token.
//      * @param src data source
//      * @param startPosition the start position of the token
//      * @param endPosition the end position of the token
//      */
//     void handleToken(final ByteBuffer src, final int startPosition, final int endPosition);
// 
//     /**
//      * Current token set is complete.
//      */
//     void complete();
// 
//     /**
//      * Reset state in preparation for handling a new data set.
//      */
//     void reset();
// }
// 
// Path: src/main/java/com/lmax/angler/monitoring/network/monitor/util/Parsers.java
// public static TokenHandler rowColumnParser(
//         TokenHandler tokenHandler)
// {
//     return new DelimitedDataParser(
//             new DelimitedDataParser(
//                     tokenHandler,
//                     COLUMN_DELIMITER,
//                     true),
//             ROW_DELIMITER,
//             true);
// }


// Path: src/main/java/com/lmax/angler/monitoring/network/monitor/system/softnet/SoftnetStatsMonitor.java
import com.lmax.angler.monitoring.network.monitor.util.FileLoader;
import com.lmax.angler.monitoring.network.monitor.util.TokenHandler;
import org.agrona.collections.Int2ObjectHashMap;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.nio.file.Paths;
import static com.lmax.angler.monitoring.network.monitor.util.Parsers.rowColumnParser;
import static java.lang.Runtime.getRuntime;

package com.lmax.angler.monitoring.network.monitor.system.softnet;




/**
 * Monitor for reporting changes in /proc/net/softnet_stat, which can indicate that the kernel thread
 * responsible for processing incoming network softIRQs is unable to keep up with the ingress rate.
 */
public final class SoftnetStatsMonitor
{
    private static final int ESTIMATED_LINE_LENGTH = 120;

    private final Int2ObjectHashMap<CpuSoftIrqData> cpuSoftIrqDataMap = new Int2ObjectHashMap<>();
    private final TokenHandler lineParser = rowColumnParser(new SoftnetStatColumnHandler(this::handleEntry));
    private final FileLoader fileLoader;