protected override BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject previousValue) { if (previousValue != null) { if (previousValue.Modifications == null) { previousValue.Modifications = new DynamicJsonValue(); } AddIndexesIfNecessary(previousValue.Modifications, previousValue, Indexes); if (previousValue.Modifications.Properties.Count == 0) { return(previousValue); } return(context.ReadObject(previousValue, GetItemId())); } var djv = new DynamicJsonValue(); AddIndexesIfNecessary(djv, null, Indexes); return(context.ReadObject(djv, GetItemId())); }
protected override BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue) { var itemId = GetItemId(); if (existingValue == null) { throw new SubscriptionDoesNotExistException($"Subscription with id '{itemId}' does not exist"); } var subscription = JsonDeserializationCluster.SubscriptionState(existingValue); var topology = record.Topology; var lastResponsibleNode = AcknowledgeSubscriptionBatchCommand.GetLastResponsibleNode(HasHighlyAvailableTasks, topology, NodeTag); var appropriateNode = topology.WhoseTaskIsIt(RachisState.Follower, subscription, lastResponsibleNode); if (appropriateNode == null && record.DeletionInProgress.ContainsKey(NodeTag)) { throw new DatabaseDoesNotExistException( $"Stopping subscription '{SubscriptionName}' on node {NodeTag}, because database '{DatabaseName}' is being deleted."); } if (appropriateNode != NodeTag) { throw new SubscriptionDoesNotBelongToNodeException( $"Can't update subscription with name {itemId} by node {NodeTag}, because it's not its task to update this subscription"); } subscription.LastClientConnectionTime = LastClientConnectionTime; subscription.NodeTag = NodeTag; return(context.ReadObject(subscription.ToJson(), itemId)); }
private IDatabaseTask GetMatchingConfiguration(RawDatabaseRecord record) { var ravenEtls = record.RavenEtls; if (ravenEtls != null) { for (var i = 0; i < ravenEtls.Count; i++) { if (ravenEtls[i].Name == ConfigurationName) { return(ravenEtls[i]); } } } var sqlEtls = record.SqlEtls; if (sqlEtls != null) { for (var i = 0; i < sqlEtls.Count; i++) { if (sqlEtls[i].Name == ConfigurationName) { return(sqlEtls[i]); } } } return(null); }
private IDatabaseTask GetMatchingConfiguration(RawDatabaseRecord record) { var ravenEtls = record.RavenEtls; if (ravenEtls != null) { for (var i = 0; i < ravenEtls.Count; i++) { if (ravenEtls[i].Name == ConfigurationName) { return(ravenEtls[i]); } } } var sqlEtls = record.SqlEtls; if (sqlEtls != null) { for (var i = 0; i < sqlEtls.Count; i++) { if (sqlEtls[i].Name == ConfigurationName) { return(sqlEtls[i]); } } } var parquetEtls = record.OlapEtls; if (parquetEtls != null) { for (var i = 0; i < parquetEtls.Count; i++) { if (parquetEtls[i].Name == ConfigurationName) { return(parquetEtls[i]); } } } var elasticEtls = record.ElasticSearchEtls; if (elasticEtls != null) { for (var i = 0; i < elasticEtls.Count; i++) { if (elasticEtls[i].Name == ConfigurationName) { return(elasticEtls[i]); } } } return(null); }
protected override BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue) { var subscriptionName = SubscriptionName; if (string.IsNullOrEmpty(subscriptionName)) { subscriptionName = SubscriptionId.ToString(); } if (existingValue == null) { throw new SubscriptionDoesNotExistException($"Subscription with name '{subscriptionName}' does not exist"); } var subscription = JsonDeserializationCluster.SubscriptionState(existingValue); var topology = record.Topology; var lastResponsibleNode = GetLastResponsibleNode(HasHighlyAvailableTasks, topology, NodeTag); var appropriateNode = topology.WhoseTaskIsIt(RachisState.Follower, subscription, lastResponsibleNode); if (appropriateNode == null && record.DeletionInProgress.ContainsKey(NodeTag)) { throw new DatabaseDoesNotExistException($"Stopping subscription '{subscriptionName}' on node {NodeTag}, because database '{DatabaseName}' is being deleted."); } if (appropriateNode != NodeTag) { throw new SubscriptionDoesNotBelongToNodeException( $"Cannot apply {nameof(AcknowledgeSubscriptionBatchCommand)} for subscription '{subscriptionName}' with id '{SubscriptionId}', on database '{DatabaseName}', on node '{NodeTag}'," + $" because the subscription task belongs to '{appropriateNode ?? "N/A"}'.") { AppropriateNode = appropriateNode }; } if (ChangeVector == nameof(Constants.Documents.SubscriptionChangeVectorSpecialStates.DoNotChange)) { return(context.ReadObject(existingValue, SubscriptionName)); } if (IsLegacyCommand()) { if (LastKnownSubscriptionChangeVector != subscription.ChangeVectorForNextBatchStartingPoint) { throw new SubscriptionChangeVectorUpdateConcurrencyException($"Can't acknowledge subscription with name {subscriptionName} due to inconsistency in change vector progress. Probably there was an admin intervention that changed the change vector value. Stored value: {subscription.ChangeVectorForNextBatchStartingPoint}, received value: {LastKnownSubscriptionChangeVector}"); } subscription.ChangeVectorForNextBatchStartingPoint = ChangeVector; } subscription.NodeTag = NodeTag; subscription.LastBatchAckTime = LastTimeServerMadeProgressWithDocuments; return(context.ReadObject(subscription.ToJson(), subscriptionName)); }
private static bool IsDatabaseBeingDeleted(string tag, RawDatabaseRecord databaseRecord) { if (databaseRecord == null) { return(false); } var deletionInProgress = databaseRecord.DeletionInProgress; return(deletionInProgress != null && deletionInProgress.TryGetValue(tag, out var delInProgress) && delInProgress != DeletionInProgressStatus.No); }
private static void UpdateDatabaseInfo(RawDatabaseRecord databaseRecord, ServerStore serverStore, string databaseName, DrivesUsage existingDrivesUsage, DatabaseInfoItem databaseInfoItem) { DatabaseInfo databaseInfo = null; if (serverStore.DatabaseInfoCache.TryGet(databaseName, databaseInfoJson => { databaseInfo = JsonDeserializationServer.DatabaseInfo(databaseInfoJson); }) == false) { return; } Debug.Assert(databaseInfo != null); var databaseTopology = databaseRecord.Topology; var indexesCount = databaseRecord.CountOfIndexes; databaseInfoItem.DocumentsCount = databaseInfo.DocumentsCount ?? 0; databaseInfoItem.IndexesCount = databaseInfo.IndexesCount ?? indexesCount; databaseInfoItem.ReplicationFactor = databaseTopology?.ReplicationFactor ?? databaseInfo.ReplicationFactor; databaseInfoItem.ErroredIndexesCount = databaseInfo.IndexingErrors ?? 0; if (databaseInfo.MountPointsUsage == null) { return; } foreach (var mountPointUsage in databaseInfo.MountPointsUsage) { var driveName = mountPointUsage.DiskSpaceResult.DriveName; var diskSpaceResult = DiskSpaceChecker.GetDiskSpaceInfo( mountPointUsage.DiskSpaceResult.DriveName, new DriveInfoBase { DriveName = driveName }); if (diskSpaceResult != null) { // update the latest drive info mountPointUsage.DiskSpaceResult = new Client.ServerWide.Operations.DiskSpaceResult { DriveName = diskSpaceResult.DriveName, VolumeLabel = diskSpaceResult.VolumeLabel, TotalFreeSpaceInBytes = diskSpaceResult.TotalFreeSpace.GetValue(SizeUnit.Bytes), TotalSizeInBytes = diskSpaceResult.TotalSize.GetValue(SizeUnit.Bytes) }; } UpdateMountPoint(serverStore.Configuration.Storage, mountPointUsage, databaseName, existingDrivesUsage); } }
protected override BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue) { EtlProcessState etlState; if (existingValue != null) { etlState = JsonDeserializationClient.EtlProcessState(existingValue); var databaseTask = GetMatchingConfiguration(record); if (databaseTask == null) { throw new RachisApplyException($"Can't update progress of ETL {ConfigurationName} by node {NodeTag}, because it's configuration can't be found"); } var topology = record.Topology; var lastResponsibleNode = GetLastResponsibleNode(HasHighlyAvailableTasks, topology, NodeTag); if (topology.WhoseTaskIsIt(RachisState.Follower, databaseTask, lastResponsibleNode) != NodeTag) { throw new RachisApplyException($"Can't update progress of ETL {ConfigurationName} by node {NodeTag}, because it's not its task to update this ETL"); } } else { etlState = new EtlProcessState { ConfigurationName = ConfigurationName, TransformationName = TransformationName }; } if (DbId != null) { etlState.LastProcessedEtagPerDbId[DbId] = LastProcessedEtag; } #pragma warning disable 618 if (etlState.LastProcessedEtagPerNode?.Count > 0) { etlState.LastProcessedEtagPerNode[NodeTag] = LastProcessedEtag; } #pragma warning restore 618 etlState.ChangeVector = ChangeVector; etlState.NodeTag = NodeTag; etlState.SkippedTimeSeriesDocs = SkippedTimeSeriesDocs; etlState.LastBatchTime = LastBatchTime; return(context.ReadObject(etlState.ToJson(), GetItemId())); }
protected override BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue) { var subscriptionName = SubscriptionName; if (string.IsNullOrEmpty(subscriptionName)) { subscriptionName = SubscriptionId.ToString(); } if (existingValue == null) { throw new SubscriptionDoesNotExistException($"Subscription with name {subscriptionName} does not exist"); } var subscription = JsonDeserializationCluster.SubscriptionState(existingValue); var topology = record.Topology; var lastResponsibleNode = GetLastResponsibleNode(HasHighlyAvailableTasks, topology, NodeTag); if (topology.WhoseTaskIsIt(RachisState.Follower, subscription, lastResponsibleNode) != NodeTag) { throw new SubscriptionDoesNotBelongToNodeException($"Can't update subscription with name {subscriptionName} by node {NodeTag}, because it's not its task to update this subscription"); } if (ChangeVector == nameof(Constants.Documents.SubscriptionChangeVectorSpecialStates.DoNotChange)) { return(context.ReadObject(existingValue, SubscriptionName)); } if (LastKnownSubscriptionChangeVector != subscription.ChangeVectorForNextBatchStartingPoint) { throw new SubscriptionChangeVectorUpdateConcurrencyException($"Can't acknowledge subscription with name {subscriptionName} due to inconsistency in change vector progress. Probably there was an admin intervention that changed the change vector value. Stored value: {subscription.ChangeVectorForNextBatchStartingPoint}, received value: {LastKnownSubscriptionChangeVector}"); } subscription.ChangeVectorForNextBatchStartingPoint = ChangeVector; subscription.NodeTag = NodeTag; subscription.LastBatchAckTime = LastTimeServerMadeProgressWithDocuments; return(context.ReadObject(subscription.ToJson(), subscriptionName)); }
protected override BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue) { var itemId = GetItemId(); if (existingValue == null) { throw new RachisApplyException($"Subscription with id '{itemId}' does not exist"); } var subscription = JsonDeserializationCluster.SubscriptionState(existingValue); var topology = record.Topology; var lastResponsibleNode = AcknowledgeSubscriptionBatchCommand.GetLastResponsibleNode(HasHighlyAvailableTasks, topology, NodeTag); if (topology.WhoseTaskIsIt(RachisState.Follower, subscription, lastResponsibleNode) != NodeTag) { throw new RachisApplyException($"Can't update subscription with name '{itemId}' by node {NodeTag}, because it's not it's task to update this subscription"); } subscription.LastClientConnectionTime = LastClientConnectionTime; subscription.NodeTag = NodeTag; return(context.ReadObject(subscription.ToJson(), itemId)); }
public static DynamicJsonValue ToJson(ServerStore serverStore, TransactionOperationContext context, RawDatabaseRecord record, long databaseIndex) { var mapping = SnmpDatabase.GetIndexMapping(context, serverStore, record.DatabaseName); var djv = new DynamicJsonValue(); if (mapping.Count == 0) { return(djv); } foreach (var indexName in record.Indexes.Keys) { if (mapping.TryGetValue(indexName, out var index) == false) { continue; } var array = new DynamicJsonArray(); foreach (var field in typeof(Indexes).GetFields()) { var fieldValue = GetFieldValue(field); var databaseOid = string.Format(fieldValue.Oid, databaseIndex); var indexOid = string.Format(databaseOid, index); array.Add(CreateJsonItem(Root + indexOid, fieldValue.Description)); } djv[indexName] = array; } return(djv); }
protected override BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue) { return(null); // it's going to delete the value }
public override unsafe void Execute(ClusterOperationContext context, Table items, long index, RawDatabaseRecord record, RachisState state, out object result) { var resultDict = new Dictionary<string, long>(); var identitiesItems = context.Transaction.InnerTransaction.OpenTable(ClusterStateMachine.IdentitiesSchema, ClusterStateMachine.Identities); foreach (var kvp in Identities) { CompareExchangeCommandBase.GetKeyAndPrefixIndexSlices(context.Allocator, DatabaseName, kvp.Key, index, out var keyTuple, out var indexTuple); using (keyTuple.Scope) using (indexTuple.Scope) using (Slice.External(context.Allocator, keyTuple.Buffer.Ptr, keyTuple.Buffer.Length, out var keySlice)) using (Slice.External(context.Allocator, indexTuple.Buffer.Ptr, indexTuple.Buffer.Length, out var prefixIndexSlice)) { bool isSet; if (Force == false) { isSet = false; if (identitiesItems.SeekOnePrimaryKeyPrefix(keySlice, out var tvr)) { var value = GetValue(tvr); if (value < kvp.Value) isSet = true; } else { using (identitiesItems.Allocate(out var tvb)) { tvb.Add(keySlice); tvb.Add(kvp.Value); tvb.Add(index); tvb.Add(prefixIndexSlice); identitiesItems.Set(tvb); } } } else isSet = true; var keyString = keySlice.ToString().ToLowerInvariant(); resultDict.TryGetValue(keyString, out var oldVal); long newVar; if (isSet) { UpdateTableRow(index, identitiesItems, kvp.Value, keySlice, prefixIndexSlice); newVar = kvp.Value; } else { identitiesItems.SeekOnePrimaryKeyPrefix(keySlice, out var tvr); newVar = GetValue(tvr); } resultDict[keyString] = Math.Max(oldVal, newVar); } } result = resultDict; }
protected override BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue) { throw new NotSupportedException(); }
public override unsafe void Execute(ClusterOperationContext context, Table items, long index, RawDatabaseRecord record, RachisState state, out object result) { long i = 1; var originalName = SubscriptionName; var tryToSetName = true; result = null; var subscriptionId = SubscriptionId ?? index; SubscriptionName = string.IsNullOrEmpty(SubscriptionName) ? subscriptionId.ToString() : SubscriptionName; var baseName = SubscriptionName; if (SubscriptionName.Length > DocumentIdWorker.MaxIdSize) { throw new SubscriptionNameException($"Subscription Name is too long, must be at most {DocumentIdWorker.MaxIdSize} bytes"); } while (tryToSetName) { var subscriptionItemName = SubscriptionState.GenerateSubscriptionItemKeyName(DatabaseName, SubscriptionName); using (Slice.From(context.Allocator, subscriptionItemName, out Slice valueName)) using (Slice.From(context.Allocator, subscriptionItemName.ToLowerInvariant(), out Slice valueNameLowered)) { if (items.ReadByKey(valueNameLowered, out TableValueReader tvr)) { var ptr = tvr.Read(2, out int size); var doc = new BlittableJsonReaderObject(ptr, size, context); var existingSubscriptionState = JsonDeserializationClient.SubscriptionState(doc); if (SubscriptionId != existingSubscriptionState.SubscriptionId) { if (string.IsNullOrEmpty(originalName)) { SubscriptionName = $"{baseName}.{i}"; i++; continue; } throw new RachisApplyException("A subscription could not be modified because the name '" + subscriptionItemName + "' is already in use in a subscription with different Id."); } if (string.IsNullOrEmpty(InitialChangeVector) == false && InitialChangeVector == nameof(Constants.Documents.SubscriptionChangeVectorSpecialStates.DoNotChange)) { InitialChangeVector = existingSubscriptionState.ChangeVectorForNextBatchStartingPoint; } else { AssertValidChangeVector(); if (InitialChangeVector != existingSubscriptionState.ChangeVectorForNextBatchStartingPoint) { // modified by the admin var subscriptionStateTable = context.Transaction.InnerTransaction.OpenTable(ClusterStateMachine.SubscriptionStateSchema, ClusterStateMachine.SubscriptionState); using (SubscriptionConnectionsState.GetDatabaseAndSubscriptionPrefix(context, DatabaseName, subscriptionId, out var prefix)) { using var _ = Slice.External(context.Allocator, prefix, out var prefixSlice); subscriptionStateTable.DeleteByPrimaryKeyPrefix(prefixSlice); } } } } else { AssertValidChangeVector(); } using (var receivedSubscriptionState = context.ReadObject(new SubscriptionState { Query = Query, ChangeVectorForNextBatchStartingPoint = InitialChangeVector, SubscriptionId = subscriptionId, SubscriptionName = SubscriptionName, LastBatchAckTime = null, Disabled = Disabled, MentorNode = MentorNode, LastClientConnectionTime = null }.ToJson(), SubscriptionName)) { ClusterStateMachine.UpdateValue(index, items, valueNameLowered, valueName, receivedSubscriptionState); } tryToSetName = false; } } }
public override unsafe void Execute(ClusterOperationContext context, Table items, long index, RawDatabaseRecord record, RachisState state, out object result) { result = null; var itemKey = SubscriptionState.GenerateSubscriptionItemKeyName(DatabaseName, SubscriptionName); using (Slice.From(context.Allocator, itemKey.ToLowerInvariant(), out Slice valueNameLowered)) { if (items.ReadByKey(valueNameLowered, out TableValueReader tvr) == false) { return; // nothing to do } var ptr = tvr.Read(2, out int size); var doc = new BlittableJsonReaderObject(ptr, size, context); var subscriptionState = JsonDeserializationClient.SubscriptionState(doc); items.DeleteByKey(valueNameLowered); if (string.IsNullOrEmpty(subscriptionState.SubscriptionName) == false) { itemKey = SubscriptionState.GenerateSubscriptionItemKeyName(DatabaseName, subscriptionState.SubscriptionName); using (Slice.From(context.Allocator, itemKey.ToLowerInvariant(), out valueNameLowered)) { items.DeleteByKey(valueNameLowered); } using (SubscriptionConnectionsState.GetDatabaseAndSubscriptionPrefix(context, DatabaseName, subscriptionState.SubscriptionId, out var prefix)) { var subscriptionStateTable = context.Transaction.InnerTransaction.OpenTable(ClusterStateMachine.SubscriptionStateSchema, ClusterStateMachine.SubscriptionState); using var _ = Slice.External(context.Allocator, prefix, out var prefixSlice); subscriptionStateTable.DeleteByPrimaryKeyPrefix(prefixSlice); } } } }
public virtual unsafe void Execute(ClusterOperationContext context, Table items, long index, RawDatabaseRecord record, RachisState state, out object result) { BlittableJsonReaderObject itemBlittable = null; var itemKey = GetItemId(); using (Slice.From(context.Allocator, itemKey.ToLowerInvariant(), out Slice valueNameLowered)) { if (items.ReadByKey(valueNameLowered, out TableValueReader reader)) { var ptr = reader.Read(2, out int size); itemBlittable = new BlittableJsonReaderObject(ptr, size, context); } itemBlittable = GetUpdatedValue(index, record, context, itemBlittable); // if returned null, means, there is nothing to update and we just wanted to delete the value if (itemBlittable == null) { items.DeleteByKey(valueNameLowered); result = GetResult(); return; } // here we get the item key again, in case it was changed (a new entity, etc) itemKey = GetItemId(); } using (Slice.From(context.Allocator, itemKey, out Slice valueName)) using (Slice.From(context.Allocator, itemKey.ToLowerInvariant(), out Slice valueNameLowered)) { ClusterStateMachine.UpdateValue(index, items, valueNameLowered, valueName, itemBlittable); result = GetResult(); } }
public bool ShouldDeleteDatabase(TransactionOperationContext context, string dbName, RawDatabaseRecord rawRecord) { var deletionInProgress = DeletionInProgressStatus.No; var directDelete = rawRecord.DeletionInProgress?.TryGetValue(_serverStore.NodeTag, out deletionInProgress) == true && deletionInProgress != DeletionInProgressStatus.No; if (directDelete == false) { return(false); } if (rawRecord.Topology.Rehabs.Contains(_serverStore.NodeTag)) { // If the deletion was issued form the cluster observer to maintain the replication factor we need to make sure // that all the documents were replicated from this node, therefor the deletion will be called from the replication code. return(false); } var record = rawRecord.MaterializedRecord; context.CloseTransaction(); DeleteDatabase(dbName, deletionInProgress, record); return(true); }
public override unsafe void Execute(ClusterOperationContext context, Table items, long index, RawDatabaseRecord record, RachisState state, out object result) { result = null; var itemKey = SubscriptionState.GenerateSubscriptionItemKeyName(DatabaseName, SubscriptionName); using (Slice.From(context.Allocator, itemKey.ToLowerInvariant(), out Slice valueNameLowered)) { if (items.ReadByKey(valueNameLowered, out TableValueReader tvr) == false) { return; // nothing to do } var ptr = tvr.Read(2, out int size); var doc = new BlittableJsonReaderObject(ptr, size, context); var subscriptionState = JsonDeserializationClient.SubscriptionState(doc); items.DeleteByKey(valueNameLowered); if (string.IsNullOrEmpty(subscriptionState.SubscriptionName) == false) { itemKey = SubscriptionState.GenerateSubscriptionItemKeyName(DatabaseName, subscriptionState.SubscriptionName); using (Slice.From(context.Allocator, itemKey.ToLowerInvariant(), out valueNameLowered)) { items.DeleteByKey(valueNameLowered); } } } }
public override unsafe void Execute(ClusterOperationContext context, Table items, long index, RawDatabaseRecord record, RachisState state, out object result) { result = null; var itemKey = SubscriptionState.GenerateSubscriptionItemKeyName(DatabaseName, SubscriptionName); using (Slice.From(context.Allocator, itemKey.ToLowerInvariant(), out Slice valueNameLowered)) using (Slice.From(context.Allocator, itemKey, out Slice valueName)) { if (items.ReadByKey(valueNameLowered, out var tvr) == false) { throw new SubscriptionDoesNotExistException($"Cannot find subscription {SubscriptionName} @ {DatabaseName}"); } var ptr = tvr.Read(2, out int size); var doc = new BlittableJsonReaderObject(ptr, size, context); var subscriptionState = JsonDeserializationClient.SubscriptionState(doc); subscriptionState.Disabled = Disable; using (var obj = context.ReadObject(subscriptionState.ToJson(), "subscription")) { ClusterStateMachine.UpdateValue(index, items, valueNameLowered, valueName, obj); } } }
public override void Execute(ClusterOperationContext context, Table items, long index, RawDatabaseRecord record, RachisState state, out object result) { base.Execute(context, items, index, record, state, out result); if (IsLegacyCommand()) { return; } ExecuteAcknowledgeSubscriptionBatch(context, index); }
public override unsafe void Execute(ClusterOperationContext context, Table items, long index, RawDatabaseRecord record, RachisState state, out object result) { result = null; var shouldUpdateChangeVector = true; var subscriptionName = SubscriptionName; if (string.IsNullOrEmpty(subscriptionName)) { subscriptionName = SubscriptionId.ToString(); } //insert all docs to voron table. If exists, then batchId will be replaced var subscriptionStateTable = context.Transaction.InnerTransaction.OpenTable(ClusterStateMachine.SubscriptionStateSchema, ClusterStateMachine.SubscriptionState); var itemKey = SubscriptionState.GenerateSubscriptionItemKeyName(DatabaseName, subscriptionName); using (Slice.From(context.Allocator, itemKey.ToLowerInvariant(), out Slice valueNameLowered)) using (Slice.From(context.Allocator, itemKey, out Slice valueName)) { if (items.ReadByKey(valueNameLowered, out var tvr) == false) { throw new RachisApplyException($"Cannot find subscription {subscriptionName} @ {DatabaseName}"); } var ptr = tvr.Read(2, out int size); var existingValue = new BlittableJsonReaderObject(ptr, size, context); if (existingValue == null) { throw new SubscriptionDoesNotExistException($"Subscription with name '{subscriptionName}' does not exist in database '{DatabaseName}'"); } var subscriptionState = JsonDeserializationClient.SubscriptionState(existingValue); var topology = record.Topology; var lastResponsibleNode = AcknowledgeSubscriptionBatchCommand.GetLastResponsibleNode(HasHighlyAvailableTasks, topology, NodeTag); var appropriateNode = topology.WhoseTaskIsIt(RachisState.Follower, subscriptionState, lastResponsibleNode); if (appropriateNode == null && record.DeletionInProgress.ContainsKey(NodeTag)) { throw new DatabaseDoesNotExistException($"Stopping subscription '{subscriptionName}' on node {NodeTag}, because database '{DatabaseName}' is being deleted."); } if (appropriateNode != NodeTag) { throw new SubscriptionDoesNotBelongToNodeException( $"Cannot apply {nameof(AcknowledgeSubscriptionBatchCommand)} for subscription '{subscriptionName}' with id '{SubscriptionId}', on database '{DatabaseName}', on node '{NodeTag}'," + $" because the subscription task belongs to '{appropriateNode ?? "N/A"}'.") { AppropriateNode = appropriateNode }; } if (CurrentChangeVector == nameof(Constants.Documents.SubscriptionChangeVectorSpecialStates.DoNotChange)) { context.ReadObject(existingValue, subscriptionName); shouldUpdateChangeVector = false; } if (subscriptionState.ChangeVectorForNextBatchStartingPoint != PreviouslyRecordedChangeVector) { throw new SubscriptionChangeVectorUpdateConcurrencyException($"Can't record subscription with name '{subscriptionName}' due to inconsistency in change vector progress. Probably there was an admin intervention that changed the change vector value. Stored value: {subscriptionState.ChangeVectorForNextBatchStartingPoint}, received value: {PreviouslyRecordedChangeVector}"); } if (shouldUpdateChangeVector) { subscriptionState.ChangeVectorForNextBatchStartingPoint = ChangeVectorUtils.MergeVectors(CurrentChangeVector, subscriptionState.ChangeVectorForNextBatchStartingPoint); subscriptionState.NodeTag = NodeTag; using (var obj = context.ReadObject(subscriptionState.ToJson(), "subscription")) { ClusterStateMachine.UpdateValue(index, items, valueNameLowered, valueName, obj); } } } foreach (var deletedId in Deleted) { using (SubscriptionConnectionsState.GetDatabaseAndSubscriptionAndDocumentKey(context, DatabaseName, SubscriptionId, deletedId, out var key)) { using var _ = Slice.External(context.Allocator, key, out var keySlice); subscriptionStateTable.DeleteByKey(keySlice); } } foreach (var documentRecord in Documents) { using (SubscriptionConnectionsState.GetDatabaseAndSubscriptionAndDocumentKey(context, DatabaseName, SubscriptionId, documentRecord.DocumentId, out var key)) using (subscriptionStateTable.Allocate(out var tvb)) { using var _ = Slice.External(context.Allocator, key, out var keySlice); using var __ = Slice.From(context.Allocator, documentRecord.ChangeVector, out var changeVectorSlice); tvb.Add(keySlice); tvb.Add(changeVectorSlice); tvb.Add(Bits.SwapBytes(index)); // batch id subscriptionStateTable.Set(tvb); } } foreach (var revisionRecord in Revisions) { using (SubscriptionConnectionsState.GetDatabaseAndSubscriptionAndRevisionKey(context, DatabaseName, SubscriptionId, revisionRecord.Current, out var key)) using (subscriptionStateTable.Allocate(out var tvb)) { using var _ = Slice.External(context.Allocator, key, out var keySlice); using var __ = Slice.From(context.Allocator, revisionRecord.Previous ?? string.Empty, out var changeVectorSlice); tvb.Add(keySlice); tvb.Add(changeVectorSlice); //prev change vector tvb.Add(Bits.SwapBytes(index)); // batch id subscriptionStateTable.Set(tvb); } } }
protected override BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue) { return(context.ReadObject(PeriodicBackupStatus.ToJson(), GetItemId())); }
protected override BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue) { return(context.ReadObject(ExternalReplicationState.ToJson(), GetItemId())); }
public override unsafe void Execute(ClusterOperationContext context, Table items, long index, RawDatabaseRecord record, RachisState state, out object result) { var identitiesItems = context.Transaction.InnerTransaction.OpenTable(ClusterStateMachine.IdentitiesSchema, ClusterStateMachine.Identities); var listResult = new List <long>(); foreach (var identity in Identities) { CompareExchangeCommandBase.GetKeyAndPrefixIndexSlices(context.Allocator, DatabaseName, identity, index, out var keyTuple, out var indexTuple); using (keyTuple.Scope) using (indexTuple.Scope) using (Slice.External(context.Allocator, keyTuple.Buffer.Ptr, keyTuple.Buffer.Length, out var keySlice)) using (Slice.External(context.Allocator, indexTuple.Buffer.Ptr, indexTuple.Buffer.Length, out var prefixIndexSlice)) { long value; if (identitiesItems.ReadByKey(keySlice, out var reader)) { value = GetValue(reader); value += 1; } else { value = 1; } UpdateTableRow(index, identitiesItems, value, keySlice, prefixIndexSlice); listResult.Add(value); } } result = listResult; }
public override unsafe void Execute(ClusterOperationContext context, Table items, long index, RawDatabaseRecord record, RachisState state, out object result) { var identitiesItems = context.Transaction.InnerTransaction.OpenTable(ClusterStateMachine.IdentitiesSchema, ClusterStateMachine.Identities); CompareExchangeCommandBase.GetKeyAndPrefixIndexSlices(context.Allocator, DatabaseName, Prefix, index, out var keyTuple, out var indexTuple); using (keyTuple.Scope) using (indexTuple.Scope) using (Slice.External(context.Allocator, keyTuple.Buffer.Ptr, keyTuple.Buffer.Length, out var keySlice)) using (Slice.External(context.Allocator, indexTuple.Buffer.Ptr, indexTuple.Buffer.Length, out var prefixIndexSlice)) { long value; if (identitiesItems.SeekOnePrimaryKeyPrefix(keySlice, out var entry)) { value = GetValue(entry); value++; } else { value = 1; } UpdateTableRow(index, identitiesItems, value, keySlice, prefixIndexSlice); result = value; } }
protected abstract BlittableJsonReaderObject GetUpdatedValue(long index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue);