summaryrefslogtreecommitdiff
path: root/workhorse/internal/lsif_transformer/parser/cache.go
blob: 395069cd2173e7ca67334c841015190ee988a87e (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
package parser

import (
	"encoding/binary"
	"io"
	"io/ioutil"
	"os"
)

// This cache implementation is using a temp file to provide key-value data storage
// It allows to avoid storing intermediate calculations in RAM
// The stored data must be a fixed-size value or a slice of fixed-size values, or a pointer to such data
type cache struct {
	file      *os.File
	chunkSize int64
}

func newCache(tempDir, filename string, data interface{}) (*cache, error) {
	f, err := ioutil.TempFile(tempDir, filename)
	if err != nil {
		return nil, err
	}

	if err := os.Remove(f.Name()); err != nil {
		return nil, err
	}

	return &cache{file: f, chunkSize: int64(binary.Size(data))}, nil
}

func (c *cache) SetEntry(id Id, data interface{}) error {
	if err := c.setOffset(id); err != nil {
		return err
	}

	return binary.Write(c.file, binary.LittleEndian, data)
}

func (c *cache) Entry(id Id, data interface{}) error {
	if err := c.setOffset(id); err != nil {
		return err
	}

	return binary.Read(c.file, binary.LittleEndian, data)
}

func (c *cache) Close() error {
	return c.file.Close()
}

func (c *cache) setOffset(id Id) error {
	offset := int64(id) * c.chunkSize
	_, err := c.file.Seek(offset, io.SeekStart)

	return err
}