1 21 package com.db4o; 22 23 import java.io.*; 24 25 import com.db4o.ext.*; 26 import com.db4o.foundation.*; 27 import com.db4o.header.*; 28 import com.db4o.inside.*; 29 30 36 public final class YapConfigBlock { 37 38 40 53 private final YapFile _stream; 54 private final TimerFileLock _timerFileLock; 55 56 private int _address; 57 private Transaction _transactionToCommit; 58 public int _bootRecordID; 59 60 private static final int MINIMUM_LENGTH = 61 YapConst.INT_LENGTH + (YapConst.LONG_LENGTH * 2) + 1; 65 static final int OPEN_TIME_OFFSET = YapConst.INT_LENGTH; 66 public static final int ACCESS_TIME_OFFSET = OPEN_TIME_OFFSET + YapConst.LONG_LENGTH; 67 68 public static final int TRANSACTION_OFFSET = MINIMUM_LENGTH; 69 private static final int BOOTRECORD_OFFSET = TRANSACTION_OFFSET + YapConst.INT_LENGTH * 2; 70 private static final int INT_FORMERLY_KNOWN_AS_BLOCK_OFFSET = BOOTRECORD_OFFSET + YapConst.INT_LENGTH; 71 private static final int ENCRYPTION_PASSWORD_LENGTH = 5; 72 private static final int PASSWORD_OFFSET = INT_FORMERLY_KNOWN_AS_BLOCK_OFFSET+ENCRYPTION_PASSWORD_LENGTH; 73 private static final int FREESPACE_SYSTEM_OFFSET = PASSWORD_OFFSET + 1; 74 private static final int FREESPACE_ADDRESS_OFFSET = FREESPACE_SYSTEM_OFFSET + YapConst.INT_LENGTH; 75 private static final int CONVERTER_VERSION_OFFSET = FREESPACE_ADDRESS_OFFSET + YapConst.INT_LENGTH; 76 private static final int UUID_INDEX_ID_OFFSET = CONVERTER_VERSION_OFFSET + YapConst.INT_LENGTH; 77 78 79 private static final int LENGTH = 81 MINIMUM_LENGTH 82 + (YapConst.INT_LENGTH * 7) + ENCRYPTION_PASSWORD_LENGTH 84 + 1; 85 86 87 public static YapConfigBlock forNewFile(YapFile file) throws IOException{ 88 return new YapConfigBlock(file, true, 0); 89 } 90 91 public static YapConfigBlock forExistingFile(YapFile file, int address) throws IOException{ 92 return new YapConfigBlock(file, false, address); 93 } 94 95 private YapConfigBlock(YapFile stream, boolean isNew, int address) throws IOException{ 96 _stream = stream; 97 _timerFileLock = TimerFileLock.forFile(stream); 98 timerFileLock().writeHeaderLock(); 99 if(! isNew){ 100 read(address); 101 } 102 timerFileLock().start(); 103 } 104 105 private TimerFileLock timerFileLock(){ 106 return _timerFileLock; 107 } 108 109 public long openTime(){ 110 return timerFileLock().openTime(); 111 } 112 113 public Transaction getTransactionToCommit(){ 114 return _transactionToCommit; 115 } 116 117 private boolean lockFile(){ 118 if(! Debug.lockFile){ 119 return false; 120 } 121 return _stream.needsLockFileThread(); 122 } 123 124 private byte[] passwordToken() { 125 byte[] pwdtoken=new byte[ENCRYPTION_PASSWORD_LENGTH]; 126 String fullpwd=_stream.configImpl().password(); 127 if(_stream.configImpl().encrypt() && fullpwd!=null) { 128 try { 129 byte[] pwdbytes=new YapStringIO().write(fullpwd); 130 YapReader encwriter=new YapWriter(_stream.getTransaction(),pwdbytes.length+ENCRYPTION_PASSWORD_LENGTH); 131 encwriter.append(pwdbytes); 132 encwriter.append(new byte[ENCRYPTION_PASSWORD_LENGTH]); 133 _stream.i_handlers.decrypt(encwriter); 134 System.arraycopy(encwriter._buffer, 0, pwdtoken, 0, ENCRYPTION_PASSWORD_LENGTH); 135 } 136 catch(Exception exc) { 137 exc.printStackTrace(); 140 } 142 } 143 return pwdtoken; 144 } 145 146 private SystemData systemData(){ 147 return _stream.systemData(); 148 } 149 150 private void read(int address) { 151 addressChanged(address); 152 timerFileLock().writeOpenTime(); 153 YapWriter reader = _stream.getWriter(_stream.getSystemTransaction(), _address, LENGTH); 154 try{ 155 _stream.readBytes(reader._buffer, _address, LENGTH); 156 }catch(Exception e){ 157 } 159 int oldLength = reader.readInt(); 160 if(oldLength > LENGTH || oldLength < MINIMUM_LENGTH){ 161 Exceptions4.throwRuntimeException(17); 162 } 163 if(oldLength != LENGTH){ 164 if(! _stream.configImpl().isReadOnly() && ! _stream.configImpl().allowVersionUpdates()){ 167 if(_stream.configImpl().automaticShutDown()) { 168 Platform4.removeShutDownHook(_stream, _stream.i_lock); 169 } 170 Exceptions4.throwRuntimeException(65); 171 } 172 } 173 174 reader.readLong(); long lastAccessTime = reader.readLong(); 176 177 systemData().stringEncoding(reader.readByte()); 178 179 if(oldLength > TRANSACTION_OFFSET){ 180 _transactionToCommit = Transaction.readInterruptedTransaction(_stream, reader); 181 } 182 183 if(oldLength > BOOTRECORD_OFFSET) { 184 _bootRecordID = reader.readInt(); 185 } 186 187 if(oldLength > INT_FORMERLY_KNOWN_AS_BLOCK_OFFSET) { 188 reader.readInt(); 191 } 192 193 if(oldLength > PASSWORD_OFFSET) { 194 byte[] encpassword=reader.readBytes(ENCRYPTION_PASSWORD_LENGTH); 195 boolean nonZeroByte = false; 196 for (int i = 0; i < encpassword.length; i++) { 197 if(encpassword[i] != 0){ 198 nonZeroByte = true; 199 break; 200 } 201 } 202 if(! nonZeroByte){ 203 _stream.i_handlers.oldEncryptionOff(); 205 }else{ 206 byte[] storedpwd=passwordToken(); 207 for (int idx = 0; idx < storedpwd.length; idx++) { 208 if(storedpwd[idx]!=encpassword[idx]) { 209 _stream.fatalException(54); 210 } 211 } 212 } 213 } 214 215 if(oldLength > FREESPACE_SYSTEM_OFFSET){ 216 systemData().freespaceSystem(reader.readByte()); 217 } 218 219 if(oldLength > FREESPACE_ADDRESS_OFFSET){ 220 systemData().freespaceAddress(reader.readInt()); 221 } 222 223 if(oldLength > CONVERTER_VERSION_OFFSET){ 224 systemData().converterVersion(reader.readInt()); 225 } 226 if(oldLength > UUID_INDEX_ID_OFFSET){ 227 final int uuidIndexId = reader.readInt(); 228 if (0 != uuidIndexId) { 229 systemData().uuidIndexId(uuidIndexId); 230 } 231 } 232 233 _stream.ensureFreespaceSlot(); 234 235 if(lockFile() && ( lastAccessTime != 0)){ 236 _stream.logMsg(28, null); 237 long waitTime = YapConst.LOCK_TIME_INTERVAL * 5; 238 long currentTime = System.currentTimeMillis(); 239 240 while(System.currentTimeMillis() < currentTime + waitTime){ 243 Cool.sleepIgnoringInterruption(waitTime); 244 } 245 reader = _stream.getWriter(_stream.getSystemTransaction(), _address, YapConst.LONG_LENGTH * 2); 246 reader.moveForward(OPEN_TIME_OFFSET); 247 reader.read(); 248 249 reader.readLong(); 251 long currentAccessTime = reader.readLong(); 252 if((currentAccessTime > lastAccessTime) ){ 253 throw new DatabaseFileLockedException(); 254 } 255 } 256 if(lockFile()){ 257 Cool.sleepIgnoringInterruption(100); 260 _stream.syncFiles(); 261 timerFileLock().checkOpenTime(); 262 } 263 if(oldLength < LENGTH){ 264 write(); 265 } 266 } 267 268 public void write() { 269 270 timerFileLock().checkHeaderLock(); 271 addressChanged(_stream.getSlot(LENGTH)); 272 273 YapWriter writer = _stream.getWriter(_stream.getTransaction(), _address,LENGTH); 274 YInt.writeInt(LENGTH, writer); 275 for (int i = 0; i < 2; i++) { 276 writer.writeLong(timerFileLock().openTime()); 277 } 278 writer.append(systemData().stringEncoding()); 279 YInt.writeInt(0, writer); 280 YInt.writeInt(0, writer); 281 YInt.writeInt(_bootRecordID, writer); 282 YInt.writeInt(0, writer); writer.append(passwordToken()); 284 writer.append(systemData().freespaceSystem()); 285 _stream.ensureFreespaceSlot(); 286 YInt.writeInt(systemData().freespaceAddress(), writer); 287 YInt.writeInt(systemData().converterVersion(), writer); 288 YInt.writeInt(systemData().uuidIndexId(), writer); 289 writer.write(); 290 writePointer(); 291 } 292 293 private void addressChanged(int address){ 294 _address = address; 295 timerFileLock().setAddresses(_address, OPEN_TIME_OFFSET, ACCESS_TIME_OFFSET); 296 } 297 298 private void writePointer() { 299 timerFileLock().checkHeaderLock(); 300 YapWriter writer = _stream.getWriter(_stream.getTransaction(), 0, YapConst.ID_LENGTH); 301 writer.moveForward(2); 302 YInt.writeInt(_address, writer); 303 writer.noXByteCheck(); 304 writer.write(); 305 timerFileLock().writeHeaderLock(); 306 } 307 308 public int address(){ 309 return _address; 310 } 311 312 public void close() throws IOException { 313 timerFileLock().close(); 314 } 315 316 } 317 318
| Popular Tags
|