<commit_before>package com.custardsource.parfait.pcp;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel.MapMode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.log4j.Logger;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.util.Assert;

import com.custardsource.parfait.Monitor;
import com.custardsource.parfait.Monitorable;
import com.custardsource.parfait.MonitorableRegistry;
import com.custardsource.parfait.MonitoringView;

/**
 * PcpMonitorBridge bridges between the set of {@link Monitorable}s in the current system and a PCP
 * monitor agent. The bridge works by persisting any changes to a Monitorable into a section of
 * memory that is also mapped into the PCP monitor agents address space.
 * <p>
 * The format of the shared address space is specified in an associated header file. A full
 * description of the communication protocol can be found under the issue ACX-5426.
 */
@ManagedResource
public class PcpMonitorBridge extends MonitoringView {

    private final Logger LOG = Logger.getLogger(PcpMonitorBridge.class);

    public static final byte PROTOCOL_VERSION = 1;

    public static final int MAX_STRING_LENGTH = 256;

    public static final int UPDATE_QUEUE_SIZE = 1024;

    public static final String ENCODING = "ISO-8859-1";

    private final Map<Monitorable<?>, Integer> monitorableOffsets = new HashMap<Monitorable<?>, Integer>();

    private final ArrayBlockingQueue<Monitorable<?>> monitorablesPendingUpdate = new ArrayBlockingQueue<Monitorable<?>>(
    		UPDATE_QUEUE_SIZE);

    private final Monitor monitor = new PcpMonitorBridgeMonitor();

    private final Thread updateThread;

    private final String serverName;

    private final File dataFileDir;

    /*
     * Determines whether value changes detected are written out to an external file for external
     * monitoring by the Aconex PCP agent.
     */
    private boolean outputValuesToPCPFile = true;

    private volatile ByteBuffer dataFileBuffer = null;

    private boolean deleteFilesOnExit = false;


    public PcpMonitorBridge(String serverName, String dataFileDir) {
    	this(serverName, dataFileDir, MonitorableRegistry.DEFAULT_REGISTRY);
    }

    public PcpMonitorBridge(String serverName, String dataFileDir, MonitorableRegistry registry) {
        super(registry);
        Assert.hasText(serverName, "Sever name can not be blank");
        this.serverName = serverName;
        this.dataFileDir = new File(dataFileDir);
        if (!this.dataFileDir.exists()) {
            this.dataFileDir.mkdirs();
        }
        Assert.isTrue(this.dataFileDir.isDirectory(), "dataFileDir [" + dataFileDir
                + "] is not a directory.");
        this.updateThread = new Thread(new Updater());
        this.updateThread.setName("PcpMonitorBridge-Updater");
        this.updateThread.setDaemon(true);
        Assert.notNull(registry);
    }

    @Override
    public void stopMonitoring(Collection<Monitorable<?>> monitorables) {
        dataFileBuffer = null;
        for (Monitorable<?> monitorable : monitorables) {
            monitorable.removeMonitor(monitor);
        }
    }

    public boolean hasUpdatesPending() {
        return monitorablesPendingUpdate.size() > 0;
    }

    @Override
    protected void startMonitoring(Collection<Monitorable<?>> monitorables) {
        try {
            // Calculate the data file offsets
            int dataFileOffset = 9; // 8 bytes for the version number and 1 for the protocol version
            for (Monitorable<?> monitorable : monitorables) {
                int dataSize = getTypeSize(monitorable.getType());
                dataFileOffset = align(dataFileOffset, dataSize);<commit_msg>Remove dependency on assert to clean up Spring dependency slightly<commit_after>package com.custardsource.parfait.pcp;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel.MapMode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;

import com.custardsource.parfait.Monitor;
import com.custardsource.parfait.Monitorable;
import com.custardsource.parfait.MonitorableRegistry;
import com.custardsource.parfait.MonitoringView;
import com.google.common.base.Preconditions;

/**
 * PcpMonitorBridge bridges between the set of {@link Monitorable}s in the current system and a PCP
 * monitor agent. The bridge works by persisting any changes to a Monitorable into a section of
 * memory that is also mapped into the PCP monitor agents address space.
 * <p>
 * The format of the shared address space is specified in an associated header file. A full
 * description of the communication protocol can be found under the issue ACX-5426.
 */
@ManagedResource
public class PcpMonitorBridge extends MonitoringView {

    private final Logger LOG = Logger.getLogger(PcpMonitorBridge.class);

    public static final byte PROTOCOL_VERSION = 1;

    public static final int MAX_STRING_LENGTH = 256;

    public static final int UPDATE_QUEUE_SIZE = 1024;

    public static final String ENCODING = "ISO-8859-1";

    private final Map<Monitorable<?>, Integer> monitorableOffsets = new HashMap<Monitorable<?>, Integer>();

    private final ArrayBlockingQueue<Monitorable<?>> monitorablesPendingUpdate = new ArrayBlockingQueue<Monitorable<?>>(
    		UPDATE_QUEUE_SIZE);

    private final Monitor monitor = new PcpMonitorBridgeMonitor();

    private final Thread updateThread;

    private final String serverName;

    private final File dataFileDir;

    /*
     * Determines whether value changes detected are written out to an external file for external
     * monitoring by the Aconex PCP agent.
     */
    private boolean outputValuesToPCPFile = true;

    private volatile ByteBuffer dataFileBuffer = null;

    private boolean deleteFilesOnExit = false;


    public PcpMonitorBridge(String serverName, String dataFileDir) {
    	this(serverName, dataFileDir, MonitorableRegistry.DEFAULT_REGISTRY);
    }

    public PcpMonitorBridge(String serverName, String dataFileDir, MonitorableRegistry registry) {
		super(registry);
		Preconditions.checkNotNull(registry);
		Preconditions.checkArgument(StringUtils.isNotBlank(serverName),
				"Sever name can not be blank");
		this.serverName = serverName;
		this.dataFileDir = new File(dataFileDir);
		if (!this.dataFileDir.exists()) {
			this.dataFileDir.mkdirs();
		}
		Preconditions.checkArgument(this.dataFileDir.isDirectory(),
				"dataFileDir [%s] is not a directory.", dataFileDir);
		this.updateThread = new Thread(new Updater());
		this.updateThread.setName("PcpMonitorBridge-Updater");
		this.updateThread.setDaemon(true);
    }

    @Override
    public void stopMonitoring(Collection<Monitorable<?>> monitorables) {
        dataFileBuffer = null;
        for (Monitorable<?> monitorable : monitorables) {
            monitorable.removeMonitor(monitor);
        }
    }

    public boolean hasUpdatesPending() {
        return monitorablesPendingUpdate.size() > 0;
    }

    @Override
    protected void startMonitoring(Collection<Monitorable<?>> monitorables) {
        try {
            // Calculate the data file offsets
            int dataFileOffset = 9; // 8 bytes for the version number and 1 for the protocol version
            for (Monitorable<?> monitorable : monitorables) {
                int dataSize = getTypeSize(monitorable.getType());
                dataFileOffset = align(dataFileOffset, dataSize);
{'fraction_non_alphanumeric': 0.08258258258258258, 'fraction_numerical': 0.005082005082005082, 'mean_word_length': 4.051925320886815, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 35, 'https://': 0, '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': '1119131', 'n_tokens_mistral': 2421, 'n_tokens_neox': 2312, 'n_words': 663}