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.tx;
006:
007: import com.tc.net.groups.ClientID;
008: import com.tc.net.protocol.tcm.ChannelID;
009: import com.tc.object.MockTCObject;
010: import com.tc.object.ObjectID;
011: import com.tc.object.bytecode.MockClassProvider;
012: import com.tc.object.dna.api.DNAEncoding;
013: import com.tc.object.dna.impl.DNAEncodingImpl;
014: import com.tc.object.dna.impl.ObjectStringSerializer;
015: import com.tc.object.gtx.DefaultGlobalTransactionIDGenerator;
016: import com.tc.object.gtx.GlobalTransactionIDGenerator;
017: import com.tc.object.lockmanager.api.LockID;
018: import com.tc.object.lockmanager.api.Notify;
019: import com.tc.object.lockmanager.api.ThreadID;
020: import com.tc.object.logging.NullRuntimeLogger;
021: import com.tc.object.tx.ClientTransaction;
022: import com.tc.object.tx.ClientTransactionImpl;
023: import com.tc.object.tx.TestClientTransaction;
024: import com.tc.object.tx.TransactionBatchWriter;
025: import com.tc.object.tx.TransactionContext;
026: import com.tc.object.tx.TransactionContextImpl;
027: import com.tc.object.tx.TransactionID;
028: import com.tc.object.tx.TxnBatchID;
029: import com.tc.object.tx.TxnType;
030: import com.tc.util.SequenceID;
031:
032: import java.io.IOException;
033: import java.util.Arrays;
034: import java.util.Iterator;
035: import java.util.LinkedList;
036: import java.util.List;
037:
038: import junit.framework.TestCase;
039:
040: public class TransactionBatchTest extends TestCase {
041:
042: private DNAEncoding encoding = new DNAEncodingImpl(
043: new MockClassProvider());
044:
045: private TransactionBatchWriter writer;
046: private TestCommitTransactionMessageFactory messageFactory;
047:
048: private GlobalTransactionIDGenerator gidGenerator;
049:
050: public void setUp() throws Exception {
051: ObjectStringSerializer serializer = new ObjectStringSerializer();
052: messageFactory = new TestCommitTransactionMessageFactory();
053: writer = new TransactionBatchWriter(new TxnBatchID(1),
054: serializer, encoding, messageFactory);
055: gidGenerator = new DefaultGlobalTransactionIDGenerator();
056: }
057:
058: public void testGetMinTransaction() throws Exception {
059: LinkedList list = new LinkedList();
060: for (int i = 0; i < 100; i++) {
061: TestClientTransaction tx = new TestClientTransaction();
062: tx.sequenceID = new SequenceID(i);
063: tx.txID = new TransactionID(i);
064: tx.txnType = TxnType.NORMAL;
065: list.add(tx);
066: writer.addTransaction(tx);
067: }
068:
069: writer.wait4AllTxns2Serialize();
070:
071: assertSame(((ClientTransaction) list.getFirst())
072: .getSequenceID(), writer.getMinTransactionSequence());
073:
074: // remove some from the middle and make sure the min is constant
075: for (int i = 50; i < 55; i++) {
076: ClientTransaction tx = (ClientTransaction) list.remove(i);
077: writer.removeTransaction(tx.getTransactionID());
078: assertSame(((ClientTransaction) list.getFirst())
079: .getSequenceID(), writer
080: .getMinTransactionSequence());
081: }
082:
083: // now remove the leastmost transaction and make sure the min increases.
084: for (Iterator i = list.iterator(); i.hasNext();) {
085: ClientTransaction tx = (ClientTransaction) i.next();
086: assertSame(((ClientTransaction) list.getFirst())
087: .getSequenceID(), writer
088: .getMinTransactionSequence());
089: i.remove();
090: writer.removeTransaction(tx.getTransactionID());
091: }
092: }
093:
094: public void testSend() throws Exception {
095: assertTrue(messageFactory.messages.isEmpty());
096:
097: writer.send();
098: assertEquals(1, messageFactory.messages.size());
099: TestCommitTransactionMessage message = (TestCommitTransactionMessage) messageFactory.messages
100: .get(0);
101: assertEquals(1, message.setBatchCalls.size());
102: assertSame(writer, message.setBatchCalls.get(0));
103: assertEquals(1, message.sendCalls.size());
104: }
105:
106: public void testWriteRead() throws IOException {
107: long sequence = 0;
108: ObjectStringSerializer serializer = new ObjectStringSerializer();
109: TestCommitTransactionMessageFactory mf = new TestCommitTransactionMessageFactory();
110: ClientID clientID = new ClientID(new ChannelID(69));
111: TxnBatchID batchID = new TxnBatchID(42);
112:
113: List tx1Notifies = new LinkedList();
114: // A nested transaction (all this buys us is more than 1 lock in a txn)
115: LockID lid1 = new LockID("1");
116: TransactionContext tc = new TransactionContextImpl(lid1,
117: TxnType.NORMAL, new LockID[] { lid1 });
118: ClientTransaction tmp = new ClientTransactionImpl(
119: new TransactionID(101), new NullRuntimeLogger());
120: tmp.setTransactionContext(tc);
121: LockID lid2 = new LockID("2");
122: tc = new TransactionContextImpl(lid2, TxnType.NORMAL,
123: new LockID[] { lid1, lid2 });
124: ClientTransaction txn1 = new ClientTransactionImpl(
125: new TransactionID(1), new NullRuntimeLogger());
126: txn1.setTransactionContext(tc);
127:
128: txn1.fieldChanged(new MockTCObject(new ObjectID(1), this ),
129: "class", "class.field", ObjectID.NULL_ID, -1);
130: txn1.createObject(new MockTCObject(new ObjectID(2), this ));
131: txn1.createRoot("root", new ObjectID(3));
132: for (int i = 0; i < 10; i++) {
133: Notify notify = new Notify(new LockID("" + i),
134: new ThreadID(i), i % 2 == 0);
135: tx1Notifies.add(notify);
136: txn1.addNotify(notify);
137: }
138:
139: tc = new TransactionContextImpl(new LockID("3"),
140: TxnType.CONCURRENT, new LockID[] { new LockID("3") });
141: ClientTransaction txn2 = new ClientTransactionImpl(
142: new TransactionID(2), new NullRuntimeLogger());
143: txn2.setTransactionContext(tc);
144:
145: writer = new TransactionBatchWriter(batchID, serializer,
146: encoding, mf);
147:
148: txn1.setSequenceID(new SequenceID(++sequence));
149: txn2.setSequenceID(new SequenceID(++sequence));
150: writer.addTransaction(txn1);
151: writer.addTransaction(txn2);
152: writer.wait4AllTxns2Serialize();
153:
154: TransactionBatchReaderImpl reader = new TransactionBatchReaderImpl(
155: gidGenerator, writer.getData(), clientID, serializer,
156: new ActiveServerTransactionFactory());
157: assertEquals(2, reader.getNumTxns());
158: assertEquals(batchID, reader.getBatchID());
159:
160: int count = 0;
161: ServerTransaction txn;
162: while ((txn = reader.getNextTransaction()) != null) {
163: count++;
164: assertEquals(clientID, txn.getSourceID());
165: assertEquals(count, txn.getTransactionID().toLong());
166:
167: switch (count) {
168: case 1:
169: assertEquals(2, txn.getChanges().size());
170: assertEquals(1, txn.getNewRoots().size());
171: assertEquals("root", txn.getNewRoots().keySet()
172: .toArray()[0]);
173: assertEquals(new ObjectID(3), txn.getNewRoots()
174: .values().toArray()[0]);
175: assertEquals(2, txn.getObjectIDs().size());
176: assertTrue(txn.getObjectIDs().containsAll(
177: Arrays.asList(new ObjectID[] { new ObjectID(1),
178: new ObjectID(2) })));
179: assertEquals(TxnType.NORMAL, txn.getTransactionType());
180: assertTrue(Arrays.equals(new LockID[] {
181: new LockID("1"), new LockID("2") }, txn
182: .getLockIDs()));
183: assertEquals(tx1Notifies, txn.getNotifies());
184: break;
185: case 2:
186: assertEquals(0, txn.getChanges().size());
187: assertEquals(0, txn.getNewRoots().size());
188: assertEquals(0, txn.getObjectIDs().size());
189: assertEquals(TxnType.CONCURRENT, txn
190: .getTransactionType());
191: assertTrue(Arrays.equals(
192: new LockID[] { new LockID("3") }, txn
193: .getLockIDs()));
194: break;
195: default:
196: fail("count is " + count);
197: }
198: }
199:
200: assertEquals(2, count);
201:
202: }
203:
204: }
|