@Override
 public void write() {
   data = store.createData();
   data.writeByte((byte) Page.TYPE_FREE_LIST);
   data.writeShortInt(0);
   for (int i = 0; i < pageCount; i += 8) {
     data.writeByte((byte) used.getByte(i));
   }
   store.writePage(getPos(), data);
 }
Пример #2
0
 /**
  * Prepare a transaction.
  *
  * @param session the session
  * @param transaction the name of the transaction
  */
 void prepareCommit(Session session, String transaction) {
   if (trace.isDebugEnabled()) {
     trace.debug("log prepare commit s: " + session.getId() + ", " + transaction);
   }
   if (store.getDatabase().getPageStore() == null) {
     // database already closed
     return;
   }
   // store it on a separate log page
   int pageSize = store.getPageSize();
   pageOut.flush();
   pageOut.fillPage();
   Data buffer = getBuffer();
   buffer.writeByte((byte) PREPARE_COMMIT);
   buffer.writeVarInt(session.getId());
   buffer.writeString(transaction);
   if (buffer.length() >= PageStreamData.getCapacity(pageSize)) {
     throw DbException.getInvalidValueException("transaction name (too long)", transaction);
   }
   write(buffer);
   // store it on a separate log page
   flushOut();
   pageOut.fillPage();
   if (store.getDatabase().getFlushOnEachCommit()) {
     flush();
   }
 }
Пример #3
0
 private void flushBuffer(Data buff) {
   buff.checkCapacity(1);
   buff.writeByte((byte) 0);
   buff.fillAligned();
   buff.setInt(0, buff.length() / Constants.FILE_BLOCK_SIZE);
   file.write(buff.getBytes(), 0, buff.length());
 }
Пример #4
0
 /** Write the header data. */
 void initWrite() {
   data = store.createData();
   data.writeByte((byte) Page.TYPE_STREAM_DATA);
   data.writeShortInt(0);
   data.writeInt(trunk);
   data.writeInt(logKey);
   remaining = store.getPageSize() - data.length();
 }
Пример #5
0
 /**
  * Set the state of an in-doubt transaction.
  *
  * @param sessionId the session
  * @param pageId the page where the commit was prepared
  * @param commit whether the transaction should be committed
  */
 void setInDoubtTransactionState(int sessionId, int pageId, boolean commit) {
   PageStreamData d = (PageStreamData) store.getPage(pageId);
   d.initWrite();
   Data buff = store.createData();
   buff.writeByte((byte) (commit ? COMMIT : ROLLBACK));
   buff.writeVarInt(sessionId);
   byte[] bytes = buff.getBytes();
   d.write(bytes, 0, bytes.length);
   bytes = new byte[d.getRemaining()];
   d.write(bytes, 0, bytes.length);
   d.write();
 }
Пример #6
0
 /** Switch to a new log section. */
 void checkpoint() {
   Data buffer = getBuffer();
   buffer.writeByte((byte) CHECKPOINT);
   write(buffer);
   undo = new BitField();
   logSectionId++;
   logPos = 0;
   pageOut.flush();
   pageOut.fillPage();
   int currentDataPage = pageOut.getCurrentDataPageId();
   logSectionPageMap.put(logSectionId, currentDataPage);
 }
Пример #7
0
 /**
  * A table is truncated.
  *
  * @param session the session
  * @param tableId the table id
  */
 void logTruncate(Session session, int tableId) {
   if (trace.isDebugEnabled()) {
     trace.debug("log truncate s: " + session.getId() + " table: " + tableId);
   }
   session.addLogPos(logSectionId, logPos);
   logPos++;
   Data buffer = getBuffer();
   buffer.writeByte((byte) TRUNCATE);
   buffer.writeVarInt(session.getId());
   buffer.writeVarInt(tableId);
   write(buffer);
 }
Пример #8
0
 private void freeLogPages(IntArray pages) {
   if (trace.isDebugEnabled()) {
     trace.debug("log frees " + pages.get(0) + ".." + pages.get(pages.size() - 1));
   }
   Data buffer = getBuffer();
   buffer.writeByte((byte) FREE_LOG);
   int size = pages.size();
   buffer.writeVarInt(size);
   for (int i = 0; i < size; i++) {
     buffer.writeVarInt(pages.get(i));
   }
   write(buffer);
 }
