<commit_before>/*
 * Copyright 2003-2006 <NAME> <winstone-devel at lists sourceforge net>
 * Distributed under the terms of either:
 * - the common development and distribution license (CDDL), v1.0; or
 * - the GNU Lesser General Public License, v2.1 or later
 */
package net.winstone.core;

import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import net.winstone.core.listener.Listener;
import net.winstone.core.listener.RequestHandlerThread;
import net.winstone.util.StringUtils;

import org.slf4j.LoggerFactory;

/**
 * Holds the object pooling code for Winstone. Presently this is only responses
 * and requests, but may increase.
 * 
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @version $Id: ObjectPool.java,v 1.9 2006/11/18 14:56:59 rickknowles Exp $
 */
public class ObjectPool {

	protected static org.slf4j.Logger logger = LoggerFactory.getLogger(ObjectPool.class);

	/**
	 * FLUSH PERIOD 60 second.
	 */
	private static final long FLUSH_PERIOD = 60000L;

	/**
	 * Default startup request handler in pool (5).
	 */
	private final static transient int STARTUP_REQUEST_HANDLERS_IN_POOL = 5;
	/**
	 * Maximum idle request handler in pool (50).
	 */
	private final static transient int MAX_IDLE_REQUEST_HANDLERS_IN_POOL = 50;
	/**
	 * Maximum request handler in pool (1000).
	 */
	private final static transient int MAX_REQUEST_HANDLERS_IN_POOL = 1000;
	/**
	 * Retry period (1 second).
	 */
	private final static transient long RETRY_PERIOD = 1000;
	/**
	 * Start requests in pool (10).
	 */
	private final static transient int START_REQUESTS_IN_POOL = 10;
	/**
	 * Max requests in pool (1000).
	 */
	private final static transient int MAX_REQUESTS_IN_POOL = 1000;
	/**
	 * Start responses in pool (10).
	 */
	private final static transient int START_RESPONSES_IN_POOL = 10;
	/**
	 * Maximum responses in pool (1000).
	 */
	private final static transient int MAX_RESPONSES_IN_POOL = 1000;

	private final List<RequestHandlerThread> unusedRequestHandlerThreads;
	private final List<RequestHandlerThread> usedRequestHandlerThreads;
	private final List<WinstoneRequest> unusedRequestPool;
	private final List<WinstoneResponse> unusedResponsePool;
	private final Object requestHandlerSemaphore = Boolean.TRUE;
	private final Object requestPoolSemaphore = Boolean.TRUE;
	private final Object responsePoolSemaphore = Boolean.TRUE;

	private int threadIndex = 0;
	private final boolean simulateModUniqueId;
	private final boolean saveSessions;

	private Thread thread;

	int startupRequest = ObjectPool.STARTUP_REQUEST_HANDLERS_IN_POOL;
	int maxRequestHandlesInPool = ObjectPool.MAX_REQUEST_HANDLERS_IN_POOL;
	int maxIdleRequestHandlesInPool = ObjectPool.MAX_IDLE_REQUEST_HANDLERS_IN_POOL;

	/**
	 * max number of parameters allowed.
	 */
	private static int MAXPARAMALLOWED = WinstoneConstant.DEFAULT_MAXIMUM_PARAMETER_ALLOWED;

