static int read_ahead_handler()

in component/libfuse/native_file_io.h [162:231]


static int read_ahead_handler(char *path, char *buf, size_t size, off_t offset, file_handle_t* handle_obj) 
{
    int new_read = 0;

    /* Random read determination logic :
        handle_obj->random_reads : is counter used for this
        - For every sequential read decrement this counter by 1
        - For every new read from physical file (random read or buffer refresh) increment the counter by 2
        - At any point if the counter value is > 5 then caller will disable read-ahead on this handle

        : If file is being read sequentially then counter will be negative and a buffer refresh will not skew the counter much
        : If file is read sequentially and later application moves to random read, at some point we will disable read-ahead logic
        : If file is read randomly then counter will be positive and we will disable read-ahead after 2-3 reads
        : If file is read randomly first and then sequentially then we assume it will be random read and disable the read-ahead
    */

    if ((handle_obj->buff_start == 0  && handle_obj->buff_end == 0) || 
        offset < handle_obj->buff_start ||
        offset >= handle_obj->buff_end)
    {
        // Either this is first read call or read is outside the current buffer boundary
        // So we need to read a fresh buffer from physical file
        new_read = 1;
        handle_obj->random_reads += 2;
    } else {
        handle_obj->random_reads--;
    }

    if (new_read) {
        // We need to refresh the data from file
        int read = native_pread(path, handle_obj->buff, RA_BLOCK_SIZE, offset, handle_obj);
        FILE *fp = fopen("blobfuse2_nat.log", "a");
        if (fp) {
            fprintf(fp, "File %s, Offset %ld, size %ld, new read %d\n",
                path, offset, size, read);
            fclose(fp);
        }

        if (read <= 0) {
            // Error or EOF reached to just return 0 now
            return read;
        }

        handle_obj->buff_start = offset;
        handle_obj->buff_end = offset + read;
    }

    // Buffer is populated so calculate how much to copy from here now.
    int start = offset - handle_obj->buff_start;
    int left = (handle_obj->buff_end - offset);
    int copy = (size > left) ? left : size;
    
    FILE *fp = fopen("blobfuse2_nat.log", "a");
    if (fp) {
        fprintf(fp, "File %s, Offset %ld, size %ld, buff start %ld, buff end %ld, start %d, left %d, copy %d\n",
           path, offset, size, handle_obj->buff_start, handle_obj->buff_end, start, left, copy);
        fclose(fp);
    }

    memcpy(buf, (handle_obj->buff + start), copy);
    
    if (copy < size) {
        // Less then request data was copied so read from next offset again
        // We need to handle this here because if we return less then size fuse is not asking from
        // correct offset in next read, it just goes to offset + size only.
        copy += read_ahead_handler(path, (buf + copy), (size - copy), (offset + copy), handle_obj);
    }

    return copy;
}