All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jmeter.control.CriticalSectionController Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jmeter.control;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.samplers.Sampler;
import org.apache.jmeter.testelement.TestStateListener;
import org.apache.jmeter.testelement.ThreadListener;
import org.apache.jmeter.testelement.property.StringProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This is a Critical Section Controller; it will execute the set of statements
 * (samplers/controllers, etc) under named lock.
 * 

* In a programming world - this is equivalent of : * *

 * try {
 *          named_lock.lock();
 *          statements ....
 * } finally {
 *          named_lock.unlock();
 * }
 * 
* * In JMeter you may have : * *
 * Thread-Group (set to loop a number of times or indefinitely,
 *    ... Samplers ... (e.g. Counter )
 *    ... Other Controllers ....
 *    ... CriticalSectionController ( lock name like "foobar" )
 *       ... statements to perform when lock acquired
 *       ...
 *    ... Other Controllers /Samplers }
 * 
* * @since 2.12 */ public class CriticalSectionController extends GenericController implements ThreadListener, TestStateListener { private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory.getLogger(CriticalSectionController.class); private static final String LOCK_NAME = "CriticalSectionController.lockName"; //$NON-NLS-1$ private static final ConcurrentHashMap LOCK_MAP = new ConcurrentHashMap<>(); private transient volatile ReentrantLock currentLock; /** * constructor */ public CriticalSectionController() { super(); } /** * constructor * @param name The name of this controller */ public CriticalSectionController(String name) { super(); this.setName(name); } /** * Condition Accessor - this is gonna be any string value * @param name The name of the lock for this controller */ public void setLockName(String name) { setProperty(new StringProperty(LOCK_NAME, name)); } /** * If lock exists returns it, otherwise creates one, puts it in LOCK_MAP * then returns it * * @return {@link ReentrantLock} */ private ReentrantLock getOrCreateLock() { String lockName = getLockName(); ReentrantLock lock = LOCK_MAP.get(lockName); ReentrantLock prev; if (lock != null) { return lock; } lock = new ReentrantLock(); prev = LOCK_MAP.putIfAbsent(lockName, lock); return prev == null ? lock : prev; } /** * @return String lock name */ public String getLockName() { return getPropertyAsString(LOCK_NAME); } /** * @see org.apache.jmeter.control.Controller#next() */ @Override public Sampler next() { if (StringUtils.isEmpty(getLockName())) { if (log.isWarnEnabled()) { log.warn("Empty lock name in Critical Section Controller: {}", getName()); } return super.next(); } if (isFirst()) { // Take the lock for first child element long startTime = System.currentTimeMillis(); if (this.currentLock == null) { this.currentLock = getOrCreateLock(); } this.currentLock.lock(); long endTime = System.currentTimeMillis(); if (log.isDebugEnabled()) { log.debug("Thread ('{}') acquired lock: '{}' in Critical Section Controller {} in: {} ms", Thread.currentThread(), getLockName(), getName(), endTime - startTime); } } return super.next(); } /** * Called after execution of last child of the controller We release lock * * @see org.apache.jmeter.control.GenericController#reInitialize() */ @Override protected void reInitialize() { if (this.currentLock != null) { if (currentLock.isHeldByCurrentThread()) { this.currentLock.unlock(); } this.currentLock = null; } super.reInitialize(); } @Override public void threadStarted() { this.currentLock = null; } @Override public void threadFinished() { if (this.currentLock != null && this.currentLock.isHeldByCurrentThread()) { if (log.isWarnEnabled()) { log.warn("Lock '{}' not released in: {}, releasing in threadFinished", getLockName(), getName()); } this.currentLock.unlock(); } this.currentLock = null; } @Override public void testStarted() { // NOOP } @Override public void testStarted(String host) { // NOOP } @Override public void testEnded() { LOCK_MAP.clear(); } @Override public void testEnded(String host) { testEnded(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy