1 5 package org.h2.store; 6 7 import java.sql.SQLException ; 8 9 import org.h2.engine.Constants; 10 import org.h2.engine.Session; 11 import org.h2.index.Cursor; 12 import org.h2.index.Index; 13 import org.h2.message.Message; 14 import org.h2.result.Row; 15 import org.h2.table.Table; 16 import org.h2.value.Value; 17 18 21 public class UndoLogRecord { 22 public static final short INSERT = 0, DELETE = 1; 23 private static final int IN_MEMORY = 0, STORED = 1, IN_MEMORY_READ_POS = 2; 24 private Table table; 25 private Row row; 26 private short operation; 27 private short state; 28 private int filePos; 29 30 public boolean isStored() { 31 return state == STORED; 32 } 33 34 public boolean canStore() { 35 return table.getUniqueIndex() != null; 36 } 37 38 public UndoLogRecord(Table table, short op, Row row) { 39 this.table = table; 40 this.row = row; 41 this.operation = op; 42 this.state = IN_MEMORY; 43 } 44 45 public void undo(Session session) throws SQLException { 46 switch (operation) { 47 case INSERT: 48 if(state == IN_MEMORY_READ_POS) { 49 Index index = table.getUniqueIndex(); 50 Cursor cursor = index.find(session, row, row); 51 cursor.next(); 52 int pos = cursor.getPos(); 53 row.setPos(pos); 54 state = IN_MEMORY; 55 } 56 if(session.getDatabase().getLockMode()==Constants.LOCK_MODE_OFF) { 57 if(row.getDeleted()) { 58 return; 60 } 61 } 62 try { 63 table.removeRow(session, row); 64 } catch(SQLException e) { 65 if(session.getDatabase().getLockMode()==Constants.LOCK_MODE_OFF && e.getErrorCode() == Message.ROW_NOT_FOUND_WHEN_DELETING_1) { 66 } else { 69 throw e; 70 } 71 } 72 break; 73 case DELETE: 74 try { 75 row.setPos(0); 76 table.addRow(session, row); 77 } catch(SQLException e) { 78 if(session.getDatabase().getLockMode()==Constants.LOCK_MODE_OFF && e.getErrorCode() == Message.DUPLICATE_KEY_1) { 79 } else { 82 throw e; 83 } 84 } 85 break; 86 default: 87 throw Message.getInternalError("op=" + operation); 88 } 89 } 90 91 public void save(DataPage buff, FileStore file) throws SQLException { 92 buff.reset(); 93 buff.writeInt(0); 94 buff.writeInt(operation); 95 buff.writeInt(row.getColumnCount()); 96 for (int i = 0; i < row.getColumnCount(); i++) { 97 buff.writeValue(row.getValue(i)); 98 } 99 buff.fillAligned(); 100 buff.setInt(0, buff.length() / Constants.FILE_BLOCK_SIZE); 101 buff.updateChecksum(); 102 filePos = (int) (file.getFilePointer() / Constants.FILE_BLOCK_SIZE); 103 file.write(buff.getBytes(), 0, buff.length()); 104 row = null; 105 state = STORED; 106 } 107 108 public void seek(FileStore file) throws SQLException { 109 file.seek(filePos * Constants.FILE_BLOCK_SIZE); 110 } 111 112 public void load(DataPage buff, FileStore file, Session session) throws SQLException { 113 int min = Constants.FILE_BLOCK_SIZE; 114 seek(file); 115 buff.reset(); 116 file.readFully(buff.getBytes(), 0, min); 117 int len = buff.readInt() * Constants.FILE_BLOCK_SIZE; 118 buff.checkCapacity(len); 119 if (len - min > 0) { 120 file.readFully(buff.getBytes(), min, len - min); 121 } 122 buff.check(len); 123 int op = buff.readInt(); 124 if (Constants.CHECK) { 125 if (operation != op) { 126 throw Message.getInternalError("operation=" + operation + " op=" + op); 127 } 128 } 129 int columnCount = buff.readInt(); 130 Value[] values = new Value[columnCount]; 131 for (int i = 0; i < columnCount; i++) { 132 values[i] = buff.readValue(); 133 } 134 row = new Row(values); 135 state = IN_MEMORY_READ_POS; 136 } 137 138 public Table getTable() { 139 return table; 140 } 141 } 142 | Popular Tags |