186 lines
6.1 KiB
Plaintext
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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|