/// <summary>
 /// Gets whether or not we should increment the skip count based on the rid of the document.
 /// </summary>
 /// <param name="currentItemProducer">The current document producer.</param>
 /// <returns>Whether or not we should increment the skip count.</returns>
 private bool ShouldIncrementSkipCount(ItemProducer currentItemProducer)
 {
     // If we are not at the beginning of the page and we saw the same rid again.
     return(!currentItemProducer.IsAtBeginningOfPage &&
            string.Equals(
                this.previousRid,
                new OrderByQueryResult(currentItemProducer.Current).Rid,
                StringComparison.Ordinal));
 }
        /// <summary>
        /// Initializes a new instance of the ItemProducerTree class.
        /// </summary>
        /// <param name="queryContext">query context.</param>
        /// <param name="querySpecForInit">query spec init.</param>
        /// <param name="partitionKeyRange">The partition key range.</param>
        /// <param name="createRetryPolicyFunc">Callback to create a retry policy.</param>
        /// <param name="produceAsyncCompleteCallback">Callback to invoke once a fetch finishes.</param>
        /// <param name="itemProducerTreeComparer">Comparer to determine, which tree to produce from.</param>
        /// <param name="equalityComparer">Comparer to see if we need to return the continuation token for a partition.</param>
        /// <param name="deferFirstPage">Whether or not to defer fetching the first page.</param>
        /// <param name="collectionRid">The collection to drain from.</param>
        /// <param name="initialPageSize">The initial page size.</param>
        /// <param name="initialContinuationToken">The initial continuation token.</param>
        public ItemProducerTree(
            CosmosQueryContext queryContext,
            SqlQuerySpec querySpecForInit,
            PartitionKeyRange partitionKeyRange,
            Func <IDocumentClientRetryPolicy> createRetryPolicyFunc,
            Action <ItemProducerTree, int, double, QueryMetrics, long, CancellationToken> produceAsyncCompleteCallback,
            IComparer <ItemProducerTree> itemProducerTreeComparer,
            IEqualityComparer <CosmosElement> equalityComparer,
            bool deferFirstPage,
            string collectionRid,
            long initialPageSize            = 50,
            string initialContinuationToken = null)
        {
            if (queryContext == null)
            {
                throw new ArgumentNullException($"{nameof(queryContext)}");
            }

            if (itemProducerTreeComparer == null)
            {
                throw new ArgumentNullException($"{nameof(itemProducerTreeComparer)}");
            }

            if (createRetryPolicyFunc == null)
            {
                throw new ArgumentNullException($"{nameof(createRetryPolicyFunc)}");
            }

            if (produceAsyncCompleteCallback == null)
            {
                throw new ArgumentNullException($"{nameof(produceAsyncCompleteCallback)}");
            }

            if (itemProducerTreeComparer == null)
            {
                throw new ArgumentNullException($"{nameof(itemProducerTreeComparer)}");
            }

            if (equalityComparer == null)
            {
                throw new ArgumentNullException($"{nameof(equalityComparer)}");
            }

            if (string.IsNullOrEmpty(collectionRid))
            {
                throw new ArgumentException($"{nameof(collectionRid)} can not be null or empty.");
            }

            this.root = new ItemProducer(
                queryContext,
                querySpecForInit,
                partitionKeyRange,
                createRetryPolicyFunc,
                (itemProducer, itemsBuffered, resourceUnitUsage, queryMetrics, requestLength, token) => produceAsyncCompleteCallback(this, itemsBuffered, resourceUnitUsage, queryMetrics, requestLength, token),
                equalityComparer,
                initialPageSize,
                initialContinuationToken);

            this.queryClient    = queryContext.QueryClient;
            this.children       = new PriorityQueue <ItemProducerTree>(itemProducerTreeComparer, true);
            this.deferFirstPage = deferFirstPage;
            this.collectionRid  = collectionRid;
            this.createItemProducerTreeCallback = ItemProducerTree.CreateItemProducerTreeCallback(
                queryContext,
                querySpecForInit,
                createRetryPolicyFunc,
                produceAsyncCompleteCallback,
                itemProducerTreeComparer,
                equalityComparer,
                deferFirstPage,
                collectionRid,
                initialPageSize);
            this.executeWithSplitProofingSemaphore = new SemaphoreSlim(1, 1);
        }