Skip to content

Commit d2e8aec

Browse files
committed
Add Insert function for schema_table
1 parent 0c1841c commit d2e8aec

File tree

9 files changed

+159
-26
lines changed

9 files changed

+159
-26
lines changed

buffer/buffer_pool_manager.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ import (
88
)
99

1010
type BufferPoolManager struct {
11-
pages []page.Page
12-
dmi diskio.DiskManager
13-
free_list *list.List
14-
page_table *PageTable
15-
replacer Replacer
11+
pages []page.Page
12+
dmi diskio.DiskManager
13+
free_list *list.List
14+
page_table *PageTable
15+
replacer Replacer
16+
buffer_size int
1617
}
1718

1819
func GetNewBufferPoolManager(buffer_size int, dmi diskio.DiskManager) *BufferPoolManager {
@@ -25,6 +26,7 @@ func (bpm *BufferPoolManager) Init(buffer_size int, dmi diskio.DiskManager) {
2526
bpm.pages = make([]page.Page, buffer_size)
2627
bpm.dmi = dmi
2728
bpm.free_list = list.New()
29+
bpm.buffer_size = buffer_size
2830
bpm.replacer = NewClockReplacer(buffer_size)
2931
for i := 0; i < buffer_size; i++ {
3032
bpm.free_list.PushBack(i)
@@ -49,6 +51,23 @@ func (bpm *BufferPoolManager) UnPinPage(page_id uint32) bool {
4951
return ok
5052
}
5153

54+
func (bpm *BufferPoolManager) PersistAll() {
55+
for i := 0; i < bpm.buffer_size; i++ {
56+
if bpm.pages[i] != nil {
57+
if bpm.pages[i].IsDirty() {
58+
bpm.dmi.WritePage(bpm.pages[i].GetPageId(), bpm.pages[i])
59+
}
60+
}
61+
}
62+
}
63+
64+
func (bpm *BufferPoolManager) AllocatePage(page_id uint32) page.Page {
65+
_page := bpm.GetPage(page_id) // this will written a page with invalid id
66+
_page.SetPageId(page_id)
67+
bpm.dmi.WritePage(page_id, _page)
68+
return _page
69+
}
70+
5271
// not thread safe
5372
func (bpm *BufferPoolManager) GetPage(page_id uint32) page.Page {
5473
// if page is not there
@@ -69,7 +88,15 @@ func (bpm *BufferPoolManager) GetPage(page_id uint32) page.Page {
6988
frame_i, ok := bpm.replacer.GetNextVictim()
7089
if ok {
7190
free_frame_i = frame_i
72-
// add logic to if page is dirty write it to disk
91+
92+
// delete entry from PageTable
93+
bpm.page_table.Delete(bpm.pages[frame_i].GetPageId())
94+
95+
// persist dirty page to disk
96+
if bpm.pages[frame_i].IsDirty() {
97+
bpm.dmi.WritePage(bpm.pages[frame_i].GetPageId(), bpm.pages[frame_i])
98+
}
99+
73100
} else {
74101
fmt.Println("Couldn't find a page")
75102
}

buffer/page_table.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package buffer
22

33
import (
4-
"fmt"
4+
// "fmt"
55
"sync"
66
)
77

@@ -23,8 +23,14 @@ func (pt *PageTable) InsertOrUpdate(key uint32, val int) {
2323
pt.index[key] = val
2424
}
2525

26+
func (pt *PageTable) Delete(key uint32) {
27+
pt._lock.Lock()
28+
defer pt._lock.Unlock()
29+
delete(pt.index, key)
30+
}
31+
2632
func (pt *PageTable) Get(key uint32) (int, bool) {
27-
fmt.Println("Getting Page", key)
33+
// fmt.Println("Getting Page", key)
2834
pt._lock.RLock()
2935
defer pt._lock.RUnlock()
3036
if val, ok := pt.index[key]; ok {

main.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,17 @@ func main() {
9595
schema_table := new(schema.SchemaTable)
9696
schema_table.Init()
9797

98+
//for i := 0; i < 1000; i++ {
99+
// tuple := schema_table.GetDefaultRow()
100+
// tuple.SetValueFor(schema.SCHEMA_ID, int64(i))
101+
// tuple.SetValueFor(schema.SCHEMA_TABLE_ID, int64(0i))
102+
// tuple.SetValueFor(schema.SCHEMA_TABLE_NAME, "first_table")
103+
// tuple.SetValueFor(schema.SCHEMA_COLUMN_NAME, "id")
104+
// tuple.SetValueFor(schema.SCHEMA_COLUMN_POSITION, int64(1))
105+
// tuple.SetValueFor(schema.SCHEMA_COLUMN_TYPE, "INTEGER")
106+
// schema_table.Insert(tuple)
107+
//}
108+
109+
schema_table.Close()
98110
schema_table.Iterator()
99111
}

schema/schema_table.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,21 @@ package schema
66
// Each table is a new file
77

88
import (
9+
// "fmt"
910
"github.com/chaitya62/noobdb/buffer"
1011
"github.com/chaitya62/noobdb/storage/disk"
1112
"github.com/chaitya62/noobdb/storage/page"
1213
)
1314

15+
const (
16+
SCHEMA_ID = iota
17+
SCHEMA_TABLE_ID
18+
SCHEMA_TABLE_NAME
19+
SCHEMA_COLUMN_POSITION
20+
SCHEMA_COLUMN_NAME
21+
SCHEMA_COLUMN_TYPE
22+
)
23+
1424
const schema_file = "schema.txt"
1525

1626
type SchemaTable struct {
@@ -26,6 +36,55 @@ func (st *SchemaTable) Init() {
2636
st.bpm = buffer.GetNewBufferPoolManager(3, st.dmi)
2737
}
2838

39+
func (st *SchemaTable) GetDefaultRow() page.Tuple {
40+
tuple := new(page.TupleImpl)
41+
tuple.Init(st._schema[:])
42+
return tuple
43+
}
44+
45+
func (st *SchemaTable) Insert(tuple page.Tuple) error {
46+
no_of_pages := st.dmi.GetNumberOfPages()
47+
var page_id uint32
48+
var _schemaPage *page.SchemaPage
49+
if no_of_pages == 0 {
50+
// create a new page
51+
// when schema table is empty
52+
page_id = uint32(0)
53+
_page := st.bpm.AllocatePage(page_id)
54+
_pageImpl := _page.(*page.PageImpl)
55+
_schemaPage = &page.SchemaPage{PageImpl: *_pageImpl}
56+
_schemaPage.Init()
57+
} else {
58+
page_id = uint32(no_of_pages - 1)
59+
_page := st.bpm.GetPage(page_id)
60+
_pageImpl := _page.(*page.PageImpl)
61+
_schemaPage = &page.SchemaPage{PageImpl: *_pageImpl}
62+
}
63+
64+
st.bpm.PinPage(page_id)
65+
err := _schemaPage.InsertTuple(tuple)
66+
st.bpm.UnPinPage(page_id)
67+
68+
// page is full
69+
// allocate new page
70+
if err != nil {
71+
page_id = uint32(page_id + 1)
72+
_page := st.bpm.AllocatePage(page_id)
73+
_pageImpl := _page.(*page.PageImpl)
74+
_schemaPage = &page.SchemaPage{PageImpl: *_pageImpl}
75+
_schemaPage.Init()
76+
77+
// we assume each tuple can fit in a page of size 4096 bytes
78+
st.bpm.PinPage(page_id)
79+
err = _schemaPage.InsertTuple(tuple)
80+
st.bpm.UnPinPage(page_id)
81+
82+
}
83+
84+
return nil
85+
86+
}
87+
2988
//TODO: Convert this to an iterator design pattern
3089
// https://ewencp.org/blog/golang-iterators/index.html
3190
func (st *SchemaTable) Iterator() {
@@ -46,3 +105,8 @@ func (st *SchemaTable) Iterator() {
46105
}
47106
}
48107
}
108+
109+
// sanatize and persist everything to disk
110+
func (st *SchemaTable) Close() {
111+
st.bpm.PersistAll()
112+
}

storage/page/page.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,40 @@
11
package page
22

3-
import "errors"
3+
import (
4+
"errors"
5+
"fmt"
6+
)
47

58
const PAGE_SIZE = 4096
69
const INVALID_PAGE_ID = 4294967295
710

811
type Page interface {
12+
Init()
913
GetData() []byte
1014
GetPageId() uint32
1115
SetData([]byte) error
1216
SetPageId(page_id uint32)
17+
IsDirty() bool
18+
SetDirtyBit(val bool)
1319
}
1420

1521
type PageImpl struct {
16-
_data [PAGE_SIZE]byte
22+
_data []byte
1723
_page_id uint32
1824
_dirty bool
1925
_pin_count uint64
2026
}
2127

28+
func (p *PageImpl) IsDirty() bool {
29+
return p._dirty
30+
}
31+
32+
func (p *PageImpl) SetDirtyBit(val bool) {
33+
p._dirty = val
34+
}
35+
2236
func (p *PageImpl) GetData() []byte {
23-
return p._data[:]
37+
return p._data
2438
}
2539

2640
func (p *PageImpl) GetPageId() uint32 {
@@ -31,28 +45,35 @@ func (p *PageImpl) SetData(d []byte) error {
3145
if len(d) != PAGE_SIZE {
3246
return errors.New("Invalid Data slice")
3347
}
34-
copy(p._data[:], d)
48+
p._data = d
3549
p._page_id = (uint32(d[0]) | (uint32(d[1]) << 8) | (uint32(d[2]) << 16) | (uint32(d[3]) << 24))
3650
p._dirty = true
3751
return nil
3852
}
3953

40-
func (p *PageImpl) ResetMemory() error {
41-
copy(p._data[:], make([]byte, PAGE_SIZE))
54+
func (p *PageImpl) Init() {
55+
p._data = make([]byte, PAGE_SIZE)
4256
p._page_id = 0
57+
p._dirty = false
58+
}
59+
60+
func (p *PageImpl) ResetMemory() error {
61+
p.Init()
4362
return nil
4463
}
4564

4665
func (p *PageImpl) SetPageId(page_id uint32) {
4766
p._page_id = page_id
67+
fmt.Println("page_id", page_id)
4868
p._data[0] = byte(page_id)
4969
p._data[1] = byte(page_id >> 8)
5070
p._data[2] = byte(page_id >> 16)
5171
p._data[3] = byte(page_id >> 24)
5272
p._dirty = true
73+
5374
}
5475

5576
func InvalidPage() Page {
5677
// the first four bits are not equal to page_id
57-
return &PageImpl{[PAGE_SIZE]byte{}, INVALID_PAGE_ID, false, 0}
78+
return &PageImpl{make([]byte, PAGE_SIZE), INVALID_PAGE_ID, false, 0}
5879
}

storage/page/schema_page.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package page
55
// slots and tuples
66

77
import (
8+
"errors"
89
"fmt"
910
//"github.com/chaitya62/noobdb/type"
1011
)
@@ -24,6 +25,10 @@ func (sp *SchemaPage) Init() {
2425
sp.SetFreeSpacePointer(4096)
2526
}
2627

28+
func (sp *SchemaPage) shallowCopy(_page Page) {
29+
sp._data = _page.GetData()
30+
}
31+
2732
func (sp *SchemaPage) GetHeader() []byte {
2833
// returning a slice returns the address space and not the copy
2934
// will have to re-think later if this is causes any unexpect behaviour
@@ -83,17 +88,18 @@ func (sp *SchemaPage) InsertTuple(tp Tuple) error {
8388

8489
if uint64(space_left) < tp_size {
8590
//TODO: ADD CUSTOM STANDARD ERROR TYPES TO DATABASE
86-
return nil
91+
fmt.Println("PAGE is FULL")
92+
return errors.New("Page is full")
8793
}
8894

8995
// assuming all tuples fit in one page
9096
//TODO: Implement handling for Tuple OVERFLOW
9197
start_at := fp - uint16(tp_size)
9298

9399
//TODO: Error handling
94-
fmt.Println("HERE")
95100
// intert tupple
96101
copy(sp._data[start_at:fp], tp.GetData())
102+
sp._dirty = true
97103

98104
// insert slot
99105
//TODO: SLOT STRUCT ?

storage/page/tuple.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,13 @@ import (
55
"github.com/chaitya62/noobdb/type"
66
)
77

8-
const (
9-
SCHEMA_ID = iota
10-
SCHEMA_TABLE_ID
11-
SCHEMA_TABLE_NAME
12-
SCHEMA_COLUMN_POSITION
13-
SCHEMA_COLUMN_NAME
14-
SCHEMA_COLUMN_TYPE
15-
)
16-
178
type Tuple interface {
189
ReadTuple(data_ []byte)
1910
SetValueFor(column_i uint64, val interface{})
2011
GetValueFor(column_i uint64) interface{}
2112
GetSize() uint64
2213
GetData() []byte
14+
PrintTuple()
2315
}
2416

2517
type TupleImpl struct {

tests/storage/disk/disk_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func TestDiskManagerImpl(t *testing.T) {
5454
}
5555

5656
dummy_page := &page.PageImpl{}
57+
dummy_page.Init()
5758

5859
ok := dmi.WritePage(dummy_page.GetPageId(), dummy_page)
5960
if ok != nil {

tests/storage/page/page_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func TestPageImpl(t *testing.T) {
2020

2121
t.Run("SetData - page_id and data", func(t *testing.T) {
2222
pageImpl := &page.PageImpl{}
23+
pageImpl.Init()
2324
data_slice := make([]byte, page.PAGE_SIZE)
2425

2526
expected_page_id := uint32(12)
@@ -39,6 +40,7 @@ func TestPageImpl(t *testing.T) {
3940

4041
t.Run("SetData - invalid slice", func(t *testing.T) {
4142
pageImpl := &page.PageImpl{}
43+
pageImpl.Init()
4244

4345
invalid_page_size := 1235
4446
data_slice := make([]byte, invalid_page_size)
@@ -77,6 +79,8 @@ func TestPageImpl(t *testing.T) {
7779

7880
t.Run("SetPageId", func(t *testing.T) {
7981
pageImpl := &page.PageImpl{}
82+
pageImpl.Init()
83+
8084
data_slice := make([]byte, page.PAGE_SIZE)
8185

8286
expected_page_id := uint32(12)

0 commit comments

Comments
 (0)