package drive import ( "github.com/alcionai/clues" "github.com/alcionai/corso/src/pkg/control" ) var ( errHitLimit = clues.New("hit limiter limits") errHitCollectionLimit = clues.New("hit item limits within the current collection") ) type driveEnumerationStats struct { numPages int numAddedFiles int numContainers int numBytes int64 } func newPagerLimiter(opts control.Options) *pagerLimiter { res := &pagerLimiter{limits: opts.PreviewLimits} if res.limits.MaxContainers == 0 { res.limits.MaxContainers = defaultPreviewMaxContainers } if res.limits.MaxItemsPerContainer == 0 { res.limits.MaxItemsPerContainer = defaultPreviewMaxItemsPerContainer } if res.limits.MaxItems == 0 { res.limits.MaxItems = defaultPreviewMaxItems } if res.limits.MaxBytes == 0 { res.limits.MaxBytes = defaultPreviewMaxBytes } if res.limits.MaxPages == 0 { res.limits.MaxPages = defaultPreviewMaxPages } return res } type pagerLimiter struct { limits control.PreviewItemLimits } func (l pagerLimiter) effectiveLimits() control.PreviewItemLimits { return l.limits } func (l pagerLimiter) enabled() bool { return l.limits.Enabled } // sizeLimit returns the total number of bytes this backup should try to // contain. func (l pagerLimiter) sizeLimit() int64 { return l.limits.MaxBytes } // atItemLimit returns true if the limiter is enabled and has reached the limit // for individual items added to collections for this backup. func (l pagerLimiter) atItemLimit(stats *driveEnumerationStats) bool { return l.enabled() && (stats.numAddedFiles >= l.limits.MaxItems || stats.numBytes >= l.limits.MaxBytes) } // atContainerItemsLimit returns true if the limiter is enabled and the current // number of items is above the limit for the number of items for a container // for this backup. func (l pagerLimiter) atContainerItemsLimit(numItems int) bool { return l.enabled() && numItems >= l.limits.MaxItemsPerContainer } // atPageLimit returns true if the limiter is enabled and the number of // pages processed so far is beyond the limit for this backup. func (l pagerLimiter) atPageLimit(stats *driveEnumerationStats) bool { return l.enabled() && stats.numPages >= l.limits.MaxPages } // atLimit returns true if the limiter is enabled and meets any of the // conditions for max items, containers, etc for this backup. func (l pagerLimiter) atLimit(stats *driveEnumerationStats) bool { return l.enabled() && (l.atItemLimit(stats) || stats.numContainers >= l.limits.MaxContainers || stats.numPages >= l.limits.MaxPages) } // --------------------------------------------------------------------------- // Used by the tree version limit handling // --------------------------------------------------------------------------- // hitPageLimit returns true if the limiter is enabled and the number of // pages processed so far is beyond the limit for this backup. func (l pagerLimiter) hitPageLimit(pageCount int) bool { return l.enabled() && pageCount >= l.limits.MaxPages } // hitContainerLimit returns true if the limiter is enabled and the number of // unique containers added so far is beyond the limit for this backup. func (l pagerLimiter) hitContainerLimit(containerCount int) bool { return l.enabled() && containerCount >= l.limits.MaxContainers } // hitItemLimit returns true if the limiter is enabled and has reached the limit // for unique items added to collections for this backup. func (l pagerLimiter) hitItemLimit(itemCount int) bool { return l.enabled() && itemCount >= l.limits.MaxItems } // alreadyHitTotalBytesLimit returns true if the limiter is enabled and has reached the limit // for the accumulated byte size of all items (the file contents, not the item metadata) // added to collections for this backup. func (l pagerLimiter) alreadyHitTotalBytesLimit(i int64) bool { return l.enabled() && i > l.limits.MaxBytes } // willStepOverBytesLimit returns true if the limiter is enabled and the provided addition // of bytes is greater than the limit plus some padding (to ensure we can always hit // the limit). func (l pagerLimiter) willStepOverBytesLimit(current, addition int64) bool { if !l.enabled() { return false } limitPlusPadding := int64(float64(l.limits.MaxBytes) * 1.03) return (current + addition) > limitPlusPadding }