-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpager.go
93 lines (77 loc) · 2.29 KB
/
pager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package main
import (
"io"
"log"
"os"
"unsafe"
)
type Pager struct {
fileDescriptor *os.File
fileLength uint32
Pages [TableMaxPages]unsafe.Pointer //each page is a [PageSize]byte
}
func pagerOpen(fileName string) *Pager {
file, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0777)
if err != nil {
log.Printf("Unable to open file %s.\n", fileName)
os.Exit(1)
}
//fileLength, err := syscall.Seek(int(file.Fd()), 0, io.SeekEnd)
fileLength, err := file.Seek(0, io.SeekEnd)
if err != nil {
log.Println("Unable to open get file length")
os.Exit(1)
}
pager := new(Pager)
pager.fileDescriptor = file
pager.fileLength = uint32(fileLength)
for i := uint32(0); i < TableMaxPages; i++ {
pager.Pages[i] = nil
}
return pager
}
func pagerFlush(pager *Pager, pageNum uint32, size uint32) {
if pager.Pages[pageNum] == nil {
log.Println("Tried to flush a null page")
os.Exit(1)
}
_, err := pager.fileDescriptor.Seek(int64(pageNum*PageSize), io.SeekStart)
if err != nil {
log.Printf("Error seeking: %v\n", err)
os.Exit(1)
}
buff := pager.Pages[pageNum]
buffArr := (*[PageSize]byte)(buff)
bytesWritten, err := pager.fileDescriptor.WriteAt(buffArr[:size], int64(pageNum*PageSize))
if err != nil {
log.Printf("Error writing: %v.\n", err)
os.Exit(1)
}
log.Printf("Wrote %d bytes to file %s\n", bytesWritten, pager.fileDescriptor.Name())
}
func getPage(pager *Pager, pageNum uint32) unsafe.Pointer {
if pageNum > TableMaxPages {
log.Printf("Tried to fetch page number out of bounds. %d > %d.\n", pageNum, TableMaxPages)
os.Exit(1)
}
if pager.Pages[pageNum] == nil {
// cache miss. allocate memory and load from file
page := [PageSize]byte{}
numPages := pager.fileLength / PageSize
// We might save a partial page at the end of the file
if pager.fileLength%PageSize > 0 {
numPages += 1
}
if numPages > 0 && pageNum <= numPages {
pager.fileDescriptor.Seek(int64(pageNum*PageSize), io.SeekStart)
bytesRead, err := pager.fileDescriptor.ReadAt(page[:], int64(pageNum*PageSize))
if err != nil && err != io.EOF {
log.Printf("Error reading file %v.\n", err)
os.Exit(1)
}
log.Printf("Successfuly read %d bytes from %s", bytesRead, pager.fileDescriptor.Name())
}
pager.Pages[pageNum] = unsafe.Pointer(&page)
}
return pager.Pages[pageNum]
}