2 {Take tracks of files in store}
3 {just simple, no cleaning, etc}
8 tfid
=array [0..19] of byte;
9 tStoreObjectInfo
=object
10 final
:boolean; {hash matched}
11 rc
:Word; {0=no error 1=not found, other}
12 length
:LongWord
; {the whole file}
13 seglen
:longword
; {from cur to end of segment}
14 offset
:LongWord
; {only valid when reading}
16 procedure Open(const fid
:tfid
);
18 procedure SegSeek(ofs
:LongWord
); unimplemented
;
19 procedure ReadAhead(cnt
:Word; into
:pointer);
20 procedure WaitRead
; {wait for read to finish, rc}
21 procedure EnableWrite(const fid
:tFID
);
22 procedure SetFLength(len
:LongWord
);
23 procedure WriteSeg(ofs
:LongWord
;len
:word;data
:pointer);
24 procedure GetMiss(out ofs
:LongWord
; out len
:LongWord
; var state
:pointer);
25 procedure GetMiss(out ofs
:LongWord
; out len
:LongWord
);
27 dh
:tHandle
; {handle to the data file}
29 segi
:pointer{to seg info obj};
31 tObjectInfo
=tStoreObjectInfo
;
33 {Should consult Download on non-final files}
36 const prefix
='object';
39 tSegStatic
=packed object
43 tSeg
=object(tSegStatic
)
46 tSegInfo_ptr
=^tSegInfo
;
47 pSegInfo
=tSegInfo_ptr
;
53 procedure SetSeg(ofs
,len
:LongWord
; state
:boolean);
54 function GetSegLen(ofs
:LongWord
):LongWord
;
57 var SegInfoChain
:^tSegInfo
;
60 procedure mkfilen(var d
:string; flag
:char; const fid
:tfid
);
61 function hc(b
:byte):char;
63 if b
<10 then hc
:=char(ord('0')+b
)
64 else hc
:=char(ord('A')-10+b
);
72 for i
:=0 to 19 do begin
73 d
[b
+(i
*2)]:=hc(fid
[i
] shr 4);
74 d
[b
+(i
*2)+1]:=hc(fid
[i
] and $F);
78 function GetSegInfo(const fid
:tFID
):tSegInfo_ptr
;
80 var fh
:file of tSegStatic
;
85 while assigned(result
) do begin
86 if CompareWord(result
^.name
,fid
,10)=0 then goto nocr
;
98 {$I-}ReSet(fh
);{$I+}if ioresult
=0 then begin
99 while not eof(fh
) do begin
112 procedure tStoreObjectInfo
.Open(const fid
:tfid
);
114 mkfilen(filename
,'f',fid
);
117 dh
:=FileOpen(filename
,fmOpenRead
or fmShareDenyWrite
);
121 length
:=FileSeek(dh
,0,fsFromEnd
);
122 FileSeek(dh
,0,fsFromBeginning
);
124 mkfilen(filename
,'p',fid
);
126 dh
:=FileOpen(filename
,fmOpenRead
or fmShareDenyWrite
);
130 length
:=FileSeek(dh
,0,fsFromEnd
);
131 FileSeek(dh
,0,fsFromBeginning
);
132 segi
:=GetSegInfo(fid
);
134 Writeln('Store1: open failed for file ',filename
,', ioresult=',IOResult
);
140 procedure tStoreObjectInfo
.EnableWrite(const fid
:tFID
);
142 writeln('Store1: enaling write');
143 assert((dh
=-1)or(not final
));
145 {file was close, create}
146 dh
:=FileCreate(filename
);
148 Writeln('Store1: create failed for file ',filename
,', ioresult=',IOResult
);
150 {init length and segments}
152 segi
:=GetSegInfo(fid
);
155 {file was open, close and reopen rw}
157 dh
:=FileOpen(filename
,fmOpenReadWrite
or fmShareDenyWrite
);
159 if dh
=-1 then rc
:=2 else rc
:=0;
161 procedure tStoreObjectInfo
.SetFLength(len
:LongWord
);
164 writeln('Store1: SetFLength ',len
);
167 FileSeek(dh
,len
,fsFromBeginning
);
168 FileSeek(dh
,0,fsFromBeginning
);
170 procedure tSegInfo
.SetSeg(ofs
,len
:LongWord
; state
:boolean);
175 procedure Dump(c
:char);
178 writeln('Store1: dumpCache ',c
,' ',LongWord(@self
));
179 while assigned(cp
) do begin
180 writeln(cp
^.first
,'-',cp
^.after
);
190 //writeln('Store1: Add: ',ofs,'-',after);
191 while assigned(cp
) do begin
193 if (ofs
<=cp
^.first
)and(after
>=cp
^.after
) then begin
194 {merge complete-encase}
200 if cp
^.after
=ofs
then begin
201 {merge left-matching}
208 if cp
^.first
=after
then begin
209 {merge right-matching}
216 if (after
>cp
^.first
)and(ofs
<=cp
^.first
)and(after
<=cp
^.after
) then begin writeln('k'); after
:=cp
^.first
; end;
217 if (ofs
<cp
^.after
)and(after
>=cp
^.after
)and(ofs
>=cp
^.first
) then begin writeln('l'); ofs
:=cp
^.after
;end;
218 if not op
then pcp
:=@cp
^.next
;
223 if ofs
<>after
then begin
232 procedure tStoreObjectInfo
.WriteSeg(ofs
:LongWord
;len
:word;data
:pointer);
235 FileSeek(dh
,ofs
,fsFromBeginning
);
236 FileWrite(dh
,data
^,len
);
237 tSegInfo(segi
^).SetSeg(ofs
,len
,true);
239 procedure tStoreObjectInfo
.GetMiss(out ofs
:LongWord
; out len
:LongWord
; var state
:pointer);
240 var cp
,cp1
,cp2
:^tSeg
;
241 begin with tSegInfo(segi
^) do begin
243 {find seg with lowest base, return 0..base-1}
247 cp
:=cache
; while assigned(cp
) do begin
248 if (cp1
=nil)or(cp
^.first
<cp1
^.first
) then cp1
:=cp
;
250 if assigned(cp1
) then begin
251 cp
:=cache
; while assigned(cp
) do begin
252 if ((cp2
=nil)or(cp
^.first
<cp2
^.first
))and(cp
^.first
>cp1
^.first
) then cp2
:=cp
;
254 if assigned(cp2
) then begin
259 len
:=self
.length
-ofs
;
261 end else len
:=self
.length
;
262 writeln('Store1: report miss ',ofs
,'+',len
);
264 procedure tStoreObjectInfo
.GetMiss(out ofs
:LongWord
; out len
:LongWord
);
268 GetMiss(ofs
,len
,state
);
272 procedure tStoreObjectInfo
.ReadAhead(cnt
:Word; into
:pointer);
275 //todo, do real async read
277 red
:=FileRead(dh
,into
^,cnt
);
280 if red
=cnt
then rc
:=0 else begin
282 writeln('Store1: read ',red
,' out of ',cnt
,' requested bytes');
286 procedure tStoreObjectInfo
.WaitRead
; {wait for read to finish, rc}
290 procedure tSegInfo
.Free
;
292 var fh
:file of tSegStatic
;
295 Dec(refc
); if refc
>0 then exit
;
296 {save segs, free segs, free}
297 mkfilen(fn
,'i',name
);
300 while assigned(cache
) do begin
306 FreeMem(@self
,sizeof(self
));
308 procedure tStoreObjectInfo
.Close
;
310 if assigned(segi
) then tSegInfo(segi
^).Free
;
314 function tSegInfo
.GetSegLen(ofs
:LongWord
):LongWord
;
318 while assigned(cp
) do begin
319 if (cp
^.first
<=ofs
)and(cp
^.after
>ofs
) then begin
320 GetSegLen
:=cp
^.after
-ofs
;
326 procedure tStoreObjectInfo
.SegSeek(ofs
:longword
);
329 if ofs
<=length
then begin
331 if FileSeek(dh
,ofs
,fsFromBeginning
)=ofs
then begin
336 end else if assigned(segi
) then begin
337 seglen
:=tSegInfo(segi
^).GetSegLen(ofs
);
338 if seglen
=0 then rc
:=4 else if FileSeek(dh
,ofs
,fsFromBeginning
)<>ofs
then rc
:=3 else rc
:=0;