?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE File Server: Server/Client: Load State Change Procedure, etc.' ??
MODULE dfm$application_manager_helpers;

{ PURPOSE:
{   This module contains the procedures which to aid the managing of defined
{   applications.

?? NEWTITLE := '  Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc clt$parameter_list
*copyc dfe$error_condition_codes
*copyc dft$cpu_queue
*copyc dft$p_state_change_procedure
*copyc oss$task_shared
*copyc ost$status
*copyc pmt$loaded_address
?? POP ??
*copyc amp$return
*copyc clp$include_line
*copyc dfi$display
*copyc dfi$log_display
*copyc dfp$find_mainframe_id
*copyc dfp$load_application_procedure
*copyc dfp$verify_system_administrator
*copyc osp$set_status_abnormal
*copyc pmp$execute
*copyc pmp$get_unique_name
*copyc dfv$file_server_debug_enabled
*copyc dfv$recovery_task
*copyc osv$task_shared_heap
?? OLDTITLE ??

  VAR
    dfv$p_state_change_task_status: [XDCL, oss$task_shared] ^pmt$task_status := NIL;

?? NEWTITLE := '[XDCL] dfp$attach_application_library', EJECT ??

{ PURPOSE:
{    Attach library file (if any) for each application.

  PROCEDURE [XDCL] dfp$attach_application_library
    (    p_cpu_queue: ^dft$cpu_queue);

    VAR
      line: string (200),
      line_size: integer,
      p_host_info: ^dft$host_application_info,
      status: ost$status,
      unique_name: ost$name;


    p_host_info := p_cpu_queue^.queue_header.p_host_application_info;
    IF p_host_info = NIL THEN
      RETURN;
    IFEND;
    IF dfv$file_server_debug_enabled THEN
      display (' Starting to attach application libraries');
    IFEND;

  /process_applications/
    WHILE p_host_info <> NIL DO
{    Attach library file for this application if it exists
      IF p_host_info^.p_library_file_path <> NIL THEN
        pmp$get_unique_name (unique_name, status);
        STRINGREP (line, line_size, '$system.attach_file file=', p_host_info^.p_library_file_path^, ' lfn=',
              unique_name);
        clp$include_line (line (1, line_size), {echo} TRUE, { utility } osc$null_name, status);
        IF status.normal THEN
          p_host_info^.attached_library_lfn := unique_name;
        ELSE
          display (' Unable to attach application library ');
          display (line (1, line_size));
          display_status (status);
          log_display_status ($pmt$ascii_logset [pmc$job_log, pmc$system_log], TRUE, status);
          p_host_info^.attached_library_lfn := osc$null_name;
        IFEND;
      IFEND;
      p_host_info := p_host_info^.next_p_application_info;
    WHILEND /process_applications/;

  PROCEND dfp$attach_application_library;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] dfp$execute_state_change_task  ', EJECT ??

{  This procedure starts the task that will call of the applications state
{ procedure.  The caller may choose to wait for the task to complete or not.
{ This procedure starts a task with the entry point DFP$STATE_CHANGE_TASK.
{ Parameters are communicated to that task by treating the parameter list
{ as a sequence with contents: mainframe_name, partner_is_server,
{ old_state, new_state, recovery_task.

  PROCEDURE [XDCL] dfp$execute_state_change_task
    (    mainframe_name: pmt$mainframe_id;
         partner_is_server: boolean;
         old_state: dft$server_state;
         new_state: dft$server_state;
         wait: ost$wait;
     VAR status: ost$status);

    VAR
      p_mainframe_name: ^pmt$mainframe_id,
      p_parameter_sequence: ^pmt$program_parameters,
      p_partner_is_server: ^boolean,
      p_program_attributes: ^pmt$program_attributes,
      p_program_description: ^pmt$program_description,
      p_recovery_task: ^boolean,
      p_state: ^dft$server_state,
      taskid: pmt$task_id;

    PUSH p_program_description: [[REP 1 OF pmt$program_attributes]];
    RESET p_program_description;
    NEXT p_program_attributes IN p_program_description;
    p_program_attributes^.contents := $pmt$prog_description_contents
          [pmc$starting_proc_specified, pmc$load_map_options_specified, pmc$term_error_level_specified];
    p_program_attributes^.starting_procedure := 'DFP$STATE_CHANGE_TASK';
    p_program_attributes^.load_map_options := $pmt$load_map_options [pmc$no_load_map];
    p_program_attributes^.termination_error_level := pmc$warning_load_errors;

    PUSH p_parameter_sequence: [[REP 1 OF ost$string]];
    RESET p_parameter_sequence;
    NEXT p_mainframe_name IN p_parameter_sequence;
    p_mainframe_name^ := mainframe_name;
    NEXT p_partner_is_server IN p_parameter_sequence;
    p_partner_is_server^ := partner_is_server;
    NEXT p_state IN p_parameter_sequence;
    p_state^ := old_state;
    NEXT p_state IN p_parameter_sequence;
    p_state^ := new_state;
    NEXT p_recovery_task IN p_parameter_sequence;
    p_recovery_task^ := dfv$recovery_task;

    IF dfv$p_state_change_task_status = NIL THEN
      ALLOCATE dfv$p_state_change_task_status IN osv$task_shared_heap^;
    IFEND;

    pmp$execute (p_program_description^, p_parameter_sequence^, wait, taskid, dfv$p_state_change_task_status^,
          status);
  PROCEND dfp$execute_state_change_task;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] dfp$load_and_call_state_change  ', EJECT ??

{ PURPOSE:
{   Load state_change_procedure (if any) for each
{   application and call the state change procedure. The procedure is
{   called directly within the calling task .
{   This procedure assumes that the applications command library has been attached.

  PROCEDURE [XDCL] dfp$load_and_call_state_change
    (    p_cpu_queue: ^dft$cpu_queue;
         partner_is_server: boolean;
         old_state: dft$server_state;
         new_state: dft$server_state;
     VAR status: ost$status);

    VAR
      line: string (200),
      line_size: integer,
      loaded_address: pmt$loaded_address,
      p_host_info: ^dft$host_application_info,
      p_state_change_procedure: dft$p_state_change_procedure;

    status.normal := TRUE;
    IF old_state = new_state THEN
      RETURN;
    IFEND;

    p_host_info := p_cpu_queue^.queue_header.p_host_application_info;
    IF p_host_info = NIL THEN
      RETURN;
    IFEND;
    IF dfv$file_server_debug_enabled THEN
      display (' Starting to load state_change_procedure(s)');
    IFEND;

  /process_applications/
    WHILE p_host_info <> NIL DO

{ Load state change procedure if it was defined.
      IF (p_host_info^.attached_library_lfn <> osc$null_name) AND
            (p_host_info^.state_change_procedure_name <> osc$null_name) THEN
        dfp$load_application_procedure (p_host_info^.state_change_procedure_name,
              p_host_info^.attached_library_lfn, loaded_address, status);
        IF status.normal THEN
          #CONVERT_POINTER_TO_PROCEDURE (loaded_address.pointer_to_procedure, p_state_change_procedure);

          IF dfv$file_server_debug_enabled THEN
            STRINGREP (line, line_size, ' Calling state_change_procedure ',
                  p_host_info^.state_change_procedure_name);
            display (line (1, line_size));
            log_display ($pmt$ascii_logset [pmc$job_log, pmc$system_log], line (1, line_size));
          IFEND;
          p_state_change_procedure^ (p_cpu_queue^.queue_header.destination_mainframe_name, partner_is_server,
                old_state, new_state, status);
          IF NOT status.normal THEN
            IF dfv$file_server_debug_enabled THEN
              display_status (status);
            IFEND;
            STRINGREP (line, line_size, ' Abnormal status from state_change_procedure: ',
                  p_host_info^.state_change_procedure_name);
            log_display ($pmt$ascii_logset [pmc$job_log, pmc$system_log], line (1, line_size));
            log_display_status ($pmt$ascii_logset [pmc$job_log, pmc$system_log], TRUE, status);
            status.normal := TRUE;
          IFEND;
        ELSE
          STRINGREP (line, line_size, ' Abnormal status while loading state_change_procedure: ',
                p_host_info^.state_change_procedure_name);
          IF dfv$file_server_debug_enabled THEN
            display (line (1, line_size));
            display_status (status);
          IFEND;
          log_display ($pmt$ascii_logset [pmc$job_log, pmc$system_log], line (1, line_size));
          log_display_status ($pmt$ascii_logset [pmc$job_log, pmc$system_log], TRUE, status);
          status.normal := TRUE;
        IFEND;
      IFEND;
      p_host_info := p_host_info^.next_p_application_info;
    WHILEND /process_applications/;

  PROCEND dfp$load_and_call_state_change;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] dfp$return_application_library', EJECT ??

{ PURPOSE:
{   The purpose of this request is to return all application libraries which
{   have been attached in this task.

  PROCEDURE [XDCL] dfp$return_application_library
    (    p_cpu_queue: ^dft$cpu_queue);

    VAR
      line: string (200),
      line_size: integer,
      local_status: ost$status,
      p_host_info: ^dft$host_application_info;

    local_status.normal := TRUE;
    p_host_info := p_cpu_queue^.queue_header.p_host_application_info;
    IF p_host_info = NIL THEN
      RETURN;
    IFEND;
    IF dfv$file_server_debug_enabled THEN
      display (' Starting to return application libraries');
    IFEND;

  /process_applications/
    WHILE p_host_info <> NIL DO
{    Return library file for this if it exists.
      IF p_host_info^.attached_library_lfn <> osc$null_name THEN
        IF dfv$file_server_debug_enabled THEN
          STRINGREP (line, line_size, ' Returning library for application: ', p_host_info^.application_name);
          display (line (1, line_size));
        IFEND;
        amp$return (p_host_info^.attached_library_lfn, local_status);
        IF local_status.normal THEN
          p_host_info^.attached_library_lfn := osc$null_name;
        ELSE
          STRINGREP (line, line_size, ' Unable to return library for application: ',
                p_host_info^.application_name);
          display (line (1, line_size));
          display_status (local_status);
          log_display_status ($pmt$ascii_logset [pmc$system_log], TRUE, local_status);
          local_status.normal := TRUE;
        IFEND;
      IFEND;
      p_host_info := p_host_info^.next_p_application_info;
    WHILEND /process_applications/;

  PROCEND dfp$return_application_library;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] dfp$state_change_task  ', EJECT ??

{ This procedure is the entry point for the state change task which was
{ started by calling dfp$execute_state_change_task.  This finds the
{ requested mainframe and then loads and calls all of the state change
{ procedures for each application.

  PROCEDURE [XDCL, #GATE] dfp$state_change_task
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

    VAR
      mainframe_found: boolean,
      p_cpu_queue: ^dft$cpu_queue,
      p_mainframe_name: ^pmt$mainframe_id,
      p_new_state: ^dft$server_state,
      p_old_state: ^dft$server_state,
      p_parameter_sequence: ^pmt$program_parameters,
      p_partner_is_server: ^boolean,
      p_q_interface_directory_entry: ^dft$q_interface_directory_entry,
      p_queue_interface_table: dft$p_queue_interface_table,
      p_recovery_task: ^boolean,
      queue_index: dft$queue_index;

    dfp$verify_system_administrator ('DFP$STATE_CHANGE_TASK', status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    { Crack the parameters in the parameter list
    p_parameter_sequence := ^parameter_list;
    RESET p_parameter_sequence;
    NEXT p_mainframe_name IN p_parameter_sequence;
    NEXT p_partner_is_server IN p_parameter_sequence;
    NEXT p_old_state IN p_parameter_sequence;
    NEXT p_new_state IN p_parameter_sequence;
    NEXT p_recovery_task IN p_parameter_sequence;
    dfv$recovery_task := p_recovery_task^;

    dfp$find_mainframe_id (p_mainframe_name^, NOT p_partner_is_server^, mainframe_found,
          p_queue_interface_table, p_cpu_queue, queue_index, p_q_interface_directory_entry);
    IF mainframe_found THEN
      dfp$load_and_call_state_change (p_cpu_queue, p_partner_is_server^, p_old_state^, p_new_state^, status);
    ELSE
      IF p_partner_is_server^ THEN
        osp$set_status_abnormal (dfc$file_server_id, dfe$mainframe_not_server, p_mainframe_name^, status);
      ELSE
        osp$set_status_abnormal (dfc$file_server_id, dfe$mainframe_not_client, p_mainframe_name^, status);
      IFEND;
    IFEND;

    IF dfv$file_server_debug_enabled AND NOT status.normal THEN
      display (' dfp$state_change_task ');
      display_status (status);
    IFEND;
  PROCEND dfp$state_change_task;
?? OLDTITLE ??
MODEND dfm$application_manager_helpers;
