-- File: CourierOps.mesa - last edit:
-- AOF                 27-Oct-87 20:19:05
-- Copyright (C) 1984, 1985, 1986, 1987 by Xerox Corporation. All rights reserved. 

DIRECTORY
  Courier USING [
    Description, Dispatcher, NotesObject, SystemElement, VersionRange],
  CourierInternal USING [ConnectionHandle, ConnectionType, ServerConnection,
    UserConnection],
  Environment USING [wordsPerPage],
  Space USING [LongPointerFromPage, PageFromLongPointer],
  Stream USING [Block, CompletionCode, SubSequenceType];
  
CourierOps: DEFINITIONS
  IMPORTS Space =
  BEGIN
  
  Block: TYPE = RECORD[pointer: LONG POINTER, start, stop: CARDINAL];
  NotesObject: TYPE = RECORD[
    object: Courier.NotesObject,
    ch: CourierInternal.ConnectionHandle];
  
  --Procedures used to handle stream processing
  FlushToEndOfMessage: PROC[cH: CourierInternal.ConnectionHandle]
    RETURNS[error: BOOLEAN];
  PutBlock: PROC[ch: CourierInternal.ConnectionHandle, block: Block];
  GetBlock: PROC[ch: CourierInternal.ConnectionHandle, block: Block];
  Store: PROC[ch: CourierInternal.ConnectionHandle, site: LONG POINTER,
    description: Courier.Description];
  Fetch: PROC[ch: CourierInternal.ConnectionHandle, site: LONG POINTER,
    description: Courier.Description];

  RedirectStream: PROCEDURE[
    ch: CourierInternal.ConnectionHandle, block: Stream.Block,
    bytesTransferred: CARDINAL, why: Stream.CompletionCode,
    sst: Stream.SubSequenceType];    
    
  --Procedures used to maintain the connection lists

  CreateInternal: PROC[
    type: CourierInternal.ConnectionType, remote: Courier.SystemElement] 
    RETURNS[ch: CourierInternal.ConnectionHandle];
  --deletes connection object.
  DeleteConnection: PROC[ch: CourierInternal.ConnectionHandle];
  --actually deletes stream.
  DeleteStream: PROC[ch: CourierInternal.ConnectionHandle];
  --include object on idle list.
  SetIdleWatcher: PROC[ch: CourierInternal.UserConnection];
  --check and set up the stream fields.
  SetStreamState: PROC[ch: CourierInternal.UserConnection];  
  SearchForExport: PROC[ch: CourierInternal.ServerConnection]
    RETURNS[dispatcher: Courier.Dispatcher, range: Courier.VersionRange];

  --starting and stopping Courier
  Start: PROC[] RETURNS[started: BOOLEAN];
  Stop: PROC[] RETURNS[stopped: BOOLEAN];
  
  --stacks (hay)
  StackHandle: TYPE = LONG POINTER TO StackObject;
  FreeHandle: TYPE = LONG POINTER TO free StackObject;
  FetchHandle: TYPE = LONG POINTER TO fetch StackObject;
  StoreHandle: TYPE = LONG POINTER TO store StackObject;
  <<
  Each stack element represents a contiguous section of virtual memory,
  assuming that addresses are really ordered.  The segment of memory defined
  includes the left word, but excludes the right word ([left..right)).
  >>
  StackObject: TYPE = MACHINE DEPENDENT RECORD[
    object(0): SELECT OVERLAID * FROM
      fetch, store => [left(0), right(2): LONG POINTER],
      free => [p(0): LONG POINTER TO LONG POINTER, class(2): FreeClass],
      ENDCASE];
  FreeClass: TYPE = {array, disjoint};

  --Stack block definition
  stackCacheLength: CARDINAL = 5;  --number of stack pages kept around
  stackPageLength: CARDINAL = 1;  --length of stack in pages
  stackBlockLength: CARDINAL = stackPageLength * Environment.wordsPerPage;
  stackObjectLimit: CARDINAL =
    (stackBlockLength - SIZE[StackBlockHandle]) / SIZE[StackObject];

  StackBlockHandle: TYPE = LONG POINTER TO StackBlock;
  StackBlock: TYPE = RECORD[
    element: ARRAY[0..stackObjectLimit) OF StackObject,
    nextBlock: StackBlockHandle];

  base: POINTER TO StackBlock = NIL;
  floor: INTEGER = LOOPHOLE[@base.element, INTEGER];
  ceiling: INTEGER = LOOPHOLE[@base.nextBlock, INTEGER];
  
  <<
  Get a pointer to a new stack block and link it to current stack.
  Stack block may come from cache or have to be created from Space.
  >>
  StackBlockPush: PROC[stack: StackBlockHandle] RETURNS[StackBlockHandle];

  <<
  Delink this stack block to next logical block.
  Old stack may go to cache or back to Space.
  >>
  StackBlockPop: PROC[stack: StackBlockHandle] RETURNS[StackBlockHandle];

  StackBase: PROC[stack: StackHandle]
    RETURNS[block: StackBlockHandle] = INLINE
    BEGIN
    block ← Space.LongPointerFromPage[Space.PageFromLongPointer[stack]];
    IF CourierOps.stackPageLength # 1 THEN  --in case we go for bigger stacks
      block ← block - CourierOps.stackBlockLength + Environment.wordsPerPage;
    END;  --StackBase

  END.
  
LOG

19-Dec-84 15:37:57  SMA  Created file.
27-May-85 10:39:09  AOF  Changed definition of stack blocks.
17-Jun-85 18:27:29  AOF  Extenstion of NotesObject.
14-Jan-86 11:44:41  AOF  Add RedirectStream to interface.
19-Jun-87 12:55:42  AOF  Added Start and Stop procedures.