public FileChannel truncate(long newLength) throws IOException {
   if (newLength >= length) {
     return this;
   }
   filePointer = Math.min(filePointer, newLength);
   int newFileCount = 1 + (int) (newLength / maxLength);
   if (newFileCount < list.length) {
     // delete some of the files
     FileChannel[] newList = new FileChannel[newFileCount];
     // delete backwards, so that truncating is somewhat transactional
     for (int i = list.length - 1; i >= newFileCount; i--) {
       // verify the file is writable
       list[i].truncate(0);
       list[i].close();
       try {
         file.getBase(i).delete();
       } catch (DbException e) {
         throw DbException.convertToIOException(e);
       }
     }
     System.arraycopy(list, 0, newList, 0, newList.length);
     list = newList;
   }
   long size = newLength - maxLength * (newFileCount - 1);
   list[list.length - 1].truncate(size);
   this.length = newLength;
   return this;
 }
Example #2
0
 private ValueLobDb createLob(InputStream in, int type) throws IOException {
   byte[] streamStoreId;
   try {
     streamStoreId = streamStore.put(in);
   } catch (Exception e) {
     throw DbException.convertToIOException(e);
   }
   long lobId = generateLobId();
   long length = streamStore.length(streamStoreId);
   int tableId = LobStorageFrontend.TABLE_TEMP;
   Object[] value = new Object[] {streamStoreId, tableId, length, 0};
   lobMap.put(lobId, value);
   Object[] key = new Object[] {streamStoreId, lobId};
   refMap.put(key, Boolean.TRUE);
   ValueLobDb lob = ValueLobDb.create(type, database, tableId, lobId, null, length);
   if (TRACE) {
     trace("create " + tableId + "/" + lobId);
   }
   return lob;
 }
 /**
  * Store a properties file. The header and the date is not written.
  *
  * @param fileName the target file name
  */
 public synchronized void store(String fileName) throws IOException {
   ByteArrayOutputStream out = new ByteArrayOutputStream();
   store(out, null);
   ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
   InputStreamReader reader = new InputStreamReader(in, "ISO8859-1");
   LineNumberReader r = new LineNumberReader(reader);
   Writer w;
   try {
     w = new OutputStreamWriter(IOUtils.openFileOutputStream(fileName, false));
   } catch (Exception e) {
     throw DbException.convertToIOException(e);
   }
   PrintWriter writer = new PrintWriter(new BufferedWriter(w));
   while (true) {
     String line = r.readLine();
     if (line == null) {
       break;
     }
     if (!line.startsWith("#")) {
       writer.print(line + "\n");
     }
   }
   writer.close();
 }
