Package com.higherfrequencytrading.chronicle.perf

Source Code of com.higherfrequencytrading.chronicle.perf.PackedHashedTable$HashRecord

/*
* Copyright 2013 Peter Lawrey
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*        http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.higherfrequencytrading.chronicle.perf;

import com.higherfrequencytrading.chronicle.Chronicle;
import com.higherfrequencytrading.chronicle.Excerpt;
import com.higherfrequencytrading.chronicle.impl.GlobalSettings;
import com.higherfrequencytrading.chronicle.impl.IntIndexedChronicle;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;

/**
* @author peter.lawrey
*/
public class PackedHashedTable {
    @NotNull
    private final Chronicle hash;
    @NotNull
    private final Chronicle records;
    @NotNull
    private final HashRecord hashRecord;
    private final Excerpt recordsExcerpt;
    private final int maxRecordSize;
    private final String basePath;

    public PackedHashedTable(String basePath, int hashBucketBits, int hashCapacityBits, int maxRecordSize) throws IOException {
        this.basePath = basePath;
        this.maxRecordSize = maxRecordSize;
        hash = new IntIndexedChronicle(basePath + ".hash", Math.min(24, hashCapacityBits - 4));
        hashRecord = new HashRecord(hash.createExcerpt(), hashBucketBits, hashCapacityBits);

        while (hash.size() < 1 << hashBucketBits)
            hashRecord.addEntry();

        records = new IntIndexedChronicle(basePath + ".record", Math.min(26, hashCapacityBits - 2));
        recordsExcerpt = records.createExcerpt();
    }

    public Excerpt startRecord() {
        recordsExcerpt.startExcerpt(maxRecordSize);
        return recordsExcerpt;
    }

    public void endRecord(int hashCode) {
        int index = (int) recordsExcerpt.index();
        recordsExcerpt.finish();

        hashRecord.addRecord(hashCode, index);
    }

    public void deleteOnExit() {
        GlobalSettings.deleteOnExit(basePath + ".hash");
        GlobalSettings.deleteOnExit(basePath + ".record");
    }

    public interface HashRecordIterator {
        /**
         * @param recordExcerpt which might be a match
         * @return true to stop or false to continue
         */
        public boolean onExcerpt(Excerpt recordExcerpt);
    }

    public void lookup(int hashCode, @NotNull HashRecordIterator iterator) {
        hashRecord.lookup(hashCode, recordsExcerpt, iterator);
    }

    public void close() {
        records.close();
        hash.close();
    }

    static class HashRecord {
        private static final int HEADER_SIZE = 4;
        private static final int PER_ENTRY_SIZE = 8; // hashCode and record index.
        private final Excerpt excerpt;
        private final int hashBucketMask;
        private final int sizeORecordBytes;

        HashRecord(Excerpt excerpt, int hashBucketBits, int hashCapacityBits) {
            this.excerpt = excerpt;
            this.hashBucketMask = (1 << hashBucketBits) - 1;
//            this.hashCapacityBits = hashCapacityBits;

            int hashBucketSizeBits = hashCapacityBits - hashBucketBits;
            sizeORecordBytes = HEADER_SIZE + (PER_ENTRY_SIZE << hashBucketSizeBits);
        }

        void addEntry() {
            excerpt.startExcerpt(sizeORecordBytes);
            excerpt.position(sizeORecordBytes);
            excerpt.finish();
        }

        public void addRecord(int hashCode, int index) {
            int bucket = bucket(hashCode);
            excerpt.index(bucket);
            int size = size();
            excerpt.position(size * PER_ENTRY_SIZE + HEADER_SIZE);
            excerpt.writeInt(hashCode);
            excerpt.writeInt(index);
            excerpt.writeInt(0, size + 1);
        }

        private int bucket(int hashCode) {
//            return ((hashCode >> 18) ^ (hashCode >> 9) ^ hashCode) & hashBucketMask;
            return hashCode & hashBucketMask;
        }

        private int size() {
            return excerpt.readInt(0);
        }

        public void lookup(int hashCode, @NotNull Excerpt recordsExcerpt, @NotNull HashRecordIterator iterator) {
            int bucket = bucket(hashCode);
            excerpt.index(bucket);
            for (int i = 0, size = size(); i < size; i++) {
                excerpt.position(i * PER_ENTRY_SIZE + HEADER_SIZE);
                int hashCode2 = excerpt.readInt();
                if (hashCode != hashCode2)
                    continue;
                int record = excerpt.readInt();
                recordsExcerpt.index(record);
                if (iterator.onExcerpt(recordsExcerpt))
                    break;
            }
        }
    }
}
TOP

Related Classes of com.higherfrequencytrading.chronicle.perf.PackedHashedTable$HashRecord

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.