Пример #1
0
    protected override bool SetItem(GameObject obj)
    {
        GameObject    player   = GameObject.FindGameObjectWithTag("Player");
        EquipmentSlot prevSlot = obj.transform.parent.GetComponent <EquipmentSlot>();

        if (prevSlot != null)
        {
            if (prevSlot.Primary)
            {
                player.GetComponent <EquipmentHandler>().SetPrimary(null);
            }
            else
            {
                player.GetComponent <EquipmentHandler>().SetSecondary(null);
            }
            return(true);
        }
        StoreSlot storeSlot = obj.transform.parent.GetComponent <StoreSlot>();

        if (storeSlot != null)
        {
            int value = obj.GetComponent <DragItem>().Item.value;
            if (value <= Inventory.Currency)
            {
                Inventory.ChangeMoneyAmount(-value);
                return(true);
            }
        }
        return(false);
    }
Пример #2
0
        private BoolResult Load(OperationContext context, StoreSlot activeSlot, bool clean = false)
        {
            try
            {
                var storeLocation = GetStoreLocation(activeSlot);

                if (clean && Directory.Exists(storeLocation))
                {
                    BuildXL.Native.IO.FileUtilities.DeleteDirectoryContents(storeLocation, deleteRootDirectory: true);
                }

                Directory.CreateDirectory(storeLocation);

                Tracer.Info(context, $"Creating rocksdb store at '{storeLocation}'.");

                var possibleStore = KeyValueStoreAccessor.Open(storeLocation,
                                                               additionalColumns: new[] { nameof(Columns.ClusterState), nameof(Columns.Metadata) },
                                                               rotateLogs: true,
                                                               failureHandler: failureEvent =>
                {
                    // By default, rethrow is true iff it is a user error. We invalidate only if it isn't
                    failureEvent.Invalidate = !failureEvent.Rethrow;
                },
                                                               invalidationHandler: failure => OnDatabaseInvalidated(context, failure),
                                                               onFailureDeleteExistingStoreAndRetry: _configuration.OnFailureDeleteExistingStoreAndRetry,
                                                               onStoreReset: failure => {
                    Tracer.Error(context, $"RocksDb critical error caused store to reset: {failure.DescribeIncludingInnerFailures()}");
                });

                if (possibleStore.Succeeded)
                {
                    var oldKeyValueStore = _keyValueStore;
                    var store            = possibleStore.Result;

                    if (oldKeyValueStore == null)
                    {
                        _keyValueStore = new KeyValueStoreGuard(store);
                    }
                    else
                    {
                        // Just replace the inner accessor
                        oldKeyValueStore.Replace(store);
                    }

                    _activeSlot    = activeSlot;
                    _storeLocation = storeLocation;
                }

                return(possibleStore.Succeeded ? BoolResult.Success : new BoolResult($"Failed to initialize a RocksDb store at {_storeLocation}:", possibleStore.Failure.DescribeIncludingInnerFailures()));
            }
            catch (Exception ex) when(ex.IsRecoverableIoException())
            {
                return(new BoolResult(ex));
            }
        }
        /// <summary>
        /// Checks if an instruction is a store and returns the slot.
        /// </summary>
        /// <param name="ins">The instruction</param>
        /// <returns>If the instruction is a store returns the slot to store. Check slot.IsNone() to see if this instruction is a store.</returns>
        private StoreSlot GetStoreSlot(Instruction ins)
        {
            switch (ins.OpCode.Code)
            {
            case Code.Stloc_0:
            case Code.Stloc_1:
            case Code.Stloc_2:
            case Code.Stloc_3:
                return(new StoreSlot(StoreType.Local, ins.OpCode.Code - Code.Stloc_0));

            case Code.Stloc_S:
            case Code.Stloc:
                return(new StoreSlot(StoreType.Local, ((VariableDefinition)ins.Operand).Index));

            case Code.Stfld:
                //TODO: we do not check what instance is on the stack
                return(new StoreSlot(StoreType.Field, ((FieldReference)ins.Operand).MetadataToken.ToInt32()));

            case Code.Stsfld:
                return(new StoreSlot(StoreType.StaticField, ((FieldReference)ins.Operand).MetadataToken.ToInt32()));

            case Code.Starg_S:             //store arg (not ref / out etc)
            case Code.Starg: {
                int sequence = ((ParameterDefinition)ins.Operand).Index + 1;
                if (!this.Method.HasThis)
                {
                    sequence--;
                }
                return(new StoreSlot(StoreType.Argument, sequence));
            }

            case Code.Stind_I:
            case Code.Stind_I1:
            case Code.Stind_I2:
            case Code.Stind_I4:
            case Code.Stind_I8:
            case Code.Stind_R4:
            case Code.Stind_R8:
            case Code.Stind_Ref:
                //TODO: improve stack check
                while (ins.Previous != null)                   //quick fix for out parameters.
                {
                    ins = ins.Previous;
                    StoreSlot last = GetLoadSlot(ins);
                    if (last.Type == StoreType.Argument)
                    {
                        return(new StoreSlot(StoreType.Out, last.Slot));
                    }
                }
                goto default;

            default:
                return(new StoreSlot(StoreType.None, -1));
            }
        }
