Source Code Cross Referenced for ClientTransactionManagerImpl.java in  » Net » Terracotta » com » tc » object » tx » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » Terracotta » com.tc.object.tx 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.object.tx;
006:
007:        import com.tc.exception.TCClassNotFoundException;
008:        import com.tc.exception.TCLockUpgradeNotSupportedError;
009:        import com.tc.logging.TCLogger;
010:        import com.tc.logging.TCLogging;
011:        import com.tc.management.beans.tx.ClientTxMonitorMBean;
012:        import com.tc.net.protocol.tcm.ChannelIDProvider;
013:        import com.tc.object.ClientObjectManager;
014:        import com.tc.object.LiteralValues;
015:        import com.tc.object.ObjectID;
016:        import com.tc.object.TCObject;
017:        import com.tc.object.appevent.NonPortableEventContextFactory;
018:        import com.tc.object.appevent.ReadOnlyObjectEvent;
019:        import com.tc.object.appevent.ReadOnlyObjectEventContext;
020:        import com.tc.object.appevent.UnlockedSharedObjectEvent;
021:        import com.tc.object.appevent.UnlockedSharedObjectEventContext;
022:        import com.tc.object.dmi.DmiDescriptor;
023:        import com.tc.object.dna.api.DNA;
024:        import com.tc.object.dna.api.DNAException;
025:        import com.tc.object.loaders.Namespace;
026:        import com.tc.object.lockmanager.api.LockID;
027:        import com.tc.object.lockmanager.api.LockLevel;
028:        import com.tc.object.lockmanager.api.ThreadLockManager;
029:        import com.tc.object.lockmanager.api.WaitListener;
030:        import com.tc.object.logging.RuntimeLogger;
031:        import com.tc.object.session.SessionID;
032:        import com.tc.object.util.ReadOnlyException;
033:        import com.tc.text.Banner;
034:        import com.tc.util.Assert;
035:        import com.tc.util.ClassUtils;
036:
037:        import java.util.Collection;
038:        import java.util.Iterator;
039:        import java.util.LinkedList;
040:        import java.util.List;
041:        import java.util.Map;
042:        import java.util.Set;
043:        import java.util.Map.Entry;
044:
045:        /**
046:         * @author steve
047:         */
048:        public class ClientTransactionManagerImpl implements 
049:                ClientTransactionManager {
050:            private static final TCLogger logger = TCLogging
051:                    .getLogger(ClientTransactionManagerImpl.class);
052:
053:            private final ThreadLocal transaction = new ThreadLocal() {
054:                protected synchronized Object initialValue() {
055:                    return new ThreadTransactionContext();
056:                }
057:            };
058:
059:            // We need to remove initialValue() here because read auto locking now calls Manager.isDsoMonitored() which will
060:            // checks if isTransactionLogging is disabled. If it runs in the context of class loading, it will try to load
061:            // the class ThreadTransactionContext and thus throws a LinkageError.
062:            private final ThreadLocal txnLogging = new ThreadLocal();
063:
064:            private final ClientTransactionFactory txFactory;
065:            private final RemoteTransactionManager remoteTxManager;
066:            private final ClientObjectManager objectManager;
067:            private final ThreadLockManager lockManager;
068:            private final NonPortableEventContextFactory appEventContextFactory;
069:            private final LiteralValues literalValues = new LiteralValues();
070:
071:            private final WaitListener waitListener = new WaitListener() {
072:                public void handleWaitEvent() {
073:                    return;
074:                }
075:            };
076:
077:            private final ChannelIDProvider cidProvider;
078:
079:            private final ClientTxMonitorMBean txMonitor;
080:
081:            private final boolean sendErrors = System
082:                    .getProperty("project.name") != null;
083:
084:            public ClientTransactionManagerImpl(ChannelIDProvider cidProvider,
085:                    ClientObjectManager objectManager,
086:                    ThreadLockManager lockManager,
087:                    ClientTransactionFactory txFactory,
088:                    RemoteTransactionManager remoteTxManager,
089:                    RuntimeLogger runtimeLogger,
090:                    final ClientTxMonitorMBean txMonitor) {
091:                this .cidProvider = cidProvider;
092:                this .txFactory = txFactory;
093:                this .remoteTxManager = remoteTxManager;
094:                this .objectManager = objectManager;
095:                this .objectManager.setTransactionManager(this );
096:                this .lockManager = lockManager;
097:                this .txMonitor = txMonitor;
098:                this .appEventContextFactory = new NonPortableEventContextFactory(
099:                        cidProvider);
100:            }
101:
102:            public int queueLength(String lockName) {
103:                final LockID lockID = lockManager.lockIDFor(lockName);
104:                return lockManager.queueLength(lockID);
105:            }
106:
107:            public int waitLength(String lockName) {
108:                final LockID lockID = lockManager.lockIDFor(lockName);
109:                return lockManager.waitLength(lockID);
110:            }
111:
112:            public int localHeldCount(String lockName, int lockLevel) {
113:                final LockID lockID = lockManager.lockIDFor(lockName);
114:                return lockManager.localHeldCount(lockID, lockLevel);
115:            }
116:
117:            public boolean isHeldByCurrentThread(String lockName, int lockLevel) {
118:                if (isTransactionLoggingDisabled()) {
119:                    return true;
120:                }
121:                final LockID lockID = lockManager.lockIDFor(lockName);
122:                return lockManager.localHeldCount(lockID, lockLevel) > 0;
123:            }
124:
125:            public boolean isLocked(String lockName, int lockLevel) {
126:                final LockID lockID = lockManager.lockIDFor(lockName);
127:                return lockManager.isLocked(lockID, lockLevel);
128:            }
129:
130:            public void lock(String lockName, int lockLevel) {
131:                final LockID lockID = lockManager.lockIDFor(lockName);
132:                lockManager.lock(lockID, lockLevel);
133:            }
134:
135:            public void unlock(String lockName) {
136:                final LockID lockID = lockManager.lockIDFor(lockName);
137:                if (lockID != null) {
138:                    lockManager.unlock(lockID);
139:                    getThreadTransactionContext().removeLock(lockID);
140:                }
141:            }
142:
143:            public boolean tryBegin(String lockName, WaitInvocation timeout,
144:                    int lockLevel) {
145:                logTryBegin0(lockName, lockLevel);
146:
147:                if (isTransactionLoggingDisabled()
148:                        || objectManager.isCreationInProgress()) {
149:                    return true;
150:                }
151:
152:                final TxnType txnType = getTxnTypeFromLockLevel(lockLevel);
153:                ClientTransaction currentTransaction = getTransactionOrNull();
154:
155:                if ((currentTransaction != null)
156:                        && lockLevel == LockLevel.CONCURRENT) {
157:                    // make formatter sane
158:                    throw new AssertionError(
159:                            "Can't acquire concurrent locks in a nested lock context.");
160:                }
161:
162:                final LockID lockID = lockManager.lockIDFor(lockName);
163:                boolean isLocked = lockManager.tryLock(lockID, timeout,
164:                        lockLevel);
165:                if (!isLocked) {
166:                    return isLocked;
167:                }
168:
169:                pushTxContext(lockID, txnType);
170:
171:                if (currentTransaction == null) {
172:                    createTxAndInitContext();
173:                } else {
174:                    currentTransaction
175:                            .setTransactionContext(this .peekContext());
176:                }
177:
178:                return isLocked;
179:            }
180:
181:            public boolean begin(String lockName, int lockLevel) {
182:                logBegin0(lockName, lockLevel);
183:
184:                if (isTransactionLoggingDisabled()
185:                        || objectManager.isCreationInProgress()) {
186:                    return false;
187:                }
188:
189:                final TxnType txnType = getTxnTypeFromLockLevel(lockLevel);
190:                ClientTransaction currentTransaction = getTransactionOrNull();
191:
192:                final LockID lockID = lockManager.lockIDFor(lockName);
193:
194:                pushTxContext(lockID, txnType);
195:
196:                if (currentTransaction == null) {
197:                    createTxAndInitContext();
198:                } else {
199:                    currentTransaction
200:                            .setTransactionContext(this .peekContext());
201:                }
202:
203:                try {
204:                    lockManager.lock(lockID, lockLevel);
205:                    return true;
206:                } catch (TCLockUpgradeNotSupportedError e) {
207:                    popTransaction(lockID);
208:                    if (peekContext() != null) {
209:                        currentTransaction.setTransactionContext(peekContext());
210:                        setTransaction(currentTransaction);
211:                    }
212:                    throw e;
213:                }
214:            }
215:
216:            private TxnType getTxnTypeFromLockLevel(int lockLevel) {
217:                switch (lockLevel) {
218:                case LockLevel.READ:
219:                    return TxnType.READ_ONLY;
220:                case LockLevel.CONCURRENT:
221:                    return TxnType.CONCURRENT;
222:                case LockLevel.WRITE:
223:                    return TxnType.NORMAL;
224:                case LockLevel.SYNCHRONOUS_WRITE:
225:                    return TxnType.NORMAL;
226:                default:
227:                    throw Assert
228:                            .failure("don't know how to translate lock level "
229:                                    + lockLevel);
230:                }
231:            }
232:
233:            public void wait(String lockName, WaitInvocation call, Object object)
234:                    throws UnlockedSharedObjectException, InterruptedException {
235:                final ClientTransaction topTxn = getTransactionOrNull();
236:
237:                if (topTxn == null) {
238:                    throw new IllegalMonitorStateException();
239:                }
240:
241:                LockID lockID = lockManager.lockIDFor(lockName);
242:
243:                if (!lockManager.isLocked(lockID, LockLevel.WRITE)) {
244:                    throw new IllegalMonitorStateException();
245:                }
246:
247:                commit(lockID, topTxn, true);
248:
249:                try {
250:                    lockManager.wait(lockID, call, object, waitListener);
251:                } finally {
252:                    createTxAndInitContext();
253:                }
254:            }
255:
256:            public void notify(String lockName, boolean all, Object object)
257:                    throws UnlockedSharedObjectException {
258:                final ClientTransaction currentTxn = getTransactionOrNull();
259:
260:                if (currentTxn == null) {
261:                    throw new IllegalMonitorStateException();
262:                }
263:
264:                LockID lockID = lockManager.lockIDFor(lockName);
265:
266:                if (!lockManager.isLocked(lockID, LockLevel.WRITE)) {
267:                    throw new IllegalMonitorStateException();
268:                }
269:
270:                currentTxn.addNotify(lockManager.notify(lockID, all));
271:            }
272:
273:            private void logTryBegin0(String lockID, int type) {
274:                if (logger.isDebugEnabled()) {
275:                    logger.debug("tryBegin(): lockID="
276:                            + (lockID == null ? "null" : lockID) + ", type = "
277:                            + type);
278:                }
279:            }
280:
281:            private void logBegin0(String lockID, int type) {
282:                if (logger.isDebugEnabled()) {
283:                    logger.debug("begin(): lockID="
284:                            + (lockID == null ? "null" : lockID) + ", type = "
285:                            + type);
286:                }
287:            }
288:
289:            private ClientTransaction getTransactionOrNull() {
290:                ThreadTransactionContext tx = getThreadTransactionContext();
291:                return tx.getCurrentTransaction();
292:            }
293:
294:            private ThreadTransactionContext getThreadTransactionContext() {
295:                return (ThreadTransactionContext) this .transaction.get();
296:            }
297:
298:            public ClientTransaction getTransaction()
299:                    throws UnlockedSharedObjectException {
300:                return getTransaction(null);
301:            }
302:
303:            private ClientTransaction getTransaction(Object context)
304:                    throws UnlockedSharedObjectException {
305:                ClientTransaction tx = getTransactionOrNull();
306:                if (tx == null) {
307:
308:                    String type = context == null ? null : context.getClass()
309:                            .getName();
310:                    String errorMsg = "Attempt to access a shared object outside the scope of a shared lock.  "
311:                            + "\nAll access to shared objects must be within the scope of one or more shared locks defined in your Terracotta configuration.  "
312:                            + "\nPlease alter the locks section of your Terracotta configuration so that this access is auto-locked or protected by a named lock."
313:                            + "\n\nFor more information on this issue, please visit our Troubleshooting Guide at:\n http://terracotta.org/kit/troubleshooting\n";
314:                    String details = "";
315:                    if (type != null) {
316:                        details += "Shared Object Type: " + type;
317:                    }
318:
319:                    throw new UnlockedSharedObjectException(errorMsg, Thread
320:                            .currentThread().getName(), cidProvider
321:                            .getChannelID().toLong(), details);
322:                }
323:                return tx;
324:            }
325:
326:            public void checkWriteAccess(Object context) {
327:                if (isTransactionLoggingDisabled()) {
328:                    return;
329:                }
330:
331:                // First check if we have any TXN context at all (else exception thrown)
332:                ClientTransaction txn;
333:
334:                try {
335:                    txn = getTransaction(context);
336:                } catch (UnlockedSharedObjectException usoe) {
337:                    if (sendErrors) {
338:                        UnlockedSharedObjectEventContext eventContext = appEventContextFactory
339:                                .createUnlockedSharedObjectEventContext(
340:                                        context, usoe);
341:                        objectManager.sendApplicationEvent(context,
342:                                new UnlockedSharedObjectEvent(eventContext));
343:                    }
344:
345:                    throw usoe;
346:                }
347:
348:                // make sure we're not in a read-only transaction
349:                // txn.readOnlyCheck();
350:                if (txn.getTransactionType() == TxnType.READ_ONLY) {
351:                    ReadOnlyException roe = makeReadOnlyException(null);
352:
353:                    if (sendErrors) {
354:                        ReadOnlyObjectEventContext eventContext = appEventContextFactory
355:                                .createReadOnlyObjectEventContext(context, roe);
356:                        objectManager.sendApplicationEvent(context,
357:                                new ReadOnlyObjectEvent(eventContext));
358:                    }
359:
360:                    throw roe;
361:                }
362:            }
363:
364:            /**
365:             * In order to support ReentrantLock, the TransactionContext that is going to be removed when doing a commit may not
366:             * always be at the top of a stack because an reentrant lock could issue a lock within a synchronized block (although
367:             * it is highly not recommended). Therefore, when a commit is issued, we need to search back the stack from the top of
368:             * the stack to find the appropriate TransactionContext to be removed. Most likely, the TransactionContext to be
369:             * removed will be on the top of the stack. Therefore, the performance should be make must difference. Only in some
370:             * weird situations where reentrantLock is mixed with synchronized block will the TransactionContext to be removed be
371:             * found otherwise.
372:             */
373:            public void commit(String lockName)
374:                    throws UnlockedSharedObjectException {
375:                logCommit0();
376:                if (isTransactionLoggingDisabled()
377:                        || objectManager.isCreationInProgress()) {
378:                    return;
379:                }
380:
381:                // ClientTransaction tx = popTransaction();
382:                ClientTransaction tx = getTransaction();
383:                LockID lockID = lockManager.lockIDFor(lockName);
384:                if (lockID == null || lockID.isNull()) {
385:                    lockID = tx.getLockID();
386:                }
387:                boolean hasCommitted = commit(lockID, tx, false);
388:
389:                popTransaction(lockManager.lockIDFor(lockName));
390:
391:                if (peekContext() != null) {
392:                    if (hasCommitted) {
393:                        createTxAndInitContext();
394:                    } else {
395:                        // If the current transaction has not committed, we will reuse the current transaction
396:                        // so that the current changes will have a chance to commit at the next commit point.
397:                        tx.setTransactionContext(peekContext());
398:                        setTransaction(tx);
399:                    }
400:                }
401:            }
402:
403:            private void createTxAndInitContext() {
404:                ClientTransaction ctx = txFactory.newInstance();
405:                ctx.setTransactionContext(peekContext());
406:                setTransaction(ctx);
407:            }
408:
409:            private ClientTransaction popTransaction() {
410:                ThreadTransactionContext ttc = getThreadTransactionContext();
411:                return ttc.popCurrentTransaction();
412:            }
413:
414:            private ClientTransaction popTransaction(LockID lockID) {
415:                if (lockID == null || lockID.isNull()) {
416:                    return popTransaction();
417:                }
418:                ThreadTransactionContext ttc = getThreadTransactionContext();
419:                return ttc.popCurrentTransaction(lockID);
420:            }
421:
422:            private TransactionContext peekContext(LockID lockID) {
423:                ThreadTransactionContext ttc = getThreadTransactionContext();
424:                return ttc.peekContext(lockID);
425:            }
426:
427:            private TransactionContext peekContext() {
428:                ThreadTransactionContext ttc = getThreadTransactionContext();
429:                return ttc.peekContext();
430:            }
431:
432:            public boolean isLockOnTopStack(String lockName) {
433:                final LockID lockID = lockManager.lockIDFor(lockName);
434:                TransactionContext tc = peekContext();
435:                if (tc == null) {
436:                    return false;
437:                }
438:                return (tc.getLockID().equals(lockID));
439:            }
440:
441:            private void pushTxContext(LockID lockID, TxnType txnType) {
442:                ThreadTransactionContext ttc = getThreadTransactionContext();
443:                ttc.pushContext(lockID, txnType);
444:            }
445:
446:            private void logCommit0() {
447:                if (logger.isDebugEnabled())
448:                    logger.debug("commit()");
449:            }
450:
451:            private boolean commit(LockID lockID,
452:                    ClientTransaction currentTransaction, boolean isWaitContext) {
453:                try {
454:                    return commitInternal(lockID, currentTransaction,
455:                            isWaitContext);
456:                } catch (Throwable t) {
457:                    remoteTxManager.stopProcessing();
458:                    Banner
459:                            .errorBanner("Terracotta client shutting down due to error "
460:                                    + t);
461:                    logger.error(t);
462:                    if (t instanceof  Error) {
463:                        throw (Error) t;
464:                    }
465:                    if (t instanceof  RuntimeException) {
466:                        throw (RuntimeException) t;
467:                    }
468:                    throw new RuntimeException(t);
469:                }
470:            }
471:
472:            private boolean commitInternal(LockID lockID,
473:                    ClientTransaction currentTransaction, boolean isWaitContext) {
474:                Assert.assertNotNull("transaction", currentTransaction);
475:
476:                try {
477:                    disableTransactionLogging();
478:
479:                    // If the current transactionContext is READ_ONLY, there is no need to commit.
480:                    TransactionContext tc = peekContext(lockID);
481:                    if (tc.getType().equals(TxnType.READ_ONLY)) {
482:                        txMonitor.committedReadTransaction();
483:                        return false;
484:                    }
485:
486:                    boolean hasPendingCreateObjects = objectManager
487:                            .hasPendingCreateObjects();
488:                    if (hasPendingCreateObjects) {
489:                        objectManager.addPendingCreateObjectsToTransaction();
490:                    }
491:
492:                    currentTransaction.setAlreadyCommitted();
493:                    if (currentTransaction.hasChangesOrNotifies()
494:                            || hasPendingCreateObjects) {
495:                        if (txMonitor.isEnabled()) {
496:                            currentTransaction.updateMBean(txMonitor);
497:                        }
498:                        remoteTxManager.commit(currentTransaction);
499:                    }
500:                    return true;
501:                } finally {
502:                    enableTransactionLogging();
503:
504:                    // always try to unlock even if we are throwing an exception
505:                    // if (!isWaitContext && !currentTransaction.isNull()) {
506:                    // lockManager.unlock(currentTransaction.getLockID());
507:                    // }
508:                    if (!isWaitContext && !currentTransaction.isNull()) {
509:                        if (lockID != null && !lockID.isNull()) {
510:                            lockManager.unlock(lockID);
511:                        } else {
512:                            throw new AssertionError(
513:                                    "Trying to unlock with lockID = null!");
514:                        }
515:                    }
516:                }
517:            }
518:
519:            private void basicApply(Collection objectChanges, Map newRoots,
520:                    boolean force) throws DNAException {
521:
522:                List l = new LinkedList();
523:
524:                for (Iterator i = objectChanges.iterator(); i.hasNext();) {
525:                    DNA dna = (DNA) i.next();
526:                    TCObject tcobj = null;
527:                    Assert.assertTrue(dna.isDelta());
528:                    try {
529:                        // This is a major hack to prevent distributed method calls
530:                        // sent to apps that don't have the right classes from dying
531:                        // This should be fixed in a better way some day :-)
532:                        objectManager.getClassFor(Namespace
533:                                .parseClassNameIfNecessary(dna.getTypeName()),
534:                                dna.getDefiningLoaderDescription());
535:                        tcobj = objectManager.lookup(dna.getObjectID());
536:                    } catch (ClassNotFoundException cnfe) {
537:                        logger
538:                                .warn("Could not apply change because class not local:"
539:                                        + dna.getTypeName());
540:                        continue;
541:                    }
542:                    // Important to have a hard reference to the object while we apply
543:                    // changes so that it doesn't get gc'd on us
544:                    Object obj = tcobj == null ? null : tcobj.getPeerObject();
545:                    l.add(obj);
546:                    if (obj != null) {
547:                        try {
548:                            tcobj.hydrate(dna, force);
549:                        } catch (ClassNotFoundException cnfe) {
550:                            logger
551:                                    .warn("Could not apply change because class not local:"
552:                                            + cnfe.getMessage());
553:                            throw new TCClassNotFoundException(cnfe);
554:                        }
555:                    }
556:                }
557:
558:                for (Iterator i = newRoots.entrySet().iterator(); i.hasNext();) {
559:                    Entry entry = (Entry) i.next();
560:                    String rootName = (String) entry.getKey();
561:                    ObjectID newRootID = (ObjectID) entry.getValue();
562:                    objectManager.replaceRootIDIfNecessary(rootName, newRootID);
563:                }
564:            }
565:
566:            public void receivedAcknowledgement(SessionID sessionID,
567:                    TransactionID transactionID) {
568:                this .remoteTxManager.receivedAcknowledgement(sessionID,
569:                        transactionID);
570:            }
571:
572:            public void receivedBatchAcknowledgement(TxnBatchID batchID) {
573:                this .remoteTxManager.receivedBatchAcknowledgement(batchID);
574:            }
575:
576:            public void apply(TxnType txType, List lockIDs,
577:                    Collection objectChanges, Set lookupObjectIDs, Map newRoots) {
578:                // beginNull(TxnType.NORMAL);
579:                try {
580:                    disableTransactionLogging();
581:                    basicApply(objectChanges, newRoots, false);
582:                } finally {
583:                    // removeTopTransaction();
584:                    enableTransactionLogging();
585:                }
586:            }
587:
588:            // private void removeTopTransaction() {
589:            // this.getThreadTransactionContext().popCurrentTransaction();
590:            // }
591:            //
592:            // private void beginNull(TxnType txType) {
593:            // this.beginNull(LockID.NULL_ID, txType);
594:            // }
595:
596:            // private void beginNull(LockID lockID, TxnType type) {
597:            // ClientTransaction current = getTransactionOrNull();
598:            // this.pushTxContext(lockID, type);
599:            // if (current == null) {
600:            // current = txFactory.newNullInstance(lockID, type);
601:            // setTransaction(current);
602:            // }
603:            // }
604:
605:            public void literalValueChanged(TCObject source, Object newValue,
606:                    Object oldValue) {
607:                if (isTransactionLoggingDisabled()) {
608:                    return;
609:                }
610:
611:                try {
612:                    disableTransactionLogging();
613:
614:                    Object pojo = source.getPeerObject();
615:                    ClientTransaction tx;
616:
617:                    try {
618:                        tx = getTransaction(pojo);
619:                    } catch (UnlockedSharedObjectException usoe) {
620:                        if (sendErrors) {
621:                            UnlockedSharedObjectEventContext eventContext = appEventContextFactory
622:                                    .createUnlockedSharedObjectEventContext(
623:                                            pojo, usoe);
624:                            objectManager
625:                                    .sendApplicationEvent(pojo,
626:                                            new UnlockedSharedObjectEvent(
627:                                                    eventContext));
628:                        }
629:
630:                        throw usoe;
631:                    }
632:
633:                    if (tx.getTransactionType() == TxnType.READ_ONLY) {
634:                        ReadOnlyException roe = makeReadOnlyException("Failed To Change Value in:  "
635:                                + newValue.getClass().getName());
636:
637:                        if (sendErrors) {
638:                            ReadOnlyObjectEventContext eventContext = appEventContextFactory
639:                                    .createReadOnlyObjectEventContext(pojo, roe);
640:                            objectManager.sendApplicationEvent(pojo,
641:                                    new ReadOnlyObjectEvent(eventContext));
642:                        }
643:
644:                        throw roe;
645:                    }
646:
647:                    tx.literalValueChanged(source, newValue, oldValue);
648:
649:                } finally {
650:                    enableTransactionLogging();
651:                }
652:
653:            }
654:
655:            public void fieldChanged(TCObject source, String classname,
656:                    String fieldname, Object newValue, int index) {
657:                if (isTransactionLoggingDisabled()) {
658:                    return;
659:                }
660:
661:                try {
662:                    disableTransactionLogging();
663:
664:                    Object pojo = source.getPeerObject();
665:
666:                    ClientTransaction tx;
667:                    try {
668:                        tx = getTransaction(pojo);
669:                    } catch (UnlockedSharedObjectException usoe) {
670:                        if (sendErrors) {
671:                            UnlockedSharedObjectEventContext eventContext = appEventContextFactory
672:                                    .createUnlockedSharedObjectEventContext(
673:                                            pojo, classname, fieldname, usoe);
674:                            objectManager
675:                                    .sendApplicationEvent(pojo,
676:                                            new UnlockedSharedObjectEvent(
677:                                                    eventContext));
678:                        }
679:
680:                        throw usoe;
681:                    }
682:
683:                    if (tx.getTransactionType() == TxnType.READ_ONLY) {
684:                        ReadOnlyException roe = makeReadOnlyException("Failed To Modify Field:  "
685:                                + fieldname + " in " + classname);
686:                        if (sendErrors) {
687:                            ReadOnlyObjectEventContext eventContext = appEventContextFactory
688:                                    .createReadOnlyObjectEventContext(pojo,
689:                                            classname, fieldname, roe);
690:                            objectManager.sendApplicationEvent(pojo,
691:                                    new ReadOnlyObjectEvent(eventContext));
692:                        }
693:                        throw roe;
694:                    }
695:
696:                    logFieldChanged0(source, classname, fieldname, newValue, tx);
697:
698:                    if (newValue != null
699:                            && literalValues.isLiteralInstance(newValue)) {
700:                        tx.fieldChanged(source, classname, fieldname, newValue,
701:                                index);
702:                    } else {
703:                        if (newValue != null) {
704:                            objectManager.checkPortabilityOfField(newValue,
705:                                    fieldname, pojo);
706:                        }
707:
708:                        TCObject tco = objectManager.lookupOrCreate(newValue);
709:
710:                        tx.fieldChanged(source, classname, fieldname, tco
711:                                .getObjectID(), index);
712:
713:                        // record the reference in this transaction -- This is to solve the race condition of transactions
714:                        // that reference objects newly "created" in other transactions that may not commit before us
715:                        if (newValue != null) {
716:                            tx.createObject(tco);
717:                        }
718:                    }
719:                } finally {
720:                    enableTransactionLogging();
721:                }
722:            }
723:
724:            public void arrayChanged(TCObject source, int startPos,
725:                    Object array, int length) {
726:                if (isTransactionLoggingDisabled()) {
727:                    return;
728:                }
729:                try {
730:                    disableTransactionLogging();
731:                    Object pojo = source.getPeerObject();
732:                    ClientTransaction tx;
733:
734:                    try {
735:                        tx = getTransaction(pojo);
736:                    } catch (UnlockedSharedObjectException usoe) {
737:                        if (sendErrors) {
738:                            UnlockedSharedObjectEventContext eventContext = appEventContextFactory
739:                                    .createUnlockedSharedObjectEventContext(
740:                                            pojo, usoe);
741:                            objectManager
742:                                    .sendApplicationEvent(pojo,
743:                                            new UnlockedSharedObjectEvent(
744:                                                    eventContext));
745:                        }
746:
747:                        throw usoe;
748:                    }
749:
750:                    if (tx.getTransactionType() == TxnType.READ_ONLY) {
751:                        ReadOnlyException roe = makeReadOnlyException("Failed To Modify Array: "
752:                                + pojo.getClass().getName());
753:
754:                        if (sendErrors) {
755:                            ReadOnlyObjectEventContext eventContext = appEventContextFactory
756:                                    .createReadOnlyObjectEventContext(pojo, roe);
757:                            objectManager.sendApplicationEvent(pojo,
758:                                    new ReadOnlyObjectEvent(eventContext));
759:                        }
760:                        throw roe;
761:
762:                    }
763:
764:                    if (!ClassUtils.isPrimitiveArray(array)) {
765:                        Object[] objArray = (Object[]) array;
766:                        for (int i = 0; i < length; i++) {
767:
768:                            Object element = objArray[i];
769:                            if (!literalValues.isLiteralInstance(element)) {
770:                                if (element != null)
771:                                    objectManager.checkPortabilityOfField(
772:                                            element, String.valueOf(i), pojo);
773:
774:                                TCObject tco = objectManager
775:                                        .lookupOrCreate(element);
776:                                objArray[i] = tco.getObjectID();
777:                                // record the reference in this transaction -- This is to solve the race condition of transactions
778:                                // that reference objects newly "created" in other transactions that may not commit before us
779:                                if (element != null)
780:                                    tx.createObject(tco);
781:                            }
782:                        }
783:                    }
784:
785:                    tx.arrayChanged(source, startPos, array, length);
786:
787:                } finally {
788:                    enableTransactionLogging();
789:                }
790:            }
791:
792:            private void logFieldChanged0(TCObject source, String classname,
793:                    String fieldname, Object newValue, ClientTransaction tx) {
794:                if (logger.isDebugEnabled())
795:                    logger.debug("fieldChanged(source=" + source
796:                            + ", classname=" + classname + ", fieldname="
797:                            + fieldname + ", newValue=" + newValue + ", tx="
798:                            + tx);
799:            }
800:
801:            public void logicalInvoke(TCObject source, int method,
802:                    String methodName, Object[] parameters) {
803:                if (isTransactionLoggingDisabled()) {
804:                    return;
805:                }
806:
807:                try {
808:                    disableTransactionLogging();
809:
810:                    Object pojo = source.getPeerObject();
811:                    ClientTransaction tx;
812:
813:                    try {
814:                        tx = getTransaction(pojo);
815:                    } catch (UnlockedSharedObjectException usoe) {
816:                        if (sendErrors) {
817:                            UnlockedSharedObjectEventContext eventContext = appEventContextFactory
818:                                    .createUnlockedSharedObjectEventContext(
819:                                            pojo, usoe);
820:                            pojo = objectManager
821:                                    .cloneAndInvokeLogicalOperation(pojo,
822:                                            methodName, parameters);
823:                            objectManager
824:                                    .sendApplicationEvent(pojo,
825:                                            new UnlockedSharedObjectEvent(
826:                                                    eventContext));
827:                        }
828:
829:                        throw usoe;
830:                    }
831:
832:                    if (tx.getTransactionType() == TxnType.READ_ONLY) {
833:                        ReadOnlyException roe = makeReadOnlyException("Failed Method Call: "
834:                                + methodName);
835:
836:                        if (sendErrors) {
837:                            ReadOnlyObjectEventContext eventContext = appEventContextFactory
838:                                    .createReadOnlyObjectEventContext(pojo, roe);
839:                            pojo = objectManager
840:                                    .cloneAndInvokeLogicalOperation(pojo,
841:                                            methodName, parameters);
842:                            objectManager.sendApplicationEvent(pojo,
843:                                    new ReadOnlyObjectEvent(eventContext));
844:                        }
845:                        throw roe;
846:                    }
847:
848:                    for (int i = 0; i < parameters.length; i++) {
849:                        Object p = parameters[i];
850:                        boolean isLiteral = literalValues.isLiteralInstance(p);
851:                        if (!isLiteral) {
852:                            if (p != null) {
853:                                objectManager.checkPortabilityOfLogicalAction(
854:                                        parameters, i, methodName, pojo);
855:                            }
856:
857:                            TCObject tco = objectManager.lookupOrCreate(p);
858:                            parameters[i] = tco.getObjectID();
859:                            if (p != null) {
860:                                // record the reference in this transaction -- This is to solve the race condition of transactions
861:                                // that reference objects newly "created" in other transactions that may not commit before us
862:                                tx.createObject(tco);
863:                            }
864:                        }
865:                    }
866:
867:                    tx.logicalInvoke(source, method, parameters, methodName);
868:                } finally {
869:                    enableTransactionLogging();
870:                }
871:            }
872:
873:            private ReadOnlyException makeReadOnlyException(String details) {
874:                long vmId = cidProvider.getChannelID().toLong();
875:
876:                final ReadOnlyException roe;
877:
878:                if (details != null) {
879:                    roe = new ReadOnlyException(READ_ONLY_TEXT, Thread
880:                            .currentThread().getName(), vmId, details);
881:                } else {
882:                    roe = new ReadOnlyException(READ_ONLY_TEXT, Thread
883:                            .currentThread().getName(), vmId);
884:                }
885:                System.err.println(roe.getMessage());
886:                return roe;
887:            }
888:
889:            private void setTransaction(ClientTransaction tx) {
890:                getThreadTransactionContext().setCurrentTransaction(tx);
891:            }
892:
893:            public void createObject(TCObject source) {
894:                getTransaction().createObject(source);
895:            }
896:
897:            public void createRoot(String name, ObjectID rootID) {
898:                getTransaction().createRoot(name, rootID);
899:            }
900:
901:            public void addReference(TCObject tco) {
902:                ClientTransaction txn = getTransactionOrNull();
903:                if (txn != null) {
904:                    txn.createObject(tco);
905:                }
906:            }
907:
908:            public ChannelIDProvider getChannelIDProvider() {
909:                return cidProvider;
910:            }
911:
912:            public void disableTransactionLogging() {
913:                ThreadTransactionLoggingStack txnStack = (ThreadTransactionLoggingStack) txnLogging
914:                        .get();
915:                if (txnStack == null) {
916:                    txnStack = new ThreadTransactionLoggingStack();
917:                    txnLogging.set(txnStack);
918:                }
919:                txnStack.increment();
920:            }
921:
922:            public void enableTransactionLogging() {
923:                ThreadTransactionLoggingStack txnStack = (ThreadTransactionLoggingStack) txnLogging
924:                        .get();
925:                Assert.assertNotNull(txnStack);
926:                final int size = txnStack.decrement();
927:                Assert.assertTrue("size=" + size, size >= 0);
928:            }
929:
930:            public boolean isTransactionLoggingDisabled() {
931:                Object txnStack = txnLogging.get();
932:                return (txnStack != null)
933:                        && (((ThreadTransactionLoggingStack) txnStack).get() > 0);
934:            }
935:
936:            public static class ThreadTransactionLoggingStack {
937:                int callCount = 0;
938:
939:                public int increment() {
940:                    return ++callCount;
941:                }
942:
943:                public int decrement() {
944:                    return --callCount;
945:                }
946:
947:                public int get() {
948:                    return callCount;
949:                }
950:            }
951:
952:            public void addDmiDescriptor(DmiDescriptor dd) {
953:                getTransaction().addDmiDescritor(dd);
954:            }
955:
956:            private static final String READ_ONLY_TEXT = "Current transaction with read-only access attempted to modify a shared object.  "
957:                    + "\nPlease alter the locks section of your Terracotta configuration so that the methods involved in this transaction have read/write access.";
958:
959:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.