KickJava   Java API By Example, From Geeks To Geeks.

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


1 /* DatabaseLockMaster.java */
2
3 package org.enhydra.shark.processlocking;
4
5 import java.util.*;
6
7 import com.lutris.appserver.server.sql.DBTransaction;
8 import com.lutris.appserver.server.sql.DatabaseManagerException;
9 import com.lutris.appserver.server.sql.LogicalDatabase;
10 import org.enhydra.dods.DODS;
11 import org.enhydra.shark.api.RootError;
12 import org.enhydra.shark.api.RootException;
13 import org.enhydra.shark.api.SharkTransaction;
14 import org.enhydra.shark.api.internal.processlocking.LockMaster;
15 import org.enhydra.shark.api.internal.working.CallbackUtilities;
16 import org.enhydra.shark.processlocking.data.LockEntryDO;
17 import org.enhydra.shark.processlocking.data.LockEntryDelete;
18 import org.enhydra.shark.processlocking.data.LockEntryQuery;
19 import org.enhydra.shark.utilities.dods.DODSUtilities;
20
21 /**
22  * DODSLockMaster is special implementation of Shark's LockMaster, which
23  * uses database (actually DODS accessed DB) as a lock repository, whereas
24  * simple lock master has only Vector in memory.
25  * <p>
26  * DODSLockMaster completely circumvents Shark's persistence layer, communicating
27  * directly to DODS classes, to store and delete lock entries in database.
28  *
29  * @author Vladimir Puskas
30  * @version 0.2
31  */

