/* * Hibernate OGM, Domain model persistence for NoSQL datastores * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.ogm.utils; import static org.junit.Assert.fail; import java.util.Deque; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.atomic.AtomicInteger; import org.hibernate.search.util.logging.impl.Log; import org.hibernate.search.util.logging.impl.LoggerFactory; import org.jboss.byteman.rule.Rule; import org.jboss.byteman.rule.helper.Helper; /** * @author Sanne Grinovero (C) 2011 Red Hat Inc. * @author Hardy Ferentschik */ public class BytemanHelper extends Helper { private static final Log log = LoggerFactory.make(); private static final String DEFAULT_COUNTER = "__DEFAULT_COUNTER_"; private static final Map<String, AtomicInteger> counters = new ConcurrentHashMap<>(); private static final Deque<String> concurrentStack = new ConcurrentLinkedDeque<>(); protected BytemanHelper(Rule rule) { super( rule ); } public void sleepASecond() { try { log.info( "Byteman rule triggered: sleeping a second" ); Thread.sleep( 1000 ); } catch (InterruptedException e) { Thread.currentThread().interrupt(); log.error( "unexpected interruption", e ); } } public void assertBooleanValue(boolean actual, boolean expected) { if ( actual != expected ) { fail( "Unexpected boolean value" ); } } public void countInvocation() { countInvocation( DEFAULT_COUNTER ); } public void countInvocation(String counter) { log.debug( "Increment call count for " + counter ); if ( !counters.containsKey( counter ) ) { counters.put( counter, new AtomicInteger() ); } counters.get( counter ).incrementAndGet(); } public static int getAndResetInvocationCount() { return getAndResetInvocationCount( DEFAULT_COUNTER ); } public static int getAndResetInvocationCount(String counter) { if ( !counters.containsKey( counter ) ) { return 0; } return counters.get( counter ).getAndSet( 0 ); } public static void resetCounters() { counters.clear(); } /** * Adds a label to a concurrent queue. * Useful to "tag" events to verify they are issued in a specific order, * even though they are generated by different threads. * @param message some label to be recorded */ public void pushEvent(String message) { concurrentStack.add( message ); } /** * Gets the first event label from the concurrent queue, * and removes it. * The next invocation will return the next one from the queue. * @return the first */ public static String consumeNextRecordedEvent() { return concurrentStack.removeFirst(); } public static boolean isEventStackEmpty() { return concurrentStack.isEmpty(); } /** * Removes all state from the concurrent queue * used to track events. */ static void resetEventStack() { concurrentStack.clear(); } }