/// <summary> /// Conditionally removes a bucket as long as it is empty of key/value pairs. /// Condenses any surrounding buckets if necessary /// </summary> internal async Task <bool> PruneBucketAsync(HashManifest manifest, long bucketIndex, string bucketName, HashBucket bucket, CancellationToken cancellationToken) { if (bucket.Head.HasValue || bucket.Tail.HasValue) { return(false); } await StateManager.RemoveStateAsync(bucketName, cancellationToken); if (bucket.Previous.HasValue) { var previousBucketName = IndexToBucket(bucket.Previous.Value); var previousBucket = await StateManager.GetStateAsync <HashBucket>(previousBucketName, cancellationToken); previousBucket.Next = bucket.Next; await StateManager.SetStateAsync(previousBucketName, previousBucket, cancellationToken); } if (bucket.Next.HasValue) { var nextBucketName = IndexToBucket(bucket.Next.Value); var nextBucket = await StateManager.GetStateAsync <HashBucket>(nextBucketName, cancellationToken); nextBucket.Previous = bucket.Previous; await StateManager.SetStateAsync(nextBucketName, nextBucket, cancellationToken); } if (manifest.Head == bucketIndex) { manifest.Head = bucket.Next; } if (manifest.Tail == bucketIndex) { manifest.Tail = bucket.Previous; } return(true); }
protected static long NextIndex(HashManifest manifest) { return(manifest.Next++); }