提交 ce8a983b authored 作者: Thomas Mueller's avatar Thomas Mueller

MVStore: improved API thanks to Simo Tripodi.

上级 a9025788
...@@ -53,7 +53,8 @@ public class ChangeCursor<K, V> implements Iterator<K> { ...@@ -53,7 +53,8 @@ public class ChangeCursor<K, V> implements Iterator<K> {
} }
public void remove() { public void remove() {
throw DataUtils.unsupportedOperationException("Removing is not supported"); throw DataUtils.newUnsupportedOperationException(
"Removing is not supported");
} }
private void fetchNext() { private void fetchNext() {
......
...@@ -89,7 +89,8 @@ public class Chunk { ...@@ -89,7 +89,8 @@ public class Chunk {
*/ */
static Chunk fromHeader(ByteBuffer buff, long start) { static Chunk fromHeader(ByteBuffer buff, long start) {
if (buff.get() != 'c') { if (buff.get() != 'c') {
throw DataUtils.illegalStateException("File corrupt reading chunk at position " + start); throw DataUtils.newIllegalStateException(
"File corrupt reading chunk at position {0}", start);
} }
int length = buff.getInt(); int length = buff.getInt();
int chunkId = buff.getInt(); int chunkId = buff.getInt();
......
...@@ -67,7 +67,8 @@ public class Cursor<K> implements Iterator<K> { ...@@ -67,7 +67,8 @@ public class Cursor<K> implements Iterator<K> {
} }
public void remove() { public void remove() {
throw DataUtils.unsupportedOperationException("Removing is not supported"); throw DataUtils.newUnsupportedOperationException(
"Removing is not supported");
} }
/** /**
......
...@@ -11,11 +11,13 @@ import java.io.IOException; ...@@ -11,11 +11,13 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.StringUtils;
/** /**
* Utility methods * Utility methods
...@@ -316,7 +318,9 @@ public class DataUtils { ...@@ -316,7 +318,9 @@ public class DataUtils {
} while (dst.remaining() > 0); } while (dst.remaining() > 0);
dst.rewind(); dst.rewind();
} catch (IOException e) { } catch (IOException e) {
throw illegalStateException("Reading from " + file + " failed; length " + dst.remaining() + " at " + pos, e); throw newIllegalStateException(
"Reading from {0} failed; length {1} at {2}",
file, dst.remaining(), pos, e);
} }
} }
...@@ -335,7 +339,9 @@ public class DataUtils { ...@@ -335,7 +339,9 @@ public class DataUtils {
off += len; off += len;
} while (src.remaining() > 0); } while (src.remaining() > 0);
} catch (IOException e) { } catch (IOException e) {
throw illegalStateException("Writing to " + file + " failed; length " + src.remaining() + " at " + pos, e); throw newIllegalStateException(
"Writing to {0} failed; length {1} at {2}",
file, src.remaining(), pos, e);
} }
} }
...@@ -553,27 +559,51 @@ public class DataUtils { ...@@ -553,27 +559,51 @@ public class DataUtils {
return (s2 << 16) | s1; return (s2 << 16) | s1;
} }
public static IllegalStateException illegalStateException(String message) { public static void checkArgument(boolean test, String message, Object... arguments) {
return new IllegalStateException(message + version()); if (!test) {
throw newIllegalArgumentException(message, arguments);
}
}
public static IllegalArgumentException newIllegalArgumentException(
String message, Object... arguments) {
return initCause(new IllegalArgumentException(
formatMessage(message, arguments)), arguments);
} }
public static IllegalStateException illegalStateException(String message, Exception cause) { public static UnsupportedOperationException newUnsupportedOperationException(
return new IllegalStateException(message + version(), cause); String message) {
return new UnsupportedOperationException(message + getVersion());
} }
public static IllegalArgumentException illegalArgumentException(String message) { public static IllegalStateException newIllegalStateException(
return new IllegalArgumentException(message + version()); String message, Object... arguments) {
return initCause(new IllegalStateException(
formatMessage(message, arguments)), arguments);
} }
public static IllegalArgumentException illegalArgumentException(String message, Exception cause) { private static <T extends Exception> T initCause(T e, Object... arguments) {
return new IllegalArgumentException(message + version(), cause); int size = arguments.length;
if (size > 0) {
Object o = arguments[size - 1];
if (o instanceof Exception) {
e.initCause((Exception) o);
}
}
return e;
} }
public static UnsupportedOperationException unsupportedOperationException(String message) { private static String formatMessage(String pattern, Object... arguments) {
return new UnsupportedOperationException(message + version()); for (int i = 0, size = arguments.length; i < size; i++) {
Object o = arguments[i];
String s = o == null ? "null" : o instanceof String ? StringUtils
.quoteIdentifier(o.toString()) : o.toString();
arguments[i] = s;
}
return MessageFormat.format(pattern, arguments) + getVersion();
} }
private static String version() { private static String getVersion() {
return " [" + Constants.VERSION_MAJOR + "." + return " [" + Constants.VERSION_MAJOR + "." +
Constants.VERSION_MINOR + "." + Constants.BUILD_ID + "]"; Constants.VERSION_MINOR + "." + Constants.BUILD_ID + "]";
} }
......
...@@ -60,7 +60,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -60,7 +60,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* @param store the store * @param store the store
* @param config the configuration * @param config the configuration
*/ */
public void open(MVStore store, HashMap<String, String> config) { protected void init(MVStore store, HashMap<String, String> config) {
this.store = store; this.store = store;
this.id = Integer.parseInt(config.get("id")); this.id = Integer.parseInt(config.get("id"));
String x = config.get("createVersion"); String x = config.get("createVersion");
...@@ -861,7 +861,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -861,7 +861,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
*/ */
protected void checkOpen() { protected void checkOpen() {
if (closed) { if (closed) {
throw DataUtils.illegalStateException("This map is closed"); throw DataUtils.newIllegalStateException("This map is closed");
} }
} }
...@@ -873,7 +873,8 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -873,7 +873,8 @@ public class MVMap<K, V> extends AbstractMap<K, V>
protected void checkWrite() { protected void checkWrite() {
if (readOnly) { if (readOnly) {
checkOpen(); checkOpen();
throw DataUtils.unsupportedOperationException("This map is read-only"); throw DataUtils.newUnsupportedOperationException(
"This map is read-only");
} }
} }
...@@ -916,12 +917,12 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -916,12 +917,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
*/ */
public MVMap<K, V> openVersion(long version) { public MVMap<K, V> openVersion(long version) {
if (readOnly) { if (readOnly) {
throw DataUtils.unsupportedOperationException( throw DataUtils.newUnsupportedOperationException(
"This map is read-only - need to call the method on the writable map"); "This map is read-only - need to call the method on the writable map");
} }
if (version < createVersion) { DataUtils.checkArgument(version >= createVersion,
throw DataUtils.illegalArgumentException("Unknown version"); "Unknown version {0}; this map was created in version is {1}",
} version, createVersion);
Page newest = null; Page newest = null;
// need to copy because it can change // need to copy because it can change
Page r = root; Page r = root;
...@@ -956,7 +957,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -956,7 +957,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
HashMap<String, String> config = New.hashMap(); HashMap<String, String> config = New.hashMap();
config.put("id", String.valueOf(id)); config.put("id", String.valueOf(id));
config.put("createVersion", String.valueOf(createVersion)); config.put("createVersion", String.valueOf(createVersion));
m.open(store, config); m.init(store, config);
m.root = root; m.root = root;
return m; return m;
} }
...@@ -1052,7 +1053,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1052,7 +1053,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* *
* @return the map * @return the map
*/ */
public M create(); M create();
} }
......
...@@ -41,8 +41,7 @@ H:3,... ...@@ -41,8 +41,7 @@ H:3,...
TODO: TODO:
- improve exception factory (fluent api) - update checkstyle
- implement table engine for H2
- automated 'kill process' and 'power failure' test - automated 'kill process' and 'power failure' test
- maybe split database into multiple files, to speed up compact - maybe split database into multiple files, to speed up compact
- auto-compact from time to time and on close - auto-compact from time to time and on close
...@@ -272,7 +271,7 @@ public class MVStore { ...@@ -272,7 +271,7 @@ public class MVStore {
String config = meta.get("map." + x); String config = meta.get("map." + x);
c = DataUtils.parseMap(config); c = DataUtils.parseMap(config);
c.put("id", x); c.put("id", x);
map.open(this, c); map.init(this, c);
String r = meta.get("root." + id); String r = meta.get("root." + id);
root = r == null ? 0 : Long.parseLong(r); root = r == null ? 0 : Long.parseLong(r);
} else { } else {
...@@ -281,9 +280,10 @@ public class MVStore { ...@@ -281,9 +280,10 @@ public class MVStore {
c.put("id", Integer.toString(id)); c.put("id", Integer.toString(id));
c.put("createVersion", Long.toString(currentVersion)); c.put("createVersion", Long.toString(currentVersion));
map = builder.create(); map = builder.create();
map.open(this, c); map.init(this, c);
meta.put("map." + id, map.asString(name)); meta.put("map." + id, map.asString(name));
meta.put("name." + name, Integer.toString(id)); meta.put("name." + name, Integer.toString(id));
markMetaChanged();
root = 0; root = 0;
} }
map.setRootPos(root, -1); map.setRootPos(root, -1);
...@@ -313,9 +313,7 @@ public class MVStore { ...@@ -313,9 +313,7 @@ public class MVStore {
private MVMap<String, String> getMetaMap(long version) { private MVMap<String, String> getMetaMap(long version) {
Chunk c = getChunkForVersion(version); Chunk c = getChunkForVersion(version);
if (c == null) { DataUtils.checkArgument(c != null, "Unknown version {}", version);
throw DataUtils.illegalArgumentException("Unknown version: " + version);
}
c = readChunkHeader(c.start); c = readChunkHeader(c.start);
MVMap<String, String> oldMeta = meta.openReadOnly(); MVMap<String, String> oldMeta = meta.openReadOnly();
oldMeta.setRootPos(c.metaRootPos, version); oldMeta.setRootPos(c.metaRootPos, version);
...@@ -340,6 +338,7 @@ public class MVStore { ...@@ -340,6 +338,7 @@ public class MVStore {
*/ */
void removeMap(int id) { void removeMap(int id) {
String name = getMapName(id); String name = getMapName(id);
markMetaChanged();
meta.remove("map." + id); meta.remove("map." + id);
meta.remove("name." + name); meta.remove("name." + name);
meta.remove("root." + id); meta.remove("root." + id);
...@@ -356,6 +355,12 @@ public class MVStore { ...@@ -356,6 +355,12 @@ public class MVStore {
mapsChanged.put(map.getId(), map); mapsChanged.put(map.getId(), map);
} }
private void markMetaChanged() {
// changes in the metadata alone are usually not detected, as the meta
// map is changed after storing
markChanged(meta);
}
/** /**
* Open the store. * Open the store.
*/ */
...@@ -364,7 +369,7 @@ public class MVStore { ...@@ -364,7 +369,7 @@ public class MVStore {
HashMap<String, String> c = New.hashMap(); HashMap<String, String> c = New.hashMap();
c.put("id", "0"); c.put("id", "0");
c.put("createVersion", Long.toString(currentVersion)); c.put("createVersion", Long.toString(currentVersion));
meta.open(this, c); meta.init(this, c);
if (fileName == null) { if (fileName == null) {
return; return;
} }
...@@ -408,7 +413,8 @@ public class MVStore { ...@@ -408,7 +413,8 @@ public class MVStore {
} catch (Exception e2) { } catch (Exception e2) {
// ignore // ignore
} }
throw DataUtils.illegalStateException("Could not open " + fileName, e); throw DataUtils.newIllegalStateException(
"Could not open file {0}", fileName, e);
} }
} }
...@@ -479,7 +485,7 @@ public class MVStore { ...@@ -479,7 +485,7 @@ public class MVStore {
} }
} }
if (currentVersion < 0) { if (currentVersion < 0) {
throw DataUtils.illegalStateException("File header is corrupt"); throw DataUtils.newIllegalStateException("File header is corrupt");
} }
} }
...@@ -493,9 +499,8 @@ public class MVStore { ...@@ -493,9 +499,8 @@ public class MVStore {
int checksum = DataUtils.getFletcher32(bytes, bytes.length / 2 * 2); int checksum = DataUtils.getFletcher32(bytes, bytes.length / 2 * 2);
DataUtils.appendMap(buff, "fletcher", Integer.toHexString(checksum)); DataUtils.appendMap(buff, "fletcher", Integer.toHexString(checksum));
bytes = StringUtils.utf8Encode(buff.toString()); bytes = StringUtils.utf8Encode(buff.toString());
if (bytes.length > BLOCK_SIZE) { DataUtils.checkArgument(bytes.length <= BLOCK_SIZE,
throw DataUtils.illegalArgumentException("File header too large: " + buff); "File header too large: {}", buff);
}
return bytes; return bytes;
} }
...@@ -534,7 +539,8 @@ public class MVStore { ...@@ -534,7 +539,8 @@ public class MVStore {
maps.clear(); maps.clear();
mapsChanged.clear(); mapsChanged.clear();
} catch (Exception e) { } catch (Exception e) {
throw DataUtils.illegalStateException("Closing failed for file " + fileName, e); throw DataUtils.newIllegalStateException(
"Closing failed for file {0}", fileName, e);
} finally { } finally {
file = null; file = null;
} }
...@@ -660,7 +666,7 @@ public class MVStore { ...@@ -660,7 +666,7 @@ public class MVStore {
if (ASSERT) { if (ASSERT) {
if (freedChunks.size() > 0) { if (freedChunks.size() > 0) {
throw DataUtils.illegalStateException("Temporary freed chunks"); throw DataUtils.newIllegalStateException("Temporary freed chunks");
} }
} }
...@@ -729,7 +735,8 @@ public class MVStore { ...@@ -729,7 +735,8 @@ public class MVStore {
Chunk c = chunks.get(f.id); Chunk c = chunks.get(f.id);
c.maxLengthLive += f.maxLengthLive; c.maxLengthLive += f.maxLengthLive;
if (c.maxLengthLive < 0) { if (c.maxLengthLive < 0) {
throw DataUtils.illegalStateException("Corrupt max length: " + c.maxLengthLive); throw DataUtils.newIllegalStateException(
"Corrupt max length {0}", c.maxLengthLive);
} }
} }
} }
...@@ -757,7 +764,9 @@ public class MVStore { ...@@ -757,7 +764,9 @@ public class MVStore {
try { try {
file.truncate(used); file.truncate(used);
} catch (IOException e) { } catch (IOException e) {
throw DataUtils.illegalStateException("Could not truncate to size " + used, e); throw DataUtils.newIllegalStateException(
"Could not truncate file {0} to size {1}",
fileName, used, e);
} }
fileSize = used; fileSize = used;
} }
...@@ -921,9 +930,7 @@ public class MVStore { ...@@ -921,9 +930,7 @@ public class MVStore {
DataUtils.readFully(file, chunk.start, buff); DataUtils.readFully(file, chunk.start, buff);
Chunk.fromHeader(buff, chunk.start); Chunk.fromHeader(buff, chunk.start);
int chunkLength = chunk.length; int chunkLength = chunk.length;
// mark a change, even if it doesn't look like there was a change markMetaChanged();
// as changes in the metadata alone are not detected
markChanged(meta);
while (buff.position() < chunkLength) { while (buff.position() < chunkLength) {
int start = buff.position(); int start = buff.position();
int pageLength = buff.getInt(); int pageLength = buff.getInt();
...@@ -978,7 +985,9 @@ public class MVStore { ...@@ -978,7 +985,9 @@ public class MVStore {
if (p == null) { if (p == null) {
Chunk c = getChunk(pos); Chunk c = getChunk(pos);
if (c == null) { if (c == null) {
throw DataUtils.illegalStateException("Chunk " + DataUtils.getPageChunkId(pos) + " not found"); throw DataUtils.newIllegalStateException(
"Chunk {0} not found",
DataUtils.getPageChunkId(pos));
} }
long filePos = c.start; long filePos = c.start;
filePos += DataUtils.getPageOffset(pos); filePos += DataUtils.getPageOffset(pos);
...@@ -1193,6 +1202,7 @@ public class MVStore { ...@@ -1193,6 +1202,7 @@ public class MVStore {
*/ */
public void setStoreVersion(int version) { public void setStoreVersion(int version) {
checkOpen(); checkOpen();
markMetaChanged();
meta.put("setting.storeVersion", Integer.toString(version)); meta.put("setting.storeVersion", Integer.toString(version));
} }
...@@ -1206,9 +1216,9 @@ public class MVStore { ...@@ -1206,9 +1216,9 @@ public class MVStore {
*/ */
public void rollbackTo(long version) { public void rollbackTo(long version) {
checkOpen(); checkOpen();
if (!isKnownVersion(version)) { DataUtils.checkArgument(
throw DataUtils.illegalArgumentException("Unknown version: " + version); isKnownVersion(version),
} "Unknown version {0}", version);
for (MVMap<?, ?> m : mapsChanged.values()) { for (MVMap<?, ?> m : mapsChanged.values()) {
m.rollbackTo(version); m.rollbackTo(version);
} }
...@@ -1330,23 +1340,23 @@ public class MVStore { ...@@ -1330,23 +1340,23 @@ public class MVStore {
private void checkOpen() { private void checkOpen() {
if (closed) { if (closed) {
throw DataUtils.illegalStateException("This store is closed"); throw DataUtils.newIllegalStateException("This store is closed");
} }
} }
void renameMap(MVMap<?, ?> map, String newName) { void renameMap(MVMap<?, ?> map, String newName) {
checkOpen(); checkOpen();
if (map == meta) { DataUtils.checkArgument(map != meta,
throw DataUtils.unsupportedOperationException("Renaming the meta map is not allowed"); "Renaming the meta map is not allowed");
}
if (map.getName().equals(newName)) { if (map.getName().equals(newName)) {
return; return;
} }
if (meta.containsKey("name." + newName)) { DataUtils.checkArgument(
throw DataUtils.illegalArgumentException("A map named " + newName + " already exists"); !meta.containsKey("name." + newName),
} "A map named {0} already exists", newName);
int id = map.getId(); int id = map.getId();
String oldName = getMapName(id); String oldName = getMapName(id);
markMetaChanged();
meta.remove("map." + id); meta.remove("map." + id);
meta.remove("name." + oldName); meta.remove("name." + oldName);
meta.put("map." + id, map.asString(newName)); meta.put("map." + id, map.asString(newName));
...@@ -1366,9 +1376,6 @@ public class MVStore { ...@@ -1366,9 +1376,6 @@ public class MVStore {
private final HashMap<String, Object> config = New.hashMap(); private final HashMap<String, Object> config = New.hashMap();
private Builder set(String key, Object value) { private Builder set(String key, Object value) {
if (config.containsKey(key)) {
throw DataUtils.illegalArgumentException("Parameter " + config.get(key) + " is already set");
}
config.put(key, value); config.put(key, value);
return this; return this;
} }
......
...@@ -426,8 +426,8 @@ public class Page { ...@@ -426,8 +426,8 @@ public class Page {
} }
} }
if (check != totalCount) { if (check != totalCount) {
throw DataUtils.illegalStateException("Expected: " + check + " got: " throw DataUtils.newIllegalStateException(
+ totalCount); "Expected: {0} got: {1}", check, totalCount);
} }
} }
return totalCount; return totalCount;
...@@ -689,21 +689,24 @@ public class Page { ...@@ -689,21 +689,24 @@ public class Page {
int start = buff.position(); int start = buff.position();
int pageLength = buff.getInt(); int pageLength = buff.getInt();
if (pageLength > maxLength) { if (pageLength > maxLength) {
throw DataUtils.illegalStateException("File corrupted, expected length =< " throw DataUtils.newIllegalStateException(
+ maxLength + " got " + pageLength); "File corrupted, expected length =< {0}, got {1}",
maxLength, pageLength);
} }
short check = buff.getShort(); short check = buff.getShort();
int mapId = DataUtils.readVarInt(buff); int mapId = DataUtils.readVarInt(buff);
if (mapId != map.getId()) { if (mapId != map.getId()) {
throw DataUtils.illegalStateException("File corrupted, expected map id " throw DataUtils.newIllegalStateException(
+ map.getId() + " got " + mapId); "File corrupted, expected map id {0}, got {1}",
map.getId(), mapId);
} }
int checkTest = DataUtils.getCheckValue(chunkId) int checkTest = DataUtils.getCheckValue(chunkId)
^ DataUtils.getCheckValue(offset) ^ DataUtils.getCheckValue(offset)
^ DataUtils.getCheckValue(pageLength); ^ DataUtils.getCheckValue(pageLength);
if (check != (short) checkTest) { if (check != (short) checkTest) {
throw DataUtils.illegalStateException("File corrupted, expected check value " throw DataUtils.newIllegalStateException(
+ checkTest + " got " + check); "File corrupted, expected check value {0}, got {1}",
checkTest, check);
} }
int len = DataUtils.readVarInt(buff); int len = DataUtils.readVarInt(buff);
keys = new Object[len]; keys = new Object[len];
...@@ -901,7 +904,7 @@ public class Page { ...@@ -901,7 +904,7 @@ public class Page {
public int getMemory() { public int getMemory() {
if (MVStore.ASSERT) { if (MVStore.ASSERT) {
if (memory != calculateMemory()) { if (memory != calculateMemory()) {
throw DataUtils.illegalStateException("Memory calculation error"); throw DataUtils.newIllegalStateException("Memory calculation error");
} }
} }
return memory; return memory;
......
...@@ -208,7 +208,8 @@ public class StreamStore { ...@@ -208,7 +208,8 @@ public class StreamStore {
map.remove(k2); map.remove(k2);
break; break;
default: default:
throw DataUtils.illegalArgumentException("Unsupported id " + StringUtils.convertBytesToHex(id)); throw DataUtils.newIllegalArgumentException(
"Unsupported id {0}", StringUtils.convertBytesToHex(id));
} }
} }
} }
...@@ -239,7 +240,8 @@ public class StreamStore { ...@@ -239,7 +240,8 @@ public class StreamStore {
DataUtils.readVarLong(idBuffer); DataUtils.readVarLong(idBuffer);
break; break;
default: default:
throw DataUtils.illegalArgumentException("Unsupported id " + StringUtils.convertBytesToHex(id)); throw DataUtils.newIllegalArgumentException(
"Unsupported id {0}", StringUtils.convertBytesToHex(id));
} }
} }
return length; return length;
...@@ -402,8 +404,8 @@ public class StreamStore { ...@@ -402,8 +404,8 @@ public class StreamStore {
return nextBuffer(); return nextBuffer();
} }
default: default:
throw DataUtils.illegalArgumentException("Unsupported id " + throw DataUtils.newIllegalArgumentException(
StringUtils.convertBytesToHex(idBuffer.array())); "Unsupported id {0}", StringUtils.convertBytesToHex(idBuffer.array()));
} }
} }
return null; return null;
......
...@@ -85,9 +85,9 @@ public class CacheLongKeyLIRS<V> { ...@@ -85,9 +85,9 @@ public class CacheLongKeyLIRS<V> {
public CacheLongKeyLIRS(long maxMemory, int averageMemory, int segmentCount, int stackMoveDistance) { public CacheLongKeyLIRS(long maxMemory, int averageMemory, int segmentCount, int stackMoveDistance) {
setMaxMemory(maxMemory); setMaxMemory(maxMemory);
setAverageMemory(averageMemory); setAverageMemory(averageMemory);
if (Integer.bitCount(segmentCount) != 1) { DataUtils.checkArgument(
throw DataUtils.illegalArgumentException("The segment count must be a power of 2, is " + segmentCount); Integer.bitCount(segmentCount) == 1,
} "The segment count must be a power of 2, is {0}", segmentCount);
this.segmentCount = segmentCount; this.segmentCount = segmentCount;
this.segmentMask = segmentCount - 1; this.segmentMask = segmentCount - 1;
this.stackMoveDistance = stackMoveDistance; this.stackMoveDistance = stackMoveDistance;
...@@ -252,9 +252,9 @@ public class CacheLongKeyLIRS<V> { ...@@ -252,9 +252,9 @@ public class CacheLongKeyLIRS<V> {
* @param maxMemory the maximum size (1 or larger) * @param maxMemory the maximum size (1 or larger)
*/ */
public void setMaxMemory(long maxMemory) { public void setMaxMemory(long maxMemory) {
if (maxMemory <= 0) { DataUtils.checkArgument(
throw DataUtils.illegalArgumentException("Max memory must be larger than 0"); maxMemory > 0,
} "Max memory must be larger than 0, is {0}", maxMemory);
this.maxMemory = maxMemory; this.maxMemory = maxMemory;
if (segments != null) { if (segments != null) {
long max = 1 + maxMemory / segments.length; long max = 1 + maxMemory / segments.length;
...@@ -271,9 +271,9 @@ public class CacheLongKeyLIRS<V> { ...@@ -271,9 +271,9 @@ public class CacheLongKeyLIRS<V> {
* @param averageMemory the average memory used (1 or larger) * @param averageMemory the average memory used (1 or larger)
*/ */
public void setAverageMemory(int averageMemory) { public void setAverageMemory(int averageMemory) {
if (averageMemory <= 0) { DataUtils.checkArgument(
throw DataUtils.illegalArgumentException("Average memory must be larger than 0"); averageMemory > 0,
} "Average memory must be larger than 0, is {0}", averageMemory);
this.averageMemory = averageMemory; this.averageMemory = averageMemory;
if (segments != null) { if (segments != null) {
for (Segment<V> s : segments) { for (Segment<V> s : segments) {
...@@ -687,7 +687,8 @@ public class CacheLongKeyLIRS<V> { ...@@ -687,7 +687,8 @@ public class CacheLongKeyLIRS<V> {
*/ */
synchronized V put(long key, int hash, V value, int memory) { synchronized V put(long key, int hash, V value, int memory) {
if (value == null) { if (value == null) {
throw DataUtils.illegalArgumentException("The value may not be null"); throw DataUtils.newIllegalArgumentException(
"The value may not be null");
} }
V old; V old;
Entry<V> e = find(key, hash); Entry<V> e = find(key, hash);
...@@ -951,9 +952,6 @@ public class CacheLongKeyLIRS<V> { ...@@ -951,9 +952,6 @@ public class CacheLongKeyLIRS<V> {
* @param maxMemory the maximum size (1 or larger) * @param maxMemory the maximum size (1 or larger)
*/ */
void setMaxMemory(long maxMemory) { void setMaxMemory(long maxMemory) {
if (maxMemory <= 0) {
throw DataUtils.illegalArgumentException("Max memory must be larger than 0");
}
this.maxMemory = maxMemory; this.maxMemory = maxMemory;
} }
...@@ -964,9 +962,6 @@ public class CacheLongKeyLIRS<V> { ...@@ -964,9 +962,6 @@ public class CacheLongKeyLIRS<V> {
* @param averageMemory the average memory used (1 or larger) * @param averageMemory the average memory used (1 or larger)
*/ */
void setAverageMemory(int averageMemory) { void setAverageMemory(int averageMemory) {
if (averageMemory <= 0) {
throw DataUtils.illegalArgumentException("Average memory must be larger than 0");
}
this.averageMemory = averageMemory; this.averageMemory = averageMemory;
} }
......
...@@ -368,12 +368,6 @@ public class MVTable extends TableBase { ...@@ -368,12 +368,6 @@ public class MVTable extends TableBase {
// if (isPersistIndexes() && indexType.isPersistent()) { // if (isPersistIndexes() && indexType.isPersistent()) {
int mainIndexColumn; int mainIndexColumn;
mainIndexColumn = getMainIndexColumn(indexType, cols); mainIndexColumn = getMainIndexColumn(indexType, cols);
// if (database.isStarting()) {
// mainIndexColumn = -1;
// } else if (!database.isStarting() && primaryIndex.getRowCount(session) != 0) {
// mainIndexColumn = -1;
// } else {
// }
if (!database.isStarting() && primaryIndex.getRowCount(session) != 0) { if (!database.isStarting() && primaryIndex.getRowCount(session) != 0) {
mainIndexColumn = -1; mainIndexColumn = -1;
} }
...@@ -386,9 +380,6 @@ public class MVTable extends TableBase { ...@@ -386,9 +380,6 @@ public class MVTable extends TableBase {
this, indexId, this, indexId,
indexName, cols, indexType); indexName, cols, indexType);
} }
// } else {
// index = new TreeIndex(this, indexId, indexName, cols, indexType);
// }
if (index.needRebuild() && rowCount > 0) { if (index.needRebuild() && rowCount > 0) {
try { try {
Index scan = getScanIndex(session); Index scan = getScanIndex(session);
...@@ -674,7 +665,7 @@ public class MVTable extends TableBase { ...@@ -674,7 +665,7 @@ public class MVTable extends TableBase {
private void storeIfRequired() { private void storeIfRequired() {
if (store.getUnsavedPageCount() > 1000) { if (store.getUnsavedPageCount() > 1000) {
store.store(); MVTableEngine.store(store);
} }
} }
...@@ -690,4 +681,8 @@ public class MVTable extends TableBase { ...@@ -690,4 +681,8 @@ public class MVTable extends TableBase {
return rowIdColumn; return rowIdColumn;
} }
public String toString() {
return getSQL();
}
} }
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package org.h2.mvstore.db; package org.h2.mvstore.db;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import org.h2.api.TableEngine; import org.h2.api.TableEngine;
...@@ -37,10 +38,14 @@ public class MVTableEngine implements TableEngine { ...@@ -37,10 +38,14 @@ public class MVTableEngine implements TableEngine {
return; return;
} }
// TODO this stores uncommitted transactions as well // TODO this stores uncommitted transactions as well
store.store.store(); store(store.store);
} }
} }
public static Collection<Store> getStores() {
return STORES.values();
}
@Override @Override
public TableBase createTable(CreateTableData data) { public TableBase createTable(CreateTableData data) {
Database db = data.session.getDatabase(); Database db = data.session.getDatabase();
...@@ -73,7 +78,7 @@ public class MVTableEngine implements TableEngine { ...@@ -73,7 +78,7 @@ public class MVTableEngine implements TableEngine {
if (store != null) { if (store != null) {
store.openTables.remove(table); store.openTables.remove(table);
if (store.openTables.size() == 0) { if (store.openTables.size() == 0) {
store.store.store(); store(store.store);
store.store.close(); store.store.close();
STORES.remove(storeName); STORES.remove(storeName);
} }
...@@ -81,10 +86,15 @@ public class MVTableEngine implements TableEngine { ...@@ -81,10 +86,15 @@ public class MVTableEngine implements TableEngine {
} }
} }
static void store(MVStore store) {
store.compact(50);
store.store();
}
/** /**
* A store with open tables. * A store with open tables.
*/ */
static class Store { public static class Store {
final Database db; final Database db;
final MVStore store; final MVStore store;
...@@ -95,6 +105,10 @@ public class MVTableEngine implements TableEngine { ...@@ -95,6 +105,10 @@ public class MVTableEngine implements TableEngine {
this.store = store; this.store = store;
} }
public MVStore getStore() {
return store;
}
} }
} }
...@@ -501,26 +501,6 @@ public class ValueArrayDataType implements DataType { ...@@ -501,26 +501,6 @@ public class ValueArrayDataType implements DataType {
} }
} }
// private void writeStringWithoutLength(char[] chars, int len) {
// int p = pos;
// byte[] buff = data;
// for (int i = 0; i < len; i++) {
// int c = chars[i];
// if (c < 0x80) {
// buff[p++] = (byte) c;
// } else if (c >= 0x800) {
// buff[p++] = (byte) (0xe0 | (c >> 12));
// buff[p++] = (byte) (((c >> 6) & 0x3f));
// buff[p++] = (byte) (c & 0x3f);
// } else {
// buff[p++] = (byte) (0xc0 | (c >> 6));
// buff[p++] = (byte) (c & 0x3f);
// }
// }
// pos = p;
// }
/** /**
* Read a value. * Read a value.
* *
......
...@@ -21,9 +21,9 @@ public class SpatialDataType implements DataType { ...@@ -21,9 +21,9 @@ public class SpatialDataType implements DataType {
private final int dimensions; private final int dimensions;
public SpatialDataType(int dimensions) { public SpatialDataType(int dimensions) {
if (dimensions <= 0 || dimensions > 255) { DataUtils.checkArgument(
throw DataUtils.illegalArgumentException("Dimensions: " + dimensions); dimensions > 1 && dimensions < 256,
} "Dimensions must be between 2 and 255, is {0}", dimensions);
this.dimensions = dimensions; this.dimensions = dimensions;
} }
......
...@@ -139,7 +139,7 @@ public class ObjectDataType implements DataType { ...@@ -139,7 +139,7 @@ public class ObjectDataType implements DataType {
case TYPE_SERIALIZED_OBJECT: case TYPE_SERIALIZED_OBJECT:
return new SerializedObjectType(this); return new SerializedObjectType(this);
} }
throw DataUtils.illegalStateException("Unsupported type: " + typeId); throw DataUtils.newIllegalStateException("Unsupported type {0}", typeId);
} }
@Override @Override
...@@ -192,7 +192,7 @@ public class ObjectDataType implements DataType { ...@@ -192,7 +192,7 @@ public class ObjectDataType implements DataType {
} else if (tag >= TAG_BYTE_ARRAY_0_15 && tag <= TAG_BYTE_ARRAY_0_15 + 15) { } else if (tag >= TAG_BYTE_ARRAY_0_15 && tag <= TAG_BYTE_ARRAY_0_15 + 15) {
typeId = TYPE_BYTE_ARRAY; typeId = TYPE_BYTE_ARRAY;
} else { } else {
throw DataUtils.illegalStateException("Unknown tag: " + tag); throw DataUtils.newIllegalStateException("Unknown tag {0}", tag);
} }
} }
} }
...@@ -241,7 +241,8 @@ public class ObjectDataType implements DataType { ...@@ -241,7 +241,8 @@ public class ObjectDataType implements DataType {
return TYPE_CHARACTER; return TYPE_CHARACTER;
} }
if (obj == null) { if (obj == null) {
throw DataUtils.illegalArgumentException("Null is not supported"); throw DataUtils.newIllegalArgumentException(
"Null is not supported");
} }
return TYPE_SERIALIZED_OBJECT; return TYPE_SERIALIZED_OBJECT;
} }
...@@ -368,7 +369,7 @@ public class ObjectDataType implements DataType { ...@@ -368,7 +369,7 @@ public class ObjectDataType implements DataType {
@Override @Override
public final Object read(ByteBuffer buff) { public final Object read(ByteBuffer buff) {
throw DataUtils.illegalStateException("Internal error"); throw DataUtils.newIllegalStateException("Internal error");
} }
/** /**
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论