Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Tree view of our folders: https://i.imgur.com/lY8TLAf.png
- ---------------------------------
- --! @file clear-backups.lua
- --! @brief Manages the backups for the Helioss.co backups server
- --! @detail
- -- Our backup management is simple,
- -- The older they are, the less we keep.
- -- It is logarithmic, meaning we keep a backup from 1 hour ago, then 2h,
- -- then 4h, 8h, 16h, 32h, 64h, ...
- --
- -- To determine these timepoints we look at the oldest backup's age in seconds
- -- and successively divide it by 2 until we reach under 3600 seconds (1h)
- ---------------------------------
- local lfs = require("lfs")
- --! @brief Given a number N, and an array of numbers A, returns the closest
- -- number to N in A
- --! @param number
- --! @param array
- --! @return array[match] the closest number to N in A, its index, the delta between N and A[index]
- --! @return match its index
- --! @return minDelta the difference between N and array[match]
- local function closestNumber(number, array)
- local match = nil
- local minDelta = math.huge
- for i,v in pairs(array) do
- local delta = math.abs(number - v)
- if delta < minDelta then
- match = i
- minDelta = delta
- end
- end
- return array[match], match, minDelta
- end
- --! @brief Find the biggest number in a table
- --! @param array Any table
- --! @return max The number
- --! @return maxI its index
- local function findMax(array)
- local max, maxI = nil, nil
- for i,v in pairs(array) do
- if max == nil or v > max then
- maxI, max = i, v
- end
- end
- return max, maxI
- end
- --! @brief Successively divide n by 2 until minimumToReach is reached then
- --! returns each iteration.
- --! @param n Starting point
- --! @param minimumToReach Number
- --! @param result Private, keep to nil
- --! @result result A table in the form {n, n/2, n/4, n/8, ...}
- local function succesiveDivBy2Results(n, minimumToReach, result)
- if result == nil then result = {} end
- table.insert(result, n)
- if (n <= minimumToReach) then
- return result
- end
- return succesiveDivBy2Results(math.floor(n/2), minimumToReach, result)
- end
- --! @brief Returns a subset of `array` composed of the elements that are closest to the
- --! numbers in `references`
- --! @param array A table of numbers
- --! @param references A table of numbers
- --! @result toKeep A subset of `array` composed of the elements that are closest to the
- --! numbers in `references`
- --! @result toDelete The elements of `array` that didn't make it into `toKeep`
- --! @result fittingPoints For internal use
- --! @example {1,2,3,4,5}, {3,8} => {3,5}, {1,2,4} (in spirit)
- local function mostFittingPoints(array, references)
- local bestDeltas = {}
- local fittingPoints = {}
- for i,v in pairs(array) do
- local match, matchI, delta = closestNumber(v, references)
- if bestDeltas[match] == nil or bestDeltas[match] > delta then
- bestDeltas[match] = delta
- fittingPoints[matchI] = {i=i,v=v,r=match}
- end
- end
- local toKeep = {}
- for _,v in pairs(fittingPoints) do
- toKeep[v.i] = v.v
- end
- local toDelete = {}
- for i,v in pairs(array) do
- if toKeep[i] == nil then
- toDelete[i] = v
- end
- end
- return toKeep, toDelete, fittingPoints
- end
- for server in lfs.dir("backups") do
- if server == "." or server == ".." then
- -- nothing
- else
- print(server .. ": ")
- -- Gather all the backups for each server, with their age
- local files = {}
- local now = os.time()
- for backup in lfs.dir("backups/" .. server) do
- if backup == "." or backup == ".." then
- -- nothing
- else
- local file = "backups/" .. server .. "/" .. backup
- local attr = {}
- local result = lfs.attributes(file)
- local lapse = math.abs(now - result.modification)
- files[file] = lapse
- end
- end
- -- not important
- local success, err = lfs.mkdir("archived/backups/" .. server)
- if not success and err ~= "File exists" then
- print(err)
- return
- end
- -- Separates the backups we should keep from the backups we can delete
- local oldest = findMax(files)
- if oldest ~= nil then
- local ref = succesiveDivBy2Results(oldest, 3600)
- -- {n, n/2, n/4, n/8, ..., ~3600}
- local keep, delete, _debug = mostFittingPoints(files, ref)
- -- {
- -- fileName=ageInSeconds,
- -- fileName=ageInSeconds,
- -- ...
- -- }
- print("", "Keep:")
- for i,v in pairs(keep) do print("", "", i, v) end
- print("", "Delete:")
- for i,v in pairs(delete) do
- print("", "", i, v)
- -- Move to ~/archived/backups/{server}/{file}
- local success, err = os.rename(i, "archived/"..i)
- if not success then
- print(i, err)
- end
- end
- --print("[debug]")
- --for i,v in pairs(_debug) do print("", v.i, v.v, v.r) end
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement