KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > quartz > impl > jdbcjobstore > DBSemaphore


1 /*
2  * Copyright 2004-2006 OpenSymphony
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy
6  * of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  *
16  */

17 package org.quartz.impl.jdbcjobstore;
18
19 import java.sql.Connection JavaDoc;
20 import java.util.HashSet JavaDoc;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 /**
26  * Base class for database based lock handlers for providing thread/resource locking
27  * in order to protect resources from being altered by multiple threads at the
28  * same time.
29  */

30 public abstract class DBSemaphore implements Semaphore, Constants,
31     StdJDBCConstants, TablePrefixAware {
32
33     private final Log log = LogFactory.getLog(getClass());
34
35     /*
36      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37      *
38      * Data members.
39      *
40      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
41      */

42
43     ThreadLocal JavaDoc lockOwners = new ThreadLocal JavaDoc();
44
45     private String JavaDoc sql;
46
47     private String JavaDoc tablePrefix;
48     
49     private String JavaDoc expandedSQL;
50
51     /*
52      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53      *
54      * Constructors.
55      *
56      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
57      */

58
59     public DBSemaphore(String JavaDoc tablePrefix, String JavaDoc sql, String JavaDoc defaultSQL) {
60         this.sql = defaultSQL;
61         this.tablePrefix = tablePrefix;
62         setSQL(sql);
63     }
64
65     /*
66      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67      *
68      * Interface.
69      *
70      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
71      */

72
73     protected Log getLog() {
74         return log;
75     }
76
77     private HashSet JavaDoc getThreadLocks() {
78         HashSet JavaDoc threadLocks = (HashSet JavaDoc) lockOwners.get();
79         if (threadLocks == null) {
80             threadLocks = new HashSet JavaDoc();
81             lockOwners.set(threadLocks);
82         }
83         return threadLocks;
84     }
85
86     /**
87      * Execute the SQL that will lock the proper database row.
88      */

89     protected abstract void executeSQL(
90         Connection JavaDoc conn, String JavaDoc lockName, String JavaDoc expandedSQL) throws LockException;
91     
92     /**
93      * Grants a lock on the identified resource to the calling thread (blocking
94      * until it is available).
95      *
96      * @return true if the lock was obtained.
97      */

98     public boolean obtainLock(Connection JavaDoc conn, String JavaDoc lockName)
99         throws LockException {
100
101         lockName = lockName.intern();
102
103         Log log = getLog();
104         
105         if(log.isDebugEnabled()) {
106             log.debug(
107                 "Lock '" + lockName + "' is desired by: "
108                         + Thread.currentThread().getName());
109         }
110         if (!isLockOwner(conn, lockName)) {
111
112             executeSQL(conn, lockName, expandedSQL);
113             
114             if(log.isDebugEnabled()) {
115                 log.debug(
116                     "Lock '" + lockName + "' given to: "
117                             + Thread.currentThread().getName());
118             }
119             getThreadLocks().add(lockName);
120             //getThreadLocksObtainer().put(lockName, new
121
// Exception("Obtainer..."));
122
} else if(log.isDebugEnabled()) {
123             log.debug(
124                 "Lock '" + lockName + "' Is already owned by: "
125                         + Thread.currentThread().getName());
126         }
127
128         return true;
129     }
130
131        
132     /**
133      * Release the lock on the identified resource if it is held by the calling
134      * thread.
135      */

136     public void releaseLock(Connection JavaDoc conn, String JavaDoc lockName) {
137
138         lockName = lockName.intern();
139
140         if (isLockOwner(conn, lockName)) {
141             if(getLog().isDebugEnabled()) {
142                 getLog().debug(
143                     "Lock '" + lockName + "' returned by: "
144                             + Thread.currentThread().getName());
145             }
146             getThreadLocks().remove(lockName);
147             //getThreadLocksObtainer().remove(lockName);
148
} else if (getLog().isDebugEnabled()) {
149             getLog().warn(
150                 "Lock '" + lockName + "' attempt to return by: "
151                         + Thread.currentThread().getName()
152                         + " -- but not owner!",
153                 new Exception JavaDoc("stack-trace of wrongful returner"));
154         }
155     }
156
157     /**
158      * Determine whether the calling thread owns a lock on the identified
159      * resource.
160      */

161     public boolean isLockOwner(Connection JavaDoc conn, String JavaDoc lockName) {
162         lockName = lockName.intern();
163
164         return getThreadLocks().contains(lockName);
165     }
166
167     /**
168      * This Semaphore implementation does use the database.
169      */

170     public boolean requiresConnection() {
171         return true;
172     }
173
174     protected String JavaDoc getSQL() {
175         return sql;
176     }
177
178     protected void setSQL(String JavaDoc sql) {
179         if ((sql != null) && (sql.trim().length() != 0)) {
180             this.sql = sql;
181         }
182         
183         setExpandedSQL();
184     }
185
186     private void setExpandedSQL() {
187         if (getTablePrefix() != null) {
188             expandedSQL = Util.rtp(this.sql, getTablePrefix());
189         }
190     }
191     
192     protected String JavaDoc getTablePrefix() {
193         return tablePrefix;
194     }
195
196     public void setTablePrefix(String JavaDoc tablePrefix) {
197         this.tablePrefix = tablePrefix;
198         
199         setExpandedSQL();
200     }
201 }
202
Popular Tags