summaryrefslogtreecommitdiff
path: root/app/flint/0.4/src/offline.manager
blob: 7f97421d84b54d10dbc08ea7dc1d9f3d1f74613e (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
PACKET offline manager                        (* Autor: Thomas Berlage *)
                                              (* Stand: 20.01.88       *)
  DEFINES

  begin,
  deferred end,
  own task password,
  continued from,
  continue,
  partner task :


LET
  ack               = 0,
  nak               = 1,
  error nak         = 2,
  second phase ack  = 5,
  password ack      = 6,

  begin code        = 4,
  password code     = 9,

  continue code         = 100,
  ask for password code = 199;

LET
  taskname invalid =
    "Taskname ungültig",
  task not ready =
    "Vater antwortet nicht",
  direct continue impossible =
    "Zieltask kann nicht direkt angekoppelt werden",
  t password =
    "Passwort:",
  t wrong password =
    "Falsches Passwort",
  order task no partner =
    "Ankoppeln nur für Partnertasks",
  continue not partner =
    "Nur Partner können angekoppelt werden";


BOOL VAR
  controlled mode := FALSE,
  end myself := FALSE;

TEXT VAR
  own password := "";

DATASPACE VAR ds := nilspace;

INT VAR
  reply,
  order,
  control channel,
  last order,
  phase number;

BOUND TEXT VAR reply message;

BOUND STRUCT (TEXT tname, tpass, TASK task, PROCA start proc) VAR sv msg;

TASK VAR
  order task,
  last order task := niltask;

ROW 4 TASK VAR pt;

INITFLAG VAR pt init;



PROC begin (TEXT CONST task name, father name) :

  enable stop;
  init partner;
  IF task name = "-" THEN
    errorstop (taskname invalid)
  END IF;
  call begin code;
  IF reply = password code THEN
    sv msg := ds;
    get password;
    call (task (father name), begin code, ds, reply)
  END IF;
  IF reply = ack THEN
    TASK CONST new task := task (task name);
    forget (ds);
    wait for init
  ELIF reply = error nak THEN
    reply message := ds;
    disable stop;
    errorstop (CONCR (reply message));
    forget (ds)
  ELSE
    forget (ds)
  END IF .

call begin code :
  INT VAR i;
  forget (ds); ds := nilspace;
  sv msg := ds;
  CONCR (sv msg). tname := task name;
  CONCR (sv msg). tpass := "";
  FOR i FROM 1 UPTO 5 REP
    pingpong (task (father name), begin code, ds, reply);
    IF reply = -2 THEN pause (5) END IF
  UNTIL reply <> -2 END REP;
  IF reply = -2 THEN
    errorstop (task not ready)
  END IF .

get password :
  dialog (t password);
  get secret line (CONCR (sv msg). tpass);
  cover tracks .

wait for init :
  WHILE status (new task) <> 2 REP pause (10) END REP .

END PROC begin;

PROC deferred end :

  end myself := TRUE

END PROC deferred end;

PROC own task password (TEXT CONST word) :

  own password := length (own password) * " ";
  own password := word;
  cover tracks

END PROC own task password;

TASK PROC continued from :

  last order task

END PROC continued from;

PROC i continue (TASK CONST t,
     PROC (DATASPACE VAR, INT CONST, INT CONST, TASK CONST) manager) :

  enable stop;
  IF is niltask (t) THEN
    break;
    disable stop
  ELSE
    ask for continue
  END IF;
  end if required;
  WHILE NOT online REP
    remember error message;
    prepare manager;
    wait for order
  END REP;
  repeat error message .

ask for continue :
  INT CONST my channel := channel;
  ask if password required;
  break (quiet);
  send continue request .

ask if password required :
  INT VAR i;
  forget (ds); ds := nilspace;
  FOR i FROM 1 UPTO 5 REP
    pingpong (t, ask for password code, ds, reply);
    IF reply = -2 THEN pause (5) END IF
  UNTIL reply <> -2 END REP;
  init password ds;
  IF reply = password ack THEN
    get password from user
  ELIF reply = ack THEN
    set password empty
  ELSE
    errorstop (direct continue impossible)
  END IF .

init password ds :
  forget (ds);
  ds := nilspace;
  reply message := ds .

get password from user :
  dialog (t password);
  get secret line (CONCR (reply message));
  cover tracks .

set password empty :
  CONCR (reply message) := "" .

send continue request :
  FOR i FROM 1 UPTO 5 REP
    pingpong (t, continue code + my channel, ds, reply);
    IF reply = -2 THEN pause (5) END IF
  UNTIL reply <> -2 END REP;
  disable stop;
  forget (ds);
  IF reply <> ack THEN
    continue (my channel)
  END IF .

end if required :
  IF end myself OR (controlled mode CAND NOT exists (pt (1))) THEN
    end (myself)
  END IF .

remember error message :
  TEXT VAR stored error;
  IF is error THEN
    stored error := error message;
    clear error
  ELSE
    stored error := ""
  END IF .

prepare manager :
  set autonom;
  command dialogue (FALSE);
  INT VAR old heap size := heap size;
  last order task := niltask .

wait for order :
  DATASPACE VAR local ds := nilspace;
  REP
    wait (local ds, order, order task);
    IF order <> second phase ack THEN
      prepare first phase;
      manager with end check
    ELIF order task = last order task THEN
      prepare second phase;
      manager (local ds, order, phase number, order task)
    ELSE
      send nak
    END IF;
    send error if necessary;
    collect heap garbage if necessary
  END REP .

prepare first phase :
  phase number := 1;
  last order := order;
  last order task := order task .

prepare second phase :
  phase number INCR 1;
  order := last order .

send nak :
  forget (local ds);
  local ds := nilspace;
  send (order task, nak, local ds) .

send error if necessary :
  IF is error THEN
    forget (local ds);
    local ds := nilspace;
    reply message := local ds;
    CONCR (reply message) := error message;
    clear error;
    send (order task, error nak, local ds)
  END IF .

collect heap garbage if necessary :
  IF heap size > old heap size + 8 THEN
    collect heap garbage;
    old heap size := heap size
  END IF .

manager with end check :
  IF order = ask for password code THEN
    answer if password required
  ELIF order > continue code AND order < continue code + 16 THEN
    try continue channel
  ELSE
    manager (local ds, order, phase number, order task)
  END IF .

answer if password required :
  IF password required THEN
    send (order task, password ack, local ds)
  ELSE
    send (order task, ack, local ds)
  END IF .

password required :
  own password <> "" .

try continue channel :
  check control;
  check password;
  call (supervisor, order, local ds, reply);
  IF NOT (order task = supervisor) THEN
    send (order task, reply, local ds)
  END IF;
  IF reply = ack THEN
    forget (local ds);
    LEAVE wait for order
  END IF .

check control :
  IF controlled mode CAND NOT is partner (order task) OR
       control channel > 0 CAND order - continue code <> control channel THEN
    errorstop (order task no partner);
    LEAVE try continue channel
  END IF .

check password :
  IF NOT (order task = supervisor) THEN
    reply message := local ds;
    IF CONCR (reply message) <> own password THEN
      errorstop (t wrong password);
      LEAVE try continue channel
    END IF
  END IF .

repeat error message :
  IF stored error <> "" THEN errorstop (stored error) END IF;
  command dialogue (TRUE) .

END PROC i continue;

PROC continue (TASK CONST t,
     PROC (DATASPACE VAR, INT CONST, INT CONST, TASK CONST) manager) :

  enable stop;
  init partner;
  control channel := 0;
  IF t = myself THEN
    (* do nothing *)
  ELIF controlled mode THEN
    IF NOT is partner (t) THEN errorstop (continue not partner) END IF
  ELIF is partner (t) THEN
    control channel := channel
  END IF;
  i continue (t,
      PROC (DATASPACE VAR, INT CONST, INT CONST, TASK CONST) manager)

END PROC continue;

BOOL PROC is partner (TASK CONST t) :

  NOT is niltask (t) CAND
    (t = pt (1) OR t = pt (2) OR t = pt (3) OR t = pt (4))

END PROC is partner;

TASK PROC partner task (INT CONST index) :

  init partner;
  pt (index)

END PROC partner task;

PROC partner task (INT CONST index, TASK CONST t) :

  init partner;
  pt (index) := t;
  IF index = 1 CAND NOT (t = myself) THEN
    controlled mode := TRUE
  END IF

END PROC partner task;

PROC init partner :

  IF NOT initialized (pt init) THEN
    do init
  END IF .

do init :
  pt (1) := niltask; pt (2) := niltask;
  pt (3) := niltask; pt (4) := niltask .

END PROC init partner;


END PACKET offline manager;