singrdk/base/Libraries/Resiliency/JournaletGroup.sg

239 lines
6.8 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Libraries\Resiliency\JournaletGroup.sg
//
// Note:
//
using System;
using System.Collections;
using System.Threading;
using Microsoft.Singularity;
namespace Microsoft.Singularity.Resiliency
{
public class JournaletGroup : IEnumerable, IRecoveryAware, ICheckpoint
{
protected IRecoveryAware parent;
protected bool syncRequest;
protected bool recoveringState;
protected bool checkpointingState = false;
protected Object! recoveryLock;
protected IList! journaletList;
protected Object! listLock;
protected ManualResetEvent! syncEvent;
public JournaletGroup()
{
recoveryLock = new Object();
listLock = new Object();
journaletList = new ArrayList();
syncEvent = new ManualResetEvent(false);
}
///
/// Adds the specified journalet to the group
///
public void Add(Journalet2 journalet)
{
if (journalet != null) {
lock (listLock) {
journaletList.Add(journalet);
journalet.Group = this;
}
}
}
///
/// Removes the specified journalet from the group
///
public void Remove(Journalet2 journalet)
{
if (journalet != null) {
lock (listLock) {
journaletList.Remove(journalet);
journalet.Group = null;
}
}
}
//
// Invoked either when the proxy starts up or when the recovery ends.
//
public void Start()
{
Journalet2 j;
DebugStub.Print("JournaletGroup: Enter Start\n");
DebugStub.Print("JournaletGroup: {0} journalets\n",
__arglist(journaletList.Count));
syncRequest = false;
recoveringState = false;
lock (listLock) {
foreach (Object obj in journaletList) {
if (obj == null) {
break;
}
j = obj as Journalet2;
if (j == null) {
continue;
}
j.Start();
DebugStub.Print("JournaletGroup: J started\n");
}
}
}
public void Stop()
{
Journalet2 j;
recoveringState = true; // to prevent subsequent recovery
lock (listLock) {
foreach (Object obj in journaletList) {
if (obj == null) {
break;
}
j = obj as Journalet2;
if (j == null) {
continue;
}
j.Stop();
}
}
}
public void Suspend()
{
Journalet2 journalet;
syncRequest = true;
lock (listLock) {
foreach (Object obj in journaletList) {
if (obj == null) {
break;
}
journalet = obj as Journalet2;
if (journalet != null) {
journalet.Suspend();
}
}
}
}
public void Flush()
{
Journalet2 journalet;
lock (listLock) {
foreach (Object obj in journaletList) {
if (obj == null) {
break;
}
journalet = obj as Journalet2;
if (journalet != null) {
journalet.Flush();
}
}
}
}
public void Resume()
{
syncRequest = false;
syncEvent.Set();
}
public bool SyncRequest
{
get { return syncRequest; }
private set {}
}
public ManualResetEvent! SyncEvent
{
get { return syncEvent; }
private set {}
}
internal IRecoveryAware Parent
{
get { return parent; }
set { parent = value; }
}
public void NotifyRecovery()
{
DebugStub.Print("JGroup: Enter NotifyRecovery\n");
// this doesn't immediately returns if the lock
// is already acquired.
//if (!Monitor.TryEnter(recoveryLock)) {
// DebugStub.Print("JGroup: Exit NotifyRecovery\n");
// return;
//}
lock (recoveryLock) {
if (recoveringState) {
DebugStub.Print("JGroup: Exit NotifyRecovery\n");
return;
}
else {
recoveringState = true;
}
}
if (parent != null || !recoveringState) {
parent.NotifyRecovery();
//recoveringState = true;
}
//Monitor.Exit(recoveryLock);
DebugStub.Print("JGroup: Exit NotifyRecovery\n");
}
public void UpdateCheckpoint()
{
//DebugStub.Print("JGroup: Enter UpdateCheckpoint\n");
//Doesn't seem work
//if (!Monitor.TryEnter(recoveryLock)) {
// DebugStub.Print("JGroup: Exit UpdateCheckpoint\n");
// return;
//}
lock (recoveryLock) {
if (checkpointingState) {
//DebugStub.Print("JGroup: Exit UpdateCheckpoint\n");
return;
}
else {
checkpointingState = true;
}
}
// Suspend all other journalets
Suspend();
// Notify to ServiceProviderProxy
if (parent != null) {
parent.UpdateCheckpoint();
}
checkpointingState = false;
// Resume the journalets
Resume();
//Monitor.Exit(recoveryLock);
//DebugStub.Print("JGroup: Exit UpdateCheckpoint\n");
}
public IEnumerator GetEnumerator()
{
return journaletList.GetEnumerator();
}
}
}