public long?GetCounterValue(DocumentsOperationContext context, string docId, string counterName) { var table = new Table(CountersSchema, context.Transaction.InnerTransaction); using (GetCounterPartialKey(context, docId, counterName, out var key)) { long?value = null; foreach (var result in table.SeekByPrimaryKeyPrefix(key, Slices.Empty, 0)) { value = value ?? 0; var pCounterDbValue = result.Value.Reader.Read((int)CountersTable.Value, out var size); Debug.Assert(size == sizeof(long)); try { value = checked (value + *(long *)pCounterDbValue); } catch (OverflowException e) { CounterOverflowException.ThrowFor(docId, counterName, e); } } return(value); } }
private static void GetCounterValue(DocumentsOperationContext context, DocumentDatabase database, string docId, string counterName, bool addFullValues, CountersDetail result) { var fullValues = addFullValues ? new Dictionary <string, long>() : null; long?value = null; foreach (var(cv, val) in database.DocumentsStorage.CountersStorage.GetCounterValues(context, docId, counterName)) { value = value ?? 0; try { value = checked (value + val); } catch (OverflowException e) { CounterOverflowException.ThrowFor(docId, counterName, e); } if (addFullValues) { fullValues[cv] = val; } } if (value == null) { return; } if (result.Counters == null) { result.Counters = new List <CounterDetail>(); } result.Counters.Add(new CounterDetail { DocumentId = docId, CounterName = counterName, TotalValue = value.Value, CounterValues = fullValues }); }
public string IncrementCounter(DocumentsOperationContext context, string documentId, string collection, string name, long delta, out bool exists) { if (context.Transaction == null) { DocumentPutAction.ThrowRequiresTransaction(); Debug.Assert(false);// never hit } var collectionName = _documentsStorage.ExtractCollectionName(context, collection); var table = GetCountersTable(context.Transaction.InnerTransaction, collectionName); using (GetCounterKey(context, documentId, name, context.Environment.Base64Id, out var counterKey)) { var value = delta; exists = table.ReadByKey(counterKey, out var existing); if (exists) { var prev = *(long *)existing.Read((int)CountersTable.Value, out var size); Debug.Assert(size == sizeof(long)); try { value = checked (prev + delta); //inc } catch (OverflowException e) { CounterOverflowException.ThrowFor(documentId, name, prev, delta, e); } } RemoveTombstoneIfExists(context, documentId, name); var etag = _documentsStorage.GenerateNextEtag(); var result = ChangeVectorUtils.TryUpdateChangeVector(_documentDatabase.ServerStore.NodeTag, _documentsStorage.Environment.Base64Id, etag, string.Empty); using (Slice.From(context.Allocator, result.ChangeVector, out var cv)) using (DocumentIdWorker.GetStringPreserveCase(context, name, out Slice nameSlice)) using (DocumentIdWorker.GetStringPreserveCase(context, collectionName.Name, out Slice collectionSlice)) using (table.Allocate(out TableValueBuilder tvb)) { tvb.Add(counterKey); tvb.Add(nameSlice); tvb.Add(Bits.SwapBytes(etag)); tvb.Add(value); tvb.Add(cv); tvb.Add(collectionSlice); tvb.Add(context.TransactionMarkerOffset); table.Set(tvb); } UpdateMetrics(counterKey, name, result.ChangeVector, collection); context.Transaction.AddAfterCommitNotification(new CounterChange { ChangeVector = result.ChangeVector, DocumentId = documentId, Name = name, Type = exists ? CounterChangeTypes.Increment : CounterChangeTypes.Put, Value = value }); return(result.ChangeVector); } }