-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathstore.go
123 lines (112 loc) · 2.76 KB
/
store.go
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
package main
import (
"errors"
"fmt"
"strings"
"time"
"log"
)
type Store interface {
Init() error
Clear() error
Begin() error
Commit() error
IsLogIndexed(filename string) (bool, error)
SetLogIndexed(filename string, ar aggregationResult, ur UpdateResult) error
Update(aggregationResult) (UpdateResult, error)
FindQueryTuples(query string) (tupleResults, error)
FindTuples(query string) (tupleResults, error)
FindIndividual(value string) (individualResults, error)
LikeTuples(query string) (tupleResults, error)
LikeIndividual(value string) (individualResults, error)
DeleteOld(days int64) (int64, error)
Close() error
}
type tupleResult struct {
Query string
Type string
Answer string
Count uint
TTL uint
First string
Last string
}
type tupleResults []tupleResult
func (tr tupleResults) Display() {
if len(tr) == 0 {
return
}
header := []string{"Query", "Type", "Answer", "Count", "TTL", "First", "Last"}
fmt.Println(strings.Join(header, "\t"))
for _, rec := range tr {
fmt.Println(rec)
}
}
func (tr tupleResult) String() string {
count := fmt.Sprintf("%d", tr.Count)
ttl := fmt.Sprintf("%d", tr.TTL)
s := []string{tr.Query, tr.Type, tr.Answer, count, ttl, tr.First, tr.Last}
return strings.Join(s, "\t")
}
type individualResult struct {
Value string
Which string
Count uint
First string
Last string
}
type individualResults []individualResult
func (ir individualResults) Display() {
if len(ir) == 0 {
return
}
header := []string{"Value", "Which", "Count", "First", "Last"}
fmt.Println(strings.Join(header, "\t"))
for _, rec := range ir {
fmt.Println(rec)
}
}
func (ir individualResult) String() string {
count := fmt.Sprintf("%d", ir.Count)
s := []string{ir.Value, ir.Which, count, ir.First, ir.Last}
return strings.Join(s, "\t")
}
type UpdateResult struct {
Inserted uint
Updated uint
Duration time.Duration
}
var storeFactories = map[string]func(string) (Store, error){
"clickhouse": NewCHStore,
"sqlite": NewSQLiteStore,
"postgresql": NewPGStore,
}
func NewStore(storeType string, filename string) (Store, error) {
storeFactory, ok := storeFactories[storeType]
if !ok {
return nil, errors.New("Invalid store type")
}
s, err := storeFactory(filename)
if err != nil {
return nil, err
}
err = s.Init()
if err != nil {
return nil, err
}
return s, err
}
//ToTS ensures a string is a unix timestamp
//Yes, this is terrible, but supporting both timestamps and iso8601 at the same
//time is tricky
func ToTS(t string) string {
//If it doesn't have a dash, it should be a unix timestamp already
if !strings.Contains(t, "-") {
return t
}
parsed, err := time.Parse(time.RFC3339, t)
if err != nil {
log.Fatalf("Unparsable timestamp, don't know what to do here: %v", t)
}
return fmt.Sprintf("%d", parsed.Unix())
}