	/**
	 * Constructs an instance of the object pool, including handlers, requests
	 * and responses
	 */
	public ObjectPool(final Map<String, String> args) throws IOException {
		super();
		// load simulateModUniqueId
		simulateModUniqueId = StringUtils.booleanArg(args, "simulateModUniqueId", Boolean.FALSE);
		// load maxParamAllowed
		int maxParamAllowed = StringUtils.intArg(args, "maxParamAllowed", WinstoneConstant.DEFAULT_MAXIMUM_PARAMETER_ALLOWED);
		if (maxParamAllowed < 1) {
			logger.error("MaxParamAllowed should be greather than 1. Set to default value {}", WinstoneConstant.DEFAULT_MAXIMUM_PARAMETER_ALLOWED);
			maxParamAllowed = WinstoneConstant.DEFAULT_MAXIMUM_PARAMETER_ALLOWED;
		}
		ObjectPool.MAXPARAMALLOWED = maxParamAllowed;
		// load saveSessions
		saveSessions = WebAppConfiguration.useSavedSessions(args);

		// Build the initial pool of handler threads
		unusedRequestHandlerThreads = new ArrayList<RequestHandlerThread>();
		usedRequestHandlerThreads = new ArrayList<RequestHandlerThread>();

		// Build the request/response pools
		unusedRequestPool = new ArrayList<WinstoneRequest>();
		unusedResponsePool = new ArrayList<WinstoneResponse>();

		// Get handler pool options
		startupRequest = StringUtils.intArg(args, "handlerCountStartup", ObjectPool.STARTUP_REQUEST_HANDLERS_IN_POOL);
		maxRequestHandlesInPool = StringUtils.intArg(args, "handlerCountMax", ObjectPool.MAX_REQUEST_HANDLERS_IN_POOL);
		maxIdleRequestHandlesInPool = StringUtils.intArg(args, "handlerCountMaxIdle", ObjectPool.MAX_IDLE_REQUEST_HANDLERS_IN_POOL);

		// Start the base set of handler threads
		for (int n = 0; n < startupRequest; n++) {
			unusedRequestHandlerThreads.add(new RequestHandlerThread(this, threadIndex++, simulateModUniqueId, saveSessions));
		}

		// Initialize the request/response pools
		for (int n = 0; n < ObjectPool.START_REQUESTS_IN_POOL; n++) {
			unusedRequestPool.add(new WinstoneRequest(ObjectPool.MAXPARAMALLOWED));
		}
		for (int n = 0; n < ObjectPool.START_RESPONSES_IN_POOL; n++) {
			unusedResponsePool.add(new WinstoneResponse());
		}

		thread = new Thread(new Runnable() {
			/**
			 * Every 60s, remove unused request handler.
			 * 
			 * @see java.lang.Runnable#run()
			 */
			@Override
			public void run() {
				boolean interrupted = Boolean.FALSE;
				while (!interrupted) {
					try {
						Thread.sleep(ObjectPool.FLUSH_PERIOD);
						removeUnusedRequestHandlers();
					} catch (final InterruptedException err) {
						interrupted = Boolean.TRUE;
					}
				}
				thread = null;
			}
		}, "WinstoneObjectPoolMgmt");
		thread.setDaemon(Boolean.TRUE);
		thread.start();
	}

	/**
	 * remove Unused RequestHandlers.
	 */
	private void removeUnusedRequestHandlers() {
		// Check max idle requestHandler count
		synchronized (requestHandlerSemaphore) {
			// If we have too many idle request handlers
			while (unusedRequestHandlerThreads.size() > maxIdleRequestHandlesInPool) {
				final RequestHandlerThread rh = unusedRequestHandlerThreads.get(0);
				rh.destroy();
				unusedRequestHandlerThreads.remove(rh);
			}
		}
	}

	/**
	 * Destroy Object Pool.
	 */
	public void destroy() {
		synchronized (requestHandlerSemaphore) {
			for (final RequestHandlerThread handlerThread : usedRequestHandlerThreads) {
				releaseRequestHandler(handlerThread);
			}
			for (final RequestHandlerThread handlerThread : unusedRequestHandlerThreads) {
				handlerThread.destroy();
			}
			unusedRequestHandlerThreads.clear();
		}
		if (thread != null) {
			thread.interrupt();
		}
	}

