-- Stub file AlpineFileRpcBinderImpl.mesa was translated on  7-Jun-83
    -- 11:45:36 PDT by Lupine of 18-Feb-83 11:25:52 PST.
    -- edited by kolling on June 7, 1983 11:48 am.

-- Source interface AlpineFile came from file AlpineFile.bcd, which
    -- was created on  7-Jun-83 11:44:55 PDT with version stamp 155#135#3502400555
    -- from source of 25-May-83 16:51:23 PDT.

-- The RPC stub modules for AlpineFile are:
    -- AlpineFileRpcControl.mesa;
    -- AlpineFileRpcClientImpl.mesa;
    -- AlpineFileRpcBinderImpl.mesa;
    -- AlpineFileRpcServerImpl.mesa.

-- The parameters for this translation are:
    -- Target language = Cedar;
    -- Default parameter passing = VALUE;
    -- Deallocate server heap arguments = TRUE;
    -- Inline RpcServerImpl dispatcher stubs = FALSE;
    -- Maximum number of dynamic heap NEWs = 50, MDS NEWs = 50;
    -- Acceptable parameter protocols = VersionRange[1,1].

-- NOTE: Discard this module unless you use dynamic client binding.


DIRECTORY
  AlpineFile,
  AlpineFileRpcControl USING [InterfaceRecord, InterfaceRecordObject],
  AlpineFileRpcClientImpl,
  RPC USING [InterfaceName, Zones],
  RTTypesBasic USING [EstablishFinalization, FinalizationQueue, FQEmpty,
      FQNext, NewFQ];


AlpineFileRpcBinderImpl: MONITOR
  IMPORTS AlpineFile, ClientPrototype: AlpineFileRpcClientImpl, RTT: RTTypesBasic
  EXPORTS AlpineFileRpcControl
  SHARES  AlpineFileRpcControl
  = BEGIN OPEN RpcControl: AlpineFileRpcControl, RpcPublic: RPC;


-- Dynamic instantiation and binding routines.

  ImportNewInterface: PUBLIC SAFE PROCEDURE [
        interfaceName: RpcPublic.InterfaceName,
        parameterStorage: RpcPublic.Zones ]
      RETURNS [interfaceRecord: RpcControl.InterfaceRecord] =
    TRUSTED BEGIN
    interfaceRecord ← NewInterface[];
    LupineDetails[interfaceRecord].module.ImportInterface [
        interfaceName: interfaceName,
        parameterStorage: parameterStorage
      ! UNWIND => FreeInterface[interfaceRecord] ];
    END;

  UnimportNewInterface: SAFE PROCEDURE [
      interfaceRecord: RpcControl.InterfaceRecord ] =
    TRUSTED BEGIN
    LupineDetails[interfaceRecord].module.UnimportInterface[];
    FreeInterface[interfaceRecord];
    END;


-- Utility routines for interface instantiation and caching.

  ConcreteLupineDetails: TYPE = REF LupineDetailsObject;

  LupineDetailsObject:  PUBLIC TYPE = RECORD [
	module: ClientModule←NIL,
	list: RpcControl.InterfaceRecord←NIL, --package reference
	next: RpcControl.InterfaceRecord←NIL --free list -- ];

  LupineDetails: PROCEDURE [abstractInterface: RpcControl.InterfaceRecord]
      RETURNS [ConcreteLupineDetails] =
    INLINE {RETURN[abstractInterface.lupineDetails]};

  ClientModule: TYPE = POINTER TO FRAME[AlpineFileRpcClientImpl];


  clientInterfaceCache: RpcControl.InterfaceRecord ← NIL; -- free interface
      -- records
  clientInterfaceList: RpcControl.InterfaceRecord ← NIL; -- all interface
      -- records

  NewInterfaceRecord: PUBLIC SAFE PROCEDURE
    RETURNS [interfaceRecord: RpcControl.InterfaceRecord] =
    TRUSTED BEGIN
    interfaceRecord ← NEW[RpcControl.InterfaceRecordObject];
    END;

  NewInterface: PROCEDURE RETURNS [interface: RpcControl.InterfaceRecord]=
    BEGIN
    GetCachedInterface: ENTRY PROCEDURE
        RETURNS [cachedIR: RpcControl.InterfaceRecord] =
      INLINE BEGIN ENABLE UNWIND => NULL;
      IF (cachedIR←clientInterfaceCache) # NIL
        THEN clientInterfaceCache ← LupineDetails[clientInterfaceCache].next;
      END;
    ReclaimInterfaces[];
    IF (interface ← GetCachedInterface[]) = NIL
      THEN BEGIN
        ChainNewInterface: ENTRY PROCEDURE =
          INLINE BEGIN ENABLE UNWIND => NULL;
          interface.lupineDetails ← NEW[
            LupineDetailsObject ← [module: module, list: clientInterfaceList]];
          clientInterfaceList ← interface;
          END; -- ChainNewInterface.
        module: ClientModule = NEW ClientPrototype;
        interface ← NewInterfaceRecord[];
        interface↑ ← [
	    Open: module.Open, Create: module.Create, Close: module.Close,
	    Delete: module.Delete, GetUniversalFile: module.GetUniversalFile,
	    GetTransID: module.GetTransID, GetAccessRights: module.GetAccessRights,
	    GetLockOption: module.GetLockOption, SetLockOption: module.SetLockOption,
	    GetRecoveryOption: module.GetRecoveryOption, GetReferencePattern:
	    module.GetReferencePattern, SetReferencePattern: module.SetReferencePattern,
	    ReadPages: module.ReadPages, WritePages: module.WritePages,
	    LockPages: module.LockPages, UnlockPages: module.UnlockPages,
	    ReadProperties: module.ReadProperties, WriteProperties: module.WriteProperties,
	    UnlockVersion: module.UnlockVersion, IncrementVersion: module.IncrementVersion,
	    GetSize: module.GetSize, SetSize: module.SetSize, AccessFailed:
	    AlpineFile.AccessFailed, LockFailed: AlpineFile.LockFailed, OperationFailed:
	    AlpineFile.OperationFailed, StaticallyInvalid: AlpineFile.StaticallyInvalid,
	    Unknown: AlpineFile.Unknown, PossiblyDamaged: AlpineFile.PossiblyDamaged];
        ChainNewInterface[];
        END;
    END;

  FreeInterface: ENTRY PROCEDURE [interface: RpcControl.InterfaceRecord]=
    INLINE BEGIN ENABLE UNWIND => NULL;
    LupineDetails[interface].next ← clientInterfaceCache;
    clientInterfaceCache ← interface;
    END;


-- Finalization for dynamic interfaces.  Just cache and reuse for now.

  freedInterfaces: RTT.FinalizationQueue = RTT.NewFQ[20];

  ReclaimInterfaces: PROCEDURE =
    INLINE BEGIN
    WHILE ~RTT.FQEmpty[freedInterfaces] DO
      interface: RpcControl.InterfaceRecord =
        NARROW[RTT.FQNext[freedInterfaces]];
      IF interface.lupineDetails # NIL THEN
        UnimportNewInterface[interface];
      ENDLOOP;
    END;


-- Module initialization.

  RTT.EstablishFinalization[
    type: CODE[RpcControl.InterfaceRecordObject],
    npr: 1,  fq: freedInterfaces ];


  END.  -- AlpineFileRpcBinderImpl.