package main

import (
	"fmt"
	"os"
	"syscall"
)

func empty(filename string, length int64) {
	f, err := os.Create(filename)
	if err != nil {
		panic(err)
	}
	fd := int(f.Fd())

	err = syscall.Ftruncate(fd, int64(length))
	if err != nil {
		panic(err)
	}

	if err = f.Close(); err != nil {
		panic(err)
	}
}

func create(filename string, length int64) {
	f, err := os.Create(filename)
	if err != nil {
		panic(err)
	}

	// Create dummy data
	bytes := make([]byte, length)
	for i := range bytes {
		bytes[i] = byte(i) % 10
	}

	// Write data
	if _, err := f.Write(bytes); err != nil {
		panic(err)
	}

	if err = f.Close(); err != nil {
		panic(err)
	}
}

func read(filename string, offset int64, length int) (mmap []byte) {
	f, err := os.Open(filename)
	if err != nil {
		panic(err)
	}
	fd := int(f.Fd())
	fmt.Println("Got file", filename, fd)

	mmap, err = syscall.Mmap(fd, offset, length, syscall.PROT_READ, syscall.MAP_SHARED)
	if err != nil {
		panic(err)
	}

	// Verify file
	for i := range mmap {
		if mmap[i] != byte(i)%10 {
			panic("Expected %10")
		}
	}

	if err = syscall.Munmap(mmap); err != nil {
		panic(err)
	}

	if err = f.Close(); err != nil {
		panic(err)
	}

	return
}

func main() {
	filename := "test.mmap"

	length := int64(1e6)
	create(filename, length)

	batch := 10
	for offset := int64(0); offset < length; offset += int64(batch) {
		mmap := read(filename, offset, batch)
		fmt.Println("Read", offset, len(mmap))
	}
}
