-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreln.c
More file actions
240 lines (222 loc) · 6.39 KB
/
reln.c
File metadata and controls
240 lines (222 loc) · 6.39 KB
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
https://powcoder.com
代写代考加微信 powcoder
Assignment Project Exam Help
Add WeChat powcoder
// reln.c ... functions on Relations
// part of Multi-attribute Linear-hashed Files
// Last modified by John Shepherd, July 2019
#include "defs.h"
#include "reln.h"
#include "page.h"
#include "tuple.h"
#include "chvec.h"
#include "bits.h"
#include "hash.h"
#define HEADERSIZE (3*sizeof(Count)+sizeof(Offset))
struct RelnRep {
Count nattrs; // number of attributes
Count depth; // depth of main data file
Offset sp; // split pointer
Count npages; // number of main data pages
Count ntups; // total number of tuples
ChVec cv; // choice vector
char mode; // open for read/write
FILE *info; // handle on info file
FILE *data; // handle on data file
FILE *ovflow; // handle on ovflow file
};
// create a new relation (three files)
Status newRelation(char *name, Count nattrs, Count npages, Count d, char *cv)
{
char fname[MAXFILENAME];
Reln r = malloc(sizeof(struct RelnRep));
r->nattrs = nattrs; r->depth = d; r->sp = 0;
r->npages = npages; r->ntups = 0; r->mode = 'w';
assert(r != NULL);
if (parseChVec(r, cv, r->cv) != OK) return ~OK;
sprintf(fname,"%s.info",name);
r->info = fopen(fname,"w");
assert(r->info != NULL);
sprintf(fname,"%s.data",name);
r->data = fopen(fname,"w");
assert(r->data != NULL);
sprintf(fname,"%s.ovflow",name);
r->ovflow = fopen(fname,"w");
assert(r->ovflow != NULL);
int i;
for (i = 0; i < npages; i++) addPage(r->data);
closeRelation(r);
return 0;
}
// check whether a relation already exists
Bool existsRelation(char *name)
{
char fname[MAXFILENAME];
sprintf(fname,"%s.info",name);
FILE *f = fopen(fname,"r");
if (f == NULL)
return FALSE;
else {
fclose(f);
return TRUE;
}
}
// set up a relation descriptor from relation name
// open files, reads information from rel.info
Reln openRelation(char *name, char *mode)
{
Reln r;
r = malloc(sizeof(struct RelnRep));
assert(r != NULL);
char fname[MAXFILENAME];
sprintf(fname,"%s.info",name);
r->info = fopen(fname,mode);
assert(r->info != NULL);
sprintf(fname,"%s.data",name);
r->data = fopen(fname,mode);
assert(r->data != NULL);
sprintf(fname,"%s.ovflow",name);
r->ovflow = fopen(fname,mode);
assert(r->ovflow != NULL);
// Naughty: assumes Count and Offset are the same size
int n = fread(r, sizeof(Count), 5, r->info);
assert(n == 5);
n = fread(r->cv, sizeof(ChVecItem), MAXCHVEC, r->info);
assert(n == MAXCHVEC);
r->mode = (mode[0] == 'w' || mode[1] =='+') ? 'w' : 'r';
return r;
}
// release files and descriptor for an open relation
// copy latest information to .info file
void closeRelation(Reln r)
{
// make sure updated global data is put in info
// Naughty: assumes Count and Offset are the same size
if (r->mode == 'w') {
fseek(r->info, 0, SEEK_SET);
// write out core relation info (#attr,#pages,d,sp)
int n = fwrite(r, sizeof(Count), 5, r->info);
assert(n == 5);
// write out choice vector
n = fwrite(r->cv, sizeof(ChVecItem), MAXCHVEC, r->info);
assert(n == MAXCHVEC);
}
fclose(r->info);
fclose(r->data);
fclose(r->ovflow);
free(r);
}
// insert a new tuple into a relation
// returns index of bucket where inserted
// - index always refers to a primary data page
// - the actual insertion page may be either a data page or an overflow page
// returns NO_PAGE if insert fails completely
// TODO: include splitting and file expansion
PageID addToRelation(Reln r, Tuple t)
{
Bits h, p;
// char buf[MAXBITS+1];
h = tupleHash(r,t);
if (r->depth == 0)
p = 1;
else {
p = getLower(h, r->depth);
if (p < r->sp) p = getLower(h, r->depth+1);
}
// bitsString(h,buf); printf("hash = %s\n",buf);
// bitsString(p,buf); printf("page = %s\n",buf);
Page pg = getPage(r->data,p);
if (addToPage(pg,t) == OK) {
putPage(r->data,p,pg);
r->ntups++;
return p;
}
// primary data page full
if (pageOvflow(pg) == NO_PAGE) {
// add first overflow page in chain
PageID newp = addPage(r->ovflow);
pageSetOvflow(pg,newp);
putPage(r->data,p,pg);
Page newpg = getPage(r->ovflow,newp);
// can't add to a new page; we have a problem
if (addToPage(newpg,t) != OK) return NO_PAGE;
putPage(r->ovflow,newp,newpg);
r->ntups++;
return p;
}
else {
// scan overflow chain until we find space
// worst case: add new ovflow page at end of chain
Page ovpg, prevpg = NULL;
PageID ovp, prevp = NO_PAGE;
ovp = pageOvflow(pg);
while (ovp != NO_PAGE) {
ovpg = getPage(r->ovflow, ovp);
if (addToPage(ovpg,t) != OK) {
prevp = ovp; prevpg = ovpg;
ovp = pageOvflow(ovpg);
}
else {
if (prevpg != NULL) free(prevpg);
putPage(r->ovflow,ovp,ovpg);
r->ntups++;
return p;
}
}
// all overflow pages are full; add another to chain
// at this point, there *must* be a prevpg
assert(prevpg != NULL);
// make new ovflow page
PageID newp = addPage(r->ovflow);
// insert tuple into new page
Page newpg = getPage(r->ovflow,newp);
if (addToPage(newpg,t) != OK) return NO_PAGE;
putPage(r->ovflow,newp,newpg);
// link to existing overflow chain
pageSetOvflow(prevpg,newp);
putPage(r->ovflow,prevp,prevpg);
r->ntups++;
return p;
}
return NO_PAGE;
}
// external interfaces for Reln data
FILE *dataFile(Reln r) { return r->data; }
FILE *ovflowFile(Reln r) { return r->ovflow; }
Count nattrs(Reln r) { return r->nattrs; }
Count npages(Reln r) { return r->npages; }
Count ntuples(Reln r) { return r->ntups; }
Count depth(Reln r) { return r->depth; }
Count splitp(Reln r) { return r->sp; }
ChVecItem *chvec(Reln r) { return r->cv; }
// displays info about open Reln
void relationStats(Reln r)
{
printf("Global Info:\n");
printf("#attrs:%d #pages:%d #tuples:%d d:%d sp:%d\n",
r->nattrs, r->npages, r->ntups, r->depth, r->sp);
printf("Choice vector\n");
printChVec(r->cv);
printf("Bucket Info:\n");
printf("%-4s %s\n","#","Info on pages in bucket");
printf("%-4s %s\n","","(pageID,#tuples,freebytes,ovflow)");
for (Offset pid = 0; pid < r->npages; pid++) {
printf("[%2d] ",pid);
Page p = getPage(r->data, pid);
Count ntups = pageNTuples(p);
Count space = pageFreeSpace(p);
Offset ovid = pageOvflow(p);
printf("(d%d,%d,%d,%d)",pid,ntups,space,ovid);
free(p);
while (ovid != NO_PAGE) {
Offset curid = ovid;
p = getPage(r->ovflow, ovid);
ntups = pageNTuples(p);
space = pageFreeSpace(p);
ovid = pageOvflow(p);
printf(" -> (ov%d,%d,%d,%d)",curid,ntups,space,ovid);
free(p);
}
putchar('\n');
}
}