public static CompareExchangeValue <T> GetSingleValue(BlittableJsonReaderObject item, bool materializeMetadata, DocumentConventions conventions)
        {
            if (item == null)
            {
                return(null);
            }

            if (item.TryGet(nameof(CompareExchangeValue <T> .Key), out string key) == false)
            {
                throw new InvalidDataException("Response is invalid. Key is missing.");
            }
            if (item.TryGet(nameof(CompareExchangeValue <T> .Index), out long index) == false)
            {
                throw new InvalidDataException("Response is invalid. Index is missing.");
            }
            if (item.TryGet(nameof(CompareExchangeValue <T> .Value), out BlittableJsonReaderObject raw) == false)
            {
                throw new InvalidDataException("Response is invalid. Value is missing.");
            }

            var type = typeof(T);

            if (raw == null)
            {
                return(new CompareExchangeValue <T>(key, index, default));
            }

            MetadataAsDictionary metadata = null;

            if (raw.TryGet(Constants.Documents.Metadata.Key, out BlittableJsonReaderObject bjro) && bjro != null)
            {
                metadata = materializeMetadata == false
                    ? new MetadataAsDictionary(bjro)
                    : MetadataAsDictionary.MaterializeFromBlittable(bjro);
            }

            if (type.IsPrimitive || type == typeof(string))
            {
                // simple
                raw.TryGet(Constants.CompareExchange.ObjectFieldName, out T value);
                return(new CompareExchangeValue <T>(key, index, value, metadata));
            }

            if (type == typeof(BlittableJsonReaderObject))
            {
                if (raw.TryGetMember(Constants.CompareExchange.ObjectFieldName, out object rawValue) == false)
                {
                    return(new CompareExchangeValue <T>(key, index, default, metadata));
Beispiel #2
0
        public async Task StoreAsync(object entity, string id, IMetadataDictionary metadata = null)
        {
            if (Interlocked.CompareExchange(ref _concurrentCheck, 1, 0) == 1)
            {
                throw new InvalidOperationException("Bulk Insert store methods cannot be executed concurrently.");
            }

            try
            {
                VerifyValidId(id);

                if (_stream == null)
                {
                    await WaitForId().ConfigureAwait(false);
                    await EnsureStream().ConfigureAwait(false);
                }

                if (_bulkInsertExecuteTask.IsFaulted)
                {
                    try
                    {
                        await _bulkInsertExecuteTask.ConfigureAwait(false);
                    }
                    catch (Exception e)
                    {
                        await ThrowBulkInsertAborted(e).ConfigureAwait(false);
                    }
                }

                if (metadata == null)
                {
                    metadata = new MetadataAsDictionary();
                }

                if (metadata.ContainsKey(Constants.Documents.Metadata.Collection) == false)
                {
                    var collection = _requestExecutor.Conventions.GetCollectionName(entity);
                    if (collection != null)
                    {
                        metadata.Add(Constants.Documents.Metadata.Collection, collection);
                    }
                }

                if (metadata.ContainsKey(Constants.Documents.Metadata.RavenClrType) == false)
                {
                    var clrType = _requestExecutor.Conventions.GetClrTypeName(entity.GetType());
                    if (clrType != null)
                    {
                        metadata[Constants.Documents.Metadata.RavenClrType] = clrType;
                    }
                }

                if (_first == false)
                {
                    _currentWriter.Write(',');
                }

                _first = false;
                try
                {
                    _currentWriter.Write("{\"Id\":\"");
                    WriteId(_currentWriter, id);
                    _currentWriter.Write("\",\"Type\":\"PUT\",\"Document\":");

                    if (_customEntitySerializer == null || _customEntitySerializer(entity, metadata, _currentWriter) == false)
                    {
                        using (var json = EntityToBlittable.ConvertEntityToBlittable(entity, _conventions, _context,
                                                                                     _defaultSerializer, new DocumentInfo
                        {
                            MetadataInstance = metadata
                        }))

                        {
                            _currentWriter.Flush();
                            json.WriteJsonTo(_currentWriter.BaseStream);
                        }
                    }

                    _currentWriter.Write("}");
                    _currentWriter.Flush();

                    if (_currentWriter.BaseStream.Position > _maxSizeInBuffer ||
                        _asyncWrite.IsCompleted)
                    {
                        await _asyncWrite.ConfigureAwait(false);

                        var tmp = _currentWriter;
                        _currentWriter    = _backgroundWriter;
                        _backgroundWriter = tmp;
                        _currentWriter.BaseStream.SetLength(0);
                        ((MemoryStream)tmp.BaseStream).TryGetBuffer(out var buffer);
                        _asyncWrite = _requestBodyStream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count, _token);
                    }
                }
                catch (Exception e)
                {
                    var error = await GetExceptionFromOperation().ConfigureAwait(false);

                    if (error != null)
                    {
                        throw error;
                    }

                    await ThrowOnUnavailableStream(id, e).ConfigureAwait(false);
                }
            }
            finally
            {
                Interlocked.CompareExchange(ref _concurrentCheck, 0, 1);
            }

            void WriteId(StreamWriter writer, string input)
            {
                for (var i = 0; i < input.Length; i++)
                {
                    var c = input[i];
                    if (c == '"')
                    {
                        if (i == 0 || input[i - 1] != '\\')
                        {
                            writer.Write("\\");
                        }
                    }

                    writer.Write(c);
                }
            }
        }
        public async Task CanAddManyCompareExchangeWithExpirationAndEditExpiration(int count)
        {
            using var server = GetNewServer();
            using (var store = GetDocumentStore(new Options
            {
                Server = server
            }))
            {
                var expiry                 = DateTime.Now.AddMinutes(2);
                var compareExchanges       = new Dictionary <string, User>();
                var compareExchangeIndexes = new Dictionary <string, long>();
                for (int i = 0; i < count; i++)
                {
                    var rnd  = new Random(DateTime.Now.Millisecond);
                    var user = new User {
                        Name = new string(Enumerable.Repeat(_chars, 10).Select(s => s[rnd.Next(s.Length)]).ToArray())
                    };
                    var key = $"{new string(Enumerable.Repeat(_chars, 10).Select(s => s[rnd.Next(s.Length)]).ToArray())}{i}";
                    compareExchanges[key] = user;
                    using (var session = store.OpenAsyncSession(new SessionOptions {
                        TransactionMode = TransactionMode.ClusterWide
                    }))
                    {
                        var result = session.Advanced.ClusterTransaction.CreateCompareExchangeValue(key, user);
                        result.Metadata[Constants.Documents.Metadata.Expires] = expiry;

                        await session.SaveChangesAsync();

                        compareExchangeIndexes[key] = result.Index;
                    }
                }
                await AssertCompareExchanges(compareExchanges, store, expiry);

                expiry = DateTime.Now.AddMinutes(4);
                foreach (var kvp in compareExchanges)
                {
                    var metadata = new MetadataAsDictionary {
                        [Constants.Documents.Metadata.Expires] = expiry
                    };
                    await store.Operations.SendAsync(new PutCompareExchangeValueOperation <User>(kvp.Key, kvp.Value, compareExchangeIndexes[kvp.Key], metadata));
                }
                await AssertCompareExchanges(compareExchanges, store, expiry);

                server.ServerStore.Observer.Time.UtcDateTime = () => DateTime.UtcNow.AddMinutes(3);

                Thread.Sleep(count == 10 ? 1000 : 3000);

                var stats = await store.Maintenance.SendAsync(new GetDetailedStatisticsOperation());

                Assert.Equal(count, stats.CountOfCompareExchange);

                server.ServerStore.Observer.Time.UtcDateTime = () => DateTime.UtcNow.AddMinutes(5);
                var val = await WaitForValueAsync(async() =>
                {
                    var stats = await store.Maintenance.SendAsync(new GetDetailedStatisticsOperation());
                    return(stats.CountOfCompareExchange);
                }, 0);

                Assert.Equal(0, val);
            }
        }
Beispiel #4
0
        public async Task StoreAsync(object entity, string id, IMetadataDictionary metadata = null)
        {
            VerifyValidId(id);

            if (_stream == null)
            {
                await WaitForId().ConfigureAwait(false);
                await EnsureStream().ConfigureAwait(false);
            }

            if (metadata == null)
            {
                metadata = new MetadataAsDictionary();
            }
            if (metadata.ContainsKey(Constants.Documents.Metadata.Collection) == false)
            {
                var collection = _requestExecutor.Conventions.GetCollectionName(entity);
                metadata.Add(Constants.Documents.Metadata.Collection, collection);
            }

            if (_first == false)
            {
                _currentWriter.Write(',');
            }
            _first = false;
            try
            {
                _currentWriter.Write("{'Id':'");
                _currentWriter.Write(id);
                _currentWriter.Write("','Type':'PUT','Document':");

                if (_customEntitySerializer == null || _customEntitySerializer(entity, _currentWriter) == false)
                {
                    _defaultSerializer.Serialize(_currentWriter, entity);
                }

                _currentWriter.Flush();
                _currentWriter.BaseStream.Position--;
                _currentWriter.Write(",'@metadata':");

                if (_customMetadataSerializer == null || _customMetadataSerializer(entity, _currentWriter) == false)
                {
                    _defaultSerializer.Serialize(_currentWriter, metadata);
                }

                _currentWriter.Write("}}");
                _currentWriter.Flush();
                if (_currentWriter.BaseStream.Position > _maxSizeInBuffer ||
                    _asyncWrite.IsCompleted)
                {
                    await _asyncWrite.ConfigureAwait(false);

                    var tmp = _currentWriter;
                    _currentWriter    = _backgroundWriter;
                    _backgroundWriter = tmp;
                    _currentWriter.BaseStream.SetLength(0);
                    ((MemoryStream)tmp.BaseStream).TryGetBuffer(out var buffer);
                    _asyncWrite = _requestBodyStream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count, _token);
                }
            }
            catch (Exception e)
            {
                var error = await GetExceptionFromOperation().ConfigureAwait(false);

                if (error != null)
                {
                    throw error;
                }
                await ThrowOnUnavailableStream(id, e).ConfigureAwait(false);
            }
        }
Beispiel #5
0
        public async Task AsyncExample()
        {
            using (var documentStore = new DocumentStore())
            {
                #region metadata_1
                // Create some metadata
                var cmpxchgMetadata = new MetadataAsDictionary {
                    ["Year"] = "2020"
                };

                // Create/update the compare exchange value "best"
                await documentStore.Operations.SendAsync(
                    new PutCompareExchangeValueOperation <User>(
                        "best",
                        new User {
                    Name = "Alice"
                },
                        0,
                        cmpxchgMetadata));

                #endregion

                // -Include examples-

                #region include_load
                using (IDocumentSession session = documentStore.OpenSession())
                {
                    // Load a user document, include the compare exchange value
                    // with the key equal to the user's Name field
                    var user = session.Load <User>("users/1-A",
                                                   includes => includes.IncludeCompareExchangeValue(
                                                       x => x.Name));

                    // Getting the compare exchange value does not require
                    // another call to the server
                    var value = session.Advanced.ClusterTransaction
                                .GetCompareExchangeValue <string>(user.Name);
                }
                #endregion

                #region include_load_async
                using (IAsyncDocumentSession session = documentStore.OpenAsyncSession())
                {
                    // Load a user document, include the compare exchange value
                    // with the key equal to the user's Name field
                    var user = await session.LoadAsync <User>("users/1-A",
                                                              includes => includes.IncludeCompareExchangeValue(
                                                                  x => x.Name));

                    // Getting the compare exchange value does not require
                    // another call to the server
                    var value = await session.Advanced.ClusterTransaction
                                .GetCompareExchangeValueAsync <string>(user.Name);
                }
                #endregion

                using (IDocumentSession session = documentStore.OpenSession())
                {
                    #region include_linq_query
                    var users = session.Query <User>()
                                .Include(builder => builder.IncludeCompareExchangeValue(x => x.Name))
                                .ToList();

                    List <CompareExchangeValue <string> > compareExchangeValues = null;

                    // Getting the compare exchange values does not require
                    // additional calls to the server
                    foreach (User u in users)
                    {
                        compareExchangeValues.Add(session.Advanced.ClusterTransaction
                                                  .GetCompareExchangeValue <string>(u.Name));
                    }
                    #endregion
                }

                using (IDocumentSession session = documentStore.OpenSession())
                {
                    #region include_raw_query
                    // First method: from body of query
                    var users1 = session.Advanced
                                 .RawQuery <User>(@"
                            from Users as u
                            select u
                            include cmpxchg(u.Name)"
                                                  )
                                 .ToList();

                    List <CompareExchangeValue <string> > compareExchangeValues1 = null;

                    // Getting the compare exchange values does not require
                    // additional calls to the server
                    foreach (User u in users1)
                    {
                        compareExchangeValues1.Add(session.Advanced.ClusterTransaction
                                                   .GetCompareExchangeValue <string>(u.Name));
                    }


                    // Second method: from a JavaScript function
                    var users2 = session.Advanced
                                 .RawQuery <User>(@"
                            declare function includeCEV(user) {
                                includes.cmpxchg(user.Name);
                                return user;
                            }

                            from Users as u
                            select includeCEV(u)"
                                                  )
                                 .ToList();
                    // Note that includeCEV() returns the same User
                    // entity it received, without modifying it

                    List <CompareExchangeValue <string> > compareExchangeValues2 = null;

                    // Does not require calls to the server
                    foreach (User u in users2)
                    {
                        compareExchangeValues2.Add(session.Advanced.ClusterTransaction
                                                   .GetCompareExchangeValue <string>(u.Name));
                    }
                    #endregion
                }
            }
        }
Beispiel #6
0
        public async Task StoreAsync(object entity, string id, IMetadataDictionary metadata = null)
        {
            using (ConcurrencyCheck())
            {
                VerifyValidId(id);

                await ExecuteBeforeStore().ConfigureAwait(false);

                if (metadata == null)
                {
                    metadata = new MetadataAsDictionary();
                }

                if (metadata.ContainsKey(Constants.Documents.Metadata.Collection) == false)
                {
                    var collection = _requestExecutor.Conventions.GetCollectionName(entity);
                    if (collection != null)
                    {
                        metadata.Add(Constants.Documents.Metadata.Collection, collection);
                    }
                }

                if (metadata.ContainsKey(Constants.Documents.Metadata.RavenClrType) == false)
                {
                    var clrType = _requestExecutor.Conventions.GetClrTypeName(entity);
                    if (clrType != null)
                    {
                        metadata[Constants.Documents.Metadata.RavenClrType] = clrType;
                    }
                }

                EndPreviousCommandIfNeeded();

                try
                {
                    if (_first == false)
                    {
                        WriteComma();
                    }

                    _first             = false;
                    _inProgressCommand = CommandType.None;

                    _currentWriter.Write("{\"Id\":\"");
                    WriteString(id);
                    _currentWriter.Write("\",\"Type\":\"PUT\",\"Document\":");

                    await FlushIfNeeded().ConfigureAwait(false);

                    if (_customEntitySerializer == null || _customEntitySerializer(entity, metadata, _currentWriter) == false)
                    {
                        using (var json = _conventions.Serialization.DefaultConverter.ToBlittable(entity, metadata, _context, _defaultSerializer))
                            json.WriteJsonTo(_currentWriter.BaseStream);
                    }

                    _currentWriter.Write('}');
                }
                catch (Exception e)
                {
                    await HandleErrors(id, e).ConfigureAwait(false);
                }
            }
        }