예제 #1
0
        private List <MutateInSpec> CreateMutationSpecs(IAtrRepository atr, string opType, object content, DocumentMetadata?dm = null)
        {
            object userSerializedContent = content;

            if (!(_userDataSerializer is Core.IO.Serializers.DefaultSerializer))
            {
                byte[] bytes = _userDataSerializer.Serialize(content);
                userSerializedContent = DefaultSerializer.Deserialize <object>(bytes) !;
            }

            var specs = new List <MutateInSpec>
            {
                MutateInSpec.Upsert(TransactionFields.TransactionId, _overallContext.TransactionId,
                                    createPath: true, isXattr: true),
                MutateInSpec.Upsert(TransactionFields.AttemptId, _attemptId, createPath: true, isXattr: true),
                MutateInSpec.Upsert(TransactionFields.AtrId, atr.AtrId, createPath: true, isXattr: true),
                MutateInSpec.Upsert(TransactionFields.AtrScopeName, atr.ScopeName, createPath: true, isXattr: true),
                MutateInSpec.Upsert(TransactionFields.AtrBucketName, atr.BucketName, createPath: true, isXattr: true),
                MutateInSpec.Upsert(TransactionFields.AtrCollName, atr.CollectionName, createPath: true, isXattr: true),
                MutateInSpec.Upsert(TransactionFields.Type, opType, createPath: true, isXattr: true),
                MutateInSpec.Upsert(TransactionFields.Crc32, MutationMacro.ValueCRC32c, createPath: true, isXattr: true),
            };

            switch (opType)
            {
            case "remove":
                specs.Add(MutateInSpec.Upsert(TransactionFields.StagedData, new { }, isXattr: true));
                specs.Add(MutateInSpec.Remove(TransactionFields.StagedData, isXattr: true));
                break;

            case "replace":
            case "insert":
                specs.Add(MutateInSpec.Upsert(TransactionFields.StagedData, userSerializedContent, createPath: true, isXattr: true));
                break;
            }

            if (dm != null)
            {
                if (dm.Cas != null)
                {
                    specs.Add(MutateInSpec.Upsert(TransactionFields.PreTxnCas, dm.Cas, createPath: true, isXattr: true));
                }

                if (dm.RevId != null)
                {
                    specs.Add(MutateInSpec.Upsert(TransactionFields.PreTxnRevid, dm.RevId, createPath: true, isXattr: true));
                }

                if (dm.ExpTime != null)
                {
                    specs.Add(MutateInSpec.Upsert(TransactionFields.PreTxnExptime, dm.ExpTime, createPath: true, isXattr: true));
                }
            }

            return(specs);
        }
        public async Task <(ulong updatedCas, MutationToken mutationToken)> MutateStagedRemove(TransactionGetResult doc, IAtrRepository atr)
        {
            // For ExtAllKvCombinations, the Java implementation was updated to write "txn" as one JSON blob instead of multiple MutateInSpecs.
            // Remove is the one where it had to be updated, given that we need to remove the staged data only if it exists.
            var txn = new TransactionXattrs()
            {
                Operation = new StagedOperation()
                {
                    Type = "remove"
                },
                Id = new CompositeId()
                {
                    Transactionid = _overallContext.TransactionId, AttemptId = _attemptId
                },
                AtrRef = new AtrRef()
                {
                    Id = atr.AtrId, ScopeName = atr.ScopeName, BucketName = atr.BucketName, CollectionName = atr.CollectionName
                },
                RestoreMetadata = doc.DocumentMetadata
            };

            var txnAsJObject = Newtonsoft.Json.Linq.JObject.FromObject(txn, _metadataSerializer);

            var specs = new MutateInSpec[]
            {
                MutateInSpec.Upsert(TransactionFields.TransactionInterfacePrefixOnly, txnAsJObject, isXattr: true),
                MutateInSpec.Upsert(TransactionFields.Crc32, MutationMacro.ValueCRC32c, createPath: true, isXattr: true),
            };

            var opts       = GetMutateInOptions(StoreSemantics.Replace).Cas(doc.Cas).CreateAsDeleted(true);
            var updatedDoc = await doc.Collection.MutateInAsync(doc.Id, specs, opts).CAF();

            return(updatedDoc.Cas, updatedDoc.MutationToken);
        }
        public async Task <(ulong updatedCas, MutationToken mutationToken)> MutateStagedReplace(TransactionGetResult doc, object content, IAtrRepository atr, bool accessDeleted)
        {
            if (doc.Cas == 0)
            {
                throw new ArgumentOutOfRangeException("Document CAS should not be wildcard or default when replacing.");
            }

            var specs = CreateMutationSpecs(atr, "replace", content, doc.DocumentMetadata);
            var opts  = GetMutateInOptions(StoreSemantics.Replace).Cas(doc.Cas);

            if (accessDeleted)
            {
                opts.AccessDeleted(true);
            }

            var updatedDoc = await doc.Collection.MutateInAsync(doc.Id, specs, opts).CAF();

            return(updatedDoc.Cas, updatedDoc.MutationToken);
        }
        public async Task <(ulong updatedCas, MutationToken mutationToken)> MutateStagedInsert(ICouchbaseCollection collection, string docId, object content, IAtrRepository atr, ulong?cas = null)
        {
            List <MutateInSpec> specs = CreateMutationSpecs(atr, "insert", content);
            var opts = GetMutateInOptions(StoreSemantics.Insert)
                       .AccessDeleted(true)
                       .CreateAsDeleted(true);

            if (cas.HasValue)
            {
                opts.Cas(cas.Value).StoreSemantics(StoreSemantics.Replace);
            }
            else
            {
                opts.Cas(0);
            }

            var mutateResult = await collection.MutateInAsync(docId, specs, opts).CAF();

            return(mutateResult.Cas, mutateResult.MutationToken);
        }
        public async Task <(ulong updatedCas, MutationToken mutationToken)> MutateStagedReplace(TransactionGetResult doc, object content, IAtrRepository atr, bool accessDeleted)
        {
            _ = await LookupDocumentAsync(doc.Collection, doc.Id);

            Interlocked.Increment(ref _rollingCas);
            return((ulong)_rollingCas, new MutationToken("fake", 1, 2, _rollingCas));
        }
        public Task <(ulong updatedCas, MutationToken mutationToken)> MutateStagedInsert(ICouchbaseCollection collection, string docId, object content, IAtrRepository atr, ulong?cas = null)
        {
            var mockLookupInResult = new Mock <ILookupInResult>(MockBehavior.Strict);

            mockLookupInResult.SetupGet(l => l.IsDeleted).Returns(false);
            mockLookupInResult.SetupGet(l => l.Cas).Returns(5);

            Add(collection, docId, new DocumentLookupResult(docId, null, new JObjectContentWrapper(content), mockLookupInResult.Object, new Components.DocumentMetadata(), collection));
            Interlocked.Increment(ref _rollingCas);
            return(Task.FromResult(((ulong)_rollingCas, new MutationToken("fake", 1, 2, _rollingCas))));
        }