?? RIGHT := 110 ??
MODULE dfm$test_job_recovery;

{
{   This module provides a simple job recovery test mechanism.
{

?? PUSH (LISTEXT := ON) ??
*copyc amp$get_segment_pointer
*copyc clp$evaluate_parameters
*copyc clt$parameter_list
*copyc dfi$display
*copyc dfe$error_condition_codes
*copyc fsp$open_file
*copyc i#program_error
*copyc pmp$wait
*copyc amp$open
*copyc osp$set_status_abnormal
?? POP ??

  CONST
    page_size_in_words = 4096 DIV 8;

?? TITLE := ' [XDCL, #GATE] dfp$test_job_recovery', EJECT ??

{  This is just a simple test of reading and writing a file.
{  The file may be specified as the output parameter.
{  The file is attached for exclusive access.

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



{  PROCEDURE test_job_recovery, tesjr  (
{    output, o: file = $user.dff$test_job_recovery.$next
{    status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 3] of clt$pdt_parameter_name,
      parameters: array [1 .. 2] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        default_value: string (33),
      recend,
      type2: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [88, 11, 26, 14, 59, 55, 313],
    clc$command, 3, 2, 0, 0, 0, 0, 2, ''], [
    ['O                              ',clc$abbreviation_entry, 1],
    ['OUTPUT                         ',clc$nominal_entry, 1],
    ['STATUS                         ',clc$nominal_entry, 2]],
    [
{ PARAMETER 1
    [2, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_default_parameter, 0, 33],
{ PARAMETER 2
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$file_type],
    '$user.dff$test_job_recovery.$next'],
{ PARAMETER 2
    [[1, 0, clc$status_type]]];

?? FMT (FORMAT := ON) ??
?? POP ??

    CONST
      p$output = 1,
      p$status = 2;

    VAR
      pvt: array [1 .. 2] of clt$parameter_value;

    CONST
      max_page_count = 50;

    VAR
      address: ^cell,
      file_content_array: ^array [1 .. 100000000] of integer,
      file_id: amt$file_identifier,
      message: string (110),
      message_length: integer,
      page_count: integer,
      pass: integer,
      segment_pointer: amt$segment_pointer,
      word_count: integer,
      word_value: integer;

    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    fsp$open_file (pvt [p$output].value^.file_value^, amc$segment, NIL, NIL, NIL, NIL, NIL, file_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    amp$get_segment_pointer (file_id, amc$cell_pointer, segment_pointer, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    file_content_array := segment_pointer.cell_pointer;

    pass := 0;
    word_value := 1;

  /forever/
    WHILE TRUE DO
      word_value := word_value + 1;
      pass := pass + 1;

    /write_all_pages/
      FOR page_count := 1 TO max_page_count DO

      /write_all_words_in_page/
        FOR word_count := 1 TO page_size_in_words DO
          file_content_array^ [((page_count - 1) * page_size_in_words) + word_count] := word_value;
        FOREND /write_all_words_in_page/;
      FOREND /write_all_pages/;

    /verify_all_pages/
      FOR page_count := 1 TO max_page_count DO

      /verify_all_words_in_page/
        FOR word_count := 1 TO page_size_in_words DO
          IF file_content_array^ [((page_count - 1) * page_size_in_words) + word_count] <> word_value THEN
            address := ^file_content_array^ [((page_count - 1) * page_size_in_words) + word_count];
            STRINGREP (message, message_length, ' Perm file test failure  - Page ', page_count, ' Word ',
                  word_count, 'address ', address,  ' Expected ', word_value, ' Actual ',
                  file_content_array^ [((page_count - 1) * page_size_in_words) + word_count], ' Pass ', pass);
            display (message (1, message_length));
            i#program_error;
            osp$set_status_abnormal (dfc$file_server_id, dfe$test_checksum_error, message (1, message_length),
                  status);
            RETURN;
          IFEND;
        FOREND /verify_all_words_in_page/;
      FOREND /verify_all_pages/;

    WHILEND /forever/;
  PROCEND dfp$test_job_recovery;
?? TITLE := ' [XDCL, #GATE] dfp$test_file_sharing', EJECT ??

{  This procedure provides a more complicated test of writing a permanent
{    file. A file is written and the read to verify its contents.
{  local_file_name:  This parameter specifies the file that is to be written.
{     This parameter may be used in conjunction with a previuous attach_file
{     or create_file paramter.  Note - amp$open is used so that the
{     job uses the access and share modes specified on an attach_file done
{     outside of this test.
{  offset_word_range:  This parameter determines what words of the file
{     the task is to write into. For example if offset_word_range=1 then
{     the task writes into the 1,9,17,... words.
{     If offset_word_range=1..4 then the tasks writes into the
{     1..4,9..12,17..20 words of the file.
{     This parameter is provided as a means of allowing multiple jobs to
{     write on the same file.
{ total_minutes:  This parameter determines how long the test will run for.
{ wait_millisecond:  This parameter determines how long the test will wait
{     between passes through the file.
{ page_count: This parameter indicates how big the file should be.

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

{ PROCEDURE test_file_sharing, tesfs  (
{   local_file_name, lfn: name = $required
{   offset_word_range, owr: range of  integer 1 .. 8  = 1.. 8
{   total_minutes, tm: integer 1 .. 1000 = 120
{   wait_milliseconds, wm: integer = 0
{   page_count, pc: integer 1 .. 1000000 = 50
{   status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 11] of clt$pdt_parameter_name,
      parameters: array [1 .. 6] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        qualifier: clt$name_type_qualifier,
      recend,
      type2: record
        header: clt$type_specification_header,
        qualifier: clt$range_type_qualifier,
        element_type_spec: record
          header: clt$type_specification_header,
          qualifier: clt$integer_type_qualifier,
        recend,
        default_value: string (5),
      recend,
      type3: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (3),
      recend,
      type4: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (1),
      recend,
      type5: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (2),
      recend,
      type6: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [89, 1, 24, 13, 43, 23, 225],
    clc$command, 11, 6, 1, 0, 0, 0, 6, ''], [
    ['LFN                            ',clc$abbreviation_entry, 1],
    ['LOCAL_FILE_NAME                ',clc$nominal_entry, 1],
    ['OFFSET_WORD_RANGE              ',clc$nominal_entry, 2],
    ['OWR                            ',clc$abbreviation_entry, 2],
    ['PAGE_COUNT                     ',clc$nominal_entry, 5],
    ['PC                             ',clc$abbreviation_entry, 5],
    ['STATUS                         ',clc$nominal_entry, 6],
    ['TM                             ',clc$abbreviation_entry, 3],
    ['TOTAL_MINUTES                  ',clc$nominal_entry, 3],
    ['WAIT_MILLISECONDS              ',clc$nominal_entry, 4],
    ['WM                             ',clc$abbreviation_entry, 4]],
    [
{ PARAMETER 1
    [2, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally]
,
    clc$pass_by_value, clc$immediate_evaluation,
clc$standard_parameter_checking, 5, clc$required_parameter, 0
  , 0],
{ PARAMETER 2
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally]
,
    clc$pass_by_value, clc$immediate_evaluation,
clc$standard_parameter_checking, 27,
  clc$optional_default_parameter, 0, 5],
{ PARAMETER 3
    [9, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally]
,
    clc$pass_by_value, clc$immediate_evaluation,
clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 3],
{ PARAMETER 4
    [10, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally]
,
    clc$pass_by_value, clc$immediate_evaluation,
clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 1],
{ PARAMETER 5
    [5, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally]
,
    clc$pass_by_value, clc$immediate_evaluation,
clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 2],
{ PARAMETER 6
    [7, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation,
clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$name_type], [1, osc$max_name_size]],
{ PARAMETER 2
    [[1, 0, clc$range_type], [20],
      [[1, 0, clc$integer_type], [1, 8, 10]]
    ,
    '1.. 8'],
{ PARAMETER 3
    [[1, 0, clc$integer_type], [1, 1000, 10],
    '120'],
{ PARAMETER 4
    [[1, 0, clc$integer_type], [clc$min_integer, clc$max_integer, 10],
    '0'],
{ PARAMETER 5
    [[1, 0, clc$integer_type], [1, 1000000, 10],
    '50'],
{ PARAMETER 6
    [[1, 0, clc$status_type]]];

?? FMT (FORMAT := ON) ??
?? POP ??

    CONST
      p$local_file_name = 1,
      p$offset_word_range = 2,
      p$total_minutes = 3,
      p$wait_milliseconds = 4,
      p$page_count = 5,
      p$status = 6;

    VAR
      pvt: array [1 .. 6] of clt$parameter_value;

    VAR
      address: ^cell,
      end_time: integer,
      file_content_array: ^array [1 .. 100000000] of integer,
      file_id: amt$file_identifier,
      high: integer,
      low: integer,
      max_page_count: integer,
      message: string (110),
      message_length: integer,
      page_count: integer,
      pass: integer,
      segment_pointer: amt$segment_pointer,
      time: integer,
      wait: integer,
      word_count: integer,
      word_value: integer;

    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    amp$open (pvt [p$local_file_name].value^.name_value, amc$segment, NIL, file_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    amp$get_segment_pointer (file_id, amc$cell_pointer, segment_pointer, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    file_content_array := segment_pointer.cell_pointer;

    low := pvt [p$offset_word_range].value^.low_value^.integer_value.value;
    high := pvt [p$offset_word_range].value^.high_value^.integer_value.value;
    wait := pvt [p$wait_milliseconds].value^.integer_value.value;
    max_page_count := pvt [p$page_count].value^.integer_value.value;
    end_time := #FREE_RUNNING_CLOCK (0) + ({Minutes} pvt [p$total_minutes].value^.integer_value.value *
          {secs_per_min} 60 * {Microsends per second } 1000000);

    pass := 0;
    word_value := 1;
    time := #FREE_RUNNING_CLOCK (0);

  /till_end_time/
    WHILE (time < end_time) DO
      word_value := word_value + 1;
      pass := pass + 1;

    /write_all_pages/
      FOR page_count := 1 TO max_page_count DO

      /write_all_words_in_page/
        FOR word_count := 1 TO page_size_in_words DO
          IF ((((word_count MOD 8) >= low) AND ((word_count MOD 8) <= high))) OR
                (((word_count MOD 8) = 0) AND (high = 8)) THEN
            file_content_array^ [((page_count - 1) * page_size_in_words) + word_count] := word_value;
          IFEND;
        FOREND /write_all_words_in_page/;
      FOREND /write_all_pages/;

    /verify_all_pages/
      FOR page_count := 1 TO max_page_count DO

      /verify_all_words_in_page/
        FOR word_count := 1 TO page_size_in_words DO
          IF ((((word_count MOD 8) >= low) AND ((word_count MOD 8) <= high))) OR
                (((word_count MOD 8) = 0) AND (high = 8)) THEN
            IF file_content_array^ [((page_count - 1) * page_size_in_words) + word_count] <> word_value THEN
              address := ^file_content_array^ [((page_count - 1) * page_size_in_words) + word_count];
              STRINGREP (message, message_length, ' Perm file test failure  - Page ', page_count, ' Word ',
                    word_count, 'Address ', address,' Expected ', word_value, ' Actual ',
                    file_content_array^ [((page_count - 1) * page_size_in_words) + word_count], ' Pass ',
                    pass);
              display (message (1, message_length));
              i#program_error;
              osp$set_status_abnormal (dfc$file_server_id, dfe$test_checksum_error,
                    message (1, message_length), status);
              RETURN;
            IFEND;
          IFEND;
        FOREND /verify_all_words_in_page/;
      FOREND /verify_all_pages/;

      pmp$wait (wait, wait);
      time := #FREE_RUNNING_CLOCK (0);
    WHILEND /till_end_time/;
  PROCEND dfp$test_file_sharing;
?? TITLE := ' [XDCL, #GATE] dfp$test_file_reading', EJECT ??

{  This procedure reads a file written by dfp$test_file_sharing
{  For now no verification of what is being read is made.
{  Note for future enhancement:
{     How would the writing and reading jobs communicate?
{  local_file_name:  This parameter specifies the file that is to be read.
{     This parameter may be used in conjunction with a previuous attach_file
{     or create_file paramter.  Note - amp$open is used so that the
{     job uses the access and share modes specified on the attach_file.
{  offset_word_range:  This parameter determines what words of the file
{     the task is to read from. For example if offset_word_range=1 then
{     the task reads from the 1,9,17,... words.
{     If offset_word_range=1..4 then the tasks reads from into the
{     1..4,9..12,17..20 words of the file.
{ total_minutes:  This parameter determines how long the test will run for.
{ wait_millisecond:  This parameter determines how long the test will wait
{     between passes through the file.
{ page_count: This parameter indicates how big the file should be.

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

{ PROCEDURE test_file_reading, tesfs  (
{   local_file_name, lfn: name = $required
{   offset_word_range, owr: range of  integer 1 .. 8  = 1.. 8
{   total_minutes, tm: integer 1 .. 1000 = 120
{   wait_milliseconds, wm: integer = 0
{   page_count, pc: integer 1 .. 1000000 = 50
{   status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 11] of clt$pdt_parameter_name,
      parameters: array [1 .. 6] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        qualifier: clt$name_type_qualifier,
      recend,
      type2: record
        header: clt$type_specification_header,
        qualifier: clt$range_type_qualifier,
        element_type_spec: record
          header: clt$type_specification_header,
          qualifier: clt$integer_type_qualifier,
        recend,
        default_value: string (5),
      recend,
      type3: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (3),
      recend,
      type4: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (1),
      recend,
      type5: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (2),
      recend,
      type6: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [89, 1, 24, 13, 43, 23, 225],
    clc$command, 11, 6, 1, 0, 0, 0, 6, ''], [
    ['LFN                            ',clc$abbreviation_entry, 1],
    ['LOCAL_FILE_NAME                ',clc$nominal_entry, 1],
    ['OFFSET_WORD_RANGE              ',clc$nominal_entry, 2],
    ['OWR                            ',clc$abbreviation_entry, 2],
    ['PAGE_COUNT                     ',clc$nominal_entry, 5],
    ['PC                             ',clc$abbreviation_entry, 5],
    ['STATUS                         ',clc$nominal_entry, 6],
    ['TM                             ',clc$abbreviation_entry, 3],
    ['TOTAL_MINUTES                  ',clc$nominal_entry, 3],
    ['WAIT_MILLISECONDS              ',clc$nominal_entry, 4],
    ['WM                             ',clc$abbreviation_entry, 4]],
    [
{ PARAMETER 1
    [2, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally]
,
    clc$pass_by_value, clc$immediate_evaluation,
clc$standard_parameter_checking, 5, clc$required_parameter, 0
  , 0],
{ PARAMETER 2
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally]
,
    clc$pass_by_value, clc$immediate_evaluation,
clc$standard_parameter_checking, 27,
  clc$optional_default_parameter, 0, 5],
{ PARAMETER 3
    [9, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally]
,
    clc$pass_by_value, clc$immediate_evaluation,
clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 3],
{ PARAMETER 4
    [10, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally]
,
    clc$pass_by_value, clc$immediate_evaluation,
clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 1],
{ PARAMETER 5
    [5, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally]
,
    clc$pass_by_value, clc$immediate_evaluation,
clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 2],
{ PARAMETER 6
    [7, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation,
clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$name_type], [1, osc$max_name_size]],
{ PARAMETER 2
    [[1, 0, clc$range_type], [20],
      [[1, 0, clc$integer_type], [1, 8, 10]]
    ,
    '1.. 8'],
{ PARAMETER 3
    [[1, 0, clc$integer_type], [1, 1000, 10],
    '120'],
{ PARAMETER 4
    [[1, 0, clc$integer_type], [clc$min_integer, clc$max_integer, 10],
    '0'],
{ PARAMETER 5
    [[1, 0, clc$integer_type], [1, 1000000, 10],
    '50'],
{ PARAMETER 6
    [[1, 0, clc$status_type]]];

?? FMT (FORMAT := ON) ??
?? POP ??

    CONST
      p$local_file_name = 1,
      p$offset_word_range = 2,
      p$total_minutes = 3,
      p$wait_milliseconds = 4,
      p$page_count = 5,
      p$status = 6;

    VAR
      pvt: array [1 .. 6] of clt$parameter_value;

    VAR
      end_time: integer,
      file_content_array: ^array [1 .. 100000000] of integer,
      file_id: amt$file_identifier,
      high: integer,
      low: integer,
      max_page_count: integer,
      page_count: integer,
      segment_pointer: amt$segment_pointer,
      time: integer,
      wait: integer,
      word_count: integer,
      word_value: integer;

    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    amp$open (pvt [p$local_file_name].value^.name_value, amc$segment, NIL, file_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    amp$get_segment_pointer (file_id, amc$cell_pointer, segment_pointer, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    file_content_array := segment_pointer.cell_pointer;

    low := pvt [p$offset_word_range].value^.low_value^.integer_value.value;
    high := pvt [p$offset_word_range].value^.high_value^.integer_value.value;
    wait := pvt [p$wait_milliseconds].value^.integer_value.value;
    max_page_count := pvt [p$page_count].value^.integer_value.value;
    end_time := #FREE_RUNNING_CLOCK (0) + ({Minutes} pvt [p$total_minutes].value^.integer_value.value *
          {secs_per_min} 60 * {Microsends per second } 1000000);

    time := #FREE_RUNNING_CLOCK (0);

  /till_end_time/
    WHILE (time < end_time) DO

    /read_all_pages/
      FOR page_count := 1 TO max_page_count DO

      /read_all_words_in_page/
        FOR word_count := 1 TO page_size_in_words DO
          IF ((((word_count MOD 8) >= low) AND ((word_count MOD 8) <= high))) OR
                (((word_count MOD 8) = 0) AND (high = 8)) THEN
            word_value := file_content_array^ [((page_count - 1) * page_size_in_words) + word_count];
          IFEND;
        FOREND /read_all_words_in_page/;
      FOREND /read_all_pages/;

      pmp$wait (wait, wait);
      time := #FREE_RUNNING_CLOCK (0);
    WHILEND /till_end_time/;
  PROCEND dfp$test_file_reading;
MODEND dfm$test_job_recovery;