32 public class DODSLockMaster implements LockMaster {
33
34    private static final String JavaDoc ENG_PARAM_NAME = "enginename";
35    private static final String JavaDoc TOUT_PARM_NAME = "DODSLockMaster.Timeout";
36    private static final String JavaDoc LWT_PARAM_NAME = "DODSLockMaster.LockWaitTime";
37    private static final String JavaDoc DBG_PARAM_NAME = "DODSLockMaster.debug";
38    private static final String JavaDoc LDB_PARAM_NAME = "DODSLockMaster.DatabaseName";
39
40    private Long JavaDoc defaultTimeout;
41    private long lockWaitTime;
42    private CallbackUtilities callback;
43    private LogicalDatabase db;
44    private Map locks;
45    private String JavaDoc lockMasterName;
46    private boolean cleanStarted;
47    private boolean _debug_;
48
49    /**
50     * Default constructor
51     */

52    public DODSLockMaster() {
53       locks = new HashMap();
54       defaultTimeout = null;
55       cleanStarted = false;
56    }
57
58    /**
59     * Configures instance of LockMaster implementaition, setting its
60     * name and default timeout.
61     *
62     * @param cbImpl a CallbackUtilities
63     *
64     * @exception RootException
65     */

66    public void configure(CallbackUtilities cbImpl) throws RootException {
67       if (null == cbImpl)
68          throw new RootException("Cannot configure without call back impl.");
69       callback = cbImpl;
70       DODSUtilities.init(callback.getProperties());
71       if (LockEntryDO
72              .getConfigurationAdministration()
73              .getCacheAdministration(0)
74              .getMaxCacheSize() > 0) {
75          callback.error("cache for lock entries isn't allowed!!!");
76          throw new RootError("cache for lock entries isn't allowed!!!");
77       }
78       lockMasterName = callback.getProperty(ENG_PARAM_NAME,"dodsLockMaster");
79       defaultTimeout = new Long JavaDoc(callback.getProperty(TOUT_PARM_NAME, "-1"));
80       lockWaitTime = Long.parseLong(callback.getProperty(LWT_PARAM_NAME,"100"));
81       String JavaDoc dbName = callback
82          .getProperty(LDB_PARAM_NAME, DODS.getDatabaseManager().getDefaultDB());
83       _debug_ = Boolean
84          .valueOf(callback.getProperty(DBG_PARAM_NAME, "false"))
85          .booleanValue();
86       try {
87          db = DODS.getDatabaseManager().findLogicalDatabase(dbName);
88       } catch (DatabaseManagerException e) {
89          throw new RootException("Couldn't find logical database.", e);
90       }
91       if (!cleanStarted) {
92          _cleanAllLocks();
93          cleanStarted = true;
94       }
95       callback.debug(new StringBuffer JavaDoc(lockMasterName)
96                         .append(" startup, timeout is ")
97                         .append(defaultTimeout)
98                         .toString());
99    }
100
101    /**
102     * Method lock ensures that nobody else (other threads) has same processId.
103     * This method may wait a while before acquiring lock requested.
104     * Implementation may set a timeout to limit the time spent waiting.
105     *
106     * @param t - SharkTransaction during wich lock is required
107     * @param processId - lock identifier
108     * @param timeout - limits waiting for this specific lock:
109     * value < 0 means wait forever
110     * value >= 0 specifies number of miliseconds
111     * null value means use default
112     * @return true if lock is acquired without waiting, false otherwise
113     * @exception RootException gets thrown if timeout expires
114     */

115    public boolean lock(SharkTransaction t,
116                        String JavaDoc processId,
117                        Long JavaDoc timeout) throws RootException {
118       boolean ret = true;
119       if (null != processId) {
120          if (null == timeout)
121             timeout = defaultTimeout;
122          long limit = timeout.longValue();
123          boolean checkTimeout = 0 < limit;
124          limit += System.currentTimeMillis();
125
126          while (hasLock(processId)) {
127             ret = false;
128             try {
129                Thread.sleep(lockWaitTime);
130             } catch (Exception JavaDoc e) {}
131             if (checkTimeout && (System.currentTimeMillis() > limit)) {
132                RootException tme = new RootException
133                   (new StringBuffer JavaDoc("Timeout expired waiting on ")
134                       .append(processId)
135                       .toString());
136                callback.error("DODSLockMaster", tme);
137                throw tme;
138             }
139          }
140       }
141       if (_debug_) System.err.println("LOCK:"+processId+":"+t);
142       return ret;
143    }
144
145    /**
146     * Method lock ensures that nobody else (other threads) has same processId.
147     * This method may wait a while before acquiring lock requested.
148     *
149     * @param processId lock identifier
150     * @return true if lock is acquired without waiting, false otherwise
151     * @exception TransactionMgrException
152     */

153    public boolean lock(SharkTransaction t,
154                        String JavaDoc processId) throws RootException {
155       return lock(t, processId, null);
156    }
157
158    /**
159     * @param processId
160     * @throws TransactionMgrException
161     */

162    public void unlock(SharkTransaction t,
163                       String JavaDoc processId) throws RootException {
164       if (null != processId) {
165          removeLock(processId);
166          if (_debug_) System.err.println("UNLOCK:"+processId+":"+t);
167       }
168    }
169
170    /**
171     * Method unlock releases all locks SharkTransaction had acquired.
172     *
173     * @param t - SharkTransaction during which locks had been obtained.
174     * @exception RootException
175     */

176    public synchronized void unlock(SharkTransaction t) throws RootException {
177       List processLocks = retrieveLocks();
178       if (null == processLocks) {
179          throw new RootException("Transaction hasn't locked anything");
180       }
181       DBTransaction dbt = createTransaction();
182       try {
183          for (Iterator it = processLocks.iterator(); it.hasNext();) {
184             String JavaDoc processId = (String JavaDoc)it.next();
185             LockEntryQuery qry = new LockEntryQuery(dbt);
186             qry.setQueryEngineName(lockMasterName);
187             qry.setQueryId(processId);
188             //qry.requireUniqueInstance();
189
LockEntryDelete led = new LockEntryDelete(qry);
190             led.save();
191             //qry.getNextDO().delete();
192
locks.remove(processId);
193             if (_debug_) System.err.println("gUNLOCK:"+processId+":"+t);
194          }
195          dbt.commit();
196       } catch (Exception JavaDoc e) {
197          throw new RootException(e);
198       } finally {
199          dbt.release();
200       }
201    }
202
203    /**
204     * Gets locks for the SharkTransaction.
205     *
206     * @param t - SharkTransaction during which lock is required
207     * @return a List of processIds SharkTransaction had previously obtained.
208     * @exception RootException
209     */

210    public List getLocks(SharkTransaction t) throws RootException {
211       List transactionLocks = retrieveLocks();
212       if (null == transactionLocks)
213          throw new RootException("Transaction hasn't locked anything");
214       return transactionLocks;
215    }
216
217    /***/
218    private List retrieveLocks() {
219       List ret = new ArrayList();
220       Set entries = locks.entrySet();
221       Thread JavaDoc th = Thread.currentThread();
222       for (Iterator it = entries.iterator(); it.hasNext();) {
223          Map.Entry me = (Map.Entry)it.next();
224          if (th.equals(me.getValue())) {
225             ret.add(me.getKey());
226          }
227       }
228       return ret;
229    }
230
231    /***/
232    private synchronized boolean hasLock(String JavaDoc processId) throws RootException {
233       Thread JavaDoc lockOwner = (Thread JavaDoc)locks.get(processId);
234       if (null == lockOwner) {
235          DBTransaction dbt = createTransaction();
236          try {
237             LockEntryDO le = LockEntryDO.createVirgin(dbt);
238             le.setEngineName(lockMasterName);
239             le.setId(processId);
240             le.save();
241             dbt.commit();
242          } catch (Exception JavaDoc e) {
243             return true;
244          } finally {
245             dbt.release();
246          }
247          locks.put(processId, Thread.currentThread());
248          return false;
249       } else if (lockOwner.equals(Thread.currentThread())) {
250          return false;
251       } else {
252          return true;
253       }
254       /**/
255    }
256
257    /***/
258    private synchronized void removeLock(String JavaDoc processId) throws RootException {
259       Thread JavaDoc lockOwner = (Thread JavaDoc)locks.get(processId);
260       if (Thread.currentThread().equals(lockOwner)) {
261          DBTransaction dbt = createTransaction();
262          try {
263             LockEntryQuery qry = new LockEntryQuery(dbt);
264             qry.setQueryEngineName(lockMasterName);
265             qry.setQueryId(processId);
266             qry.requireUniqueInstance();
267             LockEntryDO row = qry.getNextDO();
268             row.delete();
269             dbt.commit();
270          } catch (Exception JavaDoc e) {
271             throw new RootException(e);
272          } finally {
273             dbt.release();
274          }
275          locks.remove(processId);
276       } else {
277          RootException tme = new RootException
278             (new StringBuffer JavaDoc("Trying to unlock ")
279                 .append(processId)
280                 .append(" while it hasn't been locked ?!?")
281                 .toString());
282          callback.error("DODSLockMaster", tme);
283          throw tme;
284       }
285    }
286
287    /***/
288    private void _cleanAllLocks() throws RootException {
289       DBTransaction dbt = createTransaction();
290       try {
291          LockEntryQuery leqry = new LockEntryQuery(dbt);
292          leqry.setQueryEngineName(lockMasterName);
293          new LockEntryDelete(leqry).save();
294          dbt.commit();
295       } catch (Exception JavaDoc e) {
296          throw new RootException(e);
297       } finally {
298          dbt.release();
299       }
300    }
301
302    /***/
303    private DBTransaction createTransaction() throws RootException {
304       try {
305          return db.createTransaction();
306       } catch (Throwable JavaDoc t) {
307          throw new RootException
308             (new StringBuffer JavaDoc("Didn't create transaction, there are ")
309                 .append(db.getActiveConnectionCount())
310                 .append(" active connections.")
311                 .toString(), t);
312       }
313    }
314 }
315 /* End of DatabaseLockMaster.java */
316
317
Popular Tags