Skip to content

Instantly share code, notes, and snippets.

@michael1011
Created July 11, 2023 09:10
Show Gist options
  • Save michael1011/a8820682ad6d1f06b8d57dd53ae4d626 to your computer and use it in GitHub Desktop.
Save michael1011/a8820682ad6d1f06b8d57dd53ae4d626 to your computer and use it in GitHub Desktop.
LND Compactor
package main
import (
"encoding/binary"
"errors"
"fmt"
"github.com/urfave/cli/v2"
"os"
"strconv"
"time"
)
var readCommand = &cli.Command{
Name: "read",
Category: "Compact",
ArgsUsage: "file",
Usage: "Read the last compaction date",
Action: read,
}
func read(ctx *cli.Context) error {
file, err := readFileParam(ctx)
if err != nil {
return err
}
date, err := lastCompactionDate(file)
if err != nil {
return err
}
fmt.Printf("Date: %s\n", date.String())
fmt.Printf("Unix: %d\n", date.Unix())
return nil
}
var writeCommand = &cli.Command{
Name: "write",
Category: "Compact",
ArgsUsage: "file [date_unix]",
Usage: "Write the last compaction date; current date if not specified",
Action: write,
}
func write(ctx *cli.Context) error {
file, err := readFileParam(ctx)
if err != nil {
return err
}
date := time.Now()
if ctx.Args().Len() == 2 {
secs, err := strconv.ParseInt(ctx.Args().Get(1), 10, 64)
if err != nil {
return fmt.Errorf("could not parse date_unix: %s", err)
}
date = time.Unix(secs, 0)
}
return updateLastCompactionDate(file, date)
}
func readFileParam(ctx *cli.Context) (string, error) {
if ctx.Args().Len() == 0 {
return "", errors.New("missing file param")
}
return ctx.Args().First(), nil
}
/*
From https://github.com/lightningnetwork/lnd/blob/287b0ac2191c92e348bf640b13d9fef213cc2100/kvdb/backend.go#L213
*/
var byteOrder = binary.BigEndian
// fileExists returns true if the file exists, and false otherwise.
func fileExists(path string) bool {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// lastCompactionDate returns the date the given database file was last
// compacted or a zero time.Time if no compaction was recorded before. The
// compaction date is read from a file in the same directory and with the same
// name as the DB file, but with the suffix ".last-compacted".
func lastCompactionDate(tsFile string) (time.Time, error) {
zeroTime := time.Unix(0, 0)
if !fileExists(tsFile) {
return zeroTime, nil
}
tsBytes, err := os.ReadFile(tsFile)
if err != nil {
return zeroTime, err
}
tsNano := byteOrder.Uint64(tsBytes)
return time.Unix(0, int64(tsNano)), nil
}
func updateLastCompactionDate(tsFile string, date time.Time) error {
var tsBytes [8]byte
byteOrder.PutUint64(tsBytes[:], uint64(date.UnixNano()))
return os.WriteFile(tsFile, tsBytes[:], 0600)
}
package main
import (
"fmt"
"github.com/urfave/cli/v2"
"os"
)
func main() {
app := cli.NewApp()
app.Name = "compactor"
app.Usage = "Change the last compaction date"
app.Commands = []*cli.Command{
readCommand,
writeCommand,
}
if err := app.Run(os.Args); err != nil {
fmt.Println("Error: " + err.Error())
os.Exit(1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment