aboutsummaryrefslogtreecommitdiff
path: root/pkg/storage/memstore/memstore.go
blob: f0c60f57d746ab32471c9b71e8688f76f747bee0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Package memstore implements in-memory storage for atlas.
package memstore

import (
	"bytes"
	"compress/gzip"
	"crypto/sha256"
	"io"
	"sync"
)

// PdataStore stores pdata in-memory, with optional compression.
type PdataStore struct {
	gzip  bool
	pdata sync.Map
}

type pdataStoreEntry struct {
	Hash [sha256.Size]byte
	Data []byte
}

// NewPdataStore creates a new MemoryPdataStore.
func NewPdataStore(compress bool) *PdataStore {
	return &PdataStore{
		gzip: compress,
	}
}

func (m *PdataStore) GetPdataCached(uid uint64, sha [sha256.Size]byte) ([]byte, bool, error) {
	v, ok := m.pdata.Load(uid)
	if !ok {
		return nil, ok, nil
	}
	e := v.(pdataStoreEntry)
	if sha != [sha256.Size]byte{} && sha == e.Hash {
		return nil, ok, nil
	}
	var b []byte
	if m.gzip {
		r, err := gzip.NewReader(bytes.NewReader(e.Data))
		if err != nil {
			return nil, ok, err
		}
		b, err = io.ReadAll(r)
		if err != nil {
			return nil, ok, err
		}
	} else {
		b = make([]byte, len(e.Data))
		copy(b, e.Data)
	}
	return b, ok, nil
}

func (m *PdataStore) SetPdata(uid uint64, buf []byte) error {
	var b []byte
	if m.gzip {
		var f bytes.Buffer
		w := gzip.NewWriter(&f)
		if _, err := w.Write(buf); err != nil {
			return err
		}
		if err := w.Close(); err != nil {
			return err
		}
		b = f.Bytes()
	} else {
		b = make([]byte, len(buf))
		copy(b, buf)
	}
	m.pdata.Store(uid, pdataStoreEntry{
		Hash: sha256.Sum256(buf),
		Data: b,
	})
	return nil
}