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
|
Vac: module {
PATH: con "/dis/lib/vac.dis";
init: fn();
dflag: int;
# taken from venti.m, merge back later
# some of this needs to be removed from venti.m since it does not belong there
# mode bits
Modeperm: con 8r777;
Modesticky,
Modesetuid,
Modesetgid,
Modeappend,
Modeexcl,
Modesymlink,
Modedir,
Modehidden,
Modesystem,
Modearchive,
Modetemp,
Modesnapshot,
Modedev,
Modenamedpipe: con 1<<(9+iota);
Entrysize: con 40;
Rootsize: con 300;
Metablocksize: con 12;
Metaentrysize: con 4;
Dsize: con 8*1024;
Entryactive: con (1<<0); # entry is in use
Entrydir: con (1<<1); # a directory
Entrydepthshift: con 2; # shift for pointer depth
Entrydepthmask: con (16r7<<2); # mask for pointer depth
Entrylocal: con (1<<5); # used for local storage: should not be set for venti blocks
Root: adt {
version: int;
name: string;
rtype: string;
score: Venti->Score; # to a Dir block
blocksize: int; # maximum block size
prev: ref Venti->Score; # last root block
new: fn(name, rtype: string, score: Venti->Score, blocksize: int, prev: ref Venti->Score): ref Root;
unpack: fn(d: array of byte): ref Root;
pack: fn(r: self ref Root): array of byte;
};
Entry: adt {
gen: int; # generation number (XXX should be unsigned)
psize: int; # pointer block size
dsize: int; # data block size
depth: int; # unpacked from flags
flags: int;
size: big; # (XXX should be unsigned)
score: Venti->Score;
new: fn(psize, dsize, flags: int, size: big, score: Venti->Score): ref Entry;
pack: fn(e: self ref Entry): array of byte;
unpack: fn(d: array of byte): ref Entry;
};
Direntry: adt {
version: int;
elem: string;
entry, gen: int;
mentry, mgen: int;
qid: big;
uid, gid, mid: string;
mtime, mcount, ctime, atime, mode, emode: int;
new: fn(): ref Direntry;
mk: fn(d: Sys->Dir): ref Direntry;
mkdir: fn(de: self ref Direntry): ref Sys->Dir;
pack: fn(de: self ref Direntry): array of byte;
unpack: fn(d: array of byte): ref Direntry;
};
Metablock: adt {
size, free, maxindex, nindex: int;
new: fn(): ref Metablock;
pack: fn(mb: self ref Metablock, d: array of byte);
unpack: fn(d: array of byte): ref Metablock;
};
Metaentry: adt {
offset, size: int;
pack: fn(me: self ref Metaentry, d: array of byte);
unpack: fn(d: array of byte, i: int): ref Metaentry;
};
# single block
Page: adt {
d: array of byte;
o: int;
new: fn(dsize: int): ref Page;
add: fn(p: self ref Page, s: Venti->Score);
full: fn(p: self ref Page): int;
data: fn(p: self ref Page): array of byte;
};
# hash tree file
File: adt {
p: array of ref Page;
dtype, dsize: int;
size: big;
s: ref Venti->Session;
new: fn(s: ref Venti->Session, dtype, dsize: int): ref File;
write: fn(f: self ref File, d: array of byte): int;
finish: fn(f: self ref File): ref Entry;
};
# for writing venti directories
Sink: adt {
f: ref File;
d: array of byte;
nd, ne: int;
new: fn(s: ref Venti->Session, dsize: int): ref Sink;
add: fn(m: self ref Sink, e: ref Entry): int;
finish: fn(m: self ref Sink): ref Entry;
};
Mentry: adt {
elem: string;
me: ref Metaentry;
cmp: fn(a, b: ref Mentry): int;
};
# for writing directory entries (meta blocks, meta entries, direntries)
MSink: adt {
f: ref File;
de: array of byte;
nde: int;
l: list of ref Mentry;
new: fn(s: ref Venti->Session, dsize: int): ref MSink;
add: fn(m: self ref MSink, de: ref Direntry): int;
finish: fn(m: self ref MSink): ref Entry;
};
# for reading pages from a hash tree referenced by an entry
Source: adt {
session: ref Venti->Session;
e: ref Entry;
dsize: int; # real dsize
new: fn(s: ref Venti->Session, e: ref Entry): ref Source;
get: fn(s: self ref Source, i: big, d: array of byte): int;
};
# for reading from a hash tree while keeping offset
Vacfile: adt {
s: ref Source;
o: big;
mk: fn(s: ref Source): ref Vacfile;
new: fn(session: ref Venti->Session, e: ref Entry): ref Vacfile;
read: fn(v: self ref Vacfile, d: array of byte, n: int): int;
seek: fn(v: self ref Vacfile, offset: big): big;
pread: fn(v: self ref Vacfile, d: array of byte, n: int, offset: big): int;
};
# for listing contents of a vac directory and walking to path elements
Vacdir: adt {
vf: ref Vacfile;
ms: ref Source;
p: big;
i: int;
mk: fn(vf: ref Vacfile, ms: ref Source): ref Vacdir;
new: fn(session: ref Venti->Session, e, me: ref Entry): ref Vacdir;
walk: fn(v: self ref Vacdir, elem: string): ref Direntry;
open: fn(v: self ref Vacdir, de: ref Direntry): (ref Entry, ref Entry);
readdir: fn(v: self ref Vacdir): (int, ref Direntry);
rewind: fn(v: self ref Vacdir);
};
vdroot: fn(session: ref Venti->Session, score: Venti->Score): (ref Vacdir, ref Direntry, string);
};
|