369
(* method reboot_if_possible =
377
370
(* This is invisible for the user: don't set the next state *)
378
371
Task_runner.the_task_runner#schedule ~name:("create "^self#get_name) (fun () -> self#create_right_now)
380
373
method (*private*) destroy_my_simulated_device =
381
Log.printf "component \"%s\": destroying my simulated device.\n" self#get_name;
374
Log.printf1 "component \"%s\": destroying my simulated device.\n" self#get_name;
382
375
(* This is invisible for the user: don't set the next state *)
383
376
Task_runner.the_task_runner#schedule ~name:("destroy "^self#get_name)(fun () -> self#destroy_right_now)
398
391
self#set_next_simulated_device_state (Some DeviceOff);
399
392
self#enqueue_task_with_progress_bar (s_ "Stopping") (fun () -> if self#can_gracefully_shutdown then self#gracefully_shutdown_right_now)
394
method gracefully_restart =
395
if not self#can_gracefully_shutdown then () else (* continue *)
396
self#gracefully_shutdown;
397
self#set_next_simulated_device_state (Some DeviceOn);
398
self#enqueue_task_with_progress_bar
401
Thread.delay 7.; (* Ugly: to prevent a killer signal (all this part must be rewritten with Cortex_lib as soon as possible!!) *)
402
if self#can_startup then self#startup_right_now)
401
404
method poweroff =
402
405
self#set_next_simulated_device_state (Some DeviceOff);
403
406
self#enqueue_task_with_progress_bar (s_ "Shutting down") (fun () -> if self#can_poweroff then self#poweroff_right_now)
426
429
(** The unit parameter is needed: see how it's used in simulated_network: *)
427
430
method private destroy_because_of_unexpected_death () =
428
Log.printf "You don't deadlock here %s, do you? -1\n" self#get_name;
431
Log.printf1 "You don't deadlock here %s, do you? -1\n" self#get_name;
429
432
Recursive_mutex.with_mutex mutex
431
Log.printf "You don't deadlock here %s, do you? 0\n" self#get_name;
434
Log.printf1 "You don't deadlock here %s, do you? 0\n" self#get_name;
433
436
self#destroy_right_now
435
Log.printf "WARNING: destroy_because_of_unexpected_death: failed (%s)\n"
438
Log.printf1 "WARNING: destroy_because_of_unexpected_death: failed (%s)\n"
436
439
(Printexc.to_string e);
438
441
self#set_next_simulated_device_state None)); (* don't show next-state icons for this *)
440
443
method (*private*) destroy_right_now =
441
444
Recursive_mutex.with_mutex mutex
443
Log.printf "About to destroy the simulated device %s \n" self#get_name;
446
Log.printf1 "About to destroy the simulated device %s \n" self#get_name;
444
447
match !automaton_state, !simulated_device with
445
448
| (DeviceOn | DeviceSleeping), Some(d) ->
447
450
" (destroying the on/sleeping device %s. Powering it off first...)\n"
449
452
self#poweroff_right_now; (* non-gracefully *)
450
453
self#destroy_right_now
451
454
| NoDevice, None ->
453
456
" (destroying the already 'no-device' device %s. Doing nothing...)\n"
455
458
() (* Do nothing, but don't fail. *)
456
459
| DeviceOff, Some(d) ->
457
460
((* An endpoint for cables linked to self was just added; we
458
461
may need to start some cables. *)
460
463
" (destroying the off device %s: decrementing its cables rc...)\n"
464
Log.printf "Unpinning the cable %s " (cable#show "");
467
Log.printf1 "Unpinning the cable %s " (cable#show "");
465
468
cable#decrement_alive_endpoint_no;
466
Log.printf ("The cable %s was unpinned with success\n") (cable#show "");
469
Log.printf1 ("The cable %s was unpinned with success\n") (cable#show "");
468
471
self#get_involved_cables;
469
Log.printf " (destroying the simulated device implementing %s...)\n" self#get_name;
472
Log.printf1 " (destroying the simulated device implementing %s...)\n" self#get_name;
470
473
d#destroy; (* This is the a method from some object in Simulation_level *)
471
474
simulated_device := None;
472
475
automaton_state := NoDevice;
473
476
self#set_next_simulated_device_state None;
474
Log.printf "We're not deadlocked yet (%s). Great.\n" self#get_name);
477
Log.printf1 "We're not deadlocked yet (%s). Great.\n" self#get_name);
476
479
raise_forbidden_transition "destroy_right_now"
478
Log.printf "The simulated device %s was destroyed with success\n" self#get_name
481
Log.printf1 "The simulated device %s was destroyed with success\n" self#get_name
481
484
method (*private*) startup_right_now =
484
487
(* Don't startup ``incorrect'' devices. This is currently limited to cables of the
485
488
wrong crossoverness which the user has defined by mistake: *)
486
489
if self#is_correct then begin
487
Log.printf "Starting up the device %s...\n" self#get_name;
490
Log.printf1 "Starting up the device %s...\n" self#get_name;
488
491
match !automaton_state, !simulated_device with
489
492
| NoDevice, None ->
490
(Log.printf "Creating processes for %s first...\n" self#get_name;
493
(Log.printf1 "Creating processes for %s first...\n" self#get_name;
491
494
self#create_right_now;
492
Log.printf "Processes for %s were created...\n" self#get_name;
495
Log.printf1 "Processes for %s were created...\n" self#get_name;
493
496
self#startup_right_now
497
500
(d#startup; (* This is the a method from some object in Simulation_level *)
498
501
automaton_state := DeviceOn;
499
502
self#set_next_simulated_device_state None;
500
Log.printf "The device %s was started up\n" self#get_name
503
Log.printf1 "The device %s was started up\n" self#get_name
504
Log.printf "startup_right_now: called in state %s: nothing to do.\n" (self#automaton_state_as_string)
507
Log.printf1 "startup_right_now: called in state %s: nothing to do.\n" (self#automaton_state_as_string)
506
509
| _ -> raise_forbidden_transition "startup_right_now"
508
Log.printf "REFUSING TO START UP the ``incorrect'' device %s!!!\n" self#get_name
511
Log.printf1 "REFUSING TO START UP the ``incorrect'' device %s!!!\n" self#get_name
511
514
method (*private*) suspend_right_now =
512
515
Recursive_mutex.with_mutex mutex
514
Log.printf "Suspending up the device %s...\n" self#get_name;
517
Log.printf1 "Suspending up the device %s...\n" self#get_name;
515
518
match !automaton_state, !simulated_device with
516
519
DeviceOn, Some(d) ->
517
520
(d#suspend; (* This is the a method from some object in Simulation_level *)
522
525
method (*private*) resume_right_now =
523
526
Recursive_mutex.with_mutex mutex
525
Log.printf "Resuming the device %s...\n" self#get_name;
528
Log.printf1 "Resuming the device %s...\n" self#get_name;
526
529
match !automaton_state, !simulated_device with
527
530
| DeviceSleeping, Some(d) ->
528
531
(d#resume; (* This is the a method from some object in Simulation_level *)
549
552
self#gracefully_shutdown_right_now)
551
554
| NoDevice, _ | DeviceOff, _ ->
552
Log.printf "gracefully_shutdown_right_now: called in state %s: nothing to do.\n" (self#automaton_state_as_string)
555
Log.printf1 "gracefully_shutdown_right_now: called in state %s: nothing to do.\n" (self#automaton_state_as_string)
554
557
| _ -> raise_forbidden_transition "gracefully_shutdown_right_now")
556
559
method (*private*) poweroff_right_now =
557
560
Recursive_mutex.with_mutex mutex
559
Log.printf "Powering off the device %s...\n" self#get_name;
562
Log.printf1 "Powering off the device %s...\n" self#get_name;
560
563
match !automaton_state, !simulated_device with
561
564
| DeviceOn, Some(d) ->
562
565
(d#shutdown; (* non-gracefully *)
1317
1320
method destroy_my_ifconfig =
1318
Log.printf "component \"%s\": destroying my ifconfig.\n" self#get_name;
1321
Log.printf1 "component \"%s\": destroying my ifconfig.\n" self#get_name;
1319
1322
network#ifconfig#remove_subtree_by_name self#get_name;
1321
1324
method destroy_my_history =
1322
Log.printf "component \"%s\": destroying my history.\n" self#get_name;
1325
Log.printf1 "component \"%s\": destroying my history.\n" self#get_name;
1323
1326
network#history#remove_device_tree self#get_name;
1325
1328
method update_virtual_machine_with ~name ~port_no kernel =
1436
1439
method set_dotoptions x = dotoptions <- Some x
1438
1441
method components : (component list) =
1440
(nodes#get :> component list)
1443
(nodes#get :> component list)
1441
1444
(cables#get :> component list) (* CABLES MUST BE AT THE FINAL POSITION for marshaling !!!! *)
1443
method components_of_kind ?(kind:[`Node | `Cable] option) () =
1446
method components_of_kind ?(kind:[`Node | `Cable] option) () =
1444
1447
match kind with
1445
1448
| None -> self#components
1446
| Some `Node -> (nodes#get :> (component list))
1447
| Some `Cable -> (cables#get :> (component list))
1449
| Some `Node -> (nodes#get :> (component list))
1450
| Some `Cable -> (cables#get :> (component list))
1449
1452
method disjoint_union_of_nodes_and_cables : ((component * [`Node | `Cable]) list) =
1450
1453
let xs = List.map (fun x -> x,`Node ) (nodes#get :> component list) in
1451
1454
let ys = List.map (fun x -> x,`Cable) (cables#get :> component list) in
1476
1478
Log.printf "\tWait for all devices to terminate...\n";
1477
1479
(** Make sure that all devices have actually been terminated before going
1478
1480
on: we don't want them to lose filesystem access: *)
1479
Log.printf "\tAll devices did terminate.\n";
1480
Log.printf "network#reset: end (success)\n";
1481
Log.print_string "---\n";
1481
Log.printf "\tAll devices did terminate.\nnetwork#reset: end (success)\n---\n";
1484
1484
method destroy_process_before_quitting () =
1669
1669
method get_node_names =
1670
1670
List.map (fun x->x#get_name) (nodes#get)
1672
method get_nodes_that_can_startup ~devkind () =
1673
ListExtra.filter_map
1674
(fun x -> if (x#devkind = devkind) && x#can_startup then Some x#get_name else None)
1677
method get_nodes_that_can_gracefully_shutdown ~devkind () =
1678
ListExtra.filter_map
1679
(fun x -> if (x#devkind = devkind) && x#can_gracefully_shutdown then Some x#get_name else None)
1682
method get_nodes_that_can_suspend ~devkind () =
1683
ListExtra.filter_map
1684
(fun x -> if (x#devkind = devkind) && x#can_suspend then Some x#get_name else None)
1687
(* Including cables (suspend=disconnect, resume=reconnect). The boolean in the result
1688
indicates if the component is suspended (sleeping): *)
1672
method private predicate_of_optional_devkind ?devkind () =
1674
| Some devkind -> (fun x -> x#devkind = devkind)
1675
| None -> (fun x -> true)
1677
method get_nodes_such_that ?devkind (predicate) =
1678
let devkindp = self#predicate_of_optional_devkind ?devkind () in
1679
List.filter (fun x -> (devkindp x) && (predicate x)) (nodes#get)
1681
(* --- can_startup --- *)
1683
method get_nodes_that_can_startup ?devkind () =
1684
self#get_nodes_such_that ?devkind (fun x -> x#can_startup)
1686
method get_node_names_that_can_startup ?devkind () =
1687
List.map (fun x -> x#get_name) (self#get_nodes_that_can_startup ?devkind ())
1689
(* --- can_gracefully_shutdown --- *)
1691
method get_nodes_that_can_gracefully_shutdown ?devkind () =
1692
self#get_nodes_such_that ?devkind (fun x -> x#can_gracefully_shutdown)
1694
method get_node_names_that_can_gracefully_shutdown ?devkind () =
1695
List.map (fun x -> x#get_name) (self#get_nodes_that_can_gracefully_shutdown ?devkind ())
1697
(* --- can_suspend --- *)
1699
method get_nodes_that_can_suspend ?devkind () =
1700
self#get_nodes_such_that ?devkind (fun x -> x#can_suspend)
1702
method get_node_names_that_can_suspend ?devkind () =
1703
List.map (fun x -> x#get_name) (self#get_nodes_that_can_suspend ?devkind ())
1705
(* --- can_resume --- *)
1707
method get_nodes_that_can_resume ?devkind () =
1708
self#get_nodes_such_that ?devkind (fun x -> x#can_resume)
1710
method get_node_names_that_can_resume ?devkind () =
1711
List.map (fun x -> x#get_name) (self#get_nodes_that_can_resume ?devkind ())
1713
(* Including cables (suspend=disconnect, resume=reconnect). The boolean in the result
1714
indicates if the component is suspended (sleeping): *)
1689
1715
method get_component_names_that_can_suspend_or_resume () : (string * [`Node|`Cable] * bool) list =
1690
1716
ListExtra.filter_map
1691
(fun (x, node_or_cable) ->
1717
(fun (x, node_or_cable) ->
1692
1718
let can_suspend = x#can_suspend in
1693
1719
let can_resume = lazy x#can_resume in
1694
if can_suspend || (Lazy.force can_resume)
1695
then Some (x#get_name, node_or_cable, (Lazy.force can_resume))
1720
if can_suspend || (Lazy.force can_resume)
1721
then Some (x#get_name, node_or_cable, (Lazy.force can_resume))
1697
1723
self#disjoint_union_of_nodes_and_cables
1699
method get_nodes_that_can_resume ~devkind () =
1700
ListExtra.filter_map
1701
(fun x -> if (x#devkind = devkind) && x#can_resume then Some x#get_name else None)
1704
1725
(** List of direct cable names in the network *)
1705
1726
method get_direct_cable_names =