You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel/Services/FASTER/Index/Recovery/IndexRecovery.cs

145 lines
5.5 KiB

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace FASTER.core
{
/// <summary>
///
/// </summary>
public unsafe partial class FasterBase
{
internal ICheckpointManager checkpointManager;
// Derived class exposed API
internal void RecoverFuzzyIndex(IndexCheckpointInfo info)
{
var token = info.info.token;
var ht_version = resizeInfo.version;
Debug.Assert(state[ht_version].size == info.info.table_size);
// Create devices to read from using Async API
info.main_ht_device = checkpointManager.GetIndexDevice(token);
BeginMainIndexRecovery(ht_version,
info.main_ht_device,
info.info.num_ht_bytes);
var sectorSize = info.main_ht_device.SectorSize;
var alignedIndexSize = (uint)((info.info.num_ht_bytes + (sectorSize - 1)) & ~(sectorSize - 1));
overflowBucketsAllocator.Recover(info.main_ht_device, alignedIndexSize, info.info.num_buckets, info.info.num_ofb_bytes);
// Wait until reading is complete
IsFuzzyIndexRecoveryComplete(true);
// close index checkpoint files appropriately
info.main_ht_device.Close();
// Delete all tentative entries!
DeleteTentativeEntries();
}
internal void RecoverFuzzyIndex(int ht_version, IDevice device, ulong num_ht_bytes, IDevice ofbdevice, int num_buckets, ulong num_ofb_bytes)
{
BeginMainIndexRecovery(ht_version, device, num_ht_bytes);
var sectorSize = device.SectorSize;
var alignedIndexSize = (uint)((num_ht_bytes + (sectorSize - 1)) & ~(sectorSize - 1));
overflowBucketsAllocator.Recover(ofbdevice, alignedIndexSize, num_buckets, num_ofb_bytes);
}
internal bool IsFuzzyIndexRecoveryComplete(bool waitUntilComplete = false)
{
bool completed1 = IsMainIndexRecoveryCompleted(waitUntilComplete);
bool completed2 = overflowBucketsAllocator.IsRecoveryCompleted(waitUntilComplete);
return completed1 && completed2;
}
//Main Index Recovery Functions
private CountdownEvent mainIndexRecoveryEvent;
private void BeginMainIndexRecovery(
int version,
IDevice device,
ulong num_bytes)
{
int numChunksToBeRecovered = 1;
long totalSize = state[version].size * sizeof(HashBucket);
Debug.Assert(totalSize < (long)uint.MaxValue); // required since numChunks = 1
uint chunkSize = (uint)(totalSize / numChunksToBeRecovered);
mainIndexRecoveryEvent = new CountdownEvent(numChunksToBeRecovered);
HashBucket* start = state[version].tableAligned;
ulong numBytesRead = 0;
for (int index = 0; index < numChunksToBeRecovered; index++)
{
long chunkStartBucket = (long)start + (index * chunkSize);
HashIndexPageAsyncReadResult result = default(HashIndexPageAsyncReadResult);
result.chunkIndex = index;
device.ReadAsync(numBytesRead, (IntPtr)chunkStartBucket, chunkSize, AsyncPageReadCallback, result);
numBytesRead += chunkSize;
}
Debug.Assert(numBytesRead == num_bytes);
}
private bool IsMainIndexRecoveryCompleted(
bool waitUntilComplete = false)
{
bool completed = mainIndexRecoveryEvent.IsSet;
if (!completed && waitUntilComplete)
{
mainIndexRecoveryEvent.Wait();
return true;
}
return completed;
}
private unsafe void AsyncPageReadCallback(uint errorCode, uint numBytes, NativeOverlapped* overlap)
{
if (errorCode != 0)
{
Trace.TraceError("OverlappedStream GetQueuedCompletionStatus error: {0}", errorCode);
}
mainIndexRecoveryEvent.Signal();
Overlapped.Free(overlap);
}
internal void DeleteTentativeEntries()
{
HashBucketEntry entry = default(HashBucketEntry);
int version = resizeInfo.version;
var table_size_ = state[version].size;
var ptable_ = state[version].tableAligned;
for (long bucket = 0; bucket < table_size_; ++bucket)
{
HashBucket b = *(ptable_ + bucket);
while (true)
{
for (int bucket_entry = 0; bucket_entry < Constants.kOverflowBucketIndex; ++bucket_entry)
{
entry.word = b.bucket_entries[bucket_entry];
if (entry.Tentative)
b.bucket_entries[bucket_entry] = 0;
}
if (b.bucket_entries[Constants.kOverflowBucketIndex] == 0) break;
b = *((HashBucket*)overflowBucketsAllocator.GetPhysicalAddress((b.bucket_entries[Constants.kOverflowBucketIndex])));
}
}
}
}
}

Powered by TurnKey Linux.