1 package com.quadcap.sql; 2 3 40 41 import java.io.BufferedWriter ; 42 import java.io.File ; 43 import java.io.FileOutputStream ; 44 import java.io.IOException ; 45 import java.io.OutputStream ; 46 import java.io.OutputStreamWriter ; 47 import java.io.PrintWriter ; 48 49 import java.util.ArrayList ; 50 import java.util.Calendar ; 51 import java.util.Collection ; 52 import java.util.Enumeration ; 53 import java.util.Iterator ; 54 import java.util.HashMap ; 55 import java.util.List ; 56 import java.util.Map ; 57 import java.util.Properties ; 58 59 import java.util.zip.GZIPOutputStream ; 60 61 import java.sql.SQLException ; 62 63 import com.quadcap.sql.file.BlockFile; 64 import com.quadcap.sql.file.ByteUtil; 65 import com.quadcap.sql.file.Datafile; 66 import com.quadcap.sql.file.Log; 67 import com.quadcap.sql.file.SubPageManager; 68 69 import com.quadcap.sql.index.BCursor; 70 import com.quadcap.sql.index.Btree; 71 72 import com.quadcap.sql.lock.Transaction; 73 74 import com.quadcap.util.collections.LongIterator; 75 import com.quadcap.util.collections.LongMap; 76 77 import com.quadcap.util.ConfigString; 78 import com.quadcap.util.Debug; 79 import com.quadcap.util.Util; 80 81 86 public class Database extends Datafile { 87 QDriver driver; 88 Btree tableIndex; 89 Btree indexIndex; 91 Btree blobPermRefCounts; 92 Map tableMap = new HashMap (); 93 MultiSet forwardDeps = null; 94 MultiSet reverseDeps = null; 95 long rootBlock = 0; 96 public DatabaseRoot nroot; 97 98 100 LongMap blobMorgue = new LongMap(32); 101 102 103 LongMap blobActivity = new LongMap(128); 104 105 106 int connectionCount = 0; 107 int closeCount = 0; 108 long nextTransId = 0; 109 110 public Object driverLock; 111 112 static final ConfigString backupClass 113 = ConfigString.find("qed.backupClass", 114 "com.quadcap.sql.tools.XmlDump"); 115 118 public Database() {} 119 120 public void init(QDriver driver, String url, 121 String fileName, Properties props) 122 throws IOException , SQLException 123 { 124 this.driver = driver; 125 init(url, fileName, props); 126 } 127 128 131 public void createRoot(String fileName, Properties props) 132 throws IOException 133 { 134 this.rootBlock = getFile().getUserBlock(0); 135 this.root = this.nroot = new DatabaseRoot(this, fileName, props); 136 if (!readOnly && !inMemory) { 137 new File (fileName, "logfile").delete(); 138 flushRoot(); 139 } 140 } 141 142 145 public void readRoot() throws IOException { 146 this.rootBlock = getFile().getUserBlock(0); 147 root = nroot = (DatabaseRoot)file.getObject(rootBlock); 148 nroot.setDatabase(this); 149 } 150 151 154 public void flushRoot() throws IOException { 155 if (!inMemory && !readOnly) { 156 getFile().updateObject(rootBlock, root); 157 } 158 } 159 160 163 public void bootFromRoot(boolean restart) throws IOException { 164 nextTransId = root.getNextTransId(); 165 nroot.setNextTransId((nextTransId | 0xff) + 1); 166 167 blobPermRefCounts = new Btree(file, 168 nroot.getBlobRefCountRoot(), !restart); 169 tableIndex = new Btree(file, nroot.getRelationIndexNode(), !restart); 170 indexIndex = new Btree(file, nroot.getIndexIndexNode(), !restart); 171 forwardDeps = 172 new MultiSet(new Btree(file, nroot.getForwardDepsNode(), 173 !restart)); 174 reverseDeps = 175 new MultiSet(new Btree(file, nroot.getReverseDepsNode(), 176 !restart)); 177 } 178 179 182 public long getNextTransId() throws IOException { 183 synchronized (fileLock) { 184 long t = nextTransId++; 185 if (!inMemory && (nextTransId & 0xff) == 0) { 186 nroot.setNextTransId(nextTransId + 0x100); 187 flushRoot(); 188 } 189 return t; 190 } 191 } 192 193 196 public void maybeBackup() throws IOException { 197 if (inMemory) return; 198 int days = getBackupDays(); 200 if (days == 0) return; 201 202 Calendar now = Calendar.getInstance(); 204 int nowDay = now.get(Calendar.DAY_OF_WEEK); 205 if (((days >> nowDay) & 1) == 0) return; 206 207 int time = getBackupTime(); 209 int today = now.get(Calendar.DAY_OF_YEAR); 210 int nowTime = 211 now.get(Calendar.HOUR_OF_DAY) * 60 + 212 now.get(Calendar.MINUTE); 213 if (nowTime < time || today == getBackupLastDay()) return; 214 215 int count = getBackupCount(); 217 for (int i = count-2; i >= 0; i--) { 218 makeBackupFile(i).renameTo(makeBackupFile(i+1)); 219 } 220 221 OutputStream w = new FileOutputStream (makeBackupFile(0)); 223 if (getBackupFormat().equals("xml.gz")) { 224 w = new GZIPOutputStream (w); 225 } 226 OutputStreamWriter ow = new OutputStreamWriter (w); 227 BufferedWriter bw = new BufferedWriter (ow); 228 229 try { 231 java.sql.Connection conn = 232 driver.makeConnection(this, "backup", null); 233 Class c = Class.forName(backupClass.toString()); 234 Backup b = (Backup)c.newInstance(); 235 b.backup(conn, bw); 236 bw.close(); 237 } catch (IOException e) { 238 throw e; 239 } catch (Throwable t) { 240 throw new IOException (t.toString()); 241 } 242 setBackupLastDay(today); 243 } 244 245 File makeBackupFile(int n) throws IOException { 246 File bdir = new File (getBackupDir()); 247 if (!bdir.exists()) { 248 if (!bdir.mkdirs()) { 249 throw new IOException ("can't create backup directory: " + 250 bdir.getAbsolutePath()); 251 } 252 } 253 String name = "backup-" + n + "." + getBackupFormat(); 254 return new File (bdir, name); 255 } 256 257 261 public void addIndex(String indexName, String tableName) 262 throws IOException 263 { 264 synchronized (fileLock) { 265 indexIndex.set(indexName.getBytes(), tableName.getBytes()); 266 } 267 } 268 269 270 273 public String getTableForIndex(String indexName) throws IOException { 274 synchronized (fileLock) { 275 byte[] ret = indexIndex.get(indexName.getBytes()); 276 if (ret == null) return null; 277 return new String (ret); 278 } 279 } 280 281 284 public void deleteIndex(String indexName) throws IOException { 285 synchronized (fileLock) { 286 indexIndex.delete(indexName.getBytes()); 287 } 288 } 289 290 293 void renameIndexedTable(String oldN, String newN) throws IOException { 294 synchronized (fileLock) { 295 BCursor bc = indexIndex.getCursor(false); 296 if (bc != null) { 297 try { 298 while (bc.next()) { 299 String name = new String (bc.getVal()); 300 if (name.equals(oldN)) { 301 bc.prev(); 302 bc.replace(newN.getBytes()); 303 bc.next(); 304 } 305 } 306 } finally { 307 bc.release(); 308 } 309 } 310 } 311 } 312 313 318 public long getTableIdentity(String name) 319 throws IOException , SQLException 320 { 321 synchronized (fileLock) { 322 if (inMemory) { 323 Table t = (Table)getRelation(name); 324 return t.tableIdentity; 325 } else { 326 BCursor tc = tableIndex.getCursor(true); 327 try { 328 if (tc.seek(name.getBytes()) && 329 tc.getValLen() >= 16) { 330 return ByteUtil.getLong(tc.getValBuf(), 8); 331 } else { 332 throw new SQLException ("getTableIdentity(" + 333 name + "): no table"); 334 } 335 } finally { 336 tc.release(); 337 } 338 } 339 } 340 } 341 342 347 public void updateTableIdentity(String name, long num) 348 throws IOException , SQLException 349 { 350 synchronized (fileLock) { 351 if (inMemory) { 352 Table t = (Table)getRelation(name); 353 t.tableIdentity = num; 354 } else { 355 BCursor tc = tableIndex.getCursor(true); 356 try { 357 if (tc.seek(name.getBytes())) { 358 int cnt = tc.getVal(temp); 359 ByteUtil.putLong(temp, 8, num); 360 tc.replace(temp, 0, cnt); 361 return; 362 } else { 363 throw new SQLException ("getTableIdentity(" + 364 name + "): no table"); 365 } 366 } finally { 367 tc.release(); 368 } 369 } 370 } 371 } 372 373 377 public java.sql.ResultSet execute(String sql) 378 throws SQLException , IOException 379 { 380 Connection c = new Connection(this, "__NO_AUTH__", null); 381 Session session = c.createSession(); 382 return execute(session, sql); 383 } 384 385 388 public java.sql.ResultSet execute(Session session, String sql) 389 throws IOException , SQLException 390 { 391 SQLParser p = new SQLParser(session, sql, true); 392 Stmt s = null; 393 try { 394 s = p.statement(); 395 } catch (Throwable t) { 396 Debug.print(t); 397 } 398 399 if (s == null) { 400 throw new SQLException ("Parse error", "42000"); 401 } 402 session.doStatement(s); 403 return session.getResultSet(); 404 } 405 406 411 public Relation getRelation(String name) 412 throws IOException 413 { 414 Relation t = null; 415 synchronized (fileLock) { 416 t = (Relation)tableMap.get(name); 417 if (!inMemory && t == null) { 418 BCursor tc = tableIndex.getCursor(true); 419 try { 420 if (tc.seek(name.getBytes())) { 421 byte[] d = tc.getValBuf(); 422 t = (Relation)getFile().getObject(ByteUtil.getLong(d, 0)); 423 if (t != null) { 424 tableMap.put(name, t); 425 } 426 } 427 } finally { 428 tc.release(); 429 } 430 } 431 } 432 if (Trace.bit(0)) { 434 Debug.println("getRelation(" + name + ") = " + 435 ((t == null) ? "NOT FOUND" : "FOUND")); 436 } 437 return t; 439 } 440 441 444 public void addRelation(Relation table) 445 throws IOException , SQLException 446 { 447 synchronized (fileLock) { 448 String name = table.getName(); 449 if (Trace.bit(0)) { 451 Debug.println("addRelation(" + name + ")"); 452 } 453 if (tableMap.get(name) == null) { 455 tableMap.put(name, table); 456 if (!inMemory) { 457 BCursor tc = tableIndex.getCursor(true); 458 try { 459 byte[] tkey = name.getBytes(); 460 if (!tc.seek(name.getBytes())) { 461 long ref = getFile().putObject(table); 462 ByteUtil.putLong(temp, 0, ref); 463 ByteUtil.putLong(temp, 8, 1); tc.insert(tkey, tkey.length, temp, 0, 16); 465 } 466 } finally { 467 tc.release(); 468 } 469 } 470 } else { 471 throw new SQLException ("Table/view already exists: " + name, 472 "42000"); 473 } 474 } 475 } 476 477 480 public void removeRelation(String name) 481 throws IOException , SQLException 482 { 483 synchronized (fileLock) { 484 if (Trace.bit(0)) { 486 Debug.println("removeRelation(" + name + ")"); 487 } 488 Relation t = getRelation(name); 490 if (t == null) { 491 throw new SQLException ("No such table/view: " + name, "42000"); 492 } 493 removeViewDependencies(name); 494 tableMap.remove(name); 495 if (!inMemory) { 496 BCursor tc = tableIndex.getCursor(true); 497 try { 498 if (tc.seek(name.getBytes())) { 499 getFile().removeObject(tc.getValAsLong()); 500 tc.delete(); 501 } 502 } finally { 503 tc.release(); 504 } 505 } 506 } 507 if (getRelation(name) != null) { 509 throw new SQLException ("Relation not removed!!!"); 510 } 511 } 513 514 523 public void renameRelation(Relation r, String newN) throws IOException { 524 synchronized (fileLock) { 525 String oldN = r.getName(); 526 r.setName(newN); 527 tableMap.remove(oldN); 528 tableMap.put(newN, r); 529 if (!inMemory) { 530 BCursor tc = tableIndex.getCursor(true); 531 try { 532 if (tc.seek(oldN.getBytes())) { 533 byte[] d = tc.getValBuf(); 534 long ref = ByteUtil.getLong(d, 0); 535 tc.delete(); 536 byte[] nb = newN.getBytes(); 537 if (!tc.seek(nb)) { 538 tc.insert(nb, nb.length, d, 0, 16); 539 getFile().updateObject(ref, r); 540 } 541 } 542 } finally { 543 tc.release(); 544 } 545 } 546 if (true) { 547 forwardDeps.rename(oldN, newN, reverseDeps); 548 reverseDeps.rename(oldN, newN, forwardDeps); 549 } 550 if (true) { 551 renameIndexedTable(oldN, newN); 552 } 553 } 554 } 555 556 560 public void updateRelation(Relation table) throws IOException { 561 synchronized (fileLock) { 562 if (Trace.bit(0)) { 564 Debug.println("updateRelation(" + table.getName() + ")"); 565 } 567 tableMap.put(table.getName(), table); 569 if (!inMemory) { 570 BCursor tc = tableIndex.getCursor(true); 571 try { 572 if (tc.seek(table.getName().getBytes())) { 573 getFile().updateObject(tc.getValAsLong(), table); 574 } else { 575 throw new IOException ("Not found: " + table.getName()); 576 } 577 } finally { 578 tc.release(); 579 } 580 } 581 } 582 } 583 584 587 public void addViewDependency(String base, String view) 588 throws IOException 589 { 590 if (Trace.bit(0)) { 592 Debug.println("addViewDependency(" + base + ", " + view + ")"); 593 } 594 596 synchronized (fileLock) { 597 forwardDeps.put(base, view); 598 reverseDeps.put(view, base); 599 } 600 } 601 602 605 public void checkViewDependency(String base, String view) 606 throws SQLException , IOException 607 { 608 Relation baseR = getRelation(base); 609 if (baseR == null) { 610 throw new SQLException ("Base table not found: " + base, "42000"); 611 } 612 if (baseR instanceof Table) { 613 Table baseT = (Table)baseR; 614 int modifiers = baseT.getModifiers(); 615 if ((modifiers & Table.TEMPORARY) != 0) { 616 throw new SQLException ("Can't create view of temporary " + 617 "table " + base, "42000"); 618 } 619 } 620 } 621 622 625 public Enumeration getViews(String base) throws IOException { 626 synchronized (fileLock) { 627 return forwardDeps.get(base); 628 } 629 } 630 631 635 public Enumeration getBases(String view) throws IOException { 636 synchronized (fileLock) { 637 return reverseDeps.get(view); 638 } 639 } 640 641 public void removeViewDependencies(String view) 642 throws SQLException , IOException 643 { 644 if (Trace.bit(0)) { 646 Debug.println("removeViewDependencies(" + view + ")"); 647 } 648 synchronized (fileLock) { 650 Enumeration views = getViews(view); 651 if (views.hasMoreElements()) { 652 throw new SQLException ("view has dependencies: " + view, 653 "42000"); 654 } 655 Enumeration bases = getBases(view); 656 while (bases.hasMoreElements()) { 657 forwardDeps.delete(bases.nextElement().toString(), view); 658 } 659 } 660 } 661 662 667 671 public Iterator getRelationNameIterator() throws IOException { 672 if (inMemory) { 673 return tableMap.keySet().iterator(); 674 } else { 675 final BCursor tc = tableIndex.getCursor(false); 676 return new Iterator () { 677 boolean called = false; 678 boolean last = false; 679 boolean closed = false; 680 public boolean hasNext() { 681 try { 682 if (!closed && !called) { 683 last = tc.next(); 684 called = true; 685 } 686 } catch (IOException ex) { 687 last = false; 688 } 689 if (!last && !closed) { 690 closed = true; 691 try { 692 tc.release(); 693 } catch (Throwable t) { 694 Debug.print(t); 695 } 696 } 697 return last; 698 } 699 public Object next() { 700 Object ret = null; 701 try { 702 if (!called && !closed) { 703 last = tc.next(); 704 } 705 if (!last) { 706 if (!closed) { 707 closed = true; 708 try { 709 tc.release(); 710 } catch (Throwable t) { 711 Debug.print(t); 712 } 713 } 714 } else { 715 ret = new String (tc.getKey()); 716 called = false; 717 } 718 } catch (IOException ex) { 719 ret = "<Exception: " + ex + ">"; 720 } 721 return ret; 722 } 723 public void remove() { 724 try { 725 tc.delete(); 726 } catch (IOException e) { 727 Debug.print(e); 728 throw new RuntimeException ("Error deleting record", e); 729 } 730 } 731 }; 732 } 733 } 734 735 753 756 public int addConnection() { 757 synchronized (driverLock) { 758 if (Trace.bit(8)) { 760 Debug.println("addConnection, count now: " + (connectionCount+1)); 761 } 762 return ++connectionCount; 764 } 765 } 766 767 770 public QDriver getDriver() { 771 return driver; 772 } 773 774 778 public void removeConnection() { 779 synchronized (driverLock) { 780 if (--connectionCount == 0 && closeCount++ < 1) { 781 try { 782 getLog().checkpoint(); 783 } catch (Throwable e) { 784 } 785 } 786 if (Trace.bit(8)) { 788 Debug.println("removeConnection, count now: " + (connectionCount)); 789 } 790 if (connectionCount == 0 && closeCount == 1) { 792 driver.closeDatabase(origFileName); 793 } 794 } 795 } 796 797 800 public int getConnectionCount() { 801 return connectionCount; 802 } 803 804 807 public String getBackupDir() { 808 return nroot.getBackupDir(); 809 } 810 811 814 public void setBackupDir(String str) throws IOException { 815 nroot.setBackupDir(str); 816 flushRoot(); 817 } 818 819 822 public int getBackupCount() { 823 return nroot.getBackupCount(); 824 } 825 826 829 public void setBackupCount(int count) throws IOException { 830 nroot.setBackupCount(count); 831 flushRoot(); 832 } 833 834 837 public int getBackupDays() { 838 return nroot.getBackupDays(); 839 } 840 841 844 public void setBackupDays(int count) throws IOException { 845 nroot.setBackupDays(count); 846 flushRoot(); 847 } 848 849 852 public int getBackupLastDay() { 853 return nroot.getBackupLastDay(); 854 } 855 856 859 public void setBackupLastDay(int day) throws IOException { 860 nroot.setBackupLastDay(day); 861 flushRoot(); 862 } 863 864 867 public int getBackupTime() { 868 return nroot.getBackupTime(); 869 } 870 871 874 public void setBackupTime(int time) throws IOException { 875 nroot.setBackupTime(time); 876 flushRoot(); 877 } 878 879 882 public String getBackupFormat() { 883 return nroot.getBackupFormat(); 884 } 885 886 889 public void setBackupFormat(String str) throws IOException { 890 nroot.setBackupFormat(str); 891 flushRoot(); 892 } 893 894 901 public void checkAuth(String user, String passwd) throws SQLException { 902 } 904 905 908 public int getPermBlobRefCount(long blob) throws IOException { 909 synchronized (fileLock) { 910 ByteUtil.putLong(key, 0, blob); 911 byte[] val = blobPermRefCounts.get(key); 912 int refcount = val == null ? 0 : ByteUtil.getInt(val, 0); 913 return refcount; 914 } 915 } 916 917 918 922 private byte[] key = new byte[8]; 923 924 public int refCountBlob(long transId, long blob, int incr) 925 throws IOException 926 { 927 synchronized (fileLock) { 928 ByteUtil.putLong(key, 0, blob); 930 byte[] val = blobPermRefCounts.get(key); 931 int refcount = val == null ? 0 : ByteUtil.getInt(val, 0); 932 int preRefcount = refcount; 933 934 if (refcount == 0 && incr == 1) { 936 val = new byte[4]; 937 delMorgue(blob); 938 } 939 refcount += incr; 940 if (refcount < 0) { 941 throw new RuntimeException ("freePermBlobRef(" + blob + 942 "), refcount negative"); 943 } 944 945 if (refcount <= 0) { 946 if (preRefcount > 0) { 947 addMorgue(blob, transId); 948 } 949 blobPermRefCounts.delete(key); 950 } else { 951 ByteUtil.putInt(val, 0, refcount); 953 blobPermRefCounts.set(key, val); 954 } 955 956 return refcount; 957 } 958 } 959 960 963 public void addMorgue(long blob, long transId) { 964 synchronized (fileLock) { 965 blobMorgue.put(blob, new Long (transId)); 966 } 967 } 968 969 972 public void delMorgue(long blob) { 973 synchronized (fileLock) { 974 blobMorgue.remove(blob); 975 } 976 } 977 978 981 public LongIterator enumerateMorgue() { 982 return blobMorgue.keys(); 983 } 984 985 991 public void checkpointHandler(LongMap activeTransactions) 992 throws IOException 993 { 994 emptyMorgue(activeTransactions); 995 } 996 997 1001 public void emptyMorgue(LongMap activeTransactions) 1002 throws IOException 1003 { 1004 Log saveLog = getLog(); 1008 getFile().setLog(null); 1009 try { 1010 synchronized (fileLock) { 1011 LongIterator iter = enumerateMorgue(); 1012 while (iter.hasNext()) { 1013 long blob = iter.nextLong(); 1014 long transId = ((Long )(blobMorgue.get(blob))).longValue(); 1015 if (activeTransactions.get(transId) == null) { 1016 try { 1017 getFile().freeStream(blob); 1018 } catch (Throwable t) { 1019 Debug.println("Error removing blob: " + blob); 1020 Debug.print(t); 1021 } 1022 iter.remove(); 1023 } 1024 } 1025 } 1026 } finally { 1027 getFile().setLog(saveLog); 1029 } 1030 } 1031 1032 Session zSession = null; 1033 Connection zConn = null; 1034 1035 final Session getSession(Transaction t) throws IOException , SQLException { 1036 if (zSession == null) { 1037 synchronized (this) { 1038 if (zSession == null) { 1039 zConn = new Connection(this, "__SYSTEM", null); 1040 zSession = zConn.createSession(); 1041 } 1042 } 1043 } 1044 zConn.transId = t.getTransactionId(); zConn.trans = t; 1046 return zSession; 1047 } 1048 1049 public void display(PrintWriter w) throws IOException { 1051 w.println("Root:"); 1052 w.println(" blobs: " + nroot.getBlobRefCountRoot()); 1053 w.println(" relations: " + nroot.getRelationIndexNode()); 1054 w.println(" indexes: " + nroot.getIndexIndexNode()); 1055 w.println(" forward deps: " + nroot.getForwardDepsNode()); 1056 w.println(" reverse deps: " + nroot.getReverseDepsNode()); 1057 w.println(" next trans: " + nroot.getNextTransId()); 1058 if (true) { } 1060 if (true) { w.println("indexIndex:"); 1062 indexIndex.display(w); 1063 w.println("tableIndex:"); 1064 tableIndex.display(w); 1065 } 1066 if (true) { w.println("forwardDeps:"); 1068 forwardDeps.display(w); 1069 w.println("reverseDeps:"); 1070 reverseDeps.display(w); 1071 } 1072 if (true) { } 1074 if (true) { } 1076 } 1078 1080 1083 public long putRow(Session session, BlockFile f, 1084 Tuple t, Row row) 1085 throws SQLException , IOException 1086 { 1087 long rowId; 1088 if (inMemory) { 1089 rowId = f.putObject(row = new Row(row, t)); 1090 } else { 1091 byte[] buf = LazyRow.writeRow(session, t, row); 1092 rowId = f.putBytes(buf); 1093 } 1094 if (Trace.bit(11)) { 1096 Debug.println((f == this.file ? "file" : "temp") + "." + 1097 ((t == null) ? "temp" : 1098 ("Table[" + t.getName() + "]")) + 1099 ".putRow(" + row + "): " + rowId); 1100 } 1101 return rowId; 1103 } 1104 1105 1108 public final void putRow(Session session, Tuple t, 1109 long rowId, Row row) 1110 throws SQLException , IOException 1111 { 1112 if (Trace.bit(11)) { 1114 Debug.println("Table[" + t.getName() + "].putRow(" + row + ")"); 1115 } 1116 if (inMemory) { 1118 getFile().updateObject(rowId, new Row(row, t)); 1119 } else { 1120 byte[] ret = LazyRow.writeRow(session, t, row); 1121 getFile().updateBytes(rowId, ret); 1122 } 1123 } 1124 1125 public void getRow(long rowId, LazyRow row, boolean isTemp) 1126 throws IOException , SQLException 1127 { 1128 BlockFile f = isTemp ? getTempFile(false) : getFile(); 1129 if (inMemory) { 1130 Row r = (Row)f.getObject(rowId); 1131 if (r == null) { 1132 throw new IOException ("No row: " + rowId); 1133 } 1134 if (r.size() != row.size()) { 1135 Debug.println((isTemp ? "temp" : "file") + ".getRow(" + 1137 rowId + ") = " + row); 1138 Debug.println("Bad row size in getRow: " + r.size() + 1139 " vs " + row.size()); 1140 throw new IOException ("Bad row size in getRow: " + r.size() + 1142 " vs " + row.size()); 1143 } 1144 for (int i = 1; i <= row.size(); i++) { 1145 row.set(i, r.getItem(i)); 1146 } 1147 } else { 1148 byte[] rowBytes = f.getBytes(rowId); 1149 row.reset(rowBytes, this); 1150 } 1151 if (Trace.bit(11)) { 1153 Debug.println((isTemp ? "temp" : "file") + ".getRow(" + 1154 rowId + ") = " + row); 1155 } 1156 } 1158 1159 public void removeRow(long rowId) throws IOException { 1160 removeRow(getFile(), rowId); 1161 } 1162 1163 public void removeRow(BlockFile file, long rowId) throws IOException { 1164 if (inMemory) { 1165 file.removeObject(rowId); 1166 } else { 1167 file.freeStream(rowId); 1168 } 1169 } 1170 1171 public boolean inMemory() { 1172 return inMemory; 1173 } 1174} 1175 1176 | Popular Tags |