Skip to content

Commit

Permalink
bugs fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
zavla committed Dec 16, 2019
1 parent 41c5b61 commit 0c534b3
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Expand Up @@ -11,7 +11,7 @@
"mode": "auto",
"program": "${fileDirname}",
"env": {},
"args": ["--delete_archived","1"],
"args": ["-withArchiveAttr","-config","./testdata/config.json", "-dryrun"],
"cwd": "${fileDirname}"
}
]
Expand Down
86 changes: 62 additions & 24 deletions DeleteArchivedBackups.go
@@ -1,7 +1,7 @@
package main

import (
"dblist"
"dblist/v2"
"flag"
"log"
"os"
Expand All @@ -18,57 +18,95 @@ func main() {
// {"path":"g:/ShebB", "Filename":"buh_prom8", "Days":1},
// ]

delArchived := flag.Bool("delete_archived", false, "deletes files with attribute archived set")
delArchived := flag.Bool("withArchiveAttr", false, "deletes files with attribute archived set")
configfile := flag.String("config", "", "full config file name (lists databases files groups)")
dryRun := flag.Bool("dryrun", false, "dry run (doesn't actually delete files)")
keepLastNcopies := flag.Uint("keeplastN", 2, "keep recent N copies")

flag.Parse()
if *configfile == "" {
flag.Usage()
os.Exit(1)
}
conf := dblist.ReadConfig(*configfile)
conf, err := dblist.ReadConfig(*configfile)
if err != nil {
log.Printf("Config file read error: %s", err)
return
}
// sort conf by databases names to allow sort.Search by database name
sort.Slice(conf, func(i, j int) bool {
if conf[i].Filename < conf[j].Filename {
return true
}
return false
})

// collect unique suffixes
suffixes := make(map[string]int)
for _, val := range conf {
if _, has := suffixes[val.Suffix]; !has {
suffixes[val.Suffix] = 0
}

}
// transform a map into slice
uniquesuffixes := make([]string, 0, len(suffixes))
for suf := range suffixes {
uniquesuffixes = append(uniquesuffixes, suf)
}
// gets unique folders names
unique := dblist.GetUniquePaths(conf)

// get files of each folder
files := dblist.ReadFilesFromPaths(unique)

lastfilesmap := make(map[string][]dblist.FileInfoWin)

if *delArchived {
for dir, slice := range files {
lastfilesslice := dblist.GetLastFilesGroupedByFunc(slice, dblist.GroupFunc)
// make lastfilesslice descending to use sort.Search
sort.Slice(lastfilesslice, func(i, j int) bool {
return lastfilesslice[i].Name() > lastfilesslice[j].Name() //DESC
})
lastfilesmap[dir] = lastfilesslice
}
deleteArchivedFiles(files, lastfilesmap)
} else {
flag.Usage()
// We append to dontDeleteLastbackupfiles files that should not be deleted: last files and file that have no config line for them.
for dir, filesindir := range files {
// We get most recent files. The will not be deleted.
dontDeleteLastbackupfiles := dblist.GetLastFilesGroupedByFunc(filesindir, dblist.GroupFunc, uniquesuffixes, *keepLastNcopies)

notinConfigFile := dblist.GetFilesNotCoveredByConfigFile(filesindir, conf, dblist.GroupFunc, uniquesuffixes)

// some actual files may not be in config file
dontDeleteLastbackupfiles = append(dontDeleteLastbackupfiles, notinConfigFile...)

// sort dontDeleteLastbackupfiles descending to use sort.Search later.
// We exploite descending order to find most recent backup files.
sort.Slice(dontDeleteLastbackupfiles, func(i, j int) bool {
return dontDeleteLastbackupfiles[i].Name() > dontDeleteLastbackupfiles[j].Name() //DESC
})
lastfilesmap[dir] = dontDeleteLastbackupfiles
}
deleteArchivedFiles(files, lastfilesmap, *delArchived, *dryRun)

}

// deleteArchivedFiles needs exceptfiles be sorted descending
func deleteArchivedFiles(files, exceptfiles map[string][]dblist.FileInfoWin) {
// deleteArchivedFiles needs exceptfiles to be sorted descending.
// Exceptfiles sorted descending because it was used to get most recent backup file name earlier in the code.
func deleteArchivedFiles(files, exceptfiles map[string][]dblist.FileInfoWin, delArchived, dryrun bool) {
for dir, slice := range files { // for every dir
for _, finf := range slice { // for every file in dir
if !finf.IsDir() { // dont touch subdirs and not archived
if (finf.WinAttr & syscall.FILE_ATTRIBUTE_ARCHIVE) == 0 { // no ARCHIVE means file has been archived
// No ARCHIVE atrribute means that file has been archived or copied somewhere.
// If file has Archive attribute you need a flag delArchived == true
if (finf.WinAttr&syscall.FILE_ATTRIBUTE_ARCHIVE) == 0 ||
delArchived { // or you insist on deleting files with Archive attr set

// search if file in question is in the exception list
curmap := exceptfiles[dir] // exceptfiles is descending
pos := sort.Search(len(curmap), func(i int) bool { // bin search
// search if current file is in the exception list
curmap := exceptfiles[dir] // exceptfiles is already sorted descending
pos := sort.Search(len(curmap), func(i int) bool { // we use bin search
return curmap[i].Name() <= finf.Name() // <= for the descending slice

})
if pos < len(curmap) && curmap[pos].Name() == finf.Name() {
// found
continue // file should not be deleted. this is the last file in the group
continue // file should not be deleted. this is the last file in the group of backup files
}
fullFilename := filepath.Join(dir, finf.Name())
log.Printf("deleting file %s\n", fullFilename)
if true { //DEBUG
log.Printf("rm %s\n", fullFilename)
if !dryrun {
err := os.Remove(fullFilename)
if err != nil {
log.Printf("%s\n", err)
Expand Down
10 changes: 10 additions & 0 deletions README.md
@@ -0,0 +1,10 @@
## A DBA backup files tool set. ##

The utility DeleteArchivedBackups is used in databases backups operations.
Sometimes a DBA needs to keep a directory with different backup files rotated.
That is when a DBA needs to delete marked backup files. Or when one needs to deleted all but serveral last files.

Files must obey naming scheme.
Database name in file name and file suffix define a file group.
Every file group may have its most recent files and outdated files.
DeleteArchivedBackups deals with this task.
7 changes: 7 additions & 0 deletions testdata/config.json
@@ -0,0 +1,7 @@
[
{"path":"j:/b", "Filename":"BC_Cold", "suffix":"-differ.dif","Days":1},
{"path":"j:/b", "Filename":"нашипост", "suffix":"-FULL.bak","Days":5},
{"path":"j:/b", "Filename":"from_84_Dirs", "suffix":".rar","Days":7},
{"path":"g:/Shebb", "Filename":"buh_canvest", "suffix":"-differ.rar","Days":1},
{"path":"g:/Shebb", "Filename":"buh_canvest", "suffix":"-FULL.rar","Days":1}
]

0 comments on commit 0c534b3

Please sign in to comment.