예제 #1
0
        private unsafe void FillCountOfResultsAndIndexEtag(QueryResultServerSide <Document> resultToFill, QueryMetadata query, QueryOperationContext context)
        {
            var bufferSize    = 3;
            var hasCounters   = query.HasCounterSelect || query.CounterIncludes != null;
            var hasTimeSeries = query.HasTimeSeriesSelect || query.TimeSeriesIncludes != null;
            var hasCmpXchg    = query.HasCmpXchg || query.HasCmpXchgSelect || query.HasCmpXchgIncludes;

            if (hasCounters)
            {
                bufferSize++;
            }
            if (hasTimeSeries)
            {
                bufferSize++;
            }
            if (hasCmpXchg)
            {
                bufferSize++;
            }

            var collection = query.CollectionName;
            var buffer     = stackalloc long[bufferSize];

            // If the query has include or load, it's too difficult to check the etags for just the included collections,
            // it's easier to just show etag for all docs instead.
            if (collection == Constants.Documents.Collections.AllDocumentsCollection ||
                query.HasIncludeOrLoad)
            {
                var numberOfDocuments = Database.DocumentsStorage.GetNumberOfDocuments(context.Documents);
                buffer[0] = DocumentsStorage.ReadLastDocumentEtag(context.Documents.Transaction.InnerTransaction);
                buffer[1] = DocumentsStorage.ReadLastTombstoneEtag(context.Documents.Transaction.InnerTransaction);
                buffer[2] = numberOfDocuments;

                if (hasCounters)
                {
                    buffer[3] = DocumentsStorage.ReadLastCountersEtag(context.Documents.Transaction.InnerTransaction);
                }

                if (hasTimeSeries)
                {
                    buffer[hasCounters ? 4 : 3] = DocumentsStorage.ReadLastTimeSeriesEtag(context.Documents.Transaction.InnerTransaction);
                }

                resultToFill.TotalResults = (int)numberOfDocuments;
            }
            else
            {
                var collectionStats = Database.DocumentsStorage.GetCollection(collection, context.Documents);
                buffer[0] = Database.DocumentsStorage.GetLastDocumentEtag(context.Documents.Transaction.InnerTransaction, collection);
                buffer[1] = Database.DocumentsStorage.GetLastTombstoneEtag(context.Documents.Transaction.InnerTransaction, collection);
                buffer[2] = collectionStats.Count;

                if (hasCounters)
                {
                    buffer[3] = Database.DocumentsStorage.CountersStorage.GetLastCounterEtag(context.Documents, collection);
                }

                if (hasTimeSeries)
                {
                    buffer[hasCounters ? 4 : 3] = Database.DocumentsStorage.TimeSeriesStorage.GetLastTimeSeriesEtag(context.Documents, collection);
                }

                resultToFill.TotalResults = (int)collectionStats.Count;
            }

            if (hasCmpXchg)
            {
                buffer[bufferSize - 1] = Database.ServerStore.Cluster.GetLastCompareExchangeIndexForDatabase(context.Server, Database.Name);
            }

            resultToFill.ResultEtag = (long)Hashing.XXHash64.Calculate((byte *)buffer, sizeof(long) * (uint)bufferSize);
            resultToFill.NodeTag    = Database.ServerStore.NodeTag;
        }