Unverified 提交 beb14085 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1653 from katzyn/RowList

Store datetime values in local time in temporary storages
...@@ -21,6 +21,11 @@ Change Log ...@@ -21,6 +21,11 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <ul>
<li>Issue #1651: TIMESTAMP values near DST may be changed in MVStore database due to UTC-based PageStore format in some
temporary storages
</li>
<li>PR #1650: Fix race in MVStore.close()
</li>
<li>Issue #1212: TestDiskFull: The file is locked <li>Issue #1212: TestDiskFull: The file is locked
</li> </li>
<li>PR #1648: Add functions ARRAY_CAT(), ARRAY_APPEND() and ARRAY_SLICE() <li>PR #1648: Add functions ARRAY_CAT(), ARRAY_APPEND() and ARRAY_SLICE()
......
...@@ -199,7 +199,6 @@ public class Update extends Prepared { ...@@ -199,7 +199,6 @@ public class Update extends Prepared {
// the cached row is already updated - we need the old values // the cached row is already updated - we need the old values
table.updateRows(this, session, rows); table.updateRows(this, session, rows);
if (table.fireRow()) { if (table.fireRow()) {
rows.invalidateCache();
for (rows.reset(); rows.hasNext();) { for (rows.reset(); rows.hasNext();) {
Row o = rows.next(); Row o = rows.next();
Row n = rows.next(); Row n = rows.next();
......
...@@ -73,7 +73,7 @@ public class UndoLog { ...@@ -73,7 +73,7 @@ public class UndoLog {
long pos = storedEntriesPos.remove(last); long pos = storedEntriesPos.remove(last);
long end = file.length(); long end = file.length();
int bufferLength = (int) (end - pos); int bufferLength = (int) (end - pos);
Data buff = Data.create(database, bufferLength); Data buff = Data.create(database, bufferLength, true);
file.seek(pos); file.seek(pos);
file.readFully(buff.getBytes(), 0, bufferLength); file.readFully(buff.getBytes(), 0, bufferLength);
while (buff.length() < bufferLength) { while (buff.length() < bufferLength) {
...@@ -146,7 +146,7 @@ public class UndoLog { ...@@ -146,7 +146,7 @@ public class UndoLog {
file.setCheckedWriting(false); file.setCheckedWriting(false);
file.setLength(FileStore.HEADER_LENGTH); file.setLength(FileStore.HEADER_LENGTH);
} }
Data buff = Data.create(database, Constants.DEFAULT_PAGE_SIZE); Data buff = Data.create(database, Constants.DEFAULT_PAGE_SIZE, true);
for (int i = 0; i < records.size(); i++) { for (int i = 0; i < records.size(); i++) {
UndoLogRecord r = records.get(i); UndoLogRecord r = records.get(i);
buff.checkCapacity(Constants.DEFAULT_PAGE_SIZE); buff.checkCapacity(Constants.DEFAULT_PAGE_SIZE);
......
...@@ -32,7 +32,6 @@ public class RowList { ...@@ -32,7 +32,6 @@ public class RowList {
private final int maxMemory; private final int maxMemory;
private int memory; private int memory;
private boolean written; private boolean written;
private boolean readUncached;
/** /**
* Construct a new row list for this session. * Construct a new row list for this session.
...@@ -91,7 +90,7 @@ public class RowList { ...@@ -91,7 +90,7 @@ public class RowList {
file = db.openFile(fileName, "rw", false); file = db.openFile(fileName, "rw", false);
file.setCheckedWriting(false); file.setCheckedWriting(false);
file.seek(FileStore.HEADER_LENGTH); file.seek(FileStore.HEADER_LENGTH);
rowBuff = Data.create(db, Constants.DEFAULT_PAGE_SIZE); rowBuff = Data.create(db, Constants.DEFAULT_PAGE_SIZE, true);
file.seek(FileStore.HEADER_LENGTH); file.seek(FileStore.HEADER_LENGTH);
} }
Data buff = rowBuff; Data buff = rowBuff;
...@@ -170,9 +169,6 @@ public class RowList { ...@@ -170,9 +169,6 @@ public class RowList {
int columnCount = buff.readInt(); int columnCount = buff.readInt();
long key = buff.readLong(); long key = buff.readLong();
int version = buff.readInt(); int version = buff.readInt();
if (readUncached) {
key = 0;
}
boolean deleted = buff.readInt() == 1; boolean deleted = buff.readInt() == 1;
Value[] values = new Value[columnCount]; Value[] values = new Value[columnCount];
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
...@@ -243,13 +239,6 @@ public class RowList { ...@@ -243,13 +239,6 @@ public class RowList {
return size; return size;
} }
/**
* Do not use the cache.
*/
public void invalidateCache() {
readUncached = true;
}
/** /**
* Close the result list and delete the temporary file. * Close the result list and delete the temporary file.
*/ */
......
...@@ -114,9 +114,12 @@ public class Data { ...@@ -114,9 +114,12 @@ public class Data {
*/ */
private final DataHandler handler; private final DataHandler handler;
private Data(DataHandler handler, byte[] data) { private final boolean storeLocalTime;
private Data(DataHandler handler, byte[] data, boolean storeLocalTime) {
this.handler = handler; this.handler = handler;
this.data = data; this.data = data;
this.storeLocalTime = storeLocalTime;
} }
/** /**
...@@ -295,10 +298,13 @@ public class Data { ...@@ -295,10 +298,13 @@ public class Data {
* *
* @param handler the data handler * @param handler the data handler
* @param capacity the initial capacity of the buffer * @param capacity the initial capacity of the buffer
* @param storeLocalTime
* store DATE, TIME, and TIMESTAMP values with local time storage
* format
* @return the buffer * @return the buffer
*/ */
public static Data create(DataHandler handler, int capacity) { public static Data create(DataHandler handler, int capacity, boolean storeLocalTime) {
return new Data(handler, new byte[capacity]); return new Data(handler, new byte[capacity], storeLocalTime);
} }
/** /**
...@@ -307,10 +313,13 @@ public class Data { ...@@ -307,10 +313,13 @@ public class Data {
* *
* @param handler the data handler * @param handler the data handler
* @param buff the data * @param buff the data
* @param storeLocalTime
* store DATE, TIME, and TIMESTAMP values with local time storage
* format
* @return the buffer * @return the buffer
*/ */
public static Data create(DataHandler handler, byte[] buff) { public static Data create(DataHandler handler, byte[] buff, boolean storeLocalTime) {
return new Data(handler, buff); return new Data(handler, buff, storeLocalTime);
} }
/** /**
...@@ -484,20 +493,48 @@ public class Data { ...@@ -484,20 +493,48 @@ public class Data {
break; break;
} }
case Value.TIME: case Value.TIME:
writeByte((byte) type); if (storeLocalTime) {
writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(v.getTime())); writeByte((byte) LOCAL_TIME);
ValueTime t = (ValueTime) v;
long nanos = t.getNanos();
long millis = nanos / 1_000_000;
nanos -= millis * 1_000_000;
writeVarLong(millis);
writeVarLong(nanos);
} else {
writeByte((byte) type);
writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(v.getTime()));
}
break; break;
case Value.DATE: { case Value.DATE: {
writeByte((byte) type); if (storeLocalTime) {
long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate()); writeByte((byte) LOCAL_DATE);
writeVarLong(x / MILLIS_PER_MINUTE); long x = ((ValueDate) v).getDateValue();
writeVarLong(x);
} else {
writeByte((byte) type);
long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate());
writeVarLong(x / MILLIS_PER_MINUTE);
}
break; break;
} }
case Value.TIMESTAMP: { case Value.TIMESTAMP: {
Timestamp ts = v.getTimestamp(); if (storeLocalTime) {
writeByte((byte) type); writeByte((byte) LOCAL_TIMESTAMP);
writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(ts)); ValueTimestamp ts = (ValueTimestamp) v;
writeVarInt(ts.getNanos() % 1_000_000); long dateValue = ts.getDateValue();
writeVarLong(dateValue);
long nanos = ts.getTimeNanos();
long millis = nanos / 1_000_000;
nanos -= millis * 1_000_000;
writeVarLong(millis);
writeVarLong(nanos);
} else {
Timestamp ts = v.getTimestamp();
writeByte((byte) type);
writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(ts));
writeVarInt(ts.getNanos() % 1_000_000);
}
break; break;
} }
case Value.TIMESTAMP_TZ: { case Value.TIMESTAMP_TZ: {
...@@ -702,8 +739,8 @@ public class Data { ...@@ -702,8 +739,8 @@ public class Data {
} }
DbException.throwInternalError("type=" + v.getType()); DbException.throwInternalError("type=" + v.getType());
} }
assert pos - start == getValueLen(v, handler) assert pos - start == getValueLen(v)
: "value size error: got " + (pos - start) + " expected " + getValueLen(v, handler); : "value size error: got " + (pos - start) + " expected " + getValueLen(v);
} }
/** /**
...@@ -925,17 +962,19 @@ public class Data { ...@@ -925,17 +962,19 @@ public class Data {
* @return the number of bytes required to store this value * @return the number of bytes required to store this value
*/ */
public int getValueLen(Value v) { public int getValueLen(Value v) {
return getValueLen(v, handler); return getValueLen(v, storeLocalTime);
} }
/** /**
* Calculate the number of bytes required to encode the given value. * Calculate the number of bytes required to encode the given value.
* *
* @param v the value * @param v the value
* @param handler the data handler for lobs * @param storeLocalTime
* calculate size of DATE, TIME, and TIMESTAMP values with local
* time storage format
* @return the number of bytes required to store this value * @return the number of bytes required to store this value
*/ */
public static int getValueLen(Value v, DataHandler handler) { public static int getValueLen(Value v, boolean storeLocalTime) {
if (v == ValueNull.INSTANCE) { if (v == ValueNull.INSTANCE) {
return 1; return 1;
} }
...@@ -1020,12 +1059,31 @@ public class Data { ...@@ -1020,12 +1059,31 @@ public class Data {
return 1 + getVarIntLen(scale) + getVarIntLen(bytes.length) + bytes.length; return 1 + getVarIntLen(scale) + getVarIntLen(bytes.length) + bytes.length;
} }
case Value.TIME: case Value.TIME:
if (storeLocalTime) {
long nanos = ((ValueTime) v).getNanos();
long millis = nanos / 1_000_000;
nanos -= millis * 1_000_000;
return 1 + getVarLongLen(millis) + getVarLongLen(nanos);
}
return 1 + getVarLongLen(DateTimeUtils.getTimeLocalWithoutDst(v.getTime())); return 1 + getVarLongLen(DateTimeUtils.getTimeLocalWithoutDst(v.getTime()));
case Value.DATE: { case Value.DATE: {
if (storeLocalTime) {
long dateValue = ((ValueDate) v).getDateValue();
return 1 + getVarLongLen(dateValue);
}
long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate()); long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate());
return 1 + getVarLongLen(x / MILLIS_PER_MINUTE); return 1 + getVarLongLen(x / MILLIS_PER_MINUTE);
} }
case Value.TIMESTAMP: { case Value.TIMESTAMP: {
if (storeLocalTime) {
ValueTimestamp ts = (ValueTimestamp) v;
long dateValue = ts.getDateValue();
long nanos = ts.getTimeNanos();
long millis = nanos / 1_000_000;
nanos -= millis * 1_000_000;
return 1 + getVarLongLen(dateValue) + getVarLongLen(millis) +
getVarLongLen(nanos);
}
Timestamp ts = v.getTimestamp(); Timestamp ts = v.getTimestamp();
return 1 + getVarLongLen(DateTimeUtils.getTimeLocalWithoutDst(ts)) + return 1 + getVarLongLen(DateTimeUtils.getTimeLocalWithoutDst(ts)) +
getVarIntLen(ts.getNanos() % 1_000_000); getVarIntLen(ts.getNanos() % 1_000_000);
...@@ -1096,7 +1154,7 @@ public class Data { ...@@ -1096,7 +1154,7 @@ public class Data {
Value[] list = ((ValueCollectionBase) v).getList(); Value[] list = ((ValueCollectionBase) v).getList();
int len = 1 + getVarIntLen(list.length); int len = 1 + getVarIntLen(list.length);
for (Value x : list) { for (Value x : list) {
len += getValueLen(x, handler); len += getValueLen(x, storeLocalTime);
} }
return len; return len;
} }
...@@ -1118,7 +1176,7 @@ public class Data { ...@@ -1118,7 +1176,7 @@ public class Data {
Value[] row = result.currentRow(); Value[] row = result.currentRow();
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
Value val = row[i]; Value val = row[i];
len += getValueLen(val, handler); len += getValueLen(val, storeLocalTime);
} }
} }
len++; len++;
...@@ -1360,7 +1418,7 @@ public class Data { ...@@ -1360,7 +1418,7 @@ public class Data {
public static void copyString(Reader source, OutputStream target) public static void copyString(Reader source, OutputStream target)
throws IOException { throws IOException {
char[] buff = new char[Constants.IO_BUFFER_SIZE]; char[] buff = new char[Constants.IO_BUFFER_SIZE];
Data d = new Data(null, new byte[3 * Constants.IO_BUFFER_SIZE]); Data d = new Data(null, new byte[3 * Constants.IO_BUFFER_SIZE], false);
while (true) { while (true) {
int l = source.read(buff); int l = source.read(buff);
if (l < 0) { if (l < 0) {
......
...@@ -33,7 +33,7 @@ public class FileStoreInputStream extends InputStream { ...@@ -33,7 +33,7 @@ public class FileStoreInputStream extends InputStream {
} else { } else {
compress = null; compress = null;
} }
page = Data.create(handler, Constants.FILE_BLOCK_SIZE); page = Data.create(handler, Constants.FILE_BLOCK_SIZE, true);
try { try {
if (store.length() <= FileStore.HEADER_LENGTH) { if (store.length() <= FileStore.HEADER_LENGTH) {
close(); close();
......
...@@ -31,7 +31,7 @@ public class FileStoreOutputStream extends OutputStream { ...@@ -31,7 +31,7 @@ public class FileStoreOutputStream extends OutputStream {
this.compress = null; this.compress = null;
this.compressionAlgorithm = null; this.compressionAlgorithm = null;
} }
page = Data.create(handler, Constants.FILE_BLOCK_SIZE); page = Data.create(handler, Constants.FILE_BLOCK_SIZE, true);
} }
@Override @Override
......
...@@ -869,7 +869,7 @@ public class PageStore implements CacheWriter { ...@@ -869,7 +869,7 @@ public class PageStore implements CacheWriter {
private void readStaticHeader() { private void readStaticHeader() {
file.seek(FileStore.HEADER_LENGTH); file.seek(FileStore.HEADER_LENGTH);
Data page = Data.create(database, Data page = Data.create(database,
new byte[PAGE_SIZE_MIN - FileStore.HEADER_LENGTH]); new byte[PAGE_SIZE_MIN - FileStore.HEADER_LENGTH], false);
file.readFully(page.getBytes(), 0, file.readFully(page.getBytes(), 0,
PAGE_SIZE_MIN - FileStore.HEADER_LENGTH); PAGE_SIZE_MIN - FileStore.HEADER_LENGTH);
readCount++; readCount++;
...@@ -941,7 +941,7 @@ public class PageStore implements CacheWriter { ...@@ -941,7 +941,7 @@ public class PageStore implements CacheWriter {
} }
private void writeStaticHeader() { private void writeStaticHeader() {
Data page = Data.create(database, new byte[pageSize - FileStore.HEADER_LENGTH]); Data page = Data.create(database, new byte[pageSize - FileStore.HEADER_LENGTH], false);
page.writeInt(pageSize); page.writeInt(pageSize);
page.writeByte((byte) WRITE_VERSION); page.writeByte((byte) WRITE_VERSION);
page.writeByte((byte) READ_VERSION); page.writeByte((byte) READ_VERSION);
...@@ -1281,7 +1281,7 @@ public class PageStore implements CacheWriter { ...@@ -1281,7 +1281,7 @@ public class PageStore implements CacheWriter {
* @return the data page. * @return the data page.
*/ */
public Data createData() { public Data createData() {
return Data.create(database, new byte[pageSize]); return Data.create(database, new byte[pageSize], false);
} }
/** /**
......
...@@ -486,7 +486,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -486,7 +486,7 @@ public class Recover extends Tool implements DataHandler {
} catch (Exception e) { } catch (Exception e) {
writeError(writer, e); writeError(writer, e);
} }
Data s = Data.create(this, 128); Data s = Data.create(this, 128, false);
seek(0); seek(0);
store.readFully(s.getBytes(), 0, 128); store.readFully(s.getBytes(), 0, 128);
s.setPos(48); s.setPos(48);
...@@ -503,7 +503,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -503,7 +503,7 @@ public class Recover extends Tool implements DataHandler {
} }
long pageCount = length / pageSize; long pageCount = length / pageSize;
parents = new int[(int) pageCount]; parents = new int[(int) pageCount];
s = Data.create(this, pageSize); s = Data.create(this, pageSize, false);
for (long i = 3; i < pageCount; i++) { for (long i = 3; i < pageCount; i++) {
s.reset(); s.reset();
seek(i); seek(i);
...@@ -513,7 +513,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -513,7 +513,7 @@ public class Recover extends Tool implements DataHandler {
parents[(int) i] = s.readInt(); parents[(int) i] = s.readInt();
} }
int logKey = 0, logFirstTrunkPage = 0, logFirstDataPage = 0; int logKey = 0, logFirstTrunkPage = 0, logFirstDataPage = 0;
s = Data.create(this, pageSize); s = Data.create(this, pageSize, false);
for (long i = 1;; i++) { for (long i = 1;; i++) {
if (i == 3) { if (i == 3) {
break; break;
...@@ -789,9 +789,9 @@ public class Recover extends Tool implements DataHandler { ...@@ -789,9 +789,9 @@ public class Recover extends Tool implements DataHandler {
} }
private void dumpPageStore(PrintWriter writer, long pageCount) { private void dumpPageStore(PrintWriter writer, long pageCount) {
Data s = Data.create(this, pageSize); Data s = Data.create(this, pageSize, false);
for (long page = 3; page < pageCount; page++) { for (long page = 3; page < pageCount; page++) {
s = Data.create(this, pageSize); s = Data.create(this, pageSize, false);
seek(page); seek(page);
store.readFully(s.getBytes(), 0, pageSize); store.readFully(s.getBytes(), 0, pageSize);
dumpPage(writer, s, page, pageCount); dumpPage(writer, s, page, pageCount);
...@@ -899,7 +899,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -899,7 +899,7 @@ public class Recover extends Tool implements DataHandler {
private void dumpPageLogStream(PrintWriter writer, int logKey, private void dumpPageLogStream(PrintWriter writer, int logKey,
int logFirstTrunkPage, int logFirstDataPage, long pageCount) int logFirstTrunkPage, int logFirstDataPage, long pageCount)
throws IOException { throws IOException {
Data s = Data.create(this, pageSize); Data s = Data.create(this, pageSize, false);
DataReader in = new DataReader( DataReader in = new DataReader(
new PageInputStream(writer, this, store, logKey, new PageInputStream(writer, this, store, logKey,
logFirstTrunkPage, logFirstDataPage, pageSize) logFirstTrunkPage, logFirstDataPage, pageSize)
...@@ -968,7 +968,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -968,7 +968,7 @@ public class Recover extends Tool implements DataHandler {
} }
writer.println("-- undo page " + pageId + " " + typeName); writer.println("-- undo page " + pageId + " " + typeName);
if (trace) { if (trace) {
Data d = Data.create(null, data); Data d = Data.create(null, data, false);
dumpPage(writer, d, pageId, pageCount); dumpPage(writer, d, pageId, pageCount);
} }
} else if (x == PageLog.ADD) { } else if (x == PageLog.ADD) {
...@@ -1094,7 +1094,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -1094,7 +1094,7 @@ public class Recover extends Tool implements DataHandler {
this.logKey = logKey - 1; this.logKey = logKey - 1;
this.nextTrunkPage = firstTrunkPage; this.nextTrunkPage = firstTrunkPage;
this.dataPage = firstDataPage; this.dataPage = firstDataPage;
page = Data.create(handler, pageSize); page = Data.create(handler, pageSize, false);
} }
@Override @Override
...@@ -1379,7 +1379,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -1379,7 +1379,7 @@ public class Recover extends Tool implements DataHandler {
writer.println("-- empty: " + empty); writer.println("-- empty: " + empty);
} }
if (!last) { if (!last) {
Data s2 = Data.create(this, pageSize); Data s2 = Data.create(this, pageSize, false);
s.setPos(pageSize); s.setPos(pageSize);
long parent = pageId; long parent = pageId;
while (true) { while (true) {
......
...@@ -72,7 +72,7 @@ public class TestDataPage extends TestBase implements DataHandler { ...@@ -72,7 +72,7 @@ public class TestDataPage extends TestBase implements DataHandler {
} }
private static void testPerformance() { private static void testPerformance() {
Data data = Data.create(null, 1024); Data data = Data.create(null, 1024, false);
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
long time = System.nanoTime(); long time = System.nanoTime();
for (int i = 0; i < 100000; i++) { for (int i = 0; i < 100000; i++) {
...@@ -217,7 +217,17 @@ public class TestDataPage extends TestBase implements DataHandler { ...@@ -217,7 +217,17 @@ public class TestDataPage extends TestBase implements DataHandler {
} }
private void testValue(Value v) { private void testValue(Value v) {
Data data = Data.create(null, 1024); testValue(v, false);
switch (v.getType()) {
case Value.DATE:
case Value.TIME:
case Value.TIMESTAMP:
testValue(v, true);
}
}
private void testValue(Value v, boolean storeLocalTime) {
Data data = Data.create(null, 1024, storeLocalTime);
data.checkCapacity((int) v.getPrecision()); data.checkCapacity((int) v.getPrecision());
data.writeValue(v); data.writeValue(v);
data.writeInt(123); data.writeInt(123);
...@@ -229,7 +239,7 @@ public class TestDataPage extends TestBase implements DataHandler { ...@@ -229,7 +239,7 @@ public class TestDataPage extends TestBase implements DataHandler {
} }
private void testAll() { private void testAll() {
Data page = Data.create(this, 128); Data page = Data.create(this, 128, false);
char[] data = new char[0x10000]; char[] data = new char[0x10000];
for (int i = 0; i < data.length; i++) { for (int i = 0; i < data.length; i++) {
......
...@@ -33,7 +33,7 @@ public class MemoryFootprint { ...@@ -33,7 +33,7 @@ public class MemoryFootprint {
print("BigDecimal", new BigDecimal("0")); print("BigDecimal", new BigDecimal("0"));
print("BigInteger", new BigInteger("0")); print("BigInteger", new BigInteger("0"));
print("String", new String("Hello")); print("String", new String("Hello"));
print("Data", Data.create(null, 10)); print("Data", Data.create(null, 10, false));
print("Row", new RowImpl(new Value[0], 0)); print("Row", new RowImpl(new Value[0], 0));
System.out.println(); System.out.println();
for (int i = 1; i < 128; i += i) { for (int i = 1; i < 128; i += i) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论