singrdk/base/Libraries/Resiliency/Journalet2.sg

149 lines
4.2 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Libraries\Resiliency\Journalet2.sg
//
// Note:
//
using System;
using System.Threading;
using Microsoft.Singularity;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
namespace Microsoft.Singularity.Resiliency
{
public enum ProxyState : uint {
Waiting,
Running,
Synchronize,
}
public abstract class Journalet2 : ICheckpoint
{
protected bool running;
protected Thread thread;
protected JournaletGroup group;
protected ManualResetEvent recoveryEvent;
protected ManualResetEvent suspendEvent;
protected ProxyState proxyState;
public Journalet2()
{
this.recoveryEvent = new ManualResetEvent(false);
this.suspendEvent = new ManualResetEvent(false);
this.proxyState = ProxyState.Waiting;
}
//NOTE: Be sure the thread is stopped when calling this.
public abstract void CreateEndpoint(out ServiceContract.Exp! newExp);
protected abstract bool Initialize();
protected abstract bool HandleMessages();
protected abstract bool Recover();
public virtual void Start()
{
if (thread == null) {
thread = new Thread(new ThreadStart(Run));
thread.Start();
}
else {
recoveryEvent.Set();
}
}
public virtual void Stop() {}
public virtual void Run() {
if (group == null) {
DebugStub.Print("J: group is not set!\n");
return;
}
if (!Initialize()) {
return;
}
for (;;) {
if (!HandleMessages()) {
break;
}
// Now you can create another endpoint.
running = false;
group.NotifyRecovery();
recoveryEvent.WaitOne();
DebugStub.Print("J: Start recovery\n");
try {
if (!Recover()) {
break;
}
}
catch (ChannelClosedException) {
DebugStub.Print("Channel closed during recovery.\n");
break;
}
recoveryEvent.Reset();
Thread.Sleep(0);
}
}
///
/// Suspends this journalet at the nearest synchronization point.
/// This method blocks the caller until the journalet suspends.
///
public void Suspend()
{
if (running && group != null && group.SyncRequest) {
suspendEvent.WaitOne();
}
}
public abstract void Flush();
public void Resume() {}
// Checks if receiving a synchronization request.
protected void Sync()
{
proxyState = ProxyState.Synchronize;
if (group != null && group.SyncRequest) {
running = false;
suspendEvent.Set();
DebugStub.Print("J: Syncronize\n");
group.SyncEvent.WaitOne();
running = true;
}
}
protected void Checkpoint()
{
//DebugStub.Print("J: Enter Checkpoint\n");
group.UpdateCheckpoint();
//DebugStub.Print("J: Exit Checkpoint\n");
}
public ProxyState State
{
get { return proxyState; }
private set
{
lock (this) {
proxyState = value;
}
}
}
// Invoked by JournaletGroup.
internal JournaletGroup Group
{
get { return group; }
set { group = value; }
}
}
}