001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.object.tx.optimistic;
005:
006: import com.tc.object.ClientObjectManager;
007: import com.tc.object.LiteralValues;
008: import com.tc.object.TCObject;
009: import com.tc.object.change.TCChangeBuffer;
010: import com.tc.object.change.TCChangeBufferEventVisitor;
011: import com.tc.object.change.event.ArrayElementChangeEvent;
012: import com.tc.object.change.event.LogicalChangeEvent;
013: import com.tc.object.change.event.PhysicalChangeEvent;
014: import com.tc.object.tx.ClientTransaction;
015: import com.tc.object.tx.ClientTransactionManager;
016: import com.tc.util.Assert;
017: import com.tc.util.ClassUtils;
018:
019: import java.util.Iterator;
020: import java.util.Map;
021:
022: public class OptimisticTransactionManagerImpl implements
023: OptimisticTransactionManager {
024: private ThreadLocal transaction = new ThreadLocal();
025: private ClientObjectManager objectManager;
026: private ClientTransactionManager clientTxManager;
027: private LiteralValues literalValues = new LiteralValues();
028:
029: public OptimisticTransactionManagerImpl(
030: ClientObjectManager objectManager,
031: ClientTransactionManager clientTxManager) {
032: this .objectManager = objectManager;
033: this .clientTxManager = clientTxManager;
034: Assert.eval(objectManager != null);
035: }
036:
037: public void begin() {
038: if (getTransaction() != null) {
039: throw new AssertionError(
040: "Don't support nested optimistic transactions");
041: }
042:
043: transaction.set(new OptimisticTransaction());
044: }
045:
046: public void objectFieldChanged(TCObject clone, String classname,
047: String fieldname, Object newValue, int index) {
048: getTransaction().objectFieldChanged(clone, classname,
049: fieldname, newValue, index);
050: }
051:
052: public void logicalInvoke(TCObject clone, int method,
053: String methodName, Object[] parameters) {
054: getTransaction().logicalInvoke(clone, method, parameters);
055: }
056:
057: public void rollback() {
058: if (getTransaction() != null) {
059: throw new AssertionError("Can't rollback non-exsistent tx");
060: }
061: transaction.set(null);
062: }
063:
064: public Object convertToParameter(Object obj) {
065: Object nv = null;
066: OptimisticTransaction ot = getTransaction();
067: ClientTransaction ctx = clientTxManager.getTransaction();
068:
069: if (ot.hasClone(obj)) {
070: TCObject ctcobj = ot.getTCObjectFor(obj);
071: nv = ctcobj.getObjectID();
072: } else if (literalValues.isLiteralInstance(obj)) {
073: nv = obj;
074: } else {
075: TCObject ctcobj = objectManager.lookupOrCreate(obj);
076: ctx.createObject(ctcobj);
077: nv = ctcobj.getObjectID();
078: }
079: return nv;
080: }
081:
082: public void commit() throws ClassNotFoundException {
083: OptimisticTransaction ot = getTransaction();
084: final ClientTransaction ctx = clientTxManager.getTransaction();
085: Map buffers = ot.getChangeBuffers();
086: for (Iterator i = buffers.values().iterator(); i.hasNext();) {
087: TCChangeBuffer buf = (TCChangeBuffer) i.next();
088: Assert.eval(buf.getTCObject() != null);
089: final TCObject tcobj = objectManager.lookup(buf
090: .getTCObject().getObjectID());
091: try {
092: tcobj.hydrate(new DNAToChangeBufferBridge(this , buf),
093: true);
094: } catch (ClassNotFoundException e) {
095: throw e;
096: }
097:
098: // Add the changes to the dso transaction
099: buf.accept(new TCChangeBufferEventVisitor() {
100: public void visitPhysicalChangeEvent(
101: PhysicalChangeEvent pe) {
102: Object nv = convertToParameter(pe.getNewValue());
103: Assert.eval(nv != null);
104: ctx.fieldChanged(tcobj, tcobj.getTCClass()
105: .getName(), pe.getFieldName(), nv, -1);
106: }
107:
108: public void visitLogicalEvent(LogicalChangeEvent lce) {
109: Object[] params = lce.getParameters();
110: Object[] newParams = new Object[params.length];
111: for (int j = 0; j < newParams.length; j++) {
112: newParams[j] = convertToParameter(params[j]);
113: }
114: ctx.logicalInvoke(tcobj, lce.getMethodID(),
115: newParams, "");
116: }
117:
118: public void visitArrayElementChangeEvent(
119: ArrayElementChangeEvent ae) {
120: Object nv = ae.getValue();
121: if (ae.isSubarray()) {
122: if (!ClassUtils.isPrimitiveArray(nv)) {
123: Object[] values = (Object[]) nv;
124: for (int j = 0; j < values.length; j++) {
125: values[j] = convertToParameter(values[j]);
126: }
127: }
128: ctx.arrayChanged(tcobj, ae.getIndex(), nv, ae
129: .getLength());
130: } else {
131: ctx.fieldChanged(tcobj, tcobj.getTCClass()
132: .getName(), null,
133: convertToParameter(nv), ae.getIndex());
134: }
135: }
136: });
137: }
138: transaction.set(null);
139: }
140:
141: private OptimisticTransaction getTransaction() {
142: return (OptimisticTransaction) transaction.get();
143: }
144:
145: public void addClonesToTransaction(Map cloned) {
146: getTransaction().addAll(cloned);
147: }
148:
149: }
|