Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding basic version of DUMP and RESTORE commands #899

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2954d6e
Implement basic version of DUMP and RESTORE redis commands
s3w3nofficial Dec 22, 2024
0e7f821
Merge branch 'main' into s3w3nofficial/add-dump-and-restore-command
s3w3nofficial Jan 3, 2025
7406d74
refactor and add dump, restore to cluster slot verification test
s3w3nofficial Jan 12, 2025
8a9ee0a
Merge branch 'main' into s3w3nofficial/add-dump-and-restore-command
s3w3nofficial Jan 12, 2025
6133607
Update comments to use 'RESP' encoding terminology
badrishc Jan 13, 2025
c14f0b3
fix formating
s3w3nofficial Jan 15, 2025
0d18b6a
Merge branch 'main' into s3w3nofficial/add-dump-and-restore-command
s3w3nofficial Jan 15, 2025
2f9b457
fix tests
s3w3nofficial Jan 15, 2025
2fa9b08
add acl and tests and update default config to include the skip checksum
s3w3nofficial Jan 16, 2025
181d780
rm accidentally commited dump.rdb file
s3w3nofficial Jan 16, 2025
2a789d8
Remove trailing whitespace in RespCommandTests.cs
badrishc Jan 16, 2025
f15a662
fix comments
s3w3nofficial Jan 16, 2025
e281e34
run CommandInfoUpdater and replace docs / info files
s3w3nofficial Jan 16, 2025
d41421d
Merge branch 'main' into s3w3nofficial/add-dump-and-restore-command
s3w3nofficial Jan 16, 2025
737e7a9
Remove trailing whitespace in Options.cs
badrishc Jan 16, 2025
eed596f
fix RestoreACLsAsync test
s3w3nofficial Jan 16, 2025
85d0136
fix comments
s3w3nofficial Jan 16, 2025
2f2a9a3
optimize RespLengthEncodingUtils
s3w3nofficial Jan 17, 2025
024362b
implement suggestions
s3w3nofficial Jan 18, 2025
6b1b7b5
fix comments
s3w3nofficial Jan 19, 2025
60cb1e2
use SET_Conditional directly
s3w3nofficial Jan 19, 2025
02718c7
rename SkipChecksumValidation
s3w3nofficial Jan 19, 2025
1fb94a5
fix cluster restore test
s3w3nofficial Jan 19, 2025
52b1fa6
directly write to the output buffer for non-large objects
s3w3nofficial Jan 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions libs/common/Crc64.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

using System;

namespace Garnet.common;

/// <summary>
/// Port of redis crc64 from https://github.com/redis/redis/blob/7.2/src/crc64.c
/// </summary>
public static class Crc64
{
/// <summary>
/// Polynomial (same as redis)
/// </summary>
private const ulong POLY = 0xad93d23594c935a9UL;

/// <summary>
/// Reverse all bits in a 64-bit value (bit reflection).
/// Only used for data_len == 64 in this code.
/// </summary>
private static ulong Reflect64(ulong data)
{
// swap odd/even bits
data = ((data >> 1) & 0x5555555555555555UL) | ((data & 0x5555555555555555UL) << 1);
// swap consecutive pairs
data = ((data >> 2) & 0x3333333333333333UL) | ((data & 0x3333333333333333UL) << 2);
// swap nibbles
data = ((data >> 4) & 0x0F0F0F0F0F0F0F0FUL) | ((data & 0x0F0F0F0F0F0F0F0FUL) << 4);
// swap bytes, then 2-byte pairs, then 4-byte pairs
data = System.Buffers.Binary.BinaryPrimitives.ReverseEndianness(data);
return data;
}

/// <summary>
/// A direct bit-by-bit CRC64 calculation (like _crc64 in C).
/// </summary>
private static ulong Crc64Bitwise(ReadOnlySpan<byte> data)
{
ulong crc = 0;

foreach (var c in data)
{
for (byte i = 1; i != 0; i <<= 1)
{
// interpret the top bit of 'crc' and current bit of 'c'
var bitSet = (crc & 0x8000000000000000UL) != 0;
var cbit = (c & i) != 0;

// if cbit flips the sense, invert bitSet
if (cbit)
bitSet = !bitSet;

// shift
crc <<= 1;

// apply polynomial if needed
if (bitSet)
crc ^= POLY;
}

// ensure it stays in 64 bits
crc &= 0xffffffffffffffffUL;
}

// reflect and XOR, per standard
crc &= 0xffffffffffffffffUL;
crc = Reflect64(crc) ^ 0x0000000000000000UL;
return crc;
}

/// <summary>
/// Computes crc64
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static byte[] Hash(ReadOnlySpan<byte> data)
vazois marked this conversation as resolved.
Show resolved Hide resolved
{
var bitwiseCrc = Crc64Bitwise(data);
return BitConverter.GetBytes(bitwiseCrc);
}
}
111 changes: 111 additions & 0 deletions libs/common/RespLengthEncodingUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

