202 lines
5.9 KiB
Plaintext
202 lines
5.9 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.IO;
|
|
using Microsoft.SingSharp;
|
|
|
|
namespace Microsoft.Singularity.Resiliency
|
|
{
|
|
internal class UndoableMemory
|
|
{
|
|
private const int DefaultCapacity = 256;
|
|
private byte[]! master;
|
|
private byte[] shadow;
|
|
private byte[] backup;
|
|
private int capacity;
|
|
private int length;
|
|
|
|
internal UndoableMemory() : this(0) {}
|
|
|
|
internal UndoableMemory(int capacity)
|
|
requires (capacity >= 0);
|
|
{
|
|
this.master = this.shadow = new byte[capacity];
|
|
this.capacity = capacity;
|
|
}
|
|
|
|
internal byte[]! Restore()
|
|
{
|
|
byte[] buffer = new byte[length];
|
|
|
|
if (length <= 8) {
|
|
int byteCount = length;
|
|
while (--byteCount >= 0) {
|
|
buffer[byteCount] = shadow[byteCount];
|
|
}
|
|
}
|
|
else {
|
|
Buffer.BlockCopy(shadow, 0, buffer, 0, length);
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
internal void Store(byte[]! buffer)
|
|
{
|
|
int count = buffer.Length;
|
|
|
|
if (master == shadow) {
|
|
if (backup != null) {
|
|
shadow = backup;
|
|
}
|
|
else {
|
|
shadow = new byte[capacity];
|
|
Buffer.BlockCopy(master, 0, shadow, 0, capacity);
|
|
}
|
|
}
|
|
|
|
if (count >= length) {
|
|
int newLength = count + 1;
|
|
bool mustZero = count > length;
|
|
if (newLength >= capacity) {
|
|
bool allocatedNewArray = EnsureCapacity(newLength);
|
|
if (allocatedNewArray) {
|
|
mustZero = false;
|
|
}
|
|
}
|
|
if (mustZero) {
|
|
Array.Clear(shadow, length, count - length);
|
|
}
|
|
length = newLength;
|
|
}
|
|
|
|
if (count <= 8) {
|
|
int byteCount = count;
|
|
while (--byteCount >= 0) {
|
|
shadow[byteCount] = buffer[byteCount];
|
|
}
|
|
}
|
|
else {
|
|
Buffer.BlockCopy(buffer, 0, shadow, 0, buffer.Length);
|
|
}
|
|
length = buffer.Length;
|
|
}
|
|
|
|
internal void DirectStore(byte[]! buffer)
|
|
{
|
|
shadow = (byte[])buffer;
|
|
length = buffer.Length;
|
|
capacity = buffer.Length;
|
|
backup = null;
|
|
}
|
|
|
|
private bool EnsureCapacity(int value)
|
|
requires (value >= 0);
|
|
{
|
|
if (value > capacity) {
|
|
int newCapacity = value;
|
|
if (newCapacity < DefaultCapacity) {
|
|
newCapacity = DefaultCapacity;
|
|
}
|
|
if (newCapacity < capacity * 2) {
|
|
newCapacity = capacity * 2;
|
|
}
|
|
Capacity = newCapacity;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
internal void Flush()
|
|
{
|
|
if (master != shadow) {
|
|
if (shadow != null) {
|
|
//DumpMaster();
|
|
//DumpShadow();
|
|
if (master.Length < length) {
|
|
master = new byte[capacity];
|
|
}
|
|
Buffer.BlockCopy(shadow, 0, master, 0, length);
|
|
backup = shadow;
|
|
}
|
|
else {
|
|
Array.Clear(master, 0, length);
|
|
}
|
|
}
|
|
shadow = master;
|
|
}
|
|
|
|
internal void Undo()
|
|
{
|
|
shadow = master;
|
|
backup = null;
|
|
}
|
|
|
|
internal int Capacity
|
|
{
|
|
get { return capacity; }
|
|
set
|
|
{
|
|
if (value != capacity) {
|
|
if (value < length) {
|
|
throw new ArgumentOutOfRangeException(
|
|
"value", "ArgumentOutOfRange_SmallCapacity");
|
|
}
|
|
if (value > 0) {
|
|
byte[] newBuffer = new byte[value];
|
|
if (length > 0) {
|
|
Buffer.BlockCopy(shadow, 0, newBuffer, 0, length);
|
|
}
|
|
shadow = newBuffer;
|
|
}
|
|
else {
|
|
shadow = null;
|
|
}
|
|
capacity = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal int Length
|
|
{
|
|
get { return length; }
|
|
}
|
|
|
|
private void Dump(byte[]! buffer)
|
|
{
|
|
/*
|
|
for (int i = 0; i < buffer.Length; i += 20) {
|
|
for (int j = 0; j < 20 && i + j < buffer.Length; j++) {
|
|
DebugStub.Print("{0:X2} ", __arglist(buffer[i + j]));
|
|
}
|
|
DebugStub.WriteLine();
|
|
}
|
|
*/
|
|
for (int i = 0; i < buffer.Length && i < 20; i++) {
|
|
DebugStub.Print("{0:X2} ", __arglist(buffer[i]));
|
|
}
|
|
DebugStub.WriteLine();
|
|
}
|
|
|
|
internal void DumpMaster()
|
|
{
|
|
DebugStub.Print("-- Dump Master\n");
|
|
Dump(master);
|
|
}
|
|
|
|
internal void DumpShadow()
|
|
{
|
|
DebugStub.Print("-- Dump Shadow\n");
|
|
Dump(shadow);
|
|
}
|
|
}
|
|
}
|