Пример #1
0
        private CollectionName PutCounters(UpdateStep step, DocumentsOperationContext context, HashSet <string> dbIds, Dictionary <string, List <CounterDetail> > allCountersBatch, string docId)
        {
            string collection = null;

            using (DocumentIdWorker.GetSliceFromId(context, docId, out Slice lowerId))
            {
                var docsTable = new Table(DocsSchema, step.ReadTx);
                if (docsTable.ReadByKey(lowerId, out var tvr))
                {
                    using (var doc = new BlittableJsonReaderObject(tvr.Read((int)DocumentsTable.Data, out int size), size, context))
                    {
                        collection = CollectionName.GetCollectionName(doc);
                    }
                }
                else
                {
                    // document does not exist
                    return(null);
                }
            }

            var collectionName = new CollectionName(collection);

            using (DocumentIdWorker.GetSliceFromId(context, docId, out Slice documentKeyPrefix, separator: SpecialChars.RecordSeparator))
            {
                var maxNumberOfCountersPerGroup = Math.Max(32, 2048 / (dbIds.Count * 32 + 1));// rough estimate
                var orderedKeys = allCountersBatch.OrderBy(x => x.Key).ToList();
                var listOfDbIds = dbIds.ToList();

                for (int i = 0; i < orderedKeys.Count / maxNumberOfCountersPerGroup + (orderedKeys.Count % maxNumberOfCountersPerGroup == 0 ? 0 : 1); i++)
                {
                    var currentBatch = allCountersBatch.Skip(maxNumberOfCountersPerGroup * i).Take(maxNumberOfCountersPerGroup);
                    using (var data = WriteNewCountersDocument(context, listOfDbIds, currentBatch))
                    {
                        var etag         = step.DocumentsStorage.GenerateNextEtag();
                        var changeVector = ChangeVectorUtils.NewChangeVector(
                            step.DocumentsStorage.DocumentDatabase.ServerStore.NodeTag, etag, _dbId);

                        var table = step.DocumentsStorage.CountersStorage.GetCountersTable(step.WriteTx, collectionName);
                        data.TryGet(CountersStorage.Values, out BlittableJsonReaderObject values);
                        BlittableJsonReaderObject.PropertyDetails prop = default;
                        values.GetPropertyByIndex(0, ref prop);
                        using (table.Allocate(out TableValueBuilder tvb))
                        {
                            using (Slice.From(context.Allocator, changeVector, out var cv))
                                using (DocumentIdWorker.GetStringPreserveCase(context, collectionName.Name, out Slice collectionSlice))
                                    using (context.Allocator.Allocate(documentKeyPrefix.Size + prop.Name.Size, out var counterKeyBuffer))
                                        using (Slice.From(context.Allocator, prop.Name, out var nameSlice))
                                            using (CreateCounterKeySlice(context, counterKeyBuffer, documentKeyPrefix, nameSlice, out var counterKeySlice))
                                            {
                                                if (i == 0)
                                                {
                                                    tvb.Add(documentKeyPrefix);
                                                }
                                                else
                                                {
                                                    tvb.Add(counterKeySlice);
                                                }

                                                tvb.Add(Bits.SwapBytes(etag));
                                                tvb.Add(cv);
                                                tvb.Add(data.BasePointer, data.Size);
                                                tvb.Add(collectionSlice);
                                                tvb.Add(context.GetTransactionMarker());

                                                table.Set(tvb);
                                            }
                        }
                    }
                }
            }

            return(collectionName);
        }
