Unverified 提交 06da38de authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #1025 from katzyn/BitSet

Remove BitField and replace its usages with BitSet
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*/ */
package org.h2.command.dml; package org.h2.command.dml;
import java.util.BitSet;
import java.util.Random; import java.util.Random;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -13,7 +14,6 @@ import org.h2.expression.Expression; ...@@ -13,7 +14,6 @@ import org.h2.expression.Expression;
import org.h2.table.Plan; import org.h2.table.Plan;
import org.h2.table.PlanItem; import org.h2.table.PlanItem;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.util.BitField;
import org.h2.util.Permutations; import org.h2.util.Permutations;
/** /**
...@@ -26,7 +26,7 @@ class Optimizer { ...@@ -26,7 +26,7 @@ class Optimizer {
private static final int MAX_BRUTE_FORCE = 2000; private static final int MAX_BRUTE_FORCE = 2000;
private static final int MAX_GENETIC = 500; private static final int MAX_GENETIC = 500;
private long startNs; private long startNs;
private BitField switched; private BitSet switched;
// possible plans for filters, if using brute force: // possible plans for filters, if using brute force:
// 1 filter 1 plan // 1 filter 1 plan
...@@ -163,13 +163,13 @@ class Optimizer { ...@@ -163,13 +163,13 @@ class Optimizer {
} }
} }
if (generateRandom) { if (generateRandom) {
switched = new BitField(); switched = new BitSet();
System.arraycopy(filters, 0, best, 0, filters.length); System.arraycopy(filters, 0, best, 0, filters.length);
shuffleAll(best); shuffleAll(best);
System.arraycopy(best, 0, list, 0, filters.length); System.arraycopy(best, 0, list, 0, filters.length);
} }
if (testPlan(list)) { if (testPlan(list)) {
switched = new BitField(); switched = new BitSet();
System.arraycopy(list, 0, best, 0, filters.length); System.arraycopy(list, 0, best, 0, filters.length);
} }
} }
......
...@@ -8,6 +8,7 @@ package org.h2.engine; ...@@ -8,6 +8,7 @@ package org.h2.engine;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
...@@ -64,7 +65,6 @@ import org.h2.table.TableType; ...@@ -64,7 +65,6 @@ import org.h2.table.TableType;
import org.h2.table.TableView; import org.h2.table.TableView;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Server; import org.h2.tools.Server;
import org.h2.util.BitField;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.NetUtils; import org.h2.util.NetUtils;
...@@ -123,7 +123,7 @@ public class Database implements DataHandler { ...@@ -123,7 +123,7 @@ public class Database implements DataHandler {
private final Set<Session> userSessions = private final Set<Session> userSessions =
Collections.synchronizedSet(new HashSet<Session>()); Collections.synchronizedSet(new HashSet<Session>());
private final AtomicReference<Session> exclusiveSession = new AtomicReference<>(); private final AtomicReference<Session> exclusiveSession = new AtomicReference<>();
private final BitField objectIds = new BitField(); private final BitSet objectIds = new BitSet();
private final Object lobSyncObject = new Object(); private final Object lobSyncObject = new Object();
private Schema mainSchema; private Schema mainSchema;
...@@ -792,7 +792,7 @@ public class Database implements DataHandler { ...@@ -792,7 +792,7 @@ public class Database implements DataHandler {
} }
// mark all ids used in the page store // mark all ids used in the page store
if (pageStore != null) { if (pageStore != null) {
BitField f = pageStore.getObjectIds(); BitSet f = pageStore.getObjectIds();
for (int i = 0, len = f.length(); i < len; i++) { for (int i = 0, len = f.length(); i < len; i++) {
if (f.get(i) && !objectIds.get(i)) { if (f.get(i) && !objectIds.get(i)) {
trace.info("unused object id: " + i); trace.info("unused object id: " + i);
......
...@@ -22,6 +22,7 @@ import java.sql.SQLException; ...@@ -22,6 +22,7 @@ import java.sql.SQLException;
import java.sql.SQLXML; import java.sql.SQLXML;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.BitSet;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
...@@ -29,7 +30,6 @@ import org.h2.api.ErrorCode; ...@@ -29,7 +30,6 @@ import org.h2.api.ErrorCode;
import org.h2.expression.ParameterInterface; import org.h2.expression.ParameterInterface;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.message.TraceObject; import org.h2.message.TraceObject;
import org.h2.util.BitField;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
/** /**
...@@ -41,7 +41,7 @@ import org.h2.value.ValueNull; ...@@ -41,7 +41,7 @@ import org.h2.value.ValueNull;
public class JdbcCallableStatement extends JdbcPreparedStatement implements public class JdbcCallableStatement extends JdbcPreparedStatement implements
CallableStatement, JdbcCallableStatementBackwardsCompat { CallableStatement, JdbcCallableStatementBackwardsCompat {
private BitField outParameters; private BitSet outParameters;
private int maxOutParameters; private int maxOutParameters;
private HashMap<String, Integer> namedParameters; private HashMap<String, Integer> namedParameters;
...@@ -1637,7 +1637,7 @@ public class JdbcCallableStatement extends JdbcPreparedStatement implements ...@@ -1637,7 +1637,7 @@ public class JdbcCallableStatement extends JdbcPreparedStatement implements
maxOutParameters = Math.min( maxOutParameters = Math.min(
getParameterMetaData().getParameterCount(), getParameterMetaData().getParameterCount(),
getCheckedMetaData().getColumnCount()); getCheckedMetaData().getColumnCount());
outParameters = new BitField(); outParameters = new BitSet();
} }
checkIndexBounds(parameterIndex); checkIndexBounds(parameterIndex);
ParameterInterface param = command.getParameters().get(--parameterIndex); ParameterInterface param = command.getParameters().get(--parameterIndex);
......
...@@ -9,6 +9,7 @@ import java.io.InputStream; ...@@ -9,6 +9,7 @@ import java.io.InputStream;
import java.lang.Thread.UncaughtExceptionHandler; import java.lang.Thread.UncaughtExceptionHandler;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -33,7 +34,6 @@ import org.h2.store.InDoubtTransaction; ...@@ -33,7 +34,6 @@ import org.h2.store.InDoubtTransaction;
import org.h2.store.fs.FileChannelInputStream; import org.h2.store.fs.FileChannelInputStream;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.table.TableBase; import org.h2.table.TableBase;
import org.h2.util.BitField;
import org.h2.util.New; import org.h2.util.New;
/** /**
...@@ -263,7 +263,7 @@ public class MVTableEngine implements TableEngine { ...@@ -263,7 +263,7 @@ public class MVTableEngine implements TableEngine {
* *
* @param objectIds the ids of the objects to keep * @param objectIds the ids of the objects to keep
*/ */
public void removeTemporaryMaps(BitField objectIds) { public void removeTemporaryMaps(BitSet objectIds) {
for (String mapName : store.getMapNames()) { for (String mapName : store.getMapNames()) {
if (mapName.startsWith("temp.")) { if (mapName.startsWith("temp.")) {
MVMap<?, ?> map = store.openMap(mapName); MVMap<?, ?> map = store.openMap(mapName);
......
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
*/ */
package org.h2.store; package org.h2.store;
import java.util.BitSet;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.util.BitField;
/** /**
* The list of free pages of a page store. The format of a free list trunk page * The list of free pages of a page store. The format of a free list trunk page
...@@ -22,18 +23,17 @@ public class PageFreeList extends Page { ...@@ -22,18 +23,17 @@ public class PageFreeList extends Page {
private static final int DATA_START = 3; private static final int DATA_START = 3;
private final PageStore store; private final PageStore store;
private final BitField used; private final BitSet used;
private final int pageCount; private final int pageCount;
private boolean full; private boolean full;
private Data data; private Data data;
private PageFreeList(PageStore store, int pageId) { private PageFreeList(PageStore store, int pageId, int pageCount, BitSet used) {
// kept in cache, and array list in page store // kept in cache, and array list in page store
setPos(pageId); setPos(pageId);
this.store = store; this.store = store;
pageCount = (store.getPageSize() - DATA_START) * 8; this.pageCount = pageCount;
used = new BitField(pageCount); this.used = used;
used.set(0);
} }
/** /**
...@@ -45,9 +45,15 @@ public class PageFreeList extends Page { ...@@ -45,9 +45,15 @@ public class PageFreeList extends Page {
* @return the page * @return the page
*/ */
static PageFreeList read(PageStore store, Data data, int pageId) { static PageFreeList read(PageStore store, Data data, int pageId) {
PageFreeList p = new PageFreeList(store, pageId); data.reset();
data.readByte();
data.readShortInt();
int length = store.getPageSize() - DATA_START;
byte[] b = new byte[length];
data.read(b, 0, b.length);
PageFreeList p = new PageFreeList(store, pageId, length * 8, BitSet.valueOf(b));
p.data = data; p.data = data;
p.read(); p.full = false;
return p; return p;
} }
...@@ -59,7 +65,10 @@ public class PageFreeList extends Page { ...@@ -59,7 +65,10 @@ public class PageFreeList extends Page {
* @return the page * @return the page
*/ */
static PageFreeList create(PageStore store, int pageId) { static PageFreeList create(PageStore store, int pageId) {
return new PageFreeList(store, pageId); int pageCount = (store.getPageSize() - DATA_START) * 8;
BitSet used = new BitSet(pageCount);
used.set(0);
return new PageFreeList(store, pageId, pageCount, used);
} }
/** /**
...@@ -69,7 +78,7 @@ public class PageFreeList extends Page { ...@@ -69,7 +78,7 @@ public class PageFreeList extends Page {
* @param first the first page to look for * @param first the first page to look for
* @return the page, or -1 if all pages are used * @return the page, or -1 if all pages are used
*/ */
int allocate(BitField exclude, int first) { int allocate(BitSet exclude, int first) {
if (full) { if (full) {
return -1; return -1;
} }
...@@ -152,27 +161,17 @@ public class PageFreeList extends Page { ...@@ -152,27 +161,17 @@ public class PageFreeList extends Page {
store.update(this); store.update(this);
} }
/**
* Read the page from the disk.
*/
private void read() {
data.reset();
data.readByte();
data.readShortInt();
for (int i = 0; i < pageCount; i += 8) {
int x = data.readByte() & 255;
used.setByte(i, x);
}
full = false;
}
@Override @Override
public void write() { public void write() {
data = store.createData(); data = store.createData();
data.writeByte((byte) Page.TYPE_FREE_LIST); data.writeByte((byte) Page.TYPE_FREE_LIST);
data.writeShortInt(0); data.writeShortInt(0);
for (int i = 0; i < pageCount; i += 8) { int cnt = pageCount >>> 3;
data.writeByte((byte) used.getByte(i)); byte[] b = used.toByteArray();
int l = Math.min(b.length, cnt);
data.write(b, 0, l);
for (int i = cnt - l; i > 0; i--) {
data.writeByte((byte) 0);
} }
store.writePage(getPos(), data); store.writePage(getPos(), data);
} }
......
...@@ -8,9 +8,10 @@ package org.h2.store; ...@@ -8,9 +8,10 @@ package org.h2.store;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.BitSet;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.message.Trace; import org.h2.message.Trace;
import org.h2.util.BitField;
/** /**
* An input stream that reads from a page store. * An input stream that reads from a page store.
...@@ -132,8 +133,8 @@ public class PageInputStream extends InputStream { ...@@ -132,8 +133,8 @@ public class PageInputStream extends InputStream {
* *
* @return the bit set * @return the bit set
*/ */
BitField allocateAllPages() { BitSet allocateAllPages() {
BitField pages = new BitField(); BitSet pages = new BitSet();
int key = logKey; int key = logKey;
PageStreamTrunk.Iterator it = new PageStreamTrunk.Iterator( PageStreamTrunk.Iterator it = new PageStreamTrunk.Iterator(
store, firstTrunkPage); store, firstTrunkPage);
......
...@@ -8,6 +8,7 @@ package org.h2.store; ...@@ -8,6 +8,7 @@ package org.h2.store;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap; import java.util.HashMap;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.compress.CompressLZF; import org.h2.compress.CompressLZF;
...@@ -17,7 +18,6 @@ import org.h2.message.DbException; ...@@ -17,7 +18,6 @@ import org.h2.message.DbException;
import org.h2.message.Trace; import org.h2.message.Trace;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.result.RowFactory; import org.h2.result.RowFactory;
import org.h2.util.BitField;
import org.h2.util.IntArray; import org.h2.util.IntArray;
import org.h2.util.IntIntHashMap; import org.h2.util.IntIntHashMap;
import org.h2.util.New; import org.h2.util.New;
...@@ -132,13 +132,13 @@ public class PageLog { ...@@ -132,13 +132,13 @@ public class PageLog {
* If the bit is set, the given page was written to the current log section. * If the bit is set, the given page was written to the current log section.
* The undo entry of these pages doesn't need to be written again. * The undo entry of these pages doesn't need to be written again.
*/ */
private BitField undo = new BitField(); private BitSet undo = new BitSet();
/** /**
* The undo entry of those pages was written in any log section. * The undo entry of those pages was written in any log section.
* These pages may not be used in the transaction log. * These pages may not be used in the transaction log.
*/ */
private final BitField undoAll = new BitField(); private final BitSet undoAll = new BitSet();
/** /**
* The map of section ids (key) and data page where the section starts * The map of section ids (key) and data page where the section starts
...@@ -156,7 +156,7 @@ public class PageLog { ...@@ -156,7 +156,7 @@ public class PageLog {
* The map of pages used by the transaction log. * The map of pages used by the transaction log.
* Only used during recovery. * Only used during recovery.
*/ */
private BitField usedLogPages; private BitSet usedLogPages;
/** /**
* This flag is set while freeing up pages. * This flag is set while freeing up pages.
...@@ -422,7 +422,7 @@ public class PageLog { ...@@ -422,7 +422,7 @@ public class PageLog {
} catch (IOException e) { } catch (IOException e) {
trace.debug("log recovery completed"); trace.debug("log recovery completed");
} }
undo = new BitField(); undo = new BitSet();
if (stage == RECOVERY_STAGE_REDO) { if (stage == RECOVERY_STAGE_REDO) {
usedLogPages = null; usedLogPages = null;
} }
...@@ -691,7 +691,7 @@ public class PageLog { ...@@ -691,7 +691,7 @@ public class PageLog {
Data buffer = getBuffer(); Data buffer = getBuffer();
buffer.writeByte((byte) CHECKPOINT); buffer.writeByte((byte) CHECKPOINT);
write(buffer); write(buffer);
undo = new BitField(); undo = new BitSet();
logSectionId++; logSectionId++;
logPos = 0; logPos = 0;
pageOut.flush(); pageOut.flush();
......
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
*/ */
package org.h2.store; package org.h2.store;
import java.util.BitSet;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.message.Trace; import org.h2.message.Trace;
import org.h2.util.BitField;
import org.h2.util.IntArray; import org.h2.util.IntArray;
/** /**
...@@ -17,7 +18,7 @@ public class PageOutputStream { ...@@ -17,7 +18,7 @@ public class PageOutputStream {
private PageStore store; private PageStore store;
private final Trace trace; private final Trace trace;
private final BitField exclude; private final BitSet exclude;
private final boolean atEnd; private final boolean atEnd;
private final int minPageId; private final int minPageId;
...@@ -42,7 +43,7 @@ public class PageOutputStream { ...@@ -42,7 +43,7 @@ public class PageOutputStream {
* @param logKey the log key of the first trunk page * @param logKey the log key of the first trunk page
* @param atEnd whether only pages at the end of the file should be used * @param atEnd whether only pages at the end of the file should be used
*/ */
public PageOutputStream(PageStore store, int trunkPage, BitField exclude, public PageOutputStream(PageStore store, int trunkPage, BitSet exclude,
int logKey, boolean atEnd) { int logKey, boolean atEnd) {
this.trace = store.getTrace(); this.trace = store.getTrace();
this.store = store; this.store = store;
......
...@@ -8,6 +8,7 @@ package org.h2.store; ...@@ -8,6 +8,7 @@ package org.h2.store;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -42,7 +43,6 @@ import org.h2.table.IndexColumn; ...@@ -42,7 +43,6 @@ import org.h2.table.IndexColumn;
import org.h2.table.RegularTable; import org.h2.table.RegularTable;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.table.TableType; import org.h2.table.TableType;
import org.h2.util.BitField;
import org.h2.util.Cache; import org.h2.util.Cache;
import org.h2.util.CacheLRU; import org.h2.util.CacheLRU;
import org.h2.util.CacheObject; import org.h2.util.CacheObject;
...@@ -180,7 +180,7 @@ public class PageStore implements CacheWriter { ...@@ -180,7 +180,7 @@ public class PageStore implements CacheWriter {
/** /**
* Each free page is marked with a set bit. * Each free page is marked with a set bit.
*/ */
private final BitField freed = new BitField(); private final BitSet freed = new BitSet();
private final ArrayList<PageFreeList> freeLists = New.arrayList(); private final ArrayList<PageFreeList> freeLists = New.arrayList();
private boolean recordPageReads; private boolean recordPageReads;
...@@ -1160,7 +1160,7 @@ public class PageStore implements CacheWriter { ...@@ -1160,7 +1160,7 @@ public class PageStore implements CacheWriter {
* @param exclude the exclude list * @param exclude the exclude list
* @param after all allocated pages are higher than this page * @param after all allocated pages are higher than this page
*/ */
void allocatePages(IntArray list, int pagesToAllocate, BitField exclude, void allocatePages(IntArray list, int pagesToAllocate, BitSet exclude,
int after) { int after) {
list.ensureCapacity(list.size() + pagesToAllocate); list.ensureCapacity(list.size() + pagesToAllocate);
for (int i = 0; i < pagesToAllocate; i++) { for (int i = 0; i < pagesToAllocate; i++) {
...@@ -1186,7 +1186,7 @@ public class PageStore implements CacheWriter { ...@@ -1186,7 +1186,7 @@ public class PageStore implements CacheWriter {
return pos; return pos;
} }
private int allocatePage(BitField exclude, int first) { private int allocatePage(BitSet exclude, int first) {
int page; int page;
for (int i = firstFreeListIndex;; i++) { for (int i = firstFreeListIndex;; i++) {
PageFreeList list = getFreeList(i); PageFreeList list = getFreeList(i);
...@@ -2020,8 +2020,8 @@ public class PageStore implements CacheWriter { ...@@ -2020,8 +2020,8 @@ public class PageStore implements CacheWriter {
this.lockFile = lockFile; this.lockFile = lockFile;
} }
public BitField getObjectIds() { public BitSet getObjectIds() {
BitField f = new BitField(); BitSet f = new BitSet();
Cursor cursor = metaIndex.find(pageStoreSession, null, null); Cursor cursor = metaIndex.find(pageStoreSession, null, null);
while (cursor.next()) { while (cursor.next()) {
Row row = cursor.get(); Row row = cursor.get();
......
...@@ -21,6 +21,7 @@ import java.sql.PreparedStatement; ...@@ -21,6 +21,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
...@@ -62,7 +63,6 @@ import org.h2.store.PageFreeList; ...@@ -62,7 +63,6 @@ import org.h2.store.PageFreeList;
import org.h2.store.PageLog; import org.h2.store.PageLog;
import org.h2.store.PageStore; import org.h2.store.PageStore;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.util.BitField;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.IntArray; import org.h2.util.IntArray;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
...@@ -1248,15 +1248,10 @@ public class Recover extends Tool implements DataHandler { ...@@ -1248,15 +1248,10 @@ public class Recover extends Tool implements DataHandler {
private int dumpPageFreeList(PrintWriter writer, Data s, long pageId, private int dumpPageFreeList(PrintWriter writer, Data s, long pageId,
long pageCount) { long pageCount) {
int pagesAddressed = PageFreeList.getPagesAddressed(pageSize); int pagesAddressed = PageFreeList.getPagesAddressed(pageSize);
BitField used = new BitField(); int len = pagesAddressed >> 3;
for (int i = 0; i < pagesAddressed; i += 8) { byte[] b = new byte[len];
int x = s.readByte() & 255; s.read(b, 0, len);
for (int j = 0; j < 8; j++) { BitSet used = BitSet.valueOf(b);
if ((x & (1 << j)) != 0) {
used.set(i + j);
}
}
}
int free = 0; int free = 0;
for (long i = 0, j = pageId; i < pagesAddressed && j < pageCount; i++, j++) { for (long i = 0, j = pageId; i < pagesAddressed && j < pageCount; i++, j++) {
if (i == 0 || j % 100 == 0) { if (i == 0 || j % 100 == 0) {
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.util;
import java.util.Arrays;
/**
* A list of bits.
*/
public final class BitField {
private static final int ADDRESS_BITS = 6;
private static final int BITS = 64;
private static final int ADDRESS_MASK = BITS - 1;
private long[] data;
private int maxLength;
public BitField() {
this(64);
}
public BitField(int capacity) {
data = new long[capacity >>> 3];
}
/**
* Get the index of the next bit that is not set.
*
* @param fromIndex where to start searching
* @return the index of the next disabled bit
*/
public int nextClearBit(int fromIndex) {
int i = fromIndex >> ADDRESS_BITS;
int max = data.length;
for (; i < max; i++) {
if (data[i] == -1) {
continue;
}
int j = Math.max(fromIndex, i << ADDRESS_BITS);
for (int end = j + 64; j < end; j++) {
if (!get(j)) {
return j;
}
}
}
return max << ADDRESS_BITS;
}
/**
* Get the bit at the given index.
*
* @param i the index
* @return true if the bit is enabled
*/
public boolean get(int i) {
int addr = i >> ADDRESS_BITS;
if (addr >= data.length) {
return false;
}
return (data[addr] & getBitMask(i)) != 0;
}
/**
* Get the next 8 bits at the given index.
* The index must be a multiple of 8.
*
* @param i the index
* @return the next 8 bits
*/
public int getByte(int i) {
int addr = i >> ADDRESS_BITS;
if (addr >= data.length) {
return 0;
}
return (int) (data[addr] >>> (i & (7 << 3)) & 255);
}
/**
* Combine the next 8 bits at the given index with OR.
* The index must be a multiple of 8.
*
* @param i the index
* @param x the next 8 bits (0 - 255)
*/
public void setByte(int i, int x) {
int addr = i >> ADDRESS_BITS;
checkCapacity(addr);
data[addr] |= ((long) x) << (i & (7 << 3));
if (maxLength < i && x != 0) {
maxLength = i + 7;
}
}
/**
* Set bit at the given index to 'true'.
*
* @param i the index
*/
public void set(int i) {
int addr = i >> ADDRESS_BITS;
checkCapacity(addr);
data[addr] |= getBitMask(i);
if (maxLength < i) {
maxLength = i;
}
}
/**
* Set bit at the given index to 'false'.
*
* @param i the index
*/
public void clear(int i) {
int addr = i >> ADDRESS_BITS;
if (addr >= data.length) {
return;
}
data[addr] &= ~getBitMask(i);
}
private static long getBitMask(int i) {
return 1L << (i & ADDRESS_MASK);
}
private void checkCapacity(int size) {
if (size >= data.length) {
expandCapacity(size);
}
}
private void expandCapacity(int size) {
while (size >= data.length) {
int newSize = data.length == 0 ? 1 : data.length * 2;
data = Arrays.copyOf(data, newSize);
}
}
/**
* Enable or disable a number of bits.
*
* @param fromIndex the index of the first bit to enable or disable
* @param toIndex one plus the index of the last bit to enable or disable
* @param value the new value
*/
public void set(int fromIndex, int toIndex, boolean value) {
// go backwards so that OutOfMemory happens
// before some bytes are modified
for (int i = toIndex - 1; i >= fromIndex; i--) {
set(i, value);
}
if (value) {
if (toIndex > maxLength) {
maxLength = toIndex;
}
} else {
if (toIndex >= maxLength) {
maxLength = fromIndex;
}
}
}
private void set(int i, boolean value) {
if (value) {
set(i);
} else {
clear(i);
}
}
/**
* Get the index of the highest set bit plus one, or 0 if no bits are set.
*
* @return the length of the bit field
*/
public int length() {
int m = maxLength >> ADDRESS_BITS;
while (m > 0 && data[m] == 0) {
m--;
}
maxLength = (m << ADDRESS_BITS) +
(64 - Long.numberOfLeadingZeros(data[m]));
return maxLength;
}
}
...@@ -173,7 +173,6 @@ import org.h2.test.synth.thread.TestMulti; ...@@ -173,7 +173,6 @@ import org.h2.test.synth.thread.TestMulti;
import org.h2.test.unit.TestAnsCompression; import org.h2.test.unit.TestAnsCompression;
import org.h2.test.unit.TestAutoReconnect; import org.h2.test.unit.TestAutoReconnect;
import org.h2.test.unit.TestBinaryArithmeticStream; import org.h2.test.unit.TestBinaryArithmeticStream;
import org.h2.test.unit.TestBitField;
import org.h2.test.unit.TestBitStream; import org.h2.test.unit.TestBitStream;
import org.h2.test.unit.TestBnf; import org.h2.test.unit.TestBnf;
import org.h2.test.unit.TestCache; import org.h2.test.unit.TestCache;
...@@ -903,7 +902,6 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -903,7 +902,6 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestAnsCompression()); addTest(new TestAnsCompression());
addTest(new TestAutoReconnect()); addTest(new TestAutoReconnect());
addTest(new TestBinaryArithmeticStream()); addTest(new TestBinaryArithmeticStream());
addTest(new TestBitField());
addTest(new TestBitStream()); addTest(new TestBitStream());
addTest(new TestBnf()); addTest(new TestBnf());
addTest(new TestCache()); addTest(new TestCache());
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.unit;
import java.util.BitSet;
import java.util.Random;
import org.h2.test.TestBase;
import org.h2.util.BitField;
/**
* A unit test for bit fields.
*/
public class TestBitField extends TestBase {
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
@Override
public void test() {
testNextClearBit();
testByteOperations();
testRandom();
testGetSet();
testRandomSetRange();
}
private void testNextClearBit() {
BitSet set = new BitSet();
BitField field = new BitField();
set.set(0, 640);
field.set(0, 640, true);
assertEquals(set.nextClearBit(0), field.nextClearBit(0));
Random random = new Random(1);
field = new BitField();
field.set(0, 500, true);
for (int i = 0; i < 100000; i++) {
int a = random.nextInt(120);
int b = a + 1 + random.nextInt(200);
field.clear(a);
field.clear(b);
assertEquals(b, field.nextClearBit(a + 1));
field.set(a);
field.set(b);
}
}
private void testByteOperations() {
BitField used = new BitField();
testSetFast(used, false);
testSetFast(used, true);
}
private void testSetFast(BitField used, boolean init) {
int len = 10000;
Random random = new Random(1);
for (int i = 0, x = 0; i < len / 8; i++) {
int mask = random.nextInt() & 255;
if (init) {
assertEquals(mask, used.getByte(x));
x += 8;
// for (int j = 0; j < 8; j++, x++) {
// if (used.get(x) != ((mask & (1 << j)) != 0)) {
// throw Message.getInternalError(
// "Redo failure, block: " + x +
// " expected in-use bit: " + used.get(x));
// }
// }
} else {
used.setByte(x, mask);
x += 8;
// for (int j = 0; j < 8; j++, x++) {
// if ((mask & (1 << j)) != 0) {
// used.set(x);
// }
// }
}
}
}
private void testRandom() {
BitField bits = new BitField();
BitSet set = new BitSet();
int max = 300;
int count = 100000;
Random random = new Random(1);
for (int i = 0; i < count; i++) {
int idx = random.nextInt(max);
if (random.nextBoolean()) {
if (random.nextBoolean()) {
bits.set(idx);
set.set(idx);
} else {
bits.clear(idx);
set.clear(idx);
}
} else {
assertEquals(set.get(idx), bits.get(idx));
assertEquals(set.nextClearBit(idx), bits.nextClearBit(idx));
assertEquals(set.length(), bits.length());
}
}
}
private void testGetSet() {
BitField bits = new BitField();
for (int i = 0; i < 10000; i++) {
bits.set(i);
if (!bits.get(i)) {
fail("not set: " + i);
}
if (bits.get(i + 1)) {
fail("set: " + i);
}
}
for (int i = 0; i < 10000; i++) {
if (!bits.get(i)) {
fail("not set: " + i);
}
}
for (int i = 0; i < 1000; i++) {
int k = bits.nextClearBit(0);
if (k != 10000) {
fail("" + k);
}
}
}
private void testRandomSetRange() {
BitField bits = new BitField();
BitSet set = new BitSet();
Random random = new Random(1);
int maxOffset = 500;
int maxLen = 500;
int total = maxOffset + maxLen;
int count = 10000;
for (int i = 0; i < count; i++) {
int offset = random.nextInt(maxOffset);
int len = random.nextInt(maxLen);
boolean val = random.nextBoolean();
set.set(offset, offset + len, val);
bits.set(offset, offset + len, val);
for (int j = 0; j < total; j++) {
assertEquals(set.get(j), bits.get(j));
}
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论