diff options
author | Martin Polden <mpolden@mpolden.no> | 2020-01-10 18:53:49 +0100 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2020-01-11 12:25:42 +0100 |
commit | 86b038a9a3d0007b382f12816be4720dd776c8a9 (patch) | |
tree | b9119f48b43fbbac026f279d80c7dfe0598959da | |
parent | b51756462382c5dedba8020646c39fcc7e354ef5 (diff) |
Support packing of cache value
-rw-r--r-- | cache/cache.go | 41 | ||||
-rw-r--r-- | cache/cache_test.go | 21 |
2 files changed, 62 insertions, 0 deletions
diff --git a/cache/cache.go b/cache/cache.go index 5d41bbe..3838212 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -2,7 +2,11 @@ package cache import ( "encoding/binary" + "encoding/hex" + "fmt" "hash/fnv" + "strconv" + "strings" "sync" "time" @@ -41,6 +45,43 @@ func (v *Value) Answers() []string { return dnsutil.Answers(v.msg) } // TTL returns the time to live of the cached value v. func (v *Value) TTL() time.Duration { return dnsutil.MinTTL(v.msg) } +// Pack returns a string representation of Value v. +func (v *Value) Pack() (string, error) { + var sb strings.Builder + sb.WriteString(strconv.FormatInt(v.CreatedAt.Unix(), 10)) + sb.WriteString(" ") + data, err := v.msg.Pack() + if err != nil { + return "", err + } + sb.WriteString(hex.EncodeToString(data)) + return sb.String(), nil +} + +// Unpack converts a string value into a Value type. +func Unpack(value string) (Value, error) { + fields := strings.Fields(value) + if len(fields) < 2 { + return Value{}, fmt.Errorf("invalid number of fields: %q", value) + } + secs, err := strconv.ParseInt(fields[0], 10, 64) + if err != nil { + return Value{}, err + } + data, err := hex.DecodeString(fields[1]) + if err != nil { + return Value{}, err + } + msg := &dns.Msg{} + if err := msg.Unpack(data); err != nil { + return Value{}, err + } + return Value{ + CreatedAt: time.Unix(secs, 0), + msg: msg, + }, nil +} + // New creates a new cache of given capacity. // // If client is non-nil, the cache will prefetch expired entries in an effort to serve results faster. diff --git a/cache/cache_test.go b/cache/cache_test.go index 7879d65..bf4c610 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -360,6 +360,27 @@ func TestCacheEvictAndUpdate(t *testing.T) { } } +func TestPackValue(t *testing.T) { + v := Value{ + CreatedAt: time.Now().Truncate(time.Second), + msg: newA("example.com.", 60, net.ParseIP("192.0.2.1")), + } + packed, err := v.Pack() + if err != nil { + t.Fatal(err) + } + unpacked, err := Unpack(packed) + if err != nil { + t.Fatal(err) + } + if got, want := unpacked.CreatedAt, v.CreatedAt; !want.Equal(got) { + t.Errorf("CreatedAt = %s, want %s", got, want) + } + if got, want := unpacked.msg.String(), v.msg.String(); want != got { + t.Errorf("msg = %s, want %s", got, want) + } +} + func BenchmarkNewKey(b *testing.B) { for n := 0; n < b.N; n++ { NewKey("key", 1, 1) |