Пример #4
0
        private BoolResult InitialLoad(OperationContext context, StoreSlot activeSlot)
        {
            var clean  = _configuration.CleanOnInitialize;
            var result = Load(context, activeSlot, clean);

            if (!clean && !result.Succeeded)
            {
                context.TracingContext.Warning($"Failed to load database without cleaning. Retrying with clean=true. Failure: {result}");

                // If failed when cleaning is disabled, try again with forcing a clean
                return(Load(context, activeSlot, clean: true));
            }

            return(result);
        }
Пример #5
0
    // Set the default items from the start of the game in the store
    private void SetDefaultItems()
    {
        // Order list by itemcategory and after order by buyingcost
        m_StartObjects = m_StartObjects.OrderBy(item => item.ItemCategory).ThenBy(item => item.BuyingCost).ToList();

        foreach (ObjectData objectData in m_StartObjects)
        {
            // Spawn new itemPrefab
            GameObject itemPrefab = Instantiate(m_StoreItemPrefab);
            itemPrefab.transform.SetParent(m_StoreItemsParent, false); // false so it scales locally

            StoreSlot item = itemPrefab.GetComponent <StoreSlot>();
            item.ObjectData = objectData;
            item.SetAmount(objectData.DefaultStoreAmount);
            item.SetImage(objectData.Icon);

            m_StoreItemList.Add(item);
        }
    }
Пример #6
0
        private BoolResult Load(OperationContext context, StoreSlot activeSlot, bool clean = false)
        {
            try
            {
                var storeLocation = GetStoreLocation(activeSlot);

                if (clean && Directory.Exists(storeLocation))
                {
                    BuildXL.Native.IO.FileUtilities.DeleteDirectoryContents(storeLocation, deleteRootDirectory: true);
                }

                Directory.CreateDirectory(storeLocation);

                Tracer.Info(context, $"Creating rocksdb store at '{storeLocation}'.");

                var possibleStore = KeyValueStoreAccessor.Open(storeLocation,
                                                               additionalColumns: new[] { nameof(ClusterState) });
                if (possibleStore.Succeeded)
                {
                    var oldKeyValueStore = _keyValueStore;
                    var store            = possibleStore.Result;

                    if (oldKeyValueStore == null)
                    {
                        _keyValueStore = new KeyValueStoreGuard(store);
                    }
                    else
                    {
                        // Just replace the inner accessor
                        oldKeyValueStore.Replace(store);
                    }

                    _activeSlot    = activeSlot;
                    _storeLocation = storeLocation;
                }

                return(possibleStore.Succeeded ? BoolResult.Success : new BoolResult($"Failed to initialize a RocksDb store at {_storeLocation}:", possibleStore.Failure.DescribeIncludingInnerFailures()));
            }
            catch (Exception ex) when(ex.IsRecoverableIoException())
            {
                return(new BoolResult(ex));
            }
        }
Пример #7
0
    public void Setting(List <Item> ItemList, GameObject countPop)
    {
        StoreSlotList = new List <StoreSlot>();

        for (int i = 0; i < ItemList.Count; i++)
        {
            // storeslot을 생성하고,
            GameObject storeSlotObj = Instantiate(StoreSlotObject, Vector3.zero, Quaternion.identity) as GameObject;
            storeSlotObj.transform.SetParent(StoreContentsPanel.transform);

            // 데이터 셋팅
            StoreSlot storeSlot = storeSlotObj.GetComponent <StoreSlot>();
            storeSlot.StoreSlotSetting(ItemList[i]);
            storeSlot.CountPopup = countPop;

            // storeslotlist에추가
            StoreSlotList.Add(storeSlot);
        }
    }
