singrdk/base/Services/Tests/Replace/GameTable.sg

306 lines
9.3 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Service\Test\Replace\GameTable.sg
//
// Note:
//
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Text;
using System.Threading;
using Microsoft.SingSharp;
using Microsoft.Singularity;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Resiliency;
using Microsoft.Singularity.ServiceManager;
namespace Microsoft.Singularity.Services.Replace
{
internal sealed class GameTable
{
//private const String[] Names = new String[4] {"Microsoft", "Google", "Yahoo", "Apple"};
private readonly String[]! Names;
private const String ProtectionString = "PROTECTED";
private const int NumberOfNames = 4;
private const int ProtectionPeriod = 500;
private const int TableSize = 100;
private String[]! table;
private ASCIIEncoding! encoding;
private Random! random;
private TRef<ServiceProxyContract.Imp:Ready>! proxyRef;
internal GameTable([Claims]ServiceProxyContract.Imp:Start! ep)
{
DebugStub.Print("Waiting for Success message\n");
switch receive {
case ep.Success():
break;
case unsatisfiable:
new ArgumentException();
break;
}
DebugStub.Print("done\n");
Names = new String[4] {"Microsoft", "Google", "Yahoo", "Apple"};
this.table = new String[TableSize];
this.proxyRef = new TRef<ServiceProxyContract.Imp:Ready>(ep);
this.encoding = new ASCIIEncoding();
Thread.Sleep(1);
this.random = new Random();
}
internal void Initialize()
{
ServiceProxyContract.Imp:Ready! ep;
ep = proxyRef.Acquire();
DebugStub.Print("Downloading\n");
ep.SendDownload();
switch receive {
case ep.AckDownload(buffer):
{
Deserialize(buffer, table);
delete buffer;
break;
}
case ep.NakDownload():
{
int j = 0;
for (int i = 0; i < TableSize; i++) {
table[i] = Names[j++];
if (j >= NumberOfNames) {
j = 0;
}
}
break;
}
case unsatisfiable:
{
DebugStub.Break();
break;
}
}
proxyRef.Release(ep);
DebugStub.Print("-- Initial Score\n");
Print();
DebugStub.Break();
}
internal void Commit()
{
ServiceProxyContract.Imp:Ready! ep;
byte[]! in ExHeap buffer;
DebugStub.Print("-- Commit\n");
Print();
Serialize(table, out buffer);
ep = proxyRef.Acquire();
ep.SendUpload(buffer);
switch receive {
case ep.AckUpload():
break;
case unsatisfiable:
DebugStub.Break();
break;
}
proxyRef.Release(ep);
}
internal int Lookup(string! query)
{
int start;
int current;
start = random.Next(TableSize);
assert 0 <= start && start < TableSize;
if (table[start] == query) {
return start;
}
current = start + 1;
if (current >= TableSize) {
current = 0;
}
while (current != start) {
assert 0 <= current && current < TableSize;
if (table[current] == query) {
break;
}
++current;
if (current >= TableSize) {
current = -1;
}
}
if (current == start) {
current = -1;
}
return current;
}
internal void Replace(string! query, int position)
{
//DebugStub.Print("-- Replace {0}\n", __arglist(position));
if (position < 0 || TableSize <= position) {
return;
}
lock (this) {
if (!((!)table[position]).EndsWith(ProtectionString)) {
table[position] = query;
}
else {
DebugStub.Print("Protected!!\n");
}
}
}
internal void Lock(int position)
{
String! tmp;
if (position < 0 || TableSize <= position) {
return;
}
tmp = (!)table[position];
lock (this) {
table[position] += ProtectionString;
}
Thread.Sleep(ProtectionPeriod);
lock (this) {
table[position] = tmp;
}
}
internal int Score(string! query)
{
int count = 0;
lock (this) {
foreach (String! str in table) {
if (str.StartsWith(query)) {
++count;
}
}
}
return count;
}
internal void Print()
{
foreach (String! player in Names) {
DebugStub.Print("{0} : {1}\n",
__arglist(player, Score(player)));
}
}
private void Serialize(string[]! src, out byte[]! in ExHeap dest)
{
byte[][]! conversion = new byte[TableSize][];
byte[] buffer;
byte[] in ExHeap exBuffer;
int size = 0;
int offset = 0;
//
// Enumerate table elements
//
lock (this) {
for (int i = 0; i < TableSize; i++) {
conversion[i] = encoding.GetBytes((!)src[i]);
if (conversion[i] != null) {
size += ((!)conversion[i]).Length + sizeof(int) * 2;
}
else {
throw new NullReferenceException();
}
}
}
assert 0 <= size && size < Int32.MaxValue;
//
// Create a base buffer
//
buffer = new byte[size];
offset = 0;
for (int i = 0; i < TableSize; i++) {
// length
Buffer.BlockCopy(BitConverter.GetBytes(((!)conversion[i]).Length),
0, buffer, offset, sizeof(int));
offset += sizeof(int);
// index
Buffer.BlockCopy(BitConverter.GetBytes(i), 0,
buffer, offset, sizeof(int));
offset += sizeof(int);
// contents
Buffer.BlockCopy(conversion[i], 0, buffer, offset,
((!)conversion[i]).Length);
offset += ((!)conversion[i]).Length;
}
//
// Copy to ExHeap
//
exBuffer = Bitter.FromByteArray(buffer);
dest = exBuffer;
}
private void Deserialize(byte[]! in ExHeap src, string[]! dest)
{
byte[]! copyBuffer = Bitter.ToByteArray(src);
byte[] storeBuffer;
int length = src.Length;
int count;
int id;
int offset = 0;
lock (this) {
while (offset + 8 < length) {
// length
count = BitConverter.ToInt32(copyBuffer, offset);
offset += sizeof(int);
if (offset >= length) {
break;
}
// index
id = BitConverter.ToInt32(copyBuffer, offset);
offset += sizeof(int);
if (offset >= length) {
break;
}
// contents
storeBuffer = new byte[count];
Buffer.BlockCopy(copyBuffer, offset, storeBuffer, 0, count);
offset += count;
if (id < TableSize) {
dest[id] = encoding.GetString(storeBuffer);
}
else {
DebugStub.Break();
// throw new Exception();
}
}
}
}
} // class
}