Example #4
0
 /**
  * Run one recovery stage. There are three recovery stages: 0: only the undo steps are run
  * (restoring the state before the last checkpoint). 1: the pages that are used by the transaction
  * log are allocated. 2: the committed operations are re-applied.
  *
  * @param stage the recovery stage
  * @return whether the transaction log was empty
  */
 boolean recover(int stage) {
   if (trace.isDebugEnabled()) {
     trace.debug("log recover stage: " + stage);
   }
   if (stage == RECOVERY_STAGE_ALLOCATE) {
     PageInputStream in = new PageInputStream(store, logKey, firstTrunkPage, firstDataPage);
     usedLogPages = in.allocateAllPages();
     in.close();
     return true;
   }
   PageInputStream pageIn = new PageInputStream(store, logKey, firstTrunkPage, firstDataPage);
   DataReader in = new DataReader(pageIn);
   int logId = 0;
   Data data = store.createData();
   boolean isEmpty = true;
   try {
     int pos = 0;
     while (true) {
       int x = in.readByte();
       if (x < 0) {
         break;
       }
       pos++;
       isEmpty = false;
       if (x == UNDO) {
         int pageId = in.readVarInt();
         int size = in.readVarInt();
         if (size == 0) {
           in.readFully(data.getBytes(), store.getPageSize());
         } else if (size == 1) {
           // empty
           Arrays.fill(data.getBytes(), 0, store.getPageSize(), (byte) 0);
         } else {
           in.readFully(compressBuffer, size);
           try {
             compress.expand(compressBuffer, 0, size, data.getBytes(), 0, store.getPageSize());
           } catch (ArrayIndexOutOfBoundsException e) {
             DbException.convertToIOException(e);
           }
         }
         if (stage == RECOVERY_STAGE_UNDO) {
           if (!undo.get(pageId)) {
             if (trace.isDebugEnabled()) {
               trace.debug("log undo {0}", pageId);
             }
             store.writePage(pageId, data);
             undo.set(pageId);
             undoAll.set(pageId);
           } else {
             if (trace.isDebugEnabled()) {
               trace.debug("log undo skip {0}", pageId);
             }
           }
         }
       } else if (x == ADD) {
         int sessionId = in.readVarInt();
         int tableId = in.readVarInt();
         Row row = readRow(in, data);
         if (stage == RECOVERY_STAGE_UNDO) {
           store.allocateIfIndexRoot(pos, tableId, row);
         } else if (stage == RECOVERY_STAGE_REDO) {
           if (isSessionCommitted(sessionId, logId, pos)) {
             if (trace.isDebugEnabled()) {
               trace.debug("log redo + table: " + tableId + " s: " + sessionId + " " + row);
             }
             store.redo(tableId, row, true);
           } else {
             if (trace.isDebugEnabled()) {
               trace.debug("log ignore s: " + sessionId + " + table: " + tableId + " " + row);
             }
           }
         }
       } else if (x == REMOVE) {
         int sessionId = in.readVarInt();
         int tableId = in.readVarInt();
         long key = in.readVarLong();
         if (stage == RECOVERY_STAGE_REDO) {
           if (isSessionCommitted(sessionId, logId, pos)) {
             if (trace.isDebugEnabled()) {
               trace.debug("log redo - table: " + tableId + " s:" + sessionId + " key: " + key);
             }
             store.redoDelete(tableId, key);
           } else {
             if (trace.isDebugEnabled()) {
               trace.debug("log ignore s: " + sessionId + " - table: " + tableId + " " + key);
             }
           }
         }
       } else if (x == TRUNCATE) {
         int sessionId = in.readVarInt();
         int tableId = in.readVarInt();
         if (stage == RECOVERY_STAGE_REDO) {
           if (isSessionCommitted(sessionId, logId, pos)) {
             if (trace.isDebugEnabled()) {
               trace.debug("log redo truncate table: " + tableId);
             }
             store.redoTruncate(tableId);
           } else {
             if (trace.isDebugEnabled()) {
               trace.debug("log ignore s: " + sessionId + " truncate table: " + tableId);
             }
           }
         }
       } else if (x == PREPARE_COMMIT) {
         int sessionId = in.readVarInt();
         String transaction = in.readString();
         if (trace.isDebugEnabled()) {
           trace.debug("log prepare commit " + sessionId + " " + transaction + " pos: " + pos);
         }
         if (stage == RECOVERY_STAGE_UNDO) {
           int page = pageIn.getDataPage();
           setPrepareCommit(sessionId, page, transaction);
         }
       } else if (x == ROLLBACK) {
         int sessionId = in.readVarInt();
         if (trace.isDebugEnabled()) {
           trace.debug("log rollback " + sessionId + " pos: " + pos);
         }
         // ignore - this entry is just informational
       } else if (x == COMMIT) {
         int sessionId = in.readVarInt();
         if (trace.isDebugEnabled()) {
           trace.debug("log commit " + sessionId + " pos: " + pos);
         }
         if (stage == RECOVERY_STAGE_UNDO) {
           setLastCommitForSession(sessionId, logId, pos);
         }
       } else if (x == NOOP) {
         // nothing to do
       } else if (x == CHECKPOINT) {
         logId++;
       } else if (x == FREE_LOG) {
         int count = in.readVarInt();
         for (int i = 0; i < count; i++) {
           int pageId = in.readVarInt();
           if (stage == RECOVERY_STAGE_REDO) {
             if (!usedLogPages.get(pageId)) {
               store.free(pageId, false);
             }
           }
         }
       } else {
         if (trace.isDebugEnabled()) {
           trace.debug("log end");
           break;
         }
       }
     }
   } catch (DbException e) {
     if (e.getErrorCode() == ErrorCode.FILE_CORRUPTED_1) {
       trace.debug("log recovery stopped");
     } else {
       throw e;
     }
   } catch (IOException e) {
     trace.debug("log recovery completed");
   }
   undo = new BitField();
   if (stage == RECOVERY_STAGE_REDO) {
     usedLogPages = null;
   }
   return isEmpty;
 }