KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > shark > processlocking > SimpleLockMaster


1 /* SimpleLockMaster.java */
2
3 package org.enhydra.shark.processlocking;
4
5 import java.util.*;
6
7 import org.enhydra.shark.api.RootException;
8 import org.enhydra.shark.api.SharkTransaction;
9 import org.enhydra.shark.api.internal.processlocking.LockMaster;
10 import org.enhydra.shark.api.internal.working.CallbackUtilities;
11
12
13 /**
14  * This LockMaster implementation is good only for one virtual machine
15  * running Shark.
16  *
17  * @author Vladimir Puskas
18  * @version 0.3
19  */

20 public class SimpleLockMaster implements LockMaster {
21
22    private static final String JavaDoc ENG_PARAM_NAME = "enginename";
23    private static final String JavaDoc TOUT_PARM_NAME = "SimpleLockMaster.Timeout";
24    private static final String JavaDoc LWT_PARAM_NAME = "SimpleLockMaster.LockWaitTime";
25
26    private Long JavaDoc defaultTimeout;
27    private Map locks;
28    private long lockWaitTime;
29    private CallbackUtilities callback;
30
31    /**
32     * Default constructor
33     */

34    public SimpleLockMaster() {
35       locks = new HashMap();
36       defaultTimeout = null;
37    }
38
39    /**
40     * Configures instance of LockMaster implementaition, setting its
41     * name and default timeout.
42     *
43     * @param cbImpl a CallbackUtilities
44     *
45     * @exception RootException
46     */

47    public void configure(CallbackUtilities cbImpl) throws RootException {
48       if (null == cbImpl)
49          throw new RootException("Cannot configure without call back impl.");
50       callback = cbImpl;
51       String JavaDoc lockMasterName = callback.getProperty(ENG_PARAM_NAME,"simpleLockMaster");
52       defaultTimeout = new Long JavaDoc(callback.getProperty(TOUT_PARM_NAME, "-1"));
53       lockWaitTime = Long.parseLong(callback.getProperty(LWT_PARAM_NAME,"100"));
54       callback.debug(new StringBuffer JavaDoc(lockMasterName)
55                         .append(" startup, timeout is ")
56                         .append(defaultTimeout)
57                         .toString());
58    }
59
60    /**
61     * Method lock ensures that nobody else (other threads) has same processId.
62     * This method may wait a while before acquiring lock requested.
63     * Implementation may set a timeout to limit the time spent waiting.
64     *
65     * @param t - SharkTransaction during wich lock is required
66     * @param processId - lock identifier
67     * @param timeout - limits waiting for this specific lock:
68     * value < 0 means wait forever
69     * value >= 0 specifies number of miliseconds
70     * null value means use default
71     * @return true if lock is acquired without waiting, false otherwise
72     * @exception RootException gets thrown if timeout expires
73     */

74    public boolean lock(SharkTransaction t,
75                        String JavaDoc processId,
76                        Long JavaDoc timeout) throws RootException {
77       boolean ret = true;
78       if (null != processId) {
79          if (null == timeout)
80             timeout = defaultTimeout;
81          long limit = timeout.longValue();
82          boolean checkTimeout = 0 < limit;
83          limit += System.currentTimeMillis();
84
85          while (hasLock(processId)) {
86             ret = false;
87             try {
88                Thread.sleep(lockWaitTime);
89             } catch (Exception JavaDoc e) {}
90             if (checkTimeout && (System.currentTimeMillis() > limit)) {
91                RootException tme = new RootException
92                   (new StringBuffer JavaDoc("Timeout expired waiting on ")
93                       .append(processId)
94                       .toString());
95                callback.error("SimpleLockMaster", tme);
96                throw tme;
97             }
98          }
99       }
100       return ret;
101    }
102
103    /**
104     * Method lock ensures that nobody else (other threads) has same processId.
105     * This method may wait a while before acquiring lock requested.
106     *
107     * @param processId lock identifier
108     * @return true if lock is acquired without waiting, false otherwise
109     * @exception TransactionMgrException
110     */

111    public boolean lock(SharkTransaction t,
112                        String JavaDoc processId) throws RootException {
113       return lock(t, processId, null);
114    }
115
116    /**
117     * @param processId
118     * @throws TransactionMgrException
119     */

120    public void unlock(SharkTransaction t,
121                       String JavaDoc processId) throws RootException {
122       if (null != processId) {
123          removeLock(processId);
124       }
125    }
126
127    /**
128     * Method unlock releases all locks SharkTransaction had acquired.
129     *
130     * @param t - SharkTransaction during which locks had been obtained.
131     * @exception RootException
132     */

133    public synchronized void unlock(SharkTransaction t) throws RootException {
134       List processLocks = retrieveLocks();
135       if (null == processLocks) {
136          throw new RootException("Transaction hasn't locked anything");
137       }
138       for (Iterator it = processLocks.iterator(); it.hasNext();) {
139          locks.remove(it.next());
140       }
141    }
142
143    /**
144     * Gets locks for the SharkTransaction.
145     *
146     * @param t - SharkTransaction during which lock is required
147     * @return a List of processIds SharkTransaction had previously obtained.
148     * @exception RootException
149     */

150    public List getLocks(SharkTransaction t) throws RootException {
151       List transactionLocks = retrieveLocks();
152       if (null == transactionLocks)
153          throw new RootException("Transaction hasn't locked anything");
154       return transactionLocks;
155    }
156
157    /***/
158    private synchronized List retrieveLocks() {
159       List ret = new ArrayList();
160       Set entries = locks.entrySet();
161       Thread JavaDoc th = Thread.currentThread();
162       for (Iterator it = entries.iterator(); it.hasNext();) {
163          Map.Entry me = (Map.Entry)it.next();
164          if (th.equals(me.getValue())) {
165             ret.add(me.getKey());
166          }
167       }
168       return ret;
169    }
170
171    /***/
172    private synchronized boolean hasLock(String JavaDoc processId) {
173       Thread JavaDoc lockOwner = (Thread JavaDoc)locks.get(processId);
174       if (null == lockOwner) {
175          locks.put(processId, Thread.currentThread());
176          return false;
177       } else if (lockOwner.equals(Thread.currentThread())) {
178          return false;
179       } else {
180          return true;
181       }
182    }
183
184    /***/
185    private synchronized void removeLock(String JavaDoc processId) throws RootException {
186       Thread JavaDoc lockOwner = (Thread JavaDoc)locks.get(processId);
187       if (Thread.currentThread().equals(lockOwner)) {
188          locks.remove(processId);
189       } else {
190          RootException tme = new RootException
191             (new StringBuffer JavaDoc("Trying to unlock ")
192                 .append(processId)
193                 .append(" while it hasn't been locked ?!?")
194                 .toString());
195          callback.error("SimpleLockMaster", tme);
196          throw tme;
197       }
198    }
199    synchronized void info() {
200       System.err.print(locks.size()+" locks ");
201    }
202 }
203 /* End of SimpleLockMaster.java */
204
Popular Tags