001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.objectserver.handler;
006:
007: import com.tc.async.impl.MockSink;
008: import com.tc.async.impl.MockStage;
009: import com.tc.l2.ha.L2HADisabledCooridinator;
010: import com.tc.net.groups.ClientID;
011: import com.tc.net.protocol.tcm.ChannelID;
012: import com.tc.object.dmi.DmiDescriptor;
013: import com.tc.object.dna.impl.ObjectStringSerializer;
014: import com.tc.object.lockmanager.api.LockID;
015: import com.tc.object.lockmanager.api.Notify;
016: import com.tc.object.lockmanager.api.ThreadID;
017: import com.tc.object.tx.TransactionID;
018: import com.tc.object.tx.TxnBatchID;
019: import com.tc.object.tx.TxnType;
020: import com.tc.objectserver.api.ObjectInstanceMonitor;
021: import com.tc.objectserver.context.ApplyTransactionContext;
022: import com.tc.objectserver.context.BroadcastChangeContext;
023: import com.tc.objectserver.core.api.ServerConfigurationContext;
024: import com.tc.objectserver.core.impl.TestServerConfigurationContext;
025: import com.tc.objectserver.gtx.TestGlobalTransactionManager;
026: import com.tc.objectserver.impl.ObjectInstanceMonitorImpl;
027: import com.tc.objectserver.lockmanager.api.NotifiedWaiters;
028: import com.tc.objectserver.lockmanager.api.TestLockManager;
029: import com.tc.objectserver.tx.NullTransactionalObjectManager;
030: import com.tc.objectserver.tx.ServerTransaction;
031: import com.tc.objectserver.tx.ServerTransactionImpl;
032: import com.tc.objectserver.tx.TestServerTransactionManager;
033: import com.tc.util.SequenceID;
034:
035: import java.util.Collections;
036: import java.util.HashMap;
037: import java.util.Iterator;
038: import java.util.LinkedList;
039: import java.util.List;
040: import java.util.Map;
041:
042: import junit.framework.TestCase;
043:
044: public class ApplyTransactionChangeHandlerTest extends TestCase {
045:
046: private ApplyTransactionChangeHandler handler;
047: private ObjectInstanceMonitor instanceMonitor;
048: private TestServerTransactionManager transactionManager;
049: private TestGlobalTransactionManager gtxm;
050: private TestLockManager lockManager;
051: private MockSink broadcastSink;
052:
053: public void setUp() throws Exception {
054: instanceMonitor = new ObjectInstanceMonitorImpl();
055: transactionManager = new TestServerTransactionManager();
056: lockManager = new TestLockManager();
057: gtxm = new TestGlobalTransactionManager();
058: handler = new ApplyTransactionChangeHandler(instanceMonitor,
059: gtxm);
060:
061: MockStage stageBo = new MockStage("Bo");
062: MockStage stageCo = new MockStage("Co");
063: broadcastSink = stageBo.sink;
064: TestServerConfigurationContext context = new TestServerConfigurationContext();
065: context.transactionManager = transactionManager;
066: context.txnObjectManager = new NullTransactionalObjectManager();
067: context.l2Coordinator = new L2HADisabledCooridinator();
068: context.addStage(
069: ServerConfigurationContext.BROADCAST_CHANGES_STAGE,
070: stageBo);
071: context.addStage(
072: ServerConfigurationContext.COMMIT_CHANGES_STAGE,
073: stageCo);
074: context.lockManager = lockManager;
075:
076: handler.initializeContext(context);
077: }
078:
079: public void testLockManagerNotifyIsCalled() throws Exception {
080: TxnBatchID batchID = new TxnBatchID(1);
081: TransactionID txID = new TransactionID(1);
082: LockID[] lockIDs = new LockID[] { new LockID("1") };
083: ClientID cid = new ClientID(new ChannelID(1));
084: List dnas = Collections.unmodifiableList(new LinkedList());
085: ObjectStringSerializer serializer = null;
086: Map newRoots = Collections.unmodifiableMap(new HashMap());
087: TxnType txnType = TxnType.NORMAL;
088: List notifies = new LinkedList();
089:
090: for (int i = 0; i < 10; i++) {
091: notifies.add(new Notify(new LockID("" + i),
092: new ThreadID(i), i % 2 == 0));
093: }
094: SequenceID sequenceID = new SequenceID(1);
095: ServerTransaction tx = new ServerTransactionImpl(gtxm, batchID,
096: txID, sequenceID, lockIDs, cid, dnas, serializer,
097: newRoots, txnType, notifies, DmiDescriptor.EMPTY_ARRAY);
098: // call handleEvent with the global transaction reporting that it doesn't need an apply...
099: assertTrue(lockManager.notifyCalls.isEmpty());
100: assertTrue(broadcastSink.queue.isEmpty());
101: handler.handleEvent(getApplyTxnContext(tx));
102: // even if the transaction has already been applied, the notifies must be applied, since they aren't persistent.
103: assertEquals(notifies.size(), lockManager.notifyCalls.size());
104: lockManager.notifyCalls.clear();
105: assertNotNull(broadcastSink.queue.remove(0));
106:
107: // call handleEvent with the global transaction reporting that it DOES need an apply...
108: handler.handleEvent(getApplyTxnContext(tx));
109:
110: assertEquals(notifies.size(), lockManager.notifyCalls.size());
111: NotifiedWaiters notifiedWaiters = null;
112: for (Iterator i = notifies.iterator(); i.hasNext();) {
113: Notify notify = (Notify) i.next();
114: Object[] args = (Object[]) lockManager.notifyCalls
115: .remove(0);
116: assertEquals(notify.getLockID(), args[0]);
117: assertEquals(cid, args[1]);
118: assertEquals(notify.getThreadID(), args[2]);
119: assertEquals(new Boolean(notify.getIsAll()), args[3]);
120: if (notifiedWaiters == null) {
121: notifiedWaiters = (NotifiedWaiters) args[4];
122: }
123: assertNotNull(notifiedWaiters);
124: assertSame(notifiedWaiters, args[4]);
125: }
126:
127: // next, check to see that the handler puts the newly pending waiters into the broadcast context.
128: BroadcastChangeContext bctxt = (BroadcastChangeContext) broadcastSink.queue
129: .remove(0);
130: assertNotNull(bctxt);
131: assertEquals(notifiedWaiters, bctxt.getNewlyPendingWaiters());
132: }
133:
134: private ApplyTransactionContext getApplyTxnContext(
135: ServerTransaction txt) {
136: ApplyTransactionContext atc = new ApplyTransactionContext(txt,
137: new HashMap());
138: return atc;
139: }
140:
141: }
|