Пример #8
0
        private BoolResult InitialLoad(OperationContext context, StoreSlot activeSlot)
        {
            var clean = _configuration.CleanOnInitialize;

            // We backup the logs right before loading the first DB we load
            var storeLocation = GetStoreLocation(activeSlot);

            var result = Load(context, activeSlot, clean);

            bool reload = false;

            if (!clean)
            {
                if (result.Succeeded)
                {
                    if (IsStoredEpochInvalid(out var epoch))
                    {
                        Counters[ContentLocationDatabaseCounters.EpochMismatches].Increment();
                        Tracer.Debug(context, $"Stored epoch '{epoch}' does not match configured epoch '{_configuration.Epoch}'. Retrying with clean=true.");
                        reload = true;
                    }
                    else
                    {
                        Counters[ContentLocationDatabaseCounters.EpochMatches].Increment();
                    }
                }

                if (!result.Succeeded)
                {
                    Tracer.Warning(context, $"Failed to load database without cleaning. Retrying with clean=true. Failure: {result}");
                    reload = true;
                }
            }

            if (reload)
            {
                // If failed when cleaning is disabled, try again with forcing a clean
                return(Load(context, GetNextSlot(activeSlot), clean: true));
            }

            return(result);
        }
Пример #9
0
        private BoolResult InitialLoad(OperationContext context, StoreSlot activeSlot)
        {
            var clean = _configuration.CleanOnInitialize;

            // We backup the logs right before loading the first DB we load
            var storeLocation = GetStoreLocation(activeSlot);

            BackupLogs(context, storeLocation, name: $"InitialLoad{activeSlot}");

            var result = Load(context, activeSlot, clean);

            if (!clean && !result.Succeeded)
            {
                context.TracingContext.Warning($"Failed to load database without cleaning. Retrying with clean=true. Failure: {result}");

                // If failed when cleaning is disabled, try again with forcing a clean
                return(Load(context, activeSlot, clean: true));
            }

            return(result);
        }
Пример #10
0
 public void BuyItem(StoreSlot item)
 {
     if (!PlayerCanAfford(item.ObjectData.BuyingCost))
     {
         m_MoneyBar.CantAffordBlink();
     }
     else
     {
         if (item.SlotAmount > 1)
         {
             item.DecreaseAmount(1);
             Inventory.Instance.AddItem(item.ObjectData, 1);
             m_MoneyBar.LoseMoney(item.ObjectData);
         }
         else
         {
             Inventory.Instance.AddItem(item.ObjectData, 1);
             m_MoneyBar.LoseMoney(item.ObjectData);
             RemoveSlot(item);
         }
     }
 }
        /// <summary>
        /// Iterates over all Instructions inside UsedBy and spawns a new alternative if necessary.
        /// </summary>
        /// <param name="start">The first index to progress.</param>
        private void CheckUsedBy(int start)
        {
            for (int ii = start; ii < UsedBy.Count; ii++)
            {
                InstructionWithLeave use = UsedBy [ii].Key;

                StoreSlot slot = GetStoreSlot(use.Instruction); //check if this is a store instruction

                bool removeFromUseBy = false;                   //ignore the use

                if (use.Instruction.OpCode.Code == Code.Castclass)
                {
                    removeFromUseBy = true;
                    AlternativePaths.AddIfNew(new KeyValuePair <InstructionWithLeave, int> (use.Copy(use.Instruction.Next), 0));
                }
                else if (use.Instruction.OpCode.Code == Code.Pop)                    //pop is not a valid usage
                {
                    removeFromUseBy = true;
                }
                else if (!slot.IsNone)
                {
                    if (slot.Type == StoreType.Argument || slot.Type == StoreType.Local)
                    {
                        removeFromUseBy = true;                                             //temporary save
                    }
                    foreach (var ld in this.FindLoad(use.Copy(use.Instruction.Next), slot)) //start searching at the next instruction
                    {
                        AlternativePaths.AddIfNew(new KeyValuePair <InstructionWithLeave, int> (ld.Copy(ld.Instruction.Next), 0));
                    }
                }
                if (removeFromUseBy)
                {
                    UsedBy.RemoveAt(ii);
                    ii--;
                }
            }
        }
