📄 linearhashindex.java
字号:
return;
}
int next = bucket.getNextBucket();
if (SysProperties.CHECK && next >= head.bucketCount) {
throw Message.getInternalError("next=" + next + " max=" + head.bucketCount);
}
if (next < 0) {
break;
}
bucket.setNext(session, -1);
bucket = getBucket(session, next);
}
}
private void merge(Session session) throws SQLException {
if (head.bucketCount <= 1) {
return;
}
if (getUtilization() > UTILIZATION_FOR_MERGE) {
return;
}
ObjectArray old = new ObjectArray();
moveOut(session, head.nextToSplit, old);
head.nextToSplit--;
if (head.nextToSplit < 0) {
head.baseSize /= 2;
head.nextToSplit = head.baseSize - 1;
}
moveOut(session, head.nextToSplit, old);
moveOut(session, head.bucketCount - 1, old);
removeBucket(session);
// for(int i=0; i<head.bucketCount; i++) {
// LinearHashBucket bucket = this.getBucket(i);
// if(bucket.getNextBucket() >= head.bucketCount) {
// System.out.println("error");
// }
// }
addAll(session, old);
// int testALot;
// for(int i=0; i<head.bucketCount; i++) {
// LinearHashBucket bucket = this.getBucket(i);
// if(bucket.getNextBucket() >= head.bucketCount) {
// System.out.println("error");
// }
// }
}
private boolean isEquals(Session session, LinearHashEntry r, int hash, Value key) throws SQLException {
if (r.hash == hash) {
if (r.key == null) {
r.key = getKey(tableData.getRow(session, r.value));
}
if (database.compareTypeSave(r.key, key) == 0) {
return true;
}
}
return false;
}
private int get(Session session, Value key) throws SQLException {
int hash = key.hashCode();
int home = getPos(hash);
LinearHashBucket bucket = getBucket(session, home);
while (true) {
for (int i = 0; i < bucket.getRecordSize(); i++) {
LinearHashEntry r = bucket.getRecord(i);
if (isEquals(session, r, hash, key)) {
return r.value;
}
}
if (bucket.getNextBucket() < 0) {
return -1;
}
bucket = getBucket(session, bucket.getNextBucket());
}
}
private void removeRecord(Session session, LinearHashBucket bucket, int index) throws SQLException {
bucket.removeRecord(session, index);
head.recordCount--;
rowCount--;
}
private void addRecord(Session session, LinearHashBucket bucket, LinearHashEntry entry) throws SQLException {
bucket.addRecord(session, entry);
head.recordCount++;
rowCount++;
}
private void remove(Session session, Value key) throws SQLException {
merge(session);
// trace.debug("remove "+key.toString());
int hash = key.hashCode();
int home = getPos(hash);
int now = home;
while (true) {
LinearHashBucket bucket = getBucket(session, now);
for (int i = 0; i < bucket.getRecordSize(); i++) {
LinearHashEntry r = bucket.getRecord(i);
if (isEquals(session, r, hash, key)) {
removeRecord(session, bucket, i);
if (home != now) {
ObjectArray old = new ObjectArray();
moveOut(session, home, old);
addAll(session, old);
}
return;
}
}
int next = bucket.getNextBucket();
if (next < 0) {
throw Message.getInternalError("not found");
}
now = next;
}
}
private int getBlockId(int i) {
return i * blocksPerBucket + firstBucketBlock;
}
private LinearHashBucket getBucket(Session session, int i) throws SQLException {
readCount++;
if (SysProperties.CHECK && i >= head.bucketCount) {
throw Message.getInternalError("get=" + i + " max=" + head.bucketCount);
}
// trace.debug("read " + i);
// return (LinearHashBucket) buckets.get(i);
i = getBlockId(i);
// System.out.println("getBucket "+i);
LinearHashBucket bucket = (LinearHashBucket) storage.getRecord(session, i);
return bucket;
}
private void addBucket(Session session) throws SQLException {
LinearHashBucket bucket = new LinearHashBucket(this);
storage.addRecord(session, bucket, getBlockId(head.bucketCount));
// bucket.setPos(buckets.size());
// buckets.add(bucket);
//System.out.println("addBucket "+bucket.getPos());
if (SysProperties.CHECK && bucket.getBlockCount() > blocksPerBucket) {
throw Message.getInternalError("blocks=" + bucket.getBlockCount());
}
head.bucketCount++;
}
private void removeBucket(Session session) throws SQLException {
// buckets.remove(head.bucketCount-1);
int pos = getBlockId(head.bucketCount - 1);
//System.out.println("removeBucket "+pos);
storage.removeRecord(session, pos);
head.bucketCount--;
}
private int getUtilization() {
return 100 * head.recordCount / (head.bucketCount * RECORDS_PER_BUCKET);
}
void updateBucket(Session session, LinearHashBucket bucket) throws SQLException {
storage.updateRecord(session, bucket);
}
public Record read(Session session, DataPage s) throws SQLException {
char c = (char) s.readByte();
if (c == 'B') {
return new LinearHashBucket(this, s);
} else if (c == 'H') {
return new LinearHashHead(this, s);
} else {
throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, getName());
}
}
public void close(Session session) throws SQLException {
// TODO flush from time to time (after a few seconds of no activity or so)
writeHeader(session);
diskFile.close();
}
public void add(Session session, Row row) throws SQLException {
Value key = getKey(row);
if (get(session, key) != -1) {
// TODO index duplicate key for hash indexes: is this allowed?
throw getDuplicateKeyException();
}
add(session, key, row.getPos());
}
public void remove(Session session, Row row) throws SQLException {
remove(session, getKey(row));
}
private Value getKey(SearchRow row) throws SQLException {
if (columns.length == 1) {
Column column = columns[0];
int index = column.getColumnId();
Value v = row.getValue(index);
return v;
}
Value[] list = new Value[columns.length];
for (int i = 0; i < columns.length; i++) {
Column column = columns[i];
int index = column.getColumnId();
Value v = row.getValue(index);
list[i] = v;
}
return ValueArray.get(list);
}
public Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException {
if (first == null || last == null) {
// TODO hash index: should additionally check if values are the same
throw Message.getInternalError();
}
int key = get(session, getKey(first));
if (key == -1) {
return new LinearHashCursor(null);
}
return new LinearHashCursor(tableData.getRow(session, key));
}
public double getCost(Session session, int[] masks) throws SQLException {
for (int i = 0; i < columns.length; i++) {
Column column = columns[i];
int index = column.getColumnId();
int mask = masks[index];
if ((mask & IndexCondition.EQUALITY) != IndexCondition.EQUALITY) {
return Long.MAX_VALUE;
}
}
return 100;
}
public void remove(Session session) throws SQLException {
storage.delete(session);
diskFile.delete();
}
public void truncate(Session session) throws SQLException {
storage.truncate(session);
// buckets.clear();
head = new LinearHashHead(this);
head.recordCount = 0;
head.bucketCount = 0;
head.baseSize = 1;
head.nextToSplit = 0;
readCount = 0;
storage.addRecord(session, head, 0);
addBucket(session);
rowCount = 0;
}
public void checkRename() throws SQLException {
}
public boolean needRebuild() {
return needRebuild;
}
public int getBucketSize() {
return bucketSize;
}
public boolean canGetFirstOrLast() {
return false;
}
public SearchRow findFirstOrLast(Session session, boolean first) throws SQLException {
throw Message.getUnsupportedException();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -