public Task<bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            if (logger.IsVerbose) logger.Verbose("InsertRow entry = {0}, table version = {1}", entry.ToFullString(), tableVersion);
            bool result = table.Insert(entry, tableVersion);
            if (result == false)
                logger.Info(ErrorCode.MembershipGrainBasedTable2, 
                    "Insert of {0} and table version {1} failed. Table now is {2}",
                    entry.ToFullString(), tableVersion, table.ReadAll());

            return Task.FromResult(result);
        }
        public Task<bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            if (logger.IsVerbose) logger.Verbose("UpdateRow entry = {0}, etag = {1}, table version = {2}", entry.ToFullString(), etag, tableVersion);
            bool result = table.Update(entry, etag, tableVersion);
            if (result == false)
                logger.Info(ErrorCode.MembershipGrainBasedTable3,
                    "Update of {0}, eTag {1}, table version {2} failed. Table now is {3}",
                    entry.ToFullString(), etag, tableVersion, table.ReadAll());

            return Task.FromResult(result);
        }
 public bool Update(MembershipEntry entry, string etag, TableVersion version)
 {
     Tuple<MembershipEntry, string> data;
     siloTable.TryGetValue(entry.SiloAddress, out data);
     if (data == null) return false;
     if (!data.Item2.Equals(etag) || !tableVersion.VersionEtag.Equals(version.VersionEtag)) return false;
     
     siloTable[entry.SiloAddress] = new Tuple<MembershipEntry, string>(
         entry, lastETagCounter++.ToString(CultureInfo.InvariantCulture));
     tableVersion = new TableVersion(version.Version, NewETag());
     return true;
 }
        public async Task<bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                if (logger.IsVerbose) logger.Verbose("InsertRow entry = {0}, table version = {1}", entry.ToFullString(), tableVersion);
                var tableEntry = Convert(entry, tableManager.DeploymentId);
                var versionEntry = tableManager.CreateTableVersionEntry(tableVersion.Version);

                bool result = await tableManager.InsertSiloEntryConditionally(
                    tableEntry, versionEntry, tableVersion.VersionEtag);

                if (result == false)
                    logger.Warn(ErrorCode.AzureTable_22, String.Format("Insert failed due to contention on the table. Will retry. Entry {0}, table version = {1}", entry.ToFullString(), tableVersion));
                return result;
            }
            catch (Exception exc)
            {
                logger.Warn(ErrorCode.AzureTable_23, String.Format("Intermediate error inserting entry {0} tableVersion {1} to the table {2}.",
                    entry.ToFullString(), (tableVersion == null ? "null" : tableVersion.ToString()), tableManager.TableName), exc);
                throw;
            }
        }
        private async Task <bool> DeclareDead(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            if (this.clusterMembershipOptions.LivenessEnabled)
            {
                entry = entry.Copy();

                // add the killer (myself) to the suspect list, for easier diagnosis later on.
                entry.AddSuspector(myAddress, DateTime.UtcNow);

                if (log.IsEnabled(LogLevel.Debug))
                {
                    log.Debug("-Going to DeclareDead silo {0} in the table. About to write entry {1}.", entry.SiloAddress, entry.ToFullString());
                }
                entry.Status = SiloStatus.Dead;
                bool ok = await membershipTableProvider.UpdateRow(entry, etag, tableVersion.Next());

                if (ok)
                {
                    if (log.IsEnabled(LogLevel.Debug))
                    {
                        log.Debug("-Successfully updated {0} status to Dead in the Membership table.", entry.SiloAddress);
                    }

                    var table = await membershipTableProvider.ReadAll();

                    this.ProcessTableUpdate(table, "DeclareDead");
                    GossipToOthers(entry.SiloAddress, entry.Status).Ignore();
                    return(true);
                }

                log.Info(ErrorCode.MembershipMarkDeadWriteFailed, "-Failed to update {0} status to Dead in the Membership table, due to write conflicts. Will retry.", entry.SiloAddress);
                return(false);
            }

            log.Info(ErrorCode.MembershipCantWriteLivenessDisabled, "-Want to mark silo {0} as DEAD, but will ignore because Liveness is Disabled.", entry.SiloAddress);
            return(true);
        }
 private MembershipTableData Convert(List <Tuple <SiloInstanceTableEntry, string> > entries)
 {
     try
     {
         var          memEntries   = new List <Tuple <MembershipEntry, string> >();
         TableVersion tableVersion = null;
         foreach (var tuple in entries)
         {
             var tableEntry = tuple.Item1;
             if (tableEntry.RowKey.Equals(SiloInstanceTableEntry.TABLE_VERSION_ROW))
             {
                 tableVersion = new TableVersion(Int32.Parse(tableEntry.MembershipVersion), tuple.Item2);
             }
             else
             {
                 try
                 {
                     MembershipEntry membershipEntry = Parse(tableEntry);
                     memEntries.Add(new Tuple <MembershipEntry, string>(membershipEntry, tuple.Item2));
                 }
                 catch (Exception exc)
                 {
                     logger.Error((int)TableStorageErrorCode.AzureTable_61,
                                  $"Intermediate error parsing SiloInstanceTableEntry to MembershipTableData: {tableEntry}. Ignoring this entry.", exc);
                 }
             }
         }
         var data = new MembershipTableData(memEntries, tableVersion);
         return(data);
     }
     catch (Exception exc)
     {
         logger.Error((int)TableStorageErrorCode.AzureTable_60,
                      $"Intermediate error parsing SiloInstanceTableEntry to MembershipTableData: {Utils.EnumerableToString(entries, tuple => tuple.Item1.ToString())}.", exc);
         throw;
     }
 }
Exemple #7
0
        public override object Execute(ParameterList parameters, FunctionContextContainer context)
        {
            SitemapScope SitemapScope;
            Expression   filter;

            if (parameters.TryGetParameter <SitemapScope>("SitemapScope", out SitemapScope) == false)
            {
                SitemapScope = SitemapScope.Current;
            }

            switch (SitemapScope)
            {
            case SitemapScope.Current:
                Guid currentPageId = PageRenderer.CurrentPageId;
                filter = Expression.Equal(_foreignKeyPropertyExpression, Expression.Constant(currentPageId));
                break;

            case SitemapScope.All:
                filter = Expression.Constant(true);
                break;

            default:
                Guid pageId = PageRenderer.CurrentPageId;

                IEnumerable <Guid> pageIds = new FilterWrapper(
                    pageId,
                    SitemapScope, TableVersion.Get(typeof(IPageStructure)),
                    PageStructureInfo.GetAssociatedPageIds(pageId, SitemapScope));

                Expression <Func <Guid, bool> > containsExpression = f => pageIds.Contains(f);
                filter = Expression.Invoke(containsExpression, _foreignKeyPropertyExpression);
                break;
            }

            return(Expression.Lambda <Func <T, bool> >(filter, new ParameterExpression[] { _parameterExpression }));
        }
        public async Task <bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            try
            {
                var siloInstance   = entry.AsSiloInstance(_clusterId);
                var clusterVersion = tableVersion.AsClusterVersion(_clusterId);

                var batch = _mapper.CreateBatch().WithOptions(x => x.SetConsistencyLevel(DefaultConsistencyLevel));
                batch.Update(siloInstance);
                batch.Update(clusterVersion);

                await _mapper.ExecuteAsync(batch);

                return(true);
            }
            catch (DriverException)
            {
                _logger.LogWarning(
                    "Cassandra driver error occured while updating row for silo {silo}, cluster version = {clusterVersion}.",
                    entry.ToString(),
                    tableVersion.Version);
                throw;
            }
        }
