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

Spellchecking, javadocs, formatting

上级 a9d41543
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
package org.h2.api; package org.h2.api;
/** /**
* Custom serialization mechanism for java objects being stored in column of type OTHER. * Custom serialization mechanism for java objects being stored in column of
* type OTHER.
* *
* @author Sergi Vladykin * @author Sergi Vladykin
*/ */
...@@ -16,15 +17,15 @@ public interface JavaObjectSerializer { ...@@ -16,15 +17,15 @@ public interface JavaObjectSerializer {
/** /**
* Serialize object to byte array. * Serialize object to byte array.
* *
* @param obj * @param obj the object to serialize
* @return the byte array * @return the byte array of the serialized object
*/ */
byte[] serialize(Object obj) throws Exception; byte[] serialize(Object obj) throws Exception;
/** /**
* Deserialize object from byte array. * Deserialize object from byte array.
* *
* @param bytes * @param bytes the byte array of the serialized object
* @return the object * @return the object
*/ */
Object deserialize(byte[] bytes) throws Exception; Object deserialize(byte[] bytes) throws Exception;
......
...@@ -190,7 +190,7 @@ public class ScriptCommand extends ScriptBase { ...@@ -190,7 +190,7 @@ public class ScriptCommand extends ScriptBase {
Constant constant = (Constant) obj; Constant constant = (Constant) obj;
add(constant.getCreateSQL(), false); add(constant.getCreateSQL(), false);
} }
final ArrayList<Table> tables = db.getAllTablesAndViews(false); final ArrayList<Table> tables = db.getAllTablesAndViews(false);
// sort by id, so that views are after tables and views on views // sort by id, so that views are after tables and views on views
// after the base views // after the base views
...@@ -199,8 +199,8 @@ public class ScriptCommand extends ScriptBase { ...@@ -199,8 +199,8 @@ public class ScriptCommand extends ScriptBase {
return t1.getId() - t2.getId(); return t1.getId() - t2.getId();
} }
}); });
// Generate the DROP XXX ... IF EXISTS // Generate the DROP XXX ... IF EXISTS
for (Table table : tables) { for (Table table : tables) {
if (excludeSchema(table.getSchema())) { if (excludeSchema(table.getSchema())) {
continue; continue;
...@@ -246,8 +246,8 @@ public class ScriptCommand extends ScriptBase { ...@@ -246,8 +246,8 @@ public class ScriptCommand extends ScriptBase {
} }
add(sequence.getCreateSQL(), false); add(sequence.getCreateSQL(), false);
} }
// Generate CREATE TABLE and INSERT...VALUES // Generate CREATE TABLE and INSERT...VALUES
int count = 0; int count = 0;
for (Table table : tables) { for (Table table : tables) {
if (excludeSchema(table.getSchema())) { if (excludeSchema(table.getSchema())) {
...@@ -333,7 +333,7 @@ public class ScriptCommand extends ScriptBase { ...@@ -333,7 +333,7 @@ public class ScriptCommand extends ScriptBase {
} }
add(trigger.getCreateSQL(), false); add(trigger.getCreateSQL(), false);
} }
// Generate GRANT ... // Generate GRANT ...
for (Right right : db.getAllRights()) { for (Right right : db.getAllRights()) {
Table table = right.getGrantedTable(); Table table = right.getGrantedTable();
if (table != null) { if (table != null) {
...@@ -346,7 +346,7 @@ public class ScriptCommand extends ScriptBase { ...@@ -346,7 +346,7 @@ public class ScriptCommand extends ScriptBase {
} }
add(right.getCreateSQL(), false); add(right.getCreateSQL(), false);
} }
// Generate COMMENT ON ... // Generate COMMENT ON ...
for (Comment comment : db.getAllComments()) { for (Comment comment : db.getAllComments()) {
add(comment.getCreateSQL(), false); add(comment.getCreateSQL(), false);
} }
......
...@@ -399,8 +399,9 @@ public class SysProperties { ...@@ -399,8 +399,9 @@ public class SysProperties {
/** /**
* System property <code>h2.javaObjectSerializer</code> (default: null).<br /> * System property <code>h2.javaObjectSerializer</code> (default: null).<br />
* The JavaObjectSerializer class name for java objects being stored in column of type OTHER. * The JavaObjectSerializer class name for java objects being stored in
* It must be the same on client and server to work correctly. * column of type OTHER. It must be the same on client and server to work
* correctly.
*/ */
public static final String JAVA_OBJECT_SERIALIZER = Utils.getProperty("h2.javaObjectSerializer", null); public static final String JAVA_OBJECT_SERIALIZER = Utils.getProperty("h2.javaObjectSerializer", null);
......
...@@ -143,5 +143,5 @@ public class MetaRecord implements Comparable<MetaRecord> { ...@@ -143,5 +143,5 @@ public class MetaRecord implements Comparable<MetaRecord> {
public String toString() { public String toString() {
return "MetaRecord [id=" + id + ", objectType=" + objectType + ", sql=" + sql + "]"; return "MetaRecord [id=" + id + ", objectType=" + objectType + ", sql=" + sql + "]";
} }
} }
...@@ -19,10 +19,11 @@ import org.h2.value.ValueBoolean; ...@@ -19,10 +19,11 @@ import org.h2.value.ValueBoolean;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
/** /**
* Used for optimised IN(...) queries where the contents of the IN list are all constant and of the same type. * Used for optimised IN(...) queries where the contents of the IN list are all
* constant and of the same type.
* <p> * <p>
* Checking using a HashSet is has time complexity O(1), instead of O(n) for checking using * Checking using a HashSet is has time complexity O(1), instead of O(n) for
* an array. * checking using an array.
*/ */
public class ConditionInConstantSet extends Condition { public class ConditionInConstantSet extends Condition {
...@@ -30,10 +31,11 @@ public class ConditionInConstantSet extends Condition { ...@@ -30,10 +31,11 @@ public class ConditionInConstantSet extends Condition {
private int queryLevel; private int queryLevel;
private final ArrayList<Expression> valueList; private final ArrayList<Expression> valueList;
private final HashSet<Value> valueSet; private final HashSet<Value> valueSet;
/** /**
* Create a new IN(..) condition. * Create a new IN(..) condition.
* *
* @param session the session
* @param left the expression before IN * @param left the expression before IN
* @param valueList the value list (at least two elements) * @param valueList the value list (at least two elements)
*/ */
...@@ -55,7 +57,7 @@ public class ConditionInConstantSet extends Condition { ...@@ -55,7 +57,7 @@ public class ConditionInConstantSet extends Condition {
Value firstRightVal = valueSet.iterator().next(); Value firstRightVal = valueSet.iterator().next();
leftVal = leftVal.convertTo(firstRightVal.getType()); leftVal = leftVal.convertTo(firstRightVal.getType());
boolean result = valueSet.contains(leftVal); boolean result = valueSet.contains(leftVal);
if (!result && setHasNull) { if (!result && setHasNull) {
return ValueNull.INSTANCE; return ValueNull.INSTANCE;
} }
......
...@@ -1016,7 +1016,7 @@ CONCAT(string, string [,...]) ...@@ -1016,7 +1016,7 @@ CONCAT(string, string [,...])
"," ","
Combines strings." Combines strings."
"Functions (String)","CONCAT_WS"," "Functions (String)","CONCAT_WS","
CONCAT_WS(string, string, string [,...]) CONCAT_WS(separatorString, string, string [,...])
"," ","
Combines strings with separator." Combines strings with separator."
"Functions (String)","DIFFERENCE"," "Functions (String)","DIFFERENCE","
......
...@@ -1710,8 +1710,8 @@ public class PageStore implements CacheWriter { ...@@ -1710,8 +1710,8 @@ public class PageStore implements CacheWriter {
Table table = index.getTable(); Table table = index.getTable();
if (SysProperties.CHECK) { if (SysProperties.CHECK) {
if (!table.isTemporary()) { if (!table.isTemporary()) {
/* To prevent ABBA locking problems, we need to always take the Database lock before we take the // to prevent ABBA locking problems, we need to always take
* PageStore lock. */ // the Database lock before we take the PageStore lock
synchronized (database) { synchronized (database) {
synchronized (this) { synchronized (this) {
database.verifyMetaLocked(session); database.verifyMetaLocked(session);
...@@ -1764,8 +1764,8 @@ public class PageStore implements CacheWriter { ...@@ -1764,8 +1764,8 @@ public class PageStore implements CacheWriter {
public void removeMeta(Index index, Session session) { public void removeMeta(Index index, Session session) {
if (SysProperties.CHECK) { if (SysProperties.CHECK) {
if (!index.getTable().isTemporary()) { if (!index.getTable().isTemporary()) {
/* To prevent ABBA locking problems, we need to always take the Database lock before we take the // to prevent ABBA locking problems, we need to always take
* PageStore lock. */ // the Database lock before we take the PageStore lock
synchronized (database) { synchronized (database) {
synchronized (this) { synchronized (this) {
database.verifyMetaLocked(session); database.verifyMetaLocked(session);
......
...@@ -216,7 +216,11 @@ class FilePathMemLZF extends FilePathMem { ...@@ -216,7 +216,11 @@ class FilePathMemLZF extends FilePathMem {
*/ */
class FileMem extends FileBase { class FileMem extends FileBase {
/**
* The file data.
*/
final FileMemData data; final FileMemData data;
private final boolean readOnly; private final boolean readOnly;
private long pos; private long pos;
...@@ -352,6 +356,11 @@ class FileMemData { ...@@ -352,6 +356,11 @@ class FileMemData {
lastModified = System.currentTimeMillis(); lastModified = System.currentTimeMillis();
} }
/**
* Lock the file in exclusive mode if possible.
*
* @return if locking was successful
*/
synchronized boolean lockExclusive() { synchronized boolean lockExclusive() {
if (sharedLockCount > 0 || isLockedExclusive) { if (sharedLockCount > 0 || isLockedExclusive) {
return false; return false;
...@@ -360,6 +369,11 @@ class FileMemData { ...@@ -360,6 +369,11 @@ class FileMemData {
return true; return true;
} }
/**
* Lock the file in shared mode if possible.
*
* @return if locking was successful
*/
synchronized boolean lockShared() { synchronized boolean lockShared() {
if (isLockedExclusive) { if (isLockedExclusive) {
return false; return false;
...@@ -368,6 +382,9 @@ class FileMemData { ...@@ -368,6 +382,9 @@ class FileMemData {
return true; return true;
} }
/**
* Unlock the file.
*/
synchronized void unlock() { synchronized void unlock() {
if (isLockedExclusive) { if (isLockedExclusive) {
isLockedExclusive = false; isLockedExclusive = false;
......
...@@ -47,7 +47,8 @@ public class TableView extends Table { ...@@ -47,7 +47,8 @@ public class TableView extends Table {
private ViewIndex index; private ViewIndex index;
private boolean recursive; private boolean recursive;
private DbException createException; private DbException createException;
private final SmallLRUCache<IntArray, ViewIndex> indexCache = SmallLRUCache.newInstance(Constants.VIEW_INDEX_CACHE_SIZE); private final SmallLRUCache<IntArray, ViewIndex> indexCache =
SmallLRUCache.newInstance(Constants.VIEW_INDEX_CACHE_SIZE);
private long lastModificationCheck; private long lastModificationCheck;
private long maxDataModificationId; private long maxDataModificationId;
private User owner; private User owner;
......
...@@ -31,6 +31,9 @@ import org.h2.message.DbException; ...@@ -31,6 +31,9 @@ import org.h2.message.DbException;
*/ */
public class Utils { public class Utils {
/**
* The serializer to use.
*/
public static JavaObjectSerializer serializer; public static JavaObjectSerializer serializer;
/** /**
......
...@@ -321,7 +321,7 @@ public class TestOptimizations extends TestBase { ...@@ -321,7 +321,7 @@ public class TestOptimizations extends TestBase {
conn.close(); conn.close();
} }
private void testNestedInSelect() throws SQLException { private void testNestedInSelect() throws SQLException {
deleteDb("optimizations"); deleteDb("optimizations");
Connection conn = getConnection("optimizations"); Connection conn = getConnection("optimizations");
......
...@@ -335,7 +335,7 @@ public class TestStatement extends TestBase { ...@@ -335,7 +335,7 @@ public class TestStatement extends TestBase {
rs.next(); rs.next();
assertEquals(7, rs.getInt(1)); assertEquals(7, rs.getInt(1));
assertFalse(rs.next()); assertFalse(rs.next());
stat.execute("CREATE TABLE TEST2(ID identity primary key)"); stat.execute("CREATE TABLE TEST2(ID identity primary key)");
stat.execute("INSERT INTO TEST2 VALUES()"); stat.execute("INSERT INTO TEST2 VALUES()");
stat.execute("SET @X = IDENTITY()"); stat.execute("SET @X = IDENTITY()");
......
...@@ -47,7 +47,7 @@ public class TestStreamStore extends TestBase { ...@@ -47,7 +47,7 @@ public class TestStreamStore extends TestBase {
testLoop(); testLoop();
} }
public void testDetectIllegalId() throws IOException { private void testDetectIllegalId() throws IOException {
Map<Long, byte[]> map = New.hashMap(); Map<Long, byte[]> map = New.hashMap();
StreamStore store = new StreamStore(map); StreamStore store = new StreamStore(map);
try { try {
...@@ -72,7 +72,7 @@ public class TestStreamStore extends TestBase { ...@@ -72,7 +72,7 @@ public class TestStreamStore extends TestBase {
} }
} }
public void testTreeStructure() throws IOException { private void testTreeStructure() throws IOException {
final AtomicInteger reads = new AtomicInteger(); final AtomicInteger reads = new AtomicInteger();
Map<Long, byte[]> map = new HashMap<Long, byte[]>() { Map<Long, byte[]> map = new HashMap<Long, byte[]>() {
...@@ -95,7 +95,7 @@ public class TestStreamStore extends TestBase { ...@@ -95,7 +95,7 @@ public class TestStreamStore extends TestBase {
assertEquals(3, reads.get()); assertEquals(3, reads.get());
} }
public void testFormat() throws IOException { private void testFormat() throws IOException {
Map<Long, byte[]> map = New.hashMap(); Map<Long, byte[]> map = New.hashMap();
StreamStore store = new StreamStore(map); StreamStore store = new StreamStore(map);
store.setMinBlockSize(10); store.setMinBlockSize(10);
...@@ -128,7 +128,7 @@ public class TestStreamStore extends TestBase { ...@@ -128,7 +128,7 @@ public class TestStreamStore extends TestBase {
assertEquals(1, in.skip(1)); assertEquals(1, in.skip(1));
} }
public void testWithExistingData() throws IOException { private void testWithExistingData() throws IOException {
final AtomicInteger tests = new AtomicInteger(); final AtomicInteger tests = new AtomicInteger();
Map<Long, byte[]> map = new HashMap<Long, byte[]>() { Map<Long, byte[]> map = new HashMap<Long, byte[]>() {
...@@ -170,7 +170,7 @@ public class TestStreamStore extends TestBase { ...@@ -170,7 +170,7 @@ public class TestStreamStore extends TestBase {
} }
} }
public void testWithFullMap() throws IOException { private void testWithFullMap() throws IOException {
final AtomicInteger tests = new AtomicInteger(); final AtomicInteger tests = new AtomicInteger();
Map<Long, byte[]> map = new HashMap<Long, byte[]>() { Map<Long, byte[]> map = new HashMap<Long, byte[]>() {
...@@ -196,7 +196,7 @@ public class TestStreamStore extends TestBase { ...@@ -196,7 +196,7 @@ public class TestStreamStore extends TestBase {
assertEquals(Long.MAX_VALUE / 2 + 1, store.getNextKey()); assertEquals(Long.MAX_VALUE / 2 + 1, store.getNextKey());
} }
public void testLoop() throws IOException { private void testLoop() throws IOException {
Map<Long, byte[]> map = New.hashMap(); Map<Long, byte[]> map = New.hashMap();
StreamStore store = new StreamStore(map); StreamStore store = new StreamStore(map);
assertEquals(256 * 1024, store.getMaxBlockSize()); assertEquals(256 * 1024, store.getMaxBlockSize());
......
...@@ -33,8 +33,16 @@ public class SpellChecker { ...@@ -33,8 +33,16 @@ public class SpellChecker {
private static final String PREFIX_IGNORE = "abc"; private static final String PREFIX_IGNORE = "abc";
private static final String[] IGNORE_FILES = {"mainWeb.html", "pg_catalog.sql"}; private static final String[] IGNORE_FILES = {"mainWeb.html", "pg_catalog.sql"};
// these are public so we can set them during development testing // These are public so we can set them during development testing
/**
* Whether debugging is enabled.
*/
public boolean debug; public boolean debug;
/**
* Whether to print the dictionary.
*/
public boolean printDictionary; public boolean printDictionary;
private final HashSet<String> dictionary = new HashSet<String>(); private final HashSet<String> dictionary = new HashSet<String>();
......
...@@ -714,10 +714,9 @@ derive bounding greatly extreme terribly iterating pruned percentage ...@@ -714,10 +714,9 @@ derive bounding greatly extreme terribly iterating pruned percentage
apart render cloned costly antialiasing antialias quercus rect mvr retina apart render cloned costly antialiasing antialias quercus rect mvr retina
sonatype deployed uffff bhat prashant doug lea retained inefficient segments sonatype deployed uffff bhat prashant doug lea retained inefficient segments
segment supplemental adjust evenly pick diehard mixes avalanche candidates segment supplemental adjust evenly pick diehard mixes avalanche candidates
edition voytovych intersecting cow absent hickey fluid chen qian liberal edition voytovych intersecting cow absent hickey fluid chen qian liberal
richard viktor structured continuous inherent kyoto contends abba optimised richard viktor structured continuous inherent kyoto contends abba optimised
rollbacks overtaking trivial mutation pitest rectangle uncommon deltas rollbacks overtaking trivial mutation pitest rectangle uncommon deltas
purely intersection obviously cabinet berkeley configurable modular locality purely intersection obviously cabinet berkeley configurable modular locality
subsystem persisting pit jdbm bigserial rtree mutationtest serializer feff mvstore subsystem persisting pit jdbm bigserial rtree mutationtest serializer feff mvstore
versioning versioning sector survives
\ No newline at end of file
...@@ -71,11 +71,18 @@ public class Chunk { ...@@ -71,11 +71,18 @@ public class Chunk {
*/ */
long version; long version;
public Chunk(int id) { Chunk(int id) {
this.id = id; this.id = id;
} }
public static Chunk fromHeader(ByteBuffer buff, long start) { /**
* Read the header from the byte buffer.
*
* @param buff the source buffer
* @param start the start of the chunk in the file
* @return the chunk
*/
static Chunk fromHeader(ByteBuffer buff, long start) {
if (buff.get() != 'c') { if (buff.get() != 'c') {
throw new RuntimeException("File corrupt"); throw new RuntimeException("File corrupt");
} }
...@@ -95,6 +102,11 @@ public class Chunk { ...@@ -95,6 +102,11 @@ public class Chunk {
return c; return c;
} }
/**
* Write the header.
*
* @param buff the target buffer
*/
void writeHeader(ByteBuffer buff) { void writeHeader(ByteBuffer buff) {
buff.put((byte) 'c'); buff.put((byte) 'c');
buff.putInt(length); buff.putInt(length);
...@@ -137,6 +149,11 @@ public class Chunk { ...@@ -137,6 +149,11 @@ public class Chunk {
return o instanceof Chunk && ((Chunk) o).id == id; return o instanceof Chunk && ((Chunk) o).id == id;
} }
/**
* Get the chunk data as a string.
*
* @return the string
*/
public String asString() { public String asString() {
return return
"id:" + id + "," + "id:" + id + "," +
......
...@@ -44,6 +44,12 @@ public class Cursor<K> implements Iterator<K> { ...@@ -44,6 +44,12 @@ public class Cursor<K> implements Iterator<K> {
return current != null; return current != null;
} }
/**
* Skip over that many entries. This method is relatively fast (for this map
* implementation) even if many entries need to be skipped.
*
* @param n the number of entries to skip
*/
public void skip(long n) { public void skip(long n) {
if (!hasNext()) { if (!hasNext()) {
return; return;
...@@ -64,6 +70,13 @@ public class Cursor<K> implements Iterator<K> { ...@@ -64,6 +70,13 @@ public class Cursor<K> implements Iterator<K> {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/**
* Fetch the next entry that is equal or larger than the given key, starting
* from the given page.
*
* @param p the page to start
* @param from the key to search
*/
protected void min(Page p, K from) { protected void min(Page p, K from) {
while (true) { while (true) {
if (p.isLeaf()) { if (p.isLeaf()) {
...@@ -85,6 +98,9 @@ public class Cursor<K> implements Iterator<K> { ...@@ -85,6 +98,9 @@ public class Cursor<K> implements Iterator<K> {
} }
} }
/**
* Fetch the next entry if there is one.
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected void fetchNext() { protected void fetchNext() {
while (pos != null) { while (pos != null) {
......
...@@ -301,6 +301,7 @@ public class DataUtils { ...@@ -301,6 +301,7 @@ public class DataUtils {
* has been reached. The buffer is rewind at the end. * has been reached. The buffer is rewind at the end.
* *
* @param file the file channel * @param file the file channel
* @param pos the absolute position within the file
* @param dst the byte buffer * @param dst the byte buffer
*/ */
public static void readFully(FileChannel file, long pos, ByteBuffer dst) throws IOException { public static void readFully(FileChannel file, long pos, ByteBuffer dst) throws IOException {
...@@ -318,6 +319,7 @@ public class DataUtils { ...@@ -318,6 +319,7 @@ public class DataUtils {
* Write to a file channel. * Write to a file channel.
* *
* @param file the file channel * @param file the file channel
* @param pos the absolute position within the file
* @param src the source buffer * @param src the source buffer
*/ */
public static void writeFully(FileChannel file, long pos, ByteBuffer src) throws IOException { public static void writeFully(FileChannel file, long pos, ByteBuffer src) throws IOException {
......
...@@ -54,6 +54,12 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -54,6 +54,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
this.root = Page.createEmpty(this, -1); this.root = Page.createEmpty(this, -1);
} }
/**
* Open this map with the given store and configuration.
*
* @param store the store
* @param config the configuration
*/
public void open(MVStore store, HashMap<String, String> config) { public void open(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"));
...@@ -450,7 +456,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -450,7 +456,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* Remove all entries, and close the map. * Remove all entries, and close the map.
*/ */
public void removeMap() { public void removeMap() {
if (!store.isMetaMap(this)) { if (this != store.getMetaMap()) {
checkWrite(); checkWrite();
root.removeAllRecursive(); root.removeAllRecursive();
store.removeMap(name); store.removeMap(name);
...@@ -492,6 +498,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -492,6 +498,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* Add a key-value pair if it does not yet exist. * Add a key-value pair if it does not yet exist.
* *
* @param key the key (may not be null) * @param key the key (may not be null)
* @param value the new value
* @return the old value if the key existed, or null otherwise * @return the old value if the key existed, or null otherwise
*/ */
public synchronized V putIfAbsent(K key, V value) { public synchronized V putIfAbsent(K key, V value) {
...@@ -599,6 +606,11 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -599,6 +606,11 @@ public class MVMap<K, V> extends AbstractMap<K, V>
return result; return result;
} }
/**
* Use the new root page from now on.
*
* @param newRoot the new root page
*/
protected void newRoot(Page newRoot) { protected void newRoot(Page newRoot) {
if (root != newRoot) { if (root != newRoot) {
removeUnusedOldVersions(); removeUnusedOldVersions();
...@@ -907,6 +919,11 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -907,6 +919,11 @@ public class MVMap<K, V> extends AbstractMap<K, V>
return m; return m;
} }
/**
* Open a copy of the map in read-only mode.
*
* @return the opened map
*/
protected MVMap<K, V> openReadOnly() { protected MVMap<K, V> openReadOnly() {
MVMap<K, V> m = new MVMap<K, V>(keyType, valueType); MVMap<K, V> m = new MVMap<K, V>(keyType, valueType);
m.readOnly = true; m.readOnly = true;
...@@ -939,6 +956,14 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -939,6 +956,14 @@ public class MVMap<K, V> extends AbstractMap<K, V>
return root.getVersion(); return root.getVersion();
} }
/**
* Get the child page count for this page. This is to allow another map
* implementation to override the default, in case the last child is not to
* be used.
*
* @param p the page
* @return the number of direct children
*/
protected int getChildPageCount(Page p) { protected int getChildPageCount(Page p) {
return p.getChildPageCount(); return p.getChildPageCount();
} }
...@@ -952,6 +977,11 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -952,6 +977,11 @@ public class MVMap<K, V> extends AbstractMap<K, V>
return "btree"; return "btree";
} }
/**
* Get the map metadata as a string.
*
* @return the string
*/
public String asString() { public String asString() {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
DataUtils.appendMap(buff, "id", id); DataUtils.appendMap(buff, "id", id);
......
...@@ -43,12 +43,14 @@ TODO: ...@@ -43,12 +43,14 @@ TODO:
- support serialization by default - support serialization by default
- build script - build script
- test concurrent storing in a background thread - test concurrent storing in a background thread
- store store creation in file header, and seconds since creation in chunk header (plus a counter) - store store creation in file header, and seconds since creation
- recovery: keep some old chunks; don't overwritten for 5 minutes (configurable) -- in chunk header (plus a counter)
- recovery: keep some old chunks; don't overwritten
-- for 5 minutes (configurable)
- allocate memory with Utils.newBytes and so on - allocate memory with Utils.newBytes and so on
- unified exception handling - unified exception handling
- concurrent map; avoid locking during IO (pre-load pages) - concurrent map; avoid locking during IO (pre-load pages)
- maybe split database into multiple files, to speed up compact operation - maybe split database into multiple files, to speed up compact
- automated 'kill process' and 'power failure' test - automated 'kill process' and 'power failure' test
- implement table engine for H2 - implement table engine for H2
- auto-compact from time to time and on close - auto-compact from time to time and on close
...@@ -56,13 +58,15 @@ TODO: ...@@ -56,13 +58,15 @@ TODO:
- support background writes (concurrent modification & store) - support background writes (concurrent modification & store)
- limited support for writing to old versions (branches) - limited support for writing to old versions (branches)
- support concurrent operations (including file I/O) - support concurrent operations (including file I/O)
- on insert, if the child page is already full, don't load and modify it - split directly (for leaves with 1 entry) - on insert, if the child page is already full, don't load and modify it
-- split directly (for leaves with 1 entry)
- performance test with encrypting file system - performance test with encrypting file system
- possibly split chunk data into immutable and mutable - possibly split chunk data into immutable and mutable
- compact: avoid processing pages using a counting bloom filter - compact: avoid processing pages using a counting bloom filter
- defragment (re-creating maps, specially those with small pages) - defragment (re-creating maps, specially those with small pages)
- write using ByteArrayOutputStream; remove DataType.getMaxLength - write using ByteArrayOutputStream; remove DataType.getMaxLength
- file header: check formatRead and format (is formatRead needed if equal to format?) - file header: check formatRead and format (is formatRead
-- needed if equal to format?)
- chunk header: store changed chunk data as row; maybe after the root - chunk header: store changed chunk data as row; maybe after the root
- chunk checksum (header, last page, 2 bytes per page?) - chunk checksum (header, last page, 2 bytes per page?)
- allow renaming maps - allow renaming maps
...@@ -70,16 +74,22 @@ TODO: ...@@ -70,16 +74,22 @@ TODO:
- online backup - online backup
- MapFactory is the wrong name (StorePlugin?) or is too flexible: remove? - MapFactory is the wrong name (StorePlugin?) or is too flexible: remove?
- store file "header" at the end of each chunk; at the end of the file - store file "header" at the end of each chunk; at the end of the file
- is there a better name for the file header, if it's no longer always at the beginning of a file? - is there a better name for the file header,
- maybe let a chunk point to possible next chunks (so no fixed location header is needed) -- if it's no longer always at the beginning of a file?
- maybe let a chunk point to possible next chunks
-- (so no fixed location header is needed)
- support stores that span multiple files (chunks stored in other files) - support stores that span multiple files (chunks stored in other files)
- triggers (can be implemented with a custom map) - triggers (can be implemented with a custom map)
- store write operations per page (maybe defragment if much different than count) - store write operations per page (maybe defragment
-- if much different than count)
- r-tree: nearest neighbor search - r-tree: nearest neighbor search
- use FileChannel by default (nio file system), but: an interrupt close the FileChannel - use FileChannel by default (nio file system), but:
- auto-save temporary data if it uses too much memory, but revert it on startup if needed. -- an interrupt close the FileChannel
- auto-save temporary data if it uses too much memory,
-- but revert it on startup if needed.
- map and chunk metadata: do not store default values - map and chunk metadata: do not store default values
- support maps without values (non-unique indexes), and maps without keys (counted b-tree) - support maps without values (non-unique indexes),
- and maps without keys (counted b-tree)
- use a small object cache (StringCache) - use a small object cache (StringCache)
- dump values - dump values
- tool to import / manipulate CSV files - tool to import / manipulate CSV files
...@@ -96,6 +106,10 @@ public class MVStore { ...@@ -96,6 +106,10 @@ public class MVStore {
*/ */
public static final boolean ASSERT = false; public static final boolean ASSERT = false;
/**
* The block size (physical sector size) of the disk. The file header is
* written twice, one copy in each block, to ensure it survives a crash.
*/
static final int BLOCK_SIZE = 4 * 1024; static final int BLOCK_SIZE = 4 * 1024;
private final HashMap<String, Object> config; private final HashMap<String, Object> config;
...@@ -192,6 +206,7 @@ public class MVStore { ...@@ -192,6 +206,7 @@ public class MVStore {
* *
* @param version the version * @param version the version
* @param name the map name * @param name the map name
* @param template the template map
* @return the read-only map * @return the read-only map
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
...@@ -326,10 +341,6 @@ public class MVStore { ...@@ -326,10 +341,6 @@ public class MVStore {
mapsChanged.remove(map.getId()); mapsChanged.remove(map.getId());
} }
boolean isMetaMap(MVMap<?, ?> map) {
return map == meta;
}
private DataType getDataType(Class<?> clazz) { private DataType getDataType(Class<?> clazz) {
if (clazz == String.class) { if (clazz == String.class) {
return StringType.INSTANCE; return StringType.INSTANCE;
...@@ -351,6 +362,9 @@ public class MVStore { ...@@ -351,6 +362,9 @@ public class MVStore {
mapsChanged.put(map.getId(), map); mapsChanged.put(map.getId(), map);
} }
/**
* Open the store.
*/
void open() { void open() {
meta = new MVMap<String, String>(StringType.INSTANCE, StringType.INSTANCE); meta = new MVMap<String, String>(StringType.INSTANCE, StringType.INSTANCE);
HashMap<String, String> c = New.hashMap(); HashMap<String, String> c = New.hashMap();
...@@ -1090,6 +1104,9 @@ public class MVStore { ...@@ -1090,6 +1104,9 @@ public class MVStore {
return unsavedPageCount; return unsavedPageCount;
} }
/**
* Increment the number of unsaved pages.
*/
void registerUnsavedPage() { void registerUnsavedPage() {
unsavedPageCount++; unsavedPageCount++;
} }
......
...@@ -75,6 +75,12 @@ public class MVStoreBuilder { ...@@ -75,6 +75,12 @@ public class MVStoreBuilder {
return set("cacheSize", Integer.toString(mb)); return set("cacheSize", Integer.toString(mb));
} }
/**
* Use the given data type factory.
*
* @param factory the data type factory
* @return this
*/
public MVStoreBuilder with(DataTypeFactory factory) { public MVStoreBuilder with(DataTypeFactory factory) {
return set("dataTypeFactory", factory); return set("dataTypeFactory", factory);
} }
...@@ -94,6 +100,12 @@ public class MVStoreBuilder { ...@@ -94,6 +100,12 @@ public class MVStoreBuilder {
return DataUtils.appendMap(new StringBuilder(), config).toString(); return DataUtils.appendMap(new StringBuilder(), config).toString();
} }
/**
* Read the configuration from a string.
*
* @param s the string representation
* @return the builder
*/
public static MVStoreBuilder fromString(String s) { public static MVStoreBuilder fromString(String s) {
HashMap<String, String> config = DataUtils.parseMap(s); HashMap<String, String> config = DataUtils.parseMap(s);
MVStoreBuilder builder = new MVStoreBuilder(); MVStoreBuilder builder = new MVStoreBuilder();
......
...@@ -94,6 +94,7 @@ public class Page { ...@@ -94,6 +94,7 @@ public class Page {
* @param counts the children counts * @param counts the children counts
* @param totalCount the total number of keys * @param totalCount the total number of keys
* @param sharedFlags which arrays are shared * @param sharedFlags which arrays are shared
* @param memory the memory used in bytes
* @return the page * @return the page
*/ */
public static Page create(MVMap<?, ?> map, long version, public static Page create(MVMap<?, ?> map, long version,
...@@ -119,8 +120,9 @@ public class Page { ...@@ -119,8 +120,9 @@ public class Page {
* *
* @param file the file * @param file the file
* @param map the map * @param map the map
* @param filePos the position in the file
* @param pos the page position * @param pos the page position
* @param filePos the position in the file
* @param fileSize the file size (to avoid reading past EOF)
* @return the page * @return the page
*/ */
static Page read(FileChannel file, MVMap<?, ?> map, static Page read(FileChannel file, MVMap<?, ?> map,
...@@ -414,6 +416,12 @@ public class Page { ...@@ -414,6 +416,12 @@ public class Page {
return totalCount; return totalCount;
} }
/**
* Get the descendant counts for the given child.
*
* @param index the child index
* @return the descendant count
*/
long getCounts(int index) { long getCounts(int index) {
return counts[index]; return counts[index];
} }
...@@ -633,6 +641,14 @@ public class Page { ...@@ -633,6 +641,14 @@ public class Page {
} }
} }
/**
* Read the page from the buffer.
*
* @param buff the buffer
* @param chunkId the chunk id
* @param offset the offset within the chunk
* @param maxLength the maximum length
*/
void read(ByteBuffer buff, int chunkId, int offset, int maxLength) { void read(ByteBuffer buff, int chunkId, int offset, int maxLength) {
int start = buff.position(); int start = buff.position();
int pageLength = buff.getInt(); int pageLength = buff.getInt();
......
...@@ -263,6 +263,12 @@ public class StreamStore { ...@@ -263,6 +263,12 @@ public class StreamStore {
return new Stream(this, id); return new Stream(this, id);
} }
/**
* Get the block.
*
* @param key the key
* @return the block
*/
byte[] getBlock(long key) { byte[] getBlock(long key) {
return map.get(key); return map.get(key);
} }
......
...@@ -22,7 +22,11 @@ import org.h2.util.New; ...@@ -22,7 +22,11 @@ import org.h2.util.New;
*/ */
public class MVRTreeMap<V> extends MVMap<SpatialKey, V> { public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
/**
* The spatial key type.
*/
final SpatialType keyType; final SpatialType keyType;
private boolean quadraticSplit; private boolean quadraticSplit;
public MVRTreeMap(int dimensions, DataType valueType) { public MVRTreeMap(int dimensions, DataType valueType) {
...@@ -30,6 +34,14 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> { ...@@ -30,6 +34,14 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
this.keyType = (SpatialType) getKeyType(); this.keyType = (SpatialType) getKeyType();
} }
/**
* Create a new map with the given dimensions and value type.
*
* @param <V> the value type
* @param dimensions the number of dimensions
* @param valueType the value type
* @return the map
*/
public static <V> MVRTreeMap<V> create(int dimensions, DataType valueType) { public static <V> MVRTreeMap<V> create(int dimensions, DataType valueType) {
return new MVRTreeMap<V>(dimensions, valueType); return new MVRTreeMap<V>(dimensions, valueType);
} }
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version 1.0,
and under the Eclipse Public License, Version 1.0
(http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Javadoc package documentation
</title></head><body style="font: 9pt/130% Tahoma, Arial, Helvetica, sans-serif; font-weight: normal;"><p>
An R-tree implementation
</p></body></html>
\ No newline at end of file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version 1.0,
and under the Eclipse Public License, Version 1.0
(http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Javadoc package documentation
</title></head><body style="font: 9pt/130% Tahoma, Arial, Helvetica, sans-serif; font-weight: normal;"><p>
Data types and serialization / deserialization
</p></body></html>
\ No newline at end of file
...@@ -32,8 +32,8 @@ public class ClassUtils { ...@@ -32,8 +32,8 @@ public class ClassUtils {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T newObject(Class<T> clazz) { public static <T> T newObject(Class<T> clazz) {
// must create new instances, cannot use methods like Boolean.FALSE, since the caller relies // must create new instances, cannot use methods like Boolean.FALSE,
// on this creating unique objects // since the caller relies on this creating unique objects
if (clazz == Integer.class) { if (clazz == Integer.class) {
return (T) new Integer((int) COUNTER.getAndIncrement()); return (T) new Integer((int) COUNTER.getAndIncrement());
} else if (clazz == String.class) { } else if (clazz == String.class) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论