<commit_before>/*******************************************************************************
 * (C) Copyright 2016 <NAME> and <NAME>
 *  
 * This file is part of STEP
 *  
 * STEP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *  
 * STEP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *  
 * You should have received a copy of the GNU Affero General Public License
 * along with STEP.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package step.grid.agent.tokenpool;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AgentTokenPool {
	
	private static final Logger logger = LoggerFactory.getLogger(AgentTokenPool.class);
	
	private final Map<String, AgentTokenWrapper> pool = new HashMap<>();
	
	public AgentTokenPool() {
		super();
	}

	public synchronized List<AgentTokenWrapper> getTokens() {
		List<AgentTokenWrapper> result = new ArrayList<>(pool.size());
		result.addAll(pool.values());
		return result;
	}
	
	public synchronized void offerToken(AgentTokenWrapper token) {
		logger.debug("offerToken: " + token.toString());
		pool.put(token.getUid(), token);
	}
	
	public synchronized AgentTokenWrapper getTokenForExecution(String tokenId) throws InvalidTokenIdException {
		AgentTokenWrapper token = pool.get(tokenId);
		if(token!=null) {
			if(token.getTokenReservationSession()==null) {
				token.setTokenReservationSession(new TokenReservationSession() {
					@Override
					public Object get(String arg0) {
						throw unusableSessionException();
					}

					@Override
					public Object put(String arg0, Object arg1) {
						throw unusableSessionException();
					}

					private RuntimeException unusableSessionException() {
						// TODO use error codes instead of error messages
						return new RuntimeException("Session object unreachable. Wrap your keywords with a Session node in your test plan in order to make the session object available.");
					}
				});
			}
		} else {
			throw new InvalidTokenIdException();
		}
		return token;
	}
	
	private AgentTokenWrapper getToken(String tokenId) {
		AgentTokenWrapper token = pool.get(tokenId);
		return token;
	}
	
	public synchronized void createTokenReservationSession(String tokenId) throws InvalidTokenIdException {
		AgentTokenWrapper token = getToken(tokenId);
		if(token!=null) {
			TokenReservationSession previousTokenReservationSession = token.getTokenReservationSession();
			if(previousTokenReservationSession!=null) {
				logger.warn("Trying to reserve token '"+tokenId+"' which is already reserved. Closing previous session.");
				try {
					previousTokenReservationSession.close();
				} catch (Exception e) {
					logger.warn("Error while closing token session for token "+tokenId+
							". This may cause a resource leak. Creating new session anyway.", e);
				}
			}
			
			TokenReservationSession tokenReservationContext = new TokenReservationSession();
			token.setTokenReservationSession(tokenReservationContext);
		} else {
			throw new InvalidTokenIdException();
		}
	}
	
	public synchronized void closeTokenReservationSession(String tokenId) throws InvalidTokenIdException {
		AgentTokenWrapper token = getToken(tokenId);
		if(token!=null) {
			TokenReservationSession tokenReservationSession = token.getTokenReservationSession();
			token.setTokenReservationSession(null);
			if(tokenReservationSession!=null) {
				try {
					tokenReservationSession.close();					
				} catch (Exception e) {
					logger.warn("Error while closing token session for token "+tokenId+
							". This may cause a resource leak. Still returning token to the pool.", e);
				}
			} else {
				// token has already been released or has never been reserved. Nothing to do.
				logger.warn("Trying to release token '"+tokenId+"' which is not reserved");
			}
		} else {
			throw new InvalidTokenIdException();
		}
	}
	
	@SuppressWarnings("serial")
	public static class InvalidTokenIdException extends Exception {
		
	}
}
<commit_msg>Fixing synchronization issue in AgentTokenPool<commit_after>/*******************************************************************************
 * (C) Copyright 2016 <NAME> and <NAME>
 *  
 * This file is part of STEP
 *  
 * STEP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *  
 * STEP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *  
 * You should have received a copy of the GNU Affero General Public License
 * along with STEP.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package step.grid.agent.tokenpool;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AgentTokenPool {
	
	private static final Logger logger = LoggerFactory.getLogger(AgentTokenPool.class);
	
	private final Map<String, AgentTokenWrapper> pool = new ConcurrentHashMap<>();
	
	public AgentTokenPool() {
		super();
	}

	public List<AgentTokenWrapper> getTokens() {
		List<AgentTokenWrapper> result = new ArrayList<>(pool.values());
		return result;
	}
	
	public void offerToken(AgentTokenWrapper token) {
		if(logger.isDebugEnabled()) {
			logger.debug("offerToken: " + token.toString());
		}
		pool.put(token.getUid(), token);
	}
	
	public AgentTokenWrapper getTokenForExecution(String tokenId) throws InvalidTokenIdException {
		AgentTokenWrapper token = pool.get(tokenId);
		if(token!=null) {
			if(token.getTokenReservationSession()==null) {
				token.setTokenReservationSession(new TokenReservationSession() {
					@Override
					public Object get(String arg0) {
						throw unusableSessionException();
					}

					@Override
					public Object put(String arg0, Object arg1) {
						throw unusableSessionException();
					}

					private RuntimeException unusableSessionException() {
						// TODO use error codes instead of error messages
						return new RuntimeException("Session object unreachable. Wrap your keywords with a Session node in your test plan in order to make the session object available.");
					}
				});
			}
		} else {
			throw new InvalidTokenIdException();
		}
		return token;
	}
	
	private AgentTokenWrapper getToken(String tokenId) {
		AgentTokenWrapper token = pool.get(tokenId);
		return token;
	}
	
	public void createTokenReservationSession(String tokenId) throws InvalidTokenIdException {
		AgentTokenWrapper token = getToken(tokenId);
		if(token!=null) {
			TokenReservationSession previousTokenReservationSession = token.getTokenReservationSession();
			if(previousTokenReservationSession!=null) {
				logger.warn("Trying to reserve token '"+tokenId+"' which is already reserved. Closing previous session.");
				try {
					previousTokenReservationSession.close();
				} catch (Exception e) {
					logger.warn("Error while closing token session for token "+tokenId+
							". This may cause a resource leak. Creating new session anyway.", e);
				}
			}
			
			TokenReservationSession tokenReservationContext = new TokenReservationSession();
			token.setTokenReservationSession(tokenReservationContext);
		} else {
			throw new InvalidTokenIdException();
		}
	}
	
	public void closeTokenReservationSession(String tokenId) throws InvalidTokenIdException {
		AgentTokenWrapper token = getToken(tokenId);
		if(token!=null) {
			TokenReservationSession tokenReservationSession = token.getTokenReservationSession();
			token.setTokenReservationSession(null);
			if(tokenReservationSession!=null) {
				try {
					tokenReservationSession.close();					
				} catch (Exception e) {
					logger.warn("Error while closing token session for token "+tokenId+
							". This may cause a resource leak. Still returning token to the pool.", e);
				}
			} else {
				// token has already been released or has never been reserved. Nothing to do.
				logger.warn("Trying to release token '"+tokenId+"' which is not reserved");
			}
		} else {
			throw new InvalidTokenIdException();
		}
	}
	
	@SuppressWarnings("serial")
	public static class InvalidTokenIdException extends Exception {
		
	}
}

{'fraction_non_alphanumeric': 0.1165604407475424, 'fraction_numerical': 0.0021605271686291456, 'mean_word_length': 3.733128834355828, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '6079930', 'n_tokens_mistral': 2801, 'n_tokens_neox': 2355, 'n_words': 761}