Esempio n. 1
0
    public async Task <GdidBlock> AllocateBlockAsync(string scopeName, string sequenceName, int blockSize, ulong?vicinity = 1152921504606846975)
    {
        var result = await ComponentDirector.CallServiceAsync(ESConsts.SVC_PATH_GDID, ++m_Shard,
                                                              async (client) =>
        {
            var json  = await client.PostAndGetJsonMapAsync("", new { scopeName, sequenceName, blockSize, vicinity });
            var block = new GdidBlock();
            JsonReader.ToDoc(block, json);
            return(block);
        }
                                                              );

        return(result);
    }
Esempio n. 2
0
        private GdidBlock allocate(byte authority, string scopeName, string sequenceName, int blockSize, ulong?vicinity)
        {
            var scopeKey = "{0}://{1}".Args(AuthorityPathSeg(authority), scopeName);

            var scope = m_Scopes.GetOrRegister(scopeKey, (key) => new scope {
                Name = key
            }, scopeKey);

            var sequence = scope.Sequences.GetOrRegister(sequenceName, (_) => new sequence {
                Name = sequenceName, New = true
            }, 0);                                                                                                     //with NEW=TRUE

            var result = new GdidBlock()
            {
                ScopeName     = scopeName,
                SequenceName  = sequenceName,
                Authority     = authority,
                AuthorityHost = App.GetThisHostName(),
                BlockSize     = blockSize,
                ServerUTCTime = App.TimeSource.UTCNow
            };

            lock (scope)
            {
                //0. If just allocated then need to read from disk
                if (sequence.New)
                {
                    sequence.New = false;
                    var id = ReadFromLocations(authority, scopeName, sequenceName);
                    sequence.Era   = id.Era;
                    sequence.Value = id.Value;
                }

                //1. make a local copy of vars, that may mutate but don't get committed until written to disk
                var era   = sequence.Era;
                var value = sequence.Value;

                //1.1 make sure that GDID.Zero is never returned
                if (authority == 0 && era == 0 && value == 0)
                {
                    value = 1;                                          //Don't start value from Zero in ERA=0 and Authority=0
                }
                if (value >= GDID.COUNTER_MAX - (ulong)(blockSize + 1)) //its time to update ERA (+1 for safeguard/edge case)
                {
                    if (era == uint.MaxValue - 4)                       //ALERT, with some room
                    {
                        WriteLog(MessageType.CriticalAlert, "allocate()", StringConsts.GDIDAUTH_ERA_EXHAUSTED_ALERT.Args(scopeName, sequenceName));
                    }
                    if (era == uint.MaxValue) //hard stop
                    {
                        var txt = StringConsts.GDIDAUTH_ERA_EXHAUSTED_ERROR.Args(scopeName, sequenceName);
                        WriteLog(MessageType.CatastrophicError, "allocate()", txt);
                        throw new GdidException(txt);
                    }

                    era++;
                    value = 0;
                    Instrumentation.AuthEraPromotedEvent.Happened(App.Instrumentation, scopeName, sequenceName);
                    WriteLog(MessageType.Warning, "allocate()", StringConsts.GDIDAUTH_ERA_PROMOTED_WARNING.Args(scopeName, sequenceName, era));
                }

                result.Era = era;
                result.StartCounterInclusive = value;

                value = value + (ulong)blockSize;

                //2. Try to write to disk, if it fails we could not allocate anything and will bail out with exception
                WriteToLocations(authority, scopeName, sequenceName, new _id(era, value));

                //3. only after write to disk succeeds do we commit the changes back into the sequence instance
                sequence.Era   = era;
                sequence.Value = value;
            }

            return(result);
        }