summaryrefslogtreecommitdiff
path: root/system/multiuser/1.7.5/src/basic archive
blob: 82356073afa836f9ec81eeff8d7eaad5c8229b2e (plain)
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
(* ------------------- VERSION 11     06.03.86 ------------------- *)
PACKET basic archive DEFINES 

  archive blocks ,
  block number ,
  check read ,
  format archive ,
  read block ,
  read ,
  rewind ,
  search dataspace ,
  seek ,
  size ,
  skip dataspace ,
  write block ,
  write :

INT VAR blocknr  := 0 ,
        rerun    := 0 ,
        page     := -1 ,
        bit word := 1 ,
        unreadable sequence length := 0 ;
INT CONST all ones :=-1 ;


DATASPACE VAR label ds ;

LET write normal            = 0 ,
    archive version         = 1 ,
    first page stored       = 2 ,
    dr size                 = 3 ,
    first bit word          = 4 ,
(*  write deleted data mark = 64 , *)
    inconsistent            = 90 ,
    read error              = 92 ,
    label size              = 131 ;

BOUND STRUCT (ALIGN dummy for page1,
              (* Page 2 begins: *)
              ROW label size INT lab) VAR label;


INT PROC block number :
  block nr
ENDPROC block number ;

PROC seek (INT CONST block) :
  block nr := block
ENDPROC seek ;

PROC rewind :
  forget (label ds);
  label ds := nilspace;
  label := label ds;
  block nr := 0;
  rerun := session 
END PROC rewind; 
 
PROC skip dataspace:
  check rerun;
  get label; 
  IF is error
    THEN
  ELIF olivetti
    THEN block nr INCR label.lab (dr size+1)
    ELSE block nr INCR label.lab (dr size)
  FI
END PROC skip dataspace; 
 
PROC read (DATASPACE VAR ds):
  read (ds, 30000, FALSE)
ENDPROC read ;

PROC read (DATASPACE VAR ds, INT CONST max pages, BOOL CONST error accept) :
  enable stop ;
  check rerun;
  get label; 
  init next page;
  INT VAR i ;
  FOR i FROM 1 UPTO max pages REP
    next page;
    IF no further page THEN  LEAVE read FI;
    check storage ;
    check rerun ;
    read block ;
    block nr INCR 1;
  PER .

read block :
  disable stop ;
  get external block (ds, page, block nr) ;
  ignore read error if no errors accepted ;
  enable stop .

ignore read error if no errors accepted :
  IF is error CAND error code = read error CAND NOT error accept
    THEN clear error
  FI .

check storage :
  INT VAR size, used ;
  storage (size, used) ;
  IF used > size
    THEN forget (ds) ;
         ds := nilspace ;
         errorstop ("Speicherengpass") ;
         LEAVE read
  FI .

check rerun :
    IF rerun <> session
      THEN errorstop ("RERUN beim Archiv-Zugriff") ;
           LEAVE read
    FI .

END PROC read;

PROC check read :

  enable stop ;
  get label ;
  INT VAR pages, i;
  IF olivetti
    THEN pages := label.lab (dr size+1)
    ELSE pages := label.lab (dr size)
  FI ;
  FOR i FROM 1 UPTO pages REP
    get external block (label ds, 2, block nr) ;
    block nr INCR 1
  PER .

ENDPROC check read ;

PROC write (DATASPACE CONST ds):
  enable stop ;
  check rerun;
  INT VAR label block nr := block nr;
  block nr INCR 1;init label;
  INT VAR page := -1,i;
  FOR i FROM 1 UPTO ds pages (ds) REP
    check rerun ;
    page := next ds page(ds,page);
    put external block (ds, page, block nr) ;
    reset archive bit;
    label.lab(dr size) INCR 1;
    block nr INCR 1
  PER;
  put label.


  init label:
  label.lab(archive version) := 0 ;
  label.lab(first page stored) := 0 ;
  label.lab(dr size) := 0;
  INT VAR j;
  FOR j FROM first bit word UPTO label size REP
    label.lab (j) := all ones
  PER.

  put label:
  put external block (label ds, 2, label block nr).

  reset archive bit:
  reset bit (label.lab (page DIV 16+first bit word), page MOD 16).

END PROC write;

PROC get label:

  enable stop ;
  get external block (label ds, 2, block nr)  ;
  block nr INCR 1;
  check label.

check label:
  IF may be z80 format label OR may be old olivetti format label
    THEN
    ELSE errorstop (inconsistent, "Archiv inkonsistent")
  FI.

may be z80 format label :
  z80 archive AND label.lab(dr size) > 0 .

may be old olivetti format label :
  olivetti AND label.lab(first page stored)=0 AND label.lab(dr size+1) > 0 .

END PROC get label; 
 
PROC next page:
  IF z80 archive 
  THEN 
    WHILE labelbits = all ones REP
      bitword INCR 1;
      IF bitword >= label size THEN
      no further page := true; LEAVE next page FI
    PER;
    INT VAR p := lowest reset (labelbits);
    set bit (labelbits, p);
    page := 16*(bitword-first bit word)+p 
  ELSE
    WHILE oli bits = 0 REP 
      bitword INCR 1; 
      IF bitword >= labelsize-64 THEN
      no further page := true; LEAVE next page FI 
    PER; 
    p := lowest set (oli bits); 
    reset bit (olibits, p); 
    page := 16*(bitword-firstbitword)+p; 
  FI. 
 
  label bits : label.lab (bitword).
  oli bits : label.lab (bitword+1). 
 
