// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma warning disable 0162
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace FASTER.core
{
///
/// Recovery info for FASTER Log
///
internal struct FasterLogRecoveryInfo
{
///
/// Begin address
///
public long BeginAddress;
///
/// Flushed logical address
///
public long FlushedUntilAddress;
///
/// Persisted iterators
///
public Dictionary Iterators;
///
/// Initialize
///
public void Initialize()
{
BeginAddress = 0;
FlushedUntilAddress = 0;
}
///
/// Initialize from stream
///
///
public void Initialize(BinaryReader reader)
{
int version;
long checkSum;
try
{
version = reader.ReadInt32();
checkSum = reader.ReadInt64();
BeginAddress = reader.ReadInt64();
FlushedUntilAddress = reader.ReadInt64();
}
catch (Exception e)
{
throw new Exception("Unable to recover from previous commit. Inner exception: " + e.ToString());
}
if (version != 0)
throw new Exception("Invalid version found during commit recovery");
if (checkSum != (BeginAddress ^ FlushedUntilAddress))
throw new Exception("Invalid checksum found during commit recovery");
var count = 0;
try
{
count = reader.ReadInt32();
}
catch { }
if (count > 0)
{
Iterators = new Dictionary();
for (int i = 0; i < count; i++)
{
Iterators.Add(reader.ReadString(), reader.ReadInt64());
}
}
}
///
/// Recover info from token
///
///
///
internal void Recover(ILogCommitManager logCommitManager)
{
var metadata = logCommitManager.GetCommitMetadata();
if (metadata == null)
throw new Exception("Invalid log commit metadata during recovery");
Initialize(new BinaryReader(new MemoryStream(metadata)));
}
///
/// Reset
///
public void Reset()
{
Initialize();
}
///
/// Write info to byte array
///
public byte[] ToByteArray()
{
using (var ms = new MemoryStream())
{
using (var writer = new BinaryWriter(ms))
{
writer.Write(0); // version
writer.Write(BeginAddress ^ FlushedUntilAddress); // checksum
writer.Write(BeginAddress);
writer.Write(FlushedUntilAddress);
if (Iterators?.Count > 0)
{
writer.Write(Iterators.Count);
foreach (var kvp in Iterators)
{
writer.Write(kvp.Key);
writer.Write(kvp.Value);
}
}
}
return ms.ToArray();
}
}
///
/// Take snapshot of persisted iterators
///
public void PopulateIterators()
{
if (FasterLogScanIterator.PersistedIterators.Count > 0)
{
Iterators = new Dictionary();
foreach (var kvp in FasterLogScanIterator.PersistedIterators)
{
Iterators.Add(kvp.Key, kvp.Value.CurrentAddress);
}
}
}
///
/// Print checkpoint info for debugging purposes
///
public void DebugPrint()
{
Debug.WriteLine("******** Log Commit Info ********");
Debug.WriteLine("BeginAddress: {0}", BeginAddress);
Debug.WriteLine("FlushedUntilAddress: {0}", FlushedUntilAddress);
}
}
}