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); }
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); }
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); } } }