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); }
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); }