Repository: microsoft/garnet
File: libs/server/Storage/Session/ObjectStore/Common.cs (C#)

Code before:

namespace Garnet.server
{
    sealed partial class StorageSession : IDisposable
    {
        #region Common ObjectStore Methods

        unsafe GarnetStatus RMWObjectStoreOperation<TObjectContext>(byte[] key, ArgSlice input, out ObjectOutputHeader output, ref TObjectContext objectStoreContext)
            where TObjectContext : ITsavoriteContext<byte[], IGarnetObject, SpanByte, GarnetObjectStoreOutput, long, ObjectStoreFunctions>
        {
            var _input = input.SpanByte;

            output = new();
            var _output = new GarnetObjectStoreOutput { spanByteAndMemory = new(SpanByte.FromPinnedPointer((byte*)Unsafe.AsPointer(ref output), ObjectOutputHeader.Size)) };

            // Perform RMW on object store
            var status = objectStoreContext.RMW(ref key, ref _input, ref _output);

            if (status.IsPending)
                CompletePendingForObjectStoreSession(ref status, ref _output, ref objectStoreContext);

            Debug.Assert(_output.spanByteAndMemory.IsSpanByte);


            if (status.NotFound || (!status.Record.Created && !status.Record.CopyUpdated && !status.Record.InPlaceUpdated))
                return GarnetStatus.NOTFOUND;

            return GarnetStatus.OK;
        }

        /// <summary>
        /// Perform RMW operation in object store 
        /// use this method in commands that return an array
        /// </summary>
        /// <typeparam name="TObjectContext"></typeparam>
        /// <param name="key"></param>
        /// <param name="input"></param>
        /// <param name="objectStoreContext"></param>
        /// <param name="outputFooter"></param>
        /// <returns></returns>
        GarnetStatus RMWObjectStoreOperationWithOutput<TObjectContext>(byte[] key, ArgSlice input, ref TObjectContext objectStoreContext, ref GarnetObjectStoreOutput outputFooter)
            where TObjectContext : ITsavoriteContext<byte[], IGarnetObject, SpanByte, GarnetObjectStoreOutput, long, ObjectStoreFunctions>
        {
            var _input = input.SpanByte;

            // Perform RMW on object store
            var status = objectStoreContext.RMW(ref key, ref _input, ref outputFooter);

            if (status.IsPending)
                CompletePendingForObjectStoreSession(ref status, ref outputFooter, ref objectStoreContext);


Review comment (suggestion):
We should not need CopyUpdated or InPlaceUpdated to be mentioned here; NotFound cannot be true if they are present. Look at RMW_MainStore (AdvancedOps.cs); it is much more straightforward.

           return status.Found || status.Record.Created ? GarnetStatus.OK : GarnetStatus.NOTFOUND;

Code after:

namespace Garnet.server
{
    sealed partial class StorageSession : IDisposable
    {
        #region Common ObjectStore Methods

        unsafe GarnetStatus RMWObjectStoreOperation<TObjectContext>(byte[] key, ArgSlice input, out ObjectOutputHeader output, ref TObjectContext objectStoreContext)
            where TObjectContext : ITsavoriteContext<byte[], IGarnetObject, SpanByte, GarnetObjectStoreOutput, long, ObjectStoreFunctions>
        {
            var _input = input.SpanByte;

            output = new();
            var _output = new GarnetObjectStoreOutput { spanByteAndMemory = new(SpanByte.FromPinnedPointer((byte*)Unsafe.AsPointer(ref output), ObjectOutputHeader.Size)) };

            // Perform RMW on object store
            var status = objectStoreContext.RMW(ref key, ref _input, ref _output);

            if (status.IsPending)
                CompletePendingForObjectStoreSession(ref status, ref _output, ref objectStoreContext);

            Debug.Assert(_output.spanByteAndMemory.IsSpanByte);


            return status.Found || status.Record.Created ? GarnetStatus.OK : GarnetStatus.NOTFOUND;
        }

        /// <summary>
        /// Perform RMW operation in object store 
        /// use this method in commands that return an array
        /// </summary>
        /// <typeparam name="TObjectContext"></typeparam>
        /// <param name="key"></param>
        /// <param name="input"></param>
        /// <param name="objectStoreContext"></param>
        /// <param name="outputFooter"></param>
        /// <returns></returns>
        GarnetStatus RMWObjectStoreOperationWithOutput<TObjectContext>(byte[] key, ArgSlice input, ref TObjectContext objectStoreContext, ref GarnetObjectStoreOutput outputFooter)
            where TObjectContext : ITsavoriteContext<byte[], IGarnetObject, SpanByte, GarnetObjectStoreOutput, long, ObjectStoreFunctions>
        {
            var _input = input.SpanByte;

            // Perform RMW on object store
            var status = objectStoreContext.RMW(ref key, ref _input, ref outputFooter);

            if (status.IsPending)
                CompletePendingForObjectStoreSession(ref status, ref outputFooter, ref objectStoreContext);

            return status.Found || status.Record.Created ? GarnetStatus.OK : GarnetStatus.NOTFOUND;
        }