Пример #12
0
        private BoolResult Load(OperationContext context, StoreSlot activeSlot, bool clean)
        {
            try
            {
                var storeLocation = GetStoreLocation(activeSlot);

                if (Directory.Exists(storeLocation))
                {
                    // We backup right before loading. This means we should never loose any logs, but it also means
                    // the backup directory will only hold logs for DBs that have already been overwritten.
                    if (_logManager != null)
                    {
                        _logManager.BackupAsync(context, new AbsolutePath(storeLocation), activeSlot.ToString()).Result.IgnoreFailure();
                        Task.Run(() => _logManager.GarbageCollect(context)).FireAndForget(context, severityOnException: Severity.Error);
                    }

                    if (clean)
                    {
                        FileUtilities.DeleteDirectoryContents(storeLocation, deleteRootDirectory: true);
                    }
                }

                Directory.CreateDirectory(storeLocation);

                Tracer.Info(context, $"Creating RocksDb store at '{storeLocation}'.");

                var possibleStore = KeyValueStoreAccessor.Open(
                    new KeyValueStoreAccessor.RocksDbStoreArguments()
                {
                    StoreDirectory    = storeLocation,
                    AdditionalColumns = new[] { nameof(Columns.ClusterState), nameof(Columns.Metadata) },
                    RotateLogs        = true,
                    EnableStatistics  = true,
                    FastOpen          = true,
                },
                    // When an exception is caught from within methods using the database, this handler is called to
                    // decide whether the exception should be rethrown in user code, and the database invalidated. Our
                    // policy is to only invalidate if it is an exception coming from RocksDb, but not from our code.
                    failureHandler: failureEvent =>
                {
                    // By default, rethrow is true iff it is a user error. We invalidate only if it isn't
                    failureEvent.Invalidate = !failureEvent.Rethrow;
                },
                    // The database may be invalidated for a number of reasons, all related to latent bugs in our code.
                    // For example, exceptions thrown from methods that are operating on the DB. If that happens, we
                    // call a user-defined handler. This is because the instance is invalid after this happens.
                    invalidationHandler: failure => OnDatabaseInvalidated(context, failure),
                    // It is possible we may fail to open an already existing database. This can happen (most commonly)
                    // due to corruption, among others. If this happens, then we want to recreate it from empty. This
                    // only helps for the memoization store.
                    onFailureDeleteExistingStoreAndRetry: _configuration.OnFailureDeleteExistingStoreAndRetry,
                    // If the previous flag is true, and it does happen that we invalidate the database, we want to log
                    // it explicitly.
                    onStoreReset: failure =>
                {
                    Tracer.Error(context, $"RocksDb critical error caused store to reset: {failure.DescribeIncludingInnerFailures()}");
                });

                if (possibleStore.Succeeded)
                {
                    var oldKeyValueStore = _keyValueStore;
                    var store            = possibleStore.Result;

                    if (oldKeyValueStore == null)
                    {
                        _keyValueStore = new KeyValueStoreGuard(store);
                    }
                    else
                    {
                        // Just replace the inner accessor
                        oldKeyValueStore.Replace(store);
                    }

                    _activeSlot    = activeSlot;
                    _storeLocation = storeLocation;
                }

                return(possibleStore.Succeeded ? BoolResult.Success : new BoolResult($"Failed to initialize a RocksDb store at {_storeLocation}:", possibleStore.Failure.DescribeIncludingInnerFailures()));
            }
            catch (Exception ex) when(ex.IsRecoverableIoException())
            {
                return(new BoolResult(ex));
            }
        }
Пример #13
0
 private string GetStoreLocation(StoreSlot slot)
 {
     return((_configuration.StoreLocation / slot.ToString()).ToString());
 }
