diff --git a/libs/common/RespLengthEncodingUtils.cs b/libs/common/RespLengthEncodingUtils.cs
index a5ab9dea4f..c19cdd696b 100644
--- a/libs/common/RespLengthEncodingUtils.cs
+++ b/libs/common/RespLengthEncodingUtils.cs
@@ -17,7 +17,7 @@ public static class RespLengthEncodingUtils
///
///
///
- public static (long length, byte payloadStart) DecodeLength(ref ReadOnlySpan buff)
+ public static (long Length, byte PayloadStart) DecodeLength(ref ReadOnlySpan buff)
{
// remove the value type byte
var encoded = buff.Slice(1);
diff --git a/libs/server/Resp/KeyAdminCommands.cs b/libs/server/Resp/KeyAdminCommands.cs
index 06e2596683..0a947e1590 100644
--- a/libs/server/Resp/KeyAdminCommands.cs
+++ b/libs/server/Resp/KeyAdminCommands.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using System;
+using System.Buffers;
using System.Diagnostics;
using Garnet.common;
using Garnet.server.Auth;
@@ -43,12 +44,11 @@ bool NetworkRESTORE(ref TGarnetApi storageApi)
// return error if key already exists
var keyExists = storageApi.EXISTS(key);
- switch (keyExists)
+ if (keyExists is GarnetStatus.OK)
{
- case GarnetStatus.OK:
- while (!RespWriteUtils.WriteDirect(CmdStrings.RESP_ERR_KEY_ALREADY_EXISTS, ref dcurr, dend))
- SendAndReset();
- return true;
+ while (!RespWriteUtils.WriteDirect(CmdStrings.RESP_ERR_KEY_ALREADY_EXISTS, ref dcurr, dend))
+ SendAndReset();
+ return true;
}
var valueSpan = value.ReadOnlySpan;
@@ -128,24 +128,27 @@ bool NetworkDUMP(ref TGarnetApi storageApi)
var status = storageApi.GET(key, out var value);
- switch (status)
+ if (status is GarnetStatus.NOTFOUND)
{
- case GarnetStatus.NOTFOUND:
- while (!RespWriteUtils.WriteDirect(CmdStrings.RESP_ERRNOTFOUND, ref dcurr, dend))
- SendAndReset();
- return true;
+ while (!RespWriteUtils.WriteDirect(CmdStrings.RESP_ERRNOTFOUND, ref dcurr, dend))
+ SendAndReset();
+ return true;
}
var encodedLength = RespLengthEncodingUtils.EncodeLength(value.ReadOnlySpan.Length);
// Len of the dump (payload type + redis encoded payload len + payload len + rdb version + crc64)
var len = 1 + encodedLength.Length + value.ReadOnlySpan.Length + 2 + 8;
- var lengthInASCIIBytes = new Span(new byte[NumUtils.NumDigitsInLong(len)]);
+ Span lengthInASCIIBytes = stackalloc byte[NumUtils.NumDigitsInLong(len)];
var lengthInASCIIBytesLen = NumUtils.LongToSpanByte(len, lengthInASCIIBytes);
// Total len (% + length of ascii bytes + CR LF + payload type + redis encoded payload len + payload len + rdb version + crc64 + CR LF)
var totalLength = 1 + lengthInASCIIBytesLen + 2 + 1 + encodedLength.Length + value.ReadOnlySpan.Length + 2 + 8 + 2;
- Span buffer = stackalloc byte[totalLength];
+
+ var buffer = totalLength <= 128
+ ? stackalloc byte[totalLength]
+ : new byte[totalLength];
+
var offset = 0;
// Write RESP bulk string prefix and length
@@ -159,8 +162,8 @@ bool NetworkDUMP(ref TGarnetApi storageApi)
buffer[offset++] = 0x00;
// length of the span
- foreach (var b in encodedLength)
- buffer[offset++] = b;
+ encodedLength.CopyTo(buffer[offset..]);
+ offset += encodedLength.Length;
// copy value to buffer
value.ReadOnlySpan.CopyTo(buffer[offset..]);
@@ -182,7 +185,7 @@ bool NetworkDUMP(ref TGarnetApi storageApi)
buffer[offset++] = 0x0D; // CR
buffer[offset++] = 0x0A; // LF
- while (!RespWriteUtils.WriteDirect(buffer, ref dcurr, dend))
+ while (!RespWriteUtils.WriteDirect(buffer.Slice(0, totalLength), ref dcurr, dend))
SendAndReset();
return true;
diff --git a/test/Garnet.test/Resp/ACL/RespCommandTests.cs b/test/Garnet.test/Resp/ACL/RespCommandTests.cs
index c4c2ad3a2c..8dc10d1655 100644
--- a/test/Garnet.test/Resp/ACL/RespCommandTests.cs
+++ b/test/Garnet.test/Resp/ACL/RespCommandTests.cs
@@ -6439,8 +6439,8 @@ async Task DoRestoreAsync(GarnetClient client)
var val = await client.ExecuteForStringResultAsync(
"$7\r\nRESTORE\r\n"u8.ToArray(),
[
- Encoding.UTF8.GetBytes($"foo-{count}"),
- "0"u8.ToArray(),
+ Encoding.UTF8.GetBytes($"foo-{count}"),
+ "0"u8.ToArray(),
payload
]);