01: /*-
02: * See the file LICENSE for redistribution information.
03: *
04: * Copyright (c) 2002,2008 Oracle. All rights reserved.
05: *
06: * $Id: BuddyLocker.java,v 1.7.2.2 2008/01/07 15:14:17 cwl Exp $
07: */
08:
09: package com.sleepycat.je.txn;
10:
11: import com.sleepycat.je.DatabaseException;
12: import com.sleepycat.je.dbi.EnvironmentImpl;
13:
14: /**
15: * Extends BasicLocker to share locks with another specific locker.
16: *
17: * <p>In general, a BuddyLocker can be used whenever the primary (API) locker
18: * is in use, and we need to lock a node and release that lock before the
19: * primary locker transaction ends. In other words, for this particular lock
20: * we don't want to use two-phase locking. To accomplish that we use a
21: * separate BuddyLocker instance to hold the lock, while sharing locks with the
22: * primary locker. The BuddyLocker can be closed to release this particular
23: * lock, without releasing the other locks held by the primary locker.</p>
24: *
25: * <p>In particular, a BuddyLocker is used when acquiring a RANGE_INSERT lock.
26: * RANGE_INSERT only needs to be held until the point we have inserted the new
27: * node into the BIN. A separate locker is therefore used so we can release
28: * that lock separately when the insertion into the BIN is complete. But the
29: * RANGE_INSERT lock must not conflict with locks held by the primary locker.
30: * So a BuddyLocker is used that shares locks with the primary locker.</p>
31: */
32: public class BuddyLocker extends BasicLocker {
33:
34: private Locker buddy;
35:
36: /**
37: * Creates a BuddyLocker.
38: */
39: public BuddyLocker(EnvironmentImpl env, Locker buddy)
40: throws DatabaseException {
41:
42: super (env);
43: this .buddy = buddy;
44: }
45:
46: /**
47: * Returns the buddy locker.
48: */
49: Locker getBuddy() {
50: return buddy;
51: }
52:
53: /**
54: * Forwards this call to the buddy locker.
55: */
56: public Txn getTxnLocker() {
57: return buddy.getTxnLocker();
58: }
59:
60: /**
61: * Creates a new instance of this txn for the same environment. No
62: * transactional locks are held by this object, so no locks are retained.
63: * newNonTxnLocker is also called for the BuddyLocker.
64: */
65: public Locker newNonTxnLocker() throws DatabaseException {
66:
67: return new BuddyLocker(envImpl, buddy.newNonTxnLocker());
68: }
69:
70: /**
71: * Forwards this call to the base class and to the buddy locker.
72: */
73: public void releaseNonTxnLocks() throws DatabaseException {
74:
75: super .releaseNonTxnLocks();
76: buddy.releaseNonTxnLocks();
77: }
78:
79: /**
80: * Returns whether this locker can share locks with the given locker.
81: */
82: public boolean sharesLocksWith(Locker other) {
83:
84: if (super .sharesLocksWith(other)) {
85: return true;
86: } else {
87: return buddy == other;
88: }
89: }
90: }
|