?? RIGHT := 110 ??
?? TITLE := 'NOS/VE : File Server - dfm$fetch_page_status' ??
MODULE dfm$fetch_page_status;

{ PURPOSE:
{   This module contain the following procedures:
{
{      dfp$fetch_page_status - used by memory manager to determine whether a
{           page is on server or is a new page to be created.
{
{

?? NEWTITLE := '  XREF Variables', EJECT ??
*copyc dfv$served_family_table_root
?? OLDTITLE, NEWTITLE := '  XREF Procedures', EJECT ??
*copyc dfp$get_served_file_desc_p
?? OLDTITLE, NEWTITLE := '  Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dft$served_family_table
*copyc gft$locked_file_desc_entry_p
*copyc gft$page_status
*copyc osd$virtual_address
?? POP ??
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] dfp$fetch_page_status', EJECT ??
{
{   This subroutine provides MM with the information needed to administer
{   page faults on the server.  It determines whether the requested page
{   is within or beyond the current server file or if space needs to be allocated
{   for the server file.

  PROCEDURE [XDCL] dfp$fetch_page_status
    (    fde_p: gft$locked_file_desc_entry_p;
         offset: ost$segment_offset;
     VAR page_status: gft$page_status);

    VAR
      p_served_family_entry: ^dft$served_family_table_entry,
      server_descriptor_p: dft$server_descriptor_p,
      served_family_table_index: dft$served_family_table_index;


{ Locate the server descriptor.

    dfp$get_served_file_desc_p (fde_p, server_descriptor_p);
    served_family_table_index := server_descriptor_p^.header.served_family_table_index;

    p_served_family_entry := ^dfv$served_family_table_root.
          p_family_list_pointer_array^ [served_family_table_index.pointers_index].
          p_served_family_list^ [served_family_table_index.family_list_index];


{ Check if the file was missed in the recovery process - lifetime <> current lifetime
{ No matter what the state of the server is, if the file is marked
{ as terminated, do not allow access to the file.

    IF ((server_descriptor_p^.header.file_state = dfc$terminated) OR
          (p_served_family_entry^.server_state = dfc$deleted) OR
          (p_served_family_entry^.server_state = dfc$terminated)) THEN
      page_status := gfc$ps_server_terminated;


{ Even if the server is now active, but recovery has not been performed
{ on this particular file force the page fault back to job mode, to force recovery of this file.

    ELSEIF (server_descriptor_p^.header.file_state = dfc$awaiting_recovery) OR
          (p_served_family_entry^.server_state <> dfc$active) THEN
      page_status := gfc$ps_volume_unavailable;


{ A file was missed in the recovery process if lifetime <> current lifetime

    ELSEIF p_served_family_entry^.server_lifetime <> server_descriptor_p^.header.server_lifetime THEN
      page_status := gfc$ps_server_terminated;


{ The state of the file must be active or deactive and writing.

{ If the segment_offset passed in is greater than, or equal to, the total allocated length
{ in the server_descriptor, an allocation request must be made to the server before any further
{ processing can be done.

    ELSEIF offset >= server_descriptor_p^.header.total_allocated_length THEN
      page_status := gfc$ps_server_allocate_required;


{ The page must be on the server if it is within range of EOI, otherwise it
{ doesnt exist.

    ELSEIF offset < fde_p^.eoi_byte_address THEN
      page_status := gfc$ps_page_on_server;
    ELSE
      page_status := gfc$ps_page_doesnt_exist;
    IFEND;

  PROCEND dfp$fetch_page_status;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] dfp$fetch_multi_page_status', EJECT ??

{
{ PURPOSE:
{    This procedure verifies that a range of pages resides on accessible server volumes.
{

  PROCEDURE [XDCL] dfp$fetch_multi_page_status
    (    fde_p: gft$locked_file_desc_entry_p;
         offset: ost$segment_offset; {will be on page boundary}
         length: ost$segment_length; {will be multiple of page size
     VAR page_status: gft$page_status);

    VAR
      allocation_unit_size: integer,
      last_offset: integer;

    allocation_unit_size := fde_p^.allocation_unit_size;
    last_offset := ((offset + length - 1) DIV allocation_unit_size) * allocation_unit_size;

    dfp$fetch_page_status (fde_p, last_offset, page_status);

  PROCEND dfp$fetch_multi_page_status;
?? OLDTITLE, OLDTITLE ??
MODEND dfm$fetch_page_status;