Exemple #9
0
        public async Task <bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                if (this.logger.IsEnabled(LogLevel.Debug))
                {
                    this.logger.Debug("InsertRow entry = {0}", entry.ToFullString());
                }
                var tableEntry = Convert(entry);

                bool result;

                try
                {
                    var expression = $"attribute_not_exists({SiloInstanceRecord.DEPLOYMENT_ID_PROPERTY_NAME}) AND attribute_not_exists({SiloInstanceRecord.SILO_IDENTITY_PROPERTY_NAME})";

                    await this.storage.PutEntryAsync(this.options.TableName, tableEntry.GetFields(true), expression);

                    result = true;
                }
                catch (ConditionalCheckFailedException)
                {
                    result = false;
                    this.logger.Warn(ErrorCode.MembershipBase,
                                     $"Insert failed due to contention on the table. Will retry. Entry {entry.ToFullString()}");
                }

                return(result);
            }
            catch (Exception exc)
            {
                this.logger.Warn(ErrorCode.MembershipBase,
                                 $"Intermediate error inserting entry {entry.ToFullString()} to the table {this.options.TableName}.", exc);
                throw;
            }
        }
        public async Task <Boolean> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                //Use "0" as the eTag then Consul KV CAS will treat the operation as an insert and return false if the KV already exiats.
                var consulSiloRegistration = ConsulSiloRegistrationAssembler.FromMembershipEntry(_deploymentId, entry, "0");
                var insertKV = ConsulSiloRegistrationAssembler.ToKVPair(consulSiloRegistration);

                var tryUpdate = await _consulClient.KV.CAS(insertKV);

                if (!tryUpdate.Response)
                {
                    _logger.Debug("ConsulMembershipProvider failed to insert the row because a registration already exists for silo {0}.", entry.SiloAddress);
                    return(false);
                }

                return(true);
            }
            catch (Exception ex)
            {
                _logger.Info("ConsulMembershipProvider failed to insert registration for silo {0}; {1}.", entry.SiloAddress, ex);
                throw;
            }
        }
Exemple #11
0
        public async Task <bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                var siloEntity    = ConvertToEntity(entry, this._clusterOptions.ClusterId);
                var versionEntity = this.BuildVersionEntity(tableVersion);

                var response = await this._container.CreateTransactionalBatch(new PartitionKey(this._clusterOptions.ClusterId))
                               .ReplaceItem(versionEntity.Id, versionEntity, new TransactionalBatchItemRequestOptions {
                    IfMatchEtag = tableVersion.VersionEtag
                })
                               .CreateItem(siloEntity).ExecuteAsync();

                return(response.IsSuccessStatusCode);
            }
            catch (CosmosException exc)
            {
                if (exc.StatusCode == HttpStatusCode.PreconditionFailed)
                {
                    return(false);
                }
                throw;
            }
        }
        protected async Task MembershipTable_ReadAll_Insert_ReadAll(bool extendedProtocol = true)
        {
            MembershipTableData data = await this.membershipTable.ReadAll();

            this.logger?.Info("Membership.ReadAll returned TableVersion={tableVersion} Data={data}", data.Version, data);

            Assert.Equal(0, data.Members.Count);

            TableVersion newTableVersion = data.Version.Next();

            MembershipEntry newEntry = CreateMembershipEntryForTest();
            bool            ok       = await this.membershipTable.InsertRow(newEntry, newTableVersion);

            Assert.True(ok, "InsertRow failed");

            data = await this.membershipTable.ReadAll();

            this.logger?.Info("Membership.ReadAll returned TableVersion={tableVersion} Data={data}", data.Version, data);

            Assert.Equal(1, data.Members.Count);
            Assert.NotNull(data.Version.VersionEtag);

            if (extendedProtocol)
            {
                Assert.NotEqual(newTableVersion.VersionEtag, data.Version.VersionEtag);
                Assert.Equal(newTableVersion.Version, data.Version.Version);
            }

            var    membershipEntry = data.Members[0].Item1;
            string eTag            = data.Members[0].Item2;

            this.logger?.Info("Membership.ReadAll returned MembershipEntry ETag={eTag} Entry={entry}", eTag, membershipEntry);

            Assert.NotNull(eTag);
            Assert.NotNull(membershipEntry);
        }
        public async Task <bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            try
            {
                bool ret = false;

                if (string.IsNullOrEmpty(etag))
                {
                    etag = "0";
                }


                var rentry = RedisMembershipEntry.Create(clusterId, entry, etag);
                var val    = await database.StringGetAsync(clusterId);

                if (!val.IsNull)
                {
                    RedisMembershipCollection collection = serializer.Deserialize <RedisMembershipCollection>(val);
                    var items = collection.Where((x) => x.DeploymentId == clusterId && x.Address.ToParsableString() == rentry.Address.ToParsableString());
                    if (items != null && items.Count() > 0)
                    {
                        RedisMembershipEntry oldEntry = items.First();
                        rentry.LastIndex = oldEntry.LastIndex++;
                        collection.Remove(oldEntry);
                        collection.Add(rentry);
                        ret = await database.StringSetAsync(clusterId, serializer.Serialize(collection));
                    }
                }
                return(ret);
            }
            catch (Exception ex)
            {
                logger?.LogError(ex, "Redis membership table key '{0}' failed update row.", clusterId);
                throw ex;
            }
        }
