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/Common/RecordInfo.cs

244 lines
6.4 KiB

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma warning disable 1591
//#define RECORD_INFO_WITH_PIN_COUNT
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
namespace FASTER.core
{
#if RECORD_INFO_WITH_PIN_COUNT
[StructLayout(LayoutKind.Explicit, Size = 12)]
#else
[StructLayout(LayoutKind.Explicit, Size = 8)]
#endif
public unsafe struct RecordInfo
{
public const int kFinalBitOffset = 48;
public const int kTombstoneBitOffset = 49;
public const int kInvalidBitOffset = 50;
public const int kVersionBits = 13;
public const int kVersionShiftInWord = 51;
public const long kVersionMaskInWord = ((1L << kVersionBits) - 1) << kVersionShiftInWord;
public const long kVersionMaskInInteger = (1L << kVersionBits) - 1;
public const long kPreviousAddressMask = (1L << 48) - 1;
public const long kFinalBitMask = (1L << kFinalBitOffset);
public const long kTombstoneMask = (1L << kTombstoneBitOffset);
public const long kInvalidBitMask = (1L << kInvalidBitOffset);
#if RECORD_INFO_WITH_PIN_COUNT
public const int kTotalSizeInBytes = sizeof(long) + sizeof(int);
public const int kTotalBits = kTotalSizeInBytes * 8;
[FieldOffset(0)]
private long word;
[FieldOffset(sizeof(long))]
private int access_data;
public static void WriteInfo(RecordInfo* info, int checkpointVersion, bool final, bool tombstone, bool invalidBit, long previousAddress)
{
info->word = default(long);
info->Final = final;
info->Tombstone = tombstone;
info->Invalid = invalidBit;
info->PreviousAddress = previousAddress;
info->Version = checkpointVersion;
info->access_data = 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryPin()
{
return Interlocked.Increment(ref access_data) > 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryMarkReadOnly()
{
return Interlocked.CompareExchange(ref access_data, int.MinValue, 0) == 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MarkReadOnly()
{
var found_value = Interlocked.CompareExchange(ref access_data, int.MinValue, 0);
if (found_value != 0)
{
int num_iterations = 1000;
Thread.SpinWait(num_iterations);
while (Interlocked.CompareExchange(ref access_data, int.MinValue, 0) != 0)
{
Thread.SpinWait(num_iterations);
num_iterations <<= 1;
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Unpin()
{
Interlocked.Decrement(ref access_data);
}
#else
public const int kTotalSizeInBytes = sizeof(long);
public const int kTotalBits = kTotalSizeInBytes * 8;
[FieldOffset(0)]
private long word;
public static void WriteInfo(ref RecordInfo info, int checkpointVersion, bool final, bool tombstone, bool invalidBit, long previousAddress)
{
info.word = default(long);
info.Final = final;
info.Tombstone = tombstone;
info.Invalid = invalidBit;
info.PreviousAddress = previousAddress;
info.Version = checkpointVersion;
}
public static string ToString(RecordInfo* info)
{
return "RecordHeader Word = " + info->word;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryPin()
{
throw new InvalidOperationException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryMarkReadOnly()
{
throw new InvalidOperationException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MarkReadOnly()
{
throw new InvalidOperationException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Unpin()
{
throw new InvalidOperationException();
}
#endif
public bool IsNull()
{
return word == 0;
}
public bool Tombstone
{
get
{
return (word & kTombstoneMask) > 0;
}
set
{
if (value)
{
word |= kTombstoneMask;
}
else
{
word &= ~kTombstoneMask;
}
}
}
public bool Final
{
get
{
return (word & kFinalBitMask) > 0;
}
set
{
if (value)
{
word |= kFinalBitMask;
}
else
{
word &= ~kFinalBitMask;
}
}
}
public bool Invalid
{
get
{
return !((word & kInvalidBitMask) > 0);
}
set
{
if (value)
{
word &= ~kInvalidBitMask;
}
else
{
word |= kInvalidBitMask;
}
}
}
public int Version
{
get
{
return (int)(((word & kVersionMaskInWord) >> kVersionShiftInWord) & kVersionMaskInInteger);
}
set
{
word &= ~kVersionMaskInWord;
word |= ((value & kVersionMaskInInteger) << kVersionShiftInWord);
}
}
public long PreviousAddress
{
get
{
return (word & kPreviousAddressMask);
}
set
{
word &= ~kPreviousAddressMask;
word |= (value & kPreviousAddressMask);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetLength()
{
return kTotalSizeInBytes;
}
}
}

Powered by TurnKey Linux.