	/**
	 * Once the socket request comes in, this method is called. It reserves a
	 * request handler, then delegates the socket to that class. When it
	 * finishes, the handler is released back into the pool.
	 */
	public void handleRequest(final Socket socket, final Listener listener) throws IOException, InterruptedException {
		RequestHandlerThread rh = null;
		synchronized (requestHandlerSemaphore) {
			// If we have any spare, get it from the pool
			final int unused = unusedRequestHandlerThreads.size();
			if (unused > 0) {
				rh = unusedRequestHandlerThreads.remove(unused - 1);
				usedRequestHandlerThreads.add(rh);
				ObjectPool.logger.debug("RHPool: Using pooled handler thread - used: {} unused: {}", "" + usedRequestHandlerThreads.size(), "" + unusedRequestHandlerThreads.size());
			} // If we are out (and not over our limit), allocate a new one<commit_msg>FIX concurrent modification<commit_after>/*
 * Copyright 2003-2006 <NAME> <winstone-devel at lists sourceforge net>
 * Distributed under the terms of either:
 * - the common development and distribution license (CDDL), v1.0; or
 * - the GNU Lesser General Public License, v2.1 or later
 */
package net.winstone.core;

import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import net.winstone.core.listener.Listener;
import net.winstone.core.listener.RequestHandlerThread;
import net.winstone.util.StringUtils;

import org.slf4j.LoggerFactory;

/**
 * Holds the object pooling code for Winstone. Presently this is only responses
 * and requests, but may increase.
 * 
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @version $Id: ObjectPool.java,v 1.9 2006/11/18 14:56:59 rickknowles Exp $
 */
public class ObjectPool {

	protected static org.slf4j.Logger logger = LoggerFactory.getLogger(ObjectPool.class);

	/**
	 * FLUSH PERIOD 60 second.
	 */
	private static final long FLUSH_PERIOD = 60000L;

	/**
	 * Default startup request handler in pool (5).
	 */
	private final static transient int STARTUP_REQUEST_HANDLERS_IN_POOL = 5;
	/**
	 * Maximum idle request handler in pool (50).
	 */
	private final static transient int MAX_IDLE_REQUEST_HANDLERS_IN_POOL = 50;
	/**
	 * Maximum request handler in pool (1000).
	 */
	private final static transient int MAX_REQUEST_HANDLERS_IN_POOL = 1000;
	/**
	 * Retry period (1 second).
	 */
	private final static transient long RETRY_PERIOD = 1000;
	/**
	 * Start requests in pool (10).
	 */
	private final static transient int START_REQUESTS_IN_POOL = 10;
	/**
	 * Max requests in pool (1000).
	 */
	private final static transient int MAX_REQUESTS_IN_POOL = 1000;
	/**
	 * Start responses in pool (10).
	 */
	private final static transient int START_RESPONSES_IN_POOL = 10;
	/**
	 * Maximum responses in pool (1000).
	 */
	private final static transient int MAX_RESPONSES_IN_POOL = 1000;

	private final List<RequestHandlerThread> unusedRequestHandlerThreads;
	private final List<RequestHandlerThread> usedRequestHandlerThreads;
	private final List<WinstoneRequest> unusedRequestPool;
	private final List<WinstoneResponse> unusedResponsePool;
	private final Object requestHandlerSemaphore = Boolean.TRUE;
	private final Object requestPoolSemaphore = Boolean.TRUE;
	private final Object responsePoolSemaphore = Boolean.TRUE;

	private int threadIndex = 0;
	private final boolean simulateModUniqueId;
	private final boolean saveSessions;

	private Thread thread;

	int startupRequest = ObjectPool.STARTUP_REQUEST_HANDLERS_IN_POOL;
	int maxRequestHandlesInPool = ObjectPool.MAX_REQUEST_HANDLERS_IN_POOL;
	int maxIdleRequestHandlesInPool = ObjectPool.MAX_IDLE_REQUEST_HANDLERS_IN_POOL;

	/**
	 * max number of parameters allowed.
	 */
	private static int MAXPARAMALLOWED = WinstoneConstant.DEFAULT_MAXIMUM_PARAMETER_ALLOWED;

	/**
	 * Constructs an instance of the object pool, including handlers, requests
	 * and responses
	 */
	public ObjectPool(final Map<String, String> args) throws IOException {
		super();
		// load simulateModUniqueId
		simulateModUniqueId = StringUtils.booleanArg(args, "simulateModUniqueId", Boolean.FALSE);
		// load maxParamAllowed
		int maxParamAllowed = StringUtils.intArg(args, "maxParamAllowed", WinstoneConstant.DEFAULT_MAXIMUM_PARAMETER_ALLOWED);
		if (maxParamAllowed < 1) {
			logger.error("MaxParamAllowed should be greather than 1. Set to default value {}", WinstoneConstant.DEFAULT_MAXIMUM_PARAMETER_ALLOWED);
			maxParamAllowed = WinstoneConstant.DEFAULT_MAXIMUM_PARAMETER_ALLOWED;
		}
		ObjectPool.MAXPARAMALLOWED = maxParamAllowed;
		// load saveSessions
		saveSessions = WebAppConfiguration.useSavedSessions(args);

		// Build the initial pool of handler threads
		unusedRequestHandlerThreads = new ArrayList<RequestHandlerThread>();
		usedRequestHandlerThreads = new ArrayList<RequestHandlerThread>();

		// Build the request/response pools
		unusedRequestPool = new ArrayList<WinstoneRequest>();
		unusedResponsePool = new ArrayList<WinstoneResponse>();

		// Get handler pool options
		startupRequest = StringUtils.intArg(args, "handlerCountStartup", ObjectPool.STARTUP_REQUEST_HANDLERS_IN_POOL);
		maxRequestHandlesInPool = StringUtils.intArg(args, "handlerCountMax", ObjectPool.MAX_REQUEST_HANDLERS_IN_POOL);
		maxIdleRequestHandlesInPool = StringUtils.intArg(args, "handlerCountMaxIdle", ObjectPool.MAX_IDLE_REQUEST_HANDLERS_IN_POOL);

		// Start the base set of handler threads
		for (int n = 0; n < startupRequest; n++) {
			unusedRequestHandlerThreads.add(new RequestHandlerThread(this, threadIndex++, simulateModUniqueId, saveSessions));
		}

		// Initialize the request/response pools
		for (int n = 0; n < ObjectPool.START_REQUESTS_IN_POOL; n++) {
			unusedRequestPool.add(new WinstoneRequest(ObjectPool.MAXPARAMALLOWED));
		}
		for (int n = 0; n < ObjectPool.START_RESPONSES_IN_POOL; n++) {
			unusedResponsePool.add(new WinstoneResponse());
		}

		thread = new Thread(new Runnable() {
			/**
			 * Every 60s, remove unused request handler.
			 * 
			 * @see java.lang.Runnable#run()
			 */
			@Override
			public void run() {
				boolean interrupted = Boolean.FALSE;
				while (!interrupted) {
					try {
						Thread.sleep(ObjectPool.FLUSH_PERIOD);
						removeUnusedRequestHandlers();
					} catch (final InterruptedException err) {
						interrupted = Boolean.TRUE;
					}
				}
				thread = null;
			}
		}, "WinstoneObjectPoolMgmt");
		thread.setDaemon(Boolean.TRUE);
		thread.start();
	}

	/**
	 * remove Unused RequestHandlers.
	 */
	private void removeUnusedRequestHandlers() {
		// Check max idle requestHandler count
		synchronized (requestHandlerSemaphore) {
			// If we have too many idle request handlers
			while (unusedRequestHandlerThreads.size() > maxIdleRequestHandlesInPool) {
				final RequestHandlerThread rh = unusedRequestHandlerThreads.get(0);
				rh.destroy();
				unusedRequestHandlerThreads.remove(rh);
			}
		}
	}

	/**
	 * Destroy Object Pool.
	 */
	public void destroy() {
		synchronized (requestHandlerSemaphore) {
			List<RequestHandlerThread> handlerThreads = new ArrayList<RequestHandlerThread>(usedRequestHandlerThreads);
			for (final RequestHandlerThread handlerThread : handlerThreads) {
				releaseRequestHandler(handlerThread);
			}
			handlerThreads = new ArrayList<RequestHandlerThread>(unusedRequestHandlerThreads);
			for (final RequestHandlerThread handlerThread : handlerThreads) {
				handlerThread.destroy();
			}
			unusedRequestHandlerThreads.clear();
		}
		if (thread != null) {
			thread.interrupt();
		}
	}

	/**
	 * Once the socket request comes in, this method is called. It reserves a
	 * request handler, then delegates the socket to that class. When it
	 * finishes, the handler is released back into the pool.
	 */
	public void handleRequest(final Socket socket, final Listener listener) throws IOException, InterruptedException {
		RequestHandlerThread rh = null;
		synchronized (requestHandlerSemaphore) {
			// If we have any spare, get it from the pool
			final int unused = unusedRequestHandlerThreads.size();
			if (unused > 0) {
				rh = unusedRequestHandlerThreads.remove(unused - 1);
				usedRequestHandlerThreads.add(rh);
				ObjectPool.logger.debug("RHPool: Using pooled handler thread - used: {} unused: {}", "" + usedRequestHandlerThreads.size(), "" + unusedRequestHandlerThreads.size());
			} // If we are out (and not over our limit), allocate a new one
{'fraction_non_alphanumeric': 0.09284411108858706, 'fraction_numerical': 0.012298128251908912, 'mean_word_length': 4.580693815987933, 'pattern_counts': {'":': 0, '<': 44, '<?xml version=': 0, '>': 40, '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': '2978193', 'n_tokens_mistral': 4946, 'n_tokens_neox': 4359, 'n_words': 1170}