Пример #14
0
        private BoolResult Load(OperationContext context, StoreSlot activeSlot, bool clean)
        {
            try
            {
                var storeLocation = GetStoreLocation(activeSlot);

                if (Directory.Exists(storeLocation))
                {
                    if (clean)
                    {
                        FileUtilities.DeleteDirectoryContents(storeLocation, deleteRootDirectory: true);
                    }
                }

                Directory.CreateDirectory(storeLocation);

                Tracer.Info(context, $"Creating RocksDb store at '{storeLocation}'.");

                var possibleStore = KeyValueStoreAccessor.Open(
                    new KeyValueStoreAccessor.RocksDbStoreArguments()
                {
                    StoreDirectory             = storeLocation,
                    AdditionalColumns          = new[] { nameof(Columns.ClusterState), nameof(Columns.Metadata) },
                    RotateLogsMaxFileSizeBytes = _configuration.LogsKeepLongTerm ? 0ul : ((ulong)"1MB".ToSize()),
                    RotateLogsNumFiles         = _configuration.LogsKeepLongTerm ? 60ul : 1,
                    RotateLogsMaxAge           = TimeSpan.FromHours(_configuration.LogsKeepLongTerm ? 12 : 1),
                    EnableStatistics           = true,
                    FastOpen = true,
                },
                    // When an exception is caught from within methods using the database, this handler is called to
                    // decide whether the exception should be rethrown in user code, and the database invalidated. Our
                    // policy is to only invalidate if it is an exception coming from RocksDb, but not from our code.
                    failureHandler: failureEvent =>
                {
                    // By default, rethrow is true iff it is a user error. We invalidate only if it isn't
                    failureEvent.Invalidate = !failureEvent.Rethrow;
                },
                    // The database may be invalidated for a number of reasons, all related to latent bugs in our code.
                    // For example, exceptions thrown from methods that are operating on the DB. If that happens, we
                    // call a user-defined handler. This is because the instance is invalid after this happens.
                    invalidationHandler: failure => OnDatabaseInvalidated(context, failure),
                    // It is possible we may fail to open an already existing database. This can happen (most commonly)
                    // due to corruption, among others. If this happens, then we want to recreate it from empty. This
                    // only helps for the memoization store.
                    onFailureDeleteExistingStoreAndRetry: _configuration.OnFailureDeleteExistingStoreAndRetry,
                    // If the previous flag is true, and it does happen that we invalidate the database, we want to log
                    // it explicitly.
                    onStoreReset: failure =>
                {
                    Tracer.Error(context, $"RocksDb critical error caused store to reset: {failure.DescribeIncludingInnerFailures()}");
                });

                if (possibleStore.Succeeded)
                {
                    var oldKeyValueStore = _keyValueStore;
                    var store            = possibleStore.Result;

                    if (oldKeyValueStore == null)
                    {
                        _keyValueStore = new KeyValueStoreGuard(store);
                    }
                    else
                    {
                        // Just replace the inner accessor
                        oldKeyValueStore.Replace(store);
                    }

                    _activeSlot    = activeSlot;
                    _storeLocation = storeLocation;
                }

                return(possibleStore.Succeeded ? BoolResult.Success : new BoolResult($"Failed to initialize a RocksDb store at {_storeLocation}:", possibleStore.Failure.DescribeIncludingInnerFailures()));
            }
            catch (Exception ex) when(ex.IsRecoverableIoException())
            {
                return(new BoolResult(ex));
            }
        }
