?? RIGHT := 110 ??
?? NEWTITLE := 'INSTALL_SOFTWARE Utility: RAP$ACTIVATE_PRODUCTS Interface.' ??
MODULE ram$activate_products;

{ PURPOSE:
{   This module contains the interface that takes a subproduct or subproducts
{   from the staging cycle to the active state.
{
{ DESIGN:
{   The compiled module resides in RAF$LIBRARY.
{
{ NOTES:
{

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc rac$installation_cycles
*copyc rae$install_software_cc
*copyc rat$installation_control_record
?? POP ??
*copyc osp$append_status_file
*copyc osp$generate_log_message
*copyc osp$set_status_abnormal
*copyc pfp$change
*copyc rap$clear_installation
*copyc rap$convert_path_to_str
*copyc rap$get_cycle_data
*copyc rap$record_step_status
*copyc rap$record_subproduct_status
*copyc rap$sort_cycles

?? TITLE := 'Global Declarations Declared by This Module', EJECT ??

?? TITLE := '[XDCL] rap$activate_products', EJECT ??

{ PURPOSE:
{   This interface takes a subproduct or subproducts from the staging
{   cycle to the active state.
{
{ DESIGN:
{   To activate a subproduct a cycle change is performed on the subproduct's
{   files from the staging cycle to the next active cycle.
{
{   The inability to activate any file belonging to a subproduct will cause
{   the entire subproduct to have failed the activate step.  The
{   installation processing record for that subproduct is set as such and
{   the subproduct will be cleared from the the system at the conclusion of
{   this step.
{
{   The failure of one subproduct will not jeopardize the remaining
{   subproducts.  Each subproduct will be processed independently.
{
{ NOTES:
{   The SUBPRODUCT_FAILED_PROCESSING boolean has been initialized outside of
{   this interface and should never be initialized here.

  PROCEDURE [XDCL] rap$activate_products
    (VAR installation_control_record {input, output} : rat$installation_control_record;
     VAR subproducts_failed_processing: boolean;
     VAR status: ost$status);


    VAR
      ignore_status: ost$status,
      local_status: ost$status,
      processing_record: rat$subp_processing_record,
      subproduct_index: rat$subproduct_count,
      task_status: ost$status;


    status.normal := TRUE;

    IF NOT (rac$activate_subproducts_step IN installation_control_record.processing_header_p^.step_set) THEN
      RETURN;
    IFEND;

    rap$record_step_status (rac$activate_subproducts_step, rac$step_started, installation_control_record,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /main/
    FOR subproduct_index := 1 TO UPPERBOUND (installation_control_record.subproduct_processing_records_p^) DO
      processing_record := installation_control_record.subproduct_processing_records_p^ [subproduct_index];

      IF (installation_control_record.job_identifier = processing_record.job_identifier) AND
            (rac$activate_files_task IN processing_record.task_set) AND
            (processing_record.task_status <> rac$task_failed) THEN

        rap$record_subproduct_status (rac$activate_files_task, rac$task_started, subproduct_index,
              installation_control_record, ignore_status);

        activate_subproduct (processing_record.installation_catalog_p^,
              processing_record.subproduct_info_pointers.element_list_p,
              processing_record.subproduct_info_pointers.subproduct_info_seq_p, installation_control_record.
              scratch_seq_p, task_status);

        IF task_status.normal THEN
          rap$record_subproduct_status (rac$activate_files_task, rac$task_completed, subproduct_index,
                installation_control_record, ignore_status);
        ELSE
          osp$generate_log_message ($pmt$ascii_logset [pmc$job_log], task_status, ignore_status);
          rap$record_subproduct_status (rac$activate_files_task, rac$task_failed, subproduct_index,
                installation_control_record, ignore_status);
          subproducts_failed_processing := TRUE;
        IFEND;

      IFEND;
    FOREND /main/;

    rap$clear_installation (installation_control_record, ignore_status);

    rap$record_step_status (rac$activate_subproducts_step, rac$step_completed, installation_control_record,
          local_status);
    IF status.normal AND (NOT local_status.normal) THEN
      status := local_status;
    IFEND;

  PROCEND rap$activate_products;

?? TITLE := 'activate_file', EJECT ??

{ PURPOSE:
{   This procedure activates a file for a subproduct.
{
{ DESIGN:
{   Cycle data is retieved for the file.  The next active cycle is the
{   highest cycle + 1.  A standard change interface is called to change the
{   file currently in the staging cycle to the next active cycle.
{
{ NOTES:
{   The scratch sequence is used by RAP$GET_CYCLE_DATA as temporary storage
{   for cycles array.
{
{   The cycles array is sorted in decending order, so that makes the first
{   entry the highest.  Also you can assume that the highest cycle will not
{   be rac$max_active_cycle because of reconcile cycle conflicts step.
{
{   IMPORTANT - There is concern that the actual $next active cycle can
{   change between the initial pickup of the value and the changing of the
{   file cycles.
{

  PROCEDURE activate_file
    (    element_p: ^rat$element;
         file_path: pft$path;
     VAR scratch_seq_p {input} : ^SEQ ( * );
     VAR status: ost$status);


    VAR
      current_cycle: pft$cycle_selector,
      cycles_p: pft$p_cycle_array,
      new_cycle: array [1 .. 2] of pft$change_descriptor,
      next_active_cycle: 0 .. rac$max_active_cycle,
      password: pft$password;


    status.normal := TRUE;

    { Get the cycle number for the next active cycle.

    rap$get_cycle_data (file_path, scratch_seq_p, cycles_p, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    rap$sort_cycles (cycles_p);

    next_active_cycle := cycles_p^ [1].cycle_number + 1;


    { Move the file from the staging cycle to the next active cycle.

    current_cycle.cycle_option := pfc$specific_cycle;
    current_cycle.cycle_number := rac$staging_cycle;
    new_cycle [1].change_type := pfc$cycle_number_change;
    new_cycle [1].cycle_number := next_active_cycle;
    new_cycle [2].change_type := pfc$charge_change;
    password := '';

    pfp$change (file_path, current_cycle, password, new_cycle, status);

  PROCEND activate_file;

?? TITLE := 'activate_subproduct', EJECT ??

{ PURPOSE:
{   This procedure activates the files belonging to a subproduct.
{
{ DESIGN:
{   Determining what files belong to the subproduct is accomplished by
{   traversing the element list for the subproduct.  The taverse is
{   performed using recursion and each call to ACTIVATE_SUBPRODUCT moves
{   processing down to the next catalog level.
{
{   Only active elements are processed.
{
{ NOTES:
{   The scratch sequence is used by a subsequent procedure as temporary
{   storage for file information.
{

  PROCEDURE activate_subproduct
    (    element_path: pft$path;
     VAR element_p {input} : ^rat$element;
     VAR subproduct_info_seq_p {input} : ^rat$subproduct_info_sequence;
     VAR scratch_seq_p {input} : ^SEQ ( * );
     VAR status: ost$status);


    VAR
      current_element_path_p: ^pft$path,
      first_element_down_p: ^rat$element,
      i: integer;


    status.normal := TRUE;

    { The element_path parameter is the path for the current catalog.  Create
    { a PF format path array that is 1 larger than the size of the element
    { path.  This array will be used to construct the PF paths for the files
    { and subcatalogs that reside in the current catalog.

    PUSH current_element_path_p: [1 .. UPPERBOUND (element_path) + 1];
    FOR i := 1 TO UPPERBOUND (element_path) DO
      current_element_path_p^ [i] := element_path [i];
    FOREND;

    { Process the files and subcatalogs at the current catalog level.

    WHILE element_p <> NIL DO

      current_element_path_p^ [UPPERBOUND (current_element_path_p^)] := element_p^.name;

      IF element_p^.active_element THEN

        IF element_p^.element_type = rac$file THEN

          activate_file (element_p, current_element_path_p^, scratch_seq_p, status);

        ELSEIF (element_p^.element_type = rac$catalog) AND (element_p^.element_count <> 0) THEN

          first_element_down_p := #PTR (element_p^.first_element_down_p, subproduct_info_seq_p^);

          activate_subproduct (current_element_path_p^, first_element_down_p, subproduct_info_seq_p,
                scratch_seq_p, status);

        IFEND;
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;

      element_p := #PTR (element_p^.next_element_across_p, subproduct_info_seq_p^);
    WHILEND;

  PROCEND activate_subproduct;
MODEND ram$activate_products;