Exemple #14
0
        public async Task UpdateIAmAlive(MembershipEntry entry)
        {
            var key = entry.SiloAddress.ToString();
            var tx  = _db.CreateTransaction();
            var tableVersionRowTask = tx.HashGetAsync(_clusterKey, TableVersionKey);
            var entryRowTask        = tx.HashGetAsync(_clusterKey, key);

            if (!await tx.ExecuteAsync())
            {
                throw new RedisClusteringException($"Unexpected transaction failure while reading key {key}");
            }

            var entryRow = await entryRowTask;

            if (!entryRow.HasValue)
            {
                throw new RedisClusteringException($"Could not find a value for the key {key}");
            }

            TableVersion tableVersion  = GetTableVersionFromRow(await tableVersionRowTask).Next();
            var          existingEntry = Deserialize(entryRow);

            // Update only the IAmAliveTime property.
            existingEntry.IAmAliveTime = entry.IAmAliveTime;

            var result = await UpsertRowInternal(existingEntry, tableVersion, updateTableVersion : false, allowInsertOnly : false);

            if (result == UpsertResult.Conflict)
            {
                throw new RedisClusteringException($"Failed to update IAmAlive value for key {key} due to conflict");
            }
            else if (result != UpsertResult.Success)
            {
                throw new RedisClusteringException($"Failed to update IAmAlive value for key {key} for an unknown reason");
            }
        }
        protected async Task MembershipTable_InsertRow(bool extendedProtocol = true)
        {
            var membershipEntry = CreateMembershipEntryForTest();

            var data = await this.membershipTable.ReadAll();

            Assert.NotNull(data);
            Assert.Equal(0, data.Members.Count);

            TableVersion nextTableVersion = data.Version.Next();

            bool ok = await this.membershipTable.InsertRow(membershipEntry, nextTableVersion);

            Assert.True(ok, "InsertRow failed");

            data = await this.membershipTable.ReadAll();

            if (extendedProtocol)
            {
                Assert.Equal(1, data.Version.Version);
            }

            Assert.Equal(1, data.Members.Count);
        }
Exemple #16
0
    public static List <TableVersion> GetConfigVersions()
    {
        List <TableVersion> versions = new List <TableVersion>();

        foreach (var version in ConfigDataBase.VersionConfig.Versions)
        {
            TableVersion ver = new TableVersion();
            ver.tableName = version.TableName;
            ver.versionId = version.VersionText;

            versions.Add(ver);
        }

        foreach (var gmVersion in ConfigDataBase.GmVersionConfig.GmVersions)
        {
            TableVersion ver = new TableVersion();
            ver.tableName = gmVersion.TableName;
            ver.versionId = gmVersion.VersionText;

            versions.Add(ver);
        }

        return(versions);
    }
Exemple #17
0
        public async Task <MembershipTableData> ReadRow(SiloAddress key)
        {
            var tx = _db.CreateTransaction();
            var tableVersionRowTask = tx.HashGetAsync(_clusterKey, TableVersionKey);
            var entryRowTask        = tx.HashGetAsync(_clusterKey, key.ToString());

            if (!await tx.ExecuteAsync())
            {
                throw new RedisClusteringException($"Unexpected transaction failure while reading key {key}");
            }

            TableVersion tableVersion = GetTableVersionFromRow(await tableVersionRowTask);
            var          entryRow     = await entryRowTask;

            if (entryRow.HasValue)
            {
                var entry = Deserialize(entryRow);
                return(new MembershipTableData(Tuple.Create(entry, tableVersion.VersionEtag), tableVersion));
            }
            else
            {
                return(new MembershipTableData(tableVersion));
            }
        }
        public async Task<bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            try
            {
                if (logger.IsVerbose) logger.Verbose("UpdateRow entry = {0}, etag = {1}, table version = {2}", entry.ToFullString(), etag, tableVersion);
                var siloEntry = Convert(entry, tableManager.DeploymentId);
                var versionEntry = tableManager.CreateTableVersionEntry(tableVersion.Version);

                bool result = await tableManager.UpdateSiloEntryConditionally(siloEntry, etag, versionEntry, tableVersion.VersionEtag);
                if (result == false)
                    logger.Warn(ErrorCode.AzureTable_24,
                        $"Update failed due to contention on the table. Will retry. Entry {entry.ToFullString()}, eTag {etag}, table version = {tableVersion} ");
                return result;
            }
            catch (Exception exc)
            {
                logger.Warn(ErrorCode.AzureTable_25,
                    $"Intermediate error updating entry {entry.ToFullString()} tableVersion {(tableVersion == null ? "null" : tableVersion.ToString())} to the table {tableManager.TableName}.", exc);
                throw;
            }
        }
Exemple #19
0
        /// <summary>
        /// UpdateRow
        /// </summary>
        /// <param name="entry"></param>
        /// <param name="etag"></param>
        /// <param name="tableVersion"></param>
        /// <returns></returns>
        public async Task <bool> UpdateRow(
            MembershipEntry entry,
            string etag,
            TableVersion tableVersion
            )
        {
            try
            {
                if (entry == null)
                {
                    throw new ArgumentNullException(nameof(entry));
                }

                if (string.IsNullOrWhiteSpace(etag))
                {
                    throw new ArgumentNullException(nameof(etag));
                }

                if (tableVersion == null)
                {
                    throw new ArgumentNullException(nameof(tableVersion));
                }

                using (var scope = _services.CreateScope())
                {
                    var db = scope
                             .ServiceProvider
                             .GetService <OrleansEFContext>();

                    var row = await db
                              .Memberships
                              .FirstOrDefaultAsync(a =>
                                                   a.DeploymentId == _clusterOptions.ClusterId &&
                                                   a.Address == entry.SiloAddress.Endpoint.Address.ToString() &&
                                                   a.Port == (uint)entry.SiloAddress.Endpoint.Port &&
                                                   a.Generation == entry.SiloAddress.Generation
                                                   );

                    if (row == null)
                    {
                        throw new OrleansEFMembershipException.RowNotFound(
                                  entry.SiloAddress
                                  );
                    }

                    OrleansEFMapper.Map(entry, row);

                    await db.SaveChangesAsync();

                    _logger.Info(
                        0, "{0}: {1}", nameof(UpdateRow),
                        $"updated silo {entry.SiloAddress.Endpoint.ToString()}"
                        );

                    return(true);
                }
            }
            catch (Exception e)
            {
                _logger.Error(0, nameof(UpdateRow), e);
                throw;
            }
        }
 public Task <bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
 {
     return(manager.UpdateRow(entry, tableVersion, etag));
 }
Exemple #21
0
 public InMemoryMembershipTable()
 {
     siloTable       = new Dictionary <SiloAddress, Tuple <MembershipEntry, string> >();
     lastETagCounter = 0;
     tableVersion    = new TableVersion(0, NewETag());
 }
