306 lines
9.3 KiB
Plaintext
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
|
||
|
}
|