singrdk/base/Services/Tests/CounterProxy/CounterJournalet.sg

412 lines
14 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Services\Tests\CounterProxy\CounterJournalet.sg
//
// Note:
//
#define VERSION_2
using System;
using System.Threading;
using System.Collections;
using Microsoft.SingSharp;
using Microsoft.Singularity;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.Resiliency;
namespace Microsoft.Singularity.Services.CounterProxy
{
internal enum MessageType : uint
{
Unknown,
Success,
Increment,
BeginCount,
Next,
End,
AckIncrement,
NakIncrement,
Current,
Terminated,
}
#if VERSION_2
internal sealed class CounterJournalet : Journalet2
#else
internal sealed class CounterJournalet : Journalet
#endif
{
private Log! incoming;
private Log! outgoing;
private TRef<CounterContract.Imp:Ready> counterServerRef;
private TRef<CounterContract.Exp:Ready> counterClientRef;
private TRef<CounterContract.Imp:Start> initServerRef;
#if VERSION_2
private TRef<CounterContract.Exp:Start>! initClientRef;
#endif
#if VERSION_2
internal CounterJournalet([Claims]ServiceContract.Exp:Start! ep)
: base()
{
CounterContract.Exp:Start counterEp;
counterEp = ep as CounterContract.Exp:Start;
if (counterEp == null) {
throw new ArgumentException();
}
this.incoming = new Log();
this.outgoing = new Log();
this.initClientRef = new TRef<CounterContract.Exp:Start>(counterEp);
}
#else
internal CounterJournalet(JournalProducer! producer,
[Claims]ServiceContract.Exp:Start! ep)
{
base(producer, ep);
this.incoming = new Log();
this.outgoing = new Log();
this.state = ProxyState.Waiting;
}
#endif
#if VERSION_2
public override void CreateEndpoint(out ServiceContract.Exp! ep)
#else
public override void CreateServerEndpoint(out ServiceContract.Exp:Start! ep)
#endif
{
CounterContract.Imp! imp;
CounterContract.Exp! exp;
//DebugStub.Print("CJ: ENTER CreateServerEndpoint\n");
CounterContract.NewChannel(out imp, out exp);
initServerRef = new TRef<CounterContract.Imp:Start>(imp);
ep = exp;
//DebugStub.Print("CJ: EXIT CreateServerEndpoint\n");
}
#if VERSION_2
public override void Flush()
{
incoming.Flush();
outgoing.Flush();
}
#endif
protected override bool Initialize()
{
bool success = false;
CounterContract.Exp:Start clientEp;
CounterContract.Imp:Start! serverEp;
#if VERSION_2
clientEp = initClientRef.Acquire();
#else
ServiceContract.Exp:Start! ep;
ep = clientRef.Acquire();
clientEp = ep as CounterContract.Exp:Start;
if (clientEp == null) {
clientRef.Release(ep);
return false;
}
#endif
assume initServerRef != null;
serverEp = initServerRef.Acquire();
switch receive {
case serverEp.Success():
clientEp.SendSuccess();
success = true;
break;
case serverEp.ChannelClosed():
success = false;
break;
case unsatisfiable:
DebugStub.Break();
break;
}
if (success) {
counterClientRef = new TRef<CounterContract.Exp:Ready>(clientEp);
counterServerRef = new TRef<CounterContract.Imp:Ready>(serverEp);
return true;
}
else {
delete clientEp;
delete serverEp;
return false;
}
}
protected override bool HandleMessages()
{
bool recovery = false;
CounterContract.Exp:Ready! clientEp;
CounterContract.Imp:Ready! serverEp;
assume counterClientRef != null;
assume counterServerRef != null;
clientEp = counterClientRef.Acquire();
serverEp = counterServerRef.Acquire();
for (;;) {
switch receive {
case clientEp.Increment():
State = ProxyState.Running;
#if VERSION_2
Sync();
#endif
serverEp.SendIncrement();
incoming.Record((uint)MessageType.Increment, null);
break;
case clientEp.BeginCount():
State = ProxyState.Running;
DebugStub.Print("CJ: BeginCount\n");
#if VERSION_2
Sync();
#endif
serverEp.SendBeginCount();
incoming.Record((uint)MessageType.BeginCount, null);
break;
case clientEp.Next():
State = ProxyState.Running;
DebugStub.Print("CJ: Next\n");
#if VERSION_2
Sync();
#endif
serverEp.SendNext();
incoming.Record((uint)MessageType.Next, null);
break;
case clientEp.End():
State = ProxyState.Running;
serverEp.SendEnd();
#if VERSION_2
Sync();
#endif
incoming.Record((uint)MessageType.End, null);
break;
case clientEp.ChannelClosed():
State = ProxyState.Running;
// Lost client. Journalet also goes away.
DebugStub.Print("CJ: Client disconnected.\n");
recovery = false;
goto exit;
break;
case serverEp.AckIncrement(number):
#if VERSION_2
Sync();
#endif
State = ProxyState.Running;
clientEp.SendAckIncrement(number);
ArrayList al = new ArrayList(1);
al.Add(number);
outgoing.Record((uint)MessageType.AckIncrement, al);
break;
case serverEp.Current(number):
#if VERSION_2
Sync();
#endif
State = ProxyState.Running;
DebugStub.Print("CJ: Current\n");
clientEp.SendCurrent(number);
ArrayList al = new ArrayList(1);
al.Add(number);
outgoing.Record((uint)MessageType.Current, al);
break;
case serverEp.Terminated():
#if VERSION_2
Sync();
#endif
State = ProxyState.Running;
clientEp.SendTerminated();
outgoing.Record((uint)MessageType.Terminated, null);
break;
case serverEp.ChannelClosed():
State = ProxyState.Running;
DebugStub.Print("CJ: Server disconnected.\n");
recovery = true;
goto exit;
break;
}
State = ProxyState.Waiting;
}
exit:
if (recovery) {
counterClientRef.Release(clientEp);
counterServerRef.Release(serverEp);
}
else {
delete clientEp;
delete serverEp;
}
return recovery;
}
protected override bool Recover()
{
bool success = false;
uint msg;
IList args;
Object tmp;
MessageType op;
CounterContract.Imp:Start serverEp;
DebugStub.Print("-- Incoming Log Length: {0}\n",
__arglist(incoming.Count));
DebugStub.Print("-- Outgoing Log Length: {0}\n",
__arglist(outgoing.Count));
//
// Channel initialization
//
assume initServerRef != null;
DebugStub.Print("CJ: Getting an endpoint...");
serverEp = initServerRef.Acquire();
switch receive {
case serverEp.Success():
break;
case serverEp.ChannelClosed():
delete serverEp;
throw new ChannelClosedException();
break;
}
DebugStub.Print("done.\n");
//
// Channel State Recovery Main Loop
//
while (incoming.Playback(out msg, out args)) {
//
// Playback the incoming message
//
op = (MessageType)msg;
switch (op) {
case MessageType.Increment:
serverEp.SendIncrement();
break;
case MessageType.BeginCount:
serverEp.SendBeginCount();
break;
case MessageType.Next:
serverEp.SendNext();
break;
case MessageType.End:
serverEp.SendEnd();
break;
}
//
// Playback the outgoing message
//
bool res = true;
res = outgoing.Playback(out msg, out args);
op = (MessageType)msg;
if (!res) {
DebugStub.Print("Playback: End of log. Break.\n");
success = true;
break;
}
switch receive {
case serverEp.AckIncrement(number):
if (op != MessageType.AckIncrement || args == null) {
// make a decision
// 1. ignore
// 2. notify
success = false;
}
else {
tmp = args[0];
if (tmp == null) {
// make a decision
// 1. ignore
// 2. notify
success = false;
}
else {
int lognum = (int)tmp;
if (number != lognum) {
// make a decision
// 1. ignore
// 2. notify
success = false;
}
else {
success = true;
}
}
}
break;
case serverEp.NakIncrement():
if (op != MessageType.NakIncrement) {
// make a decision
// 1. ignore
// 2. notify
success = false;
}
else {
success = true;
}
break;
case serverEp.Current(number):
if (op != MessageType.Current ||
args == null) {
// make a decision
// 1. ignore
// 2. notify
success = false;
}
else {
tmp = args[0];
if (tmp == null) {
// make a decision
// 1. ignore
// 2. notify
success = false;
}
else {
int lognum = (int)tmp;
if (number != lognum) {
// make a decision
// 1. ignore
// 2. notify
success = false;
}
else {
success = true;
}
}
}
break;
case serverEp.Terminated():
if (op != MessageType.Terminated) {
// make a decision
// 1. ignore
// 2. notify
success = false;
}
else {
success = true;
}
break;
case serverEp.ChannelClosed():
delete serverEp;
throw new ChannelClosedException();
break;
}
} // end of loop
assume counterServerRef != null;
delete counterServerRef.Acquire();
counterServerRef.Release(serverEp);
return success;
}
}
}