Пример #2
0
        private unsafe bool AboutToReadPropertyNameInMetadataUnlikely(IJsonParser reader, JsonParserState state, out bool aboutToReadPropertyName)
        {
            aboutToReadPropertyName = true;

            switch (state.StringSize)
            {
            default:     // accept this property
            {
                return(true);
            }

            case -1:     // IgnoreProperty
            {
                if (reader.Read() == false)
                {
                    _state = State.IgnoreProperty;
                    aboutToReadPropertyName = false;
                    return(true);
                }
                if (state.CurrentTokenType == JsonParserToken.StartArray ||
                    state.CurrentTokenType == JsonParserToken.StartObject)
                {
                    ThrowInvalidMetadataProperty(state, reader);
                }
                break;
            }

            case 3:     // @id
                if (state.StringBuffer[0] != (byte)'@' ||
                    *(short *)(state.StringBuffer + 1) != 25705)
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                if (reader.Read() == false)
                {
                    _state = State.ReadingId;
                    aboutToReadPropertyName = false;
                    return(true);
                }
                if (state.CurrentTokenType != JsonParserToken.String)
                {
                    ThrowExpectedFieldTypeOfString(Constants.Documents.Metadata.Id, state, reader);
                }
                Id = CreateLazyStringValueFromParserState(state);
                break;

            case 5:     // @etag
                if (state.StringBuffer[0] != (byte)'@' ||
                    *(int *)(state.StringBuffer + 1) != 1734440037)
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                if (ReadFirstEtagOfLegacyRevision &&
                    (NonPersistentFlags & NonPersistentDocumentFlags.LegacyRevision) == NonPersistentDocumentFlags.LegacyRevision)
                {
                    if (_firstEtagOfLegacyRevision == null)
                    {
                        if (reader.Read() == false)
                        {
                            _state = State.ReadingFirstEtagOfLegacyRevision;
                            aboutToReadPropertyName = false;
                            return(true);
                        }
                        if (state.CurrentTokenType != JsonParserToken.String)
                        {
                            ThrowExpectedFieldTypeOfString("@etag", state, reader);
                        }
                        _firstEtagOfLegacyRevision = LegacyEtag = CreateLazyStringValueFromParserState(state);
                        ChangeVector = ChangeVectorUtils.NewChangeVector("RV", ++_legacyRevisionsCount, new Guid(_firstEtagOfLegacyRevision).ToBase64Unpadded());
                        break;
                    }

                    ChangeVector = ChangeVectorUtils.NewChangeVector("RV", ++_legacyRevisionsCount, new Guid(_firstEtagOfLegacyRevision).ToBase64Unpadded());
                }

                if (ReadLegacyEtag)
                {
                    if (reader.Read() == false)
                    {
                        _state = State.ReadingEtag;
                        aboutToReadPropertyName = false;
                        return(true);
                    }

                    if (state.CurrentTokenType != JsonParserToken.String)
                    {
                        ThrowExpectedFieldTypeOfString("@etag", state, reader);
                    }
                    LegacyEtag = CreateLazyStringValueFromParserState(state);
                    break;
                }

                goto case -1;

            case 6:     // @flags
                if (state.StringBuffer[0] != (byte)'@' ||
                    *(int *)(state.StringBuffer + 1) != 1734437990 ||
                    state.StringBuffer[1 + sizeof(int)] != (byte)'s')
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                if (reader.Read() == false)
                {
                    _state = State.ReadingFlags;
                    aboutToReadPropertyName = false;
                    return(true);
                }
                if (state.CurrentTokenType != JsonParserToken.String)
                {
                    ThrowExpectedFieldTypeOfString(Constants.Documents.Metadata.Flags, state, reader);
                }
                Flags = ReadFlags(state);
                break;

            case 12:     // @index-score
                if (state.StringBuffer[0] != (byte)'@' ||
                    *(long *)(state.StringBuffer + 1) != 7166121427196997225 ||
                    *(short *)(state.StringBuffer + 1 + sizeof(long)) != 29295 ||
                    state.StringBuffer[1 + sizeof(long) + sizeof(short)] != (byte)'e')
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                goto case -1;

            case 13:     //Last-Modified
                if (*(long *)state.StringBuffer != 7237087983830262092 ||
                    *(int *)(state.StringBuffer + sizeof(long)) != 1701406313 ||
                    state.StringBuffer[12] != (byte)'d')
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                goto case -1;

            case 14:
                if (state.StringBuffer[0] == (byte)'@')
                {
                    // @change-vector
                    if (*(long *)(state.StringBuffer + 1) == 8515573965335390307 &&
                        *(int *)(state.StringBuffer + 1 + sizeof(long)) == 1869898597 &&
                        state.StringBuffer[1 + sizeof(long) + sizeof(int)] == (byte)'r')
                    {
                        if (reader.Read() == false)
                        {
                            _state = State.ReadingChangeVector;
                            aboutToReadPropertyName = false;
                            return(true);
                        }
                        if (state.CurrentTokenType != JsonParserToken.String)
                        {
                            ThrowExpectedFieldTypeOfString(Constants.Documents.Metadata.ChangeVector, state, reader);
                        }
                        ChangeVector = CreateLazyStringValueFromParserState(state);
                        break;
                    }

                    // @last-modified
                    if (*(long *)(state.StringBuffer + 1) == 7237123168202350956 &&
                        *(int *)(state.StringBuffer + 1 + sizeof(long)) == 1701406313 &&
                        state.StringBuffer[1 + sizeof(long) + sizeof(int)] == (byte)'d')
                    {
                        if (reader.Read() == false)
                        {
                            _state = State.ReadingLastModified;
                            aboutToReadPropertyName = false;
                            return(true);
                        }
                        if (state.CurrentTokenType != JsonParserToken.String)
                        {
                            ThrowExpectedFieldTypeOfString(Constants.Documents.Metadata.LastModified, state, reader);
                        }
                        LastModified = ReadDateTime(state, reader, State.ReadingLastModified);
                        break;
                    }
                }

                aboutToReadPropertyName = true;
                return(true);

            case 15:     //Raven-Read-Only
                if (*(long *)state.StringBuffer != 7300947898092904786 ||
                    *(int *)(state.StringBuffer + sizeof(long)) != 1328374881 ||
                    *(short *)(state.StringBuffer + sizeof(long) + sizeof(int)) != 27758 ||
                    state.StringBuffer[14] != (byte)'y')
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                goto case -1;

            case 17:     //Raven-Entity-Name --> @collection
                if (*(long *)state.StringBuffer != 7945807069737017682 ||
                    *(long *)(state.StringBuffer + sizeof(long)) != 7881666780093245812 ||
                    state.StringBuffer[16] != (byte)'e')
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                var collection = _metadataCollections;
                state.StringBuffer      = collection.AllocatedMemoryData.Address;
                state.StringSize        = collection.Size;
                aboutToReadPropertyName = true;
                return(true);

            case 19:     //Raven-Last-Modified
                if (*(long *)state.StringBuffer != 7011028672080929106 ||
                    *(long *)(state.StringBuffer + sizeof(long)) != 7379539893622240371 ||
                    *(short *)(state.StringBuffer + sizeof(long) + sizeof(long)) != 25961 ||
                    state.StringBuffer[18] != (byte)'d')
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                if (reader.Read() == false)
                {
                    _state = State.ReadingLegacyLastModified;
                    aboutToReadPropertyName = false;
                    return(true);
                }

                if (state.CurrentTokenType != JsonParserToken.String)
                {
                    ThrowExpectedFieldTypeOfString(LegacyLastModified, state, reader);
                }
                LastModified = ReadDateTime(state, reader, State.ReadingLegacyLastModified);
                break;

            case 21:     //Raven-Expiration-Date
                if (*(long *)state.StringBuffer != 8666383010116297042 ||
                    *(long *)(state.StringBuffer + sizeof(long)) != 7957695015158966640 ||
                    *(short *)(state.StringBuffer + sizeof(long) + sizeof(long)) != 17453 ||
                    state.StringBuffer[20] != (byte)'e')
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                var expires = _metadataExpires;
                state.StringBuffer      = expires.AllocatedMemoryData.Address;
                state.StringSize        = expires.Size;
                aboutToReadPropertyName = true;
                return(true);

            case 23:     //Raven-Document-Revision
                if (*(long *)state.StringBuffer != 8017583188798234962 ||
                    *(long *)(state.StringBuffer + sizeof(long)) != 5921517102558967139 ||
                    *(int *)(state.StringBuffer + sizeof(long) + sizeof(long)) != 1936291429 ||
                    *(short *)(state.StringBuffer + sizeof(long) + sizeof(long) + sizeof(int)) != 28521 ||
                    state.StringBuffer[22] != (byte)'n')
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                goto case -1;

            case 24:     //Raven-Replication-Source
                if (*(long *)state.StringBuffer != 7300947898092904786 ||
                    *(long *)(state.StringBuffer + sizeof(long)) != 8028075772393122928 ||
                    *(long *)(state.StringBuffer + sizeof(long) + sizeof(long)) != 7305808869229538670)
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                goto case -1;

            case 25:     //Raven-Replication-Version OR Raven-Replication-History
                if (*(long *)state.StringBuffer != 7300947898092904786 ||
                    *(long *)(state.StringBuffer + sizeof(long)) != 8028075772393122928)
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                var value    = *(long *)(state.StringBuffer + sizeof(long) + sizeof(long));
                var lastByte = state.StringBuffer[24];
                if ((value != 8028074745928232302 || lastByte != (byte)'n') &&
                    (value != 8245937481775066478 || lastByte != (byte)'y'))
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                var isReplicationHistory = lastByte == (byte)'y';
                if (reader.Read() == false)
                {
                    _verifyStartArray       = isReplicationHistory;
                    _state                  = isReplicationHistory ? State.IgnoreArray : State.IgnoreProperty;
                    aboutToReadPropertyName = false;
                    return(true);
                }

                // Raven-Replication-History is an array
                if (isReplicationHistory)
                {
                    if (state.CurrentTokenType != JsonParserToken.StartArray)
                    {
                        ThrowInvalidReplicationHistoryType(state, reader);
                    }

                    do
                    {
                        if (reader.Read() == false)
                        {
                            _state = State.IgnoreArray;
                            aboutToReadPropertyName = false;
                            return(true);
                        }
                    } while (state.CurrentTokenType != JsonParserToken.EndArray);
                }
                else if (state.CurrentTokenType == JsonParserToken.StartArray ||
                         state.CurrentTokenType == JsonParserToken.StartObject)
                {
                    ThrowInvalidMetadataProperty(state, reader);
                }
                break;

            case 29:     //Non-Authoritative-Information
                if (*(long *)state.StringBuffer != 7526769800038477646 ||
                    *(long *)(state.StringBuffer + sizeof(long)) != 8532478930943832687 ||
                    *(long *)(state.StringBuffer + sizeof(long) + sizeof(long)) != 7886488383206796645 ||
                    *(int *)(state.StringBuffer + sizeof(long) + sizeof(long) + sizeof(long)) != 1869182049 ||
                    state.StringBuffer[28] != (byte)'n')
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                goto case -1;

            case 30:     //Raven-Document-Parent-Revision OR Raven-Document-Revision-Status
                if (*(long *)state.StringBuffer != 8017583188798234962)
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                if ((*(long *)(state.StringBuffer + sizeof(long)) != 5777401914483111267 ||
                     *(long *)(state.StringBuffer + sizeof(long) + sizeof(long)) != 7300947924012593761 ||
                     *(int *)(state.StringBuffer + sizeof(long) + sizeof(long) + sizeof(long)) != 1769171318 ||
                     *(short *)(state.StringBuffer + sizeof(long) + sizeof(long) + sizeof(long) + sizeof(int)) != 28271) &&
                    (*(long *)(state.StringBuffer + sizeof(long)) != 5921517102558967139 ||
                     *(long *)(state.StringBuffer + sizeof(long) + sizeof(long)) != 3273676477843469925 ||
                     *(int *)(state.StringBuffer + sizeof(long) + sizeof(long) + sizeof(long)) != 1952543827 ||
                     *(short *)(state.StringBuffer + sizeof(long) + sizeof(long) + sizeof(long) + sizeof(int)) != 29557))
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                var isRevisionStatusProperty = state.StringBuffer[29] == 's';
                if (reader.Read() == false)
                {
                    _state = isRevisionStatusProperty ? State.IgnoreRevisionStatusProperty : State.IgnoreProperty;
                    aboutToReadPropertyName = false;
                    return(true);
                }

                if (state.CurrentTokenType == JsonParserToken.StartArray ||
                    state.CurrentTokenType == JsonParserToken.StartObject)
                {
                    ThrowInvalidMetadataProperty(state, reader);
                }

                if (isRevisionStatusProperty)
                {
                    switch (CreateLazyStringValueFromParserState(state))
                    {
                    case LegacyHasRevisionsDocumentState:
                        NonPersistentFlags |= NonPersistentDocumentFlags.LegacyHasRevisions;
                        break;

                    case LegacyRevisionState:
                        NonPersistentFlags |= NonPersistentDocumentFlags.LegacyRevision;
                        break;
                    }
                }

                break;

            case 32:     //Raven-Replication-Merged-History
                if (*(long *)state.StringBuffer != 7300947898092904786 ||
                    *(long *)(state.StringBuffer + sizeof(long)) != 8028075772393122928 ||
                    *(long *)(state.StringBuffer + sizeof(long) + sizeof(long)) != 7234302117464059246 ||
                    *(long *)(state.StringBuffer + sizeof(long) + sizeof(long) + sizeof(long)) != 8751179571877464109)
                {
                    aboutToReadPropertyName = true;
                    return(true);
                }

                goto case -1;
            }
            return(false);
        }
