singrdk/base/Libraries/Resiliency/PersistentMemory.sg

186 lines
6.1 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// 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();
}
}
}
}
}