Пример #15
0
 private StoreSlot GetNextSlot(StoreSlot slot)
 {
     return(slot == StoreSlot.Slot1 ? StoreSlot.Slot2 : StoreSlot.Slot1);
 }
        /// <summary>
        /// Follows the codeflow starting at a given instruction and finds all loads for a given slot.
        /// Continues and follows all branches until the slot is overwritten or the method returns / throws.
        /// </summary>
        /// <param name="insWithLeave">The first instruction to start the search at.</param>
        /// <param name="slot">The slot to search.</param>
        /// <returns>An array of instructions that load from the slot.</returns>
        private List <InstructionWithLeave> FindLoad(InstructionWithLeave insWithLeave, StoreSlot slot)
        {
            LoadAlternatives.Clear();
            LoadResults.Clear();

            LoadAlternatives.Add(insWithLeave);


            for (int i = 0; i < LoadAlternatives.Count; i++)         //loop over all branches, more will get added inside the loop
            {
                insWithLeave = LoadAlternatives [i];                 //the first instruction of the block (contains the leave stack)

                Instruction ins = insWithLeave.Instruction;          //the current instruction
                while (ins != null)
                {
                    if (GetStoreSlot(ins) == slot)                      //check if the slot gets overwritten
                    {
                        break;
                    }

                    if (slot == GetLoadSlot(ins))
                    {
                        LoadResults.AddIfNew(insWithLeave.Copy(ins));                           //continue, might be loaded again
                    }
                    //we simply branch to every possible catch block.
                    IList <ExceptionHandler> ehc = null;
                    if (Body.HasExceptionHandlers)
                    {
                        ehc = Body.ExceptionHandlers;
                        foreach (ExceptionHandler handler in ehc)
                        {
                            if (handler.HandlerType != ExceptionHandlerType.Catch)
                            {
                                continue;
                            }
                            if (ins.Offset < handler.TryStart.Offset || ins.Offset >= handler.TryEnd.Offset)
                            {
                                continue;
                            }
                            LoadAlternatives.AddIfNew(insWithLeave.Copy(handler.HandlerStart));
                        }
                    }

                    //Code.Leave leaves a try/catch block. Search for the finally block.
                    if (ins.OpCode.Code == Code.Leave || ins.OpCode.Code == Code.Leave_S)
                    {
                        bool handlerFound = false;
                        if (ehc != null)
                        {
                            foreach (ExceptionHandler handler in ehc)
                            {
                                if (handler.HandlerType != ExceptionHandlerType.Finally)
                                {
                                    continue;
                                }
                                if (handler.TryStart.Offset > ins.Offset || handler.TryEnd.Offset <= ins.Offset)
                                {
                                    continue;
                                }
                                LoadAlternatives.AddIfNew(insWithLeave.Push(handler.HandlerStart, ins));                                   //push the leave instruction onto the leave stack
                                handlerFound = true;
                                break;
                            }
                        }
                        if (!handlerFound)                         //no finally found (try/catch without finally)
                        {
                            LoadAlternatives.AddIfNew(insWithLeave.Copy((Instruction)ins.Operand));
                        }
                        break;
                    }

                    if (ins.OpCode.Code == Code.Endfinally)                       //pop the last leave instruction and branch to it
                    {
                        LoadAlternatives.AddIfNew(insWithLeave.Pop());
                        break;
                    }

                    //fetch the next instruction (s)
                    object alternativeNext;
                    ins = GetNextInstruction(ins, out alternativeNext);
                    if (ins == null)
                    {
                        break;
                    }

                    if (alternativeNext != null)
                    {
                        Instruction oneTarget = alternativeNext as Instruction;
                        if (oneTarget != null)                           //normal branch
                        {
                            LoadAlternatives.AddIfNew(insWithLeave.Copy(oneTarget));
                        }
                        else                             //switch statement
                        {
                            foreach (Instruction switchTarget in (Instruction [])alternativeNext)
                            {
                                LoadAlternatives.AddIfNew(insWithLeave.Copy(switchTarget));
                            }
                        }
                    }

                    if (ins.OpCode.FlowControl == FlowControl.Branch || ins.OpCode.FlowControl == FlowControl.Cond_Branch)
                    {
                        if (ins.OpCode.Code != Code.Leave && ins.OpCode.Code != Code.Leave_S)
                        {
                            LoadAlternatives.AddIfNew(insWithLeave.Copy(ins));                               //add if new, avoid infinity loop
                            break;
                        }
                    }
                }
            }
            return(LoadResults);
        }