END PROC next page;
.
olivetti : label.lab (archive version) = -1. 
 
z80 archive : label.lab (archive version) = 0. 
 
init next page:
   BOOL VAR no further page := false;
   bitword := first bit word.

check rerun :
    IF rerun <> session
      THEN errorstop ("RERUN beim Archiv-Zugriff")
    FI .

PROC get external block (DATASPACE VAR ds, INT CONST page,
                         INT CONST block nr): 

  INT VAR error ;
  read block (ds, page, block nr, error) ;
  SELECT error OF
    CASE 0: read succeeded
    CASE 1: error stop ("Lesen unmoeglich (Archiv)")
    CASE 2: read failed
    CASE 3: error stop ("Archiv-Ueberlauf") 
    OTHERWISE error stop ("??? (Archiv)")
  END SELECT .

read succeeded :
  unreadable sequence length := 0 .

read failed :
  unreadable sequence length INCR 1 ;
  IF unreadable sequence length >= 30
    THEN errorstop ("30 unlesbare Bloecke hintereinander")
    ELSE error stop (read error, "Lesefehler (Archiv)")
  FI .

END PROC get external block; 
 
PROC put external block (DATASPACE CONST ds, INT CONST page, 
                         INT CONST block nr):
  INT VAR error;
  write block (ds, page, write normal, block nr, error) ;
  SELECT error OF
    CASE 0: 
    CASE 1: error stop ("Schreiben unmoeglich (Archiv)")
    CASE 2: error stop ("Schreibfehler (Archiv)")
    CASE 3: error stop ("Archiv-Ueberlauf") 
    OTHERWISE error stop ("??? (Archiv)") 
  END SELECT .

END PROC put external block;

PROC read block (DATASPACE VAR ds,
                 INT CONST ds page no, 
                 INT CONST block no,
                 INT VAR return code) :
  read block; 
  retry if read error.
 
read block: 
  block in (ds, ds page no, 0, block no, return code). 
 
retry if read error: 
  INT VAR retry;
  FOR retry FROM 1 UPTO 10 WHILE return code = 2 REP 
    reset to block 0 if fifth try; 
    read block 
  PER. 
 
reset to block 0 if fifth try: 
  IF retry = 5 
    THEN block in (ds, ds page no, 0, 0, return code) 
  FI. 
 
END PROC read block;
 
PROC write block (DATASPACE CONST ds,
                 INT CONST ds page no, 
                 INT CONST mode,
                 INT CONST block no,
                 INT VAR return code):
  write block; 
  retry if write error. 
 
write block: 
  block out (ds, ds page no, mode * 256, block no, return code) .

retry if write error: 
  INT VAR retry;
  FOR retry FROM 1 UPTO 10 WHILE return code = 2 REP 
    reset to block 0 if fifth try; 
    write block 
  PER. 
 
reset to block 0 if fifth try: 
  IF retry = 5 
    THEN disable stop;
         DATASPACE VAR dummy ds := nilspace;
         block in (dummy ds, 2, 0, 0, return code);
         forget (dummy ds);
         enable stop
  FI. 
 
END PROC write block;
 
INT PROC size (INT CONST key) :

  INT VAR return code ;
  control (5, key, 0, return code) ;
  return code .

ENDPROC size ;

INT PROC archive blocks :
  size (0)
ENDPROC archive blocks ;

PROC search dataspace (INT VAR ds pages) :

  disable stop ;
  ds pages := -1 ;
  INT CONST last block := archive blocks ;
 
  WHILE block nr < last block REP
    IF block is dataspace label
      THEN ds pages := pages counted ;
           LEAVE search dataspace
    FI ;
    block nr INCR 1
  UNTIL is error PER .

block is dataspace label :
  look at label block ;
  IF is error
    THEN IF error code = read error OR error code = inconsistent
           THEN clear error
         FI ;
         FALSE
    ELSE count pages ;
         pages counted = number of pages as label says
  FI .

look at label block :
  INT CONST
  old block nr := block nr ;
  get label ;
  block nr := old block nr.

count pages :
  INT VAR
  pages counted := 0 ;
  init next page ;
  next page ;
  WHILE NOT no further page REP
    pages counted INCR 1 ;
    next page
  PER .

number of pages as label says :   label.lab (dr size) .

ENDPROC search dataspace ;

PROC format archive (INT CONST format code) :

  IF format is possible
    THEN format
    ELSE errorstop ("'format' ist hier nicht implementiert")
  FI .

format is possible :
  INT VAR return code ;
  control (1,0,0, return code) ;
  bit (return code, 4) .

format :
  control (7, format code, 0, return code) ;
  IF return code = 1
    THEN errorstop ("Formatieren unmoeglich")
  ELIF return code > 1
    THEN errorstop ("Schreibfehler (Archiv)")
  FI .

ENDPROC format archive ;

END PACKET basic archive;