Skip to content

Commit

Permalink
JBTM-2673 Updated to use a map for storing the thread IDs rather than…
Browse files Browse the repository at this point in the history
… a thread local - this corrects a defect where the Thread parameter was ignored
  • Loading branch information
tomjenkinson committed Nov 15, 2016
1 parent 480b4a7 commit 45c242d
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ public final boolean addChildThread (Thread t)

public final boolean removeChildThread () // current thread
{
return removeChildThread(ThreadUtil.getThreadId());
return removeChildThread(ThreadUtil.removeThreadId(Thread.currentThread()));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
*/
package com.arjuna.ats.arjuna.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

/**
* Provides utilities to manage thread ids.
*/
Expand All @@ -28,11 +32,11 @@ public class ThreadUtil
/**
* The ID associated with the thread.
*/
private static final ThreadLocal THREAD_ID = new ThreadLocal() ;
private static final Map<Thread,String> THREAD_ID = new HashMap<Thread,String>() ;
/**
* The thread id counter.
*/
private static long id ;
private static AtomicLong id = new AtomicLong();

/**
* Get the string ID for the current thread.
Expand All @@ -50,23 +54,33 @@ public static String getThreadId()
*/
public static String getThreadId(final Thread thread)
{
final Object id = THREAD_ID.get() ;
final String id = THREAD_ID.get(thread) ;
if (id != null)
{
return (String)id ;
return id ;
}

final String newId = getNextId() ;
THREAD_ID.set(newId) ;
THREAD_ID.put(thread,newId) ;
return newId ;
}

/**
* As the association is stored in a map callers need to ensure they remove from the thread when the threadID is no longer required.
*
* @param thread The thread to remove from the map
* @return The ID that matched the thread
*/
public static String removeThreadId(final Thread thread) {
return THREAD_ID.remove(thread);
}

/**
* Get the next thread id to use.
* @return The next thread id.
*/
private static synchronized String getNextId()
private static String getNextId()
{
return "TSThread:" + Long.toHexString(++id) ;
return Long.toHexString(id.incrementAndGet()) ;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ public static void purgeActions (Thread t, boolean unregister)

if (act != null)
{
act.removeChildThread(ThreadUtil.getThreadId(t));
act.removeChildThread(ThreadUtil.removeThreadId(t));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006,
* @author JBoss Inc.
*/
package com.hp.mwtests.ts.arjuna.threadaction;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Hashtable;
import java.util.concurrent.atomic.AtomicBoolean;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.arjuna.ats.arjuna.AtomicAction;
import com.arjuna.ats.arjuna.common.CoordinatorEnvironmentBean;
import com.arjuna.ats.arjuna.common.Uid;
import com.arjuna.ats.arjuna.common.arjPropertyManager;
import com.arjuna.ats.arjuna.coordinator.ActionStatus;
import com.arjuna.ats.arjuna.coordinator.CheckedAction;
import com.arjuna.ats.arjuna.coordinator.CheckedActionFactory;
import com.arjuna.ats.arjuna.utils.ThreadUtil;

public class ThreadUtilTest {

private boolean allowCheckedActionFactoryOverride;

@Before
public void setup() {
CoordinatorEnvironmentBean coordinatorEnvironmentBean = arjPropertyManager.getCoordinatorEnvironmentBean();
allowCheckedActionFactoryOverride = coordinatorEnvironmentBean.isAllowCheckedActionFactoryOverride();
}

@After
public void tearDown() {
CoordinatorEnvironmentBean coordinatorEnvironmentBean = arjPropertyManager.getCoordinatorEnvironmentBean();
coordinatorEnvironmentBean.setAllowCheckedActionFactoryOverride(allowCheckedActionFactoryOverride);
}

@Test
public void testDisassociateFromDifferentThread() throws InterruptedException {
Thread thread = Thread.currentThread();

AtomicBoolean called = new AtomicBoolean(false);

CoordinatorEnvironmentBean coordinatorEnvironmentBean = arjPropertyManager.getCoordinatorEnvironmentBean();
coordinatorEnvironmentBean.setAllowCheckedActionFactoryOverride(true);
coordinatorEnvironmentBean.setCheckedActionFactory(new CheckedActionFactory() {

@Override
public CheckedAction getCheckedAction(Uid txId, String actionType) {
return new CheckedAction() {
public void check(boolean isCommit, Uid actUid, Hashtable list) {
called.set(true);
}
};
}
});
AtomicAction tx = new AtomicAction();
assertFalse(tx.removeChildThread(ThreadUtil.getThreadId(thread)));
tx.begin();

synchronized (tx) {
new Thread(new Runnable() {
@Override
public void run() {
assertTrue(tx.removeChildThread(ThreadUtil.getThreadId(thread)));
assertTrue(tx.end(true) == ActionStatus.COMMITTED);
synchronized (tx) {
tx.notify();
}
}
}).start();
tx.wait();
}

assertTrue(called.get() == false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public final ControlWrapper popAction (String threadId)
}

ControlWrapper action = null;
Object arg = otsCurrent.get(threadId);
Object arg = threadId == null ? null : otsCurrent.get(threadId);

if (arg != null)
{
Expand Down Expand Up @@ -296,7 +296,7 @@ public final void purgeActions (String threadId)

public final void purgeActions ()
{
purgeActions(ThreadUtil.getThreadId());
purgeActions(ThreadUtil.removeThreadId(Thread.currentThread()));
}

/**
Expand Down

0 comments on commit 45c242d

Please sign in to comment.