Пример #17
0
        private BoolResult Load(OperationContext context, StoreSlot activeSlot, bool clean)
        {
            try
            {
                var storeLocation = GetStoreLocation(activeSlot);

                if (clean)
                {
                    Counters[ContentLocationDatabaseCounters.DatabaseCleans].Increment();

                    if (Directory.Exists(storeLocation))
                    {
                        FileUtilities.DeleteDirectoryContents(storeLocation, deleteRootDirectory: true);
                    }
                }

                bool dbAlreadyExists = Directory.Exists(storeLocation);
                Directory.CreateDirectory(storeLocation);

                Tracer.Info(context, $"Creating RocksDb store at '{storeLocation}'. Clean={clean}, Configured Epoch='{_configuration.Epoch}'");

                var possibleStore = KeyValueStoreAccessor.Open(
                    new RocksDbStoreConfiguration(storeLocation)
                {
                    AdditionalColumns          = ColumnNames,
                    RotateLogsMaxFileSizeBytes = _configuration.LogsKeepLongTerm ? 0ul : ((ulong)"1MB".ToSize()),
                    RotateLogsNumFiles         = _configuration.LogsKeepLongTerm ? 60ul : 1,
                    RotateLogsMaxAge           = TimeSpan.FromHours(_configuration.LogsKeepLongTerm ? 12 : 1),
                    EnableStatistics           = true,
                    FastOpen = true,
                    // We take the user's word here. This may be completely wrong, but we don't have enough
                    // information at this point to take a decision here. If a machine is master and demoted to
                    // worker, EventHub may continue to process events for a little while. If we set this to
                    // read-only during that checkpoint, those last few events will fail with RocksDbException.
                    // NOTE: we need to check that the database exists because RocksDb will refuse to open an empty
                    // read-only instance.
                    ReadOnly = _configuration.OpenReadOnly && dbAlreadyExists,
                    // The RocksDb database here is read-only from the perspective of the default column family,
                    // but read/write from the perspective of the ClusterState (which is rewritten on every
                    // heartbeat). This means that the database may perform background compactions on the column
                    // families, possibly triggering a RocksDb corruption "block checksum mismatch" error.
                    // Since the writes to ClusterState are relatively few, we can make-do with disabling
                    // compaction here and pretending like we are using a read-only database.
                    DisableAutomaticCompactions = !IsDatabaseWriteable,
                    LeveledCompactionDynamicLevelTargetSizes = true,
                    Compression = _configuration.Compression,
                    UseReadOptionsWithSetTotalOrderSeekInDbEnumeration     = _configuration.UseReadOptionsWithSetTotalOrderSeekInDbEnumeration,
                    UseReadOptionsWithSetTotalOrderSeekInGarbageCollection = _configuration.UseReadOptionsWithSetTotalOrderSeekInGarbageCollection,
                },
                    // When an exception is caught from within methods using the database, this handler is called to
                    // decide whether the exception should be rethrown in user code, and the database invalidated. Our
                    // policy is to only invalidate if it is an exception coming from RocksDb, but not from our code.
                    failureHandler: failureEvent =>
                {
                    // By default, rethrow is true iff it is a user error. We invalidate only if it isn't
                    failureEvent.Invalidate = !failureEvent.Rethrow;
                },
                    // The database may be invalidated for a number of reasons, all related to latent bugs in our code.
                    // For example, exceptions thrown from methods that are operating on the DB. If that happens, we
                    // call a user-defined handler. This is because the instance is invalid after this happens.
                    invalidationHandler: failure => OnDatabaseInvalidated(context, failure),
                    // It is possible we may fail to open an already existing database. This can happen (most commonly)
                    // due to corruption, among others. If this happens, then we want to recreate it from empty. This
                    // only helps for the memoization store.
                    onFailureDeleteExistingStoreAndRetry: _configuration.OnFailureDeleteExistingStoreAndRetry,
                    // If the previous flag is true, and it does happen that we invalidate the database, we want to log
                    // it explicitly.
                    onStoreReset: failure =>
                {
                    Tracer.Error(context, $"RocksDb critical error caused store to reset: {failure.DescribeIncludingInnerFailures()}");
                });

                if (possibleStore.Succeeded)
                {
                    var oldKeyValueStore = _keyValueStore;
                    var store            = possibleStore.Result;

                    if (oldKeyValueStore == null)
                    {
                        _keyValueStore = new KeyValueStoreGuard(store);
                        _keyValueStore.UseExclusive((db, state) =>
                        {
                            if (db.TryGetValue(nameof(GlobalKeys.ActiveColummGroup), out var activeColumnGroup))
                            {
                                _activeColumnsGroup = (ColumnGroup)Enum.Parse(typeof(ColumnGroup), activeColumnGroup);
                            }
                            else
                            {
                                _activeColumnsGroup = ColumnGroup.One;
                            }

                            return(true);
                        },
                                                    this).ThrowOnError();
                    }
                    else
                    {
                        // Just replace the inner accessor
                        oldKeyValueStore.Replace(store, db =>
                        {
                            if (db.TryGetValue(nameof(GlobalKeys.ActiveColummGroup), out var activeColumnGroup))
                            {
                                _activeColumnsGroup = (ColumnGroup)Enum.Parse(typeof(ColumnGroup), activeColumnGroup);
                            }
                            else
                            {
                                _activeColumnsGroup = ColumnGroup.One;
                            }
                        }).ThrowOnError();
                    }

                    _activeSlot    = activeSlot;
                    _storeLocation = storeLocation;
                }

                return(possibleStore.Succeeded ? BoolResult.Success : new BoolResult($"Failed to initialize a RocksDb store at {_storeLocation}:", possibleStore.Failure.DescribeIncludingInnerFailures()));
            }
            catch (Exception ex) when(ex.IsRecoverableIoException())
            {
                return(new BoolResult(ex));
            }
        }
Пример #18
0
 public static bool Has(StoreSlot storeSlot)
 {
     return(_instance.unlocks.Contains(storeSlot));
 }
Пример #19
0
 public static void Unlock(StoreSlot unlock)
 {
     _instance.unlocks.Add(unlock);
 }