Improve version purging

This commit is contained in:
Daniel 2020-11-24 16:11:19 +01:00
parent eb17a5e6b8
commit 823b05d239

View file

@ -338,65 +338,101 @@ func (res *Resource) Blacklist(version string) error {
// Purge deletes old updates, retaining a certain amount, specified by // Purge deletes old updates, retaining a certain amount, specified by
// the keep parameter. Purge will always keep at least 2 versions so // the keep parameter. Purge will always keep at least 2 versions so
// specifying a smaller keep value will have no effect. Note that // specifying a smaller keep value will have no effect.
// blacklisted versions are not counted for the keep parameter. func (res *Resource) Purge(keepExtra int) { //nolint:gocognit
// After purging a new version will be selected.
func (res *Resource) Purge(keep int) {
res.Lock() res.Lock()
defer res.Unlock() defer res.Unlock()
// safeguard // If there is any blacklisted version within the resource, pause purging.
if keep < 2 { // In this case we may need extra available versions beyond what would be
keep = 2 // available after purging.
for _, rv := range res.Versions {
if rv.Blacklisted {
log.Debugf(
"%s: pausing purging of resource %s, as it contains blacklisted items",
res.registry.Name,
rv.resource.Identifier,
)
return
}
} }
// keep versions // Safeguard the amount of extra version to keep.
var validVersions int if keepExtra < 2 {
keepExtra = 2
}
// Search for purge boundary.
var purgeBoundary int
var skippedActiveVersion bool var skippedActiveVersion bool
var skippedSelectedVersion bool var skippedSelectedVersion bool
var purgeFrom int var skippedStableVersion bool
boundarySearch:
for i, rv := range res.Versions { for i, rv := range res.Versions {
// continue to purging? // Check if required versions are already skipped.
if validVersions >= keep && // skip at least <keep> versions switch {
skippedActiveVersion && // skip until active version case !skippedActiveVersion && res.ActiveVersion != nil:
skippedSelectedVersion { // skip until selected version // Skip versions until the active version, if it's set.
purgeFrom = i case !skippedSelectedVersion && res.SelectedVersion != nil:
break // Skip versions until the selected version, if it's set.
case !skippedStableVersion:
// Skip versions until the stable version.
default:
// All required version skipped, set purge boundary.
purgeBoundary = i + keepExtra
break boundarySearch
} }
// keep active version // Check if current instance is a required version.
if !skippedActiveVersion && rv == res.ActiveVersion { if rv == res.ActiveVersion {
skippedActiveVersion = true skippedActiveVersion = true
} }
if rv == res.SelectedVersion {
// keep selected version
if !skippedSelectedVersion && rv == res.SelectedVersion {
skippedSelectedVersion = true skippedSelectedVersion = true
} }
if rv.StableRelease {
// count valid (not blacklisted) versions skippedStableVersion = true
if !rv.Blacklisted {
validVersions++
} }
} }
// check if there is anything to purge // Check if there is anything to purge at all.
if purgeFrom < keep || purgeFrom > len(res.Versions) { if purgeBoundary <= keepExtra || purgeBoundary >= len(res.Versions) {
return return
} }
// purge phase // Purge everything beyond the purge boundary.
for _, rv := range res.Versions[purgeFrom:] { for _, rv := range res.Versions[purgeBoundary:] {
// delete storagePath := rv.storagePath()
err := os.Remove(rv.storagePath()) // Remove resource file.
err := os.Remove(storagePath)
if err != nil { if err != nil {
log.Warningf("%s: failed to purge old resource %s: %s", res.registry.Name, rv.storagePath(), err) log.Warningf("%s: failed to purge resource %s v%s: %s", res.registry.Name, rv.resource.Identifier, rv.VersionNumber, err)
} else {
log.Tracef("%s: purged resource %s v%s", res.registry.Name, rv.resource.Identifier, rv.VersionNumber)
}
// Remove unpacked version of resource.
ext := filepath.Ext(storagePath)
if ext == "" {
// Nothing to do if file does not have an extension.
continue
}
unpackedPath := strings.TrimSuffix(storagePath, ext)
// Remove if it exists, or an error occurs on access.
_, err = os.Stat(unpackedPath)
if err == nil || !os.IsNotExist(err) {
err = os.Remove(unpackedPath)
if err != nil {
log.Warningf("%s: failed to purge unpacked resource %s v%s: %s", res.registry.Name, rv.resource.Identifier, rv.VersionNumber, err)
} else {
log.Tracef("%s: purged unpacked resource %s v%s", res.registry.Name, rv.resource.Identifier, rv.VersionNumber)
}
} }
} }
// remove entries of deleted files
res.Versions = res.Versions[purgeFrom:]
res.selectVersion() // remove entries of deleted files
res.Versions = res.Versions[purgeBoundary:]
} }
func (rv *ResourceVersion) versionedPath() string { func (rv *ResourceVersion) versionedPath() string {