239 lines
6.8 KiB
Plaintext
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();
|
||
|
}
|
||
|
}
|
||
|
}
|