public List<Data> getRange(byte[] lowerKey, byte[] upperKey) throws IOException {
        if (!filesAreOpened) {
            throw new IOException("The files are not opened yet. Use openFiles() to open all files.");
        }
        // estimate first and last bucket
        int lowerBucket = drums.getHashFunction().getBucketId(lowerKey);
        int upperBucket = drums.getHashFunction().getBucketId(upperKey);

        // estimate first chunk in the first file
        long lowerChunkOffset = files[lowerBucket].getIndex().getStartOffsetOfChunkByKey(lowerKey);
        // estimate last chunk in the last file
        long upperChunkOffset = files[lowerBucket].getIndex().getStartOffsetOfChunkByKey(upperKey);
        long filesize, startOffset, endOffset;
        byte[] tmpB = new byte[elementSize];

        ArrayList<Data> elements = new ArrayList<Data>();
        // run over all files
        OUTER: for (int i = lowerBucket; i <= upperBucket; i++) {
            HeaderIndexFile<Data> aktFile = files[i];
            filesize = aktFile.getFilledUpFromContentStart();

            // start reading at lowerChunkOffset in first file, else start reading from beginning
            startOffset = i == lowerBucket ? lowerChunkOffset : 0;
            // stop reading at upperChunkOffset in last file, else read till end fo file
            endOffset = i == upperBucket ? Math.max(upperChunkOffset + aktFile.getChunkSize(), filesize) : filesize;

            while (startOffset < endOffset) {
                destBuffer.clear();
                aktFile.read(startOffset, destBuffer);
                destBuffer.flip();
                while (destBuffer.remaining() > elementSize) {
                    destBuffer.get(tmpB); // get the element
                    @SuppressWarnings("unchecked")
                    Data record = (Data) prototype.fromByteBuffer(ByteBuffer.wrap(tmpB));
                    if (KeyUtils.compareKey(record.getKey(), lowerKey) >= 0 &&
                            KeyUtils.compareKey(record.getKey(), upperKey) <= 0) {
                        elements.add(record);
                    } else if (KeyUtils.compareKey(record.getKey(), upperKey) > 0) {
                        // we have read all relevant elements
                        break OUTER;
                    }
                }
                startOffset += destBuffer.limit();
            }
        }
        return elements;
    }