Пример #3
0
        private void DeleteCounter(UpdateStep step, LazyStringValue tombstoneKey, DocumentsOperationContext context)
        {
            var(docId, counterName) = ExtractDocIdAndNameFromCounterTombstone(context, tombstoneKey);

            using (docId)
                using (counterName)
                    using (DocumentIdWorker.GetLowerIdSliceAndStorageKey(context, docId, out Slice lowerId, out _))
                    {
                        string collection = null;

                        var docsTable = new Table(DocsSchema, step.ReadTx);
                        if (docsTable.ReadByKey(lowerId, out var tvr))
                        {
                            using (var doc = new BlittableJsonReaderObject(tvr.Read((int)DocumentsTable.Data, out int size), size, context))
                            {
                                collection = CollectionName.GetCollectionName(doc);
                            }
                        }

                        var collectionName = new CollectionName(collection);
                        var table          = step.DocumentsStorage.CountersStorage.GetCountersTable(step.WriteTx, collectionName);

                        if (table.ReadByKey(lowerId, out var existing) == false)
                        {
                            return;
                        }

                        // (int)CountersTable.Data = 3
                        var data = new BlittableJsonReaderObject(existing.Read(3, out int oldSize), oldSize, context);

                        if (data.TryGet(CountersStorage.Values, out BlittableJsonReaderObject counters) == false ||
                            counters.TryGetMember(counterName, out object counterToDelete) == false ||
                            counterToDelete is LazyStringValue) // already deleted
                        {
                            return;
                        }

                        var deleteCv = step.DocumentsStorage.CountersStorage.GenerateDeleteChangeVectorFromRawBlob(data, counterToDelete as BlittableJsonReaderObject.RawBlob);
                        counters.Modifications = new DynamicJsonValue(counters)
                        {
                            [counterName] = deleteCv
                        };

                        using (var old = data)
                        {
                            data = context.ReadObject(data, null, BlittableJsonDocumentBuilder.UsageMode.ToDisk);
                        }

                        var newEtag         = step.DocumentsStorage.GenerateNextEtag();
                        var newChangeVector = ChangeVectorUtils.NewChangeVector(step.DocumentsStorage.DocumentDatabase.ServerStore.NodeTag, newEtag, _dbId);
                        using (data)
                            using (Slice.From(context.Allocator, newChangeVector, out var cv))
                                using (DocumentIdWorker.GetStringPreserveCase(context, collectionName.Name, out Slice collectionSlice))
                                    using (table.Allocate(out TableValueBuilder tvb))
                                    {
                                        tvb.Add(lowerId);
                                        tvb.Add(Bits.SwapBytes(newEtag));
                                        tvb.Add(cv);
                                        tvb.Add(data.BasePointer, data.Size);
                                        tvb.Add(collectionSlice);
                                        tvb.Add(context.GetTransactionMarker());

                                        table.Set(tvb);
                                    }
                    }
        }