1 29 30 package com.caucho.db.store; 31 32 import com.caucho.log.Log; 33 import com.caucho.util.Alarm; 34 import com.caucho.util.L10N; 35 36 import java.sql.SQLException ; 37 import java.util.logging.Level ; 38 import java.util.logging.Logger ; 39 40 43 public final class Lock { 44 private final static L10N L = new L10N(Lock.class); 45 private final static Logger log = Log.open(Lock.class); 46 47 private final String _id; 48 49 private int _tryUpgradeCount; 51 private int _tryWriteCount; 53 54 private int _readCount; 56 private boolean _isWrite; 58 59 private Thread _owner; 60 61 public Lock(String id) 62 { 63 _id = id; 64 } 65 66 69 public String getId() 70 { 71 return _id; 72 } 73 74 79 void lockRead(Transaction xa, long timeout) 80 throws LockTimeoutException 81 { 82 if (log.isLoggable(Level.FINEST)) { 83 log.finest(this + " lockRead (read:" + _readCount 84 + " write:" + _isWrite 85 + " try-write:" + _tryWriteCount + ")"); 86 } 87 88 long start = Alarm.getCurrentTime(); 89 long expire = start + timeout; 90 91 synchronized (this) { 92 long now; 93 94 while (true) { 95 if (! _isWrite && _tryWriteCount == 0) { 96 _readCount++; 97 return; 98 } 99 100 long delta = expire - Alarm.getCurrentTime(); 101 102 if (delta < 0 || Alarm.isTest()) 103 break; 104 105 try { 106 wait(delta); 107 } catch (InterruptedException e) { 108 throw new LockTimeoutException(e); 109 } 110 } 111 112 if (! Alarm.isTest()) { 113 printOwnerStack(); 114 Thread.dumpStack(); 115 } 116 117 throw new LockTimeoutException(L.l("Lock {0} timed out ({1}ms) try-writers:{2} is-write:{3}", 118 this, 119 Alarm.getCurrentTime() - start, 120 _tryWriteCount, 121 _isWrite)); 122 } 123 } 124 125 128 void unlockRead() 129 throws SQLException 130 { 131 synchronized (this) { 132 _readCount--; 133 134 if (_readCount < 0) 135 Thread.dumpStack(); 136 137 if (log.isLoggable(Level.FINEST)) { 138 log.finest(this + " unlockRead (read:" + _readCount 139 + " write:" + _isWrite 140 + " try-write:" + _tryWriteCount + ")"); 141 } 142 143 notifyAll(); 144 } 145 } 146 147 152 void lockReadAndWrite(Transaction xa, long timeout) 153 throws SQLException 154 { 155 if (log.isLoggable(Level.FINEST)) { 156 log.finest(this + " lockReadAndWrite (read:" + _readCount 157 + " write:" + _isWrite 158 + " try-write:" + _tryWriteCount + ")"); 159 } 160 161 long start = Alarm.getCurrentTime(); 162 long expire = start + timeout; 163 boolean isOkay = false; 164 165 synchronized (this) { 166 _tryWriteCount++; 167 168 if (_owner == null) 170 _owner = Thread.currentThread(); 171 172 try { 173 while (true) { 174 if (! _isWrite && _readCount == _tryUpgradeCount) { 175 _readCount++; 176 _isWrite = true; 177 _owner = Thread.currentThread(); 178 return; 179 } 180 181 long delta = expire - Alarm.getCurrentTime(); 182 183 if (delta < 0 || Alarm.isTest()) 184 break; 185 186 try { 187 wait(delta); 188 } catch (InterruptedException e) { 189 throw new LockTimeoutException(e); 190 } 191 } 192 193 if (! Alarm.isTest()) { 194 printOwnerStack(); 195 Thread.dumpStack(); 196 } 197 198 throw new LockTimeoutException(L.l("{0} lockReadAndWrite timed out ({1}ms) is-write:{2} try-writers:{3} try-upgrade:{4}", 199 this, 200 (Alarm.getCurrentTime() - start), 201 _isWrite, 202 _tryWriteCount, 203 _tryUpgradeCount)); 204 } finally { 205 _tryWriteCount--; 206 207 notifyAll(); 208 } 209 } 210 } 211 212 217 void lockWrite(Transaction xa, long timeout) 218 throws SQLException 219 { 220 if (log.isLoggable(Level.FINEST)) { 221 log.finest(this + " lockWrite (read:" + _readCount 222 + " write:" + _isWrite 223 + " try-write:" + _tryWriteCount + ")"); 224 } 225 226 long start = Alarm.getCurrentTime(); 227 long expire = start + timeout; 228 boolean isOkay = false; 229 230 synchronized (this) { 231 _tryWriteCount++; 232 _tryUpgradeCount++; 233 234 if (_owner == null) 236 _owner = Thread.currentThread(); 237 238 try { 239 while (true) { 240 if (! _isWrite && _readCount == _tryUpgradeCount) { 241 _isWrite = true; 242 _owner = Thread.currentThread(); 243 return; 244 } 245 246 long delta = expire - Alarm.getCurrentTime(); 247 248 if (delta < 0 || Alarm.isTest()) 249 break; 250 251 try { 252 wait(delta); 253 } catch (InterruptedException e) { 254 throw new LockTimeoutException(e); 255 } 256 } 257 258 if (! Alarm.isTest()) { 259 printOwnerStack(); 260 Thread.dumpStack(); 261 } 262 263 throw new LockTimeoutException(L.l("{0} lockWrite timed out ({1}ms) try-writers:{2}", 264 this, 265 Alarm.getCurrentTime() - start, 266 _tryWriteCount)); 267 } finally { 268 _tryWriteCount--; 269 _tryUpgradeCount--; 270 271 notifyAll(); 272 } 273 } 274 } 275 276 279 void unlockReadAndWrite() 280 throws SQLException 281 { 282 synchronized (this) { 283 _readCount--; 284 _isWrite = false; 285 _owner = null; 286 287 notifyAll(); 288 } 289 290 if (log.isLoggable(Level.FINEST)) { 291 log.finest(this + " unlockReadAndWrite (read:" + _readCount 292 + " write:" + _isWrite 293 + " try-write:" + _tryWriteCount + ")"); 294 } 295 } 296 297 300 void unlockWrite() 301 throws SQLException 302 { 303 synchronized (this) { 304 _isWrite = false; 305 _owner = null; 306 307 notifyAll(); 308 } 309 310 if (log.isLoggable(Level.FINEST)) { 311 log.finest(this + " unlockWrite (read:" + _readCount 312 + " write:" + _isWrite 313 + " try-write:" + _tryWriteCount + ")"); 314 } 315 } 316 317 private void printOwnerStack() 318 { 319 Thread thread = _owner; 320 321 if (thread == null) 322 return; 323 324 System.out.println("Owner-stack"); 325 StackTraceElement []stack = thread.getStackTrace(); 326 for (int i = 0; i < stack.length; i++) 327 System.out.println(stack[i]); 328 } 329 330 public String toString() 331 { 332 return "Lock[" + _id + "]"; 333 } 334 } 335 | Popular Tags |