Exemple #22
0
        public async Task<Boolean> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                //Use "0" as the eTag then Consul KV CAS will treat the operation as an insert and return false if the KV already exiats.
                var consulSiloRegistration = ConsulSiloRegistrationAssembler.FromMembershipEntry(_deploymentId, entry, "0");
                var insertKV = ConsulSiloRegistrationAssembler.ToKVPair(consulSiloRegistration);

                var tryUpdate = await _consulClient.KV.CAS(insertKV);
                if (!tryUpdate.Response)
                {
                    _logger.Verbose("ConsulMembershipProvider failed to insert the row because a registration already exists for silo {0}.", entry.SiloAddress);
                    return false;
                }

                return true;
            }
            catch (Exception ex)
            {
                _logger.Info("ConsulMembershipProvider failed to insert registration for silo {0}; {1}.", entry.SiloAddress, ex);
                throw;
            }
        }
 private MembershipTableData Convert(List<Tuple<SiloInstanceTableEntry, string>> entries)
 {
     try
     {
         var memEntries = new List<Tuple<MembershipEntry, string>>();
         TableVersion tableVersion = null;
         foreach (var tuple in entries)
         {
             var tableEntry = tuple.Item1;
             if (tableEntry.RowKey.Equals(SiloInstanceTableEntry.TABLE_VERSION_ROW))
             {
                 tableVersion = new TableVersion(Int32.Parse(tableEntry.MembershipVersion), tuple.Item2);
             }
             else
             {
                 try
                 {
                     
                     MembershipEntry membershipEntry = Parse(tableEntry);
                     memEntries.Add(new Tuple<MembershipEntry, string>(membershipEntry, tuple.Item2));
                 }
                 catch (Exception exc)
                 {
                     logger.Error(ErrorCode.AzureTable_61, String.Format(
                         "Intermediate error parsing SiloInstanceTableEntry to MembershipTableData: {0}. Ignoring this entry.",
                         tableEntry), exc);
                 }
             }
         }
         var data = new MembershipTableData(memEntries, tableVersion);
         return data;
     }
     catch (Exception exc)
     {
         logger.Error(ErrorCode.AzureTable_60, String.Format(
             "Intermediate error parsing SiloInstanceTableEntry to MembershipTableData: {0}.", 
             Utils.EnumerableToString(entries, tuple => tuple.Item1.ToString())), exc);
         throw;
     }
 }
        Task<bool> IMembershipTable.InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            if (logger.IsVerbose3) logger.Verbose3(string.Format("SqlMembershipTable.InsertRow called with entry {0} and tableVersion {1}.", entry, tableVersion));

            //The "tableVersion" parameter should always exist when inserting a row as Init should
            //have been called and membership version created and read. This is an optimization to
            //not to go through all the way to database to fail a conditional check on etag (which does
            //exist for the sake of robustness) as mandated by Orleans membership protocol.
            //Likewise, no update can be done without membership entry.
            if (entry == null)
            {
                if (logger.IsVerbose) logger.Verbose("SqlMembershipTable.InsertRow aborted due to null check. MembershipEntry is null.");
                throw new ArgumentNullException("entry");
            }
            if (tableVersion == null)
            {
                if (logger.IsVerbose) logger.Verbose("SqlMembershipTable.InsertRow aborted due to null check. TableVersion is null ");
                throw new ArgumentNullException("tableVersion");
            }

            try
            {
                var query = queryConstants.GetConstant(database.InvariantName, QueryKeys.InsertMembershipKey);
                return database.InsertMembershipRowAsync(query, deploymentId, entry, tableVersion);
            }
            catch(Exception ex)
            {
                if (logger.IsVerbose) logger.Verbose("SqlMembershipTable.InsertRow failed: {0}", ex);
                throw;
            }            
        }
        async Task<bool> IMembershipTable.UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                using (var tx = conn.BeginTransaction())
                {
                    if (tableVersion == null || await UpdateTableVersion(tableVersion, conn, tx))
                    {
                        var command = new SqlCommand(UPDATE_ROW, conn, tx);
                        ConvertToRow(entry, command, this.deploymentId);
                        command.Parameters.Add(new SqlParameter { ParameterName = "@etag", DbType = DbType.String, Value = etag });
                        command.Parameters.Add(new SqlParameter { ParameterName = "@newetag", DbType = DbType.String, Value = NewEtag() });

                        var result = await command.ExecuteNonQueryAsync();

                        tx.Commit();

                        return result > 0;
                    }
                }
                return false;
            }
        }
Exemple #26
0
        public async Task<Boolean> UpdateRow(MembershipEntry entry, String etag, TableVersion tableVersion)
        {
            //Update Silo Liveness
            try
            {
                var siloRegistration = ConsulSiloRegistrationAssembler.FromMembershipEntry(_deploymentId, entry, etag);
                var updateKV = ConsulSiloRegistrationAssembler.ToKVPair(siloRegistration);

                //If the KV.CAS() call returns false then the update failed
                var tryUpdate = await _consulClient.KV.CAS(updateKV);
                if (!tryUpdate.Response)
                {
                    _logger.Verbose("ConsulMembershipProvider failed the CAS check when updating the registration for silo {0}.", entry.SiloAddress);
                    return false;
                }

                return true;

            }
            catch (Exception ex)
            {
                _logger.Info("ConsulMembershipProvider failed to update the registration for silo {0}: {1}.", entry.SiloAddress, ex);
                throw;
            }
        }
