1 5 package org.h2.result; 6 7 import java.sql.SQLException ; 8 9 import org.h2.engine.Constants; 10 import org.h2.engine.Database; 11 import org.h2.engine.Session; 12 import org.h2.store.DataPage; 13 import org.h2.store.FileStore; 14 import org.h2.util.ObjectArray; 15 import org.h2.value.Value; 16 17 class ResultDiskBuffer { 18 19 private static final int READ_AHEAD = 128; 20 21 private DataPage rowBuff; 22 private FileStore file; 23 private ObjectArray tapes; 24 private ResultDiskTape mainTape; 25 private SortOrder sort; 26 private int columnCount; 27 28 public ResultDiskBuffer(Session session, SortOrder sort, int columnCount) throws SQLException { 29 this.sort = sort; 30 this.columnCount = columnCount; 31 Database db = session.getDatabase(); 32 rowBuff = DataPage.create(db, Constants.DEFAULT_DATA_PAGE_SIZE); 33 String fileName = session.getDatabase().createTempFile(); 34 file = session.getDatabase().openFile(fileName, false); 35 file.autoDelete(); 36 file.seek(FileStore.HEADER_LENGTH); 37 if (sort != null) { 38 tapes = new ObjectArray(); 39 } else { 40 mainTape = new ResultDiskTape(); 41 mainTape.pos = FileStore.HEADER_LENGTH; 42 } 43 } 44 45 public void addRows(ObjectArray rows) throws SQLException { 46 if (sort != null) { 47 sort.sort(rows); 48 } 49 DataPage buff = rowBuff; 50 long start = file.getFilePointer(); 51 for (int i = 0; i < rows.size(); i++) { 52 buff.reset(); 53 buff.writeInt(0); 54 Value[] row = (Value[]) rows.get(i); 55 for (int j = 0; j < columnCount; j++) { 56 buff.writeValue(row[j]); 57 } 58 buff.fillAligned(); 59 int len = buff.length(); 60 buff.setInt(0, len); 61 buff.updateChecksum(); 62 file.write(buff.getBytes(), 0, len); 63 } 64 if (sort != null) { 65 ResultDiskTape tape = new ResultDiskTape(); 66 tape.start = start; 67 tape.end = file.getFilePointer(); 68 tapes.add(tape); 69 } else { 70 mainTape.end = file.getFilePointer(); 71 } 72 } 73 74 public void done() throws SQLException { 75 file.seek(FileStore.HEADER_LENGTH); 76 } 77 78 public void reset() { 79 if (sort != null) { 80 for (int i = 0; i < tapes.size(); i++) { 81 ResultDiskTape tape = getTape(i); 82 tape.pos = tape.start; 83 tape.buffer = new ObjectArray(); 84 } 85 } else { 86 mainTape.pos = FileStore.HEADER_LENGTH; 87 } 88 } 89 90 private void readRow(ResultDiskTape tape) throws SQLException { 91 int min = Constants.FILE_BLOCK_SIZE; 92 DataPage buff = rowBuff; 93 buff.reset(); 94 file.readFully(buff.getBytes(), 0, min); 95 int len = buff.readInt(); 96 buff.checkCapacity(len); 97 if(len-min > 0) { 98 file.readFully(buff.getBytes(), min, len - min); 99 } 100 buff.check(len); 101 tape.pos += len; 102 Value[] row = new Value[columnCount]; 103 for (int k = 0; k < columnCount; k++) { 104 row[k] = buff.readValue(); 105 } 106 tape.buffer.add(row); 107 } 108 109 public Value[] next() throws SQLException { 110 return sort != null ? nextSorted() : nextUnsorted(); 111 } 112 113 private Value[] nextUnsorted() throws SQLException { 114 file.seek(mainTape.pos); 115 if (mainTape.buffer.size() == 0) { 116 for (int j = 0; mainTape.pos < mainTape.end && j < READ_AHEAD; j++) { 117 readRow(mainTape); 118 } 119 } 120 Value[] row = (Value[]) mainTape.buffer.get(0); 121 mainTape.buffer.remove(0); 122 return row; 123 } 124 125 private Value[] nextSorted() throws SQLException { 126 int next = -1; 127 for (int i = 0; i < tapes.size(); i++) { 128 ResultDiskTape tape = getTape(i); 129 if (tape.buffer.size() == 0 && tape.pos < tape.end) { 130 file.seek(tape.pos); 131 for (int j = 0; tape.pos < tape.end && j < READ_AHEAD; j++) { 132 readRow(tape); 133 } 134 } 135 if (tape.buffer.size() > 0) { 136 if (next == -1) { 137 next = i; 138 } else if (compareTapes(tape, getTape(next)) < 0) { 139 next = i; 140 } 141 } 142 } 143 ResultDiskTape t = getTape(next); 144 Value[] row = (Value[]) t.buffer.get(0); 145 t.buffer.remove(0); 146 return row; 147 } 148 149 private ResultDiskTape getTape(int i) { 150 return (ResultDiskTape) tapes.get(i); 151 } 152 153 private int compareTapes(ResultDiskTape a, ResultDiskTape b) throws SQLException { 154 Value[] va = (Value[]) a.buffer.get(0); 155 Value[] vb = (Value[]) b.buffer.get(0); 156 return sort.compare(va, vb); 157 } 158 159 protected void finalize() { 160 if(!Constants.RUN_FINALIZERS) { 161 return; 162 } 163 close(); 164 } 165 166 public void close() { 167 if (file != null) { 168 file.closeAndDeleteSilently(); 169 file = null; 170 } 171 } 172 173 } 174 | Popular Tags |