1 package com.quadcap.sql; 2 3 40 41 import java.io.IOException ; 42 43 import java.util.ArrayList ; 44 import java.util.Enumeration ; 45 import java.util.Hashtable ; 46 import java.util.List ; 47 import java.util.Random ; 48 49 import java.sql.ResultSet ; 50 import java.sql.Statement ; 51 import java.sql.SQLException ; 52 53 import com.quadcap.sql.index.Btree; 54 import com.quadcap.sql.index.Comparator; 55 56 import com.quadcap.sql.file.BlockFile; 57 import com.quadcap.sql.file.ByteUtil; 58 import com.quadcap.sql.file.DatafileException; 59 import com.quadcap.sql.file.Log; 60 import com.quadcap.sql.file.LogEntry; 61 62 import com.quadcap.sql.lock.Transaction; 63 64 import com.quadcap.sql.io.ObjectOutputStream; 65 66 import com.quadcap.util.Debug; 67 68 74 public class Session { 75 Connection qConn; 76 Database db; 77 ObjectOutputStream oos; 78 79 ResultSet rs = null; 80 int updateCount = 0; 81 long lastInsertId = 0; 82 83 Object plock = new Object (); 84 List stmtPendingActions = null; 85 86 List cursors = null; 87 Hashtable stmtContext = null; 88 int stmtId = 0; 89 90 91 int sessionIndex = -1; 92 static int lastId = 0; 93 94 boolean viewCheck = false; 95 public boolean getViewCheck() { return viewCheck; } 96 public void setViewCheck() { viewCheck = true; } 97 public void clearViewCheck() { viewCheck = false; } 98 99 106 Session(Connection conn, int sessionIndex) { 107 this.qConn = conn; 108 this.sessionIndex = sessionIndex; 109 this.db = conn.getDatabase(); 110 this.lastInsertId = conn.getLastInsertId(); 112 this.oos = new ObjectOutputStream(null); 113 } 114 115 118 public final Connection getConnection() { return qConn; } 119 120 123 public final Transaction getTransaction() { 124 return qConn.getTransaction(); 125 } 126 127 130 public final long getTransactionId() { 131 return qConn.getTransactionId(); 132 } 133 134 138 public final long makeTransaction() throws SQLException { 139 long trans = getTransactionId(); 140 if (trans < 0) { 141 qConn.makeTransaction(); 142 trans = qConn.getTransactionId(); 143 stmtId = 0; 144 } else { 145 stmtId++; 146 } 147 return trans; 148 } 149 150 153 final public Log getLog() { return db.getLog(); } 154 155 158 public int getSessionId() { return sessionIndex; } 159 160 163 public int getStmtId() { return stmtId; } 164 165 168 final Btree makeTempTree(Comparator compare) throws IOException { 169 return qConn.makeTempTree(compare); 170 } 171 172 175 final Btree makeTempTree() throws IOException { 176 return qConn.makeTempTree(); 177 } 178 179 182 public final Database getDatabase() { return db; } 183 184 187 public final BlockFile getFile() { return qConn.getFile(); } 188 189 192 final Random getRandom() { return qConn.getRandom(); } 193 194 197 public final void getTableWriteLock(String tableName) 198 throws SQLException , IOException 199 { 200 qConn.getTableWriteLock(tableName); 201 } 202 203 206 public final void getTableReadLock(String tableName) 207 throws SQLException , IOException 208 { 209 qConn.getTableReadLock(tableName); 210 } 211 212 216 final void closeResultSet() { 217 if (Trace.bit(9)) { 219 Debug.println(toString() + ".closeResultSet()"); 220 } 221 if (rs != null) { 223 try { 224 rs.close(); 225 } catch (Throwable t) { 226 } finally { 230 rs = null; 231 } 232 } 233 } 234 235 238 public final void doStatement(Stmt s) throws IOException , SQLException { 239 243 if (Trace.bit(9)) { 245 Debug.println(toString() + ".doStatement(" + s + ")"); 246 } 247 249 if (rs != null) { 250 closeResultSet(); 251 } 252 makeTransaction(); 253 if (qConn.readOnly) { 254 if (!(s instanceof SelectStmt)) { 255 throw new SQLException ( 256 "Only SELECT statements are permitted in read-only mode"); 257 } 258 s.execute(this); 259 } else { 260 updateCount = 0; 261 beginStatement(); 262 263 try { 264 s.execute(this); 265 } catch (IOException e) { 266 Debug.print(e); 268 rollbackStatement(); 270 throw e; 271 } catch (SQLException e) { 272 if (Trace.bit(1)) { 274 Debug.println("--- Verbose exception report: "); 275 Debug.print(e); 276 } 277 rollbackStatement(); 279 throw e; 280 } catch (Throwable e) { 281 Debug.print(e); 283 rollbackStatement(); 285 throw DbException.wrapThrowable(e); 286 } 287 288 if (rs == null) { 291 endStatement(false); 292 } 293 } 294 } 295 296 public final void beginStatement() throws IOException { 297 getLog().addEntry(new LogEntry(getTransactionId(), stmtId, 298 LogEntry.BEGIN_STATEMENT)); 299 } 300 301 308 public final void endStatement(boolean abort) 309 throws IOException , SQLException 310 { 311 if (Trace.bit(9)) { 313 Debug.println(toString() + ".endStatement(" + abort + ")"); 314 } 315 if (getTransactionId() >= 0) { 317 try { 318 closeCursors(abort); 319 } catch (SQLException e) { 320 rollbackStatement(); 321 throw e; 322 } 323 qConn.endStatement(this, abort); 324 } 325 } 326 327 330 final void closeCursors(boolean abort) 331 throws SQLException , IOException 332 { 333 if (cursors != null) { 334 for (int i = 0; i < cursors.size(); i++) { 335 Cursor c = (Cursor)cursors.get(i); 336 c.close(); 337 } 338 cursors = null; 339 } 340 if (abort) { 341 stmtPendingActions = null; 342 } else { 343 doPendingActions(); 344 } 345 if (stmtContext != null) { 346 try { 347 finishContexts(stmtContext, abort); 348 } finally { 349 stmtContext = null; 350 } 351 } 352 } 353 354 359 final void rollbackStatement() throws IOException , SQLException { 360 if (Trace.bit(9)) { 362 Debug.println(toString() + ".rollbackStatement()"); 363 } 364 synchronized (plock) { 366 stmtPendingActions = null; 367 } 368 qConn.rollbackStatement(this); 369 } 370 371 372 375 public final void doStep(LogStep s) throws SQLException , IOException { 376 synchronized (db.getFileLock()) { 377 s.prepare(this); 378 if (false && Trace.bit(15)) { 380 Debug.println("[T:" + qConn.getTransactionId() + 381 "].redo(" + s + ")"); 382 } 383 try { 385 db.doStep(getTransaction(), s); 386 } catch (DatafileException e) { 387 throw (SQLException )e.getCause(); 391 } 392 } 393 } 394 395 final void setResultSet(QedResultSet rs) { 396 this.rs = rs; 397 } 398 399 402 final ResultSet getResultSet() { 403 return rs; 404 } 405 406 410 public final ResultSet getResultSet(Statement stmt) { 411 getResultSet(); 412 if (rs != null) ((QedResultSet)rs).setStatement(stmt); 413 return rs; 414 } 415 416 419 public final int getUpdateCount() { 420 return updateCount; 421 } 422 423 final void setUpdateCount(int c) { 424 this.updateCount = c; 425 } 426 427 final void incrUpdateCount() { 428 this.updateCount++; 429 } 430 431 final void decrUpdateCount() { 432 this.updateCount++; 433 } 434 435 439 final void addPendingAction(LogStep action) { 440 synchronized (plock) { 441 if (stmtPendingActions == null) stmtPendingActions = new ArrayList (); 442 stmtPendingActions.add(action); 443 } 444 } 445 446 447 450 final void doPendingActions() throws SQLException , IOException { 451 synchronized (plock) { 452 if (stmtPendingActions != null) { 453 for (int i = 0; i < stmtPendingActions.size(); i++) { 454 LogStep step = (LogStep)stmtPendingActions.get(i); 455 doStep(step); 456 } 457 stmtPendingActions = null; 458 } 459 } 460 } 461 462 466 final void addCursor(Cursor c) { 467 if (cursors == null) { 468 cursors = new ArrayList (); 469 } 470 cursors.add(c); 471 } 472 473 479 final void finishContexts(Hashtable context, boolean abort) 480 throws SQLException , IOException 481 { 482 SQLException se = null; 483 IOException io = null; 484 485 int maxp = 0; 486 for (int p = 0; p <= maxp; p++) { 487 Enumeration keys = context.keys(); 488 while (keys.hasMoreElements()) { 489 Object key = keys.nextElement(); 490 StatementContext sc = (StatementContext)context.get(key); 491 int sp = sc.priority(); 492 maxp = Math.max(maxp, sp); 493 if (sp == p) { 494 try { 495 if (Trace.bit(10)) { 497 Debug.println(toString() + " Finish " + 498 Table.strip(sc.getClass().getName())); 499 } 500 sc.finish(abort); 502 } catch (SQLException ex) { 503 se = ex; 504 } catch (IOException ex) { 505 io = ex; 506 } 507 } 508 } 509 } 510 if (se != null) throw se; 511 if (io != null) throw io; 512 } 513 514 521 final StatementContext getContext(Object obj, 522 boolean deferrable) { 523 StatementContext ret = null; 524 if (deferrable) { 525 ret = qConn.getContext(obj); 526 } else if (stmtContext != null) { 527 ret = (StatementContext)stmtContext.get(obj); 528 } 529 return ret; 530 } 531 532 535 final void putContext(Object key, boolean deferrable, 536 StatementContext val) { 537 if (deferrable) { 538 qConn.putContext(key, val); 539 } else { 540 if (stmtContext == null) { 541 stmtContext = new Hashtable (); 542 } 543 stmtContext.put(key, val); 544 } 545 } 546 547 550 public final void close() throws SQLException , IOException { 551 endStatement(false); 552 qConn.removeSession(this); 553 } 554 555 558 final void setLastInsertId(long insid) { 559 lastInsertId = insid; 560 qConn.setLastInsertId(insid); 561 } 562 563 566 public long getLastInsertId() { 567 return lastInsertId; 568 } 569 570 574 public String toString() { 575 return "Session " + sessionIndex + ": " + qConn; 576 } 577 579 582 byte[] buf8 = new byte[8]; 583 public final byte[] getBuf8(long l) { 584 ByteUtil.putLong(buf8, 0, l); 585 return buf8; 586 } 587 588 public boolean inRecovery() throws IOException { 589 return qConn.inRecovery(); 590 } 591 } 592 | Popular Tags |