Exemple #27
0
 public Task <bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
 {
     return(UpdateRow(entry, "", tableVersion));
 }
        Task<bool> IMembershipTable.InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            logger.Verbose3(string.Format("SqlMembershipTable.InsertRow called with entry {0} and tableVersion {1}.", entry, tableVersion));

            //The "tableVersion" parameter should always exist when inserting a row as Init should
            //have been called and membership version created and read. This is an optimization to
            //not to go through all the way to database to fail a conditional check on etag (which does
            //exist for the sake of robustness) as mandated by Orleans membership protocol.
            //Likewise, no update can be done without membership entry.
            if(tableVersion == null || entry == null)
            {
                logger.Verbose("SqlMembershipTable.InsertRow aborted due to null check. Is null MembershipEntry = {0}, is null TableVersion = {1}", entry == null, tableVersion == null);
                return Task.FromResult(false);
            }

            try
            {
                return database.InsertMembershipRowAsync(deploymentId, entry, tableVersion);
            }
            catch(Exception ex)
            {
                logger.Verbose("SqlMembershipTable.InsertRow failed: {0}", ex);
                throw;
            }            
        }
 public Task <bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
 {
     return(manager.InsertRow(entry, tableVersion));
 }
 public Task <bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion) => this.grain.UpdateRow(entry, etag, tableVersion);
        /// <summary>
        /// Updates membership row data.
        /// </summary>
        /// <param name="deploymentId">The deployment with which to insert row.</param>
        /// <param name="etag">The etag of which to use to check if the membership data being updated is not stale.</param>
        /// <param name="membershipEntry">The membership data to used to update database.</param>
        /// <param name="version">The membership version used to update database.</param>
        /// <returns><em>TRUE</em> if update SUCCEEDS. <em>FALSE</em> ot</returns>
        internal async Task<bool> UpdateMembershipRowAsync(string deploymentId, string etag, MembershipEntry membershipEntry, TableVersion version)
        {
            var ret = await storage.ReadAsync(orleansQueries.UpdateMembershipKey, command =>
            {
                var siloIdParameter = CreateDeploymentIdParameter(command, deploymentId);
                command.Parameters.Add(siloIdParameter);


                var versionEtagParameter = CreateVersionEtagParameter(command, version.VersionEtag);
                command.Parameters.Add(versionEtagParameter);

                //The insert membership row part.
                var etagParameter = CreateEtagParameter(command, etag);
                command.Parameters.Add(etagParameter);

                var addressParameter = CreateAddressParameter(command, membershipEntry.SiloAddress.Endpoint.Address);
                command.Parameters.Add(addressParameter);

                var portParameter = CreatePortParameter(command, membershipEntry.SiloAddress.Endpoint.Port);
                command.Parameters.Add(portParameter);

                var generationParameter = CreateGenerationParameter(command, membershipEntry.SiloAddress.Generation);
                command.Parameters.Add(generationParameter);

                var hostNameParameter = CreateHostNameParameter(command, membershipEntry.HostName);
                command.Parameters.Add(hostNameParameter);

                var statusParameter = CreateStatusParameter(command, membershipEntry.Status);
                command.Parameters.Add(statusParameter);

                var proxyPortParameter = CreateProxyPortParameter(command, membershipEntry.ProxyPort);
                command.Parameters.Add(proxyPortParameter);

                var roleNameParameter = CreateRoleNameParameter(command, membershipEntry.RoleName);
                command.Parameters.Add(roleNameParameter);

                var instanceNameParameter = CreateInstanceNameParameter(command, membershipEntry.InstanceName);
                command.Parameters.Add(instanceNameParameter);

                var updateZoneParameter = CreateUpdateZoneParameter(command, membershipEntry.UpdateZone);
                command.Parameters.Add(updateZoneParameter);

                var faultZoneParameter = CreateFaultZoneParameter(command, membershipEntry.FaultZone);
                command.Parameters.Add(faultZoneParameter);

                var startTimeParameter = CreateStartTimeParameter(command, membershipEntry.StartTime);
                command.Parameters.Add(startTimeParameter);

                var iAmAliveTimeParameter = CreateIAmAliveTimeParameter(command, membershipEntry.IAmAliveTime);
                command.Parameters.Add(iAmAliveTimeParameter);
                
                var suspectingSilosParameter = CreateSuspectingSilosParameter(command, membershipEntry);
                command.Parameters.Add(suspectingSilosParameter);

                var suspectingTimesParameter = CreateSuspectingTimesParameter(command, membershipEntry);
                command.Parameters.Add(suspectingTimesParameter);

            }, (selector, resultSetCount, cancellationToken) => { return Task.FromResult(selector.GetBoolean(0)); }).ConfigureAwait(continueOnCapturedContext: false);

            return ret.First();
        }
        /// <summary>
        /// Updates membership row data.
        /// </summary>
        /// <param name="storage">The storage to use.</param>
        /// <param name="query">The query to use.</param>
        /// <param name="deploymentId">The deployment with which to insert row.</param>
        /// <param name="etag">The etag of which to use to check if the membership data being updated is not stale.</param>
        /// <param name="membershipEntry">The membership data to used to update database.</param>
        /// <param name="version">The membership version used to update database.</param>
        /// <returns><em>TRUE</em> if update SUCCEEDS. <em>FALSE</em> ot</returns>
        internal static async Task<bool> UpdateMembershipRowAsync(this IRelationalStorage storage, string query, string deploymentId, string etag, MembershipEntry membershipEntry, TableVersion version)
        {            
            var ret = await storage.ReadAsync(query, command =>
            {
                var direction = ParameterDirection.Input;
                var siloIdParameter = CreateDeploymentIdParameter(command, deploymentId, direction);
                command.Parameters.Add(siloIdParameter);

                var versionParameter = CreateVersionParameter(command, version.Version, direction);
                command.Parameters.Add(versionParameter);

                var versionEtagParameter = CreateVersionEtagParameter(command, version.VersionEtag, direction);
                command.Parameters.Add(versionEtagParameter);

                //The insert membership row part.
                var etagParameter = CreateEtagParameter(command, etag, direction);
                command.Parameters.Add(etagParameter);

                var addressParameter = CreateAddressParameter(command, membershipEntry.SiloAddress.Endpoint.Address, direction);
                command.Parameters.Add(addressParameter);

                var portParameter = CreatePortParameter(command, membershipEntry.SiloAddress.Endpoint.Port, direction);
                command.Parameters.Add(portParameter);

                var generationParameter = CreateGenerationParameter(command, membershipEntry.SiloAddress.Generation, direction);
                command.Parameters.Add(generationParameter);

                var hostNameParameter = CreateHostNameParameter(command, membershipEntry.HostName, direction);
                command.Parameters.Add(hostNameParameter);

                var statusParameter = CreateStatusParameter(command, membershipEntry.Status, direction);
                command.Parameters.Add(statusParameter);

                var proxyPortParameter = CreateProxyPortParameter(command, membershipEntry.ProxyPort, direction);
                command.Parameters.Add(proxyPortParameter);

                var roleNameParameter = CreateRoleNameParameter(command, membershipEntry.RoleName, direction);
                command.Parameters.Add(roleNameParameter);

                var instanceNameParameter = CreateInstanceNameParameter(command, membershipEntry.InstanceName, direction);
                command.Parameters.Add(instanceNameParameter);

                var updateZoneParameter = CreateUpdateZoneParameter(command, membershipEntry.UpdateZone, direction);
                command.Parameters.Add(updateZoneParameter);

                var faultZoneParameter = CreateFaultZoneParameter(command, membershipEntry.FaultZone, direction);
                command.Parameters.Add(faultZoneParameter);

                var startTimeParameter = CreateStartTimeParameter(command, membershipEntry.StartTime, direction);
                command.Parameters.Add(startTimeParameter);

                var iAmAliveTimeParameter = CreateIAmAliveTimeParameter(command, membershipEntry.IAmAliveTime, direction);
                command.Parameters.Add(iAmAliveTimeParameter);

                var suspectingSilosParameter = CreateSuspectingSilosParameter(command, membershipEntry, direction);
                command.Parameters.Add(suspectingSilosParameter);

                var suspectingTimesParameter = CreateSuspectingTimesParameter(command, membershipEntry, direction);
                command.Parameters.Add(suspectingTimesParameter);

            }, (selector, _) => { return selector.GetBoolean(0); }).ConfigureAwait(continueOnCapturedContext: false);

            return ret.First();
        }
        public async Task<bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            try
            {
                if (logger.IsVerbose) logger.Verbose("UpdateRow entry = {0}, etag = {1}", entry.ToFullString(), etag);
                var siloEntry = Convert(entry);
                int currentEtag = 0;
                if (!int.TryParse(etag, out currentEtag))
                {
                    logger.Warn(ErrorCode.MembershipBase,
                        $"Update failed. Invalid ETag value. Will retry. Entry {entry.ToFullString()}, eTag {etag}");
                    return false;
                }

                siloEntry.ETag = currentEtag + 1;

                bool result;

                try
                {
                    var conditionalValues = new Dictionary<string, AttributeValue> { { CURRENT_ETAG_ALIAS, new AttributeValue { N = etag } } };
                    var etagConditionalExpression = $"{SiloInstanceRecord.ETAG_PROPERTY_NAME} = {CURRENT_ETAG_ALIAS}";
                    await storage.UpsertEntryAsync(TABLE_NAME_DEFAULT_VALUE, siloEntry.GetKeys(),
                        siloEntry.GetFields(), etagConditionalExpression, conditionalValues);

                    result = true;
                }
                catch (ConditionalCheckFailedException)
                {
                    result = false;
                    logger.Warn(ErrorCode.MembershipBase,
                        $"Update failed due to contention on the table. Will retry. Entry {entry.ToFullString()}, eTag {etag}");
                }
                    
                return result;
            }
            catch (Exception exc)
            {
                logger.Warn(ErrorCode.MembershipBase,
                    $"Intermediate error updating entry {entry.ToFullString()} to the table {TABLE_NAME_DEFAULT_VALUE}.", exc);
                throw;
            }
        }
        private async Task<bool> UpdateTableVersion(TableVersion version, SqlConnection conn, SqlTransaction tx)
        {
            var read = new SqlCommand(READ_VERSION, conn, tx);
            read.Parameters.Add(new SqlParameter { ParameterName = "@deploymentid", DbType = DbType.String, Value = deploymentId });

            string query;

            using (var results = await read.ExecuteReaderAsync())
            {
                query = (results.HasRows) ? UPDATE_VERSION_ROW : INSERT_VERSION_ROW;
            }

            var write = new SqlCommand(query, conn, tx);
            write.Parameters.Add(new SqlParameter { ParameterName = "@deploymentid", DbType = DbType.String, Value = deploymentId });
            write.Parameters.Add(new SqlParameter { ParameterName = "@timestamp", DbType = DbType.DateTime, Value = DateTime.UtcNow });
            write.Parameters.Add(new SqlParameter { ParameterName = "@version", DbType = DbType.Int64, Value = version.Version });
            write.Parameters.Add(new SqlParameter { ParameterName = "@etag", DbType = DbType.String, Value = version.VersionEtag });
            write.Parameters.Add(new SqlParameter { ParameterName = "@newetag", DbType = DbType.String, Value = NewEtag() });

            return (await write.ExecuteNonQueryAsync()) > 0;
        }
 public Task <bool> InsertRow(MembershipEntry entry, TableVersion tableVersion) => this.grain.InsertRow(entry, tableVersion);
        Task<bool> IMembershipTable.UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            if (logger.IsVerbose3) logger.Verbose3(string.Format("IMembershipTable.UpdateRow called with entry {0}, etag {1} and tableVersion {2}.", entry, etag, tableVersion));

            //The "tableVersion" parameter should always exist when updating a row as Init should
            //have been called and membership version created and read. This is an optimization to
            //not to go through all the way to database to fail a conditional check (which does
            //exist for the sake of robustness) as mandated by Orleans membership protocol.
            //Likewise, no update can be done without membership entry or an etag.
            if (entry == null)
            {
                if (logger.IsVerbose) logger.Verbose("SqlMembershipTable.UpdateRow aborted due to null check. MembershipEntry is null.");
                throw new ArgumentNullException("entry");
            }
            if (etag == null)
            {
                if (logger.IsVerbose) logger.Verbose("SqlMembershipTable.UpdateRow aborted due to null check. etag is null.");
                throw new ArgumentNullException("etag");
            }
            if (tableVersion == null)
            {
                if (logger.IsVerbose) logger.Verbose("SqlMembershipTable.UpdateRow aborted due to null check. TableVersion is null ");
                throw new ArgumentNullException("tableVersion");
            }

            try
            {
                return orleansQueries.UpdateMembershipRowAsync(deploymentId, etag, entry, tableVersion);                                
            }
            catch(Exception ex)
            {
                if (logger.IsVerbose) logger.Verbose("SqlMembershipTable.UpdateRow failed: {0}", ex);
                throw;
            }
        }
        public async Task <bool> UpsertRow(string deploymentId, MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            var id = ReturnId(deploymentId, entry.SiloAddress);

            var document = MongoMembershipDocument.Create(entry, deploymentId, id);

            try
            {
                await Collection.ReplaceOneAsync(x => x.Id == id && x.Etag == etag, document, Upsert);

                return(true);
            }
            catch (MongoException ex)
            {
                if (ex.IsDuplicateKey())
                {
                    return(false);
                }
                throw;
            }
        }
 public Task <bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
 {
     return(Task.FromResult(true));
 }
        protected async Task MembershipTable_ReadRow_Insert_Read(bool extendedProtocol = true)
        {
            MembershipTableData data = await this.membershipTable.ReadAll();

            this.logger?.Info("Membership.ReadAll returned TableVersion={tableVersion} Data={data}", data.Version, data);

            Assert.Equal(0, data.Members.Count);

            TableVersion newTableVersion = data.Version.Next();

            MembershipEntry newEntry = CreateMembershipEntryForTest();
            bool            ok       = await this.membershipTable.InsertRow(newEntry, newTableVersion);

            Assert.True(ok, "InsertRow failed");

            ok = await this.membershipTable.InsertRow(newEntry, newTableVersion);

            Assert.False(ok, "InsertRow should have failed - same entry, old table version");

            if (extendedProtocol)
            {
                ok = await this.membershipTable.InsertRow(CreateMembershipEntryForTest(), newTableVersion);

                Assert.False(ok, "InsertRow should have failed - new entry, old table version");
            }

            data = await this.membershipTable.ReadAll();

            if (extendedProtocol)
            {
                Assert.Equal(1, data.Version.Version);
            }

            TableVersion nextTableVersion = data.Version.Next();

            ok = await this.membershipTable.InsertRow(newEntry, nextTableVersion);

            Assert.False(ok, "InsertRow should have failed - duplicate entry");

            data = await this.membershipTable.ReadAll();

            Assert.Equal(1, data.Members.Count);

            data = await this.membershipTable.ReadRow(newEntry.SiloAddress);

            if (extendedProtocol)
            {
                Assert.Equal(newTableVersion.Version, data.Version.Version);
            }

            this.logger?.Info("Membership.ReadRow returned TableVersion={tableVersion} Data={data}", data.Version, data);

            Assert.Equal(1, data.Members.Count);
            Assert.NotNull(data.Version.VersionEtag);
            if (extendedProtocol)
            {
                Assert.NotEqual(newTableVersion.VersionEtag, data.Version.VersionEtag);
                Assert.Equal(newTableVersion.Version, data.Version.Version);
            }
            var    membershipEntry = data.Members[0].Item1;
            string eTag            = data.Members[0].Item2;

            this.logger?.Info("Membership.ReadRow returned MembershipEntry ETag={eTag} Entry={entry}", eTag, membershipEntry);

            Assert.NotNull(eTag);
            Assert.NotNull(membershipEntry);
        }
        public async Task<bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                if (logger.IsVerbose) logger.Verbose("InsertRow entry = {0}", entry.ToFullString());
                var tableEntry = Convert(entry);

                bool result;

                try
                {
                    var expression = $"attribute_not_exists({SiloInstanceRecord.DEPLOYMENT_ID_PROPERTY_NAME}) AND attribute_not_exists({SiloInstanceRecord.SILO_IDENTITY_PROPERTY_NAME})";

                    await storage.PutEntryAsync(TABLE_NAME_DEFAULT_VALUE, tableEntry.GetFields(true), expression);
                    result = true;
                }
                catch (ConditionalCheckFailedException)
                {
                    result = false;
                    logger.Warn(ErrorCode.MembershipBase,
                        $"Insert failed due to contention on the table. Will retry. Entry {entry.ToFullString()}");
                }
                    
                return result;
            }
            catch (Exception exc)
            {
                logger.Warn(ErrorCode.MembershipBase,
                    $"Intermediate error inserting entry {entry.ToFullString()} to the table {TABLE_NAME_DEFAULT_VALUE}.", exc);
                throw;
            }
        }
        protected async Task MembershipTable_UpdateRow(bool extendedProtocol = true)
        {
            var tableData = await this.membershipTable.ReadAll();

            Assert.NotNull(tableData.Version);

            Assert.Equal(0, tableData.Version.Version);
            Assert.Equal(0, tableData.Members.Count);

            for (int i = 1; i < 10; i++)
            {
                var siloEntry = CreateMembershipEntryForTest();

                siloEntry.SuspectTimes =
                    new List <Tuple <SiloAddress, DateTime> >
                {
                    new Tuple <SiloAddress, DateTime>(CreateSiloAddressForTest(), GetUtcNowWithSecondsResolution().AddSeconds(1)),
                    new Tuple <SiloAddress, DateTime>(CreateSiloAddressForTest(), GetUtcNowWithSecondsResolution().AddSeconds(2))
                };

                TableVersion tableVersion = tableData.Version.Next();

                this.logger?.Info("Calling InsertRow with Entry={entry} TableVersion={tableVersion}", siloEntry, tableVersion);
                bool ok = await this.membershipTable.InsertRow(siloEntry, tableVersion);

                Assert.True(ok, "InsertRow failed");

                tableData = await this.membershipTable.ReadAll();

                var etagBefore = tableData.Get(siloEntry.SiloAddress).Item2;

                Assert.NotNull(etagBefore);

                if (extendedProtocol)
                {
                    this.logger?.Info("Calling UpdateRow with Entry={entry} correct eTag={eTag} old version={tableVersion}", siloEntry,
                                      etagBefore, tableVersion != null ? tableVersion.ToString() : "null");
                    ok = await this.membershipTable.UpdateRow(siloEntry, etagBefore, tableVersion);

                    Assert.False(ok, $"row update should have failed - Table Data = {tableData}");
                    tableData = await this.membershipTable.ReadAll();
                }

                tableVersion = tableData.Version.Next();

                this.logger?.Info("Calling UpdateRow with Entry={entry} correct eTag={eTag} correct version={tableVersion}", siloEntry,
                                  etagBefore, tableVersion != null ? tableVersion.ToString() : "null");

                ok = await this.membershipTable.UpdateRow(siloEntry, etagBefore, tableVersion);

                Assert.True(ok, $"UpdateRow failed - Table Data = {tableData}");

                this.logger?.Info("Calling UpdateRow with Entry={entry} old eTag={eTag} old version={tableVersion}", siloEntry,
                                  etagBefore, tableVersion != null ? tableVersion.ToString() : "null");
                ok = await this.membershipTable.UpdateRow(siloEntry, etagBefore, tableVersion);

                Assert.False(ok, $"row update should have failed - Table Data = {tableData}");

                tableData = await this.membershipTable.ReadAll();

                var tuple = tableData.Get(siloEntry.SiloAddress);

                //Assert.Equal(tuple.Item1.ToFullString(true), siloEntry.ToFullString(true));

                var etagAfter = tuple.Item2;

                if (extendedProtocol)
                {
                    this.logger?.Info("Calling UpdateRow with Entry={entry} correct eTag={eTag} old version={tableVersion}", siloEntry,
                                      etagAfter, tableVersion != null ? tableVersion.ToString() : "null");

                    ok = await this.membershipTable.UpdateRow(siloEntry, etagAfter, tableVersion);

                    Assert.False(ok, $"row update should have failed - Table Data = {tableData}");
                }

                tableData = await this.membershipTable.ReadAll();

                etagBefore = etagAfter;

                etagAfter = tableData.Get(siloEntry.SiloAddress).Item2;

                Assert.Equal(etagBefore, etagAfter);
                Assert.NotNull(tableData.Version);
                if (extendedProtocol)
                {
                    Assert.Equal(tableVersion.Version, tableData.Version.Version);
                }

                Assert.Equal(i, tableData.Members.Count);
            }
        }
        public async Task <bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            try
            {
                if (this.logger.IsEnabled(LogLevel.Debug))
                {
                    this.logger.Debug("UpdateRow entry = {0}, etag = {1}", entry.ToFullString(), etag);
                }
                var siloEntry = Convert(entry, tableVersion);
                if (!int.TryParse(etag, out var currentEtag))
                {
                    this.logger.Warn(ErrorCode.MembershipBase,
                                     $"Update failed. Invalid ETag value. Will retry. Entry {entry.ToFullString()}, eTag {etag}");
                    return(false);
                }

                siloEntry.ETag = currentEtag + 1;

                if (!TryCreateTableVersionRecord(tableVersion.Version, tableVersion.VersionEtag, out var versionEntry))
                {
                    this.logger.Warn(ErrorCode.MembershipBase,
                                     $"Update failed. Invalid ETag value. Will retry. Entry {entry.ToFullString()}, eTag {tableVersion.VersionEtag}");
                    return(false);
                }

                versionEntry.ETag++;

                bool result;

                try
                {
                    var etagConditionalExpression = $"{SiloInstanceRecord.ETAG_PROPERTY_NAME} = {CURRENT_ETAG_ALIAS}";

                    var siloConditionalValues = new Dictionary <string, AttributeValue> {
                        { CURRENT_ETAG_ALIAS, new AttributeValue {
                              N = etag
                          } }
                    };
                    var siloEntryUpdate = new Update
                    {
                        TableName           = this.options.TableName,
                        Key                 = siloEntry.GetKeys(),
                        ConditionExpression = etagConditionalExpression
                    };
                    (siloEntryUpdate.UpdateExpression, siloEntryUpdate.ExpressionAttributeValues) =
                        this.storage.ConvertUpdate(siloEntry.GetFields(), siloConditionalValues);


                    var versionConditionalValues = new Dictionary <string, AttributeValue> {
                        { CURRENT_ETAG_ALIAS, new AttributeValue {
                              N = tableVersion.VersionEtag
                          } }
                    };
                    var versionEntryUpdate = new Update
                    {
                        TableName           = this.options.TableName,
                        Key                 = versionEntry.GetKeys(),
                        ConditionExpression = etagConditionalExpression
                    };
                    (versionEntryUpdate.UpdateExpression, versionEntryUpdate.ExpressionAttributeValues) =
                        this.storage.ConvertUpdate(versionEntry.GetFields(), versionConditionalValues);

                    await this.storage.WriteTxAsync(updates : new[] { siloEntryUpdate, versionEntryUpdate });

                    result = true;
                }
                catch (TransactionCanceledException canceledException)
                {
                    if (canceledException.Message.Contains("ConditionalCheckFailed")) //not a good way to check for this currently
                    {
                        result = false;
                        this.logger.Warn(ErrorCode.MembershipBase,
                                         $"Update failed due to contention on the table. Will retry. Entry {entry.ToFullString()}, eTag {etag}");
                    }
                    else
                    {
                        throw;
                    }
                }

                return(result);
            }
            catch (Exception exc)
            {
                this.logger.Warn(ErrorCode.MembershipBase,
                                 $"Intermediate error updating entry {entry.ToFullString()} to the table {this.options.TableName}.", exc);
                throw;
            }
        }
 Task <bool> IMembershipTable.UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
 {
     return(session.ExecuteAsync(queries.UpdateMembership(entry, tableVersion.Version - 1)).ContinueWith(t => (bool)t.Result.First()["[applied]"]));
 }
 public InMemoryMembershipTable()
 {
     siloTable = new Dictionary<SiloAddress, Tuple<MembershipEntry, string>>();
     lastETagCounter = 0;
     tableVersion = new TableVersion(0, NewETag());
 }
 public Task <bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
 {
     return(Task.FromResult(true));
 }
        async Task <bool> IMembershipTable.UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                using (var tx = conn.BeginTransaction())
                {
                    if (tableVersion == null || await UpdateTableVersion(tableVersion, conn, tx))
                    {
                        var command = new SqlCommand(UPDATE_ROW, conn, tx);
                        ConvertToRow(entry, command, this.deploymentId);
                        command.Parameters.Add(new SqlParameter {
                            ParameterName = "@etag", DbType = DbType.String, Value = etag
                        });
                        command.Parameters.Add(new SqlParameter {
                            ParameterName = "@newetag", DbType = DbType.String, Value = NewEtag()
                        });

                        var result = await command.ExecuteNonQueryAsync();

                        tx.Commit();

                        return(result > 0);
                    }
                }
                return(false);
            }
        }
Exemple #47
0
        public async Task <bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                var siloEntity    = this.ConvertToEntity(entry);
                var versionEntity = this.BuildVersionEntity(tableVersion);

                SiloEntity existentSiloEntry = default;

                try
                {
                    existentSiloEntry = ((JObject)await this._kubeClient.GetNamespacedCustomObjectAsync(
                                             Constants.ORLEANS_GROUP,
                                             Constants.PROVIDER_MODEL_VERSION,
                                             this._namespace,
                                             SiloEntity.PLURAL,
                                             siloEntity.Metadata.Name
                                             ))?.ToObject <SiloEntity>();
                }
                catch (HttpOperationException ex)
                {
                    if (ex.Response.StatusCode != HttpStatusCode.NotFound)
                    {
                        throw;
                    }
                }

                if (existentSiloEntry != null)
                {
                    return(false);
                }

                var currentVersionEntity = await this.GetClusterVersion();

                if (currentVersionEntity == null ||
                    currentVersionEntity.ClusterVersion == versionEntity.ClusterVersion)
                {
                    return(false);
                }

                var updatedVersionEntity = await this._kubeClient.ReplaceNamespacedCustomObjectAsync(
                    versionEntity,
                    Constants.ORLEANS_GROUP,
                    Constants.PROVIDER_MODEL_VERSION,
                    this._namespace,
                    ClusterVersionEntity.PLURAL,
                    versionEntity.Metadata.Name
                    );

                if (updatedVersionEntity == null)
                {
                    return(false);
                }

                var createdSiloEntity = await this._kubeClient.CreateNamespacedCustomObjectAsync(
                    siloEntity,
                    Constants.ORLEANS_GROUP,
                    Constants.PROVIDER_MODEL_VERSION,
                    this._namespace,
                    SiloEntity.PLURAL
                    );

                return(createdSiloEntity != null);
            }
            catch (InvalidOperationException)
            {
                return(false);
            }
            catch (Exception exc)
            {
                this._logger?.LogError(exc, "Unable to insert Silo Entry.");

                throw;
            }
        }
        public async Task <bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                if (this.logger.IsEnabled(LogLevel.Debug))
                {
                    this.logger.Debug("InsertRow entry = {0}", entry.ToFullString());
                }
                var tableEntry = Convert(entry, tableVersion);

                if (!TryCreateTableVersionRecord(tableVersion.Version, tableVersion.VersionEtag, out var versionEntry))
                {
                    this.logger.Warn(ErrorCode.MembershipBase,
                                     $"Insert failed. Invalid ETag value. Will retry. Entry {entry.ToFullString()}, eTag {tableVersion.VersionEtag}");
                    return(false);
                }

                versionEntry.ETag++;

                bool result;

                try
                {
                    var notExistConditionExpression =
                        $"attribute_not_exists({SiloInstanceRecord.DEPLOYMENT_ID_PROPERTY_NAME}) AND attribute_not_exists({SiloInstanceRecord.SILO_IDENTITY_PROPERTY_NAME})";
                    var tableEntryInsert = new Put
                    {
                        Item = tableEntry.GetFields(true),
                        ConditionExpression = notExistConditionExpression,
                        TableName           = this.options.TableName
                    };

                    var conditionalValues = new Dictionary <string, AttributeValue> {
                        { CURRENT_ETAG_ALIAS, new AttributeValue {
                              N = tableVersion.VersionEtag
                          } }
                    };
                    var etagConditionalExpression = $"{SiloInstanceRecord.ETAG_PROPERTY_NAME} = {CURRENT_ETAG_ALIAS}";
                    var versionEntryUpdate        = new Update
                    {
                        TableName           = this.options.TableName,
                        Key                 = versionEntry.GetKeys(),
                        ConditionExpression = etagConditionalExpression
                    };
                    (versionEntryUpdate.UpdateExpression, versionEntryUpdate.ExpressionAttributeValues) =
                        this.storage.ConvertUpdate(versionEntry.GetFields(), conditionalValues);

                    await this.storage.WriteTxAsync(new[] { tableEntryInsert }, new[] { versionEntryUpdate });

                    result = true;
                }
                catch (TransactionCanceledException canceledException)
                {
                    if (canceledException.Message.Contains("ConditionalCheckFailed")) //not a good way to check for this currently
                    {
                        result = false;
                        this.logger.Warn(ErrorCode.MembershipBase,
                                         $"Insert failed due to contention on the table. Will retry. Entry {entry.ToFullString()}");
                    }
                    else
                    {
                        throw;
                    }
                }

                return(result);
            }
            catch (Exception exc)
            {
                this.logger.Warn(ErrorCode.MembershipBase,
                                 $"Intermediate error inserting entry {entry.ToFullString()} to the table {this.options.TableName}.", exc);
                throw;
            }
        }