using System;
using System.Buffers.Binary;

namespace Garnet.common;

/// <summary>
/// Utils for working with RESP length encoding
/// </summary>
public static class RespLengthEncodingUtils
{
/// <summary>
/// Maximum length that can be encoded
/// </summary>
private const int MaxLength = 0xFFFFFF;

/// <summary>
/// Try read RESP-encoded length
/// </summary>
/// <param name="input"></param>
/// <param name="length"></param>
/// <param name="bytesRead"></param>
/// <returns></returns>
public static bool TryReadLength(ReadOnlySpan<byte> input, out int length, out int bytesRead)
{
length = 0;
bytesRead = 0;
if (input.Length < 1)
{
return false;
}

var firstByte = input[0];
switch (firstByte >> 6)
{
case 0:
bytesRead = 1;
length = firstByte & 0x3F;
return true;
case 1 when input.Length > 1:
bytesRead = 2;
length = ((firstByte & 0x3F) << 8) | input[1];
return true;
case 2:
bytesRead = 5;
return BinaryPrimitives.TryReadInt32BigEndian(input, out length);
default:
return false;
}
}

/// <summary>
/// Try to write RESP-encoded length
/// </summary>
/// <param name="length"></param>
/// <param name="output"></param>
/// <param name="bytesWritten"></param>
/// <returns></returns>
public static bool TryWriteLength(int length, Span<byte> output, out int bytesWritten)
{
bytesWritten = 0;

if (length > MaxLength)
{
return false;
}

// 6-bit encoding (length ≤ 63)
if (length < 1 << 6)
{
if (output.Length < 1)
{
return false;
}

output[0] = (byte)(length & 0x3F);

bytesWritten = 1;
return true;
}

// 14-bit encoding (64 ≤ length ≤ 16,383)
if (length < 1 << 14)
{
if (output.Length < 2)
{
return false;
}

output[0] = (byte)(((length >> 8) & 0x3F) | (1 << 6));
output[1] = (byte)(length & 0xFF);

bytesWritten = 2;
return true;
}

// 32-bit encoding (length ≤ 4,294,967,295)
if (output.Length < 5)
{
return false;
}

output[0] = 2 << 6;
BinaryPrimitives.WriteUInt32BigEndian(output.Slice(1), (uint)length);

bytesWritten = 5;
return true;
}
}
7 changes: 6 additions & 1 deletion libs/host/Configuration/Options.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

using System;
Expand Down Expand Up @@ -509,6 +509,10 @@ internal sealed class Options
[Option("fail-on-recovery-error", Default = false, Required = false, HelpText = "Server bootup should fail if errors happen during bootup of AOF and checkpointing")]
public bool? FailOnRecoveryError { get; set; }

[OptionValidation]
[Option("skip-rdb-restore-checksum-validation", Default = false, Required = false, HelpText = "Skip RDB restore checksum validation")]
public bool? SkipRDBRestoreChecksumValidation { get; set; }

[Option("lua-memory-management-mode", Default = LuaMemoryManagementMode.Native, Required = false, HelpText = "Memory management mode for Lua scripts, must be set to LimittedNative or Managed to impose script limits")]
public LuaMemoryManagementMode LuaMemoryManagementMode { get; set; }

Expand Down Expand Up @@ -728,6 +732,7 @@ public GarnetServerOptions GetServerOptions(ILogger logger = null)
IndexResizeThreshold = IndexResizeThreshold,
LoadModuleCS = LoadModuleCS,
FailOnRecoveryError = FailOnRecoveryError.GetValueOrDefault(),
SkipRDBRestoreChecksumValidation = SkipRDBRestoreChecksumValidation.GetValueOrDefault(),
LuaOptions = EnableLua.GetValueOrDefault() ? new LuaOptions(LuaMemoryManagementMode, LuaScriptMemoryLimit, logger) : null,
};
}
Expand Down
3 changes: 3 additions & 0 deletions libs/host/defaults.conf
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@
/* Fails if encounters error during AOF replay or checkpointing */
"FailOnRecoveryError": false,

/* Skips crc64 validation in restore command */
"SkipRDBRestoreChecksumValidation": false,

/* Lua uses the default, unmanaged and untracked, allocator */
"LuaMemoryManagementMode": "Native",

Expand Down
Loading