-- File: CedarSnapshotRollback.mesa
-- last edited by Levin:  November 12, 1982 9:48 am

DIRECTORY
  CedarSnapshot USING [],
  CedarSnapshotPrivate USING [FilePoint, GetSnapshotPoint, nullFilePoint],
  File USING [Delete, delete, ID, read, Unknown],
  Snapshot USING [InLoad],
  Volume USING [Close, GetStatus, ID, NeedsScavenging, nullID, systemID],
  VolumeExtras USING [OpenVolume];

CedarSnapshotRollback: MONITOR LOCKS snapshotLock
  IMPORTS CedarSnapshotPrivate, File, Snapshot, Volume, VolumeExtras
  EXPORTS CedarSnapshot, CedarSnapshotPrivate
  SHARES File =

BEGIN OPEN CedarSnapshotPrivate;

snapshotLock: PUBLIC MONITORLOCK;

-- Rollback --

RollBack: PUBLIC ENTRY PROCEDURE [volume: Volume.ID ← Volume.nullID] =
  BEGIN
  filePoint: FilePoint;
  valid: BOOL;
  IF volume = Volume.nullID THEN volume ← Volume.systemID;
  [filePoint, valid] ← GetSnapshotPoint[volume, keep];
  IF ~valid THEN RETURN;
  BEGIN
  ENABLE ANY => CONTINUE;  -- shouldn't really happen --
  volumeOpened: BOOLEAN ← FALSE;
  IF Volume.GetStatus[volume] ~= open THEN
    BEGIN
    VolumeExtras.OpenVolume[volume: volume, readOnly: TRUE];
    volumeOpened ← TRUE;
    END;
  Snapshot.InLoad[
    pMicrocode: NIL, pGerm: NIL, countGerm: 0,
    file: [fID: filePoint.fID, permissions: File.read], firstPage: filePoint.firstPage];
  -- Note: execution normally continues inside Checkpoint.  If the
  -- above InLoad failed, we try to delete the offending checkpoint
  -- file.  However, if the volume is so badly messed up that it
  -- requires scavenging, we leave it alone (note ENABLE ANY, above).
  IF volumeOpened THEN
    BEGIN
    Volume.Close[volume: volume];
    -- Using VolumeExtras.OpenVolume instead of Volume.Open keeps
    -- the temporary files from being deleted.
    VolumeExtras.OpenVolume[volume: volume, readOnly: FALSE];
    END;
  File.Delete[[filePoint.fID, File.delete] ! File.Unknown => CONTINUE];
  [] ← GetSnapshotPoint[volume, clear];
  IF volumeOpened THEN Volume.Close[volume: volume];
  END;
  END;

-- Delete --

Delete: PUBLIC ENTRY PROCEDURE [volume: Volume.ID ← Volume.nullID] =
  BEGIN
  filePoint: FilePoint;
  volumeOpened: BOOLEAN ← FALSE;
  IF volume = Volume.nullID THEN volume ← Volume.systemID;
  IF Volume.GetStatus[volume] ~= open THEN
    BEGIN
    -- Using VolumeExtras.OpenVolume instead of Volume.Open keeps
    -- the temporary files from being deleted.
    VolumeExtras.OpenVolume[volume: volume, readOnly: FALSE
      ! Volume.NeedsScavenging => GO TO cantDelete];
    volumeOpened ← TRUE;
    END;
  IF (filePoint ← GetSnapshotPoint[volume, keep].filePoint) ~= nullFilePoint THEN
    File.Delete[[fID: filePoint.fID, permissions: File.delete] ! File.Unknown => CONTINUE];
  [] ← GetSnapshotPoint[volume, clear];
  IF volumeOpened THEN Volume.Close[volume: volume];
  EXITS
    cantDelete => NULL;
  END;

-- Validate --

ValidateSnapshot: PUBLIC ENTRY PROC [volume: Volume.ID] RETURNS [BOOL] =
  {RETURN[GetSnapshotPoint[volume, keep].valid]};


END.