Source Code Cross Referenced for Lock.java in  » JMX » je » com » sleepycat » je » txn » 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 » JMX » je » com.sleepycat.je.txn 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*-
002:         * See the file LICENSE for redistribution information.
003:         *
004:         * Copyright (c) 2002,2008 Oracle.  All rights reserved.
005:         *
006:         * $Id: Lock.java,v 1.60.2.6 2008/02/06 12:52:30 cwl Exp $
007:         */
008:
009:        package com.sleepycat.je.txn;
010:
011:        import java.util.ArrayList;
012:        import java.util.Collections;
013:        import java.util.HashSet;
014:        import java.util.Iterator;
015:        import java.util.List;
016:        import java.util.Set;
017:
018:        import com.sleepycat.je.DatabaseException;
019:        import com.sleepycat.je.dbi.MemoryBudget;
020:
021:        /**
022:         * A Lock embodies the lock state of a NodeId.  It includes a set of owners and
023:         * a list of waiters.
024:         */
025:        public// for Sizeof
026:        class Lock {
027:            private static final int REMOVE_LOCKINFO_OVERHEAD = 0 - MemoryBudget.LOCKINFO_OVERHEAD;
028:
029:            /**
030:             * A single locker always appears only once in the logical set of owners.
031:             * The owners set is always in one of the following states.
032:             *
033:             * 1- Empty
034:             * 2- A single writer
035:             * 3- One or more readers
036:             * 4- Multiple writers or a mix of readers and writers, all for
037:             * txns which share locks (all ThreadLocker instances for the same
038:             * thread)
039:             *
040:             * Both ownerSet and waiterList are a collection of LockInfo.  Since the
041:             * common case is that there is only one owner or waiter, we have added an
042:             * optimization to avoid the cost of collections.  FirstOwner and
043:             * firstWaiter are used for the first owner or waiter of the lock, and the
044:             * corresponding collection is instantiated and used only if more owners
045:             * arrive.
046:             *
047:             * In terms of memory accounting, we count up the cost of each added or
048:             * removed LockInfo, but not the cost of the HashSet/List entry
049:             * overhead. We could do the latter for more precise accounting.
050:             */
051:            private LockInfo firstOwner;
052:            private Set ownerSet;
053:            private LockInfo firstWaiter;
054:            private List waiterList;
055:
056:            /**
057:             * Create a Lock. public for Sizeof
058:             */
059:            public Lock() {
060:            }
061:
062:            /**
063:             * The first waiter goes into the firstWaiter member variable.  Once the
064:             * waiterList is made, all appended waiters go into waiterList, even after
065:             * the firstWaiter goes away and leaves that field null, so as to leave the
066:             * list ordered.
067:             */
068:            private void addWaiterToEndOfList(LockInfo waiter, MemoryBudget mb,
069:                    int lockTableIndex) {
070:                /* Careful: order important! */
071:                if (waiterList == null) {
072:                    if (firstWaiter == null) {
073:                        firstWaiter = waiter;
074:                    } else {
075:                        waiterList = new ArrayList();
076:                        waiterList.add(waiter);
077:                    }
078:                } else {
079:                    waiterList.add(waiter);
080:                }
081:                mb.updateLockMemoryUsage(MemoryBudget.LOCKINFO_OVERHEAD,
082:                        lockTableIndex);
083:            }
084:
085:            /**
086:             * Add this waiter to the front of the list.
087:             */
088:            private void addWaiterToHeadOfList(LockInfo waiter,
089:                    MemoryBudget mb, int lockTableIndex) {
090:                /* Shuffle the current first waiter down a slot. */
091:                if (firstWaiter != null) {
092:                    if (waiterList == null) {
093:                        waiterList = new ArrayList();
094:                    }
095:                    waiterList.add(0, firstWaiter);
096:                }
097:
098:                firstWaiter = waiter;
099:                mb.updateLockMemoryUsage(MemoryBudget.LOCKINFO_OVERHEAD,
100:                        lockTableIndex);
101:            }
102:
103:            /**
104:             * Get a list of waiters for debugging and error messages.
105:             */
106:            List getWaitersListClone() {
107:                List dumpWaiters = new ArrayList();
108:                if (firstWaiter != null) {
109:                    dumpWaiters.add(firstWaiter);
110:                }
111:
112:                if (waiterList != null) {
113:                    dumpWaiters.addAll(waiterList);
114:                }
115:
116:                return dumpWaiters;
117:            }
118:
119:            /**
120:             * Remove this locker from the waiter list.
121:             */
122:            void flushWaiter(Locker locker, MemoryBudget mb, int lockTableIndex) {
123:                if ((firstWaiter != null)
124:                        && (firstWaiter.getLocker() == locker)) {
125:                    firstWaiter = null;
126:                    mb.updateLockMemoryUsage(REMOVE_LOCKINFO_OVERHEAD,
127:                            lockTableIndex);
128:                } else if (waiterList != null) {
129:                    Iterator iter = waiterList.iterator();
130:                    while (iter.hasNext()) {
131:                        LockInfo info = (LockInfo) iter.next();
132:                        if (info.getLocker() == locker) {
133:                            iter.remove();
134:                            mb.updateLockMemoryUsage(REMOVE_LOCKINFO_OVERHEAD,
135:                                    lockTableIndex);
136:                            return;
137:                        }
138:                    }
139:                }
140:            }
141:
142:            private void addOwner(LockInfo newLock, MemoryBudget mb,
143:                    int lockTableIndex) {
144:                if (firstOwner == null) {
145:                    firstOwner = newLock;
146:                } else {
147:                    if (ownerSet == null) {
148:                        ownerSet = new HashSet();
149:                    }
150:                    ownerSet.add(newLock);
151:                }
152:                mb.updateLockMemoryUsage(MemoryBudget.LOCKINFO_OVERHEAD,
153:                        lockTableIndex);
154:            }
155:
156:            /**
157:             * Get a new Set of the owners.
158:             */
159:            Set getOwnersClone() {
160:
161:                /* No need to update memory usage, the returned Set is transient. */
162:                Set owners;
163:                if (ownerSet != null) {
164:                    owners = new HashSet(ownerSet);
165:                } else {
166:                    owners = new HashSet();
167:                }
168:                if (firstOwner != null) {
169:                    owners.add(firstOwner);
170:                }
171:                return owners;
172:            }
173:
174:            /**
175:             * Remove this LockInfo from the owner set.
176:             */
177:            private boolean flushOwner(LockInfo oldOwner, MemoryBudget mb,
178:                    int lockTableIndex) {
179:                boolean removed = false;
180:                if (oldOwner != null) {
181:                    if (firstOwner == oldOwner) {
182:                        firstOwner = null;
183:                        return true;
184:                    }
185:
186:                    if (ownerSet != null) {
187:                        removed = ownerSet.remove(oldOwner);
188:                    }
189:                }
190:
191:                if (removed) {
192:                    mb.updateLockMemoryUsage(REMOVE_LOCKINFO_OVERHEAD,
193:                            lockTableIndex);
194:                }
195:                return removed;
196:            }
197:
198:            /**
199:             * Remove this locker from the owner set.
200:             */
201:            private LockInfo flushOwner(Locker locker, MemoryBudget mb,
202:                    int lockTableIndex) {
203:                LockInfo flushedInfo = null;
204:                if ((firstOwner != null) && (firstOwner.getLocker() == locker)) {
205:                    flushedInfo = firstOwner;
206:                    firstOwner = null;
207:                } else if (ownerSet != null) {
208:                    Iterator iter = ownerSet.iterator();
209:                    while (iter.hasNext()) {
210:                        LockInfo o = (LockInfo) iter.next();
211:                        if (o.getLocker() == locker) {
212:                            iter.remove();
213:                            flushedInfo = o;
214:                        }
215:                    }
216:                }
217:                if (flushedInfo != null) {
218:                    mb.updateLockMemoryUsage(REMOVE_LOCKINFO_OVERHEAD,
219:                            lockTableIndex);
220:                }
221:
222:                return flushedInfo;
223:            }
224:
225:            /**
226:             * Returns the owner LockInfo for a locker, or null if locker is not an
227:             * owner.
228:             */
229:            private LockInfo getOwnerLockInfo(Locker locker) {
230:                if ((firstOwner != null) && (firstOwner.getLocker() == locker)) {
231:                    return firstOwner;
232:                }
233:
234:                if (ownerSet != null) {
235:                    Iterator iter = ownerSet.iterator();
236:                    while (iter.hasNext()) {
237:                        LockInfo o = (LockInfo) iter.next();
238:                        if (o.getLocker() == locker) {
239:                            return o;
240:                        }
241:                    }
242:                }
243:
244:                return null;
245:            }
246:
247:            /**
248:             * Return true if locker is an owner of this Lock for lockType,
249:             * false otherwise.
250:             *
251:             * This method is only used by unit tests.
252:             */
253:            boolean isOwner(Locker locker, LockType lockType) {
254:                LockInfo o = getOwnerLockInfo(locker);
255:                if (o != null) {
256:                    LockType ownedLockType = o.getLockType();
257:                    if (lockType == ownedLockType) {
258:                        return true;
259:                    }
260:                    LockUpgrade upgrade = ownedLockType.getUpgrade(lockType);
261:                    if (!upgrade.getPromotion()) {
262:                        return true;
263:                    }
264:                }
265:                return false;
266:            }
267:
268:            /**
269:             * Return true if locker is an owner of this Lock and this is a write
270:             * lock.
271:             */
272:            boolean isOwnedWriteLock(Locker locker) {
273:                LockInfo o = getOwnerLockInfo(locker);
274:                return o != null && o.getLockType().isWriteLock();
275:            }
276:
277:            /**
278:             * Return true if locker is a waiter on this Lock.
279:             *
280:             * This method is only used by unit tests.
281:             */
282:            boolean isWaiter(Locker locker) {
283:
284:                if (firstWaiter != null) {
285:                    if (firstWaiter.getLocker() == locker) {
286:                        return true;
287:                    }
288:                }
289:
290:                if (waiterList != null) {
291:                    Iterator iter = waiterList.iterator();
292:                    while (iter.hasNext()) {
293:                        LockInfo info = (LockInfo) iter.next();
294:                        if (info.getLocker() == locker) {
295:                            return true;
296:                        }
297:                    }
298:                }
299:                return false;
300:            }
301:
302:            int nWaiters() {
303:                int count = 0;
304:                if (firstWaiter != null) {
305:                    count++;
306:                }
307:                if (waiterList != null) {
308:                    count += waiterList.size();
309:                }
310:                return count;
311:            }
312:
313:            int nOwners() {
314:                int count = 0;
315:                if (firstOwner != null) {
316:                    count++;
317:                }
318:
319:                if (ownerSet != null) {
320:                    count += ownerSet.size();
321:                }
322:                return count;
323:            }
324:
325:            /**
326:             * Attempts to acquire the lock and returns the LockGrantType.
327:             *
328:             * Assumes we hold the lockTableLatch when entering this method.
329:             */
330:            LockGrantType lock(LockType requestType, Locker locker,
331:                    boolean nonBlockingRequest, MemoryBudget mb,
332:                    int lockTableIndex) {
333:
334:                assert validateRequest(locker); // intentional side effect
335:
336:                /* Request an ordinary lock by checking the owners list. */
337:                LockInfo newLock = new LockInfo(locker, requestType);
338:                LockGrantType grant = tryLock(newLock, nWaiters() == 0, mb,
339:                        lockTableIndex);
340:
341:                /* Do we have to wait for this lock? */
342:                if (grant == LockGrantType.WAIT_NEW
343:                        || grant == LockGrantType.WAIT_PROMOTION
344:                        || grant == LockGrantType.WAIT_RESTART) {
345:
346:                    /*
347:                     * If the request type can cause a restart and a restart conflict
348:                     * does not already exist, then we have to check the waiters list
349:                     * for restart conflicts.  A restart conflict must take precedence
350:                     * or it may be missed.
351:                     */
352:                    if (requestType.getCausesRestart()
353:                            && grant != LockGrantType.WAIT_RESTART) {
354:                        LockInfo waiter = null;
355:                        Iterator iter = null;
356:
357:                        if (waiterList != null) {
358:                            iter = waiterList.iterator();
359:                        }
360:
361:                        if (firstWaiter != null) {
362:                            waiter = firstWaiter;
363:                        } else if ((iter != null) && (iter.hasNext())) {
364:                            waiter = (LockInfo) iter.next();
365:                        }
366:
367:                        while (waiter != null) {
368:
369:                            /*
370:                             * Check for a restart conflict.  Ignore LockType.RESTART
371:                             * in the waiter list when checking for conflicts.
372:                             */
373:                            Locker waiterLocker = waiter.getLocker();
374:                            LockType waiterType = waiter.getLockType();
375:                            if (waiterType != LockType.RESTART
376:                                    && locker != waiterLocker
377:                                    && !locker.sharesLocksWith(waiterLocker)) {
378:                                LockConflict conflict = waiterType
379:                                        .getConflict(requestType);
380:                                if (conflict.getRestart()) {
381:                                    grant = LockGrantType.WAIT_RESTART;
382:                                    break;
383:                                }
384:                            }
385:
386:                            /* Move to the next waiter, if it's in the list. */
387:                            if ((iter != null) && (iter.hasNext())) {
388:                                waiter = (LockInfo) iter.next();
389:                            } else {
390:                                waiter = null;
391:                            }
392:                        }
393:                    }
394:
395:                    /* Add the waiter or deny the lock as appropriate. */
396:                    if (nonBlockingRequest) {
397:                        grant = LockGrantType.DENIED;
398:                    } else {
399:                        if (grant == LockGrantType.WAIT_PROMOTION) {
400:                            addWaiterToHeadOfList(newLock, mb, lockTableIndex);
401:                        } else {
402:                            assert grant == LockGrantType.WAIT_NEW
403:                                    || grant == LockGrantType.WAIT_RESTART;
404:
405:                            /*
406:                             * If waiting to restart, change the lock type to RESTART
407:                             * to avoid granting the lock later.  We wait until the
408:                             * RESTART waiter moves to the head of waiter list to
409:                             * prevent the requester from spinning performing repeated
410:                             * restarts, but we don't grant the lock.
411:                             */
412:                            if (grant == LockGrantType.WAIT_RESTART) {
413:                                newLock.setLockType(LockType.RESTART);
414:                            }
415:
416:                            addWaiterToEndOfList(newLock, mb, lockTableIndex);
417:                        }
418:                    }
419:                }
420:
421:                return grant;
422:            }
423:
424:            /**
425:             * Releases a lock and moves the next waiter(s) to the owners.
426:             * @return
427:             * null if we were not the owner,
428:             * a non-empty set if owners should be notified after releasing,
429:             * an empty set if no notification is required.
430:             */
431:            Set release(Locker locker, MemoryBudget mb, int lockTableIndex) {
432:
433:                LockInfo removedLock = flushOwner(locker, mb, lockTableIndex);
434:                if (removedLock == null) {
435:                    /* Not owner. */
436:                    return null;
437:                }
438:
439:                Set lockersToNotify = Collections.EMPTY_SET;
440:
441:                if (nWaiters() == 0) {
442:                    /* No more waiters, so no one to notify. */
443:                    return lockersToNotify;
444:                }
445:
446:                /*
447:                 * Move the next set of waiters to the owners set. Iterate through the
448:                 * firstWaiter field, then the waiterList.
449:                 */
450:                LockInfo waiter = null;
451:                Iterator iter = null;
452:                boolean isFirstWaiter = false;
453:
454:                if (waiterList != null) {
455:                    iter = waiterList.iterator();
456:                }
457:
458:                if (firstWaiter != null) {
459:                    waiter = firstWaiter;
460:                    isFirstWaiter = true;
461:                } else if ((iter != null) && (iter.hasNext())) {
462:                    waiter = (LockInfo) iter.next();
463:                }
464:
465:                while (waiter != null) {
466:                    /* Make the waiter an owner if the lock can be acquired. */
467:                    LockType waiterType = waiter.getLockType();
468:                    Locker waiterLocker = waiter.getLocker();
469:                    LockGrantType grant;
470:                    if (waiterType == LockType.RESTART) {
471:                        /* Special case for restarts: see rangeInsertConflict. */
472:                        grant = rangeInsertConflict(waiterLocker) ? LockGrantType.WAIT_NEW
473:                                : LockGrantType.NEW;
474:                    } else {
475:                        /* Try locking. */
476:                        grant = tryLock(waiter, true, mb, lockTableIndex);
477:                    }
478:                    /* Check if granted. */
479:                    if (grant == LockGrantType.NEW
480:                            || grant == LockGrantType.EXISTING
481:                            || grant == LockGrantType.PROMOTION) {
482:                        /* Remove it from the waiters list. */
483:                        if (isFirstWaiter) {
484:                            firstWaiter = null;
485:                        } else {
486:                            iter.remove();
487:                        }
488:                        if (lockersToNotify == Collections.EMPTY_SET) {
489:                            lockersToNotify = new HashSet();
490:                        }
491:                        lockersToNotify.add(waiterLocker);
492:                        mb.updateLockMemoryUsage(REMOVE_LOCKINFO_OVERHEAD,
493:                                lockTableIndex);
494:                    } else {
495:                        assert grant == LockGrantType.WAIT_NEW
496:                                || grant == LockGrantType.WAIT_PROMOTION
497:                                || grant == LockGrantType.WAIT_RESTART;
498:                        /* Stop on first waiter that cannot be an owner. */
499:                        break;
500:                    }
501:
502:                    /* Move to the next waiter, if it's in the list. */
503:                    if ((iter != null) && (iter.hasNext())) {
504:                        waiter = (LockInfo) iter.next();
505:                        isFirstWaiter = false;
506:                    } else {
507:                        waiter = null;
508:                    }
509:                }
510:                return lockersToNotify;
511:            }
512:
513:            /**
514:             * Called from lock() to try locking a new request, and from release() to
515:             * try locking a waiting request.
516:             *
517:             * @param newLock is the lock that is requested.
518:             *
519:             * @param firstWaiterInLine determines whether to grant the lock when a
520:             * NEW lock can be granted, but other non-conflicting owners exist; for
521:             * example, when a new READ lock is requested but READ locks are held by
522:             * other owners.  This parameter should be true if the requestor is the
523:             * first waiter in line (or if there are no waiters), and false otherwise.
524:             *
525:             * @param mb is the current memory budget.
526:             *
527:             * @return LockGrantType.EXISTING, NEW, PROMOTION, WAIT_RESTART, WAIT_NEW
528:             * or WAIT_PROMOTION.
529:             */
530:            private LockGrantType tryLock(LockInfo newLock,
531:                    boolean firstWaiterInLine, MemoryBudget mb,
532:                    int lockTableIndex) {
533:
534:                /* If no one owns this right now, just grab it. */
535:                if (nOwners() == 0) {
536:                    addOwner(newLock, mb, lockTableIndex);
537:                    return LockGrantType.NEW;
538:                }
539:
540:                Locker locker = newLock.getLocker();
541:                LockType requestType = newLock.getLockType();
542:                LockUpgrade upgrade = null;
543:                LockInfo lockToUpgrade = null;
544:                boolean ownerExists = false;
545:                boolean ownerConflicts = false;
546:
547:                /*
548:                 * Iterate through the current owners. See if there is a current owner
549:                 * who has to be upgraded from read to write. Also track whether there
550:                 * is a conflict with another owner.
551:                 */
552:                LockInfo owner = null;
553:                Iterator iter = null;
554:
555:                if (ownerSet != null) {
556:                    iter = ownerSet.iterator();
557:                }
558:
559:                if (firstOwner != null) {
560:                    owner = firstOwner;
561:                } else if ((iter != null) && (iter.hasNext())) {
562:                    owner = (LockInfo) iter.next();
563:                }
564:
565:                while (owner != null) {
566:                    Locker ownerLocker = owner.getLocker();
567:                    LockType ownerType = owner.getLockType();
568:                    if (locker == ownerLocker) {
569:
570:                        /*
571:                         * Requestor currently holds this lock: check for upgrades.
572:                         * If no type change is needed, return EXISTING now to avoid
573:                         * iterating further; otherwise, we need to check for conflicts
574:                         * before granting the upgrade.
575:                         */
576:                        assert (upgrade == null); // An owner should appear only once
577:                        upgrade = ownerType.getUpgrade(requestType);
578:                        if (upgrade.getUpgrade() == null) {
579:                            return LockGrantType.EXISTING;
580:                        } else {
581:                            lockToUpgrade = owner;
582:                        }
583:                    } else {
584:
585:                        /*
586:                         * Requestor does not hold this lock: check for conflicts.
587:                         * If the owner shares locks with the requestor, ignore it;
588:                         * otherwise, if a restart conflict exists, return it now;
589:                         * otherwise, save the conflict information.
590:                         */
591:                        if (!locker.sharesLocksWith(ownerLocker)) {
592:                            LockConflict conflict = ownerType
593:                                    .getConflict(requestType);
594:                            if (conflict.getRestart()) {
595:                                return LockGrantType.WAIT_RESTART;
596:                            } else {
597:                                if (!conflict.getAllowed()) {
598:                                    ownerConflicts = true;
599:                                }
600:                                ownerExists = true;
601:                            }
602:                        }
603:                    }
604:
605:                    /* Move on to the next owner. */
606:                    if ((iter != null) && (iter.hasNext())) {
607:                        owner = (LockInfo) iter.next();
608:                    } else {
609:                        owner = null;
610:                    }
611:                }
612:
613:                /* Now handle the upgrade or conflict as appropriate. */
614:                if (upgrade != null) {
615:                    /* The requestor holds this lock. */
616:                    LockType upgradeType = upgrade.getUpgrade();
617:                    assert upgradeType != null;
618:                    if (!ownerConflicts) {
619:                        /* No conflict: grant the upgrade.  */
620:                        lockToUpgrade.setLockType(upgradeType);
621:                        return upgrade.getPromotion() ? LockGrantType.PROMOTION
622:                                : LockGrantType.EXISTING;
623:                    } else {
624:                        /* Upgrade cannot be granted at this time. */
625:                        return LockGrantType.WAIT_PROMOTION;
626:                    }
627:                } else {
628:                    /* The requestor doesn't hold this lock. */
629:                    if (!ownerConflicts && (!ownerExists || firstWaiterInLine)) {
630:                        /* No conflict: grant the lock. */
631:                        addOwner(newLock, mb, lockTableIndex);
632:                        return LockGrantType.NEW;
633:                    } else {
634:                        /* Lock cannot be granted at this time. */
635:                        return LockGrantType.WAIT_NEW;
636:                    }
637:                }
638:            }
639:
640:            /**
641:             * Called from release() when a RESTART request is waiting to determine if
642:             * any RANGE_INSERT owners exist.  We can't call tryLock for a RESTART
643:             * lock because it must never be granted.
644:             */
645:            private boolean rangeInsertConflict(Locker waiterLocker) {
646:
647:                LockInfo owner = null;
648:                Iterator iter = null;
649:
650:                if (ownerSet != null) {
651:                    iter = ownerSet.iterator();
652:                }
653:
654:                if (firstOwner != null) {
655:                    owner = firstOwner;
656:                } else if ((iter != null) && (iter.hasNext())) {
657:                    owner = (LockInfo) iter.next();
658:                }
659:
660:                while (owner != null) {
661:                    Locker ownerLocker = owner.getLocker();
662:                    if (ownerLocker != waiterLocker
663:                            && !ownerLocker.sharesLocksWith(waiterLocker)
664:                            && owner.getLockType() == LockType.RANGE_INSERT) {
665:                        return true;
666:                    }
667:
668:                    /* Move on to the next owner. */
669:                    if ((iter != null) && (iter.hasNext())) {
670:                        owner = (LockInfo) iter.next();
671:                    } else {
672:                        owner = null;
673:                    }
674:                }
675:
676:                return false;
677:            }
678:
679:            /**
680:             * Downgrade a write lock to a read lock.
681:             */
682:            void demote(Locker locker) {
683:                LockInfo owner = getOwnerLockInfo(locker);
684:                if (owner != null) {
685:                    LockType type = owner.getLockType();
686:                    if (type.isWriteLock()) {
687:                        owner
688:                                .setLockType((type == LockType.RANGE_WRITE) ? LockType.RANGE_READ
689:                                        : LockType.READ);
690:                    }
691:                }
692:            }
693:
694:            /**
695:             * Transfer a lock from one transaction to another. Make sure that this
696:             * destination locker is only present as a single reader or writer.
697:             */
698:            LockType transfer(Long nodeId, Locker currentLocker,
699:                    Locker destLocker, MemoryBudget mb, int lockTableIndex)
700:                    throws DatabaseException {
701:
702:                /*
703:                 * Remove all the old owners held by the dest locker. Take all the
704:                 * owners held by currentLocker and make them dest lockers.
705:                 */
706:                LockType lockType = null;
707:                int numRemovedLockInfos = 0;
708:
709:                if (firstOwner != null) {
710:                    if (firstOwner.getLocker() == destLocker) {
711:                        firstOwner = null;
712:                        numRemovedLockInfos++;
713:                    } else if (firstOwner.getLocker() == currentLocker) {
714:                        lockType = setNewLocker(nodeId, firstOwner, destLocker);
715:                    }
716:                }
717:
718:                if (ownerSet != null) {
719:                    Iterator iter = ownerSet.iterator();
720:                    while (iter.hasNext()) {
721:                        LockInfo owner = (LockInfo) iter.next();
722:                        if (owner.getLocker() == destLocker) {
723:                            iter.remove();
724:                            numRemovedLockInfos++;
725:                        } else if (owner.getLocker() == currentLocker) {
726:                            lockType = setNewLocker(nodeId, owner, destLocker);
727:                        }
728:                    }
729:                }
730:
731:                /* Check the waiters, remove any that belonged to the dest locker. */
732:                if ((firstWaiter != null)
733:                        && (firstWaiter.getLocker() == destLocker)) {
734:                    firstWaiter = null;
735:                    numRemovedLockInfos++;
736:                }
737:                if (waiterList != null) {
738:                    Iterator iter = waiterList.iterator();
739:                    while (iter.hasNext()) {
740:                        LockInfo info = (LockInfo) iter.next();
741:                        if (info.getLocker() == destLocker) {
742:                            iter.remove();
743:                            numRemovedLockInfos++;
744:                        }
745:                    }
746:                }
747:
748:                mb
749:                        .updateLockMemoryUsage(
750:                                0 - (numRemovedLockInfos * MemoryBudget.LOCKINFO_OVERHEAD),
751:                                lockTableIndex);
752:                return lockType;
753:            }
754:
755:            private LockType setNewLocker(Long nodeId, LockInfo owner,
756:                    Locker destLocker) throws DatabaseException {
757:
758:                owner.setLocker(destLocker);
759:                destLocker.addLock(nodeId, owner.getLockType(),
760:                        LockGrantType.NEW);
761:                return owner.getLockType();
762:            }
763:
764:            /**
765:             * Transfer a lock from one transaction to many others. Only really needed
766:             * for case where a write handle lock is being transferred to multiple read
767:             * handles.
768:             */
769:            LockType transferMultiple(Long nodeId, Locker currentLocker,
770:                    Locker[] destLockers, MemoryBudget mb, int lockTableIndex)
771:                    throws DatabaseException {
772:
773:                LockType lockType = null;
774:                LockInfo oldOwner = null;
775:
776:                if (destLockers.length == 1) {
777:                    return transfer(nodeId, currentLocker, destLockers[0], mb,
778:                            lockTableIndex);
779:                } else {
780:
781:                    /*
782:                     * First remove any ownership of the dest txns
783:                     */
784:                    if (firstOwner != null) {
785:                        for (int i = 0; i < destLockers.length; i++) {
786:                            if (firstOwner.getLocker() == destLockers[i]) {
787:                                firstOwner = null;
788:                                break;
789:                            }
790:                        }
791:                    }
792:
793:                    if (ownerSet != null) {
794:                        Iterator ownersIter = ownerSet.iterator();
795:                        while (ownersIter.hasNext()) {
796:                            LockInfo o = (LockInfo) ownersIter.next();
797:                            for (int i = 0; i < destLockers.length; i++) {
798:                                if (o.getLocker() == destLockers[i]) {
799:                                    ownersIter.remove();
800:                                    break;
801:                                }
802:                            }
803:                        }
804:                    }
805:
806:                    /*
807:                     * Create the clones
808:                     */
809:                    if (firstOwner != null) {
810:                        oldOwner = cloneLockInfo(nodeId, firstOwner,
811:                                currentLocker, destLockers, mb, lockTableIndex);
812:                    }
813:
814:                    if ((ownerSet != null) && (oldOwner == null)) {
815:                        Iterator ownersIter = ownerSet.iterator();
816:                        while (ownersIter.hasNext()) {
817:                            LockInfo o = (LockInfo) ownersIter.next();
818:                            oldOwner = cloneLockInfo(nodeId, o, currentLocker,
819:                                    destLockers, mb, lockTableIndex);
820:                            if (oldOwner != null) {
821:                                break;
822:                            }
823:                        }
824:                    }
825:
826:                    /*
827:                     * Check the waiters, remove any that belonged to the dest locker.
828:                     */
829:                    if (firstWaiter != null) {
830:                        for (int i = 0; i < destLockers.length; i++) {
831:                            if (firstWaiter.getLocker() == destLockers[i]) {
832:                                firstWaiter = null;
833:                                break;
834:                            }
835:                        }
836:                    }
837:
838:                    if (waiterList != null) {
839:                        Iterator iter = waiterList.iterator();
840:                        while (iter.hasNext()) {
841:                            LockInfo o = (LockInfo) iter.next();
842:                            for (int i = 0; i < destLockers.length; i++) {
843:                                if (o.getLocker() == destLockers[i]) {
844:                                    iter.remove();
845:                                    break;
846:                                }
847:                            }
848:                        }
849:                    }
850:                }
851:
852:                boolean removed = flushOwner(oldOwner, mb, lockTableIndex);
853:                assert removed;
854:                return lockType;
855:            }
856:
857:            /**
858:             * If oldOwner is the current owner, clone it and transform it into a dest
859:             * locker.
860:             */
861:            private LockInfo cloneLockInfo(Long nodeId, LockInfo oldOwner,
862:                    Locker currentLocker, Locker[] destLockers,
863:                    MemoryBudget mb, int lockTableIndex)
864:                    throws DatabaseException {
865:
866:                if (oldOwner.getLocker() == currentLocker) {
867:                    try {
868:                        LockType lockType = oldOwner.getLockType();
869:                        for (int i = 0; i < destLockers.length; i++) {
870:                            LockInfo clonedLockInfo = (LockInfo) oldOwner
871:                                    .clone();
872:                            clonedLockInfo.setLocker(destLockers[i]);
873:                            destLockers[i].addLock(nodeId, lockType,
874:                                    LockGrantType.NEW);
875:                            addOwner(clonedLockInfo, mb, lockTableIndex);
876:                        }
877:                        return oldOwner;
878:                    } catch (CloneNotSupportedException e) {
879:                        throw new DatabaseException(e);
880:                    }
881:                } else {
882:                    return null;
883:                }
884:            }
885:
886:            /**
887:             * Return the locker that has a write ownership on this lock. If no
888:             * write owner exists, return null.
889:             */
890:            Locker getWriteOwnerLocker() {
891:
892:                LockInfo owner = null;
893:                Iterator iter = null;
894:
895:                if (ownerSet != null) {
896:                    iter = ownerSet.iterator();
897:                }
898:
899:                if (firstOwner != null) {
900:                    owner = firstOwner;
901:                } else if ((iter != null) && (iter.hasNext())) {
902:                    owner = (LockInfo) iter.next();
903:                }
904:
905:                while (owner != null) {
906:                    /* Return locker if it owns a write lock. */
907:                    if (owner.getLockType().isWriteLock()) {
908:                        return owner.getLocker();
909:                    }
910:
911:                    /* Move on to the next owner. */
912:                    if ((iter != null) && (iter.hasNext())) {
913:                        owner = (LockInfo) iter.next();
914:                    } else {
915:                        owner = null;
916:                    }
917:                }
918:
919:                return null;
920:            }
921:
922:            /**
923:             * Debugging aid, validation before a lock request.
924:             */
925:            private boolean validateRequest(Locker locker) {
926:                if (firstWaiter != null) {
927:                    if (firstWaiter.getLocker() == locker) {
928:                        assert false : "locker " + locker
929:                                + " is already on waiters list.";
930:                    }
931:                }
932:
933:                if (waiterList != null) {
934:                    Iterator iter = waiterList.iterator();
935:                    while (iter.hasNext()) {
936:                        LockInfo o = (LockInfo) iter.next();
937:                        if (o.getLocker() == locker) {
938:                            assert false : "locker " + locker
939:                                    + " is already on waiters list.";
940:                        }
941:                    }
942:                }
943:                return true;
944:            }
945:
946:            /**
947:             * Debug dumper.
948:             */
949:            public String toString() {
950:                StringBuffer sb = new StringBuffer();
951:                sb.append(" LockAddr: ").append(System.identityHashCode(this ));
952:                sb.append(" Owners:");
953:                if (nOwners() == 0) {
954:                    sb.append(" (none)");
955:                } else {
956:                    if (firstOwner != null) {
957:                        sb.append(firstOwner);
958:                    }
959:
960:                    if (ownerSet != null) {
961:                        Iterator iter = ownerSet.iterator();
962:                        while (iter.hasNext()) {
963:                            LockInfo info = (LockInfo) iter.next();
964:                            sb.append(info);
965:                        }
966:                    }
967:                }
968:
969:                sb.append(" Waiters:");
970:                if (nWaiters() == 0) {
971:                    sb.append(" (none)");
972:                } else {
973:                    sb.append(getWaitersListClone());
974:                }
975:                return sb.toString();
976:            }
977:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.