/////////////////////////////////////////////////////////////////////////////// // // 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! 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(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 }