Пример #9
0
 private void writeRow(Data buff, Row r) {
   buff.checkCapacity(1 + Data.LENGTH_INT * 8);
   buff.writeByte((byte) 1);
   buff.writeInt(r.getMemory());
   int columnCount = r.getColumnCount();
   buff.writeInt(columnCount);
   buff.writeLong(r.getKey());
   buff.writeInt(r.getVersion());
   buff.writeInt(r.isDeleted() ? 1 : 0);
   buff.writeInt(r.getSessionId());
   for (int i = 0; i < columnCount; i++) {
     Value v = r.getValue(i);
     buff.checkCapacity(1);
     if (v == null) {
       buff.writeByte((byte) 0);
     } else {
       buff.writeByte((byte) 1);
       if (v.getType() == Value.CLOB || v.getType() == Value.BLOB) {
         // need to keep a reference to temporary lobs,
         // otherwise the temp file is deleted
         if (v.getSmall() == null && v.getTableId() == 0) {
           if (lobs == null) {
             lobs = New.arrayList();
           }
           // need to create a copy, otherwise,
           // if stored multiple times, it may be renamed
           // and then not found
           v = v.copyToTemp();
           lobs.add(v);
         }
       }
       buff.checkCapacity(buff.getValueLen(v));
       buff.writeValue(v);
     }
   }
 }
Пример #10
0
 /**
  * Mark a transaction as committed.
  *
  * @param sessionId the session
  */
 void commit(int sessionId) {
   if (trace.isDebugEnabled()) {
     trace.debug("log commit s: " + sessionId);
   }
   if (store.getDatabase().getPageStore() == null) {
     // database already closed
     return;
   }
   Data buffer = getBuffer();
   buffer.writeByte((byte) COMMIT);
   buffer.writeVarInt(sessionId);
   write(buffer);
   if (store.getDatabase().getFlushOnEachCommit()) {
     flush();
   }
 }
Пример #11
0
 /**
  * A record is added to a table, or removed from a table.
  *
  * @param session the session
  * @param tableId the table id
  * @param row the row to add
  * @param add true if the row is added, false if it is removed
  */
 void logAddOrRemoveRow(Session session, int tableId, Row row, boolean add) {
   if (trace.isDebugEnabled()) {
     trace.debug(
         "log "
             + (add ? "+" : "-")
             + " s: "
             + session.getId()
             + " table: "
             + tableId
             + " row: "
             + row);
   }
   session.addLogPos(logSectionId, logPos);
   logPos++;
   Data data = dataBuffer;
   data.reset();
   int columns = row.getColumnCount();
   data.writeVarInt(columns);
   data.checkCapacity(row.getByteCount(data));
   if (session.isRedoLogBinaryEnabled()) {
     for (int i = 0; i < columns; i++) {
       data.writeValue(row.getValue(i));
     }
   } else {
     for (int i = 0; i < columns; i++) {
       Value v = row.getValue(i);
       if (v.getType() == Value.BYTES) {
         data.writeValue(ValueNull.INSTANCE);
       } else {
         data.writeValue(v);
       }
     }
   }
   Data buffer = getBuffer();
   buffer.writeByte((byte) (add ? ADD : REMOVE));
   buffer.writeVarInt(session.getId());
   buffer.writeVarInt(tableId);
   buffer.writeVarLong(row.getKey());
   if (add) {
     buffer.writeVarInt(data.length());
     buffer.checkCapacity(data.length());
     buffer.write(data.getBytes(), 0, data.length());
   }
   write(buffer);
 }
Пример #12
0
 /**
  * Add an undo entry to the log. The page data is only written once until the next checkpoint.
  *
  * @param pageId the page id
  * @param page the old page data
  */
 void addUndo(int pageId, Data page) {
   if (undo.get(pageId) || freeing) {
     return;
   }
   if (trace.isDebugEnabled()) {
     trace.debug("log undo " + pageId);
   }
   if (SysProperties.CHECK) {
     if (page == null) {
       DbException.throwInternalError("Undo entry not written");
     }
   }
   undo.set(pageId);
   undoAll.set(pageId);
   Data buffer = getBuffer();
   buffer.writeByte((byte) UNDO);
   buffer.writeVarInt(pageId);
   if (page.getBytes()[0] == 0) {
     buffer.writeVarInt(1);
   } else {
     int pageSize = store.getPageSize();
     if (COMPRESS_UNDO) {
       int size = compress.compress(page.getBytes(), pageSize, compressBuffer, 0);
       if (size < pageSize) {
         buffer.writeVarInt(size);
         buffer.checkCapacity(size);
         buffer.write(compressBuffer, 0, size);
       } else {
         buffer.writeVarInt(0);
         buffer.checkCapacity(pageSize);
         buffer.write(page.getBytes(), 0, pageSize);
       }
     } else {
       buffer.writeVarInt(0);
       buffer.checkCapacity(pageSize);
       buffer.write(page.getBytes(), 0, pageSize);
     }
   }
   write(buffer);
 }
Пример #13
0
 /**
  * Append a value.
  *
  * @param v the value
  */
 public void writeValue(Value v) {
   int start = pos;
   if (v == ValueNull.INSTANCE) {
     data[pos++] = 0;
     return;
   }
   int type = v.getType();
   switch (type) {
     case Value.BOOLEAN:
       writeByte((byte) (v.getBoolean().booleanValue() ? BOOLEAN_TRUE : BOOLEAN_FALSE));
       break;
     case Value.BYTE:
       writeByte((byte) type);
       writeByte(v.getByte());
       break;
     case Value.SHORT:
       writeByte((byte) type);
       writeShortInt(v.getShort());
       break;
     case Value.INT:
       {
         int x = v.getInt();
         if (x < 0) {
           writeByte((byte) INT_NEG);
           writeVarInt(-x);
         } else if (x < 16) {
           writeByte((byte) (INT_0_15 + x));
         } else {
           writeByte((byte) type);
           writeVarInt(x);
         }
         break;
       }
     case Value.LONG:
       {
         long x = v.getLong();
         if (x < 0) {
           writeByte((byte) LONG_NEG);
           writeVarLong(-x);
         } else if (x < 8) {
           writeByte((byte) (LONG_0_7 + x));
         } else {
           writeByte((byte) type);
           writeVarLong(x);
         }
         break;
       }
     case Value.DECIMAL:
       {
         BigDecimal x = v.getBigDecimal();
         if (BigDecimal.ZERO.equals(x)) {
           writeByte((byte) DECIMAL_0_1);
         } else if (BigDecimal.ONE.equals(x)) {
           writeByte((byte) (DECIMAL_0_1 + 1));
         } else {
           int scale = x.scale();
           BigInteger b = x.unscaledValue();
           int bits = b.bitLength();
           if (bits <= 63) {
             if (scale == 0) {
               writeByte((byte) DECIMAL_SMALL_0);
               writeVarLong(b.longValue());
             } else {
               writeByte((byte) DECIMAL_SMALL);
               writeVarInt(scale);
               writeVarLong(b.longValue());
             }
           } else {
             writeByte((byte) type);
             writeVarInt(scale);
             byte[] bytes = b.toByteArray();
             writeVarInt(bytes.length);
             write(bytes, 0, bytes.length);
           }
         }
         break;
       }
     case Value.TIME:
       if (SysProperties.STORE_LOCAL_TIME) {
         writeByte((byte) LOCAL_TIME);
         ValueTime t = (ValueTime) v;
         long nanos = t.getNanos();
         long millis = nanos / 1000000;
         nanos -= millis * 1000000;
         writeVarLong(millis);
         writeVarLong(nanos);
       } else {
         writeByte((byte) type);
         writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(v.getTime()));
       }
       break;
     case Value.DATE:
       {
         if (SysProperties.STORE_LOCAL_TIME) {
           writeByte((byte) LOCAL_DATE);
           long x = ((ValueDate) v).getDateValue();
           writeVarLong(x);
         } else {
           writeByte((byte) type);
           long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate());
           writeVarLong(x / MILLIS_PER_MINUTE);
         }
         break;
       }
     case Value.TIMESTAMP:
       {
         if (SysProperties.STORE_LOCAL_TIME) {
           writeByte((byte) LOCAL_TIMESTAMP);
           ValueTimestamp ts = (ValueTimestamp) v;
           long dateValue = ts.getDateValue();
           writeVarLong(dateValue);
           long nanos = ts.getNanos();
           long millis = nanos / 1000000;
           nanos -= millis * 1000000;
           writeVarLong(millis);
           writeVarLong(nanos);
         } else {
           Timestamp ts = v.getTimestamp();
           writeByte((byte) type);
           writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(ts));
           writeVarInt(ts.getNanos());
         }
         break;
       }
     case Value.GEOMETRY:
     case Value.JAVA_OBJECT:
       {
         writeByte((byte) type);
         byte[] b = v.getBytesNoCopy();
         int len = b.length;
         writeVarInt(len);
         write(b, 0, len);
         break;
       }
     case Value.BYTES:
       {
         byte[] b = v.getBytesNoCopy();
         int len = b.length;
         if (len < 32) {
           writeByte((byte) (BYTES_0_31 + len));
           write(b, 0, len);
         } else {
           writeByte((byte) type);
           writeVarInt(len);
           write(b, 0, len);
         }
         break;
       }
     case Value.UUID:
       {
         writeByte((byte) type);
         ValueUuid uuid = (ValueUuid) v;
         writeLong(uuid.getHigh());
         writeLong(uuid.getLow());
         break;
       }
     case Value.STRING:
       {
         String s = v.getString();
         int len = s.length();
         if (len < 32) {
           writeByte((byte) (STRING_0_31 + len));
           writeStringWithoutLength(s, len);
         } else {
           writeByte((byte) type);
           writeString(s);
         }
         break;
       }
     case Value.STRING_IGNORECASE:
     case Value.STRING_FIXED:
       writeByte((byte) type);
       writeString(v.getString());
       break;
     case Value.DOUBLE:
       {
         double x = v.getDouble();
         if (x == 1.0d) {
           writeByte((byte) (DOUBLE_0_1 + 1));
         } else {
           long d = Double.doubleToLongBits(x);
           if (d == ValueDouble.ZERO_BITS) {
             writeByte((byte) DOUBLE_0_1);
           } else {
             writeByte((byte) type);
             writeVarLong(Long.reverse(d));
           }
         }
         break;
       }
     case Value.FLOAT:
       {
         float x = v.getFloat();
         if (x == 1.0f) {
           writeByte((byte) (FLOAT_0_1 + 1));
         } else {
           int f = Float.floatToIntBits(x);
           if (f == ValueFloat.ZERO_BITS) {
             writeByte((byte) FLOAT_0_1);
           } else {
             writeByte((byte) type);
             writeVarInt(Integer.reverse(f));
           }
         }
         break;
       }
     case Value.BLOB:
     case Value.CLOB:
       {
         writeByte((byte) type);
         if (v instanceof ValueLob) {
           ValueLob lob = (ValueLob) v;
           lob.convertToFileIfRequired(handler);
           byte[] small = lob.getSmall();
           if (small == null) {
             int t = -1;
             if (!lob.isLinked()) {
               t = -2;
             }
             writeVarInt(t);
             writeVarInt(lob.getTableId());
             writeVarInt(lob.getObjectId());
             writeVarLong(lob.getPrecision());
             writeByte((byte) (lob.isCompressed() ? 1 : 0));
             if (t == -2) {
               writeString(lob.getFileName());
             }
           } else {
             writeVarInt(small.length);
             write(small, 0, small.length);
           }
         } else {
           ValueLobDb lob = (ValueLobDb) v;
           byte[] small = lob.getSmall();
           if (small == null) {
             writeVarInt(-3);
             writeVarInt(lob.getTableId());
             writeVarLong(lob.getLobId());
             writeVarLong(lob.getPrecision());
           } else {
             writeVarInt(small.length);
             write(small, 0, small.length);
           }
         }
         break;
       }
     case Value.ARRAY:
       {
         writeByte((byte) type);
         Value[] list = ((ValueArray) v).getList();
         writeVarInt(list.length);
         for (Value x : list) {
           writeValue(x);
         }
         break;
       }
     case Value.RESULT_SET:
       {
         writeByte((byte) type);
         try {
           ResultSet rs = ((ValueResultSet) v).getResultSet();
           rs.beforeFirst();
           ResultSetMetaData meta = rs.getMetaData();
           int columnCount = meta.getColumnCount();
           writeVarInt(columnCount);
           for (int i = 0; i < columnCount; i++) {
             writeString(meta.getColumnName(i + 1));
             writeVarInt(meta.getColumnType(i + 1));
             writeVarInt(meta.getPrecision(i + 1));
             writeVarInt(meta.getScale(i + 1));
           }
           while (rs.next()) {
             writeByte((byte) 1);
             for (int i = 0; i < columnCount; i++) {
               int t = DataType.getValueTypeFromResultSet(meta, i + 1);
               Value val = DataType.readValue(null, rs, i + 1, t);
               writeValue(val);
             }
           }
           writeByte((byte) 0);
           rs.beforeFirst();
         } catch (SQLException e) {
           throw DbException.convert(e);
         }
         break;
       }
     default:
       DbException.throwInternalError("type=" + v.getType());
   }
   if (SysProperties.CHECK2) {
     if (pos - start != getValueLen(v, handler)) {
       throw DbException.throwInternalError(
           "value size error: got " + (pos - start) + " expected " + getValueLen(v, handler));
     }
   }
 }