-
Notifications
You must be signed in to change notification settings - Fork 0
/
page.c
103 lines (93 loc) · 2.65 KB
/
page.c
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
94
95
96
97
98
99
100
101
102
// page.c ... functions on Pages
// part of Multi-attribute Linear-hashed Files
// Reading/writing pages into buffers and manipulating contents
// Written by John Shepherd, April 2016
#include "defs.h"
#include "page.h"
// internal representation of pages
struct PageRep {
Offset free; // offset within data[] of free space
Offset ovflow; // Offset of overflow page (if any)
Count ntuples; // #tuples in this page
char data[1]; // start of data
};
// A Page is a chunk of memory containing PAGESIZE bytes
// It is implemented as a struct (free, ovflow, data[1])
// - free is the offset of the first byte of free space
// - ovflow is the page id of the next overflow page in bucket
// - data[] is a sequence of bytes containing tuples
// - each tuple is a sequence of chars terminated by '\0'
// - PageID values count # pages from start of file
// create a new initially empty page in memory
Page newPage()
{
Page p = malloc(PAGESIZE);
assert(p != NULL);
p->free = 0;
p->ovflow = NO_PAGE;
p->ntuples = 0;
Count hdr_size = 2*sizeof(Offset) + sizeof(Count);
int dataSize = PAGESIZE - hdr_size;
memset(p->data, 0, dataSize);
return p;
}
// append a new Page to a file; return its PageID
PageID addPage(FILE *f)
{
int ok = fseek(f, 0, SEEK_END);
assert(ok == 0);
int pos = ftell(f);
assert(pos >= 0);
PageID pid = pos/PAGESIZE;
Page p = newPage();
ok = putPage(f, pid, p);
assert(ok == 0);
return pid;
}
// fetch a Page from a file; allocate a memory buffer
Page getPage(FILE *f, PageID pid)
{
assert(pid >= 0);
Page p = malloc(PAGESIZE);
assert(p != NULL);
int ok = fseek(f, pid*PAGESIZE, SEEK_SET);
assert(ok == 0);
int n = fread(p, 1, PAGESIZE, f);
assert(n == PAGESIZE);
return p;
}
// write a Page to a file; release allocated buffer
Status putPage(FILE *f, PageID pid, Page p)
{
assert(pid >= 0);
int ok = fseek(f, pid*PAGESIZE, SEEK_SET);
assert(ok == 0);
int n = fwrite(p, 1, PAGESIZE, f);
assert(n == PAGESIZE);
free(p);
return 0;
}
// insert a tuple into a page
// returns 0 status if successful
// returns -1 if not enough room
Status addToPage(Page p, Tuple t)
{
int n = tupLength(t);
char *c = p->data + p->free;
Count hdr_size = 2*sizeof(Offset) + sizeof(Count);
// doesn't fit ... return fail code
// assume caller will put it elsewhere
if (c+n > &p->data[PAGESIZE-hdr_size-2]) return -1;
strcpy(c, t);
p->free += n+1;
p->ntuples++;
return OK;
}
// extract page info
Count pageTuples(Page p) { return p->ntuples; }
Offset pageOvflow(Page p) { return p->ovflow; }
void pageSetOvflow(Page p, PageID pid) { p->ovflow = pid; }
Count pageFreeSpace(Page p) {
Count hdr_size = 2*sizeof(Offset) + sizeof(Count);
return (PAGESIZE-hdr_size-p->free);
}