1 4 5 package org.enhydra.shark.processlocking; 6 7 import java.util.ArrayList ; 8 import java.util.HashMap ; 9 import java.util.Iterator ; 10 import java.util.List ; 11 import java.util.Map ; 12 import java.util.Set ; 13 14 import net.sf.hibernate.HibernateException; 15 import net.sf.hibernate.Query; 16 import net.sf.hibernate.Session; 17 import net.sf.hibernate.Transaction; 18 19 import org.enhydra.shark.api.RootException; 20 import org.enhydra.shark.api.SharkTransaction; 21 import org.enhydra.shark.api.TransactionException; 22 import org.enhydra.shark.api.internal.processlocking.LockMaster; 23 import org.enhydra.shark.api.internal.working.CallbackUtilities; 24 25 36 public class HibernateLockMaster implements LockMaster { 37 38 private static final String ENG_PARAM_NAME = "enginename"; 39 private static final String TOUT_PARM_NAME = "HibernateLockMaster.Timeout"; 40 private static final String LWT_PARAM_NAME = "HibernateLockMaster.LockWaitTime"; 41 private static final String DBG_PARAM_NAME = "HibernateLockMaster.debug"; 42 private static final String LDB_PARAM_NAME = "HibernateLockMaster.DatabaseName"; 43 44 private Long defaultTimeout; 45 private long lockWaitTime; 46 private CallbackUtilities callback; 47 private Map locks; 48 private String lockMasterName; 49 private boolean cleanStarted; 50 private boolean _debug_; 51 52 55 public HibernateLockMaster() { 56 locks = new HashMap (); 57 defaultTimeout = null; 58 cleanStarted = false; 59 } 60 61 69 public void configure(CallbackUtilities cbImpl) throws RootException { 70 if (null == cbImpl) 71 throw new RootException("Cannot configure without call back impl."); 72 callback = cbImpl; 73 82 lockMasterName = callback.getProperty(ENG_PARAM_NAME,"hibernateLockMaster"); 83 defaultTimeout = new Long (callback.getProperty(TOUT_PARM_NAME, "-1")); 84 lockWaitTime = Long.parseLong(callback.getProperty(LWT_PARAM_NAME,"100")); 85 _debug_ = Boolean 86 .valueOf(callback.getProperty(DBG_PARAM_NAME, "false")) 87 .booleanValue(); 88 if (!cleanStarted) { 89 _cleanAllLocks(); 90 cleanStarted = true; 91 } 92 callback.debug(new StringBuffer (lockMasterName) 93 .append(" startup, timeout is ") 94 .append(defaultTimeout) 95 .toString()); 96 } 97 98 112 public boolean lock(SharkTransaction t, 113 String processId, 114 Long timeout) throws RootException { 115 boolean ret = true; 116 if (null != processId) { 117 if (null == timeout) 118 timeout = defaultTimeout; 119 long limit = timeout.longValue(); 120 boolean checkTimeout = 0 < limit; 121 limit += System.currentTimeMillis(); 122 try { 123 while (hasLock(processId)) { 124 ret = false; 125 try { 126 Thread.sleep(lockWaitTime); 127 } catch (Exception e) {} 128 if (checkTimeout && (System.currentTimeMillis() > limit)) { 129 RootException tme = new RootException 130 (new StringBuffer ("Timeout expired waiting on ") 131 .append(processId) 132 .toString()); 133 callback.error("SimpleLockMaster", tme); 134 throw tme; 135 } 136 } 137 } catch (HibernateException e) { 138 e.printStackTrace(); 139 throw new TransactionException(e); 140 } catch (RootException e) { 141 e.printStackTrace(); 142 throw new RootException(e); 143 } 144 } 145 if (_debug_) System.err.println("LOCK:"+processId+":"+t); 146 return ret; 147 } 148 149 157 public boolean lock(SharkTransaction t, 158 String processId) throws RootException { 159 return lock(t, processId, null); 160 } 161 162 166 public void unlock(SharkTransaction t, 167 String processId) throws RootException { 168 if (null != processId) { 169 try { 170 removeLock(processId); 171 if (_debug_) System.err.println("UNLOCK:"+processId+":"+t); 172 } catch (Exception e) { 173 e.printStackTrace(); 174 throw new RootException(e); 175 } 176 } 177 } 178 179 private HibernateLockEntry getLockEntry(String processIdParam, String lockMasterNameParam, Session s) throws RootException { 180 try{ 181 Query qLockEntry = s.createQuery( 182 "from HibernateLockEntry lockEntry where lockEntry.id = :keyValueParam_1 and " + 183 "lockEntry.engineName = :keyValueParam_2"); 184 qLockEntry.setString("keyValueParam_1", processIdParam); 185 qLockEntry.setString("keyValueParam_2", lockMasterNameParam); 186 HibernateLockEntry le = (HibernateLockEntry) qLockEntry.uniqueResult(); 187 return (le != null)?le:null; 188 }catch (Exception e) { 189 e.printStackTrace(); 190 throw new RootException(e); 191 } 192 } 193 194 200 public synchronized void unlock(SharkTransaction t) throws RootException { 201 List processLocks = retrieveLocks(); 202 Session session = null; 203 Transaction tr = null; 204 if (null == processLocks) { 205 throw new RootException("Transaction hasn't locked anything"); 206 } 207 try { 208 session = ThreadLocalSession.currentSession(); 209 tr = session.beginTransaction(); 210 for (Iterator it = processLocks.iterator(); it.hasNext();) { 211 String processId = (String )it.next(); 212 session.delete(getLockEntry(processId,lockMasterName,session)); 213 locks.remove(processId); 214 if (_debug_) System.err.println("gUNLOCK:"+processId+":"+t); 215 } 216 tr.commit(); 217 session.clear(); 219 session.close(); 220 } catch (Exception e) { 221 throw new RootException(e); 222 } finally { 223 tr = null; 224 } 225 } 226 227 234 public List getLocks(SharkTransaction t) throws RootException { 235 List transactionLocks = retrieveLocks(); 236 if (null == transactionLocks) 237 throw new RootException("Transaction hasn't locked anything"); 238 return transactionLocks; 239 } 240 241 242 private List retrieveLocks() { 243 List ret = new ArrayList (); 244 Set entries = locks.entrySet(); 245 Thread th = Thread.currentThread(); 246 for (Iterator it = entries.iterator(); it.hasNext();) { 247 Map.Entry me = (Map.Entry )it.next(); 248 if (th.equals(me.getValue())) { 249 ret.add(me.getKey()); 250 } 251 } 252 return ret; 253 } 254 255 private synchronized boolean hasLock(String processId) throws RootException, HibernateException { 256 Thread lockOwner = (Thread )locks.get(processId); 257 Session session = null; 258 Transaction t; 259 if (null == lockOwner) { 260 try { 261 session = ThreadLocalSession.currentSession(); 262 t = session.beginTransaction(); 263 264 HibernateLockEntry le = createLockEntry(); 265 le.setEngineName(lockMasterName); 266 le.setId(processId); 267 268 session.save(le); 269 t.commit(); 270 session.clear(); 273 session.close(); 274 } catch (Exception e) { 275 return true; 276 } finally { 277 t = null; 278 } 279 locks.put(processId, Thread.currentThread()); 280 return false; 281 } else if (lockOwner.equals(Thread.currentThread())) { 282 return false; 283 } else { 284 return true; 285 } 286 } 287 288 289 private synchronized void removeLock(String processId) throws RootException { 290 Thread lockOwner = (Thread )locks.get(processId); 291 Session session = null; 292 Transaction t = null; 293 if (Thread.currentThread().equals(lockOwner)) { 294 try { 295 session = ThreadLocalSession.currentSession(); 296 t = session.beginTransaction(); 297 HibernateLockEntry lo = getLockEntry(processId,lockMasterName,session); 298 if (lo != null) session.delete(lo); 299 300 t.commit(); 301 session.clear(); 303 session.close(); 304 } catch (Exception e) { 305 throw new RootException(e); 306 } finally { 307 t = null; 308 } 309 locks.remove(processId); 310 } else { 311 RootException tme = new RootException 312 (new StringBuffer ("Trying to unlock ") 313 .append(processId) 314 .append(" while it hasn't been locked ?!?") 315 .toString()); 316 callback.error("SimpleLockMaster", tme); 317 throw tme; 318 } 319 } 320 321 322 private void _cleanAllLocks() throws RootException { 323 Session session = null; 324 Transaction t; 325 try { 326 session = ThreadLocalSession.currentSession(); 327 t = session.beginTransaction(); 328 329 List lockEntries = getAllLockEntry(lockMasterName,session); 330 if (lockEntries.size() != 0){ 331 for (Iterator it = lockEntries.iterator(); it.hasNext();) { 332 session.delete((HibernateLockEntry)it.next()); 333 } 334 } 335 336 t.commit(); 337 session.clear(); 339 session.close(); 340 } catch (Exception e) { 341 e.printStackTrace(); 342 throw new RootException(e); 343 } finally { 344 t =null; 345 } 346 } 347 348 private List getAllLockEntry(String lockMasterName, Session s) throws RootException { 349 try{ 350 Query qLockEntry = s.createQuery( 351 "from HibernateLockEntry lockEntry where lockEntry.engineName = :keyValueParam"); 352 qLockEntry.setString("keyValueParam", lockMasterName); 353 return qLockEntry.list(); 354 }catch (Exception e) { 355 e.printStackTrace(); 356 throw new RootException(e); 357 } 358 } 359 360 private HibernateLockEntry createLockEntry(){ 361 return new HibernateLockEntry(); 362 } 363 364 } 365 | Popular Tags |