private bool TryGetCompareExchangeKeySlice(LazyStringValue keyLazy, string keyString, out Slice keySlice) { keySlice = default; if (keyLazy != null) { if (keyLazy.Length == 0) { return(false); } var key = CompareExchangeKey.GetStorageKey(_documentsStorage.DocumentDatabase.Name, keyLazy); // we intentionally don't dispose of the scope here, this is being tracked by the references // and will be disposed there. Slice.From(QueryContext.Server.Allocator, key, out keySlice); } else { if (keyString.Length == 0) { return(false); } var key = CompareExchangeKey.GetStorageKey(_documentsStorage.DocumentDatabase.Name, keyString); // we intentionally don't dispose of the scope here, this is being tracked by the references // and will be disposed there. Slice.From(QueryContext.Server.Allocator, key, out keySlice); } return(true); }
public void ValidateAtomicGuard(string id, NonPersistentDocumentFlags nonPersistentDocumentFlags, string changeVector) { if (nonPersistentDocumentFlags != NonPersistentDocumentFlags.None) // replication or engine running an operation, we can skip checking it { return; } if (_parent._documentDatabase.ClusterTransactionId == null) { return; } long indexFromChangeVector = ChangeVectorUtils.GetEtagById(changeVector, _parent._documentDatabase.ClusterTransactionId); if (indexFromChangeVector == 0) { return; } using (_serverStore.ContextPool.AllocateOperationContext(out TransactionOperationContext clusterContext)) using (clusterContext.OpenReadTransaction()) { var guardId = CompareExchangeKey.GetStorageKey(_parent._documentDatabase.Name, ClusterTransactionCommand.GetAtomicGuardKey(id)); var(indexFromCluster, val) = _serverStore.Cluster.GetCompareExchangeValue(clusterContext, guardId); if (indexFromChangeVector != indexFromCluster) { throw new ConcurrencyException( $"Cannot PUT document '{id}' because its change vector's cluster transaction index is set to {indexFromChangeVector} " + $"but the compare exchange guard ('{ClusterTransactionCommand.GetAtomicGuardKey(id)}') is set to {indexFromCluster}") { Id = id }; } } }
private async Task GetCompareExchangeValuesByKey(TransactionOperationContext context, Microsoft.Extensions.Primitives.StringValues keys) { var sw = Stopwatch.StartNew(); var items = new List <(string Key, long Index, BlittableJsonReaderObject Value)>(keys.Count); foreach (var key in keys) { var item = ServerStore.Cluster.GetCompareExchangeValue(context, CompareExchangeKey.GetStorageKey(Database.Name, key)); if (item.Value == null && keys.Count == 1) { HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; return; } items.Add((key, item.Index, item.Value)); } var numberOfResults = 0; long totalDocumentsSizeInBytes = 0; await using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream())) { writer.WriteStartObject(); writer.WriteArray(context, "Results", items, (textWriter, operationContext, item) => { numberOfResults++; totalDocumentsSizeInBytes += item.Value?.Size ?? 0; operationContext.Write(textWriter, new DynamicJsonValue { ["Key"] = item.Key, ["Value"] = item.Value, ["Index"] = item.Index }); }); writer.WriteEndObject(); } AddPagingPerformanceHint(PagingOperationType.CompareExchange, nameof(GetCompareExchangeValuesByKey), HttpContext.Request.QueryString.Value, numberOfResults, keys.Count, sw.ElapsedMilliseconds, totalDocumentsSizeInBytes); }
private void GetCompareExchangeValues(TransactionOperationContext context) { var sw = Stopwatch.StartNew(); var start = GetStart(); var pageSize = GetPageSize(); var startsWithKey = GetStringQueryString("startsWith", false); var items = ServerStore.Cluster.GetCompareExchangeValuesStartsWith(context, Database.Name, CompareExchangeKey.GetStorageKey(Database.Name, startsWithKey), start, pageSize); var numberOfResults = 0; using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream())) { writer.WriteStartObject(); writer.WriteArray(context, "Results", items, (textWriter, operationContext, item) => { numberOfResults++; operationContext.Write(textWriter, new DynamicJsonValue { [nameof(CompareExchangeListItem.Key)] = item.Key.Key, [nameof(CompareExchangeListItem.Value)] = item.Value, [nameof(CompareExchangeListItem.Index)] = item.Index }); }); writer.WriteEndObject(); } AddPagingPerformanceHint(PagingOperationType.CompareExchange, nameof(ClusterStateMachine.GetCompareExchangeValuesStartsWith), HttpContext.Request.QueryString.Value, numberOfResults, pageSize, sw.ElapsedMilliseconds); }
internal void Materialize() { if (_includedKeys == null || _includedKeys.Count == 0) { return; } if (_serverContext == null) { if (_throwWhenServerContextIsAllocated) { throw new InvalidOperationException("Cannot allocate new server context during materialization of compare exchange includes."); } _releaseContext = _database.ServerStore.ContextPool.AllocateOperationContext(out _serverContext); _serverContext.OpenReadTransaction(); } foreach (var includedKey in _includedKeys) { if (string.IsNullOrEmpty(includedKey)) { continue; } var value = _database.ServerStore.Cluster.GetCompareExchangeValue(_serverContext, CompareExchangeKey.GetStorageKey(_database.Name, includedKey)); if (Results == null) { Results = new Dictionary <string, CompareExchangeValue <BlittableJsonReaderObject> >(StringComparer.OrdinalIgnoreCase); } Results.Add(includedKey, new CompareExchangeValue <BlittableJsonReaderObject>(includedKey, value.Index, value.Value)); } }