149 lines
4.2 KiB
Plaintext
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; }
|
||
|
}
|
||
|
}
|
||
|
}
|