/////////////////////////////////////////////////////////////////////////////// // // 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; } } } }