⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linearhashindex.java

📁 非常棒的java数据库
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
                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 + -