📄 stdrowlocksemaphore.java
字号:
/* * Copyright James House (c) 2001-2004 * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: 1. * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. 2. Redistributions in * binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */package org.quartz.impl.jdbcjobstore;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.HashSet;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * An interface for providing thread/resource locking in order to protect * resources from being altered by multiple threads at the same time. * * @author jhouse */public class StdRowLockSemaphore implements Semaphore, Constants, StdJDBCConstants { /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constants. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public static final String SELECT_FOR_LOCK = "SELECT * FROM " + TABLE_PREFIX_SUBST + TABLE_LOCKS + " WHERE " + COL_LOCK_NAME + " = ? FOR UPDATE"; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Data members. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ThreadLocal lockOwners = new ThreadLocal(); // java.util.HashMap threadLocksOb = new java.util.HashMap(); private String selectWithLockSQL = SELECT_FOR_LOCK; private String tablePrefix; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constructors. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public StdRowLockSemaphore(String tablePrefix, String selectWithLockSQL) { this.tablePrefix = tablePrefix; if (selectWithLockSQL != null && selectWithLockSQL.trim().length() != 0) this.selectWithLockSQL = selectWithLockSQL; this.selectWithLockSQL = Util.rtp(this.selectWithLockSQL, tablePrefix); } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ Log getLog() { return LogFactory.getLog(getClass()); //return LogFactory.getLog("LOCK:"+Thread.currentThread().getName()); } private HashSet getThreadLocks() { HashSet threadLocks = (HashSet) lockOwners.get(); if (threadLocks == null) { threadLocks = new HashSet(); lockOwners.set(threadLocks); } return threadLocks; } /** * Grants a lock on the identified resource to the calling thread (blocking * until it is available). * * @return true if the lock was obtained. */ public boolean obtainLock(Connection conn, String lockName) throws LockException { lockName = lockName.intern(); Log log = getLog(); if(log.isDebugEnabled()) log.debug( "Lock '" + lockName + "' is desired by: " + Thread.currentThread().getName()); if (!isLockOwner(conn, lockName)) { PreparedStatement ps = null; ResultSet rs = null; try { ps = conn.prepareStatement(selectWithLockSQL); ps.setString(1, lockName); if(log.isDebugEnabled()) log.debug( "Lock '" + lockName + "' is being obtained: " + Thread.currentThread().getName()); rs = ps.executeQuery(); if (!rs.next()) throw new SQLException(Util.rtp( "No row exists in table " + TABLE_PREFIX_SUBST + TABLE_LOCKS + " for lock named: " + lockName, tablePrefix)); } catch (SQLException sqle) { //Exception src = // (Exception)getThreadLocksObtainer().get(lockName); //if(src != null) // src.printStackTrace(); //else // System.err.println("--- ***************** NO OBTAINER!"); if(log.isDebugEnabled()) log.debug( "Lock '" + lockName + "' was not obtained by: " + Thread.currentThread().getName()); throw new LockException("Failure obtaining db row lock: " + sqle.getMessage(), sqle); } finally { if (rs != null) try { rs.close(); } catch (Exception ignore) { } if (ps != null) try { ps.close(); } catch (Exception ignore) { } } if(log.isDebugEnabled()) log.debug( "Lock '" + lockName + "' given to: " + Thread.currentThread().getName()); getThreadLocks().add(lockName); //getThreadLocksObtainer().put(lockName, new // Exception("Obtainer...")); } else if(log.isDebugEnabled()) log.debug( "Lock '" + lockName + "' Is already owned by: " + Thread.currentThread().getName()); return true; } /** * Release the lock on the identified resource if it is held by the calling * thread. */ public void releaseLock(Connection conn, String lockName) { lockName = lockName.intern(); if (isLockOwner(conn, lockName)) { if(getLog().isDebugEnabled()) getLog().debug( "Lock '" + lockName + "' retuned by: " + Thread.currentThread().getName()); getThreadLocks().remove(lockName); //getThreadLocksObtainer().remove(lockName); } else if(getLog().isDebugEnabled()) getLog().warn( "Lock '" + lockName + "' attempt to retun by: " + Thread.currentThread().getName() + " -- but not owner!", new Exception("stack-trace of wrongful returner")); } /** * Determine whether the calling thread owns a lock on the identified * resource. */ public boolean isLockOwner(Connection conn, String lockName) { lockName = lockName.intern(); return getThreadLocks().contains(lockName); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -