File: source.go

package info (click to toggle)
android-platform-tools 34.0.5-12
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 150,900 kB
  • sloc: cpp: 805,786; java: 293,500; ansic: 128,288; xml: 127,491; python: 41,481; sh: 14,245; javascript: 9,665; cs: 3,846; asm: 2,049; makefile: 1,917; yacc: 440; awk: 368; ruby: 183; sql: 140; perl: 88; lex: 67
file content (140 lines) | stat: -rw-r--r-- 3,062 bytes parent folder | download | duplicates (5)
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package repositories

import (
	"database/sql"
	"fmt"

	lru "github.com/hashicorp/golang-lru"
	"github.com/pkg/errors"

	e "repodiff/entities"
	repoSQL "repodiff/persistence/sql"
)

var cacheSingleton *lru.Cache

const cacheSize = 1024

type source struct {
	db *sql.DB
}

func (s source) getOrCreateURLBranchID(url, branch string) (int16, error) {
	url = protocolStrippedURL(url)
	id, ok := cacheSingleton.Get(cacheKey(url, branch))
	if ok {
		return id.(int16), nil
	}
	val, err := s.getOrCreateURLBranchIDPersistence(url, branch)
	if err != nil {
		return 0, err
	}
	cacheSingleton.Add(cacheKey(url, branch), val)
	return val, nil
}

func (s source) getOrCreateURLBranchIDPersistence(url, branch string) (int16, error) {
	id, err := s.getIDByURLBranch(url, branch)
	if err == nil {
		return id, nil
	}
	s.insertIgnoreError(url, branch)
	return s.getIDByURLBranch(url, branch)
}

func (s source) insertIgnoreError(url, branch string) {
	repoSQL.SingleTransactionInsert(
		s.db,
		`INSERT INTO id_to_url_branch (
			url,
			branch
		) VALUES (?, ?)`,
		[][]interface{}{
			[]interface{}{
				url,
				branch,
			},
		},
	)
}

func (s source) getIDByURLBranch(url, branch string) (int16, error) {
	var id *int16
	repoSQL.Select(
		s.db,
		func(row *sql.Rows) {
			id = new(int16)
			row.Scan(id)
		},
		"SELECT id FROM id_to_url_branch WHERE url = ? AND branch = ?",
		url,
		branch,
	)
	if id == nil {
		return 0, errors.New(fmt.Sprintf("No ID found for %s %s", url, branch))
	}
	return *id, nil
}

func (s source) GetURLBranchByID(id int16) (string, string, error) {
	urlBranchPair, ok := cacheSingleton.Get(id)
	if ok {
		asSlice := urlBranchPair.([]string)
		return asSlice[0], asSlice[1], nil
	}
	url, branch, err := s.getURLBranchByIDPersistence(id)
	if err == nil {
		cacheSingleton.Add(id, []string{url, branch})
	}
	return url, branch, err
}

func (s source) getURLBranchByIDPersistence(id int16) (string, string, error) {
	url := ""
	branch := ""
	repoSQL.Select(
		s.db,
		func(row *sql.Rows) {
			row.Scan(&url, &branch)
		},
		"SELECT url, branch FROM id_to_url_branch WHERE id = ?",
		id,
	)
	if url == "" {
		return "", "", errors.New(fmt.Sprintf("No matching records for ID %d", id))
	}
	return url, branch, nil
}

func (s source) DiffTargetToMapped(target e.DiffTarget) (e.MappedDiffTarget, error) {
	upstream, errU := s.getOrCreateURLBranchID(
		target.Upstream.URL,
		target.Upstream.Branch,
	)
	downstream, errD := s.getOrCreateURLBranchID(
		target.Downstream.URL,
		target.Downstream.Branch,
	)
	if errU != nil || errD != nil {
		return e.MappedDiffTarget{}, errors.New("Failed interacting with the database")
	}
	return e.MappedDiffTarget{
		UpstreamTarget:   upstream,
		DownstreamTarget: downstream,
	}, nil
}

func NewSourceRepository() (source, error) {
	db, err := repoSQL.GetDBConnectionPool()
	return source{
		db: db,
	}, errors.Wrap(err, "Could not establish a database connection")
}

func cacheKey(url, branch string) string {
	return fmt.Sprintf("%s:%s", url, branch)
}

func init() {
	cacheSingleton, _ = lru.New(cacheSize)
}