#!/usr/bin/env bash

set -e


# block size для dd
BLOCK_SIZE=4096
# Минимальная длина фрагмента файла, в котором гарантированно будет хотя бы одна полная строка
CHUNK_SIZE=$(( BLOCK_SIZE * 10 ))


function read_file_part
{
    start_bytes=$1
    count_bytes=$2
    dd if=${FILE_NAME} bs=${BLOCK_SIZE} skip=${start_bytes} count=${count_bytes} iflag=skip_bytes,count_bytes 2> /dev/null
}


function bin_search
{
    expected_datetime="$1"

    start_bytes=0
    end_bytes=${FILE_SIZE}
    while [ $((end_bytes - start_bytes)) -gt ${CHUNK_SIZE} ]; do
        middle=$(( start_bytes + (end_bytes - start_bytes) / 2 ))

        first_full_line="`read_file_part ${middle} ${CHUNK_SIZE} | head -n 2 | tail -n 1`"
        # строка лога имеет вид "<host> <date> <time> <прочие поля>"
        datetime="`echo "${first_full_line}" | cut -d" " -f2,3`"

        if [[ "${datetime}" < "${expected_datetime}" ]]; then start_bytes=${middle}; else end_bytes=${middle}; fi
    done
    echo "${start_bytes}"
}


function main
{
    if [ "$#" -ne 3 ]; then
        echo "Usage: $0 <file_name> '<datetime_from>' '<datetime_to>' "
        exit 1
    fi

    FILE_NAME="$1"
    FROM_DATETIME="$2"
    TO_DATETIME="$3"

    FILE_SIZE=`stat --printf="%s" ${FILE_NAME}`

    interval_start=`bin_search "${FROM_DATETIME}"`
    interval_end=`bin_search "${TO_DATETIME}"`
    interval_size=$(( interval_end - interval_start ))

    read_file_part ${interval_start} ${interval_size}
}


main "$@"
