/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: Libraries\Resiliency\UndoableMemory.sg // // Note: // using System; using System.Collections; using System.Collections.Specialized; using Microsoft.SingSharp; using Microsoft.Singularity; using Microsoft.Singularity.Channels; namespace Microsoft.Singularity.Resiliency { public class PersistentMemory { private IDictionary! table; public PersistentMemory() { table = new ListDictionary(); } public void Store([Claims]byte[]! in ExHeap buffer) { int offset = 0; int length = buffer.Length; int index; int count; UndoableMemory memoryObject; byte[]! copyBuffer = Bitter.ToByteArray(buffer); byte[] storeBuffer; //DebugStub.Print("PMem: Enter Store\n"); //DebugStub.Print("PMem: Buffer length {0}\n", // __arglist(buffer.Length)); while (offset + 8 < length) { // // Deserialize // // length count = BitConverter.ToInt32(copyBuffer, offset); offset += sizeof(int); if (offset >= length) { DebugStub.Print("PMem: deserialize err\n"); break; } // index index = BitConverter.ToInt32(copyBuffer, offset); offset += sizeof(int); if (offset >= length) { DebugStub.Print("PMem: deserialize err\n"); break; } // contents storeBuffer = new byte[count]; Buffer.BlockCopy(copyBuffer, offset, storeBuffer, 0, count); offset += count; //DebugStub.Print("PMem: [{0}] {1}:{2}\n", // __arglist(index, count, offset)); // // Store the data // Object obj = table[index]; if (obj == null) { memoryObject = new UndoableMemory(); table[index] = memoryObject; } else { memoryObject = obj as UndoableMemory; } if (memoryObject != null) { memoryObject.Store(storeBuffer); } } delete buffer; //DebugStub.Print("PMem: Exit Store\n"); } public byte[] in ExHeap Restore() { byte[] buffer = null; int offset; int length; UndoableMemory memoryObject; DebugStub.Print("PMem: Enter Restore\n"); if (table.Count == 0) { return null; } length = 0; foreach (DictionaryEntry entry in table) { memoryObject = entry.Value as UndoableMemory; if (memoryObject != null) { memoryObject.Flush(); length += memoryObject.Length; } length += sizeof(int) * 2; } if (length > Int32.MaxValue) { throw new Exception(); } DebugStub.Print("PMem: Serialize\n"); // // Serialize // buffer = new byte[length]; offset = 0; foreach (DictionaryEntry entry in table) { int index = (int)entry.Key; memoryObject = entry.Value as UndoableMemory; if (memoryObject == null) { // length for (int i = 0; i < sizeof(int); i++) { buffer[offset + i] = 0; } offset += sizeof(int); // index Buffer.BlockCopy(BitConverter.GetBytes(index), 0, buffer, offset, sizeof(int)); offset += sizeof(int); } else { // length Buffer.BlockCopy(BitConverter.GetBytes(memoryObject.Length), 0, buffer, offset, sizeof(int)); offset += sizeof(int); // index Buffer.BlockCopy(BitConverter.GetBytes(index), 0, buffer, offset, sizeof(int)); offset += sizeof(int); // contents Buffer.BlockCopy(memoryObject.Restore(), 0, buffer, offset, memoryObject.Length); offset += memoryObject.Length; } } DebugStub.Print("PMem: Exit Restore\n"); return Bitter.FromByteArray(buffer); } public void Flush() { //DebugStub.Print("PMem: Enter Flush\n"); foreach (DictionaryEntry entry in table) { UndoableMemory memoryObject = entry.Value as UndoableMemory; if (memoryObject != null) { //DebugStub.Print("[{0}]\n", __arglist((int)entry.Key)); memoryObject.Flush(); } } //DebugStub.Print("PMem: Exit Flush\n"); //DebugStub.Break(); } public void Undo() { foreach (DictionaryEntry entry in table) { UndoableMemory memoryObject = entry.Value as UndoableMemory; if (memoryObject != null) { memoryObject.Undo(); } } } } }