Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
            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
                                  };
                        }
